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