30 #include <wx/wxprec.h>
55 #include <wx/apptrait.h>
56 #include <wx/stdpaths.h>
57 #include <wx/filename.h>
58 #include <wx/tokenzr.h>
59 #include <wx/textfile.h>
60 #include <wx/jsonval.h>
61 #include <wx/jsonreader.h>
65 #include "model/ais_decoder.h"
67 #include "model/base_platform.h"
69 #include "model/config_vars.h"
70 #include "model/conn_params.h"
71 #include "model/cutil.h"
72 #include "model/logger.h"
73 #include "model/ocpn_utils.h"
74 #include "model/plugin_paths.h"
75 #include "model/select.h"
77 #include "AboutFrameImpl.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
100 #include "CrashRpt.h"
106 #ifdef LINUX_CRASHRPT
107 #include "crashprint.h"
111 #include "model/macutils.h"
114 #if (defined(OCPN_GHC_FILESYSTEM) || (defined(__clang_major__) && (__clang_major__ < 15)))
116 #include <ghc/filesystem.hpp>
117 namespace fs = ghc::filesystem;
119 #include <filesystem>
121 namespace fs = std::filesystem;
127 void appendOSDirSlash(wxString *pString);
130 struct sigaction sa_all;
131 struct sigaction sa_all_old;
132 extern sigjmp_buf env;
136 extern bool g_bFirstRun;
137 extern bool g_bUpgradeInProcess;
146 extern bool g_bshowToolbar;
147 extern bool g_bexpert;
148 extern bool g_bBasicMenus;
149 extern bool g_bUIexpert;
151 extern bool g_bshowToolbar;
152 extern bool g_bBasicMenus;
154 extern bool g_bShowOutlines;
155 extern int g_nAWDefault;
157 extern bool g_bPermanentMOBIcon;
158 extern float g_toolbar_scalefactor;
161 extern bool g_boptionsactive;
163 extern wxString *pInit_Chart_Dir;
165 extern std::vector<size_t> g_config_display_size_mm;
166 extern bool g_config_display_size_manual;
168 extern bool g_bFullScreenQuilt;
169 extern bool g_bQuiltEnable;
170 extern bool g_bskew_comp;
172 extern bool g_bopengl;
173 extern bool g_bresponsive;
174 extern bool g_bShowStatusBar;
175 extern int g_cm93_zoom_factor;
176 extern int g_GUIScaleFactor;
177 extern bool g_fog_overzoom;
178 extern bool g_oz_vector_scale;
179 extern wxString g_toolbarConfig;
180 extern bool g_bPreserveScaleOnX;
181 extern bool g_running;
182 extern bool g_bEnableZoomToCursor;
183 extern bool g_bsmoothpanzoom;
184 extern bool g_bShowMenuBar;
191 extern int g_default_font_size;
192 extern wxString g_default_font_facename;
194 bool g_bEmailCrashReport;
196 extern double g_ChartNotRenderScaleFactor;
197 extern bool g_bRollover;
199 #if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
200 extern wxLocale *plocale_def_lang;
202 extern wxString g_locale;
203 extern wxString g_localeOverride;
204 extern wxArrayString g_locale_catalog_array;
207 extern int options_lastPage;
209 extern about *g_pAboutDlgLegacy;
210 extern wxColour g_colourTrackLineColour;
211 extern int g_n_ownship_min_mm;
213 extern int g_AndroidVersionCode;
214 extern bool g_bShowMuiZoomButtons;
215 extern int g_FlushNavobjChangesTimeout;
216 extern wxString g_CmdSoundString;
217 extern int g_maintoolbar_x;
218 extern int g_maintoolbar_y;
219 extern std::vector<std::string> TideCurrentDataSet;
220 extern int g_Android_SDK_Version;
221 extern wxString g_androidDownloadDirectory;
222 extern wxString g_gpx_path;
233 static const char *
const DEFAULT_XDG_DATA_DIRS =
234 "~/.local/share:/usr/local/share:/usr/share";
237 static const char PATH_SEP =
';';
239 static const char PATH_SEP =
':';
242 static bool checkIfFlatpacked() {
244 if (!wxGetEnv(
"FLATPAK_ID", &
id)) {
247 return id ==
"org.opencpn.OpenCPN";
251 OCPNPlatform::OCPNPlatform() {
253 m_bdisableWindowsDisplayEnum =
false;
254 m_monitorWidth = m_monitorHeight = 0;
256 for (
size_t i = 0; i < g_monitor_info.size(); i++) {
257 m_displaySizeMMOverride.push_back(0);
259 m_pluginDataPath =
"";
262 OCPNPlatform::~OCPNPlatform() {
274 int MyNewHandler(
size_t size) {
276 throw std::bad_alloc();
297 void catch_signals(
int signo) {
328 #ifdef OCPN_USE_CRASHREPORT
330 int CALLBACK CrashCallback(CR_CRASH_CALLBACK_INFO *pInfo) {
331 wxLog::GetActiveTarget()->Flush();
332 return CR_CB_DODEFAULT;
337 void OCPNPlatform::Initialize_1(
void) {
338 #ifdef OCPN_USE_CRASHREPORT
342 CR_INSTALL_INFO info;
343 memset(&info, 0,
sizeof(CR_INSTALL_INFO));
344 info.cb =
sizeof(CR_INSTALL_INFO);
345 info.pszAppName = _T(
"OpenCPN");
347 info.pszAppVersion = wxString(VERSION_FULL).c_str();
349 int type = MiniDumpNormal;
352 type |= MiniDumpWithDataSegs;
363 info.uMiniDumpType = (MINIDUMP_TYPE)type;
366 info.dwFlags = CR_INST_ALL_POSSIBLE_HANDLERS;
369 info.dwFlags &= ~CR_INST_NEW_OPERATOR_ERROR_HANDLER;
372 info.dwFlags |= CR_INST_ALLOW_ATTACH_MORE_FILES;
375 info.dwFlags |= CR_INST_SHOW_ADDITIONAL_INFO_FIELDS;
379 if (g_bEmailCrashReport) {
380 info.pszUrl = _T(
"https://bigdumboat.com/crashrpt/ocpn_crashrpt.php");
381 info.uPriorities[CR_HTTP] = 3;
383 info.dwFlags |= CR_INST_DONT_SEND_REPORT;
384 info.uPriorities[CR_HTTP] = CR_NEGATIVE_PRIORITY;
387 info.uPriorities[CR_SMTP] =
388 CR_NEGATIVE_PRIORITY;
389 info.uPriorities[CR_SMAPI] =
390 CR_NEGATIVE_PRIORITY;
392 wxStandardPaths &crash_std_path = g_Platform->GetStdPaths();
394 wxString crash_rpt_save_locn = crash_std_path.GetConfigDir();
396 wxFileName exec_path_crash(crash_std_path.GetExecutablePath());
397 crash_rpt_save_locn =
398 exec_path_crash.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
401 wxString locn = crash_rpt_save_locn + _T(
"\\CrashReports");
403 if (!wxDirExists(locn)) wxMkdir(locn);
405 if (wxDirExists(locn)) {
406 wxCharBuffer buf = locn.ToUTF8();
408 if (buf && (locn.Length() <
sizeof(wlocn))) {
409 MultiByteToWideChar(0, 0, buf.data(), -1, wlocn,
sizeof(wlocn) - 1);
410 info.pszErrorReportSaveDir = (LPCWSTR)wlocn;
415 wxFileName exec_path_crash(crash_std_path.GetExecutablePath());
416 wxString policy_file =
417 exec_path_crash.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
418 policy_file += _T(
"PrivacyPolicy.txt");
419 policy_file.Prepend(_T(
"file:"));
421 info.pszPrivacyPolicyURL = policy_file.c_str();
424 int nResult = crInstall(&info);
427 crGetLastErrorMsg(buff, 256);
434 crSetCrashCallback(CrashCallback, NULL);
437 crAddScreenshot2(CR_AS_PROCESS_WINDOWS | CR_AS_USE_JPEG_FORMAT, 95);
440 wxString home_data_crash = crash_std_path.GetConfigDir();
442 wxFileName f(crash_std_path.GetExecutablePath());
443 home_data_crash = f.GetPath();
445 appendOSDirSlash(&home_data_crash);
447 wxString config_crash = _T(
"opencpn.ini");
448 config_crash.Prepend(home_data_crash);
449 crAddFile2(config_crash.c_str(), NULL, NULL,
450 CR_AF_MISSING_FILE_OK | CR_AF_ALLOW_DELETE);
452 wxString log_crash = _T(
"opencpn.log");
453 log_crash.Prepend(home_data_crash);
454 crAddFile2(log_crash.c_str(), NULL, NULL,
455 CR_AF_MISSING_FILE_OK | CR_AF_ALLOW_DELETE);
460 #ifdef LINUX_CRASHRPT
461 #if wxUSE_ON_FATAL_EXCEPTION
463 wxHandleFatalExceptions(
true);
469 _set_new_handler(MyNewHandler);
479 HANDLE hProc = GetCurrentProcess();
483 DuplicateHandle( hProc, hProc, hProc, &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS );
486 GetProcessAffinityMask( hDup, &procMask, &sysMask );
490 if( ( procMask & 1 ) == 1 ) newMask = 1;
492 if( ( procMask & 2 ) == 2 ) newMask = 2;
494 if( ( procMask & 4 ) == 4 ) newMask = 4;
496 if( ( procMask & 8 ) == 8 ) newMask = 8;
499 BOOL res = SetProcessAffinityMask( hDup, (DWORD_PTR) newMask );
513 wxPlatformInfo Platform;
514 if (Platform.GetOperatingSystemId() == wxOS_WINDOWS_9X)
515 SetUnhandledExceptionFilter(&MyUnhandledExceptionFilter);
526 sa_all.sa_handler = catch_signals;
527 sigemptyset(&sa_all.sa_mask);
533 sigaction(SIGUSR1, NULL,
537 sigaction(SIGUSR1, &sa_all, NULL);
538 sigaction(SIGUSR1, NULL,
541 sigaction(SIGTERM, &sa_all, NULL);
542 sigaction(SIGTERM, NULL, &sa_all_old);
544 sigaction(SIGHUP, &sa_all, NULL);
545 sigaction(SIGHUP, NULL, &sa_all_old);
550 qDebug() <<
"Initialize_1()";
561 void OCPNPlatform::Initialize_2(
void) {
563 wxLogMessage(androidGetDeviceInfo());
567 wxChar sep = wxFileName::GetPathSeparator();
570 if (ChartDir.Last() != sep) ChartDir.Append(sep);
571 ChartDir.Append(
"Charts");
572 if (!::wxDirExists(ChartDir)) {
577 if (GRIBDir.Last() != sep) GRIBDir.Append(sep);
578 GRIBDir.Append(
"GRIBS");
579 if (!::wxDirExists(GRIBDir)) {
584 if (g_Android_SDK_Version >= 30){
585 if (!g_gpx_path.StartsWith(androidGetDownloadDirectory())){
586 g_gpx_path = androidGetDownloadDirectory();
593 g_toolbar_scalefactor = GetToolbarScaleFactor(g_GUIScaleFactor);
595 if (!configdir.DirExists()) {
596 if (!configdir.Mkdir()) {
597 auto msg = std::string(
"Cannot create config directory: ");
598 wxLogWarning(msg + configdir.GetFullPath());
605 void OCPNPlatform::Initialize_3(
void) {
606 bool bcapable = IsGLCapable();
612 bool bAndroid =
false;
621 g_bdisable_opengl =
false;
622 pConfig->UpdateSettings();
630 if ((g_bFirstRun || g_bUpgradeInProcess || bAndroid) && bcapable) {
634 g_GLOptions.m_bUseAcceleratedPanning =
true;
635 g_GLOptions.m_bTextureCompression =
true;
636 g_GLOptions.m_bTextureCompressionCaching =
true;
638 g_GLOptions.m_iTextureDimension = 512;
639 g_GLOptions.m_iTextureMemorySize = 64;
641 g_GLOptions.m_GLPolygonSmoothing =
true;
642 g_GLOptions.m_GLLineSmoothing =
true;
646 gFrame->SetGPSCompassScale();
654 if (g_bFirstRun || g_bUpgradeInProcess) {
656 g_bRollover = g_btouch ? false :
true;
659 g_FlushNavobjChangesTimeout = 300;
663 void OCPNPlatform::Initialize_4(
void) {
665 if (pSelect) pSelect->SetSelectPixelRadius(wxMax(25, 6.0 * getAndroidDPmm()));
667 pSelectTC->SetSelectPixelRadius(wxMax(25, 6.0 * getAndroidDPmm()));
669 pSelectAIS->SetSelectPixelRadius(wxMax(25, 6.0 * getAndroidDPmm()));
676 options_lastPage = 1;
680 void OCPNPlatform::OnExit_1(
void) {}
682 void OCPNPlatform::OnExit_2(
void) {
683 #ifdef OCPN_USE_CRASHREPORT
694 bool HasGLExt(wxJSONValue &glinfo,
const std::string ext) {
695 if (!glinfo.HasMember(
"GL_EXTENSIONS")) {
698 for (
int i = 0; i < glinfo[
"GL_EXTENSIONS"].Size(); i++) {
699 if (glinfo[
"GL_EXTENSIONS"][i].AsString() == ext) {
706 bool OCPNPlatform::BuildGLCaps(
void *pbuf) {
708 fs::path ep(GetExePath().ToStdString());
710 std::string gl_util_exe =
"opencpn-glutil";
712 std::string gl_util_exe =
"opencpn-glutil.exe";
714 fs::path gl_util_path = ep.parent_path().append(gl_util_exe);
716 if (!fs::exists(gl_util_path)) {
717 wxLogMessage(
"OpenGL test utility not found at %s.", gl_util_path.c_str());
721 std::string gl_json = fs::path(
GetPrivateDataDir().ToStdString()).append(
"gl_caps.json").string();
723 wxString cmd = wxString::Format(
"\"%s\" opengl-info \"%s\"", 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);
740 if (reader.GetErrorCount() > 0){
741 wxLogMessage(
"Failed to parse JSON output from OpenGL test utility.");
742 for(
const auto &l : reader.GetErrors()) {
750 if(root.HasMember(
"GL_RENDERER")) {
751 pcaps->Renderer = root[
"GL_RENDERER"].AsString();
753 wxLogMessage(
"GL_RENDERER not found.");
756 if (root.HasMember(
"GL_VERSION")) {
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.");
768 if(root.HasMember(
"GL_USABLE")) {
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(root,
"GL_ARB_vertex_buffer_object");
814 wxGLContext *pctx =
new wxGLContext(tcanvas);
815 tcanvas->SetCurrent(*pctx);
819 char *str = (
char *)glGetString(GL_RENDERER);
821 wxLogMessage(
"GL_RENDERER not found.");
826 pcaps->Renderer = std::string(str);
828 char *stv = (
char *)glGetString(GL_VERSION);
830 wxLogMessage(
"GL_VERSION not found");
835 pcaps->Version = std::string(stv);
837 char *stsv = (
char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
839 wxLogMessage(
"GL_SHADING_LANGUAGE_VERSION not found");
844 pcaps->GLSL_Version = std::string(stsv);
846 pcaps->dGLSL_Version = 0;
847 pcaps->dGLSL_Version = ::atof(pcaps->GLSL_Version.c_str());
849 if (pcaps->dGLSL_Version < 1.2){
851 msg.Printf(_T(
"GLCaps Probe: OpenGL-> GLSL Version reported: "));
852 msg += wxString(pcaps->GLSL_Version.c_str());
853 msg +=
"\n OpenGL disabled due to insufficient OpenGL capabilities";
855 pcaps->bCanDoGLSL =
false;
861 pcaps->bCanDoGLSL =
true;
863 if (QueryExtension(
"GL_ARB_texture_non_power_of_two"))
864 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
865 else if (QueryExtension(
"GL_OES_texture_npot"))
866 pcaps->TextureRectangleFormat = GL_TEXTURE_2D;
867 else if (QueryExtension(
"GL_ARB_texture_rectangle"))
868 pcaps->TextureRectangleFormat = GL_TEXTURE_RECTANGLE_ARB;
870 pcaps->bOldIntel =
false;
873 pcaps->bCanDoVBO =
true;
875 #if defined(__WXMSW__) || defined(__WXOSX__)
876 if (pcaps->bOldIntel) pcaps->bCanDoVBO =
false;
880 pcaps->bCanDoVBO =
false;
884 pcaps->bCanDoFBO =
true;
888 if (!pcaps->TextureRectangleFormat) pcaps->bCanDoFBO =
false;
891 if (!QueryExtension(
"GL_EXT_framebuffer_object")) pcaps->bCanDoFBO =
false;
901 bool OCPNPlatform::IsGLCapable() {
910 if(g_bdisable_opengl)
913 wxLogMessage(
"Starting OpenGL test...");
914 wxLog::FlushActive();
918 bool bcaps = BuildGLCaps(GL_Caps);
920 wxLogMessage(
"OpenGL test complete.");
922 wxLogMessage(
"BuildGLCaps fails.");
923 wxLog::FlushActive();
931 if (!GL_Caps->bCanDoGLSL) {
937 if (!GL_Caps->bCanDoFBO) {
942 wxLogMessage(
"OpenGL determined CAPABLE.");
943 wxLog::FlushActive();
945 g_bdisable_opengl =
false;
949 pConfig->UpdateSettings();
958 void OCPNPlatform::SetLocaleSearchPrefixes(
void) {
961 #if defined(__WINDOWS__)
964 wxString locale_location = GetSharedDataDir();
965 locale_location += _T(
"share\\locale");
966 wxLocale::AddCatalogLookupPathPrefix(locale_location);
967 wxString imsg = _T(
"Adding catalog lookup path: ");
968 imsg += locale_location;
974 usrShare.RemoveLastDir();
975 locale_location = usrShare.GetFullPath() + (
"share\\locale");
976 wxLocale::AddCatalogLookupPathPrefix(locale_location);
977 imsg = _T(
"Adding catalog lookup path: ");
978 imsg += locale_location;
981 #elif defined(__ANDROID__)
983 wxString locale_location = GetSharedDataDir() + _T(
"locale");
984 wxLocale::AddCatalogLookupPathPrefix(locale_location);
986 #elif defined(__UNIX__) && !defined(__WINE__)
991 wxString locale_location;
992 if (!wxGetEnv(_T(
"OPENCPN_PREFIX"), &locale_location)) {
993 locale_location = _T(
"/usr/local");
996 location.AssignDir(locale_location);
997 location.AppendDir(_T(
"share"));
998 location.SetName(_T(
"locale"));
999 locale_location = location.GetFullPath();
1000 wxLocale::AddCatalogLookupPathPrefix(locale_location);
1004 wxString managed_locale_location(dir +
"/locale");
1005 wxLocale::AddCatalogLookupPathPrefix(managed_locale_location);
1009 std::string macDir =
1011 "/Library/Application Support/OpenCPN/Contents/Resources";
1012 wxString Mac_managed_locale_location(macDir);
1013 wxLocale::AddCatalogLookupPathPrefix(Mac_managed_locale_location);
1019 wxString OCPNPlatform::GetDefaultSystemLocale() {
1020 wxLogMessage(_T(
"Getting DefaultSystemLocale..."));
1022 wxString retval = _T(
"en_US");
1026 const wxLanguageInfo *languageInfo =
1027 wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
1028 if (languageInfo) retval = languageInfo->CanonicalName;
1030 #if defined(__WXMSW__)
1031 LANGID lang_id = GetUserDefaultUILanguage();
1034 const wxLanguageInfo *languageInfoW = 0;
1035 if (0 != GetLocaleInfo(MAKELCID(lang_id, SORT_DEFAULT), LOCALE_SENGLANGUAGE,
1037 wxString lstring = wxString(lngcp);
1039 languageInfoW = wxLocale::FindLanguageInfo(lngcp);
1041 wxLogMessage(_T(
"Found LanguageInfo for: ") + lstring);
1043 wxLogMessage(_T(
"Could not find LanguageInfo for: ") + lstring);
1045 wxLogMessage(_T(
"Could not get LocaleInfo, using wxLANGUAGE_DEFAULT"));
1046 languageInfoW = wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
1049 if (languageInfoW) retval = languageInfoW->CanonicalName;
1052 #if defined(__ANDROID__)
1053 retval = androidGetAndroidSystemLocale();
1061 #if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1062 wxString OCPNPlatform::GetAdjustedAppLocale() {
1063 wxString adjLocale = g_locale;
1068 #if defined(__WXMSW__)
1069 if (g_bFirstRun || wxIsEmpty(adjLocale)) {
1070 wxRegKey RegKey(wxString(_T(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenCPN")));
1071 if (RegKey.Exists()) {
1073 _T(
"Retrieving initial language selection from Windows Registry"));
1074 RegKey.QueryValue(wxString(_T(
"InstallerLanguage")), adjLocale);
1077 if (wxIsEmpty(adjLocale)) {
1078 if (g_localeOverride.Length())
1079 adjLocale = g_localeOverride;
1081 adjLocale = GetDefaultSystemLocale();
1084 #if defined(__ANDROID__)
1085 if (g_localeOverride.Length())
1086 adjLocale = g_localeOverride;
1088 adjLocale = GetDefaultSystemLocale();
1094 wxString OCPNPlatform::ChangeLocale(wxString &newLocaleID,
1095 wxLocale *presentLocale,
1096 wxLocale **newLocale) {
1097 wxString return_val;
1099 wxString imsg = _T(
"ChangeLocale: Language load for: ");
1100 imsg += newLocaleID;
1104 delete (wxLocale *)presentLocale;
1106 wxLocale *locale =
new wxLocale;
1107 if (isFlatpacked()) {
1108 std::string path(getenv(
"HOME"));
1109 path +=
"/.var/app/org.opencpn.OpenCPN/data/locale";
1110 locale->AddCatalogLookupPathPrefix(path);
1111 wxLogMessage(
"Using flatpak locales at %s", path.c_str());
1113 wxString loc_lang_canonical;
1115 const wxLanguageInfo *pli = wxLocale::FindLanguageInfo(newLocaleID);
1116 bool b_initok =
false;
1119 locale->Init(pli->Language, 1);
1123 if (!locale->IsOk()) {
1124 wxString imsg = _T(
"ChangeLocale: could not initialize: ");
1125 imsg += newLocaleID;
1129 locale =
new wxLocale;
1130 locale->Init(pli->Language, 0);
1132 loc_lang_canonical = pli->CanonicalName;
1134 b_initok = locale->IsOk();
1141 wxString imsg = _T(
"ChangeLocale: Fall back to en_US");
1145 locale =
new wxLocale;
1146 locale->Init(wxLANGUAGE_ENGLISH_US, 0);
1147 loc_lang_canonical =
1148 wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US)->CanonicalName;
1152 wxString imsg = _T(
"ChangeLocale: Locale Init OK for: ");
1153 imsg += loc_lang_canonical;
1165 for (
unsigned int i = 0; i < g_locale_catalog_array.GetCount(); i++) {
1166 if(!locale->AddCatalog(g_locale_catalog_array[i])){
1167 wxString emsg = _T(
"ERROR Loading translation catalog for: ");
1168 emsg += g_locale_catalog_array[i];
1172 wxString imsg = _T(
"Loaded translation catalog for: ");
1173 imsg += g_locale_catalog_array[i];
1179 wxLogMessage(_T(
"Loading catalog for opencpn core."));
1180 locale->AddCatalog(_T(
"opencpn"));
1182 return_val = locale->GetCanonicalName();
1185 if (return_val != GetDefaultSystemLocale())
1186 g_localeOverride = return_val;
1188 g_localeOverride = _T(
"");
1191 *newLocale = locale;
1194 setlocale(LC_NUMERIC,
"C");
1205 void OCPNPlatform::SetDefaultOptions(
void) {
1207 g_bShowOutlines =
true;
1213 g_MarkLost_Mins = 8;
1214 g_bRemoveLost =
true;
1215 g_RemoveLost_Mins = 10;
1218 g_bSyncCogPredictors =
false;
1219 g_bHideMoored =
false;
1220 g_ShowMoored_Kts = 0.2;
1221 g_SOGminCOG_kts = 0.2;
1222 g_bTrackDaily =
false;
1224 g_bFullScreenQuilt =
true;
1225 g_bQuiltEnable =
true;
1226 g_bskew_comp =
false;
1227 g_bShowAreaNotices =
false;
1228 g_bDrawAISSize =
false;
1229 g_bDrawAISRealtime =
false;
1230 g_AIS_RealtPred_Kts = 0.7;
1231 g_bShowAISName =
false;
1232 g_nTrackPrecision = 2;
1233 g_bPreserveScaleOnX =
true;
1236 gps_watchdog_timeout_ticks = GPS_TIMEOUT_SECONDS;
1237 g_n_ownship_min_mm = 8;
1238 g_bShowMuiZoomButtons =
true;
1239 g_bresponsive =
false;
1243 pConfig->SetPath(_T (
"/Settings/GlobalState" ));
1244 pConfig->Write(_T (
"bShowS57Text" ),
true);
1245 pConfig->Write(_T (
"bShowS57ImportantTextOnly" ),
false);
1246 pConfig->Write(_T (
"nDisplayCategory" ), (
int)(_DisCat)STANDARD);
1247 pConfig->Write(_T (
"nSymbolStyle" ), (
int)(_LUPname)PAPER_CHART);
1248 pConfig->Write(_T (
"nBoundaryStyle" ), (
int)(_LUPname)PLAIN_BOUNDARIES);
1250 pConfig->Write(_T (
"bShowSoundg" ),
true);
1251 pConfig->Write(_T (
"bShowMeta" ),
false);
1252 pConfig->Write(_T (
"bUseSCAMIN" ),
true);
1253 pConfig->Write(_T (
"bShowAtonText" ),
false);
1254 pConfig->Write(_T (
"bShowLightDescription" ),
false);
1255 pConfig->Write(_T (
"bExtendLightSectors" ),
true);
1256 pConfig->Write(_T (
"bDeClutterText" ),
true);
1257 pConfig->Write(_T (
"bShowNationalText" ),
true);
1259 pConfig->Write(_T (
"S52_MAR_SAFETY_CONTOUR" ), 3);
1260 pConfig->Write(_T (
"S52_MAR_SHALLOW_CONTOUR" ), 2);
1261 pConfig->Write(_T (
"S52_MAR_DEEP_CONTOUR" ), 6);
1262 pConfig->Write(_T (
"S52_MAR_TWO_SHADES" ), 0);
1263 pConfig->Write(_T (
"S52_DEPTH_UNIT_SHOW" ), 1);
1265 pConfig->Write(_T (
"ZoomDetailFactorVector" ), 3);
1267 pConfig->Write(_T (
"nColorScheme" ), 1);
1271 g_bEnableZoomToCursor =
true;
1272 g_bsmoothpanzoom =
true;
1273 g_bShowMenuBar =
true;
1281 pConfig->SetPath(_T (
"/PlugIns/chartdldr_pi.dll" ));
1282 pConfig->Write(_T (
"bEnabled" ),
true);
1284 pConfig->SetPath(_T (
"/PlugIns/wmm_pi.dll" ));
1285 pConfig->Write(_T (
"bEnabled" ),
true);
1287 pConfig->SetPath(_T (
"/Settings/WMM" ));
1288 pConfig->Write(_T (
"ShowIcon" ),
true);
1289 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1296 pConfig->SetPath(_T (
"/PlugIns/libchartdldr_pi.dylib" ));
1297 pConfig->Write(_T (
"bEnabled" ),
true);
1299 pConfig->SetPath(_T (
"/PlugIns/libwmm_pi.dylib" ));
1300 pConfig->Write(_T (
"bEnabled" ),
true);
1302 pConfig->SetPath(_T (
"/Settings/WMM" ));
1303 pConfig->Write(_T (
"ShowIcon" ),
true);
1304 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1311 pConfig->SetPath(_T (
"/PlugIns/libchartdldr_pi.so" ));
1312 pConfig->Write(_T (
"bEnabled" ),
true);
1314 pConfig->SetPath(_T (
"/PlugIns/libwmm_pi.so" ));
1315 pConfig->Write(_T (
"bEnabled" ),
true);
1317 pConfig->SetPath(_T (
"/Settings/WMM" ));
1318 pConfig->Write(_T (
"ShowIcon" ),
true);
1319 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1327 g_GLOptions.m_bTextureCompression = 1;
1328 g_GLOptions.m_bTextureCompressionCaching = 1;
1331 qDebug() <<
"SetDefaultOptions";
1334 g_bresponsive =
true;
1335 g_default_font_size = 18;
1338 g_bShowStatusBar =
true;
1339 g_cm93_zoom_factor = 0;
1340 g_oz_vector_scale =
false;
1341 g_fog_overzoom =
false;
1344 g_bShowMuiZoomButtons =
true;
1346 g_GUIScaleFactor = 0;
1347 g_ChartNotRenderScaleFactor = 2.0;
1351 g_toolbarConfig = _T(
"X.....XX.......XX.XXXXXXXXXXX");
1352 g_bPermanentMOBIcon =
false;
1354 wxString sGPS = _T(
"2;3;;0;0;;0;1;0;0;;0;;1;0;0;0;0");
1357 new_params->bEnabled =
true;
1358 TheConnectionParams()->Add(new_params);
1360 g_default_font_facename = _T(
"Roboto");
1365 pConfig->SetPath(_T (
"/PlugIns/libchartdldr_pi.so" ));
1366 pConfig->Write(_T (
"bEnabled" ),
true);
1368 pConfig->SetPath(_T (
"/PlugIns/libwmm_pi.so" ));
1369 pConfig->Write(_T (
"bEnabled" ),
true);
1371 pConfig->SetPath(_T (
"/Settings/WMM" ));
1372 pConfig->Write(_T (
"ShowIcon" ),
true);
1373 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1375 pConfig->SetPath(_T (
"/PlugIns/libgrib_pi.so" ));
1376 pConfig->Write(_T (
"bEnabled" ),
true);
1378 pConfig->SetPath(_T (
"/PlugIns/libdashboard_pi.so" ));
1379 pConfig->Write(_T (
"bEnabled" ),
true);
1381 pConfig->SetPath(_T (
"/PlugIns/GRIB" ));
1382 pConfig->Write(_T (
"GRIBCtrlBarPosX" ), 100);
1383 pConfig->Write(_T (
"GRIBCtrlBarPosY" ), 0);
1385 pConfig->SetPath(_T (
"/Settings/GRIB" ));
1386 pConfig->Write(_T (
"CursorDataShown" ), 0);
1390 pConfig->SetPath(_T (
"/PlugIns/liboesenc_pi.so" ));
1391 pConfig->Write(_T (
"bEnabled" ),
true);
1393 pConfig->SetPath(_T (
"/Settings/QTFonts" ));
1396 wxString str = _T(
"en_US-b25a3899");
1397 wxString pval = _T(
"StatusBar:Roboto,26,-1,5,75,0,0,0,0,0:rgb(0, 0, 0)");
1398 pConfig->Write(str, pval);
1399 FontMgr::Get().LoadFontNative(&str, &pval);
1402 str = _T(
"en_US-9c3b3a0d");
1403 pval = _T(
"DialogStatusBar:Roboto,18,-1,5,50,0,0,0,0,0:rgb(0, 0, 0)");
1404 pConfig->Write(str, pval);
1405 FontMgr::Get().LoadFontNative(&str, &pval);
1408 pConfig->SetPath(_T (
"/Settings/Others" ));
1409 pConfig->Write(_T(
"TrackLineColour"), _T(
"#C545C3"));
1410 g_colourTrackLineColour.Set(197, 69, 195);
1412 qDebug() <<
"SetDefaultOptions.Config";
1423 void OCPNPlatform::SetUpgradeOptions(wxString vNew, wxString vOld) {
1426 qDebug() <<
"Upgrade check"
1427 <<
"from: " << vOld.mb_str() <<
" to: " << vNew.mb_str();
1429 if (androidGetVersionCode() > g_AndroidVersionCode) {
1430 qDebug() <<
"Upgrade detected"
1431 <<
"from VC: " << g_AndroidVersionCode
1432 <<
" to VC: " << androidGetVersionCode();
1436 pConfig->SetPath(_T (
"/Settings/GlobalState" ));
1437 pConfig->Write(_T (
"bShowS57Text" ),
true);
1440 g_ChartNotRenderScaleFactor = 2.0;
1441 g_n_ownship_min_mm = 8;
1442 g_toolbarConfig = _T(
"X.....XX.......XX.XXXXXXXXXXX");
1445 pConfig->DeleteGroup(_T (
"/Settings/QTFonts" ));
1446 g_default_font_size = 20;
1447 g_default_font_facename = _T(
"Roboto");
1449 FontMgr::Get().Shutdown();
1452 g_bShowMuiZoomButtons =
true;
1456 pInit_Chart_Dir->Clear();
1458 pConfig->SetPath(_T (
"/Settings/WMM" ));
1459 pConfig->Write(_T (
"ShowIcon" ),
true);
1460 pConfig->Write(_T (
"ShowLiveIcon" ),
true);
1464 g_colourTrackLineColour.Set(197, 69, 195);
1474 if (!vOld.IsSameAs(vNew)) {
1480 wxChar sep = wxFileName::GetPathSeparator();
1481 if (UserIconPath.Last() != sep) UserIconPath.Append(sep);
1482 UserIconPath.Append(_T(
"UserIcons"));
1484 if (!::wxDirExists(UserIconPath)) {
1485 ::wxMkdir(UserIconPath);
1490 if (LayersPath.Last() != sep) LayersPath.Append(sep);
1491 LayersPath.Append(_T(
"layers"));
1493 if (!::wxDirExists(LayersPath)) {
1494 ::wxMkdir(LayersPath);
1500 g_CmdSoundString = wxString(OCPN_SOUND_CMD);
1501 pConfig->SetPath(_T (
"/Settings" ));
1502 pConfig->Write(_T(
"CmdSoundString" ), g_CmdSoundString);
1506 g_bAIS_GCPA_Alert_Audio =
true;
1507 g_bAIS_SART_Alert_Audio =
true;
1508 g_bAIS_DSC_Alert_Audio =
true;
1511 g_maintoolbar_x = -1;
1515 std::vector<std::string> TCDS_temp;
1516 for (
unsigned int i=0; i < TideCurrentDataSet.size() ; i++)
1517 TCDS_temp.push_back(TideCurrentDataSet[i]);
1519 TideCurrentDataSet.clear();
1520 for (
unsigned int i=0; i < TCDS_temp.size() ; i++){
1521 wxString tide = TCDS_temp[i];
1522 wxFileName ft(tide);
1523 if (ft.FileExists())
1524 TideCurrentDataSet.push_back(TCDS_temp[i]);
1529 int OCPNPlatform::platformApplyPrivateSettingsString(wxString settings,
1530 ArrayOfCDI *pDirArray) {
1533 ret_val = androidApplySettingsString(settings, pDirArray);
1539 void OCPNPlatform::applyExpertMode(
bool mode) {
1542 g_bBasicMenus = !mode;
1546 wxString OCPNPlatform::GetSupplementalLicenseString() {
1549 lic = androidGetSupplementalLicense();
1559 static wxString ExpandPaths(wxString paths,
OCPNPlatform *platform);
1562 int OCPNPlatform::DoFileSelectorDialog(wxWindow *parent, wxString *file_spec,
1563 wxString Title, wxString initDir,
1564 wxString suggestedName,
1565 wxString wildcard) {
1567 int result = wxID_CANCEL;
1571 wxString idir = initDir;
1572 if (initDir.StartsWith(
1574 idir = GetWritableDocumentsDir();
1576 result = androidFileChooser(&file, idir, Title, suggestedName, wildcard);
1577 if (file_spec) *file_spec = file;
1579 long flag = wxFD_DEFAULT_STYLE;
1580 if (suggestedName.Length()) {
1584 wxString mask = wildcard;
1585 if (wxNOT_FOUND != mask.Find(_T(
"gpx")))
1586 mask.Prepend(_T(
"GPX files (*.gpx)|"));
1588 wxFileDialog *psaveDialog =
1589 new wxFileDialog(parent, Title, initDir, suggestedName, mask, flag);
1597 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
1600 result = psaveDialog->ShowModal();
1603 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
1606 if (file_spec) *file_spec = psaveDialog->GetPath();
1614 int OCPNPlatform::DoDirSelectorDialog(wxWindow *parent, wxString *file_spec,
1615 wxString Title, wxString initDir,
1618 int result = wxID_CANCEL;
1622 wxString idir = initDir;
1623 if (initDir.StartsWith(
1625 idir = GetWritableDocumentsDir();
1627 result = androidFileChooser(&dir, idir, Title, _T(
""), _T(
""),
true,
1629 if (file_spec) *file_spec = dir;
1631 wxDirDialog *dirSelector =
new wxDirDialog(
1632 parent, Title, initDir, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1634 wxFont *qFont = GetOCPNScaledFont(_(
"Dialog"));
1635 dirSelector->SetFont(*qFont);
1642 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
1645 result = dirSelector->ShowModal();
1648 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
1651 if (result == wxID_CANCEL) {
1654 *file_spec = dirSelector->GetPath();
1664 MyConfig *OCPNPlatform::GetConfigObject() {
1667 result =
new MyConfig(GetConfigFileName());
1676 bool OCPNPlatform::hasInternalGPS(wxString profile) {
1678 bool t = androidDeviceHasGPS();
1692 void OCPNPlatform::ShowBusySpinner(
void) {
1693 AbstractPlatform::ShowBusySpinner();
1696 void OCPNPlatform::HideBusySpinner(
void) {
1697 AbstractPlatform::HideBusySpinner();
1700 double OCPNPlatform::GetDisplayDensityFactor() {
1702 return getAndroidDisplayDensity();
1708 long OCPNPlatform::GetDefaultToolbarOrientation() {
1710 return wxTB_VERTICAL;
1712 return wxTB_VERTICAL;
1716 int OCPNPlatform::GetStatusBarFieldCount() {
1722 wxFont *templateFont = FontMgr::Get().GetFont(_(
"StatusBar"), 0);
1723 dc.SetFont(*templateFont);
1726 dc.GetTextExtent(_T(
"WWWWWW"), &width, NULL, NULL, NULL, templateFont);
1727 double font_size_pix = (double)width / 6.0;
1729 wxSize dispSize = getDisplaySize();
1731 double nChars = dispSize.x / font_size_pix;
1741 return STAT_FIELD_COUNT;
1745 double OCPNPlatform::getFontPointsperPixel(
void) {
1746 double pt_per_pixel = 1.0;
1756 if (m_pt_per_pixel == 0) {
1760 wxFont *f = FontMgr::Get().FindOrCreateFont(
1761 12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, FALSE,
1762 wxString(_T (
"" )), wxFONTENCODING_SYSTEM);
1766 dc.GetTextExtent(_T(
"H"), &width, &height, NULL, NULL, f);
1768 if (height > 0) m_pt_per_pixel = 12.0 / (double)height;
1770 if (m_pt_per_pixel > 0) pt_per_pixel = m_pt_per_pixel;
1773 return pt_per_pixel;
1776 wxSize OCPNPlatform::getDisplaySize() {
1778 return getAndroidDisplayDimensions();
1780 return wxSize(g_monitor_info[g_current_monitor].width,
1781 g_monitor_info[g_current_monitor].height);
1785 double OCPNPlatform::GetDisplaySizeMM() {
1786 if (g_current_monitor < m_displaySizeMMOverride.size()) {
1787 if (m_displaySizeMMOverride[g_current_monitor] > 0) {
1788 return m_displaySizeMMOverride[g_current_monitor];
1792 double ret = g_monitor_info[g_current_monitor].width_mm;
1795 ret = GetAndroidDisplaySize();
1801 double OCPNPlatform::GetDisplayAreaCM2() {
1802 double size1 = GetDisplaySizeMM();
1803 wxSize sz = getDisplaySize();
1806 ratio = (double)sz.x / (
double)sz.y;
1808 ratio = (double)sz.y / (
double)sz.x;
1810 double area = size1 * (size1 * ratio) / 100.;
1815 void OCPNPlatform::SetDisplaySizeMM(
size_t monitor,
double sizeMM) {
1816 if (monitor < m_displaySizeMMOverride.size()) {
1817 m_displaySizeMMOverride[monitor] = sizeMM;
1821 double OCPNPlatform::GetDisplayDPmm() {
1823 return getAndroidDPmm();
1825 double r = getDisplaySize().x;
1826 return r / GetDisplaySizeMM();
1830 unsigned int OCPNPlatform::GetSelectRadiusPix() {
1831 return GetDisplayDPmm() *
1832 (g_btouch ? g_selection_radius_touch_mm : g_selection_radius_mm);
1835 bool OCPNPlatform::GetFullscreen() {
1838 bret = androidGetFullscreen();
1846 bool OCPNPlatform::SetFullscreen(
bool bFull) {
1849 bret = androidSetFullscreen(bFull);
1856 void OCPNPlatform::PositionAISAlert(wxWindow *alert_window) {
1859 alert_window->SetSize(g_ais_alert_dialog_x, g_ais_alert_dialog_y,
1860 g_ais_alert_dialog_sx, g_ais_alert_dialog_sy);
1864 alert_window->Centre();
1870 wxDirDialog *OCPNPlatform::AdjustDirDialogFont(wxWindow *container,
1872 wxDirDialog *ret_dlg = dlg;
1876 dlg->SetSize(container->GetSize());
1879 wxSize sds = dlg->GetSize();
1880 wxSize ss = container->GetSize();
1885 wxString msg = dlg->GetMessage();
1886 wxString default_dir = dlg->GetPath();
1890 ret_dlg =
new wxDirDialog(NULL, msg, default_dir,
1891 wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1893 wxFont *dialogFont = GetOCPNScaledFont(_(
"Dialog"));
1894 wxFont *smallFont =
new wxFont(*dialogFont);
1895 smallFont->SetPointSize((smallFont->GetPointSize() / 2) +
1897 ret_dlg->SetFont(*smallFont);
1899 ret_dlg->SetSize(container->GetSize());
1907 wxFileDialog *OCPNPlatform::AdjustFileDialogFont(wxWindow *container,
1908 wxFileDialog *dlg) {
1909 wxFileDialog *ret_dlg = dlg;
1913 dlg->SetSize(container->GetSize());
1916 wxSize sds = dlg->GetSize();
1917 wxSize ss = container->GetSize();
1922 wxString msg = dlg->GetMessage();
1923 wxString default_dir = dlg->GetDirectory();
1924 wxString default_file = dlg->GetFilename();
1925 wxString wildcard = dlg->GetWildcard();
1929 ret_dlg =
new wxFileDialog(NULL, msg, default_dir, default_file, wildcard,
1932 wxFont *dialogFont = GetOCPNScaledFont(_(
"Dialog"));
1933 wxFont *smallFont =
new wxFont(*dialogFont);
1934 smallFont->SetPointSize((smallFont->GetPointSize() / 2) +
1936 ret_dlg->SetFont(*smallFont);
1938 ret_dlg->SetSize(container->GetSize());
1946 double OCPNPlatform::GetToolbarScaleFactor(
int GUIScaleFactor) {
1954 wxSize style_tool_size(32, 32);
1956 if (g_StyleManager) {
1958 if (style) style_tool_size = style->GetToolSize();
1960 double tool_size = style_tool_size.x;
1966 double premult = 1.0;
1967 if (g_config_display_size_manual && g_config_display_size_mm[0] > 0) {
1968 double target_size = 9.0;
1970 double basic_tool_size_mm = tool_size / GetDisplayDPmm();
1971 premult = target_size / basic_tool_size_mm;
1974 premult = wxMax(45 * getAndroidDisplayDensity(), 45) /
1980 double postmult = exp(GUIScaleFactor * (log(2.0) / 5.0));
1984 rv = premult * postmult;
1985 rv = wxMin(rv, getAndroidDisplayDensity() *
1989 double premult = 1.0;
1991 if (g_bresponsive) {
1994 wxSize style_tool_size = style->GetToolSize();
1995 double tool_size = style_tool_size.x;
1999 double target_size = 9.0;
2001 double basic_tool_size_mm = tool_size / GetDisplayDPmm();
2002 premult = target_size / basic_tool_size_mm;
2006 double postmult = exp(GUIScaleFactor * (0.693 / 5.0));
2008 rv = premult * postmult;
2009 rv = wxMin(rv, 3.0);
2010 rv = wxMax(rv, 0.5);
2012 rv /= g_BasePlatform->GetDisplayDIPMult(gFrame);
2019 double OCPNPlatform::GetCompassScaleFactor(
int GUIScaleFactor) {
2026 if (g_bresponsive) {
2029 wxSize style_tool_size = style->GetToolSize();
2030 double compass_size = style_tool_size.x;
2036 double premult = wxMax(28 * getAndroidDisplayDensity(), 50) / compass_size;
2039 double postmult = exp(GUIScaleFactor * (log(2.0) / 5.0));
2042 rv = premult * postmult;
2043 rv = wxMin(rv, getAndroidDisplayDensity() *
2048 double premult = 1.0;
2050 if (g_bresponsive) {
2052 wxSize style_tool_size = style->GetToolSize();
2053 double compass_size = style_tool_size.x;
2056 double target_size = 6.0;
2058 double basic_tool_size_mm = compass_size / GetDisplayDPmm();
2059 premult = target_size / basic_tool_size_mm;
2062 double postmult = exp(GUIScaleFactor * (0.693 / 5.0));
2064 rv = premult * postmult;
2066 rv = wxMin(rv, 3.0);
2067 rv = wxMax(rv, 0.5);
2069 #if defined(__WXOSX__) || defined(__WXGTK3__)
2072 rv *= gFrame->GetContentScaleFactor();
2075 rv /= g_BasePlatform->GetDisplayDIPMult(gFrame);
2082 float 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.);
2100 float OCPNPlatform::GetMarkScaleFactorExp(
float scale_linear) {
2101 if(scale_linear <= 0)
2102 return GetChartScaleFactorExp(scale_linear);
2104 return GetChartScaleFactorExp(scale_linear-1);
2121 bool OCPNPlatform::hasInternalBT(wxString profile) {
2123 bool t = androidDeviceHasBlueTooth();
2132 bool OCPNPlatform::startBluetoothScan() {
2134 return androidStartBluetoothScan();
2141 bool OCPNPlatform::stopBluetoothScan() {
2143 return androidStopBluetoothScan();
2150 wxArrayString 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"));
2168 bool 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();
2182 return (g_running && !g_boptionsactive && (nTLW <= 4));
2189 void OCPNPlatform::setChartTypeMaskSel(
int mask, wxString &indicator) {
2191 return androidSetChartTypeMaskSel(mask, indicator);
2196 QString g_qtStyleSheet;
2198 bool LoadQtStyleSheet(wxString &sheet_file) {
2199 if (wxFileExists(sheet_file)) {
2202 QString file(sheet_file.c_str());
2204 File.open(QFile::ReadOnly);
2205 g_qtStyleSheet = QLatin1String(File.readAll());
2215 QString getQtStyleSheet(
void) {
return g_qtStyleSheet; }
2220 bool OCPNPlatform::isPlatformCapable(
int flag) {
2224 if (flag == PLATFORM_CAP_PLUGINS) {
2226 wxString tsdk(android_plat_spc.msdk);
2227 if (tsdk.ToLong(&platver)) {
2228 if (platver >= 11)
return true;
2230 }
else if (flag == PLATFORM_CAP_FASTPAN) {
2232 wxString tsdk(android_plat_spc.msdk);
2233 if (tsdk.ToLong(&platver)) {
2234 if (platver >= 14)
return true;
2242 void OCPNPlatform::DoHelpDialog(
void) {
2247 g_pAboutDlg->SetFocus();
2249 g_pAboutDlg->Show();
2252 if (!g_pAboutDlgLegacy)
2253 g_pAboutDlgLegacy =
new about(gFrame, GetSharedDataDir());
2255 g_pAboutDlgLegacy->SetFocus();
2256 g_pAboutDlgLegacy->Show();
2261 void OCPNPlatform::LaunchLocalHelp(
void) {
2263 androidLaunchHelpView();
2265 wxString def_lang_canonical = _T(
"en_US");
2268 if (plocale_def_lang)
2269 def_lang_canonical = plocale_def_lang->GetCanonicalName();
2272 wxString help_locn = g_Platform->GetSharedDataDir() + _T(
"doc/help_");
2274 wxString help_try = help_locn + def_lang_canonical + _T(
".html");
2276 if (!::wxFileExists(help_try)) {
2277 help_try = help_locn + _T(
"en_US") + _T(
".html");
2279 if (!::wxFileExists(help_try)) {
2280 help_try = help_locn + _T(
"web") + _T(
".html");
2283 if (!::wxFileExists(help_try))
return;
2286 wxLaunchDefaultBrowser(wxString(_T(
"file:///")) + help_try);
2290 void OCPNPlatform::platformLaunchDefaultBrowser(wxString URL) {
2292 androidLaunchBrowser(URL);
2294 ::wxLaunchDefaultBrowser(URL);
2304 EVT_PAINT(OCPNColourPickerCtrl::OnPaint)
2313 const wxColour &initial,
2315 const wxSize &size,
long style,
2316 const wxValidator &validator,
2317 const wxString &name) {
2318 Create(parent,
id, initial, pos, size, style, validator, name);
2321 bool OCPNColourPickerCtrl::Create(wxWindow *parent, wxWindowID
id,
2322 const wxColour &col,
const wxPoint &pos,
2323 const wxSize &size,
long style,
2324 const wxValidator &validator,
2325 const wxString &name) {
2326 m_bitmap = wxBitmap(60, 13);
2329 if (!wxBitmapButton::Create(parent,
id, m_bitmap, pos, size,
2330 style | wxBU_AUTODRAW, validator, name)) {
2331 wxFAIL_MSG(wxT(
"OCPNColourPickerCtrl creation failed"));
2336 Connect(GetId(), wxEVT_BUTTON,
2337 wxCommandEventHandler(OCPNColourPickerCtrl::OnButtonClick), NULL,
2347 void OCPNColourPickerCtrl::InitColourData() {
2349 ms_data.SetChooseFull(
true);
2350 unsigned char grey = 0;
2351 for (
int i = 0; i < 16; i++, grey += 16)
2354 wxColour colour(grey, grey, grey);
2355 ms_data.SetCustomColour(i, colour);
2360 void OCPNColourPickerCtrl::OnButtonClick(wxCommandEvent &WXUNUSED(ev)) {
2362 unsigned int cco = 0;
2365 cco |= m_colour.Red();
2367 cco |= m_colour.Green();
2369 cco |= m_colour.Blue();
2370 unsigned int cc = androidColorPicker(cco);
2373 unsigned char blue = (
unsigned char)cc % 256;
2374 unsigned char green = (
unsigned char)(cc >> 8) % 256;
2376 unsigned char red = (
unsigned char)(cc >> 16) % 256;
2377 cnew.Set(red, green, blue);
2383 ms_data.SetColour(m_colour);
2386 wxColourDialog dlg(
this, &ms_data);
2387 if (dlg.ShowModal() == wxID_OK) {
2388 ms_data = dlg.GetColourData();
2389 SetColour(ms_data.GetColour());
2394 void OCPNColourPickerCtrl::UpdateColour() {
2396 SetBitmapLabel(wxBitmap());
2399 wxMemoryDC dc(m_bitmap);
2400 dc.SetPen(*wxTRANSPARENT_PEN);
2401 dc.SetBrush(wxBrush(m_colour));
2402 dc.DrawRectangle(0, 0, m_bitmap.GetWidth(), m_bitmap.GetHeight());
2404 dc.SelectObject(wxNullBitmap);
2405 SetBitmapLabel(m_bitmap);
2408 void OCPNColourPickerCtrl::SetColour(wxColour &c) {
2410 m_bitmap = wxBitmap(GetSize().x - 20, GetSize().y - 20);
2414 wxColour OCPNColourPickerCtrl::GetColour(
void) {
return m_colour; }
2416 wxSize OCPNColourPickerCtrl::DoGetBestSize()
const {
2417 wxSize sz(wxBitmapButton::DoGetBestSize());
2424 if (HasFlag(wxCLRP_SHOW_LABEL))
return sz;
2432 void OCPNColourPickerCtrl::OnPaint(wxPaintEvent &event) {
2435 int offset_x = (GetSize().x - m_bitmap.GetWidth()) / 2;
2436 int offset_y = (GetSize().y - m_bitmap.GetHeight()) / 2;
2438 dc.SetPen(*wxTRANSPARENT_PEN);
2439 dc.SetBrush(wxBrush(m_colour));
2440 dc.DrawRectangle(offset_x, offset_y, m_bitmap.GetWidth(),
2441 m_bitmap.GetHeight());
Global state for AIS decoder.
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.
Global variables reflecting command line options and arguments.
General purpose GUI support.