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