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