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>
66#include "model/base_platform.h"
68#include "model/config_vars.h"
69#include "model/conn_params.h"
70#include "model/cutil.h"
73#include "model/plugin_cache.h"
75#include "model/select.h"
83#include "ocpn_frame.h"
84#include "OCPNPlatform.h"
87#include "snd_config.h"
91#include "androidUTIL.h"
95#include "glChartCanvas.h"
99#ifdef OCPN_USE_CRASHREPORT
107#include "crashprint.h"
111#include "model/macutils.h"
114#if (defined(OCPN_GHC_FILESYSTEM) || \
115 (defined(__clang_major__) && (__clang_major__ < 15)))
117#include <ghc/filesystem.hpp>
118namespace fs = ghc::filesystem;
122namespace fs = std::filesystem;
128void appendOSDirSlash(wxString *pString);
131struct sigaction sa_all;
132struct sigaction sa_all_old;
133extern sigjmp_buf env;
137extern bool g_bFirstRun;
138extern bool g_bUpgradeInProcess;
147extern bool g_bshowToolbar;
148extern bool g_bexpert;
149extern bool g_bBasicMenus;
150extern bool g_bUIexpert;
152extern bool g_bshowToolbar;
153extern bool g_bBasicMenus;
155extern bool g_bShowOutlines;
156extern int g_nAWDefault;
158extern bool g_bPermanentMOBIcon;
159extern float g_toolbar_scalefactor;
163extern wxString *pInit_Chart_Dir;
165extern std::vector<size_t> g_config_display_size_mm;
166extern bool g_config_display_size_manual;
168extern bool g_bFullScreenQuilt;
169extern bool g_bQuiltEnable;
170extern bool g_bskew_comp;
172extern bool g_bopengl;
174extern bool g_bShowStatusBar;
175extern int g_cm93_zoom_factor;
176extern int g_GUIScaleFactor;
177extern bool g_fog_overzoom;
178extern bool g_oz_vector_scale;
179extern wxString g_toolbarConfig;
180extern bool g_bPreserveScaleOnX;
181extern bool g_running;
182extern bool g_bEnableZoomToCursor;
183extern bool g_bsmoothpanzoom;
184extern bool g_bShowMenuBar;
191extern int g_default_font_size;
192extern wxString g_default_font_facename;
194bool g_bEmailCrashReport;
196extern double g_ChartNotRenderScaleFactor;
197extern bool g_bRollover;
199#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
200extern wxLocale *plocale_def_lang;
202extern wxString g_locale;
203extern wxString g_localeOverride;
204extern wxArrayString g_locale_catalog_array;
207extern int options_lastPage;
209extern About *g_pAboutDlgLegacy;
210extern wxColour g_colourTrackLineColour;
211extern int g_n_ownship_min_mm;
213extern int g_AndroidVersionCode;
214extern bool g_bShowMuiZoomButtons;
215extern int g_FlushNavobjChangesTimeout;
216extern wxString g_CmdSoundString;
217extern int g_maintoolbar_x;
218extern int g_maintoolbar_y;
219extern std::vector<std::string> TideCurrentDataSet;
220extern int g_Android_SDK_Version;
221extern wxString g_androidDownloadDirectory;
222extern wxString g_gpx_path;
233static const char *
const DEFAULT_XDG_DATA_DIRS =
234 "~/.local/share:/usr/local/share:/usr/share";
237static const char PATH_SEP =
';';
239static const char PATH_SEP =
':';
242static bool checkIfFlatpacked() {
244 if (!wxGetEnv(
"FLATPAK_ID", &
id)) {
247 return id ==
"org.opencpn.OpenCPN";
250OCPNPlatform::OCPNPlatform() {
252 m_bdisableWindowsDisplayEnum =
false;
253 m_monitorWidth = m_monitorHeight = 0;
255 for (
size_t i = 0; i < g_monitor_info.size(); i++) {
256 m_displaySizeMMOverride.push_back(0);
258 m_pluginDataPath =
"";
261OCPNPlatform::~OCPNPlatform() {
273int MyNewHandler(
size_t size) {
275 throw std::bad_alloc();
296void catch_signals(
int signo) {
327#ifdef OCPN_USE_CRASHREPORT
329int CALLBACK CrashCallback(CR_CRASH_CALLBACK_INFO *pInfo) {
330 wxLog::GetActiveTarget()->Flush();
331 return CR_CB_DODEFAULT;
336void OCPNPlatform::Initialize_1(
void) {
337#ifdef OCPN_USE_CRASHREPORT
341 CR_INSTALL_INFO info;
342 memset(&info, 0,
sizeof(CR_INSTALL_INFO));
343 info.cb =
sizeof(CR_INSTALL_INFO);
344 info.pszAppName = _T(
"OpenCPN");
346 info.pszAppVersion = wxString(VERSION_FULL).c_str();
348 int type = MiniDumpNormal;
351 type |= MiniDumpWithDataSegs;
362 info.uMiniDumpType = (MINIDUMP_TYPE)type;
365 info.dwFlags = CR_INST_ALL_POSSIBLE_HANDLERS;
368 info.dwFlags &= ~CR_INST_NEW_OPERATOR_ERROR_HANDLER;
371 info.dwFlags |= CR_INST_ALLOW_ATTACH_MORE_FILES;
374 info.dwFlags |= CR_INST_SHOW_ADDITIONAL_INFO_FIELDS;
378 if (g_bEmailCrashReport) {
379 info.pszUrl = _T(
"https://bigdumboat.com/crashrpt/ocpn_crashrpt.php");
380 info.uPriorities[CR_HTTP] = 3;
382 info.dwFlags |= CR_INST_DONT_SEND_REPORT;
383 info.uPriorities[CR_HTTP] = CR_NEGATIVE_PRIORITY;
386 info.uPriorities[CR_SMTP] =
387 CR_NEGATIVE_PRIORITY;
388 info.uPriorities[CR_SMAPI] =
389 CR_NEGATIVE_PRIORITY;
391 wxStandardPaths &crash_std_path = g_Platform->GetStdPaths();
393 wxString crash_rpt_save_locn = crash_std_path.GetConfigDir();
395 wxFileName exec_path_crash(crash_std_path.GetExecutablePath());
396 crash_rpt_save_locn =
397 exec_path_crash.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
400 wxString locn = crash_rpt_save_locn + _T(
"\\CrashReports");
402 if (!wxDirExists(locn)) wxMkdir(locn);
404 if (wxDirExists(locn)) {
405 wxCharBuffer buf = locn.ToUTF8();
407 if (buf && (locn.Length() <
sizeof(wlocn))) {
408 MultiByteToWideChar(0, 0, buf.data(), -1, wlocn,
sizeof(wlocn) - 1);
409 info.pszErrorReportSaveDir = (LPCWSTR)wlocn;
414 wxFileName exec_path_crash(crash_std_path.GetExecutablePath());
415 wxString policy_file =
416 exec_path_crash.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
417 policy_file += _T(
"PrivacyPolicy.txt");
418 policy_file.Prepend(_T(
"file:"));
420 info.pszPrivacyPolicyURL = policy_file.c_str();
423 int nResult = crInstall(&info);
426 crGetLastErrorMsg(buff, 256);
433 crSetCrashCallback(CrashCallback, NULL);
436 crAddScreenshot2(CR_AS_PROCESS_WINDOWS | CR_AS_USE_JPEG_FORMAT, 95);
439 wxString home_data_crash = crash_std_path.GetConfigDir();
441 wxFileName f(crash_std_path.GetExecutablePath());
442 home_data_crash = f.GetPath();
444 appendOSDirSlash(&home_data_crash);
446 wxString config_crash = _T(
"opencpn.ini");
447 config_crash.Prepend(home_data_crash);
448 crAddFile2(config_crash.c_str(), NULL, NULL,
449 CR_AF_MISSING_FILE_OK | CR_AF_ALLOW_DELETE);
451 wxString log_crash = _T(
"opencpn.log");
452 log_crash.Prepend(home_data_crash);
453 crAddFile2(log_crash.c_str(), NULL, NULL,
454 CR_AF_MISSING_FILE_OK | CR_AF_ALLOW_DELETE);
460#if wxUSE_ON_FATAL_EXCEPTION
462 wxHandleFatalExceptions(
true);
468 _set_new_handler(MyNewHandler);
478 HANDLE hProc = GetCurrentProcess();
482 DuplicateHandle( hProc, hProc, hProc, &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS );
485 GetProcessAffinityMask( hDup, &procMask, &sysMask );
489 if( ( procMask & 1 ) == 1 ) newMask = 1;
491 if( ( procMask & 2 ) == 2 ) newMask = 2;
493 if( ( procMask & 4 ) == 4 ) newMask = 4;
495 if( ( procMask & 8 ) == 8 ) newMask = 8;
498 BOOL res = SetProcessAffinityMask( hDup, (DWORD_PTR) newMask );
512 wxPlatformInfo Platform;
513 if (Platform.GetOperatingSystemId() == wxOS_WINDOWS_9X)
514 SetUnhandledExceptionFilter(&MyUnhandledExceptionFilter);
525 sa_all.sa_handler = catch_signals;
526 sigemptyset(&sa_all.sa_mask);
532 sigaction(SIGUSR1, NULL,
536 sigaction(SIGUSR1, &sa_all, NULL);
537 sigaction(SIGUSR1, NULL,
540 sigaction(SIGTERM, &sa_all, NULL);
541 sigaction(SIGTERM, NULL, &sa_all_old);
543 sigaction(SIGHUP, &sa_all, NULL);
544 sigaction(SIGHUP, NULL, &sa_all_old);
549 qDebug() <<
"Initialize_1()";
559void OCPNPlatform::Initialize_2(
void) {
561 wxLogMessage(androidGetDeviceInfo());
565 wxChar sep = wxFileName::GetPathSeparator();
568 if (ChartDir.Last() != sep) ChartDir.Append(sep);
569 ChartDir.Append(
"Charts");
570 if (!::wxDirExists(ChartDir)) {
575 if (GRIBDir.Last() != sep) GRIBDir.Append(sep);
576 GRIBDir.Append(
"GRIBS");
577 if (!::wxDirExists(GRIBDir)) {
582 if (VDRDir.Last() != sep) VDRDir.Append(sep);
583 VDRDir.Append(
"VDR");
584 if (!::wxDirExists(VDRDir)) {
589 if (g_Android_SDK_Version >= 30) {
590 if (!g_gpx_path.StartsWith(androidGetDocumentsDirectory())) {
591 g_gpx_path = androidGetDocumentsDirectory();
598 g_toolbar_scalefactor = GetToolbarScaleFactor(g_GUIScaleFactor);
600 if (!configdir.DirExists()) {
601 if (!configdir.Mkdir()) {
602 auto msg = std::string(
"Cannot create config directory: ");
603 wxLogWarning(msg + configdir.GetFullPath());
610void OCPNPlatform::Initialize_3(
void) {
611 bool bcapable = IsGLCapable();
617 bool bAndroid =
false;
626 g_bdisable_opengl =
false;
627 pConfig->UpdateSettings();
634 if ((g_bFirstRun || g_bUpgradeInProcess || bAndroid) && bcapable) {
638 g_GLOptions.m_bUseAcceleratedPanning =
true;
639 g_GLOptions.m_bTextureCompression =
true;
640 g_GLOptions.m_bTextureCompressionCaching =
true;
642 g_GLOptions.m_iTextureDimension = 512;
643 g_GLOptions.m_iTextureMemorySize = 64;
645 g_GLOptions.m_GLPolygonSmoothing =
true;
646 g_GLOptions.m_GLLineSmoothing =
true;
650 gFrame->SetGPSCompassScale();
658 if (g_bFirstRun || g_bUpgradeInProcess) {
660 g_bRollover = g_btouch ? false :
true;
663 g_FlushNavobjChangesTimeout = 300;
667void OCPNPlatform::Initialize_4(
void) {
669 if (pSelect) pSelect->SetSelectPixelRadius(wxMax(25, 6.0 * getAndroidDPmm()));
671 pSelectTC->SetSelectPixelRadius(wxMax(25, 6.0 * getAndroidDPmm()));
673 pSelectAIS->SetSelectPixelRadius(wxMax(25, 6.0 * getAndroidDPmm()));
680 options_lastPage = 1;
684void OCPNPlatform::OnExit_1(
void) {}
686void OCPNPlatform::OnExit_2(
void) {
687#ifdef OCPN_USE_CRASHREPORT
697bool HasGLExt(
wxJSONValue &glinfo,
const std::string ext) {
698 if (!glinfo.
HasMember(
"GL_EXTENSIONS")) {
701 for (
int i = 0; i < glinfo[
"GL_EXTENSIONS"].
Size(); i++) {
702 if (glinfo[
"GL_EXTENSIONS"][i].AsString() == ext) {
709bool OCPNPlatform::BuildGLCaps(
void *pbuf) {
711 fs::path ep(GetExePath().ToStdString());
713 std::string gl_util_exe =
"opencpn-glutil";
715 std::string gl_util_exe =
"opencpn-glutil.exe";
717 fs::path gl_util_path = ep.parent_path().append(gl_util_exe);
719 if (!fs::exists(gl_util_path)) {
722 wxLogMessage(
"OpenGL test utility not found at %s.", gl_util_path.c_str());
727 .append(
"gl_caps.json")
730 wxString cmd = wxString::Format(
"\"%s\" opengl-info \"%s\"",
731 gl_util_path.c_str(), gl_json.c_str());
733 wxLogMessage(
"Starting OpenGL test utility: %s", cmd);
735 wxArrayString output;
736 if (
long res = wxExecute(cmd, output); res != 0) {
737 wxLogMessage(
"OpenGL test utility failed with exit code %d", res);
738 for (
const auto &l : output) {
744 wxFileInputStream fis(gl_json);
747 reader.
Parse(fis, &root);
749 wxLogMessage(
"Failed to parse JSON output from OpenGL test utility.");
750 for (
const auto &l : reader.GetErrors()) {
759 pcaps->Renderer = root[
"GL_RENDERER"].
AsString();
761 wxLogMessage(
"GL_RENDERER not found.");
765 pcaps->Version = root[
"GL_VERSION"].
AsString();
767 wxLogMessage(
"GL_VERSION not found.");
770 if (root.
HasMember(
"GL_SHADING_LANGUAGE_VERSION")) {
771 pcaps->GLSL_Version = root[
"GL_SHADING_LANGUAGE_VERSION"].
AsString();
773 wxLogMessage(
"GL_SHADING_LANGUAGE_VERSION not found.");
777 if (!root[
"GL_USABLE"].AsBool()) {
778 wxLogMessage(
"OpenGL test utility reports that OpenGL is not usable.");
782 wxLogMessage(
"GL_USABLE not found.");
785 pcaps->dGLSL_Version = 0;
786 pcaps->dGLSL_Version = ::atof(pcaps->GLSL_Version.c_str());
787 if (pcaps->dGLSL_Version < 1.2) {
789 msg.Printf(_T(
"GLCaps Probe: OpenGL-> GLSL Version reported: "));
790 msg += wxString(pcaps->GLSL_Version.c_str());
791 msg +=
"\n OpenGL disabled due to insufficient OpenGL capabilities";
793 pcaps->bCanDoGLSL =
false;
796 pcaps->bCanDoGLSL =
true;
797 if (HasGLExt(root,
"GL_ARB_texture_non_power_of_two")) {
798 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
799 }
else if (HasGLExt(root,
"GL_OES_texture_npot")) {
800 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
801 }
else if (HasGLExt(root,
"GL_ARB_texture_rectangle")) {
802 pcaps->TextureRectangleFormat = GL_TEXTURE_RECTANGLE_ARB;
805 pcaps->bOldIntel =
false;
807 pcaps->bCanDoFBO = HasGLExt(root,
"GL_EXT_framebuffer_object");
808 if (!pcaps->TextureRectangleFormat) {
809 pcaps->bCanDoFBO =
false;
812 pcaps->bCanDoVBO = HasGLExt(
813 root,
"GL_ARB_vertex_buffer_object");
825 wxGLContext *pctx =
new wxGLContext(tcanvas);
826 tcanvas->SetCurrent(*pctx);
830 char *str = (
char *)glGetString(GL_RENDERER);
832 wxLogMessage(
"GL_RENDERER not found.");
837 pcaps->Renderer = std::string(str);
839 char *stv = (
char *)glGetString(GL_VERSION);
841 wxLogMessage(
"GL_VERSION not found");
846 pcaps->Version = std::string(stv);
848 char *stsv = (
char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
850 wxLogMessage(
"GL_SHADING_LANGUAGE_VERSION not found");
855 pcaps->GLSL_Version = std::string(stsv);
857 pcaps->dGLSL_Version = 0;
858 pcaps->dGLSL_Version = ::atof(pcaps->GLSL_Version.c_str());
860 if (pcaps->dGLSL_Version < 1.2) {
862 msg.Printf(_T(
"GLCaps Probe: OpenGL-> GLSL Version reported: "));
863 msg += wxString(pcaps->GLSL_Version.c_str());
864 msg +=
"\n OpenGL disabled due to insufficient OpenGL capabilities";
866 pcaps->bCanDoGLSL =
false;
872 pcaps->bCanDoGLSL =
true;
874 if (QueryExtension(
"GL_ARB_texture_non_power_of_two"))
875 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
876 else if (QueryExtension(
"GL_OES_texture_npot"))
877 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
878 else if (QueryExtension(
"GL_ARB_texture_rectangle"))
879 pcaps->TextureRectangleFormat = GL_TEXTURE_RECTANGLE_ARB;
881 pcaps->bOldIntel =
false;
884 pcaps->bCanDoVBO =
true;
886#if defined(__WXMSW__) || defined(__WXOSX__)
887 if (pcaps->bOldIntel) pcaps->bCanDoVBO =
false;
891 pcaps->bCanDoVBO =
false;
895 pcaps->bCanDoFBO =
true;
899 if (!pcaps->TextureRectangleFormat) pcaps->bCanDoFBO =
false;
902 if (!QueryExtension(
"GL_EXT_framebuffer_object")) pcaps->bCanDoFBO =
false;
912bool OCPNPlatform::IsGLCapable() {
921 if (g_bdisable_opengl)
return false;
923 wxLogMessage(
"Starting OpenGL test...");
924 wxLog::FlushActive();
928 bool bcaps = BuildGLCaps(GL_Caps);
930 wxLogMessage(
"OpenGL test complete.");
932 wxLogMessage(
"BuildGLCaps fails.");
933 wxLog::FlushActive();
941 if (!GL_Caps->bCanDoGLSL) {
947 if (!GL_Caps->bCanDoFBO) {
952 wxLogMessage(
"OpenGL determined CAPABLE.");
953 wxLog::FlushActive();
955 g_bdisable_opengl =
false;
959 pConfig->UpdateSettings();
968void OCPNPlatform::SetLocaleSearchPrefixes(
void) {
971#if defined(__WINDOWS__)
974 wxString locale_location = GetSharedDataDir();
975 locale_location += _T(
"share\\locale");
976 wxLocale::AddCatalogLookupPathPrefix(locale_location);
977 wxString imsg = _T(
"Adding catalog lookup path: ");
978 imsg += locale_location;
983 usrShare.RemoveLastDir();
984 locale_location = usrShare.GetFullPath() + (
"share\\locale");
985 wxLocale::AddCatalogLookupPathPrefix(locale_location);
986 imsg = _T(
"Adding catalog lookup path: ");
987 imsg += locale_location;
990#elif defined(__ANDROID__)
992 wxString locale_location = GetSharedDataDir() + _T(
"locale");
993 wxLocale::AddCatalogLookupPathPrefix(locale_location);
995#elif defined(__UNIX__) && !defined(__WINE__)
1000 wxString locale_location;
1001 if (!wxGetEnv(_T(
"OPENCPN_PREFIX"), &locale_location)) {
1002 locale_location = _T(
"/usr/local");
1006 locale_location = g_Platform->GetHomeDir();
1009 wxFileName location;
1010 location.AssignDir(locale_location);
1011 location.AppendDir(_T(
"share"));
1012 location.SetName(_T(
"locale"));
1013 locale_location = location.GetFullPath();
1014 wxLocale::AddCatalogLookupPathPrefix(locale_location);
1018 wxString managed_locale_location(dir +
"/locale");
1019 wxLocale::AddCatalogLookupPathPrefix(managed_locale_location);
1023 std::string macDir =
1025 "/Library/Application Support/OpenCPN/Contents/Resources";
1026 wxString Mac_managed_locale_location(macDir);
1027 wxLocale::AddCatalogLookupPathPrefix(Mac_managed_locale_location);
1033wxString OCPNPlatform::GetDefaultSystemLocale() {
1034 wxLogMessage(_T(
"Getting DefaultSystemLocale..."));
1036 wxString retval = _T(
"en_US");
1040 const wxLanguageInfo *languageInfo =
1041 wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
1042 if (languageInfo) retval = languageInfo->CanonicalName;
1044#if defined(__WXMSW__)
1045 LANGID lang_id = GetUserDefaultUILanguage();
1048 const wxLanguageInfo *languageInfoW = 0;
1049 if (0 != GetLocaleInfo(MAKELCID(lang_id, SORT_DEFAULT), LOCALE_SENGLANGUAGE,
1051 wxString lstring = wxString(lngcp);
1053 languageInfoW = wxLocale::FindLanguageInfo(lngcp);
1055 wxLogMessage(_T(
"Found LanguageInfo for: ") + lstring);
1057 wxLogMessage(_T(
"Could not find LanguageInfo for: ") + lstring);
1059 wxLogMessage(_T(
"Could not get LocaleInfo, using wxLANGUAGE_DEFAULT"));
1060 languageInfoW = wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
1063 if (languageInfoW) retval = languageInfoW->CanonicalName;
1066#if defined(__ANDROID__)
1067 retval = androidGetAndroidSystemLocale();
1075#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1076wxString OCPNPlatform::GetAdjustedAppLocale() {
1077 wxString adjLocale = g_locale;
1082#if defined(__WXMSW__)
1083 if (g_bFirstRun || wxIsEmpty(adjLocale)) {
1084 wxRegKey RegKey(wxString(_T(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenCPN")));
1085 if (RegKey.Exists()) {
1087 _T(
"Retrieving initial language selection from Windows Registry"));
1088 RegKey.QueryValue(wxString(_T(
"InstallerLanguage")), adjLocale);
1091 if (wxIsEmpty(adjLocale)) {
1092 if (g_localeOverride.Length())
1093 adjLocale = g_localeOverride;
1095 adjLocale = GetDefaultSystemLocale();
1098#if defined(__ANDROID__)
1099 if (g_localeOverride.Length())
1100 adjLocale = g_localeOverride;
1102 adjLocale = GetDefaultSystemLocale();
1108wxString OCPNPlatform::ChangeLocale(wxString &newLocaleID,
1109 wxLocale *presentLocale,
1110 wxLocale **newLocale) {
1111 wxString return_val;
1113 wxString imsg = _T(
"ChangeLocale: Language load for: ");
1114 imsg += newLocaleID;
1118 delete (wxLocale *)presentLocale;
1120 wxLocale *locale =
new wxLocale;
1121 if (isFlatpacked()) {
1122 std::string path(getenv(
"HOME"));
1123 path +=
"/.var/app/org.opencpn.OpenCPN/data/locale";
1124 locale->AddCatalogLookupPathPrefix(path);
1125 wxLogMessage(
"Using flatpak locales at %s", path.c_str());
1127 wxString loc_lang_canonical;
1129 const wxLanguageInfo *pli = wxLocale::FindLanguageInfo(newLocaleID);
1130 bool b_initok =
false;
1133 locale->Init(pli->Language, 1);
1137 if (!locale->IsOk()) {
1138 wxString imsg = _T(
"ChangeLocale: could not initialize: ");
1139 imsg += newLocaleID;
1143 locale =
new wxLocale;
1144 locale->Init(pli->Language, 0);
1146 loc_lang_canonical = pli->CanonicalName;
1148 b_initok = locale->IsOk();
1155 wxString imsg = _T(
"ChangeLocale: Fall back to en_US");
1159 locale =
new wxLocale;
1160 locale->Init(wxLANGUAGE_ENGLISH_US, 0);
1161 loc_lang_canonical =
1162 wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US)->CanonicalName;
1166 wxString imsg = _T(
"ChangeLocale: Locale Init OK for: ");
1167 imsg += loc_lang_canonical;
1179 for (
unsigned int i = 0; i < g_locale_catalog_array.GetCount(); i++) {
1180 if (!locale->AddCatalog(g_locale_catalog_array[i])) {
1181 wxString emsg = _T(
"ERROR Loading translation catalog for: ");
1182 emsg += g_locale_catalog_array[i];
1185 wxString imsg = _T(
"Loaded translation catalog for: ");
1186 imsg += g_locale_catalog_array[i];
1192 wxLogMessage(_T(
"Loading catalog for opencpn core."));
1193 locale->AddCatalog(_T(
"opencpn"));
1195 return_val = locale->GetCanonicalName();
1198 if (return_val != GetDefaultSystemLocale())
1199 g_localeOverride = return_val;
1201 g_localeOverride = _T(
"");
1204 *newLocale = locale;
1207 setlocale(LC_NUMERIC,
"C");
1218void OCPNPlatform::SetDefaultOptions(
void) {
1220 g_bShowOutlines =
true;
1226 g_MarkLost_Mins = 8;
1227 g_bRemoveLost =
true;
1228 g_RemoveLost_Mins = 10;
1231 g_bSyncCogPredictors =
false;
1232 g_bHideMoored =
false;
1233 g_ShowMoored_Kts = 0.2;
1234 g_SOGminCOG_kts = 0.2;
1235 g_bTrackDaily =
false;
1237 g_bFullScreenQuilt =
true;
1238 g_bQuiltEnable =
true;
1239 g_bskew_comp =
false;
1240 g_bShowAreaNotices =
false;
1241 g_bDrawAISSize =
false;
1242 g_bDrawAISRealtime =
false;
1243 g_AIS_RealtPred_Kts = 0.7;
1244 g_bShowAISName =
false;
1245 g_nTrackPrecision = 2;
1246 g_bPreserveScaleOnX =
true;
1249 gps_watchdog_timeout_ticks = GPS_TIMEOUT_SECONDS;
1250 g_n_ownship_min_mm = 8;
1251 g_bShowMuiZoomButtons =
true;
1256 pConfig->SetPath(_T (
"/Settings/GlobalState" ));
1257 pConfig->Write(_T (
"bShowS57Text" ),
true);
1258 pConfig->Write(_T (
"bShowS57ImportantTextOnly" ),
false);
1259 pConfig->Write(_T (
"nDisplayCategory" ), (
int)(_DisCat)OTHER);
1260 pConfig->Write(_T (
"nSymbolStyle" ), (
int)(_LUPname)PAPER_CHART);
1261 pConfig->Write(_T (
"nBoundaryStyle" ), (
int)(_LUPname)PLAIN_BOUNDARIES);
1263 pConfig->Write(_T (
"bShowSoundg" ),
true);
1264 pConfig->Write(_T (
"bShowMeta" ),
false);
1265 pConfig->Write(_T (
"bUseSCAMIN" ),
true);
1266 pConfig->Write(_T (
"bShowAtonText" ),
false);
1267 pConfig->Write(_T (
"bShowLightDescription" ),
false);
1268 pConfig->Write(_T (
"bExtendLightSectors" ),
true);
1269 pConfig->Write(_T (
"bDeClutterText" ),
true);
1270 pConfig->Write(_T (
"bShowNationalText" ),
true);
1272 pConfig->Write(_T (
"S52_MAR_SAFETY_CONTOUR" ), 3);
1273 pConfig->Write(_T (
"S52_MAR_SHALLOW_CONTOUR" ), 2);
1274 pConfig->Write(_T (
"S52_MAR_DEEP_CONTOUR" ), 6);
1275 pConfig->Write(_T (
"S52_MAR_TWO_SHADES" ), 0);
1276 pConfig->Write(_T (
"S52_DEPTH_UNIT_SHOW" ), 1);
1278 pConfig->Write(_T (
"ZoomDetailFactorVector" ), 3);
1280 pConfig->Write(_T (
"nColorScheme" ), 1);
1284 g_bEnableZoomToCursor =
true;
1285 g_bsmoothpanzoom =
true;
1286 g_bShowMenuBar =
true;
1293 pConfig->SetPath(_T (
"/PlugIns/chartdldr_pi.dll" ));
1294 pConfig->Write(_T (
"bEnabled" ),
true);
1296 pConfig->SetPath(_T (
"/PlugIns/wmm_pi.dll" ));
1297 pConfig->Write(_T (
"bEnabled" ),
true);
1299 pConfig->SetPath(_T (
"/Settings/WMM" ));
1300 pConfig->Write(_T (
"ShowIcon" ),
true);
1301 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1308 pConfig->SetPath(_T (
"/PlugIns/libchartdldr_pi.dylib" ));
1309 pConfig->Write(_T (
"bEnabled" ),
true);
1311 pConfig->SetPath(_T (
"/PlugIns/libwmm_pi.dylib" ));
1312 pConfig->Write(_T (
"bEnabled" ),
true);
1314 pConfig->SetPath(_T (
"/Settings/WMM" ));
1315 pConfig->Write(_T (
"ShowIcon" ),
true);
1316 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1323 pConfig->SetPath(_T (
"/PlugIns/libchartdldr_pi.so" ));
1324 pConfig->Write(_T (
"bEnabled" ),
true);
1326 pConfig->SetPath(_T (
"/PlugIns/libwmm_pi.so" ));
1327 pConfig->Write(_T (
"bEnabled" ),
true);
1329 pConfig->SetPath(_T (
"/Settings/WMM" ));
1330 pConfig->Write(_T (
"ShowIcon" ),
true);
1331 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1339 g_GLOptions.m_bTextureCompression = 1;
1340 g_GLOptions.m_bTextureCompressionCaching = 1;
1343 qDebug() <<
"SetDefaultOptions";
1347 g_default_font_size = 18;
1350 g_bShowStatusBar =
true;
1351 g_cm93_zoom_factor = 0;
1352 g_oz_vector_scale =
false;
1353 g_fog_overzoom =
false;
1356 g_bShowMuiZoomButtons =
true;
1358 g_GUIScaleFactor = 0;
1359 g_ChartNotRenderScaleFactor = 2.0;
1363 g_toolbarConfig = _T(
"X.....XX.......XX.XXXXXXXXXXX");
1364 g_bPermanentMOBIcon =
false;
1366 wxString sGPS = _T(
"2;3;;0;0;;0;1;0;0;;0;;1;0;0;0;0");
1369 new_params->bEnabled =
true;
1370 TheConnectionParams().push_back(new_params);
1372 g_default_font_facename = _T(
"Roboto");
1377 pConfig->SetPath(_T (
"/PlugIns/libchartdldr_pi.so" ));
1378 pConfig->Write(_T (
"bEnabled" ),
true);
1380 pConfig->SetPath(_T (
"/PlugIns/libwmm_pi.so" ));
1381 pConfig->Write(_T (
"bEnabled" ),
true);
1383 pConfig->SetPath(_T (
"/Settings/WMM" ));
1384 pConfig->Write(_T (
"ShowIcon" ),
true);
1385 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1387 pConfig->SetPath(_T (
"/PlugIns/libgrib_pi.so" ));
1388 pConfig->Write(_T (
"bEnabled" ),
true);
1390 pConfig->SetPath(_T (
"/PlugIns/libdashboard_pi.so" ));
1391 pConfig->Write(_T (
"bEnabled" ),
true);
1393 pConfig->SetPath(_T (
"/PlugIns/GRIB" ));
1394 pConfig->Write(_T (
"GRIBCtrlBarPosX" ), 100);
1395 pConfig->Write(_T (
"GRIBCtrlBarPosY" ), 0);
1397 pConfig->SetPath(_T (
"/Settings/GRIB" ));
1398 pConfig->Write(_T (
"CursorDataShown" ), 0);
1402 pConfig->SetPath(_T (
"/PlugIns/liboesenc_pi.so" ));
1403 pConfig->Write(_T (
"bEnabled" ),
true);
1405 pConfig->SetPath(_T (
"/Settings/QTFonts" ));
1408 wxString str = _T(
"en_US-b25a3899");
1409 wxString pval = _T(
"StatusBar:Roboto,26,-1,5,75,0,0,0,0,0:rgb(0, 0, 0)");
1410 pConfig->Write(str, pval);
1414 str = _T(
"en_US-9c3b3a0d");
1415 pval = _T(
"DialogStatusBar:Roboto,18,-1,5,50,0,0,0,0,0:rgb(0, 0, 0)");
1416 pConfig->Write(str, pval);
1420 pConfig->SetPath(_T (
"/Settings/Others" ));
1421 pConfig->Write(_T(
"TrackLineColour"), _T(
"#C545C3"));
1422 g_colourTrackLineColour.Set(197, 69, 195);
1424 qDebug() <<
"SetDefaultOptions.Config";
1435void OCPNPlatform::SetUpgradeOptions(wxString vNew, wxString vOld) {
1438 qDebug() <<
"Upgrade check"
1439 <<
"from: " << vOld.mb_str() <<
" to: " << vNew.mb_str();
1441 if (androidGetVersionCode() > g_AndroidVersionCode) {
1442 qDebug() <<
"Upgrade detected"
1443 <<
"from VC: " << g_AndroidVersionCode
1444 <<
" to VC: " << androidGetVersionCode();
1448 pConfig->SetPath(_T (
"/Settings/GlobalState" ));
1449 pConfig->Write(_T (
"bShowS57Text" ),
true);
1452 g_ChartNotRenderScaleFactor = 2.0;
1453 g_n_ownship_min_mm = 8;
1454 g_toolbarConfig = _T(
"X.....XX.......XX.XXXXXXXXXXX");
1457 pConfig->DeleteGroup(_T (
"/Settings/QTFonts" ));
1458 g_default_font_size = 20;
1459 g_default_font_facename = _T(
"Roboto");
1461 FontMgr::Get().Shutdown();
1464 g_bShowMuiZoomButtons =
true;
1468 pInit_Chart_Dir->Clear();
1472 pConfig->SetPath(_T (
"/Settings/WMM" ));
1473 pConfig->Write(_T (
"ShowIcon" ),
true);
1474 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1476 pConfig->SetPath(
"/Canvas/CanvasConfig1");
1477 pConfig->Write(_T (
"canvasENCShowVisibleSectorLights" ), 0);
1487 AndroidRemoveSystemFile(
1488 "/data/user/0/org.opencpn.opencpn/manPlug/libchartscale_pi.so");
1492 g_colourTrackLineColour.Set(197, 69, 195);
1496 if (!vOld.IsSameAs(vNew)) {
1502 wxChar sep = wxFileName::GetPathSeparator();
1503 if (UserIconPath.Last() != sep) UserIconPath.Append(sep);
1504 UserIconPath.Append(_T(
"UserIcons"));
1506 if (!::wxDirExists(UserIconPath)) {
1507 ::wxMkdir(UserIconPath);
1512 if (LayersPath.Last() != sep) LayersPath.Append(sep);
1513 LayersPath.Append(_T(
"layers"));
1515 if (!::wxDirExists(LayersPath)) {
1516 ::wxMkdir(LayersPath);
1522 g_CmdSoundString = wxString(OCPN_SOUND_CMD);
1523 pConfig->SetPath(_T (
"/Settings" ));
1524 pConfig->Write(_T(
"CmdSoundString" ), g_CmdSoundString);
1528 g_bAIS_GCPA_Alert_Audio =
true;
1529 g_bAIS_SART_Alert_Audio =
true;
1530 g_bAIS_DSC_Alert_Audio =
true;
1533 g_maintoolbar_x = -1;
1537 std::vector<std::string> TCDS_temp;
1538 for (
unsigned int i = 0; i < TideCurrentDataSet.size(); i++)
1539 TCDS_temp.push_back(TideCurrentDataSet[i]);
1541 TideCurrentDataSet.clear();
1542 for (
unsigned int i = 0; i < TCDS_temp.size(); i++) {
1543 wxString tide = TCDS_temp[i];
1544 wxFileName ft(tide);
1545 if (ft.FileExists()) TideCurrentDataSet.push_back(TCDS_temp[i]);
1552 g_compatOsVersion =
"";
1553 pConfig->SetPath(_T (
"/Settings" ));
1554 pConfig->Write(_T (
"CompatOS" ), g_compatOS);
1555 pConfig->Write(_T (
"CompatOsVersion" ), g_compatOsVersion);
1559int OCPNPlatform::platformApplyPrivateSettingsString(wxString settings,
1560 ArrayOfCDI *pDirArray) {
1563 ret_val = androidApplySettingsString(settings, pDirArray);
1569void OCPNPlatform::applyExpertMode(
bool mode) {
1572 g_bBasicMenus = !mode;
1576wxString OCPNPlatform::GetSupplementalLicenseString() {
1579 lic = androidGetSupplementalLicense();
1588static wxString ExpandPaths(wxString paths,
OCPNPlatform *platform);
1590int OCPNPlatform::DoFileSelectorDialog(wxWindow *parent, wxString *file_spec,
1591 wxString Title, wxString initDir,
1592 wxString suggestedName,
1593 wxString wildcard) {
1595 int result = wxID_CANCEL;
1599 wxString idir = initDir;
1600 if (initDir.StartsWith(
1604 result = androidFileChooser(&file, idir, Title, suggestedName, wildcard);
1605 if (file_spec) *file_spec = file;
1607 long flag = wxFD_DEFAULT_STYLE;
1608 if (suggestedName.Length()) {
1612 wxString mask = wildcard;
1613 if (wxNOT_FOUND != mask.Find(_T(
"gpx")))
1614 mask.Prepend(_T(
"GPX files (*.gpx)|"));
1616 wxFileDialog *psaveDialog =
1617 new wxFileDialog(parent, Title, initDir, suggestedName, mask, flag);
1625 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
1628 result = psaveDialog->ShowModal();
1631 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
1634 if (file_spec) *file_spec = psaveDialog->GetPath();
1642int OCPNPlatform::DoDirSelectorDialog(wxWindow *parent, wxString *file_spec,
1643 wxString Title, wxString initDir,
1646 int result = wxID_CANCEL;
1650 wxString idir = initDir;
1651 if (initDir.StartsWith(
1655 result = androidFileChooser(&dir, idir, Title, _T(
""), _T(
""),
true,
1657 if (file_spec) *file_spec = dir;
1659 wxDirDialog *dirSelector =
new wxDirDialog(
1660 parent, Title, initDir, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1663 dirSelector->SetFont(*qFont);
1670 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
1673 result = dirSelector->ShowModal();
1676 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
1679 if (result == wxID_CANCEL) {
1682 *file_spec = dirSelector->GetPath();
1692MyConfig *OCPNPlatform::GetConfigObject() {
1695 result =
new MyConfig(GetConfigFileName());
1704bool OCPNPlatform::hasInternalGPS(wxString profile) {
1706 bool t = androidDeviceHasGPS();
1720void OCPNPlatform::ShowBusySpinner(
void) {
1721 AbstractPlatform::ShowBusySpinner();
1724void OCPNPlatform::HideBusySpinner(
void) {
1725 AbstractPlatform::HideBusySpinner();
1728double OCPNPlatform::GetDisplayDensityFactor() {
1730 return getAndroidDisplayDensity();
1736long OCPNPlatform::GetDefaultToolbarOrientation() {
1738 return wxTB_VERTICAL;
1740 return wxTB_VERTICAL;
1744int OCPNPlatform::GetStatusBarFieldCount() {
1750 wxFont *templateFont = FontMgr::Get().
GetFont(_(
"StatusBar"), 0);
1751 dc.SetFont(*templateFont);
1754 dc.GetTextExtent(_T(
"WWWWWW"), &width, NULL, NULL, NULL, templateFont);
1755 double font_size_pix = (double)width / 6.0;
1759 double nChars = dispSize.x / font_size_pix;
1769 return STAT_FIELD_COUNT;
1773double OCPNPlatform::getFontPointsperPixel(
void) {
1774 double pt_per_pixel = 1.0;
1784 if (m_pt_per_pixel == 0) {
1789 12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, FALSE,
1790 wxString(_T (
"" )), wxFONTENCODING_SYSTEM);
1794 dc.GetTextExtent(_T(
"H"), &width, &height, NULL, NULL, f);
1796 if (height > 0) m_pt_per_pixel = 12.0 / (double)height;
1798 if (m_pt_per_pixel > 0) pt_per_pixel = m_pt_per_pixel;
1801 return pt_per_pixel;
1806 return getAndroidDisplayDimensions();
1808 return wxSize(g_monitor_info[g_current_monitor].width,
1809 g_monitor_info[g_current_monitor].height);
1814 if (g_current_monitor < m_displaySizeMMOverride.size()) {
1815 if (m_displaySizeMMOverride[g_current_monitor] > 0) {
1816 return m_displaySizeMMOverride[g_current_monitor];
1820 double ret = g_monitor_info[g_current_monitor].width_mm;
1823 ret = GetAndroidDisplaySize();
1829double OCPNPlatform::GetDisplayAreaCM2() {
1834 ratio = (double)sz.x / (
double)sz.y;
1836 ratio = (double)sz.y / (
double)sz.x;
1838 double area = size1 * (size1 * ratio) / 100.;
1844 if (monitor < m_displaySizeMMOverride.size()) {
1845 m_displaySizeMMOverride[monitor] = sizeMM;
1849double OCPNPlatform::GetDisplayDPmm() {
1851 return getAndroidDPmm();
1858unsigned int OCPNPlatform::GetSelectRadiusPix() {
1859 return GetDisplayDPmm() *
1860 (g_btouch ? g_selection_radius_touch_mm : g_selection_radius_mm);
1863bool OCPNPlatform::GetFullscreen() {
1866 bret = androidGetFullscreen();
1874bool OCPNPlatform::SetFullscreen(
bool bFull) {
1877 bret = androidSetFullscreen(bFull);
1884void OCPNPlatform::PositionAISAlert(wxWindow *alert_window) {
1887 alert_window->SetSize(g_ais_alert_dialog_x, g_ais_alert_dialog_y,
1888 g_ais_alert_dialog_sx, g_ais_alert_dialog_sy);
1892 alert_window->Centre();
1898wxDirDialog *OCPNPlatform::AdjustDirDialogFont(wxWindow *container,
1900 wxDirDialog *ret_dlg = dlg;
1904 dlg->SetSize(container->GetSize());
1907 wxSize sds = dlg->GetSize();
1908 wxSize ss = container->GetSize();
1913 wxString msg = dlg->GetMessage();
1914 wxString default_dir = dlg->GetPath();
1918 ret_dlg =
new wxDirDialog(NULL, msg, default_dir,
1919 wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1922 wxFont *smallFont =
new wxFont(*dialogFont);
1923 smallFont->SetPointSize((smallFont->GetPointSize() / 2) +
1925 ret_dlg->SetFont(*smallFont);
1927 ret_dlg->SetSize(container->GetSize());
1935wxFileDialog *OCPNPlatform::AdjustFileDialogFont(wxWindow *container,
1936 wxFileDialog *dlg) {
1937 wxFileDialog *ret_dlg = dlg;
1941 dlg->SetSize(container->GetSize());
1944 wxSize sds = dlg->GetSize();
1945 wxSize ss = container->GetSize();
1950 wxString msg = dlg->GetMessage();
1951 wxString default_dir = dlg->GetDirectory();
1952 wxString default_file = dlg->GetFilename();
1953 wxString wildcard = dlg->GetWildcard();
1957 ret_dlg =
new wxFileDialog(NULL, msg, default_dir, default_file, wildcard,
1961 wxFont *smallFont =
new wxFont(*dialogFont);
1962 smallFont->SetPointSize((smallFont->GetPointSize() / 2) +
1964 ret_dlg->SetFont(*smallFont);
1966 ret_dlg->SetSize(container->GetSize());
1974double OCPNPlatform::GetToolbarScaleFactor(
int GUIScaleFactor) {
1982 wxSize style_tool_size(32, 32);
1984 if (g_StyleManager) {
1986 if (style) style_tool_size = style->GetToolSize();
1988 double tool_size = style_tool_size.x;
1994 double premult = 1.0;
1995 if (g_config_display_size_manual && g_config_display_size_mm[0] > 0) {
1996 double target_size = 9.0;
1998 double basic_tool_size_mm = tool_size / GetDisplayDPmm();
1999 premult = target_size / basic_tool_size_mm;
2002 premult = wxMax(45 * getAndroidDisplayDensity(), 45) /
2008 double postmult = exp(GUIScaleFactor * (log(2.0) / 5.0));
2012 rv = premult * postmult;
2013 rv = wxMin(rv, getAndroidDisplayDensity() *
2017 double premult = 1.0;
2022 wxSize style_tool_size = style->GetToolSize();
2023 double tool_size = style_tool_size.x;
2027 double target_size = 9.0;
2029 double basic_tool_size_mm = tool_size / GetDisplayDPmm();
2030 premult = target_size / basic_tool_size_mm;
2034 double postmult = exp(GUIScaleFactor * (0.693 / 5.0));
2036 rv = premult * postmult;
2037 rv = wxMin(rv, 3.0);
2038 rv = wxMax(rv, 0.5);
2047double OCPNPlatform::GetCompassScaleFactor(
int GUIScaleFactor) {
2057 wxSize style_tool_size = style->GetToolSize();
2058 double compass_size = style_tool_size.x;
2064 double premult = wxMax(28 * getAndroidDisplayDensity(), 50) / compass_size;
2067 double postmult = exp(GUIScaleFactor * (log(2.0) / 5.0));
2070 rv = premult * postmult;
2071 rv = wxMin(rv, getAndroidDisplayDensity() *
2076 double premult = 1.0;
2080 wxSize style_tool_size = style->GetToolSize();
2081 double compass_size = style_tool_size.x;
2084 double target_size = 6.0;
2086 double basic_tool_size_mm = compass_size / GetDisplayDPmm();
2087 premult = target_size / basic_tool_size_mm;
2090 double postmult = exp(GUIScaleFactor * (0.693 / 5.0));
2092 rv = premult * postmult;
2094 rv = wxMin(rv, 3.0);
2095 rv = wxMax(rv, 0.5);
2097#if defined(__WXOSX__) || defined(__WXGTK3__)
2099 if (gFrame) rv *= gFrame->GetContentScaleFactor();
2109float OCPNPlatform::GetChartScaleFactorExp(
float scale_linear) {
2110 double factor = 1.0;
2112 factor = exp(scale_linear * (log(3.0) / 5.0));
2117 factor = exp(scale_linear * (0.693 / 5.0));
2121 factor = wxMax(factor, .5);
2122 factor = wxMin(factor, 6.);
2127float OCPNPlatform::GetMarkScaleFactorExp(
float scale_linear) {
2128 if (scale_linear <= 0)
2129 return GetChartScaleFactorExp(scale_linear);
2131 return GetChartScaleFactorExp(scale_linear - 1);
2148bool OCPNPlatform::hasInternalBT(wxString profile) {
2150 bool t = androidDeviceHasBlueTooth();
2159bool OCPNPlatform::startBluetoothScan() {
2161 return androidStartBluetoothScan();
2168bool OCPNPlatform::stopBluetoothScan() {
2170 return androidStopBluetoothScan();
2177wxArrayString OCPNPlatform::getBluetoothScanResults() {
2178 wxArrayString ret_val;
2180 return androidGetBluetoothScanResults();
2183 ret_val.Add(_T(
"line 1"));
2184 ret_val.Add(_T(
"line 2"));
2185 ret_val.Add(_T(
"line 3"));
2195bool OCPNPlatform::AllowAlertDialog(
const wxString &class_name) {
2200 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
2202 wxWindow *win = node->GetData();
2203 if (win->IsShown()) nTLW++;
2205 node = node->GetNext();
2210 return (g_running && !g_options->IsShown() && (nTLW <= 4));
2212 return (g_running && (nTLW <= 4));
2219void OCPNPlatform::setChartTypeMaskSel(
int mask, wxString &indicator) {
2221 return androidSetChartTypeMaskSel(mask, indicator);
2226QString g_qtStyleSheet;
2228bool LoadQtStyleSheet(wxString &sheet_file) {
2229 if (wxFileExists(sheet_file)) {
2232 QString file(sheet_file.c_str());
2234 File.open(QFile::ReadOnly);
2235 g_qtStyleSheet = QLatin1String(File.readAll());
2245QString getQtStyleSheet(
void) {
return g_qtStyleSheet; }
2249bool OCPNPlatform::isPlatformCapable(
int flag) {
2253 if (flag == PLATFORM_CAP_PLUGINS) {
2255 wxString tsdk(android_plat_spc.msdk);
2256 if (tsdk.ToLong(&platver)) {
2257 if (platver >= 11)
return true;
2259 }
else if (flag == PLATFORM_CAP_FASTPAN) {
2261 wxString tsdk(android_plat_spc.msdk);
2262 if (tsdk.ToLong(&platver)) {
2263 if (platver >= 14)
return true;
2271void OCPNPlatform::platformLaunchDefaultBrowser(wxString URL) {
2273 androidLaunchBrowser(URL);
2275 ::wxLaunchDefaultBrowser(URL);
2285EVT_PAINT(OCPNColourPickerCtrl::OnPaint)
2294 const wxColour &initial,
2296 const wxSize &size,
long style,
2297 const wxValidator &validator,
2298 const wxString &name) {
2299 Create(parent,
id, initial, pos, size, style, validator, name);
2302bool OCPNColourPickerCtrl::Create(wxWindow *parent, wxWindowID
id,
2303 const wxColour &col,
const wxPoint &pos,
2304 const wxSize &size,
long style,
2305 const wxValidator &validator,
2306 const wxString &name) {
2307 m_bitmap = wxBitmap(60, 13);
2310 if (!wxBitmapButton::Create(parent,
id, m_bitmap, pos, size,
2311 style | wxBU_AUTODRAW, validator, name)) {
2312 wxFAIL_MSG(wxT(
"OCPNColourPickerCtrl creation failed"));
2317 Connect(GetId(), wxEVT_BUTTON,
2318 wxCommandEventHandler(OCPNColourPickerCtrl::OnButtonClick), NULL,
2328void OCPNColourPickerCtrl::InitColourData() {
2330 ms_data.SetChooseFull(
true);
2331 unsigned char grey = 0;
2332 for (
int i = 0; i < 16; i++, grey += 16)
2335 wxColour colour(grey, grey, grey);
2336 ms_data.SetCustomColour(i, colour);
2341void OCPNColourPickerCtrl::OnButtonClick(wxCommandEvent &WXUNUSED(ev)) {
2343 unsigned int cco = 0;
2346 cco |= m_colour.Red();
2348 cco |= m_colour.Green();
2350 cco |= m_colour.Blue();
2351 unsigned int cc = androidColorPicker(cco);
2354 unsigned char blue = (
unsigned char)cc % 256;
2355 unsigned char green = (
unsigned char)(cc >> 8) % 256;
2357 unsigned char red = (
unsigned char)(cc >> 16) % 256;
2358 cnew.Set(red, green, blue);
2364 ms_data.SetColour(m_colour);
2367 wxColourDialog dlg(
this, &ms_data);
2368 if (dlg.ShowModal() == wxID_OK) {
2369 ms_data = dlg.GetColourData();
2370 SetColour(ms_data.GetColour());
2375void OCPNColourPickerCtrl::UpdateColour() {
2377 SetBitmapLabel(wxBitmap());
2380 wxMemoryDC dc(m_bitmap);
2381 dc.SetPen(*wxTRANSPARENT_PEN);
2382 dc.SetBrush(wxBrush(m_colour));
2383 dc.DrawRectangle(0, 0, m_bitmap.GetWidth(), m_bitmap.GetHeight());
2385 dc.SelectObject(wxNullBitmap);
2386 SetBitmapLabel(m_bitmap);
2389void OCPNColourPickerCtrl::SetColour(wxColour &c) {
2391 m_bitmap = wxBitmap(GetSize().x - 20, GetSize().y - 20);
2395wxColour OCPNColourPickerCtrl::GetColour(
void) {
return m_colour; }
2397wxSize OCPNColourPickerCtrl::DoGetBestSize()
const {
2398 wxSize sz(wxBitmapButton::DoGetBestSize());
2405 if (HasFlag(wxCLRP_SHOW_LABEL))
return sz;
2413void OCPNColourPickerCtrl::OnPaint(wxPaintEvent &event) {
2416 int offset_x = (GetSize().x - m_bitmap.GetWidth()) / 2;
2417 int offset_y = (GetSize().y - m_bitmap.GetHeight()) / 2;
2419 dc.SetPen(*wxTRANSPARENT_PEN);
2420 dc.SetBrush(wxBrush(m_colour));
2421 dc.DrawRectangle(offset_x, offset_y, m_bitmap.GetWidth(),
2422 m_bitmap.GetHeight());
bool g_bresponsive
Flag to control adaptive UI scaling.
Class AisDecoder and helpers.
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.
void cache_clear()
Remove all files in cache:
Miscellaneous utilities, many of which string related.
Plugin installation and data paths support.
wxString GetWritableDocumentsDir(void)
Returns the platform-specific default documents directory.