1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-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    GUIApplicationWindow.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Michael Behrisch
14 /// @author  Andreas Gaubatz
15 /// @date    Sept 2002
16 /// @version $Id$
17 ///
18 // The main window of the SUMO-gui.
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #ifdef HAVE_VERSION_H
28 #include <version.h>
29 #endif
30 
31 #include <string>
32 #include <sstream>
33 #include <algorithm>
34 #include <iomanip>
35 
36 #include <guisim/GUINet.h>
37 #include <guisim/GUILane.h>
38 #include <netload/NLHandler.h>
39 #include <traci-server/TraCIServer.h>
40 #include <microsim/MSGlobals.h>
41 #include <microsim/MSEdge.h>
42 #include <microsim/MSVehicle.h>
43 #include <microsim/MSStateHandler.h>
44 #include <microsim/MSVehicleControl.h>
45 #include <microsim/MSEdgeControl.h>
46 #include <microsim/MSInsertionControl.h>
47 #include <microsim/MSTransportableControl.h>
48 
49 #include "GUISUMOViewParent.h"
50 #include "GUILoadThread.h"
51 #include "GUIRunThread.h"
52 #include "GUIApplicationWindow.h"
53 #include "GUIEvent_SimulationLoaded.h"
54 #include "GUIEvent_SimulationEnded.h"
55 
56 #include <utils/common/ToString.h>
57 #include <utils/common/RandHelper.h>
58 #include <utils/foxtools/MFXUtils.h>
59 #include <utils/foxtools/FXLCDLabel.h>
60 #include <utils/foxtools/FXThreadEvent.h>
61 #include <utils/foxtools/FXLinkLabel.h>
62 
63 #include <utils/xml/XMLSubSys.h>
64 #include <utils/gui/images/GUITexturesHelper.h>
65 #include <utils/gui/events/GUIEvent_SimulationStep.h>
66 #include <utils/gui/events/GUIEvent_Message.h>
67 #include <utils/gui/div/GUIMessageWindow.h>
68 #include <utils/gui/div/GUIDialog_GLChosenEditor.h>
69 #include <utils/gui/tracker/GUIParameterTracker.h>
70 #include <utils/gui/div/GUIParameterTableWindow.h>
71 #include <utils/gui/images/GUIIconSubSys.h>
72 #include <utils/gui/cursors/GUICursorSubSys.h>
73 #include <utils/gui/shortcuts/GUIShortcutsSubSys.h>
74 #include <utils/gui/div/GUIIOGlobals.h>
75 #include <utils/gui/div/GUIUserIO.h>
76 #include <utils/gui/div/GLHelper.h>
77 #include <utils/gui/settings/GUICompleteSchemeStorage.h>
78 #include <utils/gui/globjects/GUIGlObjectStorage.h>
79 #include <utils/gui/globjects/GUIShapeContainer.h>
80 #include <utils/gui/div/GUIGlobalSelection.h>
81 #include <utils/gui/div/GUIDesigns.h>
82 #include <utils/gui/settings/GUISettingsHandler.h>
83 #include <utils/gui/windows/GUIAppEnum.h>
84 #include <utils/gui/windows/GUISUMOAbstractView.h>
85 #include <utils/gui/windows/GUIPerspectiveChanger.h>
86 #include <utils/options/OptionsCont.h>
87 #include "GUIGlobals.h"
88 #include "dialogs/GUIDialog_AboutSUMO.h"
89 #include "dialogs/GUIDialog_AppSettings.h"
90 #include "dialogs/GUIDialog_Breakpoints.h"
91 
92 
93 //#define HAVE_DANGEROUS_SOUNDS
94 
95 // ===========================================================================
96 // FOX-declarations
97 // ===========================================================================
98 FXDEFMAP(GUIApplicationWindow) GUIApplicationWindowMap[] = {
99     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_Q_CLOSE,    GUIApplicationWindow::onCmdQuit),
100     FXMAPFUNC(SEL_SIGNAL,   MID_HOTKEY_CTRL_Q_CLOSE,    GUIApplicationWindow::onCmdQuit),
101     FXMAPFUNC(SEL_CLOSE,    MID_WINDOW,                 GUIApplicationWindow::onCmdQuit),
102 
103     FXMAPFUNC(SEL_COMMAND,  MID_OPEN_CONFIG,                    GUIApplicationWindow::onCmdOpenConfiguration),
104     FXMAPFUNC(SEL_COMMAND,  MID_OPEN_NETWORK,                   GUIApplicationWindow::onCmdOpenNetwork),
105     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_P,                  GUIApplicationWindow::onCmdOpenShapes),
106     FXMAPFUNC(SEL_COMMAND,  MID_OPEN_EDGEDATA,                  GUIApplicationWindow::onCmdOpenEdgeData),
107     FXMAPFUNC(SEL_COMMAND,  MID_RECENTFILE,                     GUIApplicationWindow::onCmdOpenRecent),
108     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_R_RELOAD,           GUIApplicationWindow::onCmdReload),
109     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_W_CLOSESIMULATION,  GUIApplicationWindow::onCmdClose),
110     FXMAPFUNC(SEL_COMMAND,  MID_EDITCHOSEN,                     GUIApplicationWindow::onCmdEditChosen),
111     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_B_EDITBREAKPOINT,   GUIApplicationWindow::onCmdEditBreakpoints),
112     FXMAPFUNC(SEL_COMMAND,  MID_EDITVIEWSCHEME,                 GUIApplicationWindow::onCmdEditViewScheme),
113     FXMAPFUNC(SEL_COMMAND,  MID_EDITVIEWPORT,                   GUIApplicationWindow::onCmdEditViewport),
114     FXMAPFUNC(SEL_COMMAND,  MID_NETEDIT,                        GUIApplicationWindow::onCmdNetedit),
115 
116     FXMAPFUNC(SEL_COMMAND,  MID_APPSETTINGS,                            GUIApplicationWindow::onCmdAppSettings),
117     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_G_GAMINGMODE_TOOGLEGRID,    GUIApplicationWindow::onCmdGaming),
118     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_F_FULSCREENMODE,            GUIApplicationWindow::onCmdFullScreen),
119     FXMAPFUNC(SEL_COMMAND,  MID_LISTINTERNAL,                           GUIApplicationWindow::onCmdListInternal),
120     FXMAPFUNC(SEL_COMMAND,  MID_LISTPARKING,                            GUIApplicationWindow::onCmdListParking),
121     FXMAPFUNC(SEL_COMMAND,  MID_LISTTELEPORTING,                        GUIApplicationWindow::onCmdListTeleporting),
122     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_F2_ABOUT,                        GUIApplicationWindow::onCmdAbout),
123     FXMAPFUNC(SEL_COMMAND,  MID_NEW_MICROVIEW,                          GUIApplicationWindow::onCmdNewView),
124 #ifdef HAVE_OSG
125     FXMAPFUNC(SEL_COMMAND,  MID_NEW_OSGVIEW,        GUIApplicationWindow::onCmdNewOSG),
126 #endif
127     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_A_STARTSIMULATION_OPENADDITIONALS,  GUIApplicationWindow::onCmdStart),
128     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_S_STOPSIMULATION_SAVENETWORK,       GUIApplicationWindow::onCmdStop),
129     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_CTRL_D_SINGLESIMULATIONSTEP_OPENDEMAND,  GUIApplicationWindow::onCmdStep),
130     FXMAPFUNC(SEL_COMMAND,  MID_SIMSAVE,                                        GUIApplicationWindow::onCmdSaveState),
131     FXMAPFUNC(SEL_COMMAND,  MID_TIME_TOOGLE,                                    GUIApplicationWindow::onCmdTimeToggle),
132     FXMAPFUNC(SEL_COMMAND,  MID_DELAY_TOOGLE,                                   GUIApplicationWindow::onCmdDelayToggle),
133     FXMAPFUNC(SEL_COMMAND,  MID_DEMAND_SCALE,                                   GUIApplicationWindow::onCmdDemandScale),
134     FXMAPFUNC(SEL_COMMAND,  MID_CLEARMESSAGEWINDOW,                             GUIApplicationWindow::onCmdClearMsgWindow),
135 
136     FXMAPFUNC(SEL_COMMAND,  MID_SHOWNETSTATS,       GUIApplicationWindow::onCmdShowStats),
137     FXMAPFUNC(SEL_COMMAND,  MID_SHOWVEHSTATS,       GUIApplicationWindow::onCmdShowStats),
138     FXMAPFUNC(SEL_COMMAND,  MID_SHOWPERSONSTATS,    GUIApplicationWindow::onCmdShowStats),
139 
140     FXMAPFUNC(SEL_UPDATE,   MID_OPEN_CONFIG,                GUIApplicationWindow::onUpdOpen),
141     FXMAPFUNC(SEL_UPDATE,   MID_OPEN_NETWORK,               GUIApplicationWindow::onUpdOpen),
142     FXMAPFUNC(SEL_UPDATE,   MID_OPEN_NETWORK,               GUIApplicationWindow::onUpdOpen),
143     FXMAPFUNC(SEL_UPDATE,   MID_HOTKEY_CTRL_P,              GUIApplicationWindow::onUpdNeedsSimulation),
144     FXMAPFUNC(SEL_UPDATE,   MID_OPEN_EDGEDATA,              GUIApplicationWindow::onUpdNeedsSimulation),
145     FXMAPFUNC(SEL_UPDATE,   MID_HOTKEY_CTRL_R_RELOAD,       GUIApplicationWindow::onUpdReload),
146     FXMAPFUNC(SEL_UPDATE,   MID_RECENTFILE,                 GUIApplicationWindow::onUpdOpenRecent),
147     FXMAPFUNC(SEL_UPDATE,   MID_NEW_MICROVIEW,              GUIApplicationWindow::onUpdAddView),
148 #ifdef HAVE_OSG
149     FXMAPFUNC(SEL_UPDATE,   MID_NEW_OSGVIEW,        GUIApplicationWindow::onUpdAddView),
150 #endif
151     FXMAPFUNC(SEL_UPDATE,   MID_HOTKEY_CTRL_A_STARTSIMULATION_OPENADDITIONALS,  GUIApplicationWindow::onUpdStart),
152     FXMAPFUNC(SEL_UPDATE,   MID_HOTKEY_CTRL_S_STOPSIMULATION_SAVENETWORK,       GUIApplicationWindow::onUpdStop),
153     FXMAPFUNC(SEL_UPDATE,   MID_HOTKEY_CTRL_D_SINGLESIMULATIONSTEP_OPENDEMAND,  GUIApplicationWindow::onUpdStep),
154     FXMAPFUNC(SEL_UPDATE,   MID_SIMSAVE,                                        GUIApplicationWindow::onUpdNeedsSimulation),
155     FXMAPFUNC(SEL_UPDATE,   MID_EDITCHOSEN,                                     GUIApplicationWindow::onUpdNeedsSimulation),
156     FXMAPFUNC(SEL_UPDATE,   MID_HOTKEY_CTRL_B_EDITBREAKPOINT,                   GUIApplicationWindow::onUpdNeedsSimulation),
157     FXMAPFUNC(SEL_UPDATE,   MID_EDITVIEWSCHEME,                                 GUIApplicationWindow::onUpdNeedsSimulation),
158     FXMAPFUNC(SEL_UPDATE,   MID_EDITVIEWPORT,                                   GUIApplicationWindow::onUpdNeedsSimulation),
159     FXMAPFUNC(SEL_UPDATE,   MID_NETEDIT,                                        GUIApplicationWindow::onUpdNeedsSimulation),
160     FXMAPFUNC(SEL_UPDATE,   MID_DEMAND_SCALE,                                   GUIApplicationWindow::onUpdNeedsSimulation),
161     FXMAPFUNC(SEL_UPDATE,   MID_TRACI_STATUS,                                   GUIApplicationWindow::onUpdTraCIStatus),
162     FXMAPFUNC(SEL_COMMAND,  MID_HOTKEY_F1_ONLINEDOCUMENTATION,                  GUIApplicationWindow::onCmdHelp),
163 
164     // forward requests to the active view
165     FXMAPFUNC(SEL_COMMAND,  MID_LOCATEJUNCTION, GUIApplicationWindow::onCmdLocate),
166     FXMAPFUNC(SEL_COMMAND,  MID_LOCATEEDGE,     GUIApplicationWindow::onCmdLocate),
167     FXMAPFUNC(SEL_COMMAND,  MID_LOCATEVEHICLE,  GUIApplicationWindow::onCmdLocate),
168     FXMAPFUNC(SEL_COMMAND,  MID_LOCATEPERSON,   GUIApplicationWindow::onCmdLocate),
169     FXMAPFUNC(SEL_COMMAND,  MID_LOCATETLS,      GUIApplicationWindow::onCmdLocate),
170     FXMAPFUNC(SEL_COMMAND,  MID_LOCATEADD,      GUIApplicationWindow::onCmdLocate),
171     FXMAPFUNC(SEL_COMMAND,  MID_LOCATEPOI,      GUIApplicationWindow::onCmdLocate),
172     FXMAPFUNC(SEL_COMMAND,  MID_LOCATEPOLY,     GUIApplicationWindow::onCmdLocate),
173     FXMAPFUNC(SEL_UPDATE,   MID_LOCATEJUNCTION, GUIApplicationWindow::onUpdNeedsSimulation),
174     FXMAPFUNC(SEL_UPDATE,   MID_LOCATEEDGE,     GUIApplicationWindow::onUpdNeedsSimulation),
175     FXMAPFUNC(SEL_UPDATE,   MID_LOCATEVEHICLE,  GUIApplicationWindow::onUpdNeedsSimulation),
176     FXMAPFUNC(SEL_UPDATE,   MID_LOCATEPERSON,   GUIApplicationWindow::onUpdNeedsSimulation),
177     FXMAPFUNC(SEL_UPDATE,   MID_LOCATETLS,      GUIApplicationWindow::onUpdNeedsSimulation),
178     FXMAPFUNC(SEL_UPDATE,   MID_LOCATEADD,      GUIApplicationWindow::onUpdNeedsSimulation),
179     FXMAPFUNC(SEL_UPDATE,   MID_LOCATEPOI,      GUIApplicationWindow::onUpdNeedsSimulation),
180     FXMAPFUNC(SEL_UPDATE,   MID_LOCATEPOLY,     GUIApplicationWindow::onUpdNeedsSimulation),
181     FXMAPFUNC(SEL_KEYPRESS,              0,     GUIApplicationWindow::onKeyPress),
182     FXMAPFUNC(SEL_KEYRELEASE,            0,     GUIApplicationWindow::onKeyRelease),
183 
184     FXMAPFUNC(SEL_CLIPBOARD_REQUEST, 0, GUIApplicationWindow::onClipboardRequest),
185 
186     FXMAPFUNC(FXEX::SEL_THREAD_EVENT, ID_LOADTHREAD_EVENT, GUIApplicationWindow::onLoadThreadEvent),
187     FXMAPFUNC(FXEX::SEL_THREAD_EVENT, ID_RUNTHREAD_EVENT,  GUIApplicationWindow::onRunThreadEvent),
188     FXMAPFUNC(FXEX::SEL_THREAD, ID_LOADTHREAD_EVENT,       GUIApplicationWindow::onLoadThreadEvent),
189     FXMAPFUNC(FXEX::SEL_THREAD, ID_RUNTHREAD_EVENT,        GUIApplicationWindow::onRunThreadEvent),
190 };
191 
192 // Object implementation
193 FXIMPLEMENT(GUIApplicationWindow, FXMainWindow, GUIApplicationWindowMap, ARRAYNUMBER(GUIApplicationWindowMap))
194 
195 // ===========================================================================
196 // static members
197 // ===========================================================================
198 std::mt19937 GUIApplicationWindow::myGamingRNG;
199 
200 // ===========================================================================
201 // member method definitions
202 // ===========================================================================
GUIApplicationWindow(FXApp * a,const std::string & configPattern)203 GUIApplicationWindow::GUIApplicationWindow(FXApp* a, const std::string& configPattern) :
204     GUIMainWindow(a),
205     myLoadThread(nullptr), myRunThread(nullptr),
206     myAmLoading(false),
207     myAlternateSimDelay(0),
208     myRecentNets(a, "nets"),
209     myConfigPattern(configPattern),
210     hadDependentBuild(false),
211     myShowTimeAsHMS(false),
212     myHaveNotifiedAboutSimEnd(false),
213     // game specific
214     myJamSoundTime(60),
215     myPreviousCollisionNumber(0),
216     myWaitingTime(0),
217     myTimeLoss(0),
218     myTotalDistance(0) {
219     // init icons
220     GUIIconSubSys::initIcons(a);
221     // init cursors
222     GUICursorSubSys::initCursors(a);
223 }
224 
225 
226 void
dependentBuild()227 GUIApplicationWindow::dependentBuild() {
228     // don't do this twice
229     if (hadDependentBuild) {
230         return;
231     }
232     hadDependentBuild = true;
233 
234     setTarget(this);
235     setSelector(MID_WINDOW);
236 
237     // build menu bar
238     myMenuBarDrag = new FXToolBarShell(this, GUIDesignToolBar);
239     myMenuBar = new FXMenuBar(myTopDock, myMenuBarDrag, GUIDesignToolbarMenuBar);
240     new FXToolBarGrip(myMenuBar, myMenuBar, FXMenuBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
241     buildToolBars();
242     // build the thread - io
243     myLoadThreadEvent.setTarget(this),  myLoadThreadEvent.setSelector(ID_LOADTHREAD_EVENT);
244     myRunThreadEvent.setTarget(this), myRunThreadEvent.setSelector(ID_RUNTHREAD_EVENT);
245 
246     // build the status bar
247     myStatusbar = new FXStatusBar(this, GUIDesignStatusBar);
248     {
249         myGeoFrame = new FXHorizontalFrame(myStatusbar, GUIDesignHorizontalFrameStatusBar);
250         myGeoCoordinate = new FXLabel(myGeoFrame, "N/A\t\tOriginal coordinate (before coordinate transformation in NETCONVERT)", nullptr, LAYOUT_CENTER_Y);
251         myCartesianFrame = new FXHorizontalFrame(myStatusbar, GUIDesignHorizontalFrameStatusBar);
252         myCartesianCoordinate = new FXLabel(myCartesianFrame, "N/A\t\tNetwork coordinate", nullptr, LAYOUT_CENTER_Y);
253         myStatButtons.push_back(new FXButton(myStatusbar, "-", GUIIconSubSys::getIcon(ICON_GREENVEHICLE), this, MID_SHOWVEHSTATS));
254         myStatButtons.push_back(new FXButton(myStatusbar, "-", GUIIconSubSys::getIcon(ICON_GREENPERSON), this, MID_SHOWPERSONSTATS));
255         myStatButtons.back()->hide();
256         myStatButtons.push_back(new FXButton(myStatusbar, "-", GUIIconSubSys::getIcon(ICON_GREENEDGE), this, MID_SHOWVEHSTATS));
257         myStatButtons.back()->hide();
258     }
259 
260     // make the window a mdi-window
261     myMainSplitter = new FXSplitter(this, GUIDesignSplitter | SPLITTER_VERTICAL | SPLITTER_REVERSED);
262     myMDIClient = new FXMDIClient(myMainSplitter, GUIDesignSplitterMDI);
263     myMDIMenu = new FXMDIMenu(this, myMDIClient);
264     new FXMDIWindowButton(myMenuBar, myMDIMenu, myMDIClient, FXMDIClient::ID_MDI_MENUWINDOW, GUIDesignMDIButtonLeft);
265     new FXMDIDeleteButton(myMenuBar, myMDIClient, FXMDIClient::ID_MDI_MENUCLOSE, GUIDesignMDIButtonRight);
266     new FXMDIRestoreButton(myMenuBar, myMDIClient, FXMDIClient::ID_MDI_MENURESTORE, GUIDesignMDIButtonRight);
267     new FXMDIMinimizeButton(myMenuBar, myMDIClient, FXMDIClient::ID_MDI_MENUMINIMIZE, GUIDesignMDIButtonRight);
268 
269     // build the message window
270     myMessageWindow = new GUIMessageWindow(myMainSplitter);
271     // fill menu and tool bar
272     fillMenuBar();
273     myToolBar6->hide();
274     myToolBar7->hide();
275     myToolBar9->hide();
276     // build additional threads
277     myLoadThread = new GUILoadThread(getApp(), this, myEvents, myLoadThreadEvent);
278     myRunThread = new GUIRunThread(getApp(), this, mySimDelay, myEvents, myRunThreadEvent);
279     // set the status bar
280     myStatusbar->getStatusLine()->setText("Ready.");
281     // set the caption
282     setTitle(MFXUtils::getTitleText("SUMO " VERSION_STRING));
283 
284     // start the simulation-thread (it will loop until the application ends deciding by itself whether to perform a step or not)
285     myRunThread->start();
286     setIcon(GUIIconSubSys::getIcon(ICON_SUMO));
287     setMiniIcon(GUIIconSubSys::getIcon(ICON_SUMO_MINI));
288 }
289 
290 
291 void
create()292 GUIApplicationWindow::create() {
293     setWindowSizeAndPos();
294     gCurrentFolder = getApp()->reg().readStringEntry("SETTINGS", "basedir", "");
295     FXMainWindow::create();
296     myMenuBarDrag->create();
297     myToolBarDrag1->create();
298     myToolBarDrag2->create();
299     myToolBarDrag3->create();
300     myToolBarDrag4->create();
301     myToolBarDrag5->create();
302     myToolBarDrag6->create();
303     myToolBarDrag7->create();
304     myFileMenu->create();
305     mySelectByPermissions->create();
306     myEditMenu->create();
307     mySettingsMenu->create();
308     myLocatorMenu->create();
309     myControlMenu->create();
310     myWindowsMenu->create();
311     myHelpMenu->create();
312 
313     FXint width = getApp()->getNormalFont()->getTextWidth("8", 1) * 24;
314     myCartesianFrame->setWidth(width);
315     myGeoFrame->setWidth(width);
316 
317     show(PLACEMENT_DEFAULT);
318     if (!OptionsCont::getOptions().isSet("window-size")) {
319         if (getApp()->reg().readIntEntry("SETTINGS", "maximized", 0) == 1) {
320             maximize();
321         }
322     }
323     myShowTimeAsHMS = (getApp()->reg().readIntEntry("gui", "timeasHMS", 0) == 1);
324     myAlternateSimDelay = getApp()->reg().readIntEntry("gui", "alternateSimDelay", 100);
325 }
326 
327 
~GUIApplicationWindow()328 GUIApplicationWindow::~GUIApplicationWindow() {
329     myRunThread->prepareDestruction();
330     myRunThread->join();
331     closeAllWindows();
332     //
333     GUIIconSubSys::close();
334     delete myGLVisual;
335     // delete some non-parented windows
336     delete myToolBarDrag1;
337     //
338     delete myRunThread;
339     delete myFileMenu;
340     delete myEditMenu;
341     delete mySelectByPermissions;
342     delete mySettingsMenu;
343     delete myLocatorMenu;
344     delete myControlMenu;
345     delete myWindowsMenu;
346     delete myHelpMenu;
347 
348     delete myLoadThread;
349 
350     while (!myEvents.empty()) {
351         // get the next event
352         GUIEvent* e = myEvents.top();
353         myEvents.pop();
354         delete e;
355     }
356 }
357 
358 
359 void
detach()360 GUIApplicationWindow::detach() {
361     FXMainWindow::detach();
362     myMenuBarDrag->detach();
363     myToolBarDrag1->detach();
364 }
365 
366 
367 void
fillMenuBar()368 GUIApplicationWindow::fillMenuBar() {
369     // build file menu
370     myFileMenu = new FXMenuPane(this);
371     new FXMenuTitle(myMenuBar, "&File", nullptr, myFileMenu);
372     new FXMenuCommand(myFileMenu,
373                       "&Open Simulation...\tCtrl+O\tOpen a simulation (Configuration file).",
374                       GUIIconSubSys::getIcon(ICON_OPEN_CONFIG), this, MID_OPEN_CONFIG);
375     new FXMenuCommand(myFileMenu,
376                       "Open &Network...\tCtrl+N\tOpen a network.",
377                       GUIIconSubSys::getIcon(ICON_OPEN_NET), this, MID_OPEN_NETWORK);
378     new FXMenuCommand(myFileMenu,
379                       "Open Shapes \tCtrl+P\tLoad POIs and Polygons for visualization.",
380                       GUIIconSubSys::getIcon(ICON_OPEN_SHAPES), this, MID_HOTKEY_CTRL_P);
381     new FXMenuCommand(myFileMenu,
382                       "Open EdgeData \tCtrl+U\tLoad edge related data for visualization.",
383                       GUIIconSubSys::getIcon(ICON_OPEN_NET), this, MID_OPEN_EDGEDATA);
384     new FXMenuCommand(myFileMenu,
385                       "&Reload\tCtrl+R\tReloads the simulation / the network.",
386                       GUIIconSubSys::getIcon(ICON_RELOAD), this, MID_HOTKEY_CTRL_R_RELOAD);
387     new FXMenuSeparator(myFileMenu);
388     new FXMenuCommand(myFileMenu,
389                       "Close\tCtrl+W\tClose the simulation.",
390                       GUIIconSubSys::getIcon(ICON_CLOSE), this, MID_HOTKEY_CTRL_W_CLOSESIMULATION);
391     // Recent files
392     FXMenuSeparator* sep1 = new FXMenuSeparator(myFileMenu);
393     sep1->setTarget(&myRecentConfigs);
394     sep1->setSelector(FXRecentFiles::ID_ANYFILES);
395     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_1);
396     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_2);
397     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_3);
398     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_4);
399     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_5);
400     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_6);
401     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_7);
402     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_8);
403     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_9);
404     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentConfigs, FXRecentFiles::ID_FILE_10);
405     new FXMenuCommand(myFileMenu, "C&lear Recent Configurations", nullptr, &myRecentConfigs, FXRecentFiles::ID_CLEAR);
406     myRecentConfigs.setTarget(this);
407     myRecentConfigs.setSelector(MID_RECENTFILE);
408     FXMenuSeparator* sep2 = new FXMenuSeparator(myFileMenu);
409     sep2->setTarget(&myRecentNets);
410     sep2->setSelector(FXRecentFiles::ID_ANYFILES);
411     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_1);
412     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_2);
413     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_3);
414     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_4);
415     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_5);
416     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_6);
417     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_7);
418     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_8);
419     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_9);
420     new FXMenuCommand(myFileMenu, "", nullptr, &myRecentNets, FXRecentFiles::ID_FILE_10);
421     new FXMenuCommand(myFileMenu, "Cl&ear Recent Networks", nullptr, &myRecentNets, FXRecentFiles::ID_CLEAR);
422     myRecentNets.setTarget(this);
423     myRecentNets.setSelector(MID_RECENTFILE);
424     new FXMenuSeparator(myFileMenu);
425     new FXMenuCommand(myFileMenu,
426                       "&Quit\tCtrl+Q\tQuit the Application.",
427                       nullptr, this, MID_HOTKEY_CTRL_Q_CLOSE, 0);
428 
429     // build edit menu
430     mySelectByPermissions = new FXMenuPane(this);
431     std::vector<std::string> vehicleClasses = SumoVehicleClassStrings.getStrings();
432     for (auto i : vehicleClasses) {
433         new FXMenuCommand(mySelectByPermissions, i.c_str(), nullptr, this, MID_EDITCHOSEN);
434     }
435 
436     myEditMenu = new FXMenuPane(this);
437     new FXMenuTitle(myMenuBar, "&Edit", nullptr, myEditMenu);
438     new FXMenuCommand(myEditMenu,
439                       "Edit Selected...\tCtrl+E\tOpens a dialog for editing the list of selected items.",
440                       GUIIconSubSys::getIcon(ICON_FLAG), this, MID_EDITCHOSEN);
441     mySelectLanesMenuCascade = new FXMenuCascade(myEditMenu,
442             "Select lanes which allow...\t\tOpens a menu for selecting a vehicle class by which to selected lanes.",
443             GUIIconSubSys::getIcon(ICON_FLAG), mySelectByPermissions);
444     new FXMenuSeparator(myEditMenu);
445     new FXMenuCommand(myEditMenu,
446                       "Edit Breakpoints\tCtrl+B\tOpens a dialog for editing breakpoints.",
447                       nullptr, this, MID_HOTKEY_CTRL_B_EDITBREAKPOINT);
448     new FXMenuCommand(myEditMenu,
449                       "Edit Visualisation\tCtrl+V\tOpens a dialog for editing visualization settings.",
450                       nullptr, this, MID_EDITVIEWSCHEME);
451     new FXMenuCommand(myEditMenu,
452                       "Edit Viewport\tCtrl+I\tOpens a dialog for editing viewing are, zoom and rotation.",
453                       nullptr, this, MID_EDITVIEWPORT);
454     new FXMenuSeparator(myEditMenu);
455     new FXMenuCommand(myEditMenu,
456                       "Open in Netedit\tCtrl+T\tOpens the netedit application with the current network.",
457                       nullptr, this, MID_NETEDIT);
458 
459     // build settings menu
460     mySettingsMenu = new FXMenuPane(this);
461     new FXMenuTitle(myMenuBar, "&Settings", nullptr, mySettingsMenu);
462     new FXMenuCommand(mySettingsMenu,
463                       "Application Settings...\t\tOpen a Dialog for Application Settings editing.",
464                       nullptr, this, MID_APPSETTINGS);
465     new FXMenuCheck(mySettingsMenu,
466                     "Gaming Mode\tCtrl+G\tToggle gaming mode on/off.",
467                     this, MID_HOTKEY_CTRL_G_GAMINGMODE_TOOGLEGRID);
468     new FXMenuCheck(mySettingsMenu,
469                     "Full Screen Mode\tCtrl+F\tToggle full screen mode on/off.",
470                     this, MID_HOTKEY_CTRL_F_FULSCREENMODE);
471     // build Locate menu
472     myLocatorMenu = new FXMenuPane(this);
473     new FXMenuTitle(myMenuBar, "&Locate", nullptr, myLocatorMenu);
474     new FXMenuCommand(myLocatorMenu,
475                       "Locate &Junctions\t\tOpen a Dialog for Locating a Junction.",
476                       GUIIconSubSys::getIcon(ICON_LOCATEJUNCTION), this, MID_LOCATEJUNCTION);
477     new FXMenuCommand(myLocatorMenu,
478                       "Locate &Edges\t\tOpen a Dialog for Locating an Edge.",
479                       GUIIconSubSys::getIcon(ICON_LOCATEEDGE), this, MID_LOCATEEDGE);
480     if (!MSGlobals::gUseMesoSim) { // there are no gui-vehicles in mesosim
481         new FXMenuCommand(myLocatorMenu,
482                           "Locate &Vehicles\t\tOpen a Dialog for Locating a Vehicle.",
483                           GUIIconSubSys::getIcon(ICON_LOCATEVEHICLE), this, MID_LOCATEVEHICLE);
484     }
485     new FXMenuCommand(myLocatorMenu,
486                       "Locate &Persons\t\tOpen a Dialog for Locating a Person.",
487                       GUIIconSubSys::getIcon(ICON_LOCATEPERSON), this, MID_LOCATEPERSON);
488     new FXMenuCommand(myLocatorMenu,
489                       "Locate &TLS\t\tOpen a Dialog for Locating a Traffic Light.",
490                       GUIIconSubSys::getIcon(ICON_LOCATETLS), this, MID_LOCATETLS);
491     new FXMenuCommand(myLocatorMenu,
492                       "Locate &Additional\t\tOpen a Dialog for Locating an Additional Structure.",
493                       GUIIconSubSys::getIcon(ICON_LOCATEADD), this, MID_LOCATEADD);
494     new FXMenuCommand(myLocatorMenu,
495                       "Locate P&oI\t\tOpen a Dialog for Locating a Point of Intereset.",
496                       GUIIconSubSys::getIcon(ICON_LOCATEPOI), this, MID_LOCATEPOI);
497     new FXMenuCommand(myLocatorMenu,
498                       "Locate Po&lygon\t\tOpen a Dialog for Locating a Polygon.",
499                       GUIIconSubSys::getIcon(ICON_LOCATEPOLY), this, MID_LOCATEPOLY);
500     new FXMenuSeparator(myLocatorMenu);
501     new FXMenuCheck(myLocatorMenu,
502                     "Show Internal Structures\t\tShow internal junctions and streets in locator dialog.",
503                     this, MID_LISTINTERNAL);
504     FXMenuCheck* listParking = new FXMenuCheck(myLocatorMenu,
505             "Show Parking Vehicles\t\tShow parking vehicles in locator dialog.",
506             this, MID_LISTPARKING);
507     listParking->setCheck(myListParking);
508     new FXMenuCheck(myLocatorMenu,
509                     "Show vehicles outside the road network\t\tShow vehicles that are teleporting or driving remote-controlled outside the road network in locator dialog.",
510                     this, MID_LISTTELEPORTING);
511     // build control menu
512     myControlMenu = new FXMenuPane(this);
513     new FXMenuTitle(myMenuBar, "Simulation", nullptr, myControlMenu);
514     new FXMenuCommand(myControlMenu,
515                       "Run\tCtrl+A\tStart running the simulation.",
516                       GUIIconSubSys::getIcon(ICON_START), this, MID_HOTKEY_CTRL_A_STARTSIMULATION_OPENADDITIONALS);
517     new FXMenuCommand(myControlMenu,
518                       "Stop\tCtrl+S\tStop running the simulation.",
519                       GUIIconSubSys::getIcon(ICON_STOP), this, MID_HOTKEY_CTRL_S_STOPSIMULATION_SAVENETWORK);
520     new FXMenuCommand(myControlMenu,
521                       "Step\tCtrl+D\tPerform one simulation step.",
522                       GUIIconSubSys::getIcon(ICON_STEP), this, MID_HOTKEY_CTRL_D_SINGLESIMULATIONSTEP_OPENDEMAND);
523     new FXMenuCommand(myControlMenu,
524                       "Save\t\tSave the current simulation state to a file.",
525                       GUIIconSubSys::getIcon(ICON_SAVE), this, MID_SIMSAVE);
526 
527     // build windows menu
528     myWindowsMenu = new FXMenuPane(this);
529     new FXMenuTitle(myMenuBar, "&Windows", nullptr, myWindowsMenu);
530     new FXMenuCheck(myWindowsMenu,
531                     "Show Status Line\t\tToggle the Status Bar on/off.",
532                     myStatusbar, FXWindow::ID_TOGGLESHOWN);
533     new FXMenuCheck(myWindowsMenu,
534                     "Show Message Window\t\tToggle the Message Window on/off.",
535                     myMessageWindow, FXWindow::ID_TOGGLESHOWN);
536     new FXMenuCheck(myWindowsMenu,
537                     "Show Simulation Time\t\tToggle the Simulation Time on/off.",
538                     myToolBar3, FXWindow::ID_TOGGLESHOWN);
539     new FXMenuCheck(myWindowsMenu,
540                     "Show Simulation Delay\t\tToggle the Simulation Delay Entry on/off.",
541                     myToolBar4, FXWindow::ID_TOGGLESHOWN);
542     addToWindowsMenu(myWindowsMenu);
543     new FXMenuSeparator(myWindowsMenu);
544     new FXMenuCommand(myWindowsMenu, "Tile &Horizontally",
545                       GUIIconSubSys::getIcon(ICON_WINDOWS_TILE_HORI),
546                       myMDIClient, FXMDIClient::ID_MDI_TILEHORIZONTAL);
547     new FXMenuCommand(myWindowsMenu, "Tile &Vertically",
548                       GUIIconSubSys::getIcon(ICON_WINDOWS_TILE_VERT),
549                       myMDIClient, FXMDIClient::ID_MDI_TILEVERTICAL);
550     new FXMenuCommand(myWindowsMenu, "Cascade",
551                       GUIIconSubSys::getIcon(ICON_WINDOWS_CASCADE),
552                       myMDIClient, FXMDIClient::ID_MDI_CASCADE);
553     new FXMenuCommand(myWindowsMenu, "&Close", nullptr,
554                       myMDIClient, FXMDIClient::ID_MDI_CLOSE);
555     sep1 = new FXMenuSeparator(myWindowsMenu);
556     sep1->setTarget(myMDIClient);
557     sep1->setSelector(FXMDIClient::ID_MDI_ANY);
558     new FXMenuCommand(myWindowsMenu, "", nullptr, myMDIClient, FXMDIClient::ID_MDI_1);
559     new FXMenuCommand(myWindowsMenu, "", nullptr, myMDIClient, FXMDIClient::ID_MDI_2);
560     new FXMenuCommand(myWindowsMenu, "", nullptr, myMDIClient, FXMDIClient::ID_MDI_3);
561     new FXMenuCommand(myWindowsMenu, "", nullptr, myMDIClient, FXMDIClient::ID_MDI_4);
562     new FXMenuCommand(myWindowsMenu, "&Others...", nullptr, myMDIClient, FXMDIClient::ID_MDI_OVER_5);
563     new FXMenuSeparator(myWindowsMenu);
564     new FXMenuCommand(myWindowsMenu,
565                       "Clear Message Window\t\tClear the message window.",
566                       nullptr, this, MID_CLEARMESSAGEWINDOW);
567 
568     // build help menu
569     myHelpMenu = new FXMenuPane(this);
570     new FXMenuTitle(myMenuBar, "&Help", nullptr, myHelpMenu);
571     new FXMenuCommand(myHelpMenu, "&Online Documentation\tF1\tOpen Online documentation", nullptr, this, MID_HOTKEY_F1_ONLINEDOCUMENTATION);
572     new FXMenuCommand(myHelpMenu, "&About\tF2\tAbout sumo-gui", GUIIconSubSys::getIcon(ICON_SUMO_MINI), this, MID_HOTKEY_F2_ABOUT);
573 
574     //new FXButton(myMenuBar, "\t\tShows TraCI status", GUIIconSubSys::getIcon(ICON_ADD), this, MID_TRACI_STATUS, 0, 0, 0, 14, 14, 0, 0, 0, 0);
575 
576     // build SUMO Accelerators (hotkeys)
577     GUIShortcutsSubSys::buildSUMOAccelerators(this);
578 }
579 
580 
581 void
buildToolBars()582 GUIApplicationWindow::buildToolBars() {
583     // build tool bars
584     {
585         // file and simulation tool bar
586         myToolBarDrag1 = new FXToolBarShell(this, GUIDesignToolBar);
587         myToolBar1 = new FXToolBar(myTopDock, myToolBarDrag1, GUIDesignToolBarRaisedNextTop);
588         new FXToolBarGrip(myToolBar1, myToolBar1, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
589         // build file tools
590         new FXButton(myToolBar1, "\t\tOpen a simulation (Configuration file).", GUIIconSubSys::getIcon(ICON_OPEN_CONFIG), this, MID_OPEN_CONFIG, GUIDesignButtonToolbar);
591         new FXButton(myToolBar1, "\t\tOpen a network.", GUIIconSubSys::getIcon(ICON_OPEN_NET), this, MID_OPEN_NETWORK, GUIDesignButtonToolbar);
592         new FXButton(myToolBar1, "\t\tReloads the simulation / the network.", GUIIconSubSys::getIcon(ICON_RELOAD), this, MID_HOTKEY_CTRL_R_RELOAD, GUIDesignButtonToolbar);
593     }
594     {
595         // simulation toolbar
596         myToolBarDrag2 = new FXToolBarShell(this, GUIDesignToolBar);
597         myToolBar2 = new FXToolBar(myTopDock, myToolBarDrag2, GUIDesignToolBarRaisedSameTop);
598         new FXToolBarGrip(myToolBar2, myToolBar2, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
599         // build simulation tools
600         new FXButton(myToolBar2, "\t\tStart the loaded simulation.", GUIIconSubSys::getIcon(ICON_START), this, MID_HOTKEY_CTRL_A_STARTSIMULATION_OPENADDITIONALS, GUIDesignButtonToolbar);
601         new FXButton(myToolBar2, "\t\tStop the running simulation.", GUIIconSubSys::getIcon(ICON_STOP), this, MID_HOTKEY_CTRL_S_STOPSIMULATION_SAVENETWORK, GUIDesignButtonToolbar);
602         new FXButton(myToolBar2, "\t\tPerform a single simulation step.", GUIIconSubSys::getIcon(ICON_STEP), this, MID_HOTKEY_CTRL_D_SINGLESIMULATIONSTEP_OPENDEMAND, GUIDesignButtonToolbar);
603     }
604     {
605         // Simulation Step Display
606         myToolBarDrag3 = new FXToolBarShell(this, GUIDesignToolBar);
607         myToolBar3 = new FXToolBar(myTopDock, myToolBarDrag3, GUIDesignToolBarRaisedSameTop);
608         new FXToolBarGrip(myToolBar3, myToolBar3, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
609         new FXButton(myToolBar3, "Time:\t\tToggle between seconds and hour:minute:seconds display", nullptr, this, MID_TIME_TOOGLE, GUIDesignButtonToolbarText);
610 
611         myLCDLabel = new FXEX::FXLCDLabel(myToolBar3, 16, nullptr, 0, JUSTIFY_RIGHT);
612         myLCDLabel->setHorizontal(2);
613         myLCDLabel->setVertical(6);
614         myLCDLabel->setThickness(2);
615         myLCDLabel->setGroove(2);
616         myLCDLabel->setText("----------------");
617     }
618     {
619         // Simulation Delay
620         myToolBarDrag4 = new FXToolBarShell(this, GUIDesignToolBar);
621         myToolBar4 = new FXToolBar(myTopDock, myToolBarDrag4, GUIDesignToolBarRaisedSameTop);
622         new FXToolBarGrip(myToolBar4, myToolBar4, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
623         new FXButton(myToolBar4, "Delay (ms):\t\tDelay per simulated second. Click to toggle between the last two delay values", nullptr, this, MID_DELAY_TOOGLE, GUIDesignButtonToolbarText);
624 
625         mySimDelay = 0;
626         mySimDelayTarget = new FXDataTarget(mySimDelay);
627         mySimDelaySpinner = new FXRealSpinner(myToolBar4, 7, mySimDelayTarget, FXDataTarget::ID_VALUE, GUIDesignSpinDial);
628         mySimDelaySlider = new FXSlider(myToolBar4, mySimDelayTarget, FXDataTarget::ID_VALUE, LAYOUT_FIX_WIDTH | SLIDER_ARROW_UP | SLIDER_TICKS_TOP, 0, 0, 300, 10, 0, 0, 5, 0);
629         mySimDelaySlider->setRange(0, 1000);
630         mySimDelaySlider->setHeadSize(10);
631         mySimDelaySlider->setIncrement(50);
632         mySimDelaySlider->setTickDelta(100);
633         mySimDelaySlider->setValue((int)mySimDelay);
634         //mySimDelayTarget->setNumberFormat(0);
635         //mySimDelayTarget->setIncrements(1, 10, 10);
636         mySimDelaySpinner->setIncrement(10);
637         mySimDelaySpinner->setRange(0, 10000);
638         mySimDelaySpinner->setValue(mySimDelay);
639     }
640     {
641         // Scale traffic (flows and incrementally loaded vehicles)
642         myToolBarDrag8 = new FXToolBarShell(this, GUIDesignToolBar);
643         myToolBar8 = new FXToolBar(myTopDock, myToolBarDrag8, GUIDesignToolBarRaisedSameTop);
644         new FXToolBarGrip(myToolBar8, myToolBar8, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
645         new FXLabel(myToolBar8, "Scale Traffic:\t\tScale traffic from flows and vehicles that are loaded incrementally from route files", nullptr, LAYOUT_TOP | LAYOUT_LEFT);
646         myDemandScaleSpinner = new FXRealSpinner(myToolBar8, 7, this, MID_DEMAND_SCALE, GUIDesignSpinDial);
647         myDemandScaleSpinner->setIncrement(0.5);
648         myDemandScaleSpinner->setRange(0, 1000);
649         myDemandScaleSpinner->setValue(1);
650     }
651     {
652         // Views
653         myToolBarDrag5 = new FXToolBarShell(this, GUIDesignToolBar);
654         myToolBar5 = new FXToolBar(myTopDock, myToolBarDrag5, GUIDesignToolBarRaisedSameTop);
655         new FXToolBarGrip(myToolBar5, myToolBar5, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
656         // build view tools
657         new FXButton(myToolBar5, "\t\tOpen a new microscopic view.",
658                      GUIIconSubSys::getIcon(ICON_MICROVIEW), this, MID_NEW_MICROVIEW, GUIDesignButtonToolbar);
659 #ifdef HAVE_OSG
660         new FXButton(myToolBar5, "\t\tOpen a new 3D view.",
661                      GUIIconSubSys::getIcon(ICON_OSGVIEW), this, MID_NEW_OSGVIEW, GUIDesignButtonToolbar);
662 #endif
663     }
664     {
665         /// game specific stuff
666         // total waitingTime
667         myToolBarDrag6 = new FXToolBarShell(this, GUIDesignToolBar);
668         myToolBar6 = new FXToolBar(myTopDock, myToolBarDrag6, GUIDesignToolBarRaisedSameTop);
669         new FXToolBarGrip(myToolBar6, myToolBar6, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
670         new FXLabel(myToolBar6, "Waiting Time:\t\tTime spent waiting accumulated for all vehicles", nullptr, LAYOUT_TOP | LAYOUT_LEFT);
671         myWaitingTimeLabel = new FXEX::FXLCDLabel(myToolBar6, 13, nullptr, 0, JUSTIFY_RIGHT);
672         myWaitingTimeLabel->setHorizontal(2);
673         myWaitingTimeLabel->setVertical(6);
674         myWaitingTimeLabel->setThickness(2);
675         myWaitingTimeLabel->setGroove(2);
676         myWaitingTimeLabel->setText("-------------");
677 
678         // idealistic time loss
679         myToolBarDrag7 = new FXToolBarShell(this, GUIDesignToolBar);
680         myToolBar7 = new FXToolBar(myTopDock, myToolBarDrag7, GUIDesignToolBarRaisedSameTop);
681         new FXToolBarGrip(myToolBar7, myToolBar7, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
682         new FXLabel(myToolBar7, "Time Loss:\t\tTime lost due to being unable to drive with maximum speed for all vehicles", nullptr, LAYOUT_TOP | LAYOUT_LEFT);
683         myTimeLossLabel = new FXEX::FXLCDLabel(myToolBar7, 13, nullptr, 0, JUSTIFY_RIGHT);
684         myTimeLossLabel->setHorizontal(2);
685         myTimeLossLabel->setVertical(6);
686         myTimeLossLabel->setThickness(2);
687         myTimeLossLabel->setGroove(2);
688         myTimeLossLabel->setText("-------------");
689 
690         // total driving distance
691         myToolBarDrag9 = new FXToolBarShell(this, GUIDesignToolBar);
692         myToolBar9 = new FXToolBar(myTopDock, myToolBarDrag9, GUIDesignToolBarRaisedSameTop);
693         new FXToolBarGrip(myToolBar9, myToolBar9, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
694         new FXLabel(myToolBar9, "Distance (km):\t\tTotal distance driven by DRT vehicles", nullptr, LAYOUT_TOP | LAYOUT_LEFT);
695         myTotalDistanceLabel = new FXEX::FXLCDLabel(myToolBar9, 13, nullptr, 0, JUSTIFY_RIGHT);
696         myTotalDistanceLabel->setHorizontal(2);
697         myTotalDistanceLabel->setVertical(6);
698         myTotalDistanceLabel->setThickness(2);
699         myTotalDistanceLabel->setGroove(2);
700         myTotalDistanceLabel->setText("-------------");
701     }
702 }
703 
704 
705 long
onCmdQuit(FXObject *,FXSelector,void *)706 GUIApplicationWindow::onCmdQuit(FXObject*, FXSelector, void*) {
707     storeWindowSizeAndPos();
708     getApp()->reg().writeStringEntry("SETTINGS", "basedir", gCurrentFolder.text());
709     getApp()->reg().writeIntEntry("SETTINGS", "maximized", isMaximized() ? 1 : 0);
710     getApp()->reg().writeIntEntry("gui", "timeasHMS", myShowTimeAsHMS ? 1 : 0);
711     getApp()->reg().writeIntEntry("gui", "alternateSimDelay", (int)myAlternateSimDelay);
712     getApp()->exit(0);
713     return 1;
714 }
715 
716 
717 long
onCmdEditChosen(FXObject * menu,FXSelector,void *)718 GUIApplicationWindow::onCmdEditChosen(FXObject* menu, FXSelector, void*) {
719     FXMenuCommand* mc = dynamic_cast<FXMenuCommand*>(menu);
720     if (mc->getText() == "Edit Selected...") {
721         GUIDialog_GLChosenEditor* chooser =
722             new GUIDialog_GLChosenEditor(this, &gSelected);
723         chooser->create();
724         chooser->show();
725     } else {
726         if (!myAmLoading && myRunThread->simulationAvailable()) {
727             const SUMOVehicleClass svc = SumoVehicleClassStrings.get(mc->getText().text());
728             for (MSEdgeVector::const_iterator i = MSEdge::getAllEdges().begin(); i != MSEdge::getAllEdges().end(); ++i) {
729                 const std::vector<MSLane*>& lanes = (*i)->getLanes();
730                 for (std::vector<MSLane*>::const_iterator it = lanes.begin(); it != lanes.end(); ++it) {
731                     GUILane* lane = dynamic_cast<GUILane*>(*it);
732                     assert(lane != 0);
733                     if ((lane->getPermissions() & svc) != 0) {
734                         gSelected.select(lane->getGlID());
735                     }
736                 }
737             }
738             if (myMDIClient->numChildren() > 0) {
739                 GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
740                 if (w != nullptr) {
741                     // color by selection
742                     w->getView()->getVisualisationSettings()->laneColorer.setActive(1);
743                 }
744             }
745         }
746         updateChildren();
747     }
748     return 1;
749 }
750 
751 
752 long
onCmdEditBreakpoints(FXObject *,FXSelector,void *)753 GUIApplicationWindow::onCmdEditBreakpoints(FXObject*, FXSelector, void*) {
754     GUIDialog_Breakpoints* chooser = new GUIDialog_Breakpoints(this, myRunThread->getBreakpoints(), myRunThread->getBreakpointLock());
755     chooser->create();
756     chooser->show();
757     return 1;
758 }
759 
760 long
onCmdEditViewport(FXObject *,FXSelector,void *)761 GUIApplicationWindow::onCmdEditViewport(FXObject*, FXSelector, void*) {
762     if (!myGLWindows.empty()) {
763         myGLWindows[0]->getView()->showViewportEditor();
764     }
765     return 1;
766 }
767 
768 
769 long
onCmdEditViewScheme(FXObject *,FXSelector,void *)770 GUIApplicationWindow::onCmdEditViewScheme(FXObject*, FXSelector, void*) {
771     if (!myGLWindows.empty()) {
772         myGLWindows[0]->getView()->showViewschemeEditor();
773     }
774     return 1;
775 }
776 
777 
778 long
onCmdHelp(FXObject *,FXSelector,void *)779 GUIApplicationWindow::onCmdHelp(FXObject*, FXSelector, void*) {
780     FXLinkLabel::fxexecute("https://sumo.dlr.de/wiki/SUMO-GUI");
781     return 1;
782 }
783 
784 
785 long
onCmdNetedit(FXObject *,FXSelector,void *)786 GUIApplicationWindow::onCmdNetedit(FXObject*, FXSelector, void*) {
787     if (myGLWindows.empty()) {
788         return 1;
789     }
790     FXRegistry reg("SUMO netedit", "Eclipse");
791     reg.read();
792     const GUISUMOAbstractView* const v = myGLWindows[0]->getView();
793     reg.writeRealEntry("viewport", "x", v->getChanger().getXPos());
794     reg.writeRealEntry("viewport", "y", v->getChanger().getYPos());
795     reg.writeRealEntry("viewport", "z", v->getChanger().getZPos());
796     reg.write();
797     std::string netedit = "netedit";
798     const char* sumoPath = getenv("SUMO_HOME");
799     if (sumoPath != nullptr) {
800         std::string newPath = std::string(sumoPath) + "/bin/netedit";
801         if (FileHelpers::isReadable(newPath) || FileHelpers::isReadable(newPath + ".exe")) {
802             netedit = "\"" + newPath + "\"";
803         }
804     }
805     std::string cmd = netedit + " --registry-viewport -s "  + OptionsCont::getOptions().getString("net-file");
806     // start in background
807 #ifndef WIN32
808     cmd = cmd + " &";
809 #else
810     // see "help start" for the parameters
811     cmd = "start /B \"\" " + cmd;
812 #endif
813     WRITE_MESSAGE("Running " + cmd + ".");
814     // yay! fun with dangerous commands... Never use this over the internet
815     SysUtils::runHiddenCommand(cmd);
816     return 1;
817 }
818 
819 
820 long
onCmdOpenConfiguration(FXObject *,FXSelector,void *)821 GUIApplicationWindow::onCmdOpenConfiguration(FXObject*, FXSelector, void*) {
822     // get the new file name
823     FXFileDialog opendialog(this, "Open Simulation Configuration");
824     opendialog.setIcon(GUIIconSubSys::getIcon(ICON_EMPTY));
825     opendialog.setSelectMode(SELECTFILE_EXISTING);
826     opendialog.setPatternList(myConfigPattern.c_str());
827     if (gCurrentFolder.length() != 0) {
828         opendialog.setDirectory(gCurrentFolder);
829     }
830     if (opendialog.execute()) {
831         gCurrentFolder = opendialog.getDirectory();
832         std::string file = opendialog.getFilename().text();
833         loadConfigOrNet(file, false);
834         myRecentConfigs.appendFile(file.c_str());
835     }
836     return 1;
837 }
838 
839 
840 long
onCmdOpenNetwork(FXObject *,FXSelector,void *)841 GUIApplicationWindow::onCmdOpenNetwork(FXObject*, FXSelector, void*) {
842     // get the new file name
843     FXFileDialog opendialog(this, "Open Network");
844     opendialog.setIcon(GUIIconSubSys::getIcon(ICON_EMPTY));
845     opendialog.setSelectMode(SELECTFILE_EXISTING);
846     opendialog.setPatternList("SUMO nets (*.net.xml)\nAll files (*)");
847     if (gCurrentFolder.length() != 0) {
848         opendialog.setDirectory(gCurrentFolder);
849     }
850     if (opendialog.execute()) {
851         gCurrentFolder = opendialog.getDirectory();
852         std::string file = opendialog.getFilename().text();
853         loadConfigOrNet(file, true);
854         myRecentNets.appendFile(file.c_str());
855     }
856     return 1;
857 }
858 
859 
860 long
onCmdOpenShapes(FXObject *,FXSelector,void *)861 GUIApplicationWindow::onCmdOpenShapes(FXObject*, FXSelector, void*) {
862     // get the shape file name
863     FXFileDialog opendialog(this, "Open Shapes");
864     opendialog.setIcon(GUIIconSubSys::getIcon(ICON_EMPTY));
865     opendialog.setSelectMode(SELECTFILE_EXISTING);
866     opendialog.setPatternList("Additional files (*.xml)\nAll files (*)");
867     if (gCurrentFolder.length() != 0) {
868         opendialog.setDirectory(gCurrentFolder);
869     }
870     if (opendialog.execute()) {
871         gCurrentFolder = opendialog.getDirectory();
872         std::string file = opendialog.getFilename().text();
873 
874         dynamic_cast<GUIShapeContainer&>(myRunThread->getNet().getShapeContainer()).allowReplacement();
875         NLShapeHandler handler(file, myRunThread->getNet().getShapeContainer());
876         if (!XMLSubSys::runParser(handler, file, false)) {
877             WRITE_MESSAGE("Loading of " + file + " failed.");
878         }
879         update();
880         if (myMDIClient->numChildren() > 0) {
881             GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
882             if (w != nullptr) {
883                 w->getView()->update();
884             }
885         }
886     }
887     return 1;
888 }
889 
890 long
onCmdOpenEdgeData(FXObject *,FXSelector,void *)891 GUIApplicationWindow::onCmdOpenEdgeData(FXObject*, FXSelector, void*) {
892     // get the shape file name
893     FXFileDialog opendialog(this, "Open EdgeData");
894     opendialog.setIcon(GUIIconSubSys::getIcon(ICON_EMPTY));
895     opendialog.setSelectMode(SELECTFILE_EXISTING);
896     opendialog.setPatternList("EdgeData files (*.xml)\nAll files (*)");
897     if (gCurrentFolder.length() != 0) {
898         opendialog.setDirectory(gCurrentFolder);
899     }
900     if (opendialog.execute()) {
901         gCurrentFolder = opendialog.getDirectory();
902         std::string file = opendialog.getFilename().text();
903         if (!GUINet::getGUIInstance()->loadEdgeData(file)) {
904             WRITE_MESSAGE("Loading of " + file + " failed.");
905         }
906         update();
907         if (myMDIClient->numChildren() > 0) {
908             GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
909             if (w != nullptr) {
910                 w->getView()->update();
911             }
912         }
913     }
914     return 1;
915 }
916 
917 long
onCmdReload(FXObject *,FXSelector,void *)918 GUIApplicationWindow::onCmdReload(FXObject*, FXSelector, void*) {
919     storeWindowSizeAndPos();
920     getApp()->beginWaitCursor();
921     myAmLoading = true;
922     closeAllWindows();
923     myLoadThread->start();
924     setStatusBarText("Reloading.");
925     update();
926     return 1;
927 }
928 
929 
930 long
onCmdOpenRecent(FXObject * sender,FXSelector,void * data)931 GUIApplicationWindow::onCmdOpenRecent(FXObject* sender, FXSelector, void* data) {
932     if (myAmLoading) {
933         myStatusbar->getStatusLine()->setText("Already loading!");
934         return 1;
935     }
936     std::string file((const char*)data);
937     loadConfigOrNet(file, sender == &myRecentNets);
938     return 1;
939 }
940 
941 
942 long
onCmdClose(FXObject *,FXSelector,void *)943 GUIApplicationWindow::onCmdClose(FXObject*, FXSelector, void*) {
944     closeAllWindows();
945     return 1;
946 }
947 
948 
949 long
onUpdOpen(FXObject * sender,FXSelector,void * ptr)950 GUIApplicationWindow::onUpdOpen(FXObject* sender, FXSelector, void* ptr) {
951     sender->handle(this,
952                    myAmLoading ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
953                    ptr);
954     return 1;
955 }
956 
957 
958 long
onUpdReload(FXObject * sender,FXSelector,void * ptr)959 GUIApplicationWindow::onUpdReload(FXObject* sender, FXSelector, void* ptr) {
960     sender->handle(this,
961                    myAmLoading || myLoadThread->getFileName() == "" || TraCIServer::getInstance() != nullptr
962                    ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
963                    ptr);
964     return 1;
965 }
966 
967 
968 long
onUpdOpenRecent(FXObject * sender,FXSelector,void * ptr)969 GUIApplicationWindow::onUpdOpenRecent(FXObject* sender, FXSelector, void* ptr) {
970     sender->handle(this,
971                    myAmLoading ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
972                    ptr);
973     return 1;
974 }
975 
976 
977 long
onUpdAddView(FXObject * sender,FXSelector,void * ptr)978 GUIApplicationWindow::onUpdAddView(FXObject* sender, FXSelector, void* ptr) {
979     sender->handle(this,
980                    myAmLoading || !myRunThread->simulationAvailable()
981                    ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
982                    ptr);
983     return 1;
984 }
985 
986 
987 long
onCmdStart(FXObject *,FXSelector,void *)988 GUIApplicationWindow::onCmdStart(FXObject*, FXSelector, void*) {
989     // check whether a net was loaded successfully
990     if (!myRunThread->simulationAvailable()) {
991         myStatusbar->getStatusLine()->setText("No simulation loaded!");
992         return 1;
993     }
994     // check whether it was started before and paused;
995     if (!myWasStarted) {
996         myRunThread->begin();
997         myWasStarted = true;
998     }
999     myRunThread->resume();
1000     getApp()->forceRefresh(); // only callking myToolBar2->forceRefresh somehow loses keyboard focus
1001     return 1;
1002 }
1003 
1004 
1005 long
onCmdStop(FXObject *,FXSelector,void *)1006 GUIApplicationWindow::onCmdStop(FXObject*, FXSelector, void*) {
1007     myRunThread->stop();
1008     getApp()->forceRefresh(); // only callking myToolBar2->forceRefresh somehow loses keyboard focus
1009     return 1;
1010 }
1011 
1012 
1013 long
onCmdStep(FXObject *,FXSelector,void *)1014 GUIApplicationWindow::onCmdStep(FXObject*, FXSelector, void*) {
1015     // check whether a net was loaded successfully
1016     if (!myRunThread->simulationAvailable()) {
1017         myStatusbar->getStatusLine()->setText("No simulation loaded!");
1018         return 1;
1019     }
1020     // check whether it was started before and paused;
1021     if (!myWasStarted) {
1022         myRunThread->begin();
1023         myWasStarted = true;
1024     }
1025     myRunThread->singleStep();
1026     return 1;
1027 }
1028 
1029 
1030 long
onCmdSaveState(FXObject *,FXSelector,void *)1031 GUIApplicationWindow::onCmdSaveState(FXObject*, FXSelector, void*) {
1032     // get the new file name
1033     FXFileDialog opendialog(this, "Save Simulation State");
1034     opendialog.setIcon(GUIIconSubSys::getIcon(ICON_SAVE));
1035     opendialog.setSelectMode(SELECTFILE_ANY);
1036     opendialog.setPatternList("Binary State (*.sbx)\nXML State (*.xml)");
1037     if (gCurrentFolder.length() != 0) {
1038         opendialog.setDirectory(gCurrentFolder);
1039     }
1040     if (!opendialog.execute() || !MFXUtils::userPermitsOverwritingWhenFileExists(this, opendialog.getFilename())) {
1041         return 1;
1042     }
1043 
1044     FXString file = MFXUtils::assureExtension(opendialog.getFilename(),
1045                     opendialog.getPatternText(opendialog.getCurrentPattern()).after('.').before(')'));
1046     MSStateHandler::saveState(file.text(), MSNet::getInstance()->getCurrentTimeStep());
1047     myStatusbar->getStatusLine()->setText("Simulation saved to " + file);
1048     return 1;
1049 }
1050 
1051 
1052 long
onCmdTimeToggle(FXObject *,FXSelector,void *)1053 GUIApplicationWindow::onCmdTimeToggle(FXObject*, FXSelector, void*) {
1054     myShowTimeAsHMS = !myShowTimeAsHMS;
1055     if (myRunThread->simulationAvailable()) {
1056         updateTimeLCD(myRunThread->getNet().getCurrentTimeStep());
1057     }
1058     return 1;
1059 }
1060 
1061 
1062 long
onCmdDelayToggle(FXObject *,FXSelector,void *)1063 GUIApplicationWindow::onCmdDelayToggle(FXObject*, FXSelector, void*) {
1064     const double tmp = myAlternateSimDelay;
1065     myAlternateSimDelay = mySimDelay;
1066     mySimDelay = tmp;
1067     return 1;
1068 }
1069 
1070 
1071 long
onCmdDemandScale(FXObject *,FXSelector,void *)1072 GUIApplicationWindow::onCmdDemandScale(FXObject*, FXSelector, void*) {
1073     if (myRunThread->simulationAvailable()) {
1074         myRunThread->getNet().getVehicleControl().setScale(myDemandScaleSpinner->getValue());
1075     }
1076     return 1;
1077 }
1078 
1079 
1080 long
onCmdClearMsgWindow(FXObject *,FXSelector,void *)1081 GUIApplicationWindow::onCmdClearMsgWindow(FXObject*, FXSelector, void*) {
1082     myMessageWindow->clear();
1083     return 1;
1084 }
1085 
1086 
1087 long
onUpdStart(FXObject * sender,FXSelector,void * ptr)1088 GUIApplicationWindow::onUpdStart(FXObject* sender, FXSelector, void* ptr) {
1089     sender->handle(this,
1090                    !myRunThread->simulationIsStartable() || myAmLoading
1091                    ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1092                    ptr);
1093     return 1;
1094 }
1095 
1096 
1097 long
onUpdStop(FXObject * sender,FXSelector,void * ptr)1098 GUIApplicationWindow::onUpdStop(FXObject* sender, FXSelector, void* ptr) {
1099     sender->handle(this,
1100                    !myRunThread->simulationIsStopable() || myAmLoading
1101                    ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1102                    ptr);
1103     return 1;
1104 }
1105 
1106 
1107 long
onUpdStep(FXObject * sender,FXSelector,void * ptr)1108 GUIApplicationWindow::onUpdStep(FXObject* sender, FXSelector, void* ptr) {
1109     sender->handle(this,
1110                    !myRunThread->simulationIsStepable() || myAmLoading
1111                    ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1112                    ptr);
1113     return 1;
1114 }
1115 
1116 
1117 long
onUpdNeedsSimulation(FXObject * sender,FXSelector,void * ptr)1118 GUIApplicationWindow::onUpdNeedsSimulation(FXObject* sender, FXSelector, void* ptr) {
1119     bool disable = !myRunThread->simulationAvailable() || myAmLoading;
1120     sender->handle(this, disable ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
1121     // mySelectLanesMenuCascade has to be disabled manually
1122     if (disable) {
1123         mySelectLanesMenuCascade->disable();
1124     } else {
1125         mySelectLanesMenuCascade->enable();
1126     }
1127     return 1;
1128 }
1129 
1130 long
onUpdTraCIStatus(FXObject * sender,FXSelector,void * ptr)1131 GUIApplicationWindow::onUpdTraCIStatus(FXObject* sender, FXSelector, void* ptr) {
1132     sender->handle(this, TraCIServer::getInstance() == nullptr ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
1133     return 1;
1134 }
1135 
1136 
1137 long
onCmdLocate(FXObject *,FXSelector sel,void *)1138 GUIApplicationWindow::onCmdLocate(FXObject*, FXSelector sel, void*) {
1139     if (myMDIClient->numChildren() > 0) {
1140         GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1141         if (w != nullptr) {
1142             w->onCmdLocate(nullptr, sel, nullptr);
1143         }
1144     }
1145     return 1;
1146 }
1147 
1148 
1149 long
onCmdShowStats(FXObject *,FXSelector,void *)1150 GUIApplicationWindow::onCmdShowStats(FXObject*, FXSelector, void*) {
1151     if (myMDIClient->numChildren() > 0) {
1152         GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1153         GUINet::getGUIInstance()->getParameterWindow(*this, *w->getView());
1154     }
1155     return 1;
1156 }
1157 
1158 
1159 long
onCmdAppSettings(FXObject *,FXSelector,void *)1160 GUIApplicationWindow::onCmdAppSettings(FXObject*, FXSelector, void*) {
1161     GUIDialog_AppSettings* d = new GUIDialog_AppSettings(this);
1162     d->create();
1163     d->show(PLACEMENT_OWNER);
1164     return 1;
1165 }
1166 
1167 
1168 long
onCmdGaming(FXObject *,FXSelector,void *)1169 GUIApplicationWindow::onCmdGaming(FXObject*, FXSelector, void*) {
1170     myAmGaming = !myAmGaming;
1171     if (myAmGaming) {
1172         myMenuBar->hide();
1173         myStatusbar->hide();
1174         myToolBar1->hide();
1175         myToolBar2->hide();
1176         myToolBar4->hide();
1177         myToolBar5->hide();
1178         myToolBar6->show();
1179         myToolBar8->hide();
1180         if (myTLSGame) {
1181             myToolBar7->show();
1182         } else {
1183             myToolBar9->show();
1184         }
1185         myMessageWindow->hide();
1186         myLCDLabel->setFgColor(MFXUtils::getFXColor(RGBColor::RED));
1187         myWaitingTimeLabel->setFgColor(MFXUtils::getFXColor(RGBColor::RED));
1188         myTimeLossLabel->setFgColor(MFXUtils::getFXColor(RGBColor::RED));
1189         myTotalDistanceLabel->setFgColor(MFXUtils::getFXColor(RGBColor::RED));
1190         gSchemeStorage.getDefault().gaming = true;
1191     } else {
1192         myMenuBar->show();
1193         myStatusbar->show();
1194         myToolBar1->show();
1195         myToolBar2->show();
1196         myToolBar4->show();
1197         myToolBar5->show();
1198         myToolBar6->hide();
1199         myToolBar7->hide();
1200         myToolBar8->show();
1201         myToolBar9->hide();
1202         myMessageWindow->show();
1203         myLCDLabel->setFgColor(MFXUtils::getFXColor(RGBColor::GREEN));
1204         gSchemeStorage.getDefault().gaming = false;
1205     }
1206     if (myMDIClient->numChildren() > 0) {
1207         GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1208         if (w != nullptr) {
1209             w->setToolBarVisibility(!myAmGaming && !myAmFullScreen);
1210         }
1211     }
1212     update();
1213     return 1;
1214 }
1215 
1216 
1217 long
onCmdFullScreen(FXObject *,FXSelector,void *)1218 GUIApplicationWindow::onCmdFullScreen(FXObject*, FXSelector, void*) {
1219     myAmFullScreen = !myAmFullScreen;
1220     if (myAmFullScreen) {
1221         getApp()->reg().writeIntEntry("SETTINGS", "x", getX());
1222         getApp()->reg().writeIntEntry("SETTINGS", "y", getY());
1223         getApp()->reg().writeIntEntry("SETTINGS", "width", getWidth());
1224         getApp()->reg().writeIntEntry("SETTINGS", "height", getHeight());
1225         maximize();
1226         setDecorations(DECOR_NONE);
1227         place(PLACEMENT_MAXIMIZED);
1228         myMenuBar->hide();
1229         myStatusbar->hide();
1230         myToolBar1->hide();
1231         myToolBar2->hide();
1232         myToolBar3->hide();
1233         myToolBar4->hide();
1234         myToolBar5->hide();
1235         myToolBar6->hide();
1236         myToolBar7->hide();
1237         myToolBar8->hide();
1238         myMessageWindow->hide();
1239         if (myMDIClient->numChildren() > 0) {
1240             GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1241             if (w != nullptr) {
1242                 w->setToolBarVisibility(false);
1243             }
1244         }
1245         update();
1246     } else {
1247         place(PLACEMENT_VISIBLE);
1248         setDecorations(DECOR_ALL);
1249         restore();
1250         myToolBar3->show();
1251         myAmGaming = !myAmGaming;
1252         onCmdGaming(nullptr, 0, nullptr);
1253         setWidth(getApp()->reg().readIntEntry("SETTINGS", "width", 600));
1254         setHeight(getApp()->reg().readIntEntry("SETTINGS", "height", 400));
1255         setX(getApp()->reg().readIntEntry("SETTINGS", "x", 150));
1256         setY(getApp()->reg().readIntEntry("SETTINGS", "y", 150));
1257     }
1258     return 1;
1259 }
1260 
1261 
1262 long
onCmdListInternal(FXObject *,FXSelector,void *)1263 GUIApplicationWindow::onCmdListInternal(FXObject*, FXSelector, void*) {
1264     myListInternal = !myListInternal;
1265     return 1;
1266 }
1267 
1268 
1269 long
onCmdListParking(FXObject *,FXSelector,void *)1270 GUIApplicationWindow::onCmdListParking(FXObject*, FXSelector, void*) {
1271     myListParking = !myListParking;
1272     return 1;
1273 }
1274 
1275 long
onCmdListTeleporting(FXObject *,FXSelector,void *)1276 GUIApplicationWindow::onCmdListTeleporting(FXObject*, FXSelector, void*) {
1277     myListTeleporting = !myListTeleporting;
1278     return 1;
1279 }
1280 
1281 
1282 long
onCmdNewView(FXObject *,FXSelector,void *)1283 GUIApplicationWindow::onCmdNewView(FXObject*, FXSelector, void*) {
1284     openNewView(GUISUMOViewParent::VIEW_2D_OPENGL);
1285     return 1;
1286 }
1287 
1288 
1289 #ifdef HAVE_OSG
1290 long
onCmdNewOSG(FXObject *,FXSelector,void *)1291 GUIApplicationWindow::onCmdNewOSG(FXObject*, FXSelector, void*) {
1292     openNewView(GUISUMOViewParent::VIEW_3D_OSG);
1293     return 1;
1294 }
1295 #endif
1296 
1297 
1298 long
onCmdAbout(FXObject *,FXSelector,void *)1299 GUIApplicationWindow::onCmdAbout(FXObject*, FXSelector, void*) {
1300     GUIDialog_AboutSUMO* about = new GUIDialog_AboutSUMO(this);
1301     about->create();
1302     about->show(PLACEMENT_OWNER);
1303     return 1;
1304 }
1305 
1306 
onClipboardRequest(FXObject *,FXSelector,void * ptr)1307 long GUIApplicationWindow::onClipboardRequest(FXObject* /* sender */, FXSelector /* sel */, void* ptr) {
1308     FXEvent* event = (FXEvent*)ptr;
1309     FXString string = GUIUserIO::clipped.c_str();
1310     setDNDData(FROM_CLIPBOARD, event->target, string);
1311     return 1;
1312 }
1313 
1314 
1315 long
onLoadThreadEvent(FXObject *,FXSelector,void *)1316 GUIApplicationWindow::onLoadThreadEvent(FXObject*, FXSelector, void*) {
1317     eventOccurred();
1318     return 1;
1319 }
1320 
1321 
1322 long
onRunThreadEvent(FXObject *,FXSelector,void *)1323 GUIApplicationWindow::onRunThreadEvent(FXObject*, FXSelector, void*) {
1324     eventOccurred();
1325     return 1;
1326 }
1327 
1328 
1329 void
eventOccurred()1330 GUIApplicationWindow::eventOccurred() {
1331     while (!myEvents.empty()) {
1332         // get the next event
1333         GUIEvent* e = myEvents.top();
1334         myEvents.pop();
1335         // process
1336         switch (e->getOwnType()) {
1337             case EVENT_SIMULATION_LOADED:
1338                 handleEvent_SimulationLoaded(e);
1339                 break;
1340             case EVENT_SIMULATION_STEP:
1341                 if (myRunThread->simulationAvailable()) { // avoid race-condition related crash if reload was pressed
1342                     handleEvent_SimulationStep(e);
1343                 }
1344                 break;
1345             case EVENT_MESSAGE_OCCURRED:
1346             case EVENT_WARNING_OCCURRED:
1347             case EVENT_ERROR_OCCURRED:
1348             case EVENT_DEBUG_OCCURRED:
1349             case EVENT_GLDEBUG_OCCURRED:
1350             case EVENT_STATUS_OCCURRED:
1351                 handleEvent_Message(e);
1352                 break;
1353             case EVENT_SIMULATION_ENDED:
1354                 handleEvent_SimulationEnded(e);
1355                 break;
1356             default:
1357                 break;
1358         }
1359         delete e;
1360     }
1361     myToolBar2->forceRefresh();
1362     myToolBar3->forceRefresh();
1363 }
1364 
1365 
1366 void
handleEvent_SimulationLoaded(GUIEvent * e)1367 GUIApplicationWindow::handleEvent_SimulationLoaded(GUIEvent* e) {
1368     myAmLoading = false;
1369     GUIEvent_SimulationLoaded* ec = static_cast<GUIEvent_SimulationLoaded*>(e);
1370     // check whether the loading was successfull
1371     if (ec->myNet == nullptr) {
1372         // report failure
1373         setStatusBarText("Loading of '" + ec->myFile + "' failed!");
1374         if (GUIGlobals::gQuitOnEnd) {
1375             closeAllWindows();
1376             getApp()->exit(1);
1377         }
1378     } else {
1379         // initialise simulation thread
1380         if (!myRunThread->init(ec->myNet, ec->myBegin, ec->myEnd)) {
1381             if (GUIGlobals::gQuitOnEnd) {
1382                 closeAllWindows();
1383                 getApp()->exit(1);
1384             }
1385         } else {
1386             // report success
1387             setStatusBarText("'" + ec->myFile + "' loaded.");
1388             setWindowSizeAndPos();
1389             myWasStarted = false;
1390             myHaveNotifiedAboutSimEnd = false;
1391             // initialise views
1392             myViewNumber = 0;
1393             const GUISUMOViewParent::ViewType defaultType = ec->myOsgView ? GUISUMOViewParent::VIEW_3D_OSG : GUISUMOViewParent::VIEW_2D_OPENGL;
1394             if (ec->mySettingsFiles.size() > 0) {
1395                 // open a view for each file and apply settings
1396                 for (std::vector<std::string>::const_iterator it = ec->mySettingsFiles.begin(); it != ec->mySettingsFiles.end(); ++it) {
1397                     GUISettingsHandler settings(*it);
1398                     GUISUMOViewParent::ViewType vt = defaultType;
1399                     if (settings.getViewType() == "osg" || settings.getViewType() == "3d") {
1400                         vt = GUISUMOViewParent::VIEW_3D_OSG;
1401                     }
1402                     if (settings.getViewType() == "opengl" || settings.getViewType() == "2d") {
1403                         vt = GUISUMOViewParent::VIEW_2D_OPENGL;
1404                     }
1405                     GUISUMOAbstractView* view = openNewView(vt);
1406                     if (view == nullptr) {
1407                         break;
1408                     }
1409                     std::string settingsName = settings.addSettings(view);
1410                     view->addDecals(settings.getDecals());
1411                     settings.applyViewport(view);
1412                     settings.setSnapshots(view);
1413                     if (settings.getDelay() > 0.) {
1414                         mySimDelay = settings.getDelay();
1415                     }
1416                     if (settings.getBreakpoints().size() > 0) {
1417                         myRunThread->getBreakpointLock().lock();
1418                         myRunThread->getBreakpoints().assign(settings.getBreakpoints().begin(), settings.getBreakpoints().end());
1419                         myRunThread->getBreakpointLock().unlock();
1420                     }
1421                     if (!OptionsCont::getOptions().isDefault("breakpoints")) {
1422                         std::vector<SUMOTime> breakpoints;
1423                         for (const std::string& val : OptionsCont::getOptions().getStringVector("breakpoints")) {
1424                             breakpoints.push_back(string2time(val));
1425                         }
1426                         std::sort(breakpoints.begin(), breakpoints.end());
1427                         myRunThread->getBreakpointLock().lock();
1428                         myRunThread->getBreakpoints().assign(breakpoints.begin(), breakpoints.end());
1429                         myRunThread->getBreakpointLock().unlock();
1430                     }
1431                     myJamSounds = settings.getEventDistribution("jam");
1432                     myCollisionSounds = settings.getEventDistribution("collision");
1433                     if (settings.getJamSoundTime() > 0) {
1434                         myJamSoundTime = settings.getJamSoundTime();
1435                     }
1436                 }
1437             } else {
1438                 openNewView(defaultType);
1439             }
1440             if (!OptionsCont::getOptions().isDefault("breakpoints")) {
1441                 std::vector<SUMOTime> breakpoints;
1442                 for (const std::string& val : OptionsCont::getOptions().getStringVector("breakpoints")) {
1443                     breakpoints.push_back(string2time(val));
1444                 }
1445                 std::sort(breakpoints.begin(), breakpoints.end());
1446                 myRunThread->getBreakpointLock().lock();
1447                 myRunThread->getBreakpoints().assign(breakpoints.begin(), breakpoints.end());
1448                 myRunThread->getBreakpointLock().unlock();
1449             }
1450 
1451             if (OptionsCont::getOptions().getBool("game")) {
1452                 if (OptionsCont::getOptions().getString("game.mode") == "tls") {
1453                     myTLSGame = true;
1454                     setTitle("SUMO Interactive Traffic Light");
1455                 } else {
1456                     myTLSGame = false;
1457                     setTitle("SUMO Interactive Demand-Responsive-Transport");
1458                 }
1459                 onCmdGaming(nullptr, 0, nullptr);
1460             } else {
1461                 // set simulation name on the caption
1462                 setTitle(MFXUtils::getTitleText("SUMO " VERSION_STRING, ec->myFile.c_str()));
1463             }
1464             if (ec->myViewportFromRegistry) {
1465                 Position off;
1466                 off.set(getApp()->reg().readRealEntry("viewport", "x"),
1467                         getApp()->reg().readRealEntry("viewport", "y"),
1468                         getApp()->reg().readRealEntry("viewport", "z"));
1469                 Position p(off.x(), off.y(), 0);
1470                 GUISUMOAbstractView* view = myGLWindows[0]->getView();
1471                 view->setViewportFromToRot(off, p, 0);
1472             }
1473             // set simulation step begin information
1474             myLCDLabel->setText("----------------");
1475             for (std::vector<FXButton*>::const_iterator it = myStatButtons.begin(); it != myStatButtons.end(); ++it) {
1476                 (*it)->setText("-");
1477             }
1478             // initialize scale from options
1479             myDemandScaleSpinner->setValue(OptionsCont::getOptions().getFloat("scale"));
1480         }
1481     }
1482     getApp()->endWaitCursor();
1483     // start if wished
1484     if (GUIGlobals::gRunAfterLoad && ec->myNet != nullptr && myRunThread->simulationIsStartable()) {
1485         onCmdStart(nullptr, 0, nullptr);
1486     }
1487     update();
1488 }
1489 
1490 
1491 void
handleEvent_SimulationStep(GUIEvent *)1492 GUIApplicationWindow::handleEvent_SimulationStep(GUIEvent*) {
1493     updateTimeLCD(myRunThread->getNet().getCurrentTimeStep());
1494     const int running = myRunThread->getNet().getVehicleControl().getRunningVehicleNo();
1495     const int backlog = myRunThread->getNet().getInsertionControl().getWaitingVehicleNo();
1496     if (backlog > running) {
1497         if (myStatButtons.front()->getIcon() == GUIIconSubSys::getIcon(ICON_GREENVEHICLE)) {
1498             myStatButtons.front()->setIcon(GUIIconSubSys::getIcon(ICON_YELLOWVEHICLE));
1499         }
1500     } else {
1501         if (myStatButtons.front()->getIcon() == GUIIconSubSys::getIcon(ICON_YELLOWVEHICLE)) {
1502             myStatButtons.front()->setIcon(GUIIconSubSys::getIcon(ICON_GREENVEHICLE));
1503         }
1504     }
1505     myStatButtons.front()->setText(toString(running).c_str());
1506     if (myRunThread->getNet().hasPersons()) {
1507         if (!myStatButtons[1]->shown()) {
1508             myStatButtons[1]->show();
1509         }
1510         myStatButtons[1]->setText(toString(myRunThread->getNet().getPersonControl().getRunningNumber()).c_str());
1511     }
1512     if (myRunThread->getNet().hasContainers()) {
1513         if (!myStatButtons[2]->shown()) {
1514             myStatButtons[2]->show();
1515         }
1516         myStatButtons[2]->setText(toString(myRunThread->getNet().getContainerControl().getRunningNumber()).c_str());
1517     }
1518     if (myAmGaming) {
1519         if (myTLSGame) {
1520             checkGamingEvents();
1521         } else {
1522             checkGamingEventsDRT();
1523         }
1524     }
1525     if (myRunThread->simulationIsStartable()) {
1526         getApp()->forceRefresh(); // restores keyboard focus
1527     }
1528     updateChildren();
1529     update();
1530 }
1531 
1532 
1533 void
handleEvent_Message(GUIEvent * e)1534 GUIApplicationWindow::handleEvent_Message(GUIEvent* e) {
1535     GUIEvent_Message* ec = static_cast<GUIEvent_Message*>(e);
1536     if (ec->getOwnType() == EVENT_STATUS_OCCURRED) {
1537         setStatusBarText(ec->getMsg());
1538     } else {
1539         myMessageWindow->appendMsg(ec->getOwnType(), ec->getMsg());
1540     }
1541 }
1542 
1543 
1544 void
handleEvent_SimulationEnded(GUIEvent * e)1545 GUIApplicationWindow::handleEvent_SimulationEnded(GUIEvent* e) {
1546     GUIEvent_SimulationEnded* ec = static_cast<GUIEvent_SimulationEnded*>(e);
1547     onCmdStop(nullptr, 0, nullptr);
1548     if (ec->getReason() == MSNet::SIMSTATE_LOADING) {
1549         onCmdReload(nullptr, 0, nullptr);
1550     } else if (GUIGlobals::gQuitOnEnd) {
1551         closeAllWindows();
1552         getApp()->exit(ec->getReason() == MSNet::SIMSTATE_ERROR_IN_SIM);
1553     } else if (GUIGlobals::gDemoAutoReload) {
1554         onCmdReload(nullptr, 0, nullptr);
1555     } else if (!myHaveNotifiedAboutSimEnd) {
1556         // build the text
1557         const std::string text = "Simulation ended at time: " + time2string(ec->getTimeStep()) +
1558                                  ".\nReason: " + MSNet::getStateMessage(ec->getReason()) +
1559                                  "\nDo you want to close all open files and views?";
1560         FXuint answer = FXMessageBox::question(this, MBOX_YES_NO, "Simulation ended", "%s", text.c_str());
1561         if (answer == 1) { //1:yes, 2:no, 4:esc
1562             closeAllWindows();
1563         }
1564         myHaveNotifiedAboutSimEnd = true;
1565     }
1566 }
1567 
1568 
1569 void
checkGamingEvents()1570 GUIApplicationWindow::checkGamingEvents() {
1571     MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
1572     MSVehicleControl::constVehIt it = vc.loadedVehBegin();
1573     MSVehicleControl::constVehIt end = vc.loadedVehEnd();
1574 #ifdef HAVE_DANGEROUS_SOUNDS // disable user-configurable command execution for public build
1575     if (myJamSounds.getOverallProb() > 0) {
1576         // play honking sound if some vehicle is waiting too long
1577         for (; it != end; ++it) {
1578             // XXX use impatience instead of waiting time ?
1579             if (it->second->getWaitingTime() > TIME2STEPS(myJamSoundTime)) {
1580                 const std::string cmd = myJamSounds.get(&myGamingRNG);
1581                 if (cmd != "") {
1582                     // yay! fun with dangerous commands... Never use this over the internet
1583                     SysUtils::runHiddenCommand(cmd);
1584                     // one sound per simulation step is enough
1585                     break;
1586                 }
1587             }
1588         }
1589     }
1590     if (myCollisionSounds.getOverallProb() > 0) {
1591         int collisions = MSNet::getInstance()->getVehicleControl().getCollisionCount();
1592         if (myPreviousCollisionNumber != collisions) {
1593             const std::string cmd = myCollisionSounds.get(&myGamingRNG);
1594             if (cmd != "") {
1595                 // yay! fun with dangerous commands... Never use this over the internet
1596                 SysUtils::runHiddenCommand(cmd);
1597             }
1598             myPreviousCollisionNumber = collisions;
1599         }
1600     }
1601 #endif
1602 
1603     // update performance indicators
1604     for (it = vc.loadedVehBegin(); it != end; ++it) {
1605         const MSVehicle* veh = dynamic_cast<MSVehicle*>(it->second);
1606         assert(veh != 0);
1607         if (veh->isOnRoad() && !veh->isStopped()) {
1608             const double vmax = MIN2(veh->getVehicleType().getMaxSpeed(), veh->getEdge()->getSpeedLimit());
1609             if (veh->getSpeed() < SUMO_const_haltingSpeed) {
1610                 myWaitingTime += DELTA_T;
1611             }
1612             myTimeLoss += TIME2STEPS(TS * (vmax - veh->getSpeed()) / vmax); // may be negative with speedFactor > 1
1613         }
1614     }
1615     myWaitingTimeLabel->setText(time2string(myWaitingTime).c_str());
1616     myTimeLossLabel->setText(time2string(myTimeLoss).c_str());
1617 }
1618 
1619 void
checkGamingEventsDRT()1620 GUIApplicationWindow::checkGamingEventsDRT() {
1621     // update performance indicators
1622     MSTransportableControl& pc = myRunThread->getNet().getPersonControl();
1623     myWaitingTime += pc.getWaitingForVehicleNumber() * DELTA_T;
1624     myWaitingTimeLabel->setText(time2string(myWaitingTime).c_str());
1625 
1626     MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
1627     MSVehicleControl::constVehIt end = vc.loadedVehEnd();
1628     for (auto it = vc.loadedVehBegin(); it != end; ++it) {
1629         const MSVehicle* veh = dynamic_cast<MSVehicle*>(it->second);
1630         assert(veh != 0);
1631         if (veh->isOnRoad() && !veh->isStopped()) {
1632             myTotalDistance += SPEED2DIST(veh->getSpeed());
1633         }
1634     }
1635     myTotalDistanceLabel->setText(toString(myTotalDistance / 100).c_str());
1636 }
1637 
1638 void
loadConfigOrNet(const std::string & file,bool isNet)1639 GUIApplicationWindow::loadConfigOrNet(const std::string& file, bool isNet) {
1640     storeWindowSizeAndPos();
1641     getApp()->beginWaitCursor();
1642     myAmLoading = true;
1643     closeAllWindows();
1644     gSchemeStorage.saveViewport(0, 0, -1, 0); // recenter view
1645     myLoadThread->loadConfigOrNet(file, isNet);
1646     setStatusBarText("Loading '" + file + "'.");
1647     update();
1648 }
1649 
1650 
1651 GUISUMOAbstractView*
openNewView(GUISUMOViewParent::ViewType vt)1652 GUIApplicationWindow::openNewView(GUISUMOViewParent::ViewType vt) {
1653     if (!myRunThread->simulationAvailable()) {
1654         myStatusbar->getStatusLine()->setText("No simulation loaded!");
1655         return nullptr;
1656     }
1657     GUISUMOAbstractView* oldView = nullptr;
1658     if (myMDIClient->numChildren() > 0) {
1659         GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1660         if (w != nullptr) {
1661             oldView = w->getView();
1662         }
1663     }
1664     std::string caption = "View #" + toString(myViewNumber++);
1665     FXuint opts = MDI_TRACKING;
1666     GUISUMOViewParent* w = new GUISUMOViewParent(myMDIClient, myMDIMenu, FXString(caption.c_str()),
1667             this, GUIIconSubSys::getIcon(ICON_SUMO_MINI), opts, 10, 10, 300, 200);
1668     GUISUMOAbstractView* v = w->init(getBuildGLCanvas(), myRunThread->getNet(), vt);
1669     if (oldView != nullptr) {
1670         // copy viewport
1671         oldView->copyViewportTo(v);
1672     }
1673     w->create();
1674     if (myMDIClient->numChildren() == 1) {
1675         w->maximize();
1676     } else {
1677         myMDIClient->vertical(true);
1678     }
1679     myMDIClient->setActiveChild(w);
1680 
1681     return v;
1682 }
1683 
1684 
1685 FXGLCanvas*
getBuildGLCanvas() const1686 GUIApplicationWindow::getBuildGLCanvas() const {
1687     if (myMDIClient->numChildren() == 0) {
1688         return nullptr;
1689     }
1690     GUISUMOViewParent* share_tmp1 =
1691         static_cast<GUISUMOViewParent*>(myMDIClient->childAtIndex(0));
1692     return share_tmp1->getBuildGLCanvas();
1693 }
1694 
1695 
1696 void
closeAllWindows()1697 GUIApplicationWindow::closeAllWindows() {
1698     myTrackerLock.lock();
1699     myLCDLabel->setText("----------------");
1700     for (std::vector<FXButton*>::const_iterator it = myStatButtons.begin(); it != myStatButtons.end(); ++it) {
1701         (*it)->setText("-");
1702         if (it != myStatButtons.begin()) {
1703             (*it)->hide();
1704         }
1705     }
1706     // delete the simulation
1707     myRunThread->deleteSim();
1708     // reset the caption
1709     setTitle(MFXUtils::getTitleText("SUMO " VERSION_STRING));
1710     // remove trackers and other external windows (must be delayed until deleteSim)
1711     while (!myGLWindows.empty()) {
1712         delete myGLWindows.front();
1713     }
1714     for (FXMainWindow* const window : myTrackerWindows) {
1715         delete window;
1716     }
1717     myTrackerWindows.clear();
1718     // clear selected items
1719     gSelected.clear();
1720     // add a separator to the log
1721     myMessageWindow->addSeparator();
1722     myTrackerLock.unlock();
1723     // remove coordinate information
1724     myGeoCoordinate->setText("N/A");
1725     myCartesianCoordinate->setText("N/A");
1726     //
1727     GUITexturesHelper::clearTextures();
1728     GLHelper::resetFont();
1729     update();
1730 }
1731 
1732 
1733 FXCursor*
getDefaultCursor()1734 GUIApplicationWindow::getDefaultCursor() {
1735     return getApp()->getDefaultCursor(DEF_ARROW_CURSOR);
1736 }
1737 
1738 
1739 SUMOTime
getCurrentSimTime() const1740 GUIApplicationWindow::getCurrentSimTime() const {
1741     return myRunThread->getNet().getCurrentTimeStep();
1742 }
1743 
1744 
1745 double
getTrackerInterval() const1746 GUIApplicationWindow::getTrackerInterval() const {
1747     return GUIGlobals::gTrackerInterval;
1748 }
1749 
1750 
1751 void
loadOnStartup()1752 GUIApplicationWindow::loadOnStartup() {
1753     loadConfigOrNet("", false);
1754 }
1755 
1756 
1757 void
setStatusBarText(const std::string & text)1758 GUIApplicationWindow::setStatusBarText(const std::string& text) {
1759     myStatusbar->getStatusLine()->setText(text.c_str());
1760 
1761     myStatusbar->getStatusLine()->setNormalText(text.c_str());
1762 }
1763 
1764 
1765 void
addRecentFile(const FX::FXString & f,const bool isNet)1766 GUIApplicationWindow::addRecentFile(const FX::FXString& f, const bool isNet) {
1767     if (isNet) {
1768         myRecentNets.appendFile(f);
1769     } else {
1770         myRecentConfigs.appendFile(f);
1771     }
1772 }
1773 
1774 
1775 void
updateTimeLCD(SUMOTime time)1776 GUIApplicationWindow::updateTimeLCD(SUMOTime time) {
1777     time -= DELTA_T; // synchronize displayed time with netstate output
1778     if (time < 0) {
1779         myLCDLabel->setText("----------------");
1780         return;
1781     }
1782     if (myAmGaming) {
1783         // show time counting backwards
1784         time = myRunThread->getSimEndTime() - time;
1785     }
1786     std::ostringstream str;
1787     str << std::setfill('0');
1788     const bool hideFraction = myAmGaming || DELTA_T % 1000 == 0;
1789     if (myShowTimeAsHMS) {
1790         SUMOTime day = time / 86400000;
1791         if (day > 0) {
1792             str << day << '-';
1793             time %= 86400000;
1794         }
1795         str << std::setw(2);
1796         str << time / 3600000 << '-';
1797         time %= 3600000;
1798         str << std::setw(2) << time / 60000 << '-';
1799         time %= 60000;
1800     }
1801     str << std::setw(2) << time / 1000;
1802     if (!hideFraction) {
1803         str << '.' << std::setw(3) << time % 1000;
1804     }
1805     myLCDLabel->setText(str.str().c_str());
1806 }
1807 
1808 
1809 long
onKeyPress(FXObject * o,FXSelector sel,void * data)1810 GUIApplicationWindow::onKeyPress(FXObject* o, FXSelector sel, void* data) {
1811     const long handled = FXMainWindow::onKeyPress(o, sel, data);
1812     if (handled == 0 && myMDIClient->numChildren() > 0) {
1813         GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1814         if (w != nullptr) {
1815             w->onKeyPress(nullptr, sel, data);
1816         }
1817     }
1818     return 0;
1819 }
1820 
1821 
1822 long
onKeyRelease(FXObject * o,FXSelector sel,void * data)1823 GUIApplicationWindow::onKeyRelease(FXObject* o, FXSelector sel, void* data) {
1824     const long handled = FXMainWindow::onKeyRelease(o, sel, data);
1825     if (handled == 0 && myMDIClient->numChildren() > 0) {
1826         GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1827         if (w != nullptr) {
1828             w->onKeyRelease(nullptr, sel, data);
1829         }
1830     }
1831     return 0;
1832 }
1833 
1834 
1835 void
sendBlockingEvent(GUIEvent * event)1836 GUIApplicationWindow::sendBlockingEvent(GUIEvent* event) {
1837     myEventMutex.lock();
1838     myEvents.push_back(event);
1839     myRunThreadEvent.signal();
1840     myEventCondition.wait(myEventMutex);
1841     myEventMutex.unlock();
1842 }
1843 
1844 void
setBreakpoints(const std::vector<SUMOTime> & breakpoints)1845 GUIApplicationWindow::setBreakpoints(const std::vector<SUMOTime>& breakpoints) {
1846     if (myRunThread != nullptr) {
1847         myRunThread->getBreakpointLock().lock();
1848         myRunThread->getBreakpoints().assign(breakpoints.begin(), breakpoints.end());
1849         myRunThread->getBreakpointLock().unlock();
1850     }
1851 }
1852 
1853 const std::vector<SUMOTime>
retrieveBreakpoints() const1854 GUIApplicationWindow::retrieveBreakpoints() const {
1855     myRunThread->getBreakpointLock().lock();
1856     std::vector<SUMOTime> result = myRunThread->getBreakpoints();
1857     myRunThread->getBreakpointLock().unlock();
1858     return result;
1859 }
1860 
1861 /****************************************************************************/
1862