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