53#include <wx/stdpaths.h>
54#include <wx/tokenzr.h>
55#include <wx/display.h>
56#include <wx/jsonreader.h>
58#include "o_sound/o_sound.h"
83#include "model/nav_object_database.h"
97#include "ais_info_gui.h"
98#include "dialog_alert.h"
102#include "ais_info_gui.h"
126#include "load_errors_dlg.h"
129#include "N2KParser.h"
152#include "user_colors.h"
158#include "androidUTIL.h"
162static constexpr long kFrameStyle = wxDEFAULT_FRAME_STYLE | wxWANTS_CHARS;
173GLenum g_texture_rectangle_format;
176#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
177extern wxLocale *plocale_def_lang;
181extern bool g_b_EnableVBO;
182extern GLenum g_texture_rectangle_format;
186static int g_last_ChartScaleFactor;
187static char nmea_tick_chars[] = {
'|',
'/',
'-',
'\\',
'|',
'/',
'-',
'\\'};
188static int options_subpage = 0;
189static bool b_reloadForPlugins;
191static wxSize options_lastWindowSize(0, 0);
192static wxPoint options_lastWindowPos(0, 0);
196static double gQueryVar = 361.0;
198static char bells_sound_file_name[2][12] = {
"1bells.wav",
"2bells.wav"};
199static o_sound::Sound *_bells_sounds[] = {o_sound::Factory(),
201static std::vector<o_sound::Sound *> bells_sound(_bells_sounds,
207typedef DWORD(WINAPI *SetSysColors_t)(DWORD, DWORD *, DWORD *);
208typedef DWORD(WINAPI *GetSysColor_t)(DWORD);
210static SetSysColors_t pSetSysColors;
211static GetSysColor_t pGetSysColor;
213void SaveSystemColors();
214void RestoreSystemColors();
219DWORD color_3ddkshadow;
221DWORD color_activecaption;
222DWORD color_gradientactivecaption;
223DWORD color_captiontext;
224DWORD color_windowframe;
225DWORD color_inactiveborder;
230#include <wx/msw/msvcrt.h>
234static const long long lNaN = 0xfff8000000000000;
235#define NAN (*(double *)&lNaN)
239static double gLat_gt, gLon_gt;
240static double gLat_gt_m1, gLon_gt_m1;
241static uint64_t fix_time_gt;
242static uint64_t fix_time_gt_last;
244static double gSog_gt, gHdt_gt;
245static double gCog_gt_m1, gHdt_gt_m1;
246static uint64_t hdt_time_gt;
247static double cog_rate_gt, hdt_rate_gt;
249void InitializeUserColors();
250void DeInitializeUserColors();
251void SetSystemColors(ColorScheme cs);
253static bool LoadAllPlugIns(
bool load_enabled) {
254 AbstractPlatform::ShowBusySpinner();
255 bool b = PluginLoader::GetInstance()->
LoadAllPlugIns(load_enabled);
256 AbstractPlatform::HideBusySpinner();
260static void LaunchLocalHelp() {
262 androidLaunchHelpView();
264 wxString def_lang_canonical =
"en_US";
267 if (plocale_def_lang)
268 def_lang_canonical = plocale_def_lang->GetCanonicalName();
271 wxString help_locn = g_Platform->GetSharedDataDir() +
"doc/help_";
273 wxString help_try = help_locn + def_lang_canonical +
".html";
275 if (!::wxFileExists(help_try)) {
276 help_try = help_locn +
"en_US" +
".html";
278 if (!::wxFileExists(help_try)) {
279 help_try = help_locn +
"web" +
".html";
282 if (!::wxFileExists(help_try))
return;
285 wxLaunchDefaultBrowser(wxString(
"file:///") + help_try);
290static wxString _menuText(wxString name, wxString shortcut) {
294 menutext <<
"\t" << shortcut;
299static void DoHelpDialog() {
311 [] { LaunchLocalHelp(); });
323#if defined(__WXGTK__) || defined(__WXQT__)
324#include "bitmaps/opencpn.xpm"
339 if (g_bInlandEcdis) {
343 wxPoint tbp_incanvas =
346 g_iENCToolbarPosY = tbp_incanvas.y;
347 g_iENCToolbarPosX = tbp_incanvas.x;
355 wxPoint posn(g_iENCToolbarPosX, g_iENCToolbarPosY);
359 if ((g_iENCToolbarPosY > g_maintoolbar_y) &&
362 g_iENCToolbarPosY = -1;
365 if ((g_iENCToolbarPosX < 0) || (g_iENCToolbarPosY < 0)) {
371 wxPoint(g_maintoolbar_x +
g_MainToolbar->GetToolbarSize().x + 4,
375 double tool_scale_factor =
376 g_Platform->GetToolbarScaleFactor(g_GUIScaleFactor);
378 tool_scale_factor, callbacks);
388#if defined(__WXGTK__) && defined(OCPN_HAVE_X11)
391static char *get_X11_property(Display *disp, Window win, Atom xa_prop_type,
392 const char *prop_name) {
396 unsigned long ret_nitems;
397 unsigned long ret_bytes_after;
398 unsigned char *ret_prop;
400 xa_prop_name = XInternAtom(disp, prop_name, False);
408 if (XGetWindowProperty(disp, win, xa_prop_name, 0, 1024, False, xa_prop_type,
409 &xa_ret_type, &ret_format, &ret_nitems,
410 &ret_bytes_after, &ret_prop) != Success)
413 if (xa_ret_type != xa_prop_type) {
417 return (
char *)ret_prop;
422static bool isTransparentToolbarInOpenGLOK() {
429 if (!g_bdisable_opengl) {
430 Display *disp = XOpenDisplay(NULL);
432 if ((sup_window = (Window *)get_X11_property(disp, DefaultRootWindow(disp),
434 "_NET_SUPPORTING_WM_CHECK")) ||
435 (sup_window = (Window *)get_X11_property(disp, DefaultRootWindow(disp),
437 "_WIN_SUPPORTING_WM_CHECK"))) {
440 if ((wm_name = get_X11_property(disp, *sup_window,
441 XInternAtom(disp,
"UTF8_STRING", False),
443 (wm_name = get_X11_property(disp, *sup_window, XA_STRING,
446 if (strstr(wm_name,
"Xfwm4") || strstr(wm_name,
"Compiz"))
461wxFont *MyFrame::GetFont(wxFont *font,
double scale) {
463 font->GetFamily(), font->GetStyle(),
464 font->GetWeight(),
false, font->GetFaceName());
466wxFont *MyFrame::GetScaledFont(
int pointSize, wxFontFamily family,
467 wxFontStyle style, wxFontWeight weight,
468 const wxString faceName,
double scale) {
472wxFont *MyFrame::GetDefaultFont(wxString label,
int Ptsize) {
473 return GetOCPNScaledFont_PlugIn(label, Ptsize);
482wxDEFINE_EVENT(BELLS_PLAYED_EVTYPE, wxCommandEvent);
484BEGIN_EVENT_TABLE(
MyFrame, wxFrame)
485EVT_CLOSE(MyFrame::OnCloseWindow)
486EVT_MENU(wxID_EXIT, MyFrame::OnExit)
487EVT_SIZE(MyFrame::OnSize)
488EVT_MOVE(MyFrame::OnMove)
489EVT_ICONIZE(MyFrame::OnIconize)
490EVT_MENU(-1, MyFrame::OnToolLeftClick)
491EVT_TIMER(INIT_TIMER, MyFrame::OnInitTimer)
493EVT_TIMER(FRAME_TC_TIMER, MyFrame::OnFrameTCTimer)
494EVT_TIMER(FRAME_COG_TIMER, MyFrame::OnFrameCOGTimer)
495EVT_TIMER(MEMORY_FOOTPRINT_TIMER, MyFrame::OnMemFootTimer)
497EVT_MAXIMIZE(MyFrame::OnMaximize)
498EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED,
499 MyFrame::RequestNewToolbarArgEvent)
500EVT_ERASE_BACKGROUND(MyFrame::OnEraseBackground)
502EVT_TIMER(RECAPTURE_TIMER, MyFrame::OnRecaptureTimer)
503EVT_TIMER(TOOLBAR_ANIMATE_TIMER, MyFrame::OnToolbarAnimateTimer)
504EVT_COMMAND(wxID_ANY, BELLS_PLAYED_EVTYPE, MyFrame::OnBellsFinished)
506#ifdef wxHAS_POWER_EVENTS
507EVT_POWER_SUSPENDING(MyFrame::OnSuspending)
508EVT_POWER_SUSPENDED(MyFrame::OnSuspended)
509EVT_POWER_SUSPEND_CANCEL(MyFrame::OnSuspendCancel)
510EVT_POWER_RESUME(MyFrame::OnResume)
521static
void onBellsFinishedCB(
void *ptr) {
522 auto framePtr =
static_cast<MyFrame *
>(ptr);
524 wxCommandEvent ev(BELLS_PLAYED_EVTYPE);
525 wxPostEvent(framePtr, ev);
530 auto msg = ev.GetString().ToStdString();
531 auto ¬eman = NotificationManager::GetInstance();
532 noteman.AddNotification(NotificationSeverity::kInformational, msg, 60);
535static NmeaLog *GetDataMonitor() {
536 auto w = wxWindow::FindWindowByName(kDataMonitorWindowName);
537 return dynamic_cast<NmeaLog *
>(w);
540MyFrame::MyFrame(
const wxString &title,
const wxPoint &pos,
const wxSize &size,
541 RestServer &rest_server, wxAuiDefaultDockArt *pauidockart,
542 OpenFileFunc open_gpx_file)
544 m_connections_dlg(nullptr),
546 m_pauidockart(pauidockart),
547 m_rest_server(rest_server),
548 m_open_gpx_file(open_gpx_file) {
560 m_ulLastNMEATicktime = 0;
561 m_data_monitor->Hide();
563 m_StatusBarFieldCount = g_Platform->GetStatusBarFieldCount();
567 m_load_errors_dlg_ctrl = std::make_unique<LoadErrorsDlgCtrl>(
this);
570 InitTimer.SetOwner(
this, INIT_TIMER);
572 m_initializing =
false;
573 m_toolbar_callbacks.render_gl_textures =
575 [&](
ocpnDC &dc,
float *coords,
float *uv) {
576 GetPrimaryCanvas()->GetglCanvas()->RenderTextures(
577 dc, coords, uv, 4, &GetPrimaryCanvas()->GetVP());
580 [&](
ocpnDC &dc,
float *coords,
float *uv) {};
584 FrameTimer1.SetOwner(
this, FRAME_TIMER_1);
587 FrameTCTimer.SetOwner(
this, FRAME_TC_TIMER);
590 FrameCOGTimer.SetOwner(
this, FRAME_COG_TIMER);
593 MemFootTimer.SetOwner(
this, MEMORY_FOOTPRINT_TIMER);
596 ToolbarAnimateTimer.SetOwner(
this, TOOLBAR_ANIMATE_TIMER);
598 FrameTenHzTimer.SetOwner(
this, FRANE_TENHZ_TIMER);
607 m_bTimeIsSet =
false;
608 m_bdefer_resize =
false;
611 for (
int i = 0; i < kMaxCogsogFilterSeconds; i++) {
612 COGFilterTable[i] = NAN;
613 SOGFilterTable[i] = NAN;
615 m_last_bGPSValid =
false;
616 m_last_bVelocityValid =
false;
626 for (
int i = 0; i < kMaxCogAverageSeconds; i++) COGTable[i] = NAN;
631 double process_noise_std = 1.0;
632 double measurement_noise_std = 0.5;
636 m_ChartUpdatePeriod = 1;
641 log_callbacks.log_is_active = [&]() {
642 auto log = GetDataMonitor();
643 return log && log->IsVisible();
645 log_callbacks.log_message = [&](
Logline ll) {
646 NmeaLog *monitor = GetDataMonitor();
649 g_pMUX =
new Multiplexer(log_callbacks, g_b_legacy_input_filter_behaviour);
652 ais_callbacks.confirm_stop_track = []() {
653 int r = OCPNMessageBox(
655 _(
"This AIS target has Persistent tracking selected by MMSI "
657 "A Persistent track recording will therefore be restarted for this "
659 "Do you instead want to stop Persistent tracking for this target?"),
660 _(
"OpenCPN Info"), wxYES_NO | wxCENTER, 60);
661 return r == wxID_YES;
663 ais_callbacks.get_target_mmsi = []() {
664 auto alert_dlg_active =
666 assert(alert_dlg_active);
667 return alert_dlg_active->Get_Dialog_MMSI();
675 wxLogMessage(
" **** Connect stuff");
681 Connect(wxEVT_OCPN_MSG,
682 (wxObjectEventFunction)(wxEventFunction)&MyFrame::OnEvtPlugInMessage);
690 (wxObjectEventFunction)(wxEventFunction)&MyFrame::OnSENCEvtThread);
698#if defined(__WXGTK__) || defined(__WXQT__)
699 wxIcon app_icon(opencpn);
707 wxDynamicLibrary dllUser32(
"user32.dll");
709 pSetSysColors = (SetSysColors_t)dllUser32.GetSymbol(
"SetSysColors");
710 pGetSysColor = (GetSysColor_t)dllUser32.GetSymbol(
"GetSysColor");
715 m_next_available_plugin_tool_id = ID_PLUGIN_BASE;
720 m_resizeTimer.SetOwner(
this, RESIZE_TIMER);
721 m_recaptureTimer.SetOwner(
this, RECAPTURE_TIMER);
723 assert(
g_pRouteMan != 0 &&
"g_pRouteMan not available");
724 m_routes_update_listener.Init(GuiEvents::GetInstance().on_routes_update,
725 [&](wxCommandEvent) { Refresh(); });
726 m_evt_drv_msg_listener.Init(CommDriverRegistry::GetInstance().evt_driver_msg,
728 m_update_statusbar_listener.Init(
729 GuiEvents::GetInstance().gframe_update_status_bar,
731 m_center_aistarget_listener.Init(
732 GuiEvents::GetInstance().on_center_ais_target, [&](
ObservedEvt &ev) {
733 auto ais_target = obs::UnpackEvtPointer<AisTargetData>(ev);
734 CenterAisTarget(ais_target);
736 m_reload_charts_listener.Init(
737 GuiEvents::GetInstance().on_finalize_chartdbs,
738 [&](
ObservedEvt &ev) { FinalizeChartDBUpdate(); });
742 EnableFullScreenView();
744 int is_day = user_colors::GetColorScheme() == GLOBAL_COLOR_SCHEME_DAY ? 1 : 0;
750 FrameTenHzTimer.Stop();
765 (wxObjectEventFunction)(wxEventFunction)&MyFrame::OnEvtPlugInMessage);
771void MyFrame::FreezeCharts() {
774 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
776 if (cc && !cc->IsFrozen()) cc->Freeze();
780void MyFrame::CenterAisTarget(
781 const std::shared_ptr<const AisTargetData> &ais_target) {
789 double factor = cc->GetScaleValue() / 5000.0;
790 JumpToPosition(GetFocusCanvas(), ais_target->Lat, ais_target->Lon,
796void MyFrame::ThawCharts() {
799 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
801 if (cc && cc->IsFrozen()) cc->Thaw();
808 switch (event.type) {
809 case SENC_BUILD_STARTED:
812 case SENC_BUILD_DONE_NOERROR:
814 chart =
event.m_ticket->m_chart;
816 chart->PostInit(FULL_INIT, global_color_scheme);
818 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
820 if (cc) cc->ClearS52PLIBStateHash();
827 delete event.m_ticket;
829 case SENC_BUILD_DONE_ERROR:
830 wxLogDebug(
"SENC build done: SENC_BUILD_DONE_ERROR");
833 delete event.m_ticket;
840void MyFrame::StartRebuildChartDatabase() {
841 bool b_SetInitialPoint =
false;
844 ArrayOfCDI ChartDirArray;
845 pConfig->LoadChartDirArray(ChartDirArray);
847 if (ChartDirArray.GetCount()) {
852 _(
"OpenCPN needs to update the chart database from config file "
856 wxICON_INFORMATION | wxOK);
864 _(
"Rebuilding chart database from configuration file entries..."));
868 wxString dummy1 = _(
"Elapsed time : ");
869 wxString dummy2 = _(
"Estimated time : ");
870 wxString dummy3 = _(
"Remaining time : ");
871 wxGenericProgressDialog *pprog =
new wxGenericProgressDialog(
872 _(
"OpenCPN Chart Update"), line, 100, NULL, wxPD_SMOOTH);
880void MyFrame::OnBellsFinished(wxCommandEvent &event) {
881 int bells = wxMin(m_BellsToPlay, 2);
882 if (bells <= 0)
return;
884 wxString soundfile =
"sounds";
885 appendOSDirSlash(&soundfile);
886 soundfile += wxString(bells_sound_file_name[bells - 1], wxConvUTF8);
887 soundfile.Prepend(g_Platform->GetSharedDataDir());
888 wxLogMessage(
"Using bells sound file: " + soundfile);
890 o_sound::Sound *sound = bells_sound[bells - 1];
891 sound->SetFinishedCallback(onBellsFinishedCB,
this);
892 auto cmd_sound =
dynamic_cast<o_sound::SystemCmdSound *
>(sound);
893 if (cmd_sound) cmd_sound->SetCmd(g_CmdSoundString.mb_str(wxConvUTF8));
894 sound->Load(soundfile);
895 if (!sound->IsOk()) {
896 wxLogMessage(
"Failed to load bells sound file: " + soundfile);
900 m_BellsToPlay -= bells;
903void MyFrame::OnEraseBackground(wxEraseEvent &event) {}
905void MyFrame::OnMaximize(wxMaximizeEvent &event) {
912void MyFrame::ReloadAllVP() {
913 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
915 if (cc) cc->ReloadVP();
919void MyFrame::SetAndApplyColorScheme(ColorScheme cs) {
920 int is_day = cs == GLOBAL_COLOR_SCHEME_DAY ? 1 : 0;
923 global_color_scheme = cs;
926 case GLOBAL_COLOR_SCHEME_DAY:
929 case GLOBAL_COLOR_SCHEME_DUSK:
932 case GLOBAL_COLOR_SCHEME_NIGHT:
933 SchemeName =
"NIGHT";
940 m_pauidockart->SetMetric(wxAUI_DOCKART_GRADIENT_TYPE, wxAUI_GRADIENT_NONE);
942 m_pauidockart->SetColour(wxAUI_DOCKART_BORDER_COLOUR, wxColour(0, 0, 0));
943 m_pauidockart->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, 1);
944 m_pauidockart->SetColour(wxAUI_DOCKART_SASH_COLOUR, wxColour(0, 0, 0));
945 m_pauidockart->SetMetric(wxAUI_DOCKART_SASH_SIZE, 0);
946 m_pauidockart->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR,
948 m_pauidockart->SetColour(wxAUI_DOCKART_BACKGROUND_COLOUR, wxColour(0, 0, 0));
977 m_pauidockart->SetColour(wxAUI_DOCKART_SASH_COLOUR, wxColour(0, 0, 0));
978 m_pauidockart->SetMetric(wxAUI_DOCKART_SASH_SIZE, 6);
982 g_StyleManager->GetCurrentStyle()->SetColorScheme(cs);
984 if (ps52plib) ps52plib->SetPLIBColorScheme(SchemeName, ChartCtxFactory());
988 user_colors::GetMapByScheme(SchemeName.ToStdString());
993 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
996 cc->SetColorScheme(cs);
997 cc->GetWorldBackgroundChart()->SetColorScheme(cs);
998 cc->HideChartInfoWindow();
999 cc->SetQuiltChartHiLiteIndex(-1);
1005 .SetColorScheme(cs, g_Platform->GetDisplayDPmm());
1017 g_pRouteMan->SetColorScheme(cs, g_Platform->GetDisplayDPmm());
1030 if (g_pais_query_dialog_active) {
1031 bool b_isshown = g_pais_query_dialog_active->IsShown();
1032 int n_mmsi = g_pais_query_dialog_active->GetMMSI();
1033 if (b_isshown) g_pais_query_dialog_active->Show(
false);
1035 g_pais_query_dialog_active->Close();
1038 g_pais_query_dialog_active->
Create(
1039 this, -1, _(
"AIS Target Query"),
1040 wxPoint(g_ais_query_dialog_x, g_ais_query_dialog_y));
1041 g_pais_query_dialog_active->SetMMSI(n_mmsi);
1042 g_pais_query_dialog_active->UpdateText();
1043 if (b_isshown) g_pais_query_dialog_active->Show();
1048 if (g_pAISTargetList) g_pAISTargetList->SetColorScheme();
1052 ApplyGlobalColorSchemetoStatusBar();
1054 UpdateAllToolbars(cs);
1059 bool btoolbarFull = g_bmasterToolbarFull;
1065 if (!btoolbarFull) {
1067 RequestNewMasterToolbar();
1069 CollapseGlobalToolbar();
1072 RequestNewMasterToolbar();
1081void MyFrame::ApplyGlobalColorSchemetoStatusBar() {
1082 if (m_pStatusBar != NULL) {
1083 m_pStatusBar->SetBackgroundColour(GetGlobalColor(
"UIBDR"));
1084 m_pStatusBar->ClearBackground();
1095void MyFrame::CancelAllMouseRoute() {
1097 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1099 if (cc) cc->CancelMouseRoute();
1103void MyFrame::CreateCanvasLayout(
bool b_useStoredSize) {
1111 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1119 for (
unsigned int i = 1; i <
g_canvasArray.GetCount(); i++) {
1128 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
1131 for (
unsigned int i = 1; i < config_array.GetCount(); i++) {
1132 config_array.Item(i)->canvas = NULL;
1138 for (
unsigned int i = 1; i <
g_canvasArray.GetCount(); i++) {
1143 switch (g_canvasConfig) {
1157 if (!cc->GetglCanvas()) cc->SetupGlCanvas();
1158 cc->GetglCanvas()->Show();
1161 config_array.Item(0)->canvas = cc;
1165 cc->ApplyCanvasConfig(config_array.Item(0));
1169 cc->ConfigureChartBar();
1170 cc->SetColorScheme(global_color_scheme);
1171 cc->GetCompass()->SetScaleFactor(g_compass_scalefactor);
1172 cc->SetShowGPS(
true);
1175 g_pauimgr->GetPane(cc).Name(
"ChartCanvas");
1177 g_pauimgr->GetPane(cc).CaptionVisible(
false);
1193 if (!cc->GetglCanvas()) cc->SetupGlCanvas();
1196 config_array.Item(0)->canvas = cc;
1198 cc->ApplyCanvasConfig(config_array.Item(0));
1201 cc->ConfigureChartBar();
1202 cc->SetColorScheme(global_color_scheme);
1203 cc->GetCompass()->SetScaleFactor(g_compass_scalefactor);
1204 cc->SetShowGPS(
false);
1207 g_pauimgr->GetPane(cc).Name(
"ChartCanvas");
1209 .CaptionVisible(
false)
1211 .CloseButton(
false);
1220 if (config_array.GetCount() < 2) {
1222 pcc->configIndex = 1;
1226 pcc->
canvasSize = wxSize(GetClientSize().x / 2, GetClientSize().y);
1227 config_array.Add(pcc);
1230 config_array.Item(1)->canvas = cc;
1232 cc->ApplyCanvasConfig(config_array.Item(1));
1235 cc->ConfigureChartBar();
1236 cc->SetColorScheme(global_color_scheme);
1237 cc->SetShowGPS(
true);
1239 cc->SetShowGPSCompassWindow(
true);
1242 g_pauimgr->GetPane(cc).Name(
"ChartCanvas2");
1244 .CaptionVisible(
false)
1246 .CloseButton(
false);
1247 g_pauimgr->GetPane(cc).RightDockable(
true);
1251 config_array.Item(1)->canvasSize =
1252 wxSize(GetClientSize().x / 2, GetClientSize().y);
1253 g_pauimgr->GetPane(cc).BestSize(GetClientSize().x / 2, GetClientSize().y);
1258 if (b_useStoredSize) {
1259 int ccw = config_array.Item(1)->canvasSize.x;
1260 int cch = config_array.Item(1)->canvasSize.y;
1263 if (ccw < GetClientSize().x / 10) {
1264 ccw = GetClientSize().x / 2;
1265 cch = GetClientSize().y;
1268 g_pauimgr->GetPane(cc).BestSize(ccw, cch);
1269 cc->SetSize(ccw, cch);
1287 console->SetColorScheme(global_color_scheme);
1292 g_pRouteMan->GetDlgContext().show_with_fresh_fonts();
1298void MyFrame::RequestNewToolbars(
bool bforcenew) {
1299 if (b_inCloseWindow) {
1303 BuildiENCToolbar(bforcenew, m_toolbar_callbacks);
1304 PositionIENCToolbar();
1313void MyFrame::UpdateAllToolbars(ColorScheme cs) {
1319void MyFrame::SetAllToolbarScale() {
1320 g_toolbar_scalefactor = g_Platform->GetToolbarScaleFactor(g_GUIScaleFactor);
1323void MyFrame::SetGPSCompassScale() {
1324 g_compass_scalefactor = g_Platform->GetCompassScaleFactor(g_GUIScaleFactor);
1328 wxPoint screenPoint = ::wxGetMousePosition();
1331 switch (g_canvasConfig) {
1333 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1336 if (canvas->GetScreenRect().Contains(
1340 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(1);
1343 if (canvas->GetScreenRect().Contains(
1350 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1353 if (canvas->GetScreenRect().Contains(
1354 canvas->ScreenToClient(screenPoint)))
1362int MyFrame::GetCanvasIndexUnderMouse() {
1363 wxPoint screenPoint = ::wxGetMousePosition();
1366 switch (g_canvasConfig) {
1368 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1371 if (canvas->GetScreenRect().Contains(
1375 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(1);
1378 if (canvas->GetScreenRect().Contains(
1385 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1388 if (canvas->GetScreenRect().Contains(
1389 canvas->ScreenToClient(screenPoint)))
1397bool MyFrame::DropMarker(
bool atOwnShip) {
1404 if (!canvas)
return false;
1411 new RoutePoint(lat, lon, g_default_wp_icon, wxEmptyString, wxEmptyString);
1413 pSelect->AddSelectableRoutePoint(lat, lon, pWP);
1415 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
1426 RefreshAllCanvas(
false);
1431void MyFrame::SwitchKBFocusCanvas(
ChartCanvas *pCanvas) {
1432 if (g_canvasConfig != 0) {
1435 int nTargetGTK = -1;
1437 wxWindow *source = FindFocus();
1443 switch (g_canvasConfig) {
1445 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1448 if (canvas && (canvas == test)) {
1453 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(1);
1456 if (canvas && (canvas == test)) {
1464 int nfinalTarget = nTarget;
1466 nfinalTarget = nTargetGTK;
1468 target = ConfigMgr::Get()
1469 .GetCanvasConfigArray()
1474 target->Refresh(
true);
1485void MyFrame::FastClose() {
1487 FrameTenHzTimer.Stop();
1489 FrameTimer1.Start(1);
1493void MyFrame::OnExit(wxCommandEvent &event) {
1497void MyFrame::OnCloseWindow(wxCloseEvent &event) {
1500 if (b_inCloseWindow) {
1510 if (!g_bDeferredInitDone)
return;
1527 if (bDBUpdateInProgress)
return;
1529 b_inCloseWindow =
true;
1531 ::wxSetCursor(wxCURSOR_WAIT);
1535 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1537 if (cc && cc->IsMeasureActive()) {
1538 cc->CancelMeasureRoute();
1543 SendPreShutdownHookToPlugins();
1547 if (g_pAISTargetList) {
1548 wxAuiPaneInfo &pane =
g_pauimgr->GetPane(g_pAISTargetList);
1549 g_AisTargetList_perspective =
g_pauimgr->SavePaneInfo(pane);
1550 g_pauimgr->DetachPane(g_pAISTargetList);
1577 SetCursor(wxCURSOR_WAIT);
1579 RefreshAllCanvas(
true);
1585 RestoreScreenBrightness();
1596 wxPoint tbp_incanvas = GetPrimaryCanvas()->ScreenToClient(locn);
1597 g_iENCToolbarPosY = tbp_incanvas.y;
1598 g_iENCToolbarPosX = tbp_incanvas.x;
1602 g_bframemax = IsMaximized();
1605 FrameTenHzTimer.Stop();
1607 FrameCOGTimer.Stop();
1621 if (g_bAutoAnchorMark) {
1622 bool watching_anchor =
false;
1630 wxDateTime now = wxDateTime::Now();
1631 wxTimeSpan uptime = now.Subtract(g_start_time);
1633 if (!watching_anchor && (g_bCruising) && (
gSog < 0.5) &&
1634 (uptime.IsLongerThan(wxTimeSpan(0, 30, 0, 0))))
1639 if (g_declutter_anchorage) {
1640 for (
RoutePoint *pr : *pWayPointMan->GetWaypointList()) {
1641 if (pr->GetName().StartsWith(
"Anchorage")) {
1642 double a =
gLat - pr->m_lat;
1643 double b =
gLon - pr->m_lon;
1644 double l = sqrt((a * a) + (b * b));
1647 if ((l * 60. * 1852.) < (.25 * 1852.)) {
1649 NavObj_dB::GetInstance().DeleteRoutePoint(pr);
1650 pSelect->DeleteSelectablePoint(pr, SELTYPE_ROUTEPOINT);
1658 wxString name = now.Format();
1659 name.Prepend(_(
"Anchorage created "));
1665 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
1674 wxLogMessage(
"opencpn::MyFrame exiting cleanly.");
1678 NavObj_dB::GetInstance().Close();
1682 pConfig->DeleteGroup(
"/Routes");
1683 pConfig->DeleteGroup(
"/Marks");
1702 if (g_pAISTargetList) {
1703 g_pAISTargetList->Disconnect_decoder();
1704 g_pAISTargetList->Destroy();
1707 if (RouteManagerDialog::getInstanceFlag()) {
1724 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1726 if (cc) cc->Destroy();
1750 CommBridge::GetInstance().SaveConfig();
1770 auto ®istry = CommDriverRegistry::GetInstance();
1771 registry.CloseAllDrivers();
1774 for (
auto *cp : TheConnectionParams()) {
1779 while (pLayerList->size())
delete *pLayerList->begin();
1783 ReleaseApiListeners();
1786 g_bTempShowMenuBar =
false;
1788#define THREAD_WAIT_SECONDS 5
1798 wxLogMessage(
"Starting compressor pool drain");
1799 wxDateTime now = wxDateTime::Now();
1800 time_t stall = now.GetTicks();
1801 time_t end = stall + THREAD_WAIT_SECONDS;
1804 while (stall < end) {
1805 wxDateTime later = wxDateTime::Now();
1806 stall = later.GetTicks();
1809 msg.Printf(
"Time: %d Job Count: %d", n_comploop,
1818 fmsg.Printf(
"Finished compressor pool drain..Time: %d Job Count: %d",
1824 uninitIXNetSystem();
1832 wxLogMessage(
"gFrame destroyed.");
1835#ifndef USE_ANDROID_GLES2
1836 qDebug() <<
"Calling OnExit()";
1840 wxTheApp->ExitMainLoop();
1843void MyFrame::OnMove(wxMoveEvent &event) {
1844 auto idx = wxDisplay::GetFromWindow(
this);
1857 DEBUG_LOG <<
"Moved to " << idx
1858#if wxCHECK_VERSION(3, 1, 6)
1859 <<
" PPI: " << wxDisplay(idx).GetPPI().GetX() <<
"x"
1860 << wxDisplay(idx).GetPPI().GetY()
1861 <<
" SF wxDisplay: " << wxDisplay(idx).GetScaleFactor()
1863 <<
" Size wxDisplay: " << wxDisplay(idx).GetGeometry().GetWidth()
1864 <<
"x" << wxDisplay(idx).GetGeometry().GetHeight()
1865 <<
" MM wxDisplay: " << wxGetDisplaySizeMM().GetX() <<
"x"
1866 << wxGetDisplaySizeMM().GetY()
1867 <<
" Name wxDisplay: " << wxDisplay(idx).GetName().c_str()
1876 if (g_config_display_size_manual) {
1885 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1888 cc->SetMUIBarPosition();
1897 UpdateGPSCompassStatusBoxes();
1907 PositionIENCToolbar();
1913 g_nframewin_posx = GetPosition().x;
1914 g_nframewin_posy = GetPosition().y;
1917void MyFrame::ProcessCanvasResize() {
1918 UpdateGPSCompassStatusBoxes(
true);
1922 PositionIENCToolbar();
1925 TriggerRecaptureTimer();
1929void MyFrame::TriggerRecaptureTimer() {
1930 m_recaptureTimer.Start(
1931 1000, wxTIMER_ONE_SHOT);
1934void MyFrame::OnRecaptureTimer(wxTimerEvent &event) { }
1936void MyFrame::SetCanvasSizes(wxSize frameSize) {
1940 int cccw = frameSize.x;
1941 int ccch = frameSize.y;
1945 switch (g_canvasConfig) {
1951 cc->GetSize( &cur_width, &cur_height );
1952 if( ( cur_width != cccw ) || ( cur_height != ccch ) ) {
1954 g_pauimgr->GetPane( cc ).BestSize( cccw, ccch );
1956 cc->SetSize( 0, 0, cccw, ccch );
1966 int ccw = g_canvasConfigArray.Item(1)->canvasSize.x;
1967 int cch = g_canvasConfigArray.Item(1)->canvasSize.y;
1969 ccw = wxMin(ccw, cccw * 8 / 10);
1970 ccw = wxMax(ccw, cccw * 2 / 10);
1974 g_canvasConfigArray.Item(1)->canvasSize = wxSize(ccw, cch);
1981 g_pauimgr->GetPane(cc).MinSize(ccw, cch);
1998void MyFrame::OnIconize(wxIconizeEvent &event) {
2008 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2010 if (cc && cc->GetMUIBar()) {
2011 if (cc->GetMUIBar()->GetCanvasOptions()) {
2012 if (cc->GetMUIBar()->GetCanvasOptions()->IsShown()) {
2013 cc->GetMUIBar()->PushCanvasOptions();
2022void MyFrame::OnSize(wxSizeEvent &event) { ODoSetSize(); }
2024void MyFrame::ODoSetSize() {
2026 GetClientSize(&x, &y);
2029 if (m_pStatusBar != NULL) {
2030 m_StatusBarFieldCount = g_Platform->GetStatusBarFieldCount();
2031 int currentCount = m_pStatusBar->GetFieldsCount();
2032 if (currentCount != m_StatusBarFieldCount) {
2033 if ((currentCount > 0) && (currentCount < 7)) {
2036 int widths[] = {2, 2, 2, 2, 2, 2};
2037 m_pStatusBar->SetStatusWidths(currentCount, widths);
2040 m_pStatusBar->SetFieldsCount(m_StatusBarFieldCount);
2043 if (m_StatusBarFieldCount) {
2048 if (m_StatusBarFieldCount > 2) {
2049 int widths[] = {-6, -5, -5, -6, -4};
2050 m_pStatusBar->SetStatusWidths(m_StatusBarFieldCount, widths);
2051 }
else if (m_StatusBarFieldCount == 2) {
2052 int cwidth = x * 90 / 100;
2053 int widths[] = {100, 100};
2054 widths[0] = cwidth * 6.4 / 10.0;
2055 widths[1] = cwidth * 3.6 / 10.0;
2056 m_pStatusBar->SetStatusWidths(m_StatusBarFieldCount, widths);
2058 int widths[] = {100, 100};
2059 widths[0] = x * 90 / 100;
2060 m_pStatusBar->SetStatusWidths(m_StatusBarFieldCount, widths);
2063 int styles[] = {wxSB_FLAT, wxSB_FLAT, wxSB_FLAT,
2064 wxSB_FLAT, wxSB_FLAT, wxSB_FLAT};
2065 m_pStatusBar->SetStatusStyles(m_StatusBarFieldCount, styles);
2067 wxString sogcog(
"SOG --- " + getUsrSpeedUnit() + +
" " +
2069 m_pStatusBar->SetStatusText(sogcog, STAT_FIELD_SOGCOG);
2077 m_pStatusBar->GetFieldRect(0, stat_box);
2080 int max_font_size = wxMin((stat_box.width / 28), (stat_box.height));
2082 wxFont sys_font = *wxNORMAL_FONT;
2083 int try_font_size = sys_font.GetPointSize();
2086 int min_font_size = 10;
2096 wxFont *statusBarFont =
2097 FontMgr::Get().
GetFont(_(
"StatusBar"), try_font_size);
2098 int font_size = statusBarFont->GetPointSize();
2100 font_size = wxMin(font_size,
2103 wxMax(font_size, min_font_size);
2106 font_size = statusBarFont->GetPointSize();
2113 font_size, statusBarFont->GetFamily(), statusBarFont->GetStyle(),
2114 statusBarFont->GetWeight(),
false, statusBarFont->GetFaceName());
2116 int min_height = stat_box.height;
2118 m_pStatusBar->SetFont(*pstat_font);
2119 m_pStatusBar->SetForegroundColour(
2120 FontMgr::Get().GetFontColor(_(
"StatusBar")));
2122 min_height = (pstat_font->GetPointSize() * getAndroidDisplayDensity()) + 10;
2124 (min_height >> 1) * 2;
2125 m_pStatusBar->SetMinHeight(min_height);
2134 SetCanvasSizes(GetClientSize());
2136 UpdateGPSCompassStatusBoxes(
true);
2138 if (
console) PositionConsole();
2141 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2143 if (cc) cc->FormatPianoKeys();
2149 g_MainToolbar->SetGeometry(GetPrimaryCanvas()->GetCompass()->IsShown(),
2150 GetPrimaryCanvas()->GetCompass()->GetRect());
2176 options_lastWindowSize = wxSize(0, 0);
2177 options_lastWindowPos = wxPoint(0, 0);
2184 if (!b_inCloseWindow) {
2187 resizeAndroidPersistents();
2191 if (GetPrimaryCanvas() && GetPrimaryCanvas()->GetNotificationsList()) {
2192 GetPrimaryCanvas()->GetNotificationsList()->RecalculateSize();
2198void MyFrame::PositionConsole() {
2199#if defined(__WXMSW__) || defined(__WXMAC__)
2200 if (NULL == GetPrimaryCanvas())
return;
2202 int ccx, ccy, ccsx, ccsy, consx, consy;
2207 consoleHost->GetSize(&ccsx, &ccsy);
2208 consoleHost->GetPosition(&ccx, &ccy);
2210 GetPrimaryCanvas()->GetSize(&ccsx, &ccsy);
2211 GetPrimaryCanvas()->GetPosition(&ccx, &ccy);
2212 consoleHost = GetPrimaryCanvas();
2217 if (consoleHost->GetCompass()) {
2218 wxRect compass_rect = consoleHost->GetCompass()->
GetRect();
2220 if (compass_rect.y < 100)
2221 yOffset = compass_rect.y + compass_rect.height + 45;
2225 wxSize csz =
console->GetSize();
2229 wxPoint screen_pos =
2230 ClientToScreen(wxPoint(ccx + ccsx - consx - 2, ccy + yOffset));
2233 if (NULL == GetPrimaryCanvas())
return;
2235 int ccx, ccy, ccsx, ccsy, consx, consy;
2240 consoleHost->GetSize(&ccsx, &ccsy);
2241 consoleHost->GetPosition(&ccx, &ccy);
2243 GetPrimaryCanvas()->GetSize(&ccsx, &ccsy);
2244 GetPrimaryCanvas()->GetPosition(&ccx, &ccy);
2245 consoleHost = GetPrimaryCanvas();
2248 int yTopOffset = 60;
2249 int yBottomOffset = 0;
2251 if (consoleHost->GetCompass()) {
2252 wxRect compass_rect = consoleHost->GetCompass()->
GetRect();
2254 if (compass_rect.y < 100)
2255 yTopOffset = compass_rect.y + compass_rect.height;
2257 if (consoleHost->GetMUIBar()) {
2258 wxRect mui_rect = consoleHost->GetMUIBarRect();
2259 yBottomOffset = ccsy - mui_rect.y;
2263 wxSize csz =
console->GetSize();
2266 int yAvail = ccsy - (yTopOffset + yBottomOffset);
2268 if (consy < yAvail) {
2269 yFinal = (yAvail - consy) / 2;
2270 yFinal += yTopOffset;
2271 }
else if (
console->GetCDI()->IsShown()) {
2272 int cdi_height =
console->GetCDI()->GetSize().y;
2273 int consy_no_cdi = consy - cdi_height;
2274 yFinal = (yAvail - consy_no_cdi) / 2;
2275 yFinal += yTopOffset;
2279 wxPoint in_canvas_pos = wxPoint(ccsx - consx - 2, yFinal);
2284void MyFrame::UpdateAllFonts() {
2293 DestroyPersistentDialogs();
2295 if (pWayPointMan) pWayPointMan->ClearRoutePointFonts();
2300void MyFrame::DestroyPersistentDialogs() {
2301 if (g_pais_query_dialog_active) {
2302 g_pais_query_dialog_active->Hide();
2303 g_pais_query_dialog_active->Destroy();
2304 g_pais_query_dialog_active = NULL;
2332void MyFrame::RefreshGroupIndices() {
2334 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2336 if (cc) cc->canvasRefreshGroupIndex();
2340bool MyFrame::DisableTbarTooltips() {
2345 wxLogWarning(
"Global g_MainToolbar has not been created.");
2349void MyFrame::EnableTbarTooltips() {
2355void MyFrame::HideTbarTooltip() {
2361void MyFrame::OnToolLeftClick(wxCommandEvent &event) {
2363 switch (event.GetId()) {
2364 case ID_MENU_SCALE_OUT:
2365 DoStackDelta(GetPrimaryCanvas(), 1);
2369 case ID_MENU_SCALE_IN:
2370 DoStackDelta(GetPrimaryCanvas(), -1);
2374 case ID_MENU_ZOOM_IN: {
2375 if (GetFocusCanvas()) {
2376 GetFocusCanvas()->
ZoomCanvas(g_plus_minus_zoom_factor,
false);
2381 case ID_MENU_ZOOM_OUT: {
2382 if (GetFocusCanvas()) {
2383 GetFocusCanvas()->
ZoomCanvas(1.0 / g_plus_minus_zoom_factor,
false);
2388 case ID_MENU_ROUTE_NEW: {
2389 if (GetFocusCanvas()) {
2390 if (0 == GetFocusCanvas()->m_routeState) {
2391 GetFocusCanvas()->StartRoute();
2393 GetFocusCanvas()->FinishRoute();
2399 case ID_MENU_TOOL_MEASURE: {
2400 GetPrimaryCanvas()->StartMeasureRoute();
2404 case ID_MENU_TOOL_NMEA_DBG_LOG:
2405 m_data_monitor->Show();
2406 m_data_monitor->Raise();
2409 case ID_MENU_TOOL_IO_MONITOR:
2410 m_data_monitor->Show();
2413 case ID_MENU_MARK_BOAT: {
2418 case ID_MENU_MARK_CURSOR: {
2423 case ID_MENU_NAV_FOLLOW: {
2424 if (
gFrame->GetPrimaryCanvas())
2425 gFrame->GetPrimaryCanvas()->TogglebFollow();
2429 case ID_MENU_CHART_OUTLINES: {
2430 ToggleChartOutlines(GetFocusCanvas());
2434 case ID_MENU_CHART_QUILTING: {
2435 ToggleQuiltMode(GetFocusCanvas());
2439 case ID_MENU_UI_CHARTBAR: {
2440 ToggleChartBar(GetFocusCanvas());
2444 case ID_MENU_ENC_TEXT:
2446 ToggleENCText(GetFocusCanvas());
2449 case ID_MENU_ENC_LIGHTS: {
2450 ToggleLights(GetFocusCanvas());
2453 case ID_MENU_ENC_SOUNDINGS: {
2454 ToggleSoundings(GetFocusCanvas());
2457 case ID_MENU_ENC_ANCHOR: {
2458 ToggleAnchor(GetFocusCanvas());
2461 case ID_MENU_ENC_DATA_QUALITY: {
2462 ToggleDataQuality(GetFocusCanvas());
2465 case ID_MENU_SHOW_NAVOBJECTS: {
2466 ToggleNavobjects(GetFocusCanvas());
2470 case ID_MENU_AIS_TARGETS: {
2471 ToggleAISDisplay(GetFocusCanvas());
2474 case ID_MENU_AIS_MOORED_TARGETS: {
2475 g_bHideMoored = !g_bHideMoored;
2478 case ID_MENU_AIS_SCALED_TARGETS: {
2479 ToggleAISMinimizeTargets(GetFocusCanvas());
2483 case ID_MENU_AIS_TARGETLIST: {
2484 if (GetPrimaryCanvas()) GetPrimaryCanvas()->ShowAISTargetList();
2488 case ID_MENU_AIS_TRACKS: {
2489 g_bAISShowTracks = !g_bAISShowTracks;
2490 SetMenubarItemState(ID_MENU_AIS_TRACKS, g_bAISShowTracks);
2494 case ID_MENU_AIS_CPADIALOG: {
2495 g_bAIS_CPA_Alert = !g_bAIS_CPA_Alert;
2496 SetMenubarItemState(ID_MENU_AIS_CPADIALOG, g_bAIS_CPA_Alert);
2497 m_pMenuBar->Enable(ID_MENU_AIS_CPASOUND, g_bAIS_CPA_Alert);
2498 if (g_bAIS_CPA_Alert) {
2499 SetMenubarItemState(ID_MENU_AIS_CPASOUND, g_bAIS_CPA_Alert_Audio);
2504 case ID_MENU_AIS_CPASOUND: {
2505 g_bAIS_CPA_Alert_Audio = !g_bAIS_CPA_Alert_Audio;
2506 SetMenubarItemState(ID_MENU_AIS_CPASOUND, g_bAIS_CPA_Alert_Audio);
2510 case ID_MENU_AIS_CPAWARNING: {
2511 if (GetPrimaryCanvas()) GetPrimaryCanvas()->ToggleCPAWarn();
2512 SetMenubarItemState(ID_MENU_AIS_CPAWARNING, g_bCPAWarn);
2516 case wxID_PREFERENCES:
2523 case ID_SETTINGS_NEW: {
2528 case ID_SETTINGS_DELETE: {
2531 g_pOptions =
nullptr;
2535 case ID_RELOAD_CHARTS: {
2540 case ID_MENU_SETTINGS_BASIC: {
2542 androidDisableFullScreen();
2544 DoAndroidPreferences();
2551 case ID_MENU_UI_FULLSCREEN: {
2556 case ID_MENU_SHOW_CURRENTS: {
2557 GetFocusCanvas()->ShowCurrents(!GetFocusCanvas()->GetbShowCurrent());
2558 GetFocusCanvas()->ReloadVP();
2559 GetFocusCanvas()->Refresh(
false);
2563 case ID_MENU_SHOW_TIDES: {
2564 GetFocusCanvas()->ShowTides(!GetFocusCanvas()->GetbShowTide());
2565 GetFocusCanvas()->ReloadVP();
2566 GetFocusCanvas()->Refresh(
false);
2586 case ID_MENU_UI_COLSCHEME:
2587 case ID_COLSCHEME: {
2588 ToggleColorScheme();
2597 case ID_MENU_OQUIT: {
2602 case ID_MENU_ROUTE_MANAGER:
2603 case ID_ROUTEMANAGER: {
2626 case ID_MENU_NAV_TRACK:
2628 if (!g_bTrackActive) {
2630 g_bTrackCarryOver =
true;
2633 g_bTrackCarryOver =
false;
2634 RefreshAllCanvas(
true);
2639 case ID_MENU_CHART_NORTHUP: {
2640 SetUpMode(GetPrimaryCanvas(), NORTH_UP_MODE);
2643 case ID_MENU_CHART_COGUP: {
2644 SetUpMode(GetPrimaryCanvas(), COURSE_UP_MODE);
2647 case ID_MENU_CHART_HEADUP: {
2648 SetUpMode(GetPrimaryCanvas(), HEAD_UP_MODE);
2652 case ID_MENU_MARK_MOB:
2658 case ID_MASTERTOGGLE: {
2660 wxString tip = _(
"Show Toolbar");
2661 if (!g_bmasterToolbarFull) tip = _(
"Hide Toolbar");
2663 g_MainToolbar->GetToolbar()->SetToolShortHelp(ID_MASTERTOGGLE, tip);
2665 g_bmasterToolbarFull = !g_bmasterToolbarFull;
2668 if (g_bmasterToolbarFull)
2669 m_nMasterToolCountShown =
2673 m_nMasterToolCountShown = 2;
2675 m_nMasterToolCountShown =
2678 ToolbarAnimateTimer.Start(10, wxTIMER_ONE_SHOT);
2686 case ID_CMD_SELECT_CHART_TYPE: {
2687 selectChartDisplay(event.GetExtraLong(), -1);
2691 case ID_CMD_SELECT_CHART_FAMILY: {
2692 selectChartDisplay(-1, event.GetExtraLong());
2696 case ID_CMD_APPLY_SETTINGS: {
2697 applySettingsString(event.GetString());
2699 androidRestoreFullScreen();
2705 case ID_CMD_NULL_REFRESH: {
2710 case ID_CMD_SETVP: {
2711 setStringVP(event.GetString());
2715 case ID_CMD_INVALIDATE: {
2721 case ID_CMD_POST_JSON_TO_PLUGINS: {
2724 nlohmann::json root;
2726 root = nlohmann::json::parse(event.GetString().ToStdString());
2727 if (root[
"MessageID"].is_string()) {
2728 std::string msg_id = root[
"MessageID"].get<std::string>();
2731 }
catch (nlohmann::json::exception &) {
2753 ArrayOfPlugInToolbarTools tool_array =
2755 for (
unsigned int i = 0; i < tool_array.size(); i++) {
2757 if (event.GetId() == pttc->id) {
2758 if (pttc->m_pplugin)
2780bool MyFrame::SetGlobalToolbarViz(
bool viz) {
2781 bool viz_now = g_bmasterToolbarFull;
2784 wxString tip = _(
"Show Toolbar");
2786 tip = _(
"Hide Toolbar");
2788 g_MainToolbar->GetToolbar()->SetToolShortHelp(ID_MASTERTOGGLE, tip);
2791 bool toggle =
false;
2792 if (viz && !g_bmasterToolbarFull)
2795 else if (!viz && g_bmasterToolbarFull)
2799 g_bmasterToolbarFull = !g_bmasterToolbarFull;
2802 if (g_bmasterToolbarFull)
2803 m_nMasterToolCountShown =
2807 m_nMasterToolCountShown = 2;
2809 m_nMasterToolCountShown =
2812 ToolbarAnimateTimer.Start(10, wxTIMER_ONE_SHOT);
2818void MyFrame::ScheduleReloadCharts() {
2819 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED);
2820 evt.SetId(ID_RELOAD_CHARTS);
2821 GetEventHandler()->AddPendingEvent(evt);
2824void MyFrame::ScheduleDeleteSettingsDialog() {
2825 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED);
2826 evt.SetId(ID_SETTINGS_DELETE);
2827 GetEventHandler()->AddPendingEvent(evt);
2830void MyFrame::ScheduleSettingsDialog() {
2831 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED);
2832 evt.SetId(ID_SETTINGS);
2833 GetEventHandler()->AddPendingEvent(evt);
2836void MyFrame::ScheduleSettingsDialogNew() {
2837 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED);
2838 evt.SetId(ID_SETTINGS_NEW);
2839 GetEventHandler()->AddPendingEvent(evt);
2842void MyFrame::ScheduleReconfigAndSettingsReload(
bool reload,
bool new_dialog) {
2843 UpdateCanvasConfigDescriptors();
2845 if ((g_canvasConfig > 0) && (last_canvasConfig == 0))
2846 CreateCanvasLayout(
true);
2848 CreateCanvasLayout();
2852 ConfigureStatusBar();
2853 wxSize lastOptSize = options_lastWindowSize;
2858 options_lastWindowSize = lastOptSize;
2862 ScheduleSettingsDialogNew();
2864 ScheduleSettingsDialog();
2869 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2872 int index_hint = -1;
2873 if (i < pathArray.GetCount())
2874 index_hint =
ChartData->FinddbIndex(pathArray.Item(i));
2875 cc->canvasChartsRefresh(index_hint);
2876 if (index_hint != -1) cc->
SetVPScale(restoreScale[i]);
2885 return GetPrimaryCanvas();
2888void MyFrame::OnToolbarAnimateTimer(wxTimerEvent &event) {
2890 if (g_bmasterToolbarFull) {
2891#ifndef OCPN_TOOLBAR_ANIMATE
2892 m_nMasterToolCountShown = (int)
g_MainToolbar->GetToolCount();
2895 if (m_nMasterToolCountShown < (
int)
g_MainToolbar->GetToolCount()) {
2896 m_nMasterToolCountShown++;
2901 ToolbarAnimateTimer.Start(20, wxTIMER_ONE_SHOT);
2909#ifndef OCPN_TOOLBAR_ANIMATE
2910 m_nMasterToolCountShown = 1;
2912 if (m_nMasterToolCountShown > 1) {
2913 m_nMasterToolCountShown--;
2917 ToolbarAnimateTimer.Start(10, wxTIMER_ONE_SHOT);
2927void MyFrame::InvalidateAllGL() {
2930 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2940void MyFrame::RefreshAllCanvas(
bool bErase) {
2942 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2945 cc->Refresh(bErase);
2950void MyFrame::setStringVP(wxString VPS) {
2955 wxStringTokenizer tkz(VPS,
";");
2957 wxString token = tkz.GetNextToken();
2959 token.ToDouble(&lat);
2961 token = tkz.GetNextToken();
2963 token.ToDouble(&lon);
2965 token = tkz.GetNextToken();
2967 token.ToDouble(&scale_ppm);
2969 cc->
SetViewPoint(lat, lon, scale_ppm, 0, cc->GetVPRotation());
2972void MyFrame::DoSettingsNew() {
2979void MyFrame::DoSettings() {
2984 ApplyGlobalSettings(
true);
2987 bool b_loadHarmonics =
false;
2988 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2991 if (cc->GetbShowCurrent() || cc->GetbShowTide()) b_loadHarmonics =
true;
2994 if (b_loadHarmonics) LoadHarmonics();
3002 g_bShowChartBar = !g_bShowChartBar;
3004 if (g_bShowChartBar) cc->m_brepaint_piano =
true;
3009 if (g_bShowChartBar) {
3011 UpdateControlBar(cc);
3014 SetMenubarItemState(ID_MENU_UI_CHARTBAR, g_bShowChartBar);
3017void MyFrame::ToggleColorScheme() {
3018 static bool lastIsNight;
3019 ColorScheme s = user_colors::GetColorScheme();
3022 if (lastIsNight && is == 3)
3025 lastIsNight =
false;
3027 if (lastIsNight) is = 2;
3028 if (is == 3) lastIsNight =
true;
3029 s = (ColorScheme)is;
3030 if (s == N_COLOR_SCHEMES) s = GLOBAL_COLOR_SCHEME_RGB;
3032 SetAndApplyColorScheme(s);
3035void MyFrame::ToggleFullScreen() {
3036 bool to = !IsFullScreen();
3041 long style = wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION;
3043 ShowFullScreen(to, style);
3046 UpdateAllToolbars(global_color_scheme);
3048 UpdateControlBar(GetPrimaryCanvas());
3050 TriggerRecaptureTimer();
3053void MyFrame::ActivateMOB() {
3055 wxDateTime mob_time = wxDateTime::Now();
3056 wxString mob_label(_(
"MAN OVERBOARD"));
3057 mob_label += _(
" on ");
3058 mob_label += ocpn::toUsrDateTimeFormat(mob_time);
3062 pWP_MOB->SetShared(
true);
3064 pWP_MOB->SetWaypointArrivalRadius(
3066 pWP_MOB->SetUseSca(
false);
3068 NavObj_dB::GetInstance().InsertRoutePoint(pWP_MOB);
3076 new RoutePoint(zlat, zlon, g_default_wp_icon,
3077 wxString(_(
"1.0 NM along COG")), wxEmptyString);
3078 pSelect->AddSelectableRoutePoint(zlat, zlon, pWP_src);
3083 temp_route->AddPoint(pWP_src);
3084 temp_route->AddPoint(pWP_MOB);
3086 pSelect->AddSelectableRouteSegment(
gLat,
gLon, zlat, zlon, pWP_src, pWP_MOB,
3096 temp_route->SetRouteArrivalRadius(-1.0);
3102 v[
"GUID"] = temp_route->
m_GUID;
3103 SendJsonMessageToAllPlugins(
"OCPN_MAN_OVERBOARD", v);
3106 if (RouteManagerDialog::getInstanceFlag()) {
3114 RefreshAllCanvas(
false);
3116 wxString mob_message(_(
"MAN OVERBOARD"));
3117 mob_message += _(
" Time: ");
3118 mob_message += ocpn::toUsrDateTimeFormat(mob_time);
3119 mob_message += _(
" Position: ");
3120 mob_message += toSDMM(1,
gLat);
3122 mob_message += toSDMM(2,
gLon);
3123 wxLogMessage(mob_message);
3125void MyFrame::TrackOn() {
3126 g_bTrackActive =
true;
3134 SetMasterToolbarItemState(ID_TRACK, g_bTrackActive);
3136 g_MainToolbar->SetToolShortHelp(ID_TRACK, _(
"Disable Tracking"));
3138 SetMenubarItemState(ID_MENU_NAV_TRACK, g_bTrackActive);
3141 androidSetTrackTool(
true);
3144 if (RouteManagerDialog::getInstanceFlag()) {
3153 if (name.IsEmpty()) {
3159 name = _(
"(Unnamed Track)");
3163 SendJsonMessageToAllPlugins(
"OCPN_TRK_ACTIVATED", v);
3165 g_FlushNavobjChangesTimeout = 30;
3168Track *MyFrame::TrackOff(
bool do_add_point) {
3174 SendJsonMessageToAllPlugins(
"OCPN_TRK_DEACTIVATED", v);
3183 if (g_bTrackDaily) {
3188 NavObj_dB::GetInstance().UpdateTrack(pExtendTrack);
3189 return_val = pExtendTrack;
3196 g_bTrackActive =
false;
3198 if (RouteManagerDialog::getInstanceFlag()) {
3205 SetMasterToolbarItemState(ID_TRACK, g_bTrackActive);
3207 g_MainToolbar->SetToolShortHelp(ID_TRACK, _(
"Enable Tracking"));
3208 SetMenubarItemState(ID_MENU_NAV_TRACK, g_bTrackActive);
3211 androidSetTrackTool(
false);
3215 m_target_rotate_time = wxInvalidDateTime;
3220void MyFrame::InitializeTrackRestart() {
3221 if (!g_bTrackDaily)
return;
3222 if (m_target_rotate_time.IsValid())
return;
3225 switch (g_track_rotate_time_type) {
3227 rotate_at = g_track_rotate_time + wxRound(
gLon * 3600. / 15.);
3229 case TIME_TYPE_COMPUTER:
3230 rotate_at = g_track_rotate_time;
3234 wxDateTime::Now().GetTicks() - wxDateTime::Now().ToUTC().GetTicks();
3235 rotate_at = g_track_rotate_time + utc_offset;
3238 if (rotate_at > 86400)
3240 else if (rotate_at < 0)
3243 wxTimeSpan rotate_seconds = wxTimeSpan(0, 0, rotate_at);
3244 m_target_rotate_time = wxDateTime::Today() + rotate_seconds;
3247 if (wxDateTime::Now().IsLaterThan(m_target_rotate_time)) {
3248 m_target_rotate_time += wxTimeSpan(24);
3252bool MyFrame::ShouldRestartTrack() {
3254 InitializeTrackRestart();
3256 if (wxDateTime::Now().IsLaterThan(m_target_rotate_time)) {
3257 m_target_rotate_time += wxTimeSpan(24);
3263void MyFrame::TrackDailyRestart() {
3265 Track *pPreviousTrack = TrackOff(
true);
3272 if (pPreviousTrack) {
3273 TrackPoint *pMidnightPoint = pPreviousTrack->GetLastPoint();
3277 if (RouteManagerDialog::getInstanceFlag()) {
3285void MyFrame::SetUpMode(
ChartCanvas *cc,
int mode) {
3287 cc->SetUpMode(mode);
3289 SetMenubarItemState(ID_MENU_CHART_COGUP, mode == COURSE_UP_MODE);
3290 SetMenubarItemState(ID_MENU_CHART_NORTHUP, mode == NORTH_UP_MODE);
3291 SetMenubarItemState(ID_MENU_CHART_HEADUP, mode == HEAD_UP_MODE);
3294 m_pMenuBar->SetLabel(ID_MENU_CHART_NORTHUP, _(
"North Up Mode"));
3299 cc->SetShowENCText(!cc->GetShowENCText());
3301 SetMenubarItemState(ID_MENU_ENC_TEXT, cc->GetShowENCText());
3309void MyFrame::SetENCDisplayCategory(
ChartCanvas *cc,
enum _DisCat nset) {
3312 cc->SetENCDisplayCategory(nset);
3314 UpdateGlobalMenuItems();
3325 cc->SetShowENCDepth(!cc->GetShowENCDepth());
3327 SetMenubarItemState(ID_MENU_ENC_SOUNDINGS, cc->GetShowENCDepth());
3336 cc->SetShowENCLights(!cc->GetShowENCLights());
3338 SetMenubarItemState(ID_MENU_ENC_LIGHTS, cc->GetShowENCLights());
3348void MyFrame::ToggleRocks(
void )
3354 for(
unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount(); iPtr++ ) {
3355 OBJLElement *pOLE = (OBJLElement *) ( ps52plib->pOBJLArray->Item( iPtr ) );
3356 if( !strncmp( pOLE->OBJLName,
"UWTROC", 6 ) ) {
3357 pOLE->nViz = !pOLE->nViz;
3361 for(
unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount(); iPtr++ ) {
3362 OBJLElement *pOLE = (OBJLElement *) ( ps52plib->pOBJLArray->Item( iPtr ) );
3363 if( !strncmp( pOLE->OBJLName,
"OBSTRN", 6 ) ) {
3366 if( !strncmp( pOLE->OBJLName,
"WRECKS", 6 ) ) {
3370 ps52plib->GenerateStateHash();
3377 cc->SetShowENCAnchor(!cc->GetShowENCAnchor());
3379 SetMenubarItemState(ID_MENU_ENC_ANCHOR, cc->GetShowENCAnchor());
3387 cc->SetShowENCDataQual(!cc->GetShowENCDataQual());
3389 SetMenubarItemState(ID_MENU_ENC_DATA_QUALITY, cc->GetShowENCDataQual());
3404 cc->m_bShowNavobjects = !cc->m_bShowNavobjects;
3405 SetMenubarItemState(ID_MENU_SHOW_NAVOBJECTS, cc->m_bShowNavobjects);
3410 cc->SetShowAIS(!cc->GetShowAIS());
3411 SetMenubarItemState(ID_MENU_AIS_TARGETS, cc->GetShowAIS());
3415void MyFrame::ToggleAISMinimizeTargets(
ChartCanvas *cc) {
3416 cc->SetAttenAIS(!cc->GetAttenAIS());
3417 SetMenubarItemState(ID_MENU_AIS_SCALED_TARGETS, cc->GetAttenAIS());
3423 cc->m_bFollow =
true;
3426 SetMenubarItemState(ID_MENU_NAV_FOLLOW,
true);
3430 SetChartUpdatePeriod();
3438 cc->m_bFollow =
false;
3440 SetMenubarItemState(ID_MENU_NAV_FOLLOW,
false);
3444 SetChartUpdatePeriod();
3447void MyFrame::ToggleChartOutlines(
ChartCanvas *cc) {
3448 cc->SetShowOutlines(!cc->GetShowOutlines());
3450 RefreshAllCanvas(
false);
3454 if (g_bopengl) InvalidateAllGL();
3457 SetMenubarItemState(ID_MENU_CHART_OUTLINES, cc->GetShowOutlines());
3460void MyFrame::ToggleTestPause() { g_bPauseTest = !g_bPauseTest; }
3462void MyFrame::SetMenubarItemState(
int item_id,
bool state) {
3464 bool enabled = m_pMenuBar->IsEnabled(item_id);
3465 m_pMenuBar->Enable(item_id,
false);
3466 m_pMenuBar->Check(item_id, state);
3467 m_pMenuBar->Enable(item_id, enabled);
3471void MyFrame::SetMasterToolbarItemState(
int tool_id,
bool state) {
3478void MyFrame::SetToolbarItemBitmaps(
int tool_id, wxBitmap *bmp,
3479 wxBitmap *bmpRollover) {
3481 g_MainToolbar->GetToolbar()->SetToolBitmaps(tool_id, bmp, bmpRollover);
3486void MyFrame::SetToolbarItemSVG(
int tool_id, wxString normalSVGfile,
3487 wxString rolloverSVGfile,
3488 wxString toggledSVGfile) {
3491 tool_id, normalSVGfile, rolloverSVGfile, toggledSVGfile);
3495void MyFrame::ConfigureStatusBar() {
3497 m_StatusBarFieldCount = g_Platform->GetStatusBarFieldCount();
3500 UseNativeStatusBar(
false);
3503 if (g_bShowStatusBar) {
3504 if (!m_pStatusBar) {
3506 CreateStatusBar(m_StatusBarFieldCount, 0);
3507 ApplyGlobalColorSchemetoStatusBar();
3512 m_pStatusBar->Destroy();
3513 m_pStatusBar = NULL;
3519void MyFrame::ApplyGlobalSettings(
bool bnewtoolbar) {
3520 ConfigureStatusBar();
3522 wxSize lastOptSize = options_lastWindowSize;
3528 options_lastWindowSize = lastOptSize;
3530 if (bnewtoolbar) UpdateAllToolbars(global_color_scheme);
3533void MyFrame::BuildMenuBar() {
3539 bool showMenuBar =
true;
3541 bool showMenuBar = g_bShowMenuBar;
3553 m_pMenuBar =
new wxMenuBar();
3554 RegisterGlobalMenuItems();
3555 SetMenuBar(m_pMenuBar);
3559 UpdateGlobalMenuItems();
3564 m_pMenuBar->Destroy();
3570void MyFrame::RegisterGlobalMenuItems() {
3571 if (!m_pMenuBar)
return;
3573 wxMenu *nav_menu =
new wxMenu();
3574 nav_menu->AppendCheckItem(ID_MENU_NAV_FOLLOW,
3575 _menuText(_(
"Auto Follow"),
"Ctrl-A"));
3576 nav_menu->AppendCheckItem(ID_MENU_NAV_TRACK, _(
"Enable Tracking"));
3577 nav_menu->AppendSeparator();
3578 nav_menu->AppendRadioItem(ID_MENU_CHART_NORTHUP, _(
"North Up Mode"));
3579 nav_menu->AppendRadioItem(ID_MENU_CHART_COGUP, _(
"Course Up Mode"));
3580 nav_menu->AppendRadioItem(ID_MENU_CHART_HEADUP, _(
"Head Up Mode"));
3581 nav_menu->AppendSeparator();
3583 nav_menu->Append(ID_MENU_ZOOM_IN, _menuText(_(
"Zoom In"),
"+"));
3584 nav_menu->Append(ID_MENU_ZOOM_OUT, _menuText(_(
"Zoom Out"),
"-"));
3586 nav_menu->Append(ID_MENU_ZOOM_IN, _menuText(_(
"Zoom In"),
"Alt-+"));
3587 nav_menu->Append(ID_MENU_ZOOM_OUT, _menuText(_(
"Zoom Out"),
"Alt--"));
3589 nav_menu->AppendSeparator();
3590 nav_menu->Append(ID_MENU_SCALE_IN,
3591 _menuText(_(
"Larger Scale Chart"),
"Ctrl-Left"));
3592 nav_menu->Append(ID_MENU_SCALE_OUT,
3593 _menuText(_(
"Smaller Scale Chart"),
"Ctrl-Right"));
3595 nav_menu->AppendSeparator();
3596 nav_menu->Append(ID_MENU_OQUIT, _menuText(_(
"Exit OpenCPN"),
"Ctrl-Q"));
3598 m_pMenuBar->Append(nav_menu, _(
"&Navigate"));
3600 wxMenu *view_menu =
new wxMenu();
3602 view_menu->AppendCheckItem(ID_MENU_CHART_QUILTING,
3603 _menuText(_(
"Enable Chart Quilting"),
"Q"));
3604 view_menu->AppendCheckItem(ID_MENU_CHART_OUTLINES,
3605 _menuText(_(
"Show Chart Outlines"),
"O"));
3607 view_menu->AppendCheckItem(ID_MENU_CHART_QUILTING,
3608 _menuText(_(
"Enable Chart Quilting"),
"Alt-Q"));
3609 view_menu->AppendCheckItem(ID_MENU_CHART_OUTLINES,
3610 _menuText(_(
"Show Chart Outlines"),
"Alt-O"));
3612 view_menu->AppendCheckItem(ID_MENU_UI_CHARTBAR,
3613 _menuText(_(
"Show Chart Bar"),
"Ctrl-B"));
3615 view_menu->AppendSeparator();
3617 view_menu->AppendCheckItem(ID_MENU_ENC_TEXT,
3618 _menuText(_(
"Show ENC text"),
"T"));
3619 view_menu->AppendCheckItem(ID_MENU_ENC_LIGHTS,
3620 _menuText(_(
"Show ENC Lights"),
"L"));
3621 view_menu->AppendCheckItem(ID_MENU_ENC_SOUNDINGS,
3622 _menuText(_(
"Show ENC Soundings"),
"S"));
3623 view_menu->AppendCheckItem(ID_MENU_ENC_ANCHOR,
3624 _menuText(_(
"Show ENC Anchoring Info"),
"A"));
3625 view_menu->AppendCheckItem(ID_MENU_ENC_DATA_QUALITY,
3626 _menuText(_(
"Show ENC Data Quality"),
"U"));
3627 view_menu->AppendCheckItem(ID_MENU_SHOW_NAVOBJECTS,
3628 _menuText(_(
"Show Navobjects"),
"V"));
3630 view_menu->AppendCheckItem(ID_MENU_ENC_TEXT,
3631 _menuText(_(
"Show ENC text"),
"Alt-T"));
3632 view_menu->AppendCheckItem(ID_MENU_ENC_LIGHTS,
3633 _menuText(_(
"Show ENC Lights"),
"Alt-L"));
3634 view_menu->AppendCheckItem(ID_MENU_ENC_SOUNDINGS,
3635 _menuText(_(
"Show ENC Soundings"),
"Alt-S"));
3636 view_menu->AppendCheckItem(ID_MENU_ENC_ANCHOR,
3637 _menuText(_(
"Show ENC Anchoring Info"),
"Alt-A"));
3638 view_menu->AppendCheckItem(ID_MENU_ENC_DATA_QUALITY,
3639 _menuText(_(
"Show ENC Data Quality"),
"Alt-U"));
3640 view_menu->AppendCheckItem(ID_MENU_SHOW_NAVOBJECTS,
3641 _menuText(_(
"Show Navobjects"),
"Alt-V"));
3643 view_menu->AppendSeparator();
3644 view_menu->AppendCheckItem(ID_MENU_SHOW_TIDES, _(
"Show Tides"));
3645 view_menu->AppendCheckItem(ID_MENU_SHOW_CURRENTS, _(
"Show Currents"));
3646 view_menu->AppendSeparator();
3648 view_menu->Append(ID_MENU_UI_COLSCHEME,
3649 _menuText(_(
"Change Color Scheme"),
"C"));
3651 view_menu->Append(ID_MENU_UI_COLSCHEME,
3652 _menuText(_(
"Change Color Scheme"),
"Alt-C"));
3655 view_menu->AppendSeparator();
3657 view_menu->Append(ID_MENU_UI_FULLSCREEN,
3658 _menuText(_(
"Toggle Full Screen"),
"F11"));
3660 m_pMenuBar->Append(view_menu, _(
"&View"));
3662 wxMenu *ais_menu =
new wxMenu();
3663 ais_menu->AppendCheckItem(ID_MENU_AIS_TARGETS, _(
"Show AIS Targets"));
3664 ais_menu->AppendCheckItem(ID_MENU_AIS_SCALED_TARGETS,
3665 _(
"Attenuate less critical AIS targets"));
3666 ais_menu->AppendSeparator();
3667 ais_menu->AppendCheckItem(ID_MENU_AIS_MOORED_TARGETS,
3668 _(
"Hide Moored AIS Targets"));
3669 ais_menu->AppendCheckItem(ID_MENU_AIS_TRACKS, _(
"Show AIS Target Tracks"));
3670 ais_menu->AppendCheckItem(ID_MENU_AIS_CPADIALOG, _(
"Show CPA Alert Dialogs"));
3671 ais_menu->AppendCheckItem(ID_MENU_AIS_CPASOUND, _(
"Sound CPA Alarms"));
3674 ais_menu->AppendCheckItem(ID_MENU_AIS_CPAWARNING,
3675 _menuText(_(
"Show CPA Warnings"),
"W"));
3677 ais_menu->AppendCheckItem(ID_MENU_AIS_CPAWARNING,
3678 _menuText(_(
"Show CPA Warnings"),
"Alt-W"));
3681 ais_menu->AppendSeparator();
3682 ais_menu->Append(ID_MENU_AIS_TARGETLIST, _(
"AIS target list") +
"...");
3683 m_pMenuBar->Append(ais_menu, _(
"&AIS"));
3685 wxMenu *tools_menu =
new wxMenu();
3687 tools_menu->Append(ID_MENU_TOOL_NMEA_DBG_LOG,
3688 _menuText(_(
"Data Monitor"),
"E"));
3689 tools_menu->Append(ID_MENU_TOOL_MEASURE,
3690 _menuText(_(
"Measure Distance"),
"M"));
3692 tools_menu->Append(ID_MENU_TOOL_NMEA_DBG_LOG,
3693 _menuText(_(
"Data Monitor"),
"Alt-E"));
3694 tools_menu->Append(ID_MENU_TOOL_MEASURE,
3695 _menuText(_(
"Measure Distance"),
"Alt-M"));
3698 tools_menu->AppendSeparator();
3699 tools_menu->Append(ID_MENU_ROUTE_MANAGER, _(
"Route && Mark Manager..."));
3700 tools_menu->Append(ID_MENU_ROUTE_NEW, _menuText(_(
"Create Route"),
"Ctrl-R"));
3701 tools_menu->AppendSeparator();
3702 tools_menu->Append(ID_MENU_MARK_BOAT,
3703 _menuText(_(
"Drop Mark at Boat"),
"Ctrl-O"));
3704 tools_menu->Append(ID_MENU_MARK_CURSOR,
3705 _menuText(_(
"Drop Mark at Cursor"),
"Ctrl-M"));
3706 tools_menu->AppendSeparator();
3710 _menuText(_(
"Drop MOB Marker"),
3712 tools_menu->AppendSeparator();
3713 tools_menu->Append(wxID_PREFERENCES,
3714 _menuText(_(
"Preferences") +
"...",
"Ctrl-,"));
3716 tools_menu->Append(ID_MENU_MARK_MOB,
3717 _menuText(_(
"Drop MOB Marker"),
"Ctrl-Space"));
3718 tools_menu->AppendSeparator();
3719 tools_menu->Append(wxID_PREFERENCES,
3720 _menuText(_(
"Options") +
"...",
"Ctrl-,"));
3722 m_pMenuBar->Append(tools_menu, _(
"&Tools"));
3725 wxMenu *window_menu =
new wxMenu();
3726 m_pMenuBar->Append(window_menu, _(
"&Window"));
3729 wxMenu *help_menu =
new wxMenu();
3730 help_menu->Append(wxID_ABOUT, _(
"About OpenCPN"));
3731 help_menu->Append(wxID_HELP, _(
"OpenCPN Help"));
3732 m_pMenuBar->Append(help_menu, _(
"&Help"));
3735 UpdateGlobalMenuItems();
3738void MyFrame::UpdateGlobalMenuItems() {
3739 if (!m_pMenuBar)
return;
3741 m_pMenuBar->FindItem(ID_MENU_NAV_FOLLOW)
3742 ->Check(GetPrimaryCanvas()->m_bFollow);
3743 m_pMenuBar->FindItem(ID_MENU_CHART_NORTHUP)
3744 ->Check(GetPrimaryCanvas()->GetUpMode() == NORTH_UP_MODE);
3745 m_pMenuBar->FindItem(ID_MENU_CHART_COGUP)
3746 ->Check(GetPrimaryCanvas()->GetUpMode() == COURSE_UP_MODE);
3747 m_pMenuBar->FindItem(ID_MENU_CHART_HEADUP)
3748 ->Check(GetPrimaryCanvas()->GetUpMode() == HEAD_UP_MODE);
3749 m_pMenuBar->FindItem(ID_MENU_NAV_TRACK)->Check(g_bTrackActive);
3750 m_pMenuBar->FindItem(ID_MENU_CHART_OUTLINES)->Check(g_bShowOutlines);
3751 m_pMenuBar->FindItem(ID_MENU_CHART_QUILTING)->Check(g_bQuiltEnable);
3752 m_pMenuBar->FindItem(ID_MENU_UI_CHARTBAR)->Check(g_bShowChartBar);
3753 m_pMenuBar->FindItem(ID_MENU_AIS_TARGETS)->Check(g_bShowAIS);
3754 m_pMenuBar->FindItem(ID_MENU_AIS_MOORED_TARGETS)->Check(g_bHideMoored);
3755 m_pMenuBar->FindItem(ID_MENU_AIS_SCALED_TARGETS)->Check(g_bShowScaled);
3756 m_pMenuBar->FindItem(ID_MENU_AIS_SCALED_TARGETS)->Enable(g_bAllowShowScaled);
3757 m_pMenuBar->FindItem(ID_MENU_AIS_TRACKS)->Check(g_bAISShowTracks);
3758 m_pMenuBar->FindItem(ID_MENU_AIS_CPADIALOG)->Check(g_bAIS_CPA_Alert);
3759 if (g_bAIS_CPA_Alert) {
3760 m_pMenuBar->FindItem(ID_MENU_AIS_CPASOUND)->Check(g_bAIS_CPA_Alert_Audio);
3761 m_pMenuBar->Enable(ID_MENU_AIS_CPASOUND,
true);
3763 m_pMenuBar->FindItem(ID_MENU_AIS_CPASOUND)->Check(
false);
3764 m_pMenuBar->Enable(ID_MENU_AIS_CPASOUND,
false);
3767 m_pMenuBar->FindItem(ID_MENU_AIS_CPAWARNING)->Check(g_bCPAWarn);
3768 m_pMenuBar->FindItem(ID_MENU_SHOW_NAVOBJECTS)
3769 ->Check(GetPrimaryCanvas()->m_bShowNavobjects);
3772 m_pMenuBar->FindItem(ID_MENU_ENC_TEXT)->Check(ps52plib->GetShowS57Text());
3773 m_pMenuBar->FindItem(ID_MENU_ENC_SOUNDINGS)
3774 ->Check(ps52plib->GetShowSoundings());
3776 bool light_state =
false;
3778 for (
unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
3780 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
3781 if (!strncmp(pOLE->OBJLName,
"LIGHTS", 6)) {
3782 light_state = (pOLE->nViz == 1);
3787 m_pMenuBar->FindItem(ID_MENU_ENC_LIGHTS)
3788 ->Check((!ps52plib->IsObjNoshow(
"LIGHTS")) && light_state);
3792 DisCat nset = ps52plib->GetDisplayCategory();
3793 if ((nset == MARINERS_STANDARD) || (nset == OTHER)) {
3794 m_pMenuBar->FindItem(ID_MENU_ENC_ANCHOR)
3795 ->Check(!ps52plib->IsObjNoshow(
"SBDARE"));
3796 m_pMenuBar->Enable(ID_MENU_ENC_ANCHOR,
true);
3797 m_pMenuBar->FindItem(ID_MENU_ENC_DATA_QUALITY)
3798 ->Check(!ps52plib->IsObjNoshow(
"M_QUAL"));
3799 m_pMenuBar->Enable(ID_MENU_ENC_DATA_QUALITY,
true);
3801 m_pMenuBar->FindItem(ID_MENU_ENC_ANCHOR)->Check(
false);
3802 m_pMenuBar->Enable(ID_MENU_ENC_ANCHOR,
false);
3803 m_pMenuBar->Enable(ID_MENU_ENC_DATA_QUALITY,
false);
3808void MyFrame::UpdateGlobalMenuItems(
ChartCanvas *cc) {
3809 if (!m_pMenuBar)
return;
3811 m_pMenuBar->FindItem(ID_MENU_NAV_FOLLOW)->Check(cc->m_bFollow);
3813 if (cc->GetUpMode() == NORTH_UP_MODE)
3814 m_pMenuBar->FindItem(ID_MENU_CHART_NORTHUP)->Check(
true);
3815 else if (cc->GetUpMode() == COURSE_UP_MODE)
3816 m_pMenuBar->FindItem(ID_MENU_CHART_COGUP)->Check(
true);
3818 m_pMenuBar->FindItem(ID_MENU_CHART_HEADUP)->Check(
true);
3820 m_pMenuBar->FindItem(ID_MENU_NAV_TRACK)->Check(g_bTrackActive);
3821 m_pMenuBar->FindItem(ID_MENU_CHART_OUTLINES)->Check(cc->GetShowOutlines());
3822 m_pMenuBar->FindItem(ID_MENU_CHART_QUILTING)->Check(cc->GetQuiltMode());
3823 m_pMenuBar->FindItem(ID_MENU_UI_CHARTBAR)->Check(cc->GetShowChartbar());
3824 m_pMenuBar->FindItem(ID_MENU_AIS_TARGETS)->Check(cc->GetShowAIS());
3825 m_pMenuBar->FindItem(ID_MENU_AIS_MOORED_TARGETS)->Check(g_bHideMoored);
3826 m_pMenuBar->FindItem(ID_MENU_AIS_SCALED_TARGETS)->Check(cc->GetAttenAIS());
3827 m_pMenuBar->FindItem(ID_MENU_AIS_SCALED_TARGETS)->Enable(g_bAllowShowScaled);
3828 m_pMenuBar->FindItem(ID_MENU_AIS_TRACKS)->Check(g_bAISShowTracks);
3829 m_pMenuBar->FindItem(ID_MENU_AIS_CPADIALOG)->Check(g_bAIS_CPA_Alert);
3830 m_pMenuBar->FindItem(ID_MENU_AIS_CPASOUND)->Check(g_bAIS_CPA_Alert_Audio);
3831 m_pMenuBar->FindItem(ID_MENU_AIS_CPAWARNING)->Check(g_bCPAWarn);
3832 m_pMenuBar->FindItem(ID_MENU_SHOW_NAVOBJECTS)->Check(cc->m_bShowNavobjects);
3833 m_pMenuBar->FindItem(ID_MENU_SHOW_TIDES)->Check(cc->GetbShowTide());
3834 m_pMenuBar->FindItem(ID_MENU_SHOW_CURRENTS)->Check(cc->GetbShowCurrent());
3837 m_pMenuBar->FindItem(ID_MENU_ENC_TEXT)->Check(cc->GetShowENCText());
3838 m_pMenuBar->FindItem(ID_MENU_ENC_SOUNDINGS)->Check(cc->GetShowENCDepth());
3841 for (
unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
3843 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
3844 if (!strncmp(pOLE->OBJLName,
"LIGHTS", 6)) {
3849 m_pMenuBar->FindItem(ID_MENU_ENC_LIGHTS)->Check(cc->GetShowENCLights());
3853 DisCat nset = (DisCat)cc->GetENCDisplayCategory();
3854 if ((nset == MARINERS_STANDARD) || (nset == OTHER)) {
3855 m_pMenuBar->FindItem(ID_MENU_ENC_ANCHOR)->Check(cc->GetShowENCAnchor());
3856 m_pMenuBar->Enable(ID_MENU_ENC_ANCHOR,
true);
3857 m_pMenuBar->FindItem(ID_MENU_ENC_DATA_QUALITY)
3858 ->Check(cc->GetShowENCDataQual());
3859 m_pMenuBar->Enable(ID_MENU_ENC_DATA_QUALITY,
true);
3861 m_pMenuBar->FindItem(ID_MENU_ENC_ANCHOR)->Check(
false);
3862 m_pMenuBar->Enable(ID_MENU_ENC_ANCHOR,
false);
3863 m_pMenuBar->Enable(ID_MENU_ENC_DATA_QUALITY,
false);
3868void MyFrame::InvalidateAllCanvasUndo() {
3870 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
3872 if (cc) cc->undo->InvalidateUndo();
3876void MyFrame::SubmergeAllCanvasToolbars() {
3878 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
3880 if (cc) cc->SubmergeToolbar();
3884void MyFrame::SurfaceAllCanvasToolbars() {
3885 if (g_bshowToolbar) {
3887 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
3889 if (cc && cc->GetToolbarEnable()) cc->SurfaceToolbar();
3896void MyFrame::JumpToPosition(
ChartCanvas *cc,
double lat,
double lon,
3898 if (lon > 180.0) lon -= 360.0;
3903 cc->JumpToPosition(lat, lon,
scale);
3906 g_pi_manager->SendViewPortToRequestingPlugIns(cc->GetVP());
3910void MyFrame::UpdateCanvasConfigDescriptors() {
3912 for (
unsigned int i = 0;
3913 i < ConfigMgr::Get().GetCanvasConfigArray().GetCount(); i++) {
3914 canvasConfig *cc = ConfigMgr::Get().GetCanvasConfigArray().Item(i);
3922 cc->DBindex = chart->GetQuiltReferenceChartIndex();
3923 cc->GroupID = chart->m_groupIndex;
3926 cc->
bQuilt = chart->GetQuiltMode();
3932 cc->bEnableBasemapTile = chart->GetbEnableBasemapTile();
3934 cc->
bFollow = chart->m_bFollow;
3939 int upmode = chart->GetUpMode();
3940 if (upmode == COURSE_UP_MODE)
3942 else if (upmode == HEAD_UP_MODE)
3949void MyFrame::CenterView(
ChartCanvas *cc,
const LLBBox &RBBox) {
3950 if (!RBBox.GetValid())
return;
3952 double clat = (RBBox.GetMinLat() + RBBox.GetMaxLat()) / 2;
3953 double clon = (RBBox.GetMinLon() + RBBox.GetMaxLon()) / 2;
3956 if (RBBox.GetMinLat() == RBBox.GetMaxLat() &&
3957 RBBox.GetMinLon() == RBBox.GetMaxLon()) {
3965 DistanceBearingMercator(RBBox.GetMinLat(), RBBox.GetMinLon(),
3966 RBBox.GetMinLat(), RBBox.GetMaxLon(), NULL, &rw);
3968 DistanceBearingMercator(RBBox.GetMinLat(), RBBox.GetMinLon(),
3969 RBBox.GetMaxLat(), RBBox.GetMinLon(), NULL, &rh);
3971 cc->GetSize(&ww, &wh);
3973 ppm = wxMin(ww / (rw * 1852), wh / (rh * 1852)) * (100 - fabs(clat)) / 90;
3975 ppm = wxMin(ppm, 1.0);
3981void MyFrame::PrepareOptionsClose(
options *settings,
3982 int settings_return_value) {
3984 options_lastPage = settings->lastPage;
3989 if (options_lastPage == 1) options_lastPage = 0;
3991 options_subpage = settings->lastSubPage;
3992 options_lastWindowPos = settings->lastWindowPos;
3993 options_lastWindowSize = settings->lastWindowSize;
3996 androidEnableBackButton(
true);
3997 androidEnableOptionsMenu(
true);
3998 androidRestoreFullScreen();
3999 androidEnableRotation();
4002 EnableSettingsTool(
true);
4005void MyFrame::DoOptionsDialog() {
4006 EnableSettingsTool(
false);
4009 AbstractPlatform::ShowBusySpinner();
4012 pConfig->SetPath(
"/Settings");
4013 pConfig->Read(
"OptionsSizeX", &sx, -1);
4014 pConfig->Read(
"OptionsSizeY", &sy, -1);
4016 wxWindow *optionsParent =
this;
4018 optionsParent = GetPrimaryCanvas();
4021 callbacks.prepare_close = [&](
options *me,
int changes) {
4022 PrepareOptionsClose(me, changes);
4024 callbacks.process_dialog = [&](
int changes, ArrayOfCDI *workdir_list) {
4025 ProcessOptionsDialog(changes, workdir_list);
4028 wxPoint(-1, -1), wxSize(sx, sy));
4030 AbstractPlatform::HideBusySpinner();
4034 g_options->SetInitChartDir(*pInit_Chart_Dir);
4038 ArrayOfCDI *pWorkDirArray =
new ArrayOfCDI;
4039 g_options->SetWorkDirListPtr(pWorkDirArray);
4045 prev_locale = g_locale;
4046 g_options->SetInitialPage(options_lastPage, options_subpage);
4049 g_options->lastWindowPos = options_lastWindowPos;
4050 if (options_lastWindowPos != wxPoint(0, 0)) {
4052 g_options->SetSize(options_lastWindowSize);
4056 if (options_lastWindowSize != wxSize(0, 0)) {
4057 g_options->SetSize(options_lastWindowSize);
4062 androidEnableBackButton(
false);
4063 androidEnableOptionsMenu(
false);
4064 androidDisableFullScreen();
4072 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4075 wxString chart_file_name;
4076 if (cc->GetQuiltMode()) {
4077 int dbi = cc->GetQuiltRefChartdbIndex();
4078 chart_file_name =
ChartData->GetDBChartFileName(dbi);
4080 if (cc->m_singleChart)
4081 chart_file_name = cc->m_singleChart->GetFullPath();
4084 pathArray.Add(chart_file_name);
4090 last_canvasConfig = g_canvasConfig;
4093 g_last_ChartScaleFactor = g_ChartScaleFactor;
4099void MyFrame::ProcessOptionsDialog(
int rr, ArrayOfCDI *pNewDirArray) {
4100 bool b_need_refresh =
false;
4103 if ((rr & VISIT_CHARTS) &&
4104 ((rr & CHANGE_CHARTS) || (rr & FORCE_UPDATE) || (rr & SCAN_UPDATE))) {
4106 UpdateChartDatabaseInplace(*pNewDirArray,
4107 ((rr & FORCE_UPDATE) == FORCE_UPDATE),
true,
4110 b_need_refresh =
true;
4115 if (rr & STYLE_CHANGED) {
4118 _(
"Please restart OpenCPN to activate language or style changes."),
4119 _(
"OpenCPN Info"), wxOK | wxICON_INFORMATION);
4122 bool charts_updating =
4123 (rr & VISIT_CHARTS) && ((rr & CHANGE_CHARTS) || (rr & SCAN_UPDATE));
4124 if (!charts_updating) RefreshGroupIndices();
4126 if (rr & TIDES_CHANGED) {
4132 if (rr & S52_CHANGED) {
4133 WayPointmanGui(*pWayPointMan).ReloadAllIcons(g_Platform->GetDisplayDPmm());
4144 g_Platform->GetDisplayDPmm());
4147 double stuffcog = NAN;
4148 double stuffsog = NAN;
4149 if (!std::isnan(
gCog)) stuffcog =
gCog;
4150 if (!std::isnan(
gSog)) stuffsog =
gSog;
4152 for (
int i = 0; i < kMaxCogsogFilterSeconds; i++) {
4153 COGFilterTable[i] = stuffcog;
4154 SOGFilterTable[i] = stuffsog;
4157 SetChartUpdatePeriod();
4159 if (rr & GL_CHANGED) {
4163 b_need_refresh =
true;
4166 if (rr & S52_CHANGED) {
4167 b_need_refresh =
true;
4171 if (rr & REBUILD_RASTER_CACHE) {
4173 GetPrimaryCanvas()->Disable();
4175 GetPrimaryCanvas()->Enable();
4180 if (g_config_display_size_manual &&
4188 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4195 int rrt = rr & S52_CHANGED;
4197 (rrt == S52_CHANGED) ||
4198 (g_last_ChartScaleFactor != g_ChartScaleFactor));
4208 ps52plib->SetScaleFactorExp(
4209 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor));
4210 ps52plib->SetScaleFactorZoomMod(g_chart_zoom_modifier_vector);
4214 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4216 if (cc) cc->ApplyGlobalSettings();
4224 if (!charts_updating) {
4225 bool ztc = g_bEnableZoomToCursor;
4226 g_bEnableZoomToCursor =
false;
4228 if (!GetPrimaryCanvas()->IsFrozen())
4230 g_bEnableZoomToCursor = ztc;
4235 if (g_last_ChartScaleFactor != g_ChartScaleFactor) {
4244 SetGPSCompassScale();
4246 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4249 cc->GetCompass()->SetScaleFactor(g_compass_scalefactor);
4250 if (!charts_updating) cc->UpdateCanvasControlBar();
4253 UpdateGPSCompassStatusBoxes();
4255 SetAllToolbarScale();
4256 RequestNewToolbars();
4258 if ((rr & MENU_CHANGED) == MENU_CHANGED) BuildMenuBar();
4261 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4264 cc->RebuildCursors();
4269 bool b_masterScaleChange =
false;
4271 (fabs(
g_MainToolbar->GetScaleFactor() - g_toolbar_scalefactor) > 0.01f))
4272 b_masterScaleChange =
true;
4274 if ((rr & TOOLBAR_CHANGED) || b_masterScaleChange)
4275 RequestNewMasterToolbar(
true);
4277 bool bMuiChange =
false;
4283 if (b_masterScaleChange || bMuiChange) {
4285 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4288 cc->ProcessNewGUIScale();
4294 if (rr & LOCALE_CHANGED) {
4295 g_Platform->ChangeLocale(g_locale, plocale_def_lang, &plocale_def_lang);
4297 rr |= NEED_NEW_OPTIONS;
4306 g_last_ChartScaleFactor = g_ChartScaleFactor;
4311bool MyFrame::CheckGroup(
int igroup) {
4312 if (igroup == 0)
return true;
4316 if (!pGroup->m_element_array.size())
4319 for (
const auto &elem : pGroup->m_element_array) {
4320 for (
unsigned int ic = 0;
4321 ic < (
unsigned int)
ChartData->GetChartTableEntries(); ic++) {
4322 auto &cte =
ChartData->GetChartTableEntry(ic);
4323 wxString chart_full_path(cte.GetpFullPath(), wxConvUTF8);
4325 if (chart_full_path.StartsWith(elem.m_element_name))
return true;
4332bool MyFrame::ScrubGroupArray() {
4337 bool b_change =
false;
4338 unsigned int igroup = 0;
4339 while (igroup < g_pGroupArray->GetCount()) {
4340 bool b_chart_in_element =
false;
4343 for (
unsigned int j = 0; j < pGroup->m_element_array.size(); j++) {
4344 const wxString &element_root = pGroup->m_element_array[j].m_element_name;
4346 for (
unsigned int ic = 0;
4347 ic < (
unsigned int)
ChartData->GetChartTableEntries(); ic++) {
4348 auto &cte =
ChartData->GetChartTableEntry(ic);
4349 wxString chart_full_path = cte.GetFullSystemPath();
4351 if (chart_full_path.StartsWith(element_root)) {
4352 b_chart_in_element =
true;
4358 if (!b_chart_in_element) {
4359 wxString test_string =
"GSHH";
4360 if (element_root.Upper().Contains(test_string))
4361 b_chart_in_element =
true;
4364 if (!b_chart_in_element)
4366 pGroup->m_element_array.erase(pGroup->m_element_array.begin() + j);
4378void MyFrame::RefreshCanvasOther(
ChartCanvas *ccThis) {
4380 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4382 if (cc && (cc != ccThis)) cc->Refresh();
4387void MyFrame::ChartsRefresh() {
4390 AbstractPlatform::ShowBusySpinner();
4392 bool b_run = FrameTimer1.IsRunning();
4395 FrameTenHzTimer.Stop();
4398 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4401 int currentIndex = cc->GetpCurrentStack()->GetCurrentEntrydbIndex();
4402 if (cc->GetQuiltMode()) {
4403 currentIndex = cc->GetQuiltReferenceChartIndex();
4405 cc->canvasChartsRefresh(currentIndex);
4409 if (b_run) FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
4410 if (b_run) FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
4412 AbstractPlatform::HideBusySpinner();
4415void MyFrame::InvalidateAllQuilts() {
4416 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4419 cc->InvalidateQuilt();
4420 cc->SetQuiltRefChart(-1);
4421 cc->m_singleChart = NULL;
4426bool MyFrame::UpdateChartDatabaseInplace(ArrayOfCDI &DirArray,
bool b_force,
4428 const wxString &ChartListFileName) {
4429 bool b_run = FrameTimer1.IsRunning();
4431 FrameTenHzTimer.Stop();
4433 bool b_runCOGTimer = FrameCOGTimer.IsRunning();
4434 FrameCOGTimer.Stop();
4437 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4440 cc->InvalidateQuilt();
4441 cc->SetQuiltRefChart(-1);
4442 cc->m_singleChart = NULL;
4452 AbstractPlatform::ShowBusySpinner();
4455 wxString longmsg = _(
"OpenCPN Chart Update");
4457 ".................................................................."
4460 Updateprog =
new wxGenericProgressDialog();
4463 Updateprog->SetFont(*qFont);
4465 Updateprog->Create(_(
"OpenCPN Chart Update"), longmsg, 100,
gFrame,
4466 wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
4467 wxPD_REMAINING_TIME);
4469 DimeControl(Updateprog);
4474 wxLogMessage(
"Starting chart database Update...");
4478 m_gshhg_chart_loc = gWorldMapLocation;
4479 gWorldMapLocation = wxEmptyString;
4483 AbstractPlatform::HideBusySpinner();
4487void MyFrame::FinalizeChartDBUpdate() {
4489 if (!g_bDeferredInitDone) {
4491 InitTimer.Start(100, wxTIMER_ONE_SHOT);
4494 bool b_groupchange = ScrubGroupArray();
4496 RefreshGroupIndices();
4498 if (b_groupchange) {
4499 pConfig->DestroyConfigGroups();
4504 if (g_bDeferredInitDone) ScheduleReloadCharts();
4509 cc->ToggleCanvasQuiltMode();
4511 bool cur_mode = cc->GetQuiltMode();
4513 if( !cc->GetQuiltMode() )
4514 cc->SetQuiltMode(
true );
4516 if( cc->GetQuiltMode() ) {
4517 cc->SetQuiltMode(
false );
4518 g_sticky_chart = cc->GetQuiltReferenceChartIndex();
4522 if( cur_mode != cc->GetQuiltMode() ){
4528 g_bQuiltEnable = cc->GetQuiltMode();
4532 ps52plib->GenerateStateHash();
4540 DoStackDelta(cc, -1);
4546 DoStackDelta(cc, 1);
4549void MyFrame::DoStackDown(
ChartCanvas *cc) { DoStackDelta(cc, -1); }
4551void MyFrame::DoStackUp(
ChartCanvas *cc) { DoStackDelta(cc, 1); }
4553void MyFrame::DoStackDelta(
ChartCanvas *cc,
int direction) {
4555 cc->DoCanvasStackDelta(direction);
4559void MyFrame::PositionIENCToolbar() {
4563 posn.x = (GetPrimaryCanvas()->GetSize().x -
g_iENCToolbar->GetSize().x) / 2;
4565 g_iENCToolbar->Move(GetPrimaryCanvas()->ClientToScreen(posn));
4573void MyFrame::OnInitTimer(wxTimerEvent &event) {
4576 msg.Printf(
"OnInitTimer...%d", m_iInitCount);
4580 wxLog::FlushActive();
4582 switch (m_iInitCount++) {
4584 EnableSettingsTool(
false);
4589 if (g_bInlandEcdis) {
4590 double range = GetPrimaryCanvas()->GetCanvasRangeMeters();
4591 double range_set = 500.;
4593 range = wxRound(range * 10) / 10.;
4597 else if (range > 2000.)
4599 else if (range > 1600.)
4601 else if (range > 1200.)
4603 else if (range > 800.)
4608 GetPrimaryCanvas()->SetCanvasRangeMeters(range_set);
4612 g_Platform->SetFullscreen(g_bFullscreen);
4616 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4619 cc->SetGroupIndex(0,
false);
4626 StartRebuildChartDatabase();
4637 if (
g_pi_manager->IsAnyPlugInChartEnabled()) b_reloadForPlugins =
true;
4651 3 * GetCharHeight());
4653 m_data_monitor->Center();
4661 pConfig->SetPath(
"/Settings");
4662 pConfig->Read(
"OptionsSizeX", &sx, -1);
4663 pConfig->Read(
"OptionsSizeY", &sy, -1);
4665 wxWindow *optionsParent =
this;
4667 optionsParent = GetPrimaryCanvas();
4669 BuildiENCToolbar(
true, m_toolbar_callbacks);
4676 if (!g_params.empty()) {
4677 for (
size_t n = 0; n < g_params.size(); n++) {
4678 wxString path = g_params[n];
4679 if (::wxFileExists(path)) {
4681 pSet->load_file(path.fn_str());
4684 pSet->LoadAllGPXObjects(
4685 !pSet->IsOpenCPN(), wpt_dups,
4687 LLBBox box = pSet->GetBBox();
4688 if (box.GetValid()) {
4689 CenterView(GetPrimaryCanvas(), box);
4698 InitAppMsgBusListener();
4703 auto loader = PluginLoader::GetInstance();
4704 bool b_haveWMM = loader && loader->IsPlugInAvailable(
"WMM");
4705 if (!b_haveWMM)
gVar = g_UserVar;
4713 auto colour_func = [](wxString c) {
return GetGlobalColor(c); };
4716 .SetColorScheme(global_color_scheme, g_Platform->GetDisplayDPmm());
4718 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4721 if (cc->SetUserOwnship()) cc->SetColorScheme(global_color_scheme);
4725 NavObj_dB::GetInstance().FullSchemaMigrate(
this);
4726 NavObj_dB::GetInstance().ImportLegacyNavobj(
this);
4727 NavObj_dB::GetInstance().LoadNavObjects();
4730 if (!g_AW1GUID.IsEmpty()) {
4733 if (!g_AW2GUID.IsEmpty()) {
4739 appendOSDirSlash(&layerdir);
4740 layerdir.Append(
"layers");
4742 if (wxDir::Exists(layerdir)) {
4744 laymsg.Printf(
"Getting .gpx layer files from: %s", layerdir.c_str());
4745 wxLogMessage(laymsg);
4746 pConfig->LoadLayers(layerdir);
4751 if (!g_kiosk_startup) {
4752 AbstractPlatform::ShowBusySpinner();
4755 pConfig->SetPath(
"/Settings");
4756 pConfig->Read(
"OptionsSizeX", &sx, -1);
4757 pConfig->Read(
"OptionsSizeY", &sy, -1);
4759 wxWindow *optionsParent =
this;
4761 optionsParent = GetPrimaryCanvas();
4764 callbacks.prepare_close = [&](
options *me,
int changes) {
4765 PrepareOptionsClose(me, changes);
4767 callbacks.process_dialog = [&](
int changes, ArrayOfCDI *workdir_list) {
4768 ProcessOptionsDialog(changes, workdir_list);
4771 wxPoint(-1, -1), wxSize(sx, sy));
4772 AbstractPlatform::HideBusySpinner();
4779 wxLogMessage(
"OnInitTimer...Last Call");
4783 RequestNewMasterToolbar();
4785 PositionIENCToolbar();
4787 g_bDeferredInitDone =
true;
4797 GetPrimaryCanvas()->SetFocus();
4798 GetPrimaryCanvas()->Enable();
4801 if (b_reloadForPlugins) {
4807 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4809 if (cc) cc->SetFirstAuto(
true);
4817 wxLogMessage(
"OnInitTimer...Finalize Canvases");
4819 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4823 cc->CheckGroupValid();
4824 cc->GetCompass()->SetScaleFactor(g_compass_scalefactor);
4825 cc->SetShowGPSCompassWindow(
true);
4830 androidEnableBackButton(
true);
4831 androidEnableRotation();
4832 androidEnableOptionItems(
true);
4836 if (g_start_fullscreen && !IsFullScreen()) ToggleFullScreen();
4842 gFrame->FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
4844 gFrame->FrameCOGTimer.Start(2000, wxTIMER_CONTINUOUS);
4846 gFrame->FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
4852 if (!g_bDeferredInitDone) InitTimer.Start(10, wxTIMER_ONE_SHOT);
4854 wxLog::FlushActive();
4856 RefreshAllCanvas(
true);
4857 UsbWatchDaemon::GetInstance().Start();
4858 EnableSettingsTool(
true);
4864void MyFrame::InitAppMsgBusListener() {
4865 auto &msgbus = AppMsgBus::GetInstance();
4868 AppMsg msg_basic(AppMsg::Type::BasicNavData);
4869 listener_basic_navdata.Listen(msg_basic,
this, EVT_BASIC_NAV_DATA);
4873 auto basicnav_msg = std::static_pointer_cast<const BasicNavDataMsg>(ptr);
4874 HandleBasicNavMsg(basicnav_msg);
4878 AppMsg msg_watchdog(AppMsg::Type::GPSWatchdog);
4879 listener_gps_watchdog.Listen(msg_watchdog,
this, EVT_GPS_WATCHDOG);
4883 auto msg = std::static_pointer_cast<const GPSWatchdogMsg>(ptr);
4884 HandleGPSWatchdogMsg(msg);
4891void MyFrame::ReleaseApiListeners() {}
4896 m_on_raise_listener.Init(server.on_raise, [&](
ObservedEvt) { Raise(); });
4897 m_on_quit_listener.Init(server.on_quit, [&](
ObservedEvt) { FastClose(); });
4898 server.SetGetRestApiEndpointCb([&] {
return m_rest_server.
GetEndpoint(); });
4899 server.open_file_cb = [&](
const std::string &path) {
4900 return m_open_gpx_file(path);
4907void MyFrame::HandleGPSWatchdogMsg(std::shared_ptr<const GPSWatchdogMsg> msg) {
4908 if (msg->gps_watchdog <= 0) {
4909 if (msg->wd_source == GPSWatchdogMsg::WDSource::position) {
4913 if (last_bGPSValid !=
bGPSValid) UpdateGPSCompassStatusBoxes(
true);
4918 if (m_fix_start_time.IsValid()) {
4919 wxDateTime now = wxDateTime::Now();
4920 wxTimeSpan span = now - m_fix_start_time;
4921 if (span.IsLongerThan(wxTimeSpan(0, 5))) {
4922 auto ¬eman = NotificationManager::GetInstance();
4923 wxString msg = _(
"GNSS Position fix lost");
4924 noteman.AddNotification(NotificationSeverity::kCritical,
4926 m_fix_start_time = wxInvalidDateTime;
4930 }
else if (msg->wd_source == GPSWatchdogMsg::WDSource::velocity) {
4931 bool last_bVelocityValid = bVelocityValid;
4932 bVelocityValid =
false;
4939void MyFrame::CalculateCOGAverage() {
4941 if (!std::isnan(
gCog)) {
4944 for (
int i =
g_COGAvgSec - 1; i > 0; i--) COGTable[i] = COGTable[i - 1];
4947 double sum = 0., count = 0;
4949 double adder = COGTable[i];
4950 if (std::isnan(adder))
continue;
4952 if (fabs(adder -
g_COGAvg) > 180.) {
4966 else if (sum >= 360.)
4975void MyFrame::HandleBasicNavMsg(std::shared_ptr<const BasicNavDataMsg> msg) {
4976 m_fixtime = msg->time;
4977 double hdt_data_interval = 0;
4978 double fix_time_interval = 0;
4980 double msgtime = msg->set_time.tv_sec;
4981 double m1 = msg->set_time.tv_nsec / 1e9;
4984 if (((msg->vflag & POS_UPDATE) == POS_UPDATE) &&
4985 ((msg->vflag & POS_VALID) == POS_VALID)) {
4987 if (!m_fix_start_time.IsValid()) {
4988 m_fix_start_time = wxDateTime::Now();
4993 DistanceBearingMercator(
gLat,
gLon, gLat_gt, gLon_gt, &brg, &dist);
4996 fix_time_gt_last = fix_time_gt;
4997 uint64_t fix_time_gt_now =
4998 msg->set_time.tv_sec * 1e9 + msg->set_time.tv_nsec;
4999 fix_time_interval = (fix_time_gt_now - fix_time_gt_last) / (
double)1e9;
5003 double implied_sog = dist / (fix_time_interval / 3600);
5008 gLat_gt_m1 = gLat_gt;
5009 gLon_gt_m1 = gLon_gt;
5013 fix_time_gt = fix_time_gt_now;
5017 if (((msg->vflag & COG_UPDATE) == COG_UPDATE) &&
5018 ((msg->vflag & SOG_UPDATE) == SOG_UPDATE)) {
5019 gCog_gt_m1 = gCog_gt;
5029 if (!std::isnan(gCog_gt_m1)) {
5031 if ((fabs(
gSog - implied_sog) /
gSog) > 0.5) {
5038 if ((fix_time_gt - fix_time_gt_last) > .08) {
5043 if (gCog_gt > gCog_gt_m1) {
5044 if ((gCog_gt - gCog_gt_m1) > 180.)
5049 if ((gCog_gt_m1 - gCog_gt) > 180.)
5054 difft = fabs(gCog_gt - gCog_gt_m1);
5055 if (fabs(difft > 180.)) difft = fabs(difft - 360.);
5063 double tentative_cog_rate_gt = diff / (fix_time_gt - fix_time_gt_last);
5064 tentative_cog_rate_gt *= 1e9;
5065 cog_rate_gt = tentative_cog_rate_gt;
5073 if ((msg->vflag & HDT_UPDATE) == HDT_UPDATE) {
5076static double hdt_avg;
5077 double hdt_norm =
gHdt;
5078 if(
gHdt > 180) hdt_norm -= 360;
5081 hdt_avg += hdt_norm * 0.1;
5086 if (!std::isnan(
gHdt)) {
5088 uint64_t hdt_time_gt_last = hdt_time_gt;
5089 hdt_time_gt = msg->set_time.tv_sec * 1e9 + msg->set_time.tv_nsec;
5090 hdt_data_interval = (hdt_time_gt - hdt_time_gt_last) / 1e9;
5093 if (hdt_data_interval > .09) {
5095 gHdt_gt_m1 = gHdt_gt;
5098 if (!std::isnan(gHdt_gt_m1)) {
5100 double tentative_hdt_rate_gt =
5101 (gHdt_gt - gHdt_gt_m1) / (hdt_time_gt - hdt_time_gt_last);
5102 tentative_hdt_rate_gt *= 1e9;
5104 if (fabs(tentative_hdt_rate_gt - hdt_rate_gt) < 180.)
5105 hdt_rate_gt = tentative_hdt_rate_gt;
5113 if (std::isnan(
gHdt)) gHdt_gt = NAN;
5116 CalculateCOGAverage();
5124 if ((msg->vflag & POS_UPDATE) == POS_UPDATE) {
5125 if ((msg->vflag & POS_VALID) == POS_VALID)
5130 if (last_bGPSValid !=
bGPSValid) UpdateGPSCompassStatusBoxes(
true);
5132 bVelocityValid =
true;
5136void MyFrame::UpdateStatusBar() {
5139 unsigned long uiCurrentTickCount;
5140 m_MMEAeventTime.SetToCurrent();
5141 uiCurrentTickCount =
5142 m_MMEAeventTime.GetMillisecond() / 100;
5143 uiCurrentTickCount += m_MMEAeventTime.GetTicks() * 10;
5144 if (uiCurrentTickCount > m_ulLastNMEATicktime + 1) {
5145 m_ulLastNMEATicktime = uiCurrentTickCount;
5147 if (m_tick_idx++ > 6) m_tick_idx = 0;
5152 if (NULL != GetStatusBar()) {
5155 tick_buf[0] = nmea_tick_chars[m_tick_idx];
5158 wxString s1(tick_buf, wxConvUTF8);
5160 s1 += toSDMM(1,
gLat);
5162 s1 += toSDMM(2,
gLon);
5164 if (STAT_FIELD_TICK >= 0) SetStatusText(s1, STAT_FIELD_TICK);
5168 if (!std::isnan(
gSog))
5169 sogcog.Printf(
"SOG %2.2f " + getUsrSpeedUnit() +
" ", toUsrSpeed(
gSog));
5171 sogcog.Printf(
"SOG --- ");
5175 if (!std::isnan(
gCog) && !std::isnan(
gSog) && (
gSog > 0.05)) {
5177 cogs << wxString::Format(wxString(
"COG %03d%c "), (
int)
gCog, 0x00B0);
5179 cogs << wxString::Format(wxString(
"COG %03d%c(M) "),
5180 (
int)toMagnetic(
gCog), 0x00B0);
5182 cogs.Printf((
"COG ---%c"), 0x00B0);
5184 sogcog.Append(cogs);
5185 SetStatusText(sogcog, STAT_FIELD_SOGCOG);
5190void MyFrame::OnMemFootTimer(wxTimerEvent &event) {
5191 MemFootTimer.Stop();
5193 int memsize = GetApplicationMemoryUse();
5196 printf(
"Memsize: %d \n", memsize);
5199 if (memsize > (g_MemFootMB * 1000)) {
5203 wxArrayPtrVoid *pCache =
ChartData->GetChartCache();
5204 unsigned int nCache = pCache->GetCount();
5207 for (
unsigned int i = 0; i < nCache; i++) {
5217 for (
unsigned int i = 0; i < nCache - 1; i++) {
5218 if (pcea[i].RecentTime > pcea[i + 1].RecentTime) {
5220 pcea[i] = pcea[i + 1];
5231 unsigned int idelete = 0;
5232 unsigned int idelete_max = pCache->GetCount();
5235 unsigned int minimum_cache = 1;
5236 if (cc->GetQuiltMode()) minimum_cache = cc->GetQuiltChartCount();
5238 while ((memsize > (g_MemFootMB * 1000)) &&
5239 (pCache->GetCount() > minimum_cache) &&
5240 (idelete < idelete_max)) {
5241 int memsizeb = memsize;
5245 memsize = GetApplicationMemoryUse();
5246 printf(
"delete, before: %d after: %d\n", memsizeb, memsize);
5254 MemFootTimer.Start(9000, wxTIMER_CONTINUOUS);
5259void MyFrame::CheckToolbarPosition() {
5262 static bool bMaximized;
5264 if (IsMaximized() && !bMaximized) {
5271 PositionIENCToolbar();
5272 }
else if (!IsMaximized() && bMaximized) {
5280 PositionIENCToolbar();
5285void MyFrame::ProcessUnitTest() {
5286 if (!g_bPauseTest && (g_unit_test_1 || g_unit_test_2)) {
5293 cc->m_bFollow =
false;
5295 g_MainToolbar->GetToolbar()->ToggleTool(ID_FOLLOW, cc->m_bFollow);
5296 int ut_index_max = ((g_unit_test_1 > 0) ? (g_unit_test_1 - 1) : INT_MAX);
5299 if (cc->m_groupIndex > 0) {
5300 while (ut_index < ChartData->GetChartTableEntries() &&
5301 !
ChartData->IsChartInGroup(ut_index, cc->m_groupIndex)) {
5305 if (ut_index < ChartData->GetChartTableEntries()) {
5309 double clat = (cte->GetLatMax() + cte->GetLatMin()) / 2;
5310 double clon = (cte->GetLonMax() + cte->GetLonMin()) / 2;
5317 if (cc->GetQuiltMode()) {
5318 if (cc->IsChartQuiltableRef(ut_index))
5319 cc->SelectQuiltRefdbChart(ut_index);
5321 cc->SelectdbChart(ut_index);
5324 if (g_unit_test_1) {
5332 DistanceBearingMercator(cte->GetLatMin(), cte->GetLonMin(),
5333 cte->GetLatMin(), cte->GetLonMax(), NULL,
5337 DistanceBearingMercator(cte->GetLatMin(), cte->GetLonMin(),
5338 cte->GetLatMax(), cte->GetLonMin(), NULL,
5341 cc->GetSize(&ww, &wh);
5342 ppm = wxMin(ww / (rw * 1852), wh / (rh * 1852)) * (100 - fabs(clat)) /
5344 ppm = wxMin(ppm, 1.0);
5351 if (ut_index > ut_index_max) exit(0);
5362 bool b_rotate =
false;
5364 if (cc) b_rotate |= (cc->GetUpMode() != NORTH_UP_MODE);
5367 if (!b_rotate && !g_btenhertz)
return;
5369 bool b_update =
false;
5371 if (!std::isnan(
gCog) && !std::isnan(
gSog)) {
5374 struct timespec now;
5375 clock_gettime(CLOCK_MONOTONIC, &now);
5376 uint64_t diff = 1e9 * (now.tv_sec) + now.tv_nsec - fix_time_gt;
5377 double diffc = diff / 1e9;
5380 double gCog_tentative = gCog_gt_m1 + (cog_rate_gt * diffc);
5381 if (gCog_tentative >= 360.) gCog_tentative -= 360.;
5382 if (gCog_tentative < 0.) gCog_tentative += 360.;
5383 gCog = gCog_tentative;
5387 if (!std::isnan(gHdt_gt) && !std::isnan(gHdt_gt_m1)) {
5388 uint64_t diff = 1e9 * (now.tv_sec) + now.tv_nsec - hdt_time_gt;
5389 double diffc = diff / 1e9;
5390 gHdt = gHdt_gt_m1 + (hdt_rate_gt * diffc);
5394 if (gSog_gt && !std::isnan(gCog_gt)) {
5395 double delta_t = diffc / 3600;
5396 double distance = gSog_gt * delta_t;
5399 double angr = gCog_gt / 180 * M_PI;
5400 double latr = gLat_gt * M_PI / 180;
5401 double D = distance / 3443;
5402 double sD = sin(D), cD = cos(D);
5403 double sy = sin(latr), cy = cos(latr);
5404 double sa = sin(angr), ca = cos(angr);
5406 gLon = gLon_gt + asin(sa * sD / cy) * 180 / M_PI;
5407 gLat = asin(sy * cD + cy * sD * ca) * 180 / M_PI;
5417 if (cc) cc->DoCanvasCOGSet();
5426 if (cc->GetUpMode() != NORTH_UP_MODE || cc->m_bFollow) {
5427 bool bnew = cc->DoCanvasUpdate();
5428 if (!bnew) cc->UpdateShips();
5437 FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
5440bool MyFrame::ProcessQuitFlag() {
5444 FrameTenHzTimer.Stop();
5446 wxWindow *top = wxTheApp ? wxTheApp->GetTopWindow() :
nullptr;
5447 if (top) top->Close(
true);
5454void MyFrame::ProcessDeferredTrackOn() {
5457 if (g_bDeferredStartTrack) {
5458 if (!g_bTrackActive) {
5461 g_bDeferredStartTrack =
false;
5464 g_bDeferredStartTrack =
false;
5469void MyFrame::ProcessAnchorWatch() {
5477 double d = g_nAWMax;
5480 bool toofar =
false;
5481 bool tooclose =
false;
5482 if (d >= 0.0) toofar = (dist * 1852. > d);
5483 if (d < 0.0) tooclose = (dist * 1852 < -d);
5485 if (tooclose || toofar)
5486 AnchorAlertOn1 =
true;
5488 AnchorAlertOn1 =
false;
5490 AnchorAlertOn1 =
false;
5498 double d = g_nAWMax;
5501 bool toofar =
false;
5502 bool tooclose =
false;
5503 if (d >= 0) toofar = (dist * 1852. > d);
5504 if (d < 0) tooclose = (dist * 1852 < -d);
5506 if (tooclose || toofar)
5507 AnchorAlertOn2 =
true;
5509 AnchorAlertOn2 =
false;
5511 AnchorAlertOn2 =
false;
5514 AnchorAlertOn1 =
true;
5517void MyFrame::SendFixToPlugins() {
5528 GPSData.
nSats = g_SatsInView;
5530 wxDateTime tCheck((time_t)m_fixtime);
5531 if (tCheck.IsValid()) {
5540 GPSData.
FixTime = wxDateTime::Now().GetTicks();
5543 SendPositionFixToAllPlugIns(&GPSData);
5547void MyFrame::ProcessLogAndBells() {
5550 wxDateTime lognow = wxDateTime::Now();
5551 int hourLOC = lognow.GetHour();
5552 int minuteLOC = lognow.GetMinute();
5554 int minuteUTC = lognow.GetMinute();
5555 int second = lognow.GetSecond();
5557 wxTimeSpan logspan = lognow.Subtract(g_loglast_time);
5558 if ((logspan.IsLongerThan(wxTimeSpan(0, 30, 0, 0))) || (minuteUTC == 0) ||
5559 (minuteUTC == 30)) {
5560 if (logspan.IsLongerThan(wxTimeSpan(0, 1, 0, 0))) {
5561 wxString day = lognow.FormatISODate();
5562 wxString utc = lognow.FormatISOTime();
5563 wxString navmsg =
"LOGBOOK: ";
5571 data.Printf(
" GPS Lat %10.5f Lon %10.5f ",
gLat,
gLon);
5575 if (std::isnan(
gCog))
5576 cog.Printf(
"COG ----- ");
5578 cog.Printf(
"COG %10.5f ",
gCog);
5581 if (std::isnan(
gSog))
5582 sog.Printf(
"SOG ----- ");
5584 sog.Printf(
"SOG %6.2f " + getUsrSpeedUnit(), toUsrSpeed(
gSog));
5590 data.Printf(
" DR Lat %10.5f Lon %10.5f",
gLat,
gLon);
5593 wxLogMessage(navmsg);
5594 g_loglast_time = lognow;
5596 int bells = (hourLOC % 4) * 2;
5597 if (minuteLOC != 0) bells++;
5598 if (!bells) bells = 8;
5600 if (g_bPlayShipsBells && ((minuteLOC == 0) || (minuteLOC == 30))) {
5601 m_BellsToPlay = bells;
5602 wxCommandEvent ev(BELLS_PLAYED_EVTYPE);
5603 wxPostEvent(
this, ev);
5610 CheckToolbarPosition();
5614 if (ProcessQuitFlag())
return;
5616 if (bDBUpdateInProgress)
return;
5619 FrameTenHzTimer.Stop();
5621 ProcessDeferredTrackOn();
5623 ProcessAnchorWatch();
5624 ProcessLogAndBells();
5626 if (ShouldRestartTrack()) TrackDailyRestart();
5629 if (g_bSleep && !AnchorAlertOn1 && !AnchorAlertOn2) {
5630 FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
5631 FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
5637 if (
gSog > 3.0) g_bCruising =
true;
5643 wxString sogcog(
"SOG --- " + getUsrSpeedUnit() + +
" " +
5645 if (GetStatusBar()) SetStatusText(sogcog, STAT_FIELD_SOGCOG);
5651 bool bnew_view =
false;
5652 if (!g_btenhertz) bnew_view = DoChartUpdate();
5659 bool bactiveRouteUpdate =
RoutemanGui(*g_pRouteMan).UpdateProgress();
5662 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5665 cc->DrawBlinkObjects();
5668 if (bactiveRouteUpdate) {
5675 cc->SetOwnShipState(SHIP_NORMAL);
5677 if (cc->GetQuiltMode()) {
5678 double erf = cc->GetQuiltMaxErrorFactor();
5679 if (erf > 0.02) cc->SetOwnShipState(SHIP_LOWACCURACY);
5681 if (cc->m_singleChart) {
5682 if (cc->m_singleChart->GetChart_Error_Factor() > 0.02)
5683 cc->SetOwnShipState(SHIP_LOWACCURACY);
5687 if (!
bGPSValid) cc->SetOwnShipState(SHIP_INVALID);
5690 (bVelocityValid != m_last_bVelocityValid) ||
5691 (!isnan(
gHdt) && (
gHdt != m_last_hdt))) {
5692 if (!g_bopengl) cc->UpdateShips();
5700 m_last_bVelocityValid = bVelocityValid;
5705 bool brq_dynamic =
false;
5707 auto *pplugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
5708 for (
unsigned int i = 0; i < pplugin_array->GetCount(); i++) {
5710 if (pic->m_enabled && pic->m_init_state) {
5711 if (pic->
m_cap_flag & WANTS_DYNAMIC_OPENGL_OVERLAY_CALLBACK) {
5718 if (brq_dynamic) bnew_view =
true;
5722 if (AnchorAlertOn1 || AnchorAlertOn2) bnew_view =
true;
5725 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5730 if (cc->GetglCanvas()) {
5732 bool b_rotate = cc->GetUpMode() != NORTH_UP_MODE;
5734 if ((!g_btenhertz)) {
5735 if (cc->m_bFollow) {
5736 cc->DoCanvasUpdate();
5753 if ((!cc->m_bFollow) || (cc->GetUpMode() != NORTH_UP_MODE)) {
5767 if (g_pais_query_dialog_active && g_pais_query_dialog_active->IsShown())
5768 g_pais_query_dialog_active->UpdateText();
5771 if (g_pAISTargetList && (0 == (g_tick % (5))))
5772 g_pAISTargetList->UpdateAISTargetList();
5775 UpdateGPSCompassStatusBoxes();
5780 console->RefreshConsoleData();
5787 if (m_bdefer_resize) {
5788 if (0 == (g_tick % (5))) {
5789 printf(
"___RESIZE\n");
5790 SetSize(m_defer_size);
5792 m_bdefer_resize =
false;
5799 FrameTimer1.Start(TIMER_GFRAME_1 * 3, wxTIMER_CONTINUOUS);
5801 FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
5802 FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
5806double MyFrame::GetMag(
double a,
double lat,
double lon) {
5807 double Variance = std::isnan(
gVar) ? g_UserVar :
gVar;
5808 auto loader = PluginLoader::GetInstance();
5809 if (loader && loader->IsPlugInAvailable(
"WMM")) {
5816 wxDateTime now = wxDateTime::Now();
5817 SendJSON_WMM_Var_Request(lat, lon, now);
5818 if (fabs(gQueryVar) < 360.0)
5819 Variance = gQueryVar;
5821 return toMagnetic(a, Variance);
5824bool MyFrame::SendJSON_WMM_Var_Request(
double lat,
double lon,
5830 v[
"Year"] = date.GetYear();
5831 v[
"Month"] = date.GetMonth();
5832 v[
"Day"] = date.GetDay();
5834 SendJsonMessageToAllPlugins(
"WMM_VARIATION_REQUEST", v);
5840void MyFrame::TouchAISActive() {
5842 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5844 if (cc) cc->TouchAISToolActive();
5848void MyFrame::UpdateAISTool() {
5852 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5854 if (cc) cc->UpdateAISTBTool();
5859void MyFrame::OnFrameTCTimer(wxTimerEvent &event) {
5861 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5863 if (cc) cc->SetbTCUpdate(
true);
5866 RefreshAllCanvas(
false);
5871void MyFrame::OnFrameCOGTimer(wxTimerEvent &event) {
5875 bool b_rotate =
false;
5876 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5878 if (cc) b_rotate |= (cc->GetUpMode() != NORTH_UP_MODE);
5882 FrameCOGTimer.Stop();
5889 int period_ms = 100;
5891 FrameCOGTimer.Start(period_ms, wxTIMER_CONTINUOUS);
5894void MyFrame::DoCOGSet() {
5896 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5898 if (cc) cc->DoCanvasCOGSet();
5902void RenderShadowText(wxDC *pdc, wxFont *pFont, wxString &str,
int x,
int y) {
5908 wxFont oldfont = pdc->GetFont();
5910 pdc->SetFont(*pFont);
5911 pdc->SetTextForeground(GetGlobalColor(
"CHGRF"));
5912 pdc->SetBackgroundMode(wxTRANSPARENT);
5914 pdc->DrawText(str, x, y + 1);
5915 pdc->DrawText(str, x, y - 1);
5916 pdc->DrawText(str, x + 1, y);
5917 pdc->DrawText(str, x - 1, y);
5919 pdc->SetTextForeground(GetGlobalColor(
"CHBLK"));
5921 pdc->DrawText(str, x, y);
5923 pdc->SetFont(oldfont);
5927void MyFrame::UpdateRotationState(
double rotation) {
5929 g_bCourseUp =
false;
5931 if (fabs(rotation) > .001) {
5932 SetMenubarItemState(ID_MENU_CHART_COGUP,
false);
5933 SetMenubarItemState(ID_MENU_CHART_NORTHUP,
true);
5935 m_pMenuBar->SetLabel(ID_MENU_CHART_NORTHUP, _(
"Rotated Mode"));
5938 SetMenubarItemState(ID_MENU_CHART_COGUP, g_bCourseUp);
5939 SetMenubarItemState(ID_MENU_CHART_NORTHUP, !g_bCourseUp);
5941 m_pMenuBar->SetLabel(ID_MENU_CHART_NORTHUP, _(
"North Up Mode"));
5945 UpdateGPSCompassStatusBoxes(
true);
5949void MyFrame::UpdateGPSCompassStatusBoxes(
bool b_force_new) {
5951 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5953 if (cc) cc->UpdateGPSCompassStatusBox(b_force_new);
5959int MyFrame::GetApplicationMemoryUse() {
5965 wxWindow *fWin = wxWindow::FindFocus();
5967 wxArrayString outputArray;
5968 wxString cmd(
"ps --no-headers -o vsize ");
5969 unsigned long pid = wxGetProcessId();
5971 cmd1.Printf(
"%ld", pid);
5973 wxExecute(cmd, outputArray);
5975 if (outputArray.GetCount()) {
5976 wxString s = outputArray.Item(0);
5978 if (s.ToLong(&vtmp)) memsize = vtmp;
5981 if (fWin) fWin->SetFocus();
5987 PROCESS_MEMORY_COUNTERS pmc;
5989 unsigned long processID = wxGetProcessId();
5991 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE,
5993 if (NULL == hProcess)
return 0;
5995 if (GetProcessMemoryInfo(hProcess, &pmc,
sizeof(pmc))) {
6013 memsize = pmc.WorkingSetSize / 1024;
6016 CloseHandle(hProcess);
6023double MyFrame::GetBestVPScale(
ChartBase *pchart) {
6024 return GetPrimaryCanvas()->GetBestVPScale(pchart);
6027void MyFrame::SetChartUpdatePeriod() {
6030 g_ChartUpdatePeriod = 0;
6035 bool bskewdc =
false;
6036 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6039 if (!g_bopengl && !cc->GetVP().b_quilt) {
6040 if (fabs(cc->GetVP().
skew) > 0.0001) bskewdc =
true;
6042 if (cc->m_bFollow) g_ChartUpdatePeriod = 1;
6046 if (bskewdc) g_ChartUpdatePeriod = g_SkewCompUpdatePeriod;
6048 m_ChartUpdatePeriod = g_ChartUpdatePeriod;
6053 cc->UpdateCanvasControlBar();
6056void MyFrame::selectChartDisplay(
int type,
int family) {
6058 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6060 if (cc) cc->selectCanvasChartDisplay(type, family);
6063 UpdateGlobalMenuItems();
6072bool MyFrame::DoChartUpdate() {
6073 bool return_val =
false;
6076 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6078 if (cc) return_val |= cc->DoCanvasUpdate();
6084void MyFrame::MouseEvent(wxMouseEvent &event) {
6086 event.GetPosition(&x, &y);
6091#include <mach/mach.h>
6092#include <mach/message.h>
6093#include <mach/kern_return.h>
6094#include <mach/task_info.h>
6096#include <malloc/malloc.h>
6103#if defined(__linux__)
6104#include "sys/types.h"
6105#include "sys/sysinfo.h"
6108void MyFrame::DoPrint(
void) {
6110 g_PrintingInProgress =
true;
6113 GetPrimaryCanvas()->GetglCanvas()->Render();
6114 GetPrimaryCanvas()->GetglCanvas()->SwapBuffers();
6124 printer.Initialize(wxLANDSCAPE);
6125 printer.EnablePageNumbers(
false);
6128 bool tooltips_were_enabled = DisableTbarTooltips();
6129 printer.Print(
this, &printout);
6130 if (tooltips_were_enabled) {
6131 EnableTbarTooltips();
6150 g_PrintingInProgress =
false;
6153 GetPrimaryCanvas()->SetFocus();
6159 wxString message_ID =
event.GetID();
6160 wxString message_JSONText =
event.GetJSONText();
6168 if (message_ID ==
"WMM_VARIATION_BOAT") {
6169 nlohmann::json root;
6171 root = nlohmann::json::parse(message_JSONText);
6172 }
catch (nlohmann::json::exception &) {
6177 gVar = root[
"Decl"].get<
double>();
6178 }
catch (nlohmann::json::exception &) {
6184 if (message_ID ==
"WMM_VARIATION") {
6185 nlohmann::json root;
6187 root = nlohmann::json::parse(message_JSONText);
6188 }
catch (nlohmann::json::exception &) {
6191 wxString decl = root[
"Decl"].get<std::string>();
6193 decl.ToDouble(&decl_val);
6195 gQueryVar = decl_val;
6198 if (message_ID ==
"GRIB_TIMELINE") {
6201 v = nlohmann::json::parse(message_JSONText);
6202 }
catch (nlohmann::json::exception &) {
6203 wxLogMessage(
"GRIB_TIMELINE: JSON parse error");
6206 wxDateTime oldTimeSource = gTimeSource;
6208 if (v[
"Day"].get<int>() == -1) {
6209 gTimeSource = wxInvalidDateTime;
6210 wxLogMessage(
"GRIB_TIMELINE: Reset to system time");
6212 gTimeSource.Set(v[
"Day"].get<int>(),
6213 (wxDateTime::Month)v[
"Month"].get<int>(),
6214 v[
"Year"].get<int>(), v[
"Hour"].get<int>(),
6215 v[
"Minute"].get<int>(), v[
"Second"].get<int>());
6219 if (oldTimeSource != gTimeSource) {
6221 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6223 if (cc && (cc->GetbShowTide() || cc->GetbShowCurrent())) {
6228 cc->pCwin->Refresh(
false);
6234 if (message_ID ==
"OCPN_TRACK_REQUEST") {
6235 nlohmann::json root;
6236 wxString trk_id =
"";
6239 root = nlohmann::json::parse(message_JSONText);
6240 }
catch (nlohmann::json::exception &) {
6243 if (root.contains(
"Track_ID")) trk_id = root[
"Track_ID"].get<std::string>();
6246 v[
"Track_ID"] = trk_id;
6248 wxString name = wxEmptyString;
6249 if (ptrack->m_GUID == trk_id) {
6250 name = ptrack->GetName();
6251 if (name.IsEmpty()) {
6257 name = _(
"(Unnamed Track)");
6264 v[
"TotalNodes"] = ptrack->GetnPoints();
6265 for (
int j = 0; j < ptrack->GetnPoints(); j++) {
6267 v[
"lat"] = tp->m_lat;
6268 v[
"lon"] = tp->m_lon;
6271 SendJsonMessageToAllPlugins(
"OCPN_TRACKPOINTS_COORDS", v);
6276 SendJsonMessageToAllPlugins(
"OCPN_TRACKPOINTS_COORDS", v);
6278 }
else if (message_ID ==
"OCPN_ROUTE_REQUEST") {
6279 nlohmann::json root;
6282 root = nlohmann::json::parse(message_JSONText);
6283 }
catch (nlohmann::json::exception &) {
6287 if (root.contains(
"GUID")) guid = root[
"GUID"].get<std::string>();
6292 wxString name = wxEmptyString;
6294 if ((*it)->m_GUID == guid) {
6295 name = (*it)->m_RouteNameString;
6296 if (name.IsEmpty()) name = _(
"(Unnamed Route)");
6302 for (RoutePointList::iterator itp = (*it)->pRoutePointList->begin();
6303 itp != (*it)->pRoutePointList->end(); itp++) {
6304 w[i][
"lat"] = (*itp)->m_lat;
6305 w[i][
"lon"] = (*itp)->m_lon;
6306 w[i][
"Name"] = (*itp)->GetName();
6307 w[i][
"Description"] = (*itp)->GetDescription();
6308 w[i][
"GUID"] = (*itp)->m_GUID;
6309 w[i][
"ArrivalRadius"] = (*itp)->GetWaypointArrivalRadius();
6311 auto node = (*itp)->m_HyperlinkList->begin();
6312 if (node != (*itp)->m_HyperlinkList->end()) {
6314 while (node != (*itp)->m_HyperlinkList->end()) {
6316 v[i][
"WPLink" + wxString::Format(
"%d", n)] = httpLink->Link;
6317 v[i][
"WPLinkDesciption" + wxString::Format(
"%d", n++)] =
6318 httpLink->DescrText;
6325 SendJsonMessageToAllPlugins(
"OCPN_ROUTE_RESPONSE", v);
6331 SendJsonMessageToAllPlugins(
"OCPN_ROUTE_RESPONSE", v);
6332 }
else if (message_ID ==
"OCPN_ROUTELIST_REQUEST") {
6333 nlohmann::json root;
6336 root = nlohmann::json::parse(message_JSONText);
6337 }
catch (nlohmann::json::exception &) {
6340 if (root.contains(
"mode")) {
6341 if (root[
"mode"].get<std::string>() ==
"Track") route =
false;
6346 for (RouteList::iterator it =
pRouteList->begin();
6348 wxString name = (*it)->m_RouteNameString;
6349 if (name.IsEmpty()) name = _(
"(Unnamed Route)");
6351 v[i][
"error"] =
false;
6352 v[i][
"name"] = name;
6353 v[i][
"GUID"] = (*it)->m_GUID;
6354 v[i][
"active"] = (*it)->IsActive();
6359 wxString name = ptrack->GetName();
6360 if (name.IsEmpty()) {
6366 name = _(
"(Unnamed Track)");
6368 v[i][
"error"] =
false;
6369 v[i][
"name"] = name;
6370 v[i][
"GUID"] = ptrack->m_GUID;
6375 SendJsonMessageToAllPlugins(
"OCPN_ROUTELIST_RESPONSE", v);
6378 v[0][
"error"] =
true;
6379 SendJsonMessageToAllPlugins(
"OCPN_ROUTELIST_RESPONSE", v);
6381 }
else if (message_ID ==
"OCPN_ACTIVE_ROUTELEG_REQUEST") {
6383 v[0][
"error"] =
true;
6386 v[0][
"error"] =
false;
6387 v[0][
"range"] =
g_pRouteMan->GetCurrentRngToActivePoint();
6388 v[0][
"bearing"] =
g_pRouteMan->GetCurrentBrgToActivePoint();
6389 v[0][
"XTE"] =
g_pRouteMan->GetCurrentXTEToActivePoint();
6390 v[0][
"active_route_GUID"] =
g_pRouteMan->GetpActiveRoute()->GetGUID();
6391 v[0][
"active_waypoint_lat"] =
6393 v[0][
"active_waypoint_lon"] =
6397 SendJsonMessageToAllPlugins(
"OCPN_ACTIVE_ROUTELEG_RESPONSE", v);
6401void MyFrame::FilterCogSog() {
6402 if (g_bfilter_cogsog) {
6404 double cog_last =
gCog;
6407 for (
int i = g_COGFilterSec - 1; i > 0; i--)
6408 COGFilterTable[i] = COGFilterTable[i - 1];
6409 COGFilterTable[0] = cog_last;
6412 if (!std::isnan(cog_last)) {
6414 double sum = 0., count = 0;
6415 for (
int i = 0; i < g_COGFilterSec; i++) {
6416 double adder = COGFilterTable[i];
6417 if (std::isnan(adder))
continue;
6419 if (fabs(adder - cog_last) > 180.) {
6420 if ((adder - cog_last) > 0.)
6433 else if (sum >= 360.)
6440 double sog_last =
gSog;
6443 for (
int i = g_SOGFilterSec - 1; i > 0; i--)
6444 SOGFilterTable[i] = SOGFilterTable[i - 1];
6445 SOGFilterTable[0] = sog_last;
6448 if (!std::isnan(
gSog)) {
6449 double sum = 0., count = 0;
6450 for (
int i = 0; i < g_SOGFilterSec; i++) {
6451 if (std::isnan(SOGFilterTable[i]))
continue;
6453 sum += SOGFilterTable[i];
6463void MyFrame::LoadHarmonics() {
6466 ptcmgr->LoadDataSources(TideCurrentDataSet);
6468 bool b_newdataset =
false;
6471 for (
auto a :
ptcmgr->GetDataSet()) {
6472 bool b_foundi =
false;
6473 for (
auto b : TideCurrentDataSet) {
6480 b_newdataset =
true;
6485 for (
auto a : TideCurrentDataSet) {
6486 bool b_foundi =
false;
6487 for (
auto b :
ptcmgr->GetDataSet()) {
6494 b_newdataset =
true;
6499 if (b_newdataset)
ptcmgr->LoadDataSources(TideCurrentDataSet);
6503void MyFrame::ActivateAISMOBRoute(
const AisTargetData *ptarget) {
6504 if (!ptarget)
return;
6507 wxDateTime mob_time = wxDateTime::Now();
6508 wxString mob_label(_(
"AIS MAN OVERBOARD"));
6509 mob_label += _(
" on ");
6510 mob_label += ocpn::toUsrDateTimeFormat(mob_time);
6513 mob_label, wxEmptyString);
6514 pWP_MOB->SetShared(
true);
6516 pSelect->AddSelectableRoutePoint(ptarget->Lat, ptarget->Lon, pWP_MOB);
6518 NavObj_dB::GetInstance().InsertRoutePoint(pWP_MOB);
6520 pWP_MOB->SetUseSca(
false);
6528 wxString(_(
"Own ship")), wxEmptyString);
6530 pWP_MOB->SetUseSca(
false);
6537 pSelect->AddSelectableRouteSegment(ptarget->Lat, ptarget->Lon,
gLat,
gLon,
6553 SendJsonMessageToAllPlugins(
"OCPN_MAN_OVERBOARD", v);
6556 if (RouteManagerDialog::getInstanceFlag()) {
6563 RefreshAllCanvas(
false);
6565 wxString mob_message(_(
"AIS MAN OVERBOARD"));
6566 mob_message += _(
" Time: ");
6567 mob_message += ocpn::toUsrDateTimeFormat(mob_time);
6568 mob_message += _(
" Ownship Position: ");
6569 mob_message += toSDMM(1,
gLat);
6571 mob_message += toSDMM(2,
gLon);
6572 mob_message += _(
" MOB Position: ");
6573 mob_message += toSDMM(1, ptarget->Lat);
6575 mob_message += toSDMM(2, ptarget->Lon);
6576 wxLogMessage(mob_message);
6579void MyFrame::UpdateAISMOBRoute(
const AisTargetData *ptarget) {
6583 OwnPoint->m_lat =
gLat;
6584 OwnPoint->m_lon =
gLon;
6586 pSelect->DeleteSelectableRoutePoint(OwnPoint);
6591 MOB_Point->m_lat = ptarget->Lat;
6592 MOB_Point->m_lon = ptarget->Lon;
6594 pSelect->DeleteSelectableRoutePoint(MOB_Point);
6595 pSelect->AddSelectableRoutePoint(ptarget->Lat, ptarget->Lon, MOB_Point);
6597 pSelect->UpdateSelectableRouteSegments(OwnPoint);
6598 pSelect->UpdateSelectableRouteSegments(MOB_Point);
6601 RefreshAllCanvas(
false);
6604 wxDateTime mob_time = wxDateTime::Now();
6606 wxString mob_message(_(
"AIS MAN OVERBOARD UPDATE"));
6607 mob_message += _(
" Time: ");
6608 mob_message += ocpn::toUsrDateTimeFormat(mob_time);
6609 mob_message += _(
" Ownship Position: ");
6610 mob_message += toSDMM(1,
gLat);
6612 mob_message += toSDMM(2,
gLon);
6613 mob_message += _(
" MOB Position: ");
6614 mob_message += toSDMM(1, ptarget->Lat);
6616 mob_message += toSDMM(2, ptarget->Lon);
6618 wxLogMessage(mob_message);
6622void MyFrame::applySettingsString(wxString settings) {
6624 int last_UIScaleFactor = g_GUIScaleFactor;
6625 bool previous_expert = g_bUIexpert;
6626 g_last_ChartScaleFactor = g_ChartScaleFactor;
6627 ArrayOfCDI *pNewDirArray =
new ArrayOfCDI;
6630 g_Platform->platformApplyPrivateSettingsString(settings, pNewDirArray);
6636 if (g_last_ChartScaleFactor != g_ChartScaleFactor) rr |= S52_CHANGED;
6638 if (rr & S52_CHANGED) {
6640 ps52plib->FlushSymbolCaches(ChartCtxFactory());
6642 ->ClearCNSYLUPArray();
6643 ps52plib->GenerateStateHash();
6647 ProcessOptionsDialog(rr, pNewDirArray);
6652 bool b_newToolbar =
false;
6654 if (g_GUIScaleFactor != last_UIScaleFactor) b_newToolbar =
true;
6656 if (previous_expert != g_bUIexpert) b_newToolbar =
true;
6658 if (rr & TOOLBAR_CHANGED) {
6659 b_newToolbar =
true;
6664 if (previous_expert && !g_bUIexpert) {
6665 androidForceFullRepaint();
6669 if (previous_expert != g_bUIexpert) g_Platform->applyExpertMode(g_bUIexpert);
6673 SetGPSCompassScale();
6675 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6677 if (cc) cc->GetCompass()->SetScaleFactor(g_compass_scalefactor);
6679 UpdateGPSCompassStatusBoxes(
true);
6682 AbstractPlatform::ShowBusySpinner();
6684 SetAllToolbarScale();
6688 AbstractPlatform::HideBusySpinner();
6690 RequestNewMasterToolbar(
true);
6697 UpdateControlBar(GetPrimaryCanvas());
6703 if (m_data_monitor->
IsVisible()) m_data_monitor->Raise();
6706#ifdef wxHAS_POWER_EVENTS
6707void MyFrame::OnSuspending(wxPowerEvent &event) {
6711 wxLogMessage(
"System suspend starting...");
6714void MyFrame::OnSuspended(wxPowerEvent &WXUNUSED(event)) {
6717 wxLogMessage(
"System is going to suspend.");
6720void MyFrame::OnSuspendCancel(wxPowerEvent &WXUNUSED(event)) {
6723 wxLogMessage(
"System suspend was cancelled.");
6726int g_last_resume_ticks;
6727void MyFrame::OnResume(wxPowerEvent &WXUNUSED(event)) {
6728 wxDateTime now = wxDateTime::Now();
6729 wxLogMessage(
"System resumed from suspend.");
6731 if ((now.GetTicks() - g_last_resume_ticks) > 5) {
6732 SystemEvents::GetInstance().
evt_resume.Notify();
6734 wxLogMessage(
"Restarting streams.");
6735 g_last_resume_ticks = now.GetTicks();
6739 g_pMUX->ClearStreams();
6741 g_pMUX->StartAllStreams();
6750 if (IsMaximized()) {
6755 wxSize sz = GetSize();
6756 SetSize(wxSize(sz.x - 1, sz.y));
6768void MyFrame::RequestNewMasterToolbar(
bool bforcenew) {
6769 bool btbRebuild =
false;
6771 bool b_reshow =
true;
6774 float ff = fabs(
g_MainToolbar->GetScaleFactor() - g_toolbar_scalefactor);
6775 if ((ff > 0.01f) || bforcenew) {
6785 long orient = g_Platform->GetDefaultToolbarOrientation();
6786 wxWindow *toolbarParent =
this;
6788 toolbarParent = GetPrimaryCanvas();
6791 toolbarParent, wxPoint(-1, -1), orient, g_toolbar_scalefactor,
6792 m_toolbar_callbacks);
6794 g_MainToolbar->SetToolbarHideMethod(TOOLBAR_HIDE_TO_FIRST_TOOL);
6801 g_bmasterToolbarFull =
true;
6805 CreateMasterToolbar();
6820bool MyFrame::CollapseGlobalToolbar() {
6822 m_nMasterToolCountShown = 1;
6826 g_bmasterToolbarFull =
false;
6842 ID_MASTERTOGGLE, style->GetToolIcon(
"MUI_menu", TOOLICON_NORMAL),
6843 wxITEM_NORMAL, _(
"Hide Toolbar"),
"MUI_menu");
6844 tic->m_bRequired =
true;
6849 ID_SETTINGS, style->GetToolIcon(
"MUI_settings", TOOLICON_NORMAL),
6850 wxITEM_NORMAL, _(
"Options"),
"MUI_settings");
6854 ID_MENU_ROUTE_NEW, style->GetToolIcon(
"MUI_route", TOOLICON_NORMAL),
6855 style->GetToolIcon(
"MUI_route", TOOLICON_TOGGLED), wxITEM_CHECK,
6856 wxString(_(
"Create Route")) <<
" (Ctrl-R)",
"MUI_route");
6861 ID_ROUTEMANAGER, style->GetToolIcon(
"MUI_RMD", TOOLICON_NORMAL),
6862 wxITEM_NORMAL, _(
"Route & Mark Manager"),
"MUI_RMD");
6866 ID_TRACK, style->GetToolIcon(
"MUI_track", TOOLICON_NORMAL),
6867 style->GetToolIcon(
"MUI_track", TOOLICON_TOGGLED), wxITEM_CHECK,
6868 _(
"Enable Tracking"),
"MUI_track");
6872 ID_COLSCHEME, style->GetToolIcon(
"MUI_colorscheme", TOOLICON_NORMAL),
6873 wxITEM_NORMAL, _(
"Change Color Scheme"),
"MUI_colorscheme");
6885 ID_PRINT, style->GetToolIcon(
"MUI_print", TOOLICON_NORMAL), wxITEM_NORMAL,
6886 _(
"Print Chart"),
"MUI_print");
6890 ID_ABOUT, style->GetToolIcon(
"MUI_help", TOOLICON_NORMAL), wxITEM_NORMAL,
6891 _(
"About OpenCPN"),
"MUI_help");
6895 AddDefaultPositionPlugInTools();
6899 ID_MOB, style->GetToolIcon(
"mob_btn", TOOLICON_NORMAL), wxITEM_NORMAL,
6900 wxString(_(
"Drop MOB Marker")) << _(
" (Ctrl-Space)"),
"mob_btn");
6911 ArrayOfPlugInToolbarTools tool_array =
6913 for (
unsigned int i = 0; i < tool_array.GetCount(); i++) {
6915 if (!pttc->b_viz)
continue;
6917 if (pttc->kind == wxITEM_CHECK) tb->ToggleTool(pttc->id, pttc->b_toggle);
6920 SetMasterToolbarItemState(ID_TRACK, g_bTrackActive);
6921 if (g_bTrackActive) {
6922 g_MainToolbar->SetToolShortHelp(ID_TRACK, _(
"Disable Tracking"));
6929bool MyFrame::CheckAndAddPlugInTool() {
6937 if (!tb)
return false;
6939 int n_tools = tb->GetToolsCount();
6943 ArrayOfPlugInToolbarTools tool_array =
6946 for (
unsigned int i = 0; i < tool_array.GetCount(); i++) {
6948 if (pttc->position == n_tools) {
6949 wxBitmap *ptool_bmp;
6951 switch (global_color_scheme) {
6952 case GLOBAL_COLOR_SCHEME_DAY:
6953 ptool_bmp = pttc->bitmap_day;
6956 case GLOBAL_COLOR_SCHEME_DUSK:
6957 ptool_bmp = pttc->bitmap_dusk;
6959 case GLOBAL_COLOR_SCHEME_NIGHT:
6960 ptool_bmp = pttc->bitmap_night;
6963 ptool_bmp = pttc->bitmap_day;
6968 pttc->id, *(ptool_bmp), pttc->kind, pttc->shortHelp,
"");
6970 tic->m_NormalIconSVG = pttc->pluginNormalIconSVG;
6971 tic->m_RolloverIconSVG = pttc->pluginRolloverIconSVG;
6972 tic->m_ToggledIconSVG = pttc->pluginToggledIconSVG;
6973 tic->m_bPlugin =
true;
6982 while (CheckAndAddPlugInTool()) {
6988bool MyFrame::AddDefaultPositionPlugInTools() {
6995 ArrayOfPlugInToolbarTools tool_array =
6998 for (
unsigned int i = 0; i < tool_array.GetCount(); i++) {
7002 if (!pttc->b_viz)
continue;
7004 if (pttc->position == -1)
7006 wxBitmap *ptool_bmp;
7008 switch (global_color_scheme) {
7009 case GLOBAL_COLOR_SCHEME_DAY:
7010 ptool_bmp = pttc->bitmap_day;
7012 case GLOBAL_COLOR_SCHEME_DUSK:
7013 ptool_bmp = pttc->bitmap_dusk;
7015 case GLOBAL_COLOR_SCHEME_NIGHT:
7016 ptool_bmp = pttc->bitmap_night;
7019 ptool_bmp = pttc->bitmap_day;
7024 pttc->id, *(ptool_bmp), pttc->kind, pttc->shortHelp,
"");
7026 tic->m_NormalIconSVG = pttc->pluginNormalIconSVG;
7027 tic->m_RolloverIconSVG = pttc->pluginRolloverIconSVG;
7028 tic->m_ToggledIconSVG = pttc->pluginToggledIconSVG;
7029 tic->m_bPlugin =
true;
7048typedef struct _MSW_COLOR_SPEC {
7050 wxString S52_RGB_COLOR;
7054MSW_COLOR_SPEC color_spec[] = {{COLOR_MENU,
"UIBCK", 0},
7055 {COLOR_MENUTEXT,
"UITX1", 0},
7056 {COLOR_BTNSHADOW,
"UIBCK", 0},
7059void SaveSystemColors() {
7073 MSW_COLOR_SPEC *pcspec = &color_spec[0];
7074 while (pcspec->COLOR_NAME != -1) {
7075 pcspec->SysRGB_COLOR = pGetSysColor(pcspec->COLOR_NAME);
7080void RestoreSystemColors() {
7081 int element[NCOLORS];
7082 int rgbcolor[NCOLORS];
7085 MSW_COLOR_SPEC *pcspec = &color_spec[0];
7086 while (pcspec->COLOR_NAME != -1) {
7087 element[i] = pcspec->COLOR_NAME;
7088 rgbcolor[i] = pcspec->SysRGB_COLOR;
7093 if (pSetSysColors) {
7094 pSetSysColors(i, (
unsigned long *)&element[0],
7095 (
unsigned long *)&rgbcolor[0]);
7101void SetSystemColors(ColorScheme cs) {
7103 int element[NCOLORS];
7104 int rgbcolor[NCOLORS];
7106 if ((GLOBAL_COLOR_SCHEME_DUSK == cs) || (GLOBAL_COLOR_SCHEME_NIGHT == cs)) {
7107 MSW_COLOR_SPEC *pcspec = &color_spec[0];
7108 while (pcspec->COLOR_NAME != -1) {
7109 wxColour color = GetGlobalColor(pcspec->S52_RGB_COLOR);
7110 rgbcolor[i] = (color.Red() << 16) + (color.Green() << 8) + color.Blue();
7111 element[i] = pcspec->COLOR_NAME;
7117 pSetSysColors(i, (
unsigned long *)&element[0],
7118 (
unsigned long *)&rgbcolor[0]);
7122 RestoreSystemColors();
7129static const WORD MAX_CONSOLE_LINES =
7134void RedirectIOToConsole()
7139 wxIntPtr lStdHandle;
7141 CONSOLE_SCREEN_BUFFER_INFO coninfo;
7151 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
7152 coninfo.dwSize.Y = MAX_CONSOLE_LINES;
7153 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
7157 lStdHandle = (wxIntPtr)GetStdHandle(STD_OUTPUT_HANDLE);
7158 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
7159 fp = _fdopen(hConHandle,
"w");
7161 setvbuf(stdout, NULL, _IONBF, 0);
7165 lStdHandle = (wxIntPtr)GetStdHandle(STD_INPUT_HANDLE);
7166 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
7167 fp = _fdopen(hConHandle,
"r");
7169 setvbuf(stdin, NULL, _IONBF, 0);
7173 lStdHandle = (wxIntPtr)GetStdHandle(STD_ERROR_HANDLE);
7174 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
7175 fp = _fdopen(hConHandle,
"w");
7177 setvbuf(stderr, NULL, _IONBF, 0);
7188 FontMgr::Get().SetLocale(g_locale);
7209 if (g_pais_query_dialog_active) {
7210 g_pais_query_dialog_active->Destroy();
7211 g_pais_query_dialog_active = NULL;
7214 auto alert_dlg_active =
7216 if (alert_dlg_active) {
7217 alert_dlg_active->Destroy();
7218 g_pais_alert_dialog_active =
nullptr;
7221 if (g_pAISTargetList) {
7223 g_pAISTargetList->Disconnect_decoder();
7224 g_pAISTargetList->Destroy();
7225 g_pAISTargetList = NULL;
7229 if (gFrame->m_pMenuBar) {
7230 gFrame->SetMenuBar(NULL);
7231 gFrame->m_pMenuBar->Destroy();
7232 gFrame->m_pMenuBar = NULL;
7234 gFrame->BuildMenuBar();
7237 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
7239 if (cc) cc->CanvasApplyLocale();
7244 wxString perspective;
7246 pConfig->Read(
"AUIPerspective", &perspective);
7260 bool bno_load =
false;
7261 wxAuiPaneInfoArray pane_array_val =
g_pauimgr->GetAllPanes();
7263 for (
unsigned int i = 0; i < pane_array_val.GetCount(); i++) {
7264 wxAuiPaneInfo pane = pane_array_val[i];
7265 if (perspective.Find(pane.name) == wxNOT_FOUND) {
7271 if (!bno_load)
g_pauimgr->LoadPerspective(perspective,
false);
7276 gFrame->RequestNewToolbars(
true);
7277 gFrame->RequestNewMasterToolbar(
true);
7284 : wxThread(wxTHREAD_JOINABLE) {
7285 m_filename = filename;
7296 newChart->SetNativeScale(m_scale);
7297 newChart->SetFullExtent(m_ext);
7299 newChart->FindOrCreateSenc(m_filename);
7304 wxString m_filename;
7310static double chart_dist(
int index) {
7316 if (cte.GetBBox().Contains(
gLat,
gLon))
7321 clon = (cte.GetLonMax() + cte.GetLonMin()) / 2;
7322 d = DistGreatCircle(cte.GetLatMax(), clon,
gLat,
gLon);
7323 t = DistGreatCircle(cte.GetLatMin(), clon,
gLat,
gLon);
7326 clat = (cte.GetLatMax() + cte.GetLatMin()) / 2;
7327 t = DistGreatCircle(clat, cte.GetLonMin(),
gLat,
gLon);
7329 t = DistGreatCircle(clat, cte.GetLonMax(),
gLat,
gLon);
7335WX_DEFINE_SORTED_ARRAY_INT(
int, MySortedArrayInt);
7336static int CompareInts(
int n1,
int n2) {
7337 double d1 = chart_dist(n1);
7338 double d2 = chart_dist(n2);
7339 return (
int)(d1 - d2);
7344 wxString chart_path;
7349WX_DEFINE_OBJARRAY(ArrayOfCompressTargets);
7351#include <wx/arrimpl.cpp>
7354void ParseAllENC(wxWindow *parent) {
7355 MySortedArrayInt idx_sorted_by_distance(CompareInts);
7363 for (
int i = 0; i <
ChartData->GetChartTableEntries(); i++) {
7366 if (CHART_TYPE_S57 != cte.GetChartType())
continue;
7368 idx_sorted_by_distance.Add(i);
7372 if (count == 0)
return;
7374 wxLogMessage(wxString::Format(
"ParseAllENC() count = %d", count));
7380 ArrayOfCompressTargets ct_array;
7381 for (
unsigned int j = 0; j < idx_sorted_by_distance.GetCount(); j++) {
7382 int i = idx_sorted_by_distance[j];
7385 double distance = chart_dist(i);
7387 wxString filename(cte.GetpFullPath(), wxConvUTF8);
7390 pct->distance = distance;
7391 pct->chart_path = filename;
7393 ct_array.push_back(pct);
7396 int thread_count = 0;
7399 if (g_nCPUCount > 0)
7400 thread_count = g_nCPUCount;
7402 thread_count = wxThread::GetCPUCount();
7404 if (thread_count < 1) {
7413 for(
int t = 0; t < thread_count; t++)
7417 wxGenericProgressDialog *prog =
nullptr;
7421 long style = wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
7422 wxPD_REMAINING_TIME | wxPD_CAN_SKIP;
7424 prog =
new wxGenericProgressDialog();
7426 prog->SetFont(*qFont);
7428 prog->Create(_(
"OpenCPN ENC Prepare"),
"Longgggggggggggggggggggggggggggg",
7429 count + 1, parent, style);
7438 prog->ShowWindowModal();
7447 for (
unsigned int j = 0; j < ct_array.size(); j++) {
7448 wxString filename = ct_array[j].chart_path;
7449 double distance = ct_array[j].distance;
7450 int index =
ChartData->FinddbIndex(filename);
7451 if (index < 0)
continue;
7454 ext.NLAT = cte.GetLatMax();
7455 ext.SLAT = cte.GetLatMin();
7456 ext.WLON = cte.GetLonMin();
7457 ext.ELON = cte.GetLonMax();
7459 int scale = cte.GetScale();
7462 msg.Printf(_(
"Distance from Ownship: %4.0f NMi"), distance);
7465 if (wxThread::IsMain()) {
7467 wxSize sz = prog->GetSize();
7472 prog->Update(count, msg, &skip);
7484 newChart->SetNativeScale(
scale);
7485 newChart->SetFullExtent(ext);
7486 newChart->DisableBackgroundSENC();
7488 newChart->FindOrCreateSenc(filename,
7492 if (wxThread::IsMain()) {
7493 msg.Printf(_(
"ENC Completed."));
7495 prog->Update(count, msg, &skip);
7505 for (
int t = 0;; t = (t + 1) % thread_count) {
7512 if (!workers[t]->IsAlive()) {
7525#if defined(__WXMSW__) || defined(__WXOSX__)
7532 for(
int t = 0; t<thread_count; t++) {
AboutFrameImpl * g_pAboutDlg
Global instance.
About * g_pAboutDlgLegacy
Global instance.
AisDecoder * g_pAIS
Global instance.
Class AisDecoder and helpers.
AisInfoGui * g_pAISGUI
Global instance.
Global state for AIS decoder.
Class AISTargetAlertDialog and helpers.
Class AISTargetListDialog.
Class AISTargetQueryDialog.
bool SendNoRouteRmbRmc(Routeman &routeman)
Send RMC + a faked RMB when there is no active route.
Autopilot output support.
Chart canvas configuration state
Class CanvasOptions and helpers – Canvas options Window/Dialog.
Wrapper for creating a ChartCtx based on global vars.
General chart base definitions.
ChartDB * ChartData
Global instance.
Charts database management
ChartGroupArray * g_pGroupArray
Global instance.
ChartCanvas * g_focusCanvas
Global instance.
arrayofCanvasPtr g_canvasArray
Global instance.
Generic Chart canvas base.
Dialog for displaying AIS target alerts.
Dialog for querying detailed information about an AIS target.
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &caption=_("Object Query"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=AIS_TARGET_QUERY_STYLE)
Creation.
Extends AboutFrame, providing implementation for various event handlers and additional methods.
The OpenCPN About dialog displaying information including version, authors, license,...
Minimal ChartCAnvas interface with very little dependencies.
Represents an active track that is currently being recorded.
Handles the AIS information GUI and sound alerts.
Base class for all chart types.
ChartCanvas - Main chart display and interaction component.
double m_cursor_lat
The latitude in degrees corresponding to the most recently processed cursor position.
double GetCanvasScaleFactor()
Return the number of logical pixels per meter for the screen.
void SetDisplaySizeMM(double size)
Set the width of the screen in millimeters.
void ZoomCanvasSimple(double factor)
Perform an immediate zoom operation without smooth transitions.
bool SetVPScale(double sc, bool b_refresh=true)
Sets the viewport scale while maintaining the center point.
float GetVPScale() override
Return ViewPort scale factor, in physical pixels per meter.
double m_cursor_lon
The longitude in degrees corresponding to the most recently processed cursor position.
void ZoomCanvas(double factor, bool can_zoom_to_cursor=true, bool stoptimer=true)
Perform a smooth zoom operation on the chart canvas by the specified factor.
bool SetViewPoint(double lat, double lon)
Centers the view on a specific lat/lon position.
Manages the chart database and provides access to chart data.
bool Create(ArrayOfCDI &dir_array, wxGenericProgressDialog *pprog)
Creates a new chart database from a list of directories.
bool Update(ArrayOfCDI &dir_array, bool bForce, wxGenericProgressDialog *pprog)
Updates the chart database.
Represents a user-defined collection of logically related charts.
void GenerateGLbmp()
In OpenGL mode, make the bitmap capture of the screen before the print method starts as to be sure th...
Overall logging handler, outputs to screen and log file.
bool IsVisible() const override
Return true if log is visible i.e., if it's any point using Add().
wxFont * FindOrCreateFont(int point_size, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underline=false, const wxString &facename=wxEmptyString, wxFontEncoding encoding=wxFONTENCODING_DEFAULT)
Creates or finds a matching font in the font cache.
void ScrubList()
Cleans up stale font entries after a locale change.
wxFont * GetFont(const wxString &TextElement, int requested_font_size=0)
Get a font object for a UI element.
obs::EventVar color_scheme_change
Notified when the day/dusk/night color scheme changes.
static void ReleaseInstance()
Release Instance.
static LocalServerApi & GetInstance()
Handle logging and forwarding of incoming n0183/n2k messages.
void OnFrameTimer1(wxTimerEvent &event)
Main application timer handler called approximately once per second.
void InitApiListeners()
Setup handling of events from the local ipc/dbus API.
void OnFrameTenHzTimer(wxTimerEvent &event)
High-frequency timer handler running at 10Hz for smooth navigation updates.
virtual bool IsVisible() const =0
Return true if log is visible i.e., if it's any point using Add().
virtual void Add(const Logline &l)=0
Add a formatted string to log output.
Custom event class for OpenCPN's notification system.
std::shared_ptr< const void > GetSharedPtr() const
Gets the event's payload data.
Data for a loaded plugin, including dl-loaded library.
int m_cap_flag
PlugIn Capabilities descriptor.
bool LoadAllPlugIns(bool enabled_plugins, bool keep_orphans=false)
Update catalog with imported metadata and load all plugin library files.
bool UnLoadAllPlugIns()
Unload allplugins i.
bool UpdatePlugIns()
Update the GetPlugInArray() list by reloading all plugins from disk.
const ArrayOfPlugIns * GetPlugInArray()
Return list of currently loaded plugins.
bool DeactivateAllPlugIns()
Deactivate all plugins.
static PrintDialog & GetInstance()
Get instance to handle the print process,.
AbstractRestServer implementation and interface to underlying IO thread.
std::string GetEndpoint() override
Return HTTPS url to local rest server.
Represents a waypoint or mark within the navigation system.
bool m_bIsolatedMark
Flag indicating if the waypoint is a standalone mark.
bool m_bShowName
Flag indicating if the waypoint name should be shown.
Represents a navigational route in the navigation system.
wxString m_RouteStartString
Name or description of the route's starting point.
bool m_bDeleteOnArrival
Flag indicating whether the route should be deleted once navigation reaches the end.
wxString m_RouteEndString
Name or description of the route's ending point.
RoutePoint * m_pRouteActivePoint
Pointer to the currently active waypoint within this route.
wxString m_RouteNameString
User-assigned name for the route.
wxString m_GUID
Globally unique identifier for this route.
bool ActivateRoute(Route *pRouteToActivate, RoutePoint *pStartPoint=NULL)
Activates a route for navigation.
obs::EventVar evt_resume
Notified when resuming from hibernate.
Represents a single point in a track.
wxDateTime GetCreateTime(void)
Retrieves the creation timestamp of a track point as a wxDateTime object.
Represents a track, which is a series of connected track points.
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
double rotation
Rotation angle of the viewport in radians.
double skew
Angular distortion (shear transform) applied to the viewport in radians.
double clon
Center longitude of the viewport in degrees.
double clat
Center latitude of the viewport in degrees.
Encapsulates persistent canvas configuration.
double iLat
Latitude of the center of the chart, in degrees.
bool bShowOutlines
Display chart outlines.
wxSize canvasSize
Canvas dimensions.
bool bShowDepthUnits
Display depth unit indicators.
double iLon
Longitude of the center of the chart, in degrees.
double iRotation
Initial rotation angle in radians.
bool bCourseUp
Orient display to course up.
bool bQuilt
Enable chart quilting.
bool bFollow
Enable vessel following mode.
double iScale
Initial chart scale factor.
bool bShowGrid
Display coordinate grid.
ChartCanvas * canvas
Pointer to associated chart canvas.
bool bShowCurrents
Display current information.
bool bShowTides
Display tide information.
bool bLookahead
Enable lookahead mode.
bool bHeadUp
Orient display to heading up.
wxRect GetRect(void) const
Return the coordinates of the compass widget, in physical pixels relative to the canvas window.
Device context class that can use either wxDC or OpenGL for drawing.
virtual void OnToolbarToolCallback(int id)
Handles toolbar tool clicks.
Represents an S57 format electronic navigational chart in OpenCPN.
CM93OffsetDialog * g_pCM93OffsetDialog
Global instance.
Class cm93chart and helpers – CM93 chart state.
Global variables reflecting command line options and arguments.
wxColorHashMap * pcurrent_user_color_hash
Global instance.
Global color handling by name.
CommBridge class and helpers.
Communication drivers factory and support.
Driver registration container, a singleton.
NMEA Data Multiplexer Object.
Raw messages layer, supports sending and recieving navmsg messages.
Variables maintained by comm stack, read-only access for others.
APConsole * console
Global instance.
Primary navigation console display for route and vessel tracking.
Config file user configuration interface.
bool g_always_send_rmb_rmc
Always send RMB and RMC n0183 messages even if there is no active route.
double g_COGAvg
Debug only usage.
int g_COGAvgSec
COG average period for Course Up Mode (sec)
std::vector< size_t > g_config_display_size_mm
Size of pysical screen in millimeters.
double g_display_size_mm
Physical display width (mm)
Global variables stored in configuration file.
Options | Connections GUI tab managing connections
Extern C linked utilities.
New NMEA Debugger successor main window.
std::vector< OCPN_MonitorInfo > g_monitor_info
Information about the monitors connected to the system.
OpenGL chart rendering canvas.
glTextureManager * g_glTextureManager
Global instance.
Hooks into gui available in model.
Misc GUI event vars, a singleton.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
General purpose GUI support.
size_t g_current_monitor
Current monitor displaying main application frame.
double vLat
Virtual lat from chcanv popup.
double vLon
Virtual lon from chcanv popup.
bool b_inCompressAllCharts
Flag to control adaptive UI scaling.
int g_NeedDBUpdate
0 - No update needed, 1 - Update needed because there is no chart database, inform user 2 - Start upd...
double g_current_monitor_dip_px_ratio
ratio to convert between DIP and physical pixels.
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
GUI constant definitions.
The local API has a server side handling commands and a client part issuing commands.
Enhanced logging interface on top of wx/log.h.
MarkInfoDlg * g_pMarkInfoDialog
global instance
Waypoint properties maintenance dialog.
MUI (Modern User Interface) Control bar.
Multiplexer class and helpers.
double AnchorDistFix(double const d, double const AnchorPointMinDist, double const AnchorPointMaxDist)
Return constrained value of d so that AnchorPointMinDist < abs(d) < AnchorPointMaxDist.
MySQL based storage for routes, tracks, etc.
MyConfig * pConfig
Global instance.
Navigation Utility Functions without GUI dependencies.
User notifications manager.
OCPN_AUIManager * g_pauimgr
Global instance.
MyFrame * gFrame
Global instance.
PlugIn Object Definition/API.
wxWindow * GetOCPNCanvasWindow()
Gets OpenCPN's main canvas window.
wxFont * FindOrCreateFont_PlugIn(int point_size, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underline, const wxString &facename, wxFontEncoding encoding)
Creates or finds a font in the font cache.
double OCPN_GetDisplayContentScaleFactor()
Gets content scaling factor for current display.
void JumpToPosition(double lat, double lon, double scale)
Centers chart display on specified position at given scale.
wxWindow * GetCanvasUnderMouse()
Gets canvas window under mouse cursor.
void SendPluginMessage(wxString message_id, wxString message_body)
Sends message to other plugins.
Miscellaneous utilities, many of which string related.
options * g_options
Global instance.
bool bGPSValid
Indicate whether the Global Navigation Satellite System (GNSS) has a valid position.
double gHdm
Magnetic heading in degrees (0-359.99).
double gVar
Magnetic variation in degrees.
double gHdt
True heading in degrees (0-359.99).
double gLat
Vessel's current latitude in decimal degrees.
double gCog
Course over ground in degrees (0-359.99).
double gSog
Speed over ground in knots.
double gLon
Vessel's current longitude in decimal degrees.
Position, course, speed, etc.
Tools to send data to plugins.
Low level code to load plugins from disk, notably the PluginLoader class.
PlugInManager * g_pi_manager
Global instance.
PlugInManager and helper classes – Mostly gui parts (dialogs) and plugin API stuff.
Generic, styled prit dialog.
Print chart canvas mix-in.
wxRect g_blink_rect
Global instance.
Purpose: Track and Trackpoint drawing stuff.
RoutePropDlgImpl * pRoutePropDialog
Global instance.
RoutePoint * pAnchorWatchPoint2
Global instance.
Routeman * g_pRouteMan
Global instance.
RouteList * pRouteList
Global instance.
RoutePoint * pAnchorWatchPoint1
Global instance.
Route * pAISMOBRoute
Global instance.
RouteManagerDialog * pRouteManagerDialog
Global instance.
S57QueryDialog * g_pObjectQueryDialog
Global instance.
S57 object query result window.
Select * pSelect
Global instance.
Selected route, segment, waypoint, etc.
const wxEventType wxEVT_OCPN_BUILDSENCTHREAD
Global instance.
SENCThreadManager * g_SencThreadManager
Global instance.
Class StdIcon, typically a small monochrome svg icon.
Represents an entry in the chart table, containing information about a single chart.
A generic position and navigation data structure.
double kCog
Course over ground in degrees.
double kHdt
True heading in degrees.
int nSats
Number of satellites used in the fix.
double kHdm
Magnetic heading in degrees.
time_t FixTime
UTC time of fix.
double kLat
Latitude in decimal degrees.
double kSog
Speed over ground in knots.
double kVar
Magnetic variation in degrees.
double kLon
Longitude in decimal degrees.
Suspend/resume and new devices events exchange point.
Tide and currents window.
TCMgr * ptcmgr
Global instance.
Tide and Current Manager @TODO Add original author copyright.
Timer identification constants.
ActiveTrack * g_pActiveTrack
global instance
std::vector< Track * > g_TrackList
Global instance.
Recorded track abstraction.
TrackPropDlg * pTrackPropDialog
Global instance.
void DestroyDeviceNotFoundDialogs()
Destroy all open "Device not found" dialog windows.
Access checks for comm devices and dongle.
Generic hardware events interface.
WaypointMan drawing stuff.