54#include <wx/apptrait.h>
55#include <wx/stdpaths.h>
56#include <wx/filename.h>
57#include <wx/tokenzr.h>
58#include <wx/textfile.h>
59#include <wx/jsonval.h>
60#include <wx/jsonreader.h>
64#include "model/ais_decoder.h"
66#include "model/base_platform.h"
68#include "model/config_vars.h"
69#include "model/conn_params.h"
70#include "model/cutil.h"
72#include "model/ocpn_utils.h"
73#include "model/plugin_paths.h"
74#include "model/select.h"
76#include "AboutFrameImpl.h"
82#include "ocpn_frame.h"
83#include "OCPNPlatform.h"
86#include "snd_config.h"
90#include "androidUTIL.h"
94#include "glChartCanvas.h"
98#ifdef OCPN_USE_CRASHREPORT
106#include "crashprint.h"
110#include "model/macutils.h"
113#if (defined(OCPN_GHC_FILESYSTEM) || \
114 (defined(__clang_major__) && (__clang_major__ < 15)))
116#include <ghc/filesystem.hpp>
117namespace fs = ghc::filesystem;
121namespace fs = std::filesystem;
127void appendOSDirSlash(wxString *pString);
130struct sigaction sa_all;
131struct sigaction sa_all_old;
132extern sigjmp_buf env;
136extern bool g_bFirstRun;
137extern bool g_bUpgradeInProcess;
146extern bool g_bshowToolbar;
147extern bool g_bexpert;
148extern bool g_bBasicMenus;
149extern bool g_bUIexpert;
151extern bool g_bshowToolbar;
152extern bool g_bBasicMenus;
154extern bool g_bShowOutlines;
155extern int g_nAWDefault;
157extern bool g_bPermanentMOBIcon;
158extern float g_toolbar_scalefactor;
162extern wxString *pInit_Chart_Dir;
164extern std::vector<size_t> g_config_display_size_mm;
165extern bool g_config_display_size_manual;
167extern bool g_bFullScreenQuilt;
168extern bool g_bQuiltEnable;
169extern bool g_bskew_comp;
171extern bool g_bopengl;
172extern bool g_bresponsive;
173extern bool g_bShowStatusBar;
174extern int g_cm93_zoom_factor;
175extern int g_GUIScaleFactor;
176extern bool g_fog_overzoom;
177extern bool g_oz_vector_scale;
178extern wxString g_toolbarConfig;
179extern bool g_bPreserveScaleOnX;
180extern bool g_running;
181extern bool g_bEnableZoomToCursor;
182extern bool g_bsmoothpanzoom;
183extern bool g_bShowMenuBar;
190extern int g_default_font_size;
191extern wxString g_default_font_facename;
193bool g_bEmailCrashReport;
195extern double g_ChartNotRenderScaleFactor;
196extern bool g_bRollover;
198#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
199extern wxLocale *plocale_def_lang;
201extern wxString g_locale;
202extern wxString g_localeOverride;
203extern wxArrayString g_locale_catalog_array;
206extern int options_lastPage;
208extern about *g_pAboutDlgLegacy;
209extern wxColour g_colourTrackLineColour;
210extern int g_n_ownship_min_mm;
212extern int g_AndroidVersionCode;
213extern bool g_bShowMuiZoomButtons;
214extern int g_FlushNavobjChangesTimeout;
215extern wxString g_CmdSoundString;
216extern int g_maintoolbar_x;
217extern int g_maintoolbar_y;
218extern std::vector<std::string> TideCurrentDataSet;
219extern int g_Android_SDK_Version;
220extern wxString g_androidDownloadDirectory;
221extern wxString g_gpx_path;
232static const char *
const DEFAULT_XDG_DATA_DIRS =
233 "~/.local/share:/usr/local/share:/usr/share";
236static const char PATH_SEP =
';';
238static const char PATH_SEP =
':';
241static bool checkIfFlatpacked() {
243 if (!wxGetEnv(
"FLATPAK_ID", &
id)) {
246 return id ==
"org.opencpn.OpenCPN";
249OCPNPlatform::OCPNPlatform() {
251 m_bdisableWindowsDisplayEnum =
false;
252 m_monitorWidth = m_monitorHeight = 0;
254 for (
size_t i = 0; i < g_monitor_info.size(); i++) {
255 m_displaySizeMMOverride.push_back(0);
257 m_pluginDataPath =
"";
260OCPNPlatform::~OCPNPlatform() {
272int MyNewHandler(
size_t size) {
274 throw std::bad_alloc();
295void catch_signals(
int signo) {
326#ifdef OCPN_USE_CRASHREPORT
328int CALLBACK CrashCallback(CR_CRASH_CALLBACK_INFO *pInfo) {
329 wxLog::GetActiveTarget()->Flush();
330 return CR_CB_DODEFAULT;
335void OCPNPlatform::Initialize_1(
void) {
336#ifdef OCPN_USE_CRASHREPORT
340 CR_INSTALL_INFO info;
341 memset(&info, 0,
sizeof(CR_INSTALL_INFO));
342 info.cb =
sizeof(CR_INSTALL_INFO);
343 info.pszAppName = _T(
"OpenCPN");
345 info.pszAppVersion = wxString(VERSION_FULL).c_str();
347 int type = MiniDumpNormal;
350 type |= MiniDumpWithDataSegs;
361 info.uMiniDumpType = (MINIDUMP_TYPE)type;
364 info.dwFlags = CR_INST_ALL_POSSIBLE_HANDLERS;
367 info.dwFlags &= ~CR_INST_NEW_OPERATOR_ERROR_HANDLER;
370 info.dwFlags |= CR_INST_ALLOW_ATTACH_MORE_FILES;
373 info.dwFlags |= CR_INST_SHOW_ADDITIONAL_INFO_FIELDS;
377 if (g_bEmailCrashReport) {
378 info.pszUrl = _T(
"https://bigdumboat.com/crashrpt/ocpn_crashrpt.php");
379 info.uPriorities[CR_HTTP] = 3;
381 info.dwFlags |= CR_INST_DONT_SEND_REPORT;
382 info.uPriorities[CR_HTTP] = CR_NEGATIVE_PRIORITY;
385 info.uPriorities[CR_SMTP] =
386 CR_NEGATIVE_PRIORITY;
387 info.uPriorities[CR_SMAPI] =
388 CR_NEGATIVE_PRIORITY;
390 wxStandardPaths &crash_std_path = g_Platform->GetStdPaths();
392 wxString crash_rpt_save_locn = crash_std_path.GetConfigDir();
394 wxFileName exec_path_crash(crash_std_path.GetExecutablePath());
395 crash_rpt_save_locn =
396 exec_path_crash.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
399 wxString locn = crash_rpt_save_locn + _T(
"\\CrashReports");
401 if (!wxDirExists(locn)) wxMkdir(locn);
403 if (wxDirExists(locn)) {
404 wxCharBuffer buf = locn.ToUTF8();
406 if (buf && (locn.Length() <
sizeof(wlocn))) {
407 MultiByteToWideChar(0, 0, buf.data(), -1, wlocn,
sizeof(wlocn) - 1);
408 info.pszErrorReportSaveDir = (LPCWSTR)wlocn;
413 wxFileName exec_path_crash(crash_std_path.GetExecutablePath());
414 wxString policy_file =
415 exec_path_crash.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
416 policy_file += _T(
"PrivacyPolicy.txt");
417 policy_file.Prepend(_T(
"file:"));
419 info.pszPrivacyPolicyURL = policy_file.c_str();
422 int nResult = crInstall(&info);
425 crGetLastErrorMsg(buff, 256);
432 crSetCrashCallback(CrashCallback, NULL);
435 crAddScreenshot2(CR_AS_PROCESS_WINDOWS | CR_AS_USE_JPEG_FORMAT, 95);
438 wxString home_data_crash = crash_std_path.GetConfigDir();
440 wxFileName f(crash_std_path.GetExecutablePath());
441 home_data_crash = f.GetPath();
443 appendOSDirSlash(&home_data_crash);
445 wxString config_crash = _T(
"opencpn.ini");
446 config_crash.Prepend(home_data_crash);
447 crAddFile2(config_crash.c_str(), NULL, NULL,
448 CR_AF_MISSING_FILE_OK | CR_AF_ALLOW_DELETE);
450 wxString log_crash = _T(
"opencpn.log");
451 log_crash.Prepend(home_data_crash);
452 crAddFile2(log_crash.c_str(), NULL, NULL,
453 CR_AF_MISSING_FILE_OK | CR_AF_ALLOW_DELETE);
459#if wxUSE_ON_FATAL_EXCEPTION
461 wxHandleFatalExceptions(
true);
467 _set_new_handler(MyNewHandler);
477 HANDLE hProc = GetCurrentProcess();
481 DuplicateHandle( hProc, hProc, hProc, &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS );
484 GetProcessAffinityMask( hDup, &procMask, &sysMask );
488 if( ( procMask & 1 ) == 1 ) newMask = 1;
490 if( ( procMask & 2 ) == 2 ) newMask = 2;
492 if( ( procMask & 4 ) == 4 ) newMask = 4;
494 if( ( procMask & 8 ) == 8 ) newMask = 8;
497 BOOL res = SetProcessAffinityMask( hDup, (DWORD_PTR) newMask );
511 wxPlatformInfo Platform;
512 if (Platform.GetOperatingSystemId() == wxOS_WINDOWS_9X)
513 SetUnhandledExceptionFilter(&MyUnhandledExceptionFilter);
524 sa_all.sa_handler = catch_signals;
525 sigemptyset(&sa_all.sa_mask);
531 sigaction(SIGUSR1, NULL,
535 sigaction(SIGUSR1, &sa_all, NULL);
536 sigaction(SIGUSR1, NULL,
539 sigaction(SIGTERM, &sa_all, NULL);
540 sigaction(SIGTERM, NULL, &sa_all_old);
542 sigaction(SIGHUP, &sa_all, NULL);
543 sigaction(SIGHUP, NULL, &sa_all_old);
548 qDebug() <<
"Initialize_1()";
558void OCPNPlatform::Initialize_2(
void) {
560 wxLogMessage(androidGetDeviceInfo());
564 wxChar sep = wxFileName::GetPathSeparator();
567 if (ChartDir.Last() != sep) ChartDir.Append(sep);
568 ChartDir.Append(
"Charts");
569 if (!::wxDirExists(ChartDir)) {
574 if (GRIBDir.Last() != sep) GRIBDir.Append(sep);
575 GRIBDir.Append(
"GRIBS");
576 if (!::wxDirExists(GRIBDir)) {
581 if (g_Android_SDK_Version >= 30) {
582 if (!g_gpx_path.StartsWith(androidGetDownloadDirectory())) {
583 g_gpx_path = androidGetDownloadDirectory();
590 g_toolbar_scalefactor = GetToolbarScaleFactor(g_GUIScaleFactor);
592 if (!configdir.DirExists()) {
593 if (!configdir.Mkdir()) {
594 auto msg = std::string(
"Cannot create config directory: ");
595 wxLogWarning(msg + configdir.GetFullPath());
602void OCPNPlatform::Initialize_3(
void) {
603 bool bcapable = IsGLCapable();
609 bool bAndroid =
false;
618 g_bdisable_opengl =
false;
619 pConfig->UpdateSettings();
626 if ((g_bFirstRun || g_bUpgradeInProcess || bAndroid) && bcapable) {
630 g_GLOptions.m_bUseAcceleratedPanning =
true;
631 g_GLOptions.m_bTextureCompression =
true;
632 g_GLOptions.m_bTextureCompressionCaching =
true;
634 g_GLOptions.m_iTextureDimension = 512;
635 g_GLOptions.m_iTextureMemorySize = 64;
637 g_GLOptions.m_GLPolygonSmoothing =
true;
638 g_GLOptions.m_GLLineSmoothing =
true;
642 gFrame->SetGPSCompassScale();
650 if (g_bFirstRun || g_bUpgradeInProcess) {
652 g_bRollover = g_btouch ? false :
true;
655 g_FlushNavobjChangesTimeout = 300;
659void OCPNPlatform::Initialize_4(
void) {
661 if (pSelect) pSelect->SetSelectPixelRadius(wxMax(25, 6.0 * getAndroidDPmm()));
663 pSelectTC->SetSelectPixelRadius(wxMax(25, 6.0 * getAndroidDPmm()));
665 pSelectAIS->SetSelectPixelRadius(wxMax(25, 6.0 * getAndroidDPmm()));
672 options_lastPage = 1;
676void OCPNPlatform::OnExit_1(
void) {}
678void OCPNPlatform::OnExit_2(
void) {
679#ifdef OCPN_USE_CRASHREPORT
689bool HasGLExt(
wxJSONValue &glinfo,
const std::string ext) {
690 if (!glinfo.
HasMember(
"GL_EXTENSIONS")) {
693 for (
int i = 0; i < glinfo[
"GL_EXTENSIONS"].
Size(); i++) {
694 if (glinfo[
"GL_EXTENSIONS"][i].AsString() == ext) {
701bool OCPNPlatform::BuildGLCaps(
void *pbuf) {
703 fs::path ep(GetExePath().ToStdString());
705 std::string gl_util_exe =
"opencpn-glutil";
707 std::string gl_util_exe =
"opencpn-glutil.exe";
709 fs::path gl_util_path = ep.parent_path().append(gl_util_exe);
711 if (!fs::exists(gl_util_path)) {
714 wxLogMessage(
"OpenGL test utility not found at %s.", gl_util_path.c_str());
719 .append(
"gl_caps.json")
722 wxString cmd = wxString::Format(
"\"%s\" opengl-info \"%s\"",
723 gl_util_path.c_str(), gl_json.c_str());
725 wxLogMessage(
"Starting OpenGL test utility: %s", cmd);
727 wxArrayString output;
728 if (
long res = wxExecute(cmd, output); res != 0) {
729 wxLogMessage(
"OpenGL test utility failed with exit code %d", res);
730 for (
const auto &l : output) {
736 wxFileInputStream fis(gl_json);
739 reader.
Parse(fis, &root);
741 wxLogMessage(
"Failed to parse JSON output from OpenGL test utility.");
742 for (
const auto &l : reader.GetErrors()) {
751 pcaps->Renderer = root[
"GL_RENDERER"].
AsString();
753 wxLogMessage(
"GL_RENDERER not found.");
757 pcaps->Version = root[
"GL_VERSION"].
AsString();
759 wxLogMessage(
"GL_VERSION not found.");
762 if (root.
HasMember(
"GL_SHADING_LANGUAGE_VERSION")) {
763 pcaps->GLSL_Version = root[
"GL_SHADING_LANGUAGE_VERSION"].
AsString();
765 wxLogMessage(
"GL_SHADING_LANGUAGE_VERSION not found.");
769 if (!root[
"GL_USABLE"].AsBool()) {
770 wxLogMessage(
"OpenGL test utility reports that OpenGL is not usable.");
774 wxLogMessage(
"GL_USABLE not found.");
777 pcaps->dGLSL_Version = 0;
778 pcaps->dGLSL_Version = ::atof(pcaps->GLSL_Version.c_str());
779 if (pcaps->dGLSL_Version < 1.2) {
781 msg.Printf(_T(
"GLCaps Probe: OpenGL-> GLSL Version reported: "));
782 msg += wxString(pcaps->GLSL_Version.c_str());
783 msg +=
"\n OpenGL disabled due to insufficient OpenGL capabilities";
785 pcaps->bCanDoGLSL =
false;
788 pcaps->bCanDoGLSL =
true;
789 if (HasGLExt(root,
"GL_ARB_texture_non_power_of_two")) {
790 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
791 }
else if (HasGLExt(root,
"GL_OES_texture_npot")) {
792 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
793 }
else if (HasGLExt(root,
"GL_ARB_texture_rectangle")) {
794 pcaps->TextureRectangleFormat = GL_TEXTURE_RECTANGLE_ARB;
797 pcaps->bOldIntel =
false;
799 pcaps->bCanDoFBO = HasGLExt(root,
"GL_EXT_framebuffer_object");
800 if (!pcaps->TextureRectangleFormat) {
801 pcaps->bCanDoFBO =
false;
804 pcaps->bCanDoVBO = HasGLExt(
805 root,
"GL_ARB_vertex_buffer_object");
817 wxGLContext *pctx =
new wxGLContext(tcanvas);
818 tcanvas->SetCurrent(*pctx);
822 char *str = (
char *)glGetString(GL_RENDERER);
824 wxLogMessage(
"GL_RENDERER not found.");
829 pcaps->Renderer = std::string(str);
831 char *stv = (
char *)glGetString(GL_VERSION);
833 wxLogMessage(
"GL_VERSION not found");
838 pcaps->Version = std::string(stv);
840 char *stsv = (
char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
842 wxLogMessage(
"GL_SHADING_LANGUAGE_VERSION not found");
847 pcaps->GLSL_Version = std::string(stsv);
849 pcaps->dGLSL_Version = 0;
850 pcaps->dGLSL_Version = ::atof(pcaps->GLSL_Version.c_str());
852 if (pcaps->dGLSL_Version < 1.2) {
854 msg.Printf(_T(
"GLCaps Probe: OpenGL-> GLSL Version reported: "));
855 msg += wxString(pcaps->GLSL_Version.c_str());
856 msg +=
"\n OpenGL disabled due to insufficient OpenGL capabilities";
858 pcaps->bCanDoGLSL =
false;
864 pcaps->bCanDoGLSL =
true;
866 if (QueryExtension(
"GL_ARB_texture_non_power_of_two"))
867 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
868 else if (QueryExtension(
"GL_OES_texture_npot"))
869 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
870 else if (QueryExtension(
"GL_ARB_texture_rectangle"))
871 pcaps->TextureRectangleFormat = GL_TEXTURE_RECTANGLE_ARB;
873 pcaps->bOldIntel =
false;
876 pcaps->bCanDoVBO =
true;
878#if defined(__WXMSW__) || defined(__WXOSX__)
879 if (pcaps->bOldIntel) pcaps->bCanDoVBO =
false;
883 pcaps->bCanDoVBO =
false;
887 pcaps->bCanDoFBO =
true;
891 if (!pcaps->TextureRectangleFormat) pcaps->bCanDoFBO =
false;
894 if (!QueryExtension(
"GL_EXT_framebuffer_object")) pcaps->bCanDoFBO =
false;
904bool OCPNPlatform::IsGLCapable() {
913 if (g_bdisable_opengl)
return false;
915 wxLogMessage(
"Starting OpenGL test...");
916 wxLog::FlushActive();
920 bool bcaps = BuildGLCaps(GL_Caps);
922 wxLogMessage(
"OpenGL test complete.");
924 wxLogMessage(
"BuildGLCaps fails.");
925 wxLog::FlushActive();
933 if (!GL_Caps->bCanDoGLSL) {
939 if (!GL_Caps->bCanDoFBO) {
944 wxLogMessage(
"OpenGL determined CAPABLE.");
945 wxLog::FlushActive();
947 g_bdisable_opengl =
false;
951 pConfig->UpdateSettings();
960void OCPNPlatform::SetLocaleSearchPrefixes(
void) {
963#if defined(__WINDOWS__)
966 wxString locale_location = GetSharedDataDir();
967 locale_location += _T(
"share\\locale");
968 wxLocale::AddCatalogLookupPathPrefix(locale_location);
969 wxString imsg = _T(
"Adding catalog lookup path: ");
970 imsg += locale_location;
975 usrShare.RemoveLastDir();
976 locale_location = usrShare.GetFullPath() + (
"share\\locale");
977 wxLocale::AddCatalogLookupPathPrefix(locale_location);
978 imsg = _T(
"Adding catalog lookup path: ");
979 imsg += locale_location;
982#elif defined(__ANDROID__)
984 wxString locale_location = GetSharedDataDir() + _T(
"locale");
985 wxLocale::AddCatalogLookupPathPrefix(locale_location);
987#elif defined(__UNIX__) && !defined(__WINE__)
992 wxString locale_location;
993 if (!wxGetEnv(_T(
"OPENCPN_PREFIX"), &locale_location)) {
994 locale_location = _T(
"/usr/local");
998 locale_location = g_Platform->GetHomeDir();
1001 wxFileName location;
1002 location.AssignDir(locale_location);
1003 location.AppendDir(_T(
"share"));
1004 location.SetName(_T(
"locale"));
1005 locale_location = location.GetFullPath();
1006 wxLocale::AddCatalogLookupPathPrefix(locale_location);
1010 wxString managed_locale_location(dir +
"/locale");
1011 wxLocale::AddCatalogLookupPathPrefix(managed_locale_location);
1015 std::string macDir =
1017 "/Library/Application Support/OpenCPN/Contents/Resources";
1018 wxString Mac_managed_locale_location(macDir);
1019 wxLocale::AddCatalogLookupPathPrefix(Mac_managed_locale_location);
1025wxString OCPNPlatform::GetDefaultSystemLocale() {
1026 wxLogMessage(_T(
"Getting DefaultSystemLocale..."));
1028 wxString retval = _T(
"en_US");
1032 const wxLanguageInfo *languageInfo =
1033 wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
1034 if (languageInfo) retval = languageInfo->CanonicalName;
1036#if defined(__WXMSW__)
1037 LANGID lang_id = GetUserDefaultUILanguage();
1040 const wxLanguageInfo *languageInfoW = 0;
1041 if (0 != GetLocaleInfo(MAKELCID(lang_id, SORT_DEFAULT), LOCALE_SENGLANGUAGE,
1043 wxString lstring = wxString(lngcp);
1045 languageInfoW = wxLocale::FindLanguageInfo(lngcp);
1047 wxLogMessage(_T(
"Found LanguageInfo for: ") + lstring);
1049 wxLogMessage(_T(
"Could not find LanguageInfo for: ") + lstring);
1051 wxLogMessage(_T(
"Could not get LocaleInfo, using wxLANGUAGE_DEFAULT"));
1052 languageInfoW = wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
1055 if (languageInfoW) retval = languageInfoW->CanonicalName;
1058#if defined(__ANDROID__)
1059 retval = androidGetAndroidSystemLocale();
1067#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1068wxString OCPNPlatform::GetAdjustedAppLocale() {
1069 wxString adjLocale = g_locale;
1074#if defined(__WXMSW__)
1075 if (g_bFirstRun || wxIsEmpty(adjLocale)) {
1076 wxRegKey RegKey(wxString(_T(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenCPN")));
1077 if (RegKey.Exists()) {
1079 _T(
"Retrieving initial language selection from Windows Registry"));
1080 RegKey.QueryValue(wxString(_T(
"InstallerLanguage")), adjLocale);
1083 if (wxIsEmpty(adjLocale)) {
1084 if (g_localeOverride.Length())
1085 adjLocale = g_localeOverride;
1087 adjLocale = GetDefaultSystemLocale();
1090#if defined(__ANDROID__)
1091 if (g_localeOverride.Length())
1092 adjLocale = g_localeOverride;
1094 adjLocale = GetDefaultSystemLocale();
1100wxString OCPNPlatform::ChangeLocale(wxString &newLocaleID,
1101 wxLocale *presentLocale,
1102 wxLocale **newLocale) {
1103 wxString return_val;
1105 wxString imsg = _T(
"ChangeLocale: Language load for: ");
1106 imsg += newLocaleID;
1110 delete (wxLocale *)presentLocale;
1112 wxLocale *locale =
new wxLocale;
1113 if (isFlatpacked()) {
1114 std::string path(getenv(
"HOME"));
1115 path +=
"/.var/app/org.opencpn.OpenCPN/data/locale";
1116 locale->AddCatalogLookupPathPrefix(path);
1117 wxLogMessage(
"Using flatpak locales at %s", path.c_str());
1119 wxString loc_lang_canonical;
1121 const wxLanguageInfo *pli = wxLocale::FindLanguageInfo(newLocaleID);
1122 bool b_initok =
false;
1125 locale->Init(pli->Language, 1);
1129 if (!locale->IsOk()) {
1130 wxString imsg = _T(
"ChangeLocale: could not initialize: ");
1131 imsg += newLocaleID;
1135 locale =
new wxLocale;
1136 locale->Init(pli->Language, 0);
1138 loc_lang_canonical = pli->CanonicalName;
1140 b_initok = locale->IsOk();
1147 wxString imsg = _T(
"ChangeLocale: Fall back to en_US");
1151 locale =
new wxLocale;
1152 locale->Init(wxLANGUAGE_ENGLISH_US, 0);
1153 loc_lang_canonical =
1154 wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US)->CanonicalName;
1158 wxString imsg = _T(
"ChangeLocale: Locale Init OK for: ");
1159 imsg += loc_lang_canonical;
1171 for (
unsigned int i = 0; i < g_locale_catalog_array.GetCount(); i++) {
1172 if (!locale->AddCatalog(g_locale_catalog_array[i])) {
1173 wxString emsg = _T(
"ERROR Loading translation catalog for: ");
1174 emsg += g_locale_catalog_array[i];
1177 wxString imsg = _T(
"Loaded translation catalog for: ");
1178 imsg += g_locale_catalog_array[i];
1184 wxLogMessage(_T(
"Loading catalog for opencpn core."));
1185 locale->AddCatalog(_T(
"opencpn"));
1187 return_val = locale->GetCanonicalName();
1190 if (return_val != GetDefaultSystemLocale())
1191 g_localeOverride = return_val;
1193 g_localeOverride = _T(
"");
1196 *newLocale = locale;
1199 setlocale(LC_NUMERIC,
"C");
1210void OCPNPlatform::SetDefaultOptions(
void) {
1212 g_bShowOutlines =
true;
1218 g_MarkLost_Mins = 8;
1219 g_bRemoveLost =
true;
1220 g_RemoveLost_Mins = 10;
1223 g_bSyncCogPredictors =
false;
1224 g_bHideMoored =
false;
1225 g_ShowMoored_Kts = 0.2;
1226 g_SOGminCOG_kts = 0.2;
1227 g_bTrackDaily =
false;
1229 g_bFullScreenQuilt =
true;
1230 g_bQuiltEnable =
true;
1231 g_bskew_comp =
false;
1232 g_bShowAreaNotices =
false;
1233 g_bDrawAISSize =
false;
1234 g_bDrawAISRealtime =
false;
1235 g_AIS_RealtPred_Kts = 0.7;
1236 g_bShowAISName =
false;
1237 g_nTrackPrecision = 2;
1238 g_bPreserveScaleOnX =
true;
1241 gps_watchdog_timeout_ticks = GPS_TIMEOUT_SECONDS;
1242 g_n_ownship_min_mm = 8;
1243 g_bShowMuiZoomButtons =
true;
1244 g_bresponsive =
false;
1248 pConfig->SetPath(_T (
"/Settings/GlobalState" ));
1249 pConfig->Write(_T (
"bShowS57Text" ),
true);
1250 pConfig->Write(_T (
"bShowS57ImportantTextOnly" ),
false);
1251 pConfig->Write(_T (
"nDisplayCategory" ), (
int)(_DisCat)STANDARD);
1252 pConfig->Write(_T (
"nSymbolStyle" ), (
int)(_LUPname)PAPER_CHART);
1253 pConfig->Write(_T (
"nBoundaryStyle" ), (
int)(_LUPname)PLAIN_BOUNDARIES);
1255 pConfig->Write(_T (
"bShowSoundg" ),
true);
1256 pConfig->Write(_T (
"bShowMeta" ),
false);
1257 pConfig->Write(_T (
"bUseSCAMIN" ),
true);
1258 pConfig->Write(_T (
"bShowAtonText" ),
false);
1259 pConfig->Write(_T (
"bShowLightDescription" ),
false);
1260 pConfig->Write(_T (
"bExtendLightSectors" ),
true);
1261 pConfig->Write(_T (
"bDeClutterText" ),
true);
1262 pConfig->Write(_T (
"bShowNationalText" ),
true);
1264 pConfig->Write(_T (
"S52_MAR_SAFETY_CONTOUR" ), 3);
1265 pConfig->Write(_T (
"S52_MAR_SHALLOW_CONTOUR" ), 2);
1266 pConfig->Write(_T (
"S52_MAR_DEEP_CONTOUR" ), 6);
1267 pConfig->Write(_T (
"S52_MAR_TWO_SHADES" ), 0);
1268 pConfig->Write(_T (
"S52_DEPTH_UNIT_SHOW" ), 1);
1270 pConfig->Write(_T (
"ZoomDetailFactorVector" ), 3);
1272 pConfig->Write(_T (
"nColorScheme" ), 1);
1276 g_bEnableZoomToCursor =
true;
1277 g_bsmoothpanzoom =
true;
1278 g_bShowMenuBar =
true;
1285 pConfig->SetPath(_T (
"/PlugIns/chartdldr_pi.dll" ));
1286 pConfig->Write(_T (
"bEnabled" ),
true);
1288 pConfig->SetPath(_T (
"/PlugIns/wmm_pi.dll" ));
1289 pConfig->Write(_T (
"bEnabled" ),
true);
1291 pConfig->SetPath(_T (
"/Settings/WMM" ));
1292 pConfig->Write(_T (
"ShowIcon" ),
true);
1293 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1300 pConfig->SetPath(_T (
"/PlugIns/libchartdldr_pi.dylib" ));
1301 pConfig->Write(_T (
"bEnabled" ),
true);
1303 pConfig->SetPath(_T (
"/PlugIns/libwmm_pi.dylib" ));
1304 pConfig->Write(_T (
"bEnabled" ),
true);
1306 pConfig->SetPath(_T (
"/Settings/WMM" ));
1307 pConfig->Write(_T (
"ShowIcon" ),
true);
1308 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1315 pConfig->SetPath(_T (
"/PlugIns/libchartdldr_pi.so" ));
1316 pConfig->Write(_T (
"bEnabled" ),
true);
1318 pConfig->SetPath(_T (
"/PlugIns/libwmm_pi.so" ));
1319 pConfig->Write(_T (
"bEnabled" ),
true);
1321 pConfig->SetPath(_T (
"/Settings/WMM" ));
1322 pConfig->Write(_T (
"ShowIcon" ),
true);
1323 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1331 g_GLOptions.m_bTextureCompression = 1;
1332 g_GLOptions.m_bTextureCompressionCaching = 1;
1335 qDebug() <<
"SetDefaultOptions";
1338 g_bresponsive =
true;
1339 g_default_font_size = 18;
1342 g_bShowStatusBar =
true;
1343 g_cm93_zoom_factor = 0;
1344 g_oz_vector_scale =
false;
1345 g_fog_overzoom =
false;
1348 g_bShowMuiZoomButtons =
true;
1350 g_GUIScaleFactor = 0;
1351 g_ChartNotRenderScaleFactor = 2.0;
1355 g_toolbarConfig = _T(
"X.....XX.......XX.XXXXXXXXXXX");
1356 g_bPermanentMOBIcon =
false;
1358 wxString sGPS = _T(
"2;3;;0;0;;0;1;0;0;;0;;1;0;0;0;0");
1361 new_params->bEnabled =
true;
1362 TheConnectionParams().push_back(new_params);
1364 g_default_font_facename = _T(
"Roboto");
1369 pConfig->SetPath(_T (
"/PlugIns/libchartdldr_pi.so" ));
1370 pConfig->Write(_T (
"bEnabled" ),
true);
1372 pConfig->SetPath(_T (
"/PlugIns/libwmm_pi.so" ));
1373 pConfig->Write(_T (
"bEnabled" ),
true);
1375 pConfig->SetPath(_T (
"/Settings/WMM" ));
1376 pConfig->Write(_T (
"ShowIcon" ),
true);
1377 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1379 pConfig->SetPath(_T (
"/PlugIns/libgrib_pi.so" ));
1380 pConfig->Write(_T (
"bEnabled" ),
true);
1382 pConfig->SetPath(_T (
"/PlugIns/libdashboard_pi.so" ));
1383 pConfig->Write(_T (
"bEnabled" ),
true);
1385 pConfig->SetPath(_T (
"/PlugIns/GRIB" ));
1386 pConfig->Write(_T (
"GRIBCtrlBarPosX" ), 100);
1387 pConfig->Write(_T (
"GRIBCtrlBarPosY" ), 0);
1389 pConfig->SetPath(_T (
"/Settings/GRIB" ));
1390 pConfig->Write(_T (
"CursorDataShown" ), 0);
1394 pConfig->SetPath(_T (
"/PlugIns/liboesenc_pi.so" ));
1395 pConfig->Write(_T (
"bEnabled" ),
true);
1397 pConfig->SetPath(_T (
"/Settings/QTFonts" ));
1400 wxString str = _T(
"en_US-b25a3899");
1401 wxString pval = _T(
"StatusBar:Roboto,26,-1,5,75,0,0,0,0,0:rgb(0, 0, 0)");
1402 pConfig->Write(str, pval);
1406 str = _T(
"en_US-9c3b3a0d");
1407 pval = _T(
"DialogStatusBar:Roboto,18,-1,5,50,0,0,0,0,0:rgb(0, 0, 0)");
1408 pConfig->Write(str, pval);
1412 pConfig->SetPath(_T (
"/Settings/Others" ));
1413 pConfig->Write(_T(
"TrackLineColour"), _T(
"#C545C3"));
1414 g_colourTrackLineColour.Set(197, 69, 195);
1416 qDebug() <<
"SetDefaultOptions.Config";
1427void OCPNPlatform::SetUpgradeOptions(wxString vNew, wxString vOld) {
1430 qDebug() <<
"Upgrade check"
1431 <<
"from: " << vOld.mb_str() <<
" to: " << vNew.mb_str();
1433 if (androidGetVersionCode() > g_AndroidVersionCode) {
1434 qDebug() <<
"Upgrade detected"
1435 <<
"from VC: " << g_AndroidVersionCode
1436 <<
" to VC: " << androidGetVersionCode();
1440 pConfig->SetPath(_T (
"/Settings/GlobalState" ));
1441 pConfig->Write(_T (
"bShowS57Text" ),
true);
1444 g_ChartNotRenderScaleFactor = 2.0;
1445 g_n_ownship_min_mm = 8;
1446 g_toolbarConfig = _T(
"X.....XX.......XX.XXXXXXXXXXX");
1449 pConfig->DeleteGroup(_T (
"/Settings/QTFonts" ));
1450 g_default_font_size = 20;
1451 g_default_font_facename = _T(
"Roboto");
1453 FontMgr::Get().Shutdown();
1456 g_bShowMuiZoomButtons =
true;
1460 pInit_Chart_Dir->Clear();
1462 pConfig->SetPath(_T (
"/Settings/WMM" ));
1463 pConfig->Write(_T (
"ShowIcon" ),
true);
1464 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1468 g_colourTrackLineColour.Set(197, 69, 195);
1478 if (!vOld.IsSameAs(vNew)) {
1484 wxChar sep = wxFileName::GetPathSeparator();
1485 if (UserIconPath.Last() != sep) UserIconPath.Append(sep);
1486 UserIconPath.Append(_T(
"UserIcons"));
1488 if (!::wxDirExists(UserIconPath)) {
1489 ::wxMkdir(UserIconPath);
1494 if (LayersPath.Last() != sep) LayersPath.Append(sep);
1495 LayersPath.Append(_T(
"layers"));
1497 if (!::wxDirExists(LayersPath)) {
1498 ::wxMkdir(LayersPath);
1504 g_CmdSoundString = wxString(OCPN_SOUND_CMD);
1505 pConfig->SetPath(_T (
"/Settings" ));
1506 pConfig->Write(_T(
"CmdSoundString" ), g_CmdSoundString);
1510 g_bAIS_GCPA_Alert_Audio =
true;
1511 g_bAIS_SART_Alert_Audio =
true;
1512 g_bAIS_DSC_Alert_Audio =
true;
1515 g_maintoolbar_x = -1;
1519 std::vector<std::string> TCDS_temp;
1520 for (
unsigned int i = 0; i < TideCurrentDataSet.size(); i++)
1521 TCDS_temp.push_back(TideCurrentDataSet[i]);
1523 TideCurrentDataSet.clear();
1524 for (
unsigned int i = 0; i < TCDS_temp.size(); i++) {
1525 wxString tide = TCDS_temp[i];
1526 wxFileName ft(tide);
1527 if (ft.FileExists()) TideCurrentDataSet.push_back(TCDS_temp[i]);
1532int OCPNPlatform::platformApplyPrivateSettingsString(wxString settings,
1533 ArrayOfCDI *pDirArray) {
1536 ret_val = androidApplySettingsString(settings, pDirArray);
1542void OCPNPlatform::applyExpertMode(
bool mode) {
1545 g_bBasicMenus = !mode;
1549wxString OCPNPlatform::GetSupplementalLicenseString() {
1552 lic = androidGetSupplementalLicense();
1561static wxString ExpandPaths(wxString paths,
OCPNPlatform *platform);
1563int OCPNPlatform::DoFileSelectorDialog(wxWindow *parent, wxString *file_spec,
1564 wxString Title, wxString initDir,
1565 wxString suggestedName,
1566 wxString wildcard) {
1568 int result = wxID_CANCEL;
1572 wxString idir = initDir;
1573 if (initDir.StartsWith(
1575 idir = GetWritableDocumentsDir();
1577 result = androidFileChooser(&file, idir, Title, suggestedName, wildcard);
1578 if (file_spec) *file_spec = file;
1580 long flag = wxFD_DEFAULT_STYLE;
1581 if (suggestedName.Length()) {
1585 wxString mask = wildcard;
1586 if (wxNOT_FOUND != mask.Find(_T(
"gpx")))
1587 mask.Prepend(_T(
"GPX files (*.gpx)|"));
1589 wxFileDialog *psaveDialog =
1590 new wxFileDialog(parent, Title, initDir, suggestedName, mask, flag);
1598 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
1601 result = psaveDialog->ShowModal();
1604 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
1607 if (file_spec) *file_spec = psaveDialog->GetPath();
1615int OCPNPlatform::DoDirSelectorDialog(wxWindow *parent, wxString *file_spec,
1616 wxString Title, wxString initDir,
1619 int result = wxID_CANCEL;
1623 wxString idir = initDir;
1624 if (initDir.StartsWith(
1626 idir = GetWritableDocumentsDir();
1628 result = androidFileChooser(&dir, idir, Title, _T(
""), _T(
""),
true,
1630 if (file_spec) *file_spec = dir;
1632 wxDirDialog *dirSelector =
new wxDirDialog(
1633 parent, Title, initDir, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1636 dirSelector->SetFont(*qFont);
1643 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
1646 result = dirSelector->ShowModal();
1649 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
1652 if (result == wxID_CANCEL) {
1655 *file_spec = dirSelector->GetPath();
1665MyConfig *OCPNPlatform::GetConfigObject() {
1668 result =
new MyConfig(GetConfigFileName());
1677bool OCPNPlatform::hasInternalGPS(wxString profile) {
1679 bool t = androidDeviceHasGPS();
1693void OCPNPlatform::ShowBusySpinner(
void) {
1694 AbstractPlatform::ShowBusySpinner();
1697void OCPNPlatform::HideBusySpinner(
void) {
1698 AbstractPlatform::HideBusySpinner();
1701double OCPNPlatform::GetDisplayDensityFactor() {
1703 return getAndroidDisplayDensity();
1709long OCPNPlatform::GetDefaultToolbarOrientation() {
1711 return wxTB_VERTICAL;
1713 return wxTB_VERTICAL;
1717int OCPNPlatform::GetStatusBarFieldCount() {
1723 wxFont *templateFont = FontMgr::Get().
GetFont(_(
"StatusBar"), 0);
1724 dc.SetFont(*templateFont);
1727 dc.GetTextExtent(_T(
"WWWWWW"), &width, NULL, NULL, NULL, templateFont);
1728 double font_size_pix = (double)width / 6.0;
1732 double nChars = dispSize.x / font_size_pix;
1742 return STAT_FIELD_COUNT;
1746double OCPNPlatform::getFontPointsperPixel(
void) {
1747 double pt_per_pixel = 1.0;
1757 if (m_pt_per_pixel == 0) {
1762 12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, FALSE,
1763 wxString(_T (
"" )), wxFONTENCODING_SYSTEM);
1767 dc.GetTextExtent(_T(
"H"), &width, &height, NULL, NULL, f);
1769 if (height > 0) m_pt_per_pixel = 12.0 / (double)height;
1771 if (m_pt_per_pixel > 0) pt_per_pixel = m_pt_per_pixel;
1774 return pt_per_pixel;
1779 return getAndroidDisplayDimensions();
1781 return wxSize(g_monitor_info[g_current_monitor].width,
1782 g_monitor_info[g_current_monitor].height);
1787 if (g_current_monitor < m_displaySizeMMOverride.size()) {
1788 if (m_displaySizeMMOverride[g_current_monitor] > 0) {
1789 return m_displaySizeMMOverride[g_current_monitor];
1793 double ret = g_monitor_info[g_current_monitor].width_mm;
1796 ret = GetAndroidDisplaySize();
1802double OCPNPlatform::GetDisplayAreaCM2() {
1807 ratio = (double)sz.x / (
double)sz.y;
1809 ratio = (double)sz.y / (
double)sz.x;
1811 double area = size1 * (size1 * ratio) / 100.;
1817 if (monitor < m_displaySizeMMOverride.size()) {
1818 m_displaySizeMMOverride[monitor] = sizeMM;
1822double OCPNPlatform::GetDisplayDPmm() {
1824 return getAndroidDPmm();
1831unsigned int OCPNPlatform::GetSelectRadiusPix() {
1832 return GetDisplayDPmm() *
1833 (g_btouch ? g_selection_radius_touch_mm : g_selection_radius_mm);
1836bool OCPNPlatform::GetFullscreen() {
1839 bret = androidGetFullscreen();
1847bool OCPNPlatform::SetFullscreen(
bool bFull) {
1850 bret = androidSetFullscreen(bFull);
1857void OCPNPlatform::PositionAISAlert(wxWindow *alert_window) {
1860 alert_window->SetSize(g_ais_alert_dialog_x, g_ais_alert_dialog_y,
1861 g_ais_alert_dialog_sx, g_ais_alert_dialog_sy);
1865 alert_window->Centre();
1871wxDirDialog *OCPNPlatform::AdjustDirDialogFont(wxWindow *container,
1873 wxDirDialog *ret_dlg = dlg;
1877 dlg->SetSize(container->GetSize());
1880 wxSize sds = dlg->GetSize();
1881 wxSize ss = container->GetSize();
1886 wxString msg = dlg->GetMessage();
1887 wxString default_dir = dlg->GetPath();
1891 ret_dlg =
new wxDirDialog(NULL, msg, default_dir,
1892 wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1895 wxFont *smallFont =
new wxFont(*dialogFont);
1896 smallFont->SetPointSize((smallFont->GetPointSize() / 2) +
1898 ret_dlg->SetFont(*smallFont);
1900 ret_dlg->SetSize(container->GetSize());
1908wxFileDialog *OCPNPlatform::AdjustFileDialogFont(wxWindow *container,
1909 wxFileDialog *dlg) {
1910 wxFileDialog *ret_dlg = dlg;
1914 dlg->SetSize(container->GetSize());
1917 wxSize sds = dlg->GetSize();
1918 wxSize ss = container->GetSize();
1923 wxString msg = dlg->GetMessage();
1924 wxString default_dir = dlg->GetDirectory();
1925 wxString default_file = dlg->GetFilename();
1926 wxString wildcard = dlg->GetWildcard();
1930 ret_dlg =
new wxFileDialog(NULL, msg, default_dir, default_file, wildcard,
1934 wxFont *smallFont =
new wxFont(*dialogFont);
1935 smallFont->SetPointSize((smallFont->GetPointSize() / 2) +
1937 ret_dlg->SetFont(*smallFont);
1939 ret_dlg->SetSize(container->GetSize());
1947double OCPNPlatform::GetToolbarScaleFactor(
int GUIScaleFactor) {
1955 wxSize style_tool_size(32, 32);
1957 if (g_StyleManager) {
1959 if (style) style_tool_size = style->GetToolSize();
1961 double tool_size = style_tool_size.x;
1967 double premult = 1.0;
1968 if (g_config_display_size_manual && g_config_display_size_mm[0] > 0) {
1969 double target_size = 9.0;
1971 double basic_tool_size_mm = tool_size / GetDisplayDPmm();
1972 premult = target_size / basic_tool_size_mm;
1975 premult = wxMax(45 * getAndroidDisplayDensity(), 45) /
1981 double postmult = exp(GUIScaleFactor * (log(2.0) / 5.0));
1985 rv = premult * postmult;
1986 rv = wxMin(rv, getAndroidDisplayDensity() *
1990 double premult = 1.0;
1992 if (g_bresponsive) {
1995 wxSize style_tool_size = style->GetToolSize();
1996 double tool_size = style_tool_size.x;
2000 double target_size = 9.0;
2002 double basic_tool_size_mm = tool_size / GetDisplayDPmm();
2003 premult = target_size / basic_tool_size_mm;
2007 double postmult = exp(GUIScaleFactor * (0.693 / 5.0));
2009 rv = premult * postmult;
2010 rv = wxMin(rv, 3.0);
2011 rv = wxMax(rv, 0.5);
2020double OCPNPlatform::GetCompassScaleFactor(
int GUIScaleFactor) {
2027 if (g_bresponsive) {
2030 wxSize style_tool_size = style->GetToolSize();
2031 double compass_size = style_tool_size.x;
2037 double premult = wxMax(28 * getAndroidDisplayDensity(), 50) / compass_size;
2040 double postmult = exp(GUIScaleFactor * (log(2.0) / 5.0));
2043 rv = premult * postmult;
2044 rv = wxMin(rv, getAndroidDisplayDensity() *
2049 double premult = 1.0;
2051 if (g_bresponsive) {
2053 wxSize style_tool_size = style->GetToolSize();
2054 double compass_size = style_tool_size.x;
2057 double target_size = 6.0;
2059 double basic_tool_size_mm = compass_size / GetDisplayDPmm();
2060 premult = target_size / basic_tool_size_mm;
2063 double postmult = exp(GUIScaleFactor * (0.693 / 5.0));
2065 rv = premult * postmult;
2067 rv = wxMin(rv, 3.0);
2068 rv = wxMax(rv, 0.5);
2070#if defined(__WXOSX__) || defined(__WXGTK3__)
2072 if (gFrame) rv *= gFrame->GetContentScaleFactor();
2082float OCPNPlatform::GetChartScaleFactorExp(
float scale_linear) {
2083 double factor = 1.0;
2085 factor = exp(scale_linear * (log(3.0) / 5.0));
2090 factor = exp(scale_linear * (0.693 / 5.0));
2094 factor = wxMax(factor, .5);
2095 factor = wxMin(factor, 6.);
2100float OCPNPlatform::GetMarkScaleFactorExp(
float scale_linear) {
2101 if (scale_linear <= 0)
2102 return GetChartScaleFactorExp(scale_linear);
2104 return GetChartScaleFactorExp(scale_linear - 1);
2121bool OCPNPlatform::hasInternalBT(wxString profile) {
2123 bool t = androidDeviceHasBlueTooth();
2132bool OCPNPlatform::startBluetoothScan() {
2134 return androidStartBluetoothScan();
2141bool OCPNPlatform::stopBluetoothScan() {
2143 return androidStopBluetoothScan();
2150wxArrayString OCPNPlatform::getBluetoothScanResults() {
2151 wxArrayString ret_val;
2153 return androidGetBluetoothScanResults();
2156 ret_val.Add(_T(
"line 1"));
2157 ret_val.Add(_T(
"line 2"));
2158 ret_val.Add(_T(
"line 3"));
2168bool OCPNPlatform::AllowAlertDialog(
const wxString &class_name) {
2173 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
2175 wxWindow *win = node->GetData();
2176 if (win->IsShown()) nTLW++;
2178 node = node->GetNext();
2183 return (g_running && !g_options->IsShown() && (nTLW <= 4));
2185 return (g_running && (nTLW <= 4));
2192void OCPNPlatform::setChartTypeMaskSel(
int mask, wxString &indicator) {
2194 return androidSetChartTypeMaskSel(mask, indicator);
2199QString g_qtStyleSheet;
2201bool LoadQtStyleSheet(wxString &sheet_file) {
2202 if (wxFileExists(sheet_file)) {
2205 QString file(sheet_file.c_str());
2207 File.open(QFile::ReadOnly);
2208 g_qtStyleSheet = QLatin1String(File.readAll());
2218QString getQtStyleSheet(
void) {
return g_qtStyleSheet; }
2222bool OCPNPlatform::isPlatformCapable(
int flag) {
2226 if (flag == PLATFORM_CAP_PLUGINS) {
2228 wxString tsdk(android_plat_spc.msdk);
2229 if (tsdk.ToLong(&platver)) {
2230 if (platver >= 11)
return true;
2232 }
else if (flag == PLATFORM_CAP_FASTPAN) {
2234 wxString tsdk(android_plat_spc.msdk);
2235 if (tsdk.ToLong(&platver)) {
2236 if (platver >= 14)
return true;
2244void OCPNPlatform::DoHelpDialog(
void) {
2249 g_pAboutDlg->SetFocus();
2251 g_pAboutDlg->Show();
2254 if (!g_pAboutDlgLegacy)
2255 g_pAboutDlgLegacy =
new about(gFrame, GetSharedDataDir());
2257 g_pAboutDlgLegacy->SetFocus();
2258 g_pAboutDlgLegacy->Show();
2263void OCPNPlatform::LaunchLocalHelp(
void) {
2265 androidLaunchHelpView();
2267 wxString def_lang_canonical = _T(
"en_US");
2270 if (plocale_def_lang)
2271 def_lang_canonical = plocale_def_lang->GetCanonicalName();
2274 wxString help_locn = g_Platform->GetSharedDataDir() + _T(
"doc/help_");
2276 wxString help_try = help_locn + def_lang_canonical + _T(
".html");
2278 if (!::wxFileExists(help_try)) {
2279 help_try = help_locn + _T(
"en_US") + _T(
".html");
2281 if (!::wxFileExists(help_try)) {
2282 help_try = help_locn + _T(
"web") + _T(
".html");
2285 if (!::wxFileExists(help_try))
return;
2288 wxLaunchDefaultBrowser(wxString(_T(
"file:///")) + help_try);
2292void OCPNPlatform::platformLaunchDefaultBrowser(wxString URL) {
2294 androidLaunchBrowser(URL);
2296 ::wxLaunchDefaultBrowser(URL);
2306EVT_PAINT(OCPNColourPickerCtrl::OnPaint)
2315 const wxColour &initial,
2317 const wxSize &size,
long style,
2318 const wxValidator &validator,
2319 const wxString &name) {
2320 Create(parent,
id, initial, pos, size, style, validator, name);
2323bool OCPNColourPickerCtrl::Create(wxWindow *parent, wxWindowID
id,
2324 const wxColour &col,
const wxPoint &pos,
2325 const wxSize &size,
long style,
2326 const wxValidator &validator,
2327 const wxString &name) {
2328 m_bitmap = wxBitmap(60, 13);
2331 if (!wxBitmapButton::Create(parent,
id, m_bitmap, pos, size,
2332 style | wxBU_AUTODRAW, validator, name)) {
2333 wxFAIL_MSG(wxT(
"OCPNColourPickerCtrl creation failed"));
2338 Connect(GetId(), wxEVT_BUTTON,
2339 wxCommandEventHandler(OCPNColourPickerCtrl::OnButtonClick), NULL,
2349void OCPNColourPickerCtrl::InitColourData() {
2351 ms_data.SetChooseFull(
true);
2352 unsigned char grey = 0;
2353 for (
int i = 0; i < 16; i++, grey += 16)
2356 wxColour colour(grey, grey, grey);
2357 ms_data.SetCustomColour(i, colour);
2362void OCPNColourPickerCtrl::OnButtonClick(wxCommandEvent &WXUNUSED(ev)) {
2364 unsigned int cco = 0;
2367 cco |= m_colour.Red();
2369 cco |= m_colour.Green();
2371 cco |= m_colour.Blue();
2372 unsigned int cc = androidColorPicker(cco);
2375 unsigned char blue = (
unsigned char)cc % 256;
2376 unsigned char green = (
unsigned char)(cc >> 8) % 256;
2378 unsigned char red = (
unsigned char)(cc >> 16) % 256;
2379 cnew.Set(red, green, blue);
2385 ms_data.SetColour(m_colour);
2388 wxColourDialog dlg(
this, &ms_data);
2389 if (dlg.ShowModal() == wxID_OK) {
2390 ms_data = dlg.GetColourData();
2391 SetColour(ms_data.GetColour());
2396void OCPNColourPickerCtrl::UpdateColour() {
2398 SetBitmapLabel(wxBitmap());
2401 wxMemoryDC dc(m_bitmap);
2402 dc.SetPen(*wxTRANSPARENT_PEN);
2403 dc.SetBrush(wxBrush(m_colour));
2404 dc.DrawRectangle(0, 0, m_bitmap.GetWidth(), m_bitmap.GetHeight());
2406 dc.SelectObject(wxNullBitmap);
2407 SetBitmapLabel(m_bitmap);
2410void OCPNColourPickerCtrl::SetColour(wxColour &c) {
2412 m_bitmap = wxBitmap(GetSize().x - 20, GetSize().y - 20);
2416wxColour OCPNColourPickerCtrl::GetColour(
void) {
return m_colour; }
2418wxSize OCPNColourPickerCtrl::DoGetBestSize()
const {
2419 wxSize sz(wxBitmapButton::DoGetBestSize());
2426 if (HasFlag(wxCLRP_SHOW_LABEL))
return sz;
2434void OCPNColourPickerCtrl::OnPaint(wxPaintEvent &event) {
2437 int offset_x = (GetSize().x - m_bitmap.GetWidth()) / 2;
2438 int offset_y = (GetSize().y - m_bitmap.GetHeight()) / 2;
2440 dc.SetPen(*wxTRANSPARENT_PEN);
2441 dc.SetBrush(wxBrush(m_colour));
2442 dc.DrawRectangle(offset_x, offset_y, m_bitmap.GetWidth(),
2443 m_bitmap.GetHeight());
Global state for AIS decoder.
Implements the AboutFrame class with additional functionality.
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 LoadFontNative(wxString *pConfigString, wxString *pNativeDesc)
Loads font settings from a string descriptor.
wxFont * GetFont(const wxString &TextElement, int requested_font_size=0)
Gets a font object for a UI element.
std::string Homedir() const
home directory, convenience stuff.
std::string UserDatadir()
The single, user-writable common parent for plugin data directories, typically ending in 'plugins'.
static PluginPaths * getInstance()
Return the singleton instance.
Represents the About dialog for OpenCPN.
int GetErrorCount() const
Return the size of the error message's array.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
int Size() const
Return the size of the array or map stored in this value.
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.
Global variables reflecting command line options and arguments.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
General purpose GUI support.
Enhanced logging interface on top of wx/log.h.