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