OpenCPN Partial API docs
Loading...
Searching...
No Matches
navutil.cpp
1/***************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: Navigation Utility Functions
5 * Author: David Register
6 *
7 ***************************************************************************
8 * Copyright (C) 2010 by David S. Register *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24 **************************************************************************/
25
26#include <wx/wxprec.h>
27
28#ifdef __MINGW32__
29#undef IPV6STRICT // mingw FTBS fix: missing struct ip_mreq
30#include <windows.h>
31#endif
32
33#include <stdlib.h>
34#include <time.h>
35#include <locale>
36#include <list>
37
38#ifndef WX_PRECOMP
39#include <wx/wx.h>
40#endif // precompiled headers
41
42#include <wx/bmpcbox.h>
43#include <wx/dir.h>
44#include <wx/filename.h>
45#include <wx/graphics.h>
46#include <wx/image.h>
47#include <wx/listbook.h>
48#include <wx/listimpl.cpp>
49#include <wx/progdlg.h>
50#include <wx/sstream.h>
51#include <wx/tglbtn.h>
52#include <wx/timectrl.h>
53#include <wx/tokenzr.h>
54
55#include "model/ais_decoder.h"
57#include "model/cmdline.h"
58#include "model/config_vars.h"
59#include "model/conn_params.h"
60#include "model/cutil.h"
61#include "model/geodesic.h"
62#include "model/georef.h"
63#include "model/idents.h"
64#include "model/multiplexer.h"
65#include "model/nav_object_database.h"
66#include "model/navutil_base.h"
67#include "model/own_ship.h"
68#include "model/plugin_comm.h"
69#include "model/route.h"
70#include "model/routeman.h"
71#include "model/select.h"
72#include "model/track.h"
73
74#include "ais.h"
75#include "CanvasConfig.h"
76#include "chartbase.h"
77#include "chartdb.h"
78#include "chcanv.h"
79#include "cm93.h"
80#include "config.h"
81#include "ConfigMgr.h"
82#include "displays.h"
83#include "dychart.h"
84#include "FontMgr.h"
85#include "Layer.h"
86#include "navutil.h"
87#include "nmea0183.h"
88#include "observable_globvar.h"
89#include "ocpndc.h"
90#include "ocpn_frame.h"
91#include "ocpn_plugin.h"
92#include "OCPNPlatform.h"
93#include "OCPN_Sound.h"
94#include "s52plib.h"
95#include "s52utils.h"
96#include "snd_config.h"
97#include "styles.h"
98
99#ifdef ocpnUSE_GL
100#include "glChartCanvas.h"
101#endif
102
103#ifdef __ANDROID__
104#include "androidUTIL.h"
105#endif
106
107// Statics
108
109extern OCPNPlatform *g_Platform;
110extern MyFrame *gFrame;
111
112extern double g_ChartNotRenderScaleFactor;
113extern int g_restore_stackindex;
114extern int g_restore_dbindex;
115extern RouteList *pRouteList;
116extern std::vector<Track *> g_TrackList;
117extern LayerList *pLayerList;
118extern MyConfig *pConfig;
119extern double vLat, vLon;
120extern double kLat, kLon;
121extern ColorScheme global_color_scheme;
122extern int g_nbrightness;
123extern bool g_bShowStatusBar;
124extern bool g_bUIexpert;
125extern bool g_bFullscreen;
126
127extern wxString g_SENCPrefix;
128extern wxString g_UserPresLibData;
129
130extern wxString *pInit_Chart_Dir;
131extern wxString gWorldMapLocation;
132extern wxString gWorldShapefileLocation;
133
134extern bool s_bSetSystemTime;
135extern bool g_bDisplayGrid; // Flag indicating if grid is to be displayed
136extern bool g_bPlayShipsBells;
137extern int g_iSoundDeviceIndex;
138extern bool g_bFullscreenToolbar;
139extern bool g_bShowLayers;
140extern bool g_bTransparentToolbar;
141extern bool g_bPermanentMOBIcon;
142
143extern bool g_bShowDepthUnits;
144extern bool g_bAutoAnchorMark;
145extern bool g_bskew_comp;
146extern bool g_bopengl;
147extern bool g_bSoftwareGL;
148extern bool g_bsmoothpanzoom;
149extern bool g_fog_overzoom;
150extern double g_overzoom_emphasis_base;
151extern bool g_oz_vector_scale;
152extern double g_plus_minus_zoom_factor;
153extern bool g_bShowOutlines;
154extern bool g_bShowActiveRouteHighway;
155extern bool g_bShowRouteTotal;
156extern int g_nAWDefault;
157extern int g_nAWMax;
158extern bool g_btenhertz;
159extern bool g_declutter_anchorage;
160
161extern int g_nframewin_x;
162extern int g_nframewin_y;
163extern int g_nframewin_posx;
164extern int g_nframewin_posy;
165extern bool g_bframemax;
166
167extern wxString g_VisibleLayers;
168extern wxString g_InvisibleLayers;
169extern wxString g_VisiNameinLayers;
170extern wxString g_InVisiNameinLayers;
171
172extern wxArrayString *pMessageOnceArray;
173
174// LIVE ETA OPTION
175extern bool g_bShowLiveETA;
176extern double g_defaultBoatSpeed;
177extern double g_defaultBoatSpeedUserUnit;
178
179extern bool g_bUseOnlyConfirmedAISName;
180extern int g_ScaledNumWeightSOG;
181
182extern int g_S57_dialog_sx, g_S57_dialog_sy;
183int g_S57_extradialog_sx, g_S57_extradialog_sy;
184
185extern int g_iNavAidRadarRingsNumberVisible;
186extern bool g_bNavAidRadarRingsShown;
187extern float g_fNavAidRadarRingsStep;
188extern int g_pNavAidRadarRingsStepUnits;
189extern bool g_bWayPointPreventDragging;
190extern bool g_bConfirmObjectDelete;
191extern wxColour g_colourOwnshipRangeRingsColour;
192
193extern bool g_bEnableZoomToCursor;
194extern wxString g_toolbarConfig;
195extern double g_TrackIntervalSeconds;
196
197extern int g_nCacheLimit;
198extern int g_memCacheLimit;
199
200extern bool g_bGDAL_Debug;
201extern bool g_bDebugCM93;
202extern bool g_bDebugS57;
203
204extern double g_ownship_predictor_minutes;
205extern int g_cog_predictor_style;
206extern wxString g_cog_predictor_color;
207extern int g_cog_predictor_endmarker;
208extern int g_cog_predictor_width;
209extern int g_ownship_HDTpredictor_style;
210extern wxString g_ownship_HDTpredictor_color;
211extern int g_ownship_HDTpredictor_endmarker;
212extern int g_ownship_HDTpredictor_width;
213extern double g_ownship_HDTpredictor_miles;
214
215extern bool g_own_ship_sog_cog_calc;
216extern int g_own_ship_sog_cog_calc_damp_sec;
217
218extern bool g_bShowMenuBar;
219extern bool g_bShowCompassWin;
220
221extern s52plib *ps52plib;
222
223extern int g_cm93_zoom_factor;
224extern bool g_b_legacy_input_filter_behaviour;
225extern bool g_bShowDetailSlider;
226extern int g_detailslider_dialog_x, g_detailslider_dialog_y;
227
228extern bool g_bUseGreenShip;
229
230extern int g_OwnShipmmsi;
231extern int g_OwnShipIconType;
232extern double g_n_ownship_length_meters;
233extern double g_n_ownship_beam_meters;
234extern double g_n_gps_antenna_offset_y;
235extern double g_n_gps_antenna_offset_x;
236extern int g_n_ownship_min_mm;
237extern int g_maxzoomin;
238
239extern bool g_bShowShipToActive;
240extern int g_shipToActiveStyle;
241extern int g_shipToActiveColor;
242
243extern bool g_bPreserveScaleOnX;
244extern bool g_bsimplifiedScalebar;
245
246extern bool g_bUseGLL;
247
248extern wxString g_locale;
249extern wxString g_localeOverride;
250
251extern bool g_bCourseUp;
252extern bool g_bLookAhead;
253extern int g_COGAvgSec;
254extern bool g_bShowChartBar;
255
256extern int g_MemFootMB;
257
258extern wxString g_AW1GUID;
259extern wxString g_AW2GUID;
260extern int g_BSBImgDebug;
261
262extern int n_NavMessageShown;
263extern wxString g_config_version_string;
264
265extern wxString g_CmdSoundString;
266
267extern bool g_bDebugGPSD;
268
269int g_navobjbackups;
270
271extern bool g_bQuiltEnable;
272extern bool g_bFullScreenQuilt;
273extern bool g_bQuiltStart;
274
275extern int g_SkewCompUpdatePeriod;
276
277extern int g_maintoolbar_x;
278extern int g_maintoolbar_y;
279extern long g_maintoolbar_orient;
280
281extern int g_lastClientRectx;
282extern int g_lastClientRecty;
283extern int g_lastClientRectw;
284extern int g_lastClientRecth;
285
286extern bool g_bHighliteTracks;
287extern int g_cog_predictor_width;
288extern int g_ais_cog_predictor_width;
289
290extern wxColour g_colourTrackLineColour;
291extern wxString g_default_wp_icon;
292
293extern ChartGroupArray *g_pGroupArray;
294
295extern bool g_bDebugOGL;
296extern int g_tcwin_scale;
297extern wxString g_uploadConnection;
298
299extern ocpnStyle::StyleManager *g_StyleManager;
300extern std::vector<std::string> TideCurrentDataSet;
301extern wxString g_TCData_Dir;
302
303extern bool g_bresponsive;
304
305extern bool g_bGLexpert;
306
307extern int g_SENC_LOD_pixels;
308extern ArrayOfMmsiProperties g_MMSI_Props_Array;
309
310extern int g_chart_zoom_modifier_raster;
311extern int g_chart_zoom_modifier_vector;
312
313extern bool g_bShowTrackPointTime;
314
315extern bool g_bAdvanceRouteWaypointOnArrivalOnly;
316extern double g_display_size_mm;
317extern std::vector<size_t> g_config_display_size_mm;
318extern bool g_config_display_size_manual;
319
320extern bool g_benable_rotate;
321extern bool g_bEmailCrashReport;
322
323extern int g_default_font_size;
324extern wxString g_default_font_facename;
325
326extern bool g_bAutoHideToolbar;
327extern int g_nAutoHideToolbar;
328extern int g_GUIScaleFactor;
329extern int g_ChartScaleFactor;
330extern float g_MarkScaleFactorExp;
331
332extern int g_ShipScaleFactor;
333extern float g_ShipScaleFactorExp;
334extern int g_ENCSoundingScaleFactor;
335extern int g_ENCTextScaleFactor;
336
337extern int g_iENCToolbarPosX;
338extern int g_iENCToolbarPosY;
339extern bool g_bRollover;
340
341extern bool g_bSpaceDropMark;
342
343extern bool g_bShowTide;
344extern bool g_bShowCurrent;
345
346extern wxString g_uiStyle;
347extern bool g_btrackContinuous;
348extern bool g_useMUI;
349
350int g_nCPUCount;
351
352extern unsigned int g_canvasConfig;
353extern wxString g_lastAppliedTemplateGUID;
354
355extern int g_route_prop_x, g_route_prop_y;
356extern int g_route_prop_sx, g_route_prop_sy;
357extern int g_AndroidVersionCode;
358
359extern wxString g_ObjQFileExt;
360
361wxString g_gpx_path;
362bool g_bLayersLoaded;
363bool g_bShowMuiZoomButtons = true;
364
365double g_mouse_zoom_sensitivity;
366int g_mouse_zoom_sensitivity_ui;
367
368#ifdef ocpnUSE_GL
369extern ocpnGLOptions g_GLOptions;
370#endif
371
372#if !defined(NAN)
373static const long long lNaN = 0xfff8000000000000;
374#define NAN (*(double *)&lNaN)
375#endif
376
377// Layer helper function
378
379wxString GetLayerName(int id) {
380 wxString name(_T("unknown layer"));
381 if (id <= 0) return (name);
382 LayerList::iterator it;
383 int index = 0;
384 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
385 Layer *lay = (Layer *)(*it);
386 if (lay->m_LayerID == id) return (lay->m_LayerName);
387 }
388 return (name);
389}
390
391// Helper conditional file name dir slash
392void appendOSDirSlash(wxString *pString);
393
394//-----------------------------------------------------------------------------
395// MyConfig Implementation
396//-----------------------------------------------------------------------------
397//
398
399MyConfig::MyConfig(const wxString &LocalFileName)
400 : wxFileConfig(_T (""), _T (""), LocalFileName, _T (""),
401 wxCONFIG_USE_LOCAL_FILE) {
402 // Create the default NavObjectCollection FileName
403 wxFileName config_file(LocalFileName);
404 m_sNavObjSetFile =
405 config_file.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
406 m_sNavObjSetFile += _T ( "navobj.xml" );
407 m_sNavObjSetChangesFile = m_sNavObjSetFile + _T ( ".changes" );
408
409 m_pNavObjectInputSet = NULL;
410 m_pNavObjectChangesSet = NavObjectChanges::getInstance();
411}
412
413MyConfig::~MyConfig() {}
414
415void MyConfig::CreateRotatingNavObjBackup() {
416 // Avoid nonsense log errors...
417#ifdef __ANDROID__
418 wxLogNull logNo;
419#endif
420 // Monthly backup, keep max 3
421 if (wxFileExists(m_sNavObjSetFile)) {
422 int month = wxDateTime::Now().GetMonth() + 1;
423 wxString fn =
424 wxString::Format(_T("%s.m%d"), m_sNavObjSetFile.c_str(), month);
425 if (!wxFileExists(fn)) {
426 wxCopyFile(m_sNavObjSetFile, fn);
427 }
428 if (month > 3) {
429 for (wxDateTime::wxDateTime_t i = 1; i <= month - 3; i++) {
430 fn = wxString::Format(_T("%s.m%d"), m_sNavObjSetFile.c_str(), i);
431 if (wxFileExists(fn)) {
432 wxRemoveFile(fn);
433 }
434 }
435 for (wxDateTime::wxDateTime_t i = month + 1; i <= 12; i++) {
436 fn = wxString::Format(_T("%s.m%d"), m_sNavObjSetFile.c_str(), i);
437 if (wxFileExists(fn)) {
438 wxRemoveFile(fn);
439 }
440 }
441 } else {
442 for (wxDateTime::wxDateTime_t i = month + 1; i <= 12 - month; i++) {
443 fn = wxString::Format(_T("%s.m%d"), m_sNavObjSetFile.c_str(), i);
444 if (wxFileExists(fn)) {
445 wxRemoveFile(fn);
446 }
447 }
448 }
449 // Weekly backup, we want to keep max 4
450 wxDateTime::wxDateTime_t week = wxDateTime::Now().GetWeekOfYear();
451 fn = wxString::Format(_T("%s.w%u"), m_sNavObjSetFile.c_str(), week);
452 if (!wxFileExists(fn)) {
453 wxCopyFile(m_sNavObjSetFile, fn);
454 }
455 if (week > 4) {
456 for (wxDateTime::wxDateTime_t i = 1; i <= week - 4; i++) {
457 fn = wxString::Format(_T("%s.w%u"), m_sNavObjSetFile.c_str(), i);
458 if (wxFileExists(fn)) {
459 wxRemoveFile(fn);
460 }
461 }
462 for (wxDateTime::wxDateTime_t i = week + 1; i <= 53; i++) {
463 fn = wxString::Format(_T("%s.w%u"), m_sNavObjSetFile.c_str(), i);
464 if (wxFileExists(fn)) {
465 wxRemoveFile(fn);
466 }
467 }
468 } else {
469 for (wxDateTime::wxDateTime_t i = week + 1; i <= 53 - week; i++) {
470 fn = wxString::Format(_T("%s.w%u"), m_sNavObjSetFile.c_str(), i);
471 if (wxFileExists(fn)) {
472 wxRemoveFile(fn);
473 }
474 }
475 }
476 }
477
478 // Rotate navobj backups, but just in case there are some changes in the
479 // current version to prevent the user trying to "fix" the problem by
480 // continuously starting the application to overwrite all of his good
481 // backups...
482 if (g_navobjbackups > 0) {
483 wxFile f;
484 wxString oldname = m_sNavObjSetFile;
485 wxString newname = wxString::Format(_T("%s.1"), m_sNavObjSetFile.c_str());
486
487 wxFileOffset s_diff = 1;
488 if (::wxFileExists(newname)) {
489 if (f.Open(oldname)) {
490 s_diff = f.Length();
491 f.Close();
492 }
493
494 if (f.Open(newname)) {
495 s_diff -= f.Length();
496 f.Close();
497 }
498 }
499
500 if (s_diff != 0) {
501 for (int i = g_navobjbackups - 1; i >= 1; i--) {
502 oldname = wxString::Format(_T("%s.%d"), m_sNavObjSetFile.c_str(), i);
503 newname =
504 wxString::Format(_T("%s.%d"), m_sNavObjSetFile.c_str(), i + 1);
505 if (wxFile::Exists(oldname)) wxCopyFile(oldname, newname);
506 }
507
508 wxULongLong size = wxFileName::GetSize(m_sNavObjSetFile);
509 if (wxFile::Exists(m_sNavObjSetFile) && size > 0) {
510 newname = wxString::Format(_T("%s.1"), m_sNavObjSetFile.c_str());
511 wxCopyFile(m_sNavObjSetFile, newname);
512 }
513 }
514 }
515 // try to clean the backups the user doesn't want - breaks if he deleted some
516 // by hand as it tries to be effective...
517 for (int i = g_navobjbackups + 1; i <= 99; i++)
518 if (wxFile::Exists(
519 wxString::Format(_T("%s.%d"), m_sNavObjSetFile.c_str(), i)))
520 wxRemoveFile(wxString::Format(_T("%s.%d"), m_sNavObjSetFile.c_str(), i));
521 else
522 break;
523}
524
525int MyConfig::LoadMyConfig() {
526 int display_width, display_height;
527 display_width = g_monitor_info[g_current_monitor].width;
528 display_height = g_monitor_info[g_current_monitor].height;
529
530 // Set up any defaults not set elsewhere
531 g_useMUI = true;
532 g_TalkerIdText = _T("EC");
533 g_maxWPNameLength = 6;
534 g_NMEAAPBPrecision = 3;
535
536#ifdef ocpnUSE_GL
537 g_GLOptions.m_bUseAcceleratedPanning = true;
538 g_GLOptions.m_GLPolygonSmoothing = true;
539 g_GLOptions.m_GLLineSmoothing = true;
540 g_GLOptions.m_iTextureDimension = 512;
541 g_GLOptions.m_iTextureMemorySize = 128;
542 if (!g_bGLexpert) {
543 g_GLOptions.m_iTextureMemorySize =
544 wxMax(128, g_GLOptions.m_iTextureMemorySize);
545 g_GLOptions.m_bTextureCompressionCaching =
546 g_GLOptions.m_bTextureCompression;
547 }
548#endif
549
550 g_maintoolbar_orient = wxTB_HORIZONTAL;
551 g_iENCToolbarPosX = -1;
552 g_iENCToolbarPosY = -1;
553 g_restore_dbindex = -1;
554 g_ChartNotRenderScaleFactor = 1.5;
555 g_detailslider_dialog_x = 200L;
556 g_detailslider_dialog_y = 200L;
557 g_SENC_LOD_pixels = 2;
558 g_SkewCompUpdatePeriod = 10;
559
560 g_bShowStatusBar = 1;
561 g_bShowCompassWin = 1;
562 g_iSoundDeviceIndex = -1;
563 g_bFullscreenToolbar = 1;
564 g_bTransparentToolbar = 0;
565 g_bShowLayers = 1;
566 g_bShowDepthUnits = 1;
567 g_bShowActiveRouteHighway = 1;
568 g_bShowChartBar = 1;
569 g_defaultBoatSpeed = 6.0;
570 g_ownship_predictor_minutes = 5;
571 g_cog_predictor_style = 105;
572 g_cog_predictor_color = _T("rgb(255,0,0)" );
573 g_cog_predictor_endmarker = 1;
574 g_ownship_HDTpredictor_style = 105;
575 g_ownship_HDTpredictor_color = _T("rgb(255,0,0)" );
576 g_ownship_HDTpredictor_endmarker = 1;
577 g_ownship_HDTpredictor_width = 0;
578 g_cog_predictor_width = 3;
579 g_ownship_HDTpredictor_miles = 1;
580 g_n_ownship_min_mm = 2;
581 g_own_ship_sog_cog_calc_damp_sec = 1;
582 g_bFullScreenQuilt = 1;
583 g_track_rotate_time_type = TIME_TYPE_COMPUTER;
584 g_bHighliteTracks = 1;
585 g_bPreserveScaleOnX = 1;
586 g_navobjbackups = 5;
587 g_benableAISNameCache = true;
588 g_n_arrival_circle_radius = 0.05;
589 g_plus_minus_zoom_factor = 2.0;
590 g_mouse_zoom_sensitivity = 1.5;
591 g_datetime_format = "UTC";
592
593 g_AISShowTracks_Mins = 20;
594 g_AISShowTracks_Limit = 300.0;
595 g_ShowScaled_Num = 10;
596 g_ScaledNumWeightSOG = 50;
597 g_ScaledNumWeightCPA = 60;
598 g_ScaledNumWeightTCPA = 25;
599 g_ScaledSizeMinimal = 50;
600 g_ScaledNumWeightRange = 75;
601 g_ScaledNumWeightSizeOfT = 25;
602 g_Show_Target_Name_Scale = 250000;
603 g_bWplUsePosition = 0;
604 g_WplAction = 0;
605 g_ais_cog_predictor_width = 3;
606 g_ais_alert_dialog_sx = 200;
607 g_ais_alert_dialog_sy = 200;
608 g_ais_alert_dialog_x = 200;
609 g_ais_alert_dialog_y = 200;
610 g_ais_query_dialog_x = 200;
611 g_ais_query_dialog_y = 200;
612 g_AisTargetList_range = 40;
613 g_AisTargetList_sortColumn = 2; // Column #2 is MMSI
614 g_S57_dialog_sx = 400;
615 g_S57_dialog_sy = 400;
616 g_S57_extradialog_sx = 400;
617 g_S57_extradialog_sy = 400;
618
619 // Reasonable starting point
620 vLat = START_LAT; // display viewpoint
621 vLon = START_LON;
622 gLat = START_LAT; // GPS position, as default
623 gLon = START_LON;
624 g_maxzoomin = 800;
625
626 g_iNavAidRadarRingsNumberVisible = 0;
627 g_bNavAidRadarRingsShown = false;
628 g_fNavAidRadarRingsStep = 1.0;
629 g_pNavAidRadarRingsStepUnits = 0;
630 g_colourOwnshipRangeRingsColour = *wxRED;
631 g_iWaypointRangeRingsNumber = 0;
632 g_fWaypointRangeRingsStep = 1.0;
633 g_iWaypointRangeRingsStepUnits = 0;
634 g_colourWaypointRangeRingsColour = wxColour(*wxRED);
635 g_bConfirmObjectDelete = true;
636
637 g_TrackIntervalSeconds = 60.0;
638 g_TrackDeltaDistance = 0.10;
639 g_route_line_width = 2;
640 g_track_line_width = 2;
641 g_colourTrackLineColour = wxColour(243, 229, 47); // Yellow
642
643 g_tcwin_scale = 100;
644 g_default_wp_icon = _T("triangle");
645 g_default_routepoint_icon = _T("diamond");
646
647 g_nAWDefault = 50;
648 g_nAWMax = 1852;
649 g_ObjQFileExt = _T("txt,rtf,png,html,gif,tif,jpg");
650
651 // Load the raw value, with no defaults, and no processing
652 int ret_Val = LoadMyConfigRaw();
653
654 // Perform any required post processing and validation
655 if (!ret_Val) {
656 g_ChartScaleFactorExp =
657 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
658 g_ShipScaleFactorExp =
659 g_Platform->GetChartScaleFactorExp(g_ShipScaleFactor);
660 g_MarkScaleFactorExp =
661 g_Platform->GetMarkScaleFactorExp(g_ChartScaleFactor);
662
663 g_COGFilterSec = wxMin(g_COGFilterSec, MAX_COGSOG_FILTER_SECONDS);
664 g_COGFilterSec = wxMax(g_COGFilterSec, 1);
665 g_SOGFilterSec = g_COGFilterSec;
666
667 if (!g_bShowTrue && !g_bShowMag) g_bShowTrue = true;
668 g_COGAvgSec =
669 wxMin(g_COGAvgSec, MAX_COG_AVERAGE_SECONDS); // Bound the array size
670
671 if (g_bInlandEcdis) g_bLookAhead = 1;
672
673 if (g_bdisable_opengl) g_bopengl = false;
674
675#ifdef ocpnUSE_GL
676 if (!g_bGLexpert) {
677 g_GLOptions.m_iTextureMemorySize =
678 wxMax(128, g_GLOptions.m_iTextureMemorySize);
679 g_GLOptions.m_bTextureCompressionCaching =
680 g_GLOptions.m_bTextureCompression;
681 }
682#endif
683
684 g_chart_zoom_modifier_raster = wxMin(g_chart_zoom_modifier_raster, 5);
685 g_chart_zoom_modifier_raster = wxMax(g_chart_zoom_modifier_raster, -5);
686 g_chart_zoom_modifier_vector = wxMin(g_chart_zoom_modifier_vector, 5);
687 g_chart_zoom_modifier_vector = wxMax(g_chart_zoom_modifier_vector, -5);
688 g_cm93_zoom_factor = wxMin(g_cm93_zoom_factor, CM93_ZOOM_FACTOR_MAX_RANGE);
689 g_cm93_zoom_factor =
690 wxMax(g_cm93_zoom_factor, (-CM93_ZOOM_FACTOR_MAX_RANGE));
691
692 if ((g_detailslider_dialog_x < 0) ||
693 (g_detailslider_dialog_x > display_width))
694 g_detailslider_dialog_x = 5;
695 if ((g_detailslider_dialog_y < 0) ||
696 (g_detailslider_dialog_y > display_height))
697 g_detailslider_dialog_y = 5;
698
699 g_defaultBoatSpeedUserUnit = toUsrSpeed(g_defaultBoatSpeed, -1);
700 g_n_ownship_min_mm = wxMax(g_n_ownship_min_mm, 2);
701
702 if (g_navobjbackups > 99) g_navobjbackups = 99;
703 if (g_navobjbackups < 0) g_navobjbackups = 0;
704 g_n_arrival_circle_radius = wxClip(g_n_arrival_circle_radius, 0.001, 0.6);
705
706 g_selection_radius_mm = wxMax(g_selection_radius_mm, 0.5);
707 g_selection_radius_touch_mm = wxMax(g_selection_radius_touch_mm, 1.0);
708
709 g_Show_Target_Name_Scale = wxMax(5000, g_Show_Target_Name_Scale);
710
711 if ((g_ais_alert_dialog_x < 0) || (g_ais_alert_dialog_x > display_width))
712 g_ais_alert_dialog_x = 5;
713 if ((g_ais_alert_dialog_y < 0) || (g_ais_alert_dialog_y > display_height))
714 g_ais_alert_dialog_y = 5;
715 if ((g_ais_query_dialog_x < 0) || (g_ais_query_dialog_x > display_width))
716 g_ais_query_dialog_x = 5;
717 if ((g_ais_query_dialog_y < 0) || (g_ais_query_dialog_y > display_height))
718 g_ais_query_dialog_y = 5;
719
720 SwitchInlandEcdisMode(g_bInlandEcdis);
721 if (g_bInlandEcdis)
722 global_color_scheme =
723 GLOBAL_COLOR_SCHEME_DUSK; // startup in duskmode if inlandEcdis
724
725 // Multicanvas Settings
726 LoadCanvasConfigs();
727 }
728
729 return ret_Val;
730}
731
732int MyConfig::LoadMyConfigRaw(bool bAsTemplate) {
733 int read_int;
734 wxString val;
735
736 int display_width, display_height;
737 display_width = g_monitor_info[g_current_monitor].width;
738 display_height = g_monitor_info[g_current_monitor].height;
739
740 // Global options and settings
741 SetPath(_T ( "/Settings" ));
742 Read("ActiveRoute", &g_active_route);
743 Read("PersistActiveRoute", &g_persist_active_route);
744 Read(_T ( "LastAppliedTemplate" ), &g_lastAppliedTemplateGUID);
745 Read(_T ( "CompatOS" ), &g_compatOS);
746 Read(_T ( "CompatOsVersion" ), &g_compatOsVersion);
747
748 // Some undocumented values
749 Read(_T ( "ConfigVersionString" ), &g_config_version_string);
750 Read(_T("CmdSoundString"), &g_CmdSoundString, wxString(OCPN_SOUND_CMD));
751 if (wxIsEmpty(g_CmdSoundString)) g_CmdSoundString = wxString(OCPN_SOUND_CMD);
752 Read(_T ( "NavMessageShown" ), &n_NavMessageShown);
753
754 Read(_T ( "AndroidVersionCode" ), &g_AndroidVersionCode);
755
756 Read(_T ( "UIexpert" ), &g_bUIexpert);
757
758 Read(_T ( "UIStyle" ), &g_uiStyle);
759
760 Read(_T ( "NCacheLimit" ), &g_nCacheLimit);
761
762 Read(_T ( "InlandEcdis" ),
763 &g_bInlandEcdis); // First read if in iENC mode as this will override
764 // some config settings
765
766 Read(_T( "SpaceDropMark" ), &g_bSpaceDropMark);
767
768 int mem_limit = 0;
769 Read(_T ( "MEMCacheLimit" ), &mem_limit);
770 if (mem_limit > 0)
771 g_memCacheLimit = mem_limit * 1024; // convert from MBytes to kBytes
772
773 Read(_T ( "UseModernUI5" ), &g_useMUI);
774
775 Read(_T( "NCPUCount" ), &g_nCPUCount);
776
777 Read(_T ( "DebugGDAL" ), &g_bGDAL_Debug);
778 Read(_T ( "DebugNMEA" ), &g_nNMEADebug);
779 Read(_T ( "AnchorWatchDefault" ), &g_nAWDefault);
780 Read(_T ( "AnchorWatchMax" ), &g_nAWMax);
781 Read(_T ( "GPSDogTimeout" ), &gps_watchdog_timeout_ticks);
782 Read(_T ( "DebugCM93" ), &g_bDebugCM93);
783 Read(_T ( "DebugS57" ),
784 &g_bDebugS57); // Show LUP and Feature info in object query
785 Read(_T ( "DebugBSBImg" ), &g_BSBImgDebug);
786 Read(_T ( "DebugGPSD" ), &g_bDebugGPSD);
787 Read(_T ( "MaxZoomScale" ), &g_maxzoomin);
788 g_maxzoomin = wxMax(g_maxzoomin, 50);
789
790 Read(_T ( "DefaultFontSize"), &g_default_font_size);
791 Read(_T ( "DefaultFontFacename"), &g_default_font_facename);
792
793 Read(_T ( "UseGreenShipIcon" ), &g_bUseGreenShip);
794
795 Read(_T ( "AutoHideToolbar" ), &g_bAutoHideToolbar);
796 Read(_T ( "AutoHideToolbarSecs" ), &g_nAutoHideToolbar);
797
798 Read(_T ( "UseSimplifiedScalebar" ), &g_bsimplifiedScalebar);
799 Read(_T ( "ShowTide" ), &g_bShowTide);
800 Read(_T ( "ShowCurrent" ), &g_bShowCurrent);
801
802 wxString size_mm;
803 Read(_T ( "DisplaySizeMM" ), &size_mm);
804
805 Read(_T ( "SelectionRadiusMM" ), &g_selection_radius_mm);
806 Read(_T ( "SelectionRadiusTouchMM" ), &g_selection_radius_touch_mm);
807
808 if (!bAsTemplate) {
809 g_config_display_size_mm.clear();
810 wxStringTokenizer tokenizer(size_mm, ",");
811 while (tokenizer.HasMoreTokens()) {
812 wxString token = tokenizer.GetNextToken();
813 int size;
814 try {
815 size = std::stoi(token.ToStdString());
816 } catch (std::invalid_argument &e) {
817 size = 0;
818 }
819 if (size > 100 && size < 2000) {
820 g_config_display_size_mm.push_back(size);
821 } else {
822 g_config_display_size_mm.push_back(0);
823 }
824 }
825 Read(_T ( "DisplaySizeManual" ), &g_config_display_size_manual);
826 }
827
828 Read(_T ( "GUIScaleFactor" ), &g_GUIScaleFactor);
829
830 Read(_T ( "ChartObjectScaleFactor" ), &g_ChartScaleFactor);
831 Read(_T ( "ShipScaleFactor" ), &g_ShipScaleFactor);
832 Read(_T ( "ENCSoundingScaleFactor" ), &g_ENCSoundingScaleFactor);
833 Read(_T ( "ENCTextScaleFactor" ), &g_ENCTextScaleFactor);
834 Read(_T ( "ObjQueryAppendFilesExt" ), &g_ObjQFileExt);
835
836 // Plugin catalog handler persistent variables.
837 Read("CatalogCustomURL", &g_catalog_custom_url);
838 Read("CatalogChannel", &g_catalog_channel);
839
840 Read("NetmaskBits", &g_netmask_bits);
841
842 // NMEA connection options.
843 if (!bAsTemplate) {
844 Read(_T ( "FilterNMEA_Avg" ), &g_bfilter_cogsog);
845 Read(_T ( "FilterNMEA_Sec" ), &g_COGFilterSec);
846 Read(_T ( "GPSIdent" ), &g_GPS_Ident);
847 Read(_T ( "UseGarminHostUpload" ), &g_bGarminHostUpload);
848 Read(_T ( "UseNMEA_GLL" ), &g_bUseGLL);
849 Read(_T ( "UseMagAPB" ), &g_bMagneticAPB);
850 Read(_T ( "TrackContinuous" ), &g_btrackContinuous, false);
851 Read(_T ( "FilterTrackDropLargeJump" ), &g_trackFilterMax, 1000);
852 }
853
854 Read(_T ( "ShowTrue" ), &g_bShowTrue);
855 Read(_T ( "ShowMag" ), &g_bShowMag);
856
857 wxString umv;
858 Read(_T ( "UserMagVariation" ), &umv);
859 if (umv.Len()) umv.ToDouble(&g_UserVar);
860
861 Read(_T ( "ScreenBrightness" ), &g_nbrightness);
862
863 Read(_T ( "MemFootprintTargetMB" ), &g_MemFootMB);
864
865 Read(_T ( "WindowsComPortMax" ), &g_nCOMPortCheck);
866
867 Read(_T ( "ChartQuilting" ), &g_bQuiltEnable);
868 Read(_T ( "ChartQuiltingInitial" ), &g_bQuiltStart);
869
870 Read(_T ( "CourseUpMode" ), &g_bCourseUp);
871 Read(_T ( "COGUPAvgSeconds" ), &g_COGAvgSec);
872 Read(_T ( "LookAheadMode" ), &g_bLookAhead);
873 Read(_T ( "SkewToNorthUp" ), &g_bskew_comp);
874 Read(_T ( "TenHzUpdate" ), &g_btenhertz, 0);
875 Read(_T ( "DeclutterAnchorage" ), &g_declutter_anchorage, 0);
876
877 Read(_T( "NMEAAPBPrecision" ), &g_NMEAAPBPrecision);
878
879 Read(_T( "TalkerIdText" ), &g_TalkerIdText);
880 Read(_T( "MaxWaypointNameLength" ), &g_maxWPNameLength);
881 Read(_T( "MbtilesMaxLayers" ), &g_mbtilesMaxLayers);
882
883 Read(_T( "ShowTrackPointTime" ), &g_bShowTrackPointTime, true);
884 /* opengl options */
885#ifdef ocpnUSE_GL
886 if (!bAsTemplate) {
887 Read(_T ( "OpenGLExpert" ), &g_bGLexpert, false);
888 Read(_T ( "UseAcceleratedPanning" ), &g_GLOptions.m_bUseAcceleratedPanning,
889 true);
890 Read(_T ( "GPUTextureCompression" ), &g_GLOptions.m_bTextureCompression);
891 Read(_T ( "GPUTextureCompressionCaching" ),
892 &g_GLOptions.m_bTextureCompressionCaching);
893 Read(_T ( "PolygonSmoothing" ), &g_GLOptions.m_GLPolygonSmoothing);
894 Read(_T ( "LineSmoothing" ), &g_GLOptions.m_GLLineSmoothing);
895 Read(_T ( "GPUTextureDimension" ), &g_GLOptions.m_iTextureDimension);
896 Read(_T ( "GPUTextureMemSize" ), &g_GLOptions.m_iTextureMemorySize);
897 Read(_T ( "DebugOpenGL" ), &g_bDebugOGL);
898 Read(_T ( "OpenGL" ), &g_bopengl);
899 Read(_T ( "SoftwareGL" ), &g_bSoftwareGL);
900 }
901#endif
902
903 Read(_T ( "SmoothPanZoom" ), &g_bsmoothpanzoom);
904
905 Read(_T ( "ToolbarX"), &g_maintoolbar_x);
906 Read(_T ( "ToolbarY" ), &g_maintoolbar_y);
907 Read(_T ( "ToolbarOrient" ), &g_maintoolbar_orient);
908 Read(_T ( "GlobalToolbarConfig" ), &g_toolbarConfig);
909
910 Read(_T ( "iENCToolbarX"), &g_iENCToolbarPosX);
911 Read(_T ( "iENCToolbarY"), &g_iENCToolbarPosY);
912
913 Read(_T ( "AnchorWatch1GUID" ), &g_AW1GUID);
914 Read(_T ( "AnchorWatch2GUID" ), &g_AW2GUID);
915
916 Read(_T ( "InitialStackIndex" ), &g_restore_stackindex);
917 Read(_T ( "InitialdBIndex" ), &g_restore_dbindex);
918
919 Read(_T ( "ChartNotRenderScaleFactor" ), &g_ChartNotRenderScaleFactor);
920
921 Read(_T ( "MobileTouch" ), &g_btouch);
922
923// "Responsive graphics" option deprecated in O58+
924// Read(_T ( "ResponsiveGraphics" ), &g_bresponsive);
925#ifdef __ANDROID__
926 g_bresponsive = true;
927#else
928 g_bresponsive = false;
929#endif
930
931 Read(_T ( "EnableRolloverBlock" ), &g_bRollover);
932
933 Read(_T ( "ZoomDetailFactor" ), &g_chart_zoom_modifier_raster);
934 Read(_T ( "ZoomDetailFactorVector" ), &g_chart_zoom_modifier_vector);
935 Read(_T ( "PlusMinusZoomFactor" ), &g_plus_minus_zoom_factor, 2.0);
936 Read("MouseZoomSensitivity", &g_mouse_zoom_sensitivity, 1.3);
937 g_mouse_zoom_sensitivity_ui =
938 MouseZoom::config_to_ui(g_mouse_zoom_sensitivity);
939 Read(_T ( "CM93DetailFactor" ), &g_cm93_zoom_factor);
940
941 Read(_T ( "CM93DetailZoomPosX" ), &g_detailslider_dialog_x);
942 Read(_T ( "CM93DetailZoomPosY" ), &g_detailslider_dialog_y);
943 Read(_T ( "ShowCM93DetailSlider" ), &g_bShowDetailSlider);
944
945 Read(_T ( "SENC_LOD_Pixels" ), &g_SENC_LOD_pixels);
946
947 Read(_T ( "SkewCompUpdatePeriod" ), &g_SkewCompUpdatePeriod);
948
949 Read(_T ( "SetSystemTime" ), &s_bSetSystemTime);
950 Read(_T ( "ShowStatusBar" ), &g_bShowStatusBar);
951#ifndef __WXOSX__
952 Read(_T ( "ShowMenuBar" ), &g_bShowMenuBar);
953#endif
954 Read(_T ( "Fullscreen" ), &g_bFullscreen);
955 Read(_T ( "ShowCompassWindow" ), &g_bShowCompassWin);
956 Read(_T ( "ShowGrid" ), &g_bDisplayGrid);
957 Read(_T ( "PlayShipsBells" ), &g_bPlayShipsBells);
958 Read(_T ( "SoundDeviceIndex" ), &g_iSoundDeviceIndex);
959 Read(_T ( "FullscreenToolbar" ), &g_bFullscreenToolbar);
960 Read(_T ( "PermanentMOBIcon" ), &g_bPermanentMOBIcon);
961 Read(_T ( "ShowLayers" ), &g_bShowLayers);
962 Read(_T ( "ShowDepthUnits" ), &g_bShowDepthUnits);
963 Read(_T ( "AutoAnchorDrop" ), &g_bAutoAnchorMark);
964 Read(_T ( "ShowChartOutlines" ), &g_bShowOutlines);
965 Read(_T ( "ShowActiveRouteHighway" ), &g_bShowActiveRouteHighway);
966 Read(_T ( "ShowActiveRouteTotal" ), &g_bShowRouteTotal);
967 Read(_T ( "MostRecentGPSUploadConnection" ), &g_uploadConnection);
968 Read(_T ( "ShowChartBar" ), &g_bShowChartBar);
969 Read(_T ( "SDMMFormat" ),
970 &g_iSDMMFormat); // 0 = "Degrees, Decimal minutes"), 1 = "Decimal
971 // degrees", 2 = "Degrees,Minutes, Seconds"
972
973 Read(_T ( "DistanceFormat" ),
974 &g_iDistanceFormat); // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
975 // "Kilometers", 3 = "Meters"
976 Read(_T ( "SpeedFormat" ),
977 &g_iSpeedFormat); // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
978 Read(_T ( "WindSpeedFormat" ),
979 &g_iWindSpeedFormat); // 0 = "knots"), 1 = "m/s", 2 = "Mph", 3 = "km/h"
980 Read(_T ("TemperatureFormat"), &g_iTempFormat); // 0 = C, 1 = F, 2 = K
981
982 // LIVE ETA OPTION
983 Read(_T ( "LiveETA" ), &g_bShowLiveETA);
984 Read(_T ( "DefaultBoatSpeed" ), &g_defaultBoatSpeed);
985
986 Read(_T ( "OwnshipCOGPredictorMinutes" ), &g_ownship_predictor_minutes);
987 Read(_T ( "OwnshipCOGPredictorStyle" ), &g_cog_predictor_style);
988 Read(_T ( "OwnshipCOGPredictorColor" ), &g_cog_predictor_color);
989 Read(_T ( "OwnshipCOGPredictorEndmarker" ), &g_cog_predictor_endmarker);
990 Read(_T ( "OwnshipCOGPredictorWidth" ), &g_cog_predictor_width);
991 Read(_T ( "OwnshipHDTPredictorStyle" ), &g_ownship_HDTpredictor_style);
992 Read(_T ( "OwnshipHDTPredictorColor" ), &g_ownship_HDTpredictor_color);
993 Read(_T ( "OwnshipHDTPredictorEndmarker" ),
994 &g_ownship_HDTpredictor_endmarker);
995 Read(_T ( "OwnshipHDTPredictorWidth" ), &g_ownship_HDTpredictor_width);
996 Read(_T ( "OwnshipHDTPredictorMiles" ), &g_ownship_HDTpredictor_miles);
997
998 Read(_T ( "OwnShipMMSINumber" ), &g_OwnShipmmsi);
999 Read(_T ( "OwnShipIconType" ), &g_OwnShipIconType);
1000 Read(_T ( "OwnShipLength" ), &g_n_ownship_length_meters);
1001 Read(_T ( "OwnShipWidth" ), &g_n_ownship_beam_meters);
1002 Read(_T ( "OwnShipGPSOffsetX" ), &g_n_gps_antenna_offset_x);
1003 Read(_T ( "OwnShipGPSOffsetY" ), &g_n_gps_antenna_offset_y);
1004 Read(_T ( "OwnShipMinSize" ), &g_n_ownship_min_mm);
1005 Read(_T ( "OwnShipSogCogCalc" ), &g_own_ship_sog_cog_calc);
1006 Read(_T ( "OwnShipSogCogCalcDampSec"), &g_own_ship_sog_cog_calc_damp_sec);
1007 Read(_T ( "ShowDirectRouteLine"), &g_bShowShipToActive);
1008 Read(_T ( "DirectRouteLineStyle"), &g_shipToActiveStyle);
1009 Read(_T( "DirectRouteLineColor" ), &g_shipToActiveColor);
1010
1011 wxString racr;
1012 Read(_T ( "RouteArrivalCircleRadius" ), &racr);
1013 if (racr.Len()) racr.ToDouble(&g_n_arrival_circle_radius);
1014
1015 Read(_T ( "FullScreenQuilt" ), &g_bFullScreenQuilt);
1016
1017 Read(_T ( "StartWithTrackActive" ), &g_bTrackCarryOver);
1018 Read(_T ( "AutomaticDailyTracks" ), &g_bTrackDaily);
1019 Read(_T ( "TrackRotateAt" ), &g_track_rotate_time);
1020 Read(_T ( "TrackRotateTimeType" ), &g_track_rotate_time_type);
1021 Read(_T ( "HighlightTracks" ), &g_bHighliteTracks);
1022
1023 Read(_T ( "DateTimeFormat" ), &g_datetime_format);
1024
1025 wxString stps;
1026 Read(_T ( "PlanSpeed" ), &stps);
1027 if (!stps.IsEmpty()) stps.ToDouble(&g_PlanSpeed);
1028
1029 Read(_T ( "VisibleLayers" ), &g_VisibleLayers);
1030 Read(_T ( "InvisibleLayers" ), &g_InvisibleLayers);
1031 Read(_T ( "VisNameInLayers" ), &g_VisiNameinLayers);
1032 Read(_T ( "InvisNameInLayers" ), &g_InVisiNameinLayers);
1033
1034 Read(_T ( "PreserveScaleOnX" ), &g_bPreserveScaleOnX);
1035
1036 Read(_T ( "ShowMUIZoomButtons" ), &g_bShowMuiZoomButtons);
1037
1038 Read(_T ( "Locale" ), &g_locale);
1039 Read(_T ( "LocaleOverride" ), &g_localeOverride);
1040
1041 // We allow 0-99 backups ov navobj.xml
1042 Read(_T ( "KeepNavobjBackups" ), &g_navobjbackups);
1043
1044 // Boolean to cater for legacy Input COM Port filer behaviour, i.e. show msg
1045 // filtered but put msg on bus.
1046 Read(_T ( "LegacyInputCOMPortFilterBehaviour" ),
1047 &g_b_legacy_input_filter_behaviour);
1048
1049 // Boolean to cater for sailing when not approaching waypoint
1050 Read(_T( "AdvanceRouteWaypointOnArrivalOnly" ),
1051 &g_bAdvanceRouteWaypointOnArrivalOnly);
1052 Read("EnableRootMenuDebug", &g_enable_root_menu_debug);
1053
1054 Read(_T ( "EnableRotateKeys" ), &g_benable_rotate);
1055 Read(_T ( "EmailCrashReport" ), &g_bEmailCrashReport);
1056
1057 g_benableAISNameCache = true;
1058 Read(_T ( "EnableAISNameCache" ), &g_benableAISNameCache);
1059
1060 Read(_T ( "EnableUDPNullHeader" ), &g_benableUDPNullHeader);
1061
1062 SetPath(_T ( "/Settings/GlobalState" ));
1063
1064 Read(_T ( "FrameWinX" ), &g_nframewin_x);
1065 Read(_T ( "FrameWinY" ), &g_nframewin_y);
1066 Read(_T ( "FrameWinPosX" ), &g_nframewin_posx);
1067 Read(_T ( "FrameWinPosY" ), &g_nframewin_posy);
1068 Read(_T ( "FrameMax" ), &g_bframemax);
1069
1070 Read(_T ( "ClientPosX" ), &g_lastClientRectx);
1071 Read(_T ( "ClientPosY" ), &g_lastClientRecty);
1072 Read(_T ( "ClientSzX" ), &g_lastClientRectw);
1073 Read(_T ( "ClientSzY" ), &g_lastClientRecth);
1074
1075 Read(_T( "RoutePropSizeX" ), &g_route_prop_sx);
1076 Read(_T( "RoutePropSizeY" ), &g_route_prop_sy);
1077 Read(_T( "RoutePropPosX" ), &g_route_prop_x);
1078 Read(_T( "RoutePropPosY" ), &g_route_prop_y);
1079
1080 read_int = -1;
1081 Read(_T ( "S52_DEPTH_UNIT_SHOW" ), &read_int); // default is metres
1082 if (read_int >= 0) {
1083 read_int = wxMax(read_int, 0); // qualify value
1084 read_int = wxMin(read_int, 2);
1085 g_nDepthUnitDisplay = read_int;
1086 }
1087
1088 // Sounds
1089 SetPath(_T ( "/Settings/Audio" ));
1090
1091 // Set reasonable defaults
1092 wxString sound_dir = g_Platform->GetSharedDataDir();
1093 sound_dir.Append(_T("sounds"));
1094 sound_dir.Append(wxFileName::GetPathSeparator());
1095
1096 g_AIS_sound_file = sound_dir + _T("beep_ssl.wav");
1097 g_DSC_sound_file = sound_dir + _T("phonering1.wav");
1098 g_SART_sound_file = sound_dir + _T("beep3.wav");
1099 g_anchorwatch_sound_file = sound_dir + _T("beep1.wav");
1100
1101 Read(_T ( "AISAlertSoundFile" ), &g_AIS_sound_file);
1102 Read(_T ( "DSCAlertSoundFile" ), &g_DSC_sound_file);
1103 Read(_T ( "SARTAlertSoundFile" ), &g_SART_sound_file);
1104 Read(_T ( "AnchorAlarmSoundFile" ), &g_anchorwatch_sound_file);
1105
1106 Read(_T ( "bAIS_GCPA_AlertAudio" ), &g_bAIS_GCPA_Alert_Audio);
1107 Read(_T ( "bAIS_SART_AlertAudio" ), &g_bAIS_SART_Alert_Audio);
1108 Read(_T ( "bAIS_DSC_AlertAudio" ), &g_bAIS_DSC_Alert_Audio);
1109 Read(_T ( "bAnchorAlertAudio" ), &g_bAnchor_Alert_Audio);
1110
1111 // AIS
1112 wxString s;
1113 SetPath(_T ( "/Settings/AIS" ));
1114
1115 g_bUseOnlyConfirmedAISName = false;
1116 Read(_T ( "UseOnlyConfirmedAISName" ), &g_bUseOnlyConfirmedAISName);
1117
1118 Read(_T ( "bNoCPAMax" ), &g_bCPAMax);
1119
1120 Read(_T ( "NoCPAMaxNMi" ), &s);
1121 s.ToDouble(&g_CPAMax_NM);
1122
1123 Read(_T ( "bCPAWarn" ), &g_bCPAWarn);
1124
1125 Read(_T ( "CPAWarnNMi" ), &s);
1126 s.ToDouble(&g_CPAWarn_NM);
1127
1128 Read(_T ( "bTCPAMax" ), &g_bTCPA_Max);
1129
1130 Read(_T ( "TCPAMaxMinutes" ), &s);
1131 s.ToDouble(&g_TCPA_Max);
1132
1133 Read(_T ( "bMarkLostTargets" ), &g_bMarkLost);
1134
1135 Read(_T ( "MarkLost_Minutes" ), &s);
1136 s.ToDouble(&g_MarkLost_Mins);
1137
1138 Read(_T ( "bRemoveLostTargets" ), &g_bRemoveLost);
1139
1140 Read(_T ( "RemoveLost_Minutes" ), &s);
1141 s.ToDouble(&g_RemoveLost_Mins);
1142
1143 Read(_T ( "bShowCOGArrows" ), &g_bShowCOG);
1144
1145 Read(_T ("bSyncCogPredictors"), &g_bSyncCogPredictors);
1146
1147 Read(_T ( "CogArrowMinutes" ), &s);
1148 s.ToDouble(&g_ShowCOG_Mins);
1149
1150 Read(_T ( "bShowTargetTracks" ), &g_bAISShowTracks);
1151
1152 if (Read(_T ( "TargetTracksLimit" ), &s)) {
1153 s.ToDouble(&g_AISShowTracks_Limit);
1154 g_AISShowTracks_Limit = wxMax(300.0, g_AISShowTracks_Limit);
1155 }
1156 if (Read(_T ( "TargetTracksMinutes" ), &s)) {
1157 s.ToDouble(&g_AISShowTracks_Mins);
1158 g_AISShowTracks_Mins = wxMax(1.0, g_AISShowTracks_Mins);
1159 g_AISShowTracks_Mins = wxMin(g_AISShowTracks_Limit, g_AISShowTracks_Mins);
1160 }
1161
1162 Read(_T ( "bHideMooredTargets" ), &g_bHideMoored);
1163 if (Read(_T ( "MooredTargetMaxSpeedKnots" ), &s))
1164 s.ToDouble(&g_ShowMoored_Kts);
1165
1166 g_SOGminCOG_kts = 0.2;
1167 if (Read(_T ( "SOGMinimumForCOGDisplay" ), &s)) s.ToDouble(&g_SOGminCOG_kts);
1168
1169 Read(_T ("bShowScaledTargets"), &g_bAllowShowScaled);
1170 Read(_T ( "AISScaledNumber" ), &g_ShowScaled_Num);
1171 Read(_T ( "AISScaledNumberWeightSOG" ), &g_ScaledNumWeightSOG);
1172 Read(_T ( "AISScaledNumberWeightCPA" ), &g_ScaledNumWeightCPA);
1173 Read(_T ( "AISScaledNumberWeightTCPA" ), &g_ScaledNumWeightTCPA);
1174 Read(_T ( "AISScaledNumberWeightRange" ), &g_ScaledNumWeightRange);
1175 Read(_T ( "AISScaledNumberWeightSizeOfTarget" ), &g_ScaledNumWeightSizeOfT);
1176 Read(_T ( "AISScaledSizeMinimal" ), &g_ScaledSizeMinimal);
1177 Read(_T("AISShowScaled"), &g_bShowScaled);
1178
1179 Read(_T ( "bShowAreaNotices" ), &g_bShowAreaNotices);
1180 Read(_T ( "bDrawAISSize" ), &g_bDrawAISSize);
1181 Read(_T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime);
1182 Read(_T ( "bShowAISName" ), &g_bShowAISName);
1183 Read(_T ( "AISRealtimeMinSpeedKnots" ), &g_AIS_RealtPred_Kts, 0.7);
1184 Read(_T ( "bAISAlertDialog" ), &g_bAIS_CPA_Alert);
1185 Read(_T ( "ShowAISTargetNameScale" ), &g_Show_Target_Name_Scale);
1186 Read(_T ( "bWplIsAprsPositionReport" ), &g_bWplUsePosition);
1187 Read(_T ( "WplSelAction"), &g_WplAction);
1188 Read(_T ( "AISCOGPredictorWidth" ), &g_ais_cog_predictor_width);
1189
1190 Read(_T ( "bAISAlertAudio" ), &g_bAIS_CPA_Alert_Audio);
1191 Read(_T ( "AISAlertAudioFile" ), &g_sAIS_Alert_Sound_File);
1192 Read(_T ( "bAISAlertSuppressMoored" ), &g_bAIS_CPA_Alert_Suppress_Moored);
1193
1194 Read(_T ( "bAISAlertAckTimeout" ), &g_bAIS_ACK_Timeout);
1195 if (Read(_T ( "AlertAckTimeoutMinutes" ), &s)) s.ToDouble(&g_AckTimeout_Mins);
1196
1197 Read(_T ( "AlertDialogSizeX" ), &g_ais_alert_dialog_sx);
1198 Read(_T ( "AlertDialogSizeY" ), &g_ais_alert_dialog_sy);
1199 Read(_T ( "AlertDialogPosX" ), &g_ais_alert_dialog_x);
1200 Read(_T ( "AlertDialogPosY" ), &g_ais_alert_dialog_y);
1201 Read(_T ( "QueryDialogPosX" ), &g_ais_query_dialog_x);
1202 Read(_T ( "QueryDialogPosY" ), &g_ais_query_dialog_y);
1203
1204 Read(_T ( "AISTargetListPerspective" ), &g_AisTargetList_perspective);
1205 Read(_T ( "AISTargetListRange" ), &g_AisTargetList_range);
1206 Read(_T ( "AISTargetListSortColumn" ), &g_AisTargetList_sortColumn);
1207 Read(_T ( "bAISTargetListSortReverse" ), &g_bAisTargetList_sortReverse);
1208 Read(_T ( "AISTargetListColumnSpec" ), &g_AisTargetList_column_spec);
1209 Read(_T ("AISTargetListColumnOrder"), &g_AisTargetList_column_order);
1210
1211 Read(_T ( "bAISRolloverShowClass" ), &g_bAISRolloverShowClass);
1212 Read(_T ( "bAISRolloverShowCOG" ), &g_bAISRolloverShowCOG);
1213 Read(_T ( "bAISRolloverShowCPA" ), &g_bAISRolloverShowCPA);
1214
1215 Read(_T ( "S57QueryDialogSizeX" ), &g_S57_dialog_sx);
1216 Read(_T ( "S57QueryDialogSizeY" ), &g_S57_dialog_sy);
1217 Read(_T ( "S57QueryExtraDialogSizeX" ), &g_S57_extradialog_sx);
1218 Read(_T ( "S57QueryExtraDialogSizeY" ), &g_S57_extradialog_sy);
1219
1220 wxString strpres(_T ( "PresentationLibraryData" ));
1221 wxString valpres;
1222 SetPath(_T ( "/Directories" ));
1223 Read(strpres, &valpres); // Get the File name
1224 if (!valpres.IsEmpty()) g_UserPresLibData = valpres;
1225
1226 wxString strs(_T ( "SENCFileLocation" ));
1227 SetPath(_T ( "/Directories" ));
1228 wxString vals;
1229 Read(strs, &vals); // Get the Directory name
1230 if (!vals.IsEmpty()) g_SENCPrefix = vals;
1231
1232 SetPath(_T ( "/Directories" ));
1233 wxString vald;
1234 Read(_T ( "InitChartDir" ), &vald); // Get the Directory name
1235
1236 wxString dirnamed(vald);
1237 if (!dirnamed.IsEmpty()) {
1238 if (pInit_Chart_Dir->IsEmpty()) // on second pass, don't overwrite
1239 {
1240 pInit_Chart_Dir->Clear();
1241 pInit_Chart_Dir->Append(vald);
1242 }
1243 }
1244
1245 Read(_T ( "GPXIODir" ), &g_gpx_path); // Get the Directory name
1246 Read(_T ( "TCDataDir" ), &g_TCData_Dir); // Get the Directory name
1247 Read(_T ( "BasemapDir"), &gWorldMapLocation);
1248 Read(_T ( "BaseShapefileDir"), &gWorldShapefileLocation);
1249 Read(_T ( "pluginInstallDir"), &g_winPluginDir);
1250 wxLogMessage("winPluginDir, read from ini file: %s",
1251 g_winPluginDir.mb_str().data());
1252
1253 SetPath(_T ( "/Settings/GlobalState" ));
1254
1255 if (Read(_T ( "nColorScheme" ), &read_int))
1256 global_color_scheme = (ColorScheme)read_int;
1257
1258 if (!bAsTemplate) {
1259 SetPath(_T ( "/Settings/NMEADataSource" ));
1260
1261 TheConnectionParams().clear();
1262 wxString connectionconfigs;
1263 Read(_T( "DataConnections" ), &connectionconfigs);
1264 if (!connectionconfigs.IsEmpty()) {
1265 wxArrayString confs = wxStringTokenize(connectionconfigs, _T("|"));
1266 for (size_t i = 0; i < confs.Count(); i++) {
1267 ConnectionParams *prm = new ConnectionParams(confs[i]);
1268 if (!prm->Valid) {
1269 wxLogMessage(_T( "Skipped invalid DataStream config"));
1270 delete prm;
1271 continue;
1272 }
1273 TheConnectionParams().push_back(prm);
1274 }
1275 }
1276 }
1277
1278 SetPath(_T ( "/Settings/GlobalState" ));
1279 wxString st;
1280
1281 double st_lat, st_lon;
1282 if (Read(_T ( "VPLatLon" ), &st)) {
1283 sscanf(st.mb_str(wxConvUTF8), "%lf,%lf", &st_lat, &st_lon);
1284
1285 // Sanity check the lat/lon...both have to be reasonable.
1286 if (fabs(st_lon) < 360.) {
1287 while (st_lon < -180.) st_lon += 360.;
1288
1289 while (st_lon > 180.) st_lon -= 360.;
1290
1291 vLon = st_lon;
1292 }
1293
1294 if (fabs(st_lat) < 90.0) vLat = st_lat;
1295
1296 s.Printf(_T ( "Setting Viewpoint Lat/Lon %g, %g" ), vLat, vLon);
1297 wxLogMessage(s);
1298 }
1299
1300 double st_view_scale, st_rotation;
1301 if (Read(wxString(_T ( "VPScale" )), &st)) {
1302 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_view_scale);
1303 // Sanity check the scale
1304 st_view_scale = fmax(st_view_scale, .001 / 32);
1305 st_view_scale = fmin(st_view_scale, 4);
1306 }
1307
1308 if (Read(wxString(_T ( "VPRotation" )), &st)) {
1309 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_rotation);
1310 // Sanity check the rotation
1311 st_rotation = fmin(st_rotation, 360);
1312 st_rotation = fmax(st_rotation, 0);
1313 }
1314
1315 wxString sll;
1316 double lat, lon;
1317 if (Read(_T ( "OwnShipLatLon" ), &sll)) {
1318 sscanf(sll.mb_str(wxConvUTF8), "%lf,%lf", &lat, &lon);
1319
1320 // Sanity check the lat/lon...both have to be reasonable.
1321 if (fabs(lon) < 360.) {
1322 while (lon < -180.) lon += 360.;
1323
1324 while (lon > 180.) lon -= 360.;
1325
1326 gLon = lon;
1327 }
1328
1329 if (fabs(lat) < 90.0) gLat = lat;
1330
1331 s.Printf(_T ( "Setting Ownship Lat/Lon %g, %g" ), gLat, gLon);
1332 wxLogMessage(s);
1333 }
1334
1335 // Fonts
1336
1337 // Load the persistent Auxiliary Font descriptor Keys
1338 SetPath(_T ( "/Settings/AuxFontKeys" ));
1339
1340 wxString strk;
1341 long dummyk;
1342 wxString kval;
1343 bool bContk = GetFirstEntry(strk, dummyk);
1344 bool bNewKey = false;
1345 while (bContk) {
1346 Read(strk, &kval);
1347 bNewKey = FontMgr::Get().AddAuxKey(kval);
1348 if (!bAsTemplate && !bNewKey) {
1349 DeleteEntry(strk);
1350 dummyk--;
1351 }
1352 bContk = GetNextEntry(strk, dummyk);
1353 }
1354
1355#ifdef __WXX11__
1356 SetPath(_T ( "/Settings/X11Fonts" ));
1357#endif
1358
1359#ifdef __WXGTK__
1360 SetPath(_T ( "/Settings/GTKFonts" ));
1361#endif
1362
1363#ifdef __WXMSW__
1364 SetPath(_T ( "/Settings/MSWFonts" ));
1365#endif
1366
1367#ifdef __WXMAC__
1368 SetPath(_T ( "/Settings/MacFonts" ));
1369#endif
1370
1371#ifdef __WXQT__
1372 SetPath(_T ( "/Settings/QTFonts" ));
1373#endif
1374
1375 wxString str;
1376 long dummy;
1377 wxString pval;
1378 wxArrayString deleteList;
1379
1380 bool bCont = GetFirstEntry(str, dummy);
1381 while (bCont) {
1382 pval = Read(str);
1383
1384 if (str.StartsWith(_T("Font"))) {
1385 // Convert pre 3.1 setting. Can't delete old entries from inside the
1386 // GetNextEntry() loop, so we need to save those and delete outside.
1387 deleteList.Add(str);
1388 wxString oldKey = pval.BeforeFirst(_T(':'));
1389 str = FontMgr::GetFontConfigKey(oldKey);
1390 }
1391
1392 if (pval.IsEmpty() || pval.StartsWith(_T(":"))) {
1393 deleteList.Add(str);
1394 } else
1395 FontMgr::Get().LoadFontNative(&str, &pval);
1396
1397 bCont = GetNextEntry(str, dummy);
1398 }
1399
1400 for (unsigned int i = 0; i < deleteList.Count(); i++) {
1401 DeleteEntry(deleteList[i]);
1402 }
1403 deleteList.Clear();
1404
1405 // Tide/Current Data Sources
1406 SetPath(_T ( "/TideCurrentDataSources" ));
1407 if (GetNumberOfEntries()) {
1408 TideCurrentDataSet.clear();
1409 wxString str, val;
1410 long dummy;
1411 bool bCont = GetFirstEntry(str, dummy);
1412 while (bCont) {
1413 Read(str, &val); // Get a file name and add it to the list just in case
1414 // it is not repeated
1415 // We have seen duplication of dataset entries in
1416 // https://github.com/OpenCPN/OpenCPN/issues/3042, this effectively gets
1417 // rid of them.
1418 if (std::find(TideCurrentDataSet.begin(), TideCurrentDataSet.end(),
1419 val.ToStdString()) == TideCurrentDataSet.end()) {
1420 TideCurrentDataSet.push_back(val.ToStdString());
1421 }
1422 bCont = GetNextEntry(str, dummy);
1423 }
1424 }
1425
1426 // Groups
1427 LoadConfigGroups(g_pGroupArray);
1428
1429 // // Multicanvas Settings
1430 // LoadCanvasConfigs();
1431
1432 SetPath(_T ( "/Settings/Others" ));
1433
1434 // Radar rings
1435 Read(_T ( "RadarRingsNumberVisible" ), &val);
1436 if (val.Length() > 0) g_iNavAidRadarRingsNumberVisible = atoi(val.mb_str());
1437 g_bNavAidRadarRingsShown = g_iNavAidRadarRingsNumberVisible > 0;
1438
1439 Read(_T ( "RadarRingsStep" ), &val);
1440 if (val.Length() > 0) g_fNavAidRadarRingsStep = atof(val.mb_str());
1441
1442 Read(_T ( "RadarRingsStepUnits" ), &g_pNavAidRadarRingsStepUnits);
1443
1444 wxString l_wxsOwnshipRangeRingsColour;
1445 Read(_T ( "RadarRingsColour" ), &l_wxsOwnshipRangeRingsColour);
1446 if (l_wxsOwnshipRangeRingsColour.Length())
1447 g_colourOwnshipRangeRingsColour.Set(l_wxsOwnshipRangeRingsColour);
1448
1449 // Waypoint Radar rings
1450 Read(_T ( "WaypointRangeRingsNumber" ), &val);
1451 if (val.Length() > 0) g_iWaypointRangeRingsNumber = atoi(val.mb_str());
1452
1453 Read(_T ( "WaypointRangeRingsStep" ), &val);
1454 if (val.Length() > 0) g_fWaypointRangeRingsStep = atof(val.mb_str());
1455
1456 Read(_T ( "WaypointRangeRingsStepUnits" ), &g_iWaypointRangeRingsStepUnits);
1457
1458 wxString l_wxsWaypointRangeRingsColour;
1459 Read(_T( "WaypointRangeRingsColour" ), &l_wxsWaypointRangeRingsColour);
1460 g_colourWaypointRangeRingsColour.Set(l_wxsWaypointRangeRingsColour);
1461
1462 if (!Read(_T("WaypointUseScaMin"), &g_bUseWptScaMin)) g_bUseWptScaMin = false;
1463 if (!Read(_T("WaypointScaMinValue"), &g_iWpt_ScaMin))
1464 g_iWpt_ScaMin = 2147483646;
1465 if (!Read(_T("WaypointUseScaMinOverrule"), &g_bOverruleScaMin))
1466 g_bOverruleScaMin = false;
1467 if (!Read(_T("WaypointsShowName"), &g_bShowWptName)) g_bShowWptName = true;
1468 if (!Read(_T("UserIconsFirst"), &g_bUserIconsFirst)) g_bUserIconsFirst = true;
1469
1470 // Support Version 3.0 and prior config setting for Radar Rings
1471 bool b300RadarRings = true;
1472 if (Read(_T ( "ShowRadarRings" ), &b300RadarRings)) {
1473 if (!b300RadarRings) g_iNavAidRadarRingsNumberVisible = 0;
1474 }
1475
1476 Read(_T ( "ConfirmObjectDeletion" ), &g_bConfirmObjectDelete);
1477
1478 // Waypoint dragging with mouse
1479 g_bWayPointPreventDragging = false;
1480 Read(_T ( "WaypointPreventDragging" ), &g_bWayPointPreventDragging);
1481
1482 g_bEnableZoomToCursor = false;
1483 Read(_T ( "EnableZoomToCursor" ), &g_bEnableZoomToCursor);
1484
1485 val.Clear();
1486 Read(_T ( "TrackIntervalSeconds" ), &val);
1487 if (val.Length() > 0) {
1488 double tval = atof(val.mb_str());
1489 if (tval >= 2.) g_TrackIntervalSeconds = tval;
1490 }
1491
1492 val.Clear();
1493 Read(_T ( "TrackDeltaDistance" ), &val);
1494 if (val.Length() > 0) {
1495 double tval = atof(val.mb_str());
1496 if (tval >= 0.05) g_TrackDeltaDistance = tval;
1497 }
1498
1499 Read(_T ( "TrackPrecision" ), &g_nTrackPrecision);
1500
1501 Read(_T ( "NavObjectFileName" ), m_sNavObjSetFile);
1502
1503 Read(_T ( "RouteLineWidth" ), &g_route_line_width);
1504 Read(_T ( "TrackLineWidth" ), &g_track_line_width);
1505
1506 wxString l_wxsTrackLineColour;
1507 if (Read(_T( "TrackLineColour" ), &l_wxsTrackLineColour))
1508 g_colourTrackLineColour.Set(l_wxsTrackLineColour);
1509
1510 Read(_T ( "TideCurrentWindowScale" ), &g_tcwin_scale);
1511 Read(_T ( "DefaultWPIcon" ), &g_default_wp_icon);
1512 Read(_T ( "DefaultRPIcon" ), &g_default_routepoint_icon);
1513
1514 SetPath(_T ( "/MmsiProperties" ));
1515 int iPMax = GetNumberOfEntries();
1516 if (iPMax) {
1517 g_MMSI_Props_Array.Empty();
1518 wxString str, val;
1519 long dummy;
1520 bool bCont = pConfig->GetFirstEntry(str, dummy);
1521 while (bCont) {
1522 pConfig->Read(str, &val); // Get an entry
1523
1524 MmsiProperties *pProps = new MmsiProperties(val);
1525 g_MMSI_Props_Array.Add(pProps);
1526
1527 bCont = pConfig->GetNextEntry(str, dummy);
1528 }
1529 }
1530
1531 return (0);
1532}
1533
1534void MyConfig::LoadS57Config() {
1535 if (!ps52plib) return;
1536
1537 int read_int;
1538 double dval;
1539 SetPath(_T ( "/Settings/GlobalState" ));
1540
1541 Read(_T ( "bShowS57Text" ), &read_int, 1);
1542 ps52plib->SetShowS57Text(!(read_int == 0));
1543
1544 Read(_T ( "bShowS57ImportantTextOnly" ), &read_int, 0);
1545 ps52plib->SetShowS57ImportantTextOnly(!(read_int == 0));
1546
1547 Read(_T ( "bShowLightDescription" ), &read_int, 0);
1548 ps52plib->SetShowLdisText(!(read_int == 0));
1549
1550 Read(_T ( "bExtendLightSectors" ), &read_int, 0);
1551 ps52plib->SetExtendLightSectors(!(read_int == 0));
1552
1553 Read(_T ( "nDisplayCategory" ), &read_int, (enum _DisCat)STANDARD);
1554 ps52plib->SetDisplayCategory((enum _DisCat)read_int);
1555
1556 Read(_T ( "nSymbolStyle" ), &read_int, (enum _LUPname)PAPER_CHART);
1557 ps52plib->m_nSymbolStyle = (LUPname)read_int;
1558
1559 Read(_T ( "nBoundaryStyle" ), &read_int, PLAIN_BOUNDARIES);
1560 ps52plib->m_nBoundaryStyle = (LUPname)read_int;
1561
1562 Read(_T ( "bShowSoundg" ), &read_int, 1);
1563 ps52plib->m_bShowSoundg = !(read_int == 0);
1564
1565 Read(_T ( "bShowMeta" ), &read_int, 0);
1566 ps52plib->m_bShowMeta = !(read_int == 0);
1567
1568 Read(_T ( "bUseSCAMIN" ), &read_int, 1);
1569 ps52plib->m_bUseSCAMIN = !(read_int == 0);
1570
1571 Read(_T ( "bUseSUPER_SCAMIN" ), &read_int, 0);
1572 ps52plib->m_bUseSUPER_SCAMIN = !(read_int == 0);
1573
1574 Read(_T ( "bShowAtonText" ), &read_int, 1);
1575 ps52plib->m_bShowAtonText = !(read_int == 0);
1576
1577 Read(_T ( "bDeClutterText" ), &read_int, 0);
1578 ps52plib->m_bDeClutterText = !(read_int == 0);
1579
1580 Read(_T ( "bShowNationalText" ), &read_int, 0);
1581 ps52plib->m_bShowNationalTexts = !(read_int == 0);
1582
1583 Read(_T ( "ENCSoundingScaleFactor" ), &read_int, 0);
1584 ps52plib->m_nSoundingFactor = read_int;
1585
1586 Read(_T ( "ENCTextScaleFactor" ), &read_int, 0);
1587 ps52plib->m_nTextFactor = read_int;
1588
1589 if (Read(_T ( "S52_MAR_SAFETY_CONTOUR" ), &dval, 3.0)) {
1590 S52_setMarinerParam(S52_MAR_SAFETY_CONTOUR, dval);
1591 S52_setMarinerParam(S52_MAR_SAFETY_DEPTH,
1592 dval); // Set safety_contour and safety_depth the same
1593 }
1594
1595 if (Read(_T ( "S52_MAR_SHALLOW_CONTOUR" ), &dval, 2.0))
1596 S52_setMarinerParam(S52_MAR_SHALLOW_CONTOUR, dval);
1597
1598 if (Read(_T ( "S52_MAR_DEEP_CONTOUR" ), &dval, 6.0))
1599 S52_setMarinerParam(S52_MAR_DEEP_CONTOUR, dval);
1600
1601 if (Read(_T ( "S52_MAR_TWO_SHADES" ), &dval, 0.0))
1602 S52_setMarinerParam(S52_MAR_TWO_SHADES, dval);
1603
1604 ps52plib->UpdateMarinerParams();
1605
1606 SetPath(_T ( "/Settings/GlobalState" ));
1607 Read(_T ( "S52_DEPTH_UNIT_SHOW" ), &read_int, 1); // default is metres
1608 read_int = wxMax(read_int, 0); // qualify value
1609 read_int = wxMin(read_int, 2);
1610 ps52plib->m_nDepthUnitDisplay = read_int;
1611 g_nDepthUnitDisplay = read_int;
1612
1613 // S57 Object Class Visibility
1614
1615 OBJLElement *pOLE;
1616
1617 SetPath(_T ( "/Settings/ObjectFilter" ));
1618
1619 int iOBJMax = GetNumberOfEntries();
1620 if (iOBJMax) {
1621 wxString str;
1622 long val;
1623 long dummy;
1624
1625 wxString sObj;
1626
1627 bool bCont = pConfig->GetFirstEntry(str, dummy);
1628 while (bCont) {
1629 pConfig->Read(str, &val); // Get an Object Viz
1630
1631 bool bNeedNew = true;
1632
1633 if (str.StartsWith(_T ( "viz" ), &sObj)) {
1634 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
1635 iPtr++) {
1636 pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
1637 if (!strncmp(pOLE->OBJLName, sObj.mb_str(), 6)) {
1638 pOLE->nViz = val;
1639 bNeedNew = false;
1640 break;
1641 }
1642 }
1643
1644 if (bNeedNew) {
1645 pOLE = (OBJLElement *)calloc(sizeof(OBJLElement), 1);
1646 memcpy(pOLE->OBJLName, sObj.mb_str(), OBJL_NAME_LEN);
1647 pOLE->nViz = 1;
1648
1649 ps52plib->pOBJLArray->Add((void *)pOLE);
1650 }
1651 }
1652 bCont = pConfig->GetNextEntry(str, dummy);
1653 }
1654 }
1655}
1656
1658static bool ReloadPendingChanges(const wxString &changes_path) {
1659 wxULongLong size = wxFileName::GetSize(changes_path);
1660
1661 // We crashed last time :(
1662 // That's why this file still exists...
1663 // Let's reconstruct the unsaved changes
1664 auto pNavObjectChangesSet = NavObjectChanges::getTempInstance();
1665 pNavObjectChangesSet->Init(changes_path);
1666 auto res = pNavObjectChangesSet->load_file(changes_path.fn_str());
1667
1668 // Remove the file before applying the changes,
1669 // just in case the changes file itself causes a fault.
1670 // If it does fault, at least the next restart will proceed without fault.
1671 if (::wxFileExists(changes_path)) ::wxRemoveFile(changes_path);
1672
1673 if (size == 0 || res.status != pugi::xml_parse_status::status_ok) {
1674 wxLogMessage(changes_path + " seems corrupted, not applying it.");
1675 pNavObjectChangesSet->reset();
1676 return false;
1677 }
1678
1679 wxLogMessage(_T("Applying NavObjChanges"));
1680 pNavObjectChangesSet->ApplyChanges();
1681 return true;
1682}
1683
1684wxString MyConfig::FindNewestUsableBackup() const {
1685 wxString newest_backup;
1687 for (int i = 1; i <= g_navobjbackups; i++) {
1688 wxString backup = m_sNavObjSetFile + "." + wxString::Format("%d", i);
1689 if (wxFileExists(backup) && wxFileName::GetSize(backup) > 461 &&
1690 doc.load_file(backup.fn_str()).status ==
1691 pugi::xml_parse_status::status_ok) {
1692 newest_backup = backup;
1693 break;
1694 }
1695 }
1696 return newest_backup;
1697}
1698
1699void MyConfig::LoadNavObjects() {
1700 // next thing to do is read tracks, etc from the NavObject XML file,
1701 wxLogMessage(_T("Loading navobjects from navobj.xml"));
1702
1703 if (NULL == m_pNavObjectInputSet)
1704 m_pNavObjectInputSet = new NavObjectCollection1();
1705
1706 int wpt_dups = 0;
1707 wxString newest_backup;
1708 if (::wxFileExists(m_sNavObjSetFile)) {
1709 if (wxFileName::GetSize(m_sNavObjSetFile) <
1710 461) { // Empty navobj.xml file with just the gpx tag is 461 bytes, so
1711 // anything smaller is obvious sign of a fatal crash while
1712 // saving it last time, replace it with latest backup if
1713 // available
1714 wxLogMessage("Navobjects file exists, but seems truncated!");
1715 newest_backup = FindNewestUsableBackup();
1716 if (wxFileExists(newest_backup)) {
1717 wxLogMessage("We do have a backup " + newest_backup +
1718 " that looks healthy and will use it.");
1719 wxCopyFile(newest_backup, m_sNavObjSetFile, true);
1720 }
1721 }
1722 } else { // File does not exist, try to recover from a backup
1723 newest_backup = FindNewestUsableBackup();
1724 if (wxFileExists(newest_backup)) {
1725 wxLogMessage("We do have a backup " + newest_backup +
1726 " that looks healthy and will use it.");
1727 wxCopyFile(newest_backup, m_sNavObjSetFile, true);
1728 } else {
1729 wxLogMessage(
1730 "No navobjects.xml file or usable backup exist, will create a new "
1731 "one.");
1732 }
1733 }
1734 bool success = false;
1735 // We did all we could to have an usable navobj.xml file in scenarios where it
1736 // did not exist or was clearly corrupted, let's try to load it
1737 if (::wxFileExists(m_sNavObjSetFile) &&
1738 m_pNavObjectInputSet->load_file(m_sNavObjSetFile.fn_str()).status ==
1739 pugi::xml_parse_status::status_ok) {
1740 CreateRotatingNavObjBackup(); // We only create backups when data is good,
1741 // there is no point in saving something we
1742 // can't even load
1743 success = m_pNavObjectInputSet->LoadAllGPXObjects(false, wpt_dups);
1744 } else {
1745 // It was still not valid after all our efforts and did not load as XML,
1746 // let's rename it to a corrupted file and try to recover from a backup on
1747 // last time
1748 wxString corrupted_file =
1749 m_sNavObjSetFile +
1750 wxDateTime::Now().Format(".corrupted.%Y-%m-%d-%H-%M-%S");
1751 wxRenameFile(m_sNavObjSetFile, corrupted_file, true);
1752 wxLogMessage("Error while loading navobjects from " + m_sNavObjSetFile +
1753 ", the corrupted file was renamed to " + corrupted_file);
1754 // If we got here with existing navobj.xml file, but it's corrupted, we can
1755 // still try to recover from a backup
1756 if (newest_backup
1757 .IsEmpty()) { // If we got here with empty newest_backup,
1758 // navobj.xml probably did exist, but was corrupted
1759 // XML-wise, so we need to find a new backup
1760 newest_backup = FindNewestUsableBackup();
1761 }
1762 m_pNavObjectInputSet->reset();
1763 if (wxFileExists(newest_backup) &&
1764 m_pNavObjectInputSet->load_file(newest_backup.fn_str()).status ==
1765 pugi::xml_parse_status::status_ok) {
1766 success = m_pNavObjectInputSet->LoadAllGPXObjects(false, wpt_dups);
1767 wxLogMessage("We do have a healthy backup " + newest_backup +
1768 " and did load it.");
1769 } else {
1770 wxLogMessage(
1771 "No usable backup found, a new navobj.xml file will be created.");
1772 m_pNavObjectInputSet->reset();
1773 }
1774 }
1775 if (success) {
1776 wxLogMessage(_T("Done loading navobjects, %d duplicate waypoints ignored"),
1777 wpt_dups);
1778 } else {
1779 wxLogMessage(
1780 _T("Failed to load navobjects, creating a new navobj.xml file."));
1781 }
1782 delete m_pNavObjectInputSet;
1783
1784 if (::wxFileExists(m_sNavObjSetChangesFile)) {
1785 if (ReloadPendingChanges(m_sNavObjSetChangesFile)) {
1786 UpdateNavObj();
1787 }
1788 }
1789 m_pNavObjectChangesSet->Init(m_sNavObjSetChangesFile);
1790 // Signal to listeners to g_active_route that it's possible to look up guid.
1791 GlobalVar<wxString> active_route(&g_active_route);
1792 active_route.Notify();
1793}
1794
1795bool MyConfig::LoadLayers(wxString &path) {
1796 wxArrayString file_array;
1797 wxDir dir;
1798 Layer *l;
1799 dir.Open(path);
1800 if (dir.IsOpened()) {
1801 wxString filename;
1802 bool cont = dir.GetFirst(&filename);
1803 while (cont) {
1804 file_array.Clear();
1805 filename.Prepend(wxFileName::GetPathSeparator());
1806 filename.Prepend(path);
1807 wxFileName f(filename);
1808 size_t nfiles = 0;
1809 if (f.GetExt().IsSameAs(wxT("gpx")))
1810 file_array.Add(filename); // single-gpx-file layer
1811 else {
1812 if (wxDir::Exists(filename)) {
1813 wxDir dir(filename);
1814 if (dir.IsOpened()) {
1815 nfiles = dir.GetAllFiles(filename, &file_array,
1816 wxT("*.gpx")); // layers subdirectory set
1817 }
1818 }
1819 }
1820
1821 if (file_array.GetCount()) {
1822 l = new Layer();
1823 l->m_LayerID = ++g_LayerIdx;
1824 l->m_LayerFileName = file_array[0];
1825 if (file_array.GetCount() <= 1)
1826 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName),
1827 NULL, NULL);
1828 else
1829 wxFileName::SplitPath(filename, NULL, NULL, &(l->m_LayerName), NULL,
1830 NULL);
1831
1832 bool bLayerViz = g_bShowLayers;
1833
1834 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
1835 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
1836
1837 l->m_bHasVisibleNames = wxCHK_UNDETERMINED;
1838 if (g_VisiNameinLayers.Contains(l->m_LayerName))
1839 l->m_bHasVisibleNames = wxCHK_CHECKED;
1840 if (g_InVisiNameinLayers.Contains(l->m_LayerName))
1841 l->m_bHasVisibleNames = wxCHK_UNCHECKED;
1842
1843 l->m_bIsVisibleOnChart = bLayerViz;
1844
1845 wxString laymsg;
1846 laymsg.Printf(wxT("New layer %d: %s"), l->m_LayerID,
1847 l->m_LayerName.c_str());
1848 wxLogMessage(laymsg);
1849
1850 pLayerList->Insert(l);
1851
1852 // Load the entire file array as a single layer
1853
1854 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
1855 wxString file_path = file_array[i];
1856
1857 if (::wxFileExists(file_path)) {
1859 if (pSet->load_file(file_path.fn_str()).status !=
1860 pugi::xml_parse_status::status_ok) {
1861 wxLogMessage("Error loading GPX file " + file_path);
1862 pSet->reset();
1863 }
1864 long nItems = pSet->LoadAllGPXObjectsAsLayer(
1865 l->m_LayerID, bLayerViz, l->m_bHasVisibleNames);
1866 l->m_NoOfItems += nItems;
1867 l->m_LayerType = _("Persistent");
1868
1869 wxString objmsg;
1870 objmsg.Printf(wxT("Loaded GPX file %s with %ld items."),
1871 file_path.c_str(), nItems);
1872 wxLogMessage(objmsg);
1873
1874 delete pSet;
1875 }
1876 }
1877 }
1878
1879 cont = dir.GetNext(&filename);
1880 }
1881 }
1882 g_bLayersLoaded = true;
1883
1884 return true;
1885}
1886
1887bool MyConfig::LoadChartDirArray(ArrayOfCDI &ChartDirArray) {
1888 // Chart Directories
1889 SetPath(_T ( "/ChartDirectories" ));
1890 int iDirMax = GetNumberOfEntries();
1891 if (iDirMax) {
1892 ChartDirArray.Empty();
1893 wxString str, val;
1894 long dummy;
1895 int nAdjustChartDirs = 0;
1896 int iDir = 0;
1897 bool bCont = pConfig->GetFirstEntry(str, dummy);
1898 while (bCont) {
1899 pConfig->Read(str, &val); // Get a Directory name
1900
1901 wxString dirname(val);
1902 if (!dirname.IsEmpty()) {
1903 /* Special case for first time run after Windows install with sample
1904 chart data... We desire that the sample configuration file opencpn.ini
1905 should not contain any installation dependencies, so... Detect and
1906 update the sample [ChartDirectories] entries to point to the Shared
1907 Data directory For instance, if the (sample) opencpn.ini file should
1908 contain shortcut coded entries like:
1909
1910 [ChartDirectories]
1911 ChartDir1=SampleCharts\\MaptechRegion7
1912
1913 then this entry will be updated to be something like:
1914 ChartDir1=c:\Program Files\opencpn\SampleCharts\\MaptechRegion7
1915
1916 */
1917 if (dirname.Find(_T ( "SampleCharts" )) ==
1918 0) // only update entries starting with "SampleCharts"
1919 {
1920 nAdjustChartDirs++;
1921
1922 pConfig->DeleteEntry(str);
1923 wxString new_dir = dirname.Mid(dirname.Find(_T ( "SampleCharts" )));
1924 new_dir.Prepend(g_Platform->GetSharedDataDir());
1925 dirname = new_dir;
1926 }
1927
1928 ChartDirInfo cdi;
1929 cdi.fullpath = dirname.BeforeFirst('^');
1930 cdi.magic_number = dirname.AfterFirst('^');
1931
1932 ChartDirArray.Add(cdi);
1933 iDir++;
1934 }
1935
1936 bCont = pConfig->GetNextEntry(str, dummy);
1937 }
1938
1939 if (nAdjustChartDirs) pConfig->UpdateChartDirs(ChartDirArray);
1940 }
1941
1942 return true;
1943}
1944
1945void MyConfig::AddNewRoute(Route *r) { m_pNavObjectChangesSet->AddNewRoute(r); }
1946
1947void MyConfig::UpdateRoute(Route *r) { m_pNavObjectChangesSet->UpdateRoute(r); }
1948
1949void MyConfig::DeleteConfigRoute(Route *pr) {
1950 m_pNavObjectChangesSet->DeleteConfigRoute(pr);
1951}
1952
1953void MyConfig::AddNewTrack(Track *pt) {
1954 m_pNavObjectChangesSet->AddNewTrack(pt);
1955}
1956
1957void MyConfig::UpdateTrack(Track *pt) {
1958 m_pNavObjectChangesSet->UpdateTrack(pt);
1959}
1960
1961void MyConfig::DeleteConfigTrack(Track *pt) {
1962 m_pNavObjectChangesSet->DeleteConfigTrack(pt);
1963}
1964
1965void MyConfig::AddNewWayPoint(RoutePoint *pWP, int crm) {
1966 m_pNavObjectChangesSet->AddNewWayPoint(pWP);
1967}
1968
1969void MyConfig::UpdateWayPoint(RoutePoint *pWP) {
1970 m_pNavObjectChangesSet->UpdateWayPoint(pWP);
1971}
1972
1973void MyConfig::DeleteWayPoint(RoutePoint *pWP) {
1974 m_pNavObjectChangesSet->DeleteWayPoint(pWP);
1975}
1976
1977void MyConfig::AddNewTrackPoint(TrackPoint *pWP, const wxString &parent_GUID) {
1978 m_pNavObjectChangesSet->AddNewTrackPoint(pWP, parent_GUID);
1979}
1980
1981bool MyConfig::UpdateChartDirs(ArrayOfCDI &dir_array) {
1982 wxString key, dir;
1983 wxString str_buf;
1984
1985 SetPath(_T ( "/ChartDirectories" ));
1986 int iDirMax = GetNumberOfEntries();
1987 if (iDirMax) {
1988 long dummy;
1989
1990 for (int i = 0; i < iDirMax; i++) {
1991 GetFirstEntry(key, dummy);
1992 DeleteEntry(key, false);
1993 }
1994 }
1995
1996 iDirMax = dir_array.GetCount();
1997
1998 for (int iDir = 0; iDir < iDirMax; iDir++) {
1999 ChartDirInfo cdi = dir_array[iDir];
2000
2001 wxString dirn = cdi.fullpath;
2002 dirn.Append(_T("^"));
2003 dirn.Append(cdi.magic_number);
2004
2005 str_buf.Printf(_T ( "ChartDir%d" ), iDir + 1);
2006
2007 Write(str_buf, dirn);
2008 }
2009
2010// Avoid nonsense log errors...
2011#ifdef __ANDROID__
2012 wxLogNull logNo;
2013#endif
2014
2015 Flush();
2016 return true;
2017}
2018
2019void MyConfig::CreateConfigGroups(ChartGroupArray *pGroupArray) {
2020 if (!pGroupArray) return;
2021
2022 SetPath(_T ( "/Groups" ));
2023 Write(_T ( "GroupCount" ), (int)pGroupArray->GetCount());
2024
2025 for (unsigned int i = 0; i < pGroupArray->GetCount(); i++) {
2026 ChartGroup *pGroup = pGroupArray->Item(i);
2027 wxString s;
2028 s.Printf(_T("Group%d"), i + 1);
2029 s.Prepend(_T ( "/Groups/" ));
2030 SetPath(s);
2031
2032 Write(_T ( "GroupName" ), pGroup->m_group_name);
2033 Write(_T ( "GroupItemCount" ), (int)pGroup->m_element_array.size());
2034
2035 for (unsigned int j = 0; j < pGroup->m_element_array.size(); j++) {
2036 wxString sg;
2037 sg.Printf(_T("Group%d/Item%d"), i + 1, j);
2038 sg.Prepend(_T ( "/Groups/" ));
2039 SetPath(sg);
2040 Write(_T ( "IncludeItem" ), pGroup->m_element_array[j].m_element_name);
2041
2042 wxString t;
2043 wxArrayString u = pGroup->m_element_array[j].m_missing_name_array;
2044 if (u.GetCount()) {
2045 for (unsigned int k = 0; k < u.GetCount(); k++) {
2046 t += u[k];
2047 t += _T(";");
2048 }
2049 Write(_T ( "ExcludeItems" ), t);
2050 }
2051 }
2052 }
2053}
2054
2055void MyConfig::DestroyConfigGroups(void) {
2056 DeleteGroup(_T ( "/Groups" )); // zap
2057}
2058
2059void MyConfig::LoadConfigGroups(ChartGroupArray *pGroupArray) {
2060 SetPath(_T ( "/Groups" ));
2061 unsigned int group_count;
2062 Read(_T ( "GroupCount" ), (int *)&group_count, 0);
2063
2064 for (unsigned int i = 0; i < group_count; i++) {
2065 ChartGroup *pGroup = new ChartGroup;
2066 wxString s;
2067 s.Printf(_T("Group%d"), i + 1);
2068 s.Prepend(_T ( "/Groups/" ));
2069 SetPath(s);
2070
2071 wxString t;
2072 Read(_T ( "GroupName" ), &t);
2073 pGroup->m_group_name = t;
2074
2075 unsigned int item_count;
2076 Read(_T ( "GroupItemCount" ), (int *)&item_count);
2077 for (unsigned int j = 0; j < item_count; j++) {
2078 wxString sg;
2079 sg.Printf(_T("Group%d/Item%d"), i + 1, j);
2080 sg.Prepend(_T ( "/Groups/" ));
2081 SetPath(sg);
2082
2083 wxString v;
2084 Read(_T ( "IncludeItem" ), &v);
2085
2086 ChartGroupElement pelement{v};
2087 wxString u;
2088 if (Read(_T ( "ExcludeItems" ), &u)) {
2089 if (!u.IsEmpty()) {
2090 wxStringTokenizer tk(u, _T(";"));
2091 while (tk.HasMoreTokens()) {
2092 wxString token = tk.GetNextToken();
2093 pelement.m_missing_name_array.Add(token);
2094 }
2095 }
2096 }
2097 pGroup->m_element_array.push_back(std::move(pelement));
2098 }
2099 pGroupArray->Add(pGroup);
2100 }
2101}
2102
2103void MyConfig::LoadCanvasConfigs(bool bApplyAsTemplate) {
2104 wxString s;
2105 canvasConfig *pcc;
2106 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
2107
2108 SetPath(_T ( "/Canvas" ));
2109
2110 // If the canvas config has never been set/persisted, use the global settings
2111 if (!HasEntry(_T ( "CanvasConfig" ))) {
2112 pcc = new canvasConfig(0);
2113 pcc->LoadFromLegacyConfig(this);
2114 config_array.Add(pcc);
2115
2116 return;
2117 }
2118
2119 Read(_T ( "CanvasConfig" ), (int *)&g_canvasConfig, 0);
2120
2121 // Do not recreate canvasConfigs when applying config dynamically
2122 if (config_array.GetCount() == 0) { // This is initial load from startup
2123 s.Printf(_T("/Canvas/CanvasConfig%d"), 1);
2124 SetPath(s);
2125 canvasConfig *pcca = new canvasConfig(0);
2126 LoadConfigCanvas(pcca, bApplyAsTemplate);
2127 config_array.Add(pcca);
2128
2129 s.Printf(_T("/Canvas/CanvasConfig%d"), 2);
2130 SetPath(s);
2131 pcca = new canvasConfig(1);
2132 LoadConfigCanvas(pcca, bApplyAsTemplate);
2133 config_array.Add(pcca);
2134 } else { // This is a dynamic (i.e. Template) load
2135 canvasConfig *pcca = config_array[0];
2136 s.Printf(_T("/Canvas/CanvasConfig%d"), 1);
2137 SetPath(s);
2138 LoadConfigCanvas(pcca, bApplyAsTemplate);
2139
2140 if (config_array.GetCount() > 1) {
2141 canvasConfig *pcca = config_array[1];
2142 s.Printf(_T("/Canvas/CanvasConfig%d"), 2);
2143 SetPath(s);
2144 LoadConfigCanvas(pcca, bApplyAsTemplate);
2145 } else {
2146 s.Printf(_T("/Canvas/CanvasConfig%d"), 2);
2147 SetPath(s);
2148 pcca = new canvasConfig(1);
2149 LoadConfigCanvas(pcca, bApplyAsTemplate);
2150 config_array.Add(pcca);
2151 }
2152 }
2153}
2154
2155void MyConfig::LoadConfigCanvas(canvasConfig *cConfig, bool bApplyAsTemplate) {
2156 wxString st;
2157 double st_lat, st_lon;
2158
2159 if (!bApplyAsTemplate) {
2160 // Reasonable starting point
2161 cConfig->iLat = START_LAT; // display viewpoint
2162 cConfig->iLon = START_LON;
2163
2164 if (Read(_T ( "canvasVPLatLon" ), &st)) {
2165 sscanf(st.mb_str(wxConvUTF8), "%lf,%lf", &st_lat, &st_lon);
2166
2167 // Sanity check the lat/lon...both have to be reasonable.
2168 if (fabs(st_lon) < 360.) {
2169 while (st_lon < -180.) st_lon += 360.;
2170
2171 while (st_lon > 180.) st_lon -= 360.;
2172
2173 cConfig->iLon = st_lon;
2174 }
2175
2176 if (fabs(st_lat) < 90.0) cConfig->iLat = st_lat;
2177 }
2178
2179 cConfig->iScale = .0003; // decent initial value
2180 cConfig->iRotation = 0;
2181
2182 double st_view_scale;
2183 if (Read(wxString(_T ( "canvasVPScale" )), &st)) {
2184 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_view_scale);
2185 // Sanity check the scale
2186 st_view_scale = fmax(st_view_scale, .001 / 32);
2187 st_view_scale = fmin(st_view_scale, 4);
2188 cConfig->iScale = st_view_scale;
2189 }
2190
2191 double st_rotation;
2192 if (Read(wxString(_T ( "canvasVPRotation" )), &st)) {
2193 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_rotation);
2194 // Sanity check the rotation
2195 st_rotation = fmin(st_rotation, 360);
2196 st_rotation = fmax(st_rotation, 0);
2197 cConfig->iRotation = st_rotation * PI / 180.;
2198 }
2199
2200 Read(_T ( "canvasInitialdBIndex" ), &cConfig->DBindex, 0);
2201 Read(_T ( "canvasbFollow" ), &cConfig->bFollow, 0);
2202
2203 Read(_T ( "canvasCourseUp" ), &cConfig->bCourseUp, 0);
2204 Read(_T ( "canvasHeadUp" ), &cConfig->bHeadUp, 0);
2205 Read(_T ( "canvasLookahead" ), &cConfig->bLookahead, 0);
2206 }
2207
2208 Read(_T ( "ActiveChartGroup" ), &cConfig->GroupID, 0);
2209
2210 // Special check for group selection when applied as template
2211 if (cConfig->GroupID && bApplyAsTemplate) {
2212 if (cConfig->GroupID > (int)g_pGroupArray->GetCount()) cConfig->GroupID = 0;
2213 }
2214
2215 Read(_T ( "canvasShowTides" ), &cConfig->bShowTides, 0);
2216 Read(_T ( "canvasShowCurrents" ), &cConfig->bShowCurrents, 0);
2217
2218 Read(_T ( "canvasQuilt" ), &cConfig->bQuilt, 1);
2219 Read(_T ( "canvasShowGrid" ), &cConfig->bShowGrid, 0);
2220 Read(_T ( "canvasShowOutlines" ), &cConfig->bShowOutlines, 0);
2221 Read(_T ( "canvasShowDepthUnits" ), &cConfig->bShowDepthUnits, 0);
2222
2223 Read(_T ( "canvasShowAIS" ), &cConfig->bShowAIS, 1);
2224 Read(_T ( "canvasAttenAIS" ), &cConfig->bAttenAIS, 0);
2225
2226 // ENC options
2227 Read(_T ( "canvasShowENCText" ), &cConfig->bShowENCText, 1);
2228 Read(_T ( "canvasENCDisplayCategory" ), &cConfig->nENCDisplayCategory,
2229 STANDARD);
2230 Read(_T ( "canvasENCShowDepths" ), &cConfig->bShowENCDepths, 1);
2231 Read(_T ( "canvasENCShowBuoyLabels" ), &cConfig->bShowENCBuoyLabels, 1);
2232 Read(_T ( "canvasENCShowLightDescriptions" ),
2233 &cConfig->bShowENCLightDescriptions, 1);
2234 Read(_T ( "canvasENCShowLights" ), &cConfig->bShowENCLights, 1);
2235 Read(_T ( "canvasENCShowVisibleSectorLights" ),
2236 &cConfig->bShowENCVisibleSectorLights, 0);
2237 Read(_T ( "canvasENCShowAnchorInfo" ), &cConfig->bShowENCAnchorInfo, 0);
2238 Read(_T ( "canvasENCShowDataQuality" ), &cConfig->bShowENCDataQuality, 0);
2239
2240 int sx, sy;
2241 Read(_T ( "canvasSizeX" ), &sx, 0);
2242 Read(_T ( "canvasSizeY" ), &sy, 0);
2243 cConfig->canvasSize = wxSize(sx, sy);
2244}
2245
2246void MyConfig::SaveCanvasConfigs() {
2247 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
2248
2249 SetPath(_T ( "/Canvas" ));
2250 Write(_T ( "CanvasConfig" ), (int)g_canvasConfig);
2251
2252 wxString s;
2253 canvasConfig *pcc;
2254
2255 switch (g_canvasConfig) {
2256 case 0:
2257 default:
2258
2259 s.Printf(_T("/Canvas/CanvasConfig%d"), 1);
2260 SetPath(s);
2261
2262 if (config_array.GetCount() > 0) {
2263 pcc = config_array.Item(0);
2264 if (pcc) {
2265 SaveConfigCanvas(pcc);
2266 }
2267 }
2268 break;
2269
2270 case 1:
2271
2272 if (config_array.GetCount() > 1) {
2273 s.Printf(_T("/Canvas/CanvasConfig%d"), 1);
2274 SetPath(s);
2275 pcc = config_array.Item(0);
2276 if (pcc) {
2277 SaveConfigCanvas(pcc);
2278 }
2279
2280 s.Printf(_T("/Canvas/CanvasConfig%d"), 2);
2281 SetPath(s);
2282 pcc = config_array.Item(1);
2283 if (pcc) {
2284 SaveConfigCanvas(pcc);
2285 }
2286 }
2287 break;
2288 }
2289}
2290
2291void MyConfig::SaveConfigCanvas(canvasConfig *cConfig) {
2292 wxString st1;
2293
2294 if (cConfig->canvas) {
2295 ViewPort vp = cConfig->canvas->GetVP();
2296
2297 if (vp.IsValid()) {
2298 st1.Printf(_T ( "%10.4f,%10.4f" ), vp.clat, vp.clon);
2299 Write(_T ( "canvasVPLatLon" ), st1);
2300 st1.Printf(_T ( "%g" ), vp.view_scale_ppm);
2301 Write(_T ( "canvasVPScale" ), st1);
2302 st1.Printf(_T ( "%i" ), ((int)(vp.rotation * 180 / PI)) % 360);
2303 Write(_T ( "canvasVPRotation" ), st1);
2304 }
2305
2306 int restore_dbindex = 0;
2307 ChartStack *pcs = cConfig->canvas->GetpCurrentStack();
2308 if (pcs) restore_dbindex = pcs->GetCurrentEntrydbIndex();
2309 if (cConfig->canvas->GetQuiltMode())
2310 restore_dbindex = cConfig->canvas->GetQuiltReferenceChartIndex();
2311 Write(_T ( "canvasInitialdBIndex" ), restore_dbindex);
2312
2313 Write(_T ( "canvasbFollow" ), cConfig->canvas->m_bFollow);
2314 Write(_T ( "ActiveChartGroup" ), cConfig->canvas->m_groupIndex);
2315
2316 Write(_T ( "canvasQuilt" ), cConfig->canvas->GetQuiltMode());
2317 Write(_T ( "canvasShowGrid" ), cConfig->canvas->GetShowGrid());
2318 Write(_T ( "canvasShowOutlines" ), cConfig->canvas->GetShowOutlines());
2319 Write(_T ( "canvasShowDepthUnits" ), cConfig->canvas->GetShowDepthUnits());
2320
2321 Write(_T ( "canvasShowAIS" ), cConfig->canvas->GetShowAIS());
2322 Write(_T ( "canvasAttenAIS" ), cConfig->canvas->GetAttenAIS());
2323
2324 Write(_T ( "canvasShowTides" ), cConfig->canvas->GetbShowTide());
2325 Write(_T ( "canvasShowCurrents" ), cConfig->canvas->GetbShowCurrent());
2326
2327 // ENC options
2328 Write(_T ( "canvasShowENCText" ), cConfig->canvas->GetShowENCText());
2329 Write(_T ( "canvasENCDisplayCategory" ),
2330 cConfig->canvas->GetENCDisplayCategory());
2331 Write(_T ( "canvasENCShowDepths" ), cConfig->canvas->GetShowENCDepth());
2332 Write(_T ( "canvasENCShowBuoyLabels" ),
2333 cConfig->canvas->GetShowENCBuoyLabels());
2334 Write(_T ( "canvasENCShowLightDescriptions" ),
2335 cConfig->canvas->GetShowENCLightDesc());
2336 Write(_T ( "canvasENCShowLights" ), cConfig->canvas->GetShowENCLights());
2337 Write(_T ( "canvasENCShowVisibleSectorLights" ),
2338 cConfig->canvas->GetShowVisibleSectors());
2339 Write(_T ( "canvasENCShowAnchorInfo" ),
2340 cConfig->canvas->GetShowENCAnchor());
2341 Write(_T ( "canvasENCShowDataQuality" ),
2342 cConfig->canvas->GetShowENCDataQual());
2343 Write(_T ( "canvasCourseUp" ),
2344 cConfig->canvas->GetUpMode() == COURSE_UP_MODE);
2345 Write(_T ( "canvasHeadUp" ), cConfig->canvas->GetUpMode() == HEAD_UP_MODE);
2346 Write(_T ( "canvasLookahead" ), cConfig->canvas->GetLookahead());
2347
2348 int width = cConfig->canvas->GetSize().x;
2349 // if(cConfig->canvas->IsPrimaryCanvas()){
2350 // width = wxMax(width, gFrame->GetClientSize().x / 10);
2351 // }
2352 // else{
2353 // width = wxMin(width, gFrame->GetClientSize().x * 9 / 10);
2354 // }
2355
2356 Write(_T ( "canvasSizeX" ), width);
2357 Write(_T ( "canvasSizeY" ), cConfig->canvas->GetSize().y);
2358 }
2359}
2360
2361void MyConfig::UpdateSettings() {
2362 // Temporarily suppress logging of trivial non-fatal wxLogSysError() messages
2363 // provoked by Android security...
2364#ifdef __ANDROID__
2365 wxLogNull logNo;
2366#endif
2367
2368 // Global options and settings
2369 SetPath(_T ( "/Settings" ));
2370
2371 Write(_T ( "LastAppliedTemplate" ), g_lastAppliedTemplateGUID);
2372 Write(_T ( "CompatOS" ), g_compatOS);
2373 Write(_T ( "CompatOsVersion" ), g_compatOsVersion);
2374 Write(_T ( "ConfigVersionString" ), g_config_version_string);
2375 if (wxIsEmpty(g_CmdSoundString)) g_CmdSoundString = wxString(OCPN_SOUND_CMD);
2376 Write(_T( "CmdSoundString" ), g_CmdSoundString);
2377 Write(_T ( "NavMessageShown" ), n_NavMessageShown);
2378 Write(_T ( "InlandEcdis" ), g_bInlandEcdis);
2379
2380 Write(_T ( "AndroidVersionCode" ), g_AndroidVersionCode);
2381
2382 Write(_T ( "UIexpert" ), g_bUIexpert);
2383 Write(_T( "SpaceDropMark" ), g_bSpaceDropMark);
2384 // Write( _T ( "UIStyle" ), g_StyleManager->GetStyleNextInvocation() );
2385 // //Not desired for O5 MUI
2386
2387 Write(_T ( "ShowStatusBar" ), g_bShowStatusBar);
2388#ifndef __WXOSX__
2389 Write(_T ( "ShowMenuBar" ), g_bShowMenuBar);
2390#endif
2391 Write(_T ( "DefaultFontSize" ), g_default_font_size);
2392 Write(_T ( "DefaultFontFacename" ), g_default_font_facename);
2393
2394 Write(_T ( "Fullscreen" ), g_bFullscreen);
2395 Write(_T ( "ShowCompassWindow" ), g_bShowCompassWin);
2396 Write(_T ( "SetSystemTime" ), s_bSetSystemTime);
2397 Write(_T ( "ShowGrid" ), g_bDisplayGrid);
2398 Write(_T ( "PlayShipsBells" ), g_bPlayShipsBells);
2399 Write(_T ( "SoundDeviceIndex" ), g_iSoundDeviceIndex);
2400 Write(_T ( "FullscreenToolbar" ), g_bFullscreenToolbar);
2401 Write(_T ( "TransparentToolbar" ), g_bTransparentToolbar);
2402 Write(_T ( "PermanentMOBIcon" ), g_bPermanentMOBIcon);
2403 Write(_T ( "ShowLayers" ), g_bShowLayers);
2404 Write(_T ( "AutoAnchorDrop" ), g_bAutoAnchorMark);
2405 Write(_T ( "ShowChartOutlines" ), g_bShowOutlines);
2406 Write(_T ( "ShowActiveRouteTotal" ), g_bShowRouteTotal);
2407 Write(_T ( "ShowActiveRouteHighway" ), g_bShowActiveRouteHighway);
2408 Write(_T ( "SDMMFormat" ), g_iSDMMFormat);
2409 Write(_T ( "MostRecentGPSUploadConnection" ), g_uploadConnection);
2410 Write(_T ( "ShowChartBar" ), g_bShowChartBar);
2411
2412 Write(_T ( "GUIScaleFactor" ), g_GUIScaleFactor);
2413 Write(_T ( "ChartObjectScaleFactor" ), g_ChartScaleFactor);
2414 Write(_T ( "ShipScaleFactor" ), g_ShipScaleFactor);
2415 Write(_T ( "ENCSoundingScaleFactor" ), g_ENCSoundingScaleFactor);
2416 Write(_T ( "ENCTextScaleFactor" ), g_ENCTextScaleFactor);
2417 Write(_T ( "ObjQueryAppendFilesExt" ), g_ObjQFileExt);
2418
2419 // Plugin catalog persistent values.
2420 Write(_T( "CatalogCustomURL"), g_catalog_custom_url);
2421 Write(_T( "CatalogChannel"), g_catalog_channel);
2422
2423 Write("NetmaskBits", g_netmask_bits);
2424 Write(_T ( "FilterNMEA_Avg" ), g_bfilter_cogsog);
2425 Write(_T ( "FilterNMEA_Sec" ), g_COGFilterSec);
2426
2427 Write(_T ( "TrackContinuous" ), g_btrackContinuous);
2428
2429 Write(_T ( "ShowTrue" ), g_bShowTrue);
2430 Write(_T ( "ShowMag" ), g_bShowMag);
2431 Write(_T ( "UserMagVariation" ), wxString::Format(_T("%.2f"), g_UserVar));
2432
2433 Write(_T ( "CM93DetailFactor" ), g_cm93_zoom_factor);
2434 Write(_T ( "CM93DetailZoomPosX" ), g_detailslider_dialog_x);
2435 Write(_T ( "CM93DetailZoomPosY" ), g_detailslider_dialog_y);
2436 Write(_T ( "ShowCM93DetailSlider" ), g_bShowDetailSlider);
2437
2438 Write(_T ( "SkewToNorthUp" ), g_bskew_comp);
2439 if (!g_bdisable_opengl) { // Only modify the saved value if OpenGL is not
2440 // force-disabled from the command line
2441 Write(_T ( "OpenGL" ), g_bopengl);
2442 }
2443 Write(_T ( "SoftwareGL" ), g_bSoftwareGL);
2444
2445 Write(_T ( "ZoomDetailFactor" ), g_chart_zoom_modifier_raster);
2446 Write(_T ( "ZoomDetailFactorVector" ), g_chart_zoom_modifier_vector);
2447
2448 Write(_T ( "FogOnOverzoom" ), g_fog_overzoom);
2449 Write(_T ( "OverzoomVectorScale" ), g_oz_vector_scale);
2450 Write(_T ( "OverzoomEmphasisBase" ), g_overzoom_emphasis_base);
2451 Write(_T ( "PlusMinusZoomFactor" ), g_plus_minus_zoom_factor);
2452 Write("MouseZoomSensitivity",
2453 MouseZoom::ui_to_config(g_mouse_zoom_sensitivity_ui));
2454 Write(_T ( "ShowMUIZoomButtons" ), g_bShowMuiZoomButtons);
2455
2456#ifdef ocpnUSE_GL
2457 /* opengl options */
2458 Write(_T ( "UseAcceleratedPanning" ), g_GLOptions.m_bUseAcceleratedPanning);
2459
2460 Write(_T ( "GPUTextureCompression" ), g_GLOptions.m_bTextureCompression);
2461 Write(_T ( "GPUTextureCompressionCaching" ),
2462 g_GLOptions.m_bTextureCompressionCaching);
2463 Write(_T ( "GPUTextureDimension" ), g_GLOptions.m_iTextureDimension);
2464 Write(_T ( "GPUTextureMemSize" ), g_GLOptions.m_iTextureMemorySize);
2465 Write(_T ( "PolygonSmoothing" ), g_GLOptions.m_GLPolygonSmoothing);
2466 Write(_T ( "LineSmoothing" ), g_GLOptions.m_GLLineSmoothing);
2467#endif
2468 Write(_T ( "SmoothPanZoom" ), g_bsmoothpanzoom);
2469
2470 Write(_T ( "CourseUpMode" ), g_bCourseUp);
2471 if (!g_bInlandEcdis) Write(_T ( "LookAheadMode" ), g_bLookAhead);
2472 Write(_T ( "TenHzUpdate" ), g_btenhertz);
2473
2474 Write(_T ( "COGUPAvgSeconds" ), g_COGAvgSec);
2475 Write(_T ( "UseMagAPB" ), g_bMagneticAPB);
2476
2477 Write(_T ( "OwnshipCOGPredictorMinutes" ), g_ownship_predictor_minutes);
2478 Write(_T ( "OwnshipCOGPredictorStyle" ), g_cog_predictor_style);
2479 Write(_T ( "OwnshipCOGPredictorColor" ), g_cog_predictor_color);
2480 Write(_T ( "OwnshipCOGPredictorEndmarker" ), g_cog_predictor_endmarker);
2481 Write(_T ( "OwnshipCOGPredictorWidth" ), g_cog_predictor_width);
2482 Write(_T ( "OwnshipHDTPredictorStyle" ), g_ownship_HDTpredictor_style);
2483 Write(_T ( "OwnshipHDTPredictorColor" ), g_ownship_HDTpredictor_color);
2484 Write(_T ( "OwnshipHDTPredictorEndmarker" ),
2485 g_ownship_HDTpredictor_endmarker);
2486 Write(_T ( "OwnShipMMSINumber" ), g_OwnShipmmsi);
2487 Write(_T ( "OwnshipHDTPredictorWidth" ), g_ownship_HDTpredictor_width);
2488 Write(_T ( "OwnshipHDTPredictorMiles" ), g_ownship_HDTpredictor_miles);
2489
2490 Write(_T ( "OwnShipIconType" ), g_OwnShipIconType);
2491 Write(_T ( "OwnShipLength" ), g_n_ownship_length_meters);
2492 Write(_T ( "OwnShipWidth" ), g_n_ownship_beam_meters);
2493 Write(_T ( "OwnShipGPSOffsetX" ), g_n_gps_antenna_offset_x);
2494 Write(_T ( "OwnShipGPSOffsetY" ), g_n_gps_antenna_offset_y);
2495 Write(_T ( "OwnShipMinSize" ), g_n_ownship_min_mm);
2496 Write(_T ( "OwnShipSogCogCalc" ), g_own_ship_sog_cog_calc);
2497 Write(_T ( "OwnShipSogCogCalcDampSec"), g_own_ship_sog_cog_calc_damp_sec);
2498 Write(_T ( "ShowDirectRouteLine"), g_bShowShipToActive);
2499 Write(_T ( "DirectRouteLineStyle"), g_shipToActiveStyle);
2500 Write(_T ( "DirectRouteLineColor" ), g_shipToActiveColor);
2501
2502 wxString racr;
2503 // racr.Printf( _T ( "%g" ), g_n_arrival_circle_radius );
2504 // Write( _T ( "RouteArrivalCircleRadius" ), racr );
2505 Write(_T ( "RouteArrivalCircleRadius" ),
2506 wxString::Format(_T("%.2f"), g_n_arrival_circle_radius));
2507
2508 Write(_T ( "ChartQuilting" ), g_bQuiltEnable);
2509
2510 Write(_T ( "PreserveScaleOnX" ), g_bPreserveScaleOnX);
2511
2512 Write(_T ( "StartWithTrackActive" ), g_bTrackCarryOver);
2513 Write(_T ( "AutomaticDailyTracks" ), g_bTrackDaily);
2514 Write(_T ( "TrackRotateAt" ), g_track_rotate_time);
2515 Write(_T ( "TrackRotateTimeType" ), g_track_rotate_time_type);
2516 Write(_T ( "HighlightTracks" ), g_bHighliteTracks);
2517
2518 Write(_T ( "DateTimeFormat" ), g_datetime_format);
2519 Write(_T ( "InitialStackIndex" ), g_restore_stackindex);
2520 Write(_T ( "InitialdBIndex" ), g_restore_dbindex);
2521
2522 Write(_T( "NMEAAPBPrecision" ), g_NMEAAPBPrecision);
2523
2524 Write(_T("TalkerIdText"), g_TalkerIdText);
2525 Write(_T("ShowTrackPointTime"), g_bShowTrackPointTime);
2526
2527 Write(_T ( "AnchorWatch1GUID" ), g_AW1GUID);
2528 Write(_T ( "AnchorWatch2GUID" ), g_AW2GUID);
2529
2530 Write(_T ( "ToolbarX" ), g_maintoolbar_x);
2531 Write(_T ( "ToolbarY" ), g_maintoolbar_y);
2532 // Write( _T ( "ToolbarOrient" ), g_maintoolbar_orient );
2533
2534 Write(_T ( "iENCToolbarX" ), g_iENCToolbarPosX);
2535 Write(_T ( "iENCToolbarY" ), g_iENCToolbarPosY);
2536
2537 if (!g_bInlandEcdis) {
2538 Write(_T ( "GlobalToolbarConfig" ), g_toolbarConfig);
2539 Write(_T ( "DistanceFormat" ), g_iDistanceFormat);
2540 Write(_T ( "SpeedFormat" ), g_iSpeedFormat);
2541 Write(_T ( "WindSpeedFormat" ), g_iWindSpeedFormat);
2542 Write(_T ( "ShowDepthUnits" ), g_bShowDepthUnits);
2543 Write(_T ( "TemperatureFormat" ), g_iTempFormat);
2544 }
2545 Write(_T ( "GPSIdent" ), g_GPS_Ident);
2546 Write("ActiveRoute", g_active_route);
2547 Write("PersistActiveRoute", g_persist_active_route);
2548 Write(_T ( "UseGarminHostUpload" ), g_bGarminHostUpload);
2549
2550 Write(_T ( "MobileTouch" ), g_btouch);
2551 Write(_T ( "ResponsiveGraphics" ), g_bresponsive);
2552 Write(_T ( "EnableRolloverBlock" ), g_bRollover);
2553
2554 Write(_T ( "AutoHideToolbar" ), g_bAutoHideToolbar);
2555 Write(_T ( "AutoHideToolbarSecs" ), g_nAutoHideToolbar);
2556
2557 wxString st0;
2558 for (const auto &mm : g_config_display_size_mm) {
2559 st0.Append(wxString::Format(_T ( "%zu," ), mm));
2560 }
2561 st0.RemoveLast(); // Strip last comma
2562 Write(_T ( "DisplaySizeMM" ), st0);
2563 Write(_T ( "DisplaySizeManual" ), g_config_display_size_manual);
2564
2565 Write(_T ( "SelectionRadiusMM" ), g_selection_radius_mm);
2566 Write(_T ( "SelectionRadiusTouchMM" ), g_selection_radius_touch_mm);
2567
2568 st0.Printf(_T ( "%g" ), g_PlanSpeed);
2569 Write(_T ( "PlanSpeed" ), st0);
2570
2571 if (g_bLayersLoaded) {
2572 wxString vis, invis, visnames, invisnames;
2573 LayerList::iterator it;
2574 int index = 0;
2575 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
2576 Layer *lay = (Layer *)(*it);
2577 if (lay->IsVisibleOnChart())
2578 vis += (lay->m_LayerName) + _T(";");
2579 else
2580 invis += (lay->m_LayerName) + _T(";");
2581
2582 if (lay->HasVisibleNames() == wxCHK_CHECKED) {
2583 visnames += (lay->m_LayerName) + _T(";");
2584 } else if (lay->HasVisibleNames() == wxCHK_UNCHECKED) {
2585 invisnames += (lay->m_LayerName) + _T(";");
2586 }
2587 }
2588 Write(_T ( "VisibleLayers" ), vis);
2589 Write(_T ( "InvisibleLayers" ), invis);
2590 Write(_T ( "VisNameInLayers" ), visnames);
2591 Write(_T ( "InvisNameInLayers" ), invisnames);
2592 }
2593 Write(_T ( "Locale" ), g_locale);
2594 Write(_T ( "LocaleOverride" ), g_localeOverride);
2595
2596 Write(_T ( "KeepNavobjBackups" ), g_navobjbackups);
2597 Write(_T ( "LegacyInputCOMPortFilterBehaviour" ),
2598 g_b_legacy_input_filter_behaviour);
2599 Write(_T( "AdvanceRouteWaypointOnArrivalOnly" ),
2600 g_bAdvanceRouteWaypointOnArrivalOnly);
2601 Write("EnableRootMenuDebug", g_enable_root_menu_debug);
2602
2603 // LIVE ETA OPTION
2604 Write(_T( "LiveETA" ), g_bShowLiveETA);
2605 Write(_T( "DefaultBoatSpeed" ), g_defaultBoatSpeed);
2606
2607 // S57 Object Filter Settings
2608
2609 SetPath(_T ( "/Settings/ObjectFilter" ));
2610
2611 if (ps52plib) {
2612 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
2613 iPtr++) {
2614 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
2615
2616 wxString st1(_T ( "viz" ));
2617 char name[7];
2618 strncpy(name, pOLE->OBJLName, 6);
2619 name[6] = 0;
2620 st1.Append(wxString(name, wxConvUTF8));
2621 Write(st1, pOLE->nViz);
2622 }
2623 }
2624
2625 // Global State
2626
2627 SetPath(_T ( "/Settings/GlobalState" ));
2628
2629 wxString st1;
2630
2631 // if( cc1 ) {
2632 // ViewPort vp = cc1->GetVP();
2633 //
2634 // if( vp.IsValid() ) {
2635 // st1.Printf( _T ( "%10.4f,%10.4f" ), vp.clat, vp.clon );
2636 // Write( _T ( "VPLatLon" ), st1 );
2637 // st1.Printf( _T ( "%g" ), vp.view_scale_ppm );
2638 // Write( _T ( "VPScale" ), st1 );
2639 // st1.Printf( _T ( "%i" ), ((int)(vp.rotation * 180 / PI)) % 360
2640 // ); Write( _T ( "VPRotation" ), st1 );
2641 // }
2642 // }
2643
2644 st1.Printf(_T ( "%10.4f, %10.4f" ), gLat, gLon);
2645 Write(_T ( "OwnShipLatLon" ), st1);
2646
2647 // Various Options
2648 SetPath(_T ( "/Settings/GlobalState" ));
2649 if (!g_bInlandEcdis)
2650 Write(_T ( "nColorScheme" ), (int)gFrame->GetColorScheme());
2651
2652 Write(_T ( "FrameWinX" ), g_nframewin_x);
2653 Write(_T ( "FrameWinY" ), g_nframewin_y);
2654 Write(_T ( "FrameWinPosX" ), g_nframewin_posx);
2655 Write(_T ( "FrameWinPosY" ), g_nframewin_posy);
2656 Write(_T ( "FrameMax" ), g_bframemax);
2657
2658 Write(_T ( "ClientPosX" ), g_lastClientRectx);
2659 Write(_T ( "ClientPosY" ), g_lastClientRecty);
2660 Write(_T ( "ClientSzX" ), g_lastClientRectw);
2661 Write(_T ( "ClientSzY" ), g_lastClientRecth);
2662
2663 Write(_T ( "S52_DEPTH_UNIT_SHOW" ), g_nDepthUnitDisplay);
2664
2665 Write(_T( "RoutePropSizeX" ), g_route_prop_sx);
2666 Write(_T( "RoutePropSizeY" ), g_route_prop_sy);
2667 Write(_T( "RoutePropPosX" ), g_route_prop_x);
2668 Write(_T( "RoutePropPosY" ), g_route_prop_y);
2669
2670 // Sounds
2671 SetPath(_T ( "/Settings/Audio" ));
2672 Write(_T ( "AISAlertSoundFile" ), g_AIS_sound_file);
2673 Write(_T ( "DSCAlertSoundFile" ), g_DSC_sound_file);
2674 Write(_T ( "SARTAlertSoundFile" ), g_SART_sound_file);
2675 Write(_T ( "AnchorAlarmSoundFile" ), g_anchorwatch_sound_file);
2676
2677 Write(_T ( "bAIS_GCPA_AlertAudio" ), g_bAIS_GCPA_Alert_Audio);
2678 Write(_T ( "bAIS_SART_AlertAudio" ), g_bAIS_SART_Alert_Audio);
2679 Write(_T ( "bAIS_DSC_AlertAudio" ), g_bAIS_DSC_Alert_Audio);
2680 Write(_T ( "bAnchorAlertAudio" ), g_bAnchor_Alert_Audio);
2681
2682 // AIS
2683 SetPath(_T ( "/Settings/AIS" ));
2684
2685 Write(_T ( "bNoCPAMax" ), g_bCPAMax);
2686 Write(_T ( "NoCPAMaxNMi" ), g_CPAMax_NM);
2687 Write(_T ( "bCPAWarn" ), g_bCPAWarn);
2688 Write(_T ( "CPAWarnNMi" ), g_CPAWarn_NM);
2689 Write(_T ( "bTCPAMax" ), g_bTCPA_Max);
2690 Write(_T ( "TCPAMaxMinutes" ), g_TCPA_Max);
2691 Write(_T ( "bMarkLostTargets" ), g_bMarkLost);
2692 Write(_T ( "MarkLost_Minutes" ), g_MarkLost_Mins);
2693 Write(_T ( "bRemoveLostTargets" ), g_bRemoveLost);
2694 Write(_T ( "RemoveLost_Minutes" ), g_RemoveLost_Mins);
2695 Write(_T ( "bShowCOGArrows" ), g_bShowCOG);
2696 Write(_T ( "bSyncCogPredictors" ), g_bSyncCogPredictors);
2697 Write(_T ( "CogArrowMinutes" ), g_ShowCOG_Mins);
2698 Write(_T ( "bShowTargetTracks" ), g_bAISShowTracks);
2699 Write(_T ( "TargetTracksMinutes" ), g_AISShowTracks_Mins);
2700
2701 Write(_T ( "bHideMooredTargets" ), g_bHideMoored);
2702 Write(_T ( "MooredTargetMaxSpeedKnots" ), g_ShowMoored_Kts);
2703
2704 Write(_T ( "bAISAlertDialog" ), g_bAIS_CPA_Alert);
2705 Write(_T ( "bAISAlertAudio" ), g_bAIS_CPA_Alert_Audio);
2706
2707 Write(_T ( "AISAlertAudioFile" ), g_sAIS_Alert_Sound_File);
2708 Write(_T ( "bAISAlertSuppressMoored" ), g_bAIS_CPA_Alert_Suppress_Moored);
2709 Write(_T ( "bShowAreaNotices" ), g_bShowAreaNotices);
2710 Write(_T ( "bDrawAISSize" ), g_bDrawAISSize);
2711 Write(_T ( "bDrawAISRealtime" ), g_bDrawAISRealtime);
2712 Write(_T ( "AISRealtimeMinSpeedKnots" ), g_AIS_RealtPred_Kts);
2713 Write(_T ( "bShowAISName" ), g_bShowAISName);
2714 Write(_T ( "ShowAISTargetNameScale" ), g_Show_Target_Name_Scale);
2715 Write(_T ( "bWplIsAprsPositionReport" ), g_bWplUsePosition);
2716 Write(_T ( "WplSelAction" ), g_WplAction);
2717 Write(_T ( "AISCOGPredictorWidth" ), g_ais_cog_predictor_width);
2718 Write(_T ( "bShowScaledTargets" ), g_bAllowShowScaled);
2719 Write(_T ( "AISScaledNumber" ), g_ShowScaled_Num);
2720 Write(_T ( "AISScaledNumberWeightSOG" ), g_ScaledNumWeightSOG);
2721 Write(_T ( "AISScaledNumberWeightCPA" ), g_ScaledNumWeightCPA);
2722 Write(_T ( "AISScaledNumberWeightTCPA" ), g_ScaledNumWeightTCPA);
2723 Write(_T ( "AISScaledNumberWeightRange" ), g_ScaledNumWeightRange);
2724 Write(_T ( "AISScaledNumberWeightSizeOfTarget" ), g_ScaledNumWeightSizeOfT);
2725 Write(_T ( "AISScaledSizeMinimal" ), g_ScaledSizeMinimal);
2726 Write(_T ( "AISShowScaled"), g_bShowScaled);
2727
2728 Write(_T ( "AlertDialogSizeX" ), g_ais_alert_dialog_sx);
2729 Write(_T ( "AlertDialogSizeY" ), g_ais_alert_dialog_sy);
2730 Write(_T ( "AlertDialogPosX" ), g_ais_alert_dialog_x);
2731 Write(_T ( "AlertDialogPosY" ), g_ais_alert_dialog_y);
2732 Write(_T ( "QueryDialogPosX" ), g_ais_query_dialog_x);
2733 Write(_T ( "QueryDialogPosY" ), g_ais_query_dialog_y);
2734 Write(_T ( "AISTargetListPerspective" ), g_AisTargetList_perspective);
2735 Write(_T ( "AISTargetListRange" ), g_AisTargetList_range);
2736 Write(_T ( "AISTargetListSortColumn" ), g_AisTargetList_sortColumn);
2737 Write(_T ( "bAISTargetListSortReverse" ), g_bAisTargetList_sortReverse);
2738 Write(_T ( "AISTargetListColumnSpec" ), g_AisTargetList_column_spec);
2739 Write(_T ("AISTargetListColumnOrder"), g_AisTargetList_column_order);
2740
2741 Write(_T ( "S57QueryDialogSizeX" ), g_S57_dialog_sx);
2742 Write(_T ( "S57QueryDialogSizeY" ), g_S57_dialog_sy);
2743 Write(_T ( "S57QueryExtraDialogSizeX" ), g_S57_extradialog_sx);
2744 Write(_T ( "S57QueryExtraDialogSizeY" ), g_S57_extradialog_sy);
2745
2746 Write(_T ( "bAISRolloverShowClass" ), g_bAISRolloverShowClass);
2747 Write(_T ( "bAISRolloverShowCOG" ), g_bAISRolloverShowCOG);
2748 Write(_T ( "bAISRolloverShowCPA" ), g_bAISRolloverShowCPA);
2749
2750 Write(_T ( "bAISAlertAckTimeout" ), g_bAIS_ACK_Timeout);
2751 Write(_T ( "AlertAckTimeoutMinutes" ), g_AckTimeout_Mins);
2752
2753 SetPath(_T ( "/Settings/GlobalState" ));
2754 if (ps52plib) {
2755 Write(_T ( "bShowS57Text" ), ps52plib->GetShowS57Text());
2756 Write(_T ( "bShowS57ImportantTextOnly" ),
2757 ps52plib->GetShowS57ImportantTextOnly());
2758 if (!g_bInlandEcdis)
2759 Write(_T ( "nDisplayCategory" ), (long)ps52plib->GetDisplayCategory());
2760 Write(_T ( "nSymbolStyle" ), (int)ps52plib->m_nSymbolStyle);
2761 Write(_T ( "nBoundaryStyle" ), (int)ps52plib->m_nBoundaryStyle);
2762
2763 Write(_T ( "bShowSoundg" ), ps52plib->m_bShowSoundg);
2764 Write(_T ( "bShowMeta" ), ps52plib->m_bShowMeta);
2765 Write(_T ( "bUseSCAMIN" ), ps52plib->m_bUseSCAMIN);
2766 Write(_T ( "bUseSUPER_SCAMIN" ), ps52plib->m_bUseSUPER_SCAMIN);
2767 Write(_T ( "bShowAtonText" ), ps52plib->m_bShowAtonText);
2768 Write(_T ( "bShowLightDescription" ), ps52plib->m_bShowLdisText);
2769 Write(_T ( "bExtendLightSectors" ), ps52plib->m_bExtendLightSectors);
2770 Write(_T ( "bDeClutterText" ), ps52plib->m_bDeClutterText);
2771 Write(_T ( "bShowNationalText" ), ps52plib->m_bShowNationalTexts);
2772
2773 Write(_T ( "S52_MAR_SAFETY_CONTOUR" ),
2774 S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR));
2775 Write(_T ( "S52_MAR_SHALLOW_CONTOUR" ),
2776 S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR));
2777 Write(_T ( "S52_MAR_DEEP_CONTOUR" ),
2778 S52_getMarinerParam(S52_MAR_DEEP_CONTOUR));
2779 Write(_T ( "S52_MAR_TWO_SHADES" ), S52_getMarinerParam(S52_MAR_TWO_SHADES));
2780 Write(_T ( "S52_DEPTH_UNIT_SHOW" ), ps52plib->m_nDepthUnitDisplay);
2781 Write(_T ( "ENCSoundingScaleFactor" ), g_ENCSoundingScaleFactor);
2782 Write(_T ( "ENCTextScaleFactor" ), g_ENCTextScaleFactor);
2783 }
2784 SetPath(_T ( "/Directories" ));
2785 Write(_T ( "S57DataLocation" ), _T(""));
2786 // Write( _T ( "SENCFileLocation" ), _T("") );
2787
2788 SetPath(_T ( "/Directories" ));
2789 Write(_T ( "InitChartDir" ), *pInit_Chart_Dir);
2790 Write(_T ( "GPXIODir" ), g_gpx_path);
2791 Write(_T ( "TCDataDir" ), g_TCData_Dir);
2792 Write(_T ( "BasemapDir" ), g_Platform->NormalizePath(gWorldMapLocation));
2793 Write(_T ( "BaseShapefileDir" ),
2794 g_Platform->NormalizePath(gWorldShapefileLocation));
2795 Write(_T ( "pluginInstallDir" ), g_Platform->NormalizePath(g_winPluginDir));
2796
2797 SetPath(_T ( "/Settings/NMEADataSource" ));
2798 wxString connectionconfigs;
2799 for (size_t i = 0; i < TheConnectionParams().size(); i++) {
2800 if (i > 0) connectionconfigs.Append(_T("|"));
2801 connectionconfigs.Append(TheConnectionParams()[i]->Serialize());
2802 }
2803 Write(_T ( "DataConnections" ), connectionconfigs);
2804
2805 // Fonts
2806
2807 // Store the persistent Auxiliary Font descriptor Keys
2808 SetPath(_T ( "/Settings/AuxFontKeys" ));
2809
2810 wxArrayString keyArray = FontMgr::Get().GetAuxKeyArray();
2811 for (unsigned int i = 0; i < keyArray.GetCount(); i++) {
2812 wxString key;
2813 key.Printf(_T("Key%i"), i);
2814 wxString keyval = keyArray[i];
2815 Write(key, keyval);
2816 }
2817
2818 wxString font_path;
2819#ifdef __WXX11__
2820 font_path = (_T ( "/Settings/X11Fonts" ));
2821#endif
2822
2823#ifdef __WXGTK__
2824 font_path = (_T ( "/Settings/GTKFonts" ));
2825#endif
2826
2827#ifdef __WXMSW__
2828 font_path = (_T ( "/Settings/MSWFonts" ));
2829#endif
2830
2831#ifdef __WXMAC__
2832 font_path = (_T ( "/Settings/MacFonts" ));
2833#endif
2834
2835#ifdef __WXQT__
2836 font_path = (_T ( "/Settings/QTFonts" ));
2837#endif
2838
2839 DeleteGroup(font_path);
2840
2841 SetPath(font_path);
2842
2843 int nFonts = FontMgr::Get().GetNumFonts();
2844
2845 for (int i = 0; i < nFonts; i++) {
2846 wxString cfstring(FontMgr::Get().GetConfigString(i));
2847 wxString valstring = FontMgr::Get().GetFullConfigDesc(i);
2848 Write(cfstring, valstring);
2849 }
2850
2851 // Tide/Current Data Sources
2852 DeleteGroup(_T ( "/TideCurrentDataSources" ));
2853 SetPath(_T ( "/TideCurrentDataSources" ));
2854 unsigned int id = 0;
2855 for (auto val : TideCurrentDataSet) {
2856 wxString key;
2857 key.Printf(_T("tcds%d"), id);
2858 Write(key, wxString(val));
2859 ++id;
2860 }
2861
2862 SetPath(_T ( "/Settings/Others" ));
2863
2864 // Radar rings
2865 Write(_T ( "ShowRadarRings" ),
2866 (bool)(g_iNavAidRadarRingsNumberVisible > 0)); // 3.0.0 config support
2867 Write(_T ( "RadarRingsNumberVisible" ), g_iNavAidRadarRingsNumberVisible);
2868 Write(_T ( "RadarRingsStep" ), g_fNavAidRadarRingsStep);
2869 Write(_T ( "RadarRingsStepUnits" ), g_pNavAidRadarRingsStepUnits);
2870 Write(_T ( "RadarRingsColour" ),
2871 g_colourOwnshipRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2872 Write(_T( "WaypointUseScaMin" ), g_bUseWptScaMin);
2873 Write(_T( "WaypointScaMinValue" ), g_iWpt_ScaMin);
2874 Write(_T( "WaypointUseScaMinOverrule" ), g_bOverruleScaMin);
2875 Write(_T("WaypointsShowName"), g_bShowWptName);
2876 Write(_T("UserIconsFirst"), g_bUserIconsFirst);
2877
2878 // Waypoint Radar rings
2879 Write(_T ( "WaypointRangeRingsNumber" ), g_iWaypointRangeRingsNumber);
2880 Write(_T ( "WaypointRangeRingsStep" ), g_fWaypointRangeRingsStep);
2881 Write(_T ( "WaypointRangeRingsStepUnits" ), g_iWaypointRangeRingsStepUnits);
2882 Write(_T ( "WaypointRangeRingsColour" ),
2883 g_colourWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2884
2885 Write(_T ( "ConfirmObjectDeletion" ), g_bConfirmObjectDelete);
2886
2887 // Waypoint dragging with mouse; toh, 2009.02.24
2888 Write(_T ( "WaypointPreventDragging" ), g_bWayPointPreventDragging);
2889
2890 Write(_T ( "EnableZoomToCursor" ), g_bEnableZoomToCursor);
2891
2892 Write(_T ( "TrackIntervalSeconds" ), g_TrackIntervalSeconds);
2893 Write(_T ( "TrackDeltaDistance" ), g_TrackDeltaDistance);
2894 Write(_T ( "TrackPrecision" ), g_nTrackPrecision);
2895
2896 Write(_T ( "RouteLineWidth" ), g_route_line_width);
2897 Write(_T ( "TrackLineWidth" ), g_track_line_width);
2898 Write(_T ( "TrackLineColour" ),
2899 g_colourTrackLineColour.GetAsString(wxC2S_HTML_SYNTAX));
2900 Write(_T ( "DefaultWPIcon" ), g_default_wp_icon);
2901 Write(_T ( "DefaultRPIcon" ), g_default_routepoint_icon);
2902
2903 DeleteGroup(_T ( "/MmsiProperties" ));
2904 SetPath(_T ( "/MmsiProperties" ));
2905 for (unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
2906 wxString p;
2907 p.Printf(_T("Props%d"), i);
2908 Write(p, g_MMSI_Props_Array[i]->Serialize());
2909 }
2910
2911 SaveCanvasConfigs();
2912
2913 Flush();
2914 SendMessageToAllPlugins("GLOBAL_SETTINGS_UPDATED", wxEmptyString);
2915}
2916
2917void MyConfig::UpdateNavObjOnly() {
2918 // Create the NavObjectCollection, and save to specified file
2919 NavObjectCollection1 *pNavObjectSet = new NavObjectCollection1();
2920
2921 pNavObjectSet->CreateAllGPXObjects();
2922 pNavObjectSet->SaveFile(m_sNavObjSetFile);
2923
2924 delete pNavObjectSet;
2925}
2926
2927void MyConfig::UpdateNavObj(bool bRecreate) {
2928 // Create the NavObjectCollection, and save to specified file
2929 NavObjectCollection1 *pNavObjectSet = new NavObjectCollection1();
2930
2931 pNavObjectSet->CreateAllGPXObjects();
2932 pNavObjectSet->SaveFile(m_sNavObjSetFile);
2933
2934 delete pNavObjectSet;
2935
2936 if (m_pNavObjectChangesSet->m_changes_file)
2937 fclose(m_pNavObjectChangesSet->m_changes_file);
2938
2939 if (::wxFileExists(m_sNavObjSetChangesFile)) {
2940 wxLogNull logNo; // avoid silly log error message.
2941 wxRemoveFile(m_sNavObjSetChangesFile);
2942 }
2943
2944 if (bRecreate) {
2945 m_pNavObjectChangesSet->Init(m_sNavObjSetChangesFile);
2946
2947 m_pNavObjectChangesSet->reset();
2948 if (m_pNavObjectChangesSet->load_file(m_sNavObjSetChangesFile.fn_str())
2949 .status != pugi::xml_parse_status::status_ok) {
2950 wxLogMessage("Error while loading " + m_sNavObjSetChangesFile +
2951 ", ignoring contents of the file.");
2952 m_pNavObjectChangesSet->reset();
2953 }
2954 }
2955}
2956
2957static wxFileName exportFileName(wxWindow *parent,
2958 const wxString suggestedName) {
2959 wxFileName ret;
2960 wxString path;
2961 wxString validName{suggestedName};
2962 // replace common date characters invalid in filename
2963 // MS-DOS file systems have many more
2964 validName.Replace(_T("/"), _T("-"));
2965 validName.Replace(_T(":"), _T("_"));
2966
2967#ifdef __ANDROID__
2968 if (!validName.EndsWith(".gpx")) {
2969 wxFileName fn(validName);
2970 fn.ClearExt();
2971 fn.SetExt("gpx");
2972 validName = fn.GetFullName();
2973 }
2974#endif
2975 int response = g_Platform->DoFileSelectorDialog(
2976 parent, &path, _("Export GPX file"), g_gpx_path, validName, wxT("*.gpx"));
2977
2978 if (response == wxID_OK) {
2979 wxFileName fn(path);
2980 g_gpx_path = fn.GetPath();
2981 fn.SetExt(_T("gpx"));
2982
2983#ifndef __WXMAC__
2984 if (wxFileExists(fn.GetFullPath())) {
2985 int answer =
2986 OCPNMessageBox(NULL, _("Overwrite existing file?"), _T("Confirm"),
2987 wxICON_QUESTION | wxYES_NO | wxCANCEL);
2988 if (answer != wxID_YES) return ret;
2989 }
2990#endif
2991 ret = fn;
2992 }
2993 return ret;
2994}
2995
2996bool MyConfig::IsChangesFileDirty() {
2997 return m_pNavObjectChangesSet->IsDirty();
2998}
2999
3000bool ExportGPXRoutes(wxWindow *parent, RouteList *pRoutes,
3001 const wxString suggestedName) {
3002 wxFileName fn = exportFileName(parent, suggestedName);
3003 if (fn.IsOk()) {
3005 pgpx->AddGPXRoutesList(pRoutes);
3006
3007#ifdef __ANDROID__
3008 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
3009 fn.GetFullName();
3010 pgpx->SaveFile(fns);
3011 AndroidSecureCopyFile(fns, fn.GetFullPath());
3012#else
3013 pgpx->SaveFile(fn.GetFullPath());
3014
3015#endif
3016
3017 delete pgpx;
3018
3019 return true;
3020 }
3021 return false;
3022}
3023
3024bool ExportGPXTracks(wxWindow *parent, std::vector<Track *> *pTracks,
3025 const wxString suggestedName) {
3026 wxFileName fn = exportFileName(parent, suggestedName);
3027 if (fn.IsOk()) {
3029 pgpx->AddGPXTracksList(pTracks);
3030#ifdef __ANDROID__
3031 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
3032 fn.GetFullName();
3033 pgpx->SaveFile(fns);
3034 AndroidSecureCopyFile(fns, fn.GetFullPath());
3035#else
3036 pgpx->SaveFile(fn.GetFullPath());
3037#endif
3038 delete pgpx;
3039
3040 return true;
3041 }
3042 return false;
3043}
3044
3045bool ExportGPXWaypoints(wxWindow *parent, RoutePointList *pRoutePoints,
3046 const wxString suggestedName) {
3047 wxFileName fn = exportFileName(parent, suggestedName);
3048 if (fn.IsOk()) {
3050 pgpx->AddGPXPointsList(pRoutePoints);
3051
3052#ifdef __ANDROID__
3053 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
3054 fn.GetFullName();
3055 pgpx->SaveFile(fns);
3056 AndroidSecureCopyFile(fns, fn.GetFullPath());
3057#else
3058 pgpx->SaveFile(fn.GetFullPath());
3059#endif
3060
3061 delete pgpx;
3062
3063 return true;
3064 }
3065 return false;
3066}
3067
3068void ExportGPX(wxWindow *parent, bool bviz_only, bool blayer) {
3069 wxFileName fn = exportFileName(parent, _T("userobjects.gpx"));
3070 if (fn.IsOk()) {
3071 ::wxBeginBusyCursor();
3072
3074
3075 wxGenericProgressDialog *pprog = nullptr;
3076 int count = pWayPointMan->GetWaypointList()->GetCount();
3077 int progStep = count / 32;
3078 if (count > 200) {
3079 pprog = new wxGenericProgressDialog(
3080 _("Export GPX file"), _T("0/0"), count, NULL,
3081 wxPD_APP_MODAL | wxPD_SMOOTH | wxPD_ELAPSED_TIME |
3082 wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME);
3083 pprog->SetSize(400, wxDefaultCoord);
3084 pprog->Centre();
3085 }
3086
3087 // WPTs
3088 int ic = 1;
3089
3090 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
3091 RoutePoint *pr;
3092 while (node) {
3093 if (pprog && !(ic % progStep)) {
3094 wxString msg;
3095 msg.Printf(_T("%d/%d"), ic, count);
3096 pprog->Update(ic, msg);
3097 }
3098 ic++;
3099
3100 pr = node->GetData();
3101
3102 bool b_add = true;
3103
3104 if (bviz_only && !pr->m_bIsVisible) b_add = false;
3105
3106 if (pr->m_bIsInLayer && !blayer) b_add = false;
3107 if (b_add) {
3108 if (pr->IsShared() || !WptIsInRouteList(pr)) pgpx->AddGPXWaypoint(pr);
3109 }
3110
3111 node = node->GetNext();
3112 }
3113 // RTEs and TRKs
3114 wxRouteListNode *node1 = pRouteList->GetFirst();
3115 while (node1) {
3116 Route *pRoute = node1->GetData();
3117
3118 bool b_add = true;
3119
3120 if (bviz_only && !pRoute->IsVisible()) b_add = false;
3121
3122 if (pRoute->m_bIsInLayer && !blayer) b_add = false;
3123
3124 if (b_add) pgpx->AddGPXRoute(pRoute);
3125
3126 node1 = node1->GetNext();
3127 }
3128
3129 for (Track *pTrack : g_TrackList) {
3130 bool b_add = true;
3131
3132 if (bviz_only && !pTrack->IsVisible()) b_add = false;
3133
3134 if (pTrack->m_bIsInLayer && !blayer) b_add = false;
3135
3136 if (b_add) pgpx->AddGPXTrack(pTrack);
3137 }
3138
3139 // Android 5+ requires special handling to support native app file writes to
3140 // SDCard We need to use a two step copy process using a guaranteed
3141 // accessible location for the first step.
3142#ifdef __ANDROID__
3143 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
3144 fn.GetFullName();
3145 pgpx->SaveFile(fns);
3146 AndroidSecureCopyFile(fns, fn.GetFullPath());
3147#else
3148 pgpx->SaveFile(fn.GetFullPath());
3149#endif
3150
3151 delete pgpx;
3152 ::wxEndBusyCursor();
3153
3154 delete pprog;
3155 }
3156}
3157
3158void UI_ImportGPX(wxWindow *parent, bool islayer, wxString dirpath,
3159 bool isdirectory, bool isPersistent) {
3160 int response = wxID_CANCEL;
3161 wxArrayString file_array;
3162 Layer *l = NULL;
3163
3164 if (!islayer || dirpath.IsSameAs(_T(""))) {
3165 // Platform DoFileSelectorDialog method does not properly handle multiple
3166 // selections So use native method if not Android, which means Android gets
3167 // single selection only.
3168#ifndef __ANDROID__
3169 wxFileDialog *popenDialog =
3170 new wxFileDialog(NULL, _("Import GPX file"), g_gpx_path, wxT(""),
3171 wxT("GPX files (*.gpx)|*.gpx|All files (*.*)|*.*"),
3172 wxFD_OPEN | wxFD_MULTIPLE);
3173
3174 if (g_bresponsive && parent)
3175 popenDialog = g_Platform->AdjustFileDialogFont(parent, popenDialog);
3176
3177 popenDialog->Centre();
3178
3179#ifdef __WXOSX__
3180 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
3181#endif
3182
3183 response = popenDialog->ShowModal();
3184
3185#ifdef __WXOSX__
3186 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
3187#endif
3188
3189 if (response == wxID_OK) {
3190 popenDialog->GetPaths(file_array);
3191
3192 // Record the currently selected directory for later use
3193 if (file_array.GetCount()) {
3194 wxFileName fn(file_array[0]);
3195 g_gpx_path = fn.GetPath();
3196 }
3197 }
3198 delete popenDialog;
3199#else
3200 wxString path;
3201 response = g_Platform->DoFileSelectorDialog(
3202 NULL, &path, _("Import GPX file"), g_gpx_path, _T(""), wxT("*.gpx"));
3203
3204 file_array.Add(path);
3205 wxFileName fn(path);
3206 g_gpx_path = fn.GetPath();
3207
3208#endif
3209
3210 } else {
3211 if (isdirectory) {
3212 if (wxDir::GetAllFiles(dirpath, &file_array, wxT("*.gpx")))
3213 response = wxID_OK;
3214 } else {
3215 file_array.Add(dirpath);
3216 response = wxID_OK;
3217 }
3218 }
3219
3220 if (response == wxID_OK) {
3221 if (islayer) {
3222 l = new Layer();
3223 l->m_LayerID = ++g_LayerIdx;
3224 l->m_LayerFileName = file_array[0];
3225 if (file_array.GetCount() <= 1)
3226 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName),
3227 NULL, NULL);
3228 else {
3229 if (dirpath.IsSameAs(_T("")))
3230 wxFileName::SplitPath(g_gpx_path, NULL, NULL, &(l->m_LayerName), NULL,
3231 NULL);
3232 else
3233 wxFileName::SplitPath(dirpath, NULL, NULL, &(l->m_LayerName), NULL,
3234 NULL);
3235 }
3236
3237 bool bLayerViz = g_bShowLayers;
3238 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
3239 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
3240 l->m_bIsVisibleOnChart = bLayerViz;
3241
3242 // Default for new layers is "Names visible"
3243 l->m_bHasVisibleNames = wxCHK_CHECKED;
3244
3245 wxString laymsg;
3246 laymsg.Printf(wxT("New layer %d: %s"), l->m_LayerID,
3247 l->m_LayerName.c_str());
3248 wxLogMessage(laymsg);
3249
3250 pLayerList->Insert(l);
3251 }
3252
3253 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
3254 wxString path = file_array[i];
3255
3256 if (::wxFileExists(path)) {
3258 if (pSet->load_file(path.fn_str()).status !=
3259 pugi::xml_parse_status::status_ok) {
3260 wxLogMessage("Error loading GPX file " + path);
3261 pSet->reset();
3262 delete pSet;
3263 continue;
3264 }
3265
3266 if (islayer) {
3267 l->m_NoOfItems = pSet->LoadAllGPXObjectsAsLayer(
3268 l->m_LayerID, l->m_bIsVisibleOnChart, l->m_bHasVisibleNames);
3269 l->m_LayerType = isPersistent ? _("Persistent") : _("Temporary");
3270
3271 if (isPersistent) {
3272 // If this is a persistent layer also copy the file to config file
3273 // dir /layers
3274 wxString destf, f, name, ext;
3275 f = l->m_LayerFileName;
3276 wxFileName::SplitPath(f, NULL, NULL, &name, &ext);
3277 destf = g_Platform->GetPrivateDataDir();
3278 appendOSDirSlash(&destf);
3279 destf.Append(_T("layers"));
3280 appendOSDirSlash(&destf);
3281 if (!wxDirExists(destf)) {
3282 if (!wxMkdir(destf, wxS_DIR_DEFAULT))
3283 wxLogMessage(_T("Error creating layer directory"));
3284 }
3285
3286 destf << name << _T(".") << ext;
3287 wxString msg;
3288 if (wxCopyFile(f, destf, true))
3289 msg.Printf(_T("File: %s.%s also added to persistent layers"),
3290 name, ext);
3291 else
3292 msg.Printf(_T("Failed adding %s.%s to persistent layers"), name,
3293 ext);
3294 wxLogMessage(msg);
3295 }
3296 } else {
3297 int wpt_dups;
3298 pSet->LoadAllGPXObjects(
3299 !pSet->IsOpenCPN(),
3300 wpt_dups); // Import with full visibility of names and objects
3301 if (wpt_dups > 0) {
3302 OCPNMessageBox(
3303 parent,
3304 wxString::Format(_T("%d ") + _("duplicate waypoints detected "
3305 "during import and ignored."),
3306 wpt_dups),
3307 _("OpenCPN Info"), wxICON_INFORMATION | wxOK, 10);
3308 }
3309 }
3310 delete pSet;
3311 }
3312 }
3313 }
3314}
3315
3316//-------------------------------------------------------------------------
3317// Static Routine Switch to Inland Ecdis Mode
3318//-------------------------------------------------------------------------
3319void SwitchInlandEcdisMode(bool Switch) {
3320 if (Switch) {
3321 wxLogMessage(_T("Switch InlandEcdis mode On"));
3322 LoadS57();
3323 // Overule some sewttings to comply with InlandEcdis
3324 // g_toolbarConfig = _T ( ".....XXXX.X...XX.XXXXXXXXXXXX" );
3325 g_iDistanceFormat = 2; // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
3326 // "Kilometers", 3 = "Meters"
3327 g_iSpeedFormat = 2; // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
3328 if (ps52plib) ps52plib->SetDisplayCategory(STANDARD);
3329 g_bDrawAISSize = false;
3330 if (gFrame) gFrame->RequestNewToolbars(true);
3331 } else {
3332 wxLogMessage(_T("Switch InlandEcdis mode Off"));
3333 // reread the settings overruled by inlandEcdis
3334 if (pConfig) {
3335 pConfig->SetPath(_T ( "/Settings" ));
3336 pConfig->Read(_T ( "GlobalToolbarConfig" ), &g_toolbarConfig);
3337 pConfig->Read(_T ( "DistanceFormat" ), &g_iDistanceFormat);
3338 pConfig->Read(_T ( "SpeedFormat" ), &g_iSpeedFormat);
3339 pConfig->Read(_T ( "ShowDepthUnits" ), &g_bShowDepthUnits, 1);
3340 int read_int;
3341 pConfig->Read(_T ( "nDisplayCategory" ), &read_int,
3342 (enum _DisCat)STANDARD);
3343 if (ps52plib) ps52plib->SetDisplayCategory((enum _DisCat)read_int);
3344 pConfig->SetPath(_T ( "/Settings/AIS" ));
3345 pConfig->Read(_T ( "bDrawAISSize" ), &g_bDrawAISSize);
3346 pConfig->Read(_T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime);
3347 }
3348 if (gFrame) gFrame->RequestNewToolbars(true);
3349 }
3350}
3351
3352//-------------------------------------------------------------------------
3353//
3354// Static GPX Support Routines
3355//
3356//-------------------------------------------------------------------------
3357// This function formats the input date/time into a valid GPX ISO 8601
3358// time string specified in the UTC time zone.
3359
3360wxString FormatGPXDateTime(wxDateTime dt) {
3361 // return dt.Format(wxT("%Y-%m-%dT%TZ"), wxDateTime::GMT0);
3362 return dt.Format(wxT("%Y-%m-%dT%H:%M:%SZ"));
3363}
3364
3365/**************************************************************************/
3366/* LogMessageOnce */
3367/**************************************************************************/
3368
3369bool LogMessageOnce(const wxString &msg) {
3370 // Search the array for a match
3371
3372 for (unsigned int i = 0; i < pMessageOnceArray->GetCount(); i++) {
3373 if (msg.IsSameAs(pMessageOnceArray->Item(i))) return false;
3374 }
3375
3376 // Not found, so add to the array
3377 pMessageOnceArray->Add(msg);
3378
3379 // And print it
3380 wxLogMessage(msg);
3381 return true;
3382}
3383
3384/**************************************************************************/
3385/* Some assorted utilities */
3386/**************************************************************************/
3387
3388wxDateTime toUsrDateTime(const wxDateTime ts, const int format,
3389 const double lon) {
3390 if (!ts.IsValid()) {
3391 return ts;
3392 }
3393 int effective_format = format;
3394 if (effective_format == GLOBAL_SETTINGS_INPUT) {
3395 if (::g_datetime_format == "UTC") {
3396 effective_format = UTCINPUT;
3397 } else if (::g_datetime_format == "LMT") {
3398 effective_format = LMTINPUT;
3399 } else if (::g_datetime_format == "Local Time") {
3400 effective_format = LTINPUT;
3401 } else {
3402 // Default to UTC
3403 effective_format = UTCINPUT;
3404 }
3405 }
3406 wxDateTime dt;
3407 switch (effective_format) {
3408 case LMTINPUT: // LMT@Location
3409 if (std::isnan(lon)) {
3410 dt = wxInvalidDateTime;
3411 } else {
3412 dt =
3413 ts.Add(wxTimeSpan(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.))));
3414 }
3415 break;
3416 case LTINPUT: // Local@PC
3417 // Convert date/time from UTC to local time.
3418 dt = ts.FromUTC();
3419 break;
3420 case UTCINPUT: // UTC
3421 // The date/time is already in UTC.
3422 dt = ts;
3423 break;
3424 }
3425 return dt;
3426}
3427
3428wxDateTime fromUsrDateTime(const wxDateTime ts, const int format,
3429 const double lon) {
3430 if (!ts.IsValid()) {
3431 return ts;
3432 }
3433 int effective_format = format;
3434 if (effective_format == GLOBAL_SETTINGS_INPUT) {
3435 if (::g_datetime_format == "UTC") {
3436 effective_format = UTCINPUT;
3437 } else if (::g_datetime_format == "LMT") {
3438 effective_format = LMTINPUT;
3439 } else if (::g_datetime_format == "Local Time") {
3440 effective_format = LTINPUT;
3441 } else {
3442 // Default to UTC
3443 effective_format = UTCINPUT;
3444 }
3445 }
3446 wxDateTime dt;
3447 switch (effective_format) {
3448 case LMTINPUT: // LMT@Location
3449 if (std::isnan(lon)) {
3450 dt = wxInvalidDateTime;
3451 } else {
3452 dt = ts.Subtract(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.)));
3453 }
3454 break;
3455 case LTINPUT: // Local@PC
3456 // The input date/time is in local time, so convert it to UTC.
3457 dt = ts.ToUTC();
3458 break;
3459 case UTCINPUT: // UTC
3460 dt = ts;
3461 break;
3462 }
3463 return dt;
3464}
3465
3466/**************************************************************************/
3467/* Converts the distance from the units selected by user to NMi */
3468/**************************************************************************/
3469double fromUsrDistance(double usr_distance, int unit) {
3470 double ret = NAN;
3471 if (unit == -1) unit = g_iDistanceFormat;
3472 switch (unit) {
3473 case DISTANCE_NMI: // Nautical miles
3474 ret = usr_distance;
3475 break;
3476 case DISTANCE_MI: // Statute miles
3477 ret = usr_distance / 1.15078;
3478 break;
3479 case DISTANCE_KM:
3480 ret = usr_distance / 1.852;
3481 break;
3482 case DISTANCE_M:
3483 ret = usr_distance / 1852;
3484 break;
3485 case DISTANCE_FT:
3486 ret = usr_distance / 6076.12;
3487 break;
3488 }
3489 return ret;
3490}
3491/**************************************************************************/
3492/* Converts the speed from the units selected by user to knots */
3493/**************************************************************************/
3494double fromUsrSpeed(double usr_speed, int unit) {
3495 double ret = NAN;
3496 if (unit == -1) unit = g_iSpeedFormat;
3497 switch (unit) {
3498 case SPEED_KTS: // kts
3499 ret = usr_speed;
3500 break;
3501 case SPEED_MPH: // mph
3502 ret = usr_speed / 1.15078;
3503 break;
3504 case SPEED_KMH: // km/h
3505 ret = usr_speed / 1.852;
3506 break;
3507 case SPEED_MS: // m/s
3508 ret = usr_speed / 0.514444444;
3509 break;
3510 }
3511 return ret;
3512}
3513/**************************************************************************/
3514/* Converts the wind speed from the units selected by user to knots */
3515/**************************************************************************/
3516double fromUsrWindSpeed(double usr_wspeed, int unit) {
3517 double ret = NAN;
3518 if (unit == -1) unit = g_iWindSpeedFormat;
3519 switch (unit) {
3520 case WSPEED_KTS: // kts
3521 ret = usr_wspeed;
3522 break;
3523 case WSPEED_MS: // m/s
3524 ret = usr_wspeed / 0.514444444;
3525 break;
3526 case WSPEED_MPH: // mph
3527 ret = usr_wspeed / 1.15078;
3528 break;
3529 case WSPEED_KMH: // km/h
3530 ret = usr_wspeed / 1.852;
3531 break;
3532 }
3533 return ret;
3534}
3535
3536/**************************************************************************/
3537/* Converts the temperature from the units selected by user to Celsius */
3538/**************************************************************************/
3539double fromUsrTemp(double usr_temp, int unit) {
3540 double ret = NAN;
3541 if (unit == -1) unit = g_iTempFormat;
3542 switch (unit) {
3543 case TEMPERATURE_C: // C
3544 ret = usr_temp;
3545 break;
3546 case TEMPERATURE_F: // F
3547 ret = (usr_temp - 32) * 5.0 / 9.0;
3548 break;
3549 case TEMPERATURE_K: // K
3550 ret = usr_temp - 273.15;
3551 break;
3552 }
3553 return ret;
3554}
3555
3556wxString formatAngle(double angle) {
3557 wxString out;
3558 if (g_bShowMag && g_bShowTrue) {
3559 out.Printf(wxT("%03.0f %cT (%.0f %cM)"), angle, 0x00B0, toMagnetic(angle),
3560 0x00B0);
3561 } else if (g_bShowTrue) {
3562 out.Printf(wxT("%03.0f %cT"), angle, 0x00B0);
3563 } else {
3564 out.Printf(wxT("%03.0f %cM"), toMagnetic(angle), 0x00B0);
3565 }
3566 return out;
3567}
3568
3569/* render a rectangle at a given color and transparency */
3570void AlphaBlending(ocpnDC &dc, int x, int y, int size_x, int size_y,
3571 float radius, wxColour color, unsigned char transparency) {
3572 wxDC *pdc = dc.GetDC();
3573 if (pdc) {
3574 // Get wxImage of area of interest
3575 wxBitmap obm(size_x, size_y);
3576 wxMemoryDC mdc1;
3577 mdc1.SelectObject(obm);
3578 mdc1.Blit(0, 0, size_x, size_y, pdc, x, y);
3579 mdc1.SelectObject(wxNullBitmap);
3580 wxImage oim = obm.ConvertToImage();
3581
3582 // Create destination image
3583 wxBitmap olbm(size_x, size_y);
3584 wxMemoryDC oldc(olbm);
3585 if (!oldc.IsOk()) return;
3586
3587 oldc.SetBackground(*wxBLACK_BRUSH);
3588 oldc.SetBrush(*wxWHITE_BRUSH);
3589 oldc.Clear();
3590
3591 if (radius > 0.0) oldc.DrawRoundedRectangle(0, 0, size_x, size_y, radius);
3592
3593 wxImage dest = olbm.ConvertToImage();
3594 unsigned char *dest_data =
3595 (unsigned char *)malloc(size_x * size_y * 3 * sizeof(unsigned char));
3596 unsigned char *bg = oim.GetData();
3597 unsigned char *box = dest.GetData();
3598 unsigned char *d = dest_data;
3599
3600 // Sometimes, on Windows, the destination image is corrupt...
3601 if (NULL == box) {
3602 free(d);
3603 return;
3604 }
3605 float alpha = 1.0 - (float)transparency / 255.0;
3606 int sb = size_x * size_y;
3607 for (int i = 0; i < sb; i++) {
3608 float a = alpha;
3609 if (*box == 0 && radius > 0.0) a = 1.0;
3610 int r = ((*bg++) * a) + (1.0 - a) * color.Red();
3611 *d++ = r;
3612 box++;
3613 int g = ((*bg++) * a) + (1.0 - a) * color.Green();
3614 *d++ = g;
3615 box++;
3616 int b = ((*bg++) * a) + (1.0 - a) * color.Blue();
3617 *d++ = b;
3618 box++;
3619 }
3620
3621 dest.SetData(dest_data);
3622
3623 // Convert destination to bitmap and draw it
3624 wxBitmap dbm(dest);
3625 dc.DrawBitmap(dbm, x, y, false);
3626
3627 // on MSW, the dc Bounding box is not updated on DrawBitmap() method.
3628 // Do it explicitely here for all platforms.
3629 dc.CalcBoundingBox(x, y);
3630 dc.CalcBoundingBox(x + size_x, y + size_y);
3631 } else {
3632#ifdef ocpnUSE_GL
3633 glEnable(GL_BLEND);
3634
3635 float radMod = wxMax(radius, 2.0);
3636 wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
3637 dc.SetBrush(wxBrush(c));
3638 dc.SetPen(wxPen(c, 1));
3639 dc.DrawRoundedRectangle(x, y, size_x, size_y, radMod);
3640
3641 glDisable(GL_BLEND);
3642
3643#endif
3644 }
3645}
3646
3647void DimeControl(wxWindow *ctrl) {
3648#ifdef __WXOSX__
3649 // On macOS 10.14+, we use the native colours in both light mode and dark
3650 // mode, and do not need to do anything else. Dark mode is toggled at the
3651 // application level in `SetAndApplyColorScheme`, and is also respected if it
3652 // is enabled system-wide.
3653 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3654 return;
3655 }
3656#endif
3657#ifdef __WXQT__
3658 return; // this is seriously broken on wxqt
3659#endif
3660
3661 if (wxSystemSettings::GetColour(wxSystemColour::wxSYS_COLOUR_WINDOW).Red() <
3662 128) {
3663 // Dark system color themes usually do better job than we do on diming UI
3664 // controls, do not fight with them
3665 return;
3666 }
3667
3668 if (NULL == ctrl) return;
3669
3670 wxColour col, window_back_color, gridline, uitext, udkrd, ctrl_back_color,
3671 text_color;
3672 col = GetGlobalColor(_T("DILG0")); // Dialog Background white
3673 window_back_color = GetGlobalColor(_T("DILG1")); // Dialog Background
3674 ctrl_back_color = GetGlobalColor(_T("DILG1")); // Control Background
3675 text_color = GetGlobalColor(_T("DILG3")); // Text
3676 uitext = GetGlobalColor(_T("UITX1")); // Menu Text, derived from UINFF
3677 udkrd = GetGlobalColor(_T("UDKRD"));
3678 gridline = GetGlobalColor(_T("GREY2"));
3679
3680 DimeControl(ctrl, col, window_back_color, ctrl_back_color, text_color, uitext,
3681 udkrd, gridline);
3682}
3683
3684void DimeControl(wxWindow *ctrl, wxColour col, wxColour window_back_color,
3685 wxColour ctrl_back_color, wxColour text_color, wxColour uitext,
3686 wxColour udkrd, wxColour gridline) {
3687#ifdef __WXOSX__
3688 // On macOS 10.14+, we use the native colours in both light mode and dark
3689 // mode, and do not need to do anything else. Dark mode is toggled at the
3690 // application level in `SetAndApplyColorScheme`, and is also respected if it
3691 // is enabled system-wide.
3692 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3693 return;
3694 }
3695#endif
3696
3697 ColorScheme cs = global_color_scheme;
3698
3699 // Are we in dusk or night mode? (Used below in several places.)
3700 bool darkMode =
3701 (cs == GLOBAL_COLOR_SCHEME_DUSK || cs == GLOBAL_COLOR_SCHEME_NIGHT);
3702
3703 static int depth = 0; // recursion count
3704 if (depth == 0) { // only for the window root, not for every child
3705 // If the color scheme is DAY or RGB, use the default platform native colour
3706 // for backgrounds
3707 if (!darkMode) {
3708#ifdef _WIN32
3709 window_back_color = wxNullColour;
3710#else
3711 window_back_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
3712#endif
3713 col = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
3714 uitext = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
3715 }
3716
3717 ctrl->SetBackgroundColour(window_back_color);
3718 if (darkMode) ctrl->SetForegroundColour(text_color);
3719 }
3720
3721 wxWindowList kids = ctrl->GetChildren();
3722 for (unsigned int i = 0; i < kids.GetCount(); i++) {
3723 wxWindowListNode *node = kids.Item(i);
3724 wxWindow *win = node->GetData();
3725
3726 if (dynamic_cast<wxListBox *>(win) || dynamic_cast<wxListCtrl *>(win) ||
3727 dynamic_cast<wxTextCtrl *>(win) ||
3728 dynamic_cast<wxTimePickerCtrl *>(win)) {
3729 win->SetBackgroundColour(col);
3730 } else if (dynamic_cast<wxStaticText *>(win) ||
3731 dynamic_cast<wxCheckBox *>(win) ||
3732 dynamic_cast<wxRadioButton *>(win)) {
3733 win->SetForegroundColour(uitext);
3734 }
3735#ifndef __WXOSX__
3736 // On macOS most controls can't be styled, and trying to do so only creates
3737 // weird coloured boxes around them. Fortunately, however, many of them
3738 // inherit a colour or tint from the background of their parent.
3739
3740 else if (dynamic_cast<wxBitmapComboBox *>(win) ||
3741 dynamic_cast<wxChoice *>(win) || dynamic_cast<wxComboBox *>(win) ||
3742 dynamic_cast<wxTreeCtrl *>(win)) {
3743 win->SetBackgroundColour(col);
3744 }
3745
3746 else if (dynamic_cast<wxScrolledWindow *>(win) ||
3747 dynamic_cast<wxGenericDirCtrl *>(win) ||
3748 dynamic_cast<wxListbook *>(win) || dynamic_cast<wxButton *>(win) ||
3749 dynamic_cast<wxToggleButton *>(win)) {
3750 win->SetBackgroundColour(window_back_color);
3751 }
3752
3753 else if (dynamic_cast<wxNotebook *>(win)) {
3754 win->SetBackgroundColour(window_back_color);
3755 win->SetForegroundColour(text_color);
3756 }
3757#endif
3758
3759 else if (dynamic_cast<wxHtmlWindow *>(win)) {
3760 if (cs != GLOBAL_COLOR_SCHEME_DAY && cs != GLOBAL_COLOR_SCHEME_RGB)
3761 win->SetBackgroundColour(ctrl_back_color);
3762 else
3763 win->SetBackgroundColour(wxNullColour);
3764 }
3765
3766 else if (dynamic_cast<wxGrid *>(win)) {
3767 dynamic_cast<wxGrid *>(win)->SetDefaultCellBackgroundColour(
3768 window_back_color);
3769 dynamic_cast<wxGrid *>(win)->SetDefaultCellTextColour(uitext);
3770 dynamic_cast<wxGrid *>(win)->SetLabelBackgroundColour(col);
3771 dynamic_cast<wxGrid *>(win)->SetLabelTextColour(uitext);
3772 dynamic_cast<wxGrid *>(win)->SetGridLineColour(gridline);
3773 }
3774
3775 if (win->GetChildren().GetCount() > 0) {
3776 depth++;
3777 wxWindow *w = win;
3778 DimeControl(w, col, window_back_color, ctrl_back_color, text_color,
3779 uitext, udkrd, gridline);
3780 depth--;
3781 }
3782 }
3783}
3784
3785#define LUMIMOSITY_NIGHT (-0.8)
3786#define LUMIMOSITY_DUSK (-0.5)
3787
3788wxColor GetDimedColor(const wxColor &c) {
3789 switch (global_color_scheme) {
3790 case ColorScheme::GLOBAL_COLOR_SCHEME_NIGHT:
3791 return (wxColor(
3792 wxMax(0, wxMin(c.Red() + c.Red() * LUMIMOSITY_NIGHT, 255)),
3793 wxMax(0, wxMin(c.Green() + c.Green() * LUMIMOSITY_NIGHT, 255)),
3794 wxMax(0, wxMin(c.Blue() + c.Blue() * LUMIMOSITY_NIGHT, 255))));
3795 case ColorScheme::GLOBAL_COLOR_SCHEME_DUSK:
3796 return (
3797 wxColor(wxMax(0, wxMin(c.Red() + c.Red() * LUMIMOSITY_DUSK, 255)),
3798 wxMax(0, wxMin(c.Green() + c.Green() * LUMIMOSITY_DUSK, 255)),
3799 wxMax(0, wxMin(c.Blue() + c.Blue() * LUMIMOSITY_DUSK, 255))));
3800 default:
3801 return c;
3802 }
3803}
bool g_bresponsive
Flag to control adaptive UI scaling.
Definition ocpn_app.cpp:662
Global state for AIS decoder.
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
Represents an individual component within a ChartGroup.
Definition chartdbs.h:444
Represents a user-defined collection of logically related charts.
Definition chartdbs.h:464
wxString GetFullConfigDesc(int i) const
Gets description of font at index i.
Definition FontMgr.cpp:362
bool AddAuxKey(wxString key)
Adds new plugin-defined font configuration key.
Definition FontMgr.cpp:667
void LoadFontNative(wxString *pConfigString, wxString *pNativeDesc)
Loads font settings from a string descriptor.
Definition FontMgr.cpp:392
static wxString GetFontConfigKey(const wxString &description)
Creates configuration key from UI element name by combining locale with hash.
Definition FontMgr.cpp:132
int GetNumFonts(void) const
Gets the total number of font configurations currently loaded.
Definition FontMgr.cpp:325
wxArrayString & GetAuxKeyArray()
Gets array of plugin-defined font configuration keys.
Definition FontMgr.h:181
Wrapper for global variable, supports notification events when value changes.
Represents a layer of chart objects in OpenCPN.
Definition Layer.h:38
static int config_to_ui(double value)
Convert configuration 1.02..3.0 value to slider scale 1..100.
Definition navutil.h:166
static double ui_to_config(int slider_pos)
Convert a slider scale 1-100 value to configuration value 1.02..3.0.
Definition navutil.h:161
Main application frame.
Definition ocpn_frame.h:136
Provides platform-specific support utilities for OpenCPN.
Represents a waypoint or mark within the navigation system.
Definition route_point.h:70
bool m_bIsVisible
Flag indicating if the waypoint should be drawn on the chart.
bool m_bIsInLayer
Flag indicating if the waypoint belongs to a layer.
Represents a navigational route in the navigation system.
Definition route.h:98
bool m_bIsInLayer
Flag indicating whether this route belongs to a layer.
Definition route.h:277
Represents a single point in a track.
Definition track.h:53
Represents a track, which is a series of connected track points.
Definition track.h:111
ViewPort - Core geographic projection and coordinate transformation engine.
Definition viewport.h:81
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
Definition viewport.h:229
double rotation
Rotation angle of the viewport in radians.
Definition viewport.h:239
double clon
Center longitude of the viewport in degrees.
Definition viewport.h:224
double clat
Center latitude of the viewport in degrees.
Definition viewport.h:222
Encapsulates persistent canvas configuration.
double iLat
Latitude of the center of the chart, in degrees.
bool bShowOutlines
Display chart outlines.
wxSize canvasSize
Canvas dimensions.
bool bShowDepthUnits
Display depth unit indicators.
double iLon
Longitude of the center of the chart, in degrees.
double iRotation
Initial rotation angle in radians.
bool bCourseUp
Orient display to course up.
bool bQuilt
Enable chart quilting.
bool bFollow
Enable vessel following mode.
double iScale
Initial chart scale factor.
bool bShowENCText
Display ENC text elements.
bool bShowAIS
Display AIS targets.
bool bShowGrid
Display coordinate grid.
ChartCanvas * canvas
Pointer to associated chart canvas.
bool bShowCurrents
Display current information.
bool bShowTides
Display tide information.
bool bLookahead
Enable lookahead mode.
bool bHeadUp
Orient display to heading up.
bool bAttenAIS
Enable AIS target attenuation.
Device context class that can use either wxDC or OpenGL for drawing.
Definition ocpndc.h:64
Global variables reflecting command line options and arguments.
NavmsgFilter Read(const std::string &name)
Read filter with given name from disk.
bool Write(const NavmsgFilter &filter, const std::string &name)
Write contents for given filter to disk.
PlugIn Object Definition/API.
Tools to send data to plugins.