Makefile: remove spurious tab
[xcsoar.git] / src / MainWindow.cpp
blobca05402ac39d6327ed71aeb8fb7d8510ee9b03d1
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "MainWindow.hpp"
25 #include "Startup.hpp"
26 #include "MapWindow/GlueMapWindow.hpp"
27 #include "resource.h"
28 #include "InfoBoxes/InfoBoxManager.hpp"
29 #include "InfoBoxes/InfoBoxLayout.hpp"
30 #include "Interface.hpp"
31 #include "ActionInterface.hpp"
32 #include "UIActions.hpp"
33 #include "PageActions.hpp"
34 #include "Input/InputEvents.hpp"
35 #include "Menu/ButtonLabel.hpp"
36 #include "Screen/Layout.hpp"
37 #include "Screen/Blank.hpp"
38 #include "Dialogs/Airspace/AirspaceWarningDialog.hpp"
39 #include "Audio/Sound.hpp"
40 #include "Components.hpp"
41 #include "ProcessTimer.hpp"
42 #include "LogFile.hpp"
43 #include "Gauge/GaugeFLARM.hpp"
44 #include "Gauge/GaugeThermalAssistant.hpp"
45 #include "Gauge/GlueGaugeVario.hpp"
46 #include "Menu/MenuBar.hpp"
47 #include "Form/Form.hpp"
48 #include "Widget/Widget.hpp"
49 #include "UtilsSystem.hpp"
50 #include "Look/Fonts.hpp"
51 #include "Look/Look.hpp"
52 #include "Profile/ProfileKeys.hpp"
53 #include "Profile/Profile.hpp"
54 #include "ProgressGlue.hpp"
55 #include "UIState.hpp"
56 #include "DrawThread.hpp"
57 #include "UIReceiveBlackboard.hpp"
58 #include "Event/Idle.hpp"
60 #ifdef ENABLE_OPENGL
61 #include "Screen/OpenGL/Cache.hpp"
62 #endif
64 #if !defined(WIN32) && !defined(ANDROID)
65 #include <unistd.h>
66 #endif
68 #if !defined(WIN32) && !defined(ANDROID)
69 #include <unistd.h> /* for execl() */
70 #endif
72 gcc_pure
73 static PixelRect
74 GetBottomWidgetRect(const PixelRect &rc, const Widget *bottom_widget)
76 if (bottom_widget == nullptr) {
77 /* no bottom widget: return empty rectangle, map uses the whole
78 main area */
79 PixelRect result = rc;
80 result.top = result.bottom;
81 return result;
84 const UPixelScalar requested_height = bottom_widget->GetMinimumSize().cy;
85 UPixelScalar height;
86 if (requested_height > 0) {
87 const UPixelScalar max_height = (rc.bottom - rc.top) / 2;
88 height = std::min(max_height, requested_height);
89 } else {
90 const UPixelScalar recommended_height = (rc.bottom - rc.top) / 3;
91 height = recommended_height;
94 PixelRect result = rc;
95 result.top = result.bottom - height;
96 return result;
99 gcc_pure
100 static PixelRect
101 GetMapRectAbove(const PixelRect &rc, const PixelRect &bottom_rect)
103 PixelRect result = rc;
104 result.bottom = bottom_rect.top;
105 return result;
108 MainWindow::MainWindow(const StatusMessageList &status_messages)
109 :look(NULL),
110 map(nullptr), bottom_widget(nullptr), widget(nullptr), vario(*this),
111 traffic_gauge(*this),
112 suppress_traffic_gauge(false), force_traffic_gauge(false),
113 thermal_assistant(*this),
114 dragging(false),
115 popup(status_messages, *this, CommonInterface::GetUISettings()),
116 timer(*this),
117 FullScreen(false),
118 #ifndef ENABLE_OPENGL
119 draw_suspended(false),
120 #endif
121 restore_page_pending(false),
122 airspace_warning_pending(false)
127 * Destructor of the MainWindow-Class
128 * @return
130 MainWindow::~MainWindow()
132 Destroy();
135 void
136 MainWindow::Create(PixelSize size, TopWindowStyle style)
138 style.EnableDoubleClicks();
139 SingleWindow::Create(title, size, style);
142 gcc_noreturn
143 static void
144 NoFontsAvailable()
146 const TCHAR *msg = _T("Font initialisation failed");
148 /* log the error */
149 LogFormat(_T("%s"), msg);
151 /* now try to get a GUI error message out to the user */
152 #ifdef WIN32
153 MessageBox(NULL, msg, _T("XCSoar"), MB_ICONEXCLAMATION|MB_OK);
154 #elif !defined(ANDROID)
155 execl("/usr/bin/xmessage", "xmessage", msg, NULL);
156 execl("/usr/X11/bin/xmessage", "xmessage", msg, NULL);
157 #endif
158 exit(EXIT_FAILURE);
161 void
162 MainWindow::Initialise()
164 Layout::Initialize(GetSize());
166 LogFormat("Initialise fonts");
167 if (!Fonts::Initialize()) {
168 Destroy();
169 NoFontsAvailable();
172 if (look == NULL)
173 look = new Look();
175 look->Initialise(Fonts::map, Fonts::map_bold, Fonts::map_label);
178 void
179 MainWindow::InitialiseConfigured()
181 const UISettings &ui_settings = CommonInterface::GetUISettings();
183 PixelRect rc = GetClientRect();
185 const InfoBoxLayout::Layout ib_layout =
186 InfoBoxLayout::Calculate(rc, ui_settings.info_boxes.geometry);
188 Fonts::SizeInfoboxFont(ib_layout.control_width);
190 if (ui_settings.custom_fonts) {
191 LogFormat("Load custom fonts");
192 if (!Fonts::LoadCustom()) {
193 LogFormat("Failed to load custom fonts");
194 if (!Fonts::Initialize()) {
195 Destroy();
196 NoFontsAvailable();
200 #ifdef ENABLE_OPENGL
201 /* fonts may have changed, discard all pre-rendered font
202 textures */
203 TextCache::Flush();
204 #endif
207 assert(look != NULL);
208 look->InitialiseConfigured(CommonInterface::GetUISettings(),
209 Fonts::map, Fonts::map_bold, Fonts::map_label,
210 Fonts::cdi, Fonts::monospace,
211 Fonts::infobox, Fonts::infobox_small,
212 #ifndef GNAV
213 Fonts::infobox_units,
214 #endif
215 Fonts::title);
217 InfoBoxManager::Create(*this, ib_layout, look->info_box, look->units);
218 map_rect = ib_layout.remaining;
220 ButtonLabel::CreateButtonLabels(*this);
221 ButtonLabel::SetFont(Fonts::map_bold);
223 ReinitialiseLayout_vario(ib_layout);
225 ReinitialiseLayoutTA(rc, ib_layout);
227 WindowStyle hidden_border;
228 hidden_border.Hide();
229 hidden_border.Border();
231 ReinitialiseLayout_flarm(rc, ib_layout);
233 map = new GlueMapWindow(*look);
234 map->SetComputerSettings(CommonInterface::GetComputerSettings());
235 map->SetMapSettings(CommonInterface::GetMapSettings());
236 map->SetUIState(CommonInterface::GetUIState());
237 map->Create(*this, map_rect);
239 popup.Create(rc);
242 void
243 MainWindow::Deinitialise()
245 InfoBoxManager::Destroy();
246 ButtonLabel::Destroy();
248 popup.Destroy();
250 // During destruction of GlueMapWindow WM_SETFOCUS gets called for
251 // MainWindow which tries to set the focus to GlueMapWindow. Prevent
252 // this issue by setting map to NULL before calling delete.
253 GlueMapWindow *temp_map = map;
254 map = NULL;
255 delete temp_map;
257 vario.Clear();
258 traffic_gauge.Clear();
259 thermal_assistant.Clear();
261 delete look;
262 look = NULL;
265 void
266 MainWindow::ReinitialiseLayout_vario(const InfoBoxLayout::Layout &layout)
268 if (!layout.HasVario()) {
269 vario.Clear();
270 return;
273 if (!vario.IsDefined())
274 vario.Set(new GlueGaugeVario(CommonInterface::GetLiveBlackboard(),
275 look->vario, look->units));
277 vario.Move(layout.vario);
278 vario.Show();
280 // XXX vario->BringToTop();
283 void
284 MainWindow::ReinitialiseLayoutTA(PixelRect rc,
285 const InfoBoxLayout::Layout &layout)
287 UPixelScalar sz = std::min(layout.control_height,
288 layout.control_width) * 2;
289 rc.right = rc.left + sz;
290 rc.top = rc.bottom - sz;
291 thermal_assistant.Move(rc);
294 void
295 MainWindow::ReinitialiseLayout()
297 if (map == NULL) {
298 #ifdef ANDROID
299 if (HasDialog())
300 dialogs.top()->ReinitialiseLayout(); // adapt simulator prompt
301 #endif
302 /* without the MapWindow, it is safe to assume that the MainWindow
303 is just being initialized, and the InfoBoxes aren't initialized
304 yet either, so there is nothing to do here */
305 return;
308 #ifndef ENABLE_OPENGL
309 if (draw_thread == NULL)
310 /* no layout changes during startup */
311 return;
312 #endif
314 InfoBoxManager::Destroy();
316 const UISettings &ui_settings = CommonInterface::GetUISettings();
318 const PixelRect rc = GetClientRect();
319 const InfoBoxLayout::Layout ib_layout =
320 InfoBoxLayout::Calculate(rc, ui_settings.info_boxes.geometry);
322 Fonts::SizeInfoboxFont(ib_layout.control_width);
324 InfoBoxManager::Create(*this, ib_layout, look->info_box, look->units);
325 InfoBoxManager::ProcessTimer();
326 map_rect = ib_layout.remaining;
328 popup.Destroy();
329 popup.Create(rc);
331 ReinitialiseLayout_vario(ib_layout);
333 ReinitialiseLayout_flarm(rc, ib_layout);
335 ReinitialiseLayoutTA(rc, ib_layout);
337 if (map != NULL) {
338 if (FullScreen)
339 InfoBoxManager::Hide();
340 else
341 InfoBoxManager::Show();
343 const PixelRect main_rect = GetMainRect();
344 const PixelRect bottom_rect = GetBottomWidgetRect(main_rect,
345 bottom_widget);
347 if (bottom_widget != nullptr)
348 bottom_widget->Move(bottom_rect);
350 map->Move(GetMapRectAbove(main_rect, bottom_rect));
351 map->FullRedraw();
354 if (widget != NULL)
355 widget->Move(GetMainRect(rc));
357 #ifdef ANDROID
358 // move topmost dialog to fit into the current layout, or close it
359 if (HasDialog())
360 dialogs.top()->ReinitialiseLayout();
361 #endif
363 if (map != NULL)
364 map->BringToBottom();
367 void
368 MainWindow::ReinitialiseLayout_flarm(PixelRect rc, const InfoBoxLayout::Layout ib_layout)
370 TrafficSettings::GaugeLocation val =
371 CommonInterface::GetUISettings().traffic.gauge_location;
373 // Automatic mode - follow info boxes
374 if (val == TrafficSettings::GaugeLocation::Auto) {
375 switch (InfoBoxManager::layout.geometry) {
376 case InfoBoxSettings::Geometry::TOP_8:
377 val = TrafficSettings::GaugeLocation::TopRight;
378 break;
379 case InfoBoxSettings::Geometry::LEFT_8:
380 val = TrafficSettings::GaugeLocation::BottomLeft;
381 break;
382 case InfoBoxSettings::Geometry::TOP_12:
383 val = TrafficSettings::GaugeLocation::TopLeft;
384 break;
385 default:
386 val = TrafficSettings::GaugeLocation::BottomRight; // Assume bottom right unles...
387 break;
391 switch (val) {
392 case TrafficSettings::GaugeLocation::TopLeft:
393 rc.right = rc.left + ib_layout.control_width * 2;
394 ++rc.left;
395 rc.bottom = rc.top + ib_layout.control_height * 2;
396 ++rc.top;
397 break;
399 case TrafficSettings::GaugeLocation::TopRight:
400 rc.left = rc.right - ib_layout.control_width * 2 + 1;
401 rc.bottom = rc.top + ib_layout.control_height * 2;
402 ++rc.top;
403 break;
405 case TrafficSettings::GaugeLocation::BottomLeft:
406 rc.right = rc.left + ib_layout.control_width * 2;
407 ++rc.left;
408 rc.top = rc.bottom - ib_layout.control_height * 2 + 1;
409 break;
411 case TrafficSettings::GaugeLocation::CentreTop:
412 rc.left = (rc.left + rc.right) / 2 - ib_layout.control_width;
413 rc.right = rc.left + ib_layout.control_width * 2 - 1;
414 rc.bottom = rc.top + ib_layout.control_height * 2;
415 ++rc.top;
416 break;
418 case TrafficSettings::GaugeLocation::CentreBottom:
419 rc.left = (rc.left + rc.right) / 2 - ib_layout.control_width;
420 rc.right = rc.left + ib_layout.control_width * 2 - 1;
421 rc.top = rc.bottom - ib_layout.control_height * 2 + 1;
422 break;
424 default: // aka flBottomRight
425 rc.left = rc.right - ib_layout.control_width * 2 + 1;
426 rc.top = rc.bottom - ib_layout.control_height * 2 + 1;
427 break;
430 traffic_gauge.Move(rc);
433 void
434 MainWindow::Destroy()
436 Deinitialise();
438 TopWindow::Destroy();
441 void
442 MainWindow::FinishStartup()
444 timer.Schedule(500); // 2 times per second
446 ResumeThreads();
449 void
450 MainWindow::BeginShutdown()
452 timer.Cancel();
455 void
456 MainWindow::SuspendThreads()
458 if (map != NULL)
459 map->SuspendThreads();
462 void
463 MainWindow::ResumeThreads()
465 if (map != NULL)
466 map->ResumeThreads();
469 void
470 MainWindow::SetDefaultFocus()
472 if (map != NULL && widget == NULL)
473 map->SetFocus();
474 else if (widget == NULL || !widget->SetFocus())
475 SetFocus();
478 void
479 MainWindow::FullRedraw()
481 if (map != NULL)
482 map->FullRedraw();
485 // Windows event handlers
487 void
488 MainWindow::OnResize(PixelSize new_size)
490 SingleWindow::OnResize(new_size);
492 Layout::Initialize(new_size);
494 ReinitialiseLayout();
496 if (map != NULL) {
497 /* the map being created already is an indicator that XCSoar is
498 running already, and so we assume the menu buttons have been
499 created, too */
500 map->BringToBottom();
503 const PixelRect rc = GetClientRect();
504 ButtonLabel::OnResize(rc);
505 ProgressGlue::Move(rc);
508 bool
509 MainWindow::OnActivate()
511 SingleWindow::OnActivate();
513 Fullscreen();
515 return true;
518 void
519 MainWindow::OnSetFocus()
521 SingleWindow::OnSetFocus();
523 if (!HasDialog()) {
524 /* the main window should never have the keyboard focus; if we
525 happen to get the focus despite of that, forward it to the map
526 window to make keyboard shortcuts work */
527 if (map != NULL && widget == NULL)
528 map->SetFocus();
529 else if (widget != NULL)
530 widget->SetFocus();
531 } else
532 /* recover the dialog focus if it got lost */
533 GetTopDialog().FocusFirstControl();
536 void
537 MainWindow::StopDragging()
539 if (!dragging)
540 return;
542 dragging = false;
543 ReleaseCapture();
546 void
547 MainWindow::OnCancelMode()
549 SingleWindow::OnCancelMode();
550 StopDragging();
553 bool
554 MainWindow::OnMouseDown(PixelScalar x, PixelScalar y)
556 if (SingleWindow::OnMouseDown(x, y))
557 return true;
559 if (!dragging && !HasDialog()) {
560 dragging = true;
561 SetCapture();
562 gestures.Start(x, y, Layout::Scale(20));
565 return true;
568 bool
569 MainWindow::OnMouseUp(PixelScalar x, PixelScalar y)
571 if (SingleWindow::OnMouseUp(x, y))
572 return true;
574 if (dragging) {
575 StopDragging();
577 const TCHAR *gesture = gestures.Finish();
578 if (gesture && InputEvents::processGesture(gesture))
579 return true;
582 return false;
585 bool
586 MainWindow::OnMouseDouble(PixelScalar x, PixelScalar y)
588 if (SingleWindow::OnMouseDouble(x, y))
589 return true;
591 StopDragging();
593 if (!HasDialog())
594 InputEvents::ShowMenu();
595 return false;
598 bool
599 MainWindow::OnMouseMove(PixelScalar x, PixelScalar y, unsigned keys)
601 if (SingleWindow::OnMouseMove(x, y, keys))
602 return true;
604 if (dragging)
605 gestures.Update(x, y);
607 return true;
610 bool
611 MainWindow::OnKeyDown(unsigned key_code)
613 return InputEvents::processKey(key_code) ||
614 SingleWindow::OnKeyDown(key_code);
617 bool
618 MainWindow::OnTimer(WindowTimer &_timer)
620 if (_timer != timer)
621 return SingleWindow::OnTimer(_timer);
623 ProcessTimer();
625 UpdateGaugeVisibility();
627 if (!CommonInterface::GetUISettings().enable_thermal_assistant_gauge) {
628 thermal_assistant.Clear();
629 } else if (!CommonInterface::Calculated().circling ||
630 InputEvents::IsFlavour(_T("TA"))) {
631 thermal_assistant.Hide();
632 } else if (!HasDialog()) {
633 if (!thermal_assistant.IsDefined())
634 thermal_assistant.Set(new GaugeThermalAssistant(CommonInterface::GetLiveBlackboard(),
635 look->thermal_assistant_gauge));
637 if (!thermal_assistant.IsVisible()) {
638 thermal_assistant.Show();
640 GaugeThermalAssistant *widget =
641 (GaugeThermalAssistant *)thermal_assistant.Get();
642 widget->Raise();
646 battery_timer.Process();
648 return true;
651 bool
652 MainWindow::OnUser(unsigned id)
654 ProtectedAirspaceWarningManager *airspace_warnings;
656 switch ((Command)id) {
657 case Command::AIRSPACE_WARNING:
658 airspace_warnings = GetAirspaceWarnings();
659 if (!airspace_warning_pending || airspace_warnings == NULL)
660 return true;
662 airspace_warning_pending = false;
663 if (dlgAirspaceWarningVisible())
664 /* already visible */
665 return true;
667 /* un-blank the display, play a sound and show the dialog */
668 ResetUserIdle();
669 PlayResource(_T("IDR_WAV_BEEPBWEEP"));
670 dlgAirspaceWarningsShowModal(*this, *airspace_warnings, true);
671 return true;
673 case Command::GPS_UPDATE:
674 UIReceiveSensorData();
675 return true;
677 case Command::CALCULATED_UPDATE:
678 UIReceiveCalculatedData();
679 return true;
681 case Command::RESTORE_PAGE:
682 if (restore_page_pending)
683 PageActions::Restore();
684 return true;
687 return false;
690 void
691 MainWindow::OnDestroy()
693 timer.Cancel();
695 KillWidget();
696 KillBottomWidget();
698 SingleWindow::OnDestroy();
701 bool MainWindow::OnClose() {
702 if (HasDialog() || !IsRunning())
703 /* no shutdown dialog if XCSoar hasn't completed initialization
704 yet (e.g. if we are in the simulator prompt) */
705 return SingleWindow::OnClose();
707 if (UIActions::CheckShutdown()) {
708 Shutdown();
710 return true;
713 void
714 MainWindow::SetFullScreen(bool _full_screen)
716 if (_full_screen == FullScreen)
717 return;
719 FullScreen = _full_screen;
721 if (FullScreen)
722 InfoBoxManager::Hide();
723 else
724 InfoBoxManager::Show();
726 if (widget != NULL)
727 widget->Move(GetMainRect());
729 if (map != NULL)
730 map->FastMove(GetMainRect());
732 // the repaint will be triggered by the DrawThread
734 UpdateVarioGaugeVisibility();
737 void
738 MainWindow::SetTerrain(RasterTerrain *terrain)
740 if (map != NULL)
741 map->SetTerrain(terrain);
744 void
745 MainWindow::SetTopography(TopographyStore *topography)
747 if (map != NULL)
748 map->SetTopography(topography);
751 void
752 MainWindow::SetComputerSettings(const ComputerSettings &settings_computer)
754 if (map != NULL)
755 map->SetComputerSettings(settings_computer);
758 void
759 MainWindow::SetMapSettings(const MapSettings &settings_map)
761 if (map != NULL)
762 map->SetMapSettings(settings_map);
765 void
766 MainWindow::SetUIState(const UIState &ui_state)
768 if (map != NULL) {
769 map->SetUIState(ui_state);
770 map->FullRedraw();
774 GlueMapWindow *
775 MainWindow::GetMapIfActive()
777 return IsMapActive() ? map : NULL;
780 GlueMapWindow *
781 MainWindow::ActivateMap()
783 restore_page_pending = false;
785 if (map == NULL)
786 return NULL;
788 if (widget != NULL) {
789 KillWidget();
790 map->Show();
791 map->SetFocus();
793 if (bottom_widget != nullptr)
794 bottom_widget->Show(GetBottomWidgetRect(GetMainRect(),
795 bottom_widget));
797 #ifndef ENABLE_OPENGL
798 if (draw_suspended) {
799 draw_suspended = false;
800 draw_thread->Resume();
802 #endif
805 return map;
808 void
809 MainWindow::DeferredRestorePage()
811 if (restore_page_pending)
812 return;
814 restore_page_pending = true;
815 SendUser((unsigned)Command::RESTORE_PAGE);
818 void
819 MainWindow::KillWidget()
821 if (widget == NULL)
822 return;
824 widget->Leave();
825 widget->Hide();
826 widget->Unprepare();
827 delete widget;
828 widget = NULL;
830 InputEvents::SetFlavour(NULL);
833 void
834 MainWindow::KillBottomWidget()
836 if (bottom_widget == nullptr)
837 return;
839 if (widget == nullptr)
840 bottom_widget->Hide();
841 bottom_widget->Unprepare();
842 delete bottom_widget;
845 void
846 MainWindow::SetBottomWidget(Widget *_widget)
848 if (bottom_widget == nullptr && _widget == nullptr)
849 return;
851 if (map == nullptr) {
852 /* this doesn't work without a map */
853 delete _widget;
854 return;
857 KillBottomWidget();
859 bottom_widget = _widget;
861 const PixelRect main_rect = GetMainRect();
862 const PixelRect bottom_rect = GetBottomWidgetRect(main_rect,
863 bottom_widget);
865 if (bottom_widget != nullptr) {
866 bottom_widget->Initialise(*this, bottom_rect);
867 bottom_widget->Prepare(*this, bottom_rect);
869 if (widget == nullptr)
870 bottom_widget->Show(bottom_rect);
873 map->Move(GetMapRectAbove(main_rect, bottom_rect));
874 map->FullRedraw();
877 void
878 MainWindow::SetWidget(Widget *_widget)
880 assert(_widget != NULL);
882 restore_page_pending = false;
884 /* delete the old widget */
885 KillWidget();
887 /* hide the map (might be hidden already) */
888 if (map != NULL) {
889 map->FastHide();
891 #ifndef ENABLE_OPENGL
892 if (!draw_suspended) {
893 draw_suspended = true;
894 draw_thread->BeginSuspend();
896 #endif
899 if (bottom_widget != nullptr)
900 bottom_widget->Hide();
902 widget = _widget;
904 const PixelRect rc = GetMainRect();
905 widget->Initialise(*this, rc);
906 widget->Prepare(*this, rc);
907 widget->Show(rc);
909 if (!widget->SetFocus())
910 SetFocus();
913 Widget *
914 MainWindow::GetFlavourWidget(const TCHAR *flavour)
916 return InputEvents::IsFlavour(flavour)
917 ? widget
918 : nullptr;
921 void
922 MainWindow::UpdateVarioGaugeVisibility()
924 bool full_screen = GetFullScreen();
926 vario.SetVisible(!full_screen &&
927 !CommonInterface::GetUIState().screen_blanked);
930 void
931 MainWindow::UpdateGaugeVisibility()
933 UpdateVarioGaugeVisibility();
934 UpdateTrafficGaugeVisibility();
937 void
938 MainWindow::UpdateTrafficGaugeVisibility()
940 const FlarmData &flarm = CommonInterface::Basic().flarm;
942 bool traffic_visible =
943 (force_traffic_gauge ||
944 (CommonInterface::GetUISettings().traffic.enable_gauge &&
945 !flarm.traffic.IsEmpty())) &&
946 !CommonInterface::GetUIState().screen_blanked &&
947 /* hide the traffic gauge while the traffic widget is visible, to
948 avoid showing the same information twice */
949 !InputEvents::IsFlavour(_T("Traffic"));
951 if (traffic_visible && suppress_traffic_gauge) {
952 if (flarm.status.available &&
953 flarm.status.alarm_level != FlarmTraffic::AlarmType::NONE)
954 suppress_traffic_gauge = false;
955 else
956 traffic_visible = false;
959 if (traffic_visible) {
960 if (HasDialog())
961 return;
963 if (!traffic_gauge.IsDefined())
964 traffic_gauge.Set(new GaugeFLARM(CommonInterface::GetLiveBlackboard(),
965 GetLook().flarm_gauge));
967 if (!traffic_gauge.IsVisible()) {
968 traffic_gauge.Show();
970 GaugeFLARM *widget = (GaugeFLARM *)traffic_gauge.Get();
971 widget->Raise();
973 } else
974 traffic_gauge.Hide();
977 const MapWindowProjection &
978 MainWindow::GetProjection() const
980 AssertThread();
981 assert(map != NULL);
983 return map->VisibleProjection();
986 void
987 MainWindow::ToggleSuppressFLARMRadar()
989 suppress_traffic_gauge = !suppress_traffic_gauge;
992 void
993 MainWindow::ToggleForceFLARMRadar()
995 force_traffic_gauge = !force_traffic_gauge;
996 CommonInterface::SetUISettings().traffic.enable_gauge = force_traffic_gauge;
999 #ifdef ANDROID
1001 void
1002 MainWindow::OnPause()
1004 if (!IsRunning() && HasDialog())
1005 /* suspending before initialization has finished doesn't leave
1006 anything worth resuming, so let's just quit now */
1007 CancelDialog();
1009 SingleWindow::OnPause();
1012 #endif /* ANDROID */