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