Eclipse SUMO - Simulation of Urban MObility
GUIMainWindow.cpp
Go to the documentation of this file.
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 /****************************************************************************/
20 //
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <string>
25 #include <algorithm>
27 // fx3d includes windows.h so we need to guard against macro pollution
28 #ifdef WIN32
29 #define NOMINMAX
30 #endif
31 #include <fx3d.h>
32 #ifdef WIN32
33 #undef NOMINMAX
34 #endif
42 #include "GUIMainWindow.h"
43 #include "GUIGlChildWindow.h"
44 
45 
46 // ===========================================================================
47 // static member definitions
48 // ===========================================================================
50 
51 // ===========================================================================
52 // member method definitions
53 // ===========================================================================
55  FXMainWindow(app, "sumo-gui main window", nullptr, nullptr, DECOR_ALL, 20, 20, 600, 400),
56  myAmFullScreen(false),
57  myTrackerLock(true),
58  myGLVisual(new FXGLVisual(app, VISUAL_DOUBLEBUFFER)),
59  myAmGaming(false),
60  myListInternal(false),
61  myListParking(true),
62  myListTeleporting(false) {
63  // build static tooltips
66  // build bold font
67  FXFontDesc fdesc;
68  app->getNormalFont()->getFontDesc(fdesc);
69  fdesc.weight = FXFont::Bold;
70  GUIDesignHeight = (int)(fdesc.size / 90.0 * 18) + 5;
71  myBoldFont = new FXFont(app, fdesc);
72  // https://en.wikipedia.org/wiki/Noto_fonts should be widely available
73  myFallbackFont = new FXFont(app, "Noto Sans CJK JP");
74  // build docks
75  myTopDock = new FXDockSite(this, LAYOUT_SIDE_TOP | LAYOUT_FILL_X);
76  myBottomDock = new FXDockSite(this, LAYOUT_SIDE_BOTTOM | LAYOUT_FILL_X);
77  myLeftDock = new FXDockSite(this, LAYOUT_SIDE_LEFT | LAYOUT_FILL_Y);
78  myRightDock = new FXDockSite(this, LAYOUT_SIDE_RIGHT | LAYOUT_FILL_Y);
79  // avoid instance Windows twice
80  if (myInstance != nullptr) {
81  throw ProcessError("MainWindow initialized twice");
82  }
83  myInstance = this;
84  //myGLVisual->setStencilSize(8); // enable stencil buffer
85 }
86 
87 
89  delete myStaticTooltipMenu;
90  delete myStaticTooltipView;
91  delete myBoldFont;
92  delete myFallbackFont;
93  delete myTopDock;
94  delete myBottomDock;
95  delete myLeftDock;
96  delete myRightDock;
97  myInstance = nullptr;
98 }
99 
100 
101 
102 void
104  myGLWindows.push_back(child);
105 }
106 
107 
108 void
110  std::vector<GUIGlChildWindow*>::iterator i = std::find(myGLWindows.begin(), myGLWindows.end(), child);
111  if (i != myGLWindows.end()) {
112  myGLWindows.erase(i);
113  }
114 }
115 
116 
117 void
118 GUIMainWindow::addChild(FXMainWindow* child) {
119  myTrackerLock.lock();
120  myTrackerWindows.push_back(child);
121  myTrackerLock.unlock();
122 }
123 
124 
125 void
126 GUIMainWindow::removeChild(FXMainWindow* child) {
127  myTrackerLock.lock();
128  std::vector<FXMainWindow*>::iterator i = std::find(myTrackerWindows.begin(), myTrackerWindows.end(), child);
129  myTrackerWindows.erase(i);
130  myTrackerLock.unlock();
131 }
132 
133 
134 FXDockSite*
136  return myTopDock;
137 }
138 
139 
140 std::vector<std::string>
142  std::vector<std::string> ret;
143  for (GUIGlChildWindow* const window : myGLWindows) {
144  ret.push_back(window->getTitle().text());
145  }
146  return ret;
147 }
148 
149 
151 GUIMainWindow::getViewByID(const std::string& id) const {
152  for (GUIGlChildWindow* const window : myGLWindows) {
153  if (std::string(window->getTitle().text()) == id) {
154  return window;
155  }
156  }
157  return nullptr;
158 }
159 
160 
161 void
162 GUIMainWindow::removeViewByID(const std::string& id) {
163  for (GUIGlChildWindow* const window : myGLWindows) {
164  if (std::string(window->getTitle().text()) == id) {
165  window->close();
166  removeGLChild(window);
167  return;
168  }
169  }
170 }
171 
172 
173 FXFont*
175  return myBoldFont;
176 }
177 
178 FXFont*
180  return myFallbackFont;
181 }
182 
183 const std::vector<GUIGlChildWindow*>&
185  return myGLWindows;
186 }
187 
188 
189 void
191  // inform views
192  myMDIClient->forallWindows(this, FXSEL(SEL_COMMAND, msg), nullptr);
193  // inform other windows
194  myTrackerLock.lock();
195  for (int i = 0; i < (int)myTrackerWindows.size(); i++) {
196  myTrackerWindows[i]->handle(this, FXSEL(SEL_COMMAND, msg), nullptr);
197  }
198  myTrackerLock.unlock();
199 }
200 
201 
202 FXGLVisual*
204  return myGLVisual;
205 }
206 
207 
210  return myStaticTooltipMenu;
211 }
212 
213 
216  return myStaticTooltipView;
217 }
218 
219 
220 FXLabel*
222  return myCartesianCoordinate;
223 }
224 
225 
226 FXLabel*
228  return myGeoCoordinate;
229 }
230 
231 
232 FXLabel*
234  return myTestCoordinate;
235 }
236 
237 
238 FXHorizontalFrame*
240  return myTestFrame;
241 }
242 
243 
244 bool
246  return myAmGaming;
247 }
248 
249 
250 bool
252  return myListInternal;
253 }
254 
255 
256 bool
258  return myListParking;
259 }
260 
261 
262 bool
264  return myListTeleporting;
265 }
266 
267 
270  if (myInstance != nullptr) {
271  return myInstance;
272  }
273  throw ProcessError("A GUIMainWindow instance was not yet constructed.");
274 }
275 
276 
279  GUIGlChildWindow* w = dynamic_cast<GUIGlChildWindow*>(myMDIClient->getActiveChild());
280  if (w != nullptr) {
281  return w->getView();
282  }
283  return nullptr;
284 }
285 
286 
287 void
289  int windowWidth = getApp()->reg().readIntEntry("SETTINGS", "width", 600);
290  int windowHeight = getApp()->reg().readIntEntry("SETTINGS", "height", 400);
291  const OptionsCont& oc = OptionsCont::getOptions();
292  if (oc.isSet("window-size")) {
293  std::vector<std::string> windowSize = oc.getStringVector("window-size");
294  if (windowSize.size() != 2) {
295  WRITE_ERROR(TL("option window-size requires INT,INT"));
296  } else {
297  try {
298  windowWidth = StringUtils::toInt(windowSize[0]);
299  windowHeight = StringUtils::toInt(windowSize[1]);
300  } catch (NumberFormatException& e) {
301  WRITE_ERROR("option window-size requires INT,INT " + toString(e.what()));
302  }
303  }
304  }
305  if (oc.isSet("window-size") || getApp()->reg().readIntEntry("SETTINGS", "maximized", 0) == 0 || oc.isSet("window-pos")) {
306  // when restoring previous pos, make sure the window fits fully onto the current screen
307  int x = MAX2(0, MIN2(getApp()->reg().readIntEntry("SETTINGS", "x", 150), getApp()->getRootWindow()->getWidth() - windowWidth));
308  int y = MAX2(50, MIN2(getApp()->reg().readIntEntry("SETTINGS", "y", 150), getApp()->getRootWindow()->getHeight() - windowHeight));
309  if (oc.isSet("window-pos")) {
310  std::vector<std::string> windowPos = oc.getStringVector("window-pos");
311  if (windowPos.size() != 2) {
312  WRITE_ERROR(TL("option window-pos requires INT,INT"));
313  } else {
314  try {
315  x = StringUtils::toInt(windowPos[0]);
316  y = StringUtils::toInt(windowPos[1]);
317  } catch (NumberFormatException& e) {
318  WRITE_ERROR("option window-pos requires INT,INT " + toString(e.what()));
319  }
320  }
321  }
322  move(x, y);
323  resize(windowWidth, windowHeight);
324  }
325 }
326 
327 void
329  if (!myAmFullScreen) {
330  getApp()->reg().writeIntEntry("SETTINGS", "x", getX());
331  getApp()->reg().writeIntEntry("SETTINGS", "y", getY());
332  getApp()->reg().writeIntEntry("SETTINGS", "width", getWidth());
333  getApp()->reg().writeIntEntry("SETTINGS", "height", getHeight());
334  }
335 }
336 
337 
338 void
339 GUIMainWindow::buildLanguageMenu(FXMenuBar* menuBar) {
340  myLanguageMenu = new FXMenuPane(this);
341  GUIDesigns::buildFXMenuTitle(menuBar, TL("Langua&ge"), nullptr, myLanguageMenu);
342 
343  GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "English", "", TL("Change language to english. (en)"),
345  GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Deutsch", "", TL("Change language to german. (de)"),
347  GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Español", "", TL("Change language to spanish. (es)"),
349  GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Français", "", TL("Change language to french. (fr)"),
351  GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Italiano", "", TL("Change language to italian. (it)"),
353  GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "简体中文", "", TL("简体中文 (zh)"),
355  GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "繁體中文", "", TL("繁體中文 (zh-Hant)"),
357  GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Türkçe", "", TL("Change language to turkish. (tr)"),
359  GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Magyar", "", TL("Change language to hungarian. (hu)"),
361 }
362 
363 
364 long
365 GUIMainWindow::onCmdChangeLanguage(FXObject*, FXSelector sel, void*) {
366  // set language
367  std::string langID;
368  std::string lang;
369  // continue depending of called button
370  switch (FXSELID(sel)) {
371  case MID_LANGUAGE_DE:
372  langID = "de";
373  lang = TL("german");
374  break;
375  case MID_LANGUAGE_ES:
376  langID = "es";
377  lang = TL("spanish");
378  break;
379  case MID_LANGUAGE_FR:
380  langID = "fr";
381  lang = TL("french");
382  break;
383  case MID_LANGUAGE_IT:
384  langID = "it";
385  lang = TL("italian");
386  break;
387  case MID_LANGUAGE_ZH:
388  langID = "zh";
389  lang = TL("simplified chinese");
390  break;
391  case MID_LANGUAGE_ZHT:
392  langID = "zh-Hant";
393  lang = TL("traditional chinese");
394  break;
395  case MID_LANGUAGE_TR:
396  langID = "tr";
397  lang = TL("turkish");
398  break;
399  case MID_LANGUAGE_HU:
400  langID = "hu";
401  lang = TL("hungarian");
402  break;
403  default:
404  langID = "C";
405  lang = TL("english");
406  break;
407  }
408  // check if change language
409  if (langID != gLanguage) {
410  // update language
411  gLanguage = langID;
412  // show info
413  WRITE_MESSAGE(TL("Language changed to ") + lang);
414  // show dialog
415  const std::string header = TL("Restart needed");
416  const std::string body = TL("Changing display language needs restart to take effect.") + std::string("\n") +
417 #ifdef DEBUG
418 #ifdef WIN32
419  TL("For the Debug build you might also need to set the LANG environment variable.") + std::string("\n") +
420 #endif
421 #endif
422  TL("Under development. You can help to improve the translation at:") + std::string("\n") +
423  "https://hosted.weblate.org/projects/eclipse-sumo/";
424  FXMessageBox::information(getApp(), MBOX_OK, header.c_str(), "%s", body.c_str());
425  // update language in registry (common for sumo and netedit)
426  std::string appKey = getApp()->reg().getAppKey().text();
427  if (appKey == "SUMO GUI") {
428  // registry is written again later so we have to modify the "life" version
429  getApp()->reg().writeStringEntry("gui", "language", langID.c_str());
430  } else {
431  FXRegistry reg("SUMO GUI", "sumo-gui");
432  reg.read();
433  reg.writeStringEntry("gui", "language", langID.c_str());
434  reg.write();
435  }
436  }
437  return 1;
438 }
439 
440 
441 long
442 GUIMainWindow::onUpdChangeLanguage(FXObject* obj, FXSelector, void*) {
443  // get language menu command
444  FXMenuCommand* menuCommand = dynamic_cast<FXMenuCommand*>(obj);
445  if (menuCommand) {
446  // check if change color
447  if ((gLanguage == "C") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_EN))) {
448  menuCommand->setTextColor(FXRGB(0, 0, 255));
449  } else if ((gLanguage == "de") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_DE))) {
450  menuCommand->setTextColor(FXRGB(0, 0, 255));
451  } else if ((gLanguage == "es") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_ES))) {
452  menuCommand->setTextColor(FXRGB(0, 0, 255));
453  } else if ((gLanguage == "fr") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_FR))) {
454  menuCommand->setTextColor(FXRGB(0, 0, 255));
455  } else if ((gLanguage == "it") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_IT))) {
456  menuCommand->setTextColor(FXRGB(0, 0, 255));
457  } else if ((gLanguage == "zh") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_ZH))) {
458  menuCommand->setTextColor(FXRGB(0, 0, 255));
459  } else if ((gLanguage == "zh-Hant") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_ZHT))) {
460  menuCommand->setTextColor(FXRGB(0, 0, 255));
461  } else if ((gLanguage == "tr") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_TR))) {
462  menuCommand->setTextColor(FXRGB(0, 0, 255));
463  } else if ((gLanguage == "hu") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_HU))) {
464  menuCommand->setTextColor(FXRGB(0, 0, 255));
465  } else {
466  menuCommand->setTextColor(FXRGB(0, 0, 0));
467  }
468  }
469  return 1;
470 }
471 
472 
473 /****************************************************************************/
@ MID_LANGUAGE_TR
change language to turkish
Definition: GUIAppEnum.h:1619
@ MID_LANGUAGE_ZHT
change language to chinese (traditional)
Definition: GUIAppEnum.h:1617
@ MID_LANGUAGE_ES
change language to spanish
Definition: GUIAppEnum.h:1609
@ MID_LANGUAGE_HU
change language to hungarian
Definition: GUIAppEnum.h:1621
@ MID_LANGUAGE_IT
change language to italian
Definition: GUIAppEnum.h:1613
@ MID_LANGUAGE_EN
change language to english
Definition: GUIAppEnum.h:1605
@ MID_LANGUAGE_DE
change language to german
Definition: GUIAppEnum.h:1607
@ MID_LANGUAGE_ZH
change language to chinese (simplified)
Definition: GUIAppEnum.h:1615
@ MID_LANGUAGE_FR
change language to french
Definition: GUIAppEnum.h:1611
@ LANGUAGE_ZHT
@ LANGUAGE_EN
icons for languages
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:297
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define TL(string)
Definition: MsgHandler.h:315
std::string gLanguage
the language for GUI elements and messages
Definition: StdDefs.cpp:34
int GUIDesignHeight
the default size for GUI elements
Definition: StdDefs.cpp:35
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static FXMenuTitle * buildFXMenuTitle(FXComposite *p, const std::string &text, FXIcon *icon, FXMenuPane *menuPane)
build menu title
Definition: GUIDesigns.cpp:31
static FXMenuCommand * buildFXMenuCommandShortcut(FXComposite *p, const std::string &text, const std::string &shortcut, const std::string &info, FXIcon *icon, FXObject *tgt, FXSelector sel)
build menu command
Definition: GUIDesigns.cpp:74
GUISUMOAbstractView * getView() const
return GUISUMOAbstractView
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
void setWindowSizeAndPos()
perform initial window positioning and sizing according to user options / previous call
const std::vector< GUIGlChildWindow * > & getViews() const
get views
bool myListParking
information whether the locator should list parking vehicles
static GUIMainWindow * myInstance
the singleton window instance
virtual ~GUIMainWindow()
destructor
FXDockSite * myRightDock
void removeViewByID(const std::string &id)
GUIGlChildWindow * getViewByID(const std::string &id) const
get specific view by ID
std::vector< FXMainWindow * > myTrackerWindows
list of tracker windows
MFXStaticToolTip * getStaticTooltipView() const
get static toolTip for view
FXFont * myFallbackFont
Fallback font for extended characters support.
std::vector< std::string > getViewIDs() const
get view IDs
FXMenuPane * myLanguageMenu
Language menu common to all applications.
GUISUMOAbstractView * getActiveView() const
get the active view or 0
FXLabel * getGeoLabel()
get geo label
bool isGaming() const
return whether the gui is in gaming mode
bool myListTeleporting
information whether the locator should list teleporting vehicles
FXLabel * myCartesianCoordinate
Labels for the current cartesian, geo-coordinate and test coordinates.
MFXStaticToolTip * myStaticTooltipMenu
static toolTip used in menus
FXMDIClient * myMDIClient
The multi view panel.
FXFont * getBoldFont()
get bold front
FXDockSite * myLeftDock
void buildLanguageMenu(FXMenuBar *menuBar)
long onCmdChangeLanguage(FXObject *, FXSelector, void *)
bool listTeleporting() const
return whether to list teleporting vehicles
FXLabel * getTestLabel()
get test label
MFXStaticToolTip * myStaticTooltipView
static toolTip used in view
MFXStaticToolTip * getStaticTooltipMenu() const
get static toolTip for menus
FXFont * myBoldFont
Font used for popup-menu titles.
static GUIMainWindow * getInstance()
get instance
bool listParking() const
return whether to list parking vehicles
FXDockSite * myBottomDock
bool listInternal() const
return whether to list internal structures
FXHorizontalFrame * myTestFrame
void addGLChild(GUIGlChildWindow *child)
Adds a further child window to the list (GUIGlChildWindow)
FXLabel * myTestCoordinate
FXMutex myTrackerLock
A lock to make the removal and addition of trackers secure.
FXDockSite * myTopDock
dock sites
bool myListInternal
information whether the locator should list internal structures
void storeWindowSizeAndPos()
record window position and size in registry
FXLabel * getCartesianLabel()
get cartesian label
FXGLVisual * getGLVisual() const
get GL Visual
bool myAmFullScreen
FOX need this.
void removeGLChild(GUIGlChildWindow *child)
removes the given child window from the list (GUIGlChildWindow)
FXDockSite * getTopDock()
get top dock
FXHorizontalFrame * getTestFrame()
get test frame
FXLabel * myGeoCoordinate
FXFont * getFallbackFont()
get fallback front
void updateChildren(int msg=MID_SIMSTEP)
update childrens
FXGLVisual * myGLVisual
The gl-visual used.
bool myAmGaming
information whether the gui is currently in gaming mode
void removeChild(FXMainWindow *child)
removes the given child window from the list (FXMainWindow)
GUIMainWindow(FXApp *app)
constructor
std::vector< GUIGlChildWindow * > myGLWindows
list of GLWindows
long onUpdChangeLanguage(FXObject *, FXSelector, void *)
void addChild(FXMainWindow *child)
Adds a further child window to the list (FXMainWindow)
MFXStaticToolTip (based on FXToolTip)
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...