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 #ifndef WX_PRECOMP
34 #include "wx/wx.h"
35 #endif //precompiled headers
36
37 #include <wx/tokenzr.h>
38 #include <wx/sstream.h>
39 #include <wx/image.h>
40 #include <wx/filename.h>
41 #include <wx/graphics.h>
42 #include <wx/dir.h>
43 #include <wx/listbook.h>
44 #include <wx/timectrl.h>
45
46 #include "dychart.h"
47
48 #include <stdlib.h>
49 //#include <math.h>
50 #include <time.h>
51 #include <locale>
52 #include <list>
53
54 #include <wx/listimpl.cpp>
55 #include <wx/progdlg.h>
56
57 #include "config.h"
58 #include "chart1.h"
59 #include "navutil.h"
60 #include "chcanv.h"
61 #include "georef.h"
62 #include "cutil.h"
63 #include "styles.h"
64 #include "routeman.h"
65 #include "s52utils.h"
66 #include "chartbase.h"
67 #include "ocpndc.h"
68 #include "geodesic.h"
69 #include "datastream.h"
70 #include "multiplexer.h"
71 #include "ais.h"
72 #include "Route.h"
73 #include "Select.h"
74 #include "FontMgr.h"
75 #include "OCPN_Sound.h"
76 #include "Layer.h"
77 #include "NavObjectCollection.h"
78 #include "NMEALogWindow.h"
79 #include "AIS_Decoder.h"
80 #include "OCPNPlatform.h"
81 #include "Track.h"
82 #include "chartdb.h"
83 #include "CanvasConfig.h"
84
85 #include "s52plib.h"
86 #include "cm93.h"
87
88 #ifdef ocpnUSE_GL
89 #include "glChartCanvas.h"
90 #endif
91
92 #ifdef __OCPN__ANDROID__
93 #include "androidUTIL.h"
94 #endif
95
96 #ifdef __WXOSX__
97 #include "DarkMode.h"
98 #endif
99
100 // Statics
101
102 extern OCPNPlatform *g_Platform;
103 extern MyFrame *gFrame;
104
105 extern double g_ChartNotRenderScaleFactor;
106 extern int g_restore_stackindex;
107 extern int g_restore_dbindex;
108 extern RouteList *pRouteList;
109 extern TrackList *pTrackList;
110 extern LayerList *pLayerList;
111 extern int g_LayerIdx;
112 extern MyConfig *pConfig;
113 extern double vLat, vLon, gLat, gLon;
114 extern double kLat, kLon;
115 extern double initial_scale_ppm, initial_rotation;
116 extern ColorScheme global_color_scheme;
117 extern int g_nbrightness;
118 extern bool g_bShowTrue, g_bShowMag;
119 extern double g_UserVar;
120 extern bool g_bShowStatusBar;
121 extern bool g_bUIexpert;
122 extern bool g_bFullscreen;
123 extern int g_nDepthUnitDisplay;
124 extern wxString g_winPluginDir;
125
126
127 extern wxArrayOfConnPrm *g_pConnectionParams;
128
129 extern wxString g_SENCPrefix;
130 extern wxString g_UserPresLibData;
131
132 extern wxString *pInit_Chart_Dir;
133 extern wxString gWorldMapLocation;
134 extern WayPointman *pWayPointMan;
135
136 extern bool s_bSetSystemTime;
137 extern bool g_bDisplayGrid; //Flag indicating if grid is to be displayed
138 extern bool g_bPlayShipsBells;
139 extern int g_iSoundDeviceIndex;
140 extern bool g_bFullscreenToolbar;
141 extern bool g_bShowLayers;
142 extern bool g_bTransparentToolbar;
143 extern bool g_bPermanentMOBIcon;
144
145 extern bool g_bShowDepthUnits;
146 extern bool g_bAutoAnchorMark;
147 extern bool g_bskew_comp;
148 extern bool g_bopengl;
149 extern bool g_bdisable_opengl;
150 extern bool g_bSoftwareGL;
151 extern bool g_bShowFPS;
152 extern bool g_bsmoothpanzoom;
153 extern bool g_fog_overzoom;
154 extern double g_overzoom_emphasis_base;
155 extern bool g_oz_vector_scale;
156 extern double g_plus_minus_zoom_factor;
157 extern bool g_bShowOutlines;
158 extern bool g_bShowActiveRouteHighway;
159 extern bool g_bShowRouteTotal;
160 extern int g_nNMEADebug;
161 extern int g_nAWDefault;
162 extern int g_nAWMax;
163 extern int g_nTrackPrecision;
164
165 extern int g_iSDMMFormat;
166 extern int g_iDistanceFormat;
167 extern int g_iSpeedFormat;
168
169 extern int g_nframewin_x;
170 extern int g_nframewin_y;
171 extern int g_nframewin_posx;
172 extern int g_nframewin_posy;
173 extern bool g_bframemax;
174
175 extern double g_PlanSpeed;
176 extern wxString g_VisibleLayers;
177 extern wxString g_InvisibleLayers;
178 extern wxString g_VisiNameinLayers;
179 extern wxString g_InVisiNameinLayers;
180
181 extern wxArrayString *pMessageOnceArray;
182
183 // LIVE ETA OPTION
184 extern bool g_bShowLiveETA;
185 extern double g_defaultBoatSpeed;
186 extern double g_defaultBoatSpeedUserUnit;
187
188 // AIS Global configuration
189 extern bool g_bCPAMax;
190 extern double g_CPAMax_NM;
191 extern bool g_bCPAWarn;
192 extern double g_CPAWarn_NM;
193 extern bool g_bTCPA_Max;
194 extern double g_TCPA_Max;
195 extern bool g_bMarkLost;
196 extern double g_MarkLost_Mins;
197 extern bool g_bRemoveLost;
198 extern double g_RemoveLost_Mins;
199 extern bool g_bShowCOG;
200 extern double g_ShowCOG_Mins;
201 extern bool g_bAISShowTracks;
202 extern bool g_bTrackCarryOver;
203 extern bool g_bTrackDaily;
204 extern int g_track_rotate_time;
205 extern int g_track_rotate_time_type;
206 extern double g_AISShowTracks_Mins;
207 extern double g_AISShowTracks_Limit;
208 extern bool g_bHideMoored;
209 extern double g_ShowMoored_Kts;
210 extern bool g_bAllowShowScaled;
211 extern bool g_bShowScaled;
212 extern int g_ShowScaled_Num;
213 extern bool g_bAIS_CPA_Alert;
214 extern bool g_bAIS_CPA_Alert_Audio;
215 extern int g_ais_alert_dialog_x, g_ais_alert_dialog_y;
216 extern int g_ais_alert_dialog_sx, g_ais_alert_dialog_sy;
217 extern int g_ais_query_dialog_x, g_ais_query_dialog_y;
218 extern wxString g_sAIS_Alert_Sound_File;
219 extern bool g_bAIS_CPA_Alert_Suppress_Moored;
220 extern bool g_bAIS_ACK_Timeout;
221 extern double g_AckTimeout_Mins;
222 extern wxString g_AisTargetList_perspective;
223 extern int g_AisTargetList_range;
224 extern int g_AisTargetList_sortColumn;
225 extern bool g_bAisTargetList_sortReverse;
226 extern wxString g_AisTargetList_column_spec;
227 extern wxString g_AisTargetList_column_order;
228 extern bool g_bShowAreaNotices;
229 extern bool g_bDrawAISSize;
230 extern bool g_bDrawAISRealtime;
231 extern double g_AIS_RealtPred_Kts;
232 extern bool g_bShowAISName;
233 extern int g_Show_Target_Name_Scale;
234 extern bool g_bWplIsAprsPosition;
235 extern bool g_benableAISNameCache;
236 extern bool g_bUseOnlyConfirmedAISName;
237 extern int g_ScaledNumWeightSOG;
238 extern int g_ScaledNumWeightCPA;
239 extern int g_ScaledNumWeightTCPA;
240 extern int g_ScaledNumWeightRange;
241 extern int g_ScaledNumWeightSizeOfT;
242 extern int g_ScaledSizeMinimal;
243
244 extern int g_S57_dialog_sx, g_S57_dialog_sy;
245 int g_S57_extradialog_sx, g_S57_extradialog_sy;
246
247 extern int g_iNavAidRadarRingsNumberVisible;
248 extern float g_fNavAidRadarRingsStep;
249 extern int g_pNavAidRadarRingsStepUnits;
250 extern int g_iWaypointRangeRingsNumber;
251 extern float g_fWaypointRangeRingsStep;
252 extern int g_iWaypointRangeRingsStepUnits;
253 extern wxColour g_colourWaypointRangeRingsColour;
254 extern bool g_bWayPointPreventDragging;
255 extern bool g_bConfirmObjectDelete;
256 extern wxColour g_colourOwnshipRangeRingsColour;
257 extern int g_iWpt_ScaMin;
258 extern bool g_bUseWptScaMin;
259 extern bool g_bOverruleScaMin;
260 extern bool g_bShowWptName;
261
262
263 extern bool g_bEnableZoomToCursor;
264 extern wxString g_toolbarConfig;
265 extern double g_TrackIntervalSeconds;
266 extern double g_TrackDeltaDistance;
267 extern int gps_watchdog_timeout_ticks;
268
269 extern int g_nCacheLimit;
270 extern int g_memCacheLimit;
271
272 extern bool g_bGDAL_Debug;
273 extern bool g_bDebugCM93;
274 extern bool g_bDebugS57;
275
276 extern double g_ownship_predictor_minutes;
277 extern double g_ownship_HDTpredictor_miles;
278
279 extern bool g_own_ship_sog_cog_calc;
280 extern int g_own_ship_sog_cog_calc_damp_sec;
281
282 extern bool g_bShowMenuBar;
283 extern bool g_bShowCompassWin;
284
285 extern s52plib *ps52plib;
286
287 extern int g_cm93_zoom_factor;
288 extern bool g_b_legacy_input_filter_behaviour;
289 extern bool g_bShowDetailSlider;
290 extern int g_detailslider_dialog_x, g_detailslider_dialog_y;
291
292 extern bool g_bUseGreenShip;
293
294 extern int g_OwnShipIconType;
295 extern double g_n_ownship_length_meters;
296 extern double g_n_ownship_beam_meters;
297 extern double g_n_gps_antenna_offset_y;
298 extern double g_n_gps_antenna_offset_x;
299 extern int g_n_ownship_min_mm;
300 extern double g_n_arrival_circle_radius;
301
302 extern bool g_bPreserveScaleOnX;
303 extern bool g_bsimplifiedScalebar;
304
305 extern bool g_bUseGLL;
306
307 extern wxString g_locale;
308 extern wxString g_localeOverride;
309
310
311 extern bool g_bCourseUp;
312 extern bool g_bLookAhead;
313 extern int g_COGAvgSec;
314 extern bool g_bMagneticAPB;
315 extern bool g_bShowChartBar;
316
317 extern int g_MemFootMB;
318
319 extern int g_nCOMPortCheck;
320
321
322 extern wxString g_AW1GUID;
323 extern wxString g_AW2GUID;
324 extern int g_BSBImgDebug;
325
326 extern int n_NavMessageShown;
327 extern wxString g_config_version_string;
328
329 extern wxString g_CmdSoundString;
330
331 extern bool g_bAISRolloverShowClass;
332 extern bool g_bAISRolloverShowCOG;
333 extern bool g_bAISRolloverShowCPA;
334
335 extern bool g_bDebugGPSD;
336
337 extern bool g_bfilter_cogsog;
338 extern int g_COGFilterSec;
339 extern int g_SOGFilterSec;
340
341 int g_navobjbackups;
342
343 extern bool g_bQuiltEnable;
344 extern bool g_bFullScreenQuilt;
345 extern bool g_bQuiltStart;
346
347 extern int g_SkewCompUpdatePeriod;
348
349 extern int g_maintoolbar_x;
350 extern int g_maintoolbar_y;
351 extern long g_maintoolbar_orient;
352
353
354 extern int g_lastClientRectx;
355 extern int g_lastClientRecty;
356 extern int g_lastClientRectw;
357 extern int g_lastClientRecth;
358
359 extern bool g_bHighliteTracks;
360 extern int g_cog_predictor_width;
361 extern int g_ais_cog_predictor_width;
362
363 extern int g_route_line_width;
364 extern int g_track_line_width;
365 extern wxColour g_colourTrackLineColour;
366 extern wxString g_default_wp_icon;
367 extern wxString g_default_routepoint_icon;
368
369 extern ChartGroupArray *g_pGroupArray;
370
371 extern bool g_bDebugOGL;
372 extern int g_tcwin_scale;
373 extern wxString g_GPS_Ident;
374 extern bool g_bGarminHostUpload;
375 extern wxString g_uploadConnection;
376
377 extern ocpnStyle::StyleManager* g_StyleManager;
378 extern wxArrayString TideCurrentDataSet;
379 extern wxString g_TCData_Dir;
380
381 extern bool g_btouch;
382 extern bool g_bresponsive;
383
384 extern bool g_bGLexpert;
385
386 extern int g_SENC_LOD_pixels;
387 extern ArrayOfMMSIProperties g_MMSI_Props_Array;
388
389 extern int g_chart_zoom_modifier;
390 extern int g_chart_zoom_modifier_vector;
391
392 extern int g_NMEAAPBPrecision;
393
394 extern wxString g_TalkerIdText;
395 extern bool g_bShowTrackPointTime;
396
397 extern int g_maxWPNameLength;
398
399 extern bool g_bAdvanceRouteWaypointOnArrivalOnly;
400 extern double g_display_size_mm;
401 extern double g_config_display_size_mm;
402 extern bool g_config_display_size_manual;
403
404 extern float g_selection_radius_mm;
405 extern float g_selection_radius_touch_mm;
406
407 extern bool g_benable_rotate;
408 extern bool g_bEmailCrashReport;
409
410 extern int g_default_font_size;
411 extern wxString g_default_font_facename;
412
413 extern bool g_bAutoHideToolbar;
414 extern int g_nAutoHideToolbar;
415 extern int g_GUIScaleFactor;
416 extern int g_ChartScaleFactor;
417 extern float g_ChartScaleFactorExp;
418 extern int g_ShipScaleFactor;
419 extern float g_ShipScaleFactorExp;
420 extern int g_ENCSoundingScaleFactor;
421
422
423 extern bool g_bInlandEcdis;
424 extern int g_iENCToolbarPosX;
425 extern int g_iENCToolbarPosY;
426 extern bool g_bRollover;
427
428 extern bool g_bSpaceDropMark;
429
430 extern bool g_bShowTide;
431 extern bool g_bShowCurrent;
432
433 extern bool g_benableUDPNullHeader;
434
435 extern wxString g_uiStyle;
436 extern bool g_btrackContinuous;
437 extern bool g_useMUI;
438
439 int g_nCPUCount;
440
441 extern bool g_bDarkDecorations;
442 extern unsigned int g_canvasConfig;
443 extern arrayofCanvasConfigPtr g_canvasConfigArray;
444 extern wxString g_lastAppliedTemplateGUID;
445
446 extern int g_route_prop_x, g_route_prop_y;
447 extern int g_route_prop_sx, g_route_prop_sy;
448 extern int g_AndroidVersionCode;
449
450 extern wxString g_compatOS;
451 extern wxString g_compatOsVersion;
452
453 wxString g_gpx_path;
454 bool g_bLayersLoaded;
455 bool g_bShowMuiZoomButtons = true;
456
457 wxString g_catalog_custom_url;
458 wxString g_catalog_channel;
459
460 #ifdef ocpnUSE_GL
461 extern ocpnGLOptions g_GLOptions;
462 #endif
463
464 #if !defined(NAN)
465 static const long long lNaN = 0xfff8000000000000;
466 #define NAN (*(double*)&lNaN)
467 #endif
468
469
470
471 // Layer helper function
472
GetLayerName(int id)473 wxString GetLayerName( int id )
474 {
475 wxString name( _T("unknown layer") );
476 if( id <= 0 ) return ( name );
477 LayerList::iterator it;
478 int index = 0;
479 for( it = ( *pLayerList ).begin(); it != ( *pLayerList ).end(); ++it, ++index ) {
480 Layer *lay = (Layer *) ( *it );
481 if( lay->m_LayerID == id )
482 return ( lay->m_LayerName );
483 }
484 return ( name );
485 }
486
487 //Helper conditional file name dir slash
488 void appendOSDirSlash(wxString* pString);
489
490
491 //-----------------------------------------------------------------------------
492 // MyConfig Implementation
493 //-----------------------------------------------------------------------------
494
MyConfig(const wxString & LocalFileName)495 MyConfig::MyConfig( const wxString &LocalFileName ) :
496 wxFileConfig( _T (""), _T (""), LocalFileName, _T (""), wxCONFIG_USE_LOCAL_FILE )
497 {
498 // Create the default NavObjectCollection FileName
499 wxFileName config_file( LocalFileName );
500 m_sNavObjSetFile = config_file.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
501 m_sNavObjSetFile += _T ( "navobj.xml" );
502 m_sNavObjSetChangesFile = m_sNavObjSetFile + _T ( ".changes" );
503
504 m_pNavObjectInputSet = NULL;
505 m_pNavObjectChangesSet = NULL;
506
507 m_bSkipChangeSetUpdate = false;
508 }
509
CreateRotatingNavObjBackup()510 void MyConfig::CreateRotatingNavObjBackup()
511 {
512
513 // Avoid nonsense log errors...
514 #ifdef __OCPN__ANDROID__
515 wxLogNull logNo;
516 #endif
517
518 //Rotate navobj backups, but just in case there are some changes in the current version
519 //to prevent the user trying to "fix" the problem by continuously starting the
520 //application to overwrite all of his good backups...
521 if( g_navobjbackups > 0 ) {
522 wxFile f;
523 wxString oldname = m_sNavObjSetFile;
524 wxString newname = wxString::Format( _T("%s.1"), m_sNavObjSetFile.c_str() );
525
526 wxFileOffset s_diff = 1;
527 if( ::wxFileExists( newname ) ) {
528
529 if( f.Open(oldname) ){
530 s_diff = f.Length();
531 f.Close();
532 }
533
534 if( f.Open(newname) ){
535 s_diff -= f.Length();
536 f.Close();
537 }
538 }
539
540
541 if ( s_diff != 0 )
542 {
543 for( int i = g_navobjbackups - 1; i >= 1; i-- )
544 {
545 oldname = wxString::Format( _T("%s.%d"), m_sNavObjSetFile.c_str(), i );
546 newname = wxString::Format( _T("%s.%d"), m_sNavObjSetFile.c_str(), i + 1 );
547 if( wxFile::Exists( oldname ) )
548 wxCopyFile( oldname, newname );
549 }
550
551 if( wxFile::Exists( m_sNavObjSetFile ) )
552 {
553 newname = wxString::Format( _T("%s.1"), m_sNavObjSetFile.c_str() );
554 wxCopyFile( m_sNavObjSetFile, newname );
555 }
556 }
557 }
558 //try to clean the backups the user doesn't want - breaks if he deleted some by hand as it tries to be effective...
559 for( int i = g_navobjbackups + 1; i <= 99; i++ )
560 if( wxFile::Exists( wxString::Format( _T("%s.%d"), m_sNavObjSetFile.c_str(), i ) ) ) wxRemoveFile(
561 wxString::Format( _T("%s.%d"), m_sNavObjSetFile.c_str(), i ) );
562 else
563 break;
564 }
565
LoadMyConfig()566 int MyConfig::LoadMyConfig()
567 {
568 int display_width, display_height;
569 wxDisplaySize( &display_width, &display_height );
570
571 // Set up any defaults not set elsewhere
572 g_useMUI = true;
573 g_TalkerIdText = _T("EC");
574 g_maxWPNameLength = 6;
575 g_NMEAAPBPrecision = 3;
576
577 #ifdef ocpnUSE_GL
578 g_GLOptions.m_bUseAcceleratedPanning = true;
579 g_GLOptions.m_GLPolygonSmoothing = true;
580 g_GLOptions.m_GLLineSmoothing = true;
581 g_GLOptions.m_iTextureDimension = 512;
582 g_GLOptions.m_iTextureMemorySize = 128;
583 if(!g_bGLexpert){
584 g_GLOptions.m_iTextureMemorySize = wxMax(128, g_GLOptions.m_iTextureMemorySize);
585 g_GLOptions.m_bTextureCompressionCaching = g_GLOptions.m_bTextureCompression;
586 }
587 #endif
588
589 g_maintoolbar_orient = wxTB_HORIZONTAL;
590 g_iENCToolbarPosX = -1;
591 g_iENCToolbarPosY = -1;
592 g_restore_dbindex = -1;
593 g_ChartNotRenderScaleFactor = 1.5;
594 g_detailslider_dialog_x = 200L;
595 g_detailslider_dialog_y = 200L;
596 g_SENC_LOD_pixels = 2;
597 g_SkewCompUpdatePeriod = 10;
598
599 g_bShowStatusBar = 1;
600 g_bShowCompassWin = 1;
601 g_iSoundDeviceIndex = -1;
602 g_bFullscreenToolbar = 1;
603 g_bTransparentToolbar = 0;
604 g_bShowLayers = 1;
605 g_bShowDepthUnits = 1;
606 g_bShowActiveRouteHighway = 1;
607 g_bShowChartBar = 1;
608 g_defaultBoatSpeed = 6.0;
609 g_ownship_predictor_minutes = 5;
610 g_cog_predictor_width = 3;
611 g_ownship_HDTpredictor_miles = 1;
612 g_n_ownship_min_mm = 5;
613 g_own_ship_sog_cog_calc_damp_sec = 1;
614 g_bFullScreenQuilt = 1;
615 g_track_rotate_time_type = TIME_TYPE_COMPUTER;
616 g_bHighliteTracks = 1;
617 g_bPreserveScaleOnX = 1;
618 g_navobjbackups = 5;
619 g_benableAISNameCache = true;
620 g_n_arrival_circle_radius = 0.05;
621 g_plus_minus_zoom_factor = 2.0;
622
623 g_AISShowTracks_Mins = 20;
624 g_AISShowTracks_Limit = 300.0;
625 g_ShowScaled_Num = 10;
626 g_ScaledNumWeightSOG = 50;
627 g_ScaledNumWeightCPA = 60;
628 g_ScaledNumWeightTCPA = 25;
629 g_ScaledNumWeightRange = 75;
630 g_ScaledNumWeightSizeOfT = 25;
631 g_ScaledSizeMinimal = 50;
632 g_Show_Target_Name_Scale = 250000;
633 g_bWplIsAprsPosition = 1;
634 g_ais_cog_predictor_width = 3;
635 g_ais_alert_dialog_sx = 200;
636 g_ais_alert_dialog_sy = 200;
637 g_ais_alert_dialog_x = 200;
638 g_ais_alert_dialog_y = 200;
639 g_ais_query_dialog_x = 200;
640 g_ais_query_dialog_y = 200;
641 g_AisTargetList_range = 40;
642 g_AisTargetList_sortColumn = 2; // Column #2 is MMSI
643 g_S57_dialog_sx = 400;
644 g_S57_dialog_sy = 400;
645 g_S57_extradialog_sx = 400;
646 g_S57_extradialog_sy = 400;
647
648 // Reasonable starting point
649 vLat = START_LAT; // display viewpoint
650 vLon = START_LON;
651 gLat = START_LAT; // GPS position, as default
652 gLon = START_LON;
653 initial_scale_ppm = .0003; // decent initial value
654 initial_rotation = 0;
655
656 g_iNavAidRadarRingsNumberVisible = 0;
657 g_fNavAidRadarRingsStep = 1.0;
658 g_pNavAidRadarRingsStepUnits = 0;
659 g_colourOwnshipRangeRingsColour = *wxRED;
660 g_iWaypointRangeRingsNumber = 0;
661 g_fWaypointRangeRingsStep = 1.0;
662 g_iWaypointRangeRingsStepUnits = 0;
663 g_colourWaypointRangeRingsColour = wxColour( *wxRED );
664 g_bConfirmObjectDelete = true;
665
666 g_TrackIntervalSeconds = 60.0;
667 g_TrackDeltaDistance = 0.10;
668 g_route_line_width = 2;
669 g_track_line_width = 2;
670 g_colourTrackLineColour = wxColour( 243, 229, 47 ); //Yellow
671
672 g_tcwin_scale = 100;
673 g_default_wp_icon = _T("triangle");
674 g_default_routepoint_icon = _T("diamond");
675
676 g_nAWDefault = 50;
677 g_nAWMax = 1852;
678
679 // Load the raw value, with no defaults, and no processing
680 int ret_Val = LoadMyConfigRaw();
681
682 // Perform any required post processing and validation
683 if(!ret_Val){
684 g_ChartScaleFactorExp = g_Platform->getChartScaleFactorExp( g_ChartScaleFactor );
685 g_ShipScaleFactorExp = g_Platform->getChartScaleFactorExp( g_ShipScaleFactor );
686
687 g_COGFilterSec = wxMin(g_COGFilterSec, MAX_COGSOG_FILTER_SECONDS);
688 g_COGFilterSec = wxMax(g_COGFilterSec, 1);
689 g_SOGFilterSec = g_COGFilterSec;
690
691 if(!g_bShowTrue && !g_bShowMag)
692 g_bShowTrue = true;
693 g_COGAvgSec = wxMin(g_COGAvgSec, MAX_COG_AVERAGE_SECONDS); // Bound the array size
694
695 if( g_bInlandEcdis )
696 g_bLookAhead=1;
697
698 if ( g_bdisable_opengl )
699 g_bopengl = false;
700
701 #ifdef ocpnUSE_GL
702 if(!g_bGLexpert){
703 g_GLOptions.m_iTextureMemorySize = wxMax(128, g_GLOptions.m_iTextureMemorySize);
704 g_GLOptions.m_bTextureCompressionCaching = g_GLOptions.m_bTextureCompression;
705 }
706 #endif
707
708 g_chart_zoom_modifier = wxMin(g_chart_zoom_modifier,5);
709 g_chart_zoom_modifier = wxMax(g_chart_zoom_modifier,-5);
710 g_chart_zoom_modifier_vector = wxMin(g_chart_zoom_modifier_vector,5);
711 g_chart_zoom_modifier_vector = wxMax(g_chart_zoom_modifier_vector,-5);
712 g_cm93_zoom_factor = wxMin(g_cm93_zoom_factor,CM93_ZOOM_FACTOR_MAX_RANGE);
713 g_cm93_zoom_factor = wxMax(g_cm93_zoom_factor,(-CM93_ZOOM_FACTOR_MAX_RANGE));
714
715 if( ( g_detailslider_dialog_x < 0 ) || ( g_detailslider_dialog_x > display_width ) )
716 g_detailslider_dialog_x = 5;
717 if( ( g_detailslider_dialog_y < 0 ) || ( g_detailslider_dialog_y > display_height ) )
718 g_detailslider_dialog_y = 5;
719
720 g_defaultBoatSpeedUserUnit = toUsrSpeed(g_defaultBoatSpeed, -1);
721 g_n_ownship_min_mm = wxMax(g_n_ownship_min_mm, 5);
722 if( g_navobjbackups > 99 ) g_navobjbackups = 99;
723 if( g_navobjbackups < 0 ) g_navobjbackups = 0;
724 g_n_arrival_circle_radius = wxClip(g_n_arrival_circle_radius, 0.001, 0.6);
725
726 g_selection_radius_mm = wxMax(g_selection_radius_mm, 0.5);
727 g_selection_radius_touch_mm = wxMax(g_selection_radius_touch_mm, 1.0);
728
729 g_Show_Target_Name_Scale = wxMax( 5000, g_Show_Target_Name_Scale );
730
731 if( ( g_ais_alert_dialog_x < 0 ) || ( g_ais_alert_dialog_x > display_width ) )
732 g_ais_alert_dialog_x = 5;
733 if( ( g_ais_alert_dialog_y < 0 ) || ( g_ais_alert_dialog_y > display_height ) )
734 g_ais_alert_dialog_y = 5;
735 if( ( g_ais_query_dialog_x < 0 ) || ( g_ais_query_dialog_x > display_width ) )
736 g_ais_query_dialog_x = 5;
737 if( ( g_ais_query_dialog_y < 0 ) || ( g_ais_query_dialog_y > display_height ) )
738 g_ais_query_dialog_y = 5;
739
740 SwitchInlandEcdisMode( g_bInlandEcdis );
741 if ( g_bInlandEcdis )
742 global_color_scheme = GLOBAL_COLOR_SCHEME_DUSK; //startup in duskmode if inlandEcdis
743
744 // Multicanvas Settings
745 LoadCanvasConfigs();
746 }
747
748 return ret_Val;
749 }
750
LoadMyConfigRaw(bool bAsTemplate)751 int MyConfig::LoadMyConfigRaw( bool bAsTemplate )
752 {
753
754 int read_int;
755 wxString val;
756
757 int display_width, display_height;
758 wxDisplaySize( &display_width, &display_height );
759
760 // Global options and settings
761 SetPath( _T ( "/Settings" ) );
762
763 Read( _T ( "LastAppliedTemplate" ), &g_lastAppliedTemplateGUID );
764 Read( _T ( "CompatOS" ), &g_compatOS );
765 Read( _T ( "CompatOsVersion" ), &g_compatOsVersion );
766
767 // Some undocumented values
768 Read( _T ( "ConfigVersionString" ), &g_config_version_string );
769 #ifdef SYSTEM_SOUND_CMD
770 Read(_T("CmdSoundString"), &g_CmdSoundString, wxString(SYSTEM_SOUND_CMD) );
771 if ( wxIsEmpty( g_CmdSoundString ) )
772 g_CmdSoundString = wxString( SYSTEM_SOUND_CMD );
773 #endif /* SYSTEM_SOUND_CMD */
774 Read( _T ( "NavMessageShown" ), &n_NavMessageShown );
775
776 Read( _T ( "AndroidVersionCode" ), &g_AndroidVersionCode );
777
778 Read( _T ( "UIexpert" ), &g_bUIexpert );
779
780 Read( _T ( "UIStyle" ), &g_uiStyle );
781
782 Read( _T ( "NCacheLimit" ), &g_nCacheLimit );
783
784 Read( _T ( "InlandEcdis" ), &g_bInlandEcdis );// First read if in iENC mode as this will override some config settings
785
786 Read( _T ("DarkDecorations" ), &g_bDarkDecorations );
787
788 Read( _T( "SpaceDropMark" ), &g_bSpaceDropMark );
789
790 int mem_limit = 0;
791 Read( _T ( "MEMCacheLimit" ), &mem_limit );
792 if(mem_limit > 0)
793 g_memCacheLimit = mem_limit * 1024; // convert from MBytes to kBytes
794
795 Read( _T ( "UseModernUI5" ), &g_useMUI );
796
797 Read( _T( "NCPUCount" ), &g_nCPUCount);
798
799 Read( _T ( "DebugGDAL" ), &g_bGDAL_Debug );
800 Read( _T ( "DebugNMEA" ), &g_nNMEADebug );
801 Read( _T ( "AnchorWatchDefault" ), &g_nAWDefault );
802 Read( _T ( "AnchorWatchMax" ), &g_nAWMax );
803 Read( _T ( "GPSDogTimeout" ), &gps_watchdog_timeout_ticks );
804 Read( _T ( "DebugCM93" ), &g_bDebugCM93 );
805 Read( _T ( "DebugS57" ), &g_bDebugS57 ); // Show LUP and Feature info in object query
806 Read( _T ( "DebugBSBImg" ), &g_BSBImgDebug );
807 Read( _T ( "DebugGPSD" ), &g_bDebugGPSD );
808
809 Read( _T ( "DefaultFontSize"), &g_default_font_size );
810 Read( _T ( "DefaultFontFacename"), &g_default_font_facename );
811
812 Read( _T ( "UseGreenShipIcon" ), &g_bUseGreenShip );
813
814
815 Read( _T ( "AutoHideToolbar" ), &g_bAutoHideToolbar );
816 Read( _T ( "AutoHideToolbarSecs" ), &g_nAutoHideToolbar );
817
818 Read( _T ( "UseSimplifiedScalebar" ), &g_bsimplifiedScalebar );
819 Read( _T ( "ShowTide" ), &g_bShowTide );
820 Read( _T ( "ShowCurrent" ), &g_bShowCurrent );
821
822 int size_mm = -1;
823 Read( _T ( "DisplaySizeMM" ), &size_mm );
824
825 Read( _T ( "SelectionRadiusMM" ), &g_selection_radius_mm);
826 Read( _T ( "SelectionRadiusTouchMM" ), &g_selection_radius_touch_mm);
827
828 if(!bAsTemplate){
829 if(size_mm > 0){
830 g_config_display_size_mm = size_mm;
831 if((size_mm > 100) && (size_mm < 2000)){
832 g_display_size_mm = size_mm;
833 }
834 }
835 Read( _T ( "DisplaySizeManual" ), &g_config_display_size_manual );
836 }
837
838 Read( _T ( "GUIScaleFactor" ), &g_GUIScaleFactor );
839
840 Read( _T ( "ChartObjectScaleFactor" ), &g_ChartScaleFactor );
841 Read( _T ( "ShipScaleFactor" ), &g_ShipScaleFactor );
842 Read( _T ( "ENCSoundingScaleFactor" ), &g_ENCSoundingScaleFactor );
843
844 // Plugin catalog handler persistent variables.
845 Read( "CatalogCustomURL", &g_catalog_custom_url);
846 Read( "CatalogChannel", &g_catalog_channel);
847
848
849 // NMEA connection options.
850 if( !bAsTemplate ){
851 Read( _T ( "FilterNMEA_Avg" ), &g_bfilter_cogsog );
852 Read( _T ( "FilterNMEA_Sec" ), &g_COGFilterSec );
853 Read( _T ( "GPSIdent" ), &g_GPS_Ident );
854 Read( _T ( "UseGarminHostUpload" ), &g_bGarminHostUpload );
855 Read( _T ( "UseNMEA_GLL" ), &g_bUseGLL );
856 Read( _T ( "UseMagAPB" ), &g_bMagneticAPB );
857 Read( _T ( "TrackContinuous" ), &g_btrackContinuous, false );
858 }
859
860 Read( _T ( "ShowTrue" ), &g_bShowTrue );
861 Read( _T ( "ShowMag" ), &g_bShowMag );
862
863 wxString umv;
864 Read( _T ( "UserMagVariation" ), &umv );
865 if(umv.Len()) umv.ToDouble( &g_UserVar );
866
867 Read( _T ( "ScreenBrightness" ), &g_nbrightness );
868
869 Read( _T ( "MemFootprintTargetMB" ), &g_MemFootMB );
870
871 Read( _T ( "WindowsComPortMax" ), &g_nCOMPortCheck );
872
873 Read( _T ( "ChartQuilting" ), &g_bQuiltEnable );
874 Read( _T ( "ChartQuiltingInitial" ), &g_bQuiltStart );
875
876 Read( _T ( "CourseUpMode" ), &g_bCourseUp );
877 Read( _T ( "COGUPAvgSeconds" ), &g_COGAvgSec );
878 Read( _T ( "LookAheadMode" ), &g_bLookAhead );
879 Read( _T ( "SkewToNorthUp" ), &g_bskew_comp );
880
881 Read( _T ( "ShowFPS" ), &g_bShowFPS );
882
883 Read( _T( "NMEAAPBPrecision" ), &g_NMEAAPBPrecision );
884
885 Read( _T( "TalkerIdText" ), &g_TalkerIdText );
886 Read( _T( "MaxWaypointNameLength" ), &g_maxWPNameLength );
887
888 Read( _T( "ShowTrackPointTime" ), &g_bShowTrackPointTime, true );
889 /* opengl options */
890 #ifdef ocpnUSE_GL
891 if(!bAsTemplate ){
892 Read( _T ( "OpenGLExpert" ), &g_bGLexpert, false );
893 Read( _T ( "UseAcceleratedPanning" ), &g_GLOptions.m_bUseAcceleratedPanning, true );
894 Read( _T ( "GPUTextureCompression" ), &g_GLOptions.m_bTextureCompression);
895 Read( _T ( "GPUTextureCompressionCaching" ), &g_GLOptions.m_bTextureCompressionCaching);
896 Read( _T ( "PolygonSmoothing" ), &g_GLOptions.m_GLPolygonSmoothing);
897 Read( _T ( "LineSmoothing" ), &g_GLOptions.m_GLLineSmoothing);
898 Read( _T ( "GPUTextureDimension" ), &g_GLOptions.m_iTextureDimension );
899 Read( _T ( "GPUTextureMemSize" ), &g_GLOptions.m_iTextureMemorySize );
900 Read( _T ( "DebugOpenGL" ), &g_bDebugOGL );
901 Read( _T ( "OpenGL" ), &g_bopengl );
902 Read( _T ( "SoftwareGL" ), &g_bSoftwareGL );
903 }
904 #endif
905
906 Read( _T ( "SmoothPanZoom" ), &g_bsmoothpanzoom );
907
908 Read( _T ( "ToolbarX"), &g_maintoolbar_x );
909 Read( _T ( "ToolbarY" ), &g_maintoolbar_y );
910 Read( _T ( "ToolbarOrient" ), &g_maintoolbar_orient );
911 Read( _T ( "GlobalToolbarConfig" ), &g_toolbarConfig );
912
913 Read( _T ( "iENCToolbarX"), &g_iENCToolbarPosX );
914 Read( _T ( "iENCToolbarY"), &g_iENCToolbarPosY );
915
916 Read( _T ( "AnchorWatch1GUID" ), &g_AW1GUID );
917 Read( _T ( "AnchorWatch2GUID" ), &g_AW2GUID );
918
919 Read( _T ( "InitialStackIndex" ), &g_restore_stackindex );
920 Read( _T ( "InitialdBIndex" ), &g_restore_dbindex );
921
922 Read( _T ( "ChartNotRenderScaleFactor" ), &g_ChartNotRenderScaleFactor );
923
924 Read( _T ( "MobileTouch" ), &g_btouch );
925 Read( _T ( "ResponsiveGraphics" ), &g_bresponsive );
926 Read( _T ( "EnableRolloverBlock" ), &g_bRollover );
927
928 Read( _T ( "ZoomDetailFactor" ), &g_chart_zoom_modifier );
929 Read( _T ( "ZoomDetailFactorVector" ), &g_chart_zoom_modifier_vector );
930 Read( _T ( "PlusMinusZoomFactor" ), &g_plus_minus_zoom_factor, 2.0);
931
932 Read( _T ( "CM93DetailFactor" ), &g_cm93_zoom_factor );
933
934 Read( _T ( "CM93DetailZoomPosX" ), &g_detailslider_dialog_x );
935 Read( _T ( "CM93DetailZoomPosY" ), &g_detailslider_dialog_y );
936 Read( _T ( "ShowCM93DetailSlider" ), &g_bShowDetailSlider );
937
938 Read( _T ( "SENC_LOD_Pixels" ), &g_SENC_LOD_pixels );
939
940 Read( _T ( "SkewCompUpdatePeriod" ), &g_SkewCompUpdatePeriod );
941
942 Read( _T ( "SetSystemTime" ), &s_bSetSystemTime );
943 Read( _T ( "ShowStatusBar" ), &g_bShowStatusBar );
944 #ifndef __WXOSX__
945 Read( _T ( "ShowMenuBar" ), &g_bShowMenuBar );
946 #endif
947 Read( _T ( "Fullscreen" ), &g_bFullscreen );
948 Read( _T ( "ShowCompassWindow" ), &g_bShowCompassWin );
949 Read( _T ( "ShowGrid" ), &g_bDisplayGrid );
950 Read( _T ( "PlayShipsBells" ), &g_bPlayShipsBells );
951 Read( _T ( "SoundDeviceIndex" ), &g_iSoundDeviceIndex );
952 Read( _T ( "FullscreenToolbar" ), &g_bFullscreenToolbar );
953 Read( _T ( "PermanentMOBIcon" ), &g_bPermanentMOBIcon );
954 Read( _T ( "ShowLayers" ), &g_bShowLayers );
955 Read( _T ( "ShowDepthUnits" ), &g_bShowDepthUnits );
956 Read( _T ( "AutoAnchorDrop" ), &g_bAutoAnchorMark );
957 Read( _T ( "ShowChartOutlines" ), &g_bShowOutlines );
958 Read( _T ( "ShowActiveRouteHighway" ), &g_bShowActiveRouteHighway );
959 Read( _T ( "ShowActiveRouteTotal" ), &g_bShowRouteTotal );
960 Read( _T ( "MostRecentGPSUploadConnection" ), &g_uploadConnection);
961 Read( _T ( "ShowChartBar" ), &g_bShowChartBar );
962 Read( _T ( "SDMMFormat" ), &g_iSDMMFormat ); //0 = "Degrees, Decimal minutes"), 1 = "Decimal degrees", 2 = "Degrees,Minutes, Seconds"
963
964 Read( _T ( "DistanceFormat" ), &g_iDistanceFormat ); //0 = "Nautical miles"), 1 = "Statute miles", 2 = "Kilometers", 3 = "Meters"
965 Read( _T ( "SpeedFormat" ), &g_iSpeedFormat ); //0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
966
967 // LIVE ETA OPTION
968 Read( _T ( "LiveETA" ), &g_bShowLiveETA );
969 Read( _T ( "DefaultBoatSpeed" ), &g_defaultBoatSpeed );
970
971 Read( _T ( "OwnshipCOGPredictorMinutes" ), &g_ownship_predictor_minutes );
972 Read( _T ( "OwnshipCOGPredictorWidth" ), &g_cog_predictor_width );
973 Read( _T ( "OwnshipHDTPredictorMiles" ), &g_ownship_HDTpredictor_miles );
974
975 Read( _T ( "OwnShipIconType" ), &g_OwnShipIconType );
976 Read( _T ( "OwnShipLength" ), &g_n_ownship_length_meters );
977 Read( _T ( "OwnShipWidth" ), &g_n_ownship_beam_meters );
978 Read( _T ( "OwnShipGPSOffsetX" ), &g_n_gps_antenna_offset_x );
979 Read( _T ( "OwnShipGPSOffsetY" ), &g_n_gps_antenna_offset_y );
980 Read( _T ( "OwnShipMinSize" ), &g_n_ownship_min_mm );
981 Read( _T ( "OwnShipSogCogCalc" ), &g_own_ship_sog_cog_calc );
982 Read( _T ( "OwnShipSogCogCalcDampSec"), &g_own_ship_sog_cog_calc_damp_sec );
983
984 wxString racr;
985 Read( _T ( "RouteArrivalCircleRadius" ), &racr );
986 if(racr.Len())
987 racr.ToDouble( &g_n_arrival_circle_radius);
988
989 Read( _T ( "FullScreenQuilt" ), &g_bFullScreenQuilt );
990
991 Read( _T ( "StartWithTrackActive" ), &g_bTrackCarryOver );
992 Read( _T ( "AutomaticDailyTracks" ), &g_bTrackDaily );
993 Read( _T ( "TrackRotateAt" ), &g_track_rotate_time );
994 Read( _T ( "TrackRotateTimeType" ), &g_track_rotate_time_type );
995 Read( _T ( "HighlightTracks" ), &g_bHighliteTracks );
996
997 wxString stps;
998 Read( _T ( "PlanSpeed" ), &stps );
999 if(!stps.IsEmpty())
1000 stps.ToDouble( &g_PlanSpeed );
1001
1002 Read( _T ( "VisibleLayers" ), &g_VisibleLayers );
1003 Read( _T ( "InvisibleLayers" ), &g_InvisibleLayers );
1004 Read( _T ( "VisNameInLayers" ), &g_VisiNameinLayers );
1005 Read( _T ( "InvisNameInLayers" ), &g_InVisiNameinLayers );
1006
1007 Read( _T ( "PreserveScaleOnX" ), &g_bPreserveScaleOnX );
1008
1009 Read( _T ( "ShowMUIZoomButtons" ), &g_bShowMuiZoomButtons );
1010
1011 Read( _T ( "Locale" ), &g_locale );
1012 Read( _T ( "LocaleOverride" ), &g_localeOverride );
1013
1014 //We allow 0-99 backups ov navobj.xml
1015 Read( _T ( "KeepNavobjBackups" ), &g_navobjbackups );
1016
1017 NMEALogWindow::Get().SetSize(Read(_T("NMEALogWindowSizeX"), 600L), Read(_T("NMEALogWindowSizeY"), 400L));
1018 NMEALogWindow::Get().SetPos(Read(_T("NMEALogWindowPosX"), 10L), Read(_T("NMEALogWindowPosY"), 10L));
1019 NMEALogWindow::Get().CheckPos(display_width, display_height);
1020
1021 // Boolean to cater for legacy Input COM Port filer behaviour, i.e. show msg filtered but put msg on bus.
1022 Read( _T ( "LegacyInputCOMPortFilterBehaviour" ), &g_b_legacy_input_filter_behaviour );
1023
1024 // Boolean to cater for sailing when not approaching waypoint
1025 Read( _T( "AdvanceRouteWaypointOnArrivalOnly" ), &g_bAdvanceRouteWaypointOnArrivalOnly);
1026
1027 Read( _T ( "EnableRotateKeys" ), &g_benable_rotate );
1028 Read( _T ( "EmailCrashReport" ), &g_bEmailCrashReport );
1029
1030 g_benableAISNameCache = true;
1031 Read( _T ( "EnableAISNameCache" ), &g_benableAISNameCache );
1032
1033 Read( _T ( "EnableUDPNullHeader" ), &g_benableUDPNullHeader );
1034
1035 SetPath( _T ( "/Settings/GlobalState" ) );
1036
1037 Read( _T ( "FrameWinX" ), &g_nframewin_x );
1038 Read( _T ( "FrameWinY" ), &g_nframewin_y );
1039 Read( _T ( "FrameWinPosX" ), &g_nframewin_posx );
1040 Read( _T ( "FrameWinPosY" ), &g_nframewin_posy );
1041 Read( _T ( "FrameMax" ), &g_bframemax );
1042
1043 Read( _T ( "ClientPosX" ), &g_lastClientRectx );
1044 Read( _T ( "ClientPosY" ), &g_lastClientRecty );
1045 Read( _T ( "ClientSzX" ), &g_lastClientRectw );
1046 Read( _T ( "ClientSzY" ), &g_lastClientRecth );
1047
1048 Read( _T( "RoutePropSizeX" ), &g_route_prop_sx );
1049 Read( _T( "RoutePropSizeY" ), &g_route_prop_sy );
1050 Read( _T( "RoutePropPosX" ), &g_route_prop_x );
1051 Read( _T( "RoutePropPosY" ), &g_route_prop_y );
1052
1053 read_int = -1;
1054 Read( _T ( "S52_DEPTH_UNIT_SHOW" ), &read_int ); // default is metres
1055 if(read_int >= 0){
1056 read_int = wxMax(read_int, 0); // qualify value
1057 read_int = wxMin(read_int, 2);
1058 g_nDepthUnitDisplay = read_int;
1059 }
1060
1061 // AIS
1062 wxString s;
1063 SetPath( _T ( "/Settings/AIS" ) );
1064
1065 g_bUseOnlyConfirmedAISName = false;
1066 Read( _T ( "UseOnlyConfirmedAISName" ), &g_bUseOnlyConfirmedAISName );
1067
1068 Read( _T ( "bNoCPAMax" ), &g_bCPAMax );
1069
1070 Read( _T ( "NoCPAMaxNMi" ), &s );
1071 s.ToDouble( &g_CPAMax_NM );
1072
1073 Read( _T ( "bCPAWarn" ), &g_bCPAWarn );
1074
1075 Read( _T ( "CPAWarnNMi" ), &s );
1076 s.ToDouble( &g_CPAWarn_NM );
1077
1078 Read( _T ( "bTCPAMax" ), &g_bTCPA_Max );
1079
1080 Read( _T ( "TCPAMaxMinutes" ), &s );
1081 s.ToDouble( &g_TCPA_Max );
1082
1083 Read( _T ( "bMarkLostTargets" ), &g_bMarkLost );
1084
1085 Read( _T ( "MarkLost_Minutes" ), &s );
1086 s.ToDouble( &g_MarkLost_Mins );
1087
1088 Read( _T ( "bRemoveLostTargets" ), &g_bRemoveLost );
1089
1090 Read( _T ( "RemoveLost_Minutes" ), &s );
1091 s.ToDouble( &g_RemoveLost_Mins );
1092
1093 Read( _T ( "bShowCOGArrows" ), &g_bShowCOG );
1094
1095 Read( _T ( "CogArrowMinutes" ), &s );
1096 s.ToDouble( &g_ShowCOG_Mins );
1097
1098 Read( _T ( "bShowTargetTracks" ), &g_bAISShowTracks );
1099
1100
1101 if( Read( _T ( "TargetTracksLimit" ), &s ) ) {
1102 s.ToDouble( &g_AISShowTracks_Limit );
1103 g_AISShowTracks_Limit = wxMax(300.0, g_AISShowTracks_Limit);
1104 }
1105 if( Read( _T ( "TargetTracksMinutes" ), &s ) ) {
1106 s.ToDouble( &g_AISShowTracks_Mins );
1107 g_AISShowTracks_Mins = wxMax(1.0, g_AISShowTracks_Mins);
1108 g_AISShowTracks_Mins = wxMin(g_AISShowTracks_Limit, g_AISShowTracks_Mins);
1109 }
1110
1111 Read( _T ( "bHideMooredTargets" ), &g_bHideMoored );
1112 if(Read( _T ( "MooredTargetMaxSpeedKnots" ), &s ))
1113 s.ToDouble( &g_ShowMoored_Kts );
1114
1115 Read(_T ("bShowScaledTargets"), &g_bAllowShowScaled );
1116 Read( _T ( "AISScaledNumber" ), &g_ShowScaled_Num );
1117 Read( _T ( "AISScaledNumberWeightSOG" ), &g_ScaledNumWeightSOG );
1118 Read( _T ( "AISScaledNumberWeightCPA" ), &g_ScaledNumWeightCPA );
1119 Read( _T ( "AISScaledNumberWeightTCPA" ), &g_ScaledNumWeightTCPA );
1120 Read( _T ( "AISScaledNumberWeightRange" ),& g_ScaledNumWeightRange );
1121 Read( _T ( "AISScaledNumberWeightSizeOfTarget" ), &g_ScaledNumWeightSizeOfT );
1122 Read( _T ( "AISScaledSizeMinimal" ), &g_ScaledSizeMinimal );
1123 Read(_T("AISShowScaled"), &g_bShowScaled );
1124
1125 Read( _T ( "bShowAreaNotices" ), &g_bShowAreaNotices );
1126 Read( _T ( "bDrawAISSize" ), &g_bDrawAISSize );
1127 Read( _T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime );
1128 Read( _T ( "bShowAISName" ), &g_bShowAISName );
1129 Read( _T ( "AISRealtimeMinSpeedKnots" ), &g_AIS_RealtPred_Kts, 0.7 );
1130 Read( _T ( "bAISAlertDialog" ), &g_bAIS_CPA_Alert );
1131 Read( _T ( "ShowAISTargetNameScale" ), &g_Show_Target_Name_Scale );
1132 Read( _T ( "bWplIsAprsPositionReport" ), &g_bWplIsAprsPosition );
1133 Read( _T ( "AISCOGPredictorWidth" ), &g_ais_cog_predictor_width );
1134
1135 Read( _T ( "bAISAlertAudio" ), &g_bAIS_CPA_Alert_Audio );
1136 Read( _T ( "AISAlertAudioFile" ), &g_sAIS_Alert_Sound_File );
1137 Read( _T ( "bAISAlertSuppressMoored" ), &g_bAIS_CPA_Alert_Suppress_Moored );
1138
1139 Read( _T ( "bAISAlertAckTimeout" ), &g_bAIS_ACK_Timeout );
1140 if(Read( _T ( "AlertAckTimeoutMinutes" ), &s ))
1141 s.ToDouble( &g_AckTimeout_Mins );
1142
1143 Read( _T ( "AlertDialogSizeX" ), &g_ais_alert_dialog_sx );
1144 Read( _T ( "AlertDialogSizeY" ), &g_ais_alert_dialog_sy );
1145 Read( _T ( "AlertDialogPosX" ), &g_ais_alert_dialog_x );
1146 Read( _T ( "AlertDialogPosY" ), &g_ais_alert_dialog_y );
1147 Read( _T ( "QueryDialogPosX" ), &g_ais_query_dialog_x );
1148 Read( _T ( "QueryDialogPosY" ), &g_ais_query_dialog_y );
1149
1150 Read( _T ( "AISTargetListPerspective" ), &g_AisTargetList_perspective );
1151 Read( _T ( "AISTargetListRange" ), &g_AisTargetList_range );
1152 Read( _T ( "AISTargetListSortColumn" ), &g_AisTargetList_sortColumn );
1153 Read( _T ( "bAISTargetListSortReverse" ), &g_bAisTargetList_sortReverse );
1154 Read( _T ( "AISTargetListColumnSpec" ), &g_AisTargetList_column_spec );
1155 Read( _T ("AISTargetListColumnOrder"), &g_AisTargetList_column_order);
1156
1157 Read( _T ( "bAISRolloverShowClass" ), &g_bAISRolloverShowClass );
1158 Read( _T ( "bAISRolloverShowCOG" ), &g_bAISRolloverShowCOG );
1159 Read( _T ( "bAISRolloverShowCPA" ), &g_bAISRolloverShowCPA );
1160
1161 Read( _T ( "S57QueryDialogSizeX" ), &g_S57_dialog_sx );
1162 Read( _T ( "S57QueryDialogSizeY" ), &g_S57_dialog_sy );
1163 Read( _T ( "S57QueryExtraDialogSizeX" ), &g_S57_extradialog_sx );
1164 Read( _T ( "S57QueryExtraDialogSizeY" ), &g_S57_extradialog_sy );
1165
1166
1167 wxString strpres( _T ( "PresentationLibraryData" ) );
1168 wxString valpres;
1169 SetPath( _T ( "/Directories" ) );
1170 Read( strpres, &valpres ); // Get the File name
1171 if(!valpres.IsEmpty())
1172 g_UserPresLibData = valpres;
1173
1174 wxString strs( _T ( "SENCFileLocation" ) );
1175 SetPath( _T ( "/Directories" ) );
1176 wxString vals;
1177 Read( strs, &vals ); // Get the Directory name
1178 if(!vals.IsEmpty())
1179 g_SENCPrefix = vals;
1180
1181 SetPath( _T ( "/Directories" ) );
1182 wxString vald;
1183 Read( _T ( "InitChartDir" ), &vald ); // Get the Directory name
1184
1185 wxString dirnamed( vald );
1186 if( !dirnamed.IsEmpty() ) {
1187 if( pInit_Chart_Dir->IsEmpty() ) // on second pass, don't overwrite
1188 {
1189 pInit_Chart_Dir->Clear();
1190 pInit_Chart_Dir->Append( vald );
1191 }
1192 }
1193
1194 Read( _T ( "GPXIODir" ), &g_gpx_path ); // Get the Directory name
1195 Read( _T ( "TCDataDir" ), &g_TCData_Dir ); // Get the Directory name
1196 Read( _T ( "BasemapDir"), &gWorldMapLocation );
1197 Read( _T ( "pluginInstallDir"), &g_winPluginDir );
1198 wxLogMessage("winPluginDir, read from ini file: %s",
1199 g_winPluginDir.mb_str().data());
1200
1201
1202 SetPath( _T ( "/Settings/GlobalState" ) );
1203
1204 if(Read( _T ( "nColorScheme" ), &read_int ))
1205 global_color_scheme = (ColorScheme) read_int;
1206
1207 if(! bAsTemplate ){
1208 SetPath( _T ( "/Settings/NMEADataSource" ) );
1209
1210 wxString connectionconfigs;
1211 Read ( _T( "DataConnections" ), &connectionconfigs );
1212 if(!connectionconfigs.IsEmpty()){
1213 wxArrayString confs = wxStringTokenize(connectionconfigs, _T("|"));
1214 g_pConnectionParams->Clear();
1215 for (size_t i = 0; i < confs.Count(); i++)
1216 {
1217 ConnectionParams * prm = new ConnectionParams(confs[i]);
1218 if (!prm->Valid) {
1219 wxLogMessage( _T( "Skipped invalid DataStream config") );
1220 delete prm;
1221 continue;
1222 }
1223 g_pConnectionParams->Add(prm);
1224 }
1225 }
1226 }
1227
1228
1229
1230 SetPath( _T ( "/Settings/GlobalState" ) );
1231 wxString st;
1232
1233 double st_lat, st_lon;
1234 if( Read( _T ( "VPLatLon" ), &st ) ) {
1235 sscanf( st.mb_str( wxConvUTF8 ), "%lf,%lf", &st_lat, &st_lon );
1236
1237 // Sanity check the lat/lon...both have to be reasonable.
1238 if( fabs( st_lon ) < 360. ) {
1239 while( st_lon < -180. )
1240 st_lon += 360.;
1241
1242 while( st_lon > 180. )
1243 st_lon -= 360.;
1244
1245 vLon = st_lon;
1246 }
1247
1248 if( fabs( st_lat ) < 90.0 ) vLat = st_lat;
1249
1250 s.Printf( _T ( "Setting Viewpoint Lat/Lon %g, %g" ), vLat, vLon );
1251 wxLogMessage( s );
1252
1253 }
1254
1255 double st_view_scale, st_rotation;
1256 if( Read( wxString( _T ( "VPScale" ) ), &st ) ) {
1257 sscanf( st.mb_str( wxConvUTF8 ), "%lf", &st_view_scale );
1258 // Sanity check the scale
1259 st_view_scale = fmax ( st_view_scale, .001/32 );
1260 st_view_scale = fmin ( st_view_scale, 4 );
1261 initial_scale_ppm = st_view_scale;
1262 }
1263
1264 if( Read( wxString( _T ( "VPRotation" ) ), &st ) ) {
1265 sscanf( st.mb_str( wxConvUTF8 ), "%lf", &st_rotation );
1266 // Sanity check the rotation
1267 st_rotation = fmin ( st_rotation, 360 );
1268 st_rotation = fmax ( st_rotation, 0 );
1269 initial_rotation = st_rotation * PI / 180.;
1270 }
1271
1272 wxString sll;
1273 double lat, lon;
1274 if( Read( _T ( "OwnShipLatLon" ), &sll ) ) {
1275 sscanf( sll.mb_str( wxConvUTF8 ), "%lf,%lf", &lat, &lon );
1276
1277 // Sanity check the lat/lon...both have to be reasonable.
1278 if( fabs( lon ) < 360. ) {
1279 while( lon < -180. )
1280 lon += 360.;
1281
1282 while( lon > 180. )
1283 lon -= 360.;
1284
1285 gLon = lon;
1286 }
1287
1288 if( fabs( lat ) < 90.0 ) gLat = lat;
1289
1290 s.Printf( _T ( "Setting Ownship Lat/Lon %g, %g" ), gLat, gLon );
1291 wxLogMessage( s );
1292
1293 }
1294
1295 // Fonts
1296
1297 // Load the persistent Auxiliary Font descriptor Keys
1298 SetPath ( _T ( "/Settings/AuxFontKeys" ) );
1299
1300 wxString strk;
1301 long dummyk;
1302 wxString kval;
1303 bool bContk = GetFirstEntry( strk, dummyk );
1304 bool bNewKey = false;
1305 while( bContk ) {
1306 Read( strk, &kval );
1307 bNewKey = FontMgr::Get().AddAuxKey(kval);
1308 if(!bAsTemplate && !bNewKey) {
1309 DeleteEntry( strk );
1310 dummyk--;
1311 }
1312 bContk = GetNextEntry( strk, dummyk );
1313 }
1314
1315 #ifdef __WXX11__
1316 SetPath ( _T ( "/Settings/X11Fonts" ) );
1317 #endif
1318
1319 #ifdef __WXGTK__
1320 SetPath ( _T ( "/Settings/GTKFonts" ) );
1321 #endif
1322
1323 #ifdef __WXMSW__
1324 SetPath( _T ( "/Settings/MSWFonts" ) );
1325 #endif
1326
1327 #ifdef __WXMAC__
1328 SetPath ( _T ( "/Settings/MacFonts" ) );
1329 #endif
1330
1331 #ifdef __WXQT__
1332 SetPath ( _T ( "/Settings/QTFonts" ) );
1333 #endif
1334
1335 wxString str;
1336 long dummy;
1337 wxString *pval = new wxString;
1338 wxArrayString deleteList;
1339
1340 bool bCont = GetFirstEntry( str, dummy );
1341 while( bCont ) {
1342 Read( str, pval );
1343
1344 if( str.StartsWith( _T("Font") ) ) {
1345 // Convert pre 3.1 setting. Can't delete old entries from inside the
1346 // GetNextEntry() loop, so we need to save those and delete outside.
1347 deleteList.Add( str );
1348 wxString oldKey = pval->BeforeFirst( _T(':') );
1349 str = FontMgr::GetFontConfigKey( oldKey );
1350 }
1351
1352 if( pval->IsEmpty() || pval->StartsWith(_T(":")) ) {
1353 deleteList.Add( str );
1354 }
1355 else
1356 FontMgr::Get().LoadFontNative( &str, pval );
1357
1358 bCont = GetNextEntry( str, dummy );
1359 }
1360
1361 for( unsigned int i=0; i<deleteList.Count(); i++ ) {
1362 DeleteEntry( deleteList[i] );
1363 }
1364 deleteList.Clear();
1365 delete pval;
1366
1367 // Tide/Current Data Sources
1368 SetPath( _T ( "/TideCurrentDataSources" ) );
1369 if( GetNumberOfEntries() ) {
1370 TideCurrentDataSet.Clear();
1371 wxString str, val;
1372 long dummy;
1373 bool bCont = GetFirstEntry( str, dummy );
1374 while( bCont ) {
1375 Read( str, &val ); // Get a file name
1376 TideCurrentDataSet.Add(val);
1377 bCont = GetNextEntry( str, dummy );
1378 }
1379 }
1380
1381
1382
1383 // Groups
1384 LoadConfigGroups( g_pGroupArray );
1385
1386 // // Multicanvas Settings
1387 // LoadCanvasConfigs();
1388
1389 SetPath( _T ( "/Settings/Others" ) );
1390
1391 // Radar rings
1392 Read( _T ( "RadarRingsNumberVisible" ), &val );
1393 if( val.Length() > 0 ) g_iNavAidRadarRingsNumberVisible = atoi( val.mb_str() );
1394
1395 Read( _T ( "RadarRingsStep" ), &val );
1396 if( val.Length() > 0 ) g_fNavAidRadarRingsStep = atof( val.mb_str() );
1397
1398 Read( _T ( "RadarRingsStepUnits" ), &g_pNavAidRadarRingsStepUnits );
1399
1400 wxString l_wxsOwnshipRangeRingsColour;
1401 Read( _T ( "RadarRingsColour" ), &l_wxsOwnshipRangeRingsColour );
1402 if(l_wxsOwnshipRangeRingsColour.Length()) g_colourOwnshipRangeRingsColour.Set( l_wxsOwnshipRangeRingsColour );
1403
1404 // Waypoint Radar rings
1405 Read( _T ( "WaypointRangeRingsNumber" ), &val );
1406 if( val.Length() > 0 ) g_iWaypointRangeRingsNumber = atoi( val.mb_str() );
1407
1408 Read( _T ( "WaypointRangeRingsStep" ), &val );
1409 if( val.Length() > 0 ) g_fWaypointRangeRingsStep = atof( val.mb_str() );
1410
1411 Read( _T ( "WaypointRangeRingsStepUnits" ), &g_iWaypointRangeRingsStepUnits );
1412
1413 wxString l_wxsWaypointRangeRingsColour;
1414 Read( _T( "WaypointRangeRingsColour" ), &l_wxsWaypointRangeRingsColour );
1415 g_colourWaypointRangeRingsColour.Set( l_wxsWaypointRangeRingsColour );
1416
1417 if ( !Read( _T("WaypointUseScaMin"), &g_bUseWptScaMin ) ) g_bUseWptScaMin = false;
1418 if ( !Read( _T("WaypointScaMinValue"), &g_iWpt_ScaMin ) ) g_iWpt_ScaMin = 2147483646;
1419 if ( !Read( _T("WaypointUseScaMinOverrule"), &g_bOverruleScaMin ) ) g_bOverruleScaMin = false;
1420 if ( !Read( _T("WaypointsShowName"), &g_bShowWptName ) ) g_bShowWptName = true;
1421
1422
1423
1424 // Support Version 3.0 and prior config setting for Radar Rings
1425 bool b300RadarRings= true;
1426 if(Read ( _T ( "ShowRadarRings" ), &b300RadarRings )){
1427 if(!b300RadarRings)
1428 g_iNavAidRadarRingsNumberVisible = 0;
1429 }
1430
1431 Read( _T ( "ConfirmObjectDeletion" ), &g_bConfirmObjectDelete );
1432
1433 // Waypoint dragging with mouse
1434 g_bWayPointPreventDragging = false;
1435 Read( _T ( "WaypointPreventDragging" ), &g_bWayPointPreventDragging );
1436
1437 g_bEnableZoomToCursor = false;
1438 Read( _T ( "EnableZoomToCursor" ), &g_bEnableZoomToCursor );
1439
1440 val.Clear();
1441 Read( _T ( "TrackIntervalSeconds" ), &val );
1442 if( val.Length() > 0 ) {
1443 double tval = atof( val.mb_str() );
1444 if( tval >= 2. ) g_TrackIntervalSeconds = tval;
1445 }
1446
1447 val.Clear();
1448 Read( _T ( "TrackDeltaDistance" ), &val );
1449 if( val.Length() > 0 ) {
1450 double tval = atof( val.mb_str() );
1451 if( tval >= 0.05 ) g_TrackDeltaDistance = tval;
1452 }
1453
1454 Read( _T ( "TrackPrecision" ), &g_nTrackPrecision );
1455
1456 Read( _T ( "NavObjectFileName" ), m_sNavObjSetFile );
1457
1458 Read( _T ( "RouteLineWidth" ), &g_route_line_width );
1459 Read( _T ( "TrackLineWidth" ), &g_track_line_width );
1460
1461 wxString l_wxsTrackLineColour;
1462 if(Read( _T( "TrackLineColour" ), &l_wxsTrackLineColour ))
1463 g_colourTrackLineColour.Set( l_wxsTrackLineColour );
1464
1465 Read( _T ( "TideCurrentWindowScale" ), &g_tcwin_scale );
1466 Read( _T ( "DefaultWPIcon" ), &g_default_wp_icon );
1467 Read( _T ( "DefaultRPIcon" ), &g_default_routepoint_icon );
1468
1469 SetPath( _T ( "/MMSIProperties" ) );
1470 int iPMax = GetNumberOfEntries();
1471 if( iPMax ) {
1472 g_MMSI_Props_Array.Empty();
1473 wxString str, val;
1474 long dummy;
1475 bool bCont = pConfig->GetFirstEntry( str, dummy );
1476 while( bCont ) {
1477 pConfig->Read( str, &val ); // Get an entry
1478
1479 MMSIProperties *pProps = new MMSIProperties( val );
1480 g_MMSI_Props_Array.Add(pProps);
1481
1482 bCont = pConfig->GetNextEntry( str, dummy );
1483
1484 }
1485 }
1486
1487 return ( 0 );
1488 }
1489
LoadS57Config()1490 void MyConfig::LoadS57Config()
1491 {
1492 if( !ps52plib )
1493 return;
1494
1495 int read_int;
1496 double dval;
1497 SetPath( _T ( "/Settings/GlobalState" ) );
1498
1499 Read( _T ( "bShowS57Text" ), &read_int, 1 );
1500 ps52plib->SetShowS57Text( !( read_int == 0 ) );
1501
1502 Read( _T ( "bShowS57ImportantTextOnly" ), &read_int, 0 );
1503 ps52plib->SetShowS57ImportantTextOnly( !( read_int == 0 ) );
1504
1505 Read( _T ( "bShowLightDescription" ), &read_int, 0 );
1506 ps52plib->SetShowLdisText( !( read_int == 0 ) );
1507
1508 Read( _T ( "bExtendLightSectors" ), &read_int, 0 );
1509 ps52plib->SetExtendLightSectors( !( read_int == 0 ) );
1510
1511 Read( _T ( "nDisplayCategory" ), &read_int, (enum _DisCat) STANDARD );
1512 ps52plib->SetDisplayCategory((enum _DisCat) read_int );
1513
1514 Read( _T ( "nSymbolStyle" ), &read_int, (enum _LUPname) PAPER_CHART );
1515 ps52plib->m_nSymbolStyle = (LUPname) read_int;
1516
1517 Read( _T ( "nBoundaryStyle" ), &read_int, PLAIN_BOUNDARIES );
1518 ps52plib->m_nBoundaryStyle = (LUPname) read_int;
1519
1520 Read( _T ( "bShowSoundg" ), &read_int, 1 );
1521 ps52plib->m_bShowSoundg = !( read_int == 0 );
1522
1523 Read( _T ( "bShowMeta" ), &read_int, 0 );
1524 ps52plib->m_bShowMeta = !( read_int == 0 );
1525
1526 Read( _T ( "bUseSCAMIN" ), &read_int, 1 );
1527 ps52plib->m_bUseSCAMIN = !( read_int == 0 );
1528
1529 Read( _T ( "bShowAtonText" ), &read_int, 1 );
1530 ps52plib->m_bShowAtonText = !( read_int == 0 );
1531
1532 Read( _T ( "bDeClutterText" ), &read_int, 0 );
1533 ps52plib->m_bDeClutterText = !( read_int == 0 );
1534
1535 Read( _T ( "bShowNationalText" ), &read_int, 0 );
1536 ps52plib->m_bShowNationalTexts = !( read_int == 0 );
1537
1538 Read( _T ( "ENCSoundingScaleFactor" ), &read_int, 0 );
1539 ps52plib->m_nSoundingFactor = read_int;
1540
1541
1542 if( Read( _T ( "S52_MAR_SAFETY_CONTOUR" ), &dval, 3.0 ) ) {
1543 S52_setMarinerParam( S52_MAR_SAFETY_CONTOUR, dval );
1544 S52_setMarinerParam( S52_MAR_SAFETY_DEPTH, dval ); // Set safety_contour and safety_depth the same
1545 }
1546
1547 if( Read( _T ( "S52_MAR_SHALLOW_CONTOUR" ), &dval, 2.0 ) ) S52_setMarinerParam(
1548 S52_MAR_SHALLOW_CONTOUR, dval );
1549
1550 if( Read( _T ( "S52_MAR_DEEP_CONTOUR" ), &dval, 6.0 ) ) S52_setMarinerParam(
1551 S52_MAR_DEEP_CONTOUR, dval );
1552
1553 if( Read( _T ( "S52_MAR_TWO_SHADES" ), &dval, 0.0 ) ) S52_setMarinerParam(
1554 S52_MAR_TWO_SHADES, dval );
1555
1556 ps52plib->UpdateMarinerParams();
1557
1558 SetPath( _T ( "/Settings/GlobalState" ) );
1559 Read( _T ( "S52_DEPTH_UNIT_SHOW" ), &read_int, 1 ); // default is metres
1560 read_int = wxMax(read_int, 0); // qualify value
1561 read_int = wxMin(read_int, 2);
1562 ps52plib->m_nDepthUnitDisplay = read_int;
1563 g_nDepthUnitDisplay = read_int;
1564
1565 // S57 Object Class Visibility
1566
1567 OBJLElement *pOLE;
1568
1569 SetPath( _T ( "/Settings/ObjectFilter" ) );
1570
1571 int iOBJMax = GetNumberOfEntries();
1572 if( iOBJMax ) {
1573
1574 wxString str;
1575 long val;
1576 long dummy;
1577
1578 wxString sObj;
1579
1580 bool bCont = pConfig->GetFirstEntry( str, dummy );
1581 while( bCont ) {
1582 pConfig->Read( str, &val ); // Get an Object Viz
1583
1584 bool bNeedNew = true;
1585
1586 if( str.StartsWith( _T ( "viz" ), &sObj ) ) {
1587 for( unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount(); iPtr++ ) {
1588 pOLE = (OBJLElement *) ( ps52plib->pOBJLArray->Item( iPtr ) );
1589 if( !strncmp( pOLE->OBJLName, sObj.mb_str(), 6 ) ) {
1590 pOLE->nViz = val;
1591 bNeedNew = false;
1592 break;
1593 }
1594 }
1595
1596 if( bNeedNew ) {
1597 pOLE = (OBJLElement *) calloc( sizeof(OBJLElement), 1 );
1598 memcpy( pOLE->OBJLName, sObj.mb_str(), OBJL_NAME_LEN );
1599 pOLE->nViz = 1;
1600
1601 ps52plib->pOBJLArray->Add( (void *) pOLE );
1602 }
1603 }
1604 bCont = pConfig->GetNextEntry( str, dummy );
1605 }
1606 }
1607 }
1608
LoadNavObjects()1609 void MyConfig::LoadNavObjects()
1610 {
1611 // next thing to do is read tracks, etc from the NavObject XML file,
1612 wxLogMessage( _T("Loading navobjects from navobj.xml") );
1613 CreateRotatingNavObjBackup();
1614
1615 if( NULL == m_pNavObjectInputSet )
1616 m_pNavObjectInputSet = new NavObjectCollection1();
1617
1618 int wpt_dups = 0;
1619 if( ::wxFileExists( m_sNavObjSetFile ) &&
1620 m_pNavObjectInputSet->load_file( m_sNavObjSetFile.fn_str() ) )
1621 m_pNavObjectInputSet->LoadAllGPXObjects(false, wpt_dups);
1622
1623 wxLogMessage( _T("Done loading navobjects, %d duplicate waypoints ignored"), wpt_dups );
1624 delete m_pNavObjectInputSet;
1625
1626 if( ::wxFileExists( m_sNavObjSetChangesFile ) ) {
1627
1628 wxULongLong size = wxFileName::GetSize(m_sNavObjSetChangesFile);
1629
1630 //We crashed last time :(
1631 //That's why this file still exists...
1632 //Let's reconstruct the unsaved changes
1633 NavObjectChanges *pNavObjectChangesSet = new NavObjectChanges();
1634 pNavObjectChangesSet->load_file( m_sNavObjSetChangesFile.fn_str() );
1635
1636 // Remove the file before applying the changes,
1637 // just in case the changes file itself causes a fault.
1638 // If it does fault, at least the next restart will proceed without fault.
1639 if( ::wxFileExists( m_sNavObjSetChangesFile ) )
1640 ::wxRemoveFile( m_sNavObjSetChangesFile );
1641
1642 if(size != 0){
1643 wxLogMessage( _T("Applying NavObjChanges") );
1644 pNavObjectChangesSet->ApplyChanges();
1645 UpdateNavObj();
1646 }
1647
1648 delete pNavObjectChangesSet;
1649
1650 }
1651
1652 m_pNavObjectChangesSet = new NavObjectChanges(m_sNavObjSetChangesFile);
1653 }
1654
LoadLayers(wxString & path)1655 bool MyConfig::LoadLayers(wxString &path)
1656 {
1657 wxArrayString file_array;
1658 wxDir dir;
1659 Layer *l;
1660 dir.Open( path );
1661 if( dir.IsOpened() ) {
1662 wxString filename;
1663 bool cont = dir.GetFirst( &filename );
1664 while( cont ) {
1665 file_array.Clear();
1666 filename.Prepend( wxFileName::GetPathSeparator() );
1667 filename.Prepend( path );
1668 wxFileName f( filename );
1669 size_t nfiles = 0;
1670 if( f.GetExt().IsSameAs( wxT("gpx") ) )
1671 file_array.Add( filename); // single-gpx-file layer
1672 else{
1673 if(wxDir::Exists( filename ) ){
1674 wxDir dir( filename );
1675 if( dir.IsOpened() ){
1676 nfiles = dir.GetAllFiles( filename, &file_array, wxT("*.gpx") ); // layers subdirectory set
1677 }
1678 }
1679 }
1680
1681 if( file_array.GetCount() ){
1682 l = new Layer();
1683 l->m_LayerID = ++g_LayerIdx;
1684 l->m_LayerFileName = file_array[0];
1685 if( file_array.GetCount() <= 1 )
1686 wxFileName::SplitPath( file_array[0], NULL, NULL, &( l->m_LayerName ), NULL, NULL );
1687 else
1688 wxFileName::SplitPath( filename, NULL, NULL, &( l->m_LayerName ), NULL, NULL );
1689
1690 bool bLayerViz = g_bShowLayers;
1691
1692 if( g_VisibleLayers.Contains( l->m_LayerName ) )
1693 bLayerViz = true;
1694 if( g_InvisibleLayers.Contains( l->m_LayerName ) )
1695 bLayerViz = false;
1696
1697 l->m_bHasVisibleNames = wxCHK_UNDETERMINED;
1698 if (g_VisiNameinLayers.Contains(l->m_LayerName))
1699 l->m_bHasVisibleNames = wxCHK_CHECKED;
1700 if (g_InVisiNameinLayers.Contains(l->m_LayerName))
1701 l->m_bHasVisibleNames = wxCHK_UNCHECKED;
1702
1703 l->m_bIsVisibleOnChart = bLayerViz;
1704
1705 wxString laymsg;
1706 laymsg.Printf( wxT("New layer %d: %s"), l->m_LayerID, l->m_LayerName.c_str() );
1707 wxLogMessage( laymsg );
1708
1709 pLayerList->Insert( l );
1710
1711 // Load the entire file array as a single layer
1712
1713 for( unsigned int i = 0; i < file_array.GetCount(); i++ ) {
1714 wxString file_path = file_array[i];
1715
1716 if( ::wxFileExists( file_path ) ) {
1717 NavObjectCollection1 *pSet = new NavObjectCollection1;
1718 pSet->load_file(file_path.fn_str());
1719 long nItems = pSet->LoadAllGPXObjectsAsLayer(l->m_LayerID, bLayerViz, l->m_bHasVisibleNames);
1720 l->m_NoOfItems += nItems;
1721 l->m_LayerType = _("Persistent");
1722
1723 wxString objmsg;
1724 objmsg.Printf( wxT("Loaded GPX file %s with %ld items."), file_path.c_str(), nItems );
1725 wxLogMessage( objmsg );
1726
1727 delete pSet;
1728 }
1729 }
1730 }
1731
1732 cont = dir.GetNext( &filename );
1733 }
1734 }
1735 g_bLayersLoaded = true;
1736
1737 return true;
1738 }
1739
LoadChartDirArray(ArrayOfCDI & ChartDirArray)1740 bool MyConfig::LoadChartDirArray( ArrayOfCDI &ChartDirArray )
1741 {
1742 // Chart Directories
1743 SetPath( _T ( "/ChartDirectories" ) );
1744 int iDirMax = GetNumberOfEntries();
1745 if( iDirMax ) {
1746 ChartDirArray.Empty();
1747 wxString str, val;
1748 long dummy;
1749 int nAdjustChartDirs = 0;
1750 int iDir = 0;
1751 bool bCont = pConfig->GetFirstEntry( str, dummy );
1752 while( bCont ) {
1753 pConfig->Read( str, &val ); // Get a Directory name
1754
1755 wxString dirname( val );
1756 if( !dirname.IsEmpty() ) {
1757
1758 /* Special case for first time run after Windows install with sample chart data...
1759 We desire that the sample configuration file opencpn.ini should not contain any
1760 installation dependencies, so...
1761 Detect and update the sample [ChartDirectories] entries to point to the Shared Data directory
1762 For instance, if the (sample) opencpn.ini file should contain shortcut coded entries like:
1763
1764 [ChartDirectories]
1765 ChartDir1=SampleCharts\\MaptechRegion7
1766
1767 then this entry will be updated to be something like:
1768 ChartDir1=c:\Program Files\opencpn\SampleCharts\\MaptechRegion7
1769
1770 */
1771 if( dirname.Find( _T ( "SampleCharts" ) ) == 0 ) // only update entries starting with "SampleCharts"
1772 {
1773 nAdjustChartDirs++;
1774
1775 pConfig->DeleteEntry( str );
1776 wxString new_dir = dirname.Mid( dirname.Find( _T ( "SampleCharts" ) ) );
1777 new_dir.Prepend( g_Platform->GetSharedDataDir() );
1778 dirname = new_dir;
1779 }
1780
1781 ChartDirInfo cdi;
1782 cdi.fullpath = dirname.BeforeFirst( '^' );
1783 cdi.magic_number = dirname.AfterFirst( '^' );
1784
1785 ChartDirArray.Add( cdi );
1786 iDir++;
1787 }
1788
1789 bCont = pConfig->GetNextEntry( str, dummy );
1790 }
1791
1792 if( nAdjustChartDirs ) pConfig->UpdateChartDirs( ChartDirArray );
1793 }
1794
1795 return true;
1796 }
1797
AddNewRoute(Route * pr)1798 void MyConfig::AddNewRoute( Route *pr )
1799 {
1800 // if( pr->m_bIsInLayer )
1801 // return true;
1802 if( !m_bSkipChangeSetUpdate )
1803 m_pNavObjectChangesSet->AddRoute( pr, "add" );
1804 }
1805
UpdateRoute(Route * pr)1806 void MyConfig::UpdateRoute( Route *pr )
1807 {
1808 // if( pr->m_bIsInLayer ) return true;
1809 if( !m_bSkipChangeSetUpdate )
1810 m_pNavObjectChangesSet->AddRoute( pr, "update" );
1811 }
1812
DeleteConfigRoute(Route * pr)1813 void MyConfig::DeleteConfigRoute( Route *pr )
1814 {
1815 // if( pr->m_bIsInLayer )
1816 // return true;
1817 if( !m_bSkipChangeSetUpdate )
1818 m_pNavObjectChangesSet->AddRoute( pr, "delete" );
1819 }
1820
AddNewTrack(Track * pt)1821 void MyConfig::AddNewTrack( Track *pt )
1822 {
1823 if( !pt->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1824 m_pNavObjectChangesSet->AddTrack( pt, "add" );
1825 }
1826
UpdateTrack(Track * pt)1827 void MyConfig::UpdateTrack( Track *pt )
1828 {
1829 if( pt->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1830 m_pNavObjectChangesSet->AddTrack( pt, "update" );
1831 }
1832
DeleteConfigTrack(Track * pt)1833 void MyConfig::DeleteConfigTrack( Track *pt )
1834 {
1835 if( !pt->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1836 m_pNavObjectChangesSet->AddTrack( pt, "delete" );
1837 }
1838
AddNewWayPoint(RoutePoint * pWP,int crm)1839 void MyConfig::AddNewWayPoint( RoutePoint *pWP, int crm )
1840 {
1841 if( !pWP->m_bIsInLayer && pWP->m_bIsolatedMark && !m_bSkipChangeSetUpdate )
1842 m_pNavObjectChangesSet->AddWP( pWP, "add" );
1843 }
1844
UpdateWayPoint(RoutePoint * pWP)1845 void MyConfig::UpdateWayPoint( RoutePoint *pWP )
1846 {
1847 if( !pWP->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1848 m_pNavObjectChangesSet->AddWP( pWP, "update" );
1849 }
1850
DeleteWayPoint(RoutePoint * pWP)1851 void MyConfig::DeleteWayPoint( RoutePoint *pWP )
1852 {
1853 if( !pWP->m_bIsInLayer && !m_bSkipChangeSetUpdate )
1854 m_pNavObjectChangesSet->AddWP( pWP, "delete" );
1855 }
1856
AddNewTrackPoint(TrackPoint * pWP,const wxString & parent_GUID)1857 void MyConfig::AddNewTrackPoint( TrackPoint *pWP, const wxString& parent_GUID )
1858 {
1859 if( !m_bSkipChangeSetUpdate )
1860 m_pNavObjectChangesSet->AddTrackPoint( pWP, "add", parent_GUID );
1861 }
1862
UpdateChartDirs(ArrayOfCDI & dir_array)1863 bool MyConfig::UpdateChartDirs( ArrayOfCDI& dir_array )
1864 {
1865 wxString key, dir;
1866 wxString str_buf;
1867
1868 SetPath( _T ( "/ChartDirectories" ) );
1869 int iDirMax = GetNumberOfEntries();
1870 if( iDirMax ) {
1871
1872 long dummy;
1873
1874 for( int i = 0; i < iDirMax; i++ ) {
1875 GetFirstEntry( key, dummy );
1876 DeleteEntry( key, false );
1877 }
1878 }
1879
1880 iDirMax = dir_array.GetCount();
1881
1882 for( int iDir = 0; iDir < iDirMax; iDir++ ) {
1883 ChartDirInfo cdi = dir_array[iDir];
1884
1885 wxString dirn = cdi.fullpath;
1886 dirn.Append( _T("^") );
1887 dirn.Append( cdi.magic_number );
1888
1889 str_buf.Printf( _T ( "ChartDir%d" ), iDir + 1 );
1890
1891 Write( str_buf, dirn );
1892
1893 }
1894
1895 // Avoid nonsense log errors...
1896 #ifdef __OCPN__ANDROID__
1897 wxLogNull logNo;
1898 #endif
1899
1900 Flush();
1901 return true;
1902 }
1903
CreateConfigGroups(ChartGroupArray * pGroupArray)1904 void MyConfig::CreateConfigGroups( ChartGroupArray *pGroupArray )
1905 {
1906 if( !pGroupArray ) return;
1907
1908 SetPath( _T ( "/Groups" ) );
1909 Write( _T ( "GroupCount" ), (int) pGroupArray->GetCount() );
1910
1911 for( unsigned int i = 0; i < pGroupArray->GetCount(); i++ ) {
1912 ChartGroup *pGroup = pGroupArray->Item( i );
1913 wxString s;
1914 s.Printf( _T("Group%d"), i + 1 );
1915 s.Prepend( _T ( "/Groups/" ) );
1916 SetPath( s );
1917
1918 Write( _T ( "GroupName" ), pGroup->m_group_name );
1919 Write( _T ( "GroupItemCount" ), (int) pGroup->m_element_array.size() );
1920
1921 for( unsigned int j = 0; j < pGroup->m_element_array.size(); j++ ) {
1922 wxString sg;
1923 sg.Printf( _T("Group%d/Item%d"), i + 1, j );
1924 sg.Prepend( _T ( "/Groups/" ) );
1925 SetPath( sg );
1926 Write( _T ( "IncludeItem" ), pGroup->m_element_array[j]->m_element_name );
1927
1928 wxString t;
1929 wxArrayString u = pGroup->m_element_array[j]->m_missing_name_array;
1930 if( u.GetCount() ) {
1931 for( unsigned int k = 0; k < u.GetCount(); k++ ) {
1932 t += u[k];
1933 t += _T(";");
1934 }
1935 Write( _T ( "ExcludeItems" ), t );
1936 }
1937 }
1938 }
1939 }
1940
DestroyConfigGroups(void)1941 void MyConfig::DestroyConfigGroups( void )
1942 {
1943 DeleteGroup( _T ( "/Groups" ) ); //zap
1944 }
1945
LoadConfigGroups(ChartGroupArray * pGroupArray)1946 void MyConfig::LoadConfigGroups( ChartGroupArray *pGroupArray )
1947 {
1948 SetPath( _T ( "/Groups" ) );
1949 unsigned int group_count;
1950 Read( _T ( "GroupCount" ), (int *) &group_count, 0 );
1951
1952 for( unsigned int i = 0; i < group_count; i++ ) {
1953 ChartGroup *pGroup = new ChartGroup;
1954 wxString s;
1955 s.Printf( _T("Group%d"), i + 1 );
1956 s.Prepend( _T ( "/Groups/" ) );
1957 SetPath( s );
1958
1959 wxString t;
1960 Read( _T ( "GroupName" ), &t );
1961 pGroup->m_group_name = t;
1962
1963 unsigned int item_count;
1964 Read( _T ( "GroupItemCount" ), (int *) &item_count );
1965 for( unsigned int j = 0; j < item_count; j++ ) {
1966 wxString sg;
1967 sg.Printf( _T("Group%d/Item%d"), i + 1, j );
1968 sg.Prepend( _T ( "/Groups/" ) );
1969 SetPath( sg );
1970
1971 wxString v;
1972 Read( _T ( "IncludeItem" ), &v );
1973 ChartGroupElement *pelement = new ChartGroupElement{v};
1974 pGroup->m_element_array.emplace_back( pelement );
1975
1976 wxString u;
1977 if( Read( _T ( "ExcludeItems" ), &u ) ) {
1978 if( !u.IsEmpty() ) {
1979 wxStringTokenizer tk( u, _T(";") );
1980 while( tk.HasMoreTokens() ) {
1981 wxString token = tk.GetNextToken();
1982 pelement->m_missing_name_array.Add( token );
1983 }
1984 }
1985 }
1986 }
1987 pGroupArray->Add( pGroup );
1988 }
1989
1990 }
1991
LoadCanvasConfigs(bool bApplyAsTemplate)1992 void MyConfig::LoadCanvasConfigs( bool bApplyAsTemplate )
1993 {
1994 wxString s;
1995 canvasConfig *pcc;
1996
1997 SetPath( _T ( "/Canvas" ) );
1998
1999 // If the canvas config has never been set/persisted, use the global settings
2000 if(!HasEntry( _T ( "CanvasConfig" ))){
2001
2002 pcc = new canvasConfig(0);
2003 pcc->LoadFromLegacyConfig( this );
2004 g_canvasConfigArray.Add(pcc);
2005
2006 return;
2007 }
2008
2009 Read( _T ( "CanvasConfig" ), (int *)&g_canvasConfig, 0 );
2010
2011 // Do not recreate canvasConfigs when applying config dynamically
2012 if(g_canvasConfigArray.GetCount() == 0){ // This is initial load from startup
2013 s.Printf( _T("/Canvas/CanvasConfig%d"), 1 );
2014 SetPath( s );
2015 canvasConfig *pcca = new canvasConfig(0);
2016 LoadConfigCanvas(pcca, bApplyAsTemplate);
2017 g_canvasConfigArray.Add(pcca);
2018
2019 s.Printf( _T("/Canvas/CanvasConfig%d"), 2 );
2020 SetPath( s );
2021 pcca = new canvasConfig(1);
2022 LoadConfigCanvas(pcca, bApplyAsTemplate);
2023 g_canvasConfigArray.Add(pcca);
2024 } else { // This is a dynamic (i.e. Template) load
2025 canvasConfig *pcca = g_canvasConfigArray[0];
2026 s.Printf( _T("/Canvas/CanvasConfig%d"), 1 );
2027 SetPath( s );
2028 LoadConfigCanvas(pcca, bApplyAsTemplate);
2029
2030 if(g_canvasConfigArray.GetCount() > 1){
2031 canvasConfig *pcca = g_canvasConfigArray[1];
2032 s.Printf( _T("/Canvas/CanvasConfig%d"), 2 );
2033 SetPath( s );
2034 LoadConfigCanvas(pcca, bApplyAsTemplate);
2035 } else {
2036 s.Printf( _T("/Canvas/CanvasConfig%d"), 2 );
2037 SetPath( s );
2038 pcca = new canvasConfig(1);
2039 LoadConfigCanvas(pcca, bApplyAsTemplate);
2040 g_canvasConfigArray.Add(pcca);
2041 }
2042 }
2043 }
2044
LoadConfigCanvas(canvasConfig * cConfig,bool bApplyAsTemplate)2045 void MyConfig::LoadConfigCanvas( canvasConfig *cConfig, bool bApplyAsTemplate )
2046 {
2047 wxString st;
2048 double st_lat, st_lon;
2049
2050 if(!bApplyAsTemplate){
2051 // Reasonable starting point
2052 cConfig->iLat = START_LAT; // display viewpoint
2053 cConfig->iLon = START_LON;
2054
2055 if( Read( _T ( "canvasVPLatLon" ), &st ) ) {
2056 sscanf( st.mb_str( wxConvUTF8 ), "%lf,%lf", &st_lat, &st_lon );
2057
2058 // Sanity check the lat/lon...both have to be reasonable.
2059 if( fabs( st_lon ) < 360. ) {
2060 while( st_lon < -180. )
2061 st_lon += 360.;
2062
2063 while( st_lon > 180. )
2064 st_lon -= 360.;
2065
2066 cConfig->iLon = st_lon;
2067 }
2068
2069 if( fabs( st_lat ) < 90.0 )
2070 cConfig->iLat = st_lat;
2071 }
2072
2073 cConfig->iScale = .0003; // decent initial value
2074 cConfig->iRotation = 0;
2075
2076 double st_view_scale;
2077 if( Read( wxString( _T ( "canvasVPScale" ) ), &st ) ) {
2078 sscanf( st.mb_str( wxConvUTF8 ), "%lf", &st_view_scale );
2079 // Sanity check the scale
2080 st_view_scale = fmax ( st_view_scale, .001/32 );
2081 st_view_scale = fmin ( st_view_scale, 4 );
2082 cConfig->iScale = st_view_scale;
2083 }
2084
2085 double st_rotation;
2086 if( Read( wxString( _T ( "canvasVPRotation" ) ), &st ) ) {
2087 sscanf( st.mb_str( wxConvUTF8 ), "%lf", &st_rotation );
2088 // Sanity check the rotation
2089 st_rotation = fmin ( st_rotation, 360 );
2090 st_rotation = fmax ( st_rotation, 0 );
2091 cConfig->iRotation = st_rotation * PI / 180.;
2092 }
2093
2094 Read( _T ( "canvasInitialdBIndex" ), &cConfig->DBindex, 0 );
2095 Read( _T ( "canvasbFollow" ), &cConfig->bFollow, 0 );
2096
2097 Read( _T ( "canvasCourseUp" ), &cConfig->bCourseUp, 0 );
2098 Read( _T ( "canvasHeadUp" ), &cConfig->bHeadUp, 0 );
2099 Read( _T ( "canvasLookahead" ), &cConfig->bLookahead, 0 );
2100 }
2101
2102 Read( _T ( "ActiveChartGroup" ), &cConfig->GroupID, 0 );
2103
2104 // Special check for group selection when applied as template
2105 if(cConfig->GroupID && bApplyAsTemplate){
2106 if( cConfig->GroupID > (int) g_pGroupArray->GetCount() )
2107 cConfig->GroupID = 0;
2108 }
2109
2110 Read( _T ( "canvasShowTides" ), &cConfig->bShowTides, 0 );
2111 Read( _T ( "canvasShowCurrents" ), &cConfig->bShowCurrents, 0 );
2112
2113
2114 Read( _T ( "canvasQuilt" ), &cConfig->bQuilt, 1 );
2115 Read( _T ( "canvasShowGrid" ), &cConfig->bShowGrid, 0 );
2116 Read( _T ( "canvasShowOutlines" ), &cConfig->bShowOutlines, 0 );
2117 Read( _T ( "canvasShowDepthUnits" ), &cConfig->bShowDepthUnits, 0 );
2118
2119 Read( _T ( "canvasShowAIS" ), &cConfig->bShowAIS, 1 );
2120 Read( _T ( "canvasAttenAIS" ), &cConfig->bAttenAIS, 0 );
2121
2122 // ENC options
2123 Read( _T ( "canvasShowENCText" ), &cConfig->bShowENCText, 1 );
2124 Read( _T ( "canvasENCDisplayCategory" ), &cConfig->nENCDisplayCategory, STANDARD );
2125 Read( _T ( "canvasENCShowDepths" ), &cConfig->bShowENCDepths, 1 );
2126 Read( _T ( "canvasENCShowBuoyLabels" ), &cConfig->bShowENCBuoyLabels, 1 );
2127 Read( _T ( "canvasENCShowLightDescriptions" ), &cConfig->bShowENCLightDescriptions, 1 );
2128 Read( _T ( "canvasENCShowLights" ), &cConfig->bShowENCLights, 1 );
2129
2130
2131 int sx, sy;
2132 Read( _T ( "canvasSizeX" ), &sx, 0 );
2133 Read( _T ( "canvasSizeY" ), &sy, 0 );
2134 cConfig->canvasSize = wxSize(sx, sy);
2135
2136
2137
2138
2139 }
2140
2141
SaveCanvasConfigs()2142 void MyConfig::SaveCanvasConfigs( )
2143 {
2144 SetPath( _T ( "/Canvas" ) );
2145 Write( _T ( "CanvasConfig" ), (int )g_canvasConfig );
2146
2147 wxString s;
2148 canvasConfig *pcc;
2149
2150 switch( g_canvasConfig ){
2151
2152 case 0:
2153 default:
2154
2155 s.Printf( _T("/Canvas/CanvasConfig%d"), 1 );
2156 SetPath( s );
2157
2158 if(g_canvasConfigArray.GetCount() > 0 ){
2159 pcc = g_canvasConfigArray.Item(0);
2160 if(pcc){
2161 SaveConfigCanvas(pcc);
2162 }
2163 }
2164 break;
2165
2166 case 1:
2167
2168 if(g_canvasConfigArray.GetCount() > 1 ){
2169
2170 s.Printf( _T("/Canvas/CanvasConfig%d"), 1 );
2171 SetPath( s );
2172 pcc = g_canvasConfigArray.Item(0);
2173 if(pcc){
2174 SaveConfigCanvas(pcc);
2175 }
2176
2177 s.Printf( _T("/Canvas/CanvasConfig%d"), 2 );
2178 SetPath( s );
2179 pcc = g_canvasConfigArray.Item(1);
2180 if(pcc){
2181 SaveConfigCanvas(pcc);
2182 }
2183 }
2184 break;
2185
2186 }
2187 }
2188
2189
SaveConfigCanvas(canvasConfig * cConfig)2190 void MyConfig::SaveConfigCanvas( canvasConfig *cConfig )
2191 {
2192 wxString st1;
2193
2194 if(cConfig->canvas){
2195 ViewPort vp = cConfig->canvas->GetVP();
2196
2197 if( vp.IsValid() ) {
2198 st1.Printf( _T ( "%10.4f,%10.4f" ), vp.clat, vp.clon );
2199 Write( _T ( "canvasVPLatLon" ), st1 );
2200 st1.Printf( _T ( "%g" ), vp.view_scale_ppm );
2201 Write( _T ( "canvasVPScale" ), st1 );
2202 st1.Printf( _T ( "%i" ), ((int)(vp.rotation * 180 / PI)) % 360 );
2203 Write( _T ( "canvasVPRotation" ), st1 );
2204 }
2205
2206 int restore_dbindex = 0;
2207 ChartStack *pcs = cConfig->canvas->GetpCurrentStack();
2208 if(pcs)
2209 restore_dbindex = pcs->GetCurrentEntrydbIndex();
2210 if( cConfig->canvas->GetQuiltMode())
2211 restore_dbindex = cConfig->canvas->GetQuiltReferenceChartIndex();
2212 Write( _T ( "canvasInitialdBIndex" ), restore_dbindex );
2213
2214 Write( _T ( "canvasbFollow" ), cConfig->canvas->m_bFollow );
2215 Write( _T ( "ActiveChartGroup" ), cConfig->canvas->m_groupIndex );
2216
2217 Write( _T ( "canvasToolbarConfig" ), cConfig->canvas->GetToolbarConfigString() );
2218 Write( _T ( "canvasShowToolbar" ), 0 ); //cConfig->canvas->GetToolbarEnable() );
2219
2220 Write( _T ( "canvasQuilt" ), cConfig->canvas->GetQuiltMode() );
2221 Write( _T ( "canvasShowGrid" ), cConfig->canvas->GetShowGrid() );
2222 Write( _T ( "canvasShowOutlines" ), cConfig->canvas->GetShowOutlines() );
2223 Write( _T ( "canvasShowDepthUnits" ), cConfig->canvas->GetShowDepthUnits() );
2224
2225 Write( _T ( "canvasShowAIS" ), cConfig->canvas->GetShowAIS() );
2226 Write( _T ( "canvasAttenAIS" ), cConfig->canvas->GetAttenAIS() );
2227
2228 Write( _T ( "canvasShowTides" ), cConfig->canvas->GetbShowTide() );
2229 Write( _T ( "canvasShowCurrents" ), cConfig->canvas->GetbShowCurrent() );
2230
2231 // ENC options
2232 Write( _T ( "canvasShowENCText" ), cConfig->canvas->GetShowENCText() );
2233 Write( _T ( "canvasENCDisplayCategory" ), cConfig->canvas->GetENCDisplayCategory() );
2234 Write( _T ( "canvasENCShowDepths" ), cConfig->canvas->GetShowENCDepth() );
2235 Write( _T ( "canvasENCShowBuoyLabels" ), cConfig->canvas->GetShowENCBuoyLabels() );
2236 Write( _T ( "canvasENCShowLightDescriptions" ), cConfig->canvas->GetShowENCLightDesc() );
2237 Write( _T ( "canvasENCShowLights" ), cConfig->canvas->GetShowENCLights() );
2238
2239 Write( _T ( "canvasCourseUp" ), cConfig->canvas->GetUpMode() == COURSE_UP_MODE );
2240 Write( _T ( "canvasHeadUp" ), cConfig->canvas->GetUpMode() == HEAD_UP_MODE );
2241 Write( _T ( "canvasLookahead" ), cConfig->canvas->GetLookahead() );
2242
2243
2244 int width = cConfig->canvas->GetSize().x;
2245 // if(cConfig->canvas->IsPrimaryCanvas()){
2246 // width = wxMax(width, gFrame->GetClientSize().x / 10);
2247 // }
2248 // else{
2249 // width = wxMin(width, gFrame->GetClientSize().x * 9 / 10);
2250 // }
2251
2252 Write( _T ( "canvasSizeX" ), width );
2253 Write( _T ( "canvasSizeY" ), cConfig->canvas->GetSize().y );
2254
2255 }
2256 }
2257
2258
2259
UpdateSettings()2260 void MyConfig::UpdateSettings()
2261 {
2262 // Temporarily suppress logging of trivial non-fatal wxLogSysError() messages provoked by Android security...
2263 #ifdef __OCPN__ANDROID__
2264 wxLogNull logNo;
2265 #endif
2266
2267
2268 // Global options and settings
2269 SetPath( _T ( "/Settings" ) );
2270
2271 Write( _T ( "LastAppliedTemplate" ), g_lastAppliedTemplateGUID );
2272 Write( _T ( "CompatOS" ), g_compatOS);
2273 Write( _T ( "CompatOsVersion" ), g_compatOsVersion);
2274 Write( _T ( "ConfigVersionString" ), g_config_version_string );
2275 #ifdef SYSTEM_SOUND_CMD
2276 if ( wxIsEmpty( g_CmdSoundString ) )
2277 g_CmdSoundString = wxString( SYSTEM_SOUND_CMD );
2278 Write( _T( "CmdSoundString" ), g_CmdSoundString );
2279 #endif /* SYSTEM_SOUND_CMD */
2280 Write( _T ( "NavMessageShown" ), n_NavMessageShown );
2281 Write( _T ( "InlandEcdis" ), g_bInlandEcdis );
2282
2283 Write( _T ( "DarkDecorations"), g_bDarkDecorations );
2284
2285 Write( _T ( "AndroidVersionCode" ), g_AndroidVersionCode );
2286
2287 Write( _T ( "UIexpert" ), g_bUIexpert );
2288 Write( _T( "SpaceDropMark" ), g_bSpaceDropMark );
2289 // Write( _T ( "UIStyle" ), g_StyleManager->GetStyleNextInvocation() ); //Not desired for O5 MUI
2290
2291 Write( _T ( "ShowStatusBar" ), g_bShowStatusBar );
2292 #ifndef __WXOSX__
2293 Write( _T ( "ShowMenuBar" ), g_bShowMenuBar );
2294 #endif
2295 Write( _T ( "DefaultFontSize" ), g_default_font_size );
2296 Write( _T ( "DefaultFontFacename" ), g_default_font_facename );
2297
2298 Write( _T ( "Fullscreen" ), g_bFullscreen );
2299 Write( _T ( "ShowCompassWindow" ), g_bShowCompassWin );
2300 Write( _T ( "SetSystemTime" ), s_bSetSystemTime );
2301 Write( _T ( "ShowGrid" ), g_bDisplayGrid );
2302 Write( _T ( "PlayShipsBells" ), g_bPlayShipsBells );
2303 Write( _T ( "SoundDeviceIndex" ), g_iSoundDeviceIndex );
2304 Write( _T ( "FullscreenToolbar" ), g_bFullscreenToolbar );
2305 Write( _T ( "TransparentToolbar" ), g_bTransparentToolbar );
2306 Write( _T ( "PermanentMOBIcon" ), g_bPermanentMOBIcon );
2307 Write( _T ( "ShowLayers" ), g_bShowLayers );
2308 Write( _T ( "AutoAnchorDrop" ), g_bAutoAnchorMark );
2309 Write( _T ( "ShowChartOutlines" ), g_bShowOutlines );
2310 Write( _T ( "ShowActiveRouteTotal" ), g_bShowRouteTotal );
2311 Write( _T ( "ShowActiveRouteHighway" ), g_bShowActiveRouteHighway );
2312 Write( _T ( "SDMMFormat" ), g_iSDMMFormat );
2313 Write( _T ( "MostRecentGPSUploadConnection" ), g_uploadConnection );
2314 Write( _T ( "ShowChartBar" ), g_bShowChartBar );
2315
2316 Write( _T ( "GUIScaleFactor" ), g_GUIScaleFactor );
2317 Write( _T ( "ChartObjectScaleFactor" ), g_ChartScaleFactor );
2318 Write( _T ( "ShipScaleFactor" ), g_ShipScaleFactor );
2319 Write( _T ( "ENCSoundingScaleFactor" ), g_ENCSoundingScaleFactor );
2320
2321 // Plugin catalog persistent values.
2322 Write( _T( "CatalogCustomURL"), g_catalog_custom_url);
2323 Write( _T( "CatalogChannel"), g_catalog_channel);
2324
2325 Write( _T ( "FilterNMEA_Avg" ), g_bfilter_cogsog );
2326 Write( _T ( "FilterNMEA_Sec" ), g_COGFilterSec );
2327
2328 Write( _T ( "TrackContinuous" ), g_btrackContinuous );
2329
2330 Write( _T ( "ShowTrue" ), g_bShowTrue );
2331 Write( _T ( "ShowMag" ), g_bShowMag );
2332 Write( _T ( "UserMagVariation" ), wxString::Format( _T("%.2f"), g_UserVar ) );
2333
2334 Write( _T ( "CM93DetailFactor" ), g_cm93_zoom_factor );
2335 Write( _T ( "CM93DetailZoomPosX" ), g_detailslider_dialog_x );
2336 Write( _T ( "CM93DetailZoomPosY" ), g_detailslider_dialog_y );
2337 Write( _T ( "ShowCM93DetailSlider" ), g_bShowDetailSlider );
2338
2339 Write( _T ( "SkewToNorthUp" ), g_bskew_comp );
2340 Write( _T ( "OpenGL" ), g_bopengl );
2341 Write( _T ( "SoftwareGL" ), g_bSoftwareGL );
2342 Write( _T ( "ShowFPS" ), g_bShowFPS );
2343
2344 Write( _T ( "ZoomDetailFactor" ), g_chart_zoom_modifier );
2345 Write( _T ( "ZoomDetailFactorVector" ), g_chart_zoom_modifier_vector );
2346
2347 Write( _T ( "FogOnOverzoom" ), g_fog_overzoom );
2348 Write( _T ( "OverzoomVectorScale" ), g_oz_vector_scale );
2349 Write( _T ( "OverzoomEmphasisBase" ), g_overzoom_emphasis_base );
2350 Write( _T ( "PlusMinusZoomFactor" ), g_plus_minus_zoom_factor );
2351 Write( _T ( "ShowMUIZoomButtons" ), g_bShowMuiZoomButtons );
2352
2353 #ifdef ocpnUSE_GL
2354 /* opengl options */
2355 Write( _T ( "UseAcceleratedPanning" ), g_GLOptions.m_bUseAcceleratedPanning );
2356
2357 Write( _T ( "GPUTextureCompression" ), g_GLOptions.m_bTextureCompression);
2358 Write( _T ( "GPUTextureCompressionCaching" ), g_GLOptions.m_bTextureCompressionCaching);
2359 Write( _T ( "GPUTextureDimension" ), g_GLOptions.m_iTextureDimension );
2360 Write( _T ( "GPUTextureMemSize" ), g_GLOptions.m_iTextureMemorySize );
2361 Write( _T ( "PolygonSmoothing" ), g_GLOptions.m_GLPolygonSmoothing);
2362 Write( _T ( "LineSmoothing" ), g_GLOptions.m_GLLineSmoothing);
2363 #endif
2364 Write( _T ( "SmoothPanZoom" ), g_bsmoothpanzoom );
2365
2366 Write( _T ( "CourseUpMode" ), g_bCourseUp );
2367 if (!g_bInlandEcdis ) Write( _T ( "LookAheadMode" ), g_bLookAhead );
2368 Write( _T ( "COGUPAvgSeconds" ), g_COGAvgSec );
2369 Write( _T ( "UseMagAPB" ), g_bMagneticAPB );
2370
2371 Write( _T ( "OwnshipCOGPredictorMinutes" ), g_ownship_predictor_minutes );
2372 Write( _T ( "OwnshipCOGPredictorWidth" ), g_cog_predictor_width );
2373 Write( _T ( "OwnshipHDTPredictorMiles" ), g_ownship_HDTpredictor_miles );
2374 Write( _T ( "OwnShipIconType" ), g_OwnShipIconType );
2375 Write( _T ( "OwnShipLength" ), g_n_ownship_length_meters );
2376 Write( _T ( "OwnShipWidth" ), g_n_ownship_beam_meters );
2377 Write( _T ( "OwnShipGPSOffsetX" ), g_n_gps_antenna_offset_x );
2378 Write( _T ( "OwnShipGPSOffsetY" ), g_n_gps_antenna_offset_y );
2379 Write( _T ( "OwnShipMinSize" ), g_n_ownship_min_mm );
2380 Write( _T ( "OwnShipSogCogCalc" ), g_own_ship_sog_cog_calc );
2381 Write( _T ( "OwnShipSogCogCalcDampSec"), g_own_ship_sog_cog_calc_damp_sec );
2382
2383 wxString racr;
2384 // racr.Printf( _T ( "%g" ), g_n_arrival_circle_radius );
2385 // Write( _T ( "RouteArrivalCircleRadius" ), racr );
2386 Write( _T ( "RouteArrivalCircleRadius" ), wxString::Format( _T("%.2f"), g_n_arrival_circle_radius ));
2387
2388 Write( _T ( "ChartQuilting" ), g_bQuiltEnable );
2389
2390 Write( _T ( "NMEALogWindowSizeX" ), NMEALogWindow::Get().GetSizeW());
2391 Write( _T ( "NMEALogWindowSizeY" ), NMEALogWindow::Get().GetSizeH());
2392 Write( _T ( "NMEALogWindowPosX" ), NMEALogWindow::Get().GetPosX());
2393 Write( _T ( "NMEALogWindowPosY" ), NMEALogWindow::Get().GetPosY());
2394
2395 Write( _T ( "PreserveScaleOnX" ), g_bPreserveScaleOnX );
2396
2397 Write( _T ( "StartWithTrackActive" ), g_bTrackCarryOver );
2398 Write( _T ( "AutomaticDailyTracks" ), g_bTrackDaily );
2399 Write( _T ( "TrackRotateAt" ), g_track_rotate_time );
2400 Write( _T ( "TrackRotateTimeType" ), g_track_rotate_time_type );
2401 Write( _T ( "HighlightTracks" ), g_bHighliteTracks );
2402
2403 Write( _T ( "InitialStackIndex" ), g_restore_stackindex );
2404 Write( _T ( "InitialdBIndex" ), g_restore_dbindex );
2405
2406 Write( _T( "NMEAAPBPrecision" ), g_NMEAAPBPrecision );
2407
2408 Write( _T("TalkerIdText"), g_TalkerIdText );
2409 Write( _T("ShowTrackPointTime"), g_bShowTrackPointTime );
2410
2411 Write( _T ( "AnchorWatch1GUID" ), g_AW1GUID );
2412 Write( _T ( "AnchorWatch2GUID" ), g_AW2GUID );
2413
2414 Write( _T ( "ToolbarX" ), g_maintoolbar_x );
2415 Write( _T ( "ToolbarY" ), g_maintoolbar_y );
2416 //Write( _T ( "ToolbarOrient" ), g_maintoolbar_orient );
2417
2418 Write( _T ( "iENCToolbarX" ), g_iENCToolbarPosX );
2419 Write( _T ( "iENCToolbarY" ), g_iENCToolbarPosY );
2420
2421 if ( !g_bInlandEcdis ){
2422 Write( _T ( "GlobalToolbarConfig" ), g_toolbarConfig );
2423 Write( _T ( "DistanceFormat" ), g_iDistanceFormat );
2424 Write( _T ( "SpeedFormat" ), g_iSpeedFormat );
2425 Write( _T ( "ShowDepthUnits" ), g_bShowDepthUnits );
2426 }
2427 Write( _T ( "GPSIdent" ), g_GPS_Ident );
2428 Write( _T ( "UseGarminHostUpload" ), g_bGarminHostUpload );
2429
2430 Write( _T ( "MobileTouch" ), g_btouch );
2431 Write( _T ( "ResponsiveGraphics" ), g_bresponsive );
2432 Write( _T ( "EnableRolloverBlock" ), g_bRollover );
2433
2434 Write( _T ( "AutoHideToolbar" ), g_bAutoHideToolbar );
2435 Write( _T ( "AutoHideToolbarSecs" ), g_nAutoHideToolbar );
2436
2437 Write( _T ( "DisplaySizeMM" ), g_config_display_size_mm );
2438 Write( _T ( "DisplaySizeManual" ), g_config_display_size_manual );
2439
2440 Write( _T ( "SelectionRadiusMM" ), g_selection_radius_mm );
2441 Write( _T ( "SelectionRadiusTouchMM" ), g_selection_radius_touch_mm );
2442
2443 wxString st0;
2444 st0.Printf( _T ( "%g" ), g_PlanSpeed );
2445 Write( _T ( "PlanSpeed" ), st0 );
2446
2447 if(g_bLayersLoaded){
2448 wxString vis, invis, visnames, invisnames;
2449 LayerList::iterator it;
2450 int index = 0;
2451 for( it = ( *pLayerList ).begin(); it != ( *pLayerList ).end(); ++it, ++index ) {
2452 Layer *lay = (Layer *) ( *it );
2453 if( lay->IsVisibleOnChart() ) vis += ( lay->m_LayerName ) + _T(";");
2454 else
2455 invis += ( lay->m_LayerName ) + _T(";");
2456
2457 if( lay->HasVisibleNames() == wxCHK_CHECKED ) {
2458 visnames += ( lay->m_LayerName) + _T(";");
2459 } else if( lay->HasVisibleNames() == wxCHK_UNCHECKED ) {
2460 invisnames += ( lay->m_LayerName) + _T(";");
2461 }
2462 }
2463 Write( _T ( "VisibleLayers" ), vis );
2464 Write( _T ( "InvisibleLayers" ), invis );
2465 Write( _T ( "VisNameInLayers" ), visnames);
2466 Write( _T ( "InvisNameInLayers" ), invisnames);
2467 }
2468 Write( _T ( "Locale" ), g_locale );
2469 Write( _T ( "LocaleOverride" ), g_localeOverride );
2470
2471 Write( _T ( "KeepNavobjBackups" ), g_navobjbackups );
2472 Write( _T ( "LegacyInputCOMPortFilterBehaviour" ), g_b_legacy_input_filter_behaviour );
2473 Write( _T( "AdvanceRouteWaypointOnArrivalOnly" ), g_bAdvanceRouteWaypointOnArrivalOnly);
2474
2475 // LIVE ETA OPTION
2476 Write( _T( "LiveETA" ), g_bShowLiveETA);
2477 Write( _T( "DefaultBoatSpeed" ), g_defaultBoatSpeed);
2478
2479 // S57 Object Filter Settings
2480
2481 SetPath( _T ( "/Settings/ObjectFilter" ) );
2482
2483 if( ps52plib ) {
2484 for( unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount(); iPtr++ ) {
2485 OBJLElement *pOLE = (OBJLElement *) ( ps52plib->pOBJLArray->Item( iPtr ) );
2486
2487 wxString st1( _T ( "viz" ) );
2488 char name[7];
2489 strncpy( name, pOLE->OBJLName, 6 );
2490 name[6] = 0;
2491 st1.Append( wxString( name, wxConvUTF8 ) );
2492 Write( st1, pOLE->nViz );
2493 }
2494 }
2495
2496 // Global State
2497
2498 SetPath( _T ( "/Settings/GlobalState" ) );
2499
2500 wxString st1;
2501
2502 // if( cc1 ) {
2503 // ViewPort vp = cc1->GetVP();
2504 //
2505 // if( vp.IsValid() ) {
2506 // st1.Printf( _T ( "%10.4f,%10.4f" ), vp.clat, vp.clon );
2507 // Write( _T ( "VPLatLon" ), st1 );
2508 // st1.Printf( _T ( "%g" ), vp.view_scale_ppm );
2509 // Write( _T ( "VPScale" ), st1 );
2510 // st1.Printf( _T ( "%i" ), ((int)(vp.rotation * 180 / PI)) % 360 );
2511 // Write( _T ( "VPRotation" ), st1 );
2512 // }
2513 // }
2514
2515 st1.Printf( _T ( "%10.4f, %10.4f" ), gLat, gLon );
2516 Write( _T ( "OwnShipLatLon" ), st1 );
2517
2518 // Various Options
2519 SetPath( _T ( "/Settings/GlobalState" ) );
2520 if ( !g_bInlandEcdis ) Write( _T ( "nColorScheme" ), (int) gFrame->GetColorScheme() );
2521
2522 Write( _T ( "FrameWinX" ), g_nframewin_x );
2523 Write( _T ( "FrameWinY" ), g_nframewin_y );
2524 Write( _T ( "FrameWinPosX" ), g_nframewin_posx );
2525 Write( _T ( "FrameWinPosY" ), g_nframewin_posy );
2526 Write( _T ( "FrameMax" ), g_bframemax );
2527
2528 Write( _T ( "ClientPosX" ), g_lastClientRectx );
2529 Write( _T ( "ClientPosY" ), g_lastClientRecty );
2530 Write( _T ( "ClientSzX" ), g_lastClientRectw );
2531 Write( _T ( "ClientSzY" ), g_lastClientRecth );
2532
2533 Write( _T ( "S52_DEPTH_UNIT_SHOW" ), g_nDepthUnitDisplay );
2534
2535 Write( _T( "RoutePropSizeX" ), g_route_prop_sx );
2536 Write( _T( "RoutePropSizeY" ), g_route_prop_sy );
2537 Write( _T( "RoutePropPosX" ), g_route_prop_x );
2538 Write( _T( "RoutePropPosY" ), g_route_prop_y );
2539
2540 // AIS
2541 SetPath( _T ( "/Settings/AIS" ) );
2542
2543 Write( _T ( "bNoCPAMax" ), g_bCPAMax );
2544 Write( _T ( "NoCPAMaxNMi" ), g_CPAMax_NM );
2545 Write( _T ( "bCPAWarn" ), g_bCPAWarn );
2546 Write( _T ( "CPAWarnNMi" ), g_CPAWarn_NM );
2547 Write( _T ( "bTCPAMax" ), g_bTCPA_Max );
2548 Write( _T ( "TCPAMaxMinutes" ), g_TCPA_Max );
2549 Write( _T ( "bMarkLostTargets" ), g_bMarkLost );
2550 Write( _T ( "MarkLost_Minutes" ), g_MarkLost_Mins );
2551 Write( _T ( "bRemoveLostTargets" ), g_bRemoveLost );
2552 Write( _T ( "RemoveLost_Minutes" ), g_RemoveLost_Mins );
2553 Write( _T ( "bShowCOGArrows" ), g_bShowCOG );
2554 Write( _T ( "CogArrowMinutes" ), g_ShowCOG_Mins );
2555 Write( _T ( "bShowTargetTracks" ), g_bAISShowTracks );
2556 Write( _T ( "TargetTracksMinutes" ), g_AISShowTracks_Mins );
2557
2558 Write( _T ( "bHideMooredTargets" ), g_bHideMoored );
2559 Write( _T ( "MooredTargetMaxSpeedKnots" ), g_ShowMoored_Kts );
2560
2561 Write( _T ( "bAISAlertDialog" ), g_bAIS_CPA_Alert );
2562 Write( _T ( "bAISAlertAudio" ), g_bAIS_CPA_Alert_Audio );
2563 Write( _T ( "AISAlertAudioFile" ), g_sAIS_Alert_Sound_File );
2564 Write( _T ( "bAISAlertSuppressMoored" ), g_bAIS_CPA_Alert_Suppress_Moored );
2565 Write( _T ( "bShowAreaNotices" ), g_bShowAreaNotices );
2566 Write( _T ( "bDrawAISSize" ), g_bDrawAISSize );
2567 Write( _T ( "bDrawAISRealtime" ), g_bDrawAISRealtime );
2568 Write( _T ( "AISRealtimeMinSpeedKnots" ), g_AIS_RealtPred_Kts );
2569 Write( _T ( "bShowAISName" ), g_bShowAISName );
2570 Write( _T ( "ShowAISTargetNameScale" ), g_Show_Target_Name_Scale );
2571 Write( _T ( "bWplIsAprsPositionReport" ), g_bWplIsAprsPosition );
2572 Write( _T ( "AISCOGPredictorWidth" ), g_ais_cog_predictor_width );
2573 Write( _T ( "bShowScaledTargets" ), g_bAllowShowScaled );
2574 Write( _T ( "AISScaledNumber" ), g_ShowScaled_Num );
2575 Write( _T ( "AISScaledNumberWeightSOG" ), g_ScaledNumWeightSOG );
2576 Write( _T ( "AISScaledNumberWeightCPA" ), g_ScaledNumWeightCPA );
2577 Write( _T ( "AISScaledNumberWeightTCPA" ), g_ScaledNumWeightTCPA );
2578 Write( _T ( "AISScaledNumberWeightRange" ), g_ScaledNumWeightRange );
2579 Write( _T ( "AISScaledNumberWeightSizeOfTarget" ), g_ScaledNumWeightSizeOfT );
2580 Write( _T ( "AISScaledSizeMinimal" ), g_ScaledSizeMinimal );
2581 Write( _T ( "AISShowScaled"), g_bShowScaled);
2582
2583 Write( _T ( "AlertDialogSizeX" ), g_ais_alert_dialog_sx );
2584 Write( _T ( "AlertDialogSizeY" ), g_ais_alert_dialog_sy );
2585 Write( _T ( "AlertDialogPosX" ), g_ais_alert_dialog_x );
2586 Write( _T ( "AlertDialogPosY" ), g_ais_alert_dialog_y );
2587 Write( _T ( "QueryDialogPosX" ), g_ais_query_dialog_x );
2588 Write( _T ( "QueryDialogPosY" ), g_ais_query_dialog_y );
2589 Write( _T ( "AISTargetListPerspective" ), g_AisTargetList_perspective );
2590 Write( _T ( "AISTargetListRange" ), g_AisTargetList_range );
2591 Write( _T ( "AISTargetListSortColumn" ), g_AisTargetList_sortColumn );
2592 Write( _T ( "bAISTargetListSortReverse" ), g_bAisTargetList_sortReverse );
2593 Write( _T ( "AISTargetListColumnSpec" ), g_AisTargetList_column_spec );
2594 Write( _T ("AISTargetListColumnOrder"), g_AisTargetList_column_order);
2595
2596 Write( _T ( "S57QueryDialogSizeX" ), g_S57_dialog_sx );
2597 Write( _T ( "S57QueryDialogSizeY" ), g_S57_dialog_sy );
2598 Write( _T ( "S57QueryExtraDialogSizeX" ), g_S57_extradialog_sx );
2599 Write( _T ( "S57QueryExtraDialogSizeY" ), g_S57_extradialog_sy );
2600
2601 Write( _T ( "bAISRolloverShowClass" ), g_bAISRolloverShowClass );
2602 Write( _T ( "bAISRolloverShowCOG" ), g_bAISRolloverShowCOG );
2603 Write( _T ( "bAISRolloverShowCPA" ), g_bAISRolloverShowCPA );
2604
2605 Write( _T ( "bAISAlertAckTimeout" ), g_bAIS_ACK_Timeout );
2606 Write( _T ( "AlertAckTimeoutMinutes" ), g_AckTimeout_Mins );
2607
2608 SetPath( _T ( "/Settings/GlobalState" ) );
2609 if( ps52plib ) {
2610 Write( _T ( "bShowS57Text" ), ps52plib->GetShowS57Text() );
2611 Write( _T ( "bShowS57ImportantTextOnly" ), ps52plib->GetShowS57ImportantTextOnly() );
2612 if ( !g_bInlandEcdis ) Write( _T ( "nDisplayCategory" ), (long) ps52plib->GetDisplayCategory() );
2613 Write( _T ( "nSymbolStyle" ), (int) ps52plib->m_nSymbolStyle );
2614 Write( _T ( "nBoundaryStyle" ), (int) ps52plib->m_nBoundaryStyle );
2615
2616 Write( _T ( "bShowSoundg" ), ps52plib->m_bShowSoundg );
2617 Write( _T ( "bShowMeta" ), ps52plib->m_bShowMeta );
2618 Write( _T ( "bUseSCAMIN" ), ps52plib->m_bUseSCAMIN );
2619 Write( _T ( "bShowAtonText" ), ps52plib->m_bShowAtonText );
2620 Write( _T ( "bShowLightDescription" ), ps52plib->m_bShowLdisText );
2621 Write( _T ( "bExtendLightSectors" ), ps52plib->m_bExtendLightSectors );
2622 Write( _T ( "bDeClutterText" ), ps52plib->m_bDeClutterText );
2623 Write( _T ( "bShowNationalText" ), ps52plib->m_bShowNationalTexts );
2624
2625 Write( _T ( "S52_MAR_SAFETY_CONTOUR" ), S52_getMarinerParam( S52_MAR_SAFETY_CONTOUR ) );
2626 Write( _T ( "S52_MAR_SHALLOW_CONTOUR" ), S52_getMarinerParam( S52_MAR_SHALLOW_CONTOUR ) );
2627 Write( _T ( "S52_MAR_DEEP_CONTOUR" ), S52_getMarinerParam( S52_MAR_DEEP_CONTOUR ) );
2628 Write( _T ( "S52_MAR_TWO_SHADES" ), S52_getMarinerParam( S52_MAR_TWO_SHADES ) );
2629 Write( _T ( "S52_DEPTH_UNIT_SHOW" ), ps52plib->m_nDepthUnitDisplay );
2630 Write( _T ( "ENCSoundingScaleFactor" ), g_ENCSoundingScaleFactor );
2631 }
2632 SetPath( _T ( "/Directories" ) );
2633 Write( _T ( "S57DataLocation" ), _T("") );
2634 // Write( _T ( "SENCFileLocation" ), _T("") );
2635
2636 SetPath( _T ( "/Directories" ) );
2637 Write( _T ( "InitChartDir" ), *pInit_Chart_Dir );
2638 Write( _T ( "GPXIODir" ), g_gpx_path );
2639 Write( _T ( "TCDataDir" ), g_TCData_Dir );
2640 Write( _T ( "BasemapDir" ), g_Platform->NormalizePath(gWorldMapLocation) );
2641 Write( _T ( "pluginInstallDir" ), g_Platform->NormalizePath(g_winPluginDir) );
2642
2643 SetPath( _T ( "/Settings/NMEADataSource" ) );
2644 wxString connectionconfigs;
2645 for (size_t i = 0; i < g_pConnectionParams->Count(); i++)
2646 {
2647 if (i > 0)
2648 connectionconfigs.Append(_T("|"));
2649 connectionconfigs.Append(g_pConnectionParams->Item(i)->Serialize());
2650 }
2651 Write ( _T ( "DataConnections" ), connectionconfigs );
2652
2653 // Fonts
2654
2655 // Store the persistent Auxiliary Font descriptor Keys
2656 SetPath( _T ( "/Settings/AuxFontKeys" ) );
2657
2658 wxArrayString keyArray = FontMgr::Get().GetAuxKeyArray();
2659 for(unsigned int i=0 ; i < keyArray.GetCount() ; i++){
2660 wxString key;
2661 key.Printf(_T("Key%i"), i);
2662 wxString keyval = keyArray[i];
2663 Write( key, keyval );
2664 }
2665
2666 wxString font_path;
2667 #ifdef __WXX11__
2668 font_path = ( _T ( "/Settings/X11Fonts" ) );
2669 #endif
2670
2671 #ifdef __WXGTK__
2672 font_path = ( _T ( "/Settings/GTKFonts" ) );
2673 #endif
2674
2675 #ifdef __WXMSW__
2676 font_path = ( _T ( "/Settings/MSWFonts" ) );
2677 #endif
2678
2679 #ifdef __WXMAC__
2680 font_path = ( _T ( "/Settings/MacFonts" ) );
2681 #endif
2682
2683 #ifdef __WXQT__
2684 font_path = ( _T ( "/Settings/QTFonts" ) );
2685 #endif
2686
2687 DeleteGroup(font_path);
2688
2689 SetPath( font_path );
2690
2691 int nFonts = FontMgr::Get().GetNumFonts();
2692
2693 for( int i = 0; i < nFonts; i++ ) {
2694 wxString cfstring(FontMgr::Get().GetConfigString(i));
2695 wxString valstring = FontMgr::Get().GetFullConfigDesc( i );
2696 Write( cfstring, valstring );
2697 }
2698
2699 // Tide/Current Data Sources
2700 DeleteGroup( _T ( "/TideCurrentDataSources" ) );
2701 SetPath( _T ( "/TideCurrentDataSources" ) );
2702 unsigned int iDirMax = TideCurrentDataSet.Count();
2703 for( unsigned int id = 0 ; id < iDirMax ; id++ ) {
2704 wxString key;
2705 key.Printf(_T("tcds%d"), id);
2706 Write( key, TideCurrentDataSet[id] );
2707 }
2708
2709 SetPath( _T ( "/Settings/Others" ) );
2710
2711 // Radar rings
2712 Write( _T ( "ShowRadarRings" ), (bool)(g_iNavAidRadarRingsNumberVisible > 0) ); //3.0.0 config support
2713 Write( _T ( "RadarRingsNumberVisible" ), g_iNavAidRadarRingsNumberVisible );
2714 Write( _T ( "RadarRingsStep" ), g_fNavAidRadarRingsStep );
2715 Write( _T ( "RadarRingsStepUnits" ), g_pNavAidRadarRingsStepUnits );
2716 Write( _T ( "RadarRingsColour" ), g_colourOwnshipRangeRingsColour.GetAsString( wxC2S_HTML_SYNTAX ) );
2717 Write( _T( "WaypointUseScaMin" ), g_bUseWptScaMin );
2718 Write( _T( "WaypointScaMinValue" ), g_iWpt_ScaMin );
2719 Write( _T( "WaypointUseScaMinOverrule" ), g_bOverruleScaMin );
2720 Write( _T("WaypointsShowName"), g_bShowWptName );
2721
2722 // Waypoint Radar rings
2723 Write( _T ( "WaypointRangeRingsNumber" ), g_iWaypointRangeRingsNumber );
2724 Write( _T ( "WaypointRangeRingsStep" ), g_fWaypointRangeRingsStep );
2725 Write( _T ( "WaypointRangeRingsStepUnits" ), g_iWaypointRangeRingsStepUnits );
2726 Write( _T ( "WaypointRangeRingsColour" ), g_colourWaypointRangeRingsColour.GetAsString( wxC2S_HTML_SYNTAX ) );
2727
2728 Write( _T ( "ConfirmObjectDeletion" ), g_bConfirmObjectDelete );
2729
2730 // Waypoint dragging with mouse; toh, 2009.02.24
2731 Write( _T ( "WaypointPreventDragging" ), g_bWayPointPreventDragging );
2732
2733 Write( _T ( "EnableZoomToCursor" ), g_bEnableZoomToCursor );
2734
2735 Write( _T ( "TrackIntervalSeconds" ), g_TrackIntervalSeconds );
2736 Write( _T ( "TrackDeltaDistance" ), g_TrackDeltaDistance );
2737 Write( _T ( "TrackPrecision" ), g_nTrackPrecision );
2738
2739 Write( _T ( "RouteLineWidth" ), g_route_line_width );
2740 Write( _T ( "TrackLineWidth" ), g_track_line_width );
2741 Write( _T ( "TrackLineColour" ), g_colourTrackLineColour.GetAsString( wxC2S_HTML_SYNTAX ) );
2742 Write( _T ( "DefaultWPIcon" ), g_default_wp_icon );
2743 Write( _T ( "DefaultRPIcon" ), g_default_routepoint_icon );
2744
2745 DeleteGroup(_T ( "/MMSIProperties" ));
2746 SetPath( _T ( "/MMSIProperties" ) );
2747 for(unsigned int i=0 ; i < g_MMSI_Props_Array.GetCount() ; i++){
2748 wxString p;
2749 p.Printf(_T("Props%d"), i);
2750 Write( p, g_MMSI_Props_Array[i]->Serialize() );
2751 }
2752
2753 SaveCanvasConfigs();
2754
2755 Flush();
2756 }
2757
UpdateNavObj(bool bRecreate)2758 void MyConfig::UpdateNavObj( bool bRecreate )
2759 {
2760
2761 // Create the NavObjectCollection, and save to specified file
2762 NavObjectCollection1 *pNavObjectSet = new NavObjectCollection1();
2763
2764 pNavObjectSet->CreateAllGPXObjects();
2765 pNavObjectSet->SaveFile( m_sNavObjSetFile );
2766
2767 delete pNavObjectSet;
2768
2769 if( ::wxFileExists( m_sNavObjSetChangesFile ) ){
2770 wxLogNull logNo; // avoid silly log error message.
2771 wxRemoveFile( m_sNavObjSetChangesFile );
2772 }
2773
2774 if(bRecreate){
2775 delete m_pNavObjectChangesSet;
2776 m_pNavObjectChangesSet = new NavObjectChanges(m_sNavObjSetChangesFile);
2777 }
2778
2779 }
2780
exportFileName(wxWindow * parent,const wxString suggestedName)2781 static wxFileName exportFileName(wxWindow* parent, const wxString suggestedName )
2782 {
2783 wxFileName ret;
2784 wxString path;
2785 wxString validName{suggestedName};
2786 // replace common date characters invalid in filename
2787 // MS-DOS file systems have many more
2788 validName.Replace(_T("/"), _T("-"));
2789 validName.Replace(_T(":"), _T("_"));
2790 int response = g_Platform->DoFileSelectorDialog( parent, &path,
2791 _( "Export GPX file" ),
2792 g_gpx_path,
2793 validName,
2794 wxT ( "*.gpx" )
2795 );
2796
2797 if( response == wxID_OK ) {
2798 wxFileName fn(path);
2799 g_gpx_path = fn.GetPath();
2800 fn.SetExt(_T("gpx"));
2801
2802 #ifndef __WXMAC__
2803 if( wxFileExists( fn.GetFullPath() ) ) {
2804 int answer = OCPNMessageBox( NULL, _("Overwrite existing file?"), _T("Confirm"),
2805 wxICON_QUESTION | wxYES_NO | wxCANCEL );
2806 if( answer != wxID_YES )
2807 return ret;
2808 }
2809 #endif
2810 ret = fn;
2811 }
2812 return ret;
2813 }
2814
IsChangesFileDirty()2815 bool MyConfig::IsChangesFileDirty()
2816 {
2817 if(m_pNavObjectChangesSet){
2818 return m_pNavObjectChangesSet->m_bdirty;
2819 }
2820 else{
2821 return true;
2822 }
2823 }
2824
2825
ExportGPXRoutes(wxWindow * parent,RouteList * pRoutes,const wxString suggestedName)2826 bool ExportGPXRoutes( wxWindow* parent, RouteList *pRoutes, const wxString suggestedName )
2827 {
2828 wxFileName fn = exportFileName(parent, suggestedName);
2829 if (fn.IsOk()) {
2830 NavObjectCollection1 *pgpx = new NavObjectCollection1;
2831 pgpx->AddGPXRoutesList( pRoutes );
2832
2833 #ifdef __OCPN__ANDROID__
2834 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() + fn.GetFullName();
2835 pgpx->SaveFile(fns);
2836 AndroidSecureCopyFile(fns, fn.GetFullPath());
2837 #else
2838 pgpx->SaveFile(fn.GetFullPath());
2839
2840 #endif
2841
2842 delete pgpx;
2843
2844 return true;
2845 }
2846 return false;
2847 }
2848
ExportGPXTracks(wxWindow * parent,TrackList * pTracks,const wxString suggestedName)2849 bool ExportGPXTracks( wxWindow* parent, TrackList *pTracks, const wxString suggestedName )
2850 {
2851 wxFileName fn = exportFileName(parent, suggestedName);
2852 if (fn.IsOk()) {
2853 NavObjectCollection1 *pgpx = new NavObjectCollection1;
2854 pgpx->AddGPXTracksList( pTracks );
2855 #ifdef __OCPN__ANDROID__
2856 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() + fn.GetFullName();
2857 pgpx->SaveFile(fns);
2858 AndroidSecureCopyFile(fns, fn.GetFullPath());
2859 #else
2860 pgpx->SaveFile(fn.GetFullPath());
2861 #endif
2862 delete pgpx;
2863
2864 return true;
2865 }
2866 return false;
2867 }
2868
ExportGPXWaypoints(wxWindow * parent,RoutePointList * pRoutePoints,const wxString suggestedName)2869 bool ExportGPXWaypoints( wxWindow* parent, RoutePointList *pRoutePoints, const wxString suggestedName )
2870 {
2871 wxFileName fn = exportFileName(parent, suggestedName);
2872 if (fn.IsOk()) {
2873 NavObjectCollection1 *pgpx = new NavObjectCollection1;
2874 pgpx->AddGPXPointsList( pRoutePoints );
2875
2876 #ifdef __OCPN__ANDROID__
2877 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() + fn.GetFullName();
2878 pgpx->SaveFile(fns);
2879 AndroidSecureCopyFile(fns, fn.GetFullPath());
2880 #else
2881 pgpx->SaveFile(fn.GetFullPath());
2882 #endif
2883
2884 delete pgpx;
2885
2886 return true;
2887 }
2888 return false;
2889 }
2890
ExportGPX(wxWindow * parent,bool bviz_only,bool blayer)2891 void ExportGPX( wxWindow* parent, bool bviz_only, bool blayer )
2892 {
2893 wxFileName fn = exportFileName(parent, _T("userobjects.gpx"));
2894 if (fn.IsOk()) {
2895 ::wxBeginBusyCursor();
2896
2897 NavObjectCollection1 *pgpx = new NavObjectCollection1;
2898
2899 wxGenericProgressDialog *pprog = nullptr;
2900 int count = pWayPointMan->GetWaypointList()->GetCount();
2901 int progStep = count / 32;
2902 if( count > 200) {
2903 pprog = new wxGenericProgressDialog( _("Export GPX file"), _T("0/0"), count, NULL,
2904 wxPD_APP_MODAL | wxPD_SMOOTH |
2905 wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME );
2906 pprog->SetSize( 400, wxDefaultCoord );
2907 pprog->Centre();
2908 }
2909
2910 //WPTs
2911 int ic = 1;
2912
2913 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
2914 RoutePoint *pr;
2915 while( node ) {
2916 if( pprog && !(ic % progStep) ) {
2917 wxString msg;
2918 msg.Printf(_T("%d/%d"), ic, count);
2919 pprog->Update( ic, msg );
2920 }
2921 ic++;
2922
2923 pr = node->GetData();
2924
2925 bool b_add = true;
2926
2927 if( bviz_only && !pr->m_bIsVisible )
2928 b_add = false;
2929
2930 if( pr->m_bIsInLayer && !blayer )
2931 b_add = false;
2932 if( b_add) {
2933 if( pr->m_bKeepXRoute || !WptIsInRouteList( pr ) )
2934 pgpx->AddGPXWaypoint( pr);
2935 }
2936
2937 node = node->GetNext();
2938 }
2939 //RTEs and TRKs
2940 wxRouteListNode *node1 = pRouteList->GetFirst();
2941 while( node1 ) {
2942 Route *pRoute = node1->GetData();
2943
2944 bool b_add = true;
2945
2946 if( bviz_only && !pRoute->IsVisible() )
2947 b_add = false;
2948
2949 if( pRoute->m_bIsInLayer && !blayer )
2950 b_add = false;
2951
2952 if( b_add )
2953 pgpx->AddGPXRoute( pRoute );
2954
2955 node1 = node1->GetNext();
2956 }
2957
2958 wxTrackListNode *node2 = pTrackList->GetFirst();
2959 while( node2 ) {
2960 Track *pTrack = node2->GetData();
2961
2962 bool b_add = true;
2963
2964 if( bviz_only && !pTrack->IsVisible() )
2965 b_add = false;
2966
2967 if( pTrack->m_bIsInLayer && !blayer )
2968 b_add = false;
2969
2970 if( b_add )
2971 pgpx->AddGPXTrack( pTrack );
2972 node2 = node2->GetNext();
2973 }
2974
2975
2976 // Android 5+ requires special handling to support native app file writes to SDCard
2977 // We need to use a two step copy process using a guaranteed accessible location for the first step.
2978 #ifdef __OCPN__ANDROID__
2979 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() + fn.GetFullName();
2980 pgpx->SaveFile(fns);
2981 AndroidSecureCopyFile(fns, fn.GetFullPath());
2982 #else
2983 pgpx->SaveFile( fn.GetFullPath() );
2984 #endif
2985
2986 delete pgpx;
2987 ::wxEndBusyCursor();
2988
2989 delete pprog;
2990
2991 }
2992 }
2993
UI_ImportGPX(wxWindow * parent,bool islayer,wxString dirpath,bool isdirectory,bool isPersistent)2994 void UI_ImportGPX( wxWindow* parent, bool islayer, wxString dirpath, bool isdirectory, bool isPersistent )
2995 {
2996 int response = wxID_CANCEL;
2997 wxArrayString file_array;
2998 Layer *l = NULL;
2999
3000 if( !islayer || dirpath.IsSameAs( _T("") ) ) {
3001
3002 // Platform DoFileSelectorDialog method does not properly handle multiple selections
3003 // So use native method if not Android, which means Android gets single selection only.
3004 #ifndef __OCPN__ANDROID__
3005 wxFileDialog *popenDialog = new wxFileDialog( NULL, _( "Import GPX file" ), g_gpx_path, wxT ( "" ),
3006 wxT ( "GPX files (*.gpx)|*.gpx|All files (*.*)|*.*" ),
3007 wxFD_OPEN | wxFD_MULTIPLE );
3008
3009 if(g_bresponsive && parent)
3010 popenDialog = g_Platform->AdjustFileDialogFont(parent, popenDialog);
3011
3012 popenDialog->Centre();
3013
3014 #ifdef __WXOSX__
3015 if(parent)
3016 parent->HideWithEffect(wxSHOW_EFFECT_BLEND );
3017 #endif
3018
3019 response = popenDialog->ShowModal();
3020
3021 #ifdef __WXOSX__
3022 if(parent)
3023 parent->ShowWithEffect(wxSHOW_EFFECT_BLEND );
3024 #endif
3025
3026 if( response == wxID_OK ) {
3027 popenDialog->GetPaths( file_array );
3028
3029 // Record the currently selected directory for later use
3030 if( file_array.GetCount() ) {
3031 wxFileName fn( file_array[0] );
3032 g_gpx_path = fn.GetPath();
3033 }
3034 }
3035 delete popenDialog;
3036 #else
3037 wxString path;
3038 response = g_Platform->DoFileSelectorDialog( NULL, &path,
3039 _( "Import GPX file" ),
3040 g_gpx_path,
3041 _T(""),
3042 wxT ( "*.gpx" )
3043 );
3044
3045 file_array.Add(path);
3046 wxFileName fn( path );
3047 g_gpx_path = fn.GetPath();
3048
3049 #endif
3050
3051 } else {
3052 if( isdirectory ) {
3053 if( wxDir::GetAllFiles( dirpath, &file_array, wxT("*.gpx") ) )
3054 response = wxID_OK;
3055 } else {
3056 file_array.Add( dirpath );
3057 response = wxID_OK;
3058 }
3059 }
3060
3061 if( response == wxID_OK ) {
3062
3063 if( islayer ) {
3064 l = new Layer();
3065 l->m_LayerID = ++g_LayerIdx;
3066 l->m_LayerFileName = file_array[0];
3067 if( file_array.GetCount() <= 1 ) wxFileName::SplitPath( file_array[0], NULL, NULL,
3068 &( l->m_LayerName ), NULL, NULL );
3069 else {
3070 if( dirpath.IsSameAs( _T("") ) ) wxFileName::SplitPath( g_gpx_path, NULL, NULL,
3071 &( l->m_LayerName ), NULL, NULL );
3072 else
3073 wxFileName::SplitPath( dirpath, NULL, NULL, &( l->m_LayerName ), NULL, NULL );
3074 }
3075
3076 bool bLayerViz = g_bShowLayers;
3077 if( g_VisibleLayers.Contains( l->m_LayerName ) )
3078 bLayerViz = true;
3079 if( g_InvisibleLayers.Contains( l->m_LayerName ) )
3080 bLayerViz = false;
3081 l->m_bIsVisibleOnChart = bLayerViz;
3082
3083 // Default for new layers is "Names visible"
3084 l->m_bHasVisibleNames = wxCHK_CHECKED;
3085
3086 wxString laymsg;
3087 laymsg.Printf( wxT("New layer %d: %s"), l->m_LayerID, l->m_LayerName.c_str() );
3088 wxLogMessage( laymsg );
3089
3090 pLayerList->Insert( l );
3091 }
3092
3093 for( unsigned int i = 0; i < file_array.GetCount(); i++ ) {
3094 wxString path = file_array[i];
3095
3096 if( ::wxFileExists( path ) ) {
3097
3098 NavObjectCollection1 *pSet = new NavObjectCollection1;
3099 pSet->load_file(path.fn_str());
3100
3101 if(islayer){
3102 l->m_NoOfItems = pSet->LoadAllGPXObjectsAsLayer(l->m_LayerID, l->m_bIsVisibleOnChart, l->m_bHasVisibleNames);
3103 l->m_LayerType = isPersistent ? _("Persistent") : _("Temporary") ;
3104
3105 if(isPersistent)
3106 {
3107 // If this is a persistent layer also copy the file to config file dir /layers
3108 wxString destf, f, name, ext;
3109 f = l->m_LayerFileName;
3110 wxFileName::SplitPath(f, NULL , NULL, &name, &ext);
3111 destf = g_Platform->GetPrivateDataDir();
3112 appendOSDirSlash(&destf);
3113 destf.Append(_T("layers"));
3114 appendOSDirSlash(&destf);
3115 if (!wxDirExists(destf))
3116 {
3117 if( !wxMkdir(destf, wxS_DIR_DEFAULT) )
3118 wxLogMessage( _T("Error creating layer directory") );
3119 }
3120
3121 destf << name << _T(".") << ext;
3122 wxString msg;
3123 if( wxCopyFile(f, destf, true) )
3124 msg.Printf(_T("File: %s.%s also added to persistent layers"), name, ext);
3125 else
3126 msg.Printf(_T("Failed adding %s.%s to persistent layers"), name, ext);
3127 wxLogMessage(msg);
3128 }
3129 }
3130 else {
3131 int wpt_dups;
3132 pSet->LoadAllGPXObjects( !pSet->IsOpenCPN(), wpt_dups ); // Import with full visibility of names and objects
3133 if(wpt_dups > 0) {
3134 OCPNMessageBox(parent, wxString::Format(_T("%d ")+_("duplicate waypoints detected during import and ignored."), wpt_dups), _("OpenCPN Info"), wxICON_INFORMATION|wxOK, 10);
3135 }
3136 }
3137 delete pSet;
3138 }
3139 }
3140 }
3141 }
3142
3143 //-------------------------------------------------------------------------
3144 // Static Routine Switch to Inland Ecdis Mode
3145 //-------------------------------------------------------------------------
SwitchInlandEcdisMode(bool Switch)3146 void SwitchInlandEcdisMode( bool Switch )
3147 {
3148 if ( Switch ){
3149 wxLogMessage( _T("Switch InlandEcdis mode On") );
3150 LoadS57();
3151 //Overule some sewttings to comply with InlandEcdis
3152 //g_toolbarConfig = _T ( ".....XXXX.X...XX.XXXXXXXXXXXX" );
3153 g_iDistanceFormat = 2; //0 = "Nautical miles"), 1 = "Statute miles", 2 = "Kilometers", 3 = "Meters"
3154 g_iSpeedFormat =2; //0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
3155 if ( ps52plib ) ps52plib->SetDisplayCategory( STANDARD );
3156 g_bDrawAISSize = false;
3157 if (gFrame) gFrame->RequestNewToolbars(true);
3158 }
3159 else{
3160 wxLogMessage( _T("Switch InlandEcdis mode Off") );
3161 //reread the settings overruled by inlandEcdis
3162 if (pConfig){
3163 pConfig->SetPath( _T ( "/Settings" ) );
3164 pConfig->Read( _T ( "GlobalToolbarConfig" ), &g_toolbarConfig );
3165 pConfig->Read( _T ( "DistanceFormat" ), &g_iDistanceFormat );
3166 pConfig->Read( _T ( "SpeedFormat" ), &g_iSpeedFormat );
3167 pConfig->Read( _T ( "ShowDepthUnits" ), &g_bShowDepthUnits, 1 );
3168 int read_int;
3169 pConfig->Read( _T ( "nDisplayCategory" ), &read_int, (enum _DisCat) STANDARD );
3170 if ( ps52plib ) ps52plib->SetDisplayCategory((enum _DisCat) read_int );
3171 pConfig->SetPath( _T ( "/Settings/AIS" ) );
3172 pConfig->Read( _T ( "bDrawAISSize" ), &g_bDrawAISSize );
3173 pConfig->Read( _T ( "bDrawAISRealtime" ), &g_bDrawAISRealtime );
3174 }
3175 if (gFrame) gFrame->RequestNewToolbars(true);
3176 }
3177 }
3178
3179 //-------------------------------------------------------------------------
3180 //
3181 // Static GPX Support Routines
3182 //
3183 //-------------------------------------------------------------------------
WaypointExists(const wxString & name,double lat,double lon)3184 RoutePoint *WaypointExists( const wxString& name, double lat, double lon )
3185 {
3186 RoutePoint *pret = NULL;
3187 // if( g_bIsNewLayer ) return NULL;
3188 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
3189 while( node ) {
3190 RoutePoint *pr = node->GetData();
3191
3192 // if( pr->m_bIsInLayer ) return NULL;
3193
3194 if( name == pr->GetName() ) {
3195 if( fabs( lat - pr->m_lat ) < 1.e-6 && fabs( lon - pr->m_lon ) < 1.e-6 ) {
3196 pret = pr;
3197 break;
3198 }
3199 }
3200 node = node->GetNext();
3201 }
3202
3203 return pret;
3204 }
3205
WaypointExists(const wxString & guid)3206 RoutePoint *WaypointExists( const wxString& guid )
3207 {
3208 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
3209 while( node ) {
3210 RoutePoint *pr = node->GetData();
3211
3212 // if( pr->m_bIsInLayer ) return NULL;
3213
3214 if( guid == pr->m_GUID ) {
3215 return pr;
3216 }
3217 node = node->GetNext();
3218 }
3219
3220 return NULL;
3221 }
3222
WptIsInRouteList(RoutePoint * pr)3223 bool WptIsInRouteList( RoutePoint *pr )
3224 {
3225 bool IsInList = false;
3226
3227 wxRouteListNode *node1 = pRouteList->GetFirst();
3228 while( node1 ) {
3229 Route *pRoute = node1->GetData();
3230 RoutePointList *pRoutePointList = pRoute->pRoutePointList;
3231
3232 wxRoutePointListNode *node2 = pRoutePointList->GetFirst();
3233 RoutePoint *prp;
3234
3235 while( node2 ) {
3236 prp = node2->GetData();
3237
3238 if( pr->IsSame( prp ) ) {
3239 IsInList = true;
3240 break;
3241 }
3242
3243 node2 = node2->GetNext();
3244 }
3245 node1 = node1->GetNext();
3246 }
3247 return IsInList;
3248 }
3249
RouteExists(const wxString & guid)3250 Route *RouteExists( const wxString& guid )
3251 {
3252 wxRouteListNode *route_node = pRouteList->GetFirst();
3253
3254 while( route_node ) {
3255 Route *proute = route_node->GetData();
3256
3257 if( guid == proute->m_GUID ) return proute;
3258
3259 route_node = route_node->GetNext();
3260 }
3261 return NULL;
3262 }
3263
RouteExists(Route * pTentRoute)3264 Route *RouteExists( Route * pTentRoute )
3265 {
3266 wxRouteListNode *route_node = pRouteList->GetFirst();
3267 while( route_node ) {
3268 Route *proute = route_node->GetData();
3269
3270 if( proute->IsEqualTo( pTentRoute ) )
3271 return proute;
3272
3273 route_node = route_node->GetNext(); // next route
3274 }
3275 return NULL;
3276 }
3277
TrackExists(const wxString & guid)3278 Track *TrackExists( const wxString& guid )
3279 {
3280 wxTrackListNode *track_node = pTrackList->GetFirst();
3281
3282 while( track_node ) {
3283 Track *ptrack = track_node->GetData();
3284
3285 if( guid == ptrack->m_GUID ) return ptrack;
3286
3287 track_node = track_node->GetNext();
3288 }
3289 return NULL;
3290 }
3291
3292
3293
3294 // This function formats the input date/time into a valid GPX ISO 8601
3295 // time string specified in the UTC time zone.
3296
FormatGPXDateTime(wxDateTime dt)3297 wxString FormatGPXDateTime( wxDateTime dt )
3298 {
3299 // return dt.Format(wxT("%Y-%m-%dT%TZ"), wxDateTime::GMT0);
3300 return dt.Format( wxT("%Y-%m-%dT%H:%M:%SZ") );
3301 }
3302
3303
3304 // This function parses a string containing a GPX time representation
3305 // and returns a wxDateTime containing the UTC corresponding to the
3306 // input. The function return value is a pointer past the last valid
3307 // character parsed (if successful) or NULL (if the string is invalid).
3308 //
3309 // Valid GPX time strings are in ISO 8601 format as follows:
3310 //
3311 // [-]<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>Z|(+|-<hh>:<mm>)
3312 //
3313 // For example, 2010-10-30T14:34:56Z and 2010-10-30T14:34:56-04:00
3314 // are the same time. The first is UTC and the second is EDT.
3315
ParseGPXDateTime(wxDateTime & dt,const wxChar * datetime)3316 const wxChar *ParseGPXDateTime( wxDateTime &dt, const wxChar *datetime )
3317 {
3318 long sign, hrs_west, mins_west;
3319 const wxChar *end;
3320
3321 // Skip any leading whitespace
3322 while( isspace( *datetime ) )
3323 datetime++;
3324
3325 // Skip (and ignore) leading hyphen
3326 if( *datetime == wxT('-') ) datetime++;
3327
3328 // Parse and validate ISO 8601 date/time string
3329 if( ( end = dt.ParseFormat( datetime, wxT("%Y-%m-%dT%T") ) ) != NULL ) {
3330
3331 // Invalid date/time
3332 if( *end == 0 ) return NULL;
3333
3334 // ParseFormat outputs in UTC if the controlling
3335 // wxDateTime class instance has not been initialized.
3336
3337 // Date/time followed by UTC time zone flag, so we are done
3338 else
3339 if( *end == wxT('Z') ) {
3340 end++;
3341 return end;
3342 }
3343
3344 // Date/time followed by given number of hrs/mins west of UTC
3345 else
3346 if( *end == wxT('+') || *end == wxT('-') ) {
3347
3348 // Save direction from UTC
3349 if( *end == wxT('+') ) sign = 1;
3350 else
3351 sign = -1;
3352 end++;
3353
3354 // Parse hrs west of UTC
3355 if( isdigit( *end ) && isdigit( *( end + 1 ) ) && *( end + 2 ) == wxT(':') ) {
3356
3357 // Extract and validate hrs west of UTC
3358 wxString( end ).ToLong( &hrs_west );
3359 if( hrs_west > 12 ) return NULL;
3360 end += 3;
3361
3362 // Parse mins west of UTC
3363 if( isdigit( *end ) && isdigit( *( end + 1 ) ) ) {
3364
3365 // Extract and validate mins west of UTC
3366 wxChar mins[3];
3367 mins[0] = *end;
3368 mins[1] = *( end + 1 );
3369 mins[2] = 0;
3370 wxString( mins ).ToLong( &mins_west );
3371 if( mins_west > 59 ) return NULL;
3372
3373 // Apply correction
3374 dt -= sign * wxTimeSpan( hrs_west, mins_west, 0, 0 );
3375 return end + 2;
3376 } else
3377 // Missing mins digits
3378 return NULL;
3379 } else
3380 // Missing hrs digits or colon
3381 return NULL;
3382 } else
3383 // Unknown field after date/time (not UTC, not hrs/mins
3384 // west of UTC)
3385 return NULL;
3386 } else
3387 // Invalid ISO 8601 date/time
3388 return NULL;
3389 }
3390
3391
3392 //---------------------------------------------------------------------------------
3393 // Private Font Manager and Helpers
3394 //---------------------------------------------------------------------------------
3395 #include <wx/fontdlg.h>
3396 #include <wx/fontenum.h>
3397 #include "wx/encinfo.h"
3398
3399 #ifdef __WXX11__
3400 #include "/usr/X11R6/include/X11/Xlib.h"
3401
3402 //-----------------------------------------------------------------------------
3403 // helper class - MyFontPreviewer
3404 //-----------------------------------------------------------------------------
3405
3406 class MyFontPreviewer : public wxWindow
3407 {
3408 public:
MyFontPreviewer(wxWindow * parent,const wxSize & sz=wxDefaultSize)3409 MyFontPreviewer ( wxWindow *parent, const wxSize& sz = wxDefaultSize ) : wxWindow ( parent, wxID_ANY, wxDefaultPosition, sz )
3410 {
3411 }
3412
3413 private:
3414 void OnPaint ( wxPaintEvent& event );
3415 DECLARE_EVENT_TABLE()
3416 };
3417
BEGIN_EVENT_TABLE(MyFontPreviewer,wxWindow)3418 BEGIN_EVENT_TABLE ( MyFontPreviewer, wxWindow )
3419 EVT_PAINT ( MyFontPreviewer::OnPaint )
3420 END_EVENT_TABLE()
3421
3422 void MyFontPreviewer::OnPaint ( wxPaintEvent& WXUNUSED ( event ) )
3423 {
3424 wxPaintDC dc ( this );
3425
3426 wxSize size = GetSize();
3427 wxFont font = GetFont();
3428
3429 dc.SetPen ( *wxBLACK_PEN );
3430 dc.SetBrush ( *wxWHITE_BRUSH );
3431 dc.DrawRectangle ( 0, 0, size.x, size.y );
3432
3433 if ( font.Ok() )
3434 {
3435 dc.SetFont ( font );
3436 // Calculate vertical centre
3437 long w, h;
3438 dc.GetTextExtent ( wxT ( "X" ), &w, &h );
3439 dc.SetTextForeground ( GetForegroundColour() );
3440 dc.SetClippingRegion ( 2, 2, size.x-4, size.y-4 );
3441 dc.DrawText ( GetName(),
3442 10, size.y/2 - h/2 );
3443 dc.DestroyClippingRegion();
3444 }
3445 }
3446
3447 //-----------------------------------------------------------------------------
3448 // X11FontPicker
3449 //-----------------------------------------------------------------------------
3450
3451 IMPLEMENT_DYNAMIC_CLASS ( X11FontPicker, wxDialog )
3452
3453 BEGIN_EVENT_TABLE ( X11FontPicker, wxDialog )
3454 EVT_CHECKBOX ( wxID_FONT_UNDERLINE, X11FontPicker::OnChangeFont )
3455 EVT_CHOICE ( wxID_FONT_STYLE, X11FontPicker::OnChangeFont )
3456 EVT_CHOICE ( wxID_FONT_WEIGHT, X11FontPicker::OnChangeFont )
3457 EVT_CHOICE ( wxID_FONT_FAMILY, X11FontPicker::OnChangeFace )
3458 EVT_CHOICE ( wxID_FONT_COLOUR, X11FontPicker::OnChangeFont )
3459 EVT_CHOICE ( wxID_FONT_SIZE, X11FontPicker::OnChangeFont )
3460
3461 EVT_CLOSE ( X11FontPicker::OnCloseWindow )
3462 END_EVENT_TABLE()
3463
3464 #define SCALEABLE_SIZES 11
3465 static wxString scaleable_pointsize[SCALEABLE_SIZES] =
3466 {
3467 wxT ( "6" ),
3468 wxT ( "8" ),
3469 wxT ( "10" ),
3470 wxT ( "12" ),
3471 wxT ( "14" ),
3472 wxT ( "16" ),
3473 wxT ( "18" ),
3474 wxT ( "20" ),
3475 wxT ( "24" ),
3476 wxT ( "30" ),
3477 wxT ( "36" )
3478 };
3479
3480 #define NUM_COLS 49
3481 static wxString wxColourDialogNames[NUM_COLS]= {wxT ( "ORANGE" ),
3482 wxT ( "GOLDENROD" ),
3483 wxT ( "WHEAT" ),
3484 wxT ( "SPRING GREEN" ),
3485 wxT ( "SKY BLUE" ),
3486 wxT ( "SLATE BLUE" ),
3487 wxT ( "MEDIUM VIOLET RED" ),
3488 wxT ( "PURPLE" ),
3489
3490 wxT ( "RED" ),
3491 wxT ( "YELLOW" ),
3492 wxT ( "MEDIUM SPRING GREEN" ),
3493 wxT ( "PALE GREEN" ),
3494 wxT ( "CYAN" ),
3495 wxT ( "LIGHT STEEL BLUE" ),
3496 wxT ( "ORCHID" ),
3497 wxT ( "LIGHT MAGENTA" ),
3498
3499 wxT ( "BROWN" ),
3500 wxT ( "YELLOW" ),
3501 wxT ( "GREEN" ),
3502 wxT ( "CADET BLUE" ),
3503 wxT ( "MEDIUM BLUE" ),
3504 wxT ( "MAGENTA" ),
3505 wxT ( "MAROON" ),
3506 wxT ( "ORANGE RED" ),
3507
3508 wxT ( "FIREBRICK" ),
3509 wxT ( "CORAL" ),
3510 wxT ( "FOREST GREEN" ),
3511 wxT ( "AQUARAMINE" ),
3512 wxT ( "BLUE" ),
3513 wxT ( "NAVY" ),
3514 wxT ( "THISTLE" ),
3515 wxT ( "MEDIUM VIOLET RED" ),
3516
3517 wxT ( "INDIAN RED" ),
3518 wxT ( "GOLD" ),
3519 wxT ( "MEDIUM SEA GREEN" ),
3520 wxT ( "MEDIUM BLUE" ),
3521 wxT ( "MIDNIGHT BLUE" ),
3522 wxT ( "GREY" ),
3523 wxT ( "PURPLE" ),
3524 wxT ( "KHAKI" ),
3525
3526 wxT ( "BLACK" ),
3527 wxT ( "MEDIUM FOREST GREEN" ),
3528 wxT ( "KHAKI" ),
3529 wxT ( "DARK GREY" ),
3530 wxT ( "SEA GREEN" ),
3531 wxT ( "LIGHT GREY" ),
3532 wxT ( "MEDIUM SLATE BLUE" ),
3533 wxT ( "WHITE" )
3534 wxT ( "SIENNA" )
3535 };
3536
3537 /*
3538 * Generic X11FontPicker
3539 */
3540
Init()3541 void X11FontPicker::Init()
3542 {
3543 m_useEvents = false;
3544 m_previewer = NULL;
3545 Create ( m_parent );
3546 }
3547
~X11FontPicker()3548 X11FontPicker::~X11FontPicker()
3549 {
3550 }
3551
OnCloseWindow(wxCloseEvent & WXUNUSED (event))3552 void X11FontPicker::OnCloseWindow ( wxCloseEvent& WXUNUSED ( event ) )
3553 {
3554 EndModal ( wxID_CANCEL );
3555 }
3556
DoCreate(wxWindow * parent)3557 bool X11FontPicker::DoCreate ( wxWindow *parent )
3558 {
3559 if ( !wxDialog::Create ( parent , wxID_ANY , _T ( "Choose Font" ) , wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE,
3560 _T ( "fontdialog" ) ) )
3561 {
3562 wxFAIL_MSG ( wxT ( "wxFontDialog creation failed" ) );
3563 return false;
3564 }
3565
3566 InitializeAllAvailableFonts();
3567 InitializeFont();
3568 CreateWidgets();
3569
3570 // sets initial font in preview area
3571 wxCommandEvent dummy;
3572 OnChangeFont ( dummy );
3573
3574 return true;
3575 }
3576
ShowModal()3577 int X11FontPicker::ShowModal()
3578 {
3579 int ret = wxDialog::ShowModal();
3580
3581 if ( ret != wxID_CANCEL )
3582 {
3583 dialogFont = *pPreviewFont;
3584 m_fontData.m_chosenFont = dialogFont;
3585 }
3586
3587 return ret;
3588 }
3589
InitializeAllAvailableFonts()3590 void X11FontPicker::InitializeAllAvailableFonts()
3591 {
3592
3593 // get the Array of all fonts facenames
3594 wxString pattern;
3595 pattern.Printf ( wxT ( "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1" ) );
3596
3597 int nFonts;
3598 char ** list = XListFonts ( ( Display * ) wxGetDisplay(), pattern.mb_str(), 32767, &nFonts );
3599
3600 pFaceNameArray = new wxArrayString;
3601 unsigned int jname;
3602 for ( int i=0; i < nFonts; i++ )
3603 {
3604 wxStringTokenizer st ( wxString ( list[i] ), _T ( "-" ) );
3605 st.GetNextToken();
3606 st.GetNextToken();
3607 wxString facename = st.GetNextToken();
3608 for ( jname=0; jname<pFaceNameArray->GetCount(); jname++ )
3609 {
3610 if ( facename == pFaceNameArray->Item ( jname ) )
3611 break;
3612 }
3613 if ( jname >= pFaceNameArray->GetCount() )
3614 {
3615 pFaceNameArray->Add ( facename );
3616 }
3617
3618 }
3619
3620 }
3621
3622 // This should be application-settable
ShowToolTips()3623 static bool ShowToolTips() {return false;}
3624
CreateWidgets()3625 void X11FontPicker::CreateWidgets()
3626 {
3627 // layout
3628
3629 bool is_pda = ( wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA );
3630 int noCols, noRows;
3631 if ( is_pda )
3632 {
3633 noCols = 2; noRows = 3;
3634 }
3635 else
3636 {
3637 noCols = 3; noRows = 2;
3638 }
3639
3640 wxBoxSizer* itemBoxSizer2 = new wxBoxSizer ( wxVERTICAL );
3641 this->SetSizer ( itemBoxSizer2 );
3642 this->SetAutoLayout ( TRUE );
3643
3644 wxBoxSizer* itemBoxSizer3 = new wxBoxSizer ( wxVERTICAL );
3645 itemBoxSizer2->Add ( itemBoxSizer3, 1, wxEXPAND|wxALL, 5 );
3646
3647 wxFlexGridSizer* itemGridSizer4 = new wxFlexGridSizer ( noRows, noCols, 0, 0 );
3648 itemBoxSizer3->Add ( itemGridSizer4, 0, wxEXPAND, 5 );
3649
3650 wxBoxSizer* itemBoxSizer5 = new wxBoxSizer ( wxVERTICAL );
3651 itemGridSizer4->Add ( itemBoxSizer5, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3652 wxStaticText* itemStaticText6 = new wxStaticText ( this, wxID_STATIC, _ ( "&Font family:" ),
3653 wxDefaultPosition, wxDefaultSize, 0 );
3654 itemBoxSizer5->Add ( itemStaticText6, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3655
3656 wxChoice* itemChoice7 = new wxChoice ( this, wxID_FONT_FAMILY, wxDefaultPosition,
3657 wxDefaultSize, *pFaceNameArray, 0 );
3658 itemChoice7->SetHelpText ( _ ( "The font family." ) );
3659 if ( ShowToolTips() )
3660 itemChoice7->SetToolTip ( _ ( "The font family." ) );
3661 itemBoxSizer5->Add ( itemChoice7, 0, wxALIGN_LEFT|wxALL, 5 );
3662
3663 wxBoxSizer* itemBoxSizer8 = new wxBoxSizer ( wxVERTICAL );
3664 itemGridSizer4->Add ( itemBoxSizer8, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3665 wxStaticText* itemStaticText9 = new wxStaticText ( this, wxID_STATIC, _ ( "&Style:" ), wxDefaultPosition, wxDefaultSize, 0 );
3666 itemBoxSizer8->Add ( itemStaticText9, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3667
3668 wxChoice* itemChoice10 = new wxChoice ( this, wxID_FONT_STYLE, wxDefaultPosition, wxDefaultSize );
3669 itemChoice10->SetHelpText ( _ ( "The font style." ) );
3670 if ( ShowToolTips() )
3671 itemChoice10->SetToolTip ( _ ( "The font style." ) );
3672 itemBoxSizer8->Add ( itemChoice10, 0, wxALIGN_LEFT|wxALL, 5 );
3673
3674 wxBoxSizer* itemBoxSizer11 = new wxBoxSizer ( wxVERTICAL );
3675 itemGridSizer4->Add ( itemBoxSizer11, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3676 wxStaticText* itemStaticText12 = new wxStaticText ( this, wxID_STATIC, _ ( "&Weight:" ), wxDefaultPosition, wxDefaultSize, 0 );
3677 itemBoxSizer11->Add ( itemStaticText12, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3678
3679 wxChoice* itemChoice13 = new wxChoice ( this, wxID_FONT_WEIGHT, wxDefaultPosition, wxDefaultSize );
3680 itemChoice13->SetHelpText ( _ ( "The font weight." ) );
3681 if ( ShowToolTips() )
3682 itemChoice13->SetToolTip ( _ ( "The font weight." ) );
3683 itemBoxSizer11->Add ( itemChoice13, 0, wxALIGN_LEFT|wxALL, 5 );
3684
3685 wxBoxSizer* itemBoxSizer14 = new wxBoxSizer ( wxVERTICAL );
3686 itemGridSizer4->Add ( itemBoxSizer14, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3687 if ( m_fontData.GetEnableEffects() )
3688 {
3689 wxStaticText* itemStaticText15 = new wxStaticText ( this, wxID_STATIC, _ ( "C&olour:" ),
3690 wxDefaultPosition, wxDefaultSize, 0 );
3691 itemBoxSizer14->Add ( itemStaticText15, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3692
3693 wxSize colourSize = wxDefaultSize;
3694 if ( is_pda )
3695 colourSize.x = 100;
3696
3697 wxChoice* itemChoice16 = new wxChoice ( this, wxID_FONT_COLOUR, wxDefaultPosition,
3698 colourSize, NUM_COLS, wxColourDialogNames, 0 );
3699 itemChoice16->SetHelpText ( _ ( "The font colour." ) );
3700 if ( ShowToolTips() )
3701 itemChoice16->SetToolTip ( _ ( "The font colour." ) );
3702 itemBoxSizer14->Add ( itemChoice16, 0, wxALIGN_LEFT|wxALL, 5 );
3703 }
3704
3705 wxBoxSizer* itemBoxSizer17 = new wxBoxSizer ( wxVERTICAL );
3706 itemGridSizer4->Add ( itemBoxSizer17, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
3707 wxStaticText* itemStaticText18 = new wxStaticText ( this, wxID_STATIC, _ ( "&Point size:" ),
3708 wxDefaultPosition, wxDefaultSize, 0 );
3709 itemBoxSizer17->Add ( itemStaticText18, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3710
3711 wxChoice *pc = new wxChoice ( this, wxID_FONT_SIZE, wxDefaultPosition, wxDefaultSize );
3712 pc->SetHelpText ( _ ( "The font point size." ) );
3713 if ( ShowToolTips() )
3714 pc->SetToolTip ( _ ( "The font point size." ) );
3715 itemBoxSizer17->Add ( pc, 0, wxALIGN_LEFT|wxALL, 5 );
3716
3717 if ( m_fontData.GetEnableEffects() )
3718 {
3719 wxBoxSizer* itemBoxSizer20 = new wxBoxSizer ( wxVERTICAL );
3720 itemGridSizer4->Add ( itemBoxSizer20, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5 );
3721 wxCheckBox* itemCheckBox21 = new wxCheckBox ( this, wxID_FONT_UNDERLINE, _ ( "&Underline" ),
3722 wxDefaultPosition, wxDefaultSize, 0 );
3723 itemCheckBox21->SetValue ( FALSE );
3724 itemCheckBox21->SetHelpText ( _ ( "Whether the font is underlined." ) );
3725 if ( ShowToolTips() )
3726 itemCheckBox21->SetToolTip ( _ ( "Whether the font is underlined." ) );
3727 itemBoxSizer20->Add ( itemCheckBox21, 0, wxALIGN_LEFT|wxALL, 5 );
3728 }
3729
3730 if ( !is_pda )
3731 itemBoxSizer3->Add ( 5, 5, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
3732
3733 wxStaticText* itemStaticText23 = new wxStaticText ( this, wxID_STATIC, _ ( "Preview:" ), wxDefaultPosition, wxDefaultSize, 0 );
3734 itemBoxSizer3->Add ( itemStaticText23, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5 );
3735
3736 MyFontPreviewer* itemWindow24 = new MyFontPreviewer ( this, wxSize ( 400, 80 ) );
3737 m_previewer = itemWindow24;
3738 itemWindow24->SetHelpText ( _ ( "Shows the font preview." ) );
3739 if ( ShowToolTips() )
3740 itemWindow24->SetToolTip ( _ ( "Shows the font preview." ) );
3741 itemBoxSizer3->Add ( itemWindow24, 0, wxEXPAND, 5 );
3742
3743 wxBoxSizer* itemBoxSizer25 = new wxBoxSizer ( wxHORIZONTAL );
3744 itemBoxSizer3->Add ( itemBoxSizer25, 0, wxEXPAND, 5 );
3745 itemBoxSizer25->Add ( 5, 5, 1, wxEXPAND|wxALL, 5 );
3746
3747 wxButton* itemButton28 = new wxButton ( this, wxID_CANCEL, _( "Cancel" ), wxDefaultPosition, wxDefaultSize, 0 );
3748
3749 if ( ShowToolTips() )
3750 itemButton28->SetToolTip ( _ ( "Click to cancel the font selection." ) );
3751 itemBoxSizer25->Add ( itemButton28, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
3752
3753 wxButton* itemButton27 = new wxButton ( this, wxID_OK, _ ( "&OK" ), wxDefaultPosition, wxDefaultSize, 0 );
3754 itemButton27->SetDefault();
3755 itemButton27->SetHelpText ( _ ( "Click to confirm the font selection." ) );
3756 if ( ShowToolTips() )
3757 itemButton27->SetToolTip ( _ ( "Click to confirm the font selection." ) );
3758 itemBoxSizer25->Add ( itemButton27, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
3759
3760 familyChoice = ( wxChoice* ) FindWindow ( wxID_FONT_FAMILY );
3761 styleChoice = ( wxChoice* ) FindWindow ( wxID_FONT_STYLE );
3762 weightChoice = ( wxChoice* ) FindWindow ( wxID_FONT_WEIGHT );
3763 colourChoice = ( wxChoice* ) FindWindow ( wxID_FONT_COLOUR );
3764 pointSizeChoice = ( wxChoice* ) FindWindow ( wxID_FONT_SIZE );
3765 underLineCheckBox = ( wxCheckBox* ) FindWindow ( wxID_FONT_UNDERLINE );
3766
3767 // Get readable font items
3768 wxString gotfontnative = dialogFont.GetNativeFontInfoDesc();
3769 wxStringTokenizer st ( gotfontnative, _T ( "-" ) );
3770 st.GetNextToken();
3771 st.GetNextToken();
3772 wxString facename = st.GetNextToken();
3773 wxString weight = st.GetNextToken();
3774 st.GetNextToken();
3775 st.GetNextToken();
3776 st.GetNextToken();
3777 st.GetNextToken();
3778 wxString pointsize = st.GetNextToken();
3779
3780 int ptsz = atoi ( pointsize.mb_str() );
3781 pointsize.Printf ( _T ( "%d" ), ptsz / 10 );
3782
3783 SetChoiceOptionsFromFacename ( facename );
3784
3785 familyChoice->SetStringSelection ( facename );
3786 weightChoice->SetStringSelection ( weight );
3787 pointSizeChoice->SetStringSelection ( pointsize );
3788
3789 m_previewer->SetFont ( dialogFont );
3790 m_previewer->SetName ( _T( "ABCDEFGabcdefg12345" ) );
3791
3792 // m_previewer->Refresh();
3793
3794 // familyChoice->SetStringSelection( wxFontFamilyIntToString(dialogFont.GetFamily()) );
3795 // styleChoice->SetStringSelection(wxFontStyleIntToString(dialogFont.GetStyle()));
3796 // weightChoice->SetStringSelection(wxFontWeightIntToString(dialogFont.GetWeight()));
3797
3798 /*
3799 if (colourChoice)
3800 {
3801 wxString name(wxTheColourDatabase->FindName(m_fontData.GetColour()));
3802 if (name.length())
3803 colourChoice->SetStringSelection(name);
3804 else
3805 colourChoice->SetStringSelection(wxT("BLACK"));
3806 }
3807
3808 if (underLineCheckBox)
3809 {
3810 underLineCheckBox->SetValue(dialogFont.GetUnderlined());
3811 }
3812
3813 // pointSizeChoice->SetSelection(dialogFont.GetPointSize()-1);
3814 pointSizeChoice->SetSelection(0);
3815
3816 #if !defined(__SMARTPHONE__) && !defined(__POCKETPC__)
3817 GetSizer()->SetItemMinSize(m_previewer, is_pda ? 100 : 430, is_pda ? 40 : 100);
3818 GetSizer()->SetSizeHints(this);
3819 GetSizer()->Fit(this);
3820
3821 Centre(wxBOTH);
3822 #endif
3823 */
3824
3825 // Don't block events any more
3826 m_useEvents = true;
3827
3828 }
3829
OnChangeFace(wxCommandEvent & WXUNUSED (event))3830 void X11FontPicker::OnChangeFace ( wxCommandEvent& WXUNUSED ( event ) )
3831 {
3832 if ( !m_useEvents ) return;
3833
3834 // Capture the current selections
3835 wxString facename = familyChoice->GetStringSelection();
3836 wxString pointsize = pointSizeChoice->GetStringSelection();
3837 wxString weight = weightChoice->GetStringSelection();
3838
3839 SetChoiceOptionsFromFacename ( facename );
3840
3841 // Reset the choices
3842 familyChoice->SetStringSelection ( facename );
3843 weightChoice->SetStringSelection ( weight );
3844 pointSizeChoice->SetStringSelection ( pointsize );
3845
3846 // And make the font change
3847 DoFontChange();
3848
3849 }
3850
SetChoiceOptionsFromFacename(const wxString & facename)3851 void X11FontPicker::SetChoiceOptionsFromFacename (const wxString &facename)
3852 {
3853 // Get a list of matching fonts
3854 char face[101];
3855 strncpy ( face, facename.mb_str(), 100 );
3856 face[100] = '\0';
3857
3858 char pattern[100];
3859 sprintf ( pattern, "-*-%s-*-*-*-*-*-*-*-*-*-*-iso8859-1", face );
3860 // wxString pattern;
3861 // pattern.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-iso8859-1"), facename.mb_str());
3862
3863 int nFonts;
3864 char ** list = XListFonts ( ( Display * ) wxGetDisplay(), pattern, 32767, &nFonts );
3865
3866 // First, look thru all the point sizes looking for "0" to indicate scaleable (e.g. TrueType) font
3867 bool scaleable = false;
3868 for ( int i=0; i < nFonts; i++ )
3869 {
3870 wxStringTokenizer st ( wxString ( list[i] ), _T ( "-" ) );
3871 st.GetNextToken();
3872 st.GetNextToken();
3873 st.GetNextToken();
3874 st.GetNextToken();
3875 st.GetNextToken();
3876 st.GetNextToken();
3877 st.GetNextToken();
3878 wxString pointsize = st.GetNextToken();
3879
3880 if ( pointsize.IsSameAs ( _T ( "0" ) ) )
3881 {
3882 scaleable = true;
3883 break;
3884 }
3885 }
3886
3887 // make different pointsize selections for scaleable fonts
3888 wxArrayString PointSizeArray;
3889
3890 if ( scaleable )
3891 {
3892 for ( int j=0; j < SCALEABLE_SIZES; j++ )
3893 PointSizeArray.Add ( scaleable_pointsize[j] );
3894 }
3895
3896 else
3897 {
3898 //Get the Point Sizes Array
3899 unsigned int jname;
3900 for ( int i=0; i < nFonts; i++ )
3901 {
3902 // printf("%s\n", list[i]);
3903 wxStringTokenizer st ( wxString ( list[i] ), _T ( "-" ) );
3904 st.GetNextToken();
3905 st.GetNextToken();
3906 st.GetNextToken();
3907 st.GetNextToken();
3908 st.GetNextToken();
3909 st.GetNextToken();
3910 st.GetNextToken();
3911 wxString pointsize = st.GetNextToken();
3912 // printf("%s\n",facename.mb_str());
3913 for ( jname=0; jname<PointSizeArray.GetCount(); jname++ )
3914 {
3915 if ( pointsize == PointSizeArray[jname] )
3916 break;
3917 }
3918 if ( jname >= PointSizeArray.GetCount() )
3919 {
3920 PointSizeArray.Add ( pointsize );
3921 // printf("Added %s\n", pointsize.mb_str());
3922 }
3923 }
3924 }
3925 pointSizeChoice->Clear();
3926 pointSizeChoice->Append ( PointSizeArray );
3927 pointSizeChoice->SetSelection ( 0 );
3928
3929 //Get the Weight Array
3930 wxArrayString WeightArray;
3931 for ( int i=0; i < nFonts; i++ )
3932 {
3933 // printf("%s\n", list[i]);
3934 wxStringTokenizer st ( wxString ( list[i] ), _T ( "-" ) );
3935 st.GetNextToken();
3936 st.GetNextToken();
3937 st.GetNextToken();
3938 wxString weight = st.GetNextToken();
3939 // printf("%s\n",facename.mb_str());
3940 unsigned int jname;
3941 for ( jname=0; jname<WeightArray.GetCount(); jname++ )
3942 {
3943 if ( weight == WeightArray[jname] )
3944 break;
3945 }
3946 if ( jname >= WeightArray.GetCount() )
3947 {
3948 WeightArray.Add ( weight );
3949 // printf("Added weight %s\n", weight.mb_str());
3950 }
3951 }
3952
3953 weightChoice->Clear();
3954 weightChoice->Append ( WeightArray );
3955 weightChoice->SetSelection ( 0 );
3956
3957 }
3958
InitializeFont()3959 void X11FontPicker::InitializeFont()
3960 {
3961 int fontFamily = wxSWISS;
3962 int fontWeight = wxNORMAL;
3963 int fontStyle = wxNORMAL;
3964 int fontSize = 12;
3965 bool fontUnderline = false;
3966
3967 wxString fontnative;
3968 if ( m_fontData.m_initialFont.Ok() )
3969 {
3970 fontnative = m_fontData.m_initialFont.GetNativeFontInfoDesc();
3971 fontFamily = m_fontData.m_initialFont.GetFamily();
3972 fontWeight = m_fontData.m_initialFont.GetWeight();
3973 fontStyle = m_fontData.m_initialFont.GetStyle();
3974 fontSize = m_fontData.m_initialFont.GetPointSize();
3975 fontUnderline = m_fontData.m_initialFont.GetUnderlined();
3976 }
3977
3978 // printf("Init Fetching %s\n", fontnative.mb_str());
3979
3980 wxFont tFont = wxFont ( fontSize, fontFamily, fontStyle,
3981 fontWeight, fontUnderline );
3982
3983 wxFont *pdialogFont = tFont.New ( fontnative );
3984
3985 // Confirm
3986 /*
3987 wxNativeFontInfo *i = (wxNativeFontInfo *)pdialogFont->GetNativeFontInfo();
3988
3989 XFontStruct *xfont = (XFontStruct*) pdialogFont->GetFontStruct( 1.0, (Display *)wxGetDisplay() );
3990 unsigned long ret;
3991 XGetFontProperty(xfont, 18, &ret);
3992 char* x = XGetAtomName((Display *)wxGetDisplay(), ret);
3993 printf(" Init Got %s\n", x);
3994 */
3995
3996 dialogFont = *pdialogFont;
3997
3998 }
3999
OnChangeFont(wxCommandEvent & WXUNUSED (event))4000 void X11FontPicker::OnChangeFont ( wxCommandEvent& WXUNUSED ( event ) )
4001 {
4002 if ( !m_useEvents ) return;
4003
4004 DoFontChange();
4005 }
4006
DoFontChange(void)4007 void X11FontPicker::DoFontChange ( void )
4008 {
4009 wxString facename = familyChoice->GetStringSelection();
4010 wxString pointsize = pointSizeChoice->GetStringSelection();
4011 wxString weight = weightChoice->GetStringSelection();
4012
4013 char font_x[200];
4014 sprintf ( font_x,"-*-%s-%s-r-normal-*-*-%s0-*-*-*-*-iso8859-1", facename.mb_str(), weight.mb_str(), pointsize.mb_str() );
4015 wxString font_xlfd ( font_x, wxConvUTF8 );
4016
4017 // printf("Fetching %s\n", font_xlfd.mb_str());
4018
4019 XFontStruct *test = XLoadQueryFont ( ( Display * ) wxGetDisplay(),font_xlfd.mb_str() );
4020
4021 // Confirm
4022 /*
4023 unsigned long ret0;
4024 if(test)
4025 {
4026 XGetFontProperty(test, 18, &ret0);
4027 char* x = XGetAtomName((Display *)wxGetDisplay(), ret0);
4028 printf("FGot %s\n", x);
4029 }
4030 */
4031 if ( test )
4032 {
4033 font_xlfd.Prepend ( "0;" );
4034 wxFont *ptf = new wxFont;
4035 pPreviewFont = ptf->New ( font_xlfd );
4036
4037 /*
4038 wxNativeFontInfo *i = (wxNativeFontInfo *)pPreviewFont->GetNativeFontInfo();
4039
4040 XFontStruct *xfont = (XFontStruct*) pPreviewFont->GetFontStruct( 1.0, (Display *)wxGetDisplay() );
4041 unsigned long ret;
4042 XGetFontProperty(xfont, 18, &ret);
4043 char* x = XGetAtomName((Display *)wxGetDisplay(), ret);
4044 printf("Got %s\n", x);
4045 */
4046 m_previewer->SetName ( _T( "ABCDEFGabcdefg12345" ) );
4047 m_previewer->SetFont ( *pPreviewFont );
4048 m_previewer->Refresh();
4049 }
4050
4051 else
4052 {
4053 wxString err ( _T ( "No Font:" ) );
4054 err.Append ( font_xlfd );
4055 m_previewer->SetName ( err );
4056 m_previewer->SetFont ( *pPreviewFont );
4057 m_previewer->Refresh();
4058 }
4059
4060 /*
4061 int fontFamily = wxFontFamilyStringToInt(WXSTRINGCAST familyChoice->GetStringSelection());
4062 int fontWeight = wxFontWeightStringToInt(WXSTRINGCAST weightChoice->GetStringSelection());
4063 int fontStyle = wxFontStyleStringToInt(WXSTRINGCAST styleChoice->GetStringSelection());
4064 int fontSize = wxAtoi(pointSizeChoice->GetStringSelection());
4065 // Start with previous underline setting, we want to retain it even if we can't edit it
4066 // dialogFont is always initialized because of the call to InitializeFont
4067 int fontUnderline = dialogFont.GetUnderlined();
4068
4069 if (underLineCheckBox)
4070 {
4071 fontUnderline = underLineCheckBox->GetValue();
4072 }
4073
4074 dialogFont = wxFont(fontSize, fontFamily, fontStyle, fontWeight, (fontUnderline != 0));
4075 m_previewer->SetFont(dialogFont);
4076
4077 if ( colourChoice )
4078 {
4079 if ( !colourChoice->GetStringSelection().empty() )
4080 {
4081 wxColour col = wxTheColourDatabase->Find(colourChoice->GetStringSelection());
4082 if (col.Ok())
4083 {
4084 m_fontData.m_fontColour = col;
4085 }
4086 }
4087 }
4088 // Update color here so that we can also use the color originally passed in
4089 // (EnableEffects may be false)
4090 if (m_fontData.m_fontColour.Ok())
4091 m_previewer->SetForegroundColour(m_fontData.m_fontColour);
4092
4093 m_previewer->Refresh();
4094 */
4095 }
4096
4097 #endif //__WXX11__
4098
4099 //---------------------------------------------------------------------------------
4100 // Vector Stuff for Hit Test Algorithm
4101 //---------------------------------------------------------------------------------
vGetLengthOfNormal(pVector2D a,pVector2D b,pVector2D n)4102 double vGetLengthOfNormal( pVector2D a, pVector2D b, pVector2D n )
4103 {
4104 vector2D c, vNormal;
4105 vNormal.x = 0;
4106 vNormal.y = 0;
4107 //
4108 //Obtain projection vector.
4109 //
4110 //c = ((a * b)/(|b|^2))*b
4111 //
4112 c.x = b->x * ( vDotProduct( a, b ) / vDotProduct( b, b ) );
4113 c.y = b->y * ( vDotProduct( a, b ) / vDotProduct( b, b ) );
4114 //
4115 //Obtain perpendicular projection : e = a - c
4116 //
4117 vSubtractVectors( a, &c, &vNormal );
4118 //
4119 //Fill PROJECTION structure with appropriate values.
4120 //
4121 *n = vNormal;
4122
4123 return ( vVectorMagnitude( &vNormal ) );
4124 }
4125
vDotProduct(pVector2D v0,pVector2D v1)4126 double vDotProduct( pVector2D v0, pVector2D v1 )
4127 {
4128 double dotprod;
4129
4130 dotprod = ( v0 == NULL || v1 == NULL ) ? 0.0 : ( v0->x * v1->x ) + ( v0->y * v1->y );
4131
4132 return ( dotprod );
4133 }
4134
vAddVectors(pVector2D v0,pVector2D v1,pVector2D v)4135 pVector2D vAddVectors( pVector2D v0, pVector2D v1, pVector2D v )
4136 {
4137 if( v0 == NULL || v1 == NULL ) v = (pVector2D) NULL;
4138 else {
4139 v->x = v0->x + v1->x;
4140 v->y = v0->y + v1->y;
4141 }
4142 return ( v );
4143 }
4144
vSubtractVectors(pVector2D v0,pVector2D v1,pVector2D v)4145 pVector2D vSubtractVectors( pVector2D v0, pVector2D v1, pVector2D v )
4146 {
4147 if( v0 == NULL || v1 == NULL ) v = (pVector2D) NULL;
4148 else {
4149 v->x = v0->x - v1->x;
4150 v->y = v0->y - v1->y;
4151 }
4152 return ( v );
4153 }
4154
vVectorSquared(pVector2D v0)4155 double vVectorSquared( pVector2D v0 )
4156 {
4157 double dS;
4158
4159 if( v0 == NULL ) dS = 0.0;
4160 else
4161 dS = ( ( v0->x * v0->x ) + ( v0->y * v0->y ) );
4162 return ( dS );
4163 }
4164
vVectorMagnitude(pVector2D v0)4165 double vVectorMagnitude( pVector2D v0 )
4166 {
4167 double dMagnitude;
4168
4169 if( v0 == NULL ) dMagnitude = 0.0;
4170 else
4171 dMagnitude = sqrt( vVectorSquared( v0 ) );
4172 return ( dMagnitude );
4173 }
4174
4175 /**************************************************************************/
4176 /* LogMessageOnce */
4177 /**************************************************************************/
4178
LogMessageOnce(const wxString & msg)4179 bool LogMessageOnce(const wxString &msg)
4180 {
4181 // Search the array for a match
4182
4183 for( unsigned int i = 0; i < pMessageOnceArray->GetCount(); i++ ) {
4184 if( msg.IsSameAs( pMessageOnceArray->Item( i ) ) ) return false;
4185 }
4186
4187 // Not found, so add to the array
4188 pMessageOnceArray->Add( msg );
4189
4190 // And print it
4191 wxLogMessage( msg );
4192 return true;
4193 }
4194
4195 /**************************************************************************/
4196 /* Some assorted utilities */
4197 /**************************************************************************/
4198
4199 /**************************************************************************/
4200 /* Converts the distance to the units selected by user */
4201 /**************************************************************************/
toUsrDistance(double nm_distance,int unit)4202 double toUsrDistance( double nm_distance, int unit )
4203 {
4204 double ret = NAN;
4205 if ( unit == -1 )
4206 unit = g_iDistanceFormat;
4207 switch( unit ){
4208 case DISTANCE_NMI: //Nautical miles
4209 ret = nm_distance;
4210 break;
4211 case DISTANCE_MI: //Statute miles
4212 ret = nm_distance * 1.15078;
4213 break;
4214 case DISTANCE_KM:
4215 ret = nm_distance * 1.852;
4216 break;
4217 case DISTANCE_M:
4218 ret = nm_distance * 1852;
4219 break;
4220 case DISTANCE_FT:
4221 ret = nm_distance * 6076.12;
4222 break;
4223 case DISTANCE_FA:
4224 ret = nm_distance * 1012.68591;
4225 break;
4226 case DISTANCE_IN:
4227 ret = nm_distance * 72913.4;
4228 break;
4229 case DISTANCE_CM:
4230 ret = nm_distance * 185200;
4231 break;
4232 }
4233 return ret;
4234 }
4235
4236 /**************************************************************************/
4237 /* Converts the distance from the units selected by user to NMi */
4238 /**************************************************************************/
fromUsrDistance(double usr_distance,int unit)4239 double fromUsrDistance( double usr_distance, int unit )
4240 {
4241 double ret = NAN;
4242 if ( unit == -1 )
4243 unit = g_iDistanceFormat;
4244 switch( unit ){
4245 case DISTANCE_NMI: //Nautical miles
4246 ret = usr_distance;
4247 break;
4248 case DISTANCE_MI: //Statute miles
4249 ret = usr_distance / 1.15078;
4250 break;
4251 case DISTANCE_KM:
4252 ret = usr_distance / 1.852;
4253 break;
4254 case DISTANCE_M:
4255 ret = usr_distance / 1852;
4256 break;
4257 case DISTANCE_FT:
4258 ret = usr_distance / 6076.12;
4259 break;
4260 }
4261 return ret;
4262 }
4263
4264 /**************************************************************************/
4265 /* Returns the abbreviation of user selected distance unit */
4266 /**************************************************************************/
getUsrDistanceUnit(int unit)4267 wxString getUsrDistanceUnit( int unit )
4268 {
4269 wxString ret;
4270 if ( unit == -1 )
4271 unit = g_iDistanceFormat;
4272 switch( unit ){
4273 case DISTANCE_NMI: //Nautical miles
4274 ret = _("NMi");
4275 break;
4276 case DISTANCE_MI: //Statute miles
4277 ret = _("mi");
4278 break;
4279 case DISTANCE_KM:
4280 ret = _("km");
4281 break;
4282 case DISTANCE_M:
4283 ret = _("m");
4284 break;
4285 case DISTANCE_FT:
4286 ret = _("ft");
4287 break;
4288 case DISTANCE_FA:
4289 ret = _("fa");
4290 break;
4291 case DISTANCE_IN:
4292 ret = _("in");
4293 break;
4294 case DISTANCE_CM:
4295 ret = _("cm");
4296 break;
4297 }
4298 return ret;
4299 }
4300
4301 /**************************************************************************/
4302 /* Converts the speed to the units selected by user */
4303 /**************************************************************************/
toUsrSpeed(double kts_speed,int unit)4304 double toUsrSpeed( double kts_speed, int unit )
4305 {
4306 double ret = NAN;
4307 if ( unit == -1 )
4308 unit = g_iSpeedFormat;
4309 switch( unit )
4310 {
4311 case SPEED_KTS: //kts
4312 ret = kts_speed;
4313 break;
4314 case SPEED_MPH: //mph
4315 ret = kts_speed * 1.15078;
4316 break;
4317 case SPEED_KMH: //km/h
4318 ret = kts_speed * 1.852;
4319 break;
4320 case SPEED_MS: //m/s
4321 ret = kts_speed * 0.514444444;
4322 break;
4323 }
4324 return ret;
4325 }
4326
4327 /**************************************************************************/
4328 /* Converts the speed from the units selected by user to knots */
4329 /**************************************************************************/
fromUsrSpeed(double usr_speed,int unit)4330 double fromUsrSpeed( double usr_speed, int unit )
4331 {
4332 double ret = NAN;
4333 if ( unit == -1 )
4334 unit = g_iSpeedFormat;
4335 switch( unit )
4336 {
4337 case SPEED_KTS: //kts
4338 ret = usr_speed;
4339 break;
4340 case SPEED_MPH: //mph
4341 ret = usr_speed / 1.15078;
4342 break;
4343 case SPEED_KMH: //km/h
4344 ret = usr_speed / 1.852;
4345 break;
4346 case SPEED_MS: //m/s
4347 ret = usr_speed / 0.514444444;
4348 break;
4349 }
4350 return ret;
4351 }
4352
4353 /**************************************************************************/
4354 /* Returns the abbreviation of user selected speed unit */
4355 /**************************************************************************/
getUsrSpeedUnit(int unit)4356 wxString getUsrSpeedUnit( int unit )
4357 {
4358 wxString ret;
4359 if ( unit == -1 )
4360 unit = g_iSpeedFormat;
4361 switch( unit ){
4362 case SPEED_KTS: //kts
4363 ret = _("kts");
4364 break;
4365 case SPEED_MPH: //mph
4366 ret = _("mph");
4367 break;
4368 case SPEED_KMH:
4369 ret = _("km/h");
4370 break;
4371 case SPEED_MS:
4372 ret = _("m/s");
4373 break;
4374 }
4375 return ret;
4376 }
4377
formatTimeDelta(wxTimeSpan span)4378 wxString formatTimeDelta(wxTimeSpan span)
4379 {
4380 wxString timeStr;
4381 int days = span.GetDays();
4382 span -= wxTimeSpan::Days(days);
4383 int hours = span.GetHours();
4384 span -= wxTimeSpan::Hours(hours);
4385 double minutes = (double)span.GetSeconds().ToLong()/60.0;
4386 span -= wxTimeSpan::Minutes(span.GetMinutes());
4387 int seconds = (double)span.GetSeconds().ToLong();
4388
4389 timeStr = (days ? wxString::Format(_("%dd "), days) : _T("")) +
4390 (hours || days ? wxString::Format(_("%2dH %2dM"), hours, (int)round(minutes)) :
4391 wxString::Format(_("%2dM %2dS"), (int)floor(minutes), seconds));
4392
4393 return timeStr;
4394 }
4395
formatTimeDelta(wxDateTime startTime,wxDateTime endTime)4396 wxString formatTimeDelta(wxDateTime startTime, wxDateTime endTime)
4397 {
4398 wxString timeStr;
4399 if(startTime.IsValid() && endTime.IsValid())
4400 {
4401 wxTimeSpan span = endTime - startTime;
4402 return formatTimeDelta(span);
4403 } else {
4404 return _("N/A");
4405 }
4406 }
4407
formatTimeDelta(wxLongLong secs)4408 wxString formatTimeDelta(wxLongLong secs)
4409 {
4410 wxString timeStr;
4411
4412 wxTimeSpan span(0, 0, secs);
4413 return formatTimeDelta(span);
4414 }
4415
FormatDistanceAdaptive(double distance)4416 wxString FormatDistanceAdaptive( double distance ) {
4417 wxString result;
4418 int unit = g_iDistanceFormat;
4419 double usrDistance = toUsrDistance( distance, unit );
4420 if( usrDistance < 0.1 && ( unit == DISTANCE_KM || unit == DISTANCE_MI || unit == DISTANCE_NMI ) ) {
4421 unit = ( unit == DISTANCE_MI ) ? DISTANCE_FT : DISTANCE_M;
4422 usrDistance = toUsrDistance( distance, unit );
4423 }
4424 wxString format;
4425 if( usrDistance < 5.0 ) {
4426 format = _T("%1.2f ");
4427 } else if( usrDistance < 100.0 ) {
4428 format = _T("%2.1f ");
4429 } else if( usrDistance < 1000.0 ) {
4430 format = _T("%3.0f ");
4431 } else {
4432 format = _T("%4.0f ");
4433 }
4434 result << wxString::Format(format, usrDistance ) << getUsrDistanceUnit( unit );
4435 return result;
4436 }
4437
4438 /**************************************************************************/
4439 /* Formats the coordinates to string */
4440 /**************************************************************************/
toSDMM(int NEflag,double a,bool hi_precision)4441 wxString toSDMM( int NEflag, double a, bool hi_precision )
4442 {
4443 wxString s;
4444 double mpy;
4445 short neg = 0;
4446 int d;
4447 long m;
4448 double ang = a;
4449 char c = 'N';
4450
4451 if( a < 0.0 ) {
4452 a = -a;
4453 neg = 1;
4454 }
4455 d = (int) a;
4456 if( neg ) d = -d;
4457 if( NEflag ) {
4458 if( NEflag == 1 ) {
4459 c = 'N';
4460
4461 if( neg ) {
4462 d = -d;
4463 c = 'S';
4464 }
4465 } else
4466 if( NEflag == 2 ) {
4467 c = 'E';
4468
4469 if( neg ) {
4470 d = -d;
4471 c = 'W';
4472 }
4473 }
4474 }
4475
4476 switch( g_iSDMMFormat ){
4477 case 0:
4478 mpy = 600.0;
4479 if( hi_precision ) mpy = mpy * 1000;
4480
4481 m = (long) wxRound( ( a - (double) d ) * mpy );
4482
4483 if( !NEflag || NEflag < 1 || NEflag > 2 ) //Does it EVER happen?
4484 {
4485 if( hi_precision ) s.Printf( _T ( "%d\u00B0 %02ld.%04ld'" ), d, m / 10000, m % 10000 );
4486 else
4487 s.Printf( _T ( "%d\u00B0 %02ld.%01ld'" ), d, m / 10, m % 10 );
4488 } else {
4489 if( hi_precision )
4490 if (NEflag == 1)
4491 s.Printf( _T ( "%02d\u00B0 %02ld.%04ld' %c" ), d, m / 10000, ( m % 10000 ), c );
4492 else
4493 s.Printf( _T ( "%03d\u00B0 %02ld.%04ld' %c" ), d, m / 10000, ( m % 10000 ), c );
4494 else
4495 if (NEflag == 1)
4496 s.Printf( _T ( "%02d\u00B0 %02ld.%01ld' %c" ), d, m / 10, ( m % 10 ), c );
4497 else
4498 s.Printf( _T ( "%03d\u00B0 %02ld.%01ld' %c" ), d, m / 10, ( m % 10 ), c );
4499 }
4500 break;
4501 case 1:
4502 if( hi_precision ) s.Printf( _T ( "%03.6f" ), ang ); //cca 11 cm - the GPX precision is higher, but as we use hi_precision almost everywhere it would be a little too much....
4503 else
4504 s.Printf( _T ( "%03.4f" ), ang ); //cca 11m
4505 break;
4506 case 2:
4507 m = (long) ( ( a - (double) d ) * 60 );
4508 mpy = 10.0;
4509 if( hi_precision ) mpy = mpy * 100;
4510 long sec = (long) ( ( a - (double) d - ( ( (double) m ) / 60 ) ) * 3600 * mpy );
4511
4512 if( !NEflag || NEflag < 1 || NEflag > 2 ) //Does it EVER happen?
4513 {
4514 if( hi_precision ) s.Printf( _T ( "%d\u00B0 %ld'%ld.%ld\"" ), d, m, sec / 1000,
4515 sec % 1000 );
4516 else
4517 s.Printf( _T ( "%d\u00B0 %ld'%ld.%ld\"" ), d, m, sec / 10, sec % 10 );
4518 } else {
4519 if( hi_precision )
4520 if (NEflag == 1)
4521 s.Printf( _T ( "%02d\u00B0 %02ld' %02ld.%03ld\" %c" ), d, m, sec / 1000, sec % 1000, c );
4522 else
4523 s.Printf( _T ( "%03d\u00B0 %02ld' %02ld.%03ld\" %c" ), d, m, sec / 1000, sec % 1000, c );
4524 else
4525 if (NEflag == 1)
4526 s.Printf( _T ( "%02d\u00B0 %02ld' %02ld.%ld\" %c" ), d, m, sec / 10, sec % 10, c );
4527 else
4528 s.Printf( _T ( "%03d\u00B0 %02ld' %02ld.%ld\" %c" ), d, m, sec / 10, sec % 10, c );
4529 }
4530 break;
4531 }
4532 return s;
4533 }
4534
4535 /****************************************************************************/
4536 // Modified from the code posted by Andy Ross at
4537 // http://www.mail-archive.com/flightgear-devel@flightgear.org/msg06702.html
4538 // Basically, it looks for a list of decimal numbers embedded in the
4539 // string and uses the first three as degree, minutes and seconds. The
4540 // presence of a "S" or "W character indicates that the result is in a
4541 // hemisphere where the final answer must be negated. Non-number
4542 // characters are treated as whitespace separating numbers.
4543 //
4544 // So there are lots of bogus strings you can feed it to get a bogus
4545 // answer, but that's not surprising. It does, however, correctly parse
4546 // all the well-formed strings I can thing of to feed it. I've tried all
4547 // the following:
4548 //
4549 // 37°54.204' N
4550 // N37 54 12
4551 // 37°54'12"
4552 // 37.9034
4553 // 122°18.621' W
4554 // 122w 18 37
4555 // -122.31035
4556 /****************************************************************************/
fromDMM(wxString sdms)4557 double fromDMM( wxString sdms )
4558 {
4559 wchar_t buf[64];
4560 char narrowbuf[64];
4561 int i, len, top = 0;
4562 double stk[32], sign = 1;
4563
4564 //First round of string modifications to accomodate some known strange formats
4565 wxString replhelper;
4566 replhelper = wxString::FromUTF8( "´·" ); //UKHO PDFs
4567 sdms.Replace( replhelper, _T(".") );
4568 replhelper = wxString::FromUTF8( "\"·" ); //Don't know if used, but to make sure
4569 sdms.Replace( replhelper, _T(".") );
4570 replhelper = wxString::FromUTF8( "·" );
4571 sdms.Replace( replhelper, _T(".") );
4572
4573 replhelper = wxString::FromUTF8( "s. š." ); //Another example: cs.wikipedia.org (someone was too active translating...)
4574 sdms.Replace( replhelper, _T("N") );
4575 replhelper = wxString::FromUTF8( "j. š." );
4576 sdms.Replace( replhelper, _T("S") );
4577 sdms.Replace( _T("v. d."), _T("E") );
4578 sdms.Replace( _T("z. d."), _T("W") );
4579
4580 //If the string contains hemisphere specified by a letter, then '-' is for sure a separator...
4581 sdms.UpperCase();
4582 if( sdms.Contains( _T("N") ) || sdms.Contains( _T("S") ) || sdms.Contains( _T("E") )
4583 || sdms.Contains( _T("W") ) ) sdms.Replace( _T("-"), _T(" ") );
4584
4585 wcsncpy( buf, sdms.wc_str( wxConvUTF8 ), 63 );
4586 buf[63] = 0;
4587 len = wxMin( wcslen( buf ), sizeof(narrowbuf)-1);;
4588
4589 for( i = 0; i < len; i++ ) {
4590 wchar_t c = buf[i];
4591 if( ( c >= '0' && c <= '9' ) || c == '-' || c == '.' || c == '+' ) {
4592 narrowbuf[i] = c;
4593 continue; /* Digit characters are cool as is */
4594 }
4595 if( c == ',' ) {
4596 narrowbuf[i] = '.'; /* convert to decimal dot */
4597 continue;
4598 }
4599 if( ( c | 32 ) == 'w' || ( c | 32 ) == 's' ) sign = -1; /* These mean "negate" (note case insensitivity) */
4600 narrowbuf[i] = 0; /* Replace everything else with nuls */
4601 }
4602
4603 /* Build a stack of doubles */
4604 stk[0] = stk[1] = stk[2] = 0;
4605 for( i = 0; i < len; i++ ) {
4606 while( i < len && narrowbuf[i] == 0 )
4607 i++;
4608 if( i != len ) {
4609 stk[top++] = atof( narrowbuf + i );
4610 i += strlen( narrowbuf + i );
4611 }
4612 }
4613
4614 return sign * ( stk[0] + ( stk[1] + stk[2] / 60 ) / 60 );
4615 }
4616
formatAngle(double angle)4617 wxString formatAngle(double angle)
4618 {
4619 wxString out;
4620 if( g_bShowMag && g_bShowTrue ) {
4621 out.Printf(wxT("%03.0f \u00B0T (%.0f \u00B0M)"), angle, gFrame->GetMag(angle));
4622 } else if( g_bShowTrue ) {
4623 out.Printf(wxT("%03.0f \u00B0T"), angle);
4624 } else {
4625 out.Printf(wxT("%03.0f \u00B0M"), gFrame->GetMag(angle));
4626 }
4627 return out;
4628 }
4629
4630 /* render a rectangle at a given color and transparency */
AlphaBlending(ocpnDC & dc,int x,int y,int size_x,int size_y,float radius,wxColour color,unsigned char transparency)4631 void AlphaBlending( ocpnDC &dc, int x, int y, int size_x, int size_y, float radius, wxColour color,
4632 unsigned char transparency )
4633 {
4634 wxDC *pdc = dc.GetDC();
4635 if( pdc ) {
4636 // Get wxImage of area of interest
4637 wxBitmap obm( size_x, size_y );
4638 wxMemoryDC mdc1;
4639 mdc1.SelectObject( obm );
4640 mdc1.Blit( 0, 0, size_x, size_y, pdc, x, y );
4641 mdc1.SelectObject( wxNullBitmap );
4642 wxImage oim = obm.ConvertToImage();
4643
4644 // Create destination image
4645 wxBitmap olbm( size_x, size_y );
4646 wxMemoryDC oldc( olbm );
4647 if(!oldc.IsOk())
4648 return;
4649
4650 oldc.SetBackground( *wxBLACK_BRUSH );
4651 oldc.SetBrush( *wxWHITE_BRUSH );
4652 oldc.Clear();
4653
4654 if( radius > 0.0 )
4655 oldc.DrawRoundedRectangle( 0, 0, size_x, size_y, radius );
4656
4657 wxImage dest = olbm.ConvertToImage();
4658 unsigned char *dest_data = (unsigned char *) malloc(
4659 size_x * size_y * 3 * sizeof(unsigned char) );
4660 unsigned char *bg = oim.GetData();
4661 unsigned char *box = dest.GetData();
4662 unsigned char *d = dest_data;
4663
4664 // Sometimes, on Windows, the destination image is corrupt...
4665 if(NULL == box)
4666 {
4667 free(d);
4668 return;
4669 }
4670 float alpha = 1.0 - (float)transparency / 255.0;
4671 int sb = size_x * size_y;
4672 for( int i = 0; i < sb; i++ ) {
4673 float a = alpha;
4674 if( *box == 0 && radius > 0.0 ) a = 1.0;
4675 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
4676 *d++ = r; box++;
4677 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
4678 *d++ = g; box++;
4679 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
4680 *d++ = b; box++;
4681 }
4682
4683 dest.SetData( dest_data );
4684
4685 // Convert destination to bitmap and draw it
4686 wxBitmap dbm( dest );
4687 dc.DrawBitmap( dbm, x, y, false );
4688
4689 // on MSW, the dc Bounding box is not updated on DrawBitmap() method.
4690 // Do it explicitely here for all platforms.
4691 dc.CalcBoundingBox( x, y );
4692 dc.CalcBoundingBox( x + size_x, y + size_y );
4693 } else {
4694 #ifdef ocpnUSE_GL
4695 #ifdef USE_ANDROID_GLES2
4696 glEnable( GL_BLEND );
4697
4698 float radMod = wxMax(radius, 2.0);
4699 wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
4700 dc.SetBrush(wxBrush(c));
4701 dc.SetPen(wxPen(c, 1));
4702 dc.DrawRoundedRectangle( x, y, size_x, size_y, radMod );
4703
4704 glDisable( GL_BLEND );
4705
4706
4707 #else
4708 /* opengl version */
4709 glEnable( GL_BLEND );
4710
4711 if(radius > 1.0f){
4712 wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
4713 dc.SetBrush(wxBrush(c));
4714 dc.DrawRoundedRectangle( x, y, size_x, size_y, radius );
4715 }
4716 else {
4717 glColor4ub( color.Red(), color.Green(), color.Blue(), transparency );
4718 glBegin( GL_QUADS );
4719 glVertex2i( x, y );
4720 glVertex2i( x + size_x, y );
4721 glVertex2i( x + size_x, y + size_y );
4722 glVertex2i( x, y + size_y );
4723 glEnd();
4724 }
4725 glDisable( GL_BLEND );
4726 #endif
4727 #endif
4728 }
4729 }
4730
4731 // RFC4122 version 4 compliant random UUIDs generator.
GetUUID(void)4732 wxString GpxDocument::GetUUID(void)
4733 {
4734 wxString str;
4735 struct {
4736 int time_low;
4737 int time_mid;
4738 int time_hi_and_version;
4739 int clock_seq_hi_and_rsv;
4740 int clock_seq_low;
4741 int node_hi;
4742 int node_low;
4743 } uuid;
4744
4745 uuid.time_low = GetRandomNumber(0, 2147483647);//FIXME: the max should be set to something like MAXINT32, but it doesn't compile un gcc...
4746 uuid.time_mid = GetRandomNumber(0, 65535);
4747 uuid.time_hi_and_version = GetRandomNumber(0, 65535);
4748 uuid.clock_seq_hi_and_rsv = GetRandomNumber(0, 255);
4749 uuid.clock_seq_low = GetRandomNumber(0, 255);
4750 uuid.node_hi = GetRandomNumber(0, 65535);
4751 uuid.node_low = GetRandomNumber(0, 2147483647);
4752
4753 /* Set the two most significant bits (bits 6 and 7) of the
4754 * clock_seq_hi_and_rsv to zero and one, respectively. */
4755 uuid.clock_seq_hi_and_rsv = (uuid.clock_seq_hi_and_rsv & 0x3F) | 0x80;
4756
4757 /* Set the four most significant bits (bits 12 through 15) of the
4758 * time_hi_and_version field to 4 */
4759 uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0fff) | 0x4000;
4760
4761 str.Printf(_T("%08x-%04x-%04x-%02x%02x-%04x%08x"),
4762 uuid.time_low,
4763 uuid.time_mid,
4764 uuid.time_hi_and_version,
4765 uuid.clock_seq_hi_and_rsv,
4766 uuid.clock_seq_low,
4767 uuid.node_hi,
4768 uuid.node_low);
4769
4770 return str;
4771 }
4772
GetRandomNumber(int range_min,int range_max)4773 int GpxDocument::GetRandomNumber(int range_min, int range_max)
4774 {
4775 long u = (long)wxRound(((double)rand() / ((double)(RAND_MAX) + 1) * (range_max - range_min)) + range_min);
4776 return (int)u;
4777 }
4778
SeedRandom()4779 void GpxDocument::SeedRandom()
4780 {
4781 /* Fill with random. Miliseconds hopefully good enough for our usage, reading /dev/random would be much better on linux and system guid function on Windows as well */
4782 wxDateTime x = wxDateTime::UNow();
4783 long seed = x.GetMillisecond();
4784 seed *= x.GetTicks();
4785 srand(seed);
4786 }
4787
DimeControl(wxWindow * ctrl)4788 void DimeControl( wxWindow* ctrl )
4789 {
4790 #ifdef __WXOSX__
4791 // On macOS 10.14+, we use the native colours in both light mode and dark mode, and do not need to do anything else.
4792 // Dark mode is toggled at the application level in `SetAndApplyColorScheme`, and is also respected if it is enabled system-wide.
4793 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
4794 return;
4795 }
4796 #endif
4797 #ifdef __WXQT__
4798 return; // this is seriously broken on wxqt
4799 #endif
4800
4801 if( NULL == ctrl ) return;
4802
4803 wxColour col, window_back_color, gridline, uitext, udkrd, ctrl_back_color, text_color;
4804 col = GetGlobalColor( _T("DILG0") ); // Dialog Background white
4805 window_back_color = GetGlobalColor( _T("DILG1") ); // Dialog Background
4806 ctrl_back_color = GetGlobalColor( _T("DILG1") ); // Control Background
4807 text_color = GetGlobalColor( _T("DILG3") ); // Text
4808 uitext = GetGlobalColor( _T("UITX1") ); // Menu Text, derived from UINFF
4809 udkrd = GetGlobalColor( _T("UDKRD") );
4810 gridline = GetGlobalColor( _T("GREY2") );
4811
4812 DimeControl( ctrl, col, window_back_color, ctrl_back_color, text_color, uitext, udkrd, gridline );
4813 }
4814
DimeControl(wxWindow * ctrl,wxColour col,wxColour window_back_color,wxColour ctrl_back_color,wxColour text_color,wxColour uitext,wxColour udkrd,wxColour gridline)4815 void DimeControl( wxWindow* ctrl, wxColour col, wxColour window_back_color, wxColour ctrl_back_color,
4816 wxColour text_color, wxColour uitext, wxColour udkrd, wxColour gridline )
4817 {
4818 #ifdef __WXOSX__
4819 // On macOS 10.14+, we use the native colours in both light mode and dark mode, and do not need to do anything else.
4820 // Dark mode is toggled at the application level in `SetAndApplyColorScheme`, and is also respected if it is enabled system-wide.
4821 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
4822 return;
4823 }
4824 #endif
4825
4826 ColorScheme cs = global_color_scheme;
4827
4828 // Are we in dusk or night mode? (Used below in several places.)
4829 bool darkMode = ( cs == GLOBAL_COLOR_SCHEME_DUSK || cs == GLOBAL_COLOR_SCHEME_NIGHT );
4830
4831 static int depth = 0; // recursion count
4832 if ( depth == 0 ) { // only for the window root, not for every child
4833 // If the color scheme is DAY or RGB, use the default platform native colour for backgrounds
4834 if ( !darkMode ) {
4835 window_back_color = wxNullColour;
4836 col = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
4837 uitext = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
4838 }
4839
4840 ctrl->SetBackgroundColour( window_back_color );
4841
4842 #if defined(__WXOSX__) && defined(OCPN_USE_DARKMODE)
4843 // On macOS 10.12, enable dark mode at the window level if appropriate.
4844 // This will enable dark window decorations but will not darken the rest of the UI.
4845 if ( wxPlatformInfo::Get().CheckOSVersion(10, 12) ) {
4846 setWindowLevelDarkMode(ctrl->MacGetTopLevelWindowRef(), darkMode);
4847 }
4848 // Force consistent coloured UI text; dark in light mode and light in dark mode.
4849 uitext = darkMode ? wxColor(228,228,228) : wxColor(0,0,0);
4850 #endif
4851 }
4852
4853 wxWindowList kids = ctrl->GetChildren();
4854 for( unsigned int i = 0; i < kids.GetCount(); i++ ) {
4855 wxWindowListNode *node = kids.Item(i);
4856 wxWindow *win = node->GetData();
4857
4858 if (
4859 win->IsKindOf(CLASSINFO(wxListBox))
4860 || win->IsKindOf(CLASSINFO(wxListCtrl))
4861 || win->IsKindOf(CLASSINFO(wxTextCtrl))
4862 #ifndef __OCPN__ANDROID__
4863 || win->IsKindOf(CLASSINFO(wxTimePickerCtrl))
4864 #endif
4865 ) {
4866 win->SetBackgroundColour(col);
4867 }
4868 else if (
4869 win->IsKindOf(CLASSINFO(wxStaticText))
4870 || win->IsKindOf(CLASSINFO(wxCheckBox))
4871 || win->IsKindOf(CLASSINFO(wxRadioButton))
4872 ) {
4873 win->SetForegroundColour(uitext);
4874 }
4875
4876 #ifndef __WXOSX__
4877 // On macOS most controls can't be styled, and trying to do so only creates weird coloured boxes around them.
4878 // Fortunately, however, many of them inherit a colour or tint from the background of their parent.
4879
4880 else if (
4881 win->IsKindOf(CLASSINFO(wxBitmapComboBox))
4882 || win->IsKindOf(CLASSINFO(wxChoice))
4883 || win->IsKindOf(CLASSINFO(wxComboBox))
4884 || win->IsKindOf(CLASSINFO(wxTreeCtrl))
4885 ) {
4886 win->SetBackgroundColour(col);
4887 }
4888
4889 else if (
4890 win->IsKindOf(CLASSINFO(wxScrolledWindow))
4891 || win->IsKindOf(CLASSINFO(wxGenericDirCtrl))
4892 || win->IsKindOf(CLASSINFO(wxListbook))
4893 || win->IsKindOf(CLASSINFO(wxButton))
4894 || win->IsKindOf(CLASSINFO(wxToggleButton))
4895 ) {
4896 win->SetBackgroundColour( window_back_color );
4897 }
4898
4899 else if ( win->IsKindOf(CLASSINFO(wxNotebook)) ) {
4900 ((wxNotebook*) win)->SetBackgroundColour(window_back_color);
4901 ((wxNotebook*) win)->SetForegroundColour(text_color);
4902 }
4903 #endif
4904
4905 else if( win->IsKindOf( CLASSINFO(wxHtmlWindow) ) ) {
4906 if( cs != GLOBAL_COLOR_SCHEME_DAY && cs != GLOBAL_COLOR_SCHEME_RGB )
4907 ( (wxPanel*) win )->SetBackgroundColour( ctrl_back_color );
4908 else
4909 ( (wxPanel*) win )->SetBackgroundColour( wxNullColour );
4910 }
4911
4912 else if( win->IsKindOf( CLASSINFO(wxGrid) ) ) {
4913 ( (wxGrid*) win )->SetDefaultCellBackgroundColour( window_back_color );
4914 ( (wxGrid*) win )->SetDefaultCellTextColour( uitext );
4915 ( (wxGrid*) win )->SetLabelBackgroundColour( col );
4916 ( (wxGrid*) win )->SetLabelTextColour( uitext );
4917 #if !wxCHECK_VERSION(3,0,0)
4918 ( (wxGrid*) win )->SetDividerPen( wxPen( col ) );
4919 #endif
4920 ( (wxGrid*) win )->SetGridLineColour( gridline );
4921 }
4922
4923 if( win->GetChildren().GetCount() > 0 ) {
4924 depth++;
4925 wxWindow * w = win;
4926 DimeControl( w, col, window_back_color, ctrl_back_color, text_color, uitext, udkrd, gridline );
4927 depth--;
4928 }
4929 }
4930 }
4931
4932
4933