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());
473wxDEFINE_EVENT(BELLS_PLAYED_EVTYPE, wxCommandEvent);
475BEGIN_EVENT_TABLE(
MyFrame, wxFrame)
476EVT_CLOSE(MyFrame::OnCloseWindow)
477EVT_MENU(wxID_EXIT, MyFrame::OnExit)
478EVT_SIZE(MyFrame::OnSize)
479EVT_MOVE(MyFrame::OnMove)
480EVT_ICONIZE(MyFrame::OnIconize)
481EVT_MENU(-1, MyFrame::OnToolLeftClick)
482EVT_TIMER(INIT_TIMER, MyFrame::OnInitTimer)
484EVT_TIMER(FRAME_TC_TIMER, MyFrame::OnFrameTCTimer)
485EVT_TIMER(FRAME_COG_TIMER, MyFrame::OnFrameCOGTimer)
486EVT_TIMER(MEMORY_FOOTPRINT_TIMER, MyFrame::OnMemFootTimer)
488EVT_MAXIMIZE(MyFrame::OnMaximize)
489EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED,
490 MyFrame::RequestNewToolbarArgEvent)
491EVT_ERASE_BACKGROUND(MyFrame::OnEraseBackground)
493EVT_TIMER(RECAPTURE_TIMER, MyFrame::OnRecaptureTimer)
494EVT_TIMER(TOOLBAR_ANIMATE_TIMER, MyFrame::OnToolbarAnimateTimer)
495EVT_COMMAND(wxID_ANY, BELLS_PLAYED_EVTYPE, MyFrame::OnBellsFinished)
497#ifdef wxHAS_POWER_EVENTS
498EVT_POWER_SUSPENDING(MyFrame::OnSuspending)
499EVT_POWER_SUSPENDED(MyFrame::OnSuspended)
500EVT_POWER_SUSPEND_CANCEL(MyFrame::OnSuspendCancel)
501EVT_POWER_RESUME(MyFrame::OnResume)
512static
void onBellsFinishedCB(
void *ptr) {
513 auto framePtr =
static_cast<MyFrame *
>(ptr);
515 wxCommandEvent ev(BELLS_PLAYED_EVTYPE);
516 wxPostEvent(framePtr, ev);
521 auto msg = ev.GetString().ToStdString();
522 auto ¬eman = NotificationManager::GetInstance();
523 noteman.AddNotification(NotificationSeverity::kInformational, msg, 60);
526static NmeaLog *GetDataMonitor() {
527 auto w = wxWindow::FindWindowByName(kDataMonitorWindowName);
528 return dynamic_cast<NmeaLog *
>(w);
531MyFrame::MyFrame(
const wxString &title,
const wxPoint &pos,
const wxSize &size,
532 RestServer &rest_server, wxAuiDefaultDockArt *pauidockart,
533 OpenFileFunc open_gpx_file)
535 m_connections_dlg(nullptr),
537 m_pauidockart(pauidockart),
538 m_rest_server(rest_server),
539 m_open_gpx_file(open_gpx_file) {
551 m_ulLastNMEATicktime = 0;
552 m_data_monitor->Hide();
554 m_StatusBarFieldCount = g_Platform->GetStatusBarFieldCount();
558 m_load_errors_dlg_ctrl = std::make_unique<LoadErrorsDlgCtrl>(
this);
561 InitTimer.SetOwner(
this, INIT_TIMER);
563 m_initializing =
false;
564 m_toolbar_callbacks.render_gl_textures =
566 [&](
ocpnDC &dc,
float *coords,
float *uv) {
567 GetPrimaryCanvas()->GetglCanvas()->RenderTextures(
568 dc, coords, uv, 4, &GetPrimaryCanvas()->GetVP());
571 [&](
ocpnDC &dc,
float *coords,
float *uv) {};
575 FrameTimer1.SetOwner(
this, FRAME_TIMER_1);
578 FrameTCTimer.SetOwner(
this, FRAME_TC_TIMER);
581 FrameCOGTimer.SetOwner(
this, FRAME_COG_TIMER);
584 MemFootTimer.SetOwner(
this, MEMORY_FOOTPRINT_TIMER);
587 ToolbarAnimateTimer.SetOwner(
this, TOOLBAR_ANIMATE_TIMER);
589 FrameTenHzTimer.SetOwner(
this, FRANE_TENHZ_TIMER);
598 m_bTimeIsSet =
false;
599 m_bdefer_resize =
false;
602 for (
int i = 0; i < kMaxCogsogFilterSeconds; i++) {
603 COGFilterTable[i] = NAN;
604 SOGFilterTable[i] = NAN;
606 m_last_bGPSValid =
false;
607 m_last_bVelocityValid =
false;
617 for (
int i = 0; i < kMaxCogAverageSeconds; i++) COGTable[i] = NAN;
622 double process_noise_std = 1.0;
623 double measurement_noise_std = 0.5;
627 m_ChartUpdatePeriod = 1;
632 log_callbacks.log_is_active = [&]() {
633 auto log = GetDataMonitor();
634 return log && log->IsVisible();
636 log_callbacks.log_message = [&](
Logline ll) {
637 NmeaLog *monitor = GetDataMonitor();
640 g_pMUX =
new Multiplexer(log_callbacks, g_b_legacy_input_filter_behaviour);
643 ais_callbacks.confirm_stop_track = []() {
644 int r = OCPNMessageBox(
646 _(
"This AIS target has Persistent tracking selected by MMSI "
648 "A Persistent track recording will therefore be restarted for this "
650 "Do you instead want to stop Persistent tracking for this target?"),
651 _(
"OpenCPN Info"), wxYES_NO | wxCENTER, 60);
652 return r == wxID_YES;
654 ais_callbacks.get_target_mmsi = []() {
655 auto alert_dlg_active =
657 assert(alert_dlg_active);
658 return alert_dlg_active->Get_Dialog_MMSI();
666 wxLogMessage(
" **** Connect stuff");
672 Connect(wxEVT_OCPN_MSG,
673 (wxObjectEventFunction)(wxEventFunction)&MyFrame::OnEvtPlugInMessage);
681 (wxObjectEventFunction)(wxEventFunction)&MyFrame::OnSENCEvtThread);
689#if defined(__WXGTK__) || defined(__WXQT__)
690 wxIcon app_icon(opencpn);
698 wxDynamicLibrary dllUser32(
"user32.dll");
700 pSetSysColors = (SetSysColors_t)dllUser32.GetSymbol(
"SetSysColors");
701 pGetSysColor = (GetSysColor_t)dllUser32.GetSymbol(
"GetSysColor");
706 m_next_available_plugin_tool_id = ID_PLUGIN_BASE;
711 m_resizeTimer.SetOwner(
this, RESIZE_TIMER);
712 m_recaptureTimer.SetOwner(
this, RECAPTURE_TIMER);
714 assert(
g_pRouteMan != 0 &&
"g_pRouteMan not available");
715 m_routes_update_listener.Init(GuiEvents::GetInstance().on_routes_update,
716 [&](wxCommandEvent) { Refresh(); });
717 m_evt_drv_msg_listener.Init(CommDriverRegistry::GetInstance().evt_driver_msg,
719 m_update_statusbar_listener.Init(
720 GuiEvents::GetInstance().gframe_update_status_bar,
722 m_center_aistarget_listener.Init(
723 GuiEvents::GetInstance().on_center_ais_target, [&](
ObservedEvt &ev) {
724 auto ais_target = UnpackEvtPointer<AisTargetData>(ev);
725 CenterAisTarget(ais_target);
727 m_reload_charts_listener.Init(
728 GuiEvents::GetInstance().on_finalize_chartdbs,
729 [&](
ObservedEvt &ev) { FinalizeChartDBUpdate(); });
733 EnableFullScreenView();
735 int is_day = user_colors::GetColorScheme() == GLOBAL_COLOR_SCHEME_DAY ? 1 : 0;
741 FrameTenHzTimer.Stop();
756 (wxObjectEventFunction)(wxEventFunction)&MyFrame::OnEvtPlugInMessage);
762void MyFrame::FreezeCharts() {
765 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
767 if (cc && !cc->IsFrozen()) cc->Freeze();
771void MyFrame::CenterAisTarget(
772 const std::shared_ptr<const AisTargetData> &ais_target) {
780 double factor = cc->GetScaleValue() / 5000.0;
781 JumpToPosition(GetFocusCanvas(), ais_target->Lat, ais_target->Lon,
787void MyFrame::ThawCharts() {
790 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
792 if (cc && cc->IsFrozen()) cc->Thaw();
799 switch (event.type) {
800 case SENC_BUILD_STARTED:
803 case SENC_BUILD_DONE_NOERROR:
805 chart =
event.m_ticket->m_chart;
807 chart->PostInit(FULL_INIT, global_color_scheme);
809 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
811 if (cc) cc->ClearS52PLIBStateHash();
816 delete event.m_ticket;
818 case SENC_BUILD_DONE_ERROR:
826void MyFrame::RebuildChartDatabase() {
827 bool b_SetInitialPoint =
false;
830 ArrayOfCDI ChartDirArray;
831 pConfig->LoadChartDirArray(ChartDirArray);
833 if (ChartDirArray.GetCount()) {
838 _(
"OpenCPN needs to update the chart database from config file "
842 wxICON_INFORMATION | wxOK);
850 _(
"Rebuilding chart database from configuration file entries..."));
854 wxString dummy1 = _(
"Elapsed time : ");
855 wxString dummy2 = _(
"Estimated time : ");
856 wxString dummy3 = _(
"Remaining time : ");
857 wxGenericProgressDialog *pprog =
new wxGenericProgressDialog(
858 _(
"OpenCPN Chart Update"), line, 100, NULL,
859 wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
860 wxPD_REMAINING_TIME);
863 ChartData->SaveBinary(ChartListFileName);
873void MyFrame::OnBellsFinished(wxCommandEvent &event) {
874 int bells = wxMin(m_BellsToPlay, 2);
875 if (bells <= 0)
return;
877 wxString soundfile =
"sounds";
878 appendOSDirSlash(&soundfile);
879 soundfile += wxString(bells_sound_file_name[bells - 1], wxConvUTF8);
880 soundfile.Prepend(g_Platform->GetSharedDataDir());
881 wxLogMessage(
"Using bells sound file: " + soundfile);
883 o_sound::Sound *sound = bells_sound[bells - 1];
884 sound->SetFinishedCallback(onBellsFinishedCB,
this);
885 auto cmd_sound =
dynamic_cast<o_sound::SystemCmdSound *
>(sound);
886 if (cmd_sound) cmd_sound->SetCmd(g_CmdSoundString.mb_str(wxConvUTF8));
887 sound->Load(soundfile);
888 if (!sound->IsOk()) {
889 wxLogMessage(
"Failed to load bells sound file: " + soundfile);
893 m_BellsToPlay -= bells;
896void MyFrame::OnEraseBackground(wxEraseEvent &event) {}
898void MyFrame::OnMaximize(wxMaximizeEvent &event) {
905void MyFrame::ReloadAllVP() {
906 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
908 if (cc) cc->ReloadVP();
912void MyFrame::SetAndApplyColorScheme(ColorScheme cs) {
913 int is_day = cs == GLOBAL_COLOR_SCHEME_DAY ? 1 : 0;
916 global_color_scheme = cs;
919 case GLOBAL_COLOR_SCHEME_DAY:
922 case GLOBAL_COLOR_SCHEME_DUSK:
925 case GLOBAL_COLOR_SCHEME_NIGHT:
926 SchemeName =
"NIGHT";
933 m_pauidockart->SetMetric(wxAUI_DOCKART_GRADIENT_TYPE, wxAUI_GRADIENT_NONE);
935 m_pauidockart->SetColour(wxAUI_DOCKART_BORDER_COLOUR, wxColour(0, 0, 0));
936 m_pauidockart->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, 1);
937 m_pauidockart->SetColour(wxAUI_DOCKART_SASH_COLOUR, wxColour(0, 0, 0));
938 m_pauidockart->SetMetric(wxAUI_DOCKART_SASH_SIZE, 0);
939 m_pauidockart->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR,
941 m_pauidockart->SetColour(wxAUI_DOCKART_BACKGROUND_COLOUR, wxColour(0, 0, 0));
970 m_pauidockart->SetColour(wxAUI_DOCKART_SASH_COLOUR, wxColour(0, 0, 0));
971 m_pauidockart->SetMetric(wxAUI_DOCKART_SASH_SIZE, 6);
975 g_StyleManager->GetCurrentStyle()->SetColorScheme(cs);
977 if (ps52plib) ps52plib->SetPLIBColorScheme(SchemeName, ChartCtxFactory());
981 user_colors::GetMapByScheme(SchemeName.ToStdString());
986 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
989 cc->SetColorScheme(cs);
990 cc->GetWorldBackgroundChart()->SetColorScheme(cs);
991 cc->HideChartInfoWindow();
992 cc->SetQuiltChartHiLiteIndex(-1);
998 .SetColorScheme(cs, g_Platform->GetDisplayDPmm());
1010 g_pRouteMan->SetColorScheme(cs, g_Platform->GetDisplayDPmm());
1023 if (g_pais_query_dialog_active) {
1024 bool b_isshown = g_pais_query_dialog_active->IsShown();
1025 int n_mmsi = g_pais_query_dialog_active->GetMMSI();
1026 if (b_isshown) g_pais_query_dialog_active->Show(
false);
1028 g_pais_query_dialog_active->Close();
1031 g_pais_query_dialog_active->
Create(
1032 this, -1, _(
"AIS Target Query"),
1033 wxPoint(g_ais_query_dialog_x, g_ais_query_dialog_y));
1034 g_pais_query_dialog_active->SetMMSI(n_mmsi);
1035 g_pais_query_dialog_active->UpdateText();
1036 if (b_isshown) g_pais_query_dialog_active->Show();
1041 if (g_pAISTargetList) g_pAISTargetList->SetColorScheme();
1045 ApplyGlobalColorSchemetoStatusBar();
1047 UpdateAllToolbars(cs);
1052 bool btoolbarFull = g_bmasterToolbarFull;
1058 if (!btoolbarFull) {
1060 RequestNewMasterToolbar();
1062 CollapseGlobalToolbar();
1065 RequestNewMasterToolbar();
1074void MyFrame::ApplyGlobalColorSchemetoStatusBar() {
1075 if (m_pStatusBar != NULL) {
1076 m_pStatusBar->SetBackgroundColour(GetGlobalColor(
"UIBDR"));
1077 m_pStatusBar->ClearBackground();
1088void MyFrame::CancelAllMouseRoute() {
1090 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1092 if (cc) cc->CancelMouseRoute();
1096void MyFrame::CreateCanvasLayout(
bool b_useStoredSize) {
1104 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1112 for (
unsigned int i = 1; i <
g_canvasArray.GetCount(); i++) {
1121 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
1124 for (
unsigned int i = 1; i < config_array.GetCount(); i++) {
1125 config_array.Item(i)->canvas = NULL;
1131 for (
unsigned int i = 1; i <
g_canvasArray.GetCount(); i++) {
1136 switch (g_canvasConfig) {
1150 if (!cc->GetglCanvas()) cc->SetupGlCanvas();
1151 cc->GetglCanvas()->Show();
1154 config_array.Item(0)->canvas = cc;
1158 cc->ApplyCanvasConfig(config_array.Item(0));
1162 cc->ConfigureChartBar();
1163 cc->SetColorScheme(global_color_scheme);
1164 cc->GetCompass()->SetScaleFactor(g_compass_scalefactor);
1165 cc->SetShowGPS(
true);
1168 g_pauimgr->GetPane(cc).Name(
"ChartCanvas");
1170 g_pauimgr->GetPane(cc).CaptionVisible(
false);
1186 if (!cc->GetglCanvas()) cc->SetupGlCanvas();
1189 config_array.Item(0)->canvas = cc;
1191 cc->ApplyCanvasConfig(config_array.Item(0));
1194 cc->ConfigureChartBar();
1195 cc->SetColorScheme(global_color_scheme);
1196 cc->GetCompass()->SetScaleFactor(g_compass_scalefactor);
1197 cc->SetShowGPS(
false);
1200 g_pauimgr->GetPane(cc).Name(
"ChartCanvas");
1202 .CaptionVisible(
false)
1204 .CloseButton(
false);
1213 if (config_array.GetCount() < 2) {
1215 pcc->configIndex = 1;
1219 pcc->
canvasSize = wxSize(GetClientSize().x / 2, GetClientSize().y);
1220 config_array.Add(pcc);
1223 config_array.Item(1)->canvas = cc;
1225 cc->ApplyCanvasConfig(config_array.Item(1));
1228 cc->ConfigureChartBar();
1229 cc->SetColorScheme(global_color_scheme);
1230 cc->SetShowGPS(
true);
1234 g_pauimgr->GetPane(cc).Name(
"ChartCanvas2");
1236 .CaptionVisible(
false)
1238 .CloseButton(
false);
1239 g_pauimgr->GetPane(cc).RightDockable(
true);
1243 config_array.Item(1)->canvasSize =
1244 wxSize(GetClientSize().x / 2, GetClientSize().y);
1245 g_pauimgr->GetPane(cc).BestSize(GetClientSize().x / 2, GetClientSize().y);
1250 if (b_useStoredSize) {
1251 int ccw = config_array.Item(1)->canvasSize.x;
1252 int cch = config_array.Item(1)->canvasSize.y;
1255 if (ccw < GetClientSize().x / 10) {
1256 ccw = GetClientSize().x / 2;
1257 cch = GetClientSize().y;
1260 g_pauimgr->GetPane(cc).BestSize(ccw, cch);
1261 cc->SetSize(ccw, cch);
1279 console->SetColorScheme(global_color_scheme);
1284 g_pRouteMan->GetDlgContext().show_with_fresh_fonts();
1290void MyFrame::RequestNewToolbars(
bool bforcenew) {
1291 if (b_inCloseWindow) {
1295 BuildiENCToolbar(bforcenew, m_toolbar_callbacks);
1296 PositionIENCToolbar();
1305void MyFrame::UpdateAllToolbars(ColorScheme cs) {
1311void MyFrame::SetAllToolbarScale() {
1312 g_toolbar_scalefactor = g_Platform->GetToolbarScaleFactor(g_GUIScaleFactor);
1315void MyFrame::SetGPSCompassScale() {
1316 g_compass_scalefactor = g_Platform->GetCompassScaleFactor(g_GUIScaleFactor);
1320 wxPoint screenPoint = ::wxGetMousePosition();
1323 switch (g_canvasConfig) {
1325 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1328 if (canvas->GetScreenRect().Contains(
1332 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(1);
1335 if (canvas->GetScreenRect().Contains(
1342 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1345 if (canvas->GetScreenRect().Contains(
1346 canvas->ScreenToClient(screenPoint)))
1354int MyFrame::GetCanvasIndexUnderMouse() {
1355 wxPoint screenPoint = ::wxGetMousePosition();
1358 switch (g_canvasConfig) {
1360 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1363 if (canvas->GetScreenRect().Contains(
1367 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(1);
1370 if (canvas->GetScreenRect().Contains(
1377 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1380 if (canvas->GetScreenRect().Contains(
1381 canvas->ScreenToClient(screenPoint)))
1389bool MyFrame::DropMarker(
bool atOwnShip) {
1396 if (!canvas)
return false;
1403 new RoutePoint(lat, lon, g_default_wp_icon, wxEmptyString, wxEmptyString);
1405 pSelect->AddSelectableRoutePoint(lat, lon, pWP);
1407 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
1418 RefreshAllCanvas(
false);
1423void MyFrame::SwitchKBFocus(
ChartCanvas *pCanvas) {
1424 if (g_canvasConfig != 0) {
1427 int nTargetGTK = -1;
1429 wxWindow *source = FindFocus();
1435 switch (g_canvasConfig) {
1437 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(0);
1440 if (canvas && (canvas == test)) {
1445 cc = ConfigMgr::Get().GetCanvasConfigArray().Item(1);
1448 if (canvas && (canvas == test)) {
1456 int nfinalTarget = nTarget;
1458 nfinalTarget = nTargetGTK;
1460 target = ConfigMgr::Get()
1461 .GetCanvasConfigArray()
1466 target->Refresh(
true);
1477void MyFrame::FastClose() {
1479 FrameTenHzTimer.Stop();
1481 FrameTimer1.Start(1);
1485void MyFrame::OnExit(wxCommandEvent &event) {
1489void MyFrame::OnCloseWindow(wxCloseEvent &event) {
1492 if (b_inCloseWindow) {
1502 if (!g_bDeferredInitDone)
return;
1519 if (bDBUpdateInProgress)
return;
1521 b_inCloseWindow =
true;
1523 ::wxSetCursor(wxCURSOR_WAIT);
1527 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1529 if (cc && cc->IsMeasureActive()) {
1530 cc->CancelMeasureRoute();
1535 SendPreShutdownHookToPlugins();
1539 if (g_pAISTargetList) {
1540 wxAuiPaneInfo &pane =
g_pauimgr->GetPane(g_pAISTargetList);
1541 g_AisTargetList_perspective =
g_pauimgr->SavePaneInfo(pane);
1542 g_pauimgr->DetachPane(g_pAISTargetList);
1569 SetCursor(wxCURSOR_WAIT);
1571 RefreshAllCanvas(
true);
1577 RestoreScreenBrightness();
1588 wxPoint tbp_incanvas = GetPrimaryCanvas()->ScreenToClient(locn);
1589 g_iENCToolbarPosY = tbp_incanvas.y;
1590 g_iENCToolbarPosX = tbp_incanvas.x;
1594 g_bframemax = IsMaximized();
1597 FrameTenHzTimer.Stop();
1599 FrameCOGTimer.Stop();
1613 if (g_bAutoAnchorMark) {
1614 bool watching_anchor =
false;
1622 wxDateTime now = wxDateTime::Now();
1623 wxTimeSpan uptime = now.Subtract(g_start_time);
1625 if (!watching_anchor && (g_bCruising) && (
gSog < 0.5) &&
1626 (uptime.IsLongerThan(wxTimeSpan(0, 30, 0, 0))))
1631 if (g_declutter_anchorage) {
1632 for (
RoutePoint *pr : *pWayPointMan->GetWaypointList()) {
1633 if (pr->GetName().StartsWith(
"Anchorage")) {
1634 double a =
gLat - pr->m_lat;
1635 double b =
gLon - pr->m_lon;
1636 double l = sqrt((a * a) + (b * b));
1639 if ((l * 60. * 1852.) < (.25 * 1852.)) {
1641 NavObj_dB::GetInstance().DeleteRoutePoint(pr);
1642 pSelect->DeleteSelectablePoint(pr, SELTYPE_ROUTEPOINT);
1650 wxString name = now.Format();
1651 name.Prepend(_(
"Anchorage created "));
1657 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
1666 wxLogMessage(
"opencpn::MyFrame exiting cleanly.");
1670 NavObj_dB::GetInstance().Close();
1674 pConfig->DeleteGroup(
"/Routes");
1675 pConfig->DeleteGroup(
"/Marks");
1701 if (g_pAISTargetList) {
1702 g_pAISTargetList->Disconnect_decoder();
1703 g_pAISTargetList->Destroy();
1710 if (RouteManagerDialog::getInstanceFlag()) {
1727 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1729 if (cc) cc->Destroy();
1753 CommBridge::GetInstance().SaveConfig();
1773 auto ®istry = CommDriverRegistry::GetInstance();
1774 registry.CloseAllDrivers();
1777 for (
auto *cp : TheConnectionParams()) {
1782 while (pLayerList->size())
delete *pLayerList->begin();
1786 ReleaseApiListeners();
1789 g_bTempShowMenuBar =
false;
1791#define THREAD_WAIT_SECONDS 5
1801 wxLogMessage(
"Starting compressor pool drain");
1802 wxDateTime now = wxDateTime::Now();
1803 time_t stall = now.GetTicks();
1804 time_t end = stall + THREAD_WAIT_SECONDS;
1807 while (stall < end) {
1808 wxDateTime later = wxDateTime::Now();
1809 stall = later.GetTicks();
1812 msg.Printf(
"Time: %d Job Count: %d", n_comploop,
1821 fmsg.Printf(
"Finished compressor pool drain..Time: %d Job Count: %d",
1827 uninitIXNetSystem();
1831 wxLogMessage(
"gFrame destroyed.");
1834#ifndef USE_ANDROID_GLES2
1835 qDebug() <<
"Calling OnExit()";
1839 wxTheApp->ExitMainLoop();
1842void MyFrame::OnMove(wxMoveEvent &event) {
1843 auto idx = wxDisplay::GetFromWindow(
this);
1856 DEBUG_LOG <<
"Moved to " << idx
1857#if wxCHECK_VERSION(3, 1, 6)
1858 <<
" PPI: " << wxDisplay(idx).GetPPI().GetX() <<
"x"
1859 << wxDisplay(idx).GetPPI().GetY()
1860 <<
" SF wxDisplay: " << wxDisplay(idx).GetScaleFactor()
1862 <<
" Size wxDisplay: " << wxDisplay(idx).GetGeometry().GetWidth()
1863 <<
"x" << wxDisplay(idx).GetGeometry().GetHeight()
1864 <<
" MM wxDisplay: " << wxGetDisplaySizeMM().GetX() <<
"x"
1865 << wxGetDisplaySizeMM().GetY()
1866 <<
" Name wxDisplay: " << wxDisplay(idx).GetName().c_str()
1875 if (g_config_display_size_manual) {
1884 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
1887 cc->SetMUIBarPosition();
1896 UpdateGPSCompassStatusBoxes();
1906 PositionIENCToolbar();
1912 g_nframewin_posx = GetPosition().x;
1913 g_nframewin_posy = GetPosition().y;
1916void MyFrame::ProcessCanvasResize() {
1917 UpdateGPSCompassStatusBoxes(
true);
1921 PositionIENCToolbar();
1924 TriggerRecaptureTimer();
1928void MyFrame::TriggerRecaptureTimer() {
1929 m_recaptureTimer.Start(
1930 1000, wxTIMER_ONE_SHOT);
1933void MyFrame::OnRecaptureTimer(wxTimerEvent &event) { }
1935void MyFrame::SetCanvasSizes(wxSize frameSize) {
1939 int cccw = frameSize.x;
1940 int ccch = frameSize.y;
1944 switch (g_canvasConfig) {
1950 cc->GetSize( &cur_width, &cur_height );
1951 if( ( cur_width != cccw ) || ( cur_height != ccch ) ) {
1953 g_pauimgr->GetPane( cc ).BestSize( cccw, ccch );
1955 cc->SetSize( 0, 0, cccw, ccch );
1965 int ccw = g_canvasConfigArray.Item(1)->canvasSize.x;
1966 int cch = g_canvasConfigArray.Item(1)->canvasSize.y;
1968 ccw = wxMin(ccw, cccw * 8 / 10);
1969 ccw = wxMax(ccw, cccw * 2 / 10);
1973 g_canvasConfigArray.Item(1)->canvasSize = wxSize(ccw, cch);
1980 g_pauimgr->GetPane(cc).MinSize(ccw, cch);
1997void MyFrame::OnIconize(wxIconizeEvent &event) {
2007 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2009 if (cc && cc->GetMUIBar()) {
2010 if (cc->GetMUIBar()->GetCanvasOptions()) {
2011 if (cc->GetMUIBar()->GetCanvasOptions()->IsShown()) {
2012 cc->GetMUIBar()->PushCanvasOptions();
2021void MyFrame::OnSize(wxSizeEvent &event) { ODoSetSize(); }
2023void MyFrame::ODoSetSize() {
2025 GetClientSize(&x, &y);
2028 if (m_pStatusBar != NULL) {
2029 m_StatusBarFieldCount = g_Platform->GetStatusBarFieldCount();
2030 int currentCount = m_pStatusBar->GetFieldsCount();
2031 if (currentCount != m_StatusBarFieldCount) {
2032 if ((currentCount > 0) && (currentCount < 7)) {
2035 int widths[] = {2, 2, 2, 2, 2, 2};
2036 m_pStatusBar->SetStatusWidths(currentCount, widths);
2039 m_pStatusBar->SetFieldsCount(m_StatusBarFieldCount);
2042 if (m_StatusBarFieldCount) {
2047 if (m_StatusBarFieldCount > 2) {
2048 int widths[] = {-6, -5, -5, -6, -4};
2049 m_pStatusBar->SetStatusWidths(m_StatusBarFieldCount, widths);
2050 }
else if (m_StatusBarFieldCount == 2) {
2051 int cwidth = x * 90 / 100;
2052 int widths[] = {100, 100};
2053 widths[0] = cwidth * 6.4 / 10.0;
2054 widths[1] = cwidth * 3.6 / 10.0;
2055 m_pStatusBar->SetStatusWidths(m_StatusBarFieldCount, widths);
2057 int widths[] = {100, 100};
2058 widths[0] = x * 90 / 100;
2059 m_pStatusBar->SetStatusWidths(m_StatusBarFieldCount, widths);
2062 int styles[] = {wxSB_FLAT, wxSB_FLAT, wxSB_FLAT,
2063 wxSB_FLAT, wxSB_FLAT, wxSB_FLAT};
2064 m_pStatusBar->SetStatusStyles(m_StatusBarFieldCount, styles);
2066 wxString sogcog(
"SOG --- " + getUsrSpeedUnit() + +
" " +
2068 m_pStatusBar->SetStatusText(sogcog, STAT_FIELD_SOGCOG);
2076 m_pStatusBar->GetFieldRect(0, stat_box);
2079 int max_font_size = wxMin((stat_box.width / 28), (stat_box.height));
2081 wxFont sys_font = *wxNORMAL_FONT;
2082 int try_font_size = sys_font.GetPointSize();
2085 int min_font_size = 10;
2095 wxFont *statusBarFont =
2096 FontMgr::Get().
GetFont(_(
"StatusBar"), try_font_size);
2097 int font_size = statusBarFont->GetPointSize();
2099 font_size = wxMin(font_size,
2102 wxMax(font_size, min_font_size);
2105 font_size = statusBarFont->GetPointSize();
2112 font_size, statusBarFont->GetFamily(), statusBarFont->GetStyle(),
2113 statusBarFont->GetWeight(),
false, statusBarFont->GetFaceName());
2115 int min_height = stat_box.height;
2117 m_pStatusBar->SetFont(*pstat_font);
2118 m_pStatusBar->SetForegroundColour(
2119 FontMgr::Get().GetFontColor(_(
"StatusBar")));
2121 min_height = (pstat_font->GetPointSize() * getAndroidDisplayDensity()) + 10;
2123 (min_height >> 1) * 2;
2124 m_pStatusBar->SetMinHeight(min_height);
2133 SetCanvasSizes(GetClientSize());
2135 UpdateGPSCompassStatusBoxes(
true);
2137 if (
console) PositionConsole();
2140 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2142 if (cc) cc->FormatPianoKeys();
2148 g_MainToolbar->SetGeometry(GetPrimaryCanvas()->GetCompass()->IsShown(),
2149 GetPrimaryCanvas()->GetCompass()->GetRect());
2175 options_lastWindowSize = wxSize(0, 0);
2176 options_lastWindowPos = wxPoint(0, 0);
2183 if (!b_inCloseWindow) {
2186 resizeAndroidPersistents();
2190 if (GetPrimaryCanvas() && GetPrimaryCanvas()->GetNotificationsList()) {
2191 GetPrimaryCanvas()->GetNotificationsList()->RecalculateSize();
2197void MyFrame::PositionConsole() {
2198#if defined(__WXMSW__) || defined(__WXMAC__)
2199 if (NULL == GetPrimaryCanvas())
return;
2201 int ccx, ccy, ccsx, ccsy, consx, consy;
2206 consoleHost->GetSize(&ccsx, &ccsy);
2207 consoleHost->GetPosition(&ccx, &ccy);
2209 GetPrimaryCanvas()->GetSize(&ccsx, &ccsy);
2210 GetPrimaryCanvas()->GetPosition(&ccx, &ccy);
2211 consoleHost = GetPrimaryCanvas();
2216 if (consoleHost->GetCompass()) {
2217 wxRect compass_rect = consoleHost->GetCompass()->
GetRect();
2219 if (compass_rect.y < 100)
2220 yOffset = compass_rect.y + compass_rect.height + 45;
2224 wxSize csz =
console->GetSize();
2228 wxPoint screen_pos =
2229 ClientToScreen(wxPoint(ccx + ccsx - consx - 2, ccy + yOffset));
2232 if (NULL == GetPrimaryCanvas())
return;
2234 int ccx, ccy, ccsx, ccsy, consx, consy;
2239 consoleHost->GetSize(&ccsx, &ccsy);
2240 consoleHost->GetPosition(&ccx, &ccy);
2242 GetPrimaryCanvas()->GetSize(&ccsx, &ccsy);
2243 GetPrimaryCanvas()->GetPosition(&ccx, &ccy);
2244 consoleHost = GetPrimaryCanvas();
2247 int yTopOffset = 60;
2248 int yBottomOffset = 0;
2250 if (consoleHost->GetCompass()) {
2251 wxRect compass_rect = consoleHost->GetCompass()->
GetRect();
2253 if (compass_rect.y < 100)
2254 yTopOffset = compass_rect.y + compass_rect.height;
2256 if (consoleHost->GetMUIBar()) {
2257 wxRect mui_rect = consoleHost->GetMUIBarRect();
2258 yBottomOffset = ccsy - mui_rect.y;
2262 wxSize csz =
console->GetSize();
2265 int yAvail = ccsy - (yTopOffset + yBottomOffset);
2267 if (consy < yAvail) {
2268 yFinal = (yAvail - consy) / 2;
2269 yFinal += yTopOffset;
2270 }
else if (
console->GetCDI()->IsShown()) {
2271 int cdi_height =
console->GetCDI()->GetSize().y;
2272 int consy_no_cdi = consy - cdi_height;
2273 yFinal = (yAvail - consy_no_cdi) / 2;
2274 yFinal += yTopOffset;
2278 wxPoint in_canvas_pos = wxPoint(ccsx - consx - 2, yFinal);
2283void MyFrame::UpdateAllFonts() {
2292 DestroyPersistentDialogs();
2294 if (pWayPointMan) pWayPointMan->ClearRoutePointFonts();
2299void MyFrame::DestroyPersistentDialogs() {
2300 if (g_pais_query_dialog_active) {
2301 g_pais_query_dialog_active->Hide();
2302 g_pais_query_dialog_active->Destroy();
2303 g_pais_query_dialog_active = NULL;
2331void MyFrame::RefreshGroupIndices() {
2333 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2335 if (cc) cc->canvasRefreshGroupIndex();
2339void MyFrame::OnToolLeftClick(wxCommandEvent &event) {
2342 switch (event.GetId()) {
2343 case ID_MENU_SCALE_OUT:
2344 DoStackDelta(GetPrimaryCanvas(), 1);
2348 case ID_MENU_SCALE_IN:
2349 DoStackDelta(GetPrimaryCanvas(), -1);
2353 case ID_MENU_ZOOM_IN: {
2354 if (GetFocusCanvas()) {
2355 GetFocusCanvas()->
ZoomCanvas(g_plus_minus_zoom_factor,
false);
2360 case ID_MENU_ZOOM_OUT: {
2361 if (GetFocusCanvas()) {
2362 GetFocusCanvas()->
ZoomCanvas(1.0 / g_plus_minus_zoom_factor,
false);
2367 case ID_MENU_ROUTE_NEW: {
2368 if (GetFocusCanvas()) {
2369 if (0 == GetFocusCanvas()->m_routeState) {
2370 GetFocusCanvas()->StartRoute();
2372 GetFocusCanvas()->FinishRoute();
2378 case ID_MENU_TOOL_MEASURE: {
2379 GetPrimaryCanvas()->StartMeasureRoute();
2383 case ID_MENU_TOOL_NMEA_DBG_LOG:
2384 m_data_monitor->Show();
2385 m_data_monitor->Raise();
2388 case ID_MENU_TOOL_IO_MONITOR:
2389 m_data_monitor->Show();
2392 case ID_MENU_MARK_BOAT: {
2397 case ID_MENU_MARK_CURSOR: {
2402 case ID_MENU_NAV_FOLLOW: {
2403 if (
gFrame->GetPrimaryCanvas())
2404 gFrame->GetPrimaryCanvas()->TogglebFollow();
2408 case ID_MENU_CHART_OUTLINES: {
2409 ToggleChartOutlines(GetFocusCanvas());
2413 case ID_MENU_CHART_QUILTING: {
2414 ToggleQuiltMode(GetFocusCanvas());
2418 case ID_MENU_UI_CHARTBAR: {
2419 ToggleChartBar(GetFocusCanvas());
2423 case ID_MENU_ENC_TEXT:
2425 ToggleENCText(GetFocusCanvas());
2428 case ID_MENU_ENC_LIGHTS: {
2429 ToggleLights(GetFocusCanvas());
2432 case ID_MENU_ENC_SOUNDINGS: {
2433 ToggleSoundings(GetFocusCanvas());
2436 case ID_MENU_ENC_ANCHOR: {
2437 ToggleAnchor(GetFocusCanvas());
2440 case ID_MENU_ENC_DATA_QUALITY: {
2441 ToggleDataQuality(GetFocusCanvas());
2444 case ID_MENU_SHOW_NAVOBJECTS: {
2445 ToggleNavobjects(GetFocusCanvas());
2449 case ID_MENU_AIS_TARGETS: {
2450 ToggleAISDisplay(GetFocusCanvas());
2453 case ID_MENU_AIS_MOORED_TARGETS: {
2454 g_bHideMoored = !g_bHideMoored;
2457 case ID_MENU_AIS_SCALED_TARGETS: {
2458 ToggleAISMinimizeTargets(GetFocusCanvas());
2462 case ID_MENU_AIS_TARGETLIST: {
2463 if (GetPrimaryCanvas()) GetPrimaryCanvas()->ShowAISTargetList();
2467 case ID_MENU_AIS_TRACKS: {
2468 g_bAISShowTracks = !g_bAISShowTracks;
2469 SetMenubarItemState(ID_MENU_AIS_TRACKS, g_bAISShowTracks);
2473 case ID_MENU_AIS_CPADIALOG: {
2474 g_bAIS_CPA_Alert = !g_bAIS_CPA_Alert;
2475 SetMenubarItemState(ID_MENU_AIS_CPADIALOG, g_bAIS_CPA_Alert);
2476 m_pMenuBar->Enable(ID_MENU_AIS_CPASOUND, g_bAIS_CPA_Alert);
2477 if (g_bAIS_CPA_Alert) {
2478 SetMenubarItemState(ID_MENU_AIS_CPASOUND, g_bAIS_CPA_Alert_Audio);
2483 case ID_MENU_AIS_CPASOUND: {
2484 g_bAIS_CPA_Alert_Audio = !g_bAIS_CPA_Alert_Audio;
2485 SetMenubarItemState(ID_MENU_AIS_CPASOUND, g_bAIS_CPA_Alert_Audio);
2489 case ID_MENU_AIS_CPAWARNING: {
2490 if (GetPrimaryCanvas()) GetPrimaryCanvas()->ToggleCPAWarn();
2491 SetMenubarItemState(ID_MENU_AIS_CPAWARNING, g_bCPAWarn);
2495 case wxID_PREFERENCES:
2502 case ID_SETTINGS_NEW: {
2507 case ID_SETTINGS_DELETE: {
2510 g_pOptions =
nullptr;
2514 case ID_RELOAD_CHARTS: {
2519 case ID_MENU_SETTINGS_BASIC: {
2521 androidDisableFullScreen();
2523 DoAndroidPreferences();
2530 case ID_MENU_UI_FULLSCREEN: {
2535 case ID_MENU_SHOW_CURRENTS: {
2536 GetFocusCanvas()->ShowCurrents(!GetFocusCanvas()->GetbShowCurrent());
2537 GetFocusCanvas()->ReloadVP();
2538 GetFocusCanvas()->Refresh(
false);
2542 case ID_MENU_SHOW_TIDES: {
2543 GetFocusCanvas()->ShowTides(!GetFocusCanvas()->GetbShowTide());
2544 GetFocusCanvas()->ReloadVP();
2545 GetFocusCanvas()->Refresh(
false);
2565 case ID_MENU_UI_COLSCHEME:
2566 case ID_COLSCHEME: {
2567 ToggleColorScheme();
2576 case ID_MENU_OQUIT: {
2581 case ID_MENU_ROUTE_MANAGER:
2582 case ID_ROUTEMANAGER: {
2605 case ID_MENU_NAV_TRACK:
2607 if (!g_bTrackActive) {
2609 g_bTrackCarryOver =
true;
2612 g_bTrackCarryOver =
false;
2613 RefreshAllCanvas(
true);
2618 case ID_MENU_CHART_NORTHUP: {
2619 SetUpMode(GetPrimaryCanvas(), NORTH_UP_MODE);
2622 case ID_MENU_CHART_COGUP: {
2623 SetUpMode(GetPrimaryCanvas(), COURSE_UP_MODE);
2626 case ID_MENU_CHART_HEADUP: {
2627 SetUpMode(GetPrimaryCanvas(), HEAD_UP_MODE);
2631 case ID_MENU_MARK_MOB:
2637 case ID_MASTERTOGGLE: {
2639 wxString tip = _(
"Show Toolbar");
2640 if (!g_bmasterToolbarFull) tip = _(
"Hide Toolbar");
2642 g_MainToolbar->GetToolbar()->SetToolShortHelp(ID_MASTERTOGGLE, tip);
2644 g_bmasterToolbarFull = !g_bmasterToolbarFull;
2647 if (g_bmasterToolbarFull)
2648 m_nMasterToolCountShown =
2652 m_nMasterToolCountShown = 2;
2654 m_nMasterToolCountShown =
2657 ToolbarAnimateTimer.Start(10, wxTIMER_ONE_SHOT);
2665 case ID_CMD_SELECT_CHART_TYPE: {
2666 selectChartDisplay(event.GetExtraLong(), -1);
2670 case ID_CMD_SELECT_CHART_FAMILY: {
2671 selectChartDisplay(-1, event.GetExtraLong());
2675 case ID_CMD_APPLY_SETTINGS: {
2676 applySettingsString(event.GetString());
2678 androidRestoreFullScreen();
2684 case ID_CMD_NULL_REFRESH: {
2689 case ID_CMD_SETVP: {
2690 setStringVP(event.GetString());
2694 case ID_CMD_INVALIDATE: {
2700 case ID_CMD_POST_JSON_TO_PLUGINS: {
2706 int numErrors = reader.
Parse(event.GetString(), &root);
2707 if (numErrors == 0) {
2708 if (root[
"MessageID"].IsString()) {
2709 wxString MsgID = root[
"MessageID"].
AsString();
2733 ArrayOfPlugInToolbarTools tool_array =
2735 for (
unsigned int i = 0; i < tool_array.size(); i++) {
2737 if (event.GetId() == pttc->id) {
2738 if (pttc->m_pplugin)
2760bool MyFrame::SetGlobalToolbarViz(
bool viz) {
2761 bool viz_now = g_bmasterToolbarFull;
2764 wxString tip = _(
"Show Toolbar");
2766 tip = _(
"Hide Toolbar");
2768 g_MainToolbar->GetToolbar()->SetToolShortHelp(ID_MASTERTOGGLE, tip);
2771 bool toggle =
false;
2772 if (viz && !g_bmasterToolbarFull)
2775 else if (!viz && g_bmasterToolbarFull)
2779 g_bmasterToolbarFull = !g_bmasterToolbarFull;
2782 if (g_bmasterToolbarFull)
2783 m_nMasterToolCountShown =
2787 m_nMasterToolCountShown = 2;
2789 m_nMasterToolCountShown =
2792 ToolbarAnimateTimer.Start(10, wxTIMER_ONE_SHOT);
2798void MyFrame::ScheduleReloadCharts() {
2799 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED);
2800 evt.SetId(ID_RELOAD_CHARTS);
2801 GetEventHandler()->AddPendingEvent(evt);
2804void MyFrame::ScheduleDeleteSettingsDialog() {
2805 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED);
2806 evt.SetId(ID_SETTINGS_DELETE);
2807 GetEventHandler()->AddPendingEvent(evt);
2810void MyFrame::ScheduleSettingsDialog() {
2811 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED);
2812 evt.SetId(ID_SETTINGS);
2813 GetEventHandler()->AddPendingEvent(evt);
2816void MyFrame::ScheduleSettingsDialogNew() {
2817 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED);
2818 evt.SetId(ID_SETTINGS_NEW);
2819 GetEventHandler()->AddPendingEvent(evt);
2822void MyFrame::ScheduleReconfigAndSettingsReload(
bool reload,
bool new_dialog) {
2823 UpdateCanvasConfigDescriptors();
2825 if ((g_canvasConfig > 0) && (last_canvasConfig == 0))
2826 CreateCanvasLayout(
true);
2828 CreateCanvasLayout();
2832 ConfigureStatusBar();
2833 wxSize lastOptSize = options_lastWindowSize;
2838 options_lastWindowSize = lastOptSize;
2842 ScheduleSettingsDialogNew();
2844 ScheduleSettingsDialog();
2849 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2852 int index_hint = -1;
2853 if (i < pathArray.GetCount())
2854 index_hint =
ChartData->FinddbIndex(pathArray.Item(i));
2855 cc->canvasChartsRefresh(index_hint);
2856 if (index_hint != -1) cc->
SetVPScale(restoreScale[i]);
2865 return GetPrimaryCanvas();
2868void MyFrame::OnToolbarAnimateTimer(wxTimerEvent &event) {
2869 if (g_bmasterToolbarFull) {
2870#ifndef OCPN_TOOLBAR_ANIMATE
2871 m_nMasterToolCountShown = (int)
g_MainToolbar->GetToolCount();
2874 if (m_nMasterToolCountShown < (
int)
g_MainToolbar->GetToolCount()) {
2875 m_nMasterToolCountShown++;
2880 ToolbarAnimateTimer.Start(20, wxTIMER_ONE_SHOT);
2888#ifndef OCPN_TOOLBAR_ANIMATE
2889 m_nMasterToolCountShown = 1;
2891 if (m_nMasterToolCountShown > 1) {
2892 m_nMasterToolCountShown--;
2896 ToolbarAnimateTimer.Start(10, wxTIMER_ONE_SHOT);
2906void MyFrame::InvalidateAllGL() {
2909 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2919void MyFrame::RefreshAllCanvas(
bool bErase) {
2921 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2924 cc->Refresh(bErase);
2929void MyFrame::setStringVP(wxString VPS) {
2934 wxStringTokenizer tkz(VPS,
";");
2936 wxString token = tkz.GetNextToken();
2938 token.ToDouble(&lat);
2940 token = tkz.GetNextToken();
2942 token.ToDouble(&lon);
2944 token = tkz.GetNextToken();
2946 token.ToDouble(&scale_ppm);
2948 cc->
SetViewPoint(lat, lon, scale_ppm, 0, cc->GetVPRotation());
2951void MyFrame::DoSettingsNew() {
2958void MyFrame::DoSettings() {
2963 ApplyGlobalSettings(
true);
2966 bool b_loadHarmonics =
false;
2967 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
2970 if (cc->GetbShowCurrent() || cc->GetbShowTide()) b_loadHarmonics =
true;
2973 if (b_loadHarmonics) LoadHarmonics();
2981 g_bShowChartBar = !g_bShowChartBar;
2983 if (g_bShowChartBar) cc->m_brepaint_piano =
true;
2988 if (g_bShowChartBar) {
2990 UpdateControlBar(cc);
2993 SetMenubarItemState(ID_MENU_UI_CHARTBAR, g_bShowChartBar);
2996void MyFrame::ToggleColorScheme() {
2997 static bool lastIsNight;
2998 ColorScheme s = user_colors::GetColorScheme();
3001 if (lastIsNight && is == 3)
3004 lastIsNight =
false;
3006 if (lastIsNight) is = 2;
3007 if (is == 3) lastIsNight =
true;
3008 s = (ColorScheme)is;
3009 if (s == N_COLOR_SCHEMES) s = GLOBAL_COLOR_SCHEME_RGB;
3011 SetAndApplyColorScheme(s);
3014void MyFrame::ToggleFullScreen() {
3015 bool to = !IsFullScreen();
3020 long style = wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION;
3022 ShowFullScreen(to, style);
3025 UpdateAllToolbars(global_color_scheme);
3027 UpdateControlBar(GetPrimaryCanvas());
3029 TriggerRecaptureTimer();
3032void MyFrame::ActivateMOB() {
3034 wxDateTime mob_time = wxDateTime::Now();
3035 wxString mob_label(_(
"MAN OVERBOARD"));
3036 mob_label += _(
" on ");
3037 mob_label += ocpn::toUsrDateTimeFormat(mob_time);
3041 pWP_MOB->SetShared(
true);
3043 pWP_MOB->SetWaypointArrivalRadius(
3045 pWP_MOB->SetUseSca(
false);
3047 NavObj_dB::GetInstance().InsertRoutePoint(pWP_MOB);
3055 new RoutePoint(zlat, zlon, g_default_wp_icon,
3056 wxString(_(
"1.0 NM along COG")), wxEmptyString);
3057 pSelect->AddSelectableRoutePoint(zlat, zlon, pWP_src);
3062 temp_route->AddPoint(pWP_src);
3063 temp_route->AddPoint(pWP_MOB);
3065 pSelect->AddSelectableRouteSegment(
gLat,
gLon, zlat, zlon, pWP_src, pWP_MOB,
3075 temp_route->SetRouteArrivalRadius(-1.0);
3081 v[
"GUID"] = temp_route->
m_GUID;
3082 wxString msg_id(
"OCPN_MAN_OVERBOARD");
3083 SendJSONMessageToAllPlugins(msg_id, v);
3086 if (RouteManagerDialog::getInstanceFlag()) {
3094 RefreshAllCanvas(
false);
3096 wxString mob_message(_(
"MAN OVERBOARD"));
3097 mob_message += _(
" Time: ");
3098 mob_message += ocpn::toUsrDateTimeFormat(mob_time);
3099 mob_message += _(
" Position: ");
3100 mob_message += toSDMM(1,
gLat);
3102 mob_message += toSDMM(2,
gLon);
3103 wxLogMessage(mob_message);
3105void MyFrame::TrackOn() {
3106 g_bTrackActive =
true;
3114 SetMasterToolbarItemState(ID_TRACK, g_bTrackActive);
3116 g_MainToolbar->SetToolShortHelp(ID_TRACK, _(
"Disable Tracking"));
3118 SetMenubarItemState(ID_MENU_NAV_TRACK, g_bTrackActive);
3121 androidSetTrackTool(
true);
3124 if (RouteManagerDialog::getInstanceFlag()) {
3133 if (name.IsEmpty()) {
3139 name = _(
"(Unnamed Track)");
3143 wxString msg_id(
"OCPN_TRK_ACTIVATED");
3144 SendJSONMessageToAllPlugins(msg_id, v);
3145 g_FlushNavobjChangesTimeout =
3149Track *MyFrame::TrackOff(
bool do_add_point) {
3154 wxString msg_id(
"OCPN_TRK_DEACTIVATED");
3156 SendJSONMessageToAllPlugins(msg_id, v);
3165 if (g_bTrackDaily) {
3170 NavObj_dB::GetInstance().UpdateTrack(pExtendTrack);
3171 return_val = pExtendTrack;
3178 g_bTrackActive =
false;
3180 if (RouteManagerDialog::getInstanceFlag()) {
3187 SetMasterToolbarItemState(ID_TRACK, g_bTrackActive);
3189 g_MainToolbar->SetToolShortHelp(ID_TRACK, _(
"Enable Tracking"));
3190 SetMenubarItemState(ID_MENU_NAV_TRACK, g_bTrackActive);
3193 androidSetTrackTool(
false);
3197 m_target_rotate_time = wxInvalidDateTime;
3202void MyFrame::InitializeTrackRestart() {
3203 if (!g_bTrackDaily)
return;
3204 if (m_target_rotate_time.IsValid())
return;
3207 switch (g_track_rotate_time_type) {
3209 rotate_at = g_track_rotate_time + wxRound(
gLon * 3600. / 15.);
3211 case TIME_TYPE_COMPUTER:
3212 rotate_at = g_track_rotate_time;
3216 wxDateTime::Now().GetTicks() - wxDateTime::Now().ToUTC().GetTicks();
3217 rotate_at = g_track_rotate_time + utc_offset;
3220 if (rotate_at > 86400)
3222 else if (rotate_at < 0)
3225 wxTimeSpan rotate_seconds = wxTimeSpan(0, 0, rotate_at);
3226 m_target_rotate_time = wxDateTime::Today() + rotate_seconds;
3229 if (wxDateTime::Now().IsLaterThan(m_target_rotate_time)) {
3230 m_target_rotate_time += wxTimeSpan(24);
3234bool MyFrame::ShouldRestartTrack() {
3236 InitializeTrackRestart();
3238 if (wxDateTime::Now().IsLaterThan(m_target_rotate_time)) {
3239 m_target_rotate_time += wxTimeSpan(24);
3245void MyFrame::TrackDailyRestart() {
3247 Track *pPreviousTrack = TrackOff(
true);
3254 if (pPreviousTrack) {
3255 TrackPoint *pMidnightPoint = pPreviousTrack->GetLastPoint();
3259 if (RouteManagerDialog::getInstanceFlag()) {
3267void MyFrame::SetUpMode(
ChartCanvas *cc,
int mode) {
3269 cc->SetUpMode(mode);
3271 SetMenubarItemState(ID_MENU_CHART_COGUP, mode == COURSE_UP_MODE);
3272 SetMenubarItemState(ID_MENU_CHART_NORTHUP, mode == NORTH_UP_MODE);
3273 SetMenubarItemState(ID_MENU_CHART_HEADUP, mode == HEAD_UP_MODE);
3276 m_pMenuBar->SetLabel(ID_MENU_CHART_NORTHUP, _(
"North Up Mode"));
3281 cc->SetShowENCText(!cc->GetShowENCText());
3283 SetMenubarItemState(ID_MENU_ENC_TEXT, cc->GetShowENCText());
3291void MyFrame::SetENCDisplayCategory(
ChartCanvas *cc,
enum _DisCat nset) {
3294 cc->SetENCDisplayCategory(nset);
3296 UpdateGlobalMenuItems();
3307 cc->SetShowENCDepth(!cc->GetShowENCDepth());
3309 SetMenubarItemState(ID_MENU_ENC_SOUNDINGS, cc->GetShowENCDepth());
3318 cc->SetShowENCLights(!cc->GetShowENCLights());
3320 SetMenubarItemState(ID_MENU_ENC_LIGHTS, cc->GetShowENCLights());
3330void MyFrame::ToggleRocks(
void )
3336 for(
unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount(); iPtr++ ) {
3337 OBJLElement *pOLE = (OBJLElement *) ( ps52plib->pOBJLArray->Item( iPtr ) );
3338 if( !strncmp( pOLE->OBJLName,
"UWTROC", 6 ) ) {
3339 pOLE->nViz = !pOLE->nViz;
3343 for(
unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount(); iPtr++ ) {
3344 OBJLElement *pOLE = (OBJLElement *) ( ps52plib->pOBJLArray->Item( iPtr ) );
3345 if( !strncmp( pOLE->OBJLName,
"OBSTRN", 6 ) ) {
3348 if( !strncmp( pOLE->OBJLName,
"WRECKS", 6 ) ) {
3352 ps52plib->GenerateStateHash();
3359 cc->SetShowENCAnchor(!cc->GetShowENCAnchor());
3361 SetMenubarItemState(ID_MENU_ENC_ANCHOR, cc->GetShowENCAnchor());
3369 cc->SetShowENCDataQual(!cc->GetShowENCDataQual());
3371 SetMenubarItemState(ID_MENU_ENC_DATA_QUALITY, cc->GetShowENCDataQual());
3386 cc->m_bShowNavobjects = !cc->m_bShowNavobjects;
3387 SetMenubarItemState(ID_MENU_SHOW_NAVOBJECTS, cc->m_bShowNavobjects);
3392 cc->SetShowAIS(!cc->GetShowAIS());
3393 SetMenubarItemState(ID_MENU_AIS_TARGETS, cc->GetShowAIS());
3397void MyFrame::ToggleAISMinimizeTargets(
ChartCanvas *cc) {
3398 cc->SetAttenAIS(!cc->GetAttenAIS());
3399 SetMenubarItemState(ID_MENU_AIS_SCALED_TARGETS, cc->GetAttenAIS());
3405 cc->m_bFollow =
true;
3408 SetMenubarItemState(ID_MENU_NAV_FOLLOW,
true);
3412 SetChartUpdatePeriod();
3420 cc->m_bFollow =
false;
3422 SetMenubarItemState(ID_MENU_NAV_FOLLOW,
false);
3426 SetChartUpdatePeriod();
3429void MyFrame::ToggleChartOutlines(
ChartCanvas *cc) {
3430 cc->SetShowOutlines(!cc->GetShowOutlines());
3432 RefreshAllCanvas(
false);
3436 if (g_bopengl) InvalidateAllGL();
3439 SetMenubarItemState(ID_MENU_CHART_OUTLINES, cc->GetShowOutlines());
3442void MyFrame::ToggleTestPause() { g_bPauseTest = !g_bPauseTest; }
3444void MyFrame::SetMenubarItemState(
int item_id,
bool state) {
3446 bool enabled = m_pMenuBar->IsEnabled(item_id);
3447 m_pMenuBar->Enable(item_id,
false);
3448 m_pMenuBar->Check(item_id, state);
3449 m_pMenuBar->Enable(item_id, enabled);
3453void MyFrame::SetMasterToolbarItemState(
int tool_id,
bool state) {
3460void MyFrame::SetToolbarItemBitmaps(
int tool_id, wxBitmap *bmp,
3461 wxBitmap *bmpRollover) {
3463 g_MainToolbar->GetToolbar()->SetToolBitmaps(tool_id, bmp, bmpRollover);
3468void MyFrame::SetToolbarItemSVG(
int tool_id, wxString normalSVGfile,
3469 wxString rolloverSVGfile,
3470 wxString toggledSVGfile) {
3473 tool_id, normalSVGfile, rolloverSVGfile, toggledSVGfile);
3477void MyFrame::ConfigureStatusBar() {
3479 m_StatusBarFieldCount = g_Platform->GetStatusBarFieldCount();
3482 UseNativeStatusBar(
false);
3485 if (g_bShowStatusBar) {
3486 if (!m_pStatusBar) {
3488 CreateStatusBar(m_StatusBarFieldCount, 0);
3489 ApplyGlobalColorSchemetoStatusBar();
3494 m_pStatusBar->Destroy();
3495 m_pStatusBar = NULL;
3501void MyFrame::ApplyGlobalSettings(
bool bnewtoolbar) {
3502 ConfigureStatusBar();
3504 wxSize lastOptSize = options_lastWindowSize;
3510 options_lastWindowSize = lastOptSize;
3512 if (bnewtoolbar) UpdateAllToolbars(global_color_scheme);
3515void MyFrame::BuildMenuBar() {
3521 bool showMenuBar =
true;
3523 bool showMenuBar = g_bShowMenuBar;
3535 m_pMenuBar =
new wxMenuBar();
3536 RegisterGlobalMenuItems();
3537 SetMenuBar(m_pMenuBar);
3541 UpdateGlobalMenuItems();
3546 m_pMenuBar->Destroy();
3552void MyFrame::RegisterGlobalMenuItems() {
3553 if (!m_pMenuBar)
return;
3555 wxMenu *nav_menu =
new wxMenu();
3556 nav_menu->AppendCheckItem(ID_MENU_NAV_FOLLOW,
3557 _menuText(_(
"Auto Follow"),
"Ctrl-A"));
3558 nav_menu->AppendCheckItem(ID_MENU_NAV_TRACK, _(
"Enable Tracking"));
3559 nav_menu->AppendSeparator();
3560 nav_menu->AppendRadioItem(ID_MENU_CHART_NORTHUP, _(
"North Up Mode"));
3561 nav_menu->AppendRadioItem(ID_MENU_CHART_COGUP, _(
"Course Up Mode"));
3562 nav_menu->AppendRadioItem(ID_MENU_CHART_HEADUP, _(
"Head Up Mode"));
3563 nav_menu->AppendSeparator();
3565 nav_menu->Append(ID_MENU_ZOOM_IN, _menuText(_(
"Zoom In"),
"+"));
3566 nav_menu->Append(ID_MENU_ZOOM_OUT, _menuText(_(
"Zoom Out"),
"-"));
3568 nav_menu->Append(ID_MENU_ZOOM_IN, _menuText(_(
"Zoom In"),
"Alt-+"));
3569 nav_menu->Append(ID_MENU_ZOOM_OUT, _menuText(_(
"Zoom Out"),
"Alt--"));
3571 nav_menu->AppendSeparator();
3572 nav_menu->Append(ID_MENU_SCALE_IN,
3573 _menuText(_(
"Larger Scale Chart"),
"Ctrl-Left"));
3574 nav_menu->Append(ID_MENU_SCALE_OUT,
3575 _menuText(_(
"Smaller Scale Chart"),
"Ctrl-Right"));
3577 nav_menu->AppendSeparator();
3578 nav_menu->Append(ID_MENU_OQUIT, _menuText(_(
"Exit OpenCPN"),
"Ctrl-Q"));
3580 m_pMenuBar->Append(nav_menu, _(
"&Navigate"));
3582 wxMenu *view_menu =
new wxMenu();
3584 view_menu->AppendCheckItem(ID_MENU_CHART_QUILTING,
3585 _menuText(_(
"Enable Chart Quilting"),
"Q"));
3586 view_menu->AppendCheckItem(ID_MENU_CHART_OUTLINES,
3587 _menuText(_(
"Show Chart Outlines"),
"O"));
3589 view_menu->AppendCheckItem(ID_MENU_CHART_QUILTING,
3590 _menuText(_(
"Enable Chart Quilting"),
"Alt-Q"));
3591 view_menu->AppendCheckItem(ID_MENU_CHART_OUTLINES,
3592 _menuText(_(
"Show Chart Outlines"),
"Alt-O"));
3594 view_menu->AppendCheckItem(ID_MENU_UI_CHARTBAR,
3595 _menuText(_(
"Show Chart Bar"),
"Ctrl-B"));
3597 view_menu->AppendSeparator();
3599 view_menu->AppendCheckItem(ID_MENU_ENC_TEXT,
3600 _menuText(_(
"Show ENC text"),
"T"));
3601 view_menu->AppendCheckItem(ID_MENU_ENC_LIGHTS,
3602 _menuText(_(
"Show ENC Lights"),
"L"));
3603 view_menu->AppendCheckItem(ID_MENU_ENC_SOUNDINGS,
3604 _menuText(_(
"Show ENC Soundings"),
"S"));
3605 view_menu->AppendCheckItem(ID_MENU_ENC_ANCHOR,
3606 _menuText(_(
"Show ENC Anchoring Info"),
"A"));
3607 view_menu->AppendCheckItem(ID_MENU_ENC_DATA_QUALITY,
3608 _menuText(_(
"Show ENC Data Quality"),
"U"));
3609 view_menu->AppendCheckItem(ID_MENU_SHOW_NAVOBJECTS,
3610 _menuText(_(
"Show Navobjects"),
"V"));
3612 view_menu->AppendCheckItem(ID_MENU_ENC_TEXT,
3613 _menuText(_(
"Show ENC text"),
"Alt-T"));
3614 view_menu->AppendCheckItem(ID_MENU_ENC_LIGHTS,
3615 _menuText(_(
"Show ENC Lights"),
"Alt-L"));
3616 view_menu->AppendCheckItem(ID_MENU_ENC_SOUNDINGS,
3617 _menuText(_(
"Show ENC Soundings"),
"Alt-S"));
3618 view_menu->AppendCheckItem(ID_MENU_ENC_ANCHOR,
3619 _menuText(_(
"Show ENC Anchoring Info"),
"Alt-A"));
3620 view_menu->AppendCheckItem(ID_MENU_ENC_DATA_QUALITY,
3621 _menuText(_(
"Show ENC Data Quality"),
"Alt-U"));
3622 view_menu->AppendCheckItem(ID_MENU_SHOW_NAVOBJECTS,
3623 _menuText(_(
"Show Navobjects"),
"Alt-V"));
3625 view_menu->AppendSeparator();
3626 view_menu->AppendCheckItem(ID_MENU_SHOW_TIDES, _(
"Show Tides"));
3627 view_menu->AppendCheckItem(ID_MENU_SHOW_CURRENTS, _(
"Show Currents"));
3628 view_menu->AppendSeparator();
3630 view_menu->Append(ID_MENU_UI_COLSCHEME,
3631 _menuText(_(
"Change Color Scheme"),
"C"));
3633 view_menu->Append(ID_MENU_UI_COLSCHEME,
3634 _menuText(_(
"Change Color Scheme"),
"Alt-C"));
3637 view_menu->AppendSeparator();
3639 view_menu->Append(ID_MENU_UI_FULLSCREEN,
3640 _menuText(_(
"Toggle Full Screen"),
"F11"));
3642 m_pMenuBar->Append(view_menu, _(
"&View"));
3644 wxMenu *ais_menu =
new wxMenu();
3645 ais_menu->AppendCheckItem(ID_MENU_AIS_TARGETS, _(
"Show AIS Targets"));
3646 ais_menu->AppendCheckItem(ID_MENU_AIS_SCALED_TARGETS,
3647 _(
"Attenuate less critical AIS targets"));
3648 ais_menu->AppendSeparator();
3649 ais_menu->AppendCheckItem(ID_MENU_AIS_MOORED_TARGETS,
3650 _(
"Hide Moored AIS Targets"));
3651 ais_menu->AppendCheckItem(ID_MENU_AIS_TRACKS, _(
"Show AIS Target Tracks"));
3652 ais_menu->AppendCheckItem(ID_MENU_AIS_CPADIALOG, _(
"Show CPA Alert Dialogs"));
3653 ais_menu->AppendCheckItem(ID_MENU_AIS_CPASOUND, _(
"Sound CPA Alarms"));
3656 ais_menu->AppendCheckItem(ID_MENU_AIS_CPAWARNING,
3657 _menuText(_(
"Show CPA Warnings"),
"W"));
3659 ais_menu->AppendCheckItem(ID_MENU_AIS_CPAWARNING,
3660 _menuText(_(
"Show CPA Warnings"),
"Alt-W"));
3663 ais_menu->AppendSeparator();
3664 ais_menu->Append(ID_MENU_AIS_TARGETLIST, _(
"AIS target list") +
"...");
3665 m_pMenuBar->Append(ais_menu, _(
"&AIS"));
3667 wxMenu *tools_menu =
new wxMenu();
3668 tools_menu->Append(ID_MENU_TOOL_NMEA_DBG_LOG,
3669 _menuText(_(
"Data Monitor"),
"E"));
3671 tools_menu->Append(ID_MENU_TOOL_MEASURE,
3672 _menuText(_(
"Measure Distance"),
"M"));
3674 tools_menu->Append(ID_MENU_TOOL_MEASURE,
3675 _menuText(_(
"Measure Distance"),
"Alt-M"));
3678 tools_menu->AppendSeparator();
3679 tools_menu->Append(ID_MENU_ROUTE_MANAGER, _(
"Route && Mark Manager..."));
3680 tools_menu->Append(ID_MENU_ROUTE_NEW, _menuText(_(
"Create Route"),
"Ctrl-R"));
3681 tools_menu->AppendSeparator();
3682 tools_menu->Append(ID_MENU_MARK_BOAT,
3683 _menuText(_(
"Drop Mark at Boat"),
"Ctrl-O"));
3684 tools_menu->Append(ID_MENU_MARK_CURSOR,
3685 _menuText(_(
"Drop Mark at Cursor"),
"Ctrl-M"));
3686 tools_menu->AppendSeparator();
3690 _menuText(_(
"Drop MOB Marker"),
3692 tools_menu->AppendSeparator();
3693 tools_menu->Append(wxID_PREFERENCES,
3694 _menuText(_(
"Preferences") +
"...",
"Ctrl-,"));
3696 tools_menu->Append(ID_MENU_MARK_MOB,
3697 _menuText(_(
"Drop MOB Marker"),
"Ctrl-Space"));
3698 tools_menu->AppendSeparator();
3699 tools_menu->Append(wxID_PREFERENCES,
3700 _menuText(_(
"Options") +
"...",
"Ctrl-,"));
3702 m_pMenuBar->Append(tools_menu, _(
"&Tools"));
3705 wxMenu *window_menu =
new wxMenu();
3706 m_pMenuBar->Append(window_menu, _(
"&Window"));
3709 wxMenu *help_menu =
new wxMenu();
3710 help_menu->Append(wxID_ABOUT, _(
"About OpenCPN"));
3711 help_menu->Append(wxID_HELP, _(
"OpenCPN Help"));
3712 m_pMenuBar->Append(help_menu, _(
"&Help"));
3715 UpdateGlobalMenuItems();
3718void MyFrame::UpdateGlobalMenuItems() {
3719 if (!m_pMenuBar)
return;
3721 m_pMenuBar->FindItem(ID_MENU_NAV_FOLLOW)
3722 ->Check(GetPrimaryCanvas()->m_bFollow);
3723 m_pMenuBar->FindItem(ID_MENU_CHART_NORTHUP)
3724 ->Check(GetPrimaryCanvas()->GetUpMode() == NORTH_UP_MODE);
3725 m_pMenuBar->FindItem(ID_MENU_CHART_COGUP)
3726 ->Check(GetPrimaryCanvas()->GetUpMode() == COURSE_UP_MODE);
3727 m_pMenuBar->FindItem(ID_MENU_CHART_HEADUP)
3728 ->Check(GetPrimaryCanvas()->GetUpMode() == HEAD_UP_MODE);
3729 m_pMenuBar->FindItem(ID_MENU_NAV_TRACK)->Check(g_bTrackActive);
3730 m_pMenuBar->FindItem(ID_MENU_CHART_OUTLINES)->Check(g_bShowOutlines);
3731 m_pMenuBar->FindItem(ID_MENU_CHART_QUILTING)->Check(g_bQuiltEnable);
3732 m_pMenuBar->FindItem(ID_MENU_UI_CHARTBAR)->Check(g_bShowChartBar);
3733 m_pMenuBar->FindItem(ID_MENU_AIS_TARGETS)->Check(g_bShowAIS);
3734 m_pMenuBar->FindItem(ID_MENU_AIS_MOORED_TARGETS)->Check(g_bHideMoored);
3735 m_pMenuBar->FindItem(ID_MENU_AIS_SCALED_TARGETS)->Check(g_bShowScaled);
3736 m_pMenuBar->FindItem(ID_MENU_AIS_SCALED_TARGETS)->Enable(g_bAllowShowScaled);
3737 m_pMenuBar->FindItem(ID_MENU_AIS_TRACKS)->Check(g_bAISShowTracks);
3738 m_pMenuBar->FindItem(ID_MENU_AIS_CPADIALOG)->Check(g_bAIS_CPA_Alert);
3739 if (g_bAIS_CPA_Alert) {
3740 m_pMenuBar->FindItem(ID_MENU_AIS_CPASOUND)->Check(g_bAIS_CPA_Alert_Audio);
3741 m_pMenuBar->Enable(ID_MENU_AIS_CPASOUND,
true);
3743 m_pMenuBar->FindItem(ID_MENU_AIS_CPASOUND)->Check(
false);
3744 m_pMenuBar->Enable(ID_MENU_AIS_CPASOUND,
false);
3747 m_pMenuBar->FindItem(ID_MENU_AIS_CPAWARNING)->Check(g_bCPAWarn);
3748 m_pMenuBar->FindItem(ID_MENU_SHOW_NAVOBJECTS)
3749 ->Check(GetPrimaryCanvas()->m_bShowNavobjects);
3752 m_pMenuBar->FindItem(ID_MENU_ENC_TEXT)->Check(ps52plib->GetShowS57Text());
3753 m_pMenuBar->FindItem(ID_MENU_ENC_SOUNDINGS)
3754 ->Check(ps52plib->GetShowSoundings());
3756 bool light_state =
false;
3758 for (
unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
3760 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
3761 if (!strncmp(pOLE->OBJLName,
"LIGHTS", 6)) {
3762 light_state = (pOLE->nViz == 1);
3767 m_pMenuBar->FindItem(ID_MENU_ENC_LIGHTS)
3768 ->Check((!ps52plib->IsObjNoshow(
"LIGHTS")) && light_state);
3772 DisCat nset = ps52plib->GetDisplayCategory();
3773 if ((nset == MARINERS_STANDARD) || (nset == OTHER)) {
3774 m_pMenuBar->FindItem(ID_MENU_ENC_ANCHOR)
3775 ->Check(!ps52plib->IsObjNoshow(
"SBDARE"));
3776 m_pMenuBar->Enable(ID_MENU_ENC_ANCHOR,
true);
3777 m_pMenuBar->FindItem(ID_MENU_ENC_DATA_QUALITY)
3778 ->Check(!ps52plib->IsObjNoshow(
"M_QUAL"));
3779 m_pMenuBar->Enable(ID_MENU_ENC_DATA_QUALITY,
true);
3781 m_pMenuBar->FindItem(ID_MENU_ENC_ANCHOR)->Check(
false);
3782 m_pMenuBar->Enable(ID_MENU_ENC_ANCHOR,
false);
3783 m_pMenuBar->Enable(ID_MENU_ENC_DATA_QUALITY,
false);
3788void MyFrame::UpdateGlobalMenuItems(
ChartCanvas *cc) {
3789 if (!m_pMenuBar)
return;
3791 m_pMenuBar->FindItem(ID_MENU_NAV_FOLLOW)->Check(cc->m_bFollow);
3793 if (cc->GetUpMode() == NORTH_UP_MODE)
3794 m_pMenuBar->FindItem(ID_MENU_CHART_NORTHUP)->Check(
true);
3795 else if (cc->GetUpMode() == COURSE_UP_MODE)
3796 m_pMenuBar->FindItem(ID_MENU_CHART_COGUP)->Check(
true);
3798 m_pMenuBar->FindItem(ID_MENU_CHART_HEADUP)->Check(
true);
3800 m_pMenuBar->FindItem(ID_MENU_NAV_TRACK)->Check(g_bTrackActive);
3801 m_pMenuBar->FindItem(ID_MENU_CHART_OUTLINES)->Check(cc->GetShowOutlines());
3802 m_pMenuBar->FindItem(ID_MENU_CHART_QUILTING)->Check(cc->GetQuiltMode());
3803 m_pMenuBar->FindItem(ID_MENU_UI_CHARTBAR)->Check(cc->GetShowChartbar());
3804 m_pMenuBar->FindItem(ID_MENU_AIS_TARGETS)->Check(cc->GetShowAIS());
3805 m_pMenuBar->FindItem(ID_MENU_AIS_MOORED_TARGETS)->Check(g_bHideMoored);
3806 m_pMenuBar->FindItem(ID_MENU_AIS_SCALED_TARGETS)->Check(cc->GetAttenAIS());
3807 m_pMenuBar->FindItem(ID_MENU_AIS_SCALED_TARGETS)->Enable(g_bAllowShowScaled);
3808 m_pMenuBar->FindItem(ID_MENU_AIS_TRACKS)->Check(g_bAISShowTracks);
3809 m_pMenuBar->FindItem(ID_MENU_AIS_CPADIALOG)->Check(g_bAIS_CPA_Alert);
3810 m_pMenuBar->FindItem(ID_MENU_AIS_CPASOUND)->Check(g_bAIS_CPA_Alert_Audio);
3811 m_pMenuBar->FindItem(ID_MENU_AIS_CPAWARNING)->Check(g_bCPAWarn);
3812 m_pMenuBar->FindItem(ID_MENU_SHOW_NAVOBJECTS)->Check(cc->m_bShowNavobjects);
3813 m_pMenuBar->FindItem(ID_MENU_SHOW_TIDES)->Check(cc->GetbShowTide());
3814 m_pMenuBar->FindItem(ID_MENU_SHOW_CURRENTS)->Check(cc->GetbShowCurrent());
3817 m_pMenuBar->FindItem(ID_MENU_ENC_TEXT)->Check(cc->GetShowENCText());
3818 m_pMenuBar->FindItem(ID_MENU_ENC_SOUNDINGS)->Check(cc->GetShowENCDepth());
3821 for (
unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
3823 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
3824 if (!strncmp(pOLE->OBJLName,
"LIGHTS", 6)) {
3829 m_pMenuBar->FindItem(ID_MENU_ENC_LIGHTS)->Check(cc->GetShowENCLights());
3833 DisCat nset = (DisCat)cc->GetENCDisplayCategory();
3834 if ((nset == MARINERS_STANDARD) || (nset == OTHER)) {
3835 m_pMenuBar->FindItem(ID_MENU_ENC_ANCHOR)->Check(cc->GetShowENCAnchor());
3836 m_pMenuBar->Enable(ID_MENU_ENC_ANCHOR,
true);
3837 m_pMenuBar->FindItem(ID_MENU_ENC_DATA_QUALITY)
3838 ->Check(cc->GetShowENCDataQual());
3839 m_pMenuBar->Enable(ID_MENU_ENC_DATA_QUALITY,
true);
3841 m_pMenuBar->FindItem(ID_MENU_ENC_ANCHOR)->Check(
false);
3842 m_pMenuBar->Enable(ID_MENU_ENC_ANCHOR,
false);
3843 m_pMenuBar->Enable(ID_MENU_ENC_DATA_QUALITY,
false);
3848void MyFrame::InvalidateAllCanvasUndo() {
3850 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
3852 if (cc) cc->undo->InvalidateUndo();
3856void MyFrame::SubmergeAllCanvasToolbars() {
3858 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
3860 if (cc) cc->SubmergeToolbar();
3864void MyFrame::SurfaceAllCanvasToolbars() {
3865 if (g_bshowToolbar) {
3867 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
3869 if (cc && cc->GetToolbarEnable()) cc->SurfaceToolbar();
3876void MyFrame::JumpToPosition(
ChartCanvas *cc,
double lat,
double lon,
3878 if (lon > 180.0) lon -= 360.0;
3883 cc->JumpToPosition(lat, lon,
scale);
3886 g_pi_manager->SendViewPortToRequestingPlugIns(cc->GetVP());
3890void MyFrame::UpdateCanvasConfigDescriptors() {
3892 for (
unsigned int i = 0;
3893 i < ConfigMgr::Get().GetCanvasConfigArray().GetCount(); i++) {
3894 canvasConfig *cc = ConfigMgr::Get().GetCanvasConfigArray().Item(i);
3902 cc->DBindex = chart->GetQuiltReferenceChartIndex();
3903 cc->GroupID = chart->m_groupIndex;
3906 cc->
bQuilt = chart->GetQuiltMode();
3913 cc->
bFollow = chart->m_bFollow;
3918 int upmode = chart->GetUpMode();
3919 if (upmode == COURSE_UP_MODE)
3921 else if (upmode == HEAD_UP_MODE)
3928void MyFrame::CenterView(
ChartCanvas *cc,
const LLBBox &RBBox) {
3929 if (!RBBox.GetValid())
return;
3931 double clat = (RBBox.GetMinLat() + RBBox.GetMaxLat()) / 2;
3932 double clon = (RBBox.GetMinLon() + RBBox.GetMaxLon()) / 2;
3935 if (RBBox.GetMinLat() == RBBox.GetMaxLat() &&
3936 RBBox.GetMinLon() == RBBox.GetMaxLon()) {
3944 DistanceBearingMercator(RBBox.GetMinLat(), RBBox.GetMinLon(),
3945 RBBox.GetMinLat(), RBBox.GetMaxLon(), NULL, &rw);
3947 DistanceBearingMercator(RBBox.GetMinLat(), RBBox.GetMinLon(),
3948 RBBox.GetMaxLat(), RBBox.GetMinLon(), NULL, &rh);
3950 cc->GetSize(&ww, &wh);
3952 ppm = wxMin(ww / (rw * 1852), wh / (rh * 1852)) * (100 - fabs(clat)) / 90;
3954 ppm = wxMin(ppm, 1.0);
3960void MyFrame::PrepareOptionsClose(
options *settings,
3961 int settings_return_value) {
3963 options_lastPage = settings->lastPage;
3968 if (options_lastPage == 1) options_lastPage = 0;
3970 options_subpage = settings->lastSubPage;
3971 options_lastWindowPos = settings->lastWindowPos;
3972 options_lastWindowSize = settings->lastWindowSize;
3975 androidEnableBackButton(
true);
3976 androidEnableOptionsMenu(
true);
3977 androidRestoreFullScreen();
3978 androidEnableRotation();
3981 EnableSettingsTool(
true);
3984void MyFrame::DoOptionsDialog() {
3985 EnableSettingsTool(
false);
3988 AbstractPlatform::ShowBusySpinner();
3991 pConfig->SetPath(
"/Settings");
3992 pConfig->Read(
"OptionsSizeX", &sx, -1);
3993 pConfig->Read(
"OptionsSizeY", &sy, -1);
3995 wxWindow *optionsParent =
this;
3997 optionsParent = GetPrimaryCanvas();
4000 callbacks.prepare_close = [&](
options *me,
int changes) {
4001 PrepareOptionsClose(me, changes);
4003 callbacks.process_dialog = [&](
int changes, ArrayOfCDI *workdir_list) {
4004 ProcessOptionsDialog(changes, workdir_list);
4007 wxPoint(-1, -1), wxSize(sx, sy));
4009 AbstractPlatform::HideBusySpinner();
4013 g_options->SetInitChartDir(*pInit_Chart_Dir);
4017 ArrayOfCDI *pWorkDirArray =
new ArrayOfCDI;
4018 g_options->SetWorkDirListPtr(pWorkDirArray);
4024 prev_locale = g_locale;
4025 g_options->SetInitialPage(options_lastPage, options_subpage);
4028 g_options->lastWindowPos = options_lastWindowPos;
4029 if (options_lastWindowPos != wxPoint(0, 0)) {
4031 g_options->SetSize(options_lastWindowSize);
4035 if (options_lastWindowSize != wxSize(0, 0)) {
4036 g_options->SetSize(options_lastWindowSize);
4041 androidEnableBackButton(
false);
4042 androidEnableOptionsMenu(
false);
4043 androidDisableFullScreen();
4051 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4054 wxString chart_file_name;
4055 if (cc->GetQuiltMode()) {
4056 int dbi = cc->GetQuiltRefChartdbIndex();
4057 chart_file_name =
ChartData->GetDBChartFileName(dbi);
4059 if (cc->m_singleChart)
4060 chart_file_name = cc->m_singleChart->GetFullPath();
4063 pathArray.Add(chart_file_name);
4069 last_canvasConfig = g_canvasConfig;
4072 g_last_ChartScaleFactor = g_ChartScaleFactor;
4078void MyFrame::ProcessOptionsDialog(
int rr, ArrayOfCDI *pNewDirArray) {
4079 bool b_need_refresh =
false;
4082 if ((rr & VISIT_CHARTS) &&
4083 ((rr & CHANGE_CHARTS) || (rr & FORCE_UPDATE) || (rr & SCAN_UPDATE))) {
4085 UpdateChartDatabaseInplace(*pNewDirArray,
4086 ((rr & FORCE_UPDATE) == FORCE_UPDATE),
true,
4089 b_need_refresh =
true;
4094 if (rr & STYLE_CHANGED) {
4097 _(
"Please restart OpenCPN to activate language or style changes."),
4098 _(
"OpenCPN Info"), wxOK | wxICON_INFORMATION);
4101 bool charts_updating =
4102 (rr & VISIT_CHARTS) && ((rr & CHANGE_CHARTS) || (rr & SCAN_UPDATE));
4103 if (!charts_updating) RefreshGroupIndices();
4105 if (rr & TIDES_CHANGED) {
4111 if (rr & S52_CHANGED) {
4112 WayPointmanGui(*pWayPointMan).ReloadAllIcons(g_Platform->GetDisplayDPmm());
4123 g_Platform->GetDisplayDPmm());
4126 double stuffcog = NAN;
4127 double stuffsog = NAN;
4128 if (!std::isnan(
gCog)) stuffcog =
gCog;
4129 if (!std::isnan(
gSog)) stuffsog =
gSog;
4131 for (
int i = 0; i < kMaxCogsogFilterSeconds; i++) {
4132 COGFilterTable[i] = stuffcog;
4133 SOGFilterTable[i] = stuffsog;
4136 SetChartUpdatePeriod();
4138 if (rr & GL_CHANGED) {
4142 b_need_refresh =
true;
4145 if (rr & S52_CHANGED) {
4146 b_need_refresh =
true;
4150 if (rr & REBUILD_RASTER_CACHE) {
4152 GetPrimaryCanvas()->Disable();
4154 GetPrimaryCanvas()->Enable();
4159 if (g_config_display_size_manual &&
4167 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4174 int rrt = rr & S52_CHANGED;
4176 (rrt == S52_CHANGED) ||
4177 (g_last_ChartScaleFactor != g_ChartScaleFactor));
4187 ps52plib->SetScaleFactorExp(
4188 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor));
4189 ps52plib->SetScaleFactorZoomMod(g_chart_zoom_modifier_vector);
4193 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4195 if (cc) cc->ApplyGlobalSettings();
4203 if (!charts_updating) {
4204 bool ztc = g_bEnableZoomToCursor;
4205 g_bEnableZoomToCursor =
false;
4207 if (!GetPrimaryCanvas()->IsFrozen())
4209 g_bEnableZoomToCursor = ztc;
4214 if (g_last_ChartScaleFactor != g_ChartScaleFactor) {
4223 SetGPSCompassScale();
4225 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4228 cc->GetCompass()->SetScaleFactor(g_compass_scalefactor);
4229 if (!charts_updating) cc->UpdateCanvasControlBar();
4232 UpdateGPSCompassStatusBoxes();
4234 SetAllToolbarScale();
4235 RequestNewToolbars();
4237 if ((rr & MENU_CHANGED) == MENU_CHANGED) BuildMenuBar();
4240 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4243 cc->RebuildCursors();
4248 bool b_masterScaleChange =
false;
4249 if (fabs(
g_MainToolbar->GetScaleFactor() - g_toolbar_scalefactor) > 0.01f)
4250 b_masterScaleChange =
true;
4252 if ((rr & TOOLBAR_CHANGED) || b_masterScaleChange)
4253 RequestNewMasterToolbar(
true);
4255 bool bMuiChange =
false;
4261 if (b_masterScaleChange || bMuiChange) {
4263 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4266 cc->ProcessNewGUIScale();
4272 if (rr & LOCALE_CHANGED) {
4273 g_Platform->ChangeLocale(g_locale, plocale_def_lang, &plocale_def_lang);
4275 rr |= NEED_NEW_OPTIONS;
4284 g_last_ChartScaleFactor = g_ChartScaleFactor;
4289bool MyFrame::CheckGroup(
int igroup) {
4290 if (igroup == 0)
return true;
4294 if (!pGroup->m_element_array.size())
4297 for (
const auto &elem : pGroup->m_element_array) {
4298 for (
unsigned int ic = 0;
4299 ic < (
unsigned int)
ChartData->GetChartTableEntries(); ic++) {
4300 auto &cte =
ChartData->GetChartTableEntry(ic);
4301 wxString chart_full_path(cte.GetpFullPath(), wxConvUTF8);
4303 if (chart_full_path.StartsWith(elem.m_element_name))
return true;
4310bool MyFrame::ScrubGroupArray() {
4315 bool b_change =
false;
4316 unsigned int igroup = 0;
4317 while (igroup < g_pGroupArray->GetCount()) {
4318 bool b_chart_in_element =
false;
4321 for (
unsigned int j = 0; j < pGroup->m_element_array.size(); j++) {
4322 const wxString &element_root = pGroup->m_element_array[j].m_element_name;
4324 for (
unsigned int ic = 0;
4325 ic < (
unsigned int)
ChartData->GetChartTableEntries(); ic++) {
4326 auto &cte =
ChartData->GetChartTableEntry(ic);
4327 wxString chart_full_path = cte.GetFullSystemPath();
4329 if (chart_full_path.StartsWith(element_root)) {
4330 b_chart_in_element =
true;
4336 if (!b_chart_in_element) {
4337 wxString test_string =
"GSHH";
4338 if (element_root.Upper().Contains(test_string))
4339 b_chart_in_element =
true;
4342 if (!b_chart_in_element)
4344 pGroup->m_element_array.erase(pGroup->m_element_array.begin() + j);
4356void MyFrame::RefreshCanvasOther(
ChartCanvas *ccThis) {
4358 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4360 if (cc && (cc != ccThis)) cc->Refresh();
4365void MyFrame::ChartsRefresh() {
4368 AbstractPlatform::ShowBusySpinner();
4370 bool b_run = FrameTimer1.IsRunning();
4373 FrameTenHzTimer.Stop();
4376 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4379 int currentIndex = cc->GetpCurrentStack()->GetCurrentEntrydbIndex();
4380 if (cc->GetQuiltMode()) {
4381 currentIndex = cc->GetQuiltReferenceChartIndex();
4383 cc->canvasChartsRefresh(currentIndex);
4387 if (b_run) FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
4388 if (b_run) FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
4390 AbstractPlatform::HideBusySpinner();
4393void MyFrame::InvalidateAllQuilts() {
4394 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4397 cc->InvalidateQuilt();
4398 cc->SetQuiltRefChart(-1);
4399 cc->m_singleChart = NULL;
4404bool MyFrame::UpdateChartDatabaseInplace(ArrayOfCDI &DirArray,
bool b_force,
4406 const wxString &ChartListFileName) {
4407 bool b_run = FrameTimer1.IsRunning();
4409 FrameTenHzTimer.Stop();
4411 bool b_runCOGTimer = FrameCOGTimer.IsRunning();
4412 FrameCOGTimer.Stop();
4415 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4418 cc->InvalidateQuilt();
4419 cc->SetQuiltRefChart(-1);
4420 cc->m_singleChart = NULL;
4430 AbstractPlatform::ShowBusySpinner();
4433 wxString longmsg = _(
"OpenCPN Chart Update");
4435 ".................................................................."
4438 Updateprog =
new wxGenericProgressDialog();
4441 Updateprog->SetFont(*qFont);
4443 Updateprog->Create(_(
"OpenCPN Chart Update"), longmsg, 100,
gFrame,
4444 wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
4445 wxPD_REMAINING_TIME);
4447 DimeControl(Updateprog);
4452 wxLogMessage(
"Starting chart database Update...");
4456 m_gshhg_chart_loc = gWorldMapLocation;
4457 gWorldMapLocation = wxEmptyString;
4461 AbstractPlatform::HideBusySpinner();
4465void MyFrame::FinalizeChartDBUpdate() {
4467 bool b_groupchange = ScrubGroupArray();
4469 RefreshGroupIndices();
4471 if (b_groupchange) {
4472 pConfig->DestroyConfigGroups();
4477 ScheduleReloadCharts();
4482 cc->ToggleCanvasQuiltMode();
4484 bool cur_mode = cc->GetQuiltMode();
4486 if( !cc->GetQuiltMode() )
4487 cc->SetQuiltMode(
true );
4489 if( cc->GetQuiltMode() ) {
4490 cc->SetQuiltMode(
false );
4491 g_sticky_chart = cc->GetQuiltReferenceChartIndex();
4495 if( cur_mode != cc->GetQuiltMode() ){
4501 g_bQuiltEnable = cc->GetQuiltMode();
4505 ps52plib->GenerateStateHash();
4513 DoStackDelta(cc, -1);
4519 DoStackDelta(cc, 1);
4522void MyFrame::DoStackDown(
ChartCanvas *cc) { DoStackDelta(cc, -1); }
4524void MyFrame::DoStackUp(
ChartCanvas *cc) { DoStackDelta(cc, 1); }
4526void MyFrame::DoStackDelta(
ChartCanvas *cc,
int direction) {
4528 cc->DoCanvasStackDelta(direction);
4532void MyFrame::PositionIENCToolbar() {
4536 posn.x = (GetPrimaryCanvas()->GetSize().x -
g_iENCToolbar->GetSize().x) / 2;
4538 g_iENCToolbar->Move(GetPrimaryCanvas()->ClientToScreen(posn));
4546void MyFrame::OnInitTimer(wxTimerEvent &event) {
4549 msg.Printf(
"OnInitTimer...%d", m_iInitCount);
4553 wxLog::FlushActive();
4555 switch (m_iInitCount++) {
4557 EnableSettingsTool(
false);
4562 if (g_bInlandEcdis) {
4563 double range = GetPrimaryCanvas()->GetCanvasRangeMeters();
4564 double range_set = 500.;
4566 range = wxRound(range * 10) / 10.;
4570 else if (range > 2000.)
4572 else if (range > 1600.)
4574 else if (range > 1200.)
4576 else if (range > 800.)
4581 GetPrimaryCanvas()->SetCanvasRangeMeters(range_set);
4585 g_Platform->SetFullscreen(g_bFullscreen);
4589 RebuildChartDatabase();
4590 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4593 cc->SetGroupIndex(0,
false);
4601 if (
ChartData->GetCentroidOfLargestScaleChart(&clat, &clon,
4602 CHART_FAMILY_RASTER)) {
4607 if (
ChartData->GetCentroidOfLargestScaleChart(&clat, &clon,
4608 CHART_FAMILY_VECTOR)) {
4621 auto colour_func = [](wxString c) {
return GetGlobalColor(c); };
4624 .SetColorScheme(global_color_scheme, g_Platform->GetDisplayDPmm());
4626 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4629 if (cc->SetUserOwnship()) cc->SetColorScheme(global_color_scheme);
4633 NavObj_dB::GetInstance().ImportLegacyNavobj(
this);
4634 NavObj_dB::GetInstance().LoadNavObjects();
4637 if (!g_AW1GUID.IsEmpty()) {
4640 if (!g_AW2GUID.IsEmpty()) {
4646 appendOSDirSlash(&layerdir);
4647 layerdir.Append(
"layers");
4649 if (wxDir::Exists(layerdir)) {
4651 laymsg.Printf(
"Getting .gpx layer files from: %s", layerdir.c_str());
4652 wxLogMessage(laymsg);
4653 pConfig->LoadLayers(layerdir);
4663 if (
g_pi_manager->IsAnyPlugInChartEnabled()) b_reloadForPlugins =
true;
4677 3 * GetCharHeight());
4679 m_data_monitor->Center();
4687 pConfig->SetPath(
"/Settings");
4688 pConfig->Read(
"OptionsSizeX", &sx, -1);
4689 pConfig->Read(
"OptionsSizeY", &sy, -1);
4691 wxWindow *optionsParent =
this;
4693 optionsParent = GetPrimaryCanvas();
4695 BuildiENCToolbar(
true, m_toolbar_callbacks);
4702 if (!g_params.empty()) {
4703 for (
size_t n = 0; n < g_params.size(); n++) {
4704 wxString path = g_params[n];
4705 if (::wxFileExists(path)) {
4707 pSet->load_file(path.fn_str());
4710 pSet->LoadAllGPXObjects(
4711 !pSet->IsOpenCPN(), wpt_dups,
4713 LLBBox box = pSet->GetBBox();
4714 if (box.GetValid()) {
4715 CenterView(GetPrimaryCanvas(), box);
4724 InitAppMsgBusListener();
4729 auto loader = PluginLoader::GetInstance();
4730 bool b_haveWMM = loader && loader->IsPlugInAvailable(
"WMM");
4731 if (!b_haveWMM)
gVar = g_UserVar;
4739 auto colour_func = [](wxString c) {
return GetGlobalColor(c); };
4742 .SetColorScheme(global_color_scheme, g_Platform->GetDisplayDPmm());
4744 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4747 if (cc->SetUserOwnship()) cc->SetColorScheme(global_color_scheme);
4751 NavObj_dB::GetInstance().ImportLegacyNavobj(
this);
4752 NavObj_dB::GetInstance().LoadNavObjects();
4755 if (!g_AW1GUID.IsEmpty()) {
4758 if (!g_AW2GUID.IsEmpty()) {
4764 appendOSDirSlash(&layerdir);
4765 layerdir.Append(
"layers");
4767 if (wxDir::Exists(layerdir)) {
4769 laymsg.Printf(
"Getting .gpx layer files from: %s", layerdir.c_str());
4770 wxLogMessage(laymsg);
4771 pConfig->LoadLayers(layerdir);
4776 if (!g_kiosk_startup) {
4777 AbstractPlatform::ShowBusySpinner();
4780 pConfig->SetPath(
"/Settings");
4781 pConfig->Read(
"OptionsSizeX", &sx, -1);
4782 pConfig->Read(
"OptionsSizeY", &sy, -1);
4784 wxWindow *optionsParent =
this;
4786 optionsParent = GetPrimaryCanvas();
4789 callbacks.prepare_close = [&](
options *me,
int changes) {
4790 PrepareOptionsClose(me, changes);
4792 callbacks.process_dialog = [&](
int changes, ArrayOfCDI *workdir_list) {
4793 ProcessOptionsDialog(changes, workdir_list);
4796 wxPoint(-1, -1), wxSize(sx, sy));
4797 AbstractPlatform::HideBusySpinner();
4804 wxLogMessage(
"OnInitTimer...Last Call");
4808 RequestNewMasterToolbar();
4810 PositionIENCToolbar();
4812 g_bDeferredInitDone =
true;
4822 GetPrimaryCanvas()->SetFocus();
4823 GetPrimaryCanvas()->Enable();
4826 if (b_reloadForPlugins) {
4832 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4834 if (cc) cc->SetFirstAuto(
true);
4842 wxLogMessage(
"OnInitTimer...Finalize Canvases");
4844 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
4848 cc->CheckGroupValid();
4853 androidEnableBackButton(
true);
4854 androidEnableRotation();
4855 androidEnableOptionItems(
true);
4859 if (g_start_fullscreen && !IsFullScreen()) ToggleFullScreen();
4865 gFrame->FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
4867 gFrame->FrameCOGTimer.Start(2000, wxTIMER_CONTINUOUS);
4869 gFrame->FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
4875 if (!g_bDeferredInitDone) InitTimer.Start(10, wxTIMER_ONE_SHOT);
4877 wxLog::FlushActive();
4879 RefreshAllCanvas(
true);
4880 UsbWatchDaemon::GetInstance().Start();
4881 EnableSettingsTool(
true);
4887void MyFrame::InitAppMsgBusListener() {
4888 auto &msgbus = AppMsgBus::GetInstance();
4891 AppMsg msg_basic(AppMsg::Type::BasicNavData);
4892 listener_basic_navdata.
Listen(msg_basic,
this, EVT_BASIC_NAV_DATA);
4896 auto basicnav_msg = std::static_pointer_cast<const BasicNavDataMsg>(ptr);
4897 HandleBasicNavMsg(basicnav_msg);
4901 AppMsg msg_watchdog(AppMsg::Type::GPSWatchdog);
4902 listener_gps_watchdog.
Listen(msg_watchdog,
this, EVT_GPS_WATCHDOG);
4906 auto msg = std::static_pointer_cast<const GPSWatchdogMsg>(ptr);
4907 HandleGPSWatchdogMsg(msg);
4914void MyFrame::ReleaseApiListeners() {}
4919 m_on_raise_listener.
Init(server.on_raise, [&](
ObservedEvt) { Raise(); });
4920 m_on_quit_listener.
Init(server.on_quit, [&](
ObservedEvt) { FastClose(); });
4921 server.SetGetRestApiEndpointCb([&] {
return m_rest_server.
GetEndpoint(); });
4922 server.open_file_cb = [&](
const std::string &path) {
4923 return m_open_gpx_file(path);
4930void MyFrame::HandleGPSWatchdogMsg(std::shared_ptr<const GPSWatchdogMsg> msg) {
4931 if (msg->gps_watchdog <= 0) {
4932 if (msg->wd_source == GPSWatchdogMsg::WDSource::position) {
4936 if (last_bGPSValid !=
bGPSValid) UpdateGPSCompassStatusBoxes(
true);
4941 if (m_fix_start_time.IsValid()) {
4942 wxDateTime now = wxDateTime::Now();
4943 wxTimeSpan span = now - m_fix_start_time;
4944 if (span.IsLongerThan(wxTimeSpan(0, 5))) {
4945 auto ¬eman = NotificationManager::GetInstance();
4946 wxString msg = _(
"GNSS Position fix lost");
4947 noteman.AddNotification(NotificationSeverity::kCritical,
4949 m_fix_start_time = wxInvalidDateTime;
4953 }
else if (msg->wd_source == GPSWatchdogMsg::WDSource::velocity) {
4954 bool last_bVelocityValid = bVelocityValid;
4955 bVelocityValid =
false;
4962void MyFrame::CalculateCOGAverage() {
4964 if (!std::isnan(
gCog)) {
4967 for (
int i =
g_COGAvgSec - 1; i > 0; i--) COGTable[i] = COGTable[i - 1];
4970 double sum = 0., count = 0;
4972 double adder = COGTable[i];
4973 if (std::isnan(adder))
continue;
4975 if (fabs(adder -
g_COGAvg) > 180.) {
4989 else if (sum >= 360.)
4998void MyFrame::HandleBasicNavMsg(std::shared_ptr<const BasicNavDataMsg> msg) {
4999 m_fixtime = msg->time;
5000 double hdt_data_interval = 0;
5001 double fix_time_interval = 0;
5003 double msgtime = msg->set_time.tv_sec;
5004 double m1 = msg->set_time.tv_nsec / 1e9;
5007 if (((msg->vflag & POS_UPDATE) == POS_UPDATE) &&
5008 ((msg->vflag & POS_VALID) == POS_VALID)) {
5010 if (!m_fix_start_time.IsValid()) {
5011 m_fix_start_time = wxDateTime::Now();
5016 DistanceBearingMercator(
gLat,
gLon, gLat_gt, gLon_gt, &brg, &dist);
5019 fix_time_gt_last = fix_time_gt;
5020 uint64_t fix_time_gt_now =
5021 msg->set_time.tv_sec * 1e9 + msg->set_time.tv_nsec;
5022 fix_time_interval = (fix_time_gt_now - fix_time_gt_last) / (
double)1e9;
5026 double implied_sog = dist / (fix_time_interval / 3600);
5031 gLat_gt_m1 = gLat_gt;
5032 gLon_gt_m1 = gLon_gt;
5036 fix_time_gt = fix_time_gt_now;
5040 if (((msg->vflag & COG_UPDATE) == COG_UPDATE) &&
5041 ((msg->vflag & SOG_UPDATE) == SOG_UPDATE)) {
5042 gCog_gt_m1 = gCog_gt;
5052 if (!std::isnan(gCog_gt_m1)) {
5054 if ((fabs(
gSog - implied_sog) /
gSog) > 0.5) {
5061 if ((fix_time_gt - fix_time_gt_last) > .08) {
5066 if (gCog_gt > gCog_gt_m1) {
5067 if ((gCog_gt - gCog_gt_m1) > 180.)
5072 if ((gCog_gt_m1 - gCog_gt) > 180.)
5077 difft = fabs(gCog_gt - gCog_gt_m1);
5078 if (fabs(difft > 180.)) difft = fabs(difft - 360.);
5086 double tentative_cog_rate_gt = diff / (fix_time_gt - fix_time_gt_last);
5087 tentative_cog_rate_gt *= 1e9;
5088 cog_rate_gt = tentative_cog_rate_gt;
5096 if ((msg->vflag & HDT_UPDATE) == HDT_UPDATE) {
5099static double hdt_avg;
5100 double hdt_norm =
gHdt;
5101 if(
gHdt > 180) hdt_norm -= 360;
5104 hdt_avg += hdt_norm * 0.1;
5109 if (!std::isnan(
gHdt)) {
5111 uint64_t hdt_time_gt_last = hdt_time_gt;
5112 hdt_time_gt = msg->set_time.tv_sec * 1e9 + msg->set_time.tv_nsec;
5113 hdt_data_interval = (hdt_time_gt - hdt_time_gt_last) / 1e9;
5116 if (hdt_data_interval > .09) {
5118 gHdt_gt_m1 = gHdt_gt;
5121 if (!std::isnan(gHdt_gt_m1)) {
5123 double tentative_hdt_rate_gt =
5124 (gHdt_gt - gHdt_gt_m1) / (hdt_time_gt - hdt_time_gt_last);
5125 tentative_hdt_rate_gt *= 1e9;
5127 if (fabs(tentative_hdt_rate_gt - hdt_rate_gt) < 180.)
5128 hdt_rate_gt = tentative_hdt_rate_gt;
5136 if (std::isnan(
gHdt)) gHdt_gt = NAN;
5139 CalculateCOGAverage();
5147 if ((msg->vflag & POS_UPDATE) == POS_UPDATE) {
5148 if ((msg->vflag & POS_VALID) == POS_VALID)
5153 if (last_bGPSValid !=
bGPSValid) UpdateGPSCompassStatusBoxes(
true);
5155 bVelocityValid =
true;
5159void MyFrame::UpdateStatusBar() {
5162 unsigned long uiCurrentTickCount;
5163 m_MMEAeventTime.SetToCurrent();
5164 uiCurrentTickCount =
5165 m_MMEAeventTime.GetMillisecond() / 100;
5166 uiCurrentTickCount += m_MMEAeventTime.GetTicks() * 10;
5167 if (uiCurrentTickCount > m_ulLastNMEATicktime + 1) {
5168 m_ulLastNMEATicktime = uiCurrentTickCount;
5170 if (m_tick_idx++ > 6) m_tick_idx = 0;
5175 if (NULL != GetStatusBar()) {
5178 tick_buf[0] = nmea_tick_chars[m_tick_idx];
5181 wxString s1(tick_buf, wxConvUTF8);
5183 s1 += toSDMM(1,
gLat);
5185 s1 += toSDMM(2,
gLon);
5187 if (STAT_FIELD_TICK >= 0) SetStatusText(s1, STAT_FIELD_TICK);
5191 if (!std::isnan(
gSog))
5192 sogcog.Printf(
"SOG %2.2f " + getUsrSpeedUnit() +
" ", toUsrSpeed(
gSog));
5194 sogcog.Printf(
"SOG --- ");
5198 if (!std::isnan(
gCog) && !std::isnan(
gSog) && (
gSog > 0.05)) {
5200 cogs << wxString::Format(wxString(
"COG %03d%c "), (
int)
gCog, 0x00B0);
5202 cogs << wxString::Format(wxString(
"COG %03d%c(M) "),
5203 (
int)toMagnetic(
gCog), 0x00B0);
5205 cogs.Printf((
"COG ---%c"), 0x00B0);
5207 sogcog.Append(cogs);
5208 SetStatusText(sogcog, STAT_FIELD_SOGCOG);
5213void MyFrame::OnMemFootTimer(wxTimerEvent &event) {
5214 MemFootTimer.Stop();
5216 int memsize = GetApplicationMemoryUse();
5219 printf(
"Memsize: %d \n", memsize);
5222 if (memsize > (g_MemFootMB * 1000)) {
5226 wxArrayPtrVoid *pCache =
ChartData->GetChartCache();
5227 unsigned int nCache = pCache->GetCount();
5230 for (
unsigned int i = 0; i < nCache; i++) {
5240 for (
unsigned int i = 0; i < nCache - 1; i++) {
5241 if (pcea[i].RecentTime > pcea[i + 1].RecentTime) {
5243 pcea[i] = pcea[i + 1];
5254 unsigned int idelete = 0;
5255 unsigned int idelete_max = pCache->GetCount();
5258 unsigned int minimum_cache = 1;
5259 if (cc->GetQuiltMode()) minimum_cache = cc->GetQuiltChartCount();
5261 while ((memsize > (g_MemFootMB * 1000)) &&
5262 (pCache->GetCount() > minimum_cache) &&
5263 (idelete < idelete_max)) {
5264 int memsizeb = memsize;
5268 memsize = GetApplicationMemoryUse();
5269 printf(
"delete, before: %d after: %d\n", memsizeb, memsize);
5277 MemFootTimer.Start(9000, wxTIMER_CONTINUOUS);
5282void MyFrame::CheckToolbarPosition() {
5285 static bool bMaximized;
5287 if (IsMaximized() && !bMaximized) {
5294 PositionIENCToolbar();
5295 }
else if (!IsMaximized() && bMaximized) {
5303 PositionIENCToolbar();
5308void MyFrame::ProcessUnitTest() {
5309 if (!g_bPauseTest && (g_unit_test_1 || g_unit_test_2)) {
5316 cc->m_bFollow =
false;
5318 g_MainToolbar->GetToolbar()->ToggleTool(ID_FOLLOW, cc->m_bFollow);
5319 int ut_index_max = ((g_unit_test_1 > 0) ? (g_unit_test_1 - 1) : INT_MAX);
5322 if (cc->m_groupIndex > 0) {
5323 while (ut_index < ChartData->GetChartTableEntries() &&
5324 !
ChartData->IsChartInGroup(ut_index, cc->m_groupIndex)) {
5328 if (ut_index < ChartData->GetChartTableEntries()) {
5332 double clat = (cte->GetLatMax() + cte->GetLatMin()) / 2;
5333 double clon = (cte->GetLonMax() + cte->GetLonMin()) / 2;
5340 if (cc->GetQuiltMode()) {
5341 if (cc->IsChartQuiltableRef(ut_index))
5342 cc->SelectQuiltRefdbChart(ut_index);
5344 cc->SelectdbChart(ut_index);
5347 if (g_unit_test_1) {
5355 DistanceBearingMercator(cte->GetLatMin(), cte->GetLonMin(),
5356 cte->GetLatMin(), cte->GetLonMax(), NULL,
5360 DistanceBearingMercator(cte->GetLatMin(), cte->GetLonMin(),
5361 cte->GetLatMax(), cte->GetLonMin(), NULL,
5364 cc->GetSize(&ww, &wh);
5365 ppm = wxMin(ww / (rw * 1852), wh / (rh * 1852)) * (100 - fabs(clat)) /
5367 ppm = wxMin(ppm, 1.0);
5374 if (ut_index > ut_index_max) exit(0);
5385 bool b_rotate =
false;
5387 if (cc) b_rotate |= (cc->GetUpMode() != NORTH_UP_MODE);
5390 if (!b_rotate && !g_btenhertz)
return;
5392 bool b_update =
false;
5394 if (!std::isnan(
gCog) && !std::isnan(
gSog)) {
5397 struct timespec now;
5398 clock_gettime(CLOCK_MONOTONIC, &now);
5399 uint64_t diff = 1e9 * (now.tv_sec) + now.tv_nsec - fix_time_gt;
5400 double diffc = diff / 1e9;
5403 double gCog_tentative = gCog_gt_m1 + (cog_rate_gt * diffc);
5404 if (gCog_tentative >= 360.) gCog_tentative -= 360.;
5405 if (gCog_tentative < 0.) gCog_tentative += 360.;
5406 gCog = gCog_tentative;
5410 if (!std::isnan(gHdt_gt) && !std::isnan(gHdt_gt_m1)) {
5411 uint64_t diff = 1e9 * (now.tv_sec) + now.tv_nsec - hdt_time_gt;
5412 double diffc = diff / 1e9;
5413 gHdt = gHdt_gt_m1 + (hdt_rate_gt * diffc);
5417 if (gSog_gt && !std::isnan(gCog_gt)) {
5418 double delta_t = diffc / 3600;
5419 double distance = gSog_gt * delta_t;
5422 double angr = gCog_gt / 180 * M_PI;
5423 double latr = gLat_gt * M_PI / 180;
5424 double D = distance / 3443;
5425 double sD = sin(D), cD = cos(D);
5426 double sy = sin(latr), cy = cos(latr);
5427 double sa = sin(angr), ca = cos(angr);
5429 gLon = gLon_gt + asin(sa * sD / cy) * 180 / M_PI;
5430 gLat = asin(sy * cD + cy * sD * ca) * 180 / M_PI;
5440 if (cc) cc->DoCanvasCOGSet();
5449 if (cc->GetUpMode() != NORTH_UP_MODE || cc->m_bFollow) {
5450 cc->DoCanvasUpdate();
5459 FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
5462bool MyFrame::ProcessQuitFlag() {
5466 FrameTenHzTimer.Stop();
5468 wxWindow *top = wxTheApp ? wxTheApp->GetTopWindow() :
nullptr;
5469 if (top) top->Close(
true);
5476void MyFrame::ProcessDeferredTrackOn() {
5479 if (g_bDeferredStartTrack) {
5480 if (!g_bTrackActive) {
5483 g_bDeferredStartTrack =
false;
5486 g_bDeferredStartTrack =
false;
5491void MyFrame::ProcessAnchorWatch() {
5499 double d = g_nAWMax;
5502 bool toofar =
false;
5503 bool tooclose =
false;
5504 if (d >= 0.0) toofar = (dist * 1852. > d);
5505 if (d < 0.0) tooclose = (dist * 1852 < -d);
5507 if (tooclose || toofar)
5508 AnchorAlertOn1 =
true;
5510 AnchorAlertOn1 =
false;
5512 AnchorAlertOn1 =
false;
5520 double d = g_nAWMax;
5523 bool toofar =
false;
5524 bool tooclose =
false;
5525 if (d >= 0) toofar = (dist * 1852. > d);
5526 if (d < 0) tooclose = (dist * 1852 < -d);
5528 if (tooclose || toofar)
5529 AnchorAlertOn2 =
true;
5531 AnchorAlertOn2 =
false;
5533 AnchorAlertOn2 =
false;
5536 AnchorAlertOn1 =
true;
5539void MyFrame::SendFixToPlugins() {
5550 GPSData.
nSats = g_SatsInView;
5552 wxDateTime tCheck((time_t)m_fixtime);
5553 if (tCheck.IsValid()) {
5562 GPSData.
FixTime = wxDateTime::Now().GetTicks();
5565 SendPositionFixToAllPlugIns(&GPSData);
5569void MyFrame::ProcessLogAndBells() {
5572 wxDateTime lognow = wxDateTime::Now();
5573 int hourLOC = lognow.GetHour();
5574 int minuteLOC = lognow.GetMinute();
5576 int minuteUTC = lognow.GetMinute();
5577 int second = lognow.GetSecond();
5579 wxTimeSpan logspan = lognow.Subtract(g_loglast_time);
5580 if ((logspan.IsLongerThan(wxTimeSpan(0, 30, 0, 0))) || (minuteUTC == 0) ||
5581 (minuteUTC == 30)) {
5582 if (logspan.IsLongerThan(wxTimeSpan(0, 1, 0, 0))) {
5583 wxString day = lognow.FormatISODate();
5584 wxString utc = lognow.FormatISOTime();
5585 wxString navmsg =
"LOGBOOK: ";
5593 data.Printf(
" GPS Lat %10.5f Lon %10.5f ",
gLat,
gLon);
5597 if (std::isnan(
gCog))
5598 cog.Printf(
"COG ----- ");
5600 cog.Printf(
"COG %10.5f ",
gCog);
5603 if (std::isnan(
gSog))
5604 sog.Printf(
"SOG ----- ");
5606 sog.Printf(
"SOG %6.2f " + getUsrSpeedUnit(), toUsrSpeed(
gSog));
5612 data.Printf(
" DR Lat %10.5f Lon %10.5f",
gLat,
gLon);
5615 wxLogMessage(navmsg);
5616 g_loglast_time = lognow;
5618 int bells = (hourLOC % 4) * 2;
5619 if (minuteLOC != 0) bells++;
5620 if (!bells) bells = 8;
5622 if (g_bPlayShipsBells && ((minuteLOC == 0) || (minuteLOC == 30))) {
5623 m_BellsToPlay = bells;
5624 wxCommandEvent ev(BELLS_PLAYED_EVTYPE);
5625 wxPostEvent(
this, ev);
5632 CheckToolbarPosition();
5636 if (ProcessQuitFlag())
return;
5638 if (bDBUpdateInProgress)
return;
5641 FrameTenHzTimer.Stop();
5643 ProcessDeferredTrackOn();
5645 ProcessAnchorWatch();
5646 ProcessLogAndBells();
5648 if (ShouldRestartTrack()) TrackDailyRestart();
5651 if (g_bSleep && !AnchorAlertOn1 && !AnchorAlertOn2) {
5652 FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
5653 FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
5659 if (
gSog > 3.0) g_bCruising =
true;
5665 wxString sogcog(
"SOG --- " + getUsrSpeedUnit() + +
" " +
5667 if (GetStatusBar()) SetStatusText(sogcog, STAT_FIELD_SOGCOG);
5673 bool bnew_view =
false;
5674 if (!g_btenhertz) bnew_view = DoChartUpdate();
5681 bool bactiveRouteUpdate =
RoutemanGui(*g_pRouteMan).UpdateProgress();
5684 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5687 cc->DrawBlinkObjects();
5690 if (bactiveRouteUpdate) {
5697 cc->SetOwnShipState(SHIP_NORMAL);
5699 if (cc->GetQuiltMode()) {
5700 double erf = cc->GetQuiltMaxErrorFactor();
5701 if (erf > 0.02) cc->SetOwnShipState(SHIP_LOWACCURACY);
5703 if (cc->m_singleChart) {
5704 if (cc->m_singleChart->GetChart_Error_Factor() > 0.02)
5705 cc->SetOwnShipState(SHIP_LOWACCURACY);
5709 if (!
bGPSValid) cc->SetOwnShipState(SHIP_INVALID);
5712 (bVelocityValid != m_last_bVelocityValid) ||
5713 (!isnan(
gHdt) && (
gHdt != m_last_hdt))) {
5714 if (!g_bopengl) cc->UpdateShips();
5722 m_last_bVelocityValid = bVelocityValid;
5727 bool brq_dynamic =
false;
5729 auto *pplugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
5730 for (
unsigned int i = 0; i < pplugin_array->GetCount(); i++) {
5732 if (pic->m_enabled && pic->m_init_state) {
5733 if (pic->
m_cap_flag & WANTS_DYNAMIC_OPENGL_OVERLAY_CALLBACK) {
5740 if (brq_dynamic) bnew_view =
true;
5744 if (AnchorAlertOn1 || AnchorAlertOn2) bnew_view =
true;
5747 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5752 if (cc->GetglCanvas()) {
5754 bool b_rotate = cc->GetUpMode() != NORTH_UP_MODE;
5757 if (cc->m_bFollow) {
5758 cc->DoCanvasUpdate();
5775 if ((!cc->m_bFollow) || (cc->GetUpMode() != NORTH_UP_MODE)) {
5789 if (g_pais_query_dialog_active && g_pais_query_dialog_active->IsShown())
5790 g_pais_query_dialog_active->UpdateText();
5793 if (g_pAISTargetList && (0 == (g_tick % (5))))
5794 g_pAISTargetList->UpdateAISTargetList();
5797 UpdateGPSCompassStatusBoxes();
5802 console->RefreshConsoleData();
5809 if (m_bdefer_resize) {
5810 if (0 == (g_tick % (5))) {
5811 printf(
"___RESIZE\n");
5812 SetSize(m_defer_size);
5814 m_bdefer_resize =
false;
5821 FrameTimer1.Start(TIMER_GFRAME_1 * 3, wxTIMER_CONTINUOUS);
5823 FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
5824 FrameTenHzTimer.Start(100, wxTIMER_CONTINUOUS);
5828double MyFrame::GetMag(
double a,
double lat,
double lon) {
5829 double Variance = std::isnan(
gVar) ? g_UserVar :
gVar;
5830 auto loader = PluginLoader::GetInstance();
5831 if (loader && loader->IsPlugInAvailable(
"WMM")) {
5838 wxDateTime now = wxDateTime::Now();
5839 SendJSON_WMM_Var_Request(lat, lon, now);
5840 if (fabs(gQueryVar) < 360.0)
5841 Variance = gQueryVar;
5843 return toMagnetic(a, Variance);
5846bool MyFrame::SendJSON_WMM_Var_Request(
double lat,
double lon,
5852 v[
"Year"] = date.GetYear();
5853 v[
"Month"] = date.GetMonth();
5854 v[
"Day"] = date.GetDay();
5856 SendJSONMessageToAllPlugins(
"WMM_VARIATION_REQUEST", v);
5862void MyFrame::TouchAISActive() {
5864 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5866 if (cc) cc->TouchAISToolActive();
5870void MyFrame::UpdateAISTool() {
5874 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5876 if (cc) cc->UpdateAISTBTool();
5881void MyFrame::OnFrameTCTimer(wxTimerEvent &event) {
5883 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5885 if (cc) cc->SetbTCUpdate(
true);
5888 RefreshAllCanvas(
false);
5893void MyFrame::OnFrameCOGTimer(wxTimerEvent &event) {
5897 bool b_rotate =
false;
5898 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5900 if (cc) b_rotate |= (cc->GetUpMode() != NORTH_UP_MODE);
5904 FrameCOGTimer.Stop();
5911 int period_ms = 100;
5913 FrameCOGTimer.Start(period_ms, wxTIMER_CONTINUOUS);
5916void MyFrame::DoCOGSet() {
5918 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5920 if (cc) cc->DoCanvasCOGSet();
5924void RenderShadowText(wxDC *pdc, wxFont *pFont, wxString &str,
int x,
int y) {
5930 wxFont oldfont = pdc->GetFont();
5932 pdc->SetFont(*pFont);
5933 pdc->SetTextForeground(GetGlobalColor(
"CHGRF"));
5934 pdc->SetBackgroundMode(wxTRANSPARENT);
5936 pdc->DrawText(str, x, y + 1);
5937 pdc->DrawText(str, x, y - 1);
5938 pdc->DrawText(str, x + 1, y);
5939 pdc->DrawText(str, x - 1, y);
5941 pdc->SetTextForeground(GetGlobalColor(
"CHBLK"));
5943 pdc->DrawText(str, x, y);
5945 pdc->SetFont(oldfont);
5949void MyFrame::UpdateRotationState(
double rotation) {
5951 g_bCourseUp =
false;
5953 if (fabs(rotation) > .001) {
5954 SetMenubarItemState(ID_MENU_CHART_COGUP,
false);
5955 SetMenubarItemState(ID_MENU_CHART_NORTHUP,
true);
5957 m_pMenuBar->SetLabel(ID_MENU_CHART_NORTHUP, _(
"Rotated Mode"));
5960 SetMenubarItemState(ID_MENU_CHART_COGUP, g_bCourseUp);
5961 SetMenubarItemState(ID_MENU_CHART_NORTHUP, !g_bCourseUp);
5963 m_pMenuBar->SetLabel(ID_MENU_CHART_NORTHUP, _(
"North Up Mode"));
5967 UpdateGPSCompassStatusBoxes(
true);
5971void MyFrame::UpdateGPSCompassStatusBoxes(
bool b_force_new) {
5973 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
5975 if (cc) cc->UpdateGPSCompassStatusBox(b_force_new);
5981int MyFrame::GetApplicationMemoryUse() {
5987 wxWindow *fWin = wxWindow::FindFocus();
5989 wxArrayString outputArray;
5990 wxString cmd(
"ps --no-headers -o vsize ");
5991 unsigned long pid = wxGetProcessId();
5993 cmd1.Printf(
"%ld", pid);
5995 wxExecute(cmd, outputArray);
5997 if (outputArray.GetCount()) {
5998 wxString s = outputArray.Item(0);
6000 if (s.ToLong(&vtmp)) memsize = vtmp;
6003 if (fWin) fWin->SetFocus();
6009 PROCESS_MEMORY_COUNTERS pmc;
6011 unsigned long processID = wxGetProcessId();
6013 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE,
6015 if (NULL == hProcess)
return 0;
6017 if (GetProcessMemoryInfo(hProcess, &pmc,
sizeof(pmc))) {
6035 memsize = pmc.WorkingSetSize / 1024;
6038 CloseHandle(hProcess);
6045double MyFrame::GetBestVPScale(
ChartBase *pchart) {
6046 return GetPrimaryCanvas()->GetBestVPScale(pchart);
6049void MyFrame::SetChartUpdatePeriod() {
6052 g_ChartUpdatePeriod = 0;
6057 bool bskewdc =
false;
6058 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6061 if (!g_bopengl && !cc->GetVP().b_quilt) {
6062 if (fabs(cc->GetVP().
skew) > 0.0001) bskewdc =
true;
6064 if (cc->m_bFollow) g_ChartUpdatePeriod = 1;
6068 if (bskewdc) g_ChartUpdatePeriod = g_SkewCompUpdatePeriod;
6070 m_ChartUpdatePeriod = g_ChartUpdatePeriod;
6075 cc->UpdateCanvasControlBar();
6078void MyFrame::selectChartDisplay(
int type,
int family) {
6080 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6082 if (cc) cc->selectCanvasChartDisplay(type, family);
6085 UpdateGlobalMenuItems();
6094bool MyFrame::DoChartUpdate() {
6095 bool return_val =
false;
6098 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6100 if (cc) return_val |= cc->DoCanvasUpdate();
6106void MyFrame::MouseEvent(wxMouseEvent &event) {
6108 event.GetPosition(&x, &y);
6113#include <mach/mach.h>
6114#include <mach/message.h>
6115#include <mach/kern_return.h>
6116#include <mach/task_info.h>
6118#include <malloc/malloc.h>
6125#if defined(__linux__)
6126#include "sys/types.h"
6127#include "sys/sysinfo.h"
6130void MyFrame::DoPrint(
void) {
6132 g_PrintingInProgress =
true;
6135 GetPrimaryCanvas()->GetglCanvas()->Render();
6136 GetPrimaryCanvas()->GetglCanvas()->SwapBuffers();
6146 printer.Initialize(wxLANDSCAPE);
6147 printer.EnablePageNumbers(
false);
6148 printer.Print(
this, &printout);
6166 g_PrintingInProgress =
false;
6169 GetPrimaryCanvas()->SetFocus();
6175 wxString message_ID =
event.GetID();
6176 wxString message_JSONText =
event.GetJSONText();
6184 if (message_ID ==
"WMM_VARIATION_BOAT") {
6192 int numErrors = reader.
Parse(message_JSONText, &root);
6193 if (numErrors > 0) {
6199 wxString decl = root[
"Decl"].
AsString();
6201 decl.ToDouble(&decl_val);
6207 if (message_ID ==
"WMM_VARIATION") {
6215 int numErrors = reader.
Parse(message_JSONText, &root);
6216 if (numErrors > 0) {
6222 wxString decl = root[
"Decl"].
AsString();
6224 decl.ToDouble(&decl_val);
6226 gQueryVar = decl_val;
6229 if (message_ID ==
"GRIB_TIMELINE") {
6232 int numErrors = r.
Parse(message_JSONText, &v);
6234 if (numErrors > 0) {
6235 wxLogMessage(
"GRIB_TIMELINE: JSON parse error");
6240 wxDateTime oldTimeSource = gTimeSource;
6242 if (v[
"Day"].AsInt() == -1) {
6243 gTimeSource = wxInvalidDateTime;
6244 wxLogMessage(
"GRIB_TIMELINE: Reset to system time");
6246 gTimeSource.Set(v[
"Day"].AsInt(), (wxDateTime::Month)v[
"Month"].AsInt(),
6247 v[
"Year"].AsInt(), v[
"Hour"].AsInt(), v[
"Minute"].AsInt(),
6248 v[
"Second"].AsInt());
6252 if (oldTimeSource != gTimeSource) {
6254 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6256 if (cc && (cc->GetbShowTide() || cc->GetbShowCurrent())) {
6261 cc->pCwin->Refresh(
false);
6267 if (message_ID ==
"OCPN_TRACK_REQUEST") {
6270 wxString trk_id = wxEmptyString;
6272 int numErrors = reader.
Parse(message_JSONText, &root);
6273 if (numErrors > 0)
return;
6278 v[
"Track_ID"] = trk_id;
6280 wxString name = wxEmptyString;
6281 if (ptrack->m_GUID == trk_id) {
6282 name = ptrack->GetName();
6283 if (name.IsEmpty()) {
6289 name = _(
"(Unnamed Track)");
6296 v[
"TotalNodes"] = ptrack->GetnPoints();
6297 for (
int j = 0; j < ptrack->GetnPoints(); j++) {
6299 v[
"lat"] = tp->m_lat;
6300 v[
"lon"] = tp->m_lon;
6303 wxString msg_id(
"OCPN_TRACKPOINTS_COORDS");
6304 SendJSONMessageToAllPlugins(msg_id, v);
6310 wxString msg_id(
"OCPN_TRACKPOINTS_COORDS");
6311 SendJSONMessageToAllPlugins(msg_id, v);
6313 }
else if (message_ID ==
"OCPN_ROUTE_REQUEST") {
6316 wxString guid = wxEmptyString;
6318 int numErrors = reader.
Parse(message_JSONText, &root);
6319 if (numErrors > 0) {
6328 wxString name = wxEmptyString;
6330 if ((*it)->m_GUID == guid) {
6331 name = (*it)->m_RouteNameString;
6332 if (name.IsEmpty()) name = _(
"(Unnamed Route)");
6338 for (RoutePointList::iterator itp = (*it)->pRoutePointList->begin();
6339 itp != (*it)->pRoutePointList->end(); itp++) {
6340 w[i][
"lat"] = (*itp)->m_lat;
6341 w[i][
"lon"] = (*itp)->m_lon;
6342 w[i][
"Name"] = (*itp)->GetName();
6343 w[i][
"Description"] = (*itp)->GetDescription();
6344 w[i][
"GUID"] = (*itp)->m_GUID;
6345 w[i][
"ArrivalRadius"] = (*itp)->GetWaypointArrivalRadius();
6347 auto node = (*itp)->m_HyperlinkList->begin();
6348 if (node != (*itp)->m_HyperlinkList->end()) {
6350 while (node != (*itp)->m_HyperlinkList->end()) {
6352 v[i][
"WPLink" + wxString::Format(
"%d", n)] = httpLink->Link;
6353 v[i][
"WPLinkDesciption" + wxString::Format(
"%d", n++)] =
6354 httpLink->DescrText;
6361 wxString msg_id(
"OCPN_ROUTE_RESPONSE");
6362 SendJSONMessageToAllPlugins(msg_id, v);
6369 wxString msg_id(
"OCPN_ROUTE_RESPONSE");
6370 SendJSONMessageToAllPlugins(msg_id, v);
6371 }
else if (message_ID ==
"OCPN_ROUTELIST_REQUEST") {
6376 int numErrors = reader.
Parse(message_JSONText, &root);
6377 if (numErrors > 0)
return;
6380 wxString str = root[
"mode"].
AsString();
6381 if (str ==
"Track") route =
false;
6386 for (RouteList::iterator it =
pRouteList->begin();
6388 wxString name = (*it)->m_RouteNameString;
6389 if (name.IsEmpty()) name = _(
"(Unnamed Route)");
6391 v[i][
"error"] =
false;
6392 v[i][
"name"] = name;
6393 v[i][
"GUID"] = (*it)->m_GUID;
6394 v[i][
"active"] = (*it)->IsActive();
6399 wxString name = ptrack->GetName();
6400 if (name.IsEmpty()) {
6406 name = _(
"(Unnamed Track)");
6408 v[i][
"error"] =
false;
6409 v[i][
"name"] = name;
6410 v[i][
"GUID"] = ptrack->m_GUID;
6415 wxString msg_id(
"OCPN_ROUTELIST_RESPONSE");
6416 SendJSONMessageToAllPlugins(msg_id, v);
6419 v[0][
"error"] =
true;
6420 wxString msg_id(
"OCPN_ROUTELIST_RESPONSE");
6421 SendJSONMessageToAllPlugins(msg_id, v);
6423 }
else if (message_ID ==
"OCPN_ACTIVE_ROUTELEG_REQUEST") {
6425 v[0][
"error"] =
true;
6428 v[0][
"error"] =
false;
6429 v[0][
"range"] =
g_pRouteMan->GetCurrentRngToActivePoint();
6430 v[0][
"bearing"] =
g_pRouteMan->GetCurrentBrgToActivePoint();
6431 v[0][
"XTE"] =
g_pRouteMan->GetCurrentXTEToActivePoint();
6432 v[0][
"active_route_GUID"] =
g_pRouteMan->GetpActiveRoute()->GetGUID();
6433 v[0][
"active_waypoint_lat"] =
6435 v[0][
"active_waypoint_lon"] =
6439 wxString msg_id(
"OCPN_ACTIVE_ROUTELEG_RESPONSE");
6440 SendJSONMessageToAllPlugins(msg_id, v);
6444void MyFrame::FilterCogSog() {
6445 if (g_bfilter_cogsog) {
6447 double cog_last =
gCog;
6450 for (
int i = g_COGFilterSec - 1; i > 0; i--)
6451 COGFilterTable[i] = COGFilterTable[i - 1];
6452 COGFilterTable[0] = cog_last;
6455 if (!std::isnan(cog_last)) {
6457 double sum = 0., count = 0;
6458 for (
int i = 0; i < g_COGFilterSec; i++) {
6459 double adder = COGFilterTable[i];
6460 if (std::isnan(adder))
continue;
6462 if (fabs(adder - cog_last) > 180.) {
6463 if ((adder - cog_last) > 0.)
6476 else if (sum >= 360.)
6483 double sog_last =
gSog;
6486 for (
int i = g_SOGFilterSec - 1; i > 0; i--)
6487 SOGFilterTable[i] = SOGFilterTable[i - 1];
6488 SOGFilterTable[0] = sog_last;
6491 if (!std::isnan(
gSog)) {
6492 double sum = 0., count = 0;
6493 for (
int i = 0; i < g_SOGFilterSec; i++) {
6494 if (std::isnan(SOGFilterTable[i]))
continue;
6496 sum += SOGFilterTable[i];
6506void MyFrame::LoadHarmonics() {
6509 ptcmgr->LoadDataSources(TideCurrentDataSet);
6511 bool b_newdataset =
false;
6514 for (
auto a :
ptcmgr->GetDataSet()) {
6515 bool b_foundi =
false;
6516 for (
auto b : TideCurrentDataSet) {
6523 b_newdataset =
true;
6528 for (
auto a : TideCurrentDataSet) {
6529 bool b_foundi =
false;
6530 for (
auto b :
ptcmgr->GetDataSet()) {
6537 b_newdataset =
true;
6542 if (b_newdataset)
ptcmgr->LoadDataSources(TideCurrentDataSet);
6546void MyFrame::ActivateAISMOBRoute(
const AisTargetData *ptarget) {
6547 if (!ptarget)
return;
6550 wxDateTime mob_time = wxDateTime::Now();
6551 wxString mob_label(_(
"AIS MAN OVERBOARD"));
6552 mob_label += _(
" on ");
6553 mob_label += ocpn::toUsrDateTimeFormat(mob_time);
6556 mob_label, wxEmptyString);
6557 pWP_MOB->SetShared(
true);
6559 pSelect->AddSelectableRoutePoint(ptarget->Lat, ptarget->Lon, pWP_MOB);
6561 NavObj_dB::GetInstance().InsertRoutePoint(pWP_MOB);
6563 pWP_MOB->SetUseSca(
false);
6571 wxString(_(
"Own ship")), wxEmptyString);
6573 pWP_MOB->SetUseSca(
false);
6580 pSelect->AddSelectableRouteSegment(ptarget->Lat, ptarget->Lon,
gLat,
gLon,
6596 wxString msg_id(
"OCPN_MAN_OVERBOARD");
6597 SendJSONMessageToAllPlugins(msg_id, v);
6600 if (RouteManagerDialog::getInstanceFlag()) {
6607 RefreshAllCanvas(
false);
6609 wxString mob_message(_(
"AIS MAN OVERBOARD"));
6610 mob_message += _(
" Time: ");
6611 mob_message += ocpn::toUsrDateTimeFormat(mob_time);
6612 mob_message += _(
" Ownship Position: ");
6613 mob_message += toSDMM(1,
gLat);
6615 mob_message += toSDMM(2,
gLon);
6616 mob_message += _(
" MOB Position: ");
6617 mob_message += toSDMM(1, ptarget->Lat);
6619 mob_message += toSDMM(2, ptarget->Lon);
6620 wxLogMessage(mob_message);
6623void MyFrame::UpdateAISMOBRoute(
const AisTargetData *ptarget) {
6627 OwnPoint->m_lat =
gLat;
6628 OwnPoint->m_lon =
gLon;
6630 pSelect->DeleteSelectableRoutePoint(OwnPoint);
6635 MOB_Point->m_lat = ptarget->Lat;
6636 MOB_Point->m_lon = ptarget->Lon;
6638 pSelect->DeleteSelectableRoutePoint(MOB_Point);
6639 pSelect->AddSelectableRoutePoint(ptarget->Lat, ptarget->Lon, MOB_Point);
6641 pSelect->UpdateSelectableRouteSegments(OwnPoint);
6642 pSelect->UpdateSelectableRouteSegments(MOB_Point);
6645 RefreshAllCanvas(
false);
6648 wxDateTime mob_time = wxDateTime::Now();
6650 wxString mob_message(_(
"AIS MAN OVERBOARD UPDATE"));
6651 mob_message += _(
" Time: ");
6652 mob_message += ocpn::toUsrDateTimeFormat(mob_time);
6653 mob_message += _(
" Ownship Position: ");
6654 mob_message += toSDMM(1,
gLat);
6656 mob_message += toSDMM(2,
gLon);
6657 mob_message += _(
" MOB Position: ");
6658 mob_message += toSDMM(1, ptarget->Lat);
6660 mob_message += toSDMM(2, ptarget->Lon);
6662 wxLogMessage(mob_message);
6666void MyFrame::applySettingsString(wxString settings) {
6668 int last_UIScaleFactor = g_GUIScaleFactor;
6669 bool previous_expert = g_bUIexpert;
6670 g_last_ChartScaleFactor = g_ChartScaleFactor;
6671 ArrayOfCDI *pNewDirArray =
new ArrayOfCDI;
6674 g_Platform->platformApplyPrivateSettingsString(settings, pNewDirArray);
6680 if (g_last_ChartScaleFactor != g_ChartScaleFactor) rr |= S52_CHANGED;
6682 if (rr & S52_CHANGED) {
6684 ps52plib->FlushSymbolCaches(ChartCtxFactory());
6686 ->ClearCNSYLUPArray();
6687 ps52plib->GenerateStateHash();
6691 ProcessOptionsDialog(rr, pNewDirArray);
6696 bool b_newToolbar =
false;
6698 if (g_GUIScaleFactor != last_UIScaleFactor) b_newToolbar =
true;
6700 if (previous_expert != g_bUIexpert) b_newToolbar =
true;
6702 if (rr & TOOLBAR_CHANGED) {
6703 b_newToolbar =
true;
6708 if (previous_expert && !g_bUIexpert) {
6709 androidForceFullRepaint();
6713 if (previous_expert != g_bUIexpert) g_Platform->applyExpertMode(g_bUIexpert);
6717 SetGPSCompassScale();
6719 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
6721 if (cc) cc->GetCompass()->SetScaleFactor(g_compass_scalefactor);
6723 UpdateGPSCompassStatusBoxes(
true);
6726 AbstractPlatform::ShowBusySpinner();
6728 SetAllToolbarScale();
6732 AbstractPlatform::HideBusySpinner();
6734 RequestNewMasterToolbar(
true);
6741 UpdateControlBar(GetPrimaryCanvas());
6747 if (m_data_monitor->
IsVisible()) m_data_monitor->Raise();
6750#ifdef wxHAS_POWER_EVENTS
6751void MyFrame::OnSuspending(wxPowerEvent &event) {
6755 wxLogMessage(
"System suspend starting...");
6758void MyFrame::OnSuspended(wxPowerEvent &WXUNUSED(event)) {
6761 wxLogMessage(
"System is going to suspend.");
6764void MyFrame::OnSuspendCancel(wxPowerEvent &WXUNUSED(event)) {
6767 wxLogMessage(
"System suspend was cancelled.");
6770int g_last_resume_ticks;
6771void MyFrame::OnResume(wxPowerEvent &WXUNUSED(event)) {
6772 wxDateTime now = wxDateTime::Now();
6773 wxLogMessage(
"System resumed from suspend.");
6775 if ((now.GetTicks() - g_last_resume_ticks) > 5) {
6778 wxLogMessage(
"Restarting streams.");
6779 g_last_resume_ticks = now.GetTicks();
6783 g_pMUX->ClearStreams();
6785 g_pMUX->StartAllStreams();
6794 if (IsMaximized()) {
6799 wxSize sz = GetSize();
6800 SetSize(wxSize(sz.x - 1, sz.y));
6812void MyFrame::RequestNewMasterToolbar(
bool bforcenew) {
6813 bool btbRebuild =
false;
6815 bool b_reshow =
true;
6818 float ff = fabs(
g_MainToolbar->GetScaleFactor() - g_toolbar_scalefactor);
6819 if ((ff > 0.01f) || bforcenew) {
6829 long orient = g_Platform->GetDefaultToolbarOrientation();
6830 wxWindow *toolbarParent =
this;
6832 toolbarParent = GetPrimaryCanvas();
6835 toolbarParent, wxPoint(-1, -1), orient, g_toolbar_scalefactor,
6836 m_toolbar_callbacks);
6838 g_MainToolbar->SetToolbarHideMethod(TOOLBAR_HIDE_TO_FIRST_TOOL);
6845 g_bmasterToolbarFull =
true;
6849 CreateMasterToolbar();
6864bool MyFrame::CollapseGlobalToolbar() {
6866 m_nMasterToolCountShown = 1;
6870 g_bmasterToolbarFull =
false;
6886 ID_MASTERTOGGLE, style->GetToolIcon(
"MUI_menu", TOOLICON_NORMAL),
6887 wxITEM_NORMAL, _(
"Hide Toolbar"),
"MUI_menu");
6888 tic->m_bRequired =
true;
6893 ID_SETTINGS, style->GetToolIcon(
"MUI_settings", TOOLICON_NORMAL),
6894 wxITEM_NORMAL, _(
"Options"),
"MUI_settings");
6898 ID_MENU_ROUTE_NEW, style->GetToolIcon(
"MUI_route", TOOLICON_NORMAL),
6899 style->GetToolIcon(
"MUI_route", TOOLICON_TOGGLED), wxITEM_CHECK,
6900 wxString(_(
"Create Route")) <<
" (Ctrl-R)",
"MUI_route");
6905 ID_ROUTEMANAGER, style->GetToolIcon(
"MUI_RMD", TOOLICON_NORMAL),
6906 wxITEM_NORMAL, _(
"Route & Mark Manager"),
"MUI_RMD");
6910 ID_TRACK, style->GetToolIcon(
"MUI_track", TOOLICON_NORMAL),
6911 style->GetToolIcon(
"MUI_track", TOOLICON_TOGGLED), wxITEM_CHECK,
6912 _(
"Enable Tracking"),
"MUI_track");
6916 ID_COLSCHEME, style->GetToolIcon(
"MUI_colorscheme", TOOLICON_NORMAL),
6917 wxITEM_NORMAL, _(
"Change Color Scheme"),
"MUI_colorscheme");
6929 ID_PRINT, style->GetToolIcon(
"MUI_print", TOOLICON_NORMAL), wxITEM_NORMAL,
6930 _(
"Print Chart"),
"MUI_print");
6934 ID_ABOUT, style->GetToolIcon(
"MUI_help", TOOLICON_NORMAL), wxITEM_NORMAL,
6935 _(
"About OpenCPN"),
"MUI_help");
6939 AddDefaultPositionPlugInTools();
6943 ID_MOB, style->GetToolIcon(
"mob_btn", TOOLICON_NORMAL), wxITEM_NORMAL,
6944 wxString(_(
"Drop MOB Marker")) << _(
" (Ctrl-Space)"),
"mob_btn");
6955 ArrayOfPlugInToolbarTools tool_array =
6957 for (
unsigned int i = 0; i < tool_array.GetCount(); i++) {
6959 if (!pttc->b_viz)
continue;
6961 if (pttc->kind == wxITEM_CHECK) tb->ToggleTool(pttc->id, pttc->b_toggle);
6964 SetMasterToolbarItemState(ID_TRACK, g_bTrackActive);
6965 if (g_bTrackActive) {
6966 g_MainToolbar->SetToolShortHelp(ID_TRACK, _(
"Disable Tracking"));
6973bool MyFrame::CheckAndAddPlugInTool() {
6981 if (!tb)
return false;
6983 int n_tools = tb->GetToolsCount();
6987 ArrayOfPlugInToolbarTools tool_array =
6990 for (
unsigned int i = 0; i < tool_array.GetCount(); i++) {
6992 if (pttc->position == n_tools) {
6993 wxBitmap *ptool_bmp;
6995 switch (global_color_scheme) {
6996 case GLOBAL_COLOR_SCHEME_DAY:
6997 ptool_bmp = pttc->bitmap_day;
7000 case GLOBAL_COLOR_SCHEME_DUSK:
7001 ptool_bmp = pttc->bitmap_dusk;
7003 case GLOBAL_COLOR_SCHEME_NIGHT:
7004 ptool_bmp = pttc->bitmap_night;
7007 ptool_bmp = pttc->bitmap_day;
7012 pttc->id, *(ptool_bmp), pttc->kind, pttc->shortHelp,
"");
7014 tic->m_NormalIconSVG = pttc->pluginNormalIconSVG;
7015 tic->m_RolloverIconSVG = pttc->pluginRolloverIconSVG;
7016 tic->m_ToggledIconSVG = pttc->pluginToggledIconSVG;
7017 tic->m_bPlugin =
true;
7026 while (CheckAndAddPlugInTool()) {
7032bool MyFrame::AddDefaultPositionPlugInTools() {
7039 ArrayOfPlugInToolbarTools tool_array =
7042 for (
unsigned int i = 0; i < tool_array.GetCount(); i++) {
7046 if (!pttc->b_viz)
continue;
7048 if (pttc->position == -1)
7050 wxBitmap *ptool_bmp;
7052 switch (global_color_scheme) {
7053 case GLOBAL_COLOR_SCHEME_DAY:
7054 ptool_bmp = pttc->bitmap_day;
7056 case GLOBAL_COLOR_SCHEME_DUSK:
7057 ptool_bmp = pttc->bitmap_dusk;
7059 case GLOBAL_COLOR_SCHEME_NIGHT:
7060 ptool_bmp = pttc->bitmap_night;
7063 ptool_bmp = pttc->bitmap_day;
7068 pttc->id, *(ptool_bmp), pttc->kind, pttc->shortHelp,
"");
7070 tic->m_NormalIconSVG = pttc->pluginNormalIconSVG;
7071 tic->m_RolloverIconSVG = pttc->pluginRolloverIconSVG;
7072 tic->m_ToggledIconSVG = pttc->pluginToggledIconSVG;
7073 tic->m_bPlugin =
true;
7092typedef struct _MSW_COLOR_SPEC {
7094 wxString S52_RGB_COLOR;
7098MSW_COLOR_SPEC color_spec[] = {{COLOR_MENU,
"UIBCK", 0},
7099 {COLOR_MENUTEXT,
"UITX1", 0},
7100 {COLOR_BTNSHADOW,
"UIBCK", 0},
7103void SaveSystemColors() {
7117 MSW_COLOR_SPEC *pcspec = &color_spec[0];
7118 while (pcspec->COLOR_NAME != -1) {
7119 pcspec->SysRGB_COLOR = pGetSysColor(pcspec->COLOR_NAME);
7124void RestoreSystemColors() {
7125 int element[NCOLORS];
7126 int rgbcolor[NCOLORS];
7129 MSW_COLOR_SPEC *pcspec = &color_spec[0];
7130 while (pcspec->COLOR_NAME != -1) {
7131 element[i] = pcspec->COLOR_NAME;
7132 rgbcolor[i] = pcspec->SysRGB_COLOR;
7137 if (pSetSysColors) {
7138 pSetSysColors(i, (
unsigned long *)&element[0],
7139 (
unsigned long *)&rgbcolor[0]);
7145void SetSystemColors(ColorScheme cs) {
7147 int element[NCOLORS];
7148 int rgbcolor[NCOLORS];
7150 if ((GLOBAL_COLOR_SCHEME_DUSK == cs) || (GLOBAL_COLOR_SCHEME_NIGHT == cs)) {
7151 MSW_COLOR_SPEC *pcspec = &color_spec[0];
7152 while (pcspec->COLOR_NAME != -1) {
7153 wxColour color = GetGlobalColor(pcspec->S52_RGB_COLOR);
7154 rgbcolor[i] = (color.Red() << 16) + (color.Green() << 8) + color.Blue();
7155 element[i] = pcspec->COLOR_NAME;
7161 pSetSysColors(i, (
unsigned long *)&element[0],
7162 (
unsigned long *)&rgbcolor[0]);
7166 RestoreSystemColors();
7173static const WORD MAX_CONSOLE_LINES =
7178void RedirectIOToConsole()
7183 wxIntPtr lStdHandle;
7185 CONSOLE_SCREEN_BUFFER_INFO coninfo;
7195 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
7196 coninfo.dwSize.Y = MAX_CONSOLE_LINES;
7197 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
7201 lStdHandle = (wxIntPtr)GetStdHandle(STD_OUTPUT_HANDLE);
7202 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
7203 fp = _fdopen(hConHandle,
"w");
7205 setvbuf(stdout, NULL, _IONBF, 0);
7209 lStdHandle = (wxIntPtr)GetStdHandle(STD_INPUT_HANDLE);
7210 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
7211 fp = _fdopen(hConHandle,
"r");
7213 setvbuf(stdin, NULL, _IONBF, 0);
7217 lStdHandle = (wxIntPtr)GetStdHandle(STD_ERROR_HANDLE);
7218 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
7219 fp = _fdopen(hConHandle,
"w");
7221 setvbuf(stderr, NULL, _IONBF, 0);
7232 FontMgr::Get().SetLocale(g_locale);
7253 if (g_pais_query_dialog_active) {
7254 g_pais_query_dialog_active->Destroy();
7255 g_pais_query_dialog_active = NULL;
7258 auto alert_dlg_active =
7260 if (alert_dlg_active) {
7261 alert_dlg_active->Destroy();
7262 g_pais_alert_dialog_active =
nullptr;
7265 if (g_pAISTargetList) {
7267 g_pAISTargetList->Disconnect_decoder();
7268 g_pAISTargetList->Destroy();
7269 g_pAISTargetList = NULL;
7273 if (gFrame->m_pMenuBar) {
7274 gFrame->SetMenuBar(NULL);
7275 gFrame->m_pMenuBar->Destroy();
7276 gFrame->m_pMenuBar = NULL;
7278 gFrame->BuildMenuBar();
7281 for (
unsigned int i = 0; i <
g_canvasArray.GetCount(); i++) {
7283 if (cc) cc->CanvasApplyLocale();
7288 wxString perspective;
7290 pConfig->Read(
"AUIPerspective", &perspective);
7304 bool bno_load =
false;
7305 wxAuiPaneInfoArray pane_array_val =
g_pauimgr->GetAllPanes();
7307 for (
unsigned int i = 0; i < pane_array_val.GetCount(); i++) {
7308 wxAuiPaneInfo pane = pane_array_val[i];
7309 if (perspective.Find(pane.name) == wxNOT_FOUND) {
7315 if (!bno_load)
g_pauimgr->LoadPerspective(perspective,
false);
7320 gFrame->RequestNewToolbars(
true);
7321 gFrame->RequestNewMasterToolbar(
true);
7328 : wxThread(wxTHREAD_JOINABLE) {
7329 m_filename = filename;
7340 newChart->SetNativeScale(m_scale);
7341 newChart->SetFullExtent(m_ext);
7343 newChart->FindOrCreateSenc(m_filename);
7348 wxString m_filename;
7354static double chart_dist(
int index) {
7360 if (cte.GetBBox().Contains(
gLat,
gLon))
7365 clon = (cte.GetLonMax() + cte.GetLonMin()) / 2;
7366 d = DistGreatCircle(cte.GetLatMax(), clon,
gLat,
gLon);
7367 t = DistGreatCircle(cte.GetLatMin(), clon,
gLat,
gLon);
7370 clat = (cte.GetLatMax() + cte.GetLatMin()) / 2;
7371 t = DistGreatCircle(clat, cte.GetLonMin(),
gLat,
gLon);
7373 t = DistGreatCircle(clat, cte.GetLonMax(),
gLat,
gLon);
7379WX_DEFINE_SORTED_ARRAY_INT(
int, MySortedArrayInt);
7380static int CompareInts(
int n1,
int n2) {
7381 double d1 = chart_dist(n1);
7382 double d2 = chart_dist(n2);
7383 return (
int)(d1 - d2);
7388 wxString chart_path;
7393WX_DEFINE_OBJARRAY(ArrayOfCompressTargets);
7395#include <wx/arrimpl.cpp>
7398void ParseAllENC(wxWindow *parent) {
7399 MySortedArrayInt idx_sorted_by_distance(CompareInts);
7407 for (
int i = 0; i <
ChartData->GetChartTableEntries(); i++) {
7410 if (CHART_TYPE_S57 != cte.GetChartType())
continue;
7412 idx_sorted_by_distance.Add(i);
7416 if (count == 0)
return;
7418 wxLogMessage(wxString::Format(
"ParseAllENC() count = %d", count));
7424 ArrayOfCompressTargets ct_array;
7425 for (
unsigned int j = 0; j < idx_sorted_by_distance.GetCount(); j++) {
7426 int i = idx_sorted_by_distance[j];
7429 double distance = chart_dist(i);
7431 wxString filename(cte.GetpFullPath(), wxConvUTF8);
7434 pct->distance = distance;
7435 pct->chart_path = filename;
7437 ct_array.push_back(pct);
7440 int thread_count = 0;
7443 if (g_nCPUCount > 0)
7444 thread_count = g_nCPUCount;
7446 thread_count = wxThread::GetCPUCount();
7448 if (thread_count < 1) {
7457 for(
int t = 0; t < thread_count; t++)
7461 wxGenericProgressDialog *prog =
nullptr;
7465 long style = wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
7466 wxPD_REMAINING_TIME | wxPD_CAN_SKIP;
7468 prog =
new wxGenericProgressDialog();
7470 prog->SetFont(*qFont);
7472 prog->Create(_(
"OpenCPN ENC Prepare"),
"Longgggggggggggggggggggggggggggg",
7473 count + 1, parent, style);
7482 prog->ShowWindowModal();
7491 for (
unsigned int j = 0; j < ct_array.size(); j++) {
7492 wxString filename = ct_array[j].chart_path;
7493 double distance = ct_array[j].distance;
7494 int index =
ChartData->FinddbIndex(filename);
7495 if (index < 0)
continue;
7498 ext.NLAT = cte.GetLatMax();
7499 ext.SLAT = cte.GetLatMin();
7500 ext.WLON = cte.GetLonMin();
7501 ext.ELON = cte.GetLonMax();
7503 int scale = cte.GetScale();
7506 msg.Printf(_(
"Distance from Ownship: %4.0f NMi"), distance);
7509 if (wxThread::IsMain()) {
7511 wxSize sz = prog->GetSize();
7516 prog->Update(count, msg, &skip);
7528 newChart->SetNativeScale(
scale);
7529 newChart->SetFullExtent(ext);
7530 newChart->DisableBackgroundSENC();
7532 newChart->FindOrCreateSenc(filename,
7536 if (wxThread::IsMain()) {
7537 msg.Printf(_(
"ENC Completed."));
7539 prog->Update(count, msg, &skip);
7549 for (
int t = 0;; t = (t + 1) % thread_count) {
7556 if (!workers[t]->IsAlive()) {
7569#if defined(__WXMSW__) || defined(__WXOSX__)
7576 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().
void Notify() override
Notify all listeners, no data supplied.
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.
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.
void Init(const KeyProvider &kp, const std::function< void(ObservedEvt &ev)> &action)
Initiate an object yet not listening.
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listener on changes in key.
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.
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.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
bool HasMember(unsigned index) const
Return TRUE if the object contains an element at the specified index.
wxString AsString() const
Return the stored value as a wxWidget's string.
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.
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.