Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file GUIApplicationWindow.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @author Andreas Gaubatz
19 : /// @author Mirko Barthauer
20 : /// @date Sept 2002
21 : ///
22 : // The main window of the SUMO-gui.
23 : /****************************************************************************/
24 : #include <config.h>
25 :
26 : #ifdef HAVE_VERSION_H
27 : #include <version.h>
28 : #endif
29 :
30 : #include <fxkeys.h>
31 :
32 : #include <guisim/GUILane.h>
33 : #include <guisim/GUINet.h>
34 : #include <guisim/GUITrafficLightLogicWrapper.h>
35 : #include <microsim/MSEdgeControl.h>
36 : #include <microsim/MSInsertionControl.h>
37 : #include <microsim/MSStateHandler.h>
38 : #include <microsim/transportables/MSTransportableControl.h>
39 : #include <microsim/devices/MSRoutingEngine.h>
40 : #include <microsim/traffic_lights/MSTLLogicControl.h>
41 : #include <netload/NLHandler.h>
42 : #include <traci-server/TraCIServer.h>
43 : #include <utils/common/MsgHandler.h>
44 : #include <utils/common/StringUtils.h>
45 : #include <utils/foxtools/MFXButtonTooltip.h>
46 : #include <utils/foxtools/MFXLabelTooltip.h>
47 : #include <utils/foxtools/MFXLCDLabel.h>
48 : #include <utils/foxtools/MFXLinkLabel.h>
49 : #include <utils/foxtools/MFXRealSpinner.h>
50 : #include <utils/gui/cursors/GUICursorSubSys.h>
51 : #include <utils/gui/div/GLHelper.h>
52 : #include <utils/gui/div/GUIDesigns.h>
53 : #include <utils/gui/div/GUIDialog_GLChosenEditor.h>
54 : #include <utils/gui/div/GUIGlobalSelection.h>
55 : #include <utils/gui/div/GUIMessageWindow.h>
56 : #include <utils/gui/div/GUIUserIO.h>
57 : #include <utils/gui/events/GUIEvent_AddView.h>
58 : #include <utils/gui/events/GUIEvent_CloseView.h>
59 : #include <utils/gui/events/GUIEvent_Message.h>
60 : #include <utils/gui/globjects/GUIShapeContainer.h>
61 : #include <utils/gui/images/GUITexturesHelper.h>
62 : #include <utils/gui/images/VClassIcons.h>
63 : #include <utils/gui/images/GUITextureSubSys.h>
64 : #include <utils/gui/settings/GUICompleteSchemeStorage.h>
65 : #include <utils/gui/settings/GUISettingsHandler.h>
66 : #include <utils/gui/shortcuts/GUIShortcutsSubSys.h>
67 : #include <utils/gui/windows/GUIPerspectiveChanger.h>
68 : #include <utils/xml/XMLSubSys.h>
69 :
70 : #include "GUIApplicationWindow.h"
71 : #include "GUIEvent_SimulationEnded.h"
72 : #include "GUIEvent_SimulationLoaded.h"
73 : #include "GUIGlobals.h"
74 : #include "GUILoadThread.h"
75 : #include "GUIRunThread.h"
76 : #include "dialogs/GUIDialog_AboutSUMO.h"
77 : #include "dialogs/GUIDialog_Feedback.h"
78 : #include "dialogs/GUIDialog_AppSettings.h"
79 : #include "dialogs/GUIDialog_Breakpoints.h"
80 : #include "dialogs/GUIDialog_HallOfFame.h"
81 :
82 :
83 : #define MIN_DRAW_DELAY 20
84 : //#define HAVE_DANGEROUS_SOUNDS
85 :
86 : #define STAT_VEHS 0
87 : #define STAT_DELAYED 1
88 : #define STAT_TELEPORTS 2
89 : #define STAT_PERSONS 3
90 : #define STAT_CONTAINERS 4
91 :
92 : // ===========================================================================
93 : // FOX-declarations
94 : // ===========================================================================
95 : FXDEFMAP(GUIApplicationWindow) GUIApplicationWindowMap[] = {
96 : // close
97 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_Q_CLOSE, GUIApplicationWindow::onCmdQuit),
98 : FXMAPFUNC(SEL_SIGNAL, MID_HOTKEY_CTRL_Q_CLOSE, GUIApplicationWindow::onCmdQuit),
99 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_ALT_F4_CLOSE, GUIApplicationWindow::onCmdQuit),
100 : FXMAPFUNC(SEL_CLOSE, MID_WINDOW, GUIApplicationWindow::onCmdQuit),
101 : // toolbar
102 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_SHIFT_N_NEWWINDOW, GUIApplicationWindow::onCmdNewWindow),
103 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_O_OPENSIMULATION_OPENNETWORK, GUIApplicationWindow::onCmdOpenConfiguration),
104 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_N_OPENNETWORK_NEWNETWORK, GUIApplicationWindow::onCmdOpenNetwork),
105 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_P_OPENSHAPES, GUIApplicationWindow::onCmdOpenShapes),
106 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_U_OPENEDGEDATA, 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_QUICK_RELOAD, GUIApplicationWindow::onCmdQuickReload),
110 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_SHIFT_S_SAVESUMOCONFIG, GUIApplicationWindow::onCmdSaveConfig),
111 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_W_CLOSESIMULATION, GUIApplicationWindow::onCmdClose),
112 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_E_EDITSELECTION_LOADNETEDITCONFIG, GUIApplicationWindow::onCmdEditChosen),
113 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_B_EDITBREAKPOINT_OPENDATAELEMENTS, GUIApplicationWindow::onCmdEditBreakpoints),
114 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_F9_EDIT_VIEWSCHEME, GUIApplicationWindow::onCmdEditViewScheme),
115 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_I_EDITVIEWPORT, GUIApplicationWindow::onCmdEditViewport),
116 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_T_OPENNETEDIT_OPENSUMO, GUIApplicationWindow::onCmdOpenInNetedit),
117 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_SHIFT_T_OPEN_NET, GUIApplicationWindow::onCmdOpenInNetedit),
118 : // gaming
119 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_H_APPSETTINGS_OPENEDGETYPES, GUIApplicationWindow::onCmdAppSettings),
120 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_G_GAMINGMODE_TOGGLEGRID, GUIApplicationWindow::onCmdGaming),
121 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_J_TOGGLEDRAWJUNCTIONSHAPE, GUIApplicationWindow::onCmdToggleDrawJunctionShape),
122 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_K_OPENTLSPROGRAMS, GUIApplicationWindow::onCmdToggleSecondaryShape),
123 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_F_FULSCREENMODE, GUIApplicationWindow::onCmdFullScreen),
124 : FXMAPFUNC(SEL_COMMAND, MID_LISTINTERNAL, GUIApplicationWindow::onCmdListInternal),
125 : FXMAPFUNC(SEL_COMMAND, MID_LISTPARKING, GUIApplicationWindow::onCmdListParking),
126 : FXMAPFUNC(SEL_COMMAND, MID_LISTTELEPORTING, GUIApplicationWindow::onCmdListTeleporting),
127 : FXMAPFUNC(SEL_COMMAND, MID_NEW_MICROVIEW, GUIApplicationWindow::onCmdNewView),
128 : // OSG
129 : #ifdef HAVE_OSG
130 : FXMAPFUNC(SEL_COMMAND, MID_NEW_OSGVIEW, GUIApplicationWindow::onCmdNewOSG),
131 : FXMAPFUNC(SEL_UPDATE, MID_NEW_OSGVIEW, GUIApplicationWindow::onUpdAddView),
132 :
133 : #endif
134 : // Time
135 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_A_MODE_STARTSIMULATION_ADDITIONALS_STOPS, GUIApplicationWindow::onCmdStart),
136 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_A_STARTSIMULATION_OPENADDITIONALELEMENTS, GUIApplicationWindow::onCmdStart),
137 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_S_MODE_STOPSIMULATION_SELECT, GUIApplicationWindow::onCmdStop),
138 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_S_STOPSIMULATION_SAVENETWORK, GUIApplicationWindow::onCmdStop),
139 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_D_MODE_SINGLESIMULATIONSTEP_DELETE, GUIApplicationWindow::onCmdStep),
140 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_CTRL_D_SINGLESIMULATIONSTEP_OPENDEMANDELEMENTS, GUIApplicationWindow::onCmdStep),
141 : FXMAPFUNC(SEL_COMMAND, MID_DELAY_INC, GUIApplicationWindow::onCmdDelayInc),
142 : FXMAPFUNC(SEL_COMMAND, MID_DELAY_DEC, GUIApplicationWindow::onCmdDelayDec),
143 : FXMAPFUNC(SEL_COMMAND, MID_SIMSAVE, GUIApplicationWindow::onCmdSaveState),
144 : FXMAPFUNC(SEL_COMMAND, MID_SIMLOAD, GUIApplicationWindow::onCmdLoadState),
145 : FXMAPFUNC(SEL_COMMAND, MID_TIME_TOGGLE, GUIApplicationWindow::onCmdTimeToggle),
146 : FXMAPFUNC(SEL_COMMAND, MID_DELAY_TOGGLE, GUIApplicationWindow::onCmdDelayToggle),
147 : FXMAPFUNC(SEL_COMMAND, MID_DEMAND_SCALE, GUIApplicationWindow::onCmdDemandScale),
148 : FXMAPFUNC(SEL_COMMAND, MID_CLEARMESSAGEWINDOW, GUIApplicationWindow::onCmdClearMsgWindow),
149 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_B_BREAKPOINT, GUIApplicationWindow::onCmdBreakpoint),
150 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_ALT_B_BREAKPOINT_EARLY, GUIApplicationWindow::onCmdBreakpointEarly),
151 : // Stats
152 : FXMAPFUNC(SEL_COMMAND, MID_SHOWNETSTATS, GUIApplicationWindow::onCmdShowStats),
153 : FXMAPFUNC(SEL_COMMAND, MID_SHOWVEHSTATS, GUIApplicationWindow::onCmdShowStats),
154 : FXMAPFUNC(SEL_COMMAND, MID_SHOWPERSONSTATS, GUIApplicationWindow::onCmdShowStats),
155 : // these functions do not assign shortcut keys to commands, but rather affect the button enable status upon other events (e.g. simulation loaded)
156 : // since those events are invoked through pseudo key events (?), the same key shortcuts as in cmd must be supplied as well
157 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_O_OPENSIMULATION_OPENNETWORK, GUIApplicationWindow::onUpdOpen),
158 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_N_OPENNETWORK_NEWNETWORK, GUIApplicationWindow::onUpdOpen),
159 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_P_OPENSHAPES, GUIApplicationWindow::onUpdNeedsNetwork),
160 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_U_OPENEDGEDATA, GUIApplicationWindow::onUpdNeedsNetwork),
161 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_R_RELOAD, GUIApplicationWindow::onUpdReload),
162 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_QUICK_RELOAD, GUIApplicationWindow::onUpdReload),
163 : FXMAPFUNC(SEL_UPDATE, MID_RECENTFILE, GUIApplicationWindow::onUpdOpenRecent),
164 : FXMAPFUNC(SEL_UPDATE, MID_NEW_MICROVIEW, GUIApplicationWindow::onUpdAddView),
165 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_A_STARTSIMULATION_OPENADDITIONALELEMENTS, GUIApplicationWindow::onUpdStart),
166 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_S_STOPSIMULATION_SAVENETWORK, GUIApplicationWindow::onUpdStop),
167 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_D_SINGLESIMULATIONSTEP_OPENDEMANDELEMENTS, GUIApplicationWindow::onUpdStep),
168 : FXMAPFUNC(SEL_UPDATE, MID_SIMSAVE, GUIApplicationWindow::onUpdNeedsNetwork),
169 : FXMAPFUNC(SEL_UPDATE, MID_SIMLOAD, GUIApplicationWindow::onUpdNeedsNetwork),
170 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_E_EDITSELECTION_LOADNETEDITCONFIG, GUIApplicationWindow::onUpdNeedsNetwork),
171 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_B_EDITBREAKPOINT_OPENDATAELEMENTS, GUIApplicationWindow::onUpdNeedsNetwork),
172 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_B_BREAKPOINT, GUIApplicationWindow::onUpdNeedsNetwork),
173 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_ALT_B_BREAKPOINT_EARLY, GUIApplicationWindow::onUpdNeedsNetwork),
174 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_F9_EDIT_VIEWSCHEME, GUIApplicationWindow::onUpdNeedsNetwork),
175 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_I_EDITVIEWPORT, GUIApplicationWindow::onUpdNeedsNetwork),
176 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_T_OPENNETEDIT_OPENSUMO, GUIApplicationWindow::onUpdNeedsNetwork),
177 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_SHIFT_T_OPEN_NET, GUIApplicationWindow::onUpdNeedsNetwork),
178 : FXMAPFUNC(SEL_UPDATE, MID_TOOLBAREDIT_LOADADDITIONALS, GUIApplicationWindow::onUpdNeedsSumoConfig),
179 : FXMAPFUNC(SEL_UPDATE, MID_TOOLBAREDIT_LOADDEMAND, GUIApplicationWindow::onUpdNeedsSumoConfig),
180 : FXMAPFUNC(SEL_UPDATE, MID_DEMAND_SCALE, GUIApplicationWindow::onUpdNeedsNetwork),
181 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_G_GAMINGMODE_TOGGLEGRID, GUIApplicationWindow::onUpdNeedsNetwork),
182 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_CTRL_F_FULSCREENMODE, GUIApplicationWindow::onUpdNeedsNetwork),
183 : FXMAPFUNC(SEL_UPDATE, MID_TRACI_STATUS, GUIApplicationWindow::onUpdTraCIStatus),
184 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_F1_ONLINEDOCUMENTATION, GUIApplicationWindow::onCmdHelp),
185 : FXMAPFUNC(SEL_COMMAND, MID_CHANGELOG, GUIApplicationWindow::onCmdChangelog),
186 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEYS, GUIApplicationWindow::onCmdHotkeys),
187 : FXMAPFUNC(SEL_COMMAND, MID_TUTORIAL, GUIApplicationWindow::onCmdTutorial),
188 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_F11_HALLOFFAME, GUIApplicationWindow::onCmdHallOfFame),
189 : FXMAPFUNC(SEL_COMMAND, MID_FEEDBACK, GUIApplicationWindow::onCmdFeedback),
190 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_F12_ABOUT, GUIApplicationWindow::onCmdAbout),
191 : // forward requests to the active view
192 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_J_LOCATEJUNCTION, GUIApplicationWindow::onCmdLocate),
193 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_E_LOCATEEDGE, GUIApplicationWindow::onCmdLocate),
194 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_V_LOCATEVEHICLE, GUIApplicationWindow::onCmdLocate),
195 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_P_LOCATEPERSON, GUIApplicationWindow::onCmdLocate),
196 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_C_LOCATECONTAINER, GUIApplicationWindow::onCmdLocate),
197 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_T_LOCATETLS, GUIApplicationWindow::onCmdLocate),
198 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL, GUIApplicationWindow::onCmdLocate),
199 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_O_LOCATEPOI, GUIApplicationWindow::onCmdLocate),
200 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_L_LOCATEPOLY, GUIApplicationWindow::onCmdLocate),
201 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_SHIFT_J_LOCATEJUNCTION, GUIApplicationWindow::onUpdNeedsNetwork),
202 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_SHIFT_E_LOCATEEDGE, GUIApplicationWindow::onUpdNeedsNetwork),
203 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_SHIFT_V_LOCATEVEHICLE, GUIApplicationWindow::onUpdNeedsNetwork),
204 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_SHIFT_P_LOCATEPERSON, GUIApplicationWindow::onUpdNeedsNetwork),
205 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_SHIFT_C_LOCATECONTAINER, GUIApplicationWindow::onUpdNeedsNetwork),
206 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_SHIFT_T_LOCATETLS, GUIApplicationWindow::onUpdNeedsNetwork),
207 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL, GUIApplicationWindow::onUpdNeedsNetwork),
208 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_SHIFT_O_LOCATEPOI, GUIApplicationWindow::onUpdNeedsNetwork),
209 : FXMAPFUNC(SEL_UPDATE, MID_HOTKEY_SHIFT_L_LOCATEPOLY, GUIApplicationWindow::onUpdNeedsNetwork),
210 : // languages
211 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_EN, GUIApplicationWindow::onCmdChangeLanguage),
212 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_EN, GUIApplicationWindow::onUpdChangeLanguage),
213 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_DE, GUIApplicationWindow::onCmdChangeLanguage),
214 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_DE, GUIApplicationWindow::onUpdChangeLanguage),
215 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_ES, GUIApplicationWindow::onCmdChangeLanguage),
216 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_ES, GUIApplicationWindow::onUpdChangeLanguage),
217 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_FR, GUIApplicationWindow::onCmdChangeLanguage),
218 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_FR, GUIApplicationWindow::onUpdChangeLanguage),
219 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_IT, GUIApplicationWindow::onCmdChangeLanguage),
220 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_IT, GUIApplicationWindow::onUpdChangeLanguage),
221 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_ZH, GUIApplicationWindow::onCmdChangeLanguage),
222 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_ZH, GUIApplicationWindow::onUpdChangeLanguage),
223 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_ZHT, GUIApplicationWindow::onCmdChangeLanguage),
224 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_ZHT, GUIApplicationWindow::onUpdChangeLanguage),
225 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_TR, GUIApplicationWindow::onCmdChangeLanguage),
226 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_TR, GUIApplicationWindow::onUpdChangeLanguage),
227 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_JA, GUIApplicationWindow::onCmdChangeLanguage),
228 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_JA, GUIApplicationWindow::onUpdChangeLanguage),
229 : FXMAPFUNC(SEL_COMMAND, MID_LANGUAGE_KO, GUIApplicationWindow::onCmdChangeLanguage),
230 : FXMAPFUNC(SEL_UPDATE, MID_LANGUAGE_KO, GUIApplicationWindow::onUpdChangeLanguage),
231 : // keys
232 : FXMAPFUNC(SEL_KEYPRESS, 0, GUIApplicationWindow::onKeyPress),
233 : FXMAPFUNC(SEL_KEYRELEASE, 0, GUIApplicationWindow::onKeyRelease),
234 : // clipboard
235 : FXMAPFUNC(SEL_CLIPBOARD_REQUEST, 0, GUIApplicationWindow::onClipboardRequest),
236 : // events
237 : FXMAPFUNC(FXEX::SEL_THREAD_EVENT, ID_LOADTHREAD_EVENT, GUIApplicationWindow::onLoadThreadEvent),
238 : FXMAPFUNC(FXEX::SEL_THREAD_EVENT, ID_RUNTHREAD_EVENT, GUIApplicationWindow::onRunThreadEvent),
239 : FXMAPFUNC(FXEX::SEL_THREAD, ID_LOADTHREAD_EVENT, GUIApplicationWindow::onLoadThreadEvent),
240 : FXMAPFUNC(FXEX::SEL_THREAD, ID_RUNTHREAD_EVENT, GUIApplicationWindow::onRunThreadEvent),
241 : };
242 :
243 : // Object implementation
244 121263345 : FXIMPLEMENT(GUIApplicationWindow, FXMainWindow, GUIApplicationWindowMap, ARRAYNUMBER(GUIApplicationWindowMap))
245 :
246 : // ===========================================================================
247 : // static members
248 : // ===========================================================================
249 : std::mt19937 GUIApplicationWindow::myGamingRNG;
250 :
251 :
252 : // ===========================================================================
253 : // member method definitions
254 : // ===========================================================================
255 : #ifdef _MSC_VER
256 : #pragma warning(push)
257 : #pragma warning(disable: 4355) // mask warning about "this" in initializers
258 : #endif
259 8992 : GUIApplicationWindow::GUIApplicationWindow(FXApp* a) :
260 : GUIMainWindow(a),
261 8992 : myFileMenuRecentNetworks(new FXMenuPane(this)),
262 8992 : myFileMenuRecentConfigs(new FXMenuPane(this)),
263 8992 : myRecentNetworks(a, "networks"),
264 8992 : myRecentConfigs(a, "configs"),
265 26976 : myLastStepEventMillis(SysUtils::getCurrentMillis() - MIN_DRAW_DELAY) {
266 : // init icons
267 8992 : GUIIconSubSys::initIcons(a);
268 : // init Textures
269 8992 : GUITextureSubSys::initTextures(a);
270 : // init cursors
271 8992 : GUICursorSubSys::initCursors(a);
272 : // disable tooltips
273 8992 : a->setTooltipTime(1000000000);
274 8992 : a->setTooltipPause(1000000000);
275 8992 : }
276 : #ifdef _MSC_VER
277 : #pragma warning(pop)
278 : #endif
279 :
280 :
281 : GUIRunThread*
282 95329 : GUIApplicationWindow::getRunner() {
283 95329 : return myRunThread;
284 : }
285 :
286 :
287 : void
288 8992 : GUIApplicationWindow::dependentBuild(const bool isLibsumo) {
289 : // don't do this twice
290 8992 : if (hadDependentBuild) {
291 : return;
292 : }
293 8992 : hadDependentBuild = true;
294 8992 : setTarget(this);
295 : setSelector(MID_WINDOW);
296 : // build menu bar
297 8992 : myMenuBarDrag = new FXToolBarShell(this, GUIDesignToolBar);
298 8992 : myMenuBar = new FXMenuBar(myTopDock, myMenuBarDrag, GUIDesignToolbarMenuBar);
299 8992 : new FXToolBarGrip(myMenuBar, myMenuBar, FXMenuBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
300 8992 : buildToolBars();
301 : // build the thread - io
302 : myLoadThreadEvent.setTarget(this);
303 : myLoadThreadEvent.setSelector(ID_LOADTHREAD_EVENT);
304 : myRunThreadEvent.setTarget(this);
305 : myRunThreadEvent.setSelector(ID_RUNTHREAD_EVENT);
306 : // build the status bar
307 8992 : myStatusbar = new FXStatusBar(this, GUIDesignStatusBar);
308 : {
309 : // build TraCi info
310 8992 : myTraCiFrame = new FXHorizontalFrame(myStatusbar, GUIDesignHorizontalFrameStatusBar);
311 17984 : auto button = GUIDesigns::buildFXButton(myTraCiFrame, "TraCI", "", "", nullptr, this, MID_TRACI_STATUS, GUIDesignButtonStatusBarFixed);
312 8992 : button->setBackColor(FXRGBA(253, 255, 206, 255));
313 8992 : if (TraCIServer::getInstance() == nullptr) {
314 8992 : myTraCiFrame->hide();
315 : }
316 : // build geo coordiantes
317 8992 : myGeoFrame = new FXHorizontalFrame(myStatusbar, GUIDesignHorizontalFrameStatusBar);
318 8992 : myGeoCoordinate = GUIDesigns::buildFXLabel(myGeoFrame, TL("N/A"), "", TL("Original coordinate (before coordinate transformation in netconvert)"), nullptr, LAYOUT_CENTER_Y);
319 : // build cartesian coordinates
320 8992 : myCartesianFrame = new FXHorizontalFrame(myStatusbar, GUIDesignHorizontalFrameStatusBar);
321 8992 : myCartesianCoordinate = GUIDesigns::buildFXLabel(myCartesianFrame, TL("N/A"), "", TL("Network coordinate"), nullptr, LAYOUT_CENTER_Y);
322 : // build buttons
323 : std::vector<std::string> help({
324 8992 : TL("number of running vehicles"),
325 8992 : TL("number of insertion backlogged vehicles"),
326 8992 : TL("percentage of teleports per departed vehicles"),
327 8992 : TL("number of active persons"),
328 53952 : TL("number of active containers")});
329 :
330 8992 : myStatButtons.push_back(GUIDesigns::buildFXButton(myStatusbar, "-", help[STAT_VEHS], help[STAT_VEHS], GUIIconSubSys::getIcon(GUIIcon::GREENVEHICLE), this, MID_SHOWVEHSTATS));
331 17984 : myStatButtons.push_back(GUIDesigns::buildFXButton(myStatusbar, "-", help[STAT_DELAYED], help[STAT_DELAYED], GUIIconSubSys::getIcon(GUIIcon::INSERTION_DELAY), this, MID_SHOWVEHSTATS));
332 8992 : myStatButtons.back()->hide();
333 17984 : myStatButtons.push_back(GUIDesigns::buildFXButton(myStatusbar, "-", help[STAT_TELEPORTS], help[STAT_TELEPORTS], GUIIconSubSys::getIcon(GUIIcon::TELEPORT), this, MID_SHOWVEHSTATS));
334 8992 : myStatButtons.back()->hide();
335 17984 : myStatButtons.push_back(GUIDesigns::buildFXButton(myStatusbar, "-", help[STAT_PERSONS], help[STAT_PERSONS], GUIIconSubSys::getIcon(GUIIcon::GREENPERSON), this, MID_SHOWPERSONSTATS));
336 8992 : myStatButtons.back()->hide();
337 17984 : myStatButtons.push_back(GUIDesigns::buildFXButton(myStatusbar, "-", help[STAT_CONTAINERS], help[STAT_CONTAINERS], GUIIconSubSys::getIcon(GUIIcon::GREENCONTAINER), this, MID_SHOWVEHSTATS));
338 8992 : myStatButtons.back()->hide();
339 8992 : }
340 : // make the window a mdi-window
341 8992 : myMainSplitter = new FXSplitter(this, GUIDesignSplitter | SPLITTER_VERTICAL | SPLITTER_REVERSED);
342 8992 : myMDIClient = new FXMDIClient(myMainSplitter, GUIDesignSplitterMDI);
343 8992 : myMDIMenu = new FXMDIMenu(this, myMDIClient);
344 8992 : new FXMDIWindowButton(myMenuBar, myMDIMenu, myMDIClient, FXMDIClient::ID_MDI_MENUWINDOW, GUIDesignMDIButtonLeft);
345 8992 : new FXMDIDeleteButton(myMenuBar, myMDIClient, FXMDIClient::ID_MDI_MENUCLOSE, GUIDesignMDIButtonRight);
346 8992 : new FXMDIRestoreButton(myMenuBar, myMDIClient, FXMDIClient::ID_MDI_MENURESTORE, GUIDesignMDIButtonRight);
347 8992 : new FXMDIMinimizeButton(myMenuBar, myMDIClient, FXMDIClient::ID_MDI_MENUMINIMIZE, GUIDesignMDIButtonRight);
348 : // build the message window
349 8992 : myMessageWindow = new GUIMessageWindow(myMainSplitter, this);
350 : // fill menu and tool bar
351 8992 : fillMenuBar();
352 8992 : myToolBar6->hide();
353 8992 : myToolBar7->hide();
354 8992 : myToolBar9->hide();
355 8992 : myToolBar10->hide();
356 : // build additional threads
357 8992 : myLoadThread = new GUILoadThread(getApp(), this, myEvents, myLoadThreadEvent, isLibsumo);
358 8992 : myRunThread = new GUIRunThread(getApp(), this, mySimDelay, myEvents, myRunThreadEvent);
359 : // set the status bar
360 8992 : setStatusBarText(TL("Ready."));
361 : // set the caption
362 8992 : setTitle(MFXUtils::getTitleText("SUMO " VERSION_STRING));
363 : // start the simulation-thread (it will loop until the application ends deciding by itself whether to perform a step or not)
364 8992 : myRunThread->start();
365 8992 : setIcon(GUIIconSubSys::getIcon(GUIIcon::SUMO));
366 8992 : setMiniIcon(GUIIconSubSys::getIcon(GUIIcon::SUMO_MINI));
367 17984 : }
368 :
369 :
370 : void
371 8992 : GUIApplicationWindow::create() {
372 8992 : setWindowSizeAndPos();
373 8992 : gCurrentFolder = getApp()->reg().readStringEntry("SETTINGS", "basedir", "");
374 8992 : FXMainWindow::create();
375 8992 : myMenuBarDrag->create();
376 8992 : myToolBarDrag1->create();
377 8992 : myToolBarDrag2->create();
378 8992 : myToolBarDrag3->create();
379 8992 : myToolBarDrag4->create();
380 8992 : myToolBarDrag5->create();
381 8992 : myToolBarDrag6->create();
382 8992 : myToolBarDrag7->create();
383 8992 : myFileMenu->create();
384 8992 : mySelectByPermissions->create();
385 8992 : myEditMenu->create();
386 8992 : mySettingsMenu->create();
387 8992 : myLocatorMenu->create();
388 8992 : myControlMenu->create();
389 8992 : myWindowMenu->create();
390 8992 : myLanguageMenu->create();
391 8992 : myHelpMenu->create();
392 8992 : FXint textWidth = getApp()->getNormalFont()->getTextWidth("8", 1) * 24;
393 8992 : myCartesianFrame->setWidth(textWidth);
394 8992 : myGeoFrame->setWidth(textWidth);
395 8992 : if (myTestFrame) {
396 0 : myTestFrame->setWidth(textWidth);
397 : }
398 :
399 8992 : show(PLACEMENT_DEFAULT);
400 17984 : if (!OptionsCont::getOptions().isSet("window-size")) {
401 8988 : if (getApp()->reg().readIntEntry("SETTINGS", "maximized", 0) == 1) {
402 0 : maximize();
403 : }
404 : }
405 8992 : myShowTimeAsHMS = (getApp()->reg().readIntEntry("gui", "timeasHMS", 0) == 1);
406 8992 : myAlternateSimDelay = getApp()->reg().readIntEntry("gui", "alternateSimDelay", 100);
407 8992 : const std::string& onlineMaps = getApp()->reg().readStringEntry("gui", "onlineMaps", "");
408 26976 : for (const std::string& entry : StringTokenizer(onlineMaps, "\n").getVector()) {
409 0 : const std::vector<std::string> split = StringTokenizer(entry, "\t").getVector();
410 0 : if (split.size() == 2) {
411 0 : myOnlineMaps[split[0]] = split[1];
412 : }
413 8992 : }
414 8992 : if (myOnlineMaps.empty()) {
415 8992 : myOnlineMaps["GeoHack"] = "https://geohack.toolforge.org/geohack.php?params=%lat;%lon_scale:1000";
416 8992 : myOnlineMaps["Google Maps"] = "https://www.google.com/maps/search/?api=1&query=%lat,%lon&zoom=19";
417 17984 : myOnlineMaps["OSM"] = "https://www.openstreetmap.org/?mlat=%lat&mlon=%lon&zoom=18&layers=M";
418 : }
419 8992 : updateTimeLCDTooltip();
420 8992 : }
421 :
422 :
423 17932 : GUIApplicationWindow::~GUIApplicationWindow() {
424 8966 : myRunThread->prepareDestruction();
425 8966 : myRunThread->join();
426 8965 : closeAllWindows();
427 : // close icons
428 8965 : GUIIconSubSys::close();
429 8965 : GUICursorSubSys::close();
430 : // delete visual
431 8965 : delete myGLVisual;
432 : // delete some non-parented windows
433 8965 : delete myToolBarDrag1;
434 8965 : delete mySimDelayTarget;
435 : // delete rest of elements
436 8965 : delete myFileMenuRecentNetworks;
437 8965 : delete myFileMenuRecentConfigs;
438 8965 : delete myRunThread;
439 8965 : delete myFileMenu;
440 8965 : delete myEditMenu;
441 8965 : delete mySelectByPermissions;
442 8965 : delete mySettingsMenu;
443 8965 : delete myLocatorMenu;
444 8965 : delete myControlMenu;
445 8965 : delete myLanguageMenu;
446 8965 : delete myWindowMenu;
447 8965 : delete myHelpMenu;
448 8965 : delete myLoadThread;
449 :
450 16744 : while (!myEvents.empty()) {
451 : // get the next event
452 7779 : GUIEvent* e = myEvents.top();
453 7779 : myEvents.pop();
454 7779 : delete e;
455 : }
456 9063 : for (auto item : myHotkeyPress) {
457 98 : delete item.second;
458 : }
459 9061 : for (auto item : myHotkeyRelease) {
460 96 : delete item.second;
461 : }
462 26896 : }
463 :
464 :
465 : void
466 0 : GUIApplicationWindow::detach() {
467 0 : FXMainWindow::detach();
468 0 : myMenuBarDrag->detach();
469 0 : myToolBarDrag1->detach();
470 0 : }
471 :
472 :
473 : void
474 8992 : GUIApplicationWindow::addToWindowsMenu(FXMenuPane* /*menuPane*/) {
475 : // unused, implement in children
476 8992 : }
477 :
478 :
479 : void
480 8992 : GUIApplicationWindow::fillMenuBar() {
481 : // build file menu
482 8992 : myFileMenu = new FXMenuPane(this);
483 8992 : GUIDesigns::buildFXMenuTitle(myMenuBar, TL("&File"), nullptr, myFileMenu);
484 26976 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
485 17984 : TL("New Window"), "Ctrl+Shift+N", TL("Open a new sumo-gui window."),
486 : nullptr, this, MID_HOTKEY_CTRL_SHIFT_N_NEWWINDOW);
487 8992 : new FXMenuSeparator(myFileMenu);
488 35968 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
489 17984 : TL("&Open Simulation..."), "Ctrl+O", TL("Open a simulation (Configuration file)."),
490 : GUIIconSubSys::getIcon(GUIIcon::OPEN_SUMOCONFIG), this, MID_HOTKEY_CTRL_O_OPENSIMULATION_OPENNETWORK);
491 35968 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
492 17984 : TL("Open &Network..."), "Ctrl+N", TL("Open a network."),
493 : GUIIconSubSys::getIcon(GUIIcon::OPEN_NET), this, MID_HOTKEY_CTRL_N_OPENNETWORK_NEWNETWORK);
494 35968 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
495 17984 : TL("Open Shapes "), "Ctrl+P", TL("Load POIs and Polygons for visualization."),
496 : GUIIconSubSys::getIcon(GUIIcon::OPEN_SHAPES), this, MID_HOTKEY_CTRL_P_OPENSHAPES);
497 35968 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
498 17984 : TL("Open EdgeData "), "Ctrl+U", TL("Load edge related data for visualization."),
499 : GUIIconSubSys::getIcon(GUIIcon::OPEN_NET), this, MID_HOTKEY_CTRL_U_OPENEDGEDATA);
500 35968 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
501 17984 : TL("&Reload"), "Ctrl+R", TL("Reloads the simulation / the network."),
502 : GUIIconSubSys::getIcon(GUIIcon::RELOAD), this, MID_HOTKEY_CTRL_R_RELOAD);
503 35968 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
504 17984 : TL("Quick-Reload"), "Ctrl+0", TL("Reloads the simulation (but not network)."),
505 : GUIIconSubSys::getIcon(GUIIcon::RELOAD), this, MID_HOTKEY_CTRL_QUICK_RELOAD);
506 8992 : new FXMenuSeparator(myFileMenu);
507 35968 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
508 17984 : TL("Save Configuration"), "Ctrl+Shift+S", TL("Save current options as a configuration file."),
509 : GUIIconSubSys::getIcon(GUIIcon::SAVE_SUMOCONFIG), this, MID_HOTKEY_CTRL_SHIFT_S_SAVESUMOCONFIG);
510 35968 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
511 17984 : TL("Close"), "Ctrl+W", TL("Close the simulation."),
512 : GUIIconSubSys::getIcon(GUIIcon::CLOSE), this, MID_HOTKEY_CTRL_W_CLOSESIMULATION);
513 8992 : new FXMenuSeparator(myFileMenu);
514 : // build recent files
515 8992 : buildRecentNetworks(myFileMenu, myFileMenuRecentNetworks);
516 8992 : buildRecentConfigs(myFileMenu, myFileMenuRecentConfigs);
517 8992 : new FXMenuSeparator(myFileMenu);
518 26976 : GUIDesigns::buildFXMenuCommandShortcut(myFileMenu,
519 17984 : TL("&Quit"), "Ctrl+Q", TL("Quit the Application."),
520 : nullptr, this, MID_HOTKEY_CTRL_Q_CLOSE);
521 : // build edit menu
522 8992 : mySelectByPermissions = new FXMenuPane(this);
523 8992 : std::vector<std::string> vehicleClasses = SumoVehicleClassStrings.getStrings();
524 314720 : for (const auto& vehicleClass : vehicleClasses) {
525 305728 : GUIDesigns::buildFXMenuCommand(mySelectByPermissions, vehicleClass, VClassIcons::getVClassIcon(SumoVehicleClassStrings.get(vehicleClass)), this, MID_HOTKEY_CTRL_E_EDITSELECTION_LOADNETEDITCONFIG);
526 : }
527 8992 : myEditMenu = new FXMenuPane(this);
528 8992 : GUIDesigns::buildFXMenuTitle(myMenuBar, TL("&Edit"), nullptr, myEditMenu);
529 35968 : GUIDesigns::buildFXMenuCommandShortcut(myEditMenu,
530 17984 : TL("Edit Selected..."), "Ctrl+E", TL("Opens a dialog for editing the list of selected items."),
531 : GUIIconSubSys::getIcon(GUIIcon::FLAG), this, MID_HOTKEY_CTRL_E_EDITSELECTION_LOADNETEDITCONFIG);
532 8992 : mySelectLanesMenuCascade = new FXMenuCascade(myEditMenu, TL("Select lanes which allow..."), GUIIconSubSys::getIcon(GUIIcon::FLAG), mySelectByPermissions);
533 8992 : mySelectLanesMenuCascade->setHelpText(TL("Opens a menu for selecting a vehicle class by which to selected lanes."));
534 8992 : new FXMenuSeparator(myEditMenu);
535 35968 : GUIDesigns::buildFXMenuCommandShortcut(myEditMenu,
536 17984 : TL("Set Breakpoint"), "B", TL("Sets a breakpoint at the current simulation step"),
537 : GUIIconSubSys::getIcon(GUIIcon::APP_BREAKPOINTS), this, MID_HOTKEY_B_BREAKPOINT);
538 35968 : GUIDesigns::buildFXMenuCommandShortcut(myEditMenu,
539 17984 : TL("Set Breakpoint with offset"), "Alt+B", TL("Sets a breakpoint at the current simulation step + offset configured in application settings"),
540 : GUIIconSubSys::getIcon(GUIIcon::APP_BREAKPOINTS), this, MID_HOTKEY_ALT_B_BREAKPOINT_EARLY);
541 35968 : GUIDesigns::buildFXMenuCommandShortcut(myEditMenu,
542 17984 : TL("Edit Breakpoints"), "Ctrl+B", TL("Opens a dialog for editing breakpoints."),
543 : GUIIconSubSys::getIcon(GUIIcon::APP_BREAKPOINTS), this, MID_HOTKEY_CTRL_B_EDITBREAKPOINT_OPENDATAELEMENTS);
544 35968 : GUIDesigns::buildFXMenuCommandShortcut(myEditMenu,
545 17984 : TL("Edit Visualisation"), "F9", TL("Opens a dialog for editing visualization settings."),
546 : GUIIconSubSys::getIcon(GUIIcon::COLORWHEEL), this, MID_HOTKEY_F9_EDIT_VIEWSCHEME);
547 35968 : GUIDesigns::buildFXMenuCommandShortcut(myEditMenu,
548 17984 : TL("Edit Viewport"), "Ctrl+I", TL("Opens a dialog for editing viewing area, zoom and rotation."),
549 : GUIIconSubSys::getIcon(GUIIcon::EDITVIEWPORT), this, MID_HOTKEY_CTRL_I_EDITVIEWPORT);
550 8992 : new FXMenuSeparator(myEditMenu);
551 : // add open in sumo options
552 8992 : myLoadAdditionalsInNetedit = GUIDesigns::buildFXMenuCheckbox(myEditMenu, TL("Load additionals in netedit"), TL("Load additionals in netedit."), this, MID_TOOLBAREDIT_LOADADDITIONALS);
553 8992 : myLoadAdditionalsInNetedit->setCheck(TRUE);
554 8992 : myLoadDemandInNetedit = GUIDesigns::buildFXMenuCheckbox(myEditMenu, TL("Load demand in netedit"), TL("Load demand in netedit."), this, MID_TOOLBAREDIT_LOADDEMAND);
555 8992 : myLoadDemandInNetedit->setCheck(FALSE);
556 26976 : myOpenInNetedit = GUIDesigns::buildFXMenuCommandShortcut(myEditMenu,
557 17984 : TL("Open in netedit"), "Ctrl+T", TL("Opens current simulation in NETEDIT."),
558 : GUIIconSubSys::getIcon(GUIIcon::NETEDIT_MINI), this, MID_HOTKEY_CTRL_T_OPENNETEDIT_OPENSUMO);
559 26976 : myOpenNetInNetedit = GUIDesigns::buildFXMenuCommandShortcut(myEditMenu,
560 17984 : TL("Open network in netedit"), "Ctrl+Shift+T", TL("Opens current network in NETEDIT."),
561 : GUIIconSubSys::getIcon(GUIIcon::NETEDIT_MINI), this, MID_HOTKEY_CTRL_SHIFT_T_OPEN_NET);
562 : // build settings menu
563 8992 : mySettingsMenu = new FXMenuPane(this);
564 8992 : GUIDesigns::buildFXMenuTitle(myMenuBar, TL("&Settings"), nullptr, mySettingsMenu);
565 26976 : GUIDesigns::buildFXMenuCommandShortcut(mySettingsMenu,
566 17984 : TL("Application Settings"), "Ctrl+H", TL("Open a Dialog for Application Settings editing."),
567 : nullptr, this, MID_HOTKEY_CTRL_H_APPSETTINGS_OPENEDGETYPES);
568 17984 : myGamingModeCheckbox = new FXMenuCheck(mySettingsMenu,
569 8992 : TL("Gaming Mode\tCtrl+G\tToggle gaming mode on/off."),
570 8992 : this, MID_HOTKEY_CTRL_G_GAMINGMODE_TOGGLEGRID);
571 35968 : GUIDesigns::buildFXMenuCommandShortcut(mySettingsMenu,
572 17984 : TL("Full Screen Mode"), "Ctrl+F", TL("Toggle full screen mode on/off."),
573 : GUIIconSubSys::getIcon(GUIIcon::FULL_SCREEN), this, MID_HOTKEY_CTRL_F_FULSCREENMODE);
574 : // build Locate menu
575 8992 : myLocatorMenu = new FXMenuPane(this);
576 8992 : GUIDesigns::buildFXMenuTitle(myMenuBar, TL("&Locate"), nullptr, myLocatorMenu);
577 35968 : GUIDesigns::buildFXMenuCommandShortcut(myLocatorMenu,
578 17984 : TL("&Junctions"), "Shift+J", TL("Open a dialog for locating a Junction."),
579 : GUIIconSubSys::getIcon(GUIIcon::LOCATEJUNCTION), this, MID_HOTKEY_SHIFT_J_LOCATEJUNCTION);
580 35968 : GUIDesigns::buildFXMenuCommandShortcut(myLocatorMenu,
581 17984 : TL("&Edges"), "Shift+E", TL("Open a dialog for locating an Edge."),
582 : GUIIconSubSys::getIcon(GUIIcon::LOCATEEDGE), this, MID_HOTKEY_SHIFT_E_LOCATEEDGE);
583 35968 : GUIDesigns::buildFXMenuCommandShortcut(myLocatorMenu,
584 17984 : TL("&Vehicles"), "Shift+V", TL("Open a dialog for locating a Vehicle."),
585 : GUIIconSubSys::getIcon(GUIIcon::LOCATEVEHICLE), this, MID_HOTKEY_SHIFT_V_LOCATEVEHICLE);
586 35968 : GUIDesigns::buildFXMenuCommandShortcut(myLocatorMenu,
587 17984 : TL("&Persons"), "Shift+P", TL("Open a dialog for locating a Person."),
588 : GUIIconSubSys::getIcon(GUIIcon::LOCATEPERSON), this, MID_HOTKEY_SHIFT_P_LOCATEPERSON);
589 35968 : GUIDesigns::buildFXMenuCommandShortcut(myLocatorMenu,
590 17984 : TL("&Container"), "Shift+C", TL("Open a dialog for locating a Container."),
591 : GUIIconSubSys::getIcon(GUIIcon::LOCATECONTAINER), this, MID_HOTKEY_SHIFT_C_LOCATECONTAINER);
592 35968 : GUIDesigns::buildFXMenuCommandShortcut(myLocatorMenu,
593 17984 : TL("&TLS"), "Shift+T", TL("Open a dialog for locating a Traffic Light."),
594 : GUIIconSubSys::getIcon(GUIIcon::LOCATETLS), this, MID_HOTKEY_SHIFT_T_LOCATETLS);
595 35968 : GUIDesigns::buildFXMenuCommandShortcut(myLocatorMenu,
596 17984 : TL("&Additional"), "Shift+A", TL("Open a dialog for locating an Additional Structure."),
597 : GUIIconSubSys::getIcon(GUIIcon::LOCATEADD), this, MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL);
598 35968 : GUIDesigns::buildFXMenuCommandShortcut(myLocatorMenu,
599 17984 : TL("P&oI"), "Shift+O", TL("Open a dialog for locating a Point of Interest."),
600 : GUIIconSubSys::getIcon(GUIIcon::LOCATEPOI), this, MID_HOTKEY_SHIFT_O_LOCATEPOI);
601 35968 : GUIDesigns::buildFXMenuCommandShortcut(myLocatorMenu,
602 17984 : TL("Po&lygon"), "Shift+L", TL("Open a dialog for locating a Polygon."),
603 : GUIIconSubSys::getIcon(GUIIcon::LOCATEPOLY), this, MID_HOTKEY_SHIFT_L_LOCATEPOLY);
604 8992 : new FXMenuSeparator(myLocatorMenu);
605 17984 : GUIDesigns::buildFXMenuCheckbox(myLocatorMenu, TL("Show Internal Structures"), TL("Show internal junctions and streets in locator dialog."), this, MID_LISTINTERNAL);
606 17984 : FXMenuCheck* listParking = GUIDesigns::buildFXMenuCheckbox(myLocatorMenu, TL("Show Parking Vehicles"), TL("Show parking vehicles in locator dialog."), this, MID_LISTPARKING);
607 8992 : listParking->setCheck(myListParking);
608 17984 : GUIDesigns::buildFXMenuCheckbox(myLocatorMenu, TL("Show vehicles outside the road network"), TL("Show vehicles that are teleporting or driving remote-controlled outside the road network in locator dialog."), this, MID_LISTTELEPORTING);
609 : // build control menu
610 : // the shortcut designator is not only at text in the submenu but also defines the real shortcut key assigned with it!
611 : // secondary shortcuts (ctrl+A, ctrl+S, ctrl+D) are defined in GUIShortcutsSubSys::buildSUMOAccelerators
612 8992 : myControlMenu = new FXMenuPane(this);
613 8992 : GUIDesigns::buildFXMenuTitle(myMenuBar, TL("Simulation"), nullptr, myControlMenu);
614 35968 : GUIDesigns::buildFXMenuCommandShortcut(myControlMenu,
615 17984 : TL("Run"), "A,space", TL("Start/ Resume the simulation."),
616 : GUIIconSubSys::getIcon(GUIIcon::START), this, MID_HOTKEY_CTRL_A_STARTSIMULATION_OPENADDITIONALELEMENTS);
617 35968 : GUIDesigns::buildFXMenuCommandShortcut(myControlMenu,
618 8992 : TLC("Simulation", "Stop"), "S,space", TL("Halt the simulation."),
619 : GUIIconSubSys::getIcon(GUIIcon::STOP), this, MID_HOTKEY_CTRL_S_STOPSIMULATION_SAVENETWORK);
620 35968 : GUIDesigns::buildFXMenuCommandShortcut(myControlMenu,
621 17984 : TL("Step"), "D", TL("Perform one simulation step."),
622 : GUIIconSubSys::getIcon(GUIIcon::STEP), this, MID_HOTKEY_CTRL_D_SINGLESIMULATIONSTEP_OPENDEMANDELEMENTS);
623 26976 : GUIDesigns::buildFXMenuCommandShortcut(myControlMenu,
624 17984 : TL("Delay+"), "PgUp", TL("Increase simulation step delay."), nullptr, this, MID_DELAY_INC);
625 26976 : GUIDesigns::buildFXMenuCommandShortcut(myControlMenu,
626 17984 : TL("Delay-"), "PgDn", TL("Decrease simulation step delay."), nullptr, this, MID_DELAY_DEC);
627 35968 : GUIDesigns::buildFXMenuCommandShortcut(myControlMenu,
628 17984 : TL("Save"), "", TL("Save the current simulation state to a file."),
629 : GUIIconSubSys::getIcon(GUIIcon::SAVE), this, MID_SIMSAVE);
630 35968 : GUIDesigns::buildFXMenuCommandShortcut(myControlMenu,
631 17984 : TL("Load"), "", TL("Load simulation state for the current network from file."),
632 : GUIIconSubSys::getIcon(GUIIcon::OPEN), this, MID_SIMLOAD);
633 : // build windows menu
634 8992 : myWindowMenu = new FXMenuPane(this);
635 8992 : GUIDesigns::buildFXMenuTitle(myMenuBar, TL("&Window"), nullptr, myWindowMenu);
636 17984 : GUIDesigns::buildFXMenuCommandShortcut(myWindowMenu, TL("Open new view"), "", TL("Open a new microscopic view."), GUIIconSubSys::getIcon(GUIIcon::MICROVIEW), this, MID_NEW_MICROVIEW);
637 : #ifdef HAVE_OSG
638 17984 : GUIDesigns::buildFXMenuCommandShortcut(myWindowMenu, TL("Open new 3D view"), "", TL("Open a new 3D view."), GUIIconSubSys::getIcon(GUIIcon::OSGVIEW), this, MID_NEW_OSGVIEW);
639 : #endif
640 26976 : GUIDesigns::buildFXMenuCommandShortcut(myWindowMenu,
641 17984 : TL("Tile &Horizontally"), "", TL("Tile the views horizontally."),
642 8992 : GUIIconSubSys::getIcon(GUIIcon::WINDOWS_TILE_HORI), myMDIClient, FXMDIClient::ID_MDI_TILEHORIZONTAL);
643 26976 : GUIDesigns::buildFXMenuCommandShortcut(myWindowMenu,
644 17984 : TL("Tile &Vertically"), "", TL("Tile the views vertically."),
645 8992 : GUIIconSubSys::getIcon(GUIIcon::WINDOWS_TILE_VERT), myMDIClient, FXMDIClient::ID_MDI_TILEVERTICAL);
646 26976 : GUIDesigns::buildFXMenuCommandShortcut(myWindowMenu,
647 17984 : TL("Cascade"), "", TL("Cascade the views."),
648 : GUIIconSubSys::getIcon(GUIIcon::WINDOWS_CASCADE),
649 8992 : myMDIClient, FXMDIClient::ID_MDI_CASCADE);
650 26976 : GUIDesigns::buildFXMenuCommandShortcut(myWindowMenu,
651 8992 : TL("&Close"), "", TL("Close the selected view."),
652 8992 : nullptr, myMDIClient, FXMDIClient::ID_MDI_CLOSE);
653 8992 : FXMenuSeparator* sep2 = new FXMenuSeparator(myWindowMenu);
654 8992 : sep2->setTarget(myMDIClient);
655 : sep2->setSelector(FXMDIClient::ID_MDI_ANY);
656 : // for whatever reason, sonar complains in the next line that sep2 may leak, but fox does the cleanup
657 8992 : GUIDesigns::buildFXMenuCommand(myWindowMenu, "", nullptr, myMDIClient, FXMDIClient::ID_MDI_1); // NOSONAR
658 8992 : GUIDesigns::buildFXMenuCommand(myWindowMenu, "", nullptr, myMDIClient, FXMDIClient::ID_MDI_2);
659 8992 : GUIDesigns::buildFXMenuCommand(myWindowMenu, "", nullptr, myMDIClient, FXMDIClient::ID_MDI_3);
660 8992 : GUIDesigns::buildFXMenuCommand(myWindowMenu, "", nullptr, myMDIClient, FXMDIClient::ID_MDI_4);
661 8992 : GUIDesigns::buildFXMenuCommand(myWindowMenu, TL("&Others..."), nullptr, myMDIClient, FXMDIClient::ID_MDI_OVER_5);
662 :
663 8992 : new FXMenuSeparator(myWindowMenu);
664 17984 : GUIDesigns::buildFXMenuCheckbox(myWindowMenu, TL("Show Status Line"), TL("Toggle the Status Bar on/off."), myStatusbar, FXWindow::ID_TOGGLESHOWN);
665 17984 : GUIDesigns::buildFXMenuCheckbox(myWindowMenu, TL("Show Message Window"), TL("Toggle the Message Window on/off."), myMessageWindow, FXWindow::ID_TOGGLESHOWN);
666 17984 : GUIDesigns::buildFXMenuCheckbox(myWindowMenu, TL("Show Simulation Time"), TL("Toggle the Simulation Time on/off."), myToolBar3, FXWindow::ID_TOGGLESHOWN);
667 17984 : GUIDesigns::buildFXMenuCheckbox(myWindowMenu, TL("Show Simulation Delay"), TL("Toggle the Simulation Delay Entry on/off."), myToolBar4, FXWindow::ID_TOGGLESHOWN);
668 8992 : addToWindowsMenu(myWindowMenu);
669 :
670 8992 : new FXMenuSeparator(myWindowMenu);
671 35968 : GUIDesigns::buildFXMenuCommandShortcut(myWindowMenu,
672 17984 : TL("Clear Message Window"), "", TL("Clear the message window."),
673 : GUIIconSubSys::getIcon(GUIIcon::CLEARMESSAGEWINDOW), this, MID_CLEARMESSAGEWINDOW);
674 : // build windows menu
675 8992 : buildLanguageMenu(myMenuBar);
676 : // build help menu
677 8992 : myHelpMenu = new FXMenuPane(this);
678 8992 : GUIDesigns::buildFXMenuTitle(myMenuBar,
679 8992 : TL("&Help"),
680 : nullptr, myHelpMenu);
681 17984 : GUIDesigns::buildFXMenuCommandShortcut(myHelpMenu, TL("&Online Documentation"), "F1", TL("Open Online documentation."),
682 : nullptr, this, MID_HOTKEY_F1_ONLINEDOCUMENTATION);
683 8992 : new FXMenuSeparator(myHelpMenu);
684 17984 : GUIDesigns::buildFXMenuCommandShortcut(myHelpMenu, TL("&Changelog"), "", TL("Open Changelog."),
685 : nullptr, this, MID_CHANGELOG);
686 17984 : GUIDesigns::buildFXMenuCommandShortcut(myHelpMenu, TL("&Hotkeys"), "", TL("Open Hotkeys."),
687 : nullptr, this, MID_HOTKEYS);
688 17984 : GUIDesigns::buildFXMenuCommandShortcut(myHelpMenu, TL("&Tutorial"), "", TL("Open Tutorial."),
689 : nullptr, this, MID_TUTORIAL);
690 17984 : GUIDesigns::buildFXMenuCommandShortcut(myHelpMenu, TL("&Feedback"), "", TL("Open feedback dialog."),
691 : nullptr, this, MID_FEEDBACK);
692 8992 : new FXMenuSeparator(myHelpMenu);
693 17984 : GUIDesigns::buildFXMenuCommandShortcut(myHelpMenu, TL("&About"), "F12", TL("About sumo-gui."),
694 : GUIIconSubSys::getIcon(GUIIcon::SUMO_MINI), this, MID_HOTKEY_F12_ABOUT);
695 : // build SUMO Accelerators (hotkeys)
696 8992 : GUIShortcutsSubSys::buildAccelerators(getAccelTable(), this, true);
697 8992 : }
698 :
699 :
700 : void
701 8992 : GUIApplicationWindow::buildToolBars() {
702 : // file and simulation tool bar
703 : {
704 8992 : myToolBarDrag1 = new FXToolBarShell(this, GUIDesignToolBar);
705 8992 : myToolBar1 = new FXToolBar(myTopDock, myToolBarDrag1, GUIDesignToolBarRaisedNextTop);
706 8992 : new FXToolBarGrip(myToolBar1, myToolBar1, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
707 : // build file tools
708 17984 : new MFXButtonTooltip(myToolBar1, myStaticTooltipMenu, TL("\tOpen simulation\tOpen a simulation (Configuration file)."),
709 8992 : GUIIconSubSys::getIcon(GUIIcon::OPEN_SUMOCONFIG), this, MID_HOTKEY_CTRL_O_OPENSIMULATION_OPENNETWORK, GUIDesignButtonToolbar);
710 17984 : new MFXButtonTooltip(myToolBar1, myStaticTooltipMenu, TL("\tOpen network\tOpen a network."),
711 8992 : GUIIconSubSys::getIcon(GUIIcon::OPEN_NET), this, MID_HOTKEY_CTRL_N_OPENNETWORK_NEWNETWORK, GUIDesignButtonToolbar);
712 17984 : new MFXButtonTooltip(myToolBar1, myStaticTooltipMenu, TL("\tReload\tReloads the simulation / the network."),
713 8992 : GUIIconSubSys::getIcon(GUIIcon::RELOAD), this, MID_HOTKEY_CTRL_R_RELOAD, GUIDesignButtonToolbar);
714 : }
715 : // simulation toolbar
716 : {
717 8992 : myToolBarDrag2 = new FXToolBarShell(this, GUIDesignToolBar);
718 8992 : myToolBar2 = new FXToolBar(myTopDock, myToolBarDrag2, GUIDesignToolBarRaisedSameTop);
719 8992 : new FXToolBarGrip(myToolBar2, myToolBar2, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
720 : // build simulation tools
721 17984 : new MFXButtonTooltip(myToolBar2, myStaticTooltipMenu, TL("\tRun\tStart/Resume the loaded simulation."),
722 8992 : GUIIconSubSys::getIcon(GUIIcon::START), this, MID_HOTKEY_CTRL_A_STARTSIMULATION_OPENADDITIONALELEMENTS, GUIDesignButtonToolbar);
723 17984 : new MFXButtonTooltip(myToolBar2, myStaticTooltipMenu, TL("\tStop\tHalt the running simulation."),
724 8992 : GUIIconSubSys::getIcon(GUIIcon::STOP), this, MID_HOTKEY_CTRL_S_STOPSIMULATION_SAVENETWORK, GUIDesignButtonToolbar);
725 17984 : new MFXButtonTooltip(myToolBar2, myStaticTooltipMenu, TL("\tStep\tPerform a single simulation step."),
726 8992 : GUIIconSubSys::getIcon(GUIIcon::STEP), this, MID_HOTKEY_CTRL_D_SINGLESIMULATIONSTEP_OPENDEMANDELEMENTS, GUIDesignButtonToolbar);
727 : }
728 : // Simulation Step Display
729 : {
730 8992 : myToolBarDrag3 = new FXToolBarShell(this, GUIDesignToolBar);
731 8992 : myToolBar3 = new FXToolBar(myTopDock, myToolBarDrag3, GUIDesignToolBarRaisedSameTop);
732 8992 : new FXToolBarGrip(myToolBar3, myToolBar3, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
733 8992 : new MFXButtonTooltip(myToolBar3, myStaticTooltipMenu, TL("Time:\tToggle between time formats\tToggle between seconds and hour:minute:seconds display."), nullptr, this, MID_TIME_TOGGLE, GUIDesignButtonToolbarText);
734 :
735 8992 : myLCDLabel = new MFXLCDLabel(myToolBar3, myStaticTooltipMenu, 16, nullptr, 0, JUSTIFY_RIGHT);
736 8992 : myLCDLabel->setHorizontal(2);
737 8992 : myLCDLabel->setVertical(6);
738 8992 : myLCDLabel->setThickness(2);
739 8992 : myLCDLabel->setGroove(2);
740 8992 : myLCDLabel->setText("----------------");
741 : }
742 : // Simulation Delay
743 : {
744 8992 : myToolBarDrag4 = new FXToolBarShell(this, GUIDesignToolBar);
745 8992 : myToolBar4 = new FXToolBar(myTopDock, myToolBarDrag4, GUIDesignToolBarRaisedSameTop);
746 8992 : new FXToolBarGrip(myToolBar4, myToolBar4, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
747 8992 : new MFXButtonTooltip(myToolBar4, myStaticTooltipMenu, TL("Delay (ms):\tDelay per simulated second\tDelay per simulated second. Click to toggle between the last two delay values."), nullptr, this, MID_DELAY_TOGGLE, GUIDesignButtonToolbarText);
748 : // create spinner for delay
749 8992 : mySimDelay = 0;
750 8992 : mySimDelayTarget = new FXDataTarget(mySimDelay);
751 8992 : mySimDelaySpinner = new MFXRealSpinner(myToolBar4, 7, mySimDelayTarget, FXDataTarget::ID_VALUE, GUIDesignSpinDial);
752 : // create slider
753 8992 : mySimDelaySlider = new FXSlider(myToolBar4, mySimDelayTarget, FXDataTarget::ID_VALUE, GUIDesignSlider);
754 8992 : mySimDelaySlider->setRange(0, 1000);
755 8992 : mySimDelaySlider->setHeadSize(10);
756 8992 : mySimDelaySlider->setIncrement(50);
757 8992 : mySimDelaySlider->setTickDelta(100);
758 8992 : mySimDelaySlider->setValue((int)mySimDelay);
759 : //mySimDelayTarget->setNumberFormat(0);
760 : //mySimDelayTarget->setIncrements(1, 10, 10);
761 8992 : mySimDelaySpinner->setIncrement(10);
762 8992 : mySimDelaySpinner->setRange(0, 10000);
763 8992 : mySimDelaySpinner->setValue(mySimDelay);
764 : }
765 : // Scale traffic (flows and incrementally loaded vehicles)
766 : {
767 8992 : myToolBarDrag8 = new FXToolBarShell(this, GUIDesignToolBar);
768 8992 : myToolBar8 = new FXToolBar(myTopDock, myToolBarDrag8, GUIDesignToolBarRaisedSameTop);
769 8992 : new FXToolBarGrip(myToolBar8, myToolBar8, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
770 8992 : myScaleTrafficTooltip = new MFXLabelTooltip(myToolBar8, myStaticTooltipMenu, TL("Scale Traffic:"), nullptr, LAYOUT_TOP | LAYOUT_LEFT);
771 17984 : myScaleTrafficTooltip->setHelpText(TL("Scale traffic volume from running flows and from vehicles that are loaded incrementally from route files."));
772 8992 : myDemandScaleSpinner = new MFXRealSpinner(myToolBar8, 7, this, MID_DEMAND_SCALE, GUIDesignSpinDial);
773 8992 : myDemandScaleSpinner->setIncrement(0.5);
774 8992 : myDemandScaleSpinner->setRange(0, 1000);
775 8992 : myDemandScaleSpinner->setValue(1);
776 : }
777 : // Views
778 : {
779 8992 : myToolBarDrag5 = new FXToolBarShell(this, GUIDesignToolBar);
780 8992 : myToolBar5 = new FXToolBar(myTopDock, myToolBarDrag5, GUIDesignToolBarRaisedSameTop);
781 8992 : new FXToolBarGrip(myToolBar5, myToolBar5, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
782 : // build view tools
783 26976 : new MFXButtonTooltip(myToolBar5, myStaticTooltipMenu, (std::string("\t") + TL("Open new view") + std::string("\t") + TL("Open a new microscopic view.")).c_str(),
784 17984 : GUIIconSubSys::getIcon(GUIIcon::MICROVIEW), this, MID_NEW_MICROVIEW, GUIDesignButtonToolbar);
785 : #ifdef HAVE_OSG
786 26976 : new MFXButtonTooltip(myToolBar5, myStaticTooltipMenu, (std::string("\t") + TL("Open new 3D view") + std::string("\t") + TL("Open a new 3D view.")).c_str(),
787 17984 : GUIIconSubSys::getIcon(GUIIcon::OSGVIEW), this, MID_NEW_OSGVIEW, GUIDesignButtonToolbar);
788 : #endif
789 : }
790 : /// game specific stuff
791 : {
792 : // total waitingTime
793 8992 : myToolBarDrag6 = new FXToolBarShell(this, GUIDesignToolBar);
794 8992 : myToolBar6 = new FXToolBar(myTopDock, myToolBarDrag6, GUIDesignToolBarRaisedSameTop);
795 8992 : new FXToolBarGrip(myToolBar6, myToolBar6, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
796 17984 : GUIDesigns::buildFXLabel(myToolBar6, TL("Waiting Time:"), "", TL("Time spent waiting accumulated for all vehicles"), nullptr, LAYOUT_TOP | LAYOUT_LEFT);
797 8992 : myWaitingTimeLabel = new MFXLCDLabel(myToolBar6, myStaticTooltipMenu, 13, nullptr, 0, JUSTIFY_RIGHT);
798 8992 : myWaitingTimeLabel->setHorizontal(2);
799 8992 : myWaitingTimeLabel->setVertical(6);
800 8992 : myWaitingTimeLabel->setThickness(2);
801 8992 : myWaitingTimeLabel->setGroove(2);
802 8992 : myWaitingTimeLabel->setText("-------------");
803 : // idealistic time loss
804 8992 : myToolBarDrag7 = new FXToolBarShell(this, GUIDesignToolBar);
805 8992 : myToolBar7 = new FXToolBar(myTopDock, myToolBarDrag7, GUIDesignToolBarRaisedSameTop);
806 8992 : new FXToolBarGrip(myToolBar7, myToolBar7, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
807 17984 : GUIDesigns::buildFXLabel(myToolBar7, TL("Time Loss:"), "", TL("Time lost due to being unable to drive with maximum speed for all vehicles"), nullptr, LAYOUT_TOP | LAYOUT_LEFT);
808 8992 : myTimeLossLabel = new MFXLCDLabel(myToolBar7, myStaticTooltipMenu, 13, nullptr, 0, JUSTIFY_RIGHT);
809 8992 : myTimeLossLabel->setHorizontal(2);
810 8992 : myTimeLossLabel->setVertical(6);
811 8992 : myTimeLossLabel->setThickness(2);
812 8992 : myTimeLossLabel->setGroove(2);
813 8992 : myTimeLossLabel->setText("-------------");
814 : // total driving distance
815 8992 : myToolBarDrag9 = new FXToolBarShell(this, GUIDesignToolBar);
816 8992 : myToolBar9 = new FXToolBar(myTopDock, myToolBarDrag9, GUIDesignToolBarRaisedSameTop);
817 8992 : new FXToolBarGrip(myToolBar9, myToolBar9, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
818 17984 : GUIDesigns::buildFXLabel(myToolBar9, TL("Distance (km):"), "", TL("Total distance driven by DRT vehicles"), nullptr, LAYOUT_TOP | LAYOUT_LEFT);
819 8992 : myTotalDistanceLabel = new MFXLCDLabel(myToolBar9, myStaticTooltipMenu, 13, nullptr, 0, JUSTIFY_RIGHT);
820 8992 : myTotalDistanceLabel->setHorizontal(2);
821 8992 : myTotalDistanceLabel->setVertical(6);
822 8992 : myTotalDistanceLabel->setThickness(2);
823 8992 : myTotalDistanceLabel->setGroove(2);
824 8992 : myTotalDistanceLabel->setText("-------------");
825 : // emergency vehicle counts
826 8992 : myToolBarDrag10 = new FXToolBarShell(this, GUIDesignToolBar);
827 8992 : myToolBar10 = new FXToolBar(myTopDock, myToolBarDrag10, GUIDesignToolBarRaisedSameTop);
828 8992 : new FXToolBarGrip(myToolBar10, myToolBar10, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
829 17984 : GUIDesigns::buildFXLabel(myToolBar10, TL("Emergency Vehicle waiting time:"), "", TL("Time spent waiting accumulated for emergency vehicles"), nullptr, LAYOUT_TOP | LAYOUT_LEFT);
830 8992 : myEmergencyVehicleLabel = new MFXLCDLabel(myToolBar10, myStaticTooltipMenu, 13, nullptr, 0, JUSTIFY_RIGHT);
831 8992 : myEmergencyVehicleLabel->setHorizontal(2);
832 8992 : myEmergencyVehicleLabel->setVertical(6);
833 8992 : myEmergencyVehicleLabel->setThickness(2);
834 8992 : myEmergencyVehicleLabel->setGroove(2);
835 8992 : myEmergencyVehicleLabel->setText("-------------");
836 : }
837 8992 : }
838 :
839 :
840 : void
841 8992 : GUIApplicationWindow::buildRecentNetworks(FXMenuPane* fileMenu, FXMenuPane* fileMenuRecentNetworks) {
842 : // for whatever reason, sonar complains in the next line that sep1 may leak, but fox does the cleanup
843 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_1);
844 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_2);
845 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_3);
846 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_4);
847 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_5);
848 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_6);
849 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_7);
850 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_8);
851 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_9);
852 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentNetworks, "", &myRecentNetworks, FXRecentFiles::ID_FILE_10);
853 8992 : new FXMenuSeparator(fileMenuRecentNetworks); // NOSONAR, Fox does the cleanup
854 8992 : GUIDesigns::buildFXMenuCommand(fileMenuRecentNetworks, TL("Cl&ear Recent Networks"), nullptr, &myRecentNetworks, FXRecentFiles::ID_CLEAR);
855 8992 : GUIDesigns::buildFXMenuCommand(fileMenuRecentNetworks, TL("No Recent Networks"), nullptr, &myRecentNetworks, MFXRecentNetworks::ID_NOFILES);
856 : // set target
857 8992 : myRecentNetworks.setTarget(this);
858 : myRecentNetworks.setSelector(MID_RECENTFILE);
859 8992 : new FXMenuCascade(fileMenu, TL("Recent Networks"), nullptr, fileMenuRecentNetworks);
860 8992 : }
861 :
862 :
863 : void
864 8992 : GUIApplicationWindow::buildRecentConfigs(FXMenuPane* fileMenu, FXMenuPane* fileMenuRecentConfigs) {
865 : // for whatever reason, sonar complains in the next line that sep1 may leak, but fox does the cleanup
866 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_1);
867 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_2);
868 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_3);
869 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_4);
870 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_5);
871 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_6);
872 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_7);
873 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_8);
874 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_9);
875 8992 : GUIDesigns::buildFXMenuCommandRecentFile(fileMenuRecentConfigs, "", &myRecentConfigs, FXRecentFiles::ID_FILE_10);
876 8992 : new FXMenuSeparator(fileMenuRecentConfigs); // NOSONAR, Fox does the cleanup
877 8992 : GUIDesigns::buildFXMenuCommand(fileMenuRecentConfigs, TL("Cl&ear Recent Configs"), nullptr, &myRecentConfigs, FXRecentFiles::ID_CLEAR);
878 8992 : GUIDesigns::buildFXMenuCommand(fileMenuRecentConfigs, TL("No Recent Configs"), nullptr, &myRecentConfigs, MFXRecentNetworks::ID_NOFILES);
879 : // set target
880 8992 : myRecentConfigs.setTarget(this);
881 : myRecentConfigs.setSelector(MID_RECENTFILE);
882 8992 : new FXMenuCascade(fileMenu, TL("Recent Configs"), nullptr, fileMenuRecentConfigs);
883 8992 : }
884 :
885 :
886 : long
887 0 : GUIApplicationWindow::onCmdQuit(FXObject*, FXSelector, void*) {
888 0 : storeWindowSizeAndPos();
889 0 : getApp()->reg().writeStringEntry("SETTINGS", "basedir", gCurrentFolder.text());
890 0 : getApp()->reg().writeIntEntry("SETTINGS", "maximized", isMaximized() ? 1 : 0);
891 0 : getApp()->reg().writeIntEntry("gui", "timeasHMS", myShowTimeAsHMS ? 1 : 0);
892 0 : getApp()->reg().writeIntEntry("gui", "alternateSimDelay", (int)myAlternateSimDelay);
893 0 : closeAllWindows();
894 0 : getApp()->exit(0);
895 0 : return 1;
896 : }
897 :
898 :
899 : long
900 0 : GUIApplicationWindow::onCmdEditChosen(FXObject* menu, FXSelector, void*) {
901 0 : FXMenuCommand* mc = dynamic_cast<FXMenuCommand*>(menu);
902 0 : if (mc->getText() == StringUtils::replace(TL("Edit Selected..."), "&", "").c_str()) {
903 0 : GUIDialog_GLChosenEditor* chooser = new GUIDialog_GLChosenEditor(this, &gSelected);
904 0 : chooser->create();
905 0 : chooser->show();
906 : } else {
907 0 : if (!myAmLoading && myRunThread->networkAvailable()) {
908 0 : const SUMOVehicleClass svc = SumoVehicleClassStrings.get(mc->getText().text());
909 0 : for (MSEdgeVector::const_iterator i = MSEdge::getAllEdges().begin(); i != MSEdge::getAllEdges().end(); ++i) {
910 0 : const std::vector<MSLane*>& lanes = (*i)->getLanes();
911 0 : for (std::vector<MSLane*>::const_iterator it = lanes.begin(); it != lanes.end(); ++it) {
912 0 : GUILane* lane = dynamic_cast<GUILane*>(*it);
913 : assert(lane != 0);
914 0 : if ((lane->getPermissions() & svc) != 0) {
915 0 : gSelected.select(lane->getGlID());
916 : }
917 : }
918 : }
919 0 : if (myMDIClient->numChildren() > 0) {
920 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
921 0 : if (w != nullptr) {
922 : // color by selection
923 0 : w->getView()->editVisualisationSettings()->laneColorer.setActive(1);
924 : }
925 : }
926 : }
927 0 : updateChildren();
928 : }
929 0 : return 1;
930 : }
931 :
932 :
933 : long
934 0 : GUIApplicationWindow::onCmdEditBreakpoints(FXObject*, FXSelector, void*) {
935 0 : if (myBreakpointDialog == nullptr) {
936 0 : myBreakpointDialog = new GUIDialog_Breakpoints(this, myRunThread->getBreakpoints(), myRunThread->getBreakpointLock(), myRunThread->getSimBegin());
937 : } else {
938 0 : myBreakpointDialog->restore();
939 0 : myBreakpointDialog->setFocus();
940 0 : myBreakpointDialog->raise();
941 : }
942 0 : return 1;
943 : }
944 :
945 :
946 : long
947 0 : GUIApplicationWindow::onCmdEditViewport(FXObject*, FXSelector, void*) {
948 0 : if (!myGLWindows.empty()) {
949 0 : myGLWindows[0]->getView()->showViewportEditor();
950 : }
951 0 : return 1;
952 : }
953 :
954 :
955 : long
956 0 : GUIApplicationWindow::onCmdEditViewScheme(FXObject*, FXSelector, void*) {
957 0 : if (!myGLWindows.empty()) {
958 0 : myGLWindows[0]->getView()->showViewschemeEditor();
959 : }
960 0 : return 1;
961 : }
962 :
963 :
964 : long
965 0 : GUIApplicationWindow::onCmdHelp(FXObject*, FXSelector, void*) {
966 0 : MFXLinkLabel::fxexecute("https://sumo.dlr.de/docs/sumo-gui.html");
967 0 : return 1;
968 : }
969 :
970 :
971 : long
972 0 : GUIApplicationWindow::onCmdChangelog(FXObject*, FXSelector, void*) {
973 : // update in every version
974 0 : MFXLinkLabel::fxexecute("https://sumo.dlr.de/docs/ChangeLog.html");
975 0 : return 1;
976 : }
977 :
978 :
979 : long
980 0 : GUIApplicationWindow::onCmdHotkeys(FXObject*, FXSelector, void*) {
981 0 : MFXLinkLabel::fxexecute("https://sumo.dlr.de/docs/sumo-gui.html#keyboard_shortcuts");
982 0 : return 1;
983 : }
984 :
985 :
986 : long
987 0 : GUIApplicationWindow::onCmdTutorial(FXObject*, FXSelector, void*) {
988 0 : MFXLinkLabel::fxexecute("https://sumo.dlr.de/docs/Tutorials/index.html");
989 0 : return 1;
990 : }
991 :
992 :
993 : long
994 0 : GUIApplicationWindow::onCmdOpenInNetedit(FXObject* sender, FXSelector, void* ptr) {
995 0 : if (myGLWindows.empty()) {
996 : return 1;
997 : }
998 : bool onlyNet;
999 0 : if (sender == myOpenNetInNetedit) {
1000 : onlyNet = true;
1001 0 : } else if (sender == myOpenInNetedit) {
1002 : onlyNet = false;
1003 : } else {
1004 : // we have to check (menu-item) sender first because ptr is only valid when
1005 : // triggered via hotkey
1006 : FXEvent* e = (FXEvent*) ptr;
1007 0 : onlyNet = (e->state & SHIFTMASK) != 0;
1008 : }
1009 0 : FXRegistry reg("SUMO netedit", "netedit");
1010 0 : reg.read();
1011 0 : const GUISUMOAbstractView* const v = myGLWindows[0]->getView();
1012 0 : reg.writeRealEntry("viewport", "x", v->getChanger().getXPos());
1013 0 : reg.writeRealEntry("viewport", "y", v->getChanger().getYPos());
1014 0 : reg.writeRealEntry("viewport", "z", v->getChanger().getZPos());
1015 0 : reg.write();
1016 0 : std::string netedit = "netedit";
1017 0 : const char* sumoPath = getenv("SUMO_HOME");
1018 0 : if (sumoPath != nullptr) {
1019 0 : std::string newPath = std::string(sumoPath) + "/bin/netedit";
1020 0 : if (FileHelpers::isReadable(newPath) || FileHelpers::isReadable(newPath + ".exe")) {
1021 0 : netedit = "\"" + newPath + "\"";
1022 : }
1023 : }
1024 : // declare command for calling netedit using the viewport saved in registry
1025 0 : std::string cmd = netedit + " --registry-viewport";
1026 : // continue depending if we're loading only a network or the entire sumo config
1027 0 : if (myLoadAdditionalsInNetedit->shown() && !onlyNet) {
1028 0 : cmd += " --sumocfg-file \"" + OptionsCont::getOptions().getString("configuration-file") + "\"";
1029 : // check if ignore additional or demand elements
1030 0 : if (myLoadAdditionalsInNetedit->getCheck() == FALSE) {
1031 : cmd += " --ignore.additionalelements";
1032 : }
1033 0 : if (myLoadDemandInNetedit->getCheck() == FALSE) {
1034 : cmd += " --ignore.routeelements";
1035 : }
1036 : } else {
1037 0 : cmd += " -s \"" + OptionsCont::getOptions().getString("net-file") + "\"";
1038 : }
1039 : // start in background
1040 : #ifndef WIN32
1041 0 : cmd = cmd + " &";
1042 : #else
1043 : // see "help start" for the parameters
1044 : cmd = "start /B \"\" " + cmd;
1045 : #endif
1046 0 : WRITE_MESSAGEF(TL("Running %."), cmd);
1047 : // yay! fun with dangerous commands... Never use this over the internet
1048 0 : SysUtils::runHiddenCommand(cmd);
1049 : return 1;
1050 0 : }
1051 :
1052 :
1053 : long
1054 0 : GUIApplicationWindow::onCmdNewWindow(FXObject*, FXSelector, void*) {
1055 0 : FXRegistry reg("SUMO sumo-gui", "sumo-gui");
1056 0 : std::string sumo_gui = "sumo-gui";
1057 0 : const char* sumoPath = getenv("SUMO_HOME");
1058 0 : if (sumoPath != nullptr) {
1059 0 : std::string newPath = std::string(sumoPath) + "/bin/sumo_gui";
1060 0 : if (FileHelpers::isReadable(newPath) || FileHelpers::isReadable(newPath + ".exe")) {
1061 0 : sumo_gui = "\"" + newPath + "\"";
1062 : }
1063 : }
1064 : std::string cmd = sumo_gui;
1065 : // start in background
1066 : #ifndef WIN32
1067 0 : cmd = cmd + " &";
1068 : #else
1069 : // see "help start" for the parameters
1070 : cmd = "start /B \"\" " + cmd;
1071 : #endif
1072 0 : WRITE_MESSAGEF(TL("Running %."), cmd);
1073 : // yay! fun with dangerous commands... Never use this over the internet
1074 0 : SysUtils::runHiddenCommand(cmd);
1075 0 : return 1;
1076 0 : }
1077 :
1078 :
1079 : long
1080 0 : GUIApplicationWindow::onCmdOpenConfiguration(FXObject*, FXSelector, void*) {
1081 : // get the new file name
1082 0 : FXFileDialog opendialog(this, TL("Open Simulation Configuration"));
1083 0 : opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN_SUMOCONFIG));
1084 0 : opendialog.setSelectMode(SELECTFILE_EXISTING);
1085 0 : opendialog.setPatternList(SUMOXMLDefinitions::SumoConfigFileExtensions.getMultilineString().c_str());
1086 0 : if (gCurrentFolder.length() != 0) {
1087 0 : opendialog.setDirectory(gCurrentFolder);
1088 : }
1089 0 : if (opendialog.execute()) {
1090 0 : gCurrentFolder = opendialog.getDirectory();
1091 0 : std::string file = opendialog.getFilename().text();
1092 0 : loadConfigOrNet(file);
1093 0 : myRecentConfigs.appendFile(file.c_str());
1094 : }
1095 0 : return 1;
1096 0 : }
1097 :
1098 :
1099 : long
1100 0 : GUIApplicationWindow::onCmdOpenNetwork(FXObject*, FXSelector, void*) {
1101 : // get the new file name
1102 0 : FXFileDialog opendialog(this, TL("Open Network"));
1103 0 : opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN_NET));
1104 0 : opendialog.setSelectMode(SELECTFILE_EXISTING);
1105 0 : opendialog.setPatternList(SUMOXMLDefinitions::NetFileExtensions.getMultilineString().c_str());
1106 0 : if (gCurrentFolder.length() != 0) {
1107 0 : opendialog.setDirectory(gCurrentFolder);
1108 : }
1109 0 : if (opendialog.execute()) {
1110 0 : gCurrentFolder = opendialog.getDirectory();
1111 0 : std::string file = opendialog.getFilename().text();
1112 0 : loadConfigOrNet(file);
1113 0 : myRecentNetworks.appendFile(file.c_str());
1114 : }
1115 0 : return 1;
1116 0 : }
1117 :
1118 :
1119 : long
1120 0 : GUIApplicationWindow::onCmdOpenShapes(FXObject*, FXSelector, void*) {
1121 : // get the shape file name
1122 0 : FXFileDialog opendialog(this, TL("Open Shapes"));
1123 0 : opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN_SHAPES));
1124 0 : opendialog.setSelectMode(SELECTFILE_EXISTING);
1125 0 : opendialog.setPatternList(SUMOXMLDefinitions::ShapesFileExtensions.getMultilineString().c_str());
1126 0 : if (gCurrentFolder.length() != 0) {
1127 0 : opendialog.setDirectory(gCurrentFolder);
1128 : }
1129 0 : if (opendialog.execute()) {
1130 0 : gCurrentFolder = opendialog.getDirectory();
1131 0 : std::string file = opendialog.getFilename().text();
1132 :
1133 0 : dynamic_cast<GUIShapeContainer&>(myRunThread->getNet().getShapeContainer()).allowReplacement();
1134 0 : NLShapeHandler handler(file, myRunThread->getNet().getShapeContainer());
1135 0 : if (!XMLSubSys::runParser(handler, file, false)) {
1136 0 : WRITE_MESSAGEF(TL("Loading of % failed."), file);
1137 : }
1138 0 : update();
1139 0 : if (myMDIClient->numChildren() > 0) {
1140 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1141 0 : if (w != nullptr) {
1142 0 : w->getView()->update();
1143 : }
1144 : }
1145 : }
1146 0 : return 1;
1147 0 : }
1148 :
1149 :
1150 : long
1151 0 : GUIApplicationWindow::onCmdOpenEdgeData(FXObject*, FXSelector, void*) {
1152 : // get the shape file name
1153 0 : FXFileDialog opendialog(this, TL("Open EdgeData"));
1154 0 : opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN_NET));
1155 0 : opendialog.setSelectMode(SELECTFILE_EXISTING);
1156 0 : opendialog.setPatternList(SUMOXMLDefinitions::EdgeDataFileExtensions.getMultilineString().c_str());
1157 0 : if (gCurrentFolder.length() != 0) {
1158 0 : opendialog.setDirectory(gCurrentFolder);
1159 : }
1160 0 : if (opendialog.execute()) {
1161 0 : gCurrentFolder = opendialog.getDirectory();
1162 0 : std::string file = opendialog.getFilename().text();
1163 0 : if (!GUINet::getGUIInstance()->loadEdgeData(file)) {
1164 0 : WRITE_MESSAGEF(TL("Loading of % failed."), file);
1165 : }
1166 0 : update();
1167 0 : if (myMDIClient->numChildren() > 0) {
1168 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1169 0 : if (w != nullptr) {
1170 0 : w->getView()->update();
1171 : }
1172 : }
1173 : }
1174 0 : return 1;
1175 0 : }
1176 :
1177 :
1178 : long
1179 0 : GUIApplicationWindow::onCmdReload(FXObject* sender, FXSelector sel, void*) {
1180 0 : if (!myAmLoading && (sender == nullptr || TraCIServer::getInstance() == nullptr)) {
1181 0 : storeWindowSizeAndPos();
1182 0 : getApp()->beginWaitCursor();
1183 0 : myAmLoading = true;
1184 0 : myIsReload = sender != nullptr || sel == 1;
1185 0 : closeAllWindows();
1186 0 : myLoadThread->start();
1187 0 : if (sender == nullptr) {
1188 0 : setStatusBarText(sel == 1 ? TL("Auto-Reloading.") : TL("TraCI-Loading."));
1189 : } else {
1190 0 : setStatusBarText(TL("Reloading."));
1191 : }
1192 0 : update();
1193 : }
1194 0 : return 1;
1195 : }
1196 :
1197 :
1198 : long
1199 0 : GUIApplicationWindow::onCmdQuickReload(FXObject*, FXSelector, void*) {
1200 0 : if (!myAmLoading) {
1201 0 : setStatusBarText(TL("Quick-Reloading."));
1202 0 : MSNet::getInstance()->quickReload();
1203 : }
1204 0 : return 1;
1205 : }
1206 :
1207 :
1208 : long
1209 0 : GUIApplicationWindow::onCmdOpenRecent(FXObject* /* sender */, FXSelector, void* ptr) {
1210 0 : if (myAmLoading) {
1211 0 : myStatusbar->getStatusLine()->setText(TL("Already loading!"));
1212 0 : return 1;
1213 : }
1214 0 : std::string file((const char*)ptr);
1215 0 : loadConfigOrNet(file);
1216 : return 1;
1217 : }
1218 :
1219 :
1220 : long
1221 0 : GUIApplicationWindow::onCmdSaveConfig(FXObject*, FXSelector, void*) {
1222 : // get the new file name
1223 0 : FXFileDialog opendialog(this, TL("Save SUMO Configuration"));
1224 0 : opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::SAVE));
1225 0 : opendialog.setSelectMode(SELECTFILE_ANY);
1226 0 : opendialog.setPatternList(SUMOXMLDefinitions::SumoConfigFileExtensions.getMultilineString().c_str());
1227 0 : if (gCurrentFolder.length() != 0) {
1228 0 : opendialog.setDirectory(gCurrentFolder);
1229 : }
1230 0 : if (!opendialog.execute() || !MFXUtils::userPermitsOverwritingWhenFileExists(this, opendialog.getFilename())) {
1231 : return 1;
1232 : }
1233 0 : const std::string file = MFXUtils::assureExtension(opendialog).text();
1234 0 : std::ofstream out(XMLSubSys::transcodeToLocal(file));
1235 0 : if (out.good()) {
1236 0 : OptionsCont::getOptions().writeConfiguration(out, true, false, false, file, true);
1237 0 : setStatusBarText(TLF("Configuration saved to %.", file));
1238 : } else {
1239 0 : setStatusBarText(TLF("Could not save configuration to %.", file));
1240 : }
1241 0 : out.close();
1242 : return 1;
1243 0 : }
1244 :
1245 :
1246 : long
1247 0 : GUIApplicationWindow::onCmdClose(FXObject*, FXSelector, void*) {
1248 0 : closeAllWindows();
1249 0 : return 1;
1250 : }
1251 :
1252 :
1253 : long
1254 1951283 : GUIApplicationWindow::onUpdOpen(FXObject* sender, FXSelector, void* ptr) {
1255 1951283 : sender->handle(this,
1256 1951283 : myAmLoading ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1257 : ptr);
1258 1951283 : return 1;
1259 : }
1260 :
1261 :
1262 : long
1263 1461968 : GUIApplicationWindow::onUpdReload(FXObject* sender, FXSelector, void* ptr) {
1264 1461968 : sender->handle(this,
1265 1461968 : myAmLoading || myLoadThread->getFileName() == "" || TraCIServer::getInstance() != nullptr
1266 : ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1267 : ptr);
1268 1461968 : return 1;
1269 : }
1270 :
1271 :
1272 : long
1273 0 : GUIApplicationWindow::onUpdOpenRecent(FXObject* sender, FXSelector, void* ptr) {
1274 0 : sender->handle(this,
1275 0 : myAmLoading ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1276 : ptr);
1277 0 : return 1;
1278 : }
1279 :
1280 :
1281 : long
1282 1948186 : GUIApplicationWindow::onUpdAddView(FXObject* sender, FXSelector, void* ptr) {
1283 1948186 : sender->handle(this,
1284 1948186 : myAmLoading || !myRunThread->networkAvailable()
1285 : ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1286 : ptr);
1287 1948186 : return 1;
1288 : }
1289 :
1290 :
1291 : long
1292 8503 : GUIApplicationWindow::onCmdStart(FXObject*, FXSelector, void*) {
1293 : // check whether a net was loaded successfully
1294 8503 : if (!myRunThread->networkAvailable()) {
1295 0 : myStatusbar->getStatusLine()->setText(TL("No simulation loaded!"));
1296 0 : return 1;
1297 : }
1298 : // check whether it was started before and paused;
1299 8503 : if (!myWasStarted) {
1300 8503 : myRunThread->begin();
1301 8503 : myWasStarted = true;
1302 : }
1303 8503 : myRunThread->resume();
1304 8503 : getApp()->forceRefresh(); // only calling myToolBar2->forceRefresh somehow looses keyboard focus
1305 8503 : return 1;
1306 : }
1307 :
1308 :
1309 : long
1310 7967 : GUIApplicationWindow::onCmdStop(FXObject*, FXSelector, void*) {
1311 7967 : myRunThread->stop();
1312 7967 : getApp()->forceRefresh(); // only calling myToolBar2->forceRefresh somehow looses keyboard focus
1313 7967 : return 1;
1314 : }
1315 :
1316 :
1317 : long
1318 0 : GUIApplicationWindow::onCmdStep(FXObject*, FXSelector, void*) {
1319 : // check whether a net was loaded successfully
1320 0 : if (!myRunThread->networkAvailable()) {
1321 0 : myStatusbar->getStatusLine()->setText(TL("No simulation loaded!"));
1322 0 : return 1;
1323 : }
1324 : // check whether it was started before and paused;
1325 0 : if (!myWasStarted) {
1326 0 : myRunThread->begin();
1327 0 : myWasStarted = true;
1328 : }
1329 0 : myRunThread->singleStep();
1330 0 : return 1;
1331 : }
1332 :
1333 :
1334 : long
1335 0 : GUIApplicationWindow::onCmdSaveState(FXObject*, FXSelector, void*) {
1336 : // get the new file name
1337 0 : FXFileDialog opendialog(this, TL("Save Simulation State"));
1338 0 : opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::SAVE));
1339 0 : opendialog.setSelectMode(SELECTFILE_ANY);
1340 0 : opendialog.setPatternList(SUMOXMLDefinitions::StateFileExtensions.getMultilineString().c_str());
1341 0 : if (gCurrentFolder.length() != 0) {
1342 0 : opendialog.setDirectory(gCurrentFolder);
1343 : }
1344 0 : if (!opendialog.execute() || !MFXUtils::userPermitsOverwritingWhenFileExists(this, opendialog.getFilename())) {
1345 : return 1;
1346 : }
1347 0 : const std::string file = MFXUtils::assureExtension(opendialog).text();
1348 0 : MSStateHandler::saveState(file, MSNet::getInstance()->getCurrentTimeStep(), false);
1349 0 : setStatusBarText(TLF("Simulation state saved to '%'.", file));
1350 : return 1;
1351 0 : }
1352 :
1353 :
1354 : long
1355 0 : GUIApplicationWindow::onCmdLoadState(FXObject*, FXSelector, void*) {
1356 : // get the new file name
1357 0 : FXFileDialog opendialog(this, TL("Load Simulation State"));
1358 0 : opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN));
1359 0 : opendialog.setSelectMode(SELECTFILE_ANY);
1360 0 : opendialog.setPatternList(SUMOXMLDefinitions::StateFileExtensions.getMultilineString().c_str());
1361 0 : if (gCurrentFolder.length() != 0) {
1362 0 : opendialog.setDirectory(gCurrentFolder);
1363 : }
1364 0 : if (opendialog.execute() && FXStat::exists(opendialog.getFilename())) {
1365 0 : gCurrentFolder = opendialog.getDirectory();
1366 0 : const std::string file = opendialog.getFilename().text();
1367 : try {
1368 0 : MSNet::getInstance()->loadState(file, true);
1369 0 : setStatusBarText(TLF("State loaded from '%'.", file));
1370 0 : } catch (ProcessError& e) {
1371 0 : setStatusBarText(TLF("Failed to load state from '%' (%).", file, e.what()));
1372 0 : }
1373 : }
1374 0 : return 1;
1375 0 : }
1376 :
1377 :
1378 : long
1379 0 : GUIApplicationWindow::onCmdTimeToggle(FXObject*, FXSelector, void*) {
1380 : // toggle show time as HMS
1381 0 : myShowTimeAsHMS = !myShowTimeAsHMS;
1382 0 : updateTimeLCDTooltip();
1383 0 : if (myRunThread->networkAvailable()) {
1384 0 : updateTimeLCD(myRunThread->getNet().getCurrentTimeStep());
1385 : }
1386 0 : return 1;
1387 : }
1388 :
1389 :
1390 : long
1391 0 : GUIApplicationWindow::onCmdDelayInc(FXObject*, FXSelector, void*) {
1392 0 : if (mySimDelay < 10) {
1393 0 : mySimDelay = 10;
1394 0 : } else if (mySimDelay >= 20 && mySimDelay < 50) {
1395 0 : mySimDelay = 50;
1396 0 : } else if (mySimDelay >= 200 && mySimDelay < 500) {
1397 0 : mySimDelay = 500;
1398 : } else {
1399 0 : mySimDelay *= 2;
1400 : }
1401 0 : if (mySimDelay > 1000) {
1402 : // setting high delay by pressing the key too often is hard to recover from
1403 0 : mySimDelay = 1000;
1404 : }
1405 0 : mySimDelaySlider->setValue((int)mySimDelay);
1406 0 : mySimDelaySpinner->setValue(mySimDelay);
1407 0 : return 1;
1408 : }
1409 :
1410 :
1411 : long
1412 0 : GUIApplicationWindow::onCmdDelayDec(FXObject*, FXSelector, void*) {
1413 0 : if (mySimDelay <= 10) {
1414 0 : mySimDelay = 0;
1415 0 : } else if (mySimDelay > 20 && mySimDelay <= 50) {
1416 0 : mySimDelay = 20;
1417 0 : } else if (mySimDelay > 200 && mySimDelay <= 500) {
1418 0 : mySimDelay = 200;
1419 : } else {
1420 0 : mySimDelay /= 2;
1421 : }
1422 0 : mySimDelaySlider->setValue((int)mySimDelay);
1423 0 : mySimDelaySpinner->setValue(mySimDelay);
1424 0 : return 1;
1425 : }
1426 :
1427 :
1428 : long
1429 0 : GUIApplicationWindow::onCmdDelayToggle(FXObject*, FXSelector, void*) {
1430 0 : const double tmp = myAlternateSimDelay;
1431 0 : myAlternateSimDelay = mySimDelay;
1432 0 : mySimDelay = tmp;
1433 0 : return 1;
1434 : }
1435 :
1436 :
1437 : long
1438 0 : GUIApplicationWindow::onCmdDemandScale(FXObject*, FXSelector, void*) {
1439 0 : if (myRunThread->networkAvailable()) {
1440 0 : myRunThread->getNet().getVehicleControl().setScale(myDemandScaleSpinner->getValue());
1441 : }
1442 0 : return 1;
1443 : }
1444 :
1445 :
1446 : long
1447 0 : GUIApplicationWindow::onCmdClearMsgWindow(FXObject*, FXSelector, void*) {
1448 0 : myMessageWindow->clear();
1449 0 : return 1;
1450 : }
1451 :
1452 :
1453 : long
1454 0 : GUIApplicationWindow::onCmdBreakpoint(FXObject*, FXSelector, void*) {
1455 : // see updateTimeLCD for the DELTA_T
1456 0 : if (myRunThread->networkAvailable()) {
1457 0 : addBreakpoint(SIMSTEP - DELTA_T);
1458 : }
1459 0 : return 1;
1460 : }
1461 :
1462 :
1463 : long
1464 0 : GUIApplicationWindow::onCmdBreakpointEarly(FXObject*, FXSelector, void*) {
1465 : // see updateTimeLCD for the DELTA_T
1466 0 : if (myRunThread->networkAvailable()) {
1467 0 : addBreakpoint(SIMSTEP - DELTA_T + GUIMessageWindow::getBreakPointOffset());
1468 : }
1469 0 : return 1;
1470 : }
1471 :
1472 :
1473 : long
1474 13302469 : GUIApplicationWindow::onUpdStart(FXObject* sender, FXSelector, void* ptr) {
1475 26604938 : sender->handle(this,
1476 14224328 : !myRunThread->simulationIsStartable() || myAmLoading
1477 : ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1478 : ptr);
1479 13302469 : if (myRunThread->simulationIsStartable() && !myAmLoading) {
1480 : // bind start simulation with space key
1481 921864 : GUIShortcutsSubSys::changeAccelerator(getAccelTable(), this, KEY_SPACE, MID_HOTKEY_CTRL_A_STARTSIMULATION_OPENADDITIONALELEMENTS);
1482 : }
1483 13302469 : return 1;
1484 : }
1485 :
1486 :
1487 : long
1488 13302453 : GUIApplicationWindow::onUpdStop(FXObject* sender, FXSelector, void* ptr) {
1489 26604906 : sender->handle(this,
1490 25618224 : !myRunThread->simulationIsStopable() || myAmLoading
1491 : ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1492 : ptr);
1493 13302453 : if (myRunThread->simulationIsStopable() && !myAmLoading) {
1494 : // bind stop simulation with space key
1495 12315769 : GUIShortcutsSubSys::changeAccelerator(getAccelTable(), this, KEY_SPACE, MID_HOTKEY_CTRL_S_STOPSIMULATION_SAVENETWORK);
1496 : }
1497 13302453 : return 1;
1498 : }
1499 :
1500 :
1501 : long
1502 13302443 : GUIApplicationWindow::onUpdStep(FXObject* sender, FXSelector, void* ptr) {
1503 26604886 : sender->handle(this,
1504 14224328 : !myRunThread->simulationIsStepable() || myAmLoading
1505 : ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
1506 : ptr);
1507 13302443 : return 1;
1508 : }
1509 :
1510 :
1511 : long
1512 28185100 : GUIApplicationWindow::onUpdNeedsNetwork(FXObject* sender, FXSelector, void* ptr) {
1513 : // check if there is a loaded network and gui isn't loading
1514 28185100 : if (myRunThread->networkAvailable() && !myAmLoading) {
1515 27856473 : sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
1516 : // enable certain elements manually
1517 27856473 : mySelectLanesMenuCascade->enable();
1518 55712946 : myScaleTrafficTooltip->setTipText(TL("Scale number of vehicles in simulation"));
1519 : } else {
1520 328627 : sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
1521 : // disable certain elements manually
1522 328627 : mySelectLanesMenuCascade->disable();
1523 657254 : myScaleTrafficTooltip->setTipText("");
1524 : }
1525 28185100 : return 1;
1526 : }
1527 :
1528 :
1529 : long
1530 971358 : GUIApplicationWindow::onUpdNeedsSumoConfig(FXObject* sender, FXSelector, void* ptr) {
1531 : // check if there is a loaded network and gui isn't loading
1532 1931809 : if (myRunThread->networkAvailable() && !myAmLoading && OptionsCont::getOptions().isSet("configuration-file")) {
1533 7081 : sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
1534 7081 : sender->handle(this, FXSEL(SEL_COMMAND, ID_SHOW), ptr);
1535 7081 : myOpenInNetedit->setText(TL("Open sumo config in netedit"));
1536 : } else {
1537 964276 : sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
1538 964276 : sender->handle(this, FXSEL(SEL_COMMAND, ID_HIDE), ptr);
1539 964276 : myOpenInNetedit->setText(TL("Open network in netedit"));
1540 : }
1541 971357 : return 1;
1542 : }
1543 :
1544 :
1545 : long
1546 487702 : GUIApplicationWindow::onUpdTraCIStatus(FXObject* /*sender*/, FXSelector, void* /*ptr*/) {
1547 487702 : if (TraCIServer::getInstance()) {
1548 1063 : myTraCiFrame->show();
1549 : } else {
1550 486639 : myTraCiFrame->hide();
1551 : }
1552 487702 : return 1;
1553 : }
1554 :
1555 :
1556 : long
1557 0 : GUIApplicationWindow::onCmdLocate(FXObject*, FXSelector sel, void*) {
1558 0 : if (myMDIClient->numChildren() > 0) {
1559 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1560 0 : if (w != nullptr) {
1561 0 : w->onCmdLocate(nullptr, sel, nullptr);
1562 : }
1563 : }
1564 0 : return 1;
1565 : }
1566 :
1567 :
1568 : long
1569 0 : GUIApplicationWindow::onCmdShowStats(FXObject*, FXSelector, void*) {
1570 0 : if (myMDIClient->numChildren() > 0) {
1571 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1572 0 : GUINet::getGUIInstance()->getParameterWindow(*this, *w->getView());
1573 : }
1574 0 : return 1;
1575 : }
1576 :
1577 :
1578 : long
1579 0 : GUIApplicationWindow::onCmdAppSettings(FXObject*, FXSelector, void*) {
1580 0 : GUIDialog_AppSettings* d = new GUIDialog_AppSettings(this);
1581 0 : d->create();
1582 0 : d->show(PLACEMENT_OWNER);
1583 0 : return 1;
1584 : }
1585 :
1586 :
1587 : long
1588 0 : GUIApplicationWindow::onCmdGaming(FXObject*, FXSelector, void*) {
1589 0 : if (myGLWindows.empty()) {
1590 : return 1;
1591 : }
1592 0 : myAmGaming = !myAmGaming;
1593 0 : myGLWindows[0]->getView()->editVisualisationSettings()->gaming = myAmGaming;
1594 0 : if (myAmGaming) {
1595 0 : myGamingModeCheckbox->setCheck(TRUE);
1596 0 : myMenuBar->hide();
1597 0 : myStatusbar->hide();
1598 0 : myToolBar1->hide();
1599 0 : myToolBar2->hide();
1600 0 : myToolBar4->hide();
1601 0 : myToolBar5->hide();
1602 0 : myToolBar6->show();
1603 0 : myToolBar8->hide();
1604 0 : myToolBar10->show();
1605 0 : if (myTLSGame) {
1606 0 : myToolBar7->show();
1607 : } else {
1608 0 : myToolBar9->show();
1609 : }
1610 0 : myMessageWindow->hide();
1611 0 : myLCDLabel->setFgColor(MFXUtils::getFXColor(RGBColor::RED));
1612 0 : myWaitingTimeLabel->setFgColor(MFXUtils::getFXColor(RGBColor::RED));
1613 0 : myTimeLossLabel->setFgColor(MFXUtils::getFXColor(RGBColor::RED));
1614 0 : myEmergencyVehicleLabel->setFgColor(MFXUtils::getFXColor(RGBColor::RED));
1615 0 : myTotalDistanceLabel->setFgColor(MFXUtils::getFXColor(RGBColor::RED));
1616 : } else {
1617 0 : myGamingModeCheckbox->setCheck(FALSE);
1618 0 : myMenuBar->show();
1619 0 : myStatusbar->show();
1620 0 : myToolBar1->show();
1621 0 : myToolBar2->show();
1622 0 : myToolBar4->show();
1623 0 : myToolBar5->show();
1624 0 : myToolBar6->hide();
1625 0 : myToolBar7->hide();
1626 0 : myToolBar8->show();
1627 0 : myToolBar9->hide();
1628 0 : myToolBar10->hide();
1629 0 : myMessageWindow->show();
1630 0 : myLCDLabel->setFgColor(MFXUtils::getFXColor(RGBColor::GREEN));
1631 : }
1632 0 : if (myMDIClient->numChildren() > 0) {
1633 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1634 0 : if (w != nullptr) {
1635 0 : w->setToolBarVisibility(!myAmGaming && !myAmFullScreen);
1636 : }
1637 : }
1638 0 : update();
1639 0 : return 1;
1640 : }
1641 :
1642 :
1643 : long
1644 0 : GUIApplicationWindow::onCmdToggleDrawJunctionShape(FXObject*, FXSelector, void*) {
1645 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1646 0 : if (w != nullptr) {
1647 : // show or hide grid depending of myNetworkViewOptions.menuCheckToggleGrid
1648 0 : if (w->getView()->getVisualisationSettings().drawJunctionShape) {
1649 0 : w->getView()->editVisualisationSettings()->drawJunctionShape = false;
1650 : } else {
1651 0 : w->getView()->editVisualisationSettings()->drawJunctionShape = true;
1652 : }
1653 0 : w->getView()->update();
1654 : }
1655 0 : return 1;
1656 : }
1657 :
1658 :
1659 : long
1660 0 : GUIApplicationWindow::onCmdToggleSecondaryShape(FXObject*, FXSelector, void*) {
1661 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1662 0 : if (w != nullptr) {
1663 : // toggle secondary shape visualization
1664 0 : w->getView()->editVisualisationSettings()->secondaryShape = !w->getView()->getVisualisationSettings().secondaryShape;
1665 0 : w->getView()->update();
1666 : }
1667 0 : return 1;
1668 : }
1669 :
1670 :
1671 : long
1672 0 : GUIApplicationWindow::onCmdFullScreen(FXObject*, FXSelector, void*) {
1673 0 : if (myGLWindows.empty()) {
1674 : return 1;
1675 : }
1676 0 : myAmFullScreen = !myAmFullScreen;
1677 0 : if (myAmFullScreen) {
1678 0 : getApp()->reg().writeIntEntry("SETTINGS", "x", getX());
1679 0 : getApp()->reg().writeIntEntry("SETTINGS", "y", getY());
1680 0 : getApp()->reg().writeIntEntry("SETTINGS", "width", getWidth());
1681 0 : getApp()->reg().writeIntEntry("SETTINGS", "height", getHeight());
1682 0 : maximize();
1683 0 : setDecorations(DECOR_NONE);
1684 0 : place(PLACEMENT_MAXIMIZED);
1685 0 : myMenuBar->hide();
1686 0 : myStatusbar->hide();
1687 0 : myToolBar1->hide();
1688 0 : myToolBar2->hide();
1689 0 : myToolBar3->hide();
1690 0 : myToolBar4->hide();
1691 0 : myToolBar5->hide();
1692 0 : myToolBar6->hide();
1693 0 : myToolBar7->hide();
1694 0 : myToolBar8->hide();
1695 0 : myMessageWindow->hide();
1696 0 : if (myMDIClient->numChildren() > 0) {
1697 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
1698 0 : if (w != nullptr) {
1699 0 : w->setToolBarVisibility(false);
1700 : }
1701 : }
1702 0 : update();
1703 : } else {
1704 0 : place(PLACEMENT_VISIBLE);
1705 0 : setDecorations(DECOR_ALL);
1706 0 : restore();
1707 0 : myToolBar3->show();
1708 0 : myAmGaming = !myAmGaming;
1709 0 : onCmdGaming(nullptr, 0, nullptr);
1710 0 : setWidth(getApp()->reg().readIntEntry("SETTINGS", "width", 600));
1711 0 : setHeight(getApp()->reg().readIntEntry("SETTINGS", "height", 400));
1712 0 : setX(getApp()->reg().readIntEntry("SETTINGS", "x", 150));
1713 0 : setY(getApp()->reg().readIntEntry("SETTINGS", "y", 150));
1714 : }
1715 : return 1;
1716 : }
1717 :
1718 :
1719 : long
1720 0 : GUIApplicationWindow::onCmdListInternal(FXObject*, FXSelector, void*) {
1721 0 : myListInternal = !myListInternal;
1722 0 : return 1;
1723 : }
1724 :
1725 :
1726 : long
1727 0 : GUIApplicationWindow::onCmdListParking(FXObject*, FXSelector, void*) {
1728 0 : myListParking = !myListParking;
1729 0 : return 1;
1730 : }
1731 :
1732 : long
1733 0 : GUIApplicationWindow::onCmdListTeleporting(FXObject*, FXSelector, void*) {
1734 0 : myListTeleporting = !myListTeleporting;
1735 0 : return 1;
1736 : }
1737 :
1738 :
1739 : long
1740 0 : GUIApplicationWindow::onCmdNewView(FXObject*, FXSelector, void*) {
1741 0 : openNewView(GUISUMOViewParent::VIEW_2D_OPENGL);
1742 0 : return 1;
1743 : }
1744 :
1745 :
1746 : #ifdef HAVE_OSG
1747 : long
1748 0 : GUIApplicationWindow::onCmdNewOSG(FXObject*, FXSelector, void*) {
1749 0 : openNewView(GUISUMOViewParent::VIEW_3D_OSG);
1750 0 : return 1;
1751 : }
1752 : #endif
1753 :
1754 :
1755 : long
1756 0 : GUIApplicationWindow::onCmdFeedback(FXObject*, FXSelector, void*) {
1757 : // create and open feedback dialog
1758 0 : GUIDialog_Feedback* feedback = new GUIDialog_Feedback(this);
1759 0 : feedback->create();
1760 0 : feedback->show(PLACEMENT_OWNER);
1761 0 : return 1;
1762 : }
1763 :
1764 :
1765 : long
1766 0 : GUIApplicationWindow::onCmdAbout(FXObject*, FXSelector, void*) {
1767 0 : GUIDialog_AboutSUMO* about = new GUIDialog_AboutSUMO(this);
1768 0 : about->create();
1769 0 : about->show(PLACEMENT_OWNER);
1770 0 : return 1;
1771 : }
1772 :
1773 :
1774 : long
1775 0 : GUIApplicationWindow::onCmdHallOfFame(FXObject*, FXSelector, void*) {
1776 0 : GUIDialog_HallOfFame* hall = new GUIDialog_HallOfFame(this);
1777 0 : hall->create();
1778 0 : hall->show(PLACEMENT_OWNER);
1779 0 : return 1;
1780 : }
1781 :
1782 :
1783 0 : long GUIApplicationWindow::onClipboardRequest(FXObject* /* sender */, FXSelector /* sel */, void* ptr) {
1784 : FXEvent* event = (FXEvent*)ptr;
1785 0 : FXString string = GUIUserIO::clipped.c_str();
1786 0 : setDNDData(FROM_CLIPBOARD, event->target, string);
1787 0 : return 1;
1788 0 : }
1789 :
1790 :
1791 : long
1792 67389 : GUIApplicationWindow::onLoadThreadEvent(FXObject*, FXSelector, void*) {
1793 67389 : eventOccurred();
1794 67389 : return 1;
1795 : }
1796 :
1797 :
1798 : long
1799 12260566 : GUIApplicationWindow::onRunThreadEvent(FXObject*, FXSelector, void*) {
1800 12260566 : eventOccurred();
1801 12260566 : return 1;
1802 : }
1803 :
1804 :
1805 : void
1806 12327955 : GUIApplicationWindow::eventOccurred() {
1807 25584373 : while (!myEvents.empty()) {
1808 : // get the next event
1809 13256418 : GUIEvent* e = myEvents.top();
1810 13256418 : myEvents.pop();
1811 : // process
1812 13256418 : switch (e->getOwnType()) {
1813 8992 : case GUIEventType::SIMULATION_LOADED:
1814 8992 : handleEvent_SimulationLoaded(e);
1815 8992 : setFocus();
1816 8992 : break;
1817 13150655 : case GUIEventType::SIMULATION_STEP:
1818 13150655 : if (myRunThread->networkAvailable()) { // avoid race-condition related crash if reload was pressed
1819 13150655 : handleEvent_SimulationStep(e);
1820 : }
1821 : break;
1822 88798 : case GUIEventType::MESSAGE_OCCURRED:
1823 : case GUIEventType::WARNING_OCCURRED:
1824 : case GUIEventType::ERROR_OCCURRED:
1825 : case GUIEventType::DEBUG_OCCURRED:
1826 : case GUIEventType::GLDEBUG_OCCURRED:
1827 : case GUIEventType::STATUS_OCCURRED:
1828 88798 : handleEvent_Message(e);
1829 88798 : break;
1830 : case GUIEventType::ADD_VIEW: {
1831 3 : GUIEvent_AddView* ave = dynamic_cast<GUIEvent_AddView*>(e);
1832 9 : auto v = openNewView(ave->in3D() ? GUISUMOViewParent::VIEW_3D_OSG : GUISUMOViewParent::VIEW_2D_OPENGL, ave->getCaption());
1833 3 : if (ave->getSchemeName() != "") {
1834 3 : MFXComboBoxIcon* sCombo = v->getColoringSchemesCombo();
1835 3 : int index = sCombo->findItem(ave->getSchemeName().c_str());
1836 3 : if (index >= 0) {
1837 3 : sCombo->setCurrentItem(index);
1838 : }
1839 3 : v->setColorScheme(ave->getSchemeName());
1840 : }
1841 : break;
1842 : }
1843 : case GUIEventType::CLOSE_VIEW: {
1844 3 : GUIEvent_CloseView* ave = dynamic_cast<GUIEvent_CloseView*>(e);
1845 3 : removeViewByID(ave->getCaption());
1846 3 : break;
1847 : }
1848 7967 : case GUIEventType::SIMULATION_ENDED:
1849 7967 : handleEvent_SimulationEnded(e);
1850 7967 : break;
1851 : default:
1852 : break;
1853 : }
1854 13256418 : delete e;
1855 : }
1856 12327955 : myToolBar2->forceRefresh();
1857 12327955 : myToolBar3->forceRefresh();
1858 12327955 : }
1859 :
1860 :
1861 : void
1862 8992 : GUIApplicationWindow::handleEvent_SimulationLoaded(GUIEvent* e) {
1863 8992 : myAmLoading = false;
1864 : GUIEvent_SimulationLoaded* ec = static_cast<GUIEvent_SimulationLoaded*>(e);
1865 : // check whether the loading was successful
1866 8992 : if (ec->myNet == nullptr) {
1867 : // report failure
1868 634 : setStatusBarText(TLF("Loading of '%' failed!", ec->myFile));
1869 317 : if (GUIGlobals::gQuitOnEnd) {
1870 317 : closeAllWindows();
1871 317 : getApp()->exit(1);
1872 : }
1873 : } else {
1874 : // initialise simulation thread
1875 8675 : if (!myRunThread->init(ec->myNet, ec->myBegin, ec->myEnd)) {
1876 172 : if (GUIGlobals::gQuitOnEnd) {
1877 172 : closeAllWindows();
1878 172 : getApp()->exit(1);
1879 : }
1880 : } else {
1881 : // report success
1882 17006 : setStatusBarText(TLF("'%' loaded.", ec->myFile));
1883 8503 : setWindowSizeAndPos();
1884 8503 : myWasStarted = false;
1885 8503 : myHaveNotifiedAboutSimEnd = false;
1886 : // initialise views
1887 8503 : myViewNumber = 0;
1888 8503 : const GUISUMOViewParent::ViewType defaultType = ec->myOsgView ? GUISUMOViewParent::VIEW_3D_OSG : GUISUMOViewParent::VIEW_2D_OPENGL;
1889 : // check/record settings file modification time
1890 8503 : long long mTime = myGuiSettingsFileMTime;
1891 8503 : if (ec->mySettingsFiles.size() > 0) {
1892 75 : for (std::string fname : ec->mySettingsFiles) {
1893 38 : mTime = MAX2(mTime, SysUtils::getModifiedTime(fname));
1894 : }
1895 : }
1896 : // always reload if settings were modified or to restore multiple views
1897 8503 : if (!myIsReload) {
1898 : gSchemeStorage.clearDecals();
1899 : }
1900 8503 : if (ec->mySettingsFiles.size() > 0 && (!myIsReload || myGuiSettingsFileMTime < mTime || ec->mySettingsFiles.size() > 1)) {
1901 : // open a view for each file and apply settings
1902 75 : for (std::string fname : ec->mySettingsFiles) {
1903 38 : GUISettingsHandler settings(getApp(), fname);
1904 : GUISUMOViewParent::ViewType vt = defaultType;
1905 38 : if (settings.getViewType() == "osg" || settings.getViewType() == "3d") {
1906 : vt = GUISUMOViewParent::VIEW_3D_OSG;
1907 : }
1908 38 : if (settings.getViewType() == "opengl" || settings.getViewType() == "2d") {
1909 : vt = GUISUMOViewParent::VIEW_2D_OPENGL;
1910 : }
1911 38 : GUISUMOAbstractView* view = openNewView(vt);
1912 38 : if (view == nullptr) {
1913 : break;
1914 : }
1915 38 : if (settings.getSettingName() != "") {
1916 38 : view->setColorScheme(settings.getSettingName());
1917 38 : MFXComboBoxIcon* sCombo = view->getColoringSchemesCombo();
1918 38 : int index = sCombo->findItem(settings.getSettingName().c_str());
1919 38 : if (index >= 0) {
1920 35 : sCombo->setCurrentItem(index);
1921 : }
1922 : }
1923 38 : view->addDecals(settings.getDecals());
1924 38 : settings.applyViewport(view);
1925 38 : settings.setSnapshots(view);
1926 38 : if (settings.getDelay() > 0.) {
1927 5 : mySimDelay = settings.getDelay();
1928 : }
1929 38 : if (settings.getBreakpoints().size() > 0) {
1930 0 : myRunThread->getBreakpointLock().lock();
1931 0 : myRunThread->getBreakpoints().assign(settings.getBreakpoints().begin(), settings.getBreakpoints().end());
1932 0 : myRunThread->getBreakpointLock().unlock();
1933 : }
1934 38 : myJamSounds = settings.getEventDistribution("jam");
1935 76 : myCollisionSounds = settings.getEventDistribution("collision");
1936 38 : if (settings.getJamSoundTime() > 0) {
1937 0 : myJamSoundTime = settings.getJamSoundTime();
1938 : }
1939 38 : for (const std::string& tlsID : settings.getTrackers()) {
1940 0 : if (MSNet::getInstance()->getTLSControl().knows(tlsID)) {
1941 0 : MSTrafficLightLogic* tll = MSNet::getInstance()->getTLSControl().get(tlsID).getActive();
1942 0 : GUITrafficLightLogicWrapper* tllW = GUINet::getGUIInstance()->getTLLWrapper(tll);
1943 0 : if (tllW) {
1944 0 : tllW->begin2TrackPhases(this);
1945 : }
1946 : } else {
1947 0 : WRITE_WARNINGF("Tracker for unknown tlLogic '%' in settings file '%'", tlsID, fname);
1948 : }
1949 38 : }
1950 38 : }
1951 : } else {
1952 16932 : openNewView(defaultType);
1953 : }
1954 8503 : myGuiSettingsFileMTime = mTime;
1955 17006 : if (!OptionsCont::getOptions().isDefault("delay")) {
1956 4 : setDelay(OptionsCont::getOptions().getFloat("delay"));
1957 4 : mySimDelaySlider->setValue((int)mySimDelay);
1958 4 : mySimDelaySpinner->setValue(mySimDelay);
1959 : }
1960 17006 : if (!OptionsCont::getOptions().isDefault("breakpoints") && !myIsReload) {
1961 : std::vector<SUMOTime> breakpoints;
1962 0 : for (const std::string& val : OptionsCont::getOptions().getStringVector("breakpoints")) {
1963 0 : SUMOTime t = string2time(val);
1964 : // round down to nearest reachable time step
1965 0 : t -= t % DELTA_T;
1966 0 : breakpoints.push_back(t);
1967 : }
1968 0 : std::sort(breakpoints.begin(), breakpoints.end());
1969 0 : myRunThread->getBreakpointLock().lock();
1970 0 : myRunThread->getBreakpoints().assign(breakpoints.begin(), breakpoints.end());
1971 0 : myRunThread->getBreakpointLock().unlock();
1972 0 : }
1973 17006 : if (!OptionsCont::getOptions().isDefault("selection-file")) {
1974 0 : delete myDynamicSelection;
1975 0 : myDynamicSelection = new std::stringstream();
1976 0 : std::string msg = gSelected.load(OptionsCont::getOptions().getString("selection-file"), GLO_MAX, myDynamicSelection);
1977 0 : if (msg != "") {
1978 0 : WRITE_ERRORF("Errors while loading selection: %", msg.c_str());
1979 : }
1980 0 : if (!myDynamicSelection->str().empty()) {
1981 : std::string dummy;
1982 : int numNotFound = 0;
1983 0 : while (myDynamicSelection->good()) {
1984 0 : (*myDynamicSelection) >> dummy;
1985 0 : numNotFound++;
1986 : }
1987 0 : myDynamicSelection->clear(); // first clear error state before seek works
1988 0 : myDynamicSelection->seekg(0);
1989 : // @note for some reason the last line is read twice
1990 0 : WRITE_MESSAGEF("% dynamic objects not present while loading selection", numNotFound - 1);
1991 : }
1992 : }
1993 8503 : myTLSGame = OptionsCont::getOptions().getString("game.mode") == "tls";
1994 17006 : if (OptionsCont::getOptions().getBool("game")) {
1995 0 : if (myTLSGame) {
1996 0 : setTitle(TL("SUMO Interactive Traffic Light"));
1997 : } else {
1998 0 : setTitle(TL("SUMO Interactive Demand-Responsive-Transport"));
1999 : }
2000 0 : onCmdGaming(nullptr, 0, nullptr);
2001 : } else {
2002 : // set simulation name on the caption
2003 8503 : setTitle(MFXUtils::getTitleText("SUMO " VERSION_STRING, ec->myFile.c_str()));
2004 : }
2005 8503 : if (ec->myViewportFromRegistry) {
2006 : Position off;
2007 0 : off.set(getApp()->reg().readRealEntry("viewport", "x"),
2008 : getApp()->reg().readRealEntry("viewport", "y"),
2009 : getApp()->reg().readRealEntry("viewport", "z"));
2010 : Position p(off.x(), off.y(), 0);
2011 0 : GUISUMOAbstractView* view = myGLWindows[0]->getView();
2012 0 : view->setViewportFromToRot(off, p, 0);
2013 : }
2014 : // set simulation step begin information
2015 8503 : myLCDLabel->setText("----------------");
2016 51018 : for (std::vector<FXButton*>::const_iterator it = myStatButtons.begin(); it != myStatButtons.end(); ++it) {
2017 42515 : (*it)->setText("-");
2018 : }
2019 : // initialize scale from options unless already set in the UI
2020 8503 : if (myDemandScaleSpinner->getValue() == 1 || !OptionsCont::getOptions().isDefault("scale")) {
2021 17006 : myDemandScaleSpinner->setValue(OptionsCont::getOptions().getFloat("scale"));
2022 : }
2023 8503 : myRunThread->getNet().getVehicleControl().setScale(myDemandScaleSpinner->getValue());
2024 : }
2025 : }
2026 8992 : getApp()->endWaitCursor();
2027 : // start if wished
2028 8992 : if (GUIGlobals::gRunAfterLoad && ec->myNet != nullptr && myRunThread->simulationIsStartable()) {
2029 8503 : onCmdStart(nullptr, 0, nullptr);
2030 : }
2031 8992 : update();
2032 8992 : }
2033 :
2034 :
2035 : void
2036 13150697 : GUIApplicationWindow::handleEvent_SimulationStep(GUIEvent*) {
2037 : #ifdef WIN32
2038 : long t = SysUtils::getCurrentMillis();
2039 : // only skip if the simulation is running
2040 : if (t - myLastStepEventMillis < MIN_DRAW_DELAY && myRunThread->simulationIsStopable()) {
2041 : // do not try to redraw with more than 50FPS (#6371)
2042 : return;
2043 : }
2044 : myLastStepEventMillis = t;
2045 : #endif
2046 13150697 : updateTimeLCD(myRunThread->getNet().getCurrentTimeStep());
2047 13150697 : FXButton* vehStats = myStatButtons[STAT_VEHS];
2048 13150697 : FXButton* delayStats = myStatButtons[STAT_DELAYED];
2049 13150697 : FXButton* teleStats = myStatButtons[STAT_TELEPORTS];
2050 13150697 : FXButton* personStats = myStatButtons[STAT_PERSONS];
2051 13150697 : FXButton* containerStats = myStatButtons[STAT_CONTAINERS];
2052 :
2053 13150697 : const int running = myRunThread->getNet().getVehicleControl().getRunningVehicleNo();
2054 13150697 : const int backlog = myRunThread->getNet().getInsertionControl().getWaitingVehicleNo();
2055 13150697 : const int teleports = myRunThread->getNet().getVehicleControl().getTeleportCount();
2056 13150697 : const int departed = myRunThread->getNet().getVehicleControl().getDepartedVehicleNo();
2057 13150697 : if (backlog > running) {
2058 1350701 : if (vehStats->getIcon() == GUIIconSubSys::getIcon(GUIIcon::GREENVEHICLE)) {
2059 1899 : vehStats->setIcon(GUIIconSubSys::getIcon(GUIIcon::YELLOWVEHICLE));
2060 : }
2061 : } else {
2062 11799996 : if (vehStats->getIcon() == GUIIconSubSys::getIcon(GUIIcon::YELLOWVEHICLE)) {
2063 1786 : vehStats->setIcon(GUIIconSubSys::getIcon(GUIIcon::GREENVEHICLE));
2064 : }
2065 : }
2066 13150697 : vehStats->setText(toString(running).c_str());
2067 13150697 : if (backlog > 0) {
2068 1933316 : if (!delayStats->shown()) {
2069 19011 : delayStats->show();
2070 : }
2071 3866632 : delayStats->setText(toString(backlog).c_str());
2072 : } else {
2073 11217381 : if (delayStats->shown()) {
2074 18818 : delayStats->hide();
2075 : }
2076 : }
2077 13150697 : if (teleports > 0) {
2078 473086 : if (!teleStats->shown()) {
2079 259 : teleStats->show();
2080 : }
2081 1419258 : teleStats->setText((toString(100.00 * teleports / departed) + "%").c_str());
2082 : }
2083 13150697 : if (myRunThread->getNet().hasPersons()) {
2084 1268043 : if (!personStats->shown()) {
2085 1560 : personStats->show();
2086 : }
2087 2536086 : personStats->setText(toString(myRunThread->getNet().getPersonControl().getRunningNumber()).c_str());
2088 : }
2089 13150697 : if (myRunThread->getNet().hasContainers()) {
2090 107857 : if (!containerStats->shown()) {
2091 170 : containerStats->show();
2092 : }
2093 215714 : containerStats->setText(toString(myRunThread->getNet().getContainerControl().getRunningNumber()).c_str());
2094 : }
2095 13150697 : if (myAmGaming) {
2096 0 : if (myTLSGame) {
2097 0 : checkGamingEvents();
2098 : } else {
2099 0 : checkGamingEventsDRT();
2100 : }
2101 : }
2102 13150697 : if (myRunThread->simulationIsStartable()) {
2103 453035 : getApp()->forceRefresh(); // restores keyboard focus
2104 : }
2105 : // try to load dynamic selection
2106 13150697 : if (myDynamicSelection != nullptr) {
2107 0 : std::stringstream tmp;
2108 0 : gSelected.load(*myDynamicSelection, GLO_MAX, &tmp);
2109 0 : if (tmp.str().empty()) {
2110 0 : delete myDynamicSelection;
2111 0 : myDynamicSelection = nullptr;
2112 : } else {
2113 0 : myDynamicSelection->str(tmp.str());
2114 0 : myDynamicSelection->clear(); // first clear error state before seek works
2115 0 : myDynamicSelection->seekg(0);
2116 : }
2117 0 : }
2118 13150697 : updateChildren();
2119 13150697 : update();
2120 13150697 : }
2121 :
2122 :
2123 : void
2124 88798 : GUIApplicationWindow::handleEvent_Message(GUIEvent* e) {
2125 : GUIEvent_Message* ec = static_cast<GUIEvent_Message*>(e);
2126 88798 : if (ec->getOwnType() == GUIEventType::STATUS_OCCURRED) {
2127 8990 : setStatusBarText(ec->getMsg());
2128 : } else {
2129 79808 : myMessageWindow->appendMsg(ec->getOwnType(), ec->getMsg());
2130 : }
2131 88798 : }
2132 :
2133 :
2134 : void
2135 7967 : GUIApplicationWindow::handleEvent_SimulationEnded(GUIEvent* e) {
2136 : GUIEvent_SimulationEnded* ec = static_cast<GUIEvent_SimulationEnded*>(e);
2137 7967 : onCmdStop(nullptr, 0, nullptr);
2138 7967 : if (ec->getReason() == MSNet::SIMSTATE_LOADING) {
2139 0 : onCmdReload(nullptr, 0, nullptr);
2140 7967 : } else if (GUIGlobals::gQuitOnEnd) {
2141 7967 : closeAllWindows();
2142 7967 : getApp()->exit(ec->getReason() == MSNet::SIMSTATE_ERROR_IN_SIM);
2143 0 : } else if (GUIGlobals::gDemoAutoReload) {
2144 0 : onCmdReload(nullptr, 1, nullptr);
2145 0 : } else if (!myHaveNotifiedAboutSimEnd) {
2146 : // GUIRunThread::deleteSim() triggers the final message to the log file
2147 : // (this will never reach the GUI but we cannot use WRITE_MESSAGE here
2148 : // to avoid a duplicate log entry)
2149 0 : myMessageWindow->appendMsg(GUIEventType::MESSAGE_OCCURRED,
2150 0 : TLF("Simulation ended at time: %. (%)",
2151 0 : time2string(ec->getTimeStep()), MSNet::getStateMessage(ec->getReason())) + "\n");
2152 : // build the text
2153 0 : const std::string text = TLF("Simulation ended at time: %.", time2string(ec->getTimeStep())) + "\n" +
2154 0 : TL("Reason:") + MSNet::getStateMessage(ec->getReason()) + "\n" +
2155 0 : TL("Do you want to close all open files and views?");
2156 0 : FXuint answer = FXMessageBox::question(this, MBOX_YES_NO, TL("Simulation ended"), "%s", text.c_str());
2157 0 : if (answer == 1) { //1:yes, 2:no, 4:esc
2158 0 : closeAllWindows();
2159 : } else {
2160 0 : GUINet::getGUIInstance()->flushOutputsAtEnd();
2161 0 : updateChildren();
2162 0 : update();
2163 : }
2164 0 : myHaveNotifiedAboutSimEnd = true;
2165 : }
2166 7967 : }
2167 :
2168 :
2169 : void
2170 0 : GUIApplicationWindow::checkGamingEvents() {
2171 0 : MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
2172 : MSVehicleControl::constVehIt it = vc.loadedVehBegin();
2173 : MSVehicleControl::constVehIt end = vc.loadedVehEnd();
2174 : #ifdef HAVE_DANGEROUS_SOUNDS // disable user-configurable command execution for public build
2175 : if (myJamSounds.getOverallProb() > 0) {
2176 : // play honking sound if some vehicle is waiting too long
2177 : for (; it != end; ++it) {
2178 : // XXX use impatience instead of waiting time ?
2179 : if (it->second->getWaitingTime() > TIME2STEPS(myJamSoundTime)) {
2180 : const std::string cmd = myJamSounds.get(&myGamingRNG);
2181 : if (cmd != "") {
2182 : // yay! fun with dangerous commands... Never use this over the internet
2183 : SysUtils::runHiddenCommand(cmd);
2184 : // one sound per simulation step is enough
2185 : break;
2186 : }
2187 : }
2188 : }
2189 : }
2190 : if (myCollisionSounds.getOverallProb() > 0) {
2191 : int collisions = MSNet::getInstance()->getVehicleControl().getCollisionCount();
2192 : if (myPreviousCollisionNumber != collisions) {
2193 : const std::string cmd = myCollisionSounds.get(&myGamingRNG);
2194 : if (cmd != "") {
2195 : // yay! fun with dangerous commands... Never use this over the internet
2196 : SysUtils::runHiddenCommand(cmd);
2197 : }
2198 : myPreviousCollisionNumber = collisions;
2199 : }
2200 : }
2201 : #endif
2202 : // update performance indicators
2203 0 : for (it = vc.loadedVehBegin(); it != end; ++it) {
2204 0 : const MSVehicle* veh = dynamic_cast<MSVehicle*>(it->second);
2205 : assert(veh != 0);
2206 0 : if (veh->isOnRoad() && !veh->isStopped()) {
2207 0 : const double vmax = veh->getLane()->getVehicleMaxSpeed(veh);
2208 0 : if (veh->getSpeed() < SUMO_const_haltingSpeed) {
2209 0 : myWaitingTime += DELTA_T;
2210 0 : if (veh->getVClass() == SVC_EMERGENCY) {
2211 0 : myEmergencyVehicleCount += DELTA_T;
2212 : }
2213 : }
2214 0 : myTimeLoss += TIME2STEPS(TS * (vmax - veh->getSpeed()) / vmax); // may be negative with speedFactor > 1
2215 : }
2216 :
2217 : }
2218 0 : myWaitingTimeLabel->setText(time2string(myWaitingTime, myShowTimeAsHMS).c_str());
2219 0 : myTimeLossLabel->setText(time2string(myTimeLoss, myShowTimeAsHMS).c_str());
2220 0 : myEmergencyVehicleLabel->setText(time2string(myEmergencyVehicleCount, myShowTimeAsHMS).c_str());
2221 0 : }
2222 :
2223 :
2224 : void
2225 0 : GUIApplicationWindow::checkGamingEventsDRT() {
2226 : // update performance indicators
2227 0 : MSTransportableControl& pc = myRunThread->getNet().getPersonControl();
2228 0 : myWaitingTime += pc.getWaitingForVehicleNumber() * DELTA_T;
2229 0 : myWaitingTimeLabel->setText(time2string(myWaitingTime).c_str());
2230 :
2231 0 : MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
2232 : MSVehicleControl::constVehIt end = vc.loadedVehEnd();
2233 0 : for (auto it = vc.loadedVehBegin(); it != end; ++it) {
2234 0 : const MSVehicle* veh = dynamic_cast<MSVehicle*>(it->second);
2235 : assert(veh != 0);
2236 0 : if (veh->isOnRoad() && !veh->isStopped()) {
2237 0 : myTotalDistance += SPEED2DIST(veh->getSpeed());
2238 : }
2239 : }
2240 0 : myTotalDistanceLabel->setText(toString(myTotalDistance / 100).c_str());
2241 0 : }
2242 :
2243 :
2244 : void
2245 8992 : GUIApplicationWindow::loadConfigOrNet(const std::string& file) {
2246 8992 : if (!myAmLoading) {
2247 8992 : storeWindowSizeAndPos();
2248 8992 : getApp()->beginWaitCursor();
2249 8992 : myAmLoading = true;
2250 8992 : myIsReload = false;
2251 8992 : closeAllWindows();
2252 8992 : gSchemeStorage.saveViewport(0, 0, -1, 0); // recenter view
2253 8992 : myLoadThread->loadConfigOrNet(file);
2254 17984 : setStatusBarText(TLF("Loading '%'.", file));
2255 8992 : update();
2256 : }
2257 8992 : }
2258 :
2259 :
2260 : GUISUMOAbstractView*
2261 8507 : GUIApplicationWindow::openNewView(GUISUMOViewParent::ViewType vt, std::string caption) {
2262 8507 : if (!myRunThread->networkAvailable()) {
2263 0 : myStatusbar->getStatusLine()->setText(TL("No simulation loaded!"));
2264 0 : return nullptr;
2265 : }
2266 : GUISUMOAbstractView* oldView = nullptr;
2267 8507 : if (myMDIClient->numChildren() > 0) {
2268 4 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
2269 4 : if (w != nullptr) {
2270 4 : oldView = w->getView();
2271 : }
2272 : }
2273 8507 : if (caption == "") {
2274 25512 : caption = "View #" + toString(myViewNumber++);
2275 : }
2276 : FXuint opts = MDI_TRACKING;
2277 17014 : GUISUMOViewParent* w = new GUISUMOViewParent(myMDIClient, myMDIMenu, FXString(caption.c_str()),
2278 8507 : this, GUIIconSubSys::getIcon(GUIIcon::SUMO_MINI), opts, 10, 10, 200, 100);
2279 8507 : GUISUMOAbstractView* v = w->init(getBuildGLCanvas(), myRunThread->getNet(), vt);
2280 8507 : if (oldView != nullptr) {
2281 : // copy viewport
2282 4 : oldView->copyViewportTo(v);
2283 : }
2284 8507 : w->create();
2285 8507 : if (myMDIClient->numChildren() == 1) {
2286 8503 : w->maximize();
2287 : } else {
2288 4 : myMDIClient->vertical(true);
2289 : }
2290 8507 : myMDIClient->setActiveChild(w);
2291 :
2292 8507 : return v;
2293 : }
2294 :
2295 :
2296 : FXGLCanvas*
2297 8507 : GUIApplicationWindow::getBuildGLCanvas() const {
2298 8507 : if (myMDIClient->numChildren() == 0) {
2299 : return nullptr;
2300 : }
2301 : GUISUMOViewParent* share_tmp1 =
2302 8507 : static_cast<GUISUMOViewParent*>(myMDIClient->childAtIndex(0));
2303 8507 : return share_tmp1->getBuildGLCanvas();
2304 : }
2305 :
2306 :
2307 : void
2308 26413 : GUIApplicationWindow::closeAllWindows() {
2309 26413 : myTrackerLock.lock();
2310 26413 : myLCDLabel->setText("----------------");
2311 158478 : for (std::vector<FXButton*>::const_iterator it = myStatButtons.begin(); it != myStatButtons.end(); ++it) {
2312 132065 : (*it)->setText("-");
2313 132065 : if (it != myStatButtons.begin()) {
2314 105652 : (*it)->hide();
2315 : }
2316 : }
2317 : // save decals and viewport
2318 34890 : for (GUIGlChildWindow* window : myGLWindows) {
2319 8477 : GUISUMOAbstractView* view = window->getView();
2320 8477 : gSchemeStorage.saveDecals(view->getDecals());
2321 8477 : gSchemeStorage.saveViewport(view->getChanger().getXPos(), view->getChanger().getYPos(),
2322 8477 : view->getChanger().getZPos(), view->getChanger().getRotation());
2323 : }
2324 : // delete the simulation
2325 26413 : myRunThread->deleteSim();
2326 : // reset the caption
2327 26413 : setTitle(MFXUtils::getTitleText("SUMO " VERSION_STRING));
2328 : // clear decals and release GPU textures
2329 34890 : for (GUIGlChildWindow* window : myGLWindows) {
2330 8477 : GUISUMOAbstractView* view = window->getView();
2331 8477 : if (view->makeCurrent()) {
2332 8477 : view->clearDecals();
2333 8477 : view->processPendingTextureDeletes();
2334 8477 : GUITextureSubSys::resetTextures();
2335 8477 : GLHelper::resetFont();
2336 8477 : view->makeNonCurrent();
2337 : }
2338 : }
2339 : // remove trackers and other external windows (must be delayed until deleteSim)
2340 34890 : while (!myGLWindows.empty()) {
2341 8477 : delete myGLWindows.front();
2342 : }
2343 : // make a copy because deleting modifyes the vector;
2344 26413 : std::vector<FXMainWindow*> trackerWindows = myTrackerWindows;
2345 26413 : for (FXMainWindow* const window : trackerWindows) {
2346 0 : delete window;
2347 : }
2348 : myTrackerWindows.clear();
2349 : // clear selected items
2350 26413 : gSelected.clear();
2351 : // add a separator to the log
2352 26413 : myMessageWindow->addSeparator();
2353 26413 : myTrackerLock.unlock();
2354 : // remove coordinate information
2355 26413 : myGeoCoordinate->setText(TL("N/A"));
2356 26413 : myCartesianCoordinate->setText(TL("N/A"));
2357 26413 : if (myTestCoordinate) {
2358 0 : myTestCoordinate->setText(TL("N/A"));
2359 : }
2360 26413 : update();
2361 26413 : }
2362 :
2363 :
2364 : FXCursor*
2365 0 : GUIApplicationWindow::getDefaultCursor() {
2366 0 : return getApp()->getDefaultCursor(DEF_ARROW_CURSOR);
2367 : }
2368 :
2369 :
2370 : SUMOTime
2371 0 : GUIApplicationWindow::getCurrentSimTime() const {
2372 0 : return myRunThread->getNet().getCurrentTimeStep();
2373 : }
2374 :
2375 :
2376 : double
2377 0 : GUIApplicationWindow::getTrackerInterval() const {
2378 0 : return GUIGlobals::gTrackerInterval;
2379 : }
2380 :
2381 :
2382 : void
2383 8992 : GUIApplicationWindow::loadOnStartup(const bool wait) {
2384 8992 : loadConfigOrNet("");
2385 8992 : if (wait) {
2386 1273 : while (myAmLoading) {
2387 737 : myRunThread->sleep(50);
2388 : }
2389 : }
2390 8992 : }
2391 :
2392 :
2393 : void
2394 35794 : GUIApplicationWindow::setStatusBarText(const std::string& text) {
2395 35794 : myStatusbar->getStatusLine()->setText(text.c_str());
2396 35794 : myStatusbar->getStatusLine()->setNormalText(text.c_str());
2397 35794 : }
2398 :
2399 :
2400 : void
2401 8643 : GUIApplicationWindow::addRecentNetwork(const FX::FXString& f) {
2402 8643 : myRecentNetworks.appendFile(f);
2403 8643 : }
2404 :
2405 :
2406 : void
2407 347 : GUIApplicationWindow::addRecentConfig(const FX::FXString& f) {
2408 347 : myRecentConfigs.appendFile(f);
2409 347 : }
2410 :
2411 :
2412 : void
2413 8992 : GUIApplicationWindow::updateTimeLCDTooltip() {
2414 8992 : if (myShowTimeAsHMS) {
2415 0 : myLCDLabel->setToolTipText("HH:MM:SS");
2416 0 : if (myAmGaming) {
2417 0 : myWaitingTimeLabel->setToolTipText("HH:MM:SS");
2418 0 : myTimeLossLabel->setToolTipText("HH:MM:SS");
2419 0 : myEmergencyVehicleLabel->setToolTipText("HH:MM:SS");
2420 : }
2421 : } else {
2422 8992 : myLCDLabel->setToolTipText(TL("seconds"));
2423 8992 : if (myAmGaming) {
2424 0 : myWaitingTimeLabel->setToolTipText(TL("seconds"));
2425 0 : myTimeLossLabel->setToolTipText(TL("seconds"));
2426 0 : myEmergencyVehicleLabel->setToolTipText(TL("seconds"));
2427 : }
2428 : }
2429 8992 : }
2430 :
2431 :
2432 : void
2433 13150697 : GUIApplicationWindow::updateTimeLCD(SUMOTime time) {
2434 13150697 : time -= DELTA_T; // synchronize displayed time with netstate output
2435 13150697 : if (time < 0) {
2436 6 : myLCDLabel->setText("----------------");
2437 6 : return;
2438 : }
2439 13150691 : if (myAmGaming) {
2440 : // show time counting backwards
2441 0 : time = myRunThread->getSimEndTime() - time;
2442 : }
2443 13150691 : std::ostringstream str;
2444 : str << std::setfill('0');
2445 13150691 : const bool hideFraction = myAmGaming || DELTA_T % 1000 == 0;
2446 13150691 : if (myShowTimeAsHMS) {
2447 0 : SUMOTime day = time / SUMOTime_DAY;
2448 0 : if (day > 0) {
2449 0 : str << day << '-';
2450 0 : time %= SUMOTime_DAY;
2451 : }
2452 : str << std::setw(2);
2453 0 : str << time / SUMOTime_HOUR << '-';
2454 0 : time %= SUMOTime_HOUR;
2455 0 : str << std::setw(2) << time / SUMOTime_MINUTE << '-';
2456 0 : time %= SUMOTime_MINUTE;
2457 : }
2458 13150691 : str << std::setw(2) << time / 1000;
2459 13150691 : if (!hideFraction) {
2460 1609924 : str << '.' << std::setw(3) << time % 1000;
2461 : }
2462 13150691 : myLCDLabel->setText(str.str().c_str());
2463 13150691 : }
2464 :
2465 :
2466 : void
2467 98 : GUIApplicationWindow::addHotkey(int key, Command* press, Command* release) {
2468 98 : if (press != nullptr) {
2469 98 : myHotkeyPress[key] = press;
2470 : }
2471 98 : if (release != nullptr) {
2472 96 : myHotkeyRelease[key] = release;
2473 : }
2474 98 : }
2475 :
2476 :
2477 : long
2478 0 : GUIApplicationWindow::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
2479 : FXEvent* e = (FXEvent*) ptr;
2480 : // PgUp and PgDown switch between widgets by default and binding them via menu shortcuts does not work reliably
2481 : // so we must intercept them before FXMainWindow can handle it
2482 0 : if (e->code == FX::KEY_Page_Up) {
2483 0 : onCmdDelayInc(nullptr, 0, nullptr);
2484 0 : } else if (e->code == FX::KEY_Page_Down) {
2485 0 : onCmdDelayDec(nullptr, 0, nullptr);
2486 : } else {
2487 : // disable hotkeys without modifiers for the game
2488 0 : const bool ignoreSimple = myAmGaming && (e->state & (CONTROLMASK | SHIFTMASK | ALTMASK)) == 0;
2489 0 : const long handled = ignoreSimple ? 0 : FXMainWindow::onKeyPress(o, sel, ptr);
2490 0 : if (handled == 0 && myMDIClient->numChildren() > 0) {
2491 : auto it = myHotkeyPress.find(e->code);
2492 0 : if (it != myHotkeyPress.end()) {
2493 0 : it->second->execute(SIMSTEP);
2494 : }
2495 0 : if (!ignoreSimple) {
2496 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
2497 0 : if (w != nullptr) {
2498 0 : w->onKeyPress(nullptr, sel, ptr);
2499 : }
2500 : }
2501 : }
2502 : }
2503 0 : return 0;
2504 : }
2505 :
2506 :
2507 : long
2508 0 : GUIApplicationWindow::onKeyRelease(FXObject* o, FXSelector sel, void* ptr) {
2509 0 : const long handled = FXMainWindow::onKeyRelease(o, sel, ptr);
2510 0 : if (handled == 0 && myMDIClient->numChildren() > 0) {
2511 : FXEvent* e = (FXEvent*) ptr;
2512 : auto it = myHotkeyRelease.find(e->code);
2513 0 : if (it != myHotkeyRelease.end()) {
2514 0 : it->second->execute(SIMSTEP);
2515 : }
2516 0 : GUISUMOViewParent* w = dynamic_cast<GUISUMOViewParent*>(myMDIClient->getActiveChild());
2517 0 : if (w != nullptr) {
2518 0 : w->onKeyRelease(nullptr, sel, ptr);
2519 : }
2520 : }
2521 0 : return 0;
2522 : }
2523 :
2524 :
2525 : double
2526 0 : GUIApplicationWindow::getDelay() const {
2527 0 : return mySimDelay;
2528 : }
2529 :
2530 :
2531 : void
2532 4 : GUIApplicationWindow::setDelay(double delay) {
2533 4 : mySimDelay = delay;
2534 4 : }
2535 :
2536 :
2537 : void
2538 6 : GUIApplicationWindow::sendBlockingEvent(GUIEvent* event) {
2539 6 : myEventMutex.lock();
2540 6 : myEvents.push_back(event);
2541 6 : myRunThreadEvent.signal();
2542 : //myEventCondition.wait(myEventMutex);
2543 6 : myEventMutex.unlock();
2544 6 : }
2545 :
2546 :
2547 : void
2548 0 : GUIApplicationWindow::setBreakpoints(const std::vector<SUMOTime>& breakpoints) {
2549 0 : if (myRunThread != nullptr) {
2550 0 : myRunThread->getBreakpointLock().lock();
2551 0 : myRunThread->getBreakpoints().assign(breakpoints.begin(), breakpoints.end());
2552 0 : myRunThread->getBreakpointLock().unlock();
2553 0 : updateChildren(MID_TIMELINK_BREAKPOINT);
2554 : }
2555 0 : }
2556 :
2557 :
2558 : void
2559 0 : GUIApplicationWindow::addBreakpoint(SUMOTime time) {
2560 0 : const SUMOTime begin = string2time(OptionsCont::getOptions().getString("begin"));
2561 0 : if (time >= begin) {
2562 : // ensure breakpoint is valid
2563 0 : time -= (time - begin) % DELTA_T;
2564 0 : std::vector<SUMOTime> breakpoints = retrieveBreakpoints();
2565 0 : if (std::find(breakpoints.begin(), breakpoints.end(), time) == breakpoints.end()) {
2566 0 : breakpoints.push_back(time);
2567 0 : std::sort(breakpoints.begin(), breakpoints.end());
2568 0 : setBreakpoints(breakpoints);
2569 0 : setStatusBarText(TLF("Set breakpoint at %", time2string(time)));
2570 : }
2571 0 : }
2572 0 : }
2573 :
2574 :
2575 : const std::vector<SUMOTime>
2576 0 : GUIApplicationWindow::retrieveBreakpoints() const {
2577 0 : myRunThread->getBreakpointLock().lock();
2578 0 : std::vector<SUMOTime> result = myRunThread->getBreakpoints();
2579 0 : myRunThread->getBreakpointLock().unlock();
2580 0 : return result;
2581 0 : }
2582 :
2583 :
2584 : void
2585 0 : GUIApplicationWindow::eraseBreakpointDialog() {
2586 0 : myBreakpointDialog = nullptr;
2587 0 : }
2588 :
2589 : /****************************************************************************/
|