OpenCPN Partial API docs
Loading...
Searching...
No Matches
options.cpp
1/***************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: Options Dialog
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#include <memory>
26
27#ifdef __linux__
28#include <unistd.h>
29#endif
30
31#ifdef __MINGW32__
32#undef IPV6STRICT // mingw FTBS fix: missing struct ip_mreq
33#include <windows.h>
34#endif
35
36// For compilers that support precompilation, includes "wx/wx.h".
37#include <wx/wxprec.h>
38
39#ifndef WX_PRECOMP
40#include <wx/wx.h>
41#endif
42
43#include <wx/progdlg.h>
44#include <wx/radiobox.h>
45#include <wx/listbox.h>
46#include <wx/imaglist.h>
47#include <wx/display.h>
48#include <wx/choice.h>
49#include <wx/dirdlg.h>
50#include <wx/clrpicker.h>
51#include <wx/fontdata.h>
52#include <wx/fontdlg.h>
53#include <wx/stdpaths.h>
54#include <wx/tokenzr.h>
55#include <wx/mediactrl.h>
56#include <wx/dir.h>
57#include <wx/odcombo.h>
58#include <wx/statline.h>
59#include <wx/regex.h>
60#include <wx/textwrapper.h>
61
62#include "comm_drv_factory.h"
63#include "comm_util.h"
64#include "conn_params_panel.h"
65
66#if wxCHECK_VERSION(2, 9, \
67 4) /* does this work in 2.8 too.. do we need a test? */
68#include <wx/renderer.h>
69#endif
70#if defined(__WXGTK__) || defined(__WXQT__)
71#include <wx/colordlg.h>
72#endif
73
74#include "config.h"
75#include "config_vars.h"
76
77#include "dychart.h"
78#include "ocpn_frame.h"
79#include "idents.h"
80
81#ifdef ocpnUSE_GL
82#include "glChartCanvas.h"
83extern GLuint g_raster_format;
84#endif
85
86#include "chartdbs.h"
87#include "options.h"
88#include "styles.h"
89#include "multiplexer.h"
90#include "FontMgr.h"
91#include "OCPN_Sound.h"
92#include "SoundFactory.h"
93#include "SystemCmdSound.h"
94
95#include "SystemCmdSound.h"
96
97#include "NMEALogWindow.h"
98#include "wx28compat.h"
99#include "routeman.h"
100#include "chcanv.h"
101#include "MarkInfo.h"
102
103#include "ais.h"
104#include "ais_decoder.h"
105#include "ais_target_data.h"
106
107#include "usb_devices.h"
108#include "navutil.h"
109#include "navutil_base.h"
110
111#include "s52plib.h"
112#include "s52utils.h"
113#include "cm93.h"
114
115#ifdef __linux__
116#include "udev_rule_mgr.h"
117#endif
118
119#ifdef __OCPN__ANDROID__
120#include "androidUTIL.h"
121#endif
122
123#ifdef __OCPN__ANDROID__
124#include <QtWidgets/QScroller>
125#endif
126
127#include "OCPNPlatform.h"
128#include "ConfigMgr.h"
129
130#include "observable_globvar.h"
131#include "ser_ports.h"
132#include "svg_utils.h"
133#include "waypointman_gui.h"
134
135#if !defined(__WXOSX__)
136#define SLIDER_STYLE wxSL_HORIZONTAL | wxSL_AUTOTICKS | wxSL_LABELS
137#else
138#define SLIDER_STYLE wxSL_HORIZONTAL | wxSL_AUTOTICKS
139#endif
140
141wxString GetOCPNKnownLanguage(const wxString lang_canonical,
142 wxString& lang_dir);
143wxString GetOCPNKnownLanguage(const wxString lang_canonical);
144
145extern OCPNPlatform* g_Platform;
146
147extern MyFrame* gFrame;
148extern WayPointman* pWayPointMan;
149extern bool g_bSoftwareGL;
150extern bool g_bShowFPS;
151
152extern bool g_bShowOutlines;
153extern bool g_bShowChartBar;
154extern bool g_bShowDepthUnits;
155extern bool g_bskew_comp;
156extern bool g_bopengl;
157extern bool g_bsmoothpanzoom;
158extern bool g_bShowTrue, g_bShowMag;
159extern double gVar;
160extern int g_chart_zoom_modifier_raster;
161extern int g_chart_zoom_modifier_vector;
162extern int g_NMEAAPBPrecision;
163extern int g_nDepthUnitDisplay;
164extern bool g_bUIexpert;
165
166extern wxString* pInit_Chart_Dir;
167extern Multiplexer* g_pMUX;
168extern bool g_bfilter_cogsog;
169extern int g_COGFilterSec;
170extern int g_SOGFilterSec;
171
172extern PlugInManager* g_pi_manager;
173extern ocpnStyle::StyleManager* g_StyleManager;
174
175extern bool g_bDisplayGrid;
176
177// LIVE ETA OPTION
178extern bool g_bShowLiveETA;
179extern double g_defaultBoatSpeed;
180extern double g_defaultBoatSpeedUserUnit;
181
182// AIS Global configuration
183extern bool g_bCPAMax;
184extern double g_CPAMax_NM;
185extern bool g_bCPAWarn;
186extern double g_CPAWarn_NM;
187extern bool g_bTCPA_Max;
188extern double g_TCPA_Max;
189extern bool g_bMarkLost;
190extern double g_MarkLost_Mins;
191extern bool g_bRemoveLost;
192extern double g_RemoveLost_Mins;
193extern bool g_bShowCOG;
194extern double g_ShowCOG_Mins;
195extern bool g_bSyncCogPredictors;
196extern bool g_bAISShowTracks;
197extern double g_AISShowTracks_Mins;
198extern double g_ShowMoored_Kts;
199extern bool g_bHideMoored;
200extern bool g_bAllowShowScaled;
201extern int g_ShowScaled_Num;
202extern bool g_bAIS_CPA_Alert;
203extern bool g_bAIS_CPA_Alert_Audio;
204extern wxString g_sAIS_Alert_Sound_File;
205extern bool g_bAIS_CPA_Alert_Suppress_Moored;
206extern bool g_bShowAreaNotices;
207extern bool g_bDrawAISSize;
208extern bool g_bDrawAISRealtime;
209extern double g_AIS_RealtPred_Kts;
210extern bool g_bShowAISName;
211extern int g_Show_Target_Name_Scale;
212extern int g_WplAction;
213
214extern int g_iNavAidRadarRingsNumberVisible;
215extern float g_fNavAidRadarRingsStep;
216extern int g_pNavAidRadarRingsStepUnits;
217extern int g_iWaypointRangeRingsNumber;
218extern float g_fWaypointRangeRingsStep;
219extern int g_iWaypointRangeRingsStepUnits;
220extern wxColour g_colourWaypointRangeRingsColour;
221extern bool g_bWayPointPreventDragging;
222extern wxColour g_colourOwnshipRangeRingsColour;
223extern bool g_bShowShipToActive;
224extern int g_shipToActiveStyle;
225extern int g_shipToActiveColor;
226
227extern bool g_own_ship_sog_cog_calc;
228extern int g_own_ship_sog_cog_calc_damp_sec;
229
230extern bool g_bPreserveScaleOnX;
231extern bool g_bPlayShipsBells;
232
233extern wxString g_CmdSoundString;
234
235extern int g_iSoundDeviceIndex;
236extern bool g_bFullscreenToolbar;
237extern bool g_bTransparentToolbar;
238extern bool g_bTransparentToolbarInOpenGLOK;
239
240extern int g_OwnShipIconType;
241extern double g_n_ownship_length_meters;
242extern double g_n_ownship_beam_meters;
243extern double g_n_gps_antenna_offset_y;
244extern double g_n_gps_antenna_offset_x;
245extern int g_n_ownship_min_mm;
246extern double g_n_arrival_circle_radius;
247
248extern bool g_bEnableZoomToCursor;
249extern bool g_bTrackDaily;
250extern int g_track_rotate_time;
251extern int g_track_rotate_time_type;
252extern bool g_bHighliteTracks;
253extern double g_TrackDeltaDistance;
254extern double g_TrackDeltaDistance;
255extern int g_nTrackPrecision;
256extern wxColour g_colourTrackLineColour;
257
258extern int g_iSDMMFormat;
259extern int g_iDistanceFormat;
260extern int g_iSpeedFormat;
261extern int g_iTempFormat;
262
263extern bool g_bAdvanceRouteWaypointOnArrivalOnly;
264
265extern int g_cm93_zoom_factor;
266
267extern int g_COGAvgSec;
268
269extern bool g_bCourseUp;
270extern bool g_bLookAhead;
271
272extern double g_ownship_predictor_minutes;
273extern double g_ownship_HDTpredictor_miles;
274
275extern bool g_bAISRolloverShowClass;
276extern bool g_bAISRolloverShowCOG;
277extern bool g_bAISRolloverShowCPA;
278
279extern bool g_bAIS_ACK_Timeout;
280extern double g_AckTimeout_Mins;
281
282extern bool g_bQuiltEnable;
283extern bool g_bFullScreenQuilt;
284extern bool g_bConfirmObjectDelete;
285extern wxString g_compatOS;
286
287#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
288extern wxLocale* plocale_def_lang;
289#endif
290
291extern double g_mouse_zoom_sensitivity;
292extern int g_mouse_zoom_sensitivity_ui;
293
294extern OcpnSound* g_anchorwatch_sound;
295extern wxString g_anchorwatch_sound_file;
296extern wxString g_DSC_sound_file;
297extern wxString g_SART_sound_file;
298extern wxString g_AIS_sound_file;
299extern bool g_bAIS_GCPA_Alert_Audio;
300extern bool g_bAIS_SART_Alert_Audio;
301extern bool g_bAIS_DSC_Alert_Audio;
302extern bool g_bAnchor_Alert_Audio;
303
304extern bool g_bMagneticAPB;
305
306extern bool g_fog_overzoom;
307extern bool g_oz_vector_scale;
308extern bool g_bShowStatusBar;
309
310extern s52plib* ps52plib;
311
312extern wxString g_locale;
313extern bool g_bportable;
314extern bool g_bdisable_opengl;
315
316extern ChartGroupArray* g_pGroupArray;
317extern ocpnStyle::StyleManager* g_StyleManager;
318
319#ifdef ocpnUSE_GL
320extern ocpnGLOptions g_GLOptions;
321#endif
322
323extern bool g_bGLexpert;
324// Some constants
325#define ID_CHOICE_NMEA wxID_HIGHEST + 1
326
327extern wxArrayString TideCurrentDataSet;
328extern wxString g_TCData_Dir;
329
330extern AisDecoder* g_pAIS;
331
332options* g_pOptions;
333
334extern bool g_bShowMenuBar;
335extern bool g_bShowCompassWin;
336
337extern bool g_btouch;
338extern bool g_bresponsive;
339extern bool g_bAutoHideToolbar;
340extern int g_nAutoHideToolbar;
341extern int g_GUIScaleFactor;
342extern int g_ChartScaleFactor;
343extern float g_ChartScaleFactorExp;
344extern float g_MarkScaleFactorExp;
345extern bool g_bRollover;
346extern int g_ShipScaleFactor;
347extern float g_ShipScaleFactorExp;
348extern int g_ENCSoundingScaleFactor;
349extern int g_ENCTextScaleFactor;
350extern bool g_bShowMuiZoomButtons;
351
352extern double g_config_display_size_mm;
353extern bool g_config_display_size_manual;
354extern bool g_bInlandEcdis;
355extern unsigned int g_canvasConfig;
356extern bool g_useMUI;
357extern wxString g_lastAppliedTemplateGUID;
358extern wxString g_default_wp_icon;
359extern wxString g_default_routepoint_icon;
360extern int g_iWpt_ScaMin;
361extern bool g_bUseWptScaMin;
362bool g_bOverruleScaMin;
363extern int osMajor, osMinor;
364extern bool g_bShowMuiZoomButtons;
365extern MyConfig* pConfig;
366
367#ifdef __OCPN__ANDROID__
368extern int g_Android_SDK_Version;
369extern MigrateAssistantDialog* g_migrateDialog;
370#endif
371
372extern wxString GetShipNameFromFile(int);
373
374WX_DEFINE_ARRAY_PTR(ChartCanvas*, arrayofCanvasPtr);
375extern arrayofCanvasPtr g_canvasArray;
376
377#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
378static int lang_list[] = {
379 wxLANGUAGE_DEFAULT, wxLANGUAGE_ABKHAZIAN, wxLANGUAGE_AFAR,
380 wxLANGUAGE_AFRIKAANS, wxLANGUAGE_ALBANIAN, wxLANGUAGE_AMHARIC,
381 wxLANGUAGE_ARABIC, wxLANGUAGE_ARABIC_ALGERIA, wxLANGUAGE_ARABIC_BAHRAIN,
382 wxLANGUAGE_ARABIC_EGYPT, wxLANGUAGE_ARABIC_IRAQ, wxLANGUAGE_ARABIC_JORDAN,
383 wxLANGUAGE_ARABIC_KUWAIT, wxLANGUAGE_ARABIC_LEBANON,
384 wxLANGUAGE_ARABIC_LIBYA, wxLANGUAGE_ARABIC_MOROCCO, wxLANGUAGE_ARABIC_OMAN,
385 wxLANGUAGE_ARABIC_QATAR, wxLANGUAGE_ARABIC_SAUDI_ARABIA,
386 wxLANGUAGE_ARABIC_SUDAN, wxLANGUAGE_ARABIC_SYRIA, wxLANGUAGE_ARABIC_TUNISIA,
387 // wxLANGUAGE_ARABIC_UAE,
388 wxLANGUAGE_ARABIC_YEMEN, wxLANGUAGE_ARMENIAN, wxLANGUAGE_ASSAMESE,
389 wxLANGUAGE_AYMARA, wxLANGUAGE_AZERI, wxLANGUAGE_AZERI_CYRILLIC,
390 wxLANGUAGE_AZERI_LATIN, wxLANGUAGE_BASHKIR, wxLANGUAGE_BASQUE,
391 wxLANGUAGE_BELARUSIAN, wxLANGUAGE_BENGALI, wxLANGUAGE_BHUTANI,
392 wxLANGUAGE_BIHARI, wxLANGUAGE_BISLAMA, wxLANGUAGE_BRETON,
393 wxLANGUAGE_BULGARIAN, wxLANGUAGE_BURMESE, wxLANGUAGE_CAMBODIAN,
394 wxLANGUAGE_CATALAN,
395 // wxLANGUAGE_CHINESE,
396 // wxLANGUAGE_CHINESE_SIMPLIFIED,
397 // wxLANGUAGE_CHINESE_TRADITIONAL,
398 // wxLANGUAGE_CHINESE_HONGKONG,
399 // wxLANGUAGE_CHINESE_MACAU,
400 // wxLANGUAGE_CHINESE_SINGAPORE,
401 wxLANGUAGE_CHINESE_TAIWAN, wxLANGUAGE_CORSICAN, wxLANGUAGE_CROATIAN,
402 wxLANGUAGE_CZECH, wxLANGUAGE_DANISH, wxLANGUAGE_DUTCH,
403 wxLANGUAGE_DUTCH_BELGIAN, wxLANGUAGE_ENGLISH_UK, wxLANGUAGE_ENGLISH_US,
404 wxLANGUAGE_ENGLISH_AUSTRALIA, wxLANGUAGE_ENGLISH_BELIZE,
405 wxLANGUAGE_ENGLISH_BOTSWANA, wxLANGUAGE_ENGLISH_CANADA,
406 wxLANGUAGE_ENGLISH_CARIBBEAN, wxLANGUAGE_ENGLISH_DENMARK,
407 wxLANGUAGE_ENGLISH_EIRE, wxLANGUAGE_ENGLISH_JAMAICA,
408 wxLANGUAGE_ENGLISH_NEW_ZEALAND, wxLANGUAGE_ENGLISH_PHILIPPINES,
409 wxLANGUAGE_ENGLISH_SOUTH_AFRICA, wxLANGUAGE_ENGLISH_TRINIDAD,
410 wxLANGUAGE_ENGLISH_ZIMBABWE, wxLANGUAGE_ESPERANTO, wxLANGUAGE_ESTONIAN,
411 wxLANGUAGE_FAEROESE, wxLANGUAGE_FARSI, wxLANGUAGE_FIJI, wxLANGUAGE_FINNISH,
412 wxLANGUAGE_FRENCH, wxLANGUAGE_FRENCH_BELGIAN, wxLANGUAGE_FRENCH_CANADIAN,
413 wxLANGUAGE_FRENCH_LUXEMBOURG, wxLANGUAGE_FRENCH_MONACO,
414 wxLANGUAGE_FRENCH_SWISS, wxLANGUAGE_FRISIAN, wxLANGUAGE_GALICIAN,
415 wxLANGUAGE_GEORGIAN, wxLANGUAGE_GERMAN, wxLANGUAGE_GERMAN_AUSTRIAN,
416 wxLANGUAGE_GERMAN_BELGIUM, wxLANGUAGE_GERMAN_LIECHTENSTEIN,
417 wxLANGUAGE_GERMAN_LUXEMBOURG, wxLANGUAGE_GERMAN_SWISS, wxLANGUAGE_GREEK,
418 wxLANGUAGE_GREENLANDIC, wxLANGUAGE_GUARANI, wxLANGUAGE_GUJARATI,
419 wxLANGUAGE_HAUSA, wxLANGUAGE_HEBREW, wxLANGUAGE_HINDI, wxLANGUAGE_HUNGARIAN,
420 wxLANGUAGE_ICELANDIC, wxLANGUAGE_INDONESIAN, wxLANGUAGE_INTERLINGUA,
421 wxLANGUAGE_INTERLINGUE, wxLANGUAGE_INUKTITUT, wxLANGUAGE_INUPIAK,
422 wxLANGUAGE_IRISH, wxLANGUAGE_ITALIAN, wxLANGUAGE_ITALIAN_SWISS,
423 wxLANGUAGE_JAPANESE, wxLANGUAGE_JAVANESE, wxLANGUAGE_KANNADA,
424 wxLANGUAGE_KASHMIRI, wxLANGUAGE_KASHMIRI_INDIA, wxLANGUAGE_KAZAKH,
425 wxLANGUAGE_KERNEWEK, wxLANGUAGE_KINYARWANDA, wxLANGUAGE_KIRGHIZ,
426 wxLANGUAGE_KIRUNDI,
427 // wxLANGUAGE_KONKANI,
428 wxLANGUAGE_KOREAN, wxLANGUAGE_KURDISH, wxLANGUAGE_LAOTHIAN,
429 wxLANGUAGE_LATIN, wxLANGUAGE_LATVIAN, wxLANGUAGE_LINGALA,
430 wxLANGUAGE_LITHUANIAN, wxLANGUAGE_MACEDONIAN, wxLANGUAGE_MALAGASY,
431 wxLANGUAGE_MALAY, wxLANGUAGE_MALAYALAM, wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM,
432 wxLANGUAGE_MALAY_MALAYSIA, wxLANGUAGE_MALTESE,
433 // wxLANGUAGE_MANIPURI,
434 wxLANGUAGE_MAORI, wxLANGUAGE_MARATHI, wxLANGUAGE_MOLDAVIAN,
435 wxLANGUAGE_MONGOLIAN, wxLANGUAGE_NAURU, wxLANGUAGE_NEPALI,
436 wxLANGUAGE_NEPALI_INDIA, wxLANGUAGE_NORWEGIAN_BOKMAL,
437 wxLANGUAGE_NORWEGIAN_NYNORSK, wxLANGUAGE_OCCITAN, wxLANGUAGE_ORIYA,
438 wxLANGUAGE_OROMO, wxLANGUAGE_PASHTO, wxLANGUAGE_POLISH,
439 wxLANGUAGE_PORTUGUESE, wxLANGUAGE_PORTUGUESE_BRAZILIAN, wxLANGUAGE_PUNJABI,
440 wxLANGUAGE_QUECHUA, wxLANGUAGE_RHAETO_ROMANCE, wxLANGUAGE_ROMANIAN,
441 wxLANGUAGE_RUSSIAN, wxLANGUAGE_RUSSIAN_UKRAINE, wxLANGUAGE_SAMOAN,
442 wxLANGUAGE_SANGHO, wxLANGUAGE_SANSKRIT, wxLANGUAGE_SCOTS_GAELIC,
443 wxLANGUAGE_SERBIAN, wxLANGUAGE_SERBIAN_CYRILLIC, wxLANGUAGE_SERBIAN_LATIN,
444 wxLANGUAGE_SERBO_CROATIAN, wxLANGUAGE_SESOTHO, wxLANGUAGE_SETSWANA,
445 wxLANGUAGE_SHONA, wxLANGUAGE_SINDHI, wxLANGUAGE_SINHALESE,
446 wxLANGUAGE_SISWATI, wxLANGUAGE_SLOVAK, wxLANGUAGE_SLOVENIAN,
447 wxLANGUAGE_SOMALI, wxLANGUAGE_SPANISH, wxLANGUAGE_SPANISH_ARGENTINA,
448 wxLANGUAGE_SPANISH_BOLIVIA, wxLANGUAGE_SPANISH_CHILE,
449 wxLANGUAGE_SPANISH_COLOMBIA, wxLANGUAGE_SPANISH_COSTA_RICA,
450 wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC, wxLANGUAGE_SPANISH_ECUADOR,
451 wxLANGUAGE_SPANISH_EL_SALVADOR, wxLANGUAGE_SPANISH_GUATEMALA,
452 wxLANGUAGE_SPANISH_HONDURAS, wxLANGUAGE_SPANISH_MEXICAN,
453 // wxLANGUAGE_SPANISH_MODERN,
454 wxLANGUAGE_SPANISH_NICARAGUA, wxLANGUAGE_SPANISH_PANAMA,
455 wxLANGUAGE_SPANISH_PARAGUAY, wxLANGUAGE_SPANISH_PERU,
456 wxLANGUAGE_SPANISH_PUERTO_RICO, wxLANGUAGE_SPANISH_URUGUAY,
457 wxLANGUAGE_SPANISH_US, wxLANGUAGE_SPANISH_VENEZUELA, wxLANGUAGE_SUNDANESE,
458 wxLANGUAGE_SWAHILI, wxLANGUAGE_SWEDISH, wxLANGUAGE_SWEDISH_FINLAND,
459 wxLANGUAGE_TAGALOG, wxLANGUAGE_TAJIK, wxLANGUAGE_TAMIL, wxLANGUAGE_TATAR,
460 wxLANGUAGE_TELUGU, wxLANGUAGE_THAI, wxLANGUAGE_TIBETAN, wxLANGUAGE_TIGRINYA,
461 wxLANGUAGE_TONGA, wxLANGUAGE_TSONGA, wxLANGUAGE_TURKISH, wxLANGUAGE_TURKMEN,
462 wxLANGUAGE_TWI, wxLANGUAGE_UIGHUR, wxLANGUAGE_UKRAINIAN, wxLANGUAGE_URDU,
463 wxLANGUAGE_URDU_INDIA, wxLANGUAGE_URDU_PAKISTAN, wxLANGUAGE_UZBEK,
464 wxLANGUAGE_UZBEK_CYRILLIC, wxLANGUAGE_UZBEK_LATIN, wxLANGUAGE_VIETNAMESE,
465 wxLANGUAGE_VOLAPUK, wxLANGUAGE_WELSH, wxLANGUAGE_WOLOF, wxLANGUAGE_XHOSA,
466 wxLANGUAGE_YIDDISH, wxLANGUAGE_YORUBA, wxLANGUAGE_ZHUANG, wxLANGUAGE_ZULU};
467#endif
468
469#ifdef __OCPN__ANDROID__
470void prepareSlider(wxSlider* slider) {
471 slider->GetHandle()->setStyleSheet(
472 prepareAndroidSliderStyleSheet(slider->GetSize().x));
473 slider->GetHandle()->setAttribute(Qt::WA_AcceptTouchEvents);
474 slider->GetHandle()->grabGesture(Qt::PanGesture);
475 slider->GetHandle()->grabGesture(Qt::SwipeGesture);
476}
477#endif
478
479// sort callback for Connections list Sort by priority.
480#if wxCHECK_VERSION(2, 9, 0)
481int wxCALLBACK SortConnectionOnPriority(wxIntPtr item1, wxIntPtr item2,
482 wxIntPtr list)
483#else
484int wxCALLBACK SortConnectionOnPriority(long item1, long item2, long list)
485#endif
486{
487 wxListCtrl* lc = reinterpret_cast<wxListCtrl*>(list);
488
489 wxListItem it1, it2;
490 it1.SetId(lc->FindItem(-1, item1));
491 it1.SetColumn(3);
492 it1.SetMask(it1.GetMask() | wxLIST_MASK_TEXT);
493
494 it2.SetId(lc->FindItem(-1, item2));
495 it2.SetColumn(3);
496 it2.SetMask(it2.GetMask() | wxLIST_MASK_TEXT);
497
498 lc->GetItem(it1);
499 lc->GetItem(it2);
500
501#ifdef __WXOSX__
502 return it1.GetText().CmpNoCase(it2.GetText());
503#else
504 return it2.GetText().CmpNoCase(it1.GetText());
505#endif
506}
507
509
510class ChartDirPanelHardBreakWrapper : public wxTextWrapper {
511public:
512 ChartDirPanelHardBreakWrapper(wxWindow* win, const wxString& text,
513 int widthMax) {
514 m_lineCount = 0;
515
516 // Replace all spaces in the string with a token character '^'
517 wxString textMod = text;
518 textMod.Replace(" ", "^");
519
520 // Replace all path separators with spaces
521 wxString sep = wxFileName::GetPathSeparator();
522 textMod.Replace(sep, " ");
523
524 Wrap(win, textMod, widthMax);
525
526 // walk the output array, repairing the substitutions
527 for (size_t i = 0; i < m_array.GetCount(); i++) {
528 wxString a = m_array[i];
529 a.Replace(" ", sep);
530 if (m_array.GetCount() > 1) {
531 if (i < m_array.GetCount() - 1) a += sep;
532 }
533 a.Replace("^", " ");
534 m_array[i] = a;
535 }
536 }
537 wxString const& GetWrapped() const { return m_wrapped; }
538 int const GetLineCount() const { return m_lineCount; }
539 wxArrayString GetLineArray() { return m_array; }
540
541protected:
542 virtual void OnOutputLine(const wxString& line) {
543 m_wrapped += line;
544 m_array.Add(line);
545 }
546 virtual void OnNewLine() {
547 m_wrapped += '\n';
548 m_lineCount++;
549 }
550
551private:
552 wxString m_wrapped;
553 int m_lineCount;
554 wxArrayString m_array;
555};
556
557class OCPNChartDirPanel : public wxPanel {
558public:
559 OCPNChartDirPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos,
560 const wxSize& size, ChartDirInfo& cdi);
562
563 void DoChartSelected();
564 void SetSelected(bool selected);
565 void OnPaint(wxPaintEvent& event);
566 // void OnEraseBackground( wxEraseEvent &event );
567 void OnSize(wxSizeEvent& event);
568 ChartDirInfo GetCDI() { return m_cdi; }
569 int GetUnselectedHeight() { return m_unselectedHeight; }
570 int GetRefHeight() { return m_refHeight; }
571 bool IsSelected() { return m_bSelected; }
572 void OnClickDown(wxMouseEvent& event);
573 void OnClickUp(wxMouseEvent& event);
574
575private:
576 // shopPanel *m_pContainer;
577 bool m_bSelected;
578 wxColour m_boxColour;
579 int m_unselectedHeight;
580 wxString m_pChartDir;
581 int m_refHeight;
582 ChartDirInfo m_cdi;
583
584 DECLARE_EVENT_TABLE()
585};
586
587BEGIN_EVENT_TABLE(OCPNChartDirPanel, wxPanel)
588EVT_PAINT(OCPNChartDirPanel::OnPaint)
589// EVT_ERASE_BACKGROUND( OCPNChartDirPanel::OnEraseBackground)
590EVT_SIZE(OCPNChartDirPanel::OnSize)
591END_EVENT_TABLE()
592
593OCPNChartDirPanel::OCPNChartDirPanel(wxWindow* parent, wxWindowID id,
594 const wxPoint& pos, const wxSize& size,
595 ChartDirInfo& cdi)
596 : wxPanel(parent, id, pos, size, wxBORDER_NONE) {
597 m_pChartDir = cdi.fullpath;
598
599 // On Android, shorten the displayed path name by removing well-known prefix
600 if (cdi.fullpath.StartsWith(
601 "/storage/emulated/0/Android/data/org.opencpn.opencpn/files"))
602 m_pChartDir = "..." + cdi.fullpath.Mid(58);
603
604 m_cdi = cdi;
605 m_bSelected = false;
606
607 m_refHeight = GetCharHeight();
608
609 m_unselectedHeight = 2 * m_refHeight;
610
611 // #ifdef __OCPN__ANDROID__
612 // m_unselectedHeight = 2 * m_refHeight;
613 // #endif
614
615 SetMinSize(wxSize(-1, m_unselectedHeight));
616
617 Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(OCPNChartDirPanel::OnClickDown),
618 NULL, this);
619#ifdef __OCPN__ANDROID__
620 Connect(wxEVT_LEFT_UP, wxMouseEventHandler(OCPNChartDirPanel::OnClickUp),
621 NULL, this);
622#endif
623}
624
625OCPNChartDirPanel::~OCPNChartDirPanel() {}
626
627static wxStopWatch swclick;
628#ifdef __OCPN__ANDROID__
629static int downx, downy;
630#endif
631
632void OCPNChartDirPanel::OnClickDown(wxMouseEvent& event) {
633#ifdef __OCPN__ANDROID__
634 swclick.Start();
635 event.GetPosition(&downx, &downy);
636#else
637 DoChartSelected();
638#endif
639}
640
641void OCPNChartDirPanel::OnClickUp(wxMouseEvent& event) {
642#ifdef __OCPN__ANDROID__
643 qDebug() << swclick.Time();
644 if (swclick.Time() < 200) {
645 int upx, upy;
646 event.GetPosition(&upx, &upy);
647 if ((fabs(upx - downx) < GetCharWidth()) &&
648 (fabs(upy - downy) < GetCharWidth())) {
649 DoChartSelected();
650 }
651 }
652 swclick.Start();
653#endif
654}
655
656void OCPNChartDirPanel::DoChartSelected() {
657 if (!m_bSelected) {
658 SetSelected(true);
659 // m_pContainer->SelectChart( this );
660 } else {
661 SetSelected(false);
662 // m_pContainer->SelectChart( (OCPNChartDirPanel*)NULL );
663 }
664}
665
666void OCPNChartDirPanel::SetSelected(bool selected) {
667 m_bSelected = selected;
668 wxColour colour;
669
670 if (selected) {
671 GetGlobalColor(_T("UIBCK"), &colour);
672 m_boxColour = colour;
673 } else {
674 GetGlobalColor(_T("DILG0"), &colour);
675 m_boxColour = colour;
676 }
677
678 Refresh(true);
679
680 g_pOptions->SetDirActionButtons();
681}
682
683// void OCPNChartDirPanel::OnEraseBackground( wxEraseEvent &event )
684// {
685// }
686
687void OCPNChartDirPanel::OnSize(wxSizeEvent& event) {
688 if (m_pChartDir.Length()) {
689 int x, y;
690 GetClientSize(&x, &y);
691
692 ChartDirPanelHardBreakWrapper wrapper(this, m_pChartDir, x * 9 / 10);
693 wxArrayString nameWrapped = wrapper.GetLineArray();
694
695 SetMinSize(wxSize(-1, (nameWrapped.GetCount() + 1) * m_refHeight));
696 }
697
698 event.Skip();
699}
700
701void OCPNChartDirPanel::OnPaint(wxPaintEvent& event) {
702 int width, height;
703 GetSize(&width, &height);
704 wxPaintDC dc(this);
705
706 dc.SetPen(*wxTRANSPARENT_PEN);
707 dc.SetBrush(wxBrush(GetBackgroundColour()));
708 dc.DrawRectangle(GetVirtualSize());
709
710 wxColour c;
711
712 wxString nameString = m_pChartDir;
713 ChartDirPanelHardBreakWrapper wrapper(this, nameString, width * 9 / 10);
714 wxArrayString nameWrapped = wrapper.GetLineArray();
715
716 if (height < (int)(nameWrapped.GetCount() + 1) * m_refHeight) {
717 SetMinSize(wxSize(-1, (nameWrapped.GetCount() + 1) * m_refHeight));
718 GetParent()->GetSizer()->Layout();
719 }
720
721 if (m_bSelected) {
722 dc.SetBrush(wxBrush(m_boxColour));
723
724 GetGlobalColor(_T ( "UITX1" ), &c);
725 dc.SetPen(wxPen(wxColor(0xCE, 0xD5, 0xD6), 3));
726
727 dc.DrawRoundedRectangle(0, 0, width - 1, height - 1, height / 10);
728
729 int offset = height / 10;
730 int text_x = offset * 2;
731
732 wxFont* dFont = GetOCPNScaledFont_PlugIn(_("Dialog"));
733 dc.SetFont(*dFont);
734
735 dc.SetTextForeground(wxColour(64, 64, 64));
736
737 int yd = height * 20 / 100;
738 for (size_t i = 0; i < nameWrapped.GetCount(); i++) {
739 if (i == 0)
740 dc.DrawText(nameWrapped[i], text_x, yd);
741 else
742 dc.DrawText(nameWrapped[i], text_x + GetCharWidth(), yd);
743 yd += GetCharHeight();
744 }
745 } // selected
746 else {
747 dc.SetBrush(wxBrush(m_boxColour));
748
749 GetGlobalColor(_T ( "GREY1" ), &c);
750 dc.SetPen(wxPen(c, 1));
751
752 int offset = height / 10;
753 dc.DrawRoundedRectangle(offset, offset, width - (2 * offset),
754 height - (2 * offset), height / 10);
755
756 int text_x = offset * 2;
757
758 wxFont* dFont = GetOCPNScaledFont_PlugIn(_("Dialog"));
759 dc.SetFont(*dFont);
760
761 dc.SetTextForeground(wxColour(64, 64, 64));
762
763 int yd = height * 20 / 100;
764 for (size_t i = 0; i < nameWrapped.GetCount(); i++) {
765 if (i == 0)
766 dc.DrawText(nameWrapped[i], text_x, yd);
767 else
768 dc.DrawText(nameWrapped[i], text_x + GetCharWidth(), yd);
769 yd += GetCharHeight();
770 }
771
772 } // not selected
773}
774
776
777
778static bool LoadAllPlugIns(bool load_enabled) {
779 g_Platform->ShowBusySpinner();
780 bool b = PluginLoader::getInstance()->LoadAllPlugIns(load_enabled);
781 g_Platform->HideBusySpinner();
782 return b;
783}
784
785WX_DECLARE_LIST(wxCheckBox, CBList);
786
787class OCPNCheckedListCtrl : public wxScrolledWindow {
788public:
790
791 OCPNCheckedListCtrl(wxWindow* parent, wxWindowID id = -1,
792 const wxPoint& pt = wxDefaultPosition,
793 const wxSize& sz = wxDefaultSize,
794 long style = wxHSCROLL | wxVSCROLL,
795 const wxString& name = _T("scrolledWindow")) {
796 Create(parent, id, pt, sz, style, name);
797 }
798
799 bool Create(wxWindow* parent, wxWindowID id = -1,
800 const wxPoint& pt = wxDefaultPosition,
801 const wxSize& sz = wxDefaultSize,
802 long style = wxHSCROLL | wxVSCROLL,
803 const wxString& name = _T("scrolledWindow"));
804
805 virtual ~OCPNCheckedListCtrl() {}
806
807 unsigned int Append(wxString& label, bool benable = true);
808 unsigned int GetCount() { return m_list.GetCount(); }
809
810 void Clear();
811 void Check(int index, bool val);
812 bool IsChecked(int index);
813
814private:
815 wxBoxSizer* m_sizer;
816
817 CBList m_list;
818};
819
820#include <wx/listimpl.cpp>
821WX_DEFINE_LIST(CBList);
822
823bool OCPNCheckedListCtrl::Create(wxWindow* parent, wxWindowID id,
824 const wxPoint& pt, const wxSize& sz,
825 long style, const wxString& name) {
826 if (!wxScrolledWindow::Create(parent, id, pt, sz, style, name)) return FALSE;
827
828#ifdef __OCPN__ANDROID__
829 GetHandle()->setObjectName("OCPNCheckedListCtrl");
830 GetHandle()->setStyleSheet(getAdjustedDialogStyleSheet());
831#endif
832
833 SetScrollRate(0, 2);
834 m_sizer = new wxBoxSizer(wxVERTICAL);
835 SetSizer(m_sizer);
836
837 return TRUE;
838}
839
840unsigned int OCPNCheckedListCtrl::Append(wxString& label, bool benable) {
841 wxCheckBox* cb = new wxCheckBox(this, wxID_ANY, label);
842 cb->Enable(benable);
843 cb->SetValue(!benable);
844 m_sizer->Add(cb);
845 m_sizer->Layout();
846
847 m_list.Append(cb);
848
849 return m_list.GetCount() - 1;
850}
851
852void OCPNCheckedListCtrl::Check(int index, bool val) {
853 CBList::Node* node = m_list.Item(index);
854 wxCheckBox* cb = node->GetData();
855
856 if (cb) cb->SetValue(val);
857}
858
859bool OCPNCheckedListCtrl::IsChecked(int index) {
860 CBList::Node* node = m_list.Item(index);
861 wxCheckBox* cb = node->GetData();
862
863 if (cb)
864 return cb->GetValue();
865 else
866 return false;
867}
868
869void OCPNCheckedListCtrl::Clear() {
870 for (unsigned int i = 0; i < m_list.GetCount(); i++) {
871 wxCheckBox* cb = m_list[i];
872 delete cb;
873 }
874 m_list.Clear();
875 Scroll(0, 0);
876}
877
878// Helper for conditional file name separator
879void appendOSDirSlash(wxString* pString);
880
881extern ArrayOfMmsiProperties g_MMSI_Props_Array;
882
886
887BEGIN_EVENT_TABLE(ConfigCreateDialog, wxDialog)
888EVT_BUTTON(ID_CONFIGEDIT_CANCEL, ConfigCreateDialog::OnConfigEditCancelClick)
889EVT_BUTTON(ID_CONFIGEDIT_OK, ConfigCreateDialog::OnConfigEditOKClick)
890END_EVENT_TABLE()
891
892ConfigCreateDialog::ConfigCreateDialog(wxWindow* parent, wxWindowID id,
893 const wxString& caption,
894 const wxPoint& pos, const wxSize& size,
895 long style)
896 : wxDialog(parent, id, caption, pos, size,
897 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
898 CreateControls();
899 GetSizer()->SetSizeHints(this);
900 Centre();
901}
902
903ConfigCreateDialog::~ConfigCreateDialog(void) {}
904
905void ConfigCreateDialog::CreateControls(void) {
906 wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
907 SetSizer(mainSizer);
908
909 mainSizer->Add(new wxStaticText(this, wxID_STATIC, _("Title")), 0,
910 wxALIGN_LEFT | wxLEFT | wxRIGHT | wxTOP, 5);
911
912 m_TitleCtl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
913 wxSize(40 * GetCharHeight(), -1), 0);
914 mainSizer->Add(m_TitleCtl, 0,
915 wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
916
917 mainSizer->AddSpacer(2 * GetCharHeight());
918
919 mainSizer->Add(new wxStaticText(this, wxID_STATIC, _("Description")), 0,
920 wxALIGN_LEFT | wxLEFT | wxRIGHT | wxTOP, 5);
921
922 m_DescriptionCtl =
923 new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
924 wxSize(-1, 6 * GetCharHeight()), wxTE_MULTILINE);
925 mainSizer->Add(m_DescriptionCtl, 0,
926 wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
927
928 mainSizer->AddSpacer(2 * GetCharHeight());
929
930 mainSizer->Add(
931 new wxStaticText(
932 this, wxID_STATIC,
933 _("Create a private configuration template based on current settings.\n\
934This template will be saved, and may be selected for further use at any time.\n\
935 ")),
936 0, wxALIGN_LEFT | wxLEFT | wxRIGHT | wxTOP, 5);
937
938 mainSizer->AddSpacer(2 * GetCharHeight());
939
940 wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
941 mainSizer->Add(btnSizer, 0, wxALIGN_RIGHT | wxALL, 5);
942
943 m_CancelButton = new wxButton(this, ID_CONFIGEDIT_CANCEL, _("Cancel"));
944 btnSizer->Add(m_CancelButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
945
946 m_OKButton = new wxButton(this, ID_CONFIGEDIT_OK, _("OK"));
947 btnSizer->Add(m_OKButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
948 m_OKButton->SetDefault();
949}
950
951void ConfigCreateDialog::OnConfigEditCancelClick(wxCommandEvent& event) {
952 EndModal(wxID_CANCEL);
953}
954
955void ConfigCreateDialog::OnConfigEditOKClick(wxCommandEvent& event) {
956 const wxString& title = m_TitleCtl->GetValue();
957 const wxString& desc = m_DescriptionCtl->GetValue();
958 m_createdTemplateGUID =
959 ConfigMgr::Get().CreateNamedConfig(title, desc, _T(""));
960 EndModal(wxID_OK);
961}
962
966
967BEGIN_EVENT_TABLE(MMSIEditDialog, wxDialog)
968EVT_BUTTON(ID_MMSIEDIT_CANCEL, MMSIEditDialog::OnMMSIEditCancelClick)
969EVT_BUTTON(ID_MMSIEDIT_OK, MMSIEditDialog::OnMMSIEditOKClick)
970END_EVENT_TABLE()
971
973 wxWindowID id, const wxString& caption,
974 const wxPoint& pos, const wxSize& size,
975 long style)
976 : wxDialog(parent, id, caption, pos, size,
977 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
978 m_props(props) {
979 CreateControls();
980 GetSizer()->SetSizeHints(this);
981 Centre();
982}
983
984MMSIEditDialog::~MMSIEditDialog(void) { delete m_MMSICtl; }
985
986void MMSIEditDialog::CreateControls(void) {
987 wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
988 SetSizer(mainSizer);
989
990 wxStaticBox* mmsiBox =
991 new wxStaticBox(this, wxID_ANY, _("MMSI Extended Properties"));
992
993 wxStaticBoxSizer* mmsiSizer = new wxStaticBoxSizer(mmsiBox, wxVERTICAL);
994 mainSizer->Add(mmsiSizer, 0, wxEXPAND | wxALL, 5);
995
996 mmsiSizer->Add(new wxStaticText(this, wxID_STATIC, _("MMSI")), 0,
997 wxALIGN_LEFT | wxLEFT | wxRIGHT | wxTOP, 5);
998
999 m_MMSICtl = new wxTextCtrl(this, ID_MMSI_CTL, wxEmptyString,
1000 wxDefaultPosition, wxSize(180, -1), 0);
1001 mmsiSizer->Add(m_MMSICtl, 0,
1002 wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
1003
1004 wxStaticBoxSizer* trackSizer = new wxStaticBoxSizer(
1005 new wxStaticBox(this, wxID_ANY, _("Tracking")), wxVERTICAL);
1006
1007 wxGridSizer* gridSizer = new wxGridSizer(0, 3, 0, 0);
1008
1009 m_rbTypeTrackDefault =
1010 new wxRadioButton(this, wxID_ANY, _("Default tracking"),
1011 wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
1012 m_rbTypeTrackDefault->SetValue(TRUE);
1013 gridSizer->Add(m_rbTypeTrackDefault, 0, wxALL, 5);
1014
1015 m_rbTypeTrackAlways = new wxRadioButton(this, wxID_ANY, _("Always track"));
1016 gridSizer->Add(m_rbTypeTrackAlways, 0, wxALL, 5);
1017
1018 m_rbTypeTrackNever = new wxRadioButton(this, wxID_ANY, _(" Never track"));
1019 gridSizer->Add(m_rbTypeTrackNever, 0, wxALL, 5);
1020
1021 m_cbTrackPersist = new wxCheckBox(this, wxID_ANY, _("Persistent"));
1022 gridSizer->Add(m_cbTrackPersist, 0, wxALL, 5);
1023
1024 trackSizer->Add(gridSizer, 0, wxEXPAND, 0);
1025 mmsiSizer->Add(trackSizer, 0, wxEXPAND, 0);
1026
1027 m_IgnoreButton = new wxCheckBox(this, wxID_ANY, _("Ignore this MMSI"));
1028 mmsiSizer->Add(m_IgnoreButton, 0, wxEXPAND, 5);
1029
1030 m_MOBButton = new wxCheckBox(this, wxID_ANY,
1031 _("Handle this MMSI as SART/PLB(AIS) MOB."));
1032 mmsiSizer->Add(m_MOBButton, 0, wxEXPAND, 5);
1033
1034 m_VDMButton =
1035 new wxCheckBox(this, wxID_ANY, _("Convert AIVDM to AIVDO for this MMSI"));
1036 mmsiSizer->Add(m_VDMButton, 0, wxEXPAND, 5);
1037
1038 m_FollowerButton = new wxCheckBox(
1039 this, wxID_ANY, _("This MMSI is my Follower - No CPA Alert"));
1040 mmsiSizer->Add(m_FollowerButton, 0, wxEXPAND, 5);
1041
1042 wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
1043 mainSizer->Add(btnSizer, 0, wxALIGN_RIGHT | wxALL, 5);
1044
1045 m_CancelButton = new wxButton(this, ID_MMSIEDIT_CANCEL, _("Cancel"));
1046 btnSizer->Add(m_CancelButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1047
1048 m_OKButton = new wxButton(this, ID_MMSIEDIT_OK, _("OK"));
1049 btnSizer->Add(m_OKButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1050 m_OKButton->SetDefault();
1051
1052 // Set initial values...
1053 wxString sMMSI;
1054 if (m_props->MMSI > 0)
1055 sMMSI.Printf(_T("%d"), m_props->MMSI);
1056 else
1057 sMMSI = _T("");
1058 m_MMSICtl->AppendText(sMMSI);
1059
1060 switch (m_props->TrackType) {
1061 case TRACKTYPE_ALWAYS:
1062 m_rbTypeTrackAlways->SetValue(TRUE);
1063 break;
1064 case TRACKTYPE_NEVER:
1065 m_rbTypeTrackNever->SetValue(TRUE);
1066 break;
1067 default:
1068 break;
1069 }
1070
1071 m_cbTrackPersist->SetValue(m_props->m_bPersistentTrack);
1072 m_IgnoreButton->SetValue(m_props->m_bignore);
1073 m_MOBButton->SetValue(m_props->m_bMOB);
1074 m_VDMButton->SetValue(m_props->m_bVDM);
1075 m_FollowerButton->SetValue(m_props->m_bFollower);
1076
1077 SetColorScheme(GLOBAL_COLOR_SCHEME_RGB);
1078}
1079
1080void MMSIEditDialog::SetColorScheme(ColorScheme cs) { DimeControl(this); }
1081
1082void MMSIEditDialog::OnMMSIEditCancelClick(wxCommandEvent& event) {
1083 EndModal(wxID_CANCEL);
1084}
1085
1086void MMSIEditDialog::Persist() {
1087 if (m_props) {
1088 if (m_rbTypeTrackDefault->GetValue())
1089 m_props->TrackType = TRACKTYPE_DEFAULT;
1090 else if (m_rbTypeTrackAlways->GetValue())
1091 m_props->TrackType = TRACKTYPE_ALWAYS;
1092 else
1093 m_props->TrackType = TRACKTYPE_NEVER;
1094
1095 m_props->m_bignore = m_IgnoreButton->GetValue();
1096 m_props->m_bMOB = m_MOBButton->GetValue();
1097 m_props->m_bVDM = m_VDMButton->GetValue();
1098 m_props->m_bFollower = m_FollowerButton->GetValue();
1099 m_props->m_bPersistentTrack = m_cbTrackPersist->GetValue();
1100 if (m_props->m_ShipName == wxEmptyString) {
1101 auto proptarget = g_pAIS->Get_Target_Data_From_MMSI(m_props->MMSI);
1102 if (proptarget) {
1103 wxString s = proptarget->GetFullName();
1104 m_props->m_ShipName = s;
1105 } else {
1106 wxString GetShipNameFromFile(int);
1107 m_props->m_ShipName = GetShipNameFromFile(m_props->MMSI);
1108 }
1109 }
1110 }
1111}
1112
1113void MMSIEditDialog::OnMMSIEditOKClick(wxCommandEvent& event) {
1114 // Update the MmsiProperties by the passed pointer
1115 if (m_props) {
1116 long nmmsi;
1117 m_MMSICtl->GetValue().ToLong(&nmmsi);
1118 m_props->MMSI = nmmsi;
1119 Persist();
1120
1121 if (m_MMSICtl->GetValue().Length() != 9) {
1123 this,
1124 _("An MMSI Id is generally a number of nine digits.\nPlease check "
1125 "your entries and cancel if necessary."),
1126 _("OpenCPN Info"), wxOK | wxCANCEL);
1127
1128 dlg->ShowWindowModalThenDo([this, dlg](int retcode) {
1129 if (retcode == wxID_OK) {
1130 Persist();
1131 }
1132 EndModal(retcode);
1133 });
1134 } else {
1135 EndModal(wxID_OK);
1136 }
1137 }
1138}
1139
1140void MMSIEditDialog::OnCtlUpdated(wxCommandEvent& event) {}
1141
1142BEGIN_EVENT_TABLE(MMSIListCtrl, wxListCtrl)
1143EVT_LIST_ITEM_SELECTED(ID_MMSI_PROPS_LIST, MMSIListCtrl::OnListItemClick)
1144EVT_LIST_ITEM_ACTIVATED(ID_MMSI_PROPS_LIST, MMSIListCtrl::OnListItemActivated)
1145EVT_LIST_ITEM_RIGHT_CLICK(ID_MMSI_PROPS_LIST,
1146 MMSIListCtrl::OnListItemRightClick)
1147EVT_MENU(ID_DEF_MENU_MMSI_EDIT, MMSIListCtrl::PopupMenuHandler)
1148EVT_MENU(ID_DEF_MENU_MMSI_DELETE, MMSIListCtrl::PopupMenuHandler)
1149END_EVENT_TABLE()
1150
1151MMSIListCtrl::MMSIListCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos,
1152 const wxSize& size, long style)
1153 : wxListCtrl(parent, id, pos, size, style) {
1154 m_parent = parent;
1155}
1156
1157MMSIListCtrl::~MMSIListCtrl(void) {}
1158
1159wxString MMSIListCtrl::OnGetItemText(long item, long column) const {
1160 wxString ret;
1161 MmsiProperties* props = g_MMSI_Props_Array[item];
1162
1163 if (!props) return ret;
1164 switch (column) {
1165 case mlMMSI:
1166 if (props->MMSI > 0) ret = wxString::Format(_T( "%d" ), props->MMSI);
1167 break;
1168 case mlTrackMode:
1169 switch (props->TrackType) {
1170 case TRACKTYPE_DEFAULT:
1171 ret = _("Default");
1172 break;
1173 case TRACKTYPE_ALWAYS:
1174 ret = _("Always");
1175 break;
1176 case TRACKTYPE_NEVER:
1177 ret = _("Never");
1178 break;
1179 default:
1180 ret = _T( "???" );
1181 }
1182 if (props->m_bPersistentTrack)
1183 ret.Append(_T( ", " )).Append(_("Persistent"));
1184 break;
1185 case mlIgnore:
1186 if (props->m_bignore) ret = _T( "X" );
1187 break;
1188 case mlMOB:
1189 if (props->m_bMOB) ret = _T( "X" );
1190 break;
1191 case mlVDM:
1192 if (props->m_bVDM) ret = _T( "X" );
1193 break;
1194 case mlFollower:
1195 if (props->m_bFollower) ret = _T("X");
1196 break;
1197 case mlShipName:
1198 ret = props->m_ShipName;
1199 break;
1200 default:
1201 ret = _T( "??" );
1202 break;
1203 }
1204 return ret;
1205}
1206
1207void MMSIListCtrl::OnListItemClick(wxListEvent& event) {}
1208
1209void MMSIListCtrl::OnListItemActivated(wxListEvent& event) {
1210 MmsiProperties* props = g_MMSI_Props_Array.Item(event.GetIndex());
1211 MmsiProperties* props_new = new MmsiProperties(*props);
1212
1213 MMSIEditDialog* pd =
1214 new MMSIEditDialog(props_new, m_parent, -1, _("Edit MMSI Properties"),
1215 wxDefaultPosition, wxSize(200, 200));
1216
1217 if (pd->ShowModal() == wxID_OK) {
1218 g_MMSI_Props_Array.RemoveAt(event.GetIndex());
1219 delete props;
1220 g_MMSI_Props_Array.Insert(props_new, event.GetIndex());
1221 } else
1222 delete props_new;
1223
1224 pd->Destroy();
1225}
1226
1227void MMSIListCtrl::OnListItemRightClick(wxListEvent& event) {
1228 m_context_item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1229 if (m_context_item == wxNOT_FOUND) return;
1230 wxMenu* menu = new wxMenu(_("MMSI Properties"));
1231 wxMenuItem* item_edit =
1232 new wxMenuItem(menu, ID_DEF_MENU_MMSI_EDIT, _("Edit") + _T("..."));
1233 menu->Append(item_edit);
1234 wxMenuItem* item_delete =
1235 new wxMenuItem(menu, ID_DEF_MENU_MMSI_DELETE, _("Delete"));
1236 menu->Append(item_delete);
1237
1238#ifdef __WXMSW__
1239 wxFont* qFont = GetOCPNScaledFont(_("Menu"));
1240 item_edit->SetFont(*qFont);
1241 item_delete->SetFont(*qFont);
1242#endif
1243
1244 wxPoint p = ScreenToClient(wxGetMousePosition());
1245 PopupMenu(menu, p.x, p.y);
1246
1247 SetItemCount(g_MMSI_Props_Array.GetCount());
1248 Refresh(TRUE);
1249}
1250
1251void MMSIListCtrl::PopupMenuHandler(wxCommandEvent& event) {
1252 int context_item = m_context_item;
1253 MmsiProperties* props = g_MMSI_Props_Array[context_item];
1254
1255 if (!props) return;
1256
1257 switch (event.GetId()) {
1258 case ID_DEF_MENU_MMSI_EDIT: {
1259 MmsiProperties* props_new = new MmsiProperties(*props);
1260 MMSIEditDialog* pd =
1261 new MMSIEditDialog(props_new, m_parent, -1, _("Edit MMSI Properties"),
1262 wxDefaultPosition, wxSize(200, 200));
1263
1264 if (pd->ShowModal() == wxID_OK) {
1265 g_MMSI_Props_Array.RemoveAt(context_item);
1266 delete props;
1267 props_new->m_ShipName = GetShipNameFromFile(props_new->MMSI);
1268 g_MMSI_Props_Array.Insert(props_new, context_item);
1269 } else {
1270 delete props_new;
1271 }
1272 pd->Destroy();
1273 break;
1274 }
1275 case ID_DEF_MENU_MMSI_DELETE:
1276 g_MMSI_Props_Array.RemoveAt(context_item);
1277 delete props;
1278 break;
1279 }
1280}
1281
1282MMSI_Props_Panel::MMSI_Props_Panel(wxWindow* parent)
1283 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
1284 wxBORDER_NONE) {
1285 m_pparent = parent;
1286
1287 wxFont* qFont = GetOCPNScaledFont(_("Dialog"));
1288 SetFont(*qFont);
1289
1290 wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
1291 SetSizer(topSizer);
1292
1293 wxString MMSI_props_column_spec = _T("120;120;100;100;100;100;100;100");
1294 // Parse the global column width string as read from config file
1295 wxStringTokenizer tkz(MMSI_props_column_spec, _T(";"));
1296 wxString s_width = tkz.GetNextToken();
1297 int width;
1298 long lwidth;
1299
1300 m_pListCtrlMMSI = new MMSIListCtrl(
1301 this, ID_MMSI_PROPS_LIST, wxDefaultPosition, wxSize(-1, -1),
1302 wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
1303 wxBORDER_SUNKEN | wxLC_VIRTUAL);
1304 // wxImageList* imglist = new wxImageList(16, 16, TRUE, 2);
1305
1306 ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();
1307 // imglist->Add(style->GetIcon(_T( "sort_asc" )));
1308 // imglist->Add(style->GetIcon(_T( "sort_desc" )));
1309
1310 // m_pListCtrlMMSI->AssignImageList( imglist, wxIMAGE_LIST_SMALL );
1311 int dx = GetCharWidth();
1312
1313 width = dx * 5;
1314 if (s_width.ToLong(&lwidth)) {
1315 width = wxMax(dx * 2, lwidth);
1316 width = wxMin(width, dx * 13);
1317 }
1318 m_pListCtrlMMSI->InsertColumn(tlMMSI, _("MMSI"), wxLIST_FORMAT_LEFT, width);
1319
1320 s_width = tkz.GetNextToken();
1321 width = dx * 12;
1322 if (s_width.ToLong(&lwidth)) {
1323 width = wxMax(dx * 2, lwidth);
1324 width = wxMin(width, dx * 25);
1325 }
1326 m_pListCtrlMMSI->InsertColumn(tlCLASS, _("Track Mode"), wxLIST_FORMAT_CENTER,
1327 width);
1328
1329 s_width = tkz.GetNextToken();
1330 width = dx * 8;
1331 if (s_width.ToLong(&lwidth)) {
1332 width = wxMax(dx * 2, lwidth);
1333 width = wxMin(width, dx * 10);
1334 }
1335 m_pListCtrlMMSI->InsertColumn(tlTYPE, _("Ignore"), wxLIST_FORMAT_CENTER,
1336 width);
1337
1338 s_width = tkz.GetNextToken();
1339 width = dx * 8;
1340 if (s_width.ToLong(&lwidth)) {
1341 width = wxMax(dx * 2, lwidth);
1342 width = wxMin(width, dx * 10);
1343 }
1344 m_pListCtrlMMSI->InsertColumn(tlTYPE, _("MOB"), wxLIST_FORMAT_CENTER, width);
1345
1346 s_width = tkz.GetNextToken();
1347 width = dx * 8;
1348 if (s_width.ToLong(&lwidth)) {
1349 width = wxMax(dx * 2, lwidth);
1350 width = wxMin(width, dx * 15);
1351 }
1352 m_pListCtrlMMSI->InsertColumn(tlTYPE, _("VDM->VDO"), wxLIST_FORMAT_CENTER,
1353 width);
1354
1355 s_width = tkz.GetNextToken();
1356 width = dx * 8;
1357 if (s_width.ToLong(&lwidth)) {
1358 width = wxMax(dx * 2, lwidth);
1359 width = wxMin(width, dx * 30);
1360 }
1361 m_pListCtrlMMSI->InsertColumn(tlTYPE, _("Ship name"), wxLIST_FORMAT_CENTER,
1362 width);
1363
1364 s_width = tkz.GetNextToken();
1365 width = dx * 8;
1366 if (s_width.ToLong(&lwidth)) {
1367 width = wxMax(dx * 2, lwidth);
1368 width = wxMin(width, dx * 10);
1369 }
1370 m_pListCtrlMMSI->InsertColumn(tlTYPE, _("Follower"), wxLIST_FORMAT_CENTER,
1371 width); // Has
1372
1373 topSizer->Add(m_pListCtrlMMSI, 1, wxEXPAND | wxALL, 0);
1374
1375 m_pButtonNew = new wxButton(this, wxID_ANY, _("New..."), wxDefaultPosition,
1376 wxSize(200, -1));
1377 m_pButtonNew->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
1378 wxCommandEventHandler(MMSI_Props_Panel::OnNewButton),
1379 NULL, this);
1380 topSizer->Add(m_pButtonNew, 0, wxALIGN_RIGHT | wxALL, 0);
1381
1382 topSizer->Layout();
1383
1384 // This is silly, but seems to be required for __WXMSW__ build
1385 // If not done, the SECOND invocation of the panel fails to expand the list
1386 // to the full wxSizer size....
1387 SetSize(GetSize().x, GetSize().y - 1);
1388
1389 SetColorScheme(GLOBAL_COLOR_SCHEME_RGB);
1390}
1391
1392MMSI_Props_Panel::~MMSI_Props_Panel(void) {}
1393
1394void MMSI_Props_Panel::OnNewButton(wxCommandEvent& event) {
1395 MmsiProperties* props = new MmsiProperties(-1);
1396
1397 MMSIEditDialog* pd =
1398 new MMSIEditDialog(props, m_parent, -1, _("Add MMSI Properties"),
1399 wxDefaultPosition, wxSize(200, 200));
1400
1401 DimeControl(pd);
1402 pd->ShowWindowModalThenDo([this, pd, props](int retcode) {
1403 if (retcode == wxID_OK) {
1404 g_MMSI_Props_Array.Add(props);
1405 } else {
1406 delete props;
1407 }
1408 UpdateMMSIList();
1409 });
1410}
1411
1412void MMSI_Props_Panel::UpdateMMSIList(void) {
1413 // Capture the MMSI of the curently selected list item
1414 long selItemID = wxNOT_FOUND;
1415 m_pListCtrlMMSI->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1416 wxLIST_STATE_SELECTED);
1417
1418 int selMMSI = wxNOT_FOUND;
1419 if (selItemID != wxNOT_FOUND) selMMSI = g_MMSI_Props_Array[selItemID]->MMSI;
1420
1421 m_pListCtrlMMSI->SetItemCount(g_MMSI_Props_Array.GetCount());
1422
1423 // Restore selected item
1424 long item_sel = wxNOT_FOUND;
1425 if (selItemID != wxNOT_FOUND && selMMSI != wxNOT_FOUND) {
1426 for (unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
1427 if (g_MMSI_Props_Array[i]->MMSI == selMMSI) {
1428 item_sel = i;
1429 break;
1430 }
1431 }
1432 }
1433
1434 if (g_MMSI_Props_Array.GetCount() > 0)
1435 m_pListCtrlMMSI->SetItemState(item_sel,
1436 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1437 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1438
1439#ifdef __WXMSW__
1440 m_pListCtrlMMSI->Refresh(FALSE);
1441#endif
1442}
1443
1444void MMSI_Props_Panel::SetColorScheme(ColorScheme cs) { DimeControl(this); }
1445
1446// WX_DECLARE_OBJARRAY(wxBitmap, ArrayOfBitmaps);
1447//#include <wx/arrimpl.cpp>
1448// WX_DEFINE_OBJARRAY(ArrayOfBitmaps);
1449
1450class OCPNFatCombo : public wxOwnerDrawnComboBox {
1451public:
1452 OCPNFatCombo();
1453
1454 OCPNFatCombo(wxWindow* parent, wxWindowID id, const wxString& value = _T(""),
1455 const wxPoint& pos = wxDefaultPosition,
1456 const wxSize& size = wxDefaultSize, int n = 0,
1457 const wxString choices[] = NULL, long style = 0,
1458 const wxValidator& validator = wxDefaultValidator,
1459 const wxString& name = _T("OCPNFatCombo"));
1460
1461 ~OCPNFatCombo();
1462
1463 void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const;
1464 wxCoord OnMeasureItem(size_t item) const;
1465 wxCoord OnMeasureItemWidth(size_t item) const;
1466 bool SetFont(const wxFont& font);
1467
1468 int Append(const wxString& item, wxBitmap bmp);
1469 void Clear(void);
1470
1471 const wxFont* dfont;
1472
1473private:
1474 int itemHeight;
1475 ArrayOfBitmaps bmpArray;
1476};
1477
1478OCPNFatCombo::OCPNFatCombo() : wxOwnerDrawnComboBox() {}
1479
1480OCPNFatCombo::OCPNFatCombo(wxWindow* parent, wxWindowID id,
1481 const wxString& value, const wxPoint& pos,
1482 const wxSize& size, int n, const wxString choices[],
1483 long style, const wxValidator& validator,
1484 const wxString& name)
1485 : wxOwnerDrawnComboBox(parent, id, value, pos, size, n, choices, style,
1486 validator, name) {
1487 double fontHeight =
1488 GetFont().GetPointSize() / g_Platform->getFontPointsperPixel();
1489 itemHeight = (int)wxRound(fontHeight);
1490 SetPopupMaxHeight(::wxGetDisplaySize().y / 2);
1491}
1492
1493OCPNFatCombo::~OCPNFatCombo() {}
1494
1495bool OCPNFatCombo::SetFont(const wxFont& font) {
1496 dfont = &font;
1497 return true;
1498}
1499
1500void OCPNFatCombo::OnDrawItem(wxDC& dc, const wxRect& rect, int item,
1501 int flags) const {
1502 int offset_x = 10;
1503 // dc.DrawBitmap(bmpArray.Item(item), rect.x, rect.y + (rect.height -
1504 // bmpHeight)/2, true);
1505 dc.SetFont(*dfont);
1506
1507 wxColor bg = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
1508 wxBrush br = wxBrush(bg);
1509 wxBrush sv = dc.GetBrush();
1510 dc.SetBrush(br);
1511 dc.DrawRectangle(0, 0, rect.width, rect.height);
1512 dc.SetBrush(sv);
1513 dc.SetTextForeground(wxColour(0, 0, 0));
1514
1515 if (flags & wxODCB_PAINTING_CONTROL) {
1516 wxString text = GetValue();
1517 int margin_x = 2;
1518 dc.DrawText(text, rect.x + margin_x + offset_x,
1519 (rect.height - dc.GetCharHeight()) / 2 + rect.y);
1520 } else {
1521 dc.SetBackground(wxBrush(br));
1522 dc.Clear();
1523 dc.DrawText(GetVListBoxComboPopup()->GetString(item), rect.x + 2 + offset_x,
1524 (rect.height - dc.GetCharHeight()) / 2 + rect.y);
1525 }
1526}
1527
1528wxCoord OCPNFatCombo::OnMeasureItem(size_t item) const {
1529 if (item < bmpArray.GetCount())
1530 return wxMax(itemHeight, bmpArray.Item(item).GetHeight());
1531
1532 return itemHeight * 12 / 10;
1533}
1534
1535wxCoord OCPNFatCombo::OnMeasureItemWidth(size_t item) const { return -1; }
1536
1537int OCPNFatCombo::Append(const wxString& item, wxBitmap bmp) {
1538 bmpArray.Add(bmp);
1539 int idx = wxOwnerDrawnComboBox::Append(item);
1540
1541 return idx;
1542}
1543
1544void OCPNFatCombo::Clear(void) {
1545 wxOwnerDrawnComboBox::Clear();
1546 bmpArray.Clear();
1547}
1548
1549BEGIN_EVENT_TABLE(options, wxDialog)
1550EVT_INIT_DIALOG(options::OnDialogInit)
1551EVT_CHECKBOX(ID_DEBUGCHECKBOX1, options::OnDebugcheckbox1Click)
1552EVT_BUTTON(ID_BUTTONADD, options::OnButtonaddClick)
1553EVT_BUTTON(ID_BUTTONDELETE, options::OnButtondeleteClick)
1554EVT_BUTTON(ID_PARSEENCBUTTON, options::OnButtonParseENC)
1555EVT_BUTTON(ID_BUTTONCOMPRESS, options::OnButtoncompressClick)
1556EVT_BUTTON(ID_BUTTONMIGRATE, options::OnButtonmigrateClick)
1557EVT_BUTTON(ID_TCDATAADD, options::OnInsertTideDataLocation)
1558EVT_BUTTON(ID_TCDATADEL, options::OnRemoveTideDataLocation)
1559EVT_BUTTON(ID_APPLY, options::OnApplyClick)
1560EVT_BUTTON(xID_OK, options::OnXidOkClick)
1561EVT_BUTTON(wxID_CANCEL, options::OnCancelClick)
1562EVT_BUTTON(ID_BUTTONFONTCHOOSE, options::OnChooseFont)
1563EVT_BUTTON(ID_BUTTONECDISHELP, options::OnButtonEcdisHelp)
1564
1565EVT_CHOICE(ID_CHOICE_FONTELEMENT, options::OnFontChoice)
1566EVT_CLOSE(options::OnClose)
1567
1568#if defined(__WXGTK__) || defined(__WXQT__)
1569EVT_BUTTON(ID_BUTTONFONTCOLOR, options::OnChooseFontColor)
1570#endif
1571#ifdef ocpnUSE_GL
1572EVT_BUTTON(ID_OPENGLOPTIONS, options::OnOpenGLOptions)
1573#endif
1574EVT_CHOICE(ID_RADARDISTUNIT, options::OnDisplayCategoryRadioButton)
1575EVT_CHOICE(ID_DEPTHUNITSCHOICE, options::OnUnitsChoice)
1576EVT_BUTTON(ID_CLEARLIST, options::OnButtonClearClick)
1577EVT_BUTTON(ID_SELECTLIST, options::OnButtonSelectClick)
1578EVT_BUTTON(ID_SETSTDLIST, options::OnButtonSetStd)
1579EVT_CHOICE(ID_SHIPICONTYPE, options::OnShipTypeSelect)
1580EVT_CHOICE(ID_RADARRINGS, options::OnRadarringSelect)
1581EVT_CHOICE(ID_OPWAYPOINTRANGERINGS, options::OnWaypointRangeRingSelect)
1582EVT_CHAR_HOOK(options::OnCharHook)
1583
1584END_EVENT_TABLE()
1585
1586options::options(MyFrame* parent, wxWindowID id, const wxString& caption,
1587 const wxPoint& pos, const wxSize& size, long style) {
1588 Init();
1589
1590 pParent = parent;
1591
1592 long wstyle = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER;
1593 SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
1594
1595 wxDialog::Create(parent, id, caption, pos, size, wstyle);
1596 SetFont(*dialogFont);
1597
1598 CreateControls();
1599 RecalculateSize();
1600
1601 // Protect against unreasonable small size
1602 // And also handle the empty config file init case.
1603 if (((size.x < 200) || (size.y < 200)) && !g_bresponsive) Fit();
1604
1605 Center();
1606
1607 wxDEFINE_EVENT(EVT_COMPAT_OS_CHANGE, wxCommandEvent);
1608 GlobalVar<wxString> compat_os(&g_compatOS);
1609 compat_os_listener.Listen(compat_os, this, EVT_COMPAT_OS_CHANGE);
1610 Bind(EVT_COMPAT_OS_CHANGE, [&](wxCommandEvent&) {
1611 PluginLoader::getInstance()->LoadAllPlugIns(false);
1612 m_pPlugInCtrl->ReloadPluginPanels();
1613 });
1614}
1615
1616options::~options(void) {
1617 wxNotebook* nb =
1618 dynamic_cast<wxNotebook*>(m_pListbook->GetPage(m_pageCharts));
1619 if (nb)
1620 nb->Disconnect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
1621 wxListbookEventHandler(options::OnChartsPageChange), NULL,
1622 this);
1623
1624 groupsPanel->EmptyChartGroupArray(m_pGroupArray);
1625 delete groupsPanel;
1626
1627 delete m_pSerialArray;
1628 delete m_pGroupArray;
1629 delete m_topImgList;
1630
1631 // Take care of the plugin manager...
1632
1633 delete m_pPlugInCtrl;
1634 if (g_pi_manager) g_pi_manager->SetListPanelPtr(NULL);
1635#ifndef __OCPN__ANDROID__
1636 delete m_PluginCatalogMgrPanel;
1637#endif
1638}
1639
1640// with AIS it's called very often
1641#if wxCHECK_VERSION(3, 0, 0)
1642bool options::SendIdleEvents(wxIdleEvent& event) {
1643 if (IsShown()) return wxDialog::SendIdleEvents(event);
1644 return false;
1645}
1646#endif
1647
1648void options::RecalculateSize(void) {
1649 if (!g_bresponsive) {
1650 m_nCharWidthMax = GetSize().x / GetCharWidth();
1651 return;
1652#if 0
1653 wxSize canvas_size = gFrame->GetSize();
1654 wxSize fitted_size = GetSize();
1655
1656 fitted_size.x = wxMin(fitted_size.x, canvas_size.x);
1657 fitted_size.y = wxMin(fitted_size.y, canvas_size.y);
1658
1659 SetSize(fitted_size);
1660
1661 Fit();
1662
1663 return;
1664#endif
1665 }
1666
1667 wxSize esize;
1668 esize.x = GetCharWidth() * 110;
1669 esize.y = GetCharHeight() * 40;
1670
1671 wxSize dsize = GetParent()->GetSize(); // GetClientSize();
1672 esize.y = wxMin(esize.y, dsize.y - 0 /*(2 * GetCharHeight())*/);
1673 esize.x = wxMin(esize.x, dsize.x - 0 /*(2 * GetCharHeight())*/);
1674 SetSize(esize);
1675
1676 wxSize fsize = GetSize();
1677 wxSize canvas_size = GetParent()->GetSize();
1678 wxPoint screen_pos = GetParent()->GetScreenPosition();
1679 int xp = (canvas_size.x - fsize.x) / 2;
1680 int yp = (canvas_size.y - fsize.y) / 2;
1681 Move(screen_pos.x + xp, screen_pos.y + yp);
1682
1683 m_nCharWidthMax = GetSize().x / GetCharWidth();
1684}
1685
1686void options::Init(void) {
1687 m_pWorkDirList = NULL;
1688
1689 pShowStatusBar = NULL;
1690 pShowMenuBar = NULL;
1691 pShowCompassWin = NULL;
1692 pSelCtl = NULL;
1693 // pActiveChartsList = NULL;
1694 m_scrollWinChartList = NULL;
1695 ps57CtlListBox = NULL;
1696 pDispCat = NULL;
1697 m_pSerialArray = NULL;
1698 pUpdateCheckBox = NULL;
1699 pParseENCButton = NULL;
1700 k_charts = 0;
1701 k_vectorcharts = 0;
1702 k_plugins = 0;
1703 k_tides = 0;
1704 m_pConfig = NULL;
1705
1706 pSoundDeviceIndex = NULL;
1707
1708 pCBNorthUp = NULL;
1709 pCBCourseUp = NULL;
1710 pCBLookAhead = NULL;
1711 pCDOQuilting = NULL;
1712 pPreserveScale = NULL;
1713 pSmoothPanZoom = NULL;
1714 pEnableZoomToCursor = NULL;
1715 pSDisplayGrid = NULL;
1716 pCDOOutlines = NULL;
1717 pSDepthUnits = NULL;
1718 pSLiveETA = NULL;
1719 pSDefaultBoatSpeed = NULL;
1720
1721 activeSizer = NULL;
1722 itemActiveChartStaticBox = NULL;
1723
1724 pCheck_SOUNDG = NULL;
1725 pCheck_META = NULL;
1726 pCheck_SHOWIMPTEXT = NULL;
1727 pCheck_SCAMIN = NULL;
1728 pCheck_ATONTEXT = NULL;
1729 pCheck_LDISTEXT = NULL;
1730 pCheck_XLSECTTEXT = NULL;
1731
1732 m_bVisitLang = FALSE;
1733 m_itemFontElementListBox = NULL;
1734 m_textSample = NULL;
1735 m_topImgList = NULL;
1736
1737 m_pListbook = NULL;
1738 m_pGroupArray = NULL;
1739 m_groups_changed = 0;
1740
1741 m_pageDisplay = -1;
1742 m_pageConnections = -1;
1743 m_pageCharts = -1;
1744 m_pageShips = -1;
1745 m_pageUI = -1;
1746 m_pagePlugins = -1;
1747 m_pageConnections = -1;
1748
1749
1750 auto loader = PluginLoader::getInstance();
1751 b_haveWMM = loader && loader->IsPlugInAvailable(_T("WMM"));
1752 b_oldhaveWMM = b_haveWMM;
1753
1754 lastPage = 0;
1755 m_bneedNew = false;
1756
1757 m_bForceNewToolbaronCancel = false;
1758
1759 m_cs = (ColorScheme)0;
1760
1761 // for deferred loading
1762 m_pPlugInCtrl = NULL;
1763 m_PluginCatalogMgrPanel = NULL;
1764
1765 m_pNMEAForm = NULL;
1766 //FIXME Do this in CTOR of connections dialog
1767 //mSelectedConnection = NULL;
1768
1769#ifdef __OCPN__ANDROID__
1770 m_scrollRate = 1;
1771#else
1772 m_scrollRate = 15;
1773#endif
1774
1775 //FIXME (dave) move
1776 //m_BTScanTimer.SetOwner(this, ID_BT_SCANTIMER);
1777 //m_BTscanning = 0;
1778
1779 dialogFont = GetOCPNScaledFont(_("Dialog"));
1780
1781 dialogFontPlus = new wxFont(
1782 *dialogFont); // we can't use Smaller() because wx2.8 doesn't support it
1783 dialogFontPlus->SetPointSize((dialogFontPlus->GetPointSize() * 1.2) +
1784 0.5); // + 0.5 to round instead of truncate
1785 dialogFontPlus->SetWeight(wxFONTWEIGHT_BOLD);
1786
1787 m_bVectorInit = false;
1788
1789 // This variable is used by plugin callback function AddOptionsPage
1790 g_pOptions = this;
1791
1792 pCmdSoundString = NULL;
1793
1794 m_sconfigSelect_single = NULL;
1795 m_sconfigSelect_twovertical = NULL;
1796
1797 wxScreenDC dc;
1798 dc.SetFont(*dialogFont);
1799 int width, height;
1800 dc.GetTextExtent(_T("H"), &width, &height, NULL, NULL, dialogFont);
1801
1802 m_colourPickerDefaultSize = wxSize(4 * height, height * 2);
1803
1804 m_bcompact = false;
1805
1806 // wxSize dSize = g_Platform->getDisplaySize();
1807 // if ( dSize.x < width * 40)
1808 // m_bcompact = true;
1809
1810 double dsizemm = g_Platform->GetDisplaySizeMM();
1811 if (dsizemm < 80) // Probably and Android Phone, portrait mode
1812 m_bcompact = true;
1813}
1814
1815#if defined(__GNUC__) && __GNUC__ < 8
1816// Handle old gcc C++-11 bugs, remove when builders updated to gcc >= 8.1.1.
1817
1818static const wxString BAD_ACCESS_MSG = _(
1819 "The device selected is not accessible; opencpn will likely not be able\n"
1820 "to use this device as-is. You might want to exit OpenCPN, reboot and\n"
1821 "retry after creating a file called /etc/udev/rules.d/70-opencpn.rules\n"
1822 "with the following contents:\n\n"
1823 " KERNEL==\"ttyUSB*\", MODE=\"0666\"\n"
1824 " KERNEL==\"ttyACM*\", MODE=\"0666\"\n"
1825 " KERNEL==\"ttyS*\", MODE=\"0666\"\n\n"
1826 "For more info, see the file LINUX_DEVICES.md in the distribution docs.\n");
1827
1828#else
1829
1830static const wxString BAD_ACCESS_MSG = _(R"(
1831The device selected is not accessible; opencpn will likely not be able
1832to use this device as-is. You might want to exit OpenCPN, reboot and
1833retry after creating a file called /etc/udev/rules.d/70-opencpn.rules
1834with the following contents:
1835
1836 KERNEL=="ttyUSB*", MODE="0666"
1837 KERNEL=="ttyACM*", MODE="0666"
1838 KERNEL=="ttyS*", MODE="0666"
1839
1840For more info, see the file LINUX_DEVICES.md in the distribution docs.
1841)");
1842
1843#endif // defined(__GNUC__) && __GNUC__ < 8
1844
1845void options::OnDialogInit(wxInitDialogEvent& event) {}
1846
1847void options::CheckDeviceAccess(/*[[maybe_unused]]*/ wxString& path) {}
1848
1849size_t options::CreatePanel(const wxString& title) {
1850 size_t id = m_pListbook->GetPageCount();
1851 /* This is the default empty content for any top tab.
1852 It'll be replaced when we call AddPage */
1853 wxPanel* panel = new wxPanel(m_pListbook, wxID_ANY, wxDefaultPosition,
1854 wxDefaultSize, wxTAB_TRAVERSAL, title);
1855 m_pListbook->AddPage(panel, title, FALSE, id);
1856 return id;
1857}
1858
1859wxScrolledWindow* options::AddPage(size_t parent, const wxString& title) {
1860 if (parent > m_pListbook->GetPageCount() - 1) {
1861 wxLogMessage(
1862 wxString::Format(
1863 _T("Warning: invalid parent in options::AddPage( %d, "), parent) +
1864 title + _T(" )"));
1865 return NULL;
1866 }
1867 wxNotebookPage* page = m_pListbook->GetPage(parent);
1868 wxNotebook* nb;
1869 wxScrolledWindow* sw;
1870
1871 int style = wxVSCROLL | wxTAB_TRAVERSAL;
1872 if ((nb = dynamic_cast<wxNotebook*>(page))) {
1873 sw = new wxScrolledWindow(page, wxID_ANY, wxDefaultPosition, wxDefaultSize,
1874 style);
1875 sw->SetScrollRate(m_scrollRate, m_scrollRate);
1876 nb->AddPage(sw, title);
1877 } else if ((sw = dynamic_cast<wxScrolledWindow*>(page))) {
1878 wxString toptitle = m_pListbook->GetPageText(parent);
1879 wxNotebook* nb = new wxNotebook(m_pListbook, wxID_ANY, wxDefaultPosition,
1880 wxDefaultSize, wxNB_TOP);
1881 /* Only remove the tab from listbook, we still have original content in
1882 * {page} */
1883 m_pListbook->InsertPage(parent, nb, toptitle, FALSE, parent);
1884 m_pListbook->SetSelection(0); // avoid gtk assertions
1885 m_pListbook->RemovePage(parent + 1);
1886 wxString previoustitle = page->GetName();
1887 page->Reparent(nb);
1888 nb->Connect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
1889 wxNotebookEventHandler(options::OnSubNBPageChange), NULL, this);
1890
1891 nb->AddPage(page, previoustitle);
1892 /* wxNotebookPage is hidden under wxGTK after RemovePage/Reparent
1893 * we must explicitely Show() it */
1894 page->Show();
1895 sw = new wxScrolledWindow(nb, wxID_ANY, wxDefaultPosition, wxDefaultSize,
1896 style);
1897 sw->SetScrollRate(m_scrollRate, m_scrollRate);
1898 nb->AddPage(sw, title);
1899 nb->ChangeSelection(0);
1900 } else { // This is the default content, we can replace it now
1901 sw = new wxScrolledWindow(m_pListbook, wxID_ANY, wxDefaultPosition,
1902 wxDefaultSize, style, title);
1903 sw->SetScrollRate(m_scrollRate, m_scrollRate);
1904 wxString toptitle = m_pListbook->GetPageText(parent);
1905 m_pListbook->InsertPage(parent, sw, toptitle, FALSE, parent);
1906 m_pListbook->SetSelection(0); // avoid gtk assertions
1907 m_pListbook->DeletePage(parent + 1);
1908 }
1909
1910#ifdef __OCPN__ANDROID__
1911 sw->GetHandle()->setStyleSheet(getAdjustedDialogStyleSheet());
1912#endif
1913
1914 return sw;
1915}
1916
1917bool options::DeletePluginPage(wxScrolledWindow* page) {
1918 for (size_t i = 0; i < m_pListbook->GetPageCount(); i++) {
1919 wxNotebookPage* pg = m_pListbook->GetPage(i);
1920 wxNotebook* nb = dynamic_cast<wxNotebook*>(pg);
1921
1922 if (nb) {
1923 for (size_t j = 0; j < nb->GetPageCount(); j++) {
1924 wxNotebookPage* spg = nb->GetPage(j);
1925 if (spg == page) {
1926 nb->DeletePage(j);
1927 if (nb->GetPageCount() != 1) return TRUE;
1928 /* There's only one page, remove inner notebook */
1929 spg = nb->GetPage(0);
1930 spg->Reparent(m_pListbook);
1931 nb->RemovePage(0);
1932 wxString toptitle = m_pListbook->GetPageText(i);
1933 m_pListbook->DeletePage(i);
1934 m_pListbook->InsertPage(i, spg, toptitle, FALSE, i);
1935 return TRUE;
1936 }
1937 }
1938 } else if (pg == page) {
1939 /* There's only one page, replace it with empty panel */
1940 m_pListbook->DeletePage(i);
1941 wxPanel* panel = new wxPanel(m_pListbook);
1942 wxString toptitle = m_pListbook->GetPageText(i);
1943 m_pListbook->InsertPage(i, panel, toptitle, FALSE, i);
1944 return TRUE;
1945 }
1946 }
1947 return FALSE;
1948}
1949
1950void options::CreatePanel_NMEA(size_t parent, int border_size,
1951 int group_item_spacing) {
1952 m_pNMEAForm = AddPage(parent, _("NMEA"));
1953
1954 comm_dialog = std::make_shared<ConnectionsDialog>(m_pNMEAForm, this);
1955
1956 //FIXME (dave) Why is this here
1957 pOpenGL->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
1958 wxCommandEventHandler(options::OnGLClicked), NULL, this);
1959
1960
1961}
1962
1963
1964void options::CreatePanel_Ownship(size_t parent, int border_size,
1965 int group_item_spacing) {
1966 itemPanelShip = AddPage(parent, _("Own ship"));
1967
1968 ownShip = new wxBoxSizer(wxVERTICAL);
1969 itemPanelShip->SetSizer(ownShip);
1970
1971 // OwnShip Display options
1972 wxStaticBox* osdBox =
1973 new wxStaticBox(itemPanelShip, wxID_ANY, _("Display Options"));
1974 dispOptions = new wxStaticBoxSizer(osdBox, wxVERTICAL);
1975 ownShip->Add(dispOptions, 0, wxTOP | wxALL | wxEXPAND, border_size);
1976
1977 wxFlexGridSizer* dispOptionsGrid =
1978 new wxFlexGridSizer(0, 2, group_item_spacing, group_item_spacing);
1979 dispOptionsGrid->AddGrowableCol(1);
1980 dispOptions->Add(dispOptionsGrid, 0, wxALL | wxEXPAND, border_size);
1981
1982 wxStaticText* pStatic_OSCOG_Predictor = new wxStaticText(
1983 itemPanelShip, wxID_ANY, _("COG Predictor Length (min)"));
1984 dispOptionsGrid->Add(pStatic_OSCOG_Predictor, 0);
1985
1986 m_pText_OSCOG_Predictor = new wxTextCtrl(itemPanelShip, wxID_ANY, "TEXT");
1987 dispOptionsGrid->Add(m_pText_OSCOG_Predictor, 0, wxALIGN_RIGHT);
1988
1989 wxStaticText* pStatic_OSHDT_Predictor = new wxStaticText(
1990 itemPanelShip, wxID_ANY, _("Heading Predictor Length (NMi)"));
1991 dispOptionsGrid->Add(pStatic_OSHDT_Predictor, 0);
1992
1993 m_pText_OSHDT_Predictor = new wxTextCtrl(itemPanelShip, wxID_ANY, "TEXT");
1994 dispOptionsGrid->Add(m_pText_OSHDT_Predictor, 0, wxALIGN_RIGHT);
1995
1996 wxStaticText* iconTypeTxt =
1997 new wxStaticText(itemPanelShip, wxID_ANY, _("Ship Icon Type"));
1998 dispOptionsGrid->Add(iconTypeTxt, 0);
1999
2000 wxString iconTypes[] = {_("Default"), _("Real Scale Bitmap"),
2001 _("Real Scale Vector")};
2002
2003 m_pShipIconType = new wxChoice(
2004 itemPanelShip, ID_SHIPICONTYPE, wxDefaultPosition,
2005 wxSize(GetCharWidth() * 20, GetCharHeight() * 2), 3, iconTypes);
2006 dispOptionsGrid->Add(m_pShipIconType, 0,
2007 wxALIGN_RIGHT | wxLEFT | wxRIGHT | wxTOP,
2008 group_item_spacing);
2009
2010 realSizes = new wxFlexGridSizer(5, 2, group_item_spacing, group_item_spacing);
2011 realSizes->AddGrowableCol(1);
2012
2013 dispOptions->Add(realSizes, 0, wxEXPAND | wxLEFT, 30);
2014
2015 realSizes->Add(
2016 new wxStaticText(itemPanelShip, wxID_ANY, _("Length Over All (m)")), 1,
2017 wxALIGN_LEFT);
2018 m_pOSLength = new wxTextCtrl(itemPanelShip, 1, "TEXT ");
2019 realSizes->Add(m_pOSLength, 1, wxALIGN_RIGHT | wxALL, group_item_spacing);
2020
2021 realSizes->Add(
2022 new wxStaticText(itemPanelShip, wxID_ANY, _("Width Over All (m)")), 1,
2023 wxALIGN_LEFT);
2024 m_pOSWidth = new wxTextCtrl(itemPanelShip, wxID_ANY, "TEXT ");
2025 realSizes->Add(m_pOSWidth, 1, wxALIGN_RIGHT | wxALL, group_item_spacing);
2026
2027 realSizes->Add(
2028 new wxStaticText(itemPanelShip, wxID_ANY, _("GPS Offset from Bow (m)")),
2029 1, wxALIGN_LEFT);
2030 m_pOSGPSOffsetY = new wxTextCtrl(itemPanelShip, wxID_ANY, "TEXT ");
2031 realSizes->Add(m_pOSGPSOffsetY, 1, wxALIGN_RIGHT | wxALL, group_item_spacing);
2032
2033 realSizes->Add(new wxStaticText(itemPanelShip, wxID_ANY,
2034 _("GPS Offset from Midship (m)")),
2035 1, wxALIGN_LEFT);
2036 m_pOSGPSOffsetX = new wxTextCtrl(itemPanelShip, wxID_ANY, "TEXT ");
2037 realSizes->Add(m_pOSGPSOffsetX, 1, wxALIGN_RIGHT | wxALL, group_item_spacing);
2038
2039 realSizes->Add(
2040 new wxStaticText(itemPanelShip, wxID_ANY, _("Minimum Screen Size (mm)")),
2041 1, wxALIGN_LEFT);
2042 m_pOSMinSize = new wxTextCtrl(itemPanelShip, wxID_ANY, "TEXT ");
2043 realSizes->Add(m_pOSMinSize, 1, wxALIGN_RIGHT | wxALL, group_item_spacing);
2044
2045 // Radar rings
2046 wxFlexGridSizer* rrSelect =
2047 new wxFlexGridSizer(1, 2, group_item_spacing, group_item_spacing);
2048 rrSelect->AddGrowableCol(1);
2049 dispOptions->Add(rrSelect, 0, wxLEFT | wxRIGHT | wxEXPAND, border_size);
2050
2051 wxStaticText* rrTxt =
2052 new wxStaticText(itemPanelShip, wxID_ANY, _("Show range rings"));
2053 rrSelect->Add(rrTxt, 1, wxEXPAND | wxALL, group_item_spacing);
2054
2055 wxString rrAlt[] = {_("None"), _T( "1" ), _T( "2" ), _T( "3" ),
2056 _T( "4" ), _T( "5" ), _T( "6" ), _T( "7" ),
2057 _T( "8" ), _T( "9" ), _T( "10" )};
2058 pNavAidRadarRingsNumberVisible =
2059 new wxChoice(itemPanelShip, ID_RADARRINGS, wxDefaultPosition,
2060 m_pShipIconType->GetSize(), 11, rrAlt);
2061 rrSelect->Add(pNavAidRadarRingsNumberVisible, 0, wxALIGN_RIGHT | wxALL,
2062 group_item_spacing);
2063
2064 radarGrid = new wxFlexGridSizer(0, 2, group_item_spacing, group_item_spacing);
2065 radarGrid->AddGrowableCol(1);
2066 dispOptions->Add(radarGrid, 0, wxLEFT | wxEXPAND, 30);
2067
2068 wxStaticText* distanceText =
2069 new wxStaticText(itemPanelShip, wxID_STATIC, _("Distance between rings"));
2070 radarGrid->Add(distanceText, 1, wxEXPAND | wxALL, group_item_spacing);
2071
2072 pNavAidRadarRingsStep = new wxTextCtrl(itemPanelShip, ID_OPTEXTCTRL, _T(""),
2073 wxDefaultPosition, wxSize(100, -1), 0);
2074 radarGrid->Add(pNavAidRadarRingsStep, 0, wxALIGN_RIGHT | wxALL,
2075 group_item_spacing);
2076
2077 wxStaticText* unitText =
2078 new wxStaticText(itemPanelShip, wxID_STATIC, _("Distance Unit"));
2079 radarGrid->Add(unitText, 1, wxEXPAND | wxALL, group_item_spacing);
2080
2081 wxString pDistUnitsStrings[] = {_("Nautical miles"), _("Kilometers")};
2082 m_itemRadarRingsUnits =
2083 new wxChoice(itemPanelShip, ID_RADARDISTUNIT, wxDefaultPosition,
2084 m_pShipIconType->GetSize(), 2, pDistUnitsStrings);
2085 radarGrid->Add(m_itemRadarRingsUnits, 0, wxALIGN_RIGHT | wxALL, border_size);
2086
2087 wxStaticText* colourText =
2088 new wxStaticText(itemPanelShip, wxID_STATIC, _("Range Ring Colour"));
2089 radarGrid->Add(colourText, 1, wxEXPAND | wxALL, group_item_spacing);
2090
2091 m_colourOwnshipRangeRingColour = new OCPNColourPickerCtrl(
2092 itemPanelShip, wxID_ANY, *wxRED, wxDefaultPosition,
2093 m_colourPickerDefaultSize, 0, wxDefaultValidator,
2094 _T( "ID_COLOUROSRANGECOLOUR" ));
2095 radarGrid->Add(m_colourOwnshipRangeRingColour, 0, wxALIGN_RIGHT, border_size);
2096
2097 // ship to active
2098 wxFlexGridSizer* shipToActiveGrid =
2099 new wxFlexGridSizer(1, 5, group_item_spacing, group_item_spacing);
2100 shipToActiveGrid->AddGrowableCol(1);
2101 dispOptions->Add(shipToActiveGrid, 0, wxALL | wxEXPAND, border_size);
2102 pShowshipToActive = new wxCheckBox(itemPanelShip, wxID_ANY,
2103 _("Show direction to Active Waypoint"));
2104 shipToActiveGrid->Add(pShowshipToActive, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT,
2105 border_size);
2106
2107 wxStaticText* shipToActiveText1 =
2108 new wxStaticText(itemPanelShip, wxID_STATIC, _("Style"));
2109 shipToActiveGrid->Add(shipToActiveText1, 1,
2110 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, border_size);
2111
2112 wxString LineStyleChoices[] = {_("Default"), _("Solid"),
2113 _("Dot"), _("Long dash"),
2114 _("Short dash"), _("Dot dash")};
2115 int LineStyleNChoices = sizeof(LineStyleChoices) / sizeof(wxString);
2116 m_shipToActiveStyle =
2117 new wxChoice(itemPanelShip, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2118 LineStyleNChoices, LineStyleChoices, 0);
2119 m_shipToActiveStyle->SetSelection(0);
2120 shipToActiveGrid->Add(m_shipToActiveStyle, 0, wxALL, 5);
2121
2122 wxStaticText* shipToActiveText2 =
2123 new wxStaticText(itemPanelShip, wxID_STATIC, _("Color"));
2124 shipToActiveGrid->Add(shipToActiveText2, 1,
2125 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, border_size);
2126
2127 wxString m_LineColorChoices[] = {
2128 ("Default color"), _("Black"), _("Dark Red"), _("Dark Green"),
2129 _("Dark Yellow"), _("Dark Blue"), _("Dark Magenta"), _("Dark Cyan"),
2130 _("Light Gray"), _("Dark Gray"), _("Red"), _("Green"),
2131 _("Yellow"), _("Blue"), _("Magenta"), _("Cyan"),
2132 _("White")};
2133 int LineColorNChoices = sizeof(m_LineColorChoices) / sizeof(wxString);
2134 m_shipToActiveColor =
2135 new wxChoice(itemPanelShip, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2136 LineColorNChoices, m_LineColorChoices, 0);
2137 m_shipToActiveColor->SetSelection(0);
2138 shipToActiveGrid->Add(m_shipToActiveColor, 0, wxALL, 5);
2139
2140 // Tracks
2141 wxStaticBox* trackText =
2142 new wxStaticBox(itemPanelShip, wxID_ANY, _("Tracks"));
2143 wxStaticBoxSizer* trackSizer = new wxStaticBoxSizer(trackText, wxVERTICAL);
2144 wxBoxSizer* trackSizer1 = new wxBoxSizer(wxHORIZONTAL);
2145 ownShip->Add(trackSizer, 0, wxGROW | wxALL, border_size);
2146
2147 pTrackDaily = new wxCheckBox(itemPanelShip, ID_DAILYCHECKBOX,
2148 _("Automatic Daily Tracks at midnight"));
2149
2150 trackSizer1->Add(pTrackDaily, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT,
2151 border_size);
2152
2153 trackSizer1->Add(0, 0, 1, wxEXPAND, 0);
2154
2155#if wxCHECK_VERSION(2, 9, 0)
2156#if wxUSE_TIMEPICKCTRL
2157 pTrackDaily->SetLabel(_("Automatic Daily Tracks at"));
2158#ifdef __WXGTK__
2159 pTrackRotateTime =
2160 new TimeCtrl(itemPanelShip, ID_TRACKROTATETIME,
2161 wxDateTime((time_t)g_track_rotate_time).ToUTC(),
2162 wxDefaultPosition, wxDefaultSize, 0);
2163#else
2164 pTrackRotateTime =
2165 new wxTimePickerCtrl(itemPanelShip, ID_TRACKROTATETIME,
2166 wxDateTime((time_t)g_track_rotate_time).ToUTC(),
2167 wxDefaultPosition, wxDefaultSize, 0);
2168#endif
2169 trackSizer1->Add(pTrackRotateTime, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT,
2170 border_size);
2171#endif
2172#endif
2173
2174 pTrackRotateComputerTime =
2175 new wxRadioButton(itemPanelShip, ID_TRACKROTATECOMPUTER, _("Computer"),
2176 wxDefaultPosition, wxDefaultSize, 0);
2177 trackSizer1->Add(pTrackRotateComputerTime, 0,
2178 wxALIGN_CENTER_VERTICAL | wxRIGHT, border_size);
2179
2180 pTrackRotateUTC =
2181 new wxRadioButton(itemPanelShip, ID_TRACKROTATEUTC, _("UTC"),
2182 wxDefaultPosition, wxDefaultSize, 0);
2183 trackSizer1->Add(pTrackRotateUTC, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT,
2184 border_size);
2185
2186 pTrackRotateLMT =
2187 new wxRadioButton(itemPanelShip, ID_TRACKROTATELMT, _("LMT"),
2188 wxDefaultPosition, wxDefaultSize, 0);
2189 trackSizer1->Add(pTrackRotateLMT, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT,
2190 border_size);
2191
2192 trackSizer->Add(trackSizer1, 1, wxEXPAND | wxALL, border_size);
2193
2194 wxFlexGridSizer* hTrackGrid =
2195 new wxFlexGridSizer(1, 3, group_item_spacing, group_item_spacing);
2196 hTrackGrid->AddGrowableCol(1);
2197 trackSizer->Add(hTrackGrid, 0, wxALL | wxEXPAND, border_size);
2198
2199 pTrackHighlite =
2200 new wxCheckBox(itemPanelShip, ID_TRACKHILITE, _("Highlight Tracks"));
2201 hTrackGrid->Add(pTrackHighlite, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL,
2202 border_size);
2203 wxStaticText* trackColourText =
2204 new wxStaticText(itemPanelShip, wxID_STATIC, _("Highlight Colour"));
2205 hTrackGrid->Add(trackColourText, 1, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL,
2206 border_size);
2207 m_colourTrackLineColour = new OCPNColourPickerCtrl(
2208 itemPanelShip, wxID_STATIC, *wxRED, wxDefaultPosition,
2209 m_colourPickerDefaultSize, 0, wxDefaultValidator,
2210 _T( "ID_COLOURTRACKCOLOUR" ));
2211 hTrackGrid->Add(m_colourTrackLineColour, 1, wxALIGN_RIGHT, border_size);
2212
2213 wxFlexGridSizer* pTrackGrid =
2214 new wxFlexGridSizer(1, 2, group_item_spacing, group_item_spacing);
2215 pTrackGrid->AddGrowableCol(1);
2216 trackSizer->Add(pTrackGrid, 0, wxALL | wxEXPAND, border_size);
2217
2218 wxStaticText* tpText =
2219 new wxStaticText(itemPanelShip, wxID_STATIC, _("Tracking Precision"));
2220 pTrackGrid->Add(tpText, 1, wxEXPAND | wxALL, group_item_spacing);
2221
2222 wxString trackAlt[] = {_("Low"), _("Medium"), _("High")};
2223 pTrackPrecision = new wxChoice(itemPanelShip, wxID_ANY, wxDefaultPosition,
2224 m_pShipIconType->GetSize(), 3, trackAlt);
2225 pTrackGrid->Add(pTrackPrecision, 0, wxALIGN_RIGHT | wxALL,
2226 group_item_spacing);
2227
2228 // Calculate values
2229 wxStaticBox* ownshipcalcText =
2230 new wxStaticBox(itemPanelShip, wxID_ANY, _("Calculate values"));
2231 wxStaticBoxSizer* ownshipcalcSizer =
2232 new wxStaticBoxSizer(ownshipcalcText, wxVERTICAL);
2233 ownShip->Add(ownshipcalcSizer, 0, wxTOP | wxALL | wxEXPAND, border_size);
2234
2235 wxFlexGridSizer* dispOwnShipCalcOptionsGrid =
2236 new wxFlexGridSizer(2, 2, group_item_spacing, group_item_spacing);
2237 ownshipcalcSizer->Add(dispOwnShipCalcOptionsGrid, 0, wxTOP | wxALL | wxEXPAND,
2238 border_size);
2239
2240 dispOwnShipCalcOptionsGrid->AddGrowableCol(1);
2241
2242 pSogCogFromLLCheckBox =
2243 new wxCheckBox(itemPanelShip, ID_SOGCOGFROMLLCHECKBOX,
2244 _("Calculate SOG and COG from position changes"));
2245 dispOwnShipCalcOptionsGrid->Add(pSogCogFromLLCheckBox, 1, wxALL, 5);
2246 dispOwnShipCalcOptionsGrid->AddSpacer(0);
2247
2248 wxStaticText* SogCogFromLLDampIntText = new wxStaticText(
2249 itemPanelShip, wxID_STATIC, _("Min seconds between updates"));
2250 dispOwnShipCalcOptionsGrid->Add(SogCogFromLLDampIntText, 1, wxEXPAND | wxALL,
2251 group_item_spacing);
2252
2253 pSogCogFromLLDampInterval = new wxSpinCtrl(
2254 itemPanelShip, ID_SOGCOGDAMPINTTEXTCTRL, wxEmptyString, wxDefaultPosition,
2255 wxDefaultSize, wxSP_ARROW_KEYS, 0, 10, 0);
2256
2257 dispOwnShipCalcOptionsGrid->Add(pSogCogFromLLDampInterval, 0,
2258 wxALIGN_RIGHT | wxALL, group_item_spacing);
2259
2260 // DimeControl(itemPanelShip);
2261}
2262
2263void options::CreatePanel_Routes(size_t parent, int border_size,
2264 int group_item_spacing) {
2265 itemPanelRoutes = AddPage(parent, _("Routes/Points"));
2266
2267 Routes = new wxBoxSizer(wxVERTICAL);
2268 itemPanelRoutes->SetSizer(Routes);
2269
2270 wxString pDistUnitsStrings[] = {_("Nautical miles"), _("Kilometers")};
2271
2272 wxString rrAlt[] = {_("None"), _T( "1" ), _T( "2" ), _T( "3" ),
2273 _T( "4" ), _T( "5" ), _T( "6" ), _T( "7" ),
2274 _T( "8" ), _T( "9" ), _T( "10" )};
2275
2276 // Routes
2277 wxStaticBox* routeText =
2278 new wxStaticBox(itemPanelRoutes, wxID_ANY, _("New Routes"));
2279 wxStaticBoxSizer* routeSizer = new wxStaticBoxSizer(routeText, wxVERTICAL);
2280 Routes->Add(routeSizer, 0, wxGROW | wxALL, border_size);
2281
2282 routeSizer->AddSpacer(5);
2283
2284 // Default ICON
2285 wxFlexGridSizer* routepointiconSelect =
2286 new wxFlexGridSizer(1, 2, group_item_spacing, group_item_spacing);
2287 routepointiconSelect->AddGrowableCol(1);
2288 routeSizer->Add(routepointiconSelect, 0, wxLEFT | wxRIGHT | wxEXPAND,
2289 border_size);
2290
2291 wxStaticText* routepointiconTxt =
2292 new wxStaticText(itemPanelRoutes, wxID_ANY, _("Waypoint default icon"));
2293 routepointiconSelect->Add(routepointiconTxt, 1, wxEXPAND | wxALL,
2294 group_item_spacing);
2295
2296 pRoutepointDefaultIconChoice = new OCPNIconCombo(
2297 itemPanelRoutes, wxID_ANY, _("Combo!"), wxDefaultPosition, wxDefaultSize,
2298 0, NULL, wxCB_READONLY);
2299 routepointiconSelect->Add(pRoutepointDefaultIconChoice, 0,
2300 wxALIGN_RIGHT | wxALL, group_item_spacing);
2301
2302 pRoutepointDefaultIconChoice->SetPopupMaxHeight(::wxGetDisplaySize().y / 2);
2303
2304 // Accomodate scaling of icon
2305 int min_size = GetCharHeight() * 2;
2306 min_size = wxMax(min_size, (32 * g_MarkScaleFactorExp) + 4);
2307 pRoutepointDefaultIconChoice->SetMinSize(
2308 wxSize(GetCharHeight() * 15, min_size));
2309
2310 routeSizer->AddSpacer(5);
2311
2312 wxFlexGridSizer* pRouteGrid =
2313 new wxFlexGridSizer(1, 2, group_item_spacing, group_item_spacing);
2314 pRouteGrid->AddGrowableCol(1);
2315 routeSizer->Add(pRouteGrid, 0, wxALL | wxEXPAND, border_size);
2316
2317 wxStaticText* raText = new wxStaticText(
2318 itemPanelRoutes, wxID_STATIC, _("Waypoint Arrival Circle Radius (NMi)"));
2319 pRouteGrid->Add(raText, 1, wxEXPAND | wxALL, group_item_spacing);
2320
2321 m_pText_ACRadius = new wxTextCtrl(itemPanelRoutes, -1, "TEXT ");
2322 pRouteGrid->Add(m_pText_ACRadius, 0, wxALL | wxALIGN_RIGHT,
2323 group_item_spacing);
2324
2325 pAdvanceRouteWaypointOnArrivalOnly =
2326 new wxCheckBox(itemPanelRoutes, ID_DAILYCHECKBOX,
2327 _("Advance route waypoint on arrival only"));
2328 routeSizer->Add(pAdvanceRouteWaypointOnArrivalOnly, 0, wxALL, 5);
2329
2330#ifdef __WXGTK__
2331 Routes->AddSpacer(8 * group_item_spacing);
2332 wxStaticLine* pln =
2333 new wxStaticLine(itemPanelRoutes, wxID_ANY, wxDefaultPosition,
2334 wxDefaultSize, wxLI_HORIZONTAL);
2335 Routes->Add(pln, 0, wxEXPAND);
2336#endif
2337
2338 // Waypoints
2339 wxStaticBox* waypointText =
2340 new wxStaticBox(itemPanelRoutes, wxID_ANY, _("New Waypoints"));
2341 wxStaticBoxSizer* waypointSizer =
2342 new wxStaticBoxSizer(waypointText, wxVERTICAL);
2343 Routes->Add(waypointSizer, 0, wxTOP | wxALL | wxEXPAND, border_size);
2344
2345 waypointSizer->AddSpacer(5);
2346
2347 // Default ICON
2348 wxFlexGridSizer* waypointiconSelect =
2349 new wxFlexGridSizer(1, 2, group_item_spacing, group_item_spacing);
2350 waypointiconSelect->AddGrowableCol(1);
2351 waypointSizer->Add(waypointiconSelect, 0, wxLEFT | wxRIGHT | wxEXPAND,
2352 border_size);
2353
2354 wxStaticText* waypointiconTxt =
2355 new wxStaticText(itemPanelRoutes, wxID_ANY, _("Waypoint default icon"));
2356 waypointiconSelect->Add(waypointiconTxt, 1, wxEXPAND | wxALL,
2357 group_item_spacing);
2358
2359 pWaypointDefaultIconChoice = new OCPNIconCombo(
2360 itemPanelRoutes, wxID_ANY, _("Combo!"), wxDefaultPosition, wxDefaultSize,
2361 0, NULL, wxCB_READONLY);
2362 waypointiconSelect->Add(pWaypointDefaultIconChoice, 0, wxALIGN_RIGHT | wxALL,
2363 group_item_spacing);
2364
2365 pWaypointDefaultIconChoice->SetPopupMaxHeight(::wxGetDisplaySize().y / 2);
2366
2367 // Accomodate scaling of icon
2368 int rmin_size = GetCharHeight() * 2;
2369 min_size = wxMax(rmin_size, (32 * g_MarkScaleFactorExp) + 4);
2370 pWaypointDefaultIconChoice->SetMinSize(
2371 wxSize(GetCharHeight() * 15, rmin_size));
2372
2373 waypointSizer->AddSpacer(5);
2374 // ScaMin
2375 wxFlexGridSizer* ScaMinSizer =
2376 new wxFlexGridSizer(1, 2, group_item_spacing, group_item_spacing);
2377 ScaMinSizer->AddGrowableCol(1);
2378 waypointSizer->Add(ScaMinSizer, 0, wxLEFT | wxRIGHT | wxEXPAND, border_size);
2379 pScaMinChckB =
2380 new wxCheckBox(itemPanelRoutes, wxID_ANY,
2381 _("Show waypoints only at a chartscale greater than 1 :"));
2382 ScaMinSizer->Add(pScaMinChckB, 0);
2383 m_pText_ScaMin = new wxTextCtrl(itemPanelRoutes, -1, "TEXTTEXTTEXT");
2384 ScaMinSizer->Add(m_pText_ScaMin, 0, wxALL | wxALIGN_RIGHT,
2385 group_item_spacing);
2386
2387 // Overrule the Scamin settings
2388 pScaMinOverruleChckB =
2389 new wxCheckBox(itemPanelRoutes, wxID_ANY,
2390 _("Override the settings for chartscale based visibility "
2391 "and show always"));
2392 waypointSizer->Add(pScaMinOverruleChckB, 0, wxALL, 5);
2393
2394 waypointSizer->AddSpacer(5);
2395 // Range Rings
2396 wxFlexGridSizer* waypointrrSelect =
2397 new wxFlexGridSizer(1, 2, group_item_spacing, group_item_spacing);
2398 waypointrrSelect->AddGrowableCol(1);
2399 waypointSizer->Add(waypointrrSelect, 0, wxLEFT | wxRIGHT | wxEXPAND,
2400 border_size);
2401
2402 wxStaticText* waypointrrTxt =
2403 new wxStaticText(itemPanelRoutes, wxID_ANY, _("Waypoint range rings"));
2404 waypointrrSelect->Add(waypointrrTxt, 1, wxEXPAND | wxALL, group_item_spacing);
2405
2406 pWaypointRangeRingsNumber =
2407 new wxChoice(itemPanelRoutes, ID_OPWAYPOINTRANGERINGS, wxDefaultPosition,
2408 m_pShipIconType->GetSize(), 11, rrAlt);
2409 waypointrrSelect->Add(pWaypointRangeRingsNumber, 0, wxALIGN_RIGHT | wxALL,
2410 group_item_spacing);
2411
2412 waypointradarGrid =
2413 new wxFlexGridSizer(0, 2, group_item_spacing, group_item_spacing);
2414 waypointradarGrid->AddGrowableCol(1);
2415 waypointSizer->Add(waypointradarGrid, 0, wxLEFT | wxEXPAND, 30);
2416
2417 wxStaticText* waypointdistanceText = new wxStaticText(
2418 itemPanelRoutes, wxID_STATIC, _("Distance between rings"));
2419 waypointradarGrid->Add(waypointdistanceText, 1, wxEXPAND | wxALL,
2420 group_item_spacing);
2421
2422 pWaypointRangeRingsStep =
2423 new wxTextCtrl(itemPanelRoutes, ID_OPTEXTCTRL, _T(""), wxDefaultPosition,
2424 wxSize(100, -1), 0);
2425 waypointradarGrid->Add(pWaypointRangeRingsStep, 0, wxALIGN_RIGHT | wxALL,
2426 group_item_spacing);
2427
2428 wxStaticText* waypointunitText =
2429 new wxStaticText(itemPanelRoutes, wxID_STATIC, _("Distance Unit"));
2430 waypointradarGrid->Add(waypointunitText, 1, wxEXPAND | wxALL,
2431 group_item_spacing);
2432
2433 m_itemWaypointRangeRingsUnits =
2434 new wxChoice(itemPanelRoutes, ID_RADARDISTUNIT, wxDefaultPosition,
2435 m_pShipIconType->GetSize(), 2, pDistUnitsStrings);
2436 waypointradarGrid->Add(m_itemWaypointRangeRingsUnits, 0,
2437 wxALIGN_RIGHT | wxALL, border_size);
2438
2439 wxStaticText* waypointrangeringsColour = new wxStaticText(
2440 itemPanelRoutes, wxID_STATIC, _("Waypoint Range Ring Colours"));
2441 waypointradarGrid->Add(waypointrangeringsColour, 1, wxEXPAND | wxALL, 1);
2442
2443 m_colourWaypointRangeRingsColour = new OCPNColourPickerCtrl(
2444 itemPanelRoutes, wxID_ANY, *wxRED, wxDefaultPosition,
2445 m_colourPickerDefaultSize, 0, wxDefaultValidator,
2446 _T( "ID_COLOURWAYPOINTRANGERINGSCOLOUR" ));
2447 waypointradarGrid->Add(m_colourWaypointRangeRingsColour, 0,
2448 wxALIGN_RIGHT | wxALL, 1);
2449
2450 // Control Options
2451
2452#ifdef __WXGTK__
2453 Routes->AddSpacer(8 * group_item_spacing);
2454 wxStaticLine* pln1 =
2455 new wxStaticLine(itemPanelRoutes, wxID_ANY, wxDefaultPosition,
2456 wxDefaultSize, wxLI_HORIZONTAL);
2457 Routes->Add(pln1, 0, wxEXPAND);
2458#endif
2459
2460 wxStaticBox* waypointControl =
2461 new wxStaticBox(itemPanelRoutes, wxID_ANY, _("Control Options"));
2462 wxStaticBoxSizer* ControlSizer =
2463 new wxStaticBoxSizer(waypointControl, wxVERTICAL);
2464 Routes->Add(ControlSizer, 0, wxTOP | wxALL | wxEXPAND, border_size);
2465
2466 ControlSizer->AddSpacer(5);
2467
2468 pWayPointPreventDragging = new wxCheckBox(
2469 itemPanelRoutes, ID_DRAGGINGCHECKBOX,
2470 _("Lock Waypoints (Unless waypoint property dialog visible)"));
2471 pWayPointPreventDragging->SetValue(FALSE);
2472 ControlSizer->Add(pWayPointPreventDragging, verticleInputFlags);
2473
2474 pConfirmObjectDeletion =
2475 new wxCheckBox(itemPanelRoutes, ID_DELETECHECKBOX,
2476 _("Confirm deletion of tracks and routes"));
2477 pConfirmObjectDeletion->SetValue(FALSE);
2478 ControlSizer->Add(pConfirmObjectDeletion, verticleInputFlags);
2479 ControlSizer->AddSpacer(5);
2480
2481 // Fill the default waypoint icon selector combo box
2482 pWaypointDefaultIconChoice->Clear();
2483 // Iterate on the Icon Descriptions, filling in the combo control
2484 bool fillCombo = true;
2485
2486 if (fillCombo) {
2487 for (int i = 0; i < pWayPointMan->GetNumIcons(); i++) {
2488 wxString* ps = pWayPointMan->GetIconDescription(i);
2489 wxBitmap bmp = pWayPointMan->GetIconBitmapForList(i, 2 * GetCharHeight());
2490
2491 pWaypointDefaultIconChoice->Append(*ps, bmp);
2492 }
2493 }
2494
2495 // find the correct item in the combo box
2496 int iconToSelect = -1;
2497 for (int i = 0; i < pWayPointMan->GetNumIcons(); i++) {
2498 if (*pWayPointMan->GetIconKey(i) == g_default_wp_icon) {
2499 iconToSelect = i;
2500 pWaypointDefaultIconChoice->Select(iconToSelect);
2501 break;
2502 }
2503 }
2504
2505 // Fill the default Routepoint icon selector combo box
2506 pRoutepointDefaultIconChoice->Clear();
2507 // Iterate on the Icon Descriptions, filling in the combo control
2508 fillCombo = true;
2509
2510 if (fillCombo) {
2511 for (int i = 0; i < pWayPointMan->GetNumIcons(); i++) {
2512 wxString* ps = pWayPointMan->GetIconDescription(i);
2513 wxBitmap bmp = pWayPointMan->GetIconBitmapForList(i, 2 * GetCharHeight());
2514
2515 pRoutepointDefaultIconChoice->Append(*ps, bmp);
2516 }
2517 }
2518
2519 // find the correct item in the combo box
2520 iconToSelect = -1;
2521 for (int i = 0; i < pWayPointMan->GetNumIcons(); i++) {
2522 if (*pWayPointMan->GetIconKey(i) == g_default_routepoint_icon) {
2523 iconToSelect = i;
2524 pRoutepointDefaultIconChoice->Select(iconToSelect);
2525 break;
2526 }
2527 }
2528
2529 // DimeControl(itemPanelRoutes);
2530}
2531
2532void options::CreatePanel_ChartsLoad(size_t parent, int border_size,
2533 int group_item_spacing) {
2534 chartPanelWin = AddPage(m_pageCharts, _("Chart Files"));
2535
2536 chartPanel = new wxBoxSizer(wxVERTICAL);
2537 chartPanelWin->SetSizer(chartPanel);
2538
2539 loadedBox = new wxStaticBox(chartPanelWin, wxID_ANY, _("Directories"));
2540 activeSizer = new wxStaticBoxSizer(loadedBox, wxHORIZONTAL);
2541 chartPanel->Add(activeSizer, 1, wxALL | wxEXPAND, border_size);
2542
2543 m_scrollWinChartList = new wxScrolledWindow(
2544 chartPanelWin, wxID_ANY, wxDefaultPosition,
2545 wxDLG_UNIT(this, wxSize(-1, -1)), wxBORDER_RAISED | wxVSCROLL);
2546
2547 activeSizer->Add(m_scrollWinChartList, 1, wxALL | wxEXPAND, 5);
2548
2549#ifndef __OCPN__ANDROID__
2550 m_scrollRate = 5;
2551#else
2552 m_scrollRate = 1;
2553#endif
2554 m_scrollWinChartList->SetScrollRate(m_scrollRate, m_scrollRate);
2555
2556 boxSizerCharts = new wxBoxSizer(wxVERTICAL);
2557 m_scrollWinChartList->SetSizer(boxSizerCharts);
2558
2559 cmdButtonSizer = new wxBoxSizer(wxVERTICAL);
2560 activeSizer->Add(cmdButtonSizer, 0, wxALL, border_size);
2561
2562 wxString b1 = _("Add Directory...");
2563 wxString b2 = _("Remove Selected");
2564 wxString b3 = _("Compress Selected");
2565
2566 if (m_bcompact) {
2567 b1 = _("Add..");
2568 b2 = _("Remove");
2569 b3 = _("Compress");
2570 }
2571
2572 wxButton* addBtn = new wxButton(chartPanelWin, ID_BUTTONADD, b1);
2573 cmdButtonSizer->Add(addBtn, 1, wxALL | wxEXPAND, group_item_spacing);
2574
2575 cmdButtonSizer->AddSpacer(GetCharHeight());
2576
2577 m_removeBtn = new wxButton(chartPanelWin, ID_BUTTONDELETE, b2);
2578 cmdButtonSizer->Add(m_removeBtn, 1, wxALL | wxEXPAND, group_item_spacing);
2579 m_removeBtn->Disable();
2580
2581 cmdButtonSizer->AddSpacer(GetCharHeight());
2582
2583#ifdef OCPN_USE_LZMA
2584 m_compressBtn = new wxButton(chartPanelWin, ID_BUTTONCOMPRESS, b3);
2585 cmdButtonSizer->Add(m_compressBtn, 1, wxALL | wxEXPAND, group_item_spacing);
2586 m_compressBtn->Disable();
2587#else
2588 m_compressBtn = NULL;
2589#endif
2590
2591#ifdef __OCPN__ANDROID__
2592 if (g_Android_SDK_Version >= 30) {
2593 m_migrateBtn =
2594 new wxButton(chartPanelWin, ID_BUTTONMIGRATE, _("Migrate Charts.."));
2595 cmdButtonSizer->Add(m_migrateBtn, 1, wxALL | wxEXPAND, group_item_spacing);
2596 }
2597#endif
2598
2599 cmdButtonSizer->AddSpacer(GetCharHeight());
2600
2601 wxStaticBox* itemStaticBoxUpdateStatic =
2602 new wxStaticBox(chartPanelWin, wxID_ANY, _("Update Control"));
2603 wxStaticBoxSizer* itemStaticBoxSizerUpdate =
2604 new wxStaticBoxSizer(itemStaticBoxUpdateStatic, wxVERTICAL);
2605 chartPanel->Add(itemStaticBoxSizerUpdate, 0, wxGROW | wxALL, 5);
2606
2607 wxFlexGridSizer* itemFlexGridSizerUpdate = new wxFlexGridSizer(1);
2608 itemFlexGridSizerUpdate->SetFlexibleDirection(wxHORIZONTAL);
2609
2610 pScanCheckBox = new wxCheckBox(chartPanelWin, ID_SCANCHECKBOX,
2611 _("Scan Charts and Update Database"));
2612 itemFlexGridSizerUpdate->Add(pScanCheckBox, 1, wxALL, 5);
2613
2614 pUpdateCheckBox = new wxCheckBox(chartPanelWin, ID_UPDCHECKBOX,
2615 _("Force Full Database Rebuild"));
2616 itemFlexGridSizerUpdate->Add(pUpdateCheckBox, 1, wxALL, 5);
2617
2618 pParseENCButton = new wxButton(chartPanelWin, ID_PARSEENCBUTTON,
2619 _("Prepare all ENC Charts"));
2620 itemFlexGridSizerUpdate->Add(pParseENCButton, 1, wxALL, 5);
2621
2622 itemStaticBoxSizerUpdate->Add(itemFlexGridSizerUpdate, 1, wxEXPAND, 5);
2623
2624 // Currently loaded chart dirs
2625 ActiveChartArray.Clear();
2626 for (size_t i = 0; i < m_CurrentDirList.GetCount(); i++) {
2627 ActiveChartArray.Add(m_CurrentDirList[i]);
2628 }
2629
2630 UpdateChartDirList();
2631
2632 chartPanel->Layout();
2633}
2634
2635void options::UpdateChartDirList() {
2636 // Clear the sizer, and delete all the child panels
2637 m_scrollWinChartList->GetSizer()->Clear(true);
2638 m_scrollWinChartList->ClearBackground();
2639
2640 panelVector.clear();
2641
2642 // Add new panels
2643 for (size_t i = 0; i < ActiveChartArray.GetCount(); i++) {
2644 OCPNChartDirPanel* chartPanel =
2645 new OCPNChartDirPanel(m_scrollWinChartList, wxID_ANY, wxDefaultPosition,
2646 wxSize(-1, -1), ActiveChartArray[i]);
2647 chartPanel->SetSelected(false);
2648
2649 m_scrollWinChartList->GetSizer()->Add(chartPanel, 0, wxEXPAND | wxALL, 0);
2650
2651 panelVector.push_back(chartPanel);
2652 }
2653
2654 m_scrollWinChartList->GetSizer()->Layout();
2655
2656 chartPanelWin->ClearBackground();
2657 chartPanelWin->Layout();
2658
2659 // There are some problems with wxScrolledWindow after add/removing items.
2660 // Typically, the problem is that blank space remains at the top of the
2661 // scrollable range of the window.
2662 // Workarounds here...
2663 // n.b. according to wx docs, none of this should be necessary...
2664#ifdef __OCPN__ANDROID__
2665 // This works on Android, but seems pretty drastic
2666 wxSize sza = GetSize();
2667 sza.y -= 1;
2668 SetSize(sza);
2669#else
2670 // This works, except on Android
2671 m_scrollWinChartList->GetParent()->Layout();
2672#endif
2673
2674 m_scrollWinChartList->Scroll(0, 0);
2675}
2676
2677void options::UpdateTemplateTitleText() {
2678 if (!m_templateTitleText) return;
2679
2680 wxString activeTitle;
2681 if (!g_lastAppliedTemplateGUID.IsEmpty()) {
2682 activeTitle = ConfigMgr::Get().GetTemplateTitle(g_lastAppliedTemplateGUID);
2683
2684 bool configCompare =
2685 ConfigMgr::Get().CheckTemplateGUID(g_lastAppliedTemplateGUID);
2686 if (!configCompare) activeTitle += _(" [Modified]");
2687 m_templateTitleText->SetLabel(activeTitle);
2688 } else
2689 m_templateTitleText->SetLabel(_("None"));
2690}
2691
2692void options::CreatePanel_Configs(size_t parent, int border_size,
2693 int group_item_spacing) {
2694 m_DisplayConfigsPage = AddPage(parent, _("Templates"));
2695
2696 // if (m_bcompact) {
2697 //}
2698 // else
2699 {
2700 wxBoxSizer* wrapperSizer = new wxBoxSizer(wxVERTICAL);
2701 m_DisplayConfigsPage->SetSizer(wrapperSizer);
2702
2703 // Template management
2704
2705 wxStaticBox* templateStatusBox =
2706 new wxStaticBox(m_DisplayConfigsPage, wxID_ANY, _("Template Status"));
2707 m_templateStatusBoxSizer =
2708 new wxStaticBoxSizer(templateStatusBox, wxHORIZONTAL);
2709 wrapperSizer->Add(m_templateStatusBoxSizer, 1, wxALL | wxEXPAND,
2710 border_size);
2711
2712 wxBoxSizer* statSizer = new wxBoxSizer(wxVERTICAL);
2713 m_templateStatusBoxSizer->Add(statSizer, 0, wxALL | wxEXPAND, border_size);
2714
2715 m_staticTextLastAppled = new wxStaticText(
2716 m_DisplayConfigsPage, wxID_ANY, _("Last Applied Template Title:"));
2717 m_staticTextLastAppled->Hide();
2718
2719 statSizer->Add(m_staticTextLastAppled);
2720
2721 m_templateTitleText =
2722 new wxStaticText(m_DisplayConfigsPage, wxID_ANY, wxEmptyString);
2723 statSizer->Add(m_templateTitleText);
2724 m_templateTitleText->Hide();
2725
2726 UpdateTemplateTitleText();
2727
2728 wxStaticBox* configsBox =
2729 new wxStaticBox(m_DisplayConfigsPage, wxID_ANY, _("Saved Templates"));
2730 wxStaticBoxSizer* configSizer =
2731 new wxStaticBoxSizer(configsBox, wxHORIZONTAL);
2732 wrapperSizer->Add(configSizer, 4, wxALL | wxEXPAND, border_size);
2733
2734 wxPanel* cPanel = new wxPanel(m_DisplayConfigsPage, wxID_ANY);
2735 configSizer->Add(cPanel, 1, wxALL | wxEXPAND, border_size);
2736
2737 wxBoxSizer* boxSizercPanel = new wxBoxSizer(wxVERTICAL);
2738 cPanel->SetSizer(boxSizercPanel);
2739
2740 m_scrollWinConfigList =
2741 new wxScrolledWindow(cPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2742 wxBORDER_RAISED | wxVSCROLL);
2743 m_scrollWinConfigList->SetScrollRate(1, 1);
2744 boxSizercPanel->Add(m_scrollWinConfigList, 0, wxALL | wxEXPAND,
2745 border_size);
2746 m_scrollWinConfigList->SetMinSize(wxSize(-1, 15 * GetCharHeight()));
2747
2748 m_boxSizerConfigs = new wxBoxSizer(wxVERTICAL);
2749 m_scrollWinConfigList->SetSizer(m_boxSizerConfigs);
2750
2751 wxBoxSizer* btnSizer = new wxBoxSizer(wxVERTICAL);
2752 configSizer->Add(btnSizer);
2753
2754 // Add the "Insert/Remove" buttons
2755 wxButton* createButton =
2756 new wxButton(m_DisplayConfigsPage, wxID_ANY, _("Create Config..."));
2757 btnSizer->Add(createButton, 1, wxALL | wxEXPAND, group_item_spacing);
2758 createButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2759 wxCommandEventHandler(options::OnCreateConfig), NULL,
2760 this);
2761
2762 // wxButton* editButton = new wxButton(m_DisplayConfigsPage, wxID_ANY,
2763 // _("Edit Config...")); btnSizer->Add(editButton, 1, wxALL | wxEXPAND,
2764 // group_item_spacing); editButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2765 // wxCommandEventHandler(options::OnEditConfig), NULL, this);
2766
2767 m_configDeleteButton = new wxButton(m_DisplayConfigsPage, wxID_ANY,
2768 _("Delete Selected Config..."));
2769 btnSizer->Add(m_configDeleteButton, 1, wxALL | wxEXPAND,
2770 group_item_spacing);
2771 m_configDeleteButton->Connect(
2772 wxEVT_COMMAND_BUTTON_CLICKED,
2773 wxCommandEventHandler(options::OnDeleteConfig), NULL, this);
2774
2775 m_configApplyButton = new wxButton(m_DisplayConfigsPage, wxID_ANY,
2776 _("Apply Selected Config"));
2777 btnSizer->Add(m_configApplyButton, 1, wxALL | wxEXPAND, group_item_spacing);
2778 m_configApplyButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2779 wxCommandEventHandler(options::OnApplyConfig),
2780 NULL, this);
2781
2782 // Populate the configs list from the ConfigMgr
2783 ClearConfigList();
2784 BuildConfigList();
2785
2786 SetConfigButtonState();
2787 }
2788}
2789
2790void options::ClearConfigList() {
2791 if (m_scrollWinConfigList) {
2792 wxWindowList kids = m_scrollWinConfigList->GetChildren();
2793 for (unsigned int i = 0; i < kids.GetCount(); i++) {
2794 wxWindowListNode* node = kids.Item(i);
2795 wxWindow* win = node->GetData();
2796 wxPanel* pcp = wxDynamicCast(win, wxPanel);
2797 if (pcp) {
2798 ConfigPanel* cPanel = wxDynamicCast(pcp, ConfigPanel);
2799 if (cPanel) {
2800 cPanel->Destroy();
2801 }
2802 }
2803 }
2804 }
2805 SetConfigButtonState();
2806}
2807
2808void options::BuildConfigList() {
2809 wxArrayString configGUIDs = ConfigMgr::Get().GetConfigGUIDArray();
2810
2811 for (size_t i = 0; i < configGUIDs.GetCount(); i++) {
2812 wxPanel* pp =
2813 ConfigMgr::Get().GetConfigPanel(m_scrollWinConfigList, configGUIDs[i]);
2814 if (pp) {
2815 m_panelBackgroundUnselected = pp->GetBackgroundColour();
2816 m_boxSizerConfigs->Add(pp, 1, wxEXPAND);
2817 pp->Connect(wxEVT_LEFT_DOWN,
2818 wxMouseEventHandler(options::OnConfigMouseSelected), NULL,
2819 this);
2820
2821 // Set mouse handler for children of the panel, too.
2822 wxWindowList kids = pp->GetChildren();
2823 for (unsigned int i = 0; i < kids.GetCount(); i++) {
2824 wxWindowListNode* node = kids.Item(i);
2825 wxWindow* win = node->GetData();
2826 win->Connect(wxEVT_LEFT_DOWN,
2827 wxMouseEventHandler(options::OnConfigMouseSelected), NULL,
2828 this);
2829 }
2830 }
2831 }
2832
2833 m_boxSizerConfigs->Layout();
2834
2835 m_selectedConfigPanelGUID = _T("");
2836 SetConfigButtonState();
2837}
2838
2839void options::SetConfigButtonState() {
2840 m_configDeleteButton->Enable(!m_selectedConfigPanelGUID.IsEmpty());
2841 if (m_selectedConfigPanelGUID.StartsWith(
2842 _T("11111111"))) // Cannot delete "Recovery" template
2843 m_configDeleteButton->Disable();
2844 m_configApplyButton->Enable(!m_selectedConfigPanelGUID.IsEmpty());
2845}
2846
2847void options::OnCreateConfig(wxCommandEvent& event) {
2849 this, -1, _("Create Config"), wxDefaultPosition, wxSize(200, 200));
2850 DimeControl(pd);
2851 pd->ShowWindowModalThenDo([this, pd](int retcode) {
2852 if (retcode == wxID_OK) {
2853 g_lastAppliedTemplateGUID = pd->GetCreatedTemplateGUID();
2854 UpdateTemplateTitleText();
2855
2856 ClearConfigList();
2857 BuildConfigList();
2858 m_DisplayConfigsPage->Layout();
2859 }
2860 SetConfigButtonState();
2861 });
2862}
2863
2864void options::OnEditConfig(wxCommandEvent& event) {}
2865
2866void options::OnDeleteConfig(wxCommandEvent& event) {
2867 if (m_selectedConfigPanelGUID.IsEmpty()) return;
2868
2869 ConfigMgr::Get().DeleteConfig(m_selectedConfigPanelGUID);
2870 m_selectedConfigPanelGUID = _T("");
2871
2872 ClearConfigList();
2873 BuildConfigList();
2874
2875 m_DisplayConfigsPage->Layout();
2876 SetConfigButtonState();
2877}
2878
2879void options::OnApplyConfig(wxCommandEvent& event) {
2880 if (m_selectedConfigPanelGUID.IsEmpty()) return;
2881
2882 // Record a few special items
2883 wxString currentLocale = g_locale;
2884
2885 // Apply any changed settings other than the target config template.
2886 wxCommandEvent evt;
2887 evt.SetId(ID_APPLY);
2888 OnApplyClick(evt);
2889
2890 // Then Apply the target config template
2891 bool bApplyStat = ConfigMgr::Get().ApplyConfigGUID(m_selectedConfigPanelGUID);
2892 if (bApplyStat) {
2893 // OCPNMessageBox(this, _("Configuration successfully applied."),
2894 // _("OpenCPN Info"), wxOK);
2895 g_lastAppliedTemplateGUID = m_selectedConfigPanelGUID;
2896 wxString activeTitle =
2897 ConfigMgr::Get().GetTemplateTitle(g_lastAppliedTemplateGUID);
2898 m_templateTitleText->SetLabel(activeTitle);
2899 m_templateTitleText->Show();
2900 m_staticTextLastAppled->Show();
2901 m_templateStatusBoxSizer->Layout();
2902 } else
2903 OCPNMessageBox(this, _("Problem applying selected configuration."),
2904 _("OpenCPN Info"), wxOK);
2905
2906 // Clear all selections
2907 if (m_scrollWinConfigList) {
2908 wxWindowList kids = m_scrollWinConfigList->GetChildren();
2909 for (unsigned int i = 0; i < kids.GetCount(); i++) {
2910 wxWindowListNode* node = kids.Item(i);
2911 wxWindow* win = node->GetData();
2912 wxPanel* pcp = wxDynamicCast(win, wxPanel);
2913 if (pcp) {
2914 ConfigPanel* cPanel = wxDynamicCast(pcp, ConfigPanel);
2915 if (cPanel) {
2916 cPanel->SetBackgroundColour(m_panelBackgroundUnselected);
2917 }
2918 }
2919 }
2920 }
2921 m_selectedConfigPanelGUID = wxEmptyString;
2922
2923 m_returnChanges |= CONFIG_CHANGED;
2924
2925 if (!currentLocale.IsSameAs(g_locale)) m_returnChanges |= LOCALE_CHANGED;
2926
2927 Finish();
2928}
2929
2930void options::OnConfigMouseSelected(wxMouseEvent& event) {
2931 wxPanel* selectedPanel = NULL;
2932 wxObject* obj = event.GetEventObject();
2933 if (obj) {
2934 wxPanel* panel = wxDynamicCast(obj, wxPanel);
2935 if (panel) {
2936 selectedPanel = panel;
2937 }
2938 // Clicked on child?
2939 else {
2940 wxWindow* win = wxDynamicCast(obj, wxWindow);
2941 if (win) {
2942 wxPanel* parentpanel = wxDynamicCast(win->GetParent(), wxPanel);
2943 if (parentpanel) {
2944 selectedPanel = parentpanel;
2945 }
2946 }
2947 }
2948
2949 if (m_scrollWinConfigList) {
2950 wxWindowList kids = m_scrollWinConfigList->GetChildren();
2951 for (unsigned int i = 0; i < kids.GetCount(); i++) {
2952 wxWindowListNode* node = kids.Item(i);
2953 wxWindow* win = node->GetData();
2954 wxPanel* panel = wxDynamicCast(win, wxPanel);
2955 if (panel) {
2956 if (panel == selectedPanel) {
2957 wxColour colour;
2958 GetGlobalColor(_T("UIBCK"), &colour);
2959 panel->SetBackgroundColour(colour);
2960 ConfigPanel* cPanel = wxDynamicCast(panel, ConfigPanel);
2961 if (cPanel) m_selectedConfigPanelGUID = cPanel->GetConfigGUID();
2962 } else
2963 panel->SetBackgroundColour(m_panelBackgroundUnselected);
2964
2965 panel->Refresh(true);
2966 }
2967 }
2968 }
2969 m_DisplayConfigsPage->Layout();
2970 SetConfigButtonState();
2971 }
2972}
2973
2974void options::CreatePanel_Advanced(size_t parent, int border_size,
2975 int group_item_spacing) {
2976 m_ChartDisplayPage = AddPage(parent, _("Advanced"));
2977
2978 if (m_bcompact) {
2979 wxSize sz = g_Platform->getDisplaySize();
2980 double dpmm = g_Platform->GetDisplayDPmm();
2981
2982 wxBoxSizer* wrapperSizer = new wxBoxSizer(wxVERTICAL);
2983 m_ChartDisplayPage->SetSizer(wrapperSizer);
2984
2985 wxBoxSizer* itemBoxSizerUI = wrapperSizer;
2986
2987 // spacer
2988 itemBoxSizerUI->Add(0, border_size * 3);
2989 itemBoxSizerUI->Add(0, border_size * 3);
2990
2991 // Chart Display Options
2992 wxBoxSizer* boxCharts = new wxBoxSizer(wxVERTICAL);
2993 itemBoxSizerUI->Add(boxCharts, groupInputFlags);
2994
2995 pSkewComp = new wxCheckBox(m_ChartDisplayPage, ID_SKEWCOMPBOX,
2996 _("De-skew Raster Charts"));
2997 boxCharts->Add(pSkewComp, inputFlags);
2998
2999 itemBoxSizerUI->Add(0, border_size * 3);
3000 itemBoxSizerUI->Add(0, border_size * 3);
3001
3002 // OpenGL Options
3003 wxBoxSizer* OpenGLSizer = new wxBoxSizer(wxVERTICAL);
3004 itemBoxSizerUI->Add(OpenGLSizer, 0, 0, 0);
3005
3006 pOpenGL = new wxCheckBox(m_ChartDisplayPage, ID_OPENGLBOX,
3007 _("Use Accelerated Graphics (OpenGL)"));
3008 OpenGLSizer->Add(pOpenGL, inputFlags);
3009 pOpenGL->Enable(!g_bdisable_opengl && g_Platform->IsGLCapable());
3010
3011 wxButton* bOpenGL = new wxButton(m_ChartDisplayPage, ID_OPENGLOPTIONS,
3012 _("OpenGL Options") + _T("..."));
3013 OpenGLSizer->Add(bOpenGL, inputFlags);
3014 bOpenGL->Enable(!g_bdisable_opengl && g_Platform->IsGLCapable());
3015
3016#ifdef __OCPN__ANDROID__
3017 pOpenGL->Hide();
3018 bOpenGL->Hide();
3019#endif
3020
3021 itemBoxSizerUI->Add(0, border_size * 3);
3022 itemBoxSizerUI->Add(0, border_size * 3);
3023
3024 // Course Up display update period
3025 wxStaticText* crat = new wxStaticText(m_ChartDisplayPage, wxID_ANY,
3026 _("Chart Rotation Averaging Time"));
3027 crat->Wrap(-1);
3028 wrapperSizer->Add(crat, 0,
3029 wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL,
3030 group_item_spacing);
3031
3032 wxBoxSizer* pCOGUPFilterRow = new wxBoxSizer(wxHORIZONTAL);
3033 wrapperSizer->Add(pCOGUPFilterRow, 0, wxALL | wxEXPAND, group_item_spacing);
3034
3035 pCOGUPUpdateSecs =
3036 new wxTextCtrl(m_ChartDisplayPage, ID_OPTEXTCTRL, _T(""),
3037 wxDefaultPosition, wxSize(sz.x / 5, -1), wxTE_RIGHT);
3038 pCOGUPFilterRow->Add(pCOGUPUpdateSecs, 0, wxALIGN_RIGHT | wxALL,
3039 group_item_spacing);
3040
3041 pCOGUPFilterRow->Add(
3042 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("seconds")),
3043 inputFlags);
3044
3045 itemBoxSizerUI->Add(0, border_size * 3);
3046 itemBoxSizerUI->Add(0, border_size * 3);
3047
3048 // Chart Zoom Scale Weighting
3049 wxStaticText* zoomTextHead = new wxStaticText(
3050 m_ChartDisplayPage, wxID_ANY, _("Chart Zoom/Scale Weighting"));
3051 zoomTextHead->Wrap(-1);
3052 itemBoxSizerUI->Add(
3053 zoomTextHead, 0,
3054 wxALL | wxEXPAND | wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL,
3055 group_item_spacing);
3056 itemBoxSizerUI->Add(0, border_size * 1);
3057
3058 itemBoxSizerUI->Add(
3059 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("Raster")),
3060 inputFlags);
3061
3062 m_pSlider_Zoom_Raster =
3063 new wxSlider(m_ChartDisplayPage, ID_RASTERZOOM, 0, -5, 5,
3064 wxDefaultPosition, m_sliderSize, SLIDER_STYLE);
3065
3066#ifdef __OCPN__ANDROID__
3067 prepareSlider(m_pSlider_Zoom_Raster);
3068#endif
3069
3070 itemBoxSizerUI->Add(m_pSlider_Zoom_Raster, inputFlags);
3071
3072 itemBoxSizerUI->Add(
3073 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("Vector")),
3074 inputFlags);
3075
3076 m_pSlider_Zoom_Vector =
3077 new wxSlider(m_ChartDisplayPage, ID_VECZOOM, 0, -5, 5,
3078 wxDefaultPosition, m_sliderSize, SLIDER_STYLE);
3079
3080#ifdef __OCPN__ANDROID__
3081 prepareSlider(m_pSlider_Zoom_Vector);
3082#endif
3083
3084 itemBoxSizerUI->Add(m_pSlider_Zoom_Vector, inputFlags);
3085
3086 itemBoxSizerUI->Add(
3087 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("CM93 Detail level")),
3088 inputFlags);
3089 m_pSlider_CM93_Zoom =
3090 new wxSlider(m_ChartDisplayPage, ID_CM93ZOOM, 0,
3091 -CM93_ZOOM_FACTOR_MAX_RANGE, CM93_ZOOM_FACTOR_MAX_RANGE,
3092 wxDefaultPosition, m_sliderSize, SLIDER_STYLE);
3093
3094#ifdef __OCPN__ANDROID__
3095 prepareSlider(m_pSlider_CM93_Zoom);
3096#endif
3097
3098 itemBoxSizerUI->Add(m_pSlider_CM93_Zoom, 0, wxALL, border_size);
3099
3100 itemBoxSizerUI->Add(0, border_size * 3);
3101 itemBoxSizerUI->Add(0, border_size * 3);
3102 itemBoxSizerUI->Add(0, border_size * 3);
3103
3104 // Display size/DPI
3105 itemBoxSizerUI->Add(new wxStaticText(m_ChartDisplayPage, wxID_ANY,
3106 _("Physical Screen Width")),
3107 inputFlags);
3108 wxBoxSizer* pDPIRow = new wxBoxSizer(wxHORIZONTAL);
3109 itemBoxSizerUI->Add(pDPIRow, 0, wxEXPAND);
3110
3111 pRBSizeAuto = new wxRadioButton(m_ChartDisplayPage, wxID_ANY, _("Auto"));
3112 pDPIRow->Add(pRBSizeAuto, inputFlags);
3113 pDPIRow->AddSpacer(10);
3114 pRBSizeManual = new wxRadioButton(m_ChartDisplayPage,
3115 ID_SIZEMANUALRADIOBUTTON, _("Manual:"));
3116 pDPIRow->Add(pRBSizeManual, inputFlags);
3117
3118 wxBoxSizer* pmmRow = new wxBoxSizer(wxHORIZONTAL);
3119 itemBoxSizerUI->Add(pmmRow, 0, wxEXPAND);
3120
3121 pScreenMM =
3122 new wxTextCtrl(m_ChartDisplayPage, ID_OPTEXTCTRL, _T(""),
3123 wxDefaultPosition, wxSize(sz.x / 5, -1), wxTE_RIGHT);
3124 pmmRow->Add(pScreenMM, 0, wxALIGN_RIGHT | wxALL, group_item_spacing);
3125
3126 pmmRow->Add(new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("mm")),
3127 inputFlags);
3128
3129 pRBSizeAuto->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
3130 wxCommandEventHandler(options::OnSizeAutoButton), NULL,
3131 this);
3132 pRBSizeManual->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
3133 wxCommandEventHandler(options::OnSizeManualButton),
3134 NULL, this);
3135
3136 }
3137
3138 else {
3139 wxFlexGridSizer* itemBoxSizerUI = new wxFlexGridSizer(2);
3140 itemBoxSizerUI->SetHGap(border_size);
3141 // itemBoxSizerUI->AddGrowableCol( 0, 1 );
3142 // itemBoxSizerUI->AddGrowableCol( 1, 1 );
3143 // m_ChartDisplayPage->SetSizer( itemBoxSizerUI );
3144
3145 // wxFlexGridSizer grows wrongly in wx2.8, so we need to centre it in
3146 // another sizer instead of letting it grow.
3147 wxBoxSizer* wrapperSizer = new wxBoxSizer(wxVERTICAL);
3148 m_ChartDisplayPage->SetSizer(wrapperSizer);
3149 wrapperSizer->Add(itemBoxSizerUI, 1, wxALL | wxALIGN_CENTER, border_size);
3150
3151 // spacer
3152 itemBoxSizerUI->Add(0, border_size * 3);
3153 itemBoxSizerUI->Add(0, border_size * 3);
3154
3155 // Chart Display Options
3156 itemBoxSizerUI->Add(
3157 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("Chart Display")),
3158 groupLabelFlags);
3159 wxBoxSizer* boxCharts = new wxBoxSizer(wxVERTICAL);
3160 itemBoxSizerUI->Add(boxCharts, groupInputFlags);
3161
3162 pSkewComp = new wxCheckBox(m_ChartDisplayPage, ID_SKEWCOMPBOX,
3163 _("Show Skewed Raster Charts as North-Up"));
3164 boxCharts->Add(pSkewComp, verticleInputFlags);
3165
3166 // pFullScreenQuilt = new wxCheckBox(m_ChartDisplayPage,
3167 // ID_FULLSCREENQUILT,
3168 // _("Disable Full Screen Quilting"));
3169 // boxCharts->Add(pFullScreenQuilt, verticleInputFlags);
3170
3171 // pOverzoomEmphasis =
3172 // new wxCheckBox(m_ChartDisplayPage, ID_FULLSCREENQUILT,
3173 // _("Suppress blur/fog effects on overzoom"));
3174 // boxCharts->Add(pOverzoomEmphasis, verticleInputFlags);
3175 //
3176 // pOZScaleVector =
3177 // new wxCheckBox(m_ChartDisplayPage, ID_FULLSCREENQUILT,
3178 // _("Suppress scaled vector charts on overzoom"));
3179 // boxCharts->Add(pOZScaleVector, verticleInputFlags);
3180
3181 // spacer
3182 itemBoxSizerUI->Add(0, border_size * 3);
3183 itemBoxSizerUI->Add(0, border_size * 3);
3184
3185 // Course Up display update period
3186 itemBoxSizerUI->Add(new wxStaticText(m_ChartDisplayPage, wxID_ANY,
3187 _("Chart Rotation Averaging Time")),
3188 labelFlags);
3189 wxBoxSizer* pCOGUPFilterRow = new wxBoxSizer(wxHORIZONTAL);
3190 itemBoxSizerUI->Add(pCOGUPFilterRow, 0, wxALL | wxEXPAND,
3191 group_item_spacing);
3192
3193 pCOGUPUpdateSecs =
3194 new wxTextCtrl(m_ChartDisplayPage, ID_OPTEXTCTRL, _T(""),
3195 wxDefaultPosition, wxSize(50, -1), wxTE_RIGHT);
3196 pCOGUPFilterRow->Add(pCOGUPUpdateSecs, 0, wxALL, group_item_spacing);
3197
3198 pCOGUPFilterRow->Add(
3199 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("seconds")),
3200 inputFlags);
3201
3202 // spacer
3203 itemBoxSizerUI->Add(0, border_size * 8);
3204 itemBoxSizerUI->Add(0, border_size * 8);
3205
3206 // Chart Zoom Scale Weighting
3207 wxStaticText* zoomTextHead = new wxStaticText(
3208 m_ChartDisplayPage, wxID_ANY, _("Chart Zoom/Scale Weighting"));
3209
3210 itemBoxSizerUI->Add(zoomTextHead, labelFlags);
3211 itemBoxSizerUI->Add(0, border_size * 1);
3212 itemBoxSizerUI->Add(0, border_size * 1);
3213
3214 wxStaticText* zoomText = new wxStaticText(
3215 m_ChartDisplayPage, wxID_ANY,
3216 _("With a lower value, the same zoom level shows a less detailed chart.\n\
3217With a higher value, the same zoom level shows a more detailed chart."));
3218
3219 smallFont = *dialogFont; // we can't use Smaller() because
3220 // wx2.8 doesn't support it
3221 smallFont.SetPointSize((smallFont.GetPointSize() / 1.2) +
3222 0.5); // + 0.5 to round instead of truncate
3223 zoomText->SetFont(smallFont);
3224 itemBoxSizerUI->Add(zoomText, 0, wxALL | wxEXPAND, group_item_spacing);
3225
3226 // spacer
3227 /*itemBoxSizerUI->Add(0, border_size * 8); itemBoxSizerUI->Add(0,
3228 * border_size * 8);*/
3229
3230 // wxSize sz = g_Platform->getDisplaySize();
3231
3232 itemBoxSizerUI->Add(
3233 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("Raster")),
3234 labelFlags);
3235 m_pSlider_Zoom_Raster =
3236 new wxSlider(m_ChartDisplayPage, ID_RASTERZOOM, 0, -5, 5,
3237 wxDefaultPosition, m_sliderSize, SLIDER_STYLE);
3238
3239#ifdef __OCPN__ANDROID__
3240 prepareSlider(m_pSlider_Zoom_Raster);
3241#endif
3242
3243 itemBoxSizerUI->Add(m_pSlider_Zoom_Raster, inputFlags);
3244
3245 itemBoxSizerUI->Add(
3246 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("Vector")),
3247 labelFlags);
3248 m_pSlider_Zoom_Vector =
3249 new wxSlider(m_ChartDisplayPage, ID_VECZOOM, 0, -5, 5,
3250 wxDefaultPosition, m_sliderSize, SLIDER_STYLE);
3251
3252#ifdef __OCPN__ANDROID__
3253 prepareSlider(m_pSlider_Zoom_Vector);
3254#endif
3255
3256 itemBoxSizerUI->Add(m_pSlider_Zoom_Vector, inputFlags);
3257
3258 // Spacer
3259 itemBoxSizerUI->Add(0, border_size * 3);
3260 itemBoxSizerUI->Add(0, border_size * 3);
3261
3262 itemBoxSizerUI->Add(
3263 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("CM93 Detail level")),
3264 labelFlags);
3265 m_pSlider_CM93_Zoom =
3266 new wxSlider(m_ChartDisplayPage, ID_CM93ZOOM, 0,
3267 -CM93_ZOOM_FACTOR_MAX_RANGE, CM93_ZOOM_FACTOR_MAX_RANGE,
3268 wxDefaultPosition, m_sliderSize, SLIDER_STYLE);
3269
3270#ifdef __OCPN__ANDROID__
3271 prepareSlider(m_pSlider_CM93_Zoom);
3272#endif
3273
3274 itemBoxSizerUI->Add(m_pSlider_CM93_Zoom, 0, wxALL, border_size);
3275
3276 // spacer
3277 itemBoxSizerUI->Add(0, border_size * 3);
3278 itemBoxSizerUI->Add(0, border_size * 3);
3279 itemBoxSizerUI->Add(0, border_size * 3);
3280 itemBoxSizerUI->Add(0, border_size * 3);
3281 itemBoxSizerUI->Add(0, border_size * 3);
3282 itemBoxSizerUI->Add(0, border_size * 3);
3283
3284 // Display size/DPI
3285 itemBoxSizerUI->Add(new wxStaticText(m_ChartDisplayPage, wxID_ANY,
3286 _("Physical Screen Width")),
3287 labelFlags);
3288 wxBoxSizer* pDPIRow = new wxBoxSizer(wxHORIZONTAL);
3289 itemBoxSizerUI->Add(pDPIRow, 0, wxEXPAND);
3290
3291 pRBSizeAuto = new wxRadioButton(m_ChartDisplayPage, wxID_ANY, _("Auto"));
3292 pDPIRow->Add(pRBSizeAuto, inputFlags);
3293 pDPIRow->AddSpacer(10);
3294 pRBSizeManual = new wxRadioButton(m_ChartDisplayPage,
3295 ID_SIZEMANUALRADIOBUTTON, _("Manual:"));
3296 pDPIRow->Add(pRBSizeManual, inputFlags);
3297
3298 pScreenMM = new wxTextCtrl(m_ChartDisplayPage, ID_OPTEXTCTRL, _T(""),
3299 wxDefaultPosition, wxSize(3 * m_fontHeight, -1),
3300 wxTE_RIGHT);
3301 pDPIRow->Add(pScreenMM, 0, wxALL, group_item_spacing);
3302
3303 pDPIRow->Add(new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("mm")),
3304 inputFlags);
3305
3306 pRBSizeAuto->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
3307 wxCommandEventHandler(options::OnSizeAutoButton), NULL,
3308 this);
3309 pRBSizeManual->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
3310 wxCommandEventHandler(options::OnSizeManualButton),
3311 NULL, this);
3312
3313 // spacer
3314 itemBoxSizerUI->Add(0, border_size * 3);
3315 itemBoxSizerUI->Add(0, border_size * 3);
3316
3317 // OpenGL Options
3318 itemBoxSizerUI->Add(
3319 new wxStaticText(m_ChartDisplayPage, wxID_ANY, _("Graphics")),
3320 labelFlags);
3321 wxBoxSizer* OpenGLSizer = new wxBoxSizer(wxHORIZONTAL);
3322 itemBoxSizerUI->Add(OpenGLSizer, 0, 0, 0);
3323
3324 pOpenGL = new wxCheckBox(m_ChartDisplayPage, ID_OPENGLBOX,
3325 _("Use Accelerated Graphics (OpenGL)"));
3326 OpenGLSizer->Add(pOpenGL, inputFlags);
3327 pOpenGL->Enable(!g_bdisable_opengl && g_Platform->IsGLCapable());
3328
3329#ifdef __OCPN__ANDROID__
3330 pOpenGL->Disable();
3331#endif
3332
3333 wxButton* bOpenGL = new wxButton(m_ChartDisplayPage, ID_OPENGLOPTIONS,
3334 _("Options") + _T("..."));
3335 OpenGLSizer->Add(bOpenGL, inputFlags);
3336 bOpenGL->Enable(!g_bdisable_opengl && g_Platform->IsGLCapable());
3337
3338 itemBoxSizerUI->Add(0, border_size * 3);
3339 /*
3340 pTransparentToolbar =
3341 new wxCheckBox(m_ChartDisplayPage, ID_TRANSTOOLBARCHECKBOX,
3342 _("Enable Transparent Toolbar"));
3343 itemBoxSizerUI->Add(pTransparentToolbar, 0, wxALL, border_size);
3344 if (g_bopengl && !g_bTransparentToolbarInOpenGLOK)
3345 pTransparentToolbar->Disable();
3346 */
3347 }
3348}
3349
3350void options::CreatePanel_VectorCharts(size_t parent, int border_size,
3351 int group_item_spacing) {
3352 ps57Ctl = AddPage(parent, _("Vector Chart Display"));
3353
3354 if (!m_bcompact) {
3355 vectorPanel = new wxBoxSizer(wxHORIZONTAL);
3356 ps57Ctl->SetSizer(vectorPanel);
3357
3358 // 1st column, all options except Mariner's Standard
3359 wxFlexGridSizer* optionsColumn = new wxFlexGridSizer(2);
3360 optionsColumn->SetHGap(border_size);
3361 optionsColumn->AddGrowableCol(0, 2);
3362 optionsColumn->AddGrowableCol(1, 3);
3363 vectorPanel->Add(optionsColumn, 3, wxALL | wxEXPAND, border_size);
3364
3365 // spacer
3366 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _T("")));
3367 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _T("")));
3368
3369 if (!g_useMUI) {
3370 // display category
3371 optionsColumn->Add(
3372 new wxStaticText(ps57Ctl, wxID_ANY, _("Display Category")),
3373 labelFlags);
3374 wxString pDispCatStrings[] = {_("Base"), _("Standard"), _("All"),
3375 _("Mariner's Standard")};
3376 pDispCat = new wxChoice(ps57Ctl, ID_RADARDISTUNIT, wxDefaultPosition,
3377 wxDefaultSize, 4, pDispCatStrings);
3378 optionsColumn->Add(pDispCat, 0, wxALL, 2);
3379 }
3380
3381 // spacer
3382 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _T("")));
3383 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _T("")));
3384
3385 // display options
3386 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Display")),
3387 groupLabelFlags);
3388
3389 wxBoxSizer* miscSizer = new wxBoxSizer(wxVERTICAL);
3390 optionsColumn->Add(miscSizer, groupInputFlags);
3391
3392 if (!g_useMUI) {
3393 pCheck_SOUNDG =
3394 new wxCheckBox(ps57Ctl, ID_SOUNDGCHECKBOX, _("Depth Soundings"));
3395 pCheck_SOUNDG->SetValue(FALSE);
3396 miscSizer->Add(pCheck_SOUNDG, verticleInputFlags);
3397 }
3398
3399 pCheck_META = new wxCheckBox(ps57Ctl, ID_METACHECKBOX,
3400 _("Chart Information Objects"));
3401 pCheck_META->SetValue(FALSE);
3402 miscSizer->Add(pCheck_META, verticleInputFlags);
3403
3404 if (!g_useMUI) {
3405 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Buoys/Lights")),
3406 groupLabelFlags);
3407
3408 wxBoxSizer* lightSizer = new wxBoxSizer(wxVERTICAL);
3409 optionsColumn->Add(lightSizer, groupInputFlags);
3410
3411 pCheck_ATONTEXT =
3412 new wxCheckBox(ps57Ctl, ID_ATONTEXTCHECKBOX, _("Buoy/Light Labels"));
3413 pCheck_ATONTEXT->SetValue(FALSE);
3414 lightSizer->Add(pCheck_ATONTEXT, verticleInputFlags);
3415
3416 pCheck_LDISTEXT =
3417 new wxCheckBox(ps57Ctl, ID_LDISTEXTCHECKBOX, _("Light Descriptions"));
3418 pCheck_LDISTEXT->SetValue(FALSE);
3419 lightSizer->Add(pCheck_LDISTEXT, verticleInputFlags);
3420
3421 pCheck_XLSECTTEXT = new wxCheckBox(ps57Ctl, ID_LDISTEXTCHECKBOX,
3422 _("Extended Light Sectors"));
3423 pCheck_XLSECTTEXT->SetValue(FALSE);
3424 lightSizer->Add(pCheck_XLSECTTEXT, verticleInputFlags);
3425 }
3426
3427 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Chart Texts")),
3428 groupLabelFlags);
3429
3430 wxBoxSizer* textSizer = new wxBoxSizer(wxVERTICAL);
3431 optionsColumn->Add(textSizer, groupInputFlags);
3432
3433 pCheck_NATIONALTEXT = new wxCheckBox(ps57Ctl, ID_NATIONALTEXTCHECKBOX,
3434 _("National text on chart"));
3435 pCheck_NATIONALTEXT->SetValue(FALSE);
3436 textSizer->Add(pCheck_NATIONALTEXT, verticleInputFlags);
3437
3438 pCheck_SHOWIMPTEXT =
3439 new wxCheckBox(ps57Ctl, ID_IMPTEXTCHECKBOX, _("Important Text Only"));
3440 pCheck_SHOWIMPTEXT->SetValue(FALSE);
3441 textSizer->Add(pCheck_SHOWIMPTEXT, verticleInputFlags);
3442
3443 pCheck_DECLTEXT =
3444 new wxCheckBox(ps57Ctl, ID_DECLTEXTCHECKBOX, _("De-Cluttered Text"));
3445 pCheck_DECLTEXT->SetValue(FALSE);
3446 textSizer->Add(pCheck_DECLTEXT, verticleInputFlags);
3447
3448 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Chart Detail")),
3449 labelFlags);
3450 pCheck_SCAMIN = new wxCheckBox(ps57Ctl, ID_SCAMINCHECKBOX,
3451 _("Reduced Detail at Small Scale"));
3452 pCheck_SCAMIN->SetValue(FALSE);
3453 optionsColumn->Add(pCheck_SCAMIN, inputFlags);
3454
3455 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, ""),
3456 labelFlags);
3457 pCheck_SuperSCAMIN = new wxCheckBox(ps57Ctl, ID_SUPERSCAMINCHECKBOX,
3458 _("Additonal detail reduction at Small Scale"));
3459 pCheck_SuperSCAMIN->SetValue(FALSE);
3460 optionsColumn->Add(pCheck_SuperSCAMIN, inputFlags);
3461
3462 // spacer
3463 optionsColumn->Add(0, border_size * 4);
3464 optionsColumn->Add(0, border_size * 4);
3465
3466 // graphics options
3467 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Graphics Style")),
3468 labelFlags);
3469 wxString pPointStyleStrings[] = {
3470 _("Paper Chart"),
3471 _("Simplified"),
3472 };
3473 pPointStyle = new wxChoice(ps57Ctl, ID_RADARDISTUNIT, wxDefaultPosition,
3474 wxDefaultSize, 2, pPointStyleStrings);
3475 optionsColumn->Add(pPointStyle, inputFlags);
3476
3477 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Boundaries")),
3478 labelFlags);
3479 wxString pBoundStyleStrings[] = {
3480 _("Plain"),
3481 _("Symbolized"),
3482 };
3483 pBoundStyle = new wxChoice(ps57Ctl, ID_RADARDISTUNIT, wxDefaultPosition,
3484 wxDefaultSize, 2, pBoundStyleStrings);
3485 optionsColumn->Add(pBoundStyle, inputFlags);
3486
3487 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Colors")),
3488 labelFlags);
3489 wxString pColorNumStrings[] = {
3490 _("2 Color"),
3491 _("4 Color"),
3492 };
3493 p24Color = new wxChoice(ps57Ctl, ID_RADARDISTUNIT, wxDefaultPosition,
3494 wxDefaultSize, 2, pColorNumStrings);
3495 optionsColumn->Add(p24Color, inputFlags);
3496
3497 // spacer
3498 optionsColumn->Add(0, border_size * 4);
3499 optionsColumn->Add(0, border_size * 4);
3500
3501 // depth options
3502 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Shallow Depth")),
3503 labelFlags);
3504 wxBoxSizer* depShalRow = new wxBoxSizer(wxHORIZONTAL);
3505 optionsColumn->Add(depShalRow);
3506 m_ShallowCtl =
3507 new wxTextCtrl(ps57Ctl, ID_OPTEXTCTRL, _T(""), wxDefaultPosition,
3508 wxSize(60, -1), wxTE_RIGHT);
3509 depShalRow->Add(m_ShallowCtl, inputFlags);
3510 m_depthUnitsShal = new wxStaticText(ps57Ctl, wxID_ANY, _("meters"));
3511 depShalRow->Add(m_depthUnitsShal, inputFlags);
3512
3513 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Safety Depth")),
3514 labelFlags);
3515 wxBoxSizer* depSafeRow = new wxBoxSizer(wxHORIZONTAL);
3516 optionsColumn->Add(depSafeRow);
3517 m_SafetyCtl = new wxTextCtrl(ps57Ctl, ID_OPTEXTCTRL, _T(""),
3518 wxDefaultPosition, wxSize(60, -1), wxTE_RIGHT);
3519 depSafeRow->Add(m_SafetyCtl, inputFlags);
3520 m_depthUnitsSafe = new wxStaticText(ps57Ctl, wxID_ANY, _("meters"));
3521 depSafeRow->Add(m_depthUnitsSafe, inputFlags);
3522
3523 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Deep Depth")),
3524 labelFlags);
3525 wxBoxSizer* depDeepRow = new wxBoxSizer(wxHORIZONTAL);
3526 optionsColumn->Add(depDeepRow);
3527 m_DeepCtl = new wxTextCtrl(ps57Ctl, ID_OPTEXTCTRL, _T(""),
3528 wxDefaultPosition, wxSize(60, -1), wxTE_RIGHT);
3529 depDeepRow->Add(m_DeepCtl, inputFlags);
3530 m_depthUnitsDeep = new wxStaticText(ps57Ctl, wxID_ANY, _("meters"));
3531 depDeepRow->Add(m_depthUnitsDeep, inputFlags);
3532
3533 // 2nd column, Display Category / Mariner's Standard options
3534 wxBoxSizer* dispSizer = new wxBoxSizer(wxVERTICAL);
3535 vectorPanel->Add(dispSizer, 2, wxALL | wxEXPAND, border_size);
3536
3537 wxStaticBox* marinersBox =
3538 new wxStaticBox(ps57Ctl, wxID_ANY, _("User Standard Objects"));
3539 wxStaticBoxSizer* marinersSizer =
3540 new wxStaticBoxSizer(marinersBox, wxVERTICAL);
3541 dispSizer->Add(marinersSizer, 1, wxALL | wxEXPAND, border_size);
3542
3543 ps57CtlListBox = new OCPNCheckedListCtrl(
3544 ps57Ctl, ID_CHECKLISTBOX, wxDefaultPosition, wxSize(250, 350));
3545 marinersSizer->Add(ps57CtlListBox, 1, wxALL | wxEXPAND, group_item_spacing);
3546
3547 wxBoxSizer* btnRow1 = new wxBoxSizer(wxHORIZONTAL);
3548 itemButtonSelectList =
3549 new wxButton(ps57Ctl, ID_SELECTLIST, _("Select All"));
3550 btnRow1->Add(itemButtonSelectList, 1, wxALL | wxEXPAND, group_item_spacing);
3551 itemButtonClearList = new wxButton(ps57Ctl, ID_CLEARLIST, _("Clear All"));
3552 btnRow1->Add(itemButtonClearList, 1, wxALL | wxEXPAND, group_item_spacing);
3553 marinersSizer->Add(btnRow1);
3554
3555 wxBoxSizer* btnRow2 = new wxBoxSizer(wxHORIZONTAL);
3556 itemButtonSetStd =
3557 new wxButton(ps57Ctl, ID_SETSTDLIST, _("Reset to STANDARD"));
3558 btnRow2->Add(itemButtonSetStd, 1, wxALL | wxEXPAND, group_item_spacing);
3559 marinersSizer->Add(btnRow2);
3560
3561 }
3562
3563 else { // compact
3564 vectorPanel = new wxBoxSizer(wxVERTICAL);
3565 ps57Ctl->SetSizer(vectorPanel);
3566
3567 wxBoxSizer* optionsColumn = vectorPanel;
3568
3569 // spacer
3570 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _T("")));
3571
3572 // display category
3573 if (!g_useMUI) {
3574 optionsColumn->Add(
3575 new wxStaticText(ps57Ctl, wxID_ANY, _("Display Category")),
3576 inputFlags);
3577 wxString pDispCatStrings[] = {_("Base"), _("Standard"), _("All"),
3578 _("Mariner's Standard")};
3579 pDispCat = new wxChoice(ps57Ctl, ID_RADARDISTUNIT, wxDefaultPosition,
3580 wxSize(350, -1), 4, pDispCatStrings);
3581 optionsColumn->Add(pDispCat, 0, wxALL, 2);
3582
3583 // spacer
3584 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _T("")));
3585 }
3586
3587 // display options
3588
3589 wxBoxSizer* miscSizer = new wxBoxSizer(wxVERTICAL);
3590 optionsColumn->Add(miscSizer, groupInputFlags);
3591
3592 pCheck_SOUNDG =
3593 new wxCheckBox(ps57Ctl, ID_SOUNDGCHECKBOX, _("Depth Soundings"));
3594 pCheck_SOUNDG->SetValue(FALSE);
3595 miscSizer->Add(pCheck_SOUNDG, inputFlags);
3596
3597 pCheck_META = new wxCheckBox(ps57Ctl, ID_METACHECKBOX,
3598 _("Chart Information Objects"));
3599 pCheck_META->SetValue(FALSE);
3600 miscSizer->Add(pCheck_META, inputFlags);
3601
3602 wxBoxSizer* lightSizer = new wxBoxSizer(wxVERTICAL);
3603 optionsColumn->Add(lightSizer, groupInputFlags);
3604
3605 pCheck_ATONTEXT =
3606 new wxCheckBox(ps57Ctl, ID_ATONTEXTCHECKBOX, _("Buoy/Light Labels"));
3607 pCheck_ATONTEXT->SetValue(FALSE);
3608 lightSizer->Add(pCheck_ATONTEXT, inputFlags);
3609
3610 pCheck_LDISTEXT =
3611 new wxCheckBox(ps57Ctl, ID_LDISTEXTCHECKBOX, _("Light Descriptions"));
3612 pCheck_LDISTEXT->SetValue(FALSE);
3613 lightSizer->Add(pCheck_LDISTEXT, inputFlags);
3614
3615 pCheck_XLSECTTEXT = new wxCheckBox(ps57Ctl, ID_LDISTEXTCHECKBOX,
3616 _("Extended Light Sectors"));
3617 pCheck_XLSECTTEXT->SetValue(FALSE);
3618 lightSizer->Add(pCheck_XLSECTTEXT, inputFlags);
3619
3620 wxBoxSizer* textSizer = new wxBoxSizer(wxVERTICAL);
3621 optionsColumn->Add(textSizer, groupInputFlags);
3622
3623 pCheck_NATIONALTEXT = new wxCheckBox(ps57Ctl, ID_NATIONALTEXTCHECKBOX,
3624 _("National text on chart"));
3625 pCheck_NATIONALTEXT->SetValue(FALSE);
3626 textSizer->Add(pCheck_NATIONALTEXT, inputFlags);
3627
3628 pCheck_SHOWIMPTEXT =
3629 new wxCheckBox(ps57Ctl, ID_IMPTEXTCHECKBOX, _("Important Text Only"));
3630 pCheck_SHOWIMPTEXT->SetValue(FALSE);
3631 textSizer->Add(pCheck_SHOWIMPTEXT, inputFlags);
3632
3633 pCheck_DECLTEXT =
3634 new wxCheckBox(ps57Ctl, ID_DECLTEXTCHECKBOX, _("De-Cluttered Text"));
3635 pCheck_DECLTEXT->SetValue(FALSE);
3636 textSizer->Add(pCheck_DECLTEXT, inputFlags);
3637
3638 pCheck_SCAMIN = new wxCheckBox(ps57Ctl, ID_SCAMINCHECKBOX,
3639 _("Reduced Detail at Small Scale"));
3640 pCheck_SCAMIN->SetValue(FALSE);
3641 optionsColumn->Add(pCheck_SCAMIN, inputFlags);
3642
3643 optionsColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, ""),
3644 labelFlags);
3645 pCheck_SuperSCAMIN = new wxCheckBox(ps57Ctl, ID_SUPERSCAMINCHECKBOX,
3646 _("Additonal detail reduction at Small Scale"));
3647 pCheck_SuperSCAMIN->SetValue(FALSE);
3648 optionsColumn->Add(pCheck_SuperSCAMIN, inputFlags);
3649
3650 // spacer
3651 optionsColumn->Add(0, border_size * 4);
3652 optionsColumn->Add(0, border_size * 4);
3653
3654 // graphics options
3655
3656 wxFlexGridSizer* StyleColumn = new wxFlexGridSizer(2);
3657 StyleColumn->SetHGap(border_size);
3658 StyleColumn->AddGrowableCol(0, 2);
3659 StyleColumn->AddGrowableCol(1, 3);
3660 optionsColumn->Add(StyleColumn);
3661
3662 StyleColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Graphics Style")),
3663 inputFlags);
3664 wxString pPointStyleStrings[] = {
3665 _("Paper Chart"),
3666 _("Simplified"),
3667 };
3668 pPointStyle = new wxChoice(ps57Ctl, ID_RADARDISTUNIT, wxDefaultPosition,
3669 wxSize(m_fontHeight * 3, m_fontHeight), 2,
3670 pPointStyleStrings);
3671#ifdef __OCPN__ANDROID__
3672 setChoiceStyleSheet(pPointStyle, m_fontHeight * 8 / 10);
3673#endif
3674
3675 StyleColumn->Add(pPointStyle, inputFlags);
3676
3677 StyleColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Boundaries")),
3678 inputFlags);
3679 wxString pBoundStyleStrings[] = {
3680 _("Plain"),
3681 _("Symbolized"),
3682 };
3683 pBoundStyle = new wxChoice(ps57Ctl, ID_RADARDISTUNIT, wxDefaultPosition,
3684 wxSize(m_fontHeight * 3, m_fontHeight), 2,
3685 pBoundStyleStrings);
3686#ifdef __OCPN__ANDROID__
3687 setChoiceStyleSheet(pBoundStyle, m_fontHeight * 8 / 10);
3688#endif
3689
3690 StyleColumn->Add(pBoundStyle, inputFlags);
3691
3692 StyleColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Colors")),
3693 inputFlags);
3694
3695 wxString pColorNumStrings[] = {
3696 _("2 Color"),
3697 _("4 Color"),
3698 };
3699 p24Color = new wxChoice(ps57Ctl, ID_RADARDISTUNIT, wxDefaultPosition,
3700 wxSize(m_fontHeight * 3, m_fontHeight), 2,
3701 pColorNumStrings);
3702#ifdef __OCPN__ANDROID__
3703 setChoiceStyleSheet(p24Color, m_fontHeight * 8 / 10);
3704#endif
3705 StyleColumn->Add(p24Color, inputFlags);
3706
3707 // spacer
3708 optionsColumn->Add(0, border_size * 4);
3709 optionsColumn->Add(0, border_size * 4);
3710
3711 wxFlexGridSizer* DepthColumn = new wxFlexGridSizer(3);
3712 DepthColumn->SetHGap(border_size);
3713 DepthColumn->AddGrowableCol(0, 3);
3714 DepthColumn->AddGrowableCol(1, 2);
3715 DepthColumn->AddGrowableCol(2, 3);
3716 optionsColumn->Add(DepthColumn);
3717
3718 // depth options
3719 DepthColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Shallow Depth")),
3720 inputFlags);
3721 m_ShallowCtl =
3722 new wxTextCtrl(ps57Ctl, ID_OPTEXTCTRL, _T(""), wxDefaultPosition,
3723 wxSize(m_fontHeight * 2, m_fontHeight), wxTE_RIGHT);
3724 DepthColumn->Add(m_ShallowCtl, inputFlags);
3725 m_depthUnitsShal = new wxStaticText(ps57Ctl, wxID_ANY, _("meters"));
3726 DepthColumn->Add(m_depthUnitsShal, inputFlags);
3727
3728 DepthColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Safety Depth")),
3729 inputFlags);
3730 m_SafetyCtl =
3731 new wxTextCtrl(ps57Ctl, ID_OPTEXTCTRL, _T(""), wxDefaultPosition,
3732 wxSize(m_fontHeight * 2, m_fontHeight), wxTE_RIGHT);
3733 DepthColumn->Add(m_SafetyCtl, inputFlags);
3734 m_depthUnitsSafe = new wxStaticText(ps57Ctl, wxID_ANY, _("meters"));
3735 DepthColumn->Add(m_depthUnitsSafe, inputFlags);
3736
3737 DepthColumn->Add(new wxStaticText(ps57Ctl, wxID_ANY, _("Deep Depth")),
3738 inputFlags);
3739 m_DeepCtl =
3740 new wxTextCtrl(ps57Ctl, ID_OPTEXTCTRL, _T(""), wxDefaultPosition,
3741 wxSize(m_fontHeight * 2, m_fontHeight), wxTE_CENTER);
3742 DepthColumn->Add(m_DeepCtl, inputFlags);
3743 m_depthUnitsDeep = new wxStaticText(ps57Ctl, wxID_ANY, _("meters"));
3744 DepthColumn->Add(m_depthUnitsDeep, inputFlags);
3745
3746 // spacer
3747 optionsColumn->Add(0, border_size * 4);
3748 optionsColumn->Add(0, border_size * 4);
3749
3750 // Display Category / Mariner's Standard options
3751 wxBoxSizer* dispSizer = new wxBoxSizer(wxVERTICAL);
3752 vectorPanel->Add(dispSizer, 2, wxALL | wxEXPAND, border_size);
3753
3754 wxStaticBox* marinersBox =
3755 new wxStaticBox(ps57Ctl, wxID_ANY, _("User Standard Objects"));
3756 wxStaticBoxSizer* marinersSizer =
3757 new wxStaticBoxSizer(marinersBox, wxVERTICAL);
3758 dispSizer->Add(marinersSizer, 1, wxALL | wxEXPAND, border_size);
3759
3760 wxBoxSizer* btnRow1 = new wxBoxSizer(wxHORIZONTAL);
3761 itemButtonSelectList =
3762 new wxButton(ps57Ctl, ID_SELECTLIST, _("Select All"));
3763 btnRow1->Add(itemButtonSelectList, 1, wxALL | wxEXPAND, group_item_spacing);
3764 itemButtonClearList = new wxButton(ps57Ctl, ID_CLEARLIST, _("Clear All"));
3765 btnRow1->Add(itemButtonClearList, 1, wxALL | wxEXPAND, group_item_spacing);
3766 marinersSizer->Add(btnRow1);
3767
3768 wxBoxSizer* btnRow2 = new wxBoxSizer(wxHORIZONTAL);
3769 itemButtonSetStd =
3770 new wxButton(ps57Ctl, ID_SETSTDLIST, _("Reset to STANDARD"));
3771 btnRow2->Add(itemButtonSetStd, 1, wxALL | wxEXPAND, group_item_spacing);
3772 marinersSizer->Add(btnRow2);
3773
3774 // #if defined(__WXMSW__) || defined(__WXOSX__)
3775 // wxString* ps57CtlListBoxStrings = NULL;
3776 // ps57CtlListBox = new wxCheckListBox(
3777 // ps57Ctl, ID_CHECKLISTBOX, wxDefaultPosition, wxSize(250, 350), 0,
3778 // ps57CtlListBoxStrings, wxLB_SINGLE | wxLB_HSCROLL | wxLB_SORT);
3779 // #else
3780 ps57CtlListBox = new OCPNCheckedListCtrl(
3781 ps57Ctl, ID_CHECKLISTBOX, wxDefaultPosition, wxSize(250, 350));
3782 // #endif
3783
3784 marinersSizer->Add(ps57CtlListBox, 1, wxALL | wxEXPAND, group_item_spacing);
3785 }
3786}
3787
3788void options::CreatePanel_TidesCurrents(size_t parent, int border_size,
3789 int group_item_spacing) {
3790 wxScrolledWindow* tcPanel = AddPage(parent, _("Tides && Currents"));
3791
3792 wxBoxSizer* mainHBoxSizer = new wxBoxSizer(wxVERTICAL);
3793 tcPanel->SetSizer(mainHBoxSizer);
3794
3795 wxStaticBox* tcBox = new wxStaticBox(tcPanel, wxID_ANY, _("Active Datasets"));
3796 wxStaticBoxSizer* tcSizer = new wxStaticBoxSizer(tcBox, wxHORIZONTAL);
3797 mainHBoxSizer->Add(tcSizer, 1, wxALL | wxEXPAND, border_size);
3798
3799 tcDataSelected =
3800 new wxListCtrl(tcPanel, ID_TIDESELECTED, wxDefaultPosition,
3801 wxSize(100, -1), wxLC_REPORT | wxLC_NO_HEADER);
3802
3803 tcSizer->Add(tcDataSelected, 1, wxALL | wxEXPAND, border_size);
3804
3805 // Populate Selection List Control with the contents
3806 // of the Global static array
3807 tcDataSelected->DeleteAllItems();
3808
3809 // Add first column
3810 wxListItem col0;
3811 col0.SetId(0);
3812 col0.SetText(_T(""));
3813 col0.SetWidth(500);
3814 col0.SetAlign(wxLIST_FORMAT_LEFT);
3815
3816 tcDataSelected->InsertColumn(0, col0);
3817
3818 int w = 400, w1, h;
3819 for (unsigned int id = 0; id < TideCurrentDataSet.Count(); id++) {
3820 wxListItem li;
3821 li.SetId(id);
3822 long idx = tcDataSelected->InsertItem(li);
3823
3824 wxString setName = TideCurrentDataSet[id];
3825 tcDataSelected->SetItem(id, 0, setName);
3826 GetTextExtent(setName, &w1, &h);
3827 w = w1 > w ? w1 : w;
3828 }
3829 tcDataSelected->SetColumnWidth(0, 20 + w);
3830
3831 // Add the "Insert/Remove" buttons
3832 wxButton* insertButton =
3833 new wxButton(tcPanel, ID_TCDATAADD, _("Add Dataset..."));
3834 wxButton* removeButton =
3835 new wxButton(tcPanel, ID_TCDATADEL, _("Remove Selected"));
3836
3837 wxBoxSizer* btnSizer = new wxBoxSizer(wxVERTICAL);
3838 tcSizer->Add(btnSizer);
3839
3840 btnSizer->Add(insertButton, 1, wxALL | wxEXPAND, group_item_spacing);
3841 btnSizer->Add(removeButton, 1, wxALL | wxEXPAND, group_item_spacing);
3842}
3843
3844void options::CreatePanel_ChartGroups(size_t parent, int border_size,
3845 int group_item_spacing) {
3846 // Special case for adding the tab here. We know this page has multiple tabs,
3847 // and we have the actual widgets in a separate class (because of its
3848 // complexity)
3849
3850 wxWindow* chartsPage = m_pListbook->GetPage(parent);
3851 groupsPanel = new ChartGroupsUI(chartsPage);
3852
3853 groupsPanel->m_panel = AddPage(parent, _("Chart Groups"));
3854
3855 groupsPanel->CreatePanel(parent, border_size, group_item_spacing);
3856}
3857
3858void ChartGroupsUI::CreatePanel(size_t parent, int border_size,
3859 int group_item_spacing) {
3860 modified = FALSE;
3861 m_border_size = border_size;
3862 m_group_item_spacing = group_item_spacing;
3863
3864 m_UIcomplete = FALSE;
3865
3866 CompletePanel();
3867}
3868
3869void ChartGroupsUI::CompletePanel(void) {
3870 m_topSizer = new wxBoxSizer(wxVERTICAL);
3871 m_panel->SetSizer(m_topSizer);
3872
3873 // The chart file/dir tree
3874 wxStaticText* allChartsLabel =
3875 new wxStaticText(m_panel, wxID_ANY, _("All Available Charts"));
3876 m_topSizer->Add(allChartsLabel, 0, wxTOP | wxRIGHT | wxLEFT, m_border_size);
3877
3878 wxBoxSizer* sizerCharts = new wxBoxSizer(wxHORIZONTAL);
3879 m_topSizer->Add(sizerCharts, 1, wxALL | wxEXPAND, 5);
3880
3881 wxBoxSizer* activeListSizer = new wxBoxSizer(wxVERTICAL);
3882 sizerCharts->Add(activeListSizer, 1, wxALL | wxEXPAND, 5);
3883
3884#ifdef __OCPN__ANDROID__
3885 allAvailableCtl =
3886 new wxGenericDirCtrl(m_panel, ID_GROUPAVAILABLE, _T(""),
3887 wxDefaultPosition, wxDefaultSize, wxVSCROLL);
3888#else
3889 allAvailableCtl =
3890 new wxGenericDirCtrl(m_panel, ID_GROUPAVAILABLE, _T(""),
3891 wxDefaultPosition, wxDefaultSize, wxVSCROLL);
3892#endif
3893 activeListSizer->Add(allAvailableCtl, 1, wxEXPAND);
3894
3895 m_pAddButton = new wxButton(m_panel, ID_GROUPINSERTDIR, _("Add"));
3896 m_pAddButton->Disable();
3897 m_pRemoveButton = new wxButton(m_panel, ID_GROUPREMOVEDIR, _("Remove Chart"));
3898 m_pRemoveButton->Disable();
3899
3900 m_pAddButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
3901 wxCommandEventHandler(ChartGroupsUI::OnInsertChartItem),
3902 NULL, this);
3903 m_pRemoveButton->Connect(
3904 wxEVT_COMMAND_BUTTON_CLICKED,
3905 wxCommandEventHandler(ChartGroupsUI::OnRemoveChartItem), NULL, this);
3906
3907 wxBoxSizer* addRemove = new wxBoxSizer(wxVERTICAL);
3908 sizerCharts->Add(addRemove, 0, wxALL | wxEXPAND, m_border_size);
3909 addRemove->Add(m_pAddButton, 0, wxALL | wxEXPAND, m_group_item_spacing);
3910
3911 sizerCharts->AddSpacer(20); // Avoid potential scrollbar
3912
3913 // Add the Groups notebook control
3914 wxStaticText* groupsLabel =
3915 new wxStaticText(m_panel, wxID_ANY, _("Chart Groups"));
3916 m_topSizer->Add(groupsLabel, 0, wxTOP | wxRIGHT | wxLEFT, m_border_size);
3917
3918 wxBoxSizer* sizerGroups = new wxBoxSizer(wxHORIZONTAL);
3919 m_topSizer->Add(sizerGroups, 1, wxALL | wxEXPAND, 5);
3920
3921 wxBoxSizer* nbSizer = new wxBoxSizer(wxVERTICAL);
3922 sizerGroups->Add(nbSizer, 1, wxALL | wxEXPAND, m_border_size);
3923 m_GroupNB = new wxNotebook(m_panel, ID_GROUPNOTEBOOK, wxDefaultPosition,
3924 wxDefaultSize, wxNB_TOP);
3925 nbSizer->Add(m_GroupNB, 1, wxEXPAND);
3926
3927 m_GroupNB->Connect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
3928 wxNotebookEventHandler(ChartGroupsUI::OnGroupPageChange),
3929 NULL, this);
3930
3931 // Add default (always present) Default Chart Group
3932 wxPanel* allActiveGroup =
3933 new wxPanel(m_GroupNB, -1, wxDefaultPosition, wxDefaultSize);
3934 m_GroupNB->AddPage(allActiveGroup, _("All Charts"));
3935
3936 wxBoxSizer* page0BoxSizer = new wxBoxSizer(wxHORIZONTAL);
3937 allActiveGroup->SetSizer(page0BoxSizer);
3938
3939 defaultAllCtl = new wxGenericDirCtrl(allActiveGroup, -1, _T(""),
3940 wxDefaultPosition, wxDefaultSize);
3941
3942 // Set the Font for the All Active Chart Group tree to be italic, dimmed
3943 iFont = new wxFont(*dialogFont);
3944 iFont->SetStyle(wxFONTSTYLE_ITALIC);
3945 iFont->SetWeight(wxFONTWEIGHT_LIGHT);
3946
3947 page0BoxSizer->Add(defaultAllCtl, 1, wxALIGN_TOP | wxALL | wxEXPAND);
3948
3949 m_DirCtrlArray.Add(defaultAllCtl);
3950
3951 // Add the Chart Group (page) "New" and "Delete" buttons
3952 m_pNewGroupButton =
3953 new wxButton(m_panel, ID_GROUPNEWGROUP, _("New Group..."));
3954 m_pDeleteGroupButton =
3955 new wxButton(m_panel, ID_GROUPDELETEGROUP, _("Delete Group"));
3956 m_pDeleteGroupButton->Disable(); // for default "all Charts" group
3957
3958 m_pNewGroupButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
3959 wxCommandEventHandler(ChartGroupsUI::OnNewGroup),
3960 NULL, this);
3961 m_pDeleteGroupButton->Connect(
3962 wxEVT_COMMAND_BUTTON_CLICKED,
3963 wxCommandEventHandler(ChartGroupsUI::OnDeleteGroup), NULL, this);
3964
3965 wxBoxSizer* newDeleteGrp = new wxBoxSizer(wxVERTICAL);
3966 sizerGroups->Add(newDeleteGrp, 0, wxALL, m_border_size);
3967
3968 newDeleteGrp->AddSpacer(25);
3969 newDeleteGrp->Add(m_pNewGroupButton, 0, wxALL | wxEXPAND,
3970 m_group_item_spacing);
3971 newDeleteGrp->AddSpacer(15);
3972 newDeleteGrp->Add(m_pDeleteGroupButton, 0, wxALL | wxEXPAND,
3973 m_group_item_spacing);
3974 newDeleteGrp->AddSpacer(25);
3975 newDeleteGrp->Add(m_pRemoveButton, 0, wxALL | wxEXPAND, m_group_item_spacing);
3976
3977 sizerGroups->AddSpacer(20); // Avoid potential scrollbar
3978
3979 // Connect this last, otherwise handler is called before all objects are
3980 // initialized.
3981 m_panel->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED,
3982 wxTreeEventHandler(ChartGroupsUI::OnAvailableSelection),
3983 NULL, this);
3984
3985 m_UIcomplete = TRUE;
3986}
3987
3988void options::CreatePanel_Display(size_t parent, int border_size,
3989 int group_item_spacing) {
3990 pDisplayPanel = AddPage(parent, _("General"));
3991
3992 if (!m_bcompact) {
3993 wxFlexGridSizer* generalSizer = new wxFlexGridSizer(2);
3994 generalSizer->SetHGap(border_size);
3995 // generalSizer->AddGrowableCol( 0, 1 );
3996 // generalSizer->AddGrowableCol( 1, 1 );
3997 // pDisplayPanel->SetSizer( generalSizer );
3998
3999 // wxFlexGridSizer grows wrongly in wx2.8, so we need to centre it in
4000 // another sizer instead of letting it grow.
4001 wxBoxSizer* wrapperSizer = new wxBoxSizer(wxVERTICAL);
4002 pDisplayPanel->SetSizer(wrapperSizer);
4003 wrapperSizer->Add(generalSizer, 1, wxALL | wxALIGN_CENTER, border_size);
4004
4005 // spacer
4006 generalSizer->Add(0, border_size * 4);
4007 generalSizer->Add(0, border_size * 4);
4008
4009 if (!g_useMUI) {
4010 // Nav Mode
4011 generalSizer->Add(
4012 new wxStaticText(pDisplayPanel, wxID_ANY, _("Navigation Mode")),
4013 groupLabelFlags);
4014 wxBoxSizer* boxNavMode = new wxBoxSizer(wxVERTICAL);
4015 generalSizer->Add(boxNavMode, groupInputFlags);
4016
4017 wxBoxSizer* rowOrientation = new wxBoxSizer(wxHORIZONTAL);
4018 boxNavMode->Add(rowOrientation);
4019
4020 pCBNorthUp = new wxRadioButton(pDisplayPanel, wxID_ANY, _("North Up"));
4021 rowOrientation->Add(pCBNorthUp, inputFlags);
4022 pCBCourseUp =
4023 new wxRadioButton(pDisplayPanel, ID_COURSEUPCHECKBOX, _("Course Up"));
4024 rowOrientation->Add(pCBCourseUp,
4025 wxSizerFlags(0)
4026 .Align(wxALIGN_CENTRE_VERTICAL)
4027 .Border(wxLEFT, group_item_spacing * 2));
4028
4029 pCBLookAhead = new wxCheckBox(pDisplayPanel, ID_CHECK_LOOKAHEAD,
4030 _("Look Ahead Mode"));
4031 boxNavMode->Add(pCBLookAhead, verticleInputFlags);
4032
4033 // spacer
4034 generalSizer->Add(0, border_size * 4);
4035 generalSizer->Add(0, border_size * 4);
4036
4037 // Control Options
4038 generalSizer->Add(
4039 new wxStaticText(pDisplayPanel, wxID_ANY, _("Chart Display")),
4040 groupLabelFlags);
4041 wxBoxSizer* boxCharts = new wxBoxSizer(wxVERTICAL);
4042 generalSizer->Add(boxCharts, groupInputFlags);
4043
4044 pCDOQuilting = new wxCheckBox(pDisplayPanel, ID_QUILTCHECKBOX1,
4045 _("Enable Chart Quilting"));
4046 boxCharts->Add(pCDOQuilting, verticleInputFlags);
4047
4048 pPreserveScale =
4049 new wxCheckBox(pDisplayPanel, ID_PRESERVECHECKBOX,
4050 _("Preserve scale when switching charts"));
4051 boxCharts->Add(pPreserveScale, verticleInputFlags);
4052
4053 // spacer
4054 generalSizer->Add(0, border_size * 4);
4055 generalSizer->Add(0, border_size * 4);
4056 }
4057
4058 // Control Options
4059 generalSizer->Add(new wxStaticText(pDisplayPanel, wxID_ANY, _("Controls")),
4060 groupLabelFlags);
4061 wxBoxSizer* boxCtrls = new wxBoxSizer(wxVERTICAL);
4062 generalSizer->Add(boxCtrls, groupInputFlags);
4063
4064 pSmoothPanZoom = new wxCheckBox(pDisplayPanel, ID_SMOOTHPANZOOMBOX,
4065 _("Smooth Panning / Zooming"));
4066 boxCtrls->Add(pSmoothPanZoom, verticleInputFlags);
4067
4068 pEnableZoomToCursor =
4069 new wxCheckBox(pDisplayPanel, ID_ZTCCHECKBOX, _("Zoom to Cursor"));
4070 pEnableZoomToCursor->SetValue(FALSE);
4071 boxCtrls->Add(pEnableZoomToCursor, verticleInputFlags);
4072
4073 // spacer
4074 generalSizer->Add(0, border_size * 4);
4075 generalSizer->Add(0, border_size * 4);
4076
4077 if (!g_useMUI) {
4078 // Display Options
4079 generalSizer->Add(
4080 new wxStaticText(pDisplayPanel, wxID_ANY, _("Display Features")),
4081 groupLabelFlags);
4082 wxBoxSizer* boxDisp = new wxBoxSizer(wxVERTICAL);
4083 generalSizer->Add(boxDisp, groupInputFlags);
4084
4085 pSDisplayGrid =
4086 new wxCheckBox(pDisplayPanel, ID_CHECK_DISPLAYGRID, _("Show Grid"));
4087 boxDisp->Add(pSDisplayGrid, verticleInputFlags);
4088
4089 pCDOOutlines = new wxCheckBox(pDisplayPanel, ID_OUTLINECHECKBOX1,
4090 _("Show Chart Outlines"));
4091 boxDisp->Add(pCDOOutlines, verticleInputFlags);
4092
4093 pSDepthUnits = new wxCheckBox(pDisplayPanel, ID_SHOWDEPTHUNITSBOX1,
4094 _("Show Depth Units"));
4095 boxDisp->Add(pSDepthUnits, verticleInputFlags);
4096 }
4097
4098 // CUSTOMIZATION - LIVE ETA OPTION
4099 // -------------------------------
4100 // Add a checkbox to activate live ETA option in status bar, and
4101 // Add a text field to set default boat speed (for calculation when
4102 // no GPS or when the boat is at the harbor).
4103
4104 // Spacer
4105 generalSizer->Add(0, border_size * 4);
4106 generalSizer->Add(0, border_size * 4);
4107
4108 // New menu status bar
4109 generalSizer->Add(
4110 new wxStaticText(pDisplayPanel, wxID_ANY, _("Status Bar Option")),
4111 groupLabelFlags);
4112 wxBoxSizer* boxDispStatusBar = new wxBoxSizer(wxVERTICAL);
4113 generalSizer->Add(boxDispStatusBar, groupInputFlags);
4114
4115 // Add option for live ETA
4116 pSLiveETA = new wxCheckBox(pDisplayPanel, ID_CHECK_LIVEETA,
4117 _("Live ETA at Cursor"));
4118 boxDispStatusBar->Add(pSLiveETA, verticleInputFlags);
4119
4120 // Add text input for default boat speed
4121 // (for calculation, in case GPS speed is null)
4122 wxBoxSizer* defaultBoatSpeedSizer = new wxBoxSizer(wxHORIZONTAL);
4123 boxDispStatusBar->Add(defaultBoatSpeedSizer, wxALL, group_item_spacing);
4124 defaultBoatSpeedSizer->Add(
4125 new wxStaticText(pDisplayPanel, wxID_ANY, _("Default Boat Speed ")),
4126 groupLabelFlagsHoriz);
4127 pSDefaultBoatSpeed =
4128 new wxTextCtrl(pDisplayPanel, ID_DEFAULT_BOAT_SPEED, _T(""),
4129 wxDefaultPosition, wxSize(50, -1), wxTE_RIGHT);
4130 defaultBoatSpeedSizer->Add(pSDefaultBoatSpeed, 0, wxALIGN_CENTER_VERTICAL,
4131 group_item_spacing);
4132
4133 // --------------------------------------
4134 // END OF CUSTOMIZATION - LIVE ETA OPTION
4135
4136#ifndef __OCPN__ANDROID__
4137 // MultiChart selection panel
4138 if (g_Platform->GetDisplayAreaCM2() > 100) {
4139 wxStaticBox* itemStaticBoxScreenConfig =
4140 new wxStaticBox(pDisplayPanel, wxID_ANY, _("Canvas Layout"));
4141 wxStaticBoxSizer* itemStaticBoxSizerScreenConfig =
4142 new wxStaticBoxSizer(itemStaticBoxScreenConfig, wxHORIZONTAL);
4143 wrapperSizer->Add(itemStaticBoxSizerScreenConfig, 1, wxALL | wxEXPAND, 5);
4144
4145 // The standard screen configs...
4146 wxString iconDir = g_Platform->GetSharedDataDir();
4147 appendOSDirSlash(&iconDir);
4148 iconDir.append(_T("uidata"));
4149 appendOSDirSlash(&iconDir);
4150 iconDir.append(_T("MUI_flat"));
4151 appendOSDirSlash(&iconDir);
4152 int bmpSize = GetCharHeight() * 3;
4153
4154 wxBitmap bmp =
4155 LoadSVG(iconDir + _T("MUI_Sconfig_1.svg"), bmpSize, bmpSize);
4156 m_sconfigSelect_single =
4157 new CanvasConfigSelect(pDisplayPanel, this, ID_SCREENCONFIG1, bmp);
4158 itemStaticBoxSizerScreenConfig->Add(m_sconfigSelect_single, 0,
4159 wxALIGN_LEFT);
4160
4161 itemStaticBoxSizerScreenConfig->AddSpacer(GetCharHeight());
4162
4163 bmp = LoadSVG(iconDir + _T("MUI_Sconfig_2.svg"), bmpSize, bmpSize);
4164 m_sconfigSelect_twovertical =
4165 new CanvasConfigSelect(pDisplayPanel, this, ID_SCREENCONFIG2, bmp);
4166 itemStaticBoxSizerScreenConfig->Add(m_sconfigSelect_twovertical, 0,
4167 wxALIGN_LEFT);
4168
4169 itemStaticBoxSizerScreenConfig->AddSpacer(GetCharHeight());
4170 }
4171#endif
4172
4173 } else { // compact follows
4174 wxFlexGridSizer* generalSizer = new wxFlexGridSizer(2);
4175 generalSizer->SetHGap(border_size);
4176 // generalSizer->AddGrowableCol( 0, 1 );
4177 // generalSizer->AddGrowableCol( 1, 1 );
4178 // pDisplayPanel->SetSizer( generalSizer );
4179
4180 // wxFlexGridSizer grows wrongly in wx2.8, so we need to centre it in
4181 // another sizer instead of letting it grow.
4182 wxBoxSizer* wrapperSizer = new wxBoxSizer(wxVERTICAL);
4183 pDisplayPanel->SetSizer(wrapperSizer);
4184 wrapperSizer->Add(generalSizer, 1, wxALL | wxALIGN_CENTER, border_size);
4185
4186 // spacer
4187 generalSizer->Add(0, border_size * 4);
4188 generalSizer->Add(0, border_size * 4);
4189
4190 if (!g_useMUI) {
4191 // Nav Mode
4192 generalSizer->Add(
4193 new wxStaticText(pDisplayPanel, wxID_ANY, _("Navigation Mode")),
4194 groupLabelFlags);
4195 wxBoxSizer* boxNavMode = new wxBoxSizer(wxVERTICAL);
4196 generalSizer->Add(boxNavMode, groupInputFlags);
4197
4198 wxBoxSizer* rowOrientation = new wxBoxSizer(wxHORIZONTAL);
4199 boxNavMode->Add(rowOrientation);
4200
4201 pCBNorthUp = new wxRadioButton(pDisplayPanel, wxID_ANY, _("North Up"));
4202 rowOrientation->Add(pCBNorthUp, inputFlags);
4203 pCBCourseUp =
4204 new wxRadioButton(pDisplayPanel, ID_COURSEUPCHECKBOX, _("Course Up"));
4205 rowOrientation->Add(pCBCourseUp,
4206 wxSizerFlags(0)
4207 .Align(wxALIGN_CENTRE_VERTICAL)
4208 .Border(wxLEFT, group_item_spacing * 2));
4209
4210 pCBLookAhead = new wxCheckBox(pDisplayPanel, ID_CHECK_LOOKAHEAD,
4211 _("Look Ahead Mode"));
4212 boxNavMode->Add(pCBLookAhead, verticleInputFlags);
4213
4214 // spacer
4215 generalSizer->Add(0, border_size * 4);
4216 generalSizer->Add(0, border_size * 4);
4217
4218 // Control Options
4219 generalSizer->Add(
4220 new wxStaticText(pDisplayPanel, wxID_ANY, _("Chart Display")),
4221 groupLabelFlags);
4222 wxBoxSizer* boxCharts = new wxBoxSizer(wxVERTICAL);
4223 generalSizer->Add(boxCharts, groupInputFlags);
4224
4225 pCDOQuilting = new wxCheckBox(pDisplayPanel, ID_QUILTCHECKBOX1,
4226 _("Enable Chart Quilting"));
4227 boxCharts->Add(pCDOQuilting, verticleInputFlags);
4228
4229 pPreserveScale =
4230 new wxCheckBox(pDisplayPanel, ID_PRESERVECHECKBOX,
4231 _("Preserve scale when switching charts"));
4232 boxCharts->Add(pPreserveScale, verticleInputFlags);
4233
4234 // spacer
4235 generalSizer->Add(0, border_size * 4);
4236 generalSizer->Add(0, border_size * 4);
4237 }
4238
4239 // Control Options
4240 generalSizer->Add(new wxStaticText(pDisplayPanel, wxID_ANY, _("Controls")),
4241 groupLabelFlags);
4242 wxBoxSizer* boxCtrls = new wxBoxSizer(wxVERTICAL);
4243 generalSizer->Add(boxCtrls, groupInputFlags);
4244
4245 pSmoothPanZoom = new wxCheckBox(pDisplayPanel, ID_SMOOTHPANZOOMBOX,
4246 _("Smooth Panning / Zooming"));
4247 boxCtrls->Add(pSmoothPanZoom, verticleInputFlags);
4248 pEnableZoomToCursor =
4249 new wxCheckBox(pDisplayPanel, ID_ZTCCHECKBOX, _("Zoom to Cursor"));
4250 pEnableZoomToCursor->SetValue(FALSE);
4251 boxCtrls->Add(pEnableZoomToCursor, verticleInputFlags);
4252
4253#ifdef __OCPN__ANDROID__
4254 pSmoothPanZoom->Hide();
4255 pEnableZoomToCursor->Hide();
4256#endif
4257
4258 // spacer
4259 generalSizer->Add(0, border_size * 4);
4260 generalSizer->Add(0, border_size * 4);
4261
4262 if (!g_useMUI) {
4263 // Display Options
4264 generalSizer->Add(
4265 new wxStaticText(pDisplayPanel, wxID_ANY, _("Display Features")),
4266 groupLabelFlags);
4267 wxBoxSizer* boxDisp = new wxBoxSizer(wxVERTICAL);
4268 generalSizer->Add(boxDisp, groupInputFlags);
4269
4270 pSDisplayGrid =
4271 new wxCheckBox(pDisplayPanel, ID_CHECK_DISPLAYGRID, _("Show Grid"));
4272 boxDisp->Add(pSDisplayGrid, verticleInputFlags);
4273
4274 pCDOOutlines = new wxCheckBox(pDisplayPanel, ID_OUTLINECHECKBOX1,
4275 _("Show Chart Outlines"));
4276 boxDisp->Add(pCDOOutlines, verticleInputFlags);
4277
4278 pSDepthUnits = new wxCheckBox(pDisplayPanel, ID_SHOWDEPTHUNITSBOX1,
4279 _("Show Depth Units"));
4280 boxDisp->Add(pSDepthUnits, verticleInputFlags);
4281 }
4282
4283 // CUSTOMIZATION - LIVE ETA OPTION
4284 // -------------------------------
4285 // Add a checkbox to activate live ETA option in status bar, and
4286 // Add a text field to set default boat speed (for calculation when
4287 // no GPS or when the boat is at the harbor).
4288
4289 // Spacer
4290 generalSizer->Add(0, border_size * 4);
4291 generalSizer->Add(0, border_size * 4);
4292
4293 // New menu status bar
4294 generalSizer->Add(
4295 new wxStaticText(pDisplayPanel, wxID_ANY, _("Status Bar")),
4296 groupLabelFlags);
4297 wxBoxSizer* boxDispStatusBar = new wxBoxSizer(wxVERTICAL);
4298 generalSizer->Add(boxDispStatusBar, groupInputFlags);
4299
4300 // Add option for live ETA
4301 pSLiveETA = new wxCheckBox(pDisplayPanel, ID_CHECK_LIVEETA,
4302 _("Live ETA at Cursor"));
4303 boxDispStatusBar->Add(pSLiveETA, verticleInputFlags);
4304
4305 // Add text input for default boat speed
4306 // (for calculation, in case GPS speed is null)
4307 wxBoxSizer* defaultBoatSpeedSizer = new wxBoxSizer(wxHORIZONTAL);
4308 boxDispStatusBar->Add(defaultBoatSpeedSizer, wxALL, group_item_spacing);
4309 defaultBoatSpeedSizer->Add(
4310 new wxStaticText(pDisplayPanel, wxID_ANY, _("Default Boat Speed ")),
4311 groupLabelFlagsHoriz);
4312 pSDefaultBoatSpeed =
4313 new wxTextCtrl(pDisplayPanel, ID_DEFAULT_BOAT_SPEED, _T(""),
4314 wxDefaultPosition, wxSize(50, -1), wxTE_RIGHT);
4315 defaultBoatSpeedSizer->Add(pSDefaultBoatSpeed, 0, wxALIGN_CENTER_VERTICAL,
4316 group_item_spacing);
4317
4318 // --------------------------------------
4319 // END OF CUSTOMIZATION - LIVE ETA OPTION
4320
4321#ifndef __OCPN__ANDROID__
4322 if (g_Platform->GetDisplayAreaCM2() > 100) {
4323 // MultiChart selection panel
4324 wxStaticBox* itemStaticBoxScreenConfig =
4325 new wxStaticBox(pDisplayPanel, wxID_ANY, _("Canvas Layout"));
4326 wxStaticBoxSizer* itemStaticBoxSizerScreenConfig =
4327 new wxStaticBoxSizer(itemStaticBoxScreenConfig, wxHORIZONTAL);
4328 wrapperSizer->Add(itemStaticBoxSizerScreenConfig, 1, wxALL | wxEXPAND, 5);
4329
4330 // The standard screen configs...
4331 wxString iconDir = g_Platform->GetSharedDataDir();
4332 appendOSDirSlash(&iconDir);
4333 iconDir.append(_T("uidata"));
4334 appendOSDirSlash(&iconDir);
4335 iconDir.append(_T("MUI_flat"));
4336 appendOSDirSlash(&iconDir);
4337 int bmpSize = GetCharHeight() * 3;
4338
4339 wxBitmap bmp =
4340 LoadSVG(iconDir + _T("MUI_Sconfig_1.svg"), bmpSize, bmpSize);
4341 m_sconfigSelect_single =
4342 new CanvasConfigSelect(pDisplayPanel, this, ID_SCREENCONFIG1, bmp);
4343 itemStaticBoxSizerScreenConfig->Add(m_sconfigSelect_single, 0,
4344 wxALIGN_LEFT);
4345
4346 itemStaticBoxSizerScreenConfig->AddSpacer(GetCharHeight());
4347
4348 bmp = LoadSVG(iconDir + _T("MUI_Sconfig_2.svg"), bmpSize, bmpSize);
4349 m_sconfigSelect_twovertical =
4350 new CanvasConfigSelect(pDisplayPanel, this, ID_SCREENCONFIG2, bmp);
4351 itemStaticBoxSizerScreenConfig->Add(m_sconfigSelect_twovertical, 0,
4352 wxALIGN_LEFT);
4353
4354 itemStaticBoxSizerScreenConfig->AddSpacer(GetCharHeight());
4355 }
4356#endif
4357 }
4358}
4359
4360void options::CreatePanel_Units(size_t parent, int border_size,
4361 int group_item_spacing) {
4362 wxScrolledWindow* panelUnits = AddPage(parent, _("Units"));
4363
4364 if (m_bcompact) {
4365 wxFlexGridSizer* unitsSizer = new wxFlexGridSizer(2);
4366 unitsSizer->SetHGap(border_size);
4367
4368 // wxFlexGridSizer grows wrongly in wx2.8, so we need to centre it in
4369 // another sizer instead of letting it grow.
4370 wxBoxSizer* wrapperSizer = new wxBoxSizer(wxVERTICAL);
4371 panelUnits->SetSizer(wrapperSizer);
4372
4373 wrapperSizer->Add(1, border_size * 24);
4374 wrapperSizer->Add(unitsSizer, 1, wxALL | wxALIGN_CENTER, border_size);
4375
4376 // spacer
4377 unitsSizer->Add(0, border_size * 4);
4378 unitsSizer->Add(0, border_size * 4);
4379
4380 // distance units
4381 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Distance")),
4382 labelFlags);
4383 wxString pDistanceFormats[] = {_("Nautical miles"), _("Statute miles"),
4384 _("Kilometers"), _("Meters")};
4385 int m_DistanceFormatsNChoices = sizeof(pDistanceFormats) / sizeof(wxString);
4386 pDistanceFormat =
4387 new wxChoice(panelUnits, ID_DISTANCEUNITSCHOICE, wxDefaultPosition,
4388 wxSize(m_fontHeight * 4, -1), m_DistanceFormatsNChoices,
4389 pDistanceFormats);
4390#ifdef __OCPN__ANDROID__
4391 setChoiceStyleSheet(pDistanceFormat, m_fontHeight * 8 / 10);
4392#endif
4393 unitsSizer->Add(pDistanceFormat, inputFlags);
4394
4395 // speed units
4396 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Speed")),
4397 labelFlags);
4398 wxString pSpeedFormats[] = {_("Knots"), _("Mph"), _("km/h"), _("m/s")};
4399 int m_SpeedFormatsNChoices = sizeof(pSpeedFormats) / sizeof(wxString);
4400 pSpeedFormat = new wxChoice(panelUnits, ID_SPEEDUNITSCHOICE,
4401 wxDefaultPosition, wxSize(m_fontHeight * 4, -1),
4402 m_SpeedFormatsNChoices, pSpeedFormats);
4403#ifdef __OCPN__ANDROID__
4404 setChoiceStyleSheet(pSpeedFormat, m_fontHeight * 8 / 10);
4405#endif
4406 unitsSizer->Add(pSpeedFormat, inputFlags);
4407
4408 // depth units
4409 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Depth")),
4410 labelFlags);
4411 wxString pDepthUnitStrings[] = {
4412 _("Feet"),
4413 _("Meters"),
4414 _("Fathoms"),
4415 };
4416 pDepthUnitSelect =
4417 new wxChoice(panelUnits, ID_DEPTHUNITSCHOICE, wxDefaultPosition,
4418 wxSize(m_fontHeight * 4, -1), 3, pDepthUnitStrings);
4419#ifdef __OCPN__ANDROID__
4420 setChoiceStyleSheet(pDepthUnitSelect, m_fontHeight * 8 / 10);
4421#endif
4422 unitsSizer->Add(pDepthUnitSelect, inputFlags);
4423
4424 // temperature units
4425 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Temperature")),
4426 labelFlags);
4427 wxString pTempUnitStrings[] = {
4428 _("Celsius"),
4429 _("Fahrenheit"),
4430 _("Kelvin"),
4431 };
4432 pTempFormat =
4433 new wxChoice(panelUnits, ID_TEMPUNITSCHOICE, wxDefaultPosition,
4434 wxSize(m_fontHeight * 4, -1), 3, pTempUnitStrings);
4435#ifdef __OCPN__ANDROID__
4436 setChoiceStyleSheet(pTempFormat, m_fontHeight * 8 / 10);
4437#endif
4438 unitsSizer->Add(pTempFormat, inputFlags);
4439
4440 // spacer
4441 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _T("")));
4442 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _T("")));
4443
4444 // lat/long units
4445 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Lat/Long")),
4446 labelFlags);
4447 wxString pSDMMFormats[] = {_("Degrees, Decimal Minutes"),
4448 _("Decimal Degrees"),
4449 _("Degrees, Minutes, Seconds")};
4450 int m_SDMMFormatsNChoices = sizeof(pSDMMFormats) / sizeof(wxString);
4451 pSDMMFormat = new wxChoice(panelUnits, ID_SDMMFORMATCHOICE,
4452 wxDefaultPosition, wxSize(m_fontHeight * 4, -1),
4453 m_SDMMFormatsNChoices, pSDMMFormats);
4454#ifdef __OCPN__ANDROID__
4455 setChoiceStyleSheet(pSDMMFormat, m_fontHeight * 8 / 10);
4456#endif
4457 unitsSizer->Add(pSDMMFormat, inputFlags);
4458
4459 // spacer
4460 unitsSizer->Add(0, border_size * 4);
4461 unitsSizer->Add(0, border_size * 4);
4462
4463 // bearings (magnetic/true, variation)
4464 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Bearings")),
4465 groupLabelFlags);
4466
4467 // "Mag Heading" checkbox
4468 pCBTrueShow =
4469 new wxCheckBox(panelUnits, ID_TRUESHOWCHECKBOX, _("Show true"));
4470 unitsSizer->Add(pCBTrueShow, 0, wxALL, group_item_spacing);
4471 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _T("")));
4472
4473 pCBMagShow =
4474 new wxCheckBox(panelUnits, ID_MAGSHOWCHECKBOX, _("Show magnetic"));
4475 unitsSizer->Add(pCBMagShow, 0, wxALL, group_item_spacing);
4476 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _T("")));
4477
4478 // Mag Heading user variation
4479
4480 wxStaticBox* itemStaticBoxVar =
4481 new wxStaticBox(panelUnits, wxID_ANY, _T(""));
4482
4483 wxStaticBoxSizer* itemStaticBoxSizerVar =
4484 new wxStaticBoxSizer(itemStaticBoxVar, wxVERTICAL);
4485 wrapperSizer->Add(itemStaticBoxSizerVar, 0, wxALL | wxEXPAND, 5);
4486
4487 itemStaticBoxSizerVar->Add(0, border_size * 4);
4488
4489 itemStaticTextUserVar =
4490 new wxStaticText(panelUnits, wxID_ANY, _("Assumed magnetic variation"));
4491 itemStaticBoxSizerVar->Add(itemStaticTextUserVar, 1, wxEXPAND | wxALL,
4492 group_item_spacing);
4493
4494 wxBoxSizer* magVarSizer = new wxBoxSizer(wxHORIZONTAL);
4495 itemStaticBoxSizerVar->Add(magVarSizer, 1, wxEXPAND | wxALL,
4496 group_item_spacing);
4497
4498 pMagVar = new wxTextCtrl(panelUnits, ID_OPTEXTCTRL, _T(""),
4499 wxDefaultPosition, wxSize(150, -1), wxTE_RIGHT);
4500 magVarSizer->AddSpacer(100);
4501
4502 magVarSizer->Add(pMagVar, 0, wxALIGN_CENTRE_VERTICAL, group_item_spacing);
4503
4504 itemStaticTextUserVar2 =
4505 new wxStaticText(panelUnits, wxID_ANY, _("deg (-W, +E)"));
4506
4507 magVarSizer->Add(itemStaticTextUserVar2, 0, wxALL | wxALIGN_CENTRE_VERTICAL,
4508 group_item_spacing);
4509
4510 itemStaticBoxSizerVar->Add(0, border_size * 40);
4511
4512 } else {
4513 wxFlexGridSizer* unitsSizer = new wxFlexGridSizer(2);
4514 unitsSizer->SetHGap(border_size);
4515
4516 // wxFlexGridSizer grows wrongly in wx2.8, so we need to centre it in
4517 // another sizer instead of letting it grow.
4518 wxBoxSizer* wrapperSizer = new wxBoxSizer(wxVERTICAL);
4519 panelUnits->SetSizer(wrapperSizer);
4520 wrapperSizer->Add(unitsSizer, 1, wxALL | wxALIGN_CENTER, border_size);
4521
4522 // spacer
4523 unitsSizer->Add(0, border_size * 4);
4524 unitsSizer->Add(0, border_size * 4);
4525
4526 // distance units
4527 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Distance")),
4528 labelFlags);
4529 wxString pDistanceFormats[] = {_("Nautical miles"), _("Statute miles"),
4530 _("Kilometers"), _("Meters")};
4531 int m_DistanceFormatsNChoices = sizeof(pDistanceFormats) / sizeof(wxString);
4532 pDistanceFormat = new wxChoice(panelUnits, ID_DISTANCEUNITSCHOICE,
4533 wxDefaultPosition, wxDefaultSize,
4534 m_DistanceFormatsNChoices, pDistanceFormats);
4535 unitsSizer->Add(pDistanceFormat, inputFlags);
4536
4537 // speed units
4538 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Speed")),
4539 labelFlags);
4540 wxString pSpeedFormats[] = {_("Knots"), _("Mph"), _("km/h"), _("m/s")};
4541 int m_SpeedFormatsNChoices = sizeof(pSpeedFormats) / sizeof(wxString);
4542 pSpeedFormat =
4543 new wxChoice(panelUnits, ID_SPEEDUNITSCHOICE, wxDefaultPosition,
4544 wxDefaultSize, m_SpeedFormatsNChoices, pSpeedFormats);
4545 unitsSizer->Add(pSpeedFormat, inputFlags);
4546
4547 // depth units
4548 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Depth")),
4549 labelFlags);
4550 wxString pDepthUnitStrings[] = {
4551 _("Feet"),
4552 _("Meters"),
4553 _("Fathoms"),
4554 };
4555 pDepthUnitSelect =
4556 new wxChoice(panelUnits, ID_DEPTHUNITSCHOICE, wxDefaultPosition,
4557 wxDefaultSize, 3, pDepthUnitStrings);
4558 unitsSizer->Add(pDepthUnitSelect, inputFlags);
4559
4560 // temperature units
4561 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Temperature")),
4562 labelFlags);
4563 wxString pTempUnitStrings[] = {
4564 _("Celsius"),
4565 _("Fahrenheit"),
4566 _("Kelvin"),
4567 };
4568 pTempFormat =
4569 new wxChoice(panelUnits, ID_TEMPUNITSCHOICE, wxDefaultPosition,
4570 wxDefaultSize, 3, pTempUnitStrings);
4571 unitsSizer->Add(pTempFormat, inputFlags);
4572
4573 // spacer
4574 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _T("")));
4575 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _T("")));
4576
4577 // lat/long units
4578 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Lat/Long")),
4579 labelFlags);
4580 wxString pSDMMFormats[] = {_("Degrees, Decimal Minutes"),
4581 _("Decimal Degrees"),
4582 _("Degrees, Minutes, Seconds")};
4583 int m_SDMMFormatsNChoices = sizeof(pSDMMFormats) / sizeof(wxString);
4584 pSDMMFormat =
4585 new wxChoice(panelUnits, ID_SDMMFORMATCHOICE, wxDefaultPosition,
4586 wxDefaultSize, m_SDMMFormatsNChoices, pSDMMFormats);
4587 unitsSizer->Add(pSDMMFormat, inputFlags);
4588
4589 // spacer
4590 unitsSizer->Add(0, border_size * 4);
4591 unitsSizer->Add(0, border_size * 4);
4592
4593 // bearings (magnetic/true, variation)
4594 unitsSizer->Add(new wxStaticText(panelUnits, wxID_ANY, _("Bearings")),
4595 groupLabelFlags);
4596
4597 wxBoxSizer* bearingsSizer = new wxBoxSizer(wxVERTICAL);
4598 unitsSizer->Add(bearingsSizer, 0, 0, 0);
4599
4600 // "Mag Heading" checkbox
4601 pCBTrueShow = new wxCheckBox(panelUnits, ID_TRUESHOWCHECKBOX,
4602 _("Show true bearings and headings"));
4603 bearingsSizer->Add(pCBTrueShow, 0, wxALL, group_item_spacing);
4604 pCBMagShow = new wxCheckBox(panelUnits, ID_MAGSHOWCHECKBOX,
4605 _("Show magnetic bearings and headings."));
4606 bearingsSizer->Add(pCBMagShow, 0, wxALL, group_item_spacing);
4607
4608 bearingsSizer->AddSpacer(10);
4609
4610 // Mag Heading user variation
4611 wxBoxSizer* magVarSizer = new wxBoxSizer(wxHORIZONTAL);
4612 bearingsSizer->Add(magVarSizer, 0, wxALL, group_item_spacing);
4613
4614 itemStaticTextUserVar =
4615 new wxStaticText(panelUnits, wxID_ANY, wxEmptyString);
4616 itemStaticTextUserVar->SetLabel(
4617 _("WMM Plugin calculated magnetic variation"));
4618
4619 magVarSizer->Add(itemStaticTextUserVar, 0, wxALL | wxALIGN_CENTRE_VERTICAL,
4620 group_item_spacing);
4621
4622 pMagVar = new wxTextCtrl(panelUnits, ID_OPTEXTCTRL, _T(""),
4623 wxDefaultPosition, wxSize(50, -1), wxTE_RIGHT);
4624 magVarSizer->Add(pMagVar, 0, wxALIGN_CENTRE_VERTICAL, group_item_spacing);
4625
4626 itemStaticTextUserVar2 =
4627 new wxStaticText(panelUnits, wxID_ANY, _("deg (-W, +E)"));
4628 magVarSizer->Add(itemStaticTextUserVar2, 0, wxALL | wxALIGN_CENTRE_VERTICAL,
4629 group_item_spacing);
4630
4631 bearingsSizer->AddSpacer(10);
4632
4633 wxStaticText* varText =
4634 new wxStaticText(panelUnits, wxID_ANY,
4635 _(" To set the magnetic variation manually,\n you "
4636 "must disable the WMM plugin."));
4637 smallFont = *dialogFont;
4638 smallFont.SetPointSize((smallFont.GetPointSize() / 1.2) +
4639 0.5); // + 0.5 to round instead of truncate
4640 varText->SetFont(smallFont);
4641
4642 bearingsSizer->Add(varText);
4643 }
4644}
4645
4646class OCPNSoundPanel: public wxPanel
4647{
4648public:
4649 OCPNSoundPanel( wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size,
4650 wxString title,
4651 wxString checkLegend,
4652 wxString selectLegend,
4653 wxString *pSoundFile
4654 );
4655
4656 ~OCPNSoundPanel() {};
4657
4658 void OnButtonSelectSound(wxCommandEvent& event);
4659 void OnButtonTestSound(wxCommandEvent& event);
4660 wxString SelectSoundFile();
4661 void SetSoundFileLabel(wxString file);
4662 wxCheckBox *GetCheckBox(){ return m_pCheck_Sound; }
4663
4664 wxCheckBox *m_pCheck_Sound;
4665 wxSize m_small_button_size;
4666 wxString m_sound_file;
4667 wxString *m_pSoundFile;
4668 wxStaticText *m_AudioFileNameText;
4669
4670 wxButton* SelSound;
4671 wxButton* TestSound;
4672
4673 DECLARE_EVENT_TABLE()
4674};
4675
4676#define ID_SELECTSOUND 9341
4677#define ID_TESTSOUND 9342
4678
4679
4680BEGIN_EVENT_TABLE(OCPNSoundPanel, wxPanel)
4681EVT_BUTTON(ID_SELECTSOUND, OCPNSoundPanel::OnButtonSelectSound)
4682EVT_BUTTON(ID_TESTSOUND, OCPNSoundPanel::OnButtonTestSound)
4683
4684
4685END_EVENT_TABLE()
4686
4687OCPNSoundPanel::OCPNSoundPanel( wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size,
4688 wxString title,
4689 wxString checkLegend,
4690 wxString selectLegend,
4691 wxString *pSoundFile)
4692:wxPanel(parent, id, pos, size, wxBORDER_NONE)
4693{
4694 wxFont* pif = FontMgr::Get().GetFont(_T("Dialog"));
4695 SetFont( *pif );
4696
4697 m_pSoundFile = pSoundFile;
4698 if(pSoundFile)
4699 m_sound_file = *pSoundFile;
4700
4701 int border_size = 4;
4702 int group_item_spacing = 2;
4703
4704 int font_size_y, font_descent, font_lead;
4705 GetTextExtent(_T("0"), NULL, &font_size_y, &font_descent, &font_lead);
4706 m_small_button_size =
4707 wxSize(-1, (int)(1.6 * (font_size_y + font_descent)));
4708
4709
4710 wxBoxSizer* wrapperSizer = new wxBoxSizer(wxVERTICAL);
4711 SetSizer(wrapperSizer);
4712
4713 wxStaticBox* StaticBox1 =
4714 new wxStaticBox(this, wxID_ANY, title);
4715 wxStaticBoxSizer* StaticBoxSizer1 =
4716 new wxStaticBoxSizer(StaticBox1, wxVERTICAL);
4717 wrapperSizer->Add(StaticBoxSizer1, 0, wxALL | wxEXPAND, border_size);
4718
4719 m_pCheck_Sound = new wxCheckBox(this, ID_ANCHORALERTAUDIO,
4720 checkLegend);
4721 StaticBoxSizer1->Add(m_pCheck_Sound, 1, wxALL, group_item_spacing);
4722
4723 // Sound file
4724 wxString LabelWrapped;
4725
4726#ifdef __OCPN__ANDROID__
4727 // Count the likely number of lines in the wrapped file name
4728 // to set the default wxStaticText size.
4729 ChartDirPanelHardBreakWrapper wrapper(this, m_sound_file, g_pOptions->GetSize().x * 8 / 10);
4730 wxArrayString LabelWrappedArray = wrapper.GetLineArray();
4731 for (unsigned int i=0 ; i < LabelWrappedArray.GetCount() ; i++){
4732 LabelWrapped += "\n";
4733 }
4734 LabelWrapped += "\n";
4735#endif
4736
4737 m_AudioFileNameText = new wxStaticText(this, wxID_ANY, LabelWrapped);
4738 m_AudioFileNameText->Wrap(-1);
4739 StaticBoxSizer1->Add(m_AudioFileNameText, 0, wxALL | wxEXPAND, border_size);
4740
4741 SetSoundFileLabel(m_sound_file);
4742
4743 // Select/Test sound
4744 wxFlexGridSizer* soundSizer1 = new wxFlexGridSizer(3);
4745 soundSizer1->SetHGap(border_size * 2);
4746 StaticBoxSizer1->Add(soundSizer1, 1, wxALL | wxLEFT, border_size);
4747
4748 SelSound = new wxButton(
4749 this, ID_SELECTSOUND, selectLegend,
4750 wxDefaultPosition, m_small_button_size, 0);
4751 soundSizer1->Add(SelSound, 0, wxALL | wxALIGN_RIGHT,
4752 group_item_spacing);
4753 soundSizer1->AddSpacer(group_item_spacing * 4);
4754 TestSound = new wxButton(
4755 this, ID_TESTSOUND, _("Test"),
4756 wxDefaultPosition, m_small_button_size, 0);
4757 soundSizer1->Add(TestSound, 0, wxALL | wxALIGN_RIGHT,
4758 group_item_spacing);
4759
4760}
4761
4762void OCPNSoundPanel::SetSoundFileLabel(wxString file)
4763{
4764 wxString soundLabel = wxString( " " + _("Audio file name:") + "\n " +
4765 file);
4766
4767 ChartDirPanelHardBreakWrapper wrapper(this, soundLabel, g_pOptions->GetSize().x * 8 / 10);
4768 wxArrayString LabelWrappedArray = wrapper.GetLineArray();
4769 wxString LabelWrapped;
4770 for (unsigned int i=0 ; i < LabelWrappedArray.GetCount() ; i++){
4771 if (i == 0)
4772 LabelWrapped += LabelWrappedArray[i].BeforeFirst('/');
4773 else
4774 LabelWrapped += LabelWrappedArray[i];
4775 LabelWrapped += "\n";
4776 }
4777
4778 m_AudioFileNameText->SetLabel(LabelWrapped);
4779 Layout();
4780}
4781
4782
4783
4784wxString OCPNSoundPanel::SelectSoundFile() {
4785 wxString sound_dir = g_Platform->GetSharedDataDir();
4786 sound_dir.Append(_T("sounds"));
4787 wxString sel_file;
4788 int response;
4789
4790#ifndef __OCPN__ANDROID__
4791 wxFileDialog* popenDialog = new wxFileDialog(
4792 NULL, _("Select Sound File"), sound_dir, wxEmptyString,
4793 _T("WAV files (*.wav)|*.wav|All files (*.*)|*.*"), wxFD_OPEN);
4794 if (g_bresponsive)
4795 popenDialog = g_Platform->AdjustFileDialogFont(this, popenDialog);
4796
4797 response = popenDialog->ShowModal();
4798 sel_file = popenDialog->GetPath();
4799 delete popenDialog;
4800
4801#else
4802 response =
4803 g_Platform->DoFileSelectorDialog(this, &sel_file, _("Select Sound File"),
4804 sound_dir, wxEmptyString, wxT("*.*"));
4805#endif
4806
4807 wxString rv;
4808 if (response == wxID_OK)
4809 return g_Platform->NormalizePath(sel_file);
4810 else
4811 return _T("");
4812}
4813
4814void OCPNSoundPanel::OnButtonSelectSound(wxCommandEvent& event) {
4815 wxString sel_file = SelectSoundFile();
4816
4817 if (!sel_file.IsEmpty()) {
4818 m_sound_file = g_Platform->NormalizePath(sel_file);
4819 if(m_pSoundFile)
4820 *m_pSoundFile = m_sound_file; // Update global variable
4821
4822 SetSoundFileLabel(m_sound_file);
4823 //g_anchorwatch_sound->Stop();
4824 }
4825}
4826
4827void OCPNSoundPanel::OnButtonTestSound(wxCommandEvent& event) {
4828 auto sound = SoundFactory();
4829 auto cmd_sound = dynamic_cast<SystemCmdSound*>(sound);
4830 if (cmd_sound) cmd_sound->SetCmd(g_CmdSoundString.mb_str());
4831 sound->SetFinishedCallback([sound](void*) { delete sound; });
4832 sound->Load(m_sound_file, g_iSoundDeviceIndex);
4833 sound->Play();
4834}
4835
4836
4837
4838
4839
4840
4841void options::CreatePanel_Sounds(size_t parent, int border_size,
4842 int group_item_spacing) {
4843
4844 wxScrolledWindow* panelSounds = AddPage(parent, _("Sounds"));
4845
4846 wxBoxSizer* wrapperSizer = new wxBoxSizer(wxVERTICAL);
4847 panelSounds->SetSizer(wrapperSizer);
4848
4849 // Anchor Alarm
4850 m_soundPanelAnchor = new OCPNSoundPanel( panelSounds, wxID_ANY,
4851 wxDefaultPosition, wxDefaultSize,
4852 _("Anchor Alarm"),
4853 _("Play Sound on Anchor Alarm."),
4854 _("Select Anchor Alarm Sound"),
4855 &g_anchorwatch_sound_file
4856 );
4857 wrapperSizer->Add(m_soundPanelAnchor, 1, wxALL | wxEXPAND, border_size);
4858
4859
4860 // AIS Alert
4861 m_soundPanelAIS = new OCPNSoundPanel( panelSounds, wxID_ANY,
4862 wxDefaultPosition, wxDefaultSize,
4863 _("AIS Alert"),
4864 _("Play Sound on AIS Alert."),
4865 _("Select AIS Alert Sound"),
4866 &g_AIS_sound_file
4867 );
4868 wrapperSizer->Add(m_soundPanelAIS, 1, wxALL | wxEXPAND, border_size);
4869
4870
4871 // SART Alert
4872 m_soundPanelSART = new OCPNSoundPanel( panelSounds, wxID_ANY,
4873 wxDefaultPosition, wxDefaultSize,
4874 _("SART Alert"),
4875 _("Play Sound on AIS SART Alert."),
4876 _("Select AIS SART Alert Sound"),
4877 &g_SART_sound_file
4878 );
4879 wrapperSizer->Add(m_soundPanelSART, 1, wxALL | wxEXPAND, border_size);
4880
4881 // DSC Call
4882 m_soundPanelDSC = new OCPNSoundPanel( panelSounds, wxID_ANY,
4883 wxDefaultPosition, wxDefaultSize,
4884 _("DSC Alert"),
4885 _("Play Sound on DSC notification."),
4886 _("Select DSC notification Sound"),
4887 &g_DSC_sound_file
4888 );
4889 wrapperSizer->Add(m_soundPanelDSC, 1, wxALL | wxEXPAND, border_size);
4890}
4891
4892void options::CreatePanel_MMSI(size_t parent, int border_size,
4893 int group_item_spacing) {
4894 wxScrolledWindow* panelMMSI = AddPage(parent, _("MMSI Properties"));
4895
4896 wxBoxSizer* MMSISizer = new wxBoxSizer(wxVERTICAL);
4897 panelMMSI->SetSizer(MMSISizer);
4898
4899 // MMSI list control (panel)
4900 wxStaticBox* itemStaticBoxMMSI =
4901 new wxStaticBox(panelMMSI, wxID_ANY, _("MMSI Properties"));
4902 wxStaticBoxSizer* itemStaticBoxSizerMMSI =
4903 new wxStaticBoxSizer(itemStaticBoxMMSI, wxVERTICAL);
4904 MMSISizer->Add(itemStaticBoxSizerMMSI, 0, wxALL | wxEXPAND, border_size);
4905
4906 MMSI_Props_Panel* pPropsPanel = new MMSI_Props_Panel(panelMMSI);
4907
4908 pPropsPanel->UpdateMMSIList();
4909
4910 itemStaticBoxSizerMMSI->Add(pPropsPanel, 0, wxALL | wxEXPAND, border_size);
4911
4912 panelMMSI->Layout();
4913}
4914
4915void options::CreatePanel_AIS(size_t parent, int border_size,
4916 int group_item_spacing) {
4917 wxScrolledWindow* panelAIS = AddPage(parent, _("AIS Targets"));
4918
4919 wxBoxSizer* aisSizer = new wxBoxSizer(wxVERTICAL);
4920 panelAIS->SetSizer(aisSizer);
4921
4922 // CPA Box
4923 wxStaticBox* itemStaticBoxCPA =
4924 new wxStaticBox(panelAIS, wxID_ANY, _("CPA Calculation"));
4925 wxStaticBoxSizer* itemStaticBoxSizerCPA =
4926 new wxStaticBoxSizer(itemStaticBoxCPA, wxVERTICAL);
4927 aisSizer->Add(itemStaticBoxSizerCPA, 0, wxALL | wxEXPAND, border_size);
4928
4929 wxFlexGridSizer* pCPAGrid = new wxFlexGridSizer(2);
4930 pCPAGrid->AddGrowableCol(1);
4931 itemStaticBoxSizerCPA->Add(pCPAGrid, 0, wxALL | wxEXPAND, border_size);
4932
4933 m_pCheck_CPA_Max = new wxCheckBox(
4934 panelAIS, -1,
4935 _("No (T)CPA Alerts if target range is greater than (NMi)"));
4936 pCPAGrid->Add(m_pCheck_CPA_Max, 0, wxALL, group_item_spacing);
4937
4938 m_pText_CPA_Max = new wxTextCtrl(panelAIS, -1, "TEXT ");
4939 pCPAGrid->Add(m_pText_CPA_Max, 0, wxALL | wxALIGN_RIGHT, group_item_spacing);
4940
4941 m_pCheck_CPA_Warn =
4942 new wxCheckBox(panelAIS, -1, _("Warn if CPA less than (NMi)"));
4943 pCPAGrid->Add(m_pCheck_CPA_Warn, 0, wxALL, group_item_spacing);
4944
4945 m_pText_CPA_Warn =
4946 new wxTextCtrl(panelAIS, -1,"TEXT ", wxDefaultPosition, wxSize(-1, -1));
4947 pCPAGrid->Add(m_pText_CPA_Warn, 0, wxALL | wxALIGN_RIGHT, group_item_spacing);
4948
4949 m_pCheck_CPA_Warn->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
4950 wxCommandEventHandler(options::OnCPAWarnClick),
4951 NULL, this);
4952
4953 m_pCheck_CPA_WarnT =
4954 new wxCheckBox(panelAIS, -1, _("...and TCPA is less than (min)"));
4955 pCPAGrid->Add(m_pCheck_CPA_WarnT, 0, wxALL, group_item_spacing);
4956
4957 m_pText_CPA_WarnT = new wxTextCtrl(panelAIS, -1, "TEXT ");
4958 pCPAGrid->Add(m_pText_CPA_WarnT, 0, wxALL | wxALIGN_RIGHT,
4959 group_item_spacing);
4960
4961 // Lost Targets
4962 wxStaticBox* lostBox = new wxStaticBox(panelAIS, wxID_ANY, _("Lost Targets"));
4963 wxStaticBoxSizer* lostSizer = new wxStaticBoxSizer(lostBox, wxVERTICAL);
4964 aisSizer->Add(lostSizer, 0, wxALL | wxEXPAND, 3);
4965
4966 wxFlexGridSizer* pLostGrid = new wxFlexGridSizer(2);
4967 pLostGrid->AddGrowableCol(1);
4968 lostSizer->Add(pLostGrid, 0, wxALL | wxEXPAND, border_size);
4969
4970 m_pCheck_Mark_Lost =
4971 new wxCheckBox(panelAIS, -1, _("Mark targets as lost after (min)"));
4972 pLostGrid->Add(m_pCheck_Mark_Lost, 1, wxALL, group_item_spacing);
4973
4974 m_pText_Mark_Lost = new wxTextCtrl(panelAIS, -1, "TEXT ");
4975 pLostGrid->Add(m_pText_Mark_Lost, 1, wxALL | wxALIGN_RIGHT,
4976 group_item_spacing);
4977
4978 m_pCheck_Remove_Lost =
4979 new wxCheckBox(panelAIS, -1, _("Remove lost targets after (min)"));
4980 pLostGrid->Add(m_pCheck_Remove_Lost, 1, wxALL, group_item_spacing);
4981
4982 m_pText_Remove_Lost = new wxTextCtrl(panelAIS, -1, "TEXT ");
4983 pLostGrid->Add(m_pText_Remove_Lost, 1, wxALL | wxALIGN_RIGHT,
4984 group_item_spacing);
4985
4986 if (g_bInlandEcdis) lostSizer->Hide(pLostGrid, true);
4987
4988 // Display
4989 wxStaticBox* displBox = new wxStaticBox(panelAIS, wxID_ANY, _("Display"));
4990 wxStaticBoxSizer* displSizer = new wxStaticBoxSizer(displBox, wxHORIZONTAL);
4991 aisSizer->Add(displSizer, 0, wxALL | wxEXPAND, border_size);
4992
4993 wxFlexGridSizer* pDisplayGrid = new wxFlexGridSizer(2);
4994 pDisplayGrid->AddGrowableCol(1);
4995 displSizer->Add(pDisplayGrid, 1, wxALL | wxEXPAND, border_size);
4996
4997 m_pCheck_Show_COG = new wxCheckBox(
4998 panelAIS, -1, _("Show target COG predictor arrow, length (min)"));
4999 pDisplayGrid->Add(m_pCheck_Show_COG, 1, wxALL | wxEXPAND, group_item_spacing);
5000
5001 m_pText_COG_Predictor = new wxTextCtrl(panelAIS, -1, "TEXT ");
5002 pDisplayGrid->Add(m_pText_COG_Predictor, 1, wxALL | wxALIGN_RIGHT,
5003 group_item_spacing);
5004
5005 m_pCheck_Sync_OCOG_ACOG = new wxCheckBox(
5006 panelAIS, -1, _("Sync AIS arrow length with own ship's COG predictor"));
5007 pDisplayGrid->Add(m_pCheck_Sync_OCOG_ACOG, 1, wxALL, group_item_spacing);
5008 m_pCheck_Sync_OCOG_ACOG->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
5009 wxCommandEventHandler(options::OnSyncCogPredClick),
5010 NULL, this);
5011
5012 wxStaticText* pStatic_Dummy4a = new wxStaticText(panelAIS, -1, _T(""));
5013 pDisplayGrid->Add(pStatic_Dummy4a, 1, wxALL, group_item_spacing);
5014
5015 m_pCheck_Show_Tracks =
5016 new wxCheckBox(panelAIS, -1, _("Show target tracks, length (min)"));
5017 pDisplayGrid->Add(m_pCheck_Show_Tracks, 1, wxALL, group_item_spacing);
5018
5019 m_pText_Track_Length = new wxTextCtrl(panelAIS, -1, "TEXT ");
5020 pDisplayGrid->Add(m_pText_Track_Length, 1, wxALL | wxALIGN_RIGHT,
5021 group_item_spacing);
5022
5023 m_pCheck_Hide_Moored = new wxCheckBox(
5024 panelAIS, -1, _("Suppress anchored/moored targets, speed max (kn)"));
5025 pDisplayGrid->Add(m_pCheck_Hide_Moored, 1, wxALL, group_item_spacing);
5026
5027 m_pText_Moored_Speed = new wxTextCtrl(panelAIS, -1, "TEXT ");
5028 pDisplayGrid->Add(m_pText_Moored_Speed, 1, wxALL | wxALIGN_RIGHT,
5029 group_item_spacing);
5030
5031 m_pCheck_Draw_Realtime_Prediction = new wxCheckBox(
5032 panelAIS, -1, _("Draw AIS realtime prediction, target speed min (kn)"));
5033 pDisplayGrid->Add(m_pCheck_Draw_Realtime_Prediction, 1, wxALL,
5034 group_item_spacing);
5035
5036 m_pText_RealtPred_Speed = new wxTextCtrl(panelAIS, -1, "TEXT ");
5037 pDisplayGrid->Add(m_pText_RealtPred_Speed, 1, wxALL | wxALIGN_RIGHT,
5038 group_item_spacing);
5039
5040 m_pCheck_Scale_Priority = new wxCheckBox(
5041 panelAIS, -1,
5042 _("Allow attenuation of less critical targets if more than ... targets"));
5043 pDisplayGrid->Add(m_pCheck_Scale_Priority, 1, wxALL, group_item_spacing);
5044
5045 m_pText_Scale_Priority = new wxTextCtrl(panelAIS, -1, "TEXT ");
5046 pDisplayGrid->Add(m_pText_Scale_Priority, 1, wxALL | wxALIGN_RIGHT,
5047 group_item_spacing);
5048
5049 m_pCheck_Show_Area_Notices = new wxCheckBox(
5050 panelAIS, -1, _("Show area notices (from AIS binary messages)"));
5051 pDisplayGrid->Add(m_pCheck_Show_Area_Notices, 1, wxALL, group_item_spacing);
5052
5053 wxStaticText* pStatic_Dummy5 = new wxStaticText(panelAIS, -1, _T(""));
5054 pDisplayGrid->Add(pStatic_Dummy5, 1, wxALL, group_item_spacing);
5055
5056 m_pCheck_Draw_Target_Size =
5057 new wxCheckBox(panelAIS, -1, _("Show AIS targets real size"));
5058 pDisplayGrid->Add(m_pCheck_Draw_Target_Size, 1, wxALL, group_item_spacing);
5059
5060 wxStaticText* pStatic_Dummy6 = new wxStaticText(panelAIS, -1, _T(""));
5061 pDisplayGrid->Add(pStatic_Dummy6, 1, wxALL, group_item_spacing);
5062
5063 m_pCheck_Show_Target_Name = new wxCheckBox(
5064 panelAIS, -1, _("Show names with AIS targets at scale greater than 1:"));
5065 pDisplayGrid->Add(m_pCheck_Show_Target_Name, 1, wxALL, group_item_spacing);
5066
5067 m_pText_Show_Target_Name_Scale = new wxTextCtrl(panelAIS, -1, "TEXT ");
5068 pDisplayGrid->Add(m_pText_Show_Target_Name_Scale, 1, wxALL | wxALIGN_RIGHT,
5069 group_item_spacing);
5070
5071 m_pCheck_use_Wpl = new wxCheckBox(
5072 panelAIS, -1, _("Use WPL position messages. Action when received:"));
5073 pDisplayGrid->Add(m_pCheck_use_Wpl, 1, wxALL, group_item_spacing);
5074
5075 wxString Wpl_Action[] = {_("APRS position report"), _("Create mark")};
5076 m_pWplAction = new wxChoice(panelAIS, wxID_ANY, wxDefaultPosition,
5077 wxDefaultSize, 2, Wpl_Action);
5078 pDisplayGrid->Add(m_pWplAction, 1, wxALIGN_RIGHT | wxALL, group_item_spacing);
5079
5080 // Rollover
5081 wxStaticBox* rolloverBox = new wxStaticBox(panelAIS, wxID_ANY, _("Rollover"));
5082 wxStaticBoxSizer* rolloverSizer =
5083 new wxStaticBoxSizer(rolloverBox, wxVERTICAL);
5084 aisSizer->Add(rolloverSizer, 0, wxALL | wxEXPAND, border_size);
5085
5086 pRollover = new wxCheckBox(panelAIS, ID_ROLLOVERBOX,
5087 _("Enable route/AIS info block"));
5088 rolloverSizer->Add(pRollover, 1, wxALL, 2 * group_item_spacing);
5089
5090 pRollover->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
5091 wxCommandEventHandler(options::OnAISRolloverClick), NULL,
5092 this);
5093
5094 pStatic_CallSign =
5095 new wxStaticText(panelAIS, -1, _("\"Ship Name\" MMSI (Call Sign)"));
5096 rolloverSizer->Add(pStatic_CallSign, 1, wxALL, 2 * group_item_spacing);
5097
5098 m_pCheck_Rollover_Class =
5099 new wxCheckBox(panelAIS, -1, _("[Class] Type (Status)"));
5100 rolloverSizer->Add(m_pCheck_Rollover_Class, 1, wxALL, 2 * group_item_spacing);
5101
5102 m_pCheck_Rollover_COG = new wxCheckBox(panelAIS, -1, _("SOG COG"));
5103 rolloverSizer->Add(m_pCheck_Rollover_COG, 1, wxALL, 2 * group_item_spacing);
5104
5105 m_pCheck_Rollover_CPA = new wxCheckBox(panelAIS, -1, _("CPA TCPA"));
5106 rolloverSizer->Add(m_pCheck_Rollover_CPA, 1, wxALL, 2 * group_item_spacing);
5107
5108 // Alert Box
5109 wxStaticBox* alertBox =
5110 new wxStaticBox(panelAIS, wxID_ANY, _("CPA/TCPA Alerts"));
5111 wxStaticBoxSizer* alertSizer = new wxStaticBoxSizer(alertBox, wxVERTICAL);
5112 aisSizer->Add(alertSizer, 0, wxALL | wxEXPAND, group_item_spacing);
5113
5114 wxFlexGridSizer* pAlertGrid = new wxFlexGridSizer(2);
5115 pAlertGrid->AddGrowableCol(1);
5116 alertSizer->Add(pAlertGrid, 0, wxALL | wxEXPAND, group_item_spacing);
5117
5118 m_pCheck_AlertDialog = new wxCheckBox(panelAIS, ID_AISALERTDIALOG,
5119 _("Show CPA/TCPA Alert Dialog"));
5120 pAlertGrid->Add(m_pCheck_AlertDialog, 0, wxALL, group_item_spacing);
5121
5122 m_pCheck_AlertDialog->Connect(
5123 wxEVT_COMMAND_CHECKBOX_CLICKED,
5124 wxCommandEventHandler(options::OnAlertEnableButtonClick), NULL, this);
5125
5126 // wxButton* m_SelSound =
5127 // new wxButton(panelAIS, ID_AISALERTSELECTSOUND, _("Select Alert
5128 // Sound"),
5129 // wxDefaultPosition, m_small_button_size, 0);
5130 // pAlertGrid->Add(m_SelSound, 0, wxALL | wxALIGN_RIGHT,
5131 // group_item_spacing);
5132
5133 wxStaticText* pStatic_Dummy5a = new wxStaticText(panelAIS, -1, _T(""));
5134 pAlertGrid->Add(pStatic_Dummy5a, 1, wxALL, group_item_spacing);
5135
5136 m_pCheck_AlertAudio = new wxCheckBox(
5137 panelAIS, ID_AISALERTAUDIO,
5138 _("Play Sound on CPA/TCPA Alerts and DSC/SART emergencies."));
5139 pAlertGrid->Add(m_pCheck_AlertAudio, 0, wxALL, group_item_spacing);
5140
5141 m_pCheck_AlertAudio->Connect(
5142 wxEVT_COMMAND_CHECKBOX_CLICKED,
5143 wxCommandEventHandler(options::OnAlertAudioEnableButtonClick), NULL,
5144 this);
5145
5146 // wxButton* m_pPlay_Sound =
5147 // new wxButton(panelAIS, ID_AISALERTTESTSOUND, _("Test Alert Sound"),
5148 // wxDefaultPosition, m_small_button_size, 0);
5149 // pAlertGrid->Add(m_pPlay_Sound, 0, wxALL | wxALIGN_RIGHT,
5150 // group_item_spacing);
5151
5152 wxStaticText* pStatic_Dummy5b = new wxStaticText(panelAIS, -1, _T(""));
5153 pAlertGrid->Add(pStatic_Dummy5b, 1, wxALL, group_item_spacing);
5154
5155 m_pCheck_Alert_Moored = new wxCheckBox(
5156 panelAIS, -1, _("Suppress Alerts for anchored/moored targets"));
5157 pAlertGrid->Add(m_pCheck_Alert_Moored, 1, wxALL, group_item_spacing);
5158
5159 wxStaticText* pStatic_Dummy2 = new wxStaticText(panelAIS, -1, _T(""));
5160 pAlertGrid->Add(pStatic_Dummy2, 1, wxALL, group_item_spacing);
5161
5162 m_pCheck_Ack_Timout = new wxCheckBox(
5163 panelAIS, -1, _("Enable Target Alert Acknowledge timeout (min)"));
5164 pAlertGrid->Add(m_pCheck_Ack_Timout, 1, wxALL, group_item_spacing);
5165
5166 m_pText_ACK_Timeout = new wxTextCtrl(panelAIS, -1, "TEXT ");
5167 pAlertGrid->Add(m_pText_ACK_Timeout, 1, wxALL | wxALIGN_RIGHT,
5168 group_item_spacing);
5169
5170 panelAIS->Layout();
5171}
5172
5173class MouseZoomSlider : public wxSlider {
5174public:
5175 MouseZoomSlider(wxWindow* parent, wxSize size)
5176 : wxSlider(parent, wxID_ANY, 10, 1, 100, wxDefaultPosition, size,
5177 SLIDER_STYLE) {
5178 Show();
5179#ifdef __OCPN__ANDROID__
5180 GetHandle()->setStyleSheet(getQtStyleSheet());
5181#endif
5182 }
5183};
5184
5185void options::CreatePanel_UI(size_t parent, int border_size,
5186 int group_item_spacing) {
5187 wxScrolledWindow* itemPanelFont = AddPage(parent, _("General Options"));
5188
5189 m_itemBoxSizerFontPanel = new wxBoxSizer(wxVERTICAL);
5190 itemPanelFont->SetSizer(m_itemBoxSizerFontPanel);
5191
5192 wxBoxSizer* langStyleBox = new wxBoxSizer(wxHORIZONTAL);
5193 m_itemBoxSizerFontPanel->Add(langStyleBox, 0, wxEXPAND | wxALL, border_size);
5194
5195 wxStaticBox* itemLangStaticBox =
5196 new wxStaticBox(itemPanelFont, wxID_ANY, _("Language"));
5197 wxStaticBoxSizer* itemLangStaticBoxSizer =
5198 new wxStaticBoxSizer(itemLangStaticBox, wxVERTICAL);
5199
5200 langStyleBox->Add(itemLangStaticBoxSizer, 1, wxEXPAND | wxALL, border_size);
5201
5202 m_itemLangListBox = new wxChoice(itemPanelFont, ID_CHOICE_LANG);
5203
5204 itemLangStaticBoxSizer->Add(m_itemLangListBox, 0, wxEXPAND | wxALL,
5205 border_size);
5206#ifdef __OCPN__ANDROID__
5207 m_itemLangListBox->Disable();
5208#endif
5209
5210 wxStaticBox* itemFontStaticBox =
5211 new wxStaticBox(itemPanelFont, wxID_ANY, _("Fonts"));
5212
5213 wxSize fontChoiceSize = wxSize(-1, -1);
5214
5215 int fLayout = wxHORIZONTAL;
5216#ifdef __OCPN__ANDROID__
5217 // Compensate for very narrow displays on Android
5218 if (m_nCharWidthMax < 40) fLayout = wxVERTICAL;
5219
5220 // Need to set wxChoice vertical size explicitely in Android
5221 fontChoiceSize = wxSize(-1, m_fontHeight * 3 / 4);
5222#endif
5223
5224 wxStaticBoxSizer* itemFontStaticBoxSizer =
5225 new wxStaticBoxSizer(itemFontStaticBox, fLayout);
5226 m_itemBoxSizerFontPanel->Add(itemFontStaticBoxSizer, 0, wxEXPAND | wxALL,
5227 border_size);
5228
5229 m_itemFontElementListBox =
5230 new wxChoice(itemPanelFont, ID_CHOICE_FONTELEMENT, wxDefaultPosition,
5231 fontChoiceSize, 0, NULL, wxCB_SORT);
5232
5233 int nFonts = FontMgr::Get().GetNumFonts();
5234 for (int it = 0; it < nFonts; it++) {
5235 const wxString& t = FontMgr::Get().GetDialogString(it);
5236
5237 if (FontMgr::Get().GetConfigString(it).StartsWith(g_locale)) {
5238 m_itemFontElementListBox->Append(t);
5239 }
5240 }
5241
5242 if (nFonts) m_itemFontElementListBox->SetSelection(0);
5243
5244 itemFontStaticBoxSizer->Add(m_itemFontElementListBox, 0, wxALL, border_size);
5245
5246 wxButton* itemFontChooseButton =
5247 new wxButton(itemPanelFont, ID_BUTTONFONTCHOOSE, _("Choose Font..."),
5248 wxDefaultPosition, wxDefaultSize, 0);
5249 itemFontStaticBoxSizer->Add(itemFontChooseButton, 0, wxALL, border_size);
5250#if defined(__WXGTK__) || defined(__WXQT__)
5251 wxButton* itemFontColorButton =
5252 new wxButton(itemPanelFont, ID_BUTTONFONTCOLOR, _("Choose Font Color..."),
5253 wxDefaultPosition, wxDefaultSize, 0);
5254 itemFontStaticBoxSizer->Add(itemFontColorButton, 0, wxALL, border_size);
5255#endif
5256 m_textSample = new wxStaticText(itemPanelFont, wxID_ANY, _("Sample"),
5257 wxDefaultPosition, wxDefaultSize, 0);
5258 itemFontStaticBoxSizer->Add(m_textSample, 0, wxALL, border_size);
5259 wxCommandEvent e;
5260 OnFontChoice(e);
5261
5262#if 0
5263 wxStaticBox* itemStyleStaticBox =
5264 new wxStaticBox(itemPanelFont, wxID_ANY, _("Toolbar and Window Style"));
5265 wxStaticBoxSizer* itemStyleStaticBoxSizer =
5266 new wxStaticBoxSizer(itemStyleStaticBox, wxVERTICAL);
5267 langStyleBox->Add(itemStyleStaticBoxSizer, 1, wxEXPAND | wxALL, border_size);
5268
5269 m_itemStyleListBox = new wxChoice(itemPanelFont, ID_STYLESCOMBOBOX);
5270
5271 wxArrayPtrVoid styles = g_StyleManager->GetArrayOfStyles();
5272 for (unsigned int i = 0; i < styles.Count(); i++) {
5273 ocpnStyle::Style* style = (ocpnStyle::Style*)(styles[i]);
5274 m_itemStyleListBox->Append(style->name);
5275 }
5276 m_itemStyleListBox->SetStringSelection(
5277 g_StyleManager->GetCurrentStyle()->name);
5278 itemStyleStaticBoxSizer->Add(m_itemStyleListBox, 1, wxEXPAND | wxALL,
5279 border_size);
5280#endif
5281 wxStaticBox* miscOptionsBox =
5282 new wxStaticBox(itemPanelFont, wxID_ANY, _("Interface Options"));
5283 wxStaticBoxSizer* miscOptions =
5284 new wxStaticBoxSizer(miscOptionsBox, wxVERTICAL);
5285 m_itemBoxSizerFontPanel->Add(miscOptions, 0, wxALL | wxEXPAND, border_size);
5286
5287 pShowStatusBar =
5288 new wxCheckBox(itemPanelFont, ID_DEBUGCHECKBOX1, _("Show Status Bar"));
5289 pShowStatusBar->SetValue(FALSE);
5290 miscOptions->Add(pShowStatusBar, 0, wxALL, border_size);
5291
5292#ifndef __WXOSX__
5293 pShowMenuBar = new wxCheckBox(itemPanelFont, wxID_ANY, _("Show Menu Bar"));
5294 pShowMenuBar->SetValue(FALSE);
5295 miscOptions->Add(pShowMenuBar, 0, wxALL, border_size);
5296#endif
5297
5298#ifdef __OCPN__ANDROID__
5299 pShowMenuBar->Hide();
5300#endif
5301
5302 pShowChartBar = new wxCheckBox(itemPanelFont, wxID_ANY, _("Show Chart Bar"));
5303 pShowChartBar->SetValue(g_bShowChartBar);
5304 miscOptions->Add(pShowChartBar, 0, wxALL, border_size);
5305
5306 pShowCompassWin = new wxCheckBox(itemPanelFont, wxID_ANY,
5307 _("Show Compass/GPS Status Window"));
5308 pShowCompassWin->SetValue(FALSE);
5309 miscOptions->Add(pShowCompassWin, 0, wxALL, border_size);
5310
5311 wxBoxSizer* pToolbarAutoHide = new wxBoxSizer(wxHORIZONTAL);
5312 miscOptions->Add(pToolbarAutoHide, 0, wxALL | wxEXPAND, group_item_spacing);
5313
5314 pToolbarAutoHideCB =
5315 new wxCheckBox(itemPanelFont, wxID_ANY, _("Enable Toolbar auto-hide"));
5316 pToolbarAutoHide->Add(pToolbarAutoHideCB, 0, wxALL, group_item_spacing);
5317
5318 pToolbarHideSecs =
5319 new wxTextCtrl(itemPanelFont, ID_OPTEXTCTRL, _T(""), wxDefaultPosition,
5320 wxSize(50, -1), wxTE_RIGHT);
5321 pToolbarAutoHide->Add(pToolbarHideSecs, 0, wxALL, group_item_spacing);
5322
5323 pToolbarAutoHide->Add(new wxStaticText(itemPanelFont, wxID_ANY, _("seconds")),
5324 group_item_spacing);
5325
5326 wxBoxSizer* pShipsBellsSizer = new wxBoxSizer(wxHORIZONTAL);
5327 miscOptions->Add(pShipsBellsSizer, 0, wxALL, group_item_spacing);
5328 // Sound options
5329 pPlayShipsBells =
5330 new wxCheckBox(itemPanelFont, ID_BELLSCHECKBOX, _("Play Ships Bells"));
5331 pShipsBellsSizer->Add(pPlayShipsBells, 0, wxALL | wxEXPAND, border_size);
5332
5333#ifndef __OCPN__ANDROID__
5334 if (g_bUIexpert && (bool)dynamic_cast<SystemCmdSound*>(SoundFactory())) {
5335 wxBoxSizer* pSoundSizer = new wxBoxSizer(wxVERTICAL);
5336 pShipsBellsSizer->Add(pSoundSizer, 0, wxALL | wxEXPAND, group_item_spacing);
5337 pCmdSoundString =
5338 new wxTextCtrl(itemPanelFont, wxID_ANY, _T( "" ), wxDefaultPosition,
5339 wxSize(450, -1), wxTE_LEFT);
5340 pSoundSizer->Add(
5341 new wxStaticText(itemPanelFont, wxID_ANY, _("Audio Play command:")), 0,
5342 wxALIGN_CENTER_HORIZONTAL | wxALL);
5343 pSoundSizer->Add(pCmdSoundString, 1, wxEXPAND | wxALIGN_LEFT, border_size);
5344 }
5345#endif
5346
5347 auto sound = std::unique_ptr<OcpnSound>(SoundFactory());
5348 int deviceCount = sound->DeviceCount();
5349 wxLogMessage("options: got device count: %d", deviceCount);
5350 if (deviceCount >= 1) {
5351 wxArrayString labels;
5352 for (int i = 0; i < deviceCount; i += 1) {
5353 wxString label(sound->GetDeviceInfo(i));
5354 if (label == "") {
5355 std::ostringstream stm;
5356 stm << i;
5357 label = _("Unknown device :") + stm.str();
5358 }
5359 if (!sound->IsOutputDevice(i)) {
5360 std::ostringstream stm;
5361 stm << i;
5362 label = _("Input device :") + stm.str();
5363 }
5364 labels.Add(label);
5365 }
5366
5367 // if sound device index is uninitialized, set to "default", if found.
5368 // Otherwise, set to 0
5369 int iDefault = labels.Index("default");
5370
5371 if (g_iSoundDeviceIndex == -1) {
5372 if (iDefault >= 0)
5373 g_iSoundDeviceIndex = iDefault;
5374 else
5375 g_iSoundDeviceIndex = 0;
5376 }
5377
5378 pSoundDeviceIndex = new wxChoice();
5379 if (pSoundDeviceIndex) {
5380 pSoundDeviceIndex->Create(itemPanelFont, wxID_ANY, wxDefaultPosition,
5381 wxDefaultSize, labels);
5382 pSoundDeviceIndex->SetSelection(g_iSoundDeviceIndex);
5383 pSoundDeviceIndex->Show();
5384 wxFlexGridSizer* pSoundDeviceIndexGrid = new wxFlexGridSizer(2);
5385 miscOptions->Add(pSoundDeviceIndexGrid, 0, wxALL | wxEXPAND,
5386 group_item_spacing);
5387
5388 stSoundDeviceIndex =
5389 new wxStaticText(itemPanelFont, wxID_STATIC, _("Sound Device"));
5390 pSoundDeviceIndexGrid->Add(stSoundDeviceIndex, 0, wxALL, 5);
5391 pSoundDeviceIndexGrid->Add(pSoundDeviceIndex, 0, wxALL, border_size);
5392 }
5393 }
5394#ifdef __OCPN__ANDROID__
5395 stSoundDeviceIndex->Hide();
5396 pSoundDeviceIndex->Hide();
5397#endif
5398
5399 // Mobile/Touchscreen checkboxes
5400 pMobile = new wxCheckBox(itemPanelFont, ID_MOBILEBOX,
5401 _("Enable Touchscreen interface"));
5402 miscOptions->Add(pMobile, 0, wxALL, border_size);
5403
5404 pResponsive = new wxCheckBox(itemPanelFont, ID_REPONSIVEBOX,
5405 _("Enable Scaled Graphics interface"));
5406 miscOptions->Add(pResponsive, 0, wxALL, border_size);
5407
5408 // These two options are always needed ON for Android
5409#ifdef __OCPN__ANDROID__
5410 pMobile->Hide();
5411 pResponsive->Hide();
5412#endif
5413
5414 // "Responsive graphics" option deprecated in O58+
5415 pResponsive->Hide();
5416
5417 pZoomButtons =
5418 new wxCheckBox(itemPanelFont, ID_ZOOMBUTTONS, _("Show Zoom buttons"));
5419 miscOptions->Add(pZoomButtons, 0, wxALL, border_size);
5420#ifndef __OCPN__ANDROID__
5421 pZoomButtons->Hide();
5422#endif
5423
5424 pInlandEcdis = new wxCheckBox(itemPanelFont, ID_INLANDECDISBOX,
5425 _("Use Inland ECDIS"));
5426 miscOptions->Add(pInlandEcdis, 0, wxALL, border_size);
5427
5428 wxButton* itemEcdisHelp =
5429 new wxButton(itemPanelFont, ID_BUTTONECDISHELP, _("Inland ECDIS Manual"),
5430 wxDefaultPosition, wxDefaultSize, 0);
5431 miscOptions->Add(itemEcdisHelp, 0, wxALL, border_size);
5432
5433#ifdef __OCPN__ANDROID__
5434 pInlandEcdis->Hide();
5435 itemEcdisHelp->Hide();
5436#endif
5437
5438 miscOptions->AddSpacer(10);
5439
5440 wxFlexGridSizer* sliderSizer;
5441 sliderSizer = new wxFlexGridSizer(0, 2, 0, 0);
5442 sliderSizer->AddGrowableCol(1);
5443 sliderSizer->SetFlexibleDirection(wxBOTH);
5444 sliderSizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
5445
5446 m_pSlider_GUI_Factor =
5447 new wxSlider(itemPanelFont, wxID_ANY, 0, -5, 5, wxDefaultPosition,
5448 m_sliderSize, SLIDER_STYLE);
5449 m_pSlider_GUI_Factor->Hide();
5450 sliderSizer->Add(new wxStaticText(itemPanelFont, wxID_ANY,
5451 _("User Interface scale factor")),
5452 inputFlags);
5453 sliderSizer->Add(m_pSlider_GUI_Factor, 0, wxALL, border_size);
5454 m_pSlider_GUI_Factor->Show();
5455
5456#ifdef __OCPN__ANDROID__
5457 prepareSlider(m_pSlider_GUI_Factor);
5458#endif
5459
5460 m_pSlider_Chart_Factor =
5461 new wxSlider(itemPanelFont, wxID_ANY, 0, -5, 5, wxDefaultPosition,
5462 m_sliderSize, SLIDER_STYLE);
5463 m_pSlider_Chart_Factor->Hide();
5464 sliderSizer->Add(
5465 new wxStaticText(itemPanelFont, wxID_ANY, _("Chart Object scale factor")),
5466 inputFlags);
5467 sliderSizer->Add(m_pSlider_Chart_Factor, 0, wxALL, border_size);
5468 m_pSlider_Chart_Factor->Show();
5469
5470#ifdef __OCPN__ANDROID__
5471 prepareSlider(m_pSlider_Chart_Factor);
5472#endif
5473
5474 m_pSlider_Ship_Factor =
5475 new wxSlider(itemPanelFont, wxID_ANY, 0, -5, 5, wxDefaultPosition,
5476 m_sliderSize, SLIDER_STYLE);
5477 m_pSlider_Ship_Factor->Hide();
5478 sliderSizer->Add(
5479 new wxStaticText(itemPanelFont, wxID_ANY, _("Ship scale factor")),
5480 inputFlags);
5481 sliderSizer->Add(m_pSlider_Ship_Factor, 0, wxALL, border_size);
5482 m_pSlider_Ship_Factor->Show();
5483
5484#ifdef __OCPN__ANDROID__
5485 m_pSlider_Ship_Factor->GetHandle()->setStyleSheet(getQtStyleSheet());
5486#endif
5487
5488 m_pSlider_Text_Factor =
5489 new wxSlider(itemPanelFont, wxID_ANY, 0, -5, 5, wxDefaultPosition,
5490 m_sliderSize, SLIDER_STYLE);
5491 m_pSlider_Text_Factor->Hide();
5492 sliderSizer->Add(
5493 new wxStaticText(itemPanelFont, wxID_ANY, _("ENC Sounding factor")),
5494 inputFlags);
5495 sliderSizer->Add(m_pSlider_Text_Factor, 0, wxALL, border_size);
5496 m_pSlider_Text_Factor->Show();
5497
5498#ifdef __OCPN__ANDROID__
5499 m_pSlider_Text_Factor->GetHandle()->setStyleSheet(getQtStyleSheet());
5500#endif
5501
5502 m_pSlider_ENCText_Factor =
5503 new wxSlider(itemPanelFont, wxID_ANY, 0, -5, 5, wxDefaultPosition,
5504 m_sliderSize, SLIDER_STYLE);
5505 m_pSlider_ENCText_Factor->Hide();
5506 sliderSizer->Add(
5507 new wxStaticText(itemPanelFont, wxID_ANY, _("ENC Text Scale")),
5508 inputFlags);
5509 sliderSizer->Add(m_pSlider_ENCText_Factor, 0, wxALL, border_size);
5510 m_pSlider_ENCText_Factor->Show();
5511
5512#ifdef __OCPN__ANDROID__
5513 m_pSlider_ENCText_Factor->GetHandle()->setStyleSheet(getQtStyleSheet());
5514#endif
5515
5516 sliderSizer->Add(
5517 new wxStaticText(itemPanelFont, wxID_ANY, "Mouse wheel zoom sensitivity"),
5518 inputFlags);
5519 m_pMouse_Zoom_Slider = new MouseZoomSlider(itemPanelFont, m_sliderSize);
5520 sliderSizer->Add(m_pMouse_Zoom_Slider, 0, wxALL, border_size);
5521
5522 miscOptions->Add(sliderSizer, 0, wxEXPAND, 5);
5523 miscOptions->AddSpacer(20);
5524}
5525
5526void options::OnAlertEnableButtonClick(wxCommandEvent& event) {
5527 if (event.IsChecked()) {
5528 m_pCheck_AlertAudio->Enable();
5529 m_soundPanelAIS->GetCheckBox()->Enable();
5530 m_soundPanelSART->GetCheckBox()->Enable();
5531 m_soundPanelDSC->GetCheckBox()->Enable();
5532 } else {
5533 m_pCheck_AlertAudio->Disable();
5534 m_soundPanelAIS->GetCheckBox()->Disable();
5535 m_soundPanelSART->GetCheckBox()->Disable();
5536 m_soundPanelDSC->GetCheckBox()->Disable();
5537 }
5538}
5539
5540void options::OnAlertAudioEnableButtonClick(wxCommandEvent& event) {
5541 if (event.IsChecked()) {
5542 m_soundPanelAIS->GetCheckBox()->Enable();
5543 m_soundPanelSART->GetCheckBox()->Enable();
5544 m_soundPanelDSC->GetCheckBox()->Enable();
5545 } else {
5546 m_soundPanelAIS->GetCheckBox()->Disable();
5547 m_soundPanelSART->GetCheckBox()->Disable();
5548 m_soundPanelDSC->GetCheckBox()->Disable();
5549 }
5550}
5551
5552void options::CreateListbookIcons() {
5553 ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();
5554
5555 if (!g_bresponsive) {
5556 int sx = 40;
5557 int sy = 40;
5558 m_topImgList = new wxImageList(sx, sy, TRUE, 0);
5559
5560#if wxCHECK_VERSION(2, 8, 12)
5561 m_topImgList->Add(style->GetIcon(_T("Display"), sx, sy));
5562 m_topImgList->Add(style->GetIcon(_T("Charts"), sx, sy));
5563 m_topImgList->Add(style->GetIcon(_T("Connections"), sx, sy));
5564 m_topImgList->Add(style->GetIcon(_T("Ship"), sx, sy));
5565 m_topImgList->Add(style->GetIcon(_T("UI"), sx, sy));
5566 m_topImgList->Add(style->GetIcon(_T("Plugins"), sx, sy));
5567#else
5568 wxBitmap bmp;
5569 wxImage img;
5570 bmp = style->GetIcon(_T("Display"));
5571 img = bmp.ConvertToImage();
5572 img.ConvertAlphaToMask(128);
5573 bmp = wxBitmap(img);
5574 m_topImgList->Add(bmp);
5575 bmp = style->GetIcon(_T("Charts"));
5576 img = bmp.ConvertToImage();
5577 img.ConvertAlphaToMask(128);
5578 bmp = wxBitmap(img);
5579 m_topImgList->Add(bmp);
5580 bmp = style->GetIcon(_T("Connections"));
5581 img = bmp.ConvertToImage();
5582 img.ConvertAlphaToMask(128);
5583 bmp = wxBitmap(img);
5584 m_topImgList->Add(bmp);
5585 bmp = style->GetIcon(_T("Ship"));
5586 img = bmp.ConvertToImage();
5587 img.ConvertAlphaToMask(128);
5588 bmp = wxBitmap(img);
5589 m_topImgList->Add(bmp);
5590 bmp = style->GetIcon(_T("UI"));
5591 img = bmp.ConvertToImage();
5592 img.ConvertAlphaToMask(128);
5593 bmp = wxBitmap(img);
5594 m_topImgList->Add(bmp);
5595 bmp = style->GetIcon(_T("Plugins"));
5596 img = bmp.ConvertToImage();
5597 img.ConvertAlphaToMask(128);
5598 bmp = wxBitmap(img);
5599 m_topImgList->Add(bmp);
5600#endif
5601 } else {
5602 wxBitmap bmps;
5603 bmps = style->GetIcon(_T("Display"));
5604 int base_size = bmps.GetWidth();
5605 double tool_size = base_size;
5606
5607 double premult = 1.0;
5608
5609 // unless overridden by user, we declare the "best" size
5610 // to be roughly 6 mm square.
5611 double target_size = 6.0; // mm
5612
5613 double basic_tool_size_mm = tool_size / g_Platform->GetDisplayDPmm();
5614 premult = target_size / basic_tool_size_mm;
5615
5616 // Adjust the scale factor using the global GUI scale parameter
5617 double postmult = exp(g_GUIScaleFactor * (0.693 / 5.0)); // exp(2)
5618 postmult = wxMin(postmult, 3.0);
5619 postmult = wxMax(postmult, 1.0);
5620
5621 int sizeTab = base_size * postmult * premult;
5622
5623 m_topImgList = new wxImageList(sizeTab, sizeTab, TRUE, 1);
5624
5625 wxBitmap bmp;
5626 wxImage img, simg;
5627 bmp = style->GetIcon(_T("Display"));
5628 img = bmp.ConvertToImage();
5629 simg = img.Scale(sizeTab, sizeTab);
5630 bmp = wxBitmap(simg);
5631 m_topImgList->Add(bmp);
5632 bmp = style->GetIcon(_T("Charts"));
5633 img = bmp.ConvertToImage();
5634 simg = img.Scale(sizeTab, sizeTab);
5635 bmp = wxBitmap(simg);
5636 m_topImgList->Add(bmp);
5637 bmp = style->GetIcon(_T("Connections"));
5638 img = bmp.ConvertToImage();
5639 simg = img.Scale(sizeTab, sizeTab);
5640 bmp = wxBitmap(simg);
5641 m_topImgList->Add(bmp);
5642 bmp = style->GetIcon(_T("Ship"));
5643 img = bmp.ConvertToImage();
5644 simg = img.Scale(sizeTab, sizeTab);
5645 bmp = wxBitmap(simg);
5646 m_topImgList->Add(bmp);
5647 bmp = style->GetIcon(_T("UI"));
5648 img = bmp.ConvertToImage();
5649 simg = img.Scale(sizeTab, sizeTab);
5650 bmp = wxBitmap(simg);
5651 m_topImgList->Add(bmp);
5652 bmp = style->GetIcon(_T("Plugins"));
5653 img = bmp.ConvertToImage();
5654 simg = img.Scale(sizeTab, sizeTab);
5655 bmp = wxBitmap(simg);
5656 m_topImgList->Add(bmp);
5657 }
5658}
5659
5660void options::CreateControls(void) {
5661 int border_size = 4;
5662 // use for items within one group, with Add(...wxALL)
5663 int group_item_spacing = 2;
5664
5665 int font_size_y, font_descent, font_lead;
5666 GetTextExtent(_T("0"), NULL, &font_size_y, &font_descent, &font_lead);
5667 m_fontHeight = font_size_y + font_descent + font_lead;
5668
5669#ifdef __OCPN__ANDROID__
5670 m_sliderSize =
5671 wxSize(wxMin(m_fontHeight * 8, g_Platform->getDisplaySize().x / 2),
5672 m_fontHeight * 8 / 10);
5673#else
5674 m_sliderSize =
5675 wxSize(wxMin(m_fontHeight * 8, g_Platform->getDisplaySize().x / 2),
5676 m_fontHeight * 2);
5677#endif
5678
5679 m_small_button_size =
5680 wxSize(-1, (int)(1.2 * (font_size_y + font_descent /*+ font_lead*/)));
5681
5682 m_nCharWidthMax = GetSize().x / GetCharWidth();
5683
5684 // Some members (pointers to controls) need to initialized
5685 pEnableZoomToCursor = NULL;
5686 pSmoothPanZoom = NULL;
5687
5688 // Check the display size.
5689 // If "small", adjust some factors to squish out some more white space
5690 int width, height;
5691 ::wxDisplaySize(&width, &height);
5692
5693 if (!g_bresponsive && height <= 800) {
5694 border_size = 2;
5695 group_item_spacing = 1;
5696 }
5697
5698 labelFlags =
5699 wxSizerFlags(0).Align(wxALIGN_RIGHT).Border(wxALL, group_item_spacing);
5700 inputFlags = wxSizerFlags(0)
5701 .Align(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL)
5702 .Border(wxALL, group_item_spacing);
5703 verticleInputFlags =
5704 wxSizerFlags(0).Align(wxALIGN_LEFT).Border(wxALL, group_item_spacing);
5705 groupLabelFlags = wxSizerFlags(0)
5706 .Align(wxALIGN_RIGHT | wxALIGN_TOP)
5707 .Border(wxALL, group_item_spacing);
5708 groupLabelFlagsHoriz =
5709 wxSizerFlags(0).Align(wxALIGN_TOP).Border(wxALL, group_item_spacing);
5710 groupInputFlags = wxSizerFlags(0)
5711 .Align(wxALIGN_LEFT | wxALIGN_TOP)
5712 .Border(wxBOTTOM, group_item_spacing * 2)
5713 .Expand();
5714
5715#ifdef __WXGTK__
5716 groupLabelFlags.Border(wxTOP, group_item_spacing + 3);
5717#endif
5718
5719 options* itemDialog1 = this;
5720
5721 wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
5722 itemDialog1->SetSizer(itemBoxSizer2);
5723
5724#ifdef __OCPN__ANDROID__
5725 // Set Dialog Font by custom crafted Qt Stylesheet.
5726 wxFont* qFont = dialogFont;
5727
5728 wxString wqs = getFontQtStylesheet(qFont);
5729 wxCharBuffer sbuf = wqs.ToUTF8();
5730 QString qsb = QString(sbuf.data());
5731
5732 QString qsbq = getQtStyleSheet(); // basic scrollbars, etc
5733
5734 itemDialog1->GetHandle()->setStyleSheet(qsb +
5735 qsbq); // Concatenated style sheets
5736
5737#endif
5738
5739 int flags = 0;
5740
5741#ifdef __OCPN__OPTIONS_USE_LISTBOOK__
5742 flags = wxLB_TOP;
5743 m_pListbook = new wxListbook(itemDialog1, ID_NOTEBOOK, wxDefaultPosition,
5744 wxSize(-1, -1), flags);
5745 m_pListbook->Connect(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED,
5746 wxListbookEventHandler(options::OnPageChange), NULL,
5747 this);
5748#else
5749 flags = wxNB_TOP;
5750 m_pListbook = new wxNotebook(itemDialog1, ID_NOTEBOOK, wxDefaultPosition,
5751 wxSize(-1, -1), flags);
5752 m_pListbook->Connect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
5753 wxNotebookEventHandler(options::OnTopNBPageChange), NULL,
5754 this);
5755#endif
5756
5757#ifdef __OCPN__ANDROID__
5758 // In wxQT, we can dynamically style the little scroll buttons on a small
5759 // display, to make them bigger
5760 m_pListbook->GetHandle()->setStyleSheet(getListBookStyleSheet());
5761
5762#endif
5763
5764 CreateListbookIcons();
5765
5766 m_pListbook->SetImageList(m_topImgList);
5767 itemBoxSizer2->Add(m_pListbook, 1, wxALL | wxEXPAND, border_size);
5768
5769 wxBoxSizer* buttons = new wxBoxSizer(wxHORIZONTAL);
5770 itemBoxSizer2->Add(buttons, 0, wxALIGN_RIGHT | wxALL, border_size);
5771
5772 m_OKButton = new wxButton(itemDialog1, xID_OK, _("OK"));
5773 m_OKButton->SetDefault();
5774 buttons->Add(m_OKButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, border_size);
5775
5776 m_CancelButton = new wxButton(itemDialog1, wxID_CANCEL, _("Cancel"));
5777 buttons->Add(m_CancelButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, border_size);
5778
5779 m_ApplyButton = new wxButton(itemDialog1, ID_APPLY, _("Apply"));
5780 buttons->Add(m_ApplyButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, border_size);
5781
5782 m_pageDisplay = CreatePanel(_("Display"));
5783 CreatePanel_Display(m_pageDisplay, border_size, group_item_spacing);
5784 CreatePanel_Units(m_pageDisplay, border_size, group_item_spacing);
5785 CreatePanel_Advanced(m_pageDisplay, border_size, group_item_spacing);
5786 CreatePanel_Configs(m_pageDisplay, border_size, group_item_spacing);
5787
5788 m_pageCharts = CreatePanel(_("Charts"));
5789 CreatePanel_ChartsLoad(m_pageCharts, border_size, group_item_spacing);
5790 CreatePanel_VectorCharts(m_pageCharts, border_size, group_item_spacing);
5791 // ChartGroups must be created after ChartsLoad and must be at least third
5792 CreatePanel_ChartGroups(m_pageCharts, border_size, group_item_spacing);
5793 RecalculateSize();
5794 CreatePanel_TidesCurrents(m_pageCharts, border_size, group_item_spacing);
5795
5796 wxNotebook* nb =
5797 dynamic_cast<wxNotebook*>(m_pListbook->GetPage(m_pageCharts));
5798 if (nb) {
5799#ifdef __OCPN__OPTIONS_USE_LISTBOOK__
5800 nb->Connect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
5801 wxListbookEventHandler(options::OnChartsPageChange), NULL,
5802 this);
5803#else
5804 nb->Connect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
5805 wxNotebookEventHandler(options::OnChartsPageChange), NULL,
5806 this);
5807
5808#endif
5809 }
5810
5811 wxString ConnTab = _("Connections");
5812 if (g_Platform->GetDisplayDIPMult(gFrame) < 1)
5813 ConnTab = _("Connect");
5814
5815 m_pageConnections = CreatePanel(ConnTab);
5816#ifndef __OCPN__ANDROID__
5817 CreatePanel_NMEA(m_pageConnections, border_size, group_item_spacing);
5818#else
5819 CreatePanel_NMEA(m_pageConnections, border_size, group_item_spacing);
5820// CreatePanel_NMEA_Compact(m_pageConnections, border_size, group_item_spacing);
5821#endif
5822
5823 // SetDefaultConnectionParams();
5824
5825 m_pageShips = CreatePanel(_("Ships"));
5826 CreatePanel_Ownship(m_pageShips, border_size, group_item_spacing);
5827 CreatePanel_AIS(m_pageShips, border_size, group_item_spacing);
5828#ifndef __OCPN__ANDROID__
5829 CreatePanel_MMSI(m_pageShips, border_size, group_item_spacing);
5830#endif
5831
5832 CreatePanel_Routes(m_pageShips, border_size, group_item_spacing);
5833
5834 wxString UITab = _("User Interface");
5835 if (g_Platform->GetDisplayDIPMult(gFrame) < 1)
5836 UITab = _("User");
5837
5838 m_pageUI = CreatePanel(UITab);
5839 CreatePanel_UI(m_pageUI, border_size, group_item_spacing);
5840 CreatePanel_Sounds(m_pageUI, border_size, group_item_spacing);
5841
5842 m_pagePlugins = CreatePanel(_("Plugins"));
5843 itemPanelPlugins = AddPage(m_pagePlugins, _("Plugins"));
5844
5845 itemBoxSizerPanelPlugins = new wxBoxSizer(wxVERTICAL);
5846 itemPanelPlugins->SetSizer(itemBoxSizerPanelPlugins);
5847
5848 // PlugIns can add panels, too
5849 if (g_pi_manager) g_pi_manager->NotifySetupOptions();
5850
5851 SetColorScheme(static_cast<ColorScheme>(0));
5852
5853 // Set the maximum size of the entire settings dialog
5854 // leaving a slightly larger border for larger displays.
5855 int marginx = 10;
5856 int marginy = 40;
5857 if (width > 800) {
5858 marginx = 100;
5859 marginy = 100;
5860 }
5861
5862 SetSizeHints(-1, -1, width - marginx, height - marginy);
5863
5864 // The s57 chart panel is the one which controls the minimum width required
5865 // to avoid horizontal scroll bars
5866 vectorPanel->SetSizeHints(ps57Ctl);
5867}
5868
5869void options::SetInitialPage(int page_sel, int sub_page) {
5870 if (page_sel < (int)m_pListbook->GetPageCount())
5871 m_pListbook->SetSelection(page_sel);
5872 else
5873 m_pListbook->SetSelection(0);
5874
5875 if (sub_page >= 0) {
5876 for (size_t i = 0; i < m_pListbook->GetPageCount(); i++) {
5877 wxNotebookPage* pg = m_pListbook->GetPage(i);
5878 wxNotebook* nb = dynamic_cast<wxNotebook*>(pg);
5879 if (nb) {
5880 if (i == (size_t)page_sel) {
5881 if (sub_page < (int)nb->GetPageCount())
5882 nb->SetSelection(sub_page);
5883 else
5884 nb->SetSelection(0);
5885 } else
5886 nb->ChangeSelection(0);
5887 }
5888 }
5889 }
5890}
5891
5892void options::SetColorScheme(ColorScheme cs) {
5893 DimeControl(this);
5894
5895#ifdef __OCPN__OPTIONS_USE_LISTBOOK__
5896 wxListView* lv = m_pListbook->GetListView();
5897 lv->SetBackgroundColour(GetBackgroundColour());
5898
5899 if (m_cs != cs) {
5900 delete m_topImgList;
5901 CreateListbookIcons();
5902 m_pListbook->SetImageList(m_topImgList);
5903
5904 m_cs = cs;
5905 }
5906
5907#endif
5908}
5909
5910void options::OnAISRolloverClick(wxCommandEvent& event) {
5911 m_pCheck_Rollover_Class->Enable(event.IsChecked());
5912 m_pCheck_Rollover_COG->Enable(event.IsChecked());
5913 m_pCheck_Rollover_CPA->Enable(event.IsChecked());
5914 pStatic_CallSign->Enable(event.IsChecked());
5915}
5916
5917void options::OnCanvasConfigSelectClick(int ID, bool selected) {
5918 switch (ID) {
5919 case ID_SCREENCONFIG1:
5920 if (m_sconfigSelect_twovertical)
5921 m_sconfigSelect_twovertical->SetSelected(false);
5922 m_screenConfig = 0;
5923 break;
5924
5925 case ID_SCREENCONFIG2:
5926 if (m_sconfigSelect_single) m_sconfigSelect_single->SetSelected(false);
5927 m_screenConfig = 1;
5928 break;
5929 }
5930}
5931
5932void options::SetInitialSettings(void) {
5933 wxString s;
5934
5935 m_returnChanges = 0; // reset the flags
5936 m_bfontChanged = false;
5937
5938 b_oldhaveWMM = b_haveWMM;
5939 auto loader = PluginLoader::getInstance();
5940 b_haveWMM = loader && loader->IsPlugInAvailable(_T("WMM"));
5941
5942 // Canvas configuration
5943 switch (g_canvasConfig) {
5944 case 0:
5945 default:
5946 if (m_sconfigSelect_single) m_sconfigSelect_single->SetSelected(true);
5947 if (m_sconfigSelect_twovertical)
5948 m_sconfigSelect_twovertical->SetSelected(false);
5949 break;
5950 case 1:
5951 if (m_sconfigSelect_single) m_sconfigSelect_single->SetSelected(false);
5952 if (m_sconfigSelect_twovertical)
5953 m_sconfigSelect_twovertical->SetSelected(true);
5954 break;
5955 }
5956 m_screenConfig = g_canvasConfig;
5957
5958 // Initial Charts Load
5959
5960 ActiveChartArray.Clear();
5961 for (size_t i = 0; i < m_CurrentDirList.GetCount(); i++) {
5962 ActiveChartArray.Add(m_CurrentDirList[i]);
5963 }
5964
5965 // ChartGroups
5966 if (m_pWorkDirList) {
5967 UpdateWorkArrayFromDisplayPanel();
5968 groupsPanel->SetDBDirs(*m_pWorkDirList);
5969
5970 // Make a deep copy of the current global Group Array
5971 groupsPanel->EmptyChartGroupArray(m_pGroupArray);
5972 delete m_pGroupArray;
5973 m_pGroupArray = groupsPanel->CloneChartGroupArray(g_pGroupArray);
5974 groupsPanel->SetGroupArray(m_pGroupArray);
5975 groupsPanel->SetInitialSettings();
5976 }
5977
5978 if (m_pConfig) {
5979 pShowStatusBar->SetValue(g_bShowStatusBar);
5980#ifndef __WXOSX__
5981 pShowMenuBar->SetValue(g_bShowMenuBar);
5982#endif
5983 pShowCompassWin->SetValue(g_bShowCompassWin);
5984 }
5985
5986 s.Printf(_T("%d"), g_COGAvgSec);
5987 pCOGUPUpdateSecs->SetValue(s);
5988
5989 if (pCDOOutlines) pCDOOutlines->SetValue(g_bShowOutlines);
5990 if (pCDOQuilting) pCDOQuilting->SetValue(g_bQuiltEnable);
5991 // if(pFullScreenQuilt) pFullScreenQuilt->SetValue(!g_bFullScreenQuilt);
5992 if (pSDepthUnits) pSDepthUnits->SetValue(g_bShowDepthUnits);
5993 if (pSkewComp) pSkewComp->SetValue(g_bskew_comp);
5994 pMobile->SetValue(g_btouch);
5995 pResponsive->SetValue(g_bresponsive);
5996 pRollover->SetValue(g_bRollover);
5997 m_pCheck_Rollover_Class->Enable(g_bRollover);
5998 m_pCheck_Rollover_COG->Enable(g_bRollover);
5999 m_pCheck_Rollover_CPA->Enable(g_bRollover);
6000 pStatic_CallSign->Enable(g_bRollover);
6001
6002 pZoomButtons->SetValue(g_bShowMuiZoomButtons);
6003
6004 // pOverzoomEmphasis->SetValue(!g_fog_overzoom);
6005 // pOZScaleVector->SetValue(!g_oz_vector_scale);
6006 pInlandEcdis->SetValue(g_bInlandEcdis);
6007 pOpenGL->SetValue(g_bopengl);
6008 if (pSmoothPanZoom) pSmoothPanZoom->SetValue(g_bsmoothpanzoom);
6009 pCBTrueShow->SetValue(g_bShowTrue);
6010 pCBMagShow->SetValue(g_bShowMag);
6011
6012 int oldLength = itemStaticTextUserVar->GetLabel().Length();
6013
6014 // disable input for variation if WMM is available
6015 if (b_haveWMM) {
6016 itemStaticTextUserVar->SetLabel(
6017 _("WMM Plugin calculated magnetic variation"));
6018 wxString s;
6019 s.Printf(_T("%4.1f"), gVar);
6020 pMagVar->SetValue(s);
6021 } else {
6022 itemStaticTextUserVar->SetLabel(_("User set magnetic variation"));
6023 wxString s;
6024 s.Printf(_T("%4.1f"), g_UserVar);
6025 pMagVar->SetValue(s);
6026 }
6027
6028 int newLength = itemStaticTextUserVar->GetLabel().Length();
6029
6030 // size hack to adjust change in static text size
6031 if ((newLength != oldLength) || (b_oldhaveWMM != b_haveWMM)) {
6032 wxSize sz = GetSize();
6033 SetSize(sz.x + 1, sz.y);
6034 SetSize(sz);
6035 }
6036
6037 itemStaticTextUserVar2->Enable(!b_haveWMM);
6038 pMagVar->Enable(!b_haveWMM);
6039
6040 if (pSDisplayGrid) pSDisplayGrid->SetValue(g_bDisplayGrid);
6041
6042 // LIVE ETA OPTION
6043
6044 // Checkbox
6045 if (pSLiveETA) pSLiveETA->SetValue(g_bShowLiveETA);
6046
6047 // Defaut boat speed text input field
6048 // Speed always in knots, and converted to user speed unit
6049 wxString stringDefaultBoatSpeed;
6050 if (!g_defaultBoatSpeed || !g_defaultBoatSpeedUserUnit) {
6051 g_defaultBoatSpeed = 6.0;
6052 g_defaultBoatSpeedUserUnit = toUsrSpeed(g_defaultBoatSpeed, -1);
6053 }
6054 stringDefaultBoatSpeed.Printf(_T("%d"), (int)g_defaultBoatSpeedUserUnit);
6055 if (pSDefaultBoatSpeed) pSDefaultBoatSpeed->SetValue(stringDefaultBoatSpeed);
6056
6057 // END LIVE ETA OPTION
6058
6059 if (pCBCourseUp) pCBCourseUp->SetValue(g_bCourseUp);
6060 if (pCBNorthUp) pCBNorthUp->SetValue(!g_bCourseUp);
6061 if (pCBLookAhead) pCBLookAhead->SetValue(g_bLookAhead);
6062
6063 if (fabs(wxRound(g_ownship_predictor_minutes) - g_ownship_predictor_minutes) >
6064 1e-4)
6065 s.Printf(_T("%6.2f"), g_ownship_predictor_minutes);
6066 else
6067 s.Printf(_T("%4.0f"), g_ownship_predictor_minutes);
6068 m_pText_OSCOG_Predictor->SetValue(s);
6069
6070 if (fabs(wxRound(g_ownship_HDTpredictor_miles) -
6071 g_ownship_HDTpredictor_miles) > 1e-4)
6072 s.Printf(_T("%6.2f"), g_ownship_HDTpredictor_miles);
6073 else
6074 s.Printf(_T("%4.0f"), g_ownship_HDTpredictor_miles);
6075 m_pText_OSHDT_Predictor->SetValue(s);
6076
6077 m_pShipIconType->SetSelection(g_OwnShipIconType);
6078 wxCommandEvent eDummy;
6079 OnShipTypeSelect(eDummy);
6080 m_pOSLength->SetValue(
6081 wxString::Format(_T("%.1f"), g_n_ownship_length_meters));
6082 m_pOSWidth->SetValue(wxString::Format(_T("%.1f"), g_n_ownship_beam_meters));
6083 m_pOSGPSOffsetX->SetValue(
6084 wxString::Format(_T("%.1f"), g_n_gps_antenna_offset_x));
6085 m_pOSGPSOffsetY->SetValue(
6086 wxString::Format(_T("%.1f"), g_n_gps_antenna_offset_y));
6087 m_pOSMinSize->SetValue(wxString::Format(_T("%d"), g_n_ownship_min_mm));
6088 m_pText_ACRadius->SetValue(
6089 wxString::Format(_T("%.3f"), g_n_arrival_circle_radius));
6090
6091 wxString buf;
6092 if (g_iNavAidRadarRingsNumberVisible > 10)
6093 g_iNavAidRadarRingsNumberVisible = 10;
6094 pNavAidRadarRingsNumberVisible->SetSelection(
6095 g_iNavAidRadarRingsNumberVisible);
6096 buf.Printf(_T("%.3f"), g_fNavAidRadarRingsStep);
6097 pNavAidRadarRingsStep->SetValue(buf);
6098 m_itemRadarRingsUnits->SetSelection(g_pNavAidRadarRingsStepUnits);
6099 m_colourOwnshipRangeRingColour->SetColour(g_colourOwnshipRangeRingsColour);
6100
6101 pScaMinChckB->SetValue(g_bUseWptScaMin);
6102 m_pText_ScaMin->SetValue(wxString::Format(_T("%i"), g_iWpt_ScaMin));
6103 pScaMinOverruleChckB->SetValue(g_bOverruleScaMin);
6104
6105 OnRadarringSelect(eDummy);
6106
6107 if (g_iWaypointRangeRingsNumber > 10) g_iWaypointRangeRingsNumber = 10;
6108 pWaypointRangeRingsNumber->SetSelection(g_iWaypointRangeRingsNumber);
6109 buf.Printf(_T("%.3f"), g_fWaypointRangeRingsStep);
6110 pWaypointRangeRingsStep->SetValue(buf);
6111 m_itemWaypointRangeRingsUnits->SetSelection(g_iWaypointRangeRingsStepUnits);
6112 m_colourWaypointRangeRingsColour->SetColour(g_colourWaypointRangeRingsColour);
6113 OnWaypointRangeRingSelect(eDummy);
6114 pShowshipToActive->SetValue(g_bShowShipToActive);
6115 m_shipToActiveStyle->SetSelection(g_shipToActiveStyle);
6116 m_shipToActiveColor->SetSelection(g_shipToActiveColor);
6117
6118 pWayPointPreventDragging->SetValue(g_bWayPointPreventDragging);
6119 pConfirmObjectDeletion->SetValue(g_bConfirmObjectDelete);
6120
6121 pSogCogFromLLCheckBox->SetValue(g_own_ship_sog_cog_calc);
6122 pSogCogFromLLDampInterval->SetValue(g_own_ship_sog_cog_calc_damp_sec);
6123
6124 if (pEnableZoomToCursor) pEnableZoomToCursor->SetValue(g_bEnableZoomToCursor);
6125
6126 if (pPreserveScale) pPreserveScale->SetValue(g_bPreserveScaleOnX);
6127 pPlayShipsBells->SetValue(g_bPlayShipsBells);
6128
6129 if (g_bUIexpert && pCmdSoundString)
6130 pCmdSoundString->SetValue(g_CmdSoundString);
6131
6132 if (pSoundDeviceIndex) pSoundDeviceIndex->SetSelection(g_iSoundDeviceIndex);
6133 // pFullScreenToolbar->SetValue( g_bFullscreenToolbar );
6134 // pTransparentToolbar->SetValue(g_bTransparentToolbar);
6135 pSDMMFormat->Select(g_iSDMMFormat);
6136 pDistanceFormat->Select(g_iDistanceFormat);
6137 pSpeedFormat->Select(g_iSpeedFormat);
6138 pTempFormat->Select(g_iTempFormat);
6139
6140 pAdvanceRouteWaypointOnArrivalOnly->SetValue(
6141 g_bAdvanceRouteWaypointOnArrivalOnly);
6142
6143 pTrackDaily->SetValue(g_bTrackDaily);
6144 pTrackRotateLMT->SetValue(g_track_rotate_time_type == TIME_TYPE_LMT);
6145 pTrackRotateUTC->SetValue(g_track_rotate_time_type == TIME_TYPE_UTC);
6146 pTrackRotateComputerTime->SetValue(g_track_rotate_time_type ==
6147 TIME_TYPE_COMPUTER);
6148 pTrackHighlite->SetValue(g_bHighliteTracks);
6149 m_colourTrackLineColour->SetColour(g_colourTrackLineColour);
6150 pTrackPrecision->SetSelection(g_nTrackPrecision);
6151
6152 m_soundPanelAnchor->GetCheckBox()->SetValue(g_bAnchor_Alert_Audio);
6153
6154 // AIS Parameters
6155 // CPA Box
6156 m_pCheck_CPA_Max->SetValue(g_bCPAMax);
6157
6158 s.Printf(_T("%4.1f"), g_CPAMax_NM);
6159 m_pText_CPA_Max->SetValue(s);
6160
6161 m_pCheck_CPA_Warn->SetValue(g_bCPAWarn);
6162
6163 s.Printf(_T("%4.1f"), g_CPAWarn_NM);
6164 m_pText_CPA_Warn->SetValue(s);
6165
6166 if (m_pCheck_CPA_Warn->GetValue()) {
6167 m_pCheck_CPA_WarnT->Enable();
6168 m_pCheck_CPA_WarnT->SetValue(g_bTCPA_Max);
6169 } else
6170 m_pCheck_CPA_WarnT->Disable();
6171
6172 s.Printf(_T("%4.0f"), g_TCPA_Max);
6173 m_pText_CPA_WarnT->SetValue(s);
6174
6175 // Lost Targets
6176 m_pCheck_Mark_Lost->SetValue(g_bMarkLost);
6177
6178 s.Printf(_T("%4.0f"), g_MarkLost_Mins);
6179 m_pText_Mark_Lost->SetValue(s);
6180
6181 m_pCheck_Remove_Lost->SetValue(g_bRemoveLost);
6182
6183 s.Printf(_T("%4.0f"), g_RemoveLost_Mins);
6184 m_pText_Remove_Lost->SetValue(s);
6185
6186 // Display
6187 m_pCheck_Show_COG->SetValue(g_bShowCOG);
6188
6189 s.Printf(_T("%4.0f"), g_ShowCOG_Mins);
6190 m_pText_COG_Predictor->SetValue(s);
6191
6192 m_pCheck_Sync_OCOG_ACOG->SetValue(g_bSyncCogPredictors);
6193 if(g_bSyncCogPredictors) m_pText_COG_Predictor->Disable();
6194
6195 m_pCheck_Show_Tracks->SetValue(g_bAISShowTracks);
6196
6197 s.Printf(_T("%4.0f"), g_AISShowTracks_Mins);
6198 m_pText_Track_Length->SetValue(s);
6199
6200 m_pCheck_Hide_Moored->SetValue(g_bHideMoored);
6201
6202 s.Printf(_T("%4.1f"), g_ShowMoored_Kts);
6203 m_pText_Moored_Speed->SetValue(s);
6204
6205 m_pCheck_Draw_Realtime_Prediction->SetValue(g_bDrawAISRealtime);
6206
6207 s.Printf(_T("%4.1f"), g_AIS_RealtPred_Kts);
6208 m_pText_RealtPred_Speed->SetValue(s);
6209
6210 m_pCheck_Scale_Priority->SetValue(g_bAllowShowScaled);
6211
6212 s.Printf(_T("%i"), g_ShowScaled_Num);
6213 m_pText_Scale_Priority->SetValue(s);
6214
6215 m_pCheck_Show_Area_Notices->SetValue(g_bShowAreaNotices);
6216
6217 m_pCheck_Draw_Target_Size->SetValue(g_bDrawAISSize);
6218 m_pCheck_Draw_Realtime_Prediction->SetValue(g_bDrawAISRealtime);
6219
6220 m_pCheck_Show_Target_Name->SetValue(g_bShowAISName);
6221
6222 s.Printf(_T("%d"), g_Show_Target_Name_Scale);
6223 m_pText_Show_Target_Name_Scale->SetValue(s);
6224
6225 m_pCheck_use_Wpl->SetValue(g_bWplUsePosition);
6226 m_pWplAction->SetSelection(g_WplAction);
6227
6228 // Alerts
6229 m_pCheck_AlertDialog->SetValue(g_bAIS_CPA_Alert);
6230 if (m_pCheck_AlertDialog->GetValue()) {
6231 m_pCheck_AlertAudio->Enable();
6232 m_pCheck_AlertAudio->SetValue(g_bAIS_CPA_Alert_Audio);
6233 } else {
6234 m_pCheck_AlertAudio->Disable();
6235 m_pCheck_AlertAudio->SetValue(false);
6236 }
6237
6238 m_pCheck_Alert_Moored->SetValue(g_bAIS_CPA_Alert_Suppress_Moored);
6239
6240 m_pCheck_Ack_Timout->SetValue(g_bAIS_ACK_Timeout);
6241 s.Printf(_T("%4.0f"), g_AckTimeout_Mins);
6242 m_pText_ACK_Timeout->SetValue(s);
6243
6244 // Sounds
6245 if (m_pCheck_AlertDialog
6246 ->GetValue()) { // AIS Alert sound only if Alert dialog is enabled
6247
6248 m_soundPanelAIS->GetCheckBox()->Enable(m_pCheck_AlertAudio->GetValue());
6249 m_soundPanelAIS->GetCheckBox()->SetValue(g_bAIS_GCPA_Alert_Audio);
6250 m_soundPanelSART->GetCheckBox()->Enable(m_pCheck_AlertAudio->GetValue());
6251 m_soundPanelSART->GetCheckBox()->SetValue(g_bAIS_SART_Alert_Audio);
6252 m_soundPanelDSC->GetCheckBox()->Enable(m_pCheck_AlertAudio->GetValue());
6253 m_soundPanelDSC->GetCheckBox()->SetValue(g_bAIS_DSC_Alert_Audio);
6254 } else {
6255 m_soundPanelAIS->GetCheckBox()->Disable();
6256 m_soundPanelAIS->GetCheckBox()->SetValue(false);
6257 m_soundPanelSART->GetCheckBox()->Disable();
6258 m_soundPanelSART->GetCheckBox()->SetValue(false);
6259 m_soundPanelDSC->GetCheckBox()->Disable();
6260 m_soundPanelDSC->GetCheckBox()->SetValue(false);
6261 }
6262
6263 // Rollover
6264 m_pCheck_Rollover_Class->SetValue(g_bAISRolloverShowClass);
6265 m_pCheck_Rollover_COG->SetValue(g_bAISRolloverShowCOG);
6266 m_pCheck_Rollover_CPA->SetValue(g_bAISRolloverShowCPA);
6267
6268 m_pSlider_Zoom_Raster->SetValue(g_chart_zoom_modifier_raster);
6269 m_pSlider_Zoom_Vector->SetValue(g_chart_zoom_modifier_vector);
6270
6271 m_pSlider_GUI_Factor->SetValue(g_GUIScaleFactor);
6272 m_pSlider_Chart_Factor->SetValue(g_ChartScaleFactor);
6273 m_pSlider_Ship_Factor->SetValue(g_ShipScaleFactor);
6274 m_pSlider_Text_Factor->SetValue(g_ENCSoundingScaleFactor);
6275 m_pSlider_ENCText_Factor->SetValue(g_ENCTextScaleFactor);
6276 m_pMouse_Zoom_Slider->SetValue(g_mouse_zoom_sensitivity_ui);
6277 wxString screenmm;
6278
6279 if (!g_config_display_size_manual) {
6280 pRBSizeAuto->SetValue(TRUE);
6281 screenmm.Printf(_T("%d"), int(g_Platform->GetDisplaySizeMM()));
6282 pScreenMM->Disable();
6283 } else {
6284 screenmm.Printf(_T("%d"), int(g_config_display_size_mm));
6285 pRBSizeManual->SetValue(TRUE);
6286 }
6287
6288 pScreenMM->SetValue(screenmm);
6289
6290
6291 pDepthUnitSelect->SetSelection(g_nDepthUnitDisplay);
6292 UpdateOptionsUnits(); // sets depth values using the user's unit preference
6293
6294 SetInitialVectorSettings();
6295
6296 pToolbarAutoHideCB->SetValue(g_bAutoHideToolbar);
6297
6298 s.Printf(_T("%d"), g_nAutoHideToolbar);
6299 pToolbarHideSecs->SetValue(s);
6300
6301
6302 // Serial ports
6303
6304 delete m_pSerialArray;
6305 m_pSerialArray = NULL;
6306 m_pSerialArray = EnumerateSerialPorts();
6307
6308 comm_dialog->SetInitialSettings();
6309
6310 m_bForceNewToolbaronCancel = false;
6311}
6312
6313void options::resetMarStdList(bool bsetConfig, bool bsetStd) {
6314 if (ps57CtlListBox) {
6315 // S52 Primary Filters
6316 ps57CtlListBox->Clear();
6317 marinersStdXref.clear();
6318
6319 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
6320 iPtr++) {
6321 OBJLElement* pOLE = (OBJLElement*)(ps52plib->pOBJLArray->Item(iPtr));
6322
6323 wxString item;
6324 if (iPtr < ps52plib->OBJLDescriptions.size()) {
6325 item = ps52plib->OBJLDescriptions[iPtr];
6326 } else {
6327 item = wxString(pOLE->OBJLName, wxConvUTF8);
6328 }
6329
6330 // Find the most conservative Category, among Point, Area, and Line LUPs
6331 DisCat cat = OTHER;
6332
6333 DisCat catp = ps52plib->findLUPDisCat(pOLE->OBJLName, SIMPLIFIED);
6334 DisCat cata = ps52plib->findLUPDisCat(pOLE->OBJLName, PLAIN_BOUNDARIES);
6335 DisCat catl = ps52plib->findLUPDisCat(pOLE->OBJLName, LINES);
6336
6337 if ((catp == DISPLAYBASE) || (cata == DISPLAYBASE) ||
6338 (catl == DISPLAYBASE))
6339 cat = DISPLAYBASE;
6340 else if ((catp == STANDARD) || (cata == STANDARD) || (catl == STANDARD))
6341 cat = STANDARD;
6342
6343 bool benable = true;
6344 if (cat > 0) benable = cat != DISPLAYBASE;
6345
6346 // The ListBox control will insert entries in sorted order, which means
6347 // we need to
6348 // keep track of already inserted items that gets pushed down the line.
6349 int newpos = ps57CtlListBox->Append(item, benable);
6350 marinersStdXref.push_back(newpos);
6351 for (size_t i = 0; i < iPtr; i++) {
6352 if (marinersStdXref[i] >= newpos) marinersStdXref[i]++;
6353 }
6354
6355 bool bviz = 0;
6356 if (bsetConfig) bviz = !(pOLE->nViz == 0);
6357
6358 if (cat == DISPLAYBASE) bviz = true;
6359
6360 if (bsetStd) {
6361 if (cat == STANDARD) {
6362 bviz = true;
6363 }
6364 }
6365
6366 ps57CtlListBox->Check(newpos, bviz);
6367 }
6368 // Force the wxScrolledWindow to recalculate its scroll bars
6369 wxSize s = ps57CtlListBox->GetSize();
6370 ps57CtlListBox->SetSize(s.x, s.y - 1);
6371 }
6372}
6373
6374void options::SetInitialVectorSettings(void) {
6375 m_pSlider_CM93_Zoom->SetValue(g_cm93_zoom_factor);
6376
6377 // Diplay Category
6378 if (ps52plib) {
6379 m_bVectorInit = true;
6380 resetMarStdList(true, false);
6381
6382#ifdef __OCPN__ANDROID__
6383 ps57CtlListBox->GetHandle()->setStyleSheet(getAdjustedDialogStyleSheet());
6384#endif
6385
6386 int nset = 2; // default OTHER
6387 switch (ps52plib->GetDisplayCategory()) {
6388 case (DISPLAYBASE):
6389 nset = 0;
6390 break;
6391 case (STANDARD):
6392 nset = 1;
6393 break;
6394 case (OTHER):
6395 nset = 2;
6396 break;
6397 case (MARINERS_STANDARD):
6398 nset = 3;
6399 break;
6400 default:
6401 nset = 3;
6402 break;
6403 }
6404
6405 if (pDispCat) pDispCat->SetSelection(nset);
6406
6407 // Enable the UserStandard object list if either canvas is in
6408 // MARINERS_STANDARD display category
6409 bool benableMarStd = false;
6410 // .. for each canvas...
6411 for (unsigned int i = 0; i < g_canvasArray.GetCount(); i++) {
6412 ChartCanvas* cc = g_canvasArray.Item(i);
6413 if (cc) {
6414 if (cc->GetENCDisplayCategory() == MARINERS_STANDARD)
6415 benableMarStd = true;
6416 }
6417 }
6418
6419 // if(g_useMUI)
6420 // benableMarStd = true;
6421
6422 if (ps57CtlListBox) ps57CtlListBox->Enable(benableMarStd);
6423 itemButtonClearList->Enable(benableMarStd);
6424 itemButtonSelectList->Enable(benableMarStd);
6425 itemButtonSetStd->Enable(benableMarStd);
6426
6427 // Other Display Filters
6428 if (pCheck_SOUNDG) pCheck_SOUNDG->SetValue(ps52plib->m_bShowSoundg);
6429 if (pCheck_ATONTEXT) pCheck_ATONTEXT->SetValue(ps52plib->m_bShowAtonText);
6430 if (pCheck_LDISTEXT) pCheck_LDISTEXT->SetValue(ps52plib->m_bShowLdisText);
6431 if (pCheck_XLSECTTEXT)
6432 pCheck_XLSECTTEXT->SetValue(ps52plib->m_bExtendLightSectors);
6433
6434 pCheck_META->SetValue(ps52plib->m_bShowMeta);
6435 pCheck_SHOWIMPTEXT->SetValue(ps52plib->m_bShowS57ImportantTextOnly);
6436 pCheck_SCAMIN->SetValue(ps52plib->m_bUseSCAMIN);
6437 pCheck_SuperSCAMIN->SetValue(ps52plib->m_bUseSUPER_SCAMIN);
6438
6439 pCheck_DECLTEXT->SetValue(ps52plib->m_bDeClutterText);
6440 pCheck_NATIONALTEXT->SetValue(ps52plib->m_bShowNationalTexts);
6441
6442 // Chart Display Style
6443 if (ps52plib->m_nSymbolStyle == PAPER_CHART)
6444 pPointStyle->SetSelection(0);
6445 else
6446 pPointStyle->SetSelection(1);
6447
6448 if (ps52plib->m_nBoundaryStyle == PLAIN_BOUNDARIES)
6449 pBoundStyle->SetSelection(0);
6450 else
6451 pBoundStyle->SetSelection(1);
6452
6453 if (S52_getMarinerParam(S52_MAR_TWO_SHADES) == 1.0)
6454 p24Color->SetSelection(0);
6455 else
6456 p24Color->SetSelection(1);
6457
6458 UpdateOptionsUnits(); // sets depth values using the user's unit preference
6459 }
6460}
6461
6462void options::UpdateOptionsUnits(void) {
6463 int depthUnit = pDepthUnitSelect->GetSelection();
6464
6465 depthUnit = wxMax(depthUnit, 0);
6466 depthUnit = wxMin(depthUnit, 2);
6467
6468 // depth unit conversion factor
6469 float conv = 1;
6470 if (depthUnit == 0) // feet
6471 conv = 0.3048f; // international definiton of 1 foot is 0.3048 metres
6472 else if (depthUnit == 2) // fathoms
6473 conv = 0.3048f * 6; // 1 fathom is 6 feet
6474
6475 // set depth input values
6476
6477 // set depth unit labels
6478 wxString depthUnitStrings[] = {_("feet"), _("meters"), _("fathoms")};
6479 wxString depthUnitString = depthUnitStrings[depthUnit];
6480 m_depthUnitsShal->SetLabel(depthUnitString);
6481 m_depthUnitsSafe->SetLabel(depthUnitString);
6482 m_depthUnitsDeep->SetLabel(depthUnitString);
6483
6484 wxString s;
6485 s.Printf(_T( "%6.2f" ), S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR) / conv);
6486 s.Trim(FALSE);
6487 m_ShallowCtl->SetValue(s);
6488
6489 s.Printf(_T( "%6.2f" ), S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR) / conv);
6490 s.Trim(FALSE);
6491 m_SafetyCtl->SetValue(s);
6492
6493 s.Printf(_T( "%6.2f" ), S52_getMarinerParam(S52_MAR_DEEP_CONTOUR) / conv);
6494 s.Trim(FALSE);
6495 m_DeepCtl->SetValue(s);
6496 /*
6497 int oldLength = itemStaticTextUserVar->GetLabel().Length();
6498
6499 //disable input for variation if WMM is available
6500 if(b_haveWMM){
6501 itemStaticTextUserVar->SetLabel(_("WMM Plugin calculated magnetic
6502 variation")); wxString s; s.Printf(_T("%4.1f"), gVar); pMagVar->SetValue(s);
6503 }
6504 else{
6505 itemStaticTextUserVar->SetLabel(_("User set magnetic variation"));
6506 wxString s;
6507 s.Printf(_T("%4.1f"), g_UserVar);
6508 pMagVar->SetValue(s);
6509 }
6510
6511 int newLength = itemStaticTextUserVar->GetLabel().Length();
6512
6513 // size hack to adjust change in static text size
6514 if( (newLength != oldLength) || (b_oldhaveWMM != b_haveWMM) ){
6515 wxSize sz = GetSize();
6516 SetSize(sz.x+1, sz.y);
6517 SetSize(sz);
6518 }
6519
6520 itemStaticTextUserVar2->Enable(!b_haveWMM);
6521 pMagVar->Enable(!b_haveWMM);
6522 */
6523}
6524
6525void options::OnSizeAutoButton(wxCommandEvent& event) {
6526 wxString screenmm = wxString::Format(
6527 _T( "%d" ), static_cast<int>(g_Platform->GetDisplaySizeMM()));
6528 pScreenMM->SetValue(screenmm);
6529 pScreenMM->Disable();
6530 g_config_display_size_manual = FALSE;
6531}
6532
6533void options::OnSizeManualButton(wxCommandEvent& event) {
6534 wxString screenmm = wxString::Format(
6535 _T( "%d" ), static_cast<int>(g_config_display_size_mm > 0
6536 ? g_config_display_size_mm
6537 : g_Platform->GetDisplaySizeMM()));
6538 pScreenMM->SetValue(screenmm);
6539 pScreenMM->Enable();
6540 g_config_display_size_manual = TRUE;
6541}
6542
6543void options::OnUnitsChoice(wxCommandEvent& event) { UpdateOptionsUnits(); }
6544
6545void options::OnCPAWarnClick(wxCommandEvent& event) {
6546 if (m_pCheck_CPA_Warn->GetValue()) {
6547 m_pCheck_CPA_WarnT->Enable();
6548 } else {
6549 m_pCheck_CPA_WarnT->SetValue(FALSE);
6550 m_pCheck_CPA_WarnT->Disable();
6551 }
6552}
6553
6554void options::OnSyncCogPredClick(wxCommandEvent &event) {
6555 if (m_pCheck_Sync_OCOG_ACOG->GetValue()) {
6556 m_pText_COG_Predictor->SetValue(m_pText_OSCOG_Predictor->GetValue());
6557 m_pText_COG_Predictor->Disable();
6558 }
6559 else {
6560 wxString s;
6561 s.Printf(_T("%4.0f"), g_ShowCOG_Mins);
6562 m_pText_COG_Predictor->SetValue(s);
6563 m_pText_COG_Predictor->Enable();
6564 }
6565}
6566
6567void options::OnShipTypeSelect(wxCommandEvent& event) {
6568 realSizes->ShowItems(m_pShipIconType->GetSelection() != 0);
6569 dispOptions->Layout();
6570 ownShip->Layout();
6571 itemPanelShip->Layout();
6572 itemPanelShip->Refresh();
6573 event.Skip();
6574}
6575
6576void options::OnRadarringSelect(wxCommandEvent& event) {
6577 radarGrid->ShowItems(pNavAidRadarRingsNumberVisible->GetSelection() != 0);
6578 dispOptions->Layout();
6579 ownShip->Layout();
6580 itemPanelShip->Layout();
6581 itemPanelShip->Refresh();
6582 event.Skip();
6583}
6584
6585void options::OnWaypointRangeRingSelect(wxCommandEvent& event) {
6586 waypointradarGrid->ShowItems(pWaypointRangeRingsNumber->GetSelection() != 0);
6587 dispOptions->Layout();
6588 Routes->Layout();
6589 itemPanelRoutes->Layout();
6590 itemPanelRoutes->Refresh();
6591 event.Skip();
6592}
6593
6594void options::OnGLClicked(wxCommandEvent& event) {
6595 // if (!g_bTransparentToolbarInOpenGLOK)
6596 // pTransparentToolbar->Enable(!pOpenGL->GetValue());
6597}
6598
6599void options::OnOpenGLOptions(wxCommandEvent& event) {
6600#ifdef ocpnUSE_GL
6601 OpenGLOptionsDlg dlg(this);
6602
6603 if (dlg.ShowModal() == wxID_OK) {
6604 if (gFrame->GetPrimaryCanvas()->GetglCanvas()) {
6605 g_GLOptions.m_bUseAcceleratedPanning = g_bGLexpert
6606 ? dlg.GetAcceleratedPanning()
6607 : gFrame->GetPrimaryCanvas()
6608 ->GetglCanvas()
6609 ->CanAcceleratePanning();
6610 }
6611
6612 g_bShowFPS = dlg.GetShowFPS();
6613 g_bSoftwareGL = dlg.GetSoftwareGL();
6614
6615 g_GLOptions.m_GLPolygonSmoothing = dlg.GetPolygonSmoothing();
6616 g_GLOptions.m_GLLineSmoothing = dlg.GetLineSmoothing();
6617
6618 if (g_bGLexpert) {
6619 // user defined
6620 g_GLOptions.m_bTextureCompressionCaching =
6621 dlg.GetTextureCompressionCaching();
6622 g_GLOptions.m_iTextureMemorySize = dlg.GetTextureMemorySize();
6623 } else {
6624 // caching is on if textures are compressed
6625 g_GLOptions.m_bTextureCompressionCaching = dlg.GetTextureCompression();
6626 }
6627
6628 if (g_bopengl && g_glTextureManager &&
6629 g_GLOptions.m_bTextureCompression != dlg.GetTextureCompression()) {
6630 // new g_GLoptions setting is needed in callees
6631 g_GLOptions.m_bTextureCompression = dlg.GetTextureCompression();
6632
6633 if (gFrame->GetPrimaryCanvas()->GetglCanvas()) {
6634 ::wxBeginBusyCursor();
6635 gFrame->GetPrimaryCanvas()->GetglCanvas()->SetupCompression();
6636 g_glTextureManager->ClearAllRasterTextures();
6637 ::wxEndBusyCursor();
6638 }
6639 } else
6640 g_GLOptions.m_bTextureCompression = dlg.GetTextureCompression();
6641 }
6642
6643 if (dlg.GetRebuildCache()) {
6644 m_returnChanges = REBUILD_RASTER_CACHE;
6645 Finish();
6646 }
6647#endif
6648}
6649
6650void options::OnChartDirListSelect(wxCommandEvent& event) {
6651#if 0
6652 bool selected = (pActiveChartsList->GetSelectedItemCount() > 0);
6653 m_removeBtn->Enable(selected);
6654 if (m_compressBtn) m_compressBtn->Enable(selected);
6655#endif
6656}
6657
6658void options::OnDisplayCategoryRadioButton(wxCommandEvent& event) {
6659 if (!g_useMUI) {
6660 if (pDispCat) {
6661 const bool select = pDispCat->GetSelection() == 3;
6662 ps57CtlListBox->Enable(select);
6663 itemButtonClearList->Enable(select);
6664 itemButtonSelectList->Enable(select);
6665 itemButtonSetStd->Enable(select);
6666 }
6667 }
6668 event.Skip();
6669}
6670
6671void options::OnButtonClearClick(wxCommandEvent& event) {
6672 resetMarStdList(false, false);
6673
6674 // int nOBJL = ps57CtlListBox->GetCount();
6675 // for (int iPtr = 0; iPtr < nOBJL; iPtr++){
6676 // ps57CtlListBox->Check(iPtr, FALSE);
6677 // }
6678 event.Skip();
6679}
6680
6681void options::OnButtonSelectClick(wxCommandEvent& event) {
6682 int nOBJL = ps57CtlListBox->GetCount();
6683 for (int iPtr = 0; iPtr < nOBJL; iPtr++) ps57CtlListBox->Check(iPtr, TRUE);
6684
6685 event.Skip();
6686}
6687
6688void options::OnButtonSetStd(wxCommandEvent& event) {
6689 resetMarStdList(false, true);
6690
6691 event.Skip();
6692}
6693
6694bool options::ShowToolTips(void) { return TRUE; }
6695
6696void options::OnCharHook(wxKeyEvent& event) {
6697 if (event.GetKeyCode() == WXK_RETURN &&
6698 event.GetModifiers() == wxMOD_CONTROL) {
6699 wxCommandEvent okEvent;
6700 okEvent.SetId(xID_OK);
6701 okEvent.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED);
6702 GetEventHandler()->AddPendingEvent(okEvent);
6703 }
6704 event.Skip();
6705}
6706
6707void options::OnButtonaddClick(wxCommandEvent& event) {
6708 wxString selDir;
6709 int dresult = g_Platform->DoDirSelectorDialog(
6710 this, &selDir, _("Add a directory containing chart files"),
6711 *pInit_Chart_Dir, false); // no add files allowed
6712
6713 if (dresult != wxID_CANCEL) AddChartDir(selDir);
6714
6715 event.Skip();
6716}
6717
6718void options::AddChartDir(const wxString& dir) {
6719 wxFileName dirname = wxFileName(dir);
6720 pInit_Chart_Dir->Empty();
6721
6722 wxString dirAdd;
6723 if (g_bportable) {
6724 wxFileName f(dir);
6725 f.MakeRelativeTo(g_Platform->GetHomeDir());
6726 dirAdd = f.GetFullPath();
6727 } else {
6728 pInit_Chart_Dir->Append(dirname.GetPath());
6729 dirAdd = dir;
6730 }
6731
6732 ChartDirInfo cdi;
6733 cdi.fullpath = dirAdd;
6734 ActiveChartArray.Add(cdi);
6735
6736 UpdateChartDirList();
6737
6738 k_charts |= CHANGE_CHARTS;
6739
6740 pScanCheckBox->Disable();
6741}
6742
6743void options::UpdateDisplayedChartDirList(ArrayOfCDI p) {
6744 // Called by pluginmanager after adding single chart to database
6745
6746 ActiveChartArray.Clear();
6747 for (size_t i = 0; i < p.GetCount(); i++) {
6748 ActiveChartArray.Add(p[i]);
6749 }
6750
6751 UpdateChartDirList();
6752}
6753
6754void options::UpdateWorkArrayFromDisplayPanel(void) {
6755 wxString dirname;
6756 int n = ActiveChartArray.GetCount();
6757 if (m_pWorkDirList) {
6758 m_pWorkDirList->Clear();
6759 for (int i = 0; i < n; i++) {
6760 dirname = ActiveChartArray[i].fullpath;
6761 if (!dirname.IsEmpty()) {
6762 // This is a fix for OSX, which appends EOL to results of
6763 // GetLineText()
6764 while ((dirname.Last() == wxChar(_T('\n'))) ||
6765 (dirname.Last() == wxChar(_T('\r'))))
6766 dirname.RemoveLast();
6767
6768 // scan the current array to find a match
6769 // if found, add the info to the work list, preserving the magic
6770 // number
6771 // If not found, make a new ChartDirInfo, and add it
6772 bool b_added = FALSE;
6773 // if(m_pCurrentDirList)
6774 {
6775 int nDir = m_CurrentDirList.GetCount();
6776
6777 for (int i = 0; i < nDir; i++) {
6778 if (m_CurrentDirList[i].fullpath == dirname) {
6779 ChartDirInfo cdi = m_CurrentDirList[i];
6780 m_pWorkDirList->Add(cdi);
6781 b_added = TRUE;
6782 break;
6783 }
6784 }
6785 }
6786 if (!b_added) {
6787 ChartDirInfo cdin;
6788 cdin.fullpath = dirname;
6789 m_pWorkDirList->Add(cdin);
6790 }
6791 }
6792 }
6793 }
6794}
6795
6796
6797void options::OnApplyClick(wxCommandEvent& event) {
6798 //::wxBeginBusyCursor();
6799 //FIXME This function is in ConnectionsDialog StopBTScan();
6800
6801 // Start with the stuff that requires intelligent validation.
6802
6803 if (m_pShipIconType->GetSelection() > 0) {
6804 double n_ownship_length_meters;
6805 double n_ownship_beam_meters;
6806 double n_gps_antenna_offset_y;
6807 double n_gps_antenna_offset_x;
6808 long n_ownship_min_mm;
6809 m_pOSLength->GetValue().ToDouble(&n_ownship_length_meters);
6810 m_pOSWidth->GetValue().ToDouble(&n_ownship_beam_meters);
6811 m_pOSGPSOffsetX->GetValue().ToDouble(&n_gps_antenna_offset_x);
6812 m_pOSGPSOffsetY->GetValue().ToDouble(&n_gps_antenna_offset_y);
6813 m_pOSMinSize->GetValue().ToLong(&n_ownship_min_mm);
6814 wxString msg;
6815 if (n_ownship_length_meters <= 0)
6816 msg += _("\n - your ship's length must be > 0");
6817 if (n_ownship_beam_meters <= 0)
6818 msg += _("\n - your ship's beam must be > 0");
6819 if (fabs(n_gps_antenna_offset_x) > n_ownship_beam_meters / 2.0)
6820 msg += _(
6821 "\n - your GPS offset from midship must be within your ship's beam");
6822 if (n_gps_antenna_offset_y < 0 ||
6823 n_gps_antenna_offset_y > n_ownship_length_meters)
6824 msg +=
6825 _("\n - your GPS offset from bow must be within your ship's length");
6826 if (n_ownship_min_mm <= 0 || n_ownship_min_mm > 100)
6827 msg += _("\n - your minimum ship icon size must be between 1 and 100 mm");
6828 if (!msg.IsEmpty()) {
6829 msg.Prepend(_("The settings for own ship real size are not correct:"));
6830 OCPNMessageBox(this, msg, _("OpenCPN info"), wxICON_ERROR | wxOK);
6831 ::wxEndBusyCursor();
6832 event.SetInt(wxID_STOP);
6833 return;
6834 }
6835 g_n_ownship_length_meters = n_ownship_length_meters;
6836 g_n_ownship_beam_meters = n_ownship_beam_meters;
6837 g_n_gps_antenna_offset_y = n_gps_antenna_offset_y;
6838 g_n_gps_antenna_offset_x = n_gps_antenna_offset_x;
6839 g_n_ownship_min_mm = static_cast<int>(n_ownship_min_mm);
6840 }
6841 g_OwnShipIconType = m_pShipIconType->GetSelection();
6842 g_bShowShipToActive = pShowshipToActive->GetValue();
6843 g_shipToActiveStyle = m_shipToActiveStyle->GetSelection();
6844 g_shipToActiveColor = m_shipToActiveColor->GetSelection();
6845
6846 m_pText_ACRadius->GetValue().ToDouble(&g_n_arrival_circle_radius);
6847 g_n_arrival_circle_radius =
6848 wxClip(g_n_arrival_circle_radius, 0.001, 0.6); // Correct abnormally
6849
6850 wxString* icon_name =
6851 pWayPointMan->GetIconKey(pWaypointDefaultIconChoice->GetSelection());
6852 if (icon_name && icon_name->Length()) g_default_wp_icon = *icon_name;
6853
6854 icon_name =
6855 pWayPointMan->GetIconKey(pRoutepointDefaultIconChoice->GetSelection());
6856 if (icon_name && icon_name->Length()) g_default_routepoint_icon = *icon_name;
6857
6858 g_bUseWptScaMin = pScaMinChckB->GetValue();
6859 g_iWpt_ScaMin = wxAtoi(m_pText_ScaMin->GetValue());
6860 g_bOverruleScaMin = pScaMinOverruleChckB->GetValue();
6861
6862 // Any Font changes?
6863 if (m_bfontChanged){
6864 if (gFrame->GetPrimaryCanvas()->GetglCanvas()) {
6865 gFrame->GetPrimaryCanvas()->GetglCanvas()->ResetGridFont();
6866 }
6867 m_returnChanges |= FONT_CHANGED;
6868 }
6869
6870 // Handle Chart Tab
6871 UpdateWorkArrayFromDisplayPanel();
6872
6873 groupsPanel->SetDBDirs(*m_pWorkDirList); // update the Groups tab
6874 groupsPanel->m_treespopulated = FALSE;
6875
6876 int k_force = FORCE_UPDATE;
6877 if (pUpdateCheckBox) {
6878 if (!pUpdateCheckBox->GetValue()) k_force = 0;
6879 pUpdateCheckBox->Enable();
6880 pUpdateCheckBox->SetValue(FALSE);
6881 } else {
6882 k_force = 0;
6883 }
6884
6885 m_returnChanges |= k_force;
6886
6887 int k_scan = SCAN_UPDATE;
6888 if (pScanCheckBox) {
6889 if (!pScanCheckBox->GetValue()) k_scan = 0;
6890 pScanCheckBox->Enable();
6891 pScanCheckBox->SetValue(FALSE);
6892 } else {
6893 k_scan = 0;
6894 }
6895
6896 m_returnChanges |= k_scan;
6897
6898 // Chart Groups
6899
6900 if (groupsPanel->modified) {
6901 groupsPanel->EmptyChartGroupArray(g_pGroupArray);
6902 delete g_pGroupArray;
6903 g_pGroupArray = groupsPanel->CloneChartGroupArray(m_pGroupArray);
6904 m_returnChanges |= GROUPS_CHANGED;
6905 }
6906
6907 // Handle Settings Tab
6908 if (m_pConfig) {
6909 g_bShowStatusBar = pShowStatusBar->GetValue();
6910#ifndef __WXOSX__
6911 g_bShowMenuBar = pShowMenuBar->GetValue();
6912#endif
6913 g_bShowCompassWin = pShowCompassWin->GetValue();
6914 }
6915
6916 g_bShowChartBar = pShowChartBar->GetValue();
6917
6918 wxString screenmm = pScreenMM->GetValue();
6919 long mm = -1;
6920 screenmm.ToLong(&mm);
6921 g_config_display_size_mm = mm > 0 ? mm : -1;
6922 g_config_display_size_manual = pRBSizeManual->GetValue();
6923
6924 // Connections page.
6925 comm_dialog->ApplySettings();
6926
6927 if (pCDOOutlines) g_bShowOutlines = pCDOOutlines->GetValue();
6928 if (pSDisplayGrid) g_bDisplayGrid = pSDisplayGrid->GetValue();
6929
6930 if (pCDOQuilting) {
6931 bool temp_bquilting = pCDOQuilting->GetValue();
6932 // if (!g_bQuiltEnable && temp_bquilting)
6933 // cc1->ReloadVP(); /* compose the quilt */
6934 g_bQuiltEnable = temp_bquilting;
6935 }
6936 // g_bFullScreenQuilt = !pFullScreenQuilt->GetValue();
6937
6938 if (pSDepthUnits) g_bShowDepthUnits = pSDepthUnits->GetValue();
6939 g_bskew_comp = pSkewComp->GetValue();
6940 g_btouch = pMobile->GetValue();
6941 g_bresponsive = pResponsive->GetValue();
6942 g_bRollover = pRollover->GetValue();
6943 g_bShowMuiZoomButtons = pZoomButtons->GetValue();
6944
6945 g_bAutoHideToolbar = pToolbarAutoHideCB->GetValue();
6946
6947 long hide_val = 10;
6948 pToolbarHideSecs->GetValue().ToLong(&hide_val);
6949 g_nAutoHideToolbar = wxMin(static_cast<int>(hide_val), 100);
6950 g_nAutoHideToolbar = wxMax(g_nAutoHideToolbar, 2);
6951
6952 // g_fog_overzoom = !pOverzoomEmphasis->GetValue();
6953 // g_oz_vector_scale = !pOZScaleVector->GetValue();
6954
6955 g_bsmoothpanzoom = pSmoothPanZoom->GetValue();
6956#ifdef __OCPN__ANDROID__
6957 g_bsmoothpanzoom = false;
6958#endif
6959 if (pSmoothPanZoom) g_bsmoothpanzoom = pSmoothPanZoom->GetValue();
6960#ifdef __OCPN__ANDROID__
6961 g_bsmoothpanzoom = false;
6962#endif
6963
6964 long update_val = 1;
6965 pCOGUPUpdateSecs->GetValue().ToLong(&update_val);
6966 g_COGAvgSec = wxMin(static_cast<int>(update_val), MAX_COG_AVERAGE_SECONDS);
6967
6968 // TODO if (g_bCourseUp != pCBCourseUp->GetValue()) gFrame->ToggleCourseUp();
6969
6970 if (pCBLookAhead) g_bLookAhead = pCBLookAhead->GetValue();
6971
6972 g_bShowTrue = pCBTrueShow->GetValue();
6973 g_bShowMag = pCBMagShow->GetValue();
6974
6975 auto loader = PluginLoader::getInstance();
6976 b_haveWMM = loader && loader->IsPlugInAvailable(_T("WMM"));
6977 if (!b_haveWMM && !b_oldhaveWMM) {
6978 pMagVar->GetValue().ToDouble(&g_UserVar);
6979 gVar = g_UserVar;
6980 }
6981
6982 m_pText_OSCOG_Predictor->GetValue().ToDouble(&g_ownship_predictor_minutes);
6983 m_pText_OSHDT_Predictor->GetValue().ToDouble(&g_ownship_HDTpredictor_miles);
6984
6985 double temp_dbl;
6986 g_iNavAidRadarRingsNumberVisible =
6987 pNavAidRadarRingsNumberVisible->GetSelection();
6988 if (pNavAidRadarRingsStep->GetValue().ToDouble(&temp_dbl))
6989 g_fNavAidRadarRingsStep = temp_dbl;
6990 g_pNavAidRadarRingsStepUnits = m_itemRadarRingsUnits->GetSelection();
6991 g_iWaypointRangeRingsNumber = pWaypointRangeRingsNumber->GetSelection();
6992 if (pWaypointRangeRingsStep->GetValue().ToDouble(&temp_dbl))
6993 g_fWaypointRangeRingsStep = temp_dbl;
6994 g_iWaypointRangeRingsStepUnits =
6995 m_itemWaypointRangeRingsUnits->GetSelection();
6996 g_colourWaypointRangeRingsColour =
6997 m_colourWaypointRangeRingsColour->GetColour();
6998 g_colourWaypointRangeRingsColour =
6999 wxColour(g_colourWaypointRangeRingsColour.Red(),
7000 g_colourWaypointRangeRingsColour.Green(),
7001 g_colourWaypointRangeRingsColour.Blue());
7002 g_bWayPointPreventDragging = pWayPointPreventDragging->GetValue();
7003 g_own_ship_sog_cog_calc = pSogCogFromLLCheckBox->GetValue();
7004 g_own_ship_sog_cog_calc_damp_sec = pSogCogFromLLDampInterval->GetValue();
7005
7006 g_bConfirmObjectDelete = pConfirmObjectDeletion->GetValue();
7007
7008 if (pPreserveScale) g_bPreserveScaleOnX = pPreserveScale->GetValue();
7009
7010 if (g_bUIexpert && pCmdSoundString) {
7011 g_CmdSoundString = pCmdSoundString->GetValue();
7012 if (wxIsEmpty(g_CmdSoundString)) {
7013 g_CmdSoundString = wxString(OCPN_SOUND_CMD);
7014 pCmdSoundString->SetValue(g_CmdSoundString);
7015 }
7016 }
7017
7018 g_bPlayShipsBells = pPlayShipsBells->GetValue();
7019 if (pSoundDeviceIndex)
7020 g_iSoundDeviceIndex = pSoundDeviceIndex->GetSelection();
7021 // g_bTransparentToolbar = pTransparentToolbar->GetValue();
7022 g_iSDMMFormat = pSDMMFormat->GetSelection();
7023 g_iDistanceFormat = pDistanceFormat->GetSelection();
7024 g_iSpeedFormat = pSpeedFormat->GetSelection();
7025 g_iTempFormat = pTempFormat->GetSelection();
7026
7027 // LIVE ETA OPTION
7028 if (pSLiveETA) g_bShowLiveETA = pSLiveETA->GetValue();
7029 if (pSDefaultBoatSpeed)
7030 pSDefaultBoatSpeed->GetValue().ToDouble(&g_defaultBoatSpeedUserUnit);
7031 g_defaultBoatSpeed = fromUsrSpeed(g_defaultBoatSpeedUserUnit);
7032
7033 g_bAdvanceRouteWaypointOnArrivalOnly =
7034 pAdvanceRouteWaypointOnArrivalOnly->GetValue();
7035
7036 g_colourTrackLineColour = m_colourTrackLineColour->GetColour();
7037 g_colourTrackLineColour =
7038 wxColour(g_colourTrackLineColour.Red(), g_colourTrackLineColour.Green(),
7039 g_colourTrackLineColour.Blue());
7040 g_nTrackPrecision = pTrackPrecision->GetSelection();
7041
7042 g_bTrackDaily = pTrackDaily->GetValue();
7043
7044 g_track_rotate_time = 0;
7045#if wxCHECK_VERSION(2, 9, 0)
7046#if wxUSE_TIMEPICKCTRL
7047 int h, m, s;
7048 if (pTrackRotateTime->GetTime(&h, &m, &s))
7049 g_track_rotate_time = h * 3600 + m * 60 + s;
7050#endif
7051#endif
7052
7053 if (pTrackRotateUTC->GetValue())
7054 g_track_rotate_time_type = TIME_TYPE_UTC;
7055 else if (pTrackRotateLMT->GetValue())
7056 g_track_rotate_time_type = TIME_TYPE_LMT;
7057 else
7058 g_track_rotate_time_type = TIME_TYPE_COMPUTER;
7059
7060 g_bHighliteTracks = pTrackHighlite->GetValue();
7061
7062 if (pEnableZoomToCursor)
7063 g_bEnableZoomToCursor = pEnableZoomToCursor->GetValue();
7064#ifdef __OCPN__ANDROID__
7065 g_bEnableZoomToCursor = false;
7066#endif
7067
7068 g_colourOwnshipRangeRingsColour = m_colourOwnshipRangeRingColour->GetColour();
7069 g_colourOwnshipRangeRingsColour =
7070 wxColour(g_colourOwnshipRangeRingsColour.Red(),
7071 g_colourOwnshipRangeRingsColour.Green(),
7072 g_colourOwnshipRangeRingsColour.Blue());
7073
7074 // Sounds
7075 g_bAIS_GCPA_Alert_Audio = m_soundPanelAIS->GetCheckBox()->GetValue();
7076 g_bAIS_SART_Alert_Audio = m_soundPanelSART->GetCheckBox()->GetValue();
7077 g_bAIS_DSC_Alert_Audio = m_soundPanelDSC->GetCheckBox()->GetValue();
7078 g_bAnchor_Alert_Audio = m_soundPanelAnchor->GetCheckBox()->GetValue();
7079
7080 // AIS Parameters
7081 // CPA Box
7082 g_bCPAMax = m_pCheck_CPA_Max->GetValue();
7083 m_pText_CPA_Max->GetValue().ToDouble(&g_CPAMax_NM);
7084 g_bCPAWarn = m_pCheck_CPA_Warn->GetValue();
7085 m_pText_CPA_Warn->GetValue().ToDouble(&g_CPAWarn_NM);
7086 g_bTCPA_Max = m_pCheck_CPA_WarnT->GetValue();
7087 m_pText_CPA_WarnT->GetValue().ToDouble(&g_TCPA_Max);
7088
7089 // Lost Targets
7090 g_bMarkLost = m_pCheck_Mark_Lost->GetValue();
7091 m_pText_Mark_Lost->GetValue().ToDouble(&g_MarkLost_Mins);
7092 g_bRemoveLost = m_pCheck_Remove_Lost->GetValue();
7093 m_pText_Remove_Lost->GetValue().ToDouble(&g_RemoveLost_Mins);
7094
7095 // Display
7096 g_bShowCOG = m_pCheck_Show_COG->GetValue();
7097 // If synchronized with own ship predictor
7098 g_bSyncCogPredictors = m_pCheck_Sync_OCOG_ACOG->GetValue();
7099 if (g_bSyncCogPredictors) {
7100 m_pText_COG_Predictor->SetValue(m_pText_OSCOG_Predictor->GetValue());
7101 }
7102 m_pText_COG_Predictor->GetValue().ToDouble(&g_ShowCOG_Mins);
7103
7104 g_bAISShowTracks = m_pCheck_Show_Tracks->GetValue();
7105 m_pText_Track_Length->GetValue().ToDouble(&g_AISShowTracks_Mins);
7106
7107 // Update all the current targets
7108 if (g_pAIS) {
7109 for (const auto& it : g_pAIS->GetTargetList()) {
7110 auto pAISTarget = it.second;
7111 if (NULL != pAISTarget) {
7112 pAISTarget->b_show_track = g_bAISShowTracks;
7113 // Check for exceptions in MMSI properties
7114 for (unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
7115 if (pAISTarget->MMSI == g_MMSI_Props_Array[i]->MMSI) {
7116 MmsiProperties *props = g_MMSI_Props_Array[i];
7117 if (TRACKTYPE_NEVER == props->TrackType) {
7118 pAISTarget->b_show_track = false;
7119 break;
7120 }
7121 else if (TRACKTYPE_ALWAYS == props->TrackType) {
7122 pAISTarget->b_show_track = true;
7123 break;
7124 }
7125 else
7126 break;
7127 }
7128 }
7129 }
7130 }
7131 }
7132
7133 g_bHideMoored = m_pCheck_Hide_Moored->GetValue();
7134 m_pText_Moored_Speed->GetValue().ToDouble(&g_ShowMoored_Kts);
7135
7136 g_bDrawAISRealtime = m_pCheck_Draw_Realtime_Prediction->GetValue();
7137 m_pText_RealtPred_Speed->GetValue().ToDouble(&g_AIS_RealtPred_Kts);
7138
7139 g_bAllowShowScaled = m_pCheck_Scale_Priority->GetValue();
7140 long l;
7141 m_pText_Scale_Priority->GetValue().ToLong(&l);
7142 g_ShowScaled_Num = (int)l;
7143
7144 g_bShowAreaNotices = m_pCheck_Show_Area_Notices->GetValue();
7145 g_bDrawAISSize = m_pCheck_Draw_Target_Size->GetValue();
7146 g_bShowAISName = m_pCheck_Show_Target_Name->GetValue();
7147 long ais_name_scale = 5000;
7148 m_pText_Show_Target_Name_Scale->GetValue().ToLong(&ais_name_scale);
7149 g_Show_Target_Name_Scale = (int)wxMax(5000, ais_name_scale);
7150 g_bWplUsePosition = m_pCheck_use_Wpl->GetValue();
7151 g_WplAction = m_pWplAction->GetSelection();
7152
7153 // Alert
7154 g_bAIS_CPA_Alert = m_pCheck_AlertDialog->GetValue();
7155 g_bAIS_CPA_Alert_Audio = m_pCheck_AlertAudio->GetValue();
7156 g_bAIS_CPA_Alert_Suppress_Moored = m_pCheck_Alert_Moored->GetValue();
7157
7158 g_bAIS_ACK_Timeout = m_pCheck_Ack_Timout->GetValue();
7159 m_pText_ACK_Timeout->GetValue().ToDouble(&g_AckTimeout_Mins);
7160
7161 // Rollover
7162 g_bAISRolloverShowClass = m_pCheck_Rollover_Class->GetValue();
7163 g_bAISRolloverShowCOG = m_pCheck_Rollover_COG->GetValue();
7164 g_bAISRolloverShowCPA = m_pCheck_Rollover_CPA->GetValue();
7165
7166 g_chart_zoom_modifier_raster = m_pSlider_Zoom_Raster->GetValue();
7167 g_chart_zoom_modifier_vector = m_pSlider_Zoom_Vector->GetValue();
7168 g_cm93_zoom_factor = m_pSlider_CM93_Zoom->GetValue();
7169 g_GUIScaleFactor = m_pSlider_GUI_Factor->GetValue();
7170 g_ChartScaleFactor = m_pSlider_Chart_Factor->GetValue();
7171 g_ChartScaleFactorExp =
7172 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
7173 g_MarkScaleFactorExp =
7174 g_Platform->GetMarkScaleFactorExp(g_ChartScaleFactor);
7175 g_ShipScaleFactor = m_pSlider_Ship_Factor->GetValue();
7176 g_ShipScaleFactorExp = g_Platform->GetChartScaleFactorExp(g_ShipScaleFactor);
7177 g_ENCSoundingScaleFactor = m_pSlider_Text_Factor->GetValue();
7178 g_ENCTextScaleFactor = m_pSlider_ENCText_Factor->GetValue();
7179
7180 g_mouse_zoom_sensitivity_ui = m_pMouse_Zoom_Slider->GetValue();
7181 g_mouse_zoom_sensitivity =
7182 MouseZoom::ui_to_config(g_mouse_zoom_sensitivity_ui);
7183
7184 // Only reload the icons if user has actually visted the UI page
7185 if(m_bVisitLang)
7186 if (pWayPointMan)
7187 WayPointmanGui(*pWayPointMan).ReloadRoutepointIcons();
7188
7189 //FIXME Move these two
7190 //g_NMEAAPBPrecision = m_choicePrecision->GetCurrentSelection();
7191 //g_TalkerIdText = m_TalkerIdText->GetValue().MakeUpper();
7192
7193 if (g_bopengl != pOpenGL->GetValue()) m_returnChanges |= GL_CHANGED;
7194 g_bopengl = pOpenGL->GetValue();
7195
7196 // Handle Vector Charts Tab
7197 int depthUnit = pDepthUnitSelect->GetSelection();
7198 g_nDepthUnitDisplay = depthUnit;
7199
7200 // Process the UserStandard display list, noting if any changes were made
7201 bool bUserStdChange = false;
7202
7203 int nOBJL = ps57CtlListBox->GetCount();
7204
7205 for (int iPtr = 0; iPtr < nOBJL; iPtr++) {
7206 int itemIndex = -1;
7207 for (size_t i = 0; i < marinersStdXref.size(); i++) {
7208 if (marinersStdXref[i] == iPtr) {
7209 itemIndex = i;
7210 break;
7211 }
7212 }
7213 assert(itemIndex >= 0);
7214 OBJLElement* pOLE = (OBJLElement*)(ps52plib->pOBJLArray->Item(itemIndex));
7215 if (pOLE->nViz != (int)(ps57CtlListBox->IsChecked(iPtr)))
7216 bUserStdChange = true;
7217 pOLE->nViz = ps57CtlListBox->IsChecked(iPtr);
7218 }
7219
7220 if (ps52plib) {
7221 // Take a snapshot of the S52 config right now,
7222 // for later comparison
7223 ps52plib->GenerateStateHash();
7224 long stateHash = ps52plib->GetStateHash();
7225
7226 if (m_returnChanges & GL_CHANGED) {
7227 // Do this now to handle the screen refresh that is automatically
7228 // generated on Windows at closure of the options dialog...
7229 ps52plib->FlushSymbolCaches();
7230 // some CNSY depends on renderer (e.g. CARC)
7231 ps52plib->ClearCNSYLUPArray();
7232 ps52plib->GenerateStateHash();
7233 }
7234
7235 if (pDispCat) {
7236 enum _DisCat nset = OTHER;
7237 switch (pDispCat->GetSelection()) {
7238 case 0:
7239 nset = DISPLAYBASE;
7240 break;
7241 case 1:
7242 nset = STANDARD;
7243 break;
7244 case 2:
7245 nset = OTHER;
7246 break;
7247 case 3:
7248 nset = MARINERS_STANDARD;
7249 break;
7250 }
7251 ps52plib->SetDisplayCategory(nset);
7252 }
7253
7254 if (pCheck_SOUNDG) ps52plib->m_bShowSoundg = pCheck_SOUNDG->GetValue();
7255 if (pCheck_ATONTEXT)
7256 ps52plib->m_bShowAtonText = pCheck_ATONTEXT->GetValue();
7257 if (pCheck_LDISTEXT)
7258 ps52plib->m_bShowLdisText = pCheck_LDISTEXT->GetValue();
7259 if (pCheck_XLSECTTEXT)
7260 ps52plib->m_bExtendLightSectors = pCheck_XLSECTTEXT->GetValue();
7261
7262 ps52plib->m_bShowMeta = pCheck_META->GetValue();
7263 ps52plib->m_bDeClutterText = pCheck_DECLTEXT->GetValue();
7264 ps52plib->m_bShowNationalTexts = pCheck_NATIONALTEXT->GetValue();
7265 ps52plib->m_bShowS57ImportantTextOnly = pCheck_SHOWIMPTEXT->GetValue();
7266 ps52plib->m_bUseSCAMIN = pCheck_SCAMIN->GetValue();
7267 ps52plib->m_bUseSUPER_SCAMIN = pCheck_SuperSCAMIN->GetValue();
7268
7269 ps52plib->m_nSymbolStyle =
7270 pPointStyle->GetSelection() == 0 ? PAPER_CHART : SIMPLIFIED;
7271
7272 ps52plib->m_nBoundaryStyle = pBoundStyle->GetSelection() == 0
7273 ? PLAIN_BOUNDARIES
7274 : SYMBOLIZED_BOUNDARIES;
7275 ps52plib->m_nSoundingFactor = m_pSlider_Text_Factor->GetValue();
7276 ps52plib->m_nTextFactor = m_pSlider_ENCText_Factor->GetValue();
7277
7278 S52_setMarinerParam(S52_MAR_TWO_SHADES,
7279 (p24Color->GetSelection() == 0) ? 1.0 : 0.0);
7280
7281 // Depths
7282 double dval;
7283 float conv = 1;
7284
7285 if (depthUnit == 0) // feet
7286 conv = 0.3048f; // international definiton of 1 foot is 0.3048 metres
7287 else if (depthUnit == 2) // fathoms
7288 conv = 0.3048f * 6; // 1 fathom is 6 feet
7289
7290 if (m_SafetyCtl->GetValue().ToDouble(&dval)) {
7291 S52_setMarinerParam(S52_MAR_SAFETY_DEPTH,
7292 dval * conv); // controls sounding display
7293 S52_setMarinerParam(S52_MAR_SAFETY_CONTOUR,
7294 dval * conv); // controls colour
7295 }
7296
7297 if (m_ShallowCtl->GetValue().ToDouble(&dval))
7298 S52_setMarinerParam(S52_MAR_SHALLOW_CONTOUR, dval * conv);
7299
7300 if (m_DeepCtl->GetValue().ToDouble(&dval))
7301 S52_setMarinerParam(S52_MAR_DEEP_CONTOUR, dval * conv);
7302
7303 ps52plib->UpdateMarinerParams();
7304 ps52plib->m_nDepthUnitDisplay = depthUnit;
7305
7306 ps52plib->GenerateStateHash();
7307
7308 // Detect a change to S52 library config
7309 if ((stateHash != ps52plib->GetStateHash()) || bUserStdChange)
7310 m_returnChanges |= S52_CHANGED;
7311 }
7312
7313// User Interface Panel
7314#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
7315 if (m_bVisitLang) {
7316 wxString new_canon = _T("en_US");
7317 wxString lang_sel = m_itemLangListBox->GetStringSelection();
7318
7319 int nLang = sizeof(lang_list) / sizeof(int);
7320 for (int it = 0; it < nLang; it++) {
7321 const wxLanguageInfo* pli = wxLocale::GetLanguageInfo(lang_list[it]);
7322 if (pli) {
7323 wxString lang_canonical = pli->CanonicalName;
7324 wxString test_string = GetOCPNKnownLanguage(lang_canonical);
7325 if (lang_sel == test_string) {
7326 new_canon = lang_canonical;
7327 break;
7328 }
7329 }
7330 }
7331
7332 wxString locale_old = g_locale;
7333 g_locale = new_canon;
7334
7335 if (g_locale != locale_old) m_returnChanges |= LOCALE_CHANGED;
7336
7337 wxString oldStyle = g_StyleManager->GetCurrentStyle()->name;
7338 // g_StyleManager->SetStyleNextInvocation(
7339 // m_itemStyleListBox->GetStringSelection());
7340 if (g_StyleManager->GetStyleNextInvocation() != oldStyle) {
7341 m_returnChanges |= STYLE_CHANGED;
7342 }
7343 wxSizeEvent nullEvent;
7344 gFrame->OnSize(nullEvent);
7345 }
7346#endif
7347 if (g_bInlandEcdis != pInlandEcdis->GetValue()) { // InlandEcdis changed
7348 g_bInlandEcdis = pInlandEcdis->GetValue();
7349 SwitchInlandEcdisMode(g_bInlandEcdis);
7350 m_returnChanges |= TOOLBAR_CHANGED;
7351 }
7352 // PlugIn Manager Panel
7353
7354 // Pick up any changes to selections
7355 if (PluginLoader::getInstance()->UpdatePlugIns())
7356 m_returnChanges |= TOOLBAR_CHANGED;
7357
7358 // And keep config in sync
7359 if (m_pPlugInCtrl) m_pPlugInCtrl->UpdatePluginsOrder();
7360 g_pi_manager->UpdateConfig();
7361
7362 // PlugIns may have added panels
7363 if (g_pi_manager) g_pi_manager->CloseAllPlugInPanels((int)wxOK);
7364
7365 m_returnChanges |= GENERIC_CHANGED | k_vectorcharts | k_charts |
7366 m_groups_changed | k_plugins | k_tides;
7367
7368 // Pick up all the entries in the Tide/current DataSelected control
7369 // and update the global static array
7370 TideCurrentDataSet.Clear();
7371 int nEntry = tcDataSelected->GetItemCount();
7372 for (int i = 0; i < nEntry; i++) {
7373 wxString setName = tcDataSelected->GetItemText(i);
7374 TideCurrentDataSet.Add(setName);
7375 }
7376
7377 if (event.GetId() != ID_APPLY) // only on ID_OK
7378 g_canvasConfig = m_screenConfig;
7379
7380 if (event.GetId() == ID_APPLY) {
7381 gFrame->ProcessOptionsDialog(m_returnChanges, m_pWorkDirList);
7382 m_CurrentDirList =
7383 *m_pWorkDirList; // Perform a deep copy back to main database.
7384
7385 // We can clear a few flag bits on "Apply", so they won't be recognised at
7386 // the "OK" click. Their actions have already been accomplished once...
7387 m_returnChanges &= ~(CHANGE_CHARTS | FORCE_UPDATE | SCAN_UPDATE);
7388 k_charts = 0;
7389
7390 gFrame->RefreshAllCanvas();
7391 }
7392
7393 // Some layout changes requiring a new options instance?
7394 if (m_bneedNew) m_returnChanges |= NEED_NEW_OPTIONS;
7395
7396 // Record notice of any changes to last applied template
7397 UpdateTemplateTitleText();
7398
7399 if (::wxIsBusy()) // FIXME: Not sure why this is needed here
7400 ::wxEndBusyCursor();
7401}
7402
7403void options::OnXidOkClick(wxCommandEvent& event) {
7404 // When closing the form with Ctrl-Enter sometimes we get double events, the
7405 // second is empty??
7406 if (event.GetEventObject() == NULL) return;
7407
7408 OnApplyClick(event);
7409 if (event.GetInt() == wxID_STOP) return;
7410
7411 Finish();
7412}
7413
7414void options::Finish(void) {
7415 // Required to avoid intermittent crash on wxGTK
7416 m_pListbook->ChangeSelection(0);
7417 for (size_t i = 0; i < m_pListbook->GetPageCount(); i++) {
7418 wxNotebookPage* pg = m_pListbook->GetPage(i);
7419 wxNotebook* nb = dynamic_cast<wxNotebook*>(pg);
7420 if (nb) nb->ChangeSelection(0);
7421 }
7422
7423 lastWindowPos = GetPosition();
7424 lastWindowSize = GetSize();
7425
7426 pConfig->SetPath("/Settings");
7427 pConfig->Write("OptionsSizeX", lastWindowSize.x);
7428 pConfig->Write("OptionsSizeY", lastWindowSize.y);
7429
7430 SetReturnCode(m_returnChanges);
7431 EndModal(m_returnChanges);
7432}
7433
7434ArrayOfCDI options::GetSelectedChartDirs() {
7435 ArrayOfCDI rv;
7436 for (size_t i = 0; i < panelVector.size(); i++) {
7437 if (panelVector[i]->IsSelected()) {
7438 rv.Add(panelVector[i]->GetCDI());
7439 }
7440 }
7441
7442 return rv;
7443}
7444
7445ArrayOfCDI options::GetUnSelectedChartDirs() {
7446 ArrayOfCDI rv;
7447 for (size_t i = 0; i < panelVector.size(); i++) {
7448 if (!panelVector[i]->IsSelected()) {
7449 rv.Add(panelVector[i]->GetCDI());
7450 }
7451 }
7452
7453 return rv;
7454}
7455
7456void options::SetDirActionButtons() {
7457 ArrayOfCDI selArray = GetSelectedChartDirs();
7458 if (selArray.GetCount())
7459 m_removeBtn->Enable();
7460 else
7461 m_removeBtn->Disable();
7462}
7463
7464void options::OnButtondeleteClick(wxCommandEvent& event) {
7465 ArrayOfCDI unselArray = GetUnSelectedChartDirs();
7466 ActiveChartArray.Clear();
7467 for (size_t i = 0; i < unselArray.GetCount(); i++) {
7468 ActiveChartArray.Add(unselArray[i]);
7469 }
7470
7471 UpdateChartDirList();
7472
7473 UpdateWorkArrayFromDisplayPanel();
7474
7475#if 0
7476 if (m_pWorkDirList) {
7477 pActiveChartsList->DeleteAllItems();
7478 for (size_t id = 0; id < m_pWorkDirList->GetCount(); id++) {
7479 wxString dirname = m_pWorkDirList->Item(id).fullpath;
7480 wxListItem li;
7481 li.SetId(id);
7482 li.SetAlign(wxLIST_FORMAT_LEFT);
7483 li.SetText(dirname);
7484 li.SetColumn(0);
7485 long idx = pActiveChartsList->InsertItem(li);
7486 }
7487 }
7488#endif
7489
7490 k_charts |= CHANGE_CHARTS;
7491
7492 pScanCheckBox->Disable();
7493
7494 event.Skip();
7495}
7496
7497void options::OnButtonParseENC(wxCommandEvent& event) {
7498 gFrame->GetPrimaryCanvas()->EnablePaint(false);
7499
7500 extern void ParseAllENC(wxWindow * parent);
7501
7502 ParseAllENC(g_pOptions);
7503
7504 ViewPort vp;
7505 gFrame->ChartsRefresh();
7506
7507 gFrame->GetPrimaryCanvas()->EnablePaint(true);
7508}
7509
7510#ifdef OCPN_USE_LZMA
7511#include <lzma.h>
7512
7513static bool compress(lzma_stream* strm, FILE* infile, FILE* outfile) {
7514 // This will be LZMA_RUN until the end of the input file is reached.
7515 // This tells lzma_code() when there will be no more input.
7516 lzma_action action = LZMA_RUN;
7517
7518 // Buffers to temporarily hold uncompressed input
7519 // and compressed output.
7520 uint8_t inbuf[BUFSIZ];
7521 uint8_t outbuf[BUFSIZ];
7522
7523 // Initialize the input and output pointers. Initializing next_in
7524 // and avail_in isn't really necessary when we are going to encode
7525 // just one file since LZMA_STREAM_INIT takes care of initializing
7526 // those already. But it doesn't hurt much and it will be needed
7527 // if encoding more than one file like we will in 02_decompress.c.
7528 //
7529 // While we don't care about strm->total_in or strm->total_out in this
7530 // example, it is worth noting that initializing the encoder will
7531 // always reset total_in and total_out to zero. But the encoder
7532 // initialization doesn't touch next_in, avail_in, next_out, or
7533 // avail_out.
7534 strm->next_in = NULL;
7535 strm->avail_in = 0;
7536 strm->next_out = outbuf;
7537 strm->avail_out = sizeof(outbuf);
7538
7539 // Loop until the file has been successfully compressed or until
7540 // an error occurs.
7541 while (true) {
7542 // Fill the input buffer if it is empty.
7543 if (strm->avail_in == 0 && !feof(infile)) {
7544 strm->next_in = inbuf;
7545 strm->avail_in = fread(inbuf, 1, sizeof(inbuf), infile);
7546
7547 if (ferror(infile)) {
7548 fprintf(stderr, "Read error: %s\n", strerror(errno));
7549 return false;
7550 }
7551
7552 // Once the end of the input file has been reached,
7553 // we need to tell lzma_code() that no more input
7554 // will be coming and that it should finish the
7555 // encoding.
7556 if (feof(infile)) action = LZMA_FINISH;
7557 }
7558
7559 // Tell liblzma do the actual encoding.
7560 //
7561 // This reads up to strm->avail_in bytes of input starting
7562 // from strm->next_in. avail_in will be decremented and
7563 // next_in incremented by an equal amount to match the
7564 // number of input bytes consumed.
7565 //
7566 // Up to strm->avail_out bytes of compressed output will be
7567 // written starting from strm->next_out. avail_out and next_out
7568 // will be incremented by an equal amount to match the number
7569 // of output bytes written.
7570 //
7571 // The encoder has to do internal buffering, which means that
7572 // it may take quite a bit of input before the same data is
7573 // available in compressed form in the output buffer.
7574 lzma_ret ret = lzma_code(strm, action);
7575
7576 // If the output buffer is full or if the compression finished
7577 // successfully, write the data from the output bufffer to
7578 // the output file.
7579 if (strm->avail_out == 0 || ret == LZMA_STREAM_END) {
7580 // When lzma_code() has returned LZMA_STREAM_END,
7581 // the output buffer is likely to be only partially
7582 // full. Calculate how much new data there is to
7583 // be written to the output file.
7584 size_t write_size = sizeof(outbuf) - strm->avail_out;
7585
7586 if (fwrite(outbuf, 1, write_size, outfile) != write_size) {
7587 fprintf(stderr, "Write error: %s\n", strerror(errno));
7588 return false;
7589 }
7590
7591 // Reset next_out and avail_out.
7592 strm->next_out = outbuf;
7593 strm->avail_out = sizeof(outbuf);
7594 }
7595
7596 // Normally the return value of lzma_code() will be LZMA_OK
7597 // until everything has been encoded.
7598 if (ret != LZMA_OK) {
7599 // Once everything has been encoded successfully, the
7600 // return value of lzma_code() will be LZMA_STREAM_END.
7601 //
7602 // It is important to check for LZMA_STREAM_END. Do not
7603 // assume that getting ret != LZMA_OK would mean that
7604 // everything has gone well.
7605 if (ret == LZMA_STREAM_END) return true;
7606
7607 // It's not LZMA_OK nor LZMA_STREAM_END,
7608 // so it must be an error code. See lzma/base.h
7609 // (src/liblzma/api/lzma/base.h in the source package
7610 // or e.g. /usr/include/lzma/base.h depending on the
7611 // install prefix) for the list and documentation of
7612 // possible values. Most values listen in lzma_ret
7613 // enumeration aren't possible in this example.
7614 const char* msg;
7615 switch (ret) {
7616 case LZMA_MEM_ERROR:
7617 msg = "Memory allocation failed";
7618 break;
7619
7620 case LZMA_DATA_ERROR:
7621 // This error is returned if the compressed
7622 // or uncompressed size get near 8 EiB
7623 // (2^63 bytes) because that's where the .xz
7624 // file format size limits currently are.
7625 // That is, the possibility of this error
7626 // is mostly theoretical unless you are doing
7627 // something very unusual.
7628 //
7629 // Note that strm->total_in and strm->total_out
7630 // have nothing to do with this error. Changing
7631 // those variables won't increase or decrease
7632 // the chance of getting this error.
7633 msg = "File size limits exceeded";
7634 break;
7635
7636 default:
7637 // This is most likely LZMA_PROG_ERROR, but
7638 // if this program is buggy (or liblzma has
7639 // a bug), it may be e.g. LZMA_BUF_ERROR or
7640 // LZMA_OPTIONS_ERROR too.
7641 //
7642 // It is inconvenient to have a separate
7643 // error message for errors that should be
7644 // impossible to occur, but knowing the error
7645 // code is important for debugging. That's why
7646 // it is good to print the error code at least
7647 // when there is no good error message to show.
7648 msg = "Unknown error, possibly a bug";
7649 break;
7650 }
7651
7652 wxLogMessage(_T("LZMA Encoder error: %s (error code %u)\n"), msg, ret);
7653 return false;
7654 }
7655 }
7656}
7657#endif
7658
7659static bool CompressChart(wxString in, wxString out) {
7660#ifdef OCPN_USE_LZMA
7661 FILE* infile = fopen(in.mb_str(), "rb");
7662 if (!infile) return false;
7663
7664 FILE* outfile = fopen(out.mb_str(), "wb");
7665 if (!outfile) {
7666 fclose(infile);
7667 return false;
7668 }
7669
7670 lzma_stream strm = LZMA_STREAM_INIT;
7671 bool success = false;
7672 if (lzma_easy_encoder(&strm, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64) ==
7673 LZMA_OK)
7674 success = compress(&strm, infile, outfile);
7675
7676 lzma_end(&strm);
7677 fclose(infile);
7678 fclose(outfile);
7679
7680 return success;
7681#endif
7682 return false;
7683}
7684
7685void options::OnButtonmigrateClick(wxCommandEvent& event) {
7686#ifdef __OCPN__ANDROID__
7687
7688 // Run the chart migration assistant
7689 g_migrateDialog =
7690 new MigrateAssistantDialog(gFrame, true); // skip Folder scan
7691 g_migrateDialog->SetSize(gFrame->GetSize());
7692 g_migrateDialog->Centre();
7693 g_migrateDialog->Raise();
7694 g_migrateDialog->ShowModal();
7695#endif
7696}
7697
7698void options::OnButtonEcdisHelp(wxCommandEvent& event) {
7699
7700 wxString testFile = "/doc/iECDIS/index.html";
7701
7702 if (!::wxFileExists(testFile)) {
7703 wxString msg = _("The Inland ECDIS Manual is not available locally.");
7704 msg += "\n";
7705 msg +=
7706 _("Would you like to visit the iECDIS Manual website for more "
7707 "information?");
7708
7709 if (wxID_YES ==
7710 OCPNMessageBox(NULL, msg, _("Inland ECDIS Manual"), wxYES_NO | wxCENTER, 60)) {
7711 wxLaunchDefaultBrowser("https://opencpn-manuals.github.io/inland-ecdis");
7712 }
7713 } else {
7714#ifdef __WXMSW__
7715 wxLaunchDefaultBrowser("file:///" + *GetpSharedDataLocation() +
7716 testFile);
7717#else
7718 wxLaunchDefaultBrowser("file://" + *GetpSharedDataLocation() +
7719 testFile);
7720#endif
7721 }
7722
7723}
7724
7725void options::OnButtoncompressClick(wxCommandEvent& event) {
7726#if 0
7727 wxArrayInt pListBoxSelections;
7728 long item = -1;
7729 for (;;) {
7730 item = pActiveChartsList->GetNextItem(item, wxLIST_NEXT_ALL,
7731 wxLIST_STATE_SELECTED);
7732 if (item == -1) break;
7733 //pListBoxSelections.Add((int)item);
7734 item = -1; // Restart
7735 }
7736
7737 if (OCPNMessageBox(this, _("Compression will alter chart files on disk.\n\
7738This may make them incompatible with other programs or older versions of OpenCPN.\n\
7739Compressed charts may take slightly longer to load and display on some systems.\n\
7740They can be decompressed again using unxz or 7 zip programs."),
7741 _("OpenCPN Warning"),
7742 wxYES | wxCANCEL | wxCANCEL_DEFAULT | wxICON_WARNING) !=
7743 wxID_YES)
7744 return;
7745
7746 wxArrayString filespecs;
7747 filespecs.Add("*.kap");
7748 filespecs.Add("*.KAP");
7749 filespecs.Add("*.000");
7750
7751 // should we verify we are in a cm93 directory for these?
7752 filespecs.Add("*.A"), filespecs.Add("*.B"), filespecs.Add("*.C"),
7753 filespecs.Add("*.D");
7754 filespecs.Add("*.E"), filespecs.Add("*.F"), filespecs.Add("*.G"),
7755 filespecs.Add("*.Z");
7756
7757 wxGenericProgressDialog prog1(
7758 _("OpenCPN Compress Charts"), wxEmptyString,
7759 filespecs.GetCount() * pListBoxSelections.GetCount() + 1, this,
7760 wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
7761 wxPD_REMAINING_TIME | wxPD_CAN_SKIP);
7762
7763 // Make sure the dialog is big enough to be readable
7764 wxSize sz = prog1.GetSize();
7765 sz.x = gFrame->GetClientSize().x * 8 / 10;
7766 prog1.SetSize(sz);
7767
7768 wxArrayString charts;
7769 for (unsigned int i = 0; i < pListBoxSelections.GetCount(); i++) {
7770 wxString dirname = pActiveChartsList->GetItemText(pListBoxSelections[i]);
7771 if (dirname.IsEmpty()) continue;
7772 // This is a fix for OSX, which appends EOL to results of
7773 // GetLineText()
7774 while ((dirname.Last() == wxChar(_T('\n'))) ||
7775 (dirname.Last() == wxChar(_T('\r'))))
7776 dirname.RemoveLast();
7777
7778 if (!wxDir::Exists(dirname)) continue;
7779
7780 wxDir dir(dirname);
7781 wxArrayString FileList;
7782 for (unsigned int j = 0; j < filespecs.GetCount(); j++) {
7783 dir.GetAllFiles(dirname, &FileList, filespecs[j]);
7784 bool skip = false;
7785 prog1.Update(i * filespecs.GetCount() + j, dirname + filespecs[j], &skip);
7786 if (skip) return;
7787 }
7788
7789 for (unsigned int j = 0; j < FileList.GetCount(); j++)
7790 charts.Add(FileList[j]);
7791 }
7792 prog1.Hide();
7793
7794 if (charts.GetCount() == 0) {
7795 OCPNMessageBox(this, _("No charts found to compress."), _("OpenCPN Info"));
7796 return;
7797 }
7798
7799 // TODO: make this use threads
7800 unsigned long total_size = 0, total_compressed_size = 0, count = 0;
7801 wxGenericProgressDialog prog(
7802 _("OpenCPN Compress Charts"), wxEmptyString, charts.GetCount() + 1, this,
7803 wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
7804 wxPD_REMAINING_TIME | wxPD_CAN_SKIP);
7805
7806 prog.SetSize(sz);
7807
7808 for (unsigned int i = 0; i < charts.GetCount(); i++) {
7809 bool skip = false;
7810 prog.Update(i, charts[i], &skip);
7811 if (skip) break;
7812
7813 wxString compchart = charts[i] + _T(".xz");
7814 if (CompressChart(charts[i], compchart)) {
7815 total_size += wxFileName::GetSize(charts[i]).ToULong();
7816 total_compressed_size += wxFileName::GetSize(compchart).ToULong();
7817 wxRemoveFile(charts[i]);
7818 count++;
7819 }
7820 }
7821
7822 // report statistics
7823 double total_size_mb = total_size / 1024.0 / 1024.0;
7824 double total_compressed_size_mb = total_compressed_size / 1024.0 / 1024.0;
7825 OCPNMessageBox(
7826 this,
7827 wxString::Format(_("compressed %ld charts\nfrom %.1fMB to %.1fMB\nsaved "
7828 "%.1fMB (%.1f%%)"),
7829 count, total_size_mb, total_compressed_size_mb,
7830 total_size_mb - total_compressed_size_mb,
7831 (1 - total_compressed_size_mb / total_size_mb) * 100.0),
7832 _("OpenCPN Info"));
7833
7834 UpdateWorkArrayFromTextCtl();
7835
7836 if (m_pWorkDirList) {
7837 pActiveChartsList->DeleteAllItems();
7838 for (size_t id = 0; id < m_pWorkDirList->GetCount(); id++) {
7839 wxString dirname = m_pWorkDirList->Item(id).fullpath;
7840 wxListItem li;
7841 li.SetId(id);
7842 li.SetAlign(wxLIST_FORMAT_LEFT);
7843 li.SetText(dirname);
7844 li.SetColumn(0);
7845 long idx = pActiveChartsList->InsertItem(li);
7846 }
7847 }
7848
7849 k_charts |= CHANGE_CHARTS;
7850
7851 pScanCheckBox->Disable();
7852
7853 event.Skip();
7854#endif
7855}
7856
7857void options::OnDebugcheckbox1Click(wxCommandEvent& event) { event.Skip(); }
7858
7859void options::OnCancelClick(wxCommandEvent& event) {
7860 m_pListbook->ChangeSelection(0);
7861
7862 lastWindowPos = GetPosition();
7863 lastWindowSize = GetSize();
7864
7865 if (g_pi_manager) g_pi_manager->CloseAllPlugInPanels((int)wxCANCEL);
7866
7867 pConfig->SetPath("/Settings");
7868 pConfig->Write("OptionsSizeX", lastWindowSize.x);
7869 pConfig->Write("OptionsSizeY", lastWindowSize.y);
7870
7871 int rv = 0;
7872 if (m_bForceNewToolbaronCancel) rv = TOOLBAR_CHANGED;
7873 EndModal(rv);
7874}
7875
7876void options::OnClose(wxCloseEvent& event) {
7877 // PlugIns may have added panels
7878 if (g_pi_manager) g_pi_manager->CloseAllPlugInPanels((int)wxOK);
7879
7880 m_pListbook->ChangeSelection(0);
7881
7882 lastWindowPos = GetPosition();
7883 lastWindowSize = GetSize();
7884
7885 pConfig->SetPath("/Settings");
7886 pConfig->Write("OptionsSizeX", lastWindowSize.x);
7887 pConfig->Write("OptionsSizeY", lastWindowSize.y);
7888
7889 EndModal(0);
7890}
7891
7892void options::OnFontChoice(wxCommandEvent& event) {
7893 wxString sel_text_element = m_itemFontElementListBox->GetStringSelection();
7894
7895 wxFont* pif = FontMgr::Get().GetFont(sel_text_element);
7896 wxColour init_color = FontMgr::Get().GetFontColor(sel_text_element);
7897
7898 m_textSample->SetFont(*pif);
7899 m_textSample->SetForegroundColour(init_color);
7900 m_itemBoxSizerFontPanel->Layout();
7901 event.Skip();
7902}
7903
7904void options::OnChooseFont(wxCommandEvent& event) {
7905#ifdef __OCPN__ANDROID__
7906 androidDisableRotation();
7907#endif
7908
7909 wxString sel_text_element = m_itemFontElementListBox->GetStringSelection();
7910 wxFontData font_data;
7911
7912 wxFont* pif = FontMgr::Get().GetFont(sel_text_element);
7913 wxColour init_color = FontMgr::Get().GetFontColor(sel_text_element);
7914
7915 wxFontData init_font_data;
7916 if (pif) init_font_data.SetInitialFont(*pif);
7917 init_font_data.SetColour(init_color);
7918
7919#ifdef __WXGTK__
7920 wxFontDialog dg(this, init_font_data);
7921#else
7922 wxFontDialog dg(pParent, init_font_data);
7923#endif
7924
7925 wxFont* qFont = dialogFont;
7926 dg.SetFont(*qFont);
7927
7928#ifdef __WXQT__
7929 // Make sure that font dialog will fit on the screen without scrolling
7930 // We do this by setting the dialog font size "small enough" to show "n" lines
7931 wxSize proposed_size = GetSize();
7932 float n_lines = 30;
7933 float font_size = dialogFont->GetPointSize();
7934
7935 if ((proposed_size.y / font_size) < n_lines) {
7936 float new_font_size = proposed_size.y / n_lines;
7937 wxFont* smallFont = new wxFont(*dialogFont);
7938 smallFont->SetPointSize(new_font_size);
7939 dg.SetFont(*smallFont);
7940 }
7941#endif
7942
7943 if (g_bresponsive) {
7944 dg.SetSize(GetSize());
7945 dg.Centre();
7946 }
7947
7948 int retval = dg.ShowModal();
7949 if (wxID_CANCEL != retval) {
7950 font_data = dg.GetFontData();
7951 wxFont font = font_data.GetChosenFont();
7952 wxFont* psfont = new wxFont(font);
7953 wxColor color = font_data.GetColour();
7954 FontMgr::Get().SetFont(sel_text_element, psfont, color);
7955 pParent->UpdateAllFonts();
7956 m_bfontChanged = true;
7957 OnFontChoice(event);
7958 }
7959
7960#ifdef __OCPN__ANDROID__
7961 androidEnableRotation();
7962#endif
7963
7964 event.Skip();
7965}
7966
7967#if defined(__WXGTK__) || defined(__WXQT__)
7968void options::OnChooseFontColor(wxCommandEvent& event) {
7969 wxString sel_text_element = m_itemFontElementListBox->GetStringSelection();
7970
7971 wxColourData colour_data;
7972
7973 wxFont* pif = FontMgr::Get().GetFont(sel_text_element);
7974 wxColour init_color = FontMgr::Get().GetFontColor(sel_text_element);
7975
7976#ifdef __OCPN__ANDROID__
7977 androidDisableRotation();
7978
7979 unsigned int cco = 0;
7980 cco |= 0xff;
7981 cco = cco << 8;
7982 cco |= init_color.Red();
7983 cco = cco << 8;
7984 cco |= init_color.Green();
7985 cco = cco << 8;
7986 cco |= init_color.Blue();
7987 unsigned int cc = androidColorPicker(cco);
7988
7989 wxColor cn;
7990 unsigned char blue = (unsigned char)cc % 256;
7991 unsigned char green = (unsigned char)(cc >> 8) % 256;
7992 ;
7993 unsigned char red = (unsigned char)(cc >> 16) % 256;
7994 cn.Set(red, green, blue);
7995
7996 FontMgr::Get().SetFont(sel_text_element, pif, cn);
7997
7998 pParent->UpdateAllFonts();
7999 m_bfontChanged = true;
8000
8001 androidEnableRotation();
8002#else
8003 wxScrolledWindow* sw =
8004 new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(400, 400));
8005
8006 wxColourData init_colour_data;
8007 init_colour_data.SetColour(init_color);
8008
8009 wxColourDialog dg(sw, &init_colour_data);
8010
8011 int retval = dg.ShowModal();
8012 if (wxID_CANCEL != retval) {
8013 colour_data = dg.GetColourData();
8014
8015 wxColor color = colour_data.GetColour();
8016 FontMgr::Get().SetFont(sel_text_element, pif, color);
8017
8018 pParent->UpdateAllFonts();
8019 m_bfontChanged = true;
8020 OnFontChoice(event);
8021 }
8022
8023 sw->Destroy();
8024#endif
8025 event.Skip();
8026}
8027#endif
8028
8029void options::OnChartsPageChange(wxListbookEvent& event) {
8030 unsigned int i = event.GetSelection();
8031
8032 UpdateChartDirList();
8033
8034 // User selected Chart Groups Page?
8035 // If so, build the remaining UI elements
8036 if (2 == i) { // 2 is the index of "Chart Groups" page
8037 if (!groupsPanel->m_UIcomplete) groupsPanel->CompletePanel();
8038
8039 if (!groupsPanel->m_settingscomplete) {
8040 ::wxBeginBusyCursor();
8041 groupsPanel->CompleteInitialSettings();
8042 ::wxEndBusyCursor();
8043 } else if (!groupsPanel->m_treespopulated) {
8044 groupsPanel->PopulateTrees();
8045 groupsPanel->m_treespopulated = TRUE;
8046 }
8047 } else if (1 == i) { // Vector charts panel
8048 LoadS57();
8049 if (!m_bVectorInit) {
8050 SetInitialVectorSettings();
8051 UpdateOptionsUnits(); // sets depth values, overriding defaults
8052 }
8053 }
8054
8055 event.Skip(); // Allow continued event processing
8056}
8057
8058void options::OnPageChange(wxListbookEvent& event) {
8059 DoOnPageChange(event.GetSelection());
8060}
8061
8062void options::OnSubNBPageChange(wxNotebookEvent& event) {
8063 // In the case where wxNotebooks are nested, we need to identify the subpage
8064 // But otherwise do nothing
8065 if (event.GetEventObject()) {
8066 if (dynamic_cast<wxWindow*>(event.GetEventObject())) {
8067 wxWindow* win = dynamic_cast<wxWindow*>(event.GetEventObject());
8068 wxWindow* parent = dynamic_cast<wxWindow*>(win->GetParent());
8069 if (dynamic_cast<wxNotebook*>(parent)) {
8070 lastSubPage = event.GetSelection();
8071 return;
8072 }
8073 if (dynamic_cast<wxListbook*>(parent)) {
8074 lastSubPage = event.GetSelection();
8075 return;
8076 }
8077 }
8078 }
8079}
8080
8081void options::OnTopNBPageChange(wxNotebookEvent& event) {
8082 DoOnPageChange(event.GetSelection());
8083}
8084
8085void options::DoOnPageChange(size_t page) {
8086 unsigned int i = page;
8087
8088 // Sometimes there is a (-1) page selected.
8089 if (page > 10) return;
8090
8091 lastPage = i;
8092
8093#ifndef __OCPN__ANDROID__
8094 if (0 == i) { // Display
8095 if (m_sconfigSelect_single) m_sconfigSelect_single->Refresh(true);
8096 if (m_sconfigSelect_twovertical) m_sconfigSelect_twovertical->Refresh(true);
8097 }
8098#endif
8099
8100 // User selected Chart Page?
8101 // If so, build the "Charts" page variants
8102 if (1 == i) { // 2 is the index of "Charts" page
8103 k_charts = VISIT_CHARTS;
8104 UpdateChartDirList();
8105 }
8106
8107 else if (m_pageUI == i) { // 5 is the index of "User Interface" page
8108 if (!m_itemLangListBox) return;
8109#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
8110
8111 if (!m_bVisitLang) {
8112 ::wxBeginBusyCursor();
8113
8114 int current_language = plocale_def_lang->GetLanguage();
8115 wxString current_sel = wxLocale::GetLanguageName(current_language);
8116
8117 current_sel = GetOCPNKnownLanguage(g_locale);
8118
8119 int nLang = sizeof(lang_list) / sizeof(int);
8120
8121#ifdef __WXMSW__
8122 // always add us english
8123 m_itemLangListBox->Append(_T("English (U.S.)"));
8124
8125 wxString lang_dir = g_Platform->GetSharedDataDir() + _T("share/locale/");
8126 for (int it = 1; it < nLang; it++) {
8127 if (wxLocale::IsAvailable(lang_list[it])) {
8128 wxLocale ltest(lang_list[it], 0);
8129 ltest.AddCatalog(_T("opencpn"));
8130 if (!ltest.IsLoaded(_T("opencpn"))) continue;
8131
8132 // Defaults
8133 wxString loc_lang_name = wxLocale::GetLanguageName(lang_list[it]);
8134 wxString widgets_lang_name = loc_lang_name;
8135 wxString lang_canonical =
8136 wxLocale::GetLanguageInfo(lang_list[it])->CanonicalName;
8137
8138 // Make opencpn substitutions
8139 wxString lang_suffix;
8140 loc_lang_name = GetOCPNKnownLanguage(lang_canonical, lang_suffix);
8141
8142 // Look explicitely to see if .mo is available
8143 wxString test_dir = lang_dir + lang_suffix;
8144 if (!wxDir::Exists(test_dir))
8145 continue;
8146
8147 m_itemLangListBox->Append(loc_lang_name);
8148 }
8149 }
8150#else
8151 wxArrayString lang_array;
8152
8153 // always add us english
8154 lang_array.Add(_T("en_US"));
8155
8156 for (int it = 0; it < nLang; it++) {
8157 {
8158 wxLog::EnableLogging(
8159 FALSE); // avoid "Cannot set locale to..." log message
8160
8161 wxLocale ltest(lang_list[it], 0);
8162#if wxCHECK_VERSION(2, 9, 0)
8163#ifdef __WXGTK__
8164 ltest.AddCatalogLookupPathPrefix(
8165 wxStandardPaths::Get().GetInstallPrefix() +
8166 _T( "/share/locale" ));
8167#endif
8168#endif
8169 ltest.AddCatalog(_T("opencpn"));
8170
8171 wxLog::EnableLogging(TRUE);
8172
8173 if (ltest.IsLoaded(_T("opencpn"))) {
8174 wxString s0 =
8175 wxLocale::GetLanguageInfo(lang_list[it])->CanonicalName;
8176 wxString sl = wxLocale::GetLanguageName(lang_list[it]);
8177 if (wxNOT_FOUND == lang_array.Index(s0)) lang_array.Add(s0);
8178 }
8179 }
8180 }
8181
8182 for (unsigned int i = 0; i < lang_array.GetCount(); i++) {
8183 // Make opencpn substitutions
8184 wxString loc_lang_name = GetOCPNKnownLanguage(lang_array[i]);
8185 m_itemLangListBox->Append(loc_lang_name);
8186 }
8187#endif
8188
8189 // BUGBUG
8190 // Remember that wxLocale ctor has the effect of changing the system
8191 // locale, including the "C" libraries.
8192 // It should then also happen that the locale should be switched back to
8193 // ocpn initial load setting
8194 // upon the dtor of the above wxLocale instantiations....
8195 // wxWidgets may do so internally, but there seems to be no effect upon
8196 // the system libraries, so that
8197 // functions like strftime() do not revert to the correct locale setting.
8198 // Also, the catalog for the application is not reloaded by the ctor, so
8199 // we must reload them directly
8200 // So as workaround, we reset the locale explicitely.
8201
8202 delete plocale_def_lang;
8203 plocale_def_lang = new wxLocale(current_language);
8204
8205 setlocale(LC_NUMERIC, "C");
8206 plocale_def_lang->AddCatalog(_T("opencpn"));
8207
8208 m_itemLangListBox->SetStringSelection(current_sel);
8209
8210 // Initialize Language tab
8211 const wxLanguageInfo* pli = wxLocale::FindLanguageInfo(g_locale);
8212 if (pli) {
8213 wxString clang = pli->Description;
8214 // m_itemLangListBox->SetValue(clang);
8215 }
8216
8217 m_bVisitLang = TRUE;
8218
8219 ::wxEndBusyCursor();
8220 }
8221#endif
8222 } else if (m_pagePlugins == i) { // 7 is the index of "Plugins" page
8223 // load the disabled plugins finally because the user might want to enable
8224 // them
8225 auto loader = PluginLoader::getInstance();
8226 if (LoadAllPlugIns(false)) {
8227 delete m_pPlugInCtrl;
8228 m_pPlugInCtrl = NULL;
8229 delete m_PluginCatalogMgrPanel;
8230 m_PluginCatalogMgrPanel = NULL;
8231 itemBoxSizerPanelPlugins->Clear();
8232 }
8233
8234 if (!m_pPlugInCtrl) {
8235 // Build the PlugIn Manager Panel
8236 ::wxBeginBusyCursor();
8237
8238 m_pPlugInCtrl =
8239 new PluginListPanel(itemPanelPlugins, ID_PANELPIM, wxDefaultPosition,
8240 wxDefaultSize,
8241 PluginLoader::getInstance()->GetPlugInArray());
8242 m_pPlugInCtrl->SetScrollRate(m_scrollRate, m_scrollRate);
8243 itemBoxSizerPanelPlugins->Add(m_pPlugInCtrl, 01,
8244 wxEXPAND | wxGROW | wxALL, 4);
8245 if (g_pi_manager) g_pi_manager->SetListPanelPtr(m_pPlugInCtrl);
8246
8247 m_PluginCatalogMgrPanel = new CatalogMgrPanel(itemPanelPlugins);
8248 m_PluginCatalogMgrPanel->SetListPanelPtr(m_pPlugInCtrl);
8249
8250 itemBoxSizerPanelPlugins->Add(m_PluginCatalogMgrPanel, 0,
8251 wxEXPAND | wxALL, 4);
8252 itemBoxSizerPanelPlugins->Layout();
8253
8254 // Update the PlugIn page to reflect the state of individual selections
8255 m_pPlugInCtrl->UpdateSelections();
8256
8257 ::wxEndBusyCursor();
8258
8259 wxDEFINE_EVENT(EVT_COMPAT_OS_CHANGE, wxCommandEvent);
8260 GlobalVar<wxString> compat_os(&g_compatOS);
8261 }
8262 k_plugins = TOOLBAR_CHANGED;
8263 }
8264}
8265
8266wxString options::SelectSoundFile() {
8267 wxString sound_dir = g_Platform->GetSharedDataDir();
8268 sound_dir.Append(_T("sounds"));
8269 wxString sel_file;
8270 int response;
8271
8272#ifndef __OCPN__ANDROID__
8273 wxFileDialog* popenDialog = new wxFileDialog(
8274 NULL, _("Select Sound File"), sound_dir, wxEmptyString,
8275 _T("WAV files (*.wav)|*.wav|All files (*.*)|*.*"), wxFD_OPEN);
8276 if (g_bresponsive)
8277 popenDialog = g_Platform->AdjustFileDialogFont(this, popenDialog);
8278
8279 response = popenDialog->ShowModal();
8280 sel_file = popenDialog->GetPath();
8281 delete popenDialog;
8282
8283#else
8284 response =
8285 g_Platform->DoFileSelectorDialog(this, &sel_file, _("Select Sound File"),
8286 sound_dir, wxEmptyString, wxT("*.*"));
8287#endif
8288
8289 if (response == wxID_OK)
8290 return g_Platform->NormalizePath(sel_file);
8291 else
8292 return _T("");
8293}
8294
8295void options::OnButtonSelectSound(wxCommandEvent& event) {
8296 wxString sel_file = SelectSoundFile();
8297
8298 if (!sel_file.IsEmpty()) {
8299 g_sAIS_Alert_Sound_File = g_Platform->NormalizePath(sel_file);
8300 }
8301}
8302
8303void options::OnButtonTestSound(wxCommandEvent& event) {
8304 auto sound = SoundFactory();
8305 auto cmd_sound = dynamic_cast<SystemCmdSound*>(sound);
8306 if (cmd_sound) cmd_sound->SetCmd(g_CmdSoundString.mb_str());
8307 sound->SetFinishedCallback([sound](void*) { delete sound; });
8308 sound->Load(g_sAIS_Alert_Sound_File, g_iSoundDeviceIndex);
8309 sound->Play();
8310}
8311
8312wxString GetOCPNKnownLanguage(wxString lang_canonical, wxString& lang_dir) {
8313 wxString return_string;
8314 wxString dir_suffix;
8315
8316#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
8317
8318 if (lang_canonical == _T("en_US")) {
8319 dir_suffix = _T("en");
8320 return_string = wxString("English (U.S.)", wxConvUTF8);
8321
8322 } else if ((lang_canonical == _T("cs_CZ")) || (lang_canonical == _T("cs"))) {
8323 dir_suffix = _T("cs");
8324 return_string = wxString("Čeština", wxConvUTF8);
8325
8326 } else if ((lang_canonical == _T("da_DK")) || (lang_canonical == _T("da"))) {
8327 dir_suffix = _T("da");
8328 return_string = wxString("Dansk", wxConvUTF8);
8329
8330 } else if ((lang_canonical == _T("de_DE")) || (lang_canonical == _T("de"))) {
8331 dir_suffix = _T("de");
8332 return_string = wxString("Deutsch", wxConvUTF8);
8333
8334 } else if ((lang_canonical == _T("et_EE")) || (lang_canonical == _T("et"))) {
8335 dir_suffix = _T("et");
8336 return_string = wxString("Eesti", wxConvUTF8);
8337
8338 } else if ((lang_canonical == _T("es_ES")) || (lang_canonical == _T("es"))) {
8339 dir_suffix = _T("es");
8340 return_string = wxString("Español", wxConvUTF8);
8341
8342 } else if ((lang_canonical == _T("fr_FR")) || (lang_canonical == _T("fr"))) {
8343 dir_suffix = _T("fr");
8344 return_string = wxString("Français", wxConvUTF8);
8345
8346 } else if ((lang_canonical == _T("it_IT")) || (lang_canonical == _T("it"))) {
8347 dir_suffix = _T("it");
8348 return_string = wxString("Italiano", wxConvUTF8);
8349
8350 } else if ((lang_canonical == _T("nl_NL")) || (lang_canonical == _T("nl"))) {
8351 dir_suffix = _T("nl");
8352 return_string = wxString("Nederlands", wxConvUTF8);
8353
8354 } else if ((lang_canonical == _T("pl_PL")) || (lang_canonical == _T("pl"))) {
8355 dir_suffix = _T("pl");
8356 return_string = wxString("Polski", wxConvUTF8);
8357
8358 } else if ((lang_canonical == _T("pt_PT")) || (lang_canonical == _T("pt"))) {
8359 dir_suffix = _T("pt_PT");
8360 return_string = wxString("Português", wxConvUTF8);
8361
8362 } else if ((lang_canonical == _T("pt_BR")) || (lang_canonical == _T("pt_BR"))) {
8363 dir_suffix = _T("pt_BR");
8364 return_string = wxString("Português Brasileiro", wxConvUTF8);
8365
8366 } else if ((lang_canonical == _T("ru_RU")) || (lang_canonical == _T("ru"))) {
8367 dir_suffix = _T("ru");
8368 return_string = wxString("Русский", wxConvUTF8);
8369
8370 } else if ((lang_canonical == _T("sv_SE")) || (lang_canonical == _T("sv"))) {
8371 dir_suffix = _T("sv");
8372 return_string = wxString("Svenska", wxConvUTF8);
8373
8374 } else if ((lang_canonical == _T("fi_FI")) || (lang_canonical == _T("fi"))) {
8375 dir_suffix = _T("fi_FI");
8376 return_string = wxString("Suomi", wxConvUTF8);
8377
8378 } else if ((lang_canonical == _T("nb_NO")) || (lang_canonical == _T("nb"))) {
8379 dir_suffix = _T("nb_NO");
8380 return_string = wxString("Norsk", wxConvUTF8);
8381
8382 } else if ((lang_canonical == _T("tr_TR")) || (lang_canonical == _T("tr"))) {
8383 dir_suffix = _T("tr_TR");
8384 return_string = wxString("Türkçe", wxConvUTF8);
8385
8386 } else if ((lang_canonical == _T("el_GR")) || (lang_canonical == _T("el"))) {
8387 dir_suffix = _T("el_GR");
8388 return_string = wxString("Ελληνικά", wxConvUTF8);
8389
8390 } else if ((lang_canonical == _T("hu_HU")) || (lang_canonical == _T("hu"))) {
8391 dir_suffix = _T("hu_HU");
8392 return_string = wxString("Magyar", wxConvUTF8);
8393
8394 } else if ((lang_canonical == _T("zh_TW")) || (lang_canonical == _T("zh_TW"))) {
8395 dir_suffix = _T("zh_TW");
8396 return_string = wxString("正體字", wxConvUTF8);
8397
8398 } else if ((lang_canonical == _T("zh_CN")) || (lang_canonical == _T("zh_CN"))) {
8399 dir_suffix = _T("zh_CN");
8400 return_string = wxString("Simplified Chinese", wxConvUTF8);
8401
8402 } else if ((lang_canonical == _T("ca_ES")) || (lang_canonical == _T("ca"))) {
8403 dir_suffix = _T("ca_ES");
8404 return_string = wxString("Catalan", wxConvUTF8);
8405
8406 } else if ((lang_canonical == _T("gl_ES")) || (lang_canonical == _T("gl_ES"))) {
8407 dir_suffix = _T("gl_ES");
8408 return_string = wxString("Galician", wxConvUTF8);
8409
8410 } else if ((lang_canonical == _T("ja_JP")) || (lang_canonical == _T("ja_JP"))) {
8411 dir_suffix = _T("ja_JP");
8412 return_string = wxString("Japanese", wxConvUTF8);
8413
8414 } else if ((lang_canonical == _T("vi_VN")) || (lang_canonical == _T("vi_VN"))) {
8415 dir_suffix = _T("vi_VN");
8416 return_string = wxString("Vietnamese", wxConvUTF8);
8417
8418 } else {
8419 dir_suffix = lang_canonical;
8420 const wxLanguageInfo* info = wxLocale::FindLanguageInfo(lang_canonical);
8421 if(info)
8422 return_string = info->Description;
8423 else
8424 return_string = lang_canonical;
8425 }
8426
8427 lang_dir = dir_suffix;
8428#endif
8429 return return_string;
8430}
8431
8432
8433wxString GetOCPNKnownLanguage(const wxString lang_canonical) {
8434 wxString lang_dir;
8435 return GetOCPNKnownLanguage(lang_canonical, lang_dir);
8436}
8437
8438ChartGroupArray* ChartGroupsUI::CloneChartGroupArray(ChartGroupArray* s) {
8439 ChartGroupArray* d = new ChartGroupArray;
8440 for (unsigned int i = 0; i < s->GetCount(); i++) {
8441 ChartGroup* psg = s->Item(i);
8442 ChartGroup* pdg = new ChartGroup;
8443 pdg->m_group_name = psg->m_group_name;
8444 pdg->m_element_array.reserve(psg->m_element_array.size());
8445
8446 for (auto& elem : psg->m_element_array)
8447 pdg->m_element_array.push_back(elem);
8448
8449 d->Add(pdg);
8450 }
8451 return d;
8452}
8453
8454void ChartGroupsUI::EmptyChartGroupArray(ChartGroupArray* s) {
8455 if (!s) return;
8456
8457 // ChartGroups don't need anything special for delete, just calling the
8458 // destructor is enough.
8459 WX_CLEAR_ARRAY(*s);
8460}
8461
8462// Chart Groups dialog implementation
8463BEGIN_EVENT_TABLE(ChartGroupsUI, wxEvtHandler)
8464EVT_TREE_ITEM_EXPANDED(wxID_TREECTRL, ChartGroupsUI::OnNodeExpanded)
8465EVT_NOTEBOOK_PAGE_CHANGED(
8466 wxID_ANY,
8467 ChartGroupsUI::OnGroupPageChange) // This should work under Windows :-(
8468END_EVENT_TABLE()
8469
8470ChartGroupsUI::ChartGroupsUI(wxWindow* parent) {
8471 m_GroupSelectedPage = -1;
8472 m_pActiveChartsTree = 0;
8473 pParent = parent;
8474 lastSelectedCtl = NULL;
8475 allAvailableCtl = NULL;
8476 defaultAllCtl = NULL;
8477 iFont = NULL;
8478 m_pAddButton = NULL;
8479 m_pRemoveButton = NULL;
8480 m_pDeleteGroupButton = NULL;
8481 m_pNewGroupButton = NULL;
8482 m_pGroupArray = NULL;
8483 m_GroupNB = NULL;
8484 modified = false;
8485 m_UIcomplete = false;
8486 m_treespopulated = false;
8487 dialogFont = GetOCPNScaledFont(_("Dialog"));
8488}
8489
8490ChartGroupsUI::~ChartGroupsUI(void) {
8491 m_DirCtrlArray.Clear();
8492 m_GroupNB->Disconnect(
8493 wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
8494 wxNotebookEventHandler(ChartGroupsUI::OnGroupPageChange), NULL, this);
8495
8496 delete iFont;
8497}
8498
8499void ChartGroupsUI::SetInitialSettings(void) {
8500 m_settingscomplete = FALSE;
8501 m_treespopulated = FALSE;
8502}
8503
8504void ChartGroupsUI::PopulateTrees(void) {
8505 // Fill in the "Active chart" tree control
8506 // from the options dialog "Active Chart Directories" list
8507 wxArrayString dir_array;
8508 int nDir = m_db_dirs.GetCount();
8509 for (int i = 0; i < nDir; i++) {
8510 wxString dirname = m_db_dirs[i].fullpath;
8511 if (!dirname.IsEmpty()) dir_array.Add(dirname);
8512 }
8513
8514 PopulateTreeCtrl(allAvailableCtl->GetTreeCtrl(), dir_array, wxColour(0, 0, 0),
8515 dialogFont);
8516 m_pActiveChartsTree = allAvailableCtl->GetTreeCtrl();
8517
8518 // Fill in the Page 0 tree control
8519 // from the options dialog "Active Chart Directories" list
8520 wxArrayString dir_array0;
8521 int nDir0 = m_db_dirs.GetCount();
8522 for (int i = 0; i < nDir0; i++) {
8523 wxString dirname = m_db_dirs[i].fullpath;
8524 if (!dirname.IsEmpty()) dir_array0.Add(dirname);
8525 }
8526 PopulateTreeCtrl(defaultAllCtl->GetTreeCtrl(), dir_array0,
8527 wxColour(128, 128, 128), iFont);
8528}
8529
8530void ChartGroupsUI::CompleteInitialSettings(void) {
8531 PopulateTrees();
8532
8533 BuildNotebookPages(m_pGroupArray);
8534
8535 m_panel->GetSizer()->Layout();
8536
8537 m_settingscomplete = TRUE;
8538 m_treespopulated = TRUE;
8539}
8540
8541void ChartGroupsUI::PopulateTreeCtrl(wxTreeCtrl* ptc,
8542 const wxArrayString& dir_array,
8543 const wxColour& col, wxFont* pFont) {
8544 ptc->DeleteAllItems();
8545
8546 wxDirItemData* rootData = new wxDirItemData(_T("Dummy"), _T("Dummy"), TRUE);
8547 wxString rootName;
8548 rootName = _T("Dummy");
8549 wxTreeItemId m_rootId = ptc->AddRoot(rootName, 3, -1, rootData);
8550 ptc->SetItemHasChildren(m_rootId);
8551
8552 wxString dirname;
8553 int nDir = dir_array.GetCount();
8554 for (int i = 0; i < nDir; i++) {
8555 wxString dirname = dir_array[i];
8556 if (!dirname.IsEmpty()) {
8557 wxDirItemData* dir_item = new wxDirItemData(dirname, dirname, TRUE);
8558 wxTreeItemId id = ptc->AppendItem(m_rootId, dirname, 0, -1, dir_item);
8559
8560 // wxWidgets bug workaraound (Ticket #10085)
8561 ptc->SetItemText(id, dirname);
8562 if (pFont) ptc->SetItemFont(id, *pFont);
8563
8564 // On MacOS, use the default system dialog color, to honor Dark mode.
8565#ifndef __WXOSX__
8566 ptc->SetItemTextColour(id, col);
8567#endif
8568 ptc->SetItemHasChildren(id);
8569 }
8570 }
8571}
8572
8573void ChartGroupsUI::OnInsertChartItem(wxCommandEvent& event) {
8574 wxString insert_candidate = allAvailableCtl->GetPath();
8575 if (!insert_candidate.IsEmpty()) {
8576 if (m_DirCtrlArray.GetCount()) {
8577 wxGenericDirCtrl* pDirCtrl = (m_DirCtrlArray[m_GroupSelectedPage]);
8578 ChartGroup* pGroup = m_pGroupArray->Item(m_GroupSelectedPage - 1);
8579 if (pDirCtrl) {
8580 wxTreeCtrl* ptree = pDirCtrl->GetTreeCtrl();
8581 if (ptree) {
8582 if (ptree->IsEmpty()) {
8583 wxDirItemData* rootData =
8584 new wxDirItemData(wxEmptyString, wxEmptyString, TRUE);
8585 wxString rootName = _T("Dummy");
8586 wxTreeItemId rootId = ptree->AddRoot(rootName, 3, -1, rootData);
8587
8588 ptree->SetItemHasChildren(rootId);
8589 }
8590
8591 wxTreeItemId root_Id = ptree->GetRootItem();
8592 wxDirItemData* dir_item =
8593 new wxDirItemData(insert_candidate, insert_candidate, TRUE);
8594 wxTreeItemId id =
8595 ptree->AppendItem(root_Id, insert_candidate, 0, -1, dir_item);
8596 if (wxDir::Exists(insert_candidate)) ptree->SetItemHasChildren(id);
8597 }
8598
8599 pGroup->m_element_array.push_back({insert_candidate});
8600 }
8601 }
8602 }
8603 modified = TRUE;
8604 allAvailableCtl->GetTreeCtrl()->UnselectAll();
8605 m_pAddButton->Disable();
8606
8607 wxGenericDirCtrl* pDirCtrl = (m_DirCtrlArray[m_GroupSelectedPage]);
8608 if (pDirCtrl) {
8609 wxTreeCtrl* ptree = pDirCtrl->GetTreeCtrl();
8610 if (ptree) ptree->Refresh();
8611 }
8612}
8613
8614void ChartGroupsUI::OnRemoveChartItem(wxCommandEvent& event) {
8615 if (m_DirCtrlArray.GetCount()) {
8616 wxGenericDirCtrl* pDirCtrl = (m_DirCtrlArray[m_GroupSelectedPage]);
8617 ChartGroup* pGroup = m_pGroupArray->Item(m_GroupSelectedPage - 1);
8618
8619 if (pDirCtrl) {
8620 wxString sel_item = pDirCtrl->GetPath();
8621
8622 wxTreeCtrl* ptree = pDirCtrl->GetTreeCtrl();
8623 if (ptree && ptree->GetCount()) {
8624 wxTreeItemId id = ptree->GetSelection();
8625 lastDeletedItem = id;
8626 if (id.IsOk()) {
8627 wxString branch_adder;
8628 int group_item_index =
8629 FindGroupBranch(pGroup, ptree, id, &branch_adder);
8630 if (group_item_index >= 0) {
8631 ChartGroupElement &pelement =
8632 pGroup->m_element_array[group_item_index];
8633 bool b_duplicate = FALSE;
8634 for (unsigned int k = 0; k < pelement.m_missing_name_array.size();
8635 k++) {
8636 if (pelement.m_missing_name_array[k] == sel_item) {
8637 b_duplicate = TRUE;
8638 break;
8639 }
8640 }
8641 if (!b_duplicate) {
8642 pelement.m_missing_name_array.Add(sel_item);
8643 }
8644
8645 // Special case...
8646 // If the selection is a branch itself,
8647 // Then delete from the tree, and delete from the group
8648 if (branch_adder == _T("")) {
8649 ptree->Delete(id);
8650 pGroup->m_element_array.erase(pGroup->m_element_array.begin() +
8651 group_item_index);
8652 } else {
8653 ptree->SetItemTextColour(id, wxColour(128, 128, 128));
8654 // what about toggle back?
8655 }
8656 }
8657 }
8658 modified = TRUE;
8659 lastSelectedCtl->Unselect();
8660 lastSelectedCtl = 0;
8661 m_pRemoveButton->Disable();
8662
8663 wxGenericDirCtrl* pDirCtrl = (m_DirCtrlArray[m_GroupSelectedPage]);
8664 if (pDirCtrl) {
8665 wxTreeCtrl* ptree = pDirCtrl->GetTreeCtrl();
8666 if (ptree) ptree->Refresh();
8667 }
8668 }
8669 }
8670 }
8671 event.Skip();
8672}
8673
8674void ChartGroupsUI::OnGroupPageChange(wxNotebookEvent& event) {
8675 m_GroupSelectedPage = event.GetSelection();
8676 allAvailableCtl->GetTreeCtrl()->UnselectAll();
8677 if (lastSelectedCtl) {
8678 lastSelectedCtl->UnselectAll();
8679 lastSelectedCtl = 0;
8680 }
8681 m_pRemoveButton->Disable();
8682 m_pAddButton->Disable();
8683
8684 // Disable delete option for "All Charts" group
8685 if (m_GroupSelectedPage == 0) {
8686 if (m_pDeleteGroupButton) m_pDeleteGroupButton->Disable();
8687 } else {
8688 if (m_pDeleteGroupButton) m_pDeleteGroupButton->Enable();
8689 }
8690}
8691
8692void ChartGroupsUI::OnAvailableSelection(wxTreeEvent& event) {
8693 wxObject* evtObj = event.GetEventObject();
8694 if (allAvailableCtl && (evtObj == allAvailableCtl->GetTreeCtrl())) {
8695 wxTreeItemId item = allAvailableCtl->GetTreeCtrl()->GetSelection();
8696 if (item && item.IsOk() && m_GroupSelectedPage > 0) {
8697 m_pAddButton->Enable();
8698 } else {
8699 m_pAddButton->Disable();
8700 }
8701 } else {
8702 lastSelectedCtl = dynamic_cast<wxTreeCtrl*>(evtObj);
8703 if (!lastSelectedCtl) goto out;
8704 wxTreeItemId item = lastSelectedCtl->GetSelection();
8705 if (item && item.IsOk() && m_GroupSelectedPage > 0) {
8706 // We need a trick for wxGTK here, since it gives us a Selection
8707 // event with the just deleted element after OnRemoveChartItem()
8708 wxGenericDirCtrl* dirCtrl =
8709 dynamic_cast<wxGenericDirCtrl*>(lastSelectedCtl->GetParent());
8710 if (!dirCtrl) goto out;
8711 wxString itemPath = dirCtrl->GetPath();
8712 if (!itemPath.IsEmpty()) m_pRemoveButton->Enable();
8713 } else {
8714 m_pRemoveButton->Disable();
8715 }
8716 }
8717
8718out:
8719 event.Skip();
8720}
8721
8722void ChartGroupsUI::OnNewGroup(wxCommandEvent& event) {
8723 wxTextEntryDialog* pd = new wxTextEntryDialog();
8724 wxFont* qFont = GetOCPNScaledFont(_("Dialog"));
8725 pd->SetFont(*qFont);
8726
8727 pd->Create(m_panel, _("Enter Group Name"), _("New Chart Group"));
8728
8729#ifdef __OCPN__ANDROID__
8730 androidDisableRotation();
8731#endif
8732
8733 if (pd->ShowModal() == wxID_OK) {
8734 if (pd->GetValue().Length()) {
8735 AddEmptyGroupPage(pd->GetValue());
8736 ChartGroup* pGroup = new ChartGroup;
8737 pGroup->m_group_name = pd->GetValue();
8738 m_pGroupArray->Add(pGroup);
8739
8740 m_GroupSelectedPage =
8741 m_GroupNB->GetPageCount() - 1; // select the new page
8742 m_GroupNB->ChangeSelection(m_GroupSelectedPage);
8743 m_pDeleteGroupButton->Enable();
8744 modified = TRUE;
8745 }
8746 }
8747 delete pd;
8748
8749#ifdef __OCPN__ANDROID__
8750 androidEnableRotation();
8751#endif
8752}
8753
8754void ChartGroupsUI::OnDeleteGroup(wxCommandEvent& event) {
8755 if (0 != m_GroupSelectedPage) {
8756 m_DirCtrlArray.RemoveAt(m_GroupSelectedPage);
8757 if (m_pGroupArray) m_pGroupArray->RemoveAt(m_GroupSelectedPage - 1);
8758 m_GroupNB->DeletePage(m_GroupSelectedPage);
8759 modified = TRUE;
8760 }
8761 if (m_GroupSelectedPage <= 0) {
8762 m_pAddButton->Disable();
8763 m_pDeleteGroupButton->Disable();
8764 }
8765}
8766
8767int ChartGroupsUI::FindGroupBranch(ChartGroup* pGroup, wxTreeCtrl* ptree,
8768 wxTreeItemId item, wxString* pbranch_adder) {
8769 wxString branch_name;
8770 wxString branch_adder;
8771
8772 wxTreeItemId current_node = item;
8773 while (current_node.IsOk()) {
8774 wxTreeItemId parent_node = ptree->GetItemParent(current_node);
8775 if (!parent_node) break;
8776
8777 if (parent_node == ptree->GetRootItem()) {
8778 branch_name = ptree->GetItemText(current_node);
8779 break;
8780 }
8781
8782 branch_adder.Prepend(ptree->GetItemText(current_node));
8783 branch_adder.Prepend(wxString(wxFILE_SEP_PATH));
8784
8785 current_node = ptree->GetItemParent(current_node);
8786 }
8787
8788 // Find the index and element pointer of the target branch in the Group
8789 unsigned int target_item_index = -1;
8790
8791 for (unsigned int i = 0; i < pGroup->m_element_array.size(); i++) {
8792 const wxString &target = pGroup->m_element_array[i].m_element_name;
8793 if (branch_name == target) {
8794 target_item_index = i;
8795 break;
8796 }
8797 }
8798
8799 if (pbranch_adder) *pbranch_adder = branch_adder;
8800
8801 return target_item_index;
8802}
8803
8804void ChartGroupsUI::OnNodeExpanded(wxTreeEvent& event) {
8805 wxTreeItemId node = event.GetItem();
8806
8807 if (m_GroupSelectedPage <= 0) return;
8808 wxGenericDirCtrl* pDirCtrl = (m_DirCtrlArray[m_GroupSelectedPage]);
8809 ChartGroup* pGroup = m_pGroupArray->Item(m_GroupSelectedPage - 1);
8810 if (!pDirCtrl) return;
8811
8812 wxTreeCtrl* ptree = pDirCtrl->GetTreeCtrl();
8813 wxString branch_adder;
8814 int target_item_index = FindGroupBranch(pGroup, ptree, node, &branch_adder);
8815 if (target_item_index < 0) return;
8816 const ChartGroupElement& target_element =
8817 pGroup->m_element_array[target_item_index];
8818 const wxString &branch_name = target_element.m_element_name;
8819
8820 // Walk the children of the expanded node, marking any items which appear in
8821 // the "missing" list
8822 if (!target_element.m_missing_name_array.GetCount()) return;
8823 wxString full_root = branch_name;
8824 full_root += branch_adder;
8825 full_root += wxString(wxFILE_SEP_PATH);
8826
8827 wxTreeItemIdValue cookie;
8828 wxTreeItemId child = ptree->GetFirstChild(node, cookie);
8829 while (child.IsOk()) {
8830 wxString target_string = full_root;
8831 target_string += ptree->GetItemText(child);
8832
8833 for (unsigned int k = 0;
8834 k < target_element.m_missing_name_array.GetCount(); k++) {
8835 if (target_element.m_missing_name_array[k] == target_string) {
8836 ptree->SetItemTextColour(child, wxColour(128, 128, 128));
8837 break;
8838 }
8839 }
8840 child = ptree->GetNextChild(node, cookie);
8841 }
8842}
8843
8844void ChartGroupsUI::BuildNotebookPages(ChartGroupArray* pGroupArray) {
8845 ClearGroupPages();
8846
8847 for (unsigned int i = 0; i < pGroupArray->GetCount(); i++) {
8848 ChartGroup* pGroup = pGroupArray->Item(i);
8849 wxTreeCtrl* ptc = AddEmptyGroupPage(pGroup->m_group_name);
8850
8851 wxString itemname;
8852 int nItems = pGroup->m_element_array.size();
8853 for (int i = 0; i < nItems; i++) {
8854 const wxString &itemname = pGroup->m_element_array[i].m_element_name;
8855 if (!itemname.IsEmpty()) {
8856 wxDirItemData* dir_item = new wxDirItemData(itemname, itemname, TRUE);
8857 wxTreeItemId id =
8858 ptc->AppendItem(ptc->GetRootItem(), itemname, 0, -1, dir_item);
8859
8860 if (wxDir::Exists(itemname)) ptc->SetItemHasChildren(id);
8861 }
8862 }
8863 }
8864}
8865
8866wxTreeCtrl* ChartGroupsUI::AddEmptyGroupPage(const wxString& label) {
8867 wxGenericDirCtrl* GroupDirCtl =
8868 new wxGenericDirCtrl(m_GroupNB, wxID_ANY, _T("TESTDIR"));
8869 m_GroupNB->AddPage(GroupDirCtl, label);
8870
8871 wxTreeCtrl* ptree = GroupDirCtl->GetTreeCtrl();
8872 ptree->DeleteAllItems();
8873
8874 wxDirItemData* rootData =
8875 new wxDirItemData(wxEmptyString, wxEmptyString, TRUE);
8876 wxString rootName = _T("Dummy");
8877 wxTreeItemId rootId = ptree->AddRoot(rootName, 3, -1, rootData);
8878 ptree->SetItemHasChildren(rootId);
8879
8880 m_DirCtrlArray.Add(GroupDirCtl);
8881
8882 return ptree;
8883}
8884
8885void ChartGroupsUI::ClearGroupPages() {
8886 if (m_GroupNB->GetPageCount() == 0) return;
8887
8888 for (unsigned int i = m_GroupNB->GetPageCount() - 1; i > 0; i--) {
8889 m_DirCtrlArray.RemoveAt(i);
8890 m_GroupNB->DeletePage(i);
8891 }
8892}
8893
8894void options::OnInsertTideDataLocation(wxCommandEvent& event) {
8895 wxString sel_file;
8896 int response = wxID_CANCEL;
8897
8898#ifndef __OCPN__ANDROID__
8899 wxFileDialog* popenDialog = new wxFileDialog(
8900 NULL, _("Select Tide/Current Data"), g_TCData_Dir, wxT(""),
8901 wxT("Tide/Current Data files (*.IDX; *.TCD)|*.IDX;*.idx;*.TCD;*.tcd|All ")
8902 wxT("files (*.*)|*.*"),
8903 wxFD_OPEN);
8904 if (g_bresponsive)
8905 popenDialog = g_Platform->AdjustFileDialogFont(this, popenDialog);
8906
8907 response = popenDialog->ShowModal();
8908 sel_file = popenDialog->GetPath();
8909 delete popenDialog;
8910
8911#else
8912 wxString path;
8913 response = g_Platform->DoFileSelectorDialog(this, &path,
8914 _("Select Tide/Current Data"),
8915 g_TCData_Dir, _T(""), wxT("*.*"));
8916 sel_file = path;
8917#endif
8918
8919 if (response == wxID_OK) {
8920 wxListItem li;
8921 int id = tcDataSelected->GetItemCount(); // next index
8922 li.SetId(id);
8923 long idx = tcDataSelected->InsertItem(li);
8924 tcDataSelected->SetItem(id, 0, g_Platform->NormalizePath(sel_file));
8925
8926 // Record the currently selected directory for later use
8927 wxFileName fn(sel_file);
8928 wxString data_dir = fn.GetPath();
8929 g_TCData_Dir = g_Platform->NormalizePath(data_dir);
8930 }
8931}
8932
8933void options::OnRemoveTideDataLocation(wxCommandEvent& event) {
8934 long item = -1;
8935 for (;;) {
8936 item = tcDataSelected->GetNextItem(item, wxLIST_NEXT_ALL,
8937 wxLIST_STATE_SELECTED);
8938 if (item == -1) break;
8939 tcDataSelected->DeleteItem(item);
8940 item = -1; // Restart
8941 }
8942}
8943
8944
8945// OpenGLOptionsDlg
8946enum { ID_BUTTON_REBUILD, ID_BUTTON_CLEAR };
8947
8948#ifdef ocpnUSE_GL
8949BEGIN_EVENT_TABLE(OpenGLOptionsDlg, wxDialog)
8950EVT_BUTTON(ID_BUTTON_REBUILD, OpenGLOptionsDlg::OnButtonRebuild)
8951EVT_BUTTON(ID_BUTTON_CLEAR, OpenGLOptionsDlg::OnButtonClear)
8952END_EVENT_TABLE()
8953
8954OpenGLOptionsDlg::OpenGLOptionsDlg(wxWindow* parent)
8955 : wxDialog(parent, wxID_ANY, _T( "OpenGL Options" ), wxDefaultPosition,
8956 wxDefaultSize,
8957 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER
8958#ifdef __WXOSX__
8959 | wxSTAY_ON_TOP
8960#endif
8961 ),
8962 m_brebuild_cache(FALSE) {
8963
8964 wxFont* dialogFont = GetOCPNScaledFont(_("Dialog"));
8965 SetFont(*dialogFont);
8966
8967 wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
8968 wxFlexGridSizer* flexSizer = new wxFlexGridSizer(2);
8969
8970 m_cbTextureCompression =
8971 new wxCheckBox(this, wxID_ANY,
8972 g_bGLexpert ? _("Texture Compression")
8973 : _("Texture Compression with Caching"));
8974 m_cbTextureCompressionCaching =
8975 new wxCheckBox(this, wxID_ANY, _("Texture Compression Caching"));
8976 m_memorySize =
8977 new wxStaticText(this, wxID_ANY, _("Texture Memory Size (MB)"));
8978 m_sTextureMemorySize = new wxSpinCtrl(this);
8979 m_sTextureMemorySize->SetRange(1, 16384);
8980 m_cacheSize =
8981 new wxStaticText(this, wxID_ANY, _("Size: ") + GetTextureCacheSize());
8982 wxButton* btnRebuild =
8983 new wxButton(this, ID_BUTTON_REBUILD, _("Rebuild Texture Cache"));
8984 wxButton* btnClear =
8985 new wxButton(this, ID_BUTTON_CLEAR, _("Clear Texture Cache"));
8986 btnRebuild->Enable(g_GLOptions.m_bTextureCompressionCaching);
8987 if (!g_bopengl || g_raster_format == GL_RGB) btnRebuild->Disable();
8988 btnClear->Enable(g_GLOptions.m_bTextureCompressionCaching);
8989 m_cbShowFPS = new wxCheckBox(this, wxID_ANY, _("Show FPS"));
8990 m_cbPolygonSmoothing = new wxCheckBox(this, wxID_ANY, _("Polygon Smoothing"));
8991 m_cbLineSmoothing = new wxCheckBox(this, wxID_ANY, _("Line Smoothing"));
8992 m_cbSoftwareGL =
8993 new wxCheckBox(this, wxID_ANY, _("Software OpenGL (restart OpenCPN)"));
8994 m_cbUseAcceleratedPanning =
8995 new wxCheckBox(this, wxID_ANY, _("Use Accelerated Panning"));
8996
8997 flexSizer->Add(new wxStaticText(this, wxID_ANY, _("Texture Settings")), 0,
8998 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 5);
8999 flexSizer->Add(m_cbTextureCompression, 0, wxALL | wxEXPAND, 5);
9000 flexSizer->AddSpacer(0);
9001 flexSizer->Add(m_cbTextureCompressionCaching, 0, wxALL | wxEXPAND, 5);
9002 flexSizer->Add(m_memorySize, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 5);
9003 flexSizer->Add(m_sTextureMemorySize, 0, wxALL | wxEXPAND, 5);
9004 flexSizer->Add(new wxStaticText(this, wxID_ANY, _("Texture Cache")), 0,
9005 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 5);
9006 flexSizer->Add(m_cacheSize, 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL, 5);
9007 flexSizer->AddSpacer(0);
9008 flexSizer->Add(btnRebuild, 0, wxALL | wxEXPAND, 5);
9009 flexSizer->AddSpacer(0);
9010 flexSizer->Add(btnClear, 0, wxALL | wxEXPAND, 5);
9011 flexSizer->Add(new wxStaticText(this, wxID_ANY, _("Miscellaneous")), 0,
9012 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 5);
9013 flexSizer->Add(m_cbPolygonSmoothing, 0, wxALL | wxEXPAND, 5);
9014 flexSizer->AddSpacer(0);
9015 flexSizer->Add(m_cbLineSmoothing, 0, wxALL | wxEXPAND, 5);
9016 flexSizer->AddSpacer(0);
9017 flexSizer->Add(m_cbShowFPS, 0, wxALL | wxEXPAND, 5);
9018 flexSizer->AddSpacer(0);
9019 flexSizer->Add(m_cbSoftwareGL, 0, wxALL | wxEXPAND, 5);
9020 flexSizer->AddSpacer(0);
9021 flexSizer->Add(m_cbUseAcceleratedPanning, 0, wxALL | wxEXPAND, 5);
9022 flexSizer->AddGrowableCol(1);
9023 mainSizer->Add(flexSizer, 0, wxALL | wxEXPAND, 5);
9024
9025 wxStdDialogButtonSizer* btnSizer = new wxStdDialogButtonSizer();
9026 btnSizer->AddButton(new wxButton(this, wxID_OK));
9027 btnSizer->AddButton(new wxButton(this, wxID_CANCEL, _("Cancel")));
9028 btnSizer->Realize();
9029
9030 mainSizer->AddStretchSpacer();
9031 mainSizer->Add(btnSizer, 0, wxALL | wxEXPAND, 5);
9032
9033 Populate();
9034
9035 SetSizer(mainSizer);
9036 mainSizer->SetSizeHints(this);
9037 Centre();
9038}
9039
9040bool OpenGLOptionsDlg::GetAcceleratedPanning(void) const {
9041 return m_cbUseAcceleratedPanning->GetValue();
9042}
9043
9044bool OpenGLOptionsDlg::GetTextureCompression(void) const {
9045 return m_cbTextureCompression->GetValue();
9046}
9047
9048bool OpenGLOptionsDlg::GetPolygonSmoothing(void) const {
9049 return m_cbPolygonSmoothing->GetValue();
9050}
9051
9052bool OpenGLOptionsDlg::GetLineSmoothing(void) const {
9053 return m_cbLineSmoothing->GetValue();
9054}
9055
9056bool OpenGLOptionsDlg::GetShowFPS(void) const {
9057 return m_cbShowFPS->GetValue();
9058}
9059
9060bool OpenGLOptionsDlg::GetSoftwareGL(void) const {
9061 return m_cbSoftwareGL->GetValue();
9062}
9063
9064bool OpenGLOptionsDlg::GetTextureCompressionCaching(void) const {
9065 return m_cbTextureCompressionCaching->GetValue();
9066}
9067
9068bool OpenGLOptionsDlg::GetRebuildCache(void) const { return m_brebuild_cache; }
9069
9070int OpenGLOptionsDlg::GetTextureMemorySize(void) const {
9071 return m_sTextureMemorySize->GetValue();
9072}
9073
9074void OpenGLOptionsDlg::Populate(void) {
9075
9076 m_cbTextureCompression->SetValue(g_GLOptions.m_bTextureCompression);
9077 /* disable caching if unsupported */
9078// if (b_glEntryPointsSet && !s_glCompressedTexImage2D) {
9079// g_GLOptions.m_bTextureCompressionCaching = FALSE;
9080// m_cbTextureCompression->Disable();
9081// m_cbTextureCompression->SetValue(FALSE);
9082// }
9083
9084 m_cbTextureCompressionCaching->Show(g_bGLexpert);
9085 m_memorySize->Show(g_bGLexpert);
9086 m_sTextureMemorySize->Show(g_bGLexpert);
9087 if (g_bGLexpert) {
9088 m_cbTextureCompressionCaching->SetValue(
9089 g_GLOptions.m_bTextureCompressionCaching);
9090 m_sTextureMemorySize->SetValue(g_GLOptions.m_iTextureMemorySize);
9091 }
9092 m_cbShowFPS->SetValue(g_bShowFPS);
9093 m_cbPolygonSmoothing->SetValue(g_GLOptions.m_GLPolygonSmoothing);
9094 m_cbLineSmoothing->SetValue(g_GLOptions.m_GLLineSmoothing);
9095
9096#if defined(__UNIX__) && !defined(__OCPN__ANDROID__) && !defined(__WXOSX__)
9097 if (gFrame->GetPrimaryCanvas()->GetglCanvas()) {
9098 if (gFrame->GetPrimaryCanvas()
9099 ->GetglCanvas()
9100 ->GetVersionString()
9101 .Upper()
9102 .Find(_T( "MESA" )) != wxNOT_FOUND)
9103 m_cbSoftwareGL->SetValue(g_bSoftwareGL);
9104 }
9105#else
9106 m_cbSoftwareGL->Hide();
9107#endif
9108
9109 wxFont* dialogFont = GetOCPNScaledFont(_("Dialog"));
9110 SetFont(*dialogFont);
9111
9112 if (g_bGLexpert) {
9113 if (gFrame->GetPrimaryCanvas()->GetglCanvas()) {
9114 if (gFrame->GetPrimaryCanvas()->GetglCanvas()->CanAcceleratePanning()) {
9115 m_cbUseAcceleratedPanning->Enable();
9116 m_cbUseAcceleratedPanning->SetValue(
9117 g_GLOptions.m_bUseAcceleratedPanning);
9118 } else {
9119 m_cbUseAcceleratedPanning->SetValue(FALSE);
9120 m_cbUseAcceleratedPanning->Disable();
9121 }
9122 } else {
9123 m_cbUseAcceleratedPanning->SetValue(g_GLOptions.m_bUseAcceleratedPanning);
9124 }
9125 } else {
9126 m_cbUseAcceleratedPanning->SetValue(g_GLOptions.m_bUseAcceleratedPanning);
9127 m_cbUseAcceleratedPanning->Disable();
9128 }
9129}
9130
9131void OpenGLOptionsDlg::OnButtonRebuild(wxCommandEvent& event) {
9132 if (g_GLOptions.m_bTextureCompressionCaching) {
9133 m_brebuild_cache = TRUE;
9134 EndModal(wxID_CANCEL);
9135 }
9136}
9137
9138void OpenGLOptionsDlg::OnButtonClear(wxCommandEvent& event) {
9139 if (g_bopengl && g_glTextureManager) {
9140 ::wxBeginBusyCursor();
9141 g_glTextureManager->ClearAllRasterTextures();
9142
9143 wxString path = g_Platform->GetPrivateDataDir();
9144 appendOSDirSlash(&path);
9145 path.append(_T("raster_texture_cache"));
9146
9147 if (::wxDirExists(path)) {
9148 wxArrayString files;
9149 size_t nfiles = wxDir::GetAllFiles(path, &files);
9150 for (unsigned int i = 0; i < files.GetCount(); i++)
9151 ::wxRemoveFile(files[i]);
9152 }
9153
9154 m_cacheSize->SetLabel(_("Size: ") + GetTextureCacheSize());
9155 ::wxEndBusyCursor();
9156 }
9157}
9158
9159wxString OpenGLOptionsDlg::GetTextureCacheSize(void) {
9160 wxString path = g_Platform->GetPrivateDataDir();
9161 appendOSDirSlash(&path);
9162 path.append(_T("raster_texture_cache"));
9163 long long total = 0;
9164
9165 if (::wxDirExists(path)) {
9166 wxArrayString files;
9167 size_t nfiles = wxDir::GetAllFiles(path, &files);
9168 for (unsigned int i = 0; i < files.GetCount(); i++)
9169 total += wxFile(files[i]).Length();
9170 }
9171 double mb = total / (1024.0 * 1024.0);
9172 if (mb < 10000.0) return wxString::Format(_T( "%.1f MB" ), mb);
9173 mb = mb / 1024.0;
9174 return wxString::Format(_T( "%.1f GB" ), mb);
9175}
9176
9177//-------------------------------------------------------------------------------------------------
9178// CanvasConfig selection panel
9179//-------------------------------------------------------------------------------------------------
9180
9181BEGIN_EVENT_TABLE(CanvasConfigSelect, wxPanel)
9182EVT_PAINT(CanvasConfigSelect::OnPaint)
9183END_EVENT_TABLE()
9184
9185CanvasConfigSelect::CanvasConfigSelect(wxWindow* parent, options* parentOptions,
9186 wxWindowID id, wxBitmap& bmp,
9187 const wxPoint& pos, const wxSize& size)
9188 : wxPanel(parent, id, pos, size, wxBORDER_NONE) {
9189 m_parentOptions = parentOptions;
9190 m_bmpNormal = bmp;
9191 m_borderWidth = 5;
9192 SetSelected(false);
9193
9194 int refHeight = GetCharHeight();
9195 // SetMinSize(wxSize(-1, 5 * refHeight));
9196 SetMinSize(wxSize(bmp.GetSize().x + m_borderWidth * 2,
9197 bmp.GetSize().y + m_borderWidth * 2));
9198
9199 Connect(wxEVT_LEFT_DOWN,
9200 wxMouseEventHandler(CanvasConfigSelect::OnMouseSelected), NULL, this);
9201}
9202
9203CanvasConfigSelect::~CanvasConfigSelect() {}
9204
9205void CanvasConfigSelect::OnMouseSelected(wxMouseEvent& event) {
9206 if (!m_bSelected) {
9207 SetSelected(true);
9208 } else {
9209 SetSelected(false);
9210 }
9211 if (m_parentOptions)
9212 m_parentOptions->OnCanvasConfigSelectClick(GetId(), GetSelected());
9213}
9214
9215void CanvasConfigSelect::SetSelected(bool selected) {
9216 m_bSelected = selected;
9217 wxColour colour;
9218
9219 if (selected) {
9220 GetGlobalColor(_T("UIBCK"), &colour);
9221 m_boxColour = colour;
9222 } else {
9223 GetGlobalColor(_T("DILG0"), &colour);
9224 m_boxColour = colour;
9225 }
9226
9227 Refresh(true);
9228}
9229
9230void CanvasConfigSelect::OnPaint(wxPaintEvent& event) {
9231 int width, height;
9232 GetSize(&width, &height);
9233 wxPaintDC dc(this);
9234
9235 dc.SetBackground(*wxLIGHT_GREY);
9236
9237 dc.SetPen(*wxTRANSPARENT_PEN);
9238 dc.SetBrush(wxBrush(GetBackgroundColour()));
9239 dc.DrawRectangle(GetVirtualSize());
9240
9241 wxColour c;
9242
9243 if (m_bSelected) {
9244 dc.SetBrush(wxBrush(m_boxColour));
9245
9246 GetGlobalColor(_T ( "UITX1" ), &c);
9247 dc.SetPen(wxPen(wxColor(0xCE, 0xD5, 0xD6), 3));
9248
9249 dc.DrawRoundedRectangle(0, 0, width - 1, height - 1, height / 10);
9250 } else {
9251 dc.SetBrush(wxBrush(m_boxColour));
9252
9253 GetGlobalColor(_T ( "UITX1" ), &c);
9254 dc.SetPen(wxPen(wxColor(0xCE, 0xD5, 0xD6), 3));
9255
9256 dc.DrawRoundedRectangle(0, 0, width - 1, height - 1, height / 10);
9257 }
9258
9259 dc.DrawBitmap(m_bmpNormal, m_borderWidth, m_borderWidth, false);
9260}
9261
9262#endif // ocpnUSE_GL
Wrapper for global variable, supports notification events when value changes.
static double ui_to_config(int slider_pos)
Convert a slider scale 1-100 value to configuration value 1.02..3.0.
Definition: navutil.h:126