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"
74#include "model/select.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;
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;
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";
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]);
1534 g_compatOsVersion =
"";
1535 pConfig->SetPath(_T (
"/Settings" ));
1536 pConfig->Write(_T (
"CompatOS" ), g_compatOS);
1537 pConfig->Write(_T (
"CompatOsVersion" ), g_compatOsVersion);
1541int OCPNPlatform::platformApplyPrivateSettingsString(wxString settings,
1542 ArrayOfCDI *pDirArray) {
1545 ret_val = androidApplySettingsString(settings, pDirArray);
1551void OCPNPlatform::applyExpertMode(
bool mode) {
1554 g_bBasicMenus = !mode;
1558wxString OCPNPlatform::GetSupplementalLicenseString() {
1561 lic = androidGetSupplementalLicense();
1570static wxString ExpandPaths(wxString paths,
OCPNPlatform *platform);
1572int OCPNPlatform::DoFileSelectorDialog(wxWindow *parent, wxString *file_spec,
1573 wxString Title, wxString initDir,
1574 wxString suggestedName,
1575 wxString wildcard) {
1577 int result = wxID_CANCEL;
1581 wxString idir = initDir;
1582 if (initDir.StartsWith(
1584 idir = GetWritableDocumentsDir();
1586 result = androidFileChooser(&file, idir, Title, suggestedName, wildcard);
1587 if (file_spec) *file_spec = file;
1589 long flag = wxFD_DEFAULT_STYLE;
1590 if (suggestedName.Length()) {
1594 wxString mask = wildcard;
1595 if (wxNOT_FOUND != mask.Find(_T(
"gpx")))
1596 mask.Prepend(_T(
"GPX files (*.gpx)|"));
1598 wxFileDialog *psaveDialog =
1599 new wxFileDialog(parent, Title, initDir, suggestedName, mask, flag);
1607 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
1610 result = psaveDialog->ShowModal();
1613 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
1616 if (file_spec) *file_spec = psaveDialog->GetPath();
1624int OCPNPlatform::DoDirSelectorDialog(wxWindow *parent, wxString *file_spec,
1625 wxString Title, wxString initDir,
1628 int result = wxID_CANCEL;
1632 wxString idir = initDir;
1633 if (initDir.StartsWith(
1635 idir = GetWritableDocumentsDir();
1637 result = androidFileChooser(&dir, idir, Title, _T(
""), _T(
""),
true,
1639 if (file_spec) *file_spec = dir;
1641 wxDirDialog *dirSelector =
new wxDirDialog(
1642 parent, Title, initDir, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1645 dirSelector->SetFont(*qFont);
1652 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
1655 result = dirSelector->ShowModal();
1658 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
1661 if (result == wxID_CANCEL) {
1664 *file_spec = dirSelector->GetPath();
1674MyConfig *OCPNPlatform::GetConfigObject() {
1677 result =
new MyConfig(GetConfigFileName());
1686bool OCPNPlatform::hasInternalGPS(wxString profile) {
1688 bool t = androidDeviceHasGPS();
1702void OCPNPlatform::ShowBusySpinner(
void) {
1703 AbstractPlatform::ShowBusySpinner();
1706void OCPNPlatform::HideBusySpinner(
void) {
1707 AbstractPlatform::HideBusySpinner();
1710double OCPNPlatform::GetDisplayDensityFactor() {
1712 return getAndroidDisplayDensity();
1718long OCPNPlatform::GetDefaultToolbarOrientation() {
1720 return wxTB_VERTICAL;
1722 return wxTB_VERTICAL;
1726int OCPNPlatform::GetStatusBarFieldCount() {
1732 wxFont *templateFont = FontMgr::Get().
GetFont(_(
"StatusBar"), 0);
1733 dc.SetFont(*templateFont);
1736 dc.GetTextExtent(_T(
"WWWWWW"), &width, NULL, NULL, NULL, templateFont);
1737 double font_size_pix = (double)width / 6.0;
1741 double nChars = dispSize.x / font_size_pix;
1751 return STAT_FIELD_COUNT;
1755double OCPNPlatform::getFontPointsperPixel(
void) {
1756 double pt_per_pixel = 1.0;
1766 if (m_pt_per_pixel == 0) {
1771 12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, FALSE,
1772 wxString(_T (
"" )), wxFONTENCODING_SYSTEM);
1776 dc.GetTextExtent(_T(
"H"), &width, &height, NULL, NULL, f);
1778 if (height > 0) m_pt_per_pixel = 12.0 / (double)height;
1780 if (m_pt_per_pixel > 0) pt_per_pixel = m_pt_per_pixel;
1783 return pt_per_pixel;
1788 return getAndroidDisplayDimensions();
1790 return wxSize(g_monitor_info[g_current_monitor].width,
1791 g_monitor_info[g_current_monitor].height);
1796 if (g_current_monitor < m_displaySizeMMOverride.size()) {
1797 if (m_displaySizeMMOverride[g_current_monitor] > 0) {
1798 return m_displaySizeMMOverride[g_current_monitor];
1802 double ret = g_monitor_info[g_current_monitor].width_mm;
1805 ret = GetAndroidDisplaySize();
1811double OCPNPlatform::GetDisplayAreaCM2() {
1816 ratio = (double)sz.x / (
double)sz.y;
1818 ratio = (double)sz.y / (
double)sz.x;
1820 double area = size1 * (size1 * ratio) / 100.;
1826 if (monitor < m_displaySizeMMOverride.size()) {
1827 m_displaySizeMMOverride[monitor] = sizeMM;
1831double OCPNPlatform::GetDisplayDPmm() {
1833 return getAndroidDPmm();
1840unsigned int OCPNPlatform::GetSelectRadiusPix() {
1841 return GetDisplayDPmm() *
1842 (g_btouch ? g_selection_radius_touch_mm : g_selection_radius_mm);
1845bool OCPNPlatform::GetFullscreen() {
1848 bret = androidGetFullscreen();
1856bool OCPNPlatform::SetFullscreen(
bool bFull) {
1859 bret = androidSetFullscreen(bFull);
1866void OCPNPlatform::PositionAISAlert(wxWindow *alert_window) {
1869 alert_window->SetSize(g_ais_alert_dialog_x, g_ais_alert_dialog_y,
1870 g_ais_alert_dialog_sx, g_ais_alert_dialog_sy);
1874 alert_window->Centre();
1880wxDirDialog *OCPNPlatform::AdjustDirDialogFont(wxWindow *container,
1882 wxDirDialog *ret_dlg = dlg;
1886 dlg->SetSize(container->GetSize());
1889 wxSize sds = dlg->GetSize();
1890 wxSize ss = container->GetSize();
1895 wxString msg = dlg->GetMessage();
1896 wxString default_dir = dlg->GetPath();
1900 ret_dlg =
new wxDirDialog(NULL, msg, default_dir,
1901 wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1904 wxFont *smallFont =
new wxFont(*dialogFont);
1905 smallFont->SetPointSize((smallFont->GetPointSize() / 2) +
1907 ret_dlg->SetFont(*smallFont);
1909 ret_dlg->SetSize(container->GetSize());
1917wxFileDialog *OCPNPlatform::AdjustFileDialogFont(wxWindow *container,
1918 wxFileDialog *dlg) {
1919 wxFileDialog *ret_dlg = dlg;
1923 dlg->SetSize(container->GetSize());
1926 wxSize sds = dlg->GetSize();
1927 wxSize ss = container->GetSize();
1932 wxString msg = dlg->GetMessage();
1933 wxString default_dir = dlg->GetDirectory();
1934 wxString default_file = dlg->GetFilename();
1935 wxString wildcard = dlg->GetWildcard();
1939 ret_dlg =
new wxFileDialog(NULL, msg, default_dir, default_file, wildcard,
1943 wxFont *smallFont =
new wxFont(*dialogFont);
1944 smallFont->SetPointSize((smallFont->GetPointSize() / 2) +
1946 ret_dlg->SetFont(*smallFont);
1948 ret_dlg->SetSize(container->GetSize());
1956double OCPNPlatform::GetToolbarScaleFactor(
int GUIScaleFactor) {
1964 wxSize style_tool_size(32, 32);
1966 if (g_StyleManager) {
1968 if (style) style_tool_size = style->GetToolSize();
1970 double tool_size = style_tool_size.x;
1976 double premult = 1.0;
1977 if (g_config_display_size_manual && g_config_display_size_mm[0] > 0) {
1978 double target_size = 9.0;
1980 double basic_tool_size_mm = tool_size / GetDisplayDPmm();
1981 premult = target_size / basic_tool_size_mm;
1984 premult = wxMax(45 * getAndroidDisplayDensity(), 45) /
1990 double postmult = exp(GUIScaleFactor * (log(2.0) / 5.0));
1994 rv = premult * postmult;
1995 rv = wxMin(rv, getAndroidDisplayDensity() *
1999 double premult = 1.0;
2004 wxSize style_tool_size = style->GetToolSize();
2005 double tool_size = style_tool_size.x;
2009 double target_size = 9.0;
2011 double basic_tool_size_mm = tool_size / GetDisplayDPmm();
2012 premult = target_size / basic_tool_size_mm;
2016 double postmult = exp(GUIScaleFactor * (0.693 / 5.0));
2018 rv = premult * postmult;
2019 rv = wxMin(rv, 3.0);
2020 rv = wxMax(rv, 0.5);
2029double OCPNPlatform::GetCompassScaleFactor(
int GUIScaleFactor) {
2039 wxSize style_tool_size = style->GetToolSize();
2040 double compass_size = style_tool_size.x;
2046 double premult = wxMax(28 * getAndroidDisplayDensity(), 50) / compass_size;
2049 double postmult = exp(GUIScaleFactor * (log(2.0) / 5.0));
2052 rv = premult * postmult;
2053 rv = wxMin(rv, getAndroidDisplayDensity() *
2058 double premult = 1.0;
2062 wxSize style_tool_size = style->GetToolSize();
2063 double compass_size = style_tool_size.x;
2066 double target_size = 6.0;
2068 double basic_tool_size_mm = compass_size / GetDisplayDPmm();
2069 premult = target_size / basic_tool_size_mm;
2072 double postmult = exp(GUIScaleFactor * (0.693 / 5.0));
2074 rv = premult * postmult;
2076 rv = wxMin(rv, 3.0);
2077 rv = wxMax(rv, 0.5);
2079#if defined(__WXOSX__) || defined(__WXGTK3__)
2081 if (gFrame) rv *= gFrame->GetContentScaleFactor();
2091float OCPNPlatform::GetChartScaleFactorExp(
float scale_linear) {
2092 double factor = 1.0;
2094 factor = exp(scale_linear * (log(3.0) / 5.0));
2099 factor = exp(scale_linear * (0.693 / 5.0));
2103 factor = wxMax(factor, .5);
2104 factor = wxMin(factor, 6.);
2109float OCPNPlatform::GetMarkScaleFactorExp(
float scale_linear) {
2110 if (scale_linear <= 0)
2111 return GetChartScaleFactorExp(scale_linear);
2113 return GetChartScaleFactorExp(scale_linear - 1);
2130bool OCPNPlatform::hasInternalBT(wxString profile) {
2132 bool t = androidDeviceHasBlueTooth();
2141bool OCPNPlatform::startBluetoothScan() {
2143 return androidStartBluetoothScan();
2150bool OCPNPlatform::stopBluetoothScan() {
2152 return androidStopBluetoothScan();
2159wxArrayString OCPNPlatform::getBluetoothScanResults() {
2160 wxArrayString ret_val;
2162 return androidGetBluetoothScanResults();
2165 ret_val.Add(_T(
"line 1"));
2166 ret_val.Add(_T(
"line 2"));
2167 ret_val.Add(_T(
"line 3"));
2177bool OCPNPlatform::AllowAlertDialog(
const wxString &class_name) {
2182 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
2184 wxWindow *win = node->GetData();
2185 if (win->IsShown()) nTLW++;
2187 node = node->GetNext();
2192 return (g_running && !g_options->IsShown() && (nTLW <= 4));
2194 return (g_running && (nTLW <= 4));
2201void OCPNPlatform::setChartTypeMaskSel(
int mask, wxString &indicator) {
2203 return androidSetChartTypeMaskSel(mask, indicator);
2208QString g_qtStyleSheet;
2210bool LoadQtStyleSheet(wxString &sheet_file) {
2211 if (wxFileExists(sheet_file)) {
2214 QString file(sheet_file.c_str());
2216 File.open(QFile::ReadOnly);
2217 g_qtStyleSheet = QLatin1String(File.readAll());
2227QString getQtStyleSheet(
void) {
return g_qtStyleSheet; }
2231bool OCPNPlatform::isPlatformCapable(
int flag) {
2235 if (flag == PLATFORM_CAP_PLUGINS) {
2237 wxString tsdk(android_plat_spc.msdk);
2238 if (tsdk.ToLong(&platver)) {
2239 if (platver >= 11)
return true;
2241 }
else if (flag == PLATFORM_CAP_FASTPAN) {
2243 wxString tsdk(android_plat_spc.msdk);
2244 if (tsdk.ToLong(&platver)) {
2245 if (platver >= 14)
return true;
2253void OCPNPlatform::platformLaunchDefaultBrowser(wxString URL) {
2255 androidLaunchBrowser(URL);
2257 ::wxLaunchDefaultBrowser(URL);
2267EVT_PAINT(OCPNColourPickerCtrl::OnPaint)
2276 const wxColour &initial,
2278 const wxSize &size,
long style,
2279 const wxValidator &validator,
2280 const wxString &name) {
2281 Create(parent,
id, initial, pos, size, style, validator, name);
2284bool OCPNColourPickerCtrl::Create(wxWindow *parent, wxWindowID
id,
2285 const wxColour &col,
const wxPoint &pos,
2286 const wxSize &size,
long style,
2287 const wxValidator &validator,
2288 const wxString &name) {
2289 m_bitmap = wxBitmap(60, 13);
2292 if (!wxBitmapButton::Create(parent,
id, m_bitmap, pos, size,
2293 style | wxBU_AUTODRAW, validator, name)) {
2294 wxFAIL_MSG(wxT(
"OCPNColourPickerCtrl creation failed"));
2299 Connect(GetId(), wxEVT_BUTTON,
2300 wxCommandEventHandler(OCPNColourPickerCtrl::OnButtonClick), NULL,
2310void OCPNColourPickerCtrl::InitColourData() {
2312 ms_data.SetChooseFull(
true);
2313 unsigned char grey = 0;
2314 for (
int i = 0; i < 16; i++, grey += 16)
2317 wxColour colour(grey, grey, grey);
2318 ms_data.SetCustomColour(i, colour);
2323void OCPNColourPickerCtrl::OnButtonClick(wxCommandEvent &WXUNUSED(ev)) {
2325 unsigned int cco = 0;
2328 cco |= m_colour.Red();
2330 cco |= m_colour.Green();
2332 cco |= m_colour.Blue();
2333 unsigned int cc = androidColorPicker(cco);
2336 unsigned char blue = (
unsigned char)cc % 256;
2337 unsigned char green = (
unsigned char)(cc >> 8) % 256;
2339 unsigned char red = (
unsigned char)(cc >> 16) % 256;
2340 cnew.Set(red, green, blue);
2346 ms_data.SetColour(m_colour);
2349 wxColourDialog dlg(
this, &ms_data);
2350 if (dlg.ShowModal() == wxID_OK) {
2351 ms_data = dlg.GetColourData();
2352 SetColour(ms_data.GetColour());
2357void OCPNColourPickerCtrl::UpdateColour() {
2359 SetBitmapLabel(wxBitmap());
2362 wxMemoryDC dc(m_bitmap);
2363 dc.SetPen(*wxTRANSPARENT_PEN);
2364 dc.SetBrush(wxBrush(m_colour));
2365 dc.DrawRectangle(0, 0, m_bitmap.GetWidth(), m_bitmap.GetHeight());
2367 dc.SelectObject(wxNullBitmap);
2368 SetBitmapLabel(m_bitmap);
2371void OCPNColourPickerCtrl::SetColour(wxColour &c) {
2373 m_bitmap = wxBitmap(GetSize().x - 20, GetSize().y - 20);
2377wxColour OCPNColourPickerCtrl::GetColour(
void) {
return m_colour; }
2379wxSize OCPNColourPickerCtrl::DoGetBestSize()
const {
2380 wxSize sz(wxBitmapButton::DoGetBestSize());
2387 if (HasFlag(wxCLRP_SHOW_LABEL))
return sz;
2395void OCPNColourPickerCtrl::OnPaint(wxPaintEvent &event) {
2398 int offset_x = (GetSize().x - m_bitmap.GetWidth()) / 2;
2399 int offset_y = (GetSize().y - m_bitmap.GetHeight()) / 2;
2401 dc.SetPen(*wxTRANSPARENT_PEN);
2402 dc.SetBrush(wxBrush(m_colour));
2403 dc.DrawRectangle(offset_x, offset_y, m_bitmap.GetWidth(),
2404 m_bitmap.GetHeight());
bool g_bresponsive
Flag to control adaptive UI scaling.
Global state for AIS decoder.
Extends AboutFrame, providing implementation for various event handlers and additional methods.
The OpenCPN About dialog displaying information including version, authors, license,...
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.
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.
Miscellaneous utilities, many of which string related.
Plugin installation and data paths support.