Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file GUIApplicationWindow.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Christian Roessel
18 : /// @author Michael Behrisch
19 : /// @date Sept 2002
20 : ///
21 : // The main window of the SUMO-gui.
22 : /****************************************************************************/
23 : #pragma once
24 : #include <config.h>
25 :
26 : #include <utils/foxtools/MFXRecentNetworks.h>
27 : #include <utils/foxtools/MFXInterThreadEventClient.h>
28 : #include <utils/gui/windows/GUIMainWindow.h>
29 :
30 : #include "GUISUMOViewParent.h"
31 :
32 :
33 : // ===========================================================================
34 : // class declarations
35 : // ===========================================================================
36 :
37 : class Command;
38 : class GUILoadThread;
39 : class GUIRunThread;
40 : class GUIMessageWindow;
41 : class GUIEvent;
42 : class GUIParameterTracker;
43 : class GUIParameterTableWindow;
44 : class GUIDialog_Breakpoints;
45 : class MFXLCDLabel;
46 : class MFXLabelTooltip;
47 :
48 :
49 : // ===========================================================================
50 : // class definition
51 : // ===========================================================================
52 : /**
53 : * @class GUIApplicationWindow
54 : * @brief The main window of the SUMO-gui.
55 : *
56 : * Beside views on the simulation, shown within a MDI-window, the main window
57 : * may also have some further views (children) assigned which are stored
58 : * within a separate list.
59 : */
60 : class GUIApplicationWindow : public GUIMainWindow, public MFXInterThreadEventClient {
61 : // FOX-declarations
62 0 : FXDECLARE(GUIApplicationWindow)
63 :
64 : public:
65 : /// @brief Constructor
66 : GUIApplicationWindow(FXApp* a);
67 :
68 : /// @brief Destructor
69 : virtual ~GUIApplicationWindow();
70 :
71 : /// @name FOX-interactions
72 : /// {
73 :
74 : /// @brief Creates the main window (required by FOX)
75 : virtual void create();
76 :
77 : /// @brief Detaches the tool/menu bar
78 : virtual void detach();
79 :
80 : /// @}
81 :
82 : /// @brief config or net on startup
83 : void loadOnStartup(const bool wait = false);
84 :
85 : /// @brief get run thread
86 : GUIRunThread* getRunner();
87 :
88 : /// @brief build dependt
89 : void dependentBuild(const bool isLibsumo);
90 :
91 : /// @brief set status bar text
92 : void setStatusBarText(const std::string& text);
93 :
94 : /// @brief add recent network to recent file list
95 : void addRecentNetwork(const FX::FXString& f);
96 :
97 : /// @brief add recent config to recent file list
98 : void addRecentConfig(const FX::FXString& f);
99 :
100 : /// @brief get build GLCanvas
101 : FXGLCanvas* getBuildGLCanvas() const;
102 :
103 : /// @brief get current simulation time
104 : SUMOTime getCurrentSimTime() const;
105 :
106 : /// @brief get tracker interval
107 : double getTrackerInterval() const;
108 :
109 : /// @brief get default cursor
110 : FXCursor* getDefaultCursor();
111 :
112 : /// @name Inter-thread event handling
113 : /// @{
114 :
115 : /// @brief a certain event ocurred
116 : virtual void eventOccurred();
117 :
118 : /// @brief called when event "simulation loaded" ocurred
119 : void handleEvent_SimulationLoaded(GUIEvent* e);
120 :
121 : /// @brief called when event "simulation step" ocurred
122 : void handleEvent_SimulationStep(GUIEvent* e);
123 :
124 : /// @brief called when event "message" ocurred
125 : void handleEvent_Message(GUIEvent* e);
126 :
127 : /// @brief called when event "simulation ended" ocurred
128 : void handleEvent_SimulationEnded(GUIEvent* e);
129 :
130 : /// @}
131 :
132 : /// @name FOX-callbacks
133 : /// @{
134 :
135 : /// @brief Called on menu File->New Window
136 : long onCmdNewWindow(FXObject*, FXSelector, void*);
137 :
138 : /// @brief Called on menu File->Open Configuration
139 : long onCmdOpenConfiguration(FXObject*, FXSelector, void*);
140 :
141 : /// @brief Called on menu File->Open Network
142 : long onCmdOpenNetwork(FXObject*, FXSelector, void*);
143 :
144 : /// @brief Called on menu File->Load Shapes
145 : long onCmdOpenShapes(FXObject*, FXSelector, void*);
146 :
147 : /// @brief Called on menu File->Load EdgeData
148 : long onCmdOpenEdgeData(FXObject*, FXSelector, void*);
149 :
150 : /// @brief Called on reload
151 : long onCmdReload(FXObject*, FXSelector, void*);
152 :
153 : /// @brief Called on quick-reload
154 : long onCmdQuickReload(FXObject*, FXSelector, void*);
155 :
156 : /// @brief Called on opening a recent file
157 : long onCmdOpenRecent(FXObject*, FXSelector, void*);
158 :
159 : /// @brief Called on menu File->Close
160 : long onCmdSaveConfig(FXObject*, FXSelector, void*);
161 :
162 : /// @brief Called on menu File->Close
163 : long onCmdClose(FXObject*, FXSelector, void*);
164 :
165 : /// @brief Called by FOX if the application shall be closed (Called either by FileMenu->Quit, the normal close-menu or SIGINT)
166 : long onCmdQuit(FXObject*, FXSelector, void*);
167 :
168 : /// @brief Called on menu Edit->Edit Chosen
169 : long onCmdEditChosen(FXObject*, FXSelector, void*);
170 :
171 : /// @brief Called on menu Edit->Edit Breakpoints
172 : long onCmdEditBreakpoints(FXObject*, FXSelector, void*);
173 :
174 : /// @brief Called on menu Edit->Visualization
175 : long onCmdEditViewScheme(FXObject*, FXSelector, void*);
176 :
177 : /// @brief Called on menu Edit->Viewport
178 : long onCmdEditViewport(FXObject*, FXSelector, void*);
179 :
180 : /// @brief called if the user selects help->Documentation
181 : long onCmdHelp(FXObject* sender, FXSelector sel, void* ptr);
182 :
183 : /// @brief called if the user selects help->Changelog
184 : long onCmdChangelog(FXObject* sender, FXSelector sel, void* ptr);
185 :
186 : /// @brief called if the user selects help->Hotkeys
187 : long onCmdHotkeys(FXObject* sender, FXSelector sel, void* ptr);
188 :
189 : /// @brief called if the user selects help->Tutorial
190 : long onCmdTutorial(FXObject* sender, FXSelector sel, void* ptr);
191 :
192 : /// @brief Called on menu Edit->open in Netedit
193 : long onCmdOpenInNetedit(FXObject*, FXSelector, void*);
194 :
195 : /// @brief Opens the application settings menu (Settings->Application Settings...)
196 : long onCmdAppSettings(FXObject*, FXSelector, void*);
197 :
198 : /// @brief Toggle gaming mode
199 : long onCmdGaming(FXObject*, FXSelector, void*);
200 :
201 : /// @brief Toggle draw junction shape
202 : long onCmdToggleDrawJunctionShape(FXObject*, FXSelector, void*);
203 :
204 : /// @brief Toggle draw junction shape
205 : long onCmdToggleSecondaryShape(FXObject*, FXSelector, void*);
206 :
207 : /// @brief Toggle full screen mode
208 : long onCmdFullScreen(FXObject*, FXSelector, void*);
209 :
210 : /// @brief Toggle listing of internal structures
211 : long onCmdListInternal(FXObject*, FXSelector, void*);
212 :
213 : /// @brief Toggle listing of parking vehicles
214 : long onCmdListParking(FXObject*, FXSelector, void*);
215 :
216 : /// @brief Toggle listing of teleporting vehicles
217 : long onCmdListTeleporting(FXObject*, FXSelector, void*);
218 :
219 : /// @brief Shows the feedback dialog
220 : long onCmdFeedback(FXObject*, FXSelector, void*);
221 :
222 : /// @brief Shows the about dialog
223 : long onCmdAbout(FXObject*, FXSelector, void*);
224 :
225 : /// @brief Shows the Hall of Fame dialog
226 : long onCmdHallOfFame(FXObject*, FXSelector, void*);
227 :
228 : /// @brief Called on "play"
229 : long onCmdStart(FXObject*, FXSelector, void*);
230 :
231 : /// @brief Called on "stop"
232 : long onCmdStop(FXObject*, FXSelector, void*);
233 :
234 : /// @brief Called on "step"
235 : long onCmdStep(FXObject*, FXSelector, void*);
236 :
237 : /// @brief Called on "save state"
238 : long onCmdSaveState(FXObject*, FXSelector, void*);
239 :
240 : /// @brief Called on "save state"
241 : long onCmdLoadState(FXObject*, FXSelector, void*);
242 :
243 : /// @brief Called on "time toggle"
244 : long onCmdTimeToggle(FXObject*, FXSelector, void*);
245 :
246 : /// @brief Called on "delay inc"
247 : long onCmdDelayInc(FXObject*, FXSelector, void*);
248 :
249 : /// @brief Called on "delay dec"
250 : long onCmdDelayDec(FXObject*, FXSelector, void*);
251 :
252 : /// @brief Called on "delay toggle"
253 : long onCmdDelayToggle(FXObject*, FXSelector, void*);
254 :
255 : /// @brief Called on "demand scale"
256 : long onCmdDemandScale(FXObject*, FXSelector, void*);
257 :
258 : /// @brief Called if a new view shall be opened (2D view)
259 : long onCmdNewView(FXObject*, FXSelector, void*);
260 :
261 : #ifdef HAVE_OSG
262 : /// @brief Called if a new 3D view shall be opened
263 : long onCmdNewOSG(FXObject*, FXSelector, void*);
264 : #endif
265 :
266 : /// @brief Determines whether opening is enabled
267 : long onUpdOpen(FXObject*, FXSelector, void*);
268 :
269 : /// @brief Determines whether reloading is enabled
270 : long onUpdReload(FXObject*, FXSelector, void*);
271 :
272 : /// @brief Determines whether opening a recent file is enabled
273 : long onUpdOpenRecent(FXObject*, FXSelector, void*);
274 :
275 : /// @brief Determines whether adding a view is enabled
276 : long onUpdAddView(FXObject*, FXSelector, void*);
277 :
278 : /// @brief Determines whether "play" is enabled
279 : long onUpdStart(FXObject* sender, FXSelector, void* ptr);
280 :
281 : /// @brief Determines whether "stop" is enabled
282 : long onUpdStop(FXObject*, FXSelector, void*);
283 :
284 : /// @brief Determines whether "step" is enabled
285 : long onUpdStep(FXObject*, FXSelector, void*);
286 :
287 : /// @brief Determines whether some buttons which require an active network may be shown
288 : long onUpdNeedsNetwork(FXObject*, FXSelector, void*);
289 :
290 : /// @brief Determines whether some buttons which require an sumoConfig may be shown
291 : long onUpdNeedsSumoConfig(FXObject*, FXSelector, void*);
292 :
293 : /// @brief Determines whether traci is active
294 : long onUpdTraCIStatus(FXObject*, FXSelector, void*);
295 :
296 : /// @brief Called if the message window shall be cleared
297 : long onCmdClearMsgWindow(FXObject*, FXSelector, void*);
298 :
299 : /// @brief Called to set a breakpoint via hotkey
300 : long onCmdBreakpoint(FXObject*, FXSelector, void*);
301 :
302 : /// @brief Called to set an early breakpoint via hotkey
303 : long onCmdBreakpointEarly(FXObject*, FXSelector, void*);
304 :
305 : /// @brief Called on menu commands from the Locator menu
306 : long onCmdLocate(FXObject*, FXSelector, void*);
307 :
308 : /// @brief Called on commands from the statistic buttons
309 : long onCmdShowStats(FXObject*, FXSelector, void*);
310 :
311 : /// @brief Called on an event from the loading thread
312 : long onLoadThreadEvent(FXObject*, FXSelector, void*);
313 :
314 : /// @brief Called on an event from the simulation thread
315 : long onRunThreadEvent(FXObject*, FXSelector, void*);
316 :
317 : /// @brief Somebody wants our clipped text
318 : long onClipboardRequest(FXObject* sender, FXSelector sel, void* ptr);
319 :
320 : /// @brief called when a key is pressed
321 : long onKeyPress(FXObject* o, FXSelector sel, void* data);
322 :
323 : /// @brief called when a key is released
324 : long onKeyRelease(FXObject* o, FXSelector sel, void* data);
325 :
326 : /// @}
327 :
328 : /// @brief Returns the simulation delay in miliseconds
329 : virtual double getDelay() const;
330 :
331 : /// @brief Sets the delay of the parent application in milliseconds
332 : virtual void setDelay(double delay);
333 :
334 : /// @brief Sets the breakpoints of the parent application
335 : virtual void setBreakpoints(const std::vector<SUMOTime>& breakpoints);
336 :
337 : /// @brief Adds the given breakpoint
338 : void addBreakpoint(SUMOTime time);
339 :
340 : /// @brief Sends an event from the application thread to the GUI and waits until it is handled
341 : virtual void sendBlockingEvent(GUIEvent* event);
342 :
343 : /// @brief retrieve list of breakpoints
344 : const std::vector<SUMOTime> retrieveBreakpoints() const;
345 :
346 : /// @brief erase current breakpoint dialog
347 : void eraseBreakpointDialog();
348 :
349 : /// @brief register custom hotkey action
350 : void addHotkey(int key, Command* press, Command* release);
351 :
352 : protected:
353 : /// @brief FOX need this
354 0 : FOX_CONSTRUCTOR(GUIApplicationWindow)
355 :
356 : /// @brief add the given menuPane to windows Menu
357 : virtual void addToWindowsMenu(FXMenuPane* menuPane);
358 :
359 : /// Builds the menu bar
360 : virtual void fillMenuBar();
361 :
362 : /// Builds the tool bar
363 : virtual void buildToolBars();
364 :
365 : /// @brief build recent networks
366 : void buildRecentNetworks(FXMenuPane* fileMenu, FXMenuPane* fileMenuRecentNetworks);
367 :
368 : /// @brief build recent configs
369 : void buildRecentConfigs(FXMenuPane* fileMenu, FXMenuPane* fileMenuRecentConfigs);
370 :
371 : /// @brief the name of the simulation
372 : std::string myName;
373 :
374 : /// @brief the thread that loads simulations
375 : GUILoadThread* myLoadThread = nullptr;
376 :
377 : /// @brief the thread that runs simulations
378 : GUIRunThread* myRunThread = nullptr;
379 :
380 : /// @brief the information whether the simulation was started before
381 : bool myWasStarted = false;
382 :
383 : /// @brief The current view number
384 : int myViewNumber;
385 :
386 : /// @brief information whether the gui is currently loading and the load-options shall be greyed out
387 : bool myAmLoading = false;
388 :
389 : /// @brief whether we are reloading the simulation
390 : bool myIsReload = false;
391 :
392 : /// @brief last modification time of the gui setting file
393 : long long myGuiSettingsFileMTime = -2;
394 :
395 : /// @brief the submenus
396 : FXMenuPane* myFileMenu = nullptr,
397 : *myEditMenu = nullptr,
398 : *mySelectByPermissions = nullptr,
399 : *mySettingsMenu = nullptr,
400 : *myLocatorMenu = nullptr,
401 : *myControlMenu = nullptr,
402 : *myWindowMenu = nullptr,
403 : *myHelpMenu = nullptr;
404 :
405 : /// @brief FXMenu pane for recent networks
406 : FXMenuPane* myFileMenuRecentNetworks = nullptr;
407 :
408 : /// @brief FXMenu pane for recent configs
409 : FXMenuPane* myFileMenuRecentConfigs = nullptr;
410 :
411 : /// @brief the menu cascades
412 : FXMenuCascade* mySelectLanesMenuCascade = nullptr;
413 :
414 : /// @brief menuCheck for enable/disable load additionals in netedit
415 : FXMenuCheck* myLoadAdditionalsInNetedit = nullptr;
416 :
417 : /// @brief menuCheck for enable/disable load demand elements in netedit
418 : FXMenuCheck* myLoadDemandInNetedit = nullptr;
419 :
420 : /// @brief menuCommand for opening simulation/network in netedit
421 : FXMenuCommand* myOpenInNetedit = nullptr;
422 : /// @brief menuCommand for opening only the network in netedit
423 : FXMenuCommand* myOpenNetInNetedit = nullptr;
424 :
425 : /// @brief Buttons showing and running values and triggering statistic windows
426 : std::vector<FXButton*> myStatButtons;
427 :
428 : /// @brief A window to display messages, warnings and error in
429 : GUIMessageWindow* myMessageWindow = nullptr;
430 :
431 : /// @brief The splitter that divides the main window into views and the log window
432 : FXSplitter* myMainSplitter = nullptr;
433 :
434 : /// @brief for some menu detaching fun
435 : FXToolBarShell* myToolBarDrag1 = nullptr,
436 : *myToolBarDrag2 = nullptr,
437 : *myToolBarDrag3 = nullptr,
438 : *myToolBarDrag4 = nullptr,
439 : *myToolBarDrag5 = nullptr,
440 : *myMenuBarDrag = nullptr,
441 : *myToolBarDrag8 = nullptr;
442 :
443 : /// @brief the simulation delay in milliseconds
444 : double mySimDelay = 0.;
445 :
446 : /// @brief Simulation delay target
447 : FXDataTarget* mySimDelayTarget = nullptr;
448 :
449 : /// @brief Simulation delay spinner
450 : FXRealSpinner* mySimDelaySpinner = nullptr;
451 :
452 : /// @brief Simulation delay slider
453 : FXSlider* mySimDelaySlider = nullptr;
454 :
455 : /// @brief the demand scale label
456 : MFXLabelTooltip* myScaleTrafficTooltip = nullptr;
457 :
458 : /// @brief the demand scale
459 : FXRealSpinner* myDemandScaleSpinner = nullptr;
460 :
461 : /// @brief The alternate simulation delay in milliseconds for toggling
462 : double myAlternateSimDelay = 0;
463 :
464 : /// @brief List of got requests
465 : MFXSynchQue<GUIEvent*> myEvents;
466 :
467 : /// @brief The menu used for the MDI-windows
468 : FXMDIMenu* myMDIMenu = nullptr;
469 :
470 : /// @brief The application menu bar
471 : FXMenuBar* myMenuBar = nullptr;
472 :
473 : /// @brief The application tool bar
474 : FXToolBar* myToolBar1 = nullptr,
475 : *myToolBar2 = nullptr,
476 : *myToolBar3 = nullptr,
477 : *myToolBar4 = nullptr,
478 : *myToolBar5 = nullptr,
479 : *myToolBar8 = nullptr;
480 :
481 : /// @brief the simulation step display
482 : MFXLCDLabel* myLCDLabel = nullptr;
483 :
484 : /// @brief io-event with the load-thread
485 : FXEX::MFXThreadEvent myLoadThreadEvent;
486 :
487 : /// @brief io-event with the run-thread
488 : FXEX::MFXThreadEvent myRunThreadEvent;
489 :
490 : /// @brief List of recent networks
491 : MFXRecentNetworks myRecentNetworks;
492 :
493 : /// @brief List of recent configs
494 : MFXRecentNetworks myRecentConfigs;
495 :
496 : /// @brief flag to mark if GUIApplicationWIndow has depend build
497 : bool hadDependentBuild = false;
498 :
499 : /// @brief whether to show time as hour:minute:second
500 : bool myShowTimeAsHMS = false;
501 :
502 : /// @brief whether the simulation end was already announced
503 : bool myHaveNotifiedAboutSimEnd = false;
504 :
505 : /// @brief the mutex for the waiting semaphore
506 : FXMutex myEventMutex;
507 :
508 : /// @brief the semaphore when waiting for event completion
509 : FXCondition myEventCondition;
510 :
511 : /// @brief menu checkbox to activate game mode
512 : FXMenuCheck* myGamingModeCheckbox;
513 :
514 : /// @name game related things
515 : /// {
516 :
517 : /// @brief random list of jam sounds
518 : RandomDistributor<std::string> myJamSounds;
519 :
520 : /// @brief random list of collision sounds
521 : RandomDistributor<std::string> myCollisionSounds;
522 :
523 : /// @brief waiting time after which vehicles trigger jam sounds
524 : double myJamSoundTime = 60;
525 :
526 : /// @brief A random number generator used to choose a gaming sound
527 : static std::mt19937 myGamingRNG;
528 :
529 : /// @brief previous collision number
530 : int myPreviousCollisionNumber = 0;
531 :
532 : /// @brief flag for enable TLS gameMode
533 : bool myTLSGame = false;
534 :
535 : /// @brief waiting time label
536 : MFXLCDLabel* myWaitingTimeLabel = nullptr;
537 :
538 : /// @brief waiting time
539 : SUMOTime myWaitingTime = 0;
540 :
541 : /// @brief time loss label
542 : MFXLCDLabel* myTimeLossLabel = nullptr;
543 :
544 : /// @brief time loss
545 : SUMOTime myTimeLoss = 0;
546 :
547 : /// @brief total distance label
548 : MFXLCDLabel* myTotalDistanceLabel = nullptr;
549 :
550 : /// @brief total distance
551 : double myTotalDistance = 0;
552 :
553 : /// @brief emergency vehicle label
554 : MFXLCDLabel* myEmergencyVehicleLabel = nullptr;
555 :
556 : /// @brief emergency vehicle count
557 : SUMOTime myEmergencyVehicleCount = 0;
558 :
559 : /// @brief toolbars used in game
560 : FXToolBar* myToolBar6 = nullptr,
561 : *myToolBar7 = nullptr,
562 : *myToolBar9 = nullptr,
563 : *myToolBar10 = nullptr;
564 :
565 : /// @brief toolbars shell used in game
566 : FXToolBarShell* myToolBarDrag6 = nullptr,
567 : *myToolBarDrag7 = nullptr,
568 : *myToolBarDrag9 = nullptr,
569 : *myToolBarDrag10 = nullptr;
570 : ////}
571 :
572 : /// @brief last time the simulation view was redrawn due to a simStep
573 : long myLastStepEventMillis;
574 :
575 : /// @brief custom hotkeys pressed
576 : std::map<int, Command*> myHotkeyPress;
577 :
578 : /// @brief custom hotkeys released
579 : std::map<int, Command*> myHotkeyRelease;
580 :
581 : /// @brief breakpoint dialog
582 : GUIDialog_Breakpoints* myBreakpointDialog = nullptr;
583 :
584 : std::stringstream* myDynamicSelection = nullptr;
585 :
586 : private:
587 : /// @brief starts to load a simulation
588 : void loadConfigOrNet(const std::string& file);
589 :
590 : /// @brief this method closes all windows and deletes the current simulation
591 : void closeAllWindows();
592 :
593 : /// @brief updates the simulation time display
594 : void updateTimeLCD(SUMOTime time);
595 :
596 : /// @brief update LCD timer tooltip
597 : void updateTimeLCDTooltip();
598 :
599 : /// @brief opens a new simulation display
600 : GUISUMOAbstractView* openNewView(GUISUMOViewParent::ViewType vt = GUISUMOViewParent::VIEW_2D_OPENGL, std::string caption = "");
601 :
602 : /// @brief handles additional game-related events
603 : void checkGamingEvents();
604 :
605 : /// @brief handles additional game-related events (DRT)
606 : void checkGamingEventsDRT();
607 :
608 : /// @brief invalidate copy constructor
609 : GUIApplicationWindow(const GUIApplicationWindow& s) = delete;
610 :
611 : /// @brief invalidate assignment operator
612 : GUIApplicationWindow& operator=(const GUIApplicationWindow& s) = delete;
613 : };
|