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