OpenCPN Partial API docs
Loading...
Searching...
No Matches
MarkInfo.cpp
1/**************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: MarkProperties Support
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 "config.h"
26
27// For compilers that support precompilation, includes "wx/wx.h".
28#include <wx/wxprec.h>
29
30#ifndef WX_PRECOMP
31#include <wx/wx.h>
32#endif
33
34#include <wx/datetime.h>
35#include <wx/clipbrd.h>
36#include <wx/print.h>
37#include <wx/printdlg.h>
38#include <wx/stattext.h>
39#include <wx/clrpicker.h>
40#include <wx/bmpbuttn.h>
41
42#include "chcanv.h"
43#include "gui_lib.h"
44#include "MarkInfo.h"
45#include "model/georef.h"
46#include "model/navutil_base.h"
47#include "model/own_ship.h"
48#include "model/position_parser.h"
49#include "model/route.h"
50#include "model/routeman.h"
51#include "model/select.h"
52#include "navutil.h" // for Route
53#include "ocpn_frame.h"
54#include "OCPNPlatform.h"
55#include "pluginmanager.h"
56#include "routemanagerdialog.h"
57#include "RoutePropDlgImpl.h"
58#include "styles.h"
59#include "model/svg_utils.h"
60#include "TCWin.h"
61#include "ui_utils.h"
62#include "model/navobj_db.h"
63
64#ifdef __ANDROID__
65#include "androidUTIL.h"
66#include <QtWidgets/QScroller>
67#endif
68
69MarkInfoDlg* g_pMarkInfoDialog;
70
71extern TCMgr* ptcmgr;
72extern MyConfig* pConfig;
73extern Routeman* g_pRouteMan;
74extern RouteManagerDialog* pRouteManagerDialog;
75extern RoutePropDlgImpl* pRoutePropDialog;
76extern ocpnStyle::StyleManager* g_StyleManager;
77
78extern MyFrame* gFrame;
79extern OCPNPlatform* g_Platform;
80extern wxString g_default_wp_icon;
81
82// Global print data, to remember settings during the session
83
84// Global page setup data
85
86extern float g_MarkScaleFactorExp;
87
88extern MarkInfoDlg* g_pMarkInfoDialog;
89
90#include <wx/arrimpl.cpp>
91WX_DEFINE_OBJARRAY(ArrayOfBitmaps);
92
93#define EXTENDED_PROP_PAGE 2 // Index of the extended properties page
94
95OCPNIconCombo::OCPNIconCombo(wxWindow* parent, wxWindowID id,
96 const wxString& value, const wxPoint& pos,
97 const wxSize& size, int n,
98 const wxString choices[], long style,
99 const wxValidator& validator, const wxString& name)
100 : wxOwnerDrawnComboBox(parent, id, value, pos, size, n, choices, style,
101 validator, name) {
102 double fontHeight =
103 GetFont().GetPointSize() / g_Platform->getFontPointsperPixel();
104 itemHeight = (int)wxRound(fontHeight);
105}
106
107OCPNIconCombo::~OCPNIconCombo() {}
108
109void OCPNIconCombo::OnDrawItem(wxDC& dc, const wxRect& rect, int item,
110 int flags) const {
111 int offset_x = bmpArray[item].GetWidth();
112 int bmpHeight = bmpArray[item].GetHeight();
113 dc.DrawBitmap(bmpArray[item], rect.x, rect.y + (rect.height - bmpHeight) / 2,
114 true);
115
116 if (flags & wxODCB_PAINTING_CONTROL) {
117 wxString text = GetValue();
118 int margin_x = 2;
119
120#if wxCHECK_VERSION(2, 9, 0)
121 if (ShouldUseHintText()) {
122 text = GetHint();
123 wxColour col = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
124 dc.SetTextForeground(col);
125 }
126
127 margin_x = GetMargins().x;
128#endif
129
130 dc.DrawText(text, rect.x + margin_x + offset_x,
131 (rect.height - dc.GetCharHeight()) / 2 + rect.y);
132 } else {
133 dc.DrawText(GetVListBoxComboPopup()->GetString(item), rect.x + 2 + offset_x,
134 (rect.height - dc.GetCharHeight()) / 2 + rect.y);
135 }
136}
137
138wxCoord OCPNIconCombo::OnMeasureItem(size_t item) const {
139 int bmpHeight = bmpArray[item].GetHeight();
140
141 return wxMax(itemHeight, bmpHeight);
142}
143
144wxCoord OCPNIconCombo::OnMeasureItemWidth(size_t item) const { return -1; }
145
146int OCPNIconCombo::Append(const wxString& item, wxBitmap bmp) {
147 bmpArray.Add(bmp);
148 int idx = wxOwnerDrawnComboBox::Append(item);
149
150 return idx;
151}
152
153void OCPNIconCombo::Clear(void) {
154 wxOwnerDrawnComboBox::Clear();
155 bmpArray.Clear();
156}
157
158//-------------------------------------------------------------------------------
159//
160// Mark Properties Dialog Implementation
161//
162//-------------------------------------------------------------------------------
167// DEFINE_EVENT_TYPE(EVT_LLCHANGE) // events from LatLonTextCtrl
168const wxEventType EVT_LLCHANGE = wxNewEventType();
169//------------------------------------------------------------------------------
170// LatLonTextCtrl Window Implementation
171//------------------------------------------------------------------------------
172BEGIN_EVENT_TABLE(LatLonTextCtrl, wxWindow)
173END_EVENT_TABLE()
174
175// constructor
176LatLonTextCtrl::LatLonTextCtrl(wxWindow* parent, wxWindowID id,
177 const wxString& value, const wxPoint& pos,
178 const wxSize& size, long style,
179 const wxValidator& validator,
180 const wxString& name)
181 : wxTextCtrl(parent, id, value, pos, size, style, validator, name) {
182 m_pParentEventHandler = parent->GetEventHandler();
183}
184
185void LatLonTextCtrl::OnKillFocus(wxFocusEvent& event) {
186 // Send an event to the Parent Dialog
187 wxCommandEvent up_event(EVT_LLCHANGE, GetId());
188 up_event.SetEventObject((wxObject*)this);
189 m_pParentEventHandler->AddPendingEvent(up_event);
190}
191
192//-------------------------------------------------------------------------------
193//
194// Mark Information Dialog Implementation
195//
196//-------------------------------------------------------------------------------
197BEGIN_EVENT_TABLE(MarkInfoDlg, DIALOG_PARENT)
198EVT_BUTTON(wxID_OK, MarkInfoDlg::OnMarkInfoOKClick)
199EVT_BUTTON(wxID_CANCEL, MarkInfoDlg::OnMarkInfoCancelClick)
200EVT_BUTTON(ID_BTN_DESC_BASIC, MarkInfoDlg::OnExtDescriptionClick)
201EVT_BUTTON(ID_DEFAULT, MarkInfoDlg::DefautlBtnClicked)
202EVT_BUTTON(ID_BTN_SHOW_TIDES, MarkInfoDlg::ShowTidesBtnClicked)
203EVT_COMBOBOX(ID_BITMAPCOMBOCTRL, MarkInfoDlg::OnBitmapCombClick)
204EVT_CHECKBOX(ID_CHECKBOX_SCAMIN_VIS, MarkInfoDlg::OnSelectScaMinExt)
205EVT_TEXT(ID_DESCR_CTR_DESC, MarkInfoDlg::OnDescChangedExt)
206EVT_TEXT(ID_DESCR_CTR_BASIC, MarkInfoDlg::OnDescChangedBasic)
207EVT_TEXT(ID_LATCTRL, MarkInfoDlg::OnPositionCtlUpdated)
208EVT_TEXT(ID_LONCTRL, MarkInfoDlg::OnPositionCtlUpdated)
209EVT_CHOICE(ID_WPT_RANGERINGS_NO, MarkInfoDlg::OnWptRangeRingsNoChange)
210// the HTML listbox's events
211EVT_HTML_LINK_CLICKED(wxID_ANY, MarkInfoDlg::OnHtmlLinkClicked)
212EVT_COMMAND(wxID_ANY, EVT_LAYOUT_RESIZE, MarkInfoDlg::OnLayoutResize)
213EVT_CLOSE(MarkInfoDlg::OnClose)
214
215// EVT_CHOICE( ID_WAYPOINTRANGERINGS, MarkInfoDef::OnWaypointRangeRingSelect )
216END_EVENT_TABLE()
217
218MarkInfoDlg::MarkInfoDlg(wxWindow* parent, wxWindowID id, const wxString& title,
219 const wxPoint& pos, const wxSize& size, long style) {
220 DIALOG_PARENT::Create(parent, id, title, pos, size, style);
221
222 wxFont* qFont = GetOCPNScaledFont(_("Dialog"));
223 SetFont(*qFont);
224 int metric = GetCharHeight();
225
226#ifdef __ANDROID__
227 // Set Dialog Font by custom crafted Qt Stylesheet.
228 wxString wqs = getFontQtStylesheet(qFont);
229 wxCharBuffer sbuf = wqs.ToUTF8();
230 QString qsb = QString(sbuf.data());
231 QString qsbq = getQtStyleSheet(); // basic scrollbars, etc
232 this->GetHandle()->setStyleSheet(qsb + qsbq); // Concatenated style sheets
233 wxScreenDC sdc;
234 if (sdc.IsOk()) sdc.GetTextExtent("W", NULL, &metric, NULL, NULL, qFont);
235#endif
236 Create();
237 m_pMyLinkList = NULL;
238 SetColorScheme((ColorScheme)0);
239 m_pRoutePoint = NULL;
240 m_SaveDefaultDlg = NULL;
241 CenterOnScreen();
242
243#ifdef __WXOSX__
244 Connect(wxEVT_ACTIVATE, wxActivateEventHandler(MarkInfoDlg::OnActivate), NULL,
245 this);
246#endif
247}
248
249void MarkInfoDlg::OnActivate(wxActivateEvent& event) {
250 auto pWin = dynamic_cast<DIALOG_PARENT*>(event.GetEventObject());
251 long int style = pWin->GetWindowStyle();
252 if (event.GetActive())
253 pWin->SetWindowStyle(style | wxSTAY_ON_TOP);
254 else
255 pWin->SetWindowStyle(style ^ wxSTAY_ON_TOP);
256}
257
258void MarkInfoDlg::initialize_images(void) {
259 wxString iconDir = g_Platform->GetSharedDataDir() + "uidata/MUI_flat/";
260 _img_MUI_settings_svg = LoadSVG(iconDir + "MUI_settings.svg",
261 2 * GetCharHeight(), 2 * GetCharHeight());
262
263 ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();
264 wxBitmap tide = style->GetIcon("tidesml");
265 wxImage tide1 = tide.ConvertToImage();
266 wxImage tide1s = tide1.Scale(m_sizeMetric * 3 / 2, m_sizeMetric * 3 / 2,
267 wxIMAGE_QUALITY_HIGH);
268 m_bmTide = wxBitmap(tide1s);
269
270 return;
271}
272
273void MarkInfoDlg::Create() {
274 wxFont* qFont = GetOCPNScaledFont(_("Dialog"));
275 SetFont(*qFont);
276 m_sizeMetric = GetCharHeight();
277
278#ifdef __ANDROID__
279 // Set Dialog Font by custom crafted Qt Stylesheet.
280
281 wxString wqs = getFontQtStylesheet(qFont);
282 wxCharBuffer sbuf = wqs.ToUTF8();
283 QString qsb = QString(sbuf.data());
284
285 QString qsbq = getAdjustedDialogStyleSheet(); // basic scrollbars, etc
286
287 this->GetHandle()->setStyleSheet(qsb + qsbq); // Concatenated style sheets
288
289 wxScreenDC sdc;
290 if (sdc.IsOk())
291 sdc.GetTextExtent("W", NULL, &m_sizeMetric, NULL, NULL, qFont);
292
293#endif
294
295 initialize_images();
296
297 wxBoxSizer* bSizer1;
298 bSizer1 = new wxBoxSizer(wxVERTICAL);
299 SetSizer(bSizer1);
300 bSizer1->SetSizeHints(this); // set size hints to honour minimum size
301
302 // Notebook with fixed width tabs
303 m_notebookProperties = new wxNotebook(this, wxID_ANY, wxDefaultPosition,
304 wxDefaultSize, wxNB_FIXEDWIDTH);
305
306 m_panelBasicProperties = new wxScrolledWindow(
307 m_notebookProperties, wxID_ANY, wxDefaultPosition, wxDefaultSize,
308 wxHSCROLL | wxVSCROLL | wxTAB_TRAVERSAL);
309#ifdef __ANDROID__
310 m_panelBasicProperties->GetHandle()->setStyleSheet(
311 getAdjustedDialogStyleSheet());
312#endif
313
314 // Basic panel
315 m_panelBasicProperties->SetScrollRate(0, 2);
316 m_notebookProperties->AddPage(m_panelBasicProperties, _("Basic"), true);
317 bSizerBasicProperties = new wxBoxSizer(wxVERTICAL);
318 m_panelBasicProperties->SetSizer(bSizerBasicProperties);
319
320 // Layer notification
321 m_staticTextLayer = new wxStaticText(
322 m_panelBasicProperties, wxID_ANY,
323 _("This waypoint is part of a layer and can't be edited"),
324 wxDefaultPosition, wxDefaultSize, 0);
325 m_staticTextLayer->Enable(false);
326 bSizerBasicProperties->Add(m_staticTextLayer, 0, wxALL, 5);
327
328 // Basic properties grid layout
329 wxPanel* props_panel = new wxPanel(m_panelBasicProperties);
330 FormGrid* props_sizer = new FormGrid(this);
331 props_panel->SetSizer(props_sizer);
332 bSizerBasicProperties->Add(props_panel, 0, wxALL | wxEXPAND, 16);
333 int label_size = m_sizeMetric * 4;
334
335 // Name property
336 m_textName = new TextField(props_panel, _("Name"));
337
338 // Show name checkbox
339 wxStaticText* name_cb_label =
340 new wxStaticText(props_panel, wxID_ANY, _("Show waypoint name"));
341 m_checkBoxShowName =
342 new wxCheckBox(props_panel, wxID_ANY, wxEmptyString, wxDefaultPosition,
343 wxDefaultSize, wxALIGN_CENTER_VERTICAL);
344 m_checkBoxShowName->Bind(wxEVT_CHECKBOX,
345 &MarkInfoDlg::OnShowWaypointNameSelectBasic, this);
346 props_sizer->Add(name_cb_label, 0, wxALIGN_TOP);
347 props_sizer->Add(m_checkBoxShowName, 0, wxEXPAND);
348
349 // Icon property (with icon scaling)
350 int icon_size = m_sizeMetric * 2;
351 icon_size = wxMax(icon_size, (32 * g_MarkScaleFactorExp) + 4);
352 m_bcomboBoxIcon =
353 new OCPNIconCombo(props_panel, wxID_ANY, _("Combo!"), wxDefaultPosition,
354 wxDefaultSize, 0, NULL, wxCB_READONLY);
355 m_bcomboBoxIcon->SetPopupMaxHeight(::wxGetDisplaySize().y / 2);
356 m_bcomboBoxIcon->SetMinSize(wxSize(-1, icon_size));
357
358 wxStaticText* icon_label = new wxStaticText(props_panel, wxID_ANY, _("Icon"));
359 icon_label->SetMinSize(wxSize(label_size, -1));
360 props_sizer->Add(icon_label, 0, wxALIGN_CENTER_VERTICAL);
361 props_sizer->Add(m_bcomboBoxIcon, 0, wxEXPAND);
362
363 // Lat/lon properties
364 m_textLatitude = new TextField(props_panel, _("Latitude"));
365 m_textLongitude = new TextField(props_panel, _("Longitude"));
366 props_sizer->Fit(props_panel);
367
368 // Description box
369 wxStaticBox* desc_box =
370 new wxStaticBox(m_panelBasicProperties, wxID_ANY, _("Description"));
371 wxStaticBoxSizer* desc_sizer = new wxStaticBoxSizer(desc_box, wxHORIZONTAL);
372 bSizerBasicProperties->Add(desc_sizer, 1, wxALL | wxEXPAND, 8);
373 m_textDescription = new wxTextCtrl(
374 m_panelBasicProperties, ID_DESCR_CTR_BASIC, wxEmptyString,
375 wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);
376 m_textDescription->SetMinSize(wxSize(-1, 80));
377 desc_sizer->Add(m_textDescription, 1, wxEXPAND);
378
379 // Description expand button
380 m_buttonExtDescription =
381 new wxButton(m_panelBasicProperties, ID_BTN_DESC_BASIC, "...",
382 wxDefaultPosition, wxSize(GetCharHeight() * 15 / 10, -1), 0);
383 desc_sizer->Add(m_buttonExtDescription, 0, wxEXPAND);
384
385 // Links box
386 wxStaticBox* links_box =
387 new wxStaticBox(m_panelBasicProperties, wxID_ANY, _("Links"));
388 wxStaticBoxSizer* links_sizer = new wxStaticBoxSizer(links_box, wxHORIZONTAL);
389 bSizerBasicProperties->Add(links_sizer, 1, wxALL | wxEXPAND, 8);
390
391#ifndef __ANDROID__ // wxSimpleHtmlListBox is broken on Android....
392 m_htmlList = new wxSimpleHtmlListBox(m_panelBasicProperties, wxID_ANY,
393 wxDefaultPosition, wxDefaultSize, 0);
394 links_sizer->Add(m_htmlList, 1, wxEXPAND);
395#else
396
397 m_scrolledWindowLinks =
398 new wxScrolledWindow(m_panelBasicProperties, wxID_ANY, wxDefaultPosition,
399 wxSize(-1, 100), wxHSCROLL | wxVSCROLL);
400 m_scrolledWindowLinks->SetMinSize(wxSize(-1, 80));
401 m_scrolledWindowLinks->SetScrollRate(2, 2);
402 links_sizer->Add(m_scrolledWindowLinks, 1, wxEXPAND);
403
404 bSizerLinks = new wxBoxSizer(wxVERTICAL);
405 m_scrolledWindowLinks->SetSizer(bSizerLinks);
406
407 m_menuLink = new wxMenu();
408 wxMenuItem* m_menuItemDelete;
409 m_menuItemDelete = new wxMenuItem(m_menuLink, wxID_ANY, wxString(_("Delete")),
410 wxEmptyString, wxITEM_NORMAL);
411 m_menuLink->Append(m_menuItemDelete);
412
413 wxMenuItem* m_menuItemEdit;
414 m_menuItemEdit = new wxMenuItem(m_menuLink, wxID_ANY, wxString(_("Edit")),
415 wxEmptyString, wxITEM_NORMAL);
416 m_menuLink->Append(m_menuItemEdit);
417
418 wxMenuItem* m_menuItemAdd;
419 m_menuItemAdd = new wxMenuItem(m_menuLink, wxID_ANY, wxString(_("Add new")),
420 wxEmptyString, wxITEM_NORMAL);
421 m_menuLink->Append(m_menuItemAdd);
422
423 wxBoxSizer* bSizer9 = new wxBoxSizer(wxHORIZONTAL);
424
425 m_buttonAddLink =
426 new wxButton(m_panelBasicProperties, wxID_ANY, _("Add new"),
427 wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
428 bSizer9->Add(m_buttonAddLink, 0, wxALL, 5);
429
430 m_buttonAddLink->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
431 wxCommandEventHandler(MarkInfoDlg::OnAddLink), NULL,
432 this);
433
434 links_sizer->Add(bSizer9, 0, wxEXPAND, 5);
435
436#endif
437
438 m_panelDescription =
439 new wxPanel(m_notebookProperties, wxID_ANY, wxDefaultPosition,
440 wxDefaultSize, wxTAB_TRAVERSAL);
441 wxBoxSizer* bSizer15;
442 bSizer15 = new wxBoxSizer(wxVERTICAL);
443
444 m_textCtrlExtDescription =
445 new wxTextCtrl(m_panelDescription, ID_DESCR_CTR_DESC, wxEmptyString,
446 wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
447 bSizer15->Add(m_textCtrlExtDescription, 1, wxALL | wxEXPAND, 5);
448
449 m_panelDescription->SetSizer(bSizer15);
450 m_notebookProperties->AddPage(m_panelDescription, _("Description"), false);
451
454
455 m_panelExtendedProperties = new wxScrolledWindow(
456 m_notebookProperties, wxID_ANY, wxDefaultPosition, wxDefaultSize,
457 wxHSCROLL | wxVSCROLL | wxTAB_TRAVERSAL);
458#ifdef __ANDROID__
459 m_panelExtendedProperties->GetHandle()->setStyleSheet(
460 getAdjustedDialogStyleSheet());
461#endif
462
463 m_panelExtendedProperties->SetScrollRate(0, 2);
464
465 wxBoxSizer* fSizerExtProperties = new wxBoxSizer(wxVERTICAL);
466 m_panelExtendedProperties->SetSizer(fSizerExtProperties);
467 m_notebookProperties->AddPage(m_panelExtendedProperties, _("Extended"),
468 false);
469
470 sbSizerExtProperties = new wxStaticBoxSizer(
471 wxVERTICAL, m_panelExtendedProperties, _("Extended Properties"));
472 wxFlexGridSizer* gbSizerInnerExtProperties = new wxFlexGridSizer(3, 0, 0);
473 gbSizerInnerExtProperties->AddGrowableCol(2);
474 gbSizerInnerExtProperties->SetFlexibleDirection(wxBOTH);
475 gbSizerInnerExtProperties->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
476
477 m_checkBoxVisible = new wxCheckBox(sbSizerExtProperties->GetStaticBox(),
478 ID_CHECKBOX_VIS_EXT, wxEmptyString);
479 gbSizerInnerExtProperties->Add(m_checkBoxVisible);
480 wxStaticText* m_staticTextVisible = new wxStaticText(
481 sbSizerExtProperties->GetStaticBox(), wxID_ANY, _("Show on chart"));
482 gbSizerInnerExtProperties->Add(m_staticTextVisible);
483 gbSizerInnerExtProperties->Add(0, 0, 1, wxEXPAND, 0);
484
485 m_checkBoxScaMin = new wxCheckBox(sbSizerExtProperties->GetStaticBox(),
486 ID_CHECKBOX_SCAMIN_VIS, wxEmptyString);
487 gbSizerInnerExtProperties->Add(m_checkBoxScaMin, 0, wxALIGN_CENTRE_VERTICAL,
488 0);
489 m_staticTextScaMin = new wxStaticText(sbSizerExtProperties->GetStaticBox(),
490 wxID_ANY, _("Show at scale > 1 :"));
491 gbSizerInnerExtProperties->Add(m_staticTextScaMin, 0, wxALIGN_CENTRE_VERTICAL,
492 0);
493 m_textScaMin = new wxTextCtrl(sbSizerExtProperties->GetStaticBox(), wxID_ANY);
494 gbSizerInnerExtProperties->Add(m_textScaMin, 0, wxALL | wxEXPAND, 5);
495
496 m_checkBoxShowNameExt = new wxCheckBox(sbSizerExtProperties->GetStaticBox(),
497 wxID_ANY, wxEmptyString);
498 m_checkBoxShowNameExt->Bind(wxEVT_CHECKBOX,
499 &MarkInfoDlg::OnShowWaypointNameSelectExt, this);
500 gbSizerInnerExtProperties->Add(m_checkBoxShowNameExt);
501 m_staticTextShowNameExt = new wxStaticText(
502 sbSizerExtProperties->GetStaticBox(), wxID_ANY, _("Show waypoint name"));
503
504 gbSizerInnerExtProperties->Add(m_staticTextShowNameExt);
505 gbSizerInnerExtProperties->Add(0, 0, 1, wxEXPAND, 0);
506
507 sbRangeRingsExtProperties = new wxStaticBoxSizer(
508 wxVERTICAL, sbSizerExtProperties->GetStaticBox(), _("Range rings"));
509 wxFlexGridSizer* gbRRExtProperties = new wxFlexGridSizer(4, 0, 0);
510 gbRRExtProperties->AddGrowableCol(0);
511 gbRRExtProperties->AddGrowableCol(1);
512 gbRRExtProperties->AddGrowableCol(3);
513 m_staticTextRR1 = new wxStaticText(sbSizerExtProperties->GetStaticBox(),
514 wxID_ANY, _("Number"));
515 gbRRExtProperties->Add(m_staticTextRR1, 0, wxLEFT, 5);
516 m_staticTextRR2 = new wxStaticText(sbSizerExtProperties->GetStaticBox(),
517 wxID_ANY, _("Distance"));
518 gbRRExtProperties->Add(m_staticTextRR2, 0, wxLEFT, 5);
519 gbRRExtProperties->Add(0, 0, 1, wxEXPAND, 5); // a spacer
520 m_staticTextRR4 = new wxStaticText(sbSizerExtProperties->GetStaticBox(),
521 wxID_ANY, _("Color"));
522 gbRRExtProperties->Add(m_staticTextRR4, 0, wxLEFT, 5);
523
524 wxString rrAlt[] = {_("None"), _T( "1" ), _T( "2" ), _T( "3" ),
525 _T( "4" ), _T( "5" ), _T( "6" ), _T( "7" ),
526 _T( "8" ), _T( "9" ), _T( "10" )};
527 m_ChoiceWaypointRangeRingsNumber =
528 new wxChoice(sbSizerExtProperties->GetStaticBox(), ID_WPT_RANGERINGS_NO,
529 wxDefaultPosition, wxDefaultSize, 11, rrAlt);
530
531 gbRRExtProperties->Add(m_ChoiceWaypointRangeRingsNumber, 0, wxALL | wxEXPAND,
532 5);
533 m_textWaypointRangeRingsStep =
534 new wxTextCtrl(sbSizerExtProperties->GetStaticBox(), wxID_ANY, _("0.05"),
535 wxDefaultPosition, wxDefaultSize, 0);
536 gbRRExtProperties->Add(m_textWaypointRangeRingsStep, 0, wxALL | wxEXPAND, 5);
537
538 wxString pDistUnitsStrings[] = {_("NMi"), _("km")};
539 m_RangeRingUnits =
540 new wxChoice(sbSizerExtProperties->GetStaticBox(), wxID_ANY,
541 wxDefaultPosition, wxDefaultSize, 2, pDistUnitsStrings);
542 gbRRExtProperties->Add(m_RangeRingUnits, 0, wxALIGN_CENTRE_VERTICAL, 0);
543
544 m_PickColor = new wxColourPickerCtrl(sbSizerExtProperties->GetStaticBox(),
545 wxID_ANY, wxColour(0, 0, 0),
546 wxDefaultPosition, wxDefaultSize, 0);
547 gbRRExtProperties->Add(m_PickColor, 0, wxALL | wxEXPAND, 5);
548 sbRangeRingsExtProperties->Add(
549 gbRRExtProperties, 1,
550 wxLEFT | wxTOP | wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP, 5);
551
552 sbSizerExtProperties->GetStaticBox()->Layout();
553
554 wxFlexGridSizer* gbSizerInnerExtProperties2 = new wxFlexGridSizer(2, 0, 0);
555 gbSizerInnerExtProperties2->AddGrowableCol(1);
556
557 m_staticTextGuid =
558 new wxStaticText(sbSizerExtProperties->GetStaticBox(), wxID_ANY,
559 _("GUID"), wxDefaultPosition, wxDefaultSize, 0);
560 gbSizerInnerExtProperties2->Add(m_staticTextGuid, 0, wxALIGN_CENTRE_VERTICAL,
561 0);
562 m_textCtrlGuid = new wxTextCtrl(sbSizerExtProperties->GetStaticBox(),
563 wxID_ANY, wxEmptyString, wxDefaultPosition,
564 wxDefaultSize, wxTE_READONLY);
565 m_textCtrlGuid->SetEditable(false);
566 gbSizerInnerExtProperties2->Add(m_textCtrlGuid, 0, wxALL | wxEXPAND, 5);
567
568 wxFlexGridSizer* gbSizerInnerExtProperties1 = new wxFlexGridSizer(3, 0, 0);
569 gbSizerInnerExtProperties1->AddGrowableCol(1);
570
571 m_staticTextTideStation =
572 new wxStaticText(sbSizerExtProperties->GetStaticBox(), wxID_ANY,
573 _("Tide Station"), wxDefaultPosition, wxDefaultSize, 0);
574 gbSizerInnerExtProperties1->Add(m_staticTextTideStation, 0,
575 wxALIGN_CENTRE_VERTICAL, 5);
576
577#ifdef __ANDROID__
578 m_choiceTideChoices.Add(" ");
579 m_comboBoxTideStation =
580 new wxChoice(sbSizerExtProperties->GetStaticBox(), wxID_ANY,
581 wxDefaultPosition, wxDefaultSize, m_choiceTideChoices);
582
583 gbSizerInnerExtProperties1->Add(
584 m_comboBoxTideStation, 0, wxALL | wxEXPAND | wxALIGN_CENTRE_VERTICAL, 5);
585
586#else
587 m_comboBoxTideStation = new wxComboBox(
588 sbSizerExtProperties->GetStaticBox(), wxID_ANY, wxEmptyString,
589 wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
590 gbSizerInnerExtProperties1->Add(
591 m_comboBoxTideStation, 0, wxALL | wxEXPAND | wxALIGN_CENTRE_VERTICAL, 5);
592#endif
593 m_comboBoxTideStation->SetToolTip(
594 _("Associate this waypoint with a tide station to quickly access tide "
595 "predictions. Select from nearby stations or leave empty for no "
596 "association."));
597
598 m_buttonShowTides = new wxBitmapButton(
599 sbSizerExtProperties->GetStaticBox(), ID_BTN_SHOW_TIDES, m_bmTide,
600 wxDefaultPosition, m_bmTide.GetSize(), 0);
601 gbSizerInnerExtProperties1->Add(m_buttonShowTides, 0,
602 wxALL | wxALIGN_CENTRE_VERTICAL, 5);
603
604 m_staticTextArrivalRadius = new wxStaticText(
605 sbSizerExtProperties->GetStaticBox(), wxID_ANY, _("Arrival Radius"));
606 gbSizerInnerExtProperties1->Add(m_staticTextArrivalRadius, 0,
607 wxALIGN_CENTRE_VERTICAL, 0);
608 m_textArrivalRadius =
609 new wxTextCtrl(sbSizerExtProperties->GetStaticBox(), wxID_ANY,
610 wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
611 m_textArrivalRadius->SetToolTip(
612 _("Distance from the waypoint at which OpenCPN will consider the "
613 "waypoint reached. Used for automatic waypoint advancement during "
614 "active navigation."));
615 gbSizerInnerExtProperties1->Add(m_textArrivalRadius, 0, wxALL | wxEXPAND, 5);
616 m_staticTextArrivalUnits =
617 new wxStaticText(sbSizerExtProperties->GetStaticBox(), wxID_ANY,
618 wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
619 gbSizerInnerExtProperties1->Add(m_staticTextArrivalUnits, 0,
620 wxALIGN_CENTRE_VERTICAL, 0);
621
622 m_staticTextPlSpeed =
623 new wxStaticText(sbSizerExtProperties->GetStaticBox(), wxID_ANY,
624 _("Planned Speed"), wxDefaultPosition, wxDefaultSize, 0);
625 gbSizerInnerExtProperties1->Add(m_staticTextPlSpeed, 0,
626 wxALIGN_CENTRE_VERTICAL, 0);
628 new wxTextCtrl(sbSizerExtProperties->GetStaticBox(), wxID_ANY,
629 wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
630 m_textCtrlPlSpeed->SetToolTip(_(
631 "Enter the planned vessel speed for the leg FOLLOWING this waypoint. "
632 "This speed is used when traveling FROM this waypoint TO the next "
633 "waypoint in the route. The value is used to calculate estimated time "
634 "of arrival at the next waypoint based on the ETD from this waypoint.\n\n"
635 "If left blank, the route's default speed will be used for this leg. "
636 "Individual waypoint speeds override the route-level speed setting."));
637 gbSizerInnerExtProperties1->Add(m_textCtrlPlSpeed, 0, wxALL | wxEXPAND, 5);
638 m_staticTextPlSpeedUnits =
639 new wxStaticText(sbSizerExtProperties->GetStaticBox(), wxID_ANY,
640 getUsrSpeedUnit(), wxDefaultPosition, wxDefaultSize, 0);
641 gbSizerInnerExtProperties1->Add(m_staticTextPlSpeedUnits, 0,
642 wxALIGN_CENTRE_VERTICAL, 0);
643
644 // The value of m_staticTextEtd is updated in UpdateProperties() based on
645 // the date/time format specified in the "Options" dialog.
646 m_staticTextEtd = new wxStaticText(sbSizerExtProperties->GetStaticBox(),
647 wxID_ANY, _("ETD"));
648 gbSizerInnerExtProperties1->Add(m_staticTextEtd, 0, wxALIGN_CENTRE_VERTICAL,
649 0);
650 wxBoxSizer* bsTimestamp = new wxBoxSizer(wxHORIZONTAL);
651 m_cbEtdPresent = new wxCheckBox(sbSizerExtProperties->GetStaticBox(),
652 wxID_ANY, wxEmptyString);
653 m_cbEtdPresent->SetToolTip(
654 _("Enable to manually set a planned departure time (ETD) for this "
655 "waypoint.\n"
656 "When checked, the specified date and time will be used instead of the "
657 "automatically calculated ETD. This affects ETA calculations for "
658 "subsequent waypoints in the route."));
659 bsTimestamp->Add(m_cbEtdPresent, 0, wxALL | wxEXPAND, 5);
660 m_EtdDatePickerCtrl = new wxDatePickerCtrl(
661 sbSizerExtProperties->GetStaticBox(), ID_ETA_DATEPICKERCTRL,
662 wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxDP_DEFAULT,
663 wxDefaultValidator);
664 m_EtdDatePickerCtrl->SetToolTip(_(
665 "Select the planned departure date (ETD) for this waypoint.\nUsed "
666 "together with the time control to calculate arrival times at subsequent "
667 "waypoints.\nETD information is only used for route planning "
668 "and does not affect navigation."));
669 bsTimestamp->Add(m_EtdDatePickerCtrl, 0, wxALL | wxEXPAND, 5);
670
671#ifdef __WXGTK__
673 new TimeCtrl(sbSizerExtProperties->GetStaticBox(), ID_ETA_TIMEPICKERCTRL,
674 wxDefaultDateTime, wxDefaultPosition, wxDefaultSize);
675#else
676 m_EtdTimePickerCtrl = new wxTimePickerCtrl(
677 sbSizerExtProperties->GetStaticBox(), ID_ETA_TIMEPICKERCTRL,
678 wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxDP_DEFAULT,
679 wxDefaultValidator);
680#endif
681
682 bsTimestamp->Add(m_EtdTimePickerCtrl, 0, wxALL | wxEXPAND, 5);
683 gbSizerInnerExtProperties1->Add(bsTimestamp, 0, wxEXPAND, 0);
684 sbSizerExtProperties->Add(gbSizerInnerExtProperties, 0, wxALL | wxEXPAND, 5);
685 sbSizerExtProperties->Add(sbRangeRingsExtProperties, 0, wxALL | wxEXPAND, 5);
686 sbSizerExtProperties->Add(gbSizerInnerExtProperties2, 0, wxALL | wxEXPAND, 5);
687 sbSizerExtProperties->Add(gbSizerInnerExtProperties1, 0, wxALL | wxEXPAND, 5);
688
689 fSizerExtProperties->Add(sbSizerExtProperties, 1, wxALL | wxEXPAND);
690
691 //-----------------
692 bSizer1->Add(m_notebookProperties, 1, wxEXPAND);
693
694 wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
695 bSizer1->Add(btnSizer, 0, wxEXPAND, 0);
696
697 DefaultsBtn =
698 new wxBitmapButton(this, ID_DEFAULT, _img_MUI_settings_svg,
699 wxDefaultPosition, _img_MUI_settings_svg.GetSize(), 0);
700 btnSizer->Add(DefaultsBtn, 0, wxALL | wxALIGN_LEFT | wxALIGN_BOTTOM, 5);
701 btnSizer->Add(0, 0, 1, wxEXPAND); // spacer
702
703 m_sdbSizerButtons = new wxStdDialogButtonSizer();
704 m_buttonOkay = new wxButton(this, wxID_OK);
705 m_sdbSizerButtons->AddButton(m_buttonOkay);
706 m_sdbSizerButtons->AddButton(new wxButton(this, wxID_CANCEL, _("Cancel")));
707 m_sdbSizerButtons->Realize();
708 btnSizer->Add(m_sdbSizerButtons, 0, wxALL, 5);
709
710 // SetMinSize(wxSize(-1, 600));
711
712 // Connect Events
713 m_textLatitude->Connect(
714 wxEVT_CONTEXT_MENU,
715 wxCommandEventHandler(MarkInfoDlg::OnRightClickLatLon), NULL, this);
716 m_textLongitude->Connect(
717 wxEVT_CONTEXT_MENU,
718 wxCommandEventHandler(MarkInfoDlg::OnRightClickLatLon), NULL, this);
719#ifndef __ANDROID__ // wxSimpleHtmlListBox is broken on Android....
720 m_htmlList->Connect(wxEVT_RIGHT_DOWN,
721 wxMouseEventHandler(MarkInfoDlg::m_htmlListContextMenu),
722 NULL, this);
723#else
724#endif
725 m_notebookProperties->Connect(
726 wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
727 wxNotebookEventHandler(MarkInfoDlg::OnNotebookPageChanged), NULL, this);
728 // m_EtdTimePickerCtrl->Connect( wxEVT_TIME_CHANGED, wxDateEventHandler(
729 // MarkInfoDlg::OnTimeChanged ), NULL, this ); m_EtdDatePickerCtrl->Connect(
730 // wxEVT_DATE_CHANGED, wxDateEventHandler( MarkInfoDlg::OnTimeChanged ), NULL,
731 // this );
732 m_comboBoxTideStation->Connect(
733 wxEVT_COMMAND_COMBOBOX_SELECTED,
734 wxCommandEventHandler(MarkInfoDlg::OnTideStationCombobox), NULL, this);
735}
736
737void MarkInfoDlg::OnClose(wxCloseEvent& event) {
738 Hide();
739 event.Veto();
740 if (m_pRoutePoint) m_pRoutePoint->m_bRPIsBeingEdited = false;
741}
742
743#define TIDESTATION_BATCH_SIZE 10
744
745void MarkInfoDlg::OnTideStationCombobox(wxCommandEvent& event) {
746 int count = m_comboBoxTideStation->GetCount();
747 int sel = m_comboBoxTideStation->GetSelection();
748 if (sel == count - 1) {
749 wxString n;
750 int i = 0;
751 for (auto ts : m_tss) {
752 if (i == count + TIDESTATION_BATCH_SIZE) {
753 break;
754 }
755 if (i > count) {
756 n = wxString::FromUTF8(ts.second->IDX_station_name);
757 m_comboBoxTideStation->Append(n);
758 }
759 i++;
760 }
761 }
762}
763
764void MarkInfoDlg::OnNotebookPageChanged(wxNotebookEvent& event) {
765 if (event.GetSelection() == EXTENDED_PROP_PAGE) {
766 if (m_lasttspos.IsSameAs(m_textLatitude->GetValue() +
767 m_textLongitude->GetValue())) {
768 return;
769 }
770 m_lasttspos = m_textLatitude->GetValue() + m_textLongitude->GetValue();
771 double lat = fromDMM(m_textLatitude->GetValue());
772 double lon = fromDMM(m_textLongitude->GetValue());
773 m_tss = ptcmgr->GetStationsForLL(lat, lon);
774 wxString s = m_comboBoxTideStation->GetStringSelection();
775 wxString n;
776 int i = 0;
777 m_comboBoxTideStation->Clear();
778 m_comboBoxTideStation->Append(wxEmptyString);
779 for (auto ts : m_tss) {
780 if (i == TIDESTATION_BATCH_SIZE) {
781 break;
782 }
783 i++;
784 n = wxString::FromUTF8(ts.second->IDX_station_name);
785 m_comboBoxTideStation->Append(n);
786 if (s == n) {
787 m_comboBoxTideStation->SetSelection(i);
788 }
789 }
790 if (m_comboBoxTideStation->GetStringSelection() != s) {
791 m_comboBoxTideStation->Insert(s, 1);
792 m_comboBoxTideStation->SetSelection(1);
793 }
794 }
795}
796
797void MarkInfoDlg::RecalculateSize(void) {
798#ifdef __ANDROID__
799
800 Layout();
801
802 wxSize dsize = GetParent()->GetClientSize();
803
804 wxSize esize;
805
806 esize.x = GetCharHeight() * 20;
807 esize.y = GetCharHeight() * 40;
808 // qDebug() << "esizeA" << esize.x << esize.y;
809
810 esize.y = wxMin(esize.y, dsize.y - (2 * GetCharHeight()));
811 esize.x = wxMin(esize.x, dsize.x - (1 * GetCharHeight()));
812 SetSize(wxSize(esize.x, esize.y));
813 // qDebug() << "esize" << esize.x << esize.y;
814
815 wxSize fsize = GetSize();
816 fsize.y = wxMin(fsize.y, dsize.y - (2 * GetCharHeight()));
817 fsize.x = wxMin(fsize.x, dsize.x - (1 * GetCharHeight()));
818 // qDebug() << "fsize" << fsize.x << fsize.y;
819
820 // And finally, not too tall...
821 fsize.y = wxMin(fsize.y, (25 * GetCharHeight()));
822
823 SetSize(wxSize(-1, fsize.y));
824
825 m_defaultClientSize = GetClientSize();
826 Center();
827#else
828 wxSize dsize = GetParent()->GetClientSize();
829 SetSize(-1, wxMax(GetSize().y, dsize.y / 1.5));
830#endif
831}
832
833MarkInfoDlg::~MarkInfoDlg() {
834 // Disconnect Events
835 m_textLatitude->Disconnect(
836 wxEVT_CONTEXT_MENU,
837 wxCommandEventHandler(MarkInfoDlg::OnRightClickLatLon), NULL, this);
838 m_textLongitude->Disconnect(
839 wxEVT_CONTEXT_MENU,
840 wxCommandEventHandler(MarkInfoDlg::OnRightClickLatLon), NULL, this);
841#ifndef __ANDROID__ // wxSimpleHtmlListBox is broken on Android....
842 m_htmlList->Disconnect(
843 wxEVT_RIGHT_DOWN, wxMouseEventHandler(MarkInfoDlg::m_htmlListContextMenu),
844 NULL, this);
845#else
846#endif
847
848 m_notebookProperties->Disconnect(
849 wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
850 wxNotebookEventHandler(MarkInfoDlg::OnNotebookPageChanged), NULL, this);
851 m_EtdTimePickerCtrl->Disconnect(
852 wxEVT_TIME_CHANGED, wxDateEventHandler(MarkInfoDlg::OnTimeChanged), NULL,
853 this);
854 m_EtdDatePickerCtrl->Disconnect(
855 wxEVT_DATE_CHANGED, wxDateEventHandler(MarkInfoDlg::OnTimeChanged), NULL,
856 this);
857
858#ifdef __ANDROID__
859 androidEnableBackButton(true);
860#endif
861}
862
863void MarkInfoDlg::InitialFocus(void) {
864 m_textName->SetFocus();
865 m_textName->SetInsertionPointEnd();
866}
867
868void MarkInfoDlg::SetColorScheme(ColorScheme cs) { DimeControl(this); }
869
870void MarkInfoDlg::ClearData() {
871 m_pRoutePoint = NULL;
872 UpdateProperties();
873}
874
875void MarkInfoDlg::SetRoutePoint(RoutePoint* pRP) {
876 m_pRoutePoint = pRP;
877 if (m_pRoutePoint) {
878 m_lat_save = m_pRoutePoint->m_lat;
879 m_lon_save = m_pRoutePoint->m_lon;
880 m_IconName_save = m_pRoutePoint->GetIconName();
881 m_bShowName_save = m_pRoutePoint->m_bShowName;
882 m_bIsVisible_save = m_pRoutePoint->m_bIsVisible;
883 m_Name_save = m_pRoutePoint->GetName();
884 m_Description_save = m_pRoutePoint->m_MarkDescription;
885 m_bUseScaMin_save = m_pRoutePoint->GetUseSca();
886 m_iScaminVal_save = m_pRoutePoint->GetScaMin();
887
888 if (m_pMyLinkList) delete m_pMyLinkList;
889 m_pMyLinkList = new HyperlinkList();
890 int NbrOfLinks = m_pRoutePoint->m_HyperlinkList->GetCount();
891 if (NbrOfLinks > 0) {
892 wxHyperlinkListNode* linknode =
893 m_pRoutePoint->m_HyperlinkList->GetFirst();
894 while (linknode) {
895 Hyperlink* link = linknode->GetData();
896
897 Hyperlink* h = new Hyperlink();
898 h->DescrText = link->DescrText;
899 h->Link = link->Link;
900 h->LType = link->LType;
901
902 m_pMyLinkList->Append(h);
903
904 linknode = linknode->GetNext();
905 }
906 }
907 }
908}
909
910void MarkInfoDlg::UpdateHtmlList() {
911#ifndef __ANDROID__ // wxSimpleHtmlListBox is broken on Android....
912 GetSimpleBox()->Clear();
913 int NbrOfLinks = m_pRoutePoint->m_HyperlinkList->GetCount();
914
915 if (NbrOfLinks > 0) {
916 wxHyperlinkListNode* linknode = m_pRoutePoint->m_HyperlinkList->GetFirst();
917 while (linknode) {
918 Hyperlink* link = linknode->GetData();
919 wxString s =
920 wxString::Format("<a href='%s'>%s</a>", link->Link, link->DescrText);
921 GetSimpleBox()->AppendString(s);
922 linknode = linknode->GetNext();
923 }
924 }
925#else
926 // Clear the list
927 wxWindowList kids = m_scrolledWindowLinks->GetChildren();
928 for (unsigned int i = 0; i < kids.GetCount(); i++) {
929 wxWindowListNode* node = kids.Item(i);
930 wxWindow* win = node->GetData();
931
932 auto link_win = dynamic_cast<wxHyperlinkCtrl*>(win);
933 if (link_win) {
934 link_win->Disconnect(
935 wxEVT_COMMAND_HYPERLINK,
936 wxHyperlinkEventHandler(MarkInfoDlg::OnHyperLinkClick));
937 link_win->Disconnect(
938 wxEVT_RIGHT_DOWN,
939 wxMouseEventHandler(MarkInfoDlg::m_htmlListContextMenu));
940 win->Destroy();
941 }
942 }
943
944 int NbrOfLinks = m_pRoutePoint->m_HyperlinkList->GetCount();
945 HyperlinkList* hyperlinklist = m_pRoutePoint->m_HyperlinkList;
946 if (NbrOfLinks > 0) {
947 wxHyperlinkListNode* linknode = hyperlinklist->GetFirst();
948 while (linknode) {
949 Hyperlink* link = linknode->GetData();
950 wxString Link = link->Link;
951 wxString Descr = link->DescrText;
952
953 wxHyperlinkCtrl* ctrl = new wxHyperlinkCtrl(
954 m_scrolledWindowLinks, wxID_ANY, Descr, Link, wxDefaultPosition,
955 wxDefaultSize, wxNO_BORDER | wxHL_CONTEXTMENU | wxHL_ALIGN_LEFT);
956 ctrl->Connect(wxEVT_COMMAND_HYPERLINK,
957 wxHyperlinkEventHandler(MarkInfoDlg::OnHyperLinkClick),
958 NULL, this);
959 if (!m_pRoutePoint->m_bIsInLayer)
960 ctrl->Connect(wxEVT_RIGHT_DOWN,
961 wxMouseEventHandler(MarkInfoDlg::m_htmlListContextMenu),
962 NULL, this);
963
964 bSizerLinks->Add(ctrl, 1, wxALL | wxEXPAND, 5);
965
966 linknode = linknode->GetNext();
967 }
968 }
969
970 // Integrate all of the rebuilt hyperlink controls
971 m_scrolledWindowLinks->Layout();
972#endif
973}
974
975void MarkInfoDlg::OnHyperLinkClick(wxHyperlinkEvent& event) {
976 wxString url = event.GetURL();
977 url.Replace(" ", "%20");
978 if (g_Platform) g_Platform->platformLaunchDefaultBrowser(url);
979}
980
981void MarkInfoDlg::OnHtmlLinkClicked(wxHtmlLinkEvent& event) {
982 // Windows has trouble handling local file URLs with embedded anchor
983 // points, e.g file://testfile.html#point1 The trouble is with the
984 // wxLaunchDefaultBrowser with verb "open" Workaround is to probe the
985 // registry to get the default browser, and open directly
986 //
987 // But, we will do this only if the URL contains the anchor point
988 // character '#' What a hack......
989
990#ifdef __WXMSW__
991 wxString cc = event.GetLinkInfo().GetHref().c_str();
992 if (cc.Find("#") != wxNOT_FOUND) {
993 wxRegKey RegKey(wxString("HKEY_CLASSES_ROOT\\HTTP\\shell\\open\\command"));
994 if (RegKey.Exists()) {
995 wxString command_line;
996 RegKey.QueryValue(wxString(""), command_line);
997
998 // Remove "
999 command_line.Replace(wxString("\""), wxString(""));
1000
1001 // Strip arguments
1002 int l = command_line.Find(".exe");
1003 if (wxNOT_FOUND == l) l = command_line.Find(".EXE");
1004
1005 if (wxNOT_FOUND != l) {
1006 wxString cl = command_line.Mid(0, l + 4);
1007 cl += " ";
1008 cc.Prepend("\"");
1009 cc.Append("\"");
1010 cl += cc;
1011 wxExecute(cl); // Async, so Fire and Forget...
1012 }
1013 }
1014 } else {
1015 wxString url = event.GetLinkInfo().GetHref().c_str();
1016 url.Replace(" ", "%20");
1017 ::wxLaunchDefaultBrowser(url);
1018 event.Skip();
1019 }
1020#else
1021 wxString url = event.GetLinkInfo().GetHref().c_str();
1022 url.Replace(" ", "%20");
1023 if (g_Platform) g_Platform->platformLaunchDefaultBrowser(url);
1024
1025 event.Skip();
1026#endif
1027}
1028
1029void MarkInfoDlg::OnLayoutResize(wxCommandEvent& event) {
1030 m_panelBasicProperties->Layout();
1031 this->Layout();
1032}
1033
1034void MarkInfoDlg::OnDescChangedExt(wxCommandEvent& event) {
1035 if (m_panelDescription->IsShownOnScreen()) {
1036 m_textDescription->ChangeValue(m_textCtrlExtDescription->GetValue());
1037 }
1038 event.Skip();
1039}
1040void MarkInfoDlg::OnDescChangedBasic(wxCommandEvent& event) {
1041 if (m_panelBasicProperties->IsShownOnScreen()) {
1042 m_textCtrlExtDescription->ChangeValue(m_textDescription->GetValue());
1043 }
1044 event.Skip();
1045}
1046
1047void MarkInfoDlg::OnExtDescriptionClick(wxCommandEvent& event) {
1048 long pos = m_textDescription->GetInsertionPoint();
1049 m_notebookProperties->SetSelection(1);
1050 m_textCtrlExtDescription->SetInsertionPoint(pos);
1051 event.Skip();
1052}
1053
1054void MarkInfoDlg::OnShowWaypointNameSelectBasic(wxCommandEvent& event) {
1055 m_checkBoxShowNameExt->SetValue(m_checkBoxShowName->GetValue());
1056 event.Skip();
1057}
1058void MarkInfoDlg::OnShowWaypointNameSelectExt(wxCommandEvent& event) {
1059 m_checkBoxShowName->SetValue(m_checkBoxShowNameExt->GetValue());
1060 event.Skip();
1061}
1062
1063void MarkInfoDlg::OnWptRangeRingsNoChange(wxCommandEvent& event) {
1064 if (!m_pRoutePoint->m_bIsInLayer) {
1065 m_textWaypointRangeRingsStep->Enable(
1066 (bool)(m_ChoiceWaypointRangeRingsNumber->GetSelection() != 0));
1067 m_PickColor->Enable(
1068 (bool)(m_ChoiceWaypointRangeRingsNumber->GetSelection() != 0));
1069 }
1070}
1071
1072void MarkInfoDlg::OnSelectScaMinExt(wxCommandEvent& event) {
1073 if (!m_pRoutePoint->m_bIsInLayer) {
1074 m_textScaMin->Enable(m_checkBoxScaMin->GetValue());
1075 }
1076}
1077
1078void MarkInfoDlg::OnPositionCtlUpdated(wxCommandEvent& event) {
1079 // Fetch the control values, convert to degrees
1080 double lat = fromDMM(m_textLatitude->GetValue());
1081 double lon = fromDMM(m_textLongitude->GetValue());
1082 if (!m_pRoutePoint->m_bIsInLayer) {
1083 m_pRoutePoint->SetPosition(lat, lon);
1084 pSelect->ModifySelectablePoint(lat, lon, (void*)m_pRoutePoint,
1085 SELTYPE_ROUTEPOINT);
1086 }
1087 // Update the mark position dynamically
1088 gFrame->RefreshAllCanvas();
1089}
1090
1091void MarkInfoDlg::m_htmlListContextMenu(wxMouseEvent& event) {
1092#ifndef __ANDROID__
1093 // SimpleHtmlList->HitTest doesn't seem to work under msWin, so we use a
1094 // custom made version
1095 wxPoint pos = event.GetPosition();
1096 i_htmlList_item = -1;
1097 for (int i = 0; i < (int)GetSimpleBox()->GetCount(); i++) {
1098 wxRect rect = GetSimpleBox()->GetItemRect(i);
1099 if (rect.Contains(pos)) {
1100 i_htmlList_item = i;
1101 break;
1102 }
1103 }
1104
1105 wxMenu* popup = new wxMenu();
1106 if ((GetSimpleBox()->GetCount()) > 0 && (i_htmlList_item > -1) &&
1107 (i_htmlList_item < (int)GetSimpleBox()->GetCount())) {
1108 popup->Append(ID_RCLK_MENU_DELETE_LINK, _("Delete"));
1109 popup->Append(ID_RCLK_MENU_EDIT_LINK, _("Edit"));
1110 }
1111 popup->Append(ID_RCLK_MENU_ADD_LINK, _("Add New"));
1112
1113 m_contextObject = event.GetEventObject();
1114 popup->Connect(
1115 wxEVT_COMMAND_MENU_SELECTED,
1116 wxCommandEventHandler(MarkInfoDlg::On_html_link_popupmenu_Click), NULL,
1117 this);
1118 PopupMenu(popup);
1119 delete popup;
1120#else
1121
1122 m_pEditedLink = dynamic_cast<wxHyperlinkCtrl*>(event.GetEventObject());
1123
1124 if (m_pEditedLink) {
1125 wxString url = m_pEditedLink->GetURL();
1126 wxString label = m_pEditedLink->GetLabel();
1127 i_htmlList_item = -1;
1128 HyperlinkList* hyperlinklist = m_pRoutePoint->m_HyperlinkList;
1129 if (hyperlinklist->GetCount() > 0) {
1130 int i = 0;
1131 wxHyperlinkListNode* linknode = hyperlinklist->GetFirst();
1132 while (linknode) {
1133 Hyperlink* link = linknode->GetData();
1134 if (link->DescrText == label) {
1135 i_htmlList_item = i;
1136 break;
1137 }
1138
1139 linknode = linknode->GetNext();
1140 i++;
1141 }
1142 }
1143
1144 wxFont sFont = GetOCPNGUIScaledFont(_("Menu"));
1145
1146 wxMenu* popup = new wxMenu();
1147 {
1148 wxMenuItem* menuItemDelete =
1149 new wxMenuItem(popup, ID_RCLK_MENU_DELETE_LINK, wxString(_("Delete")),
1150 wxEmptyString, wxITEM_NORMAL);
1151#ifdef __WXQT__
1152 menuItemDelete->SetFont(sFont);
1153#endif
1154 popup->Append(menuItemDelete);
1155
1156 wxMenuItem* menuItemEdit =
1157 new wxMenuItem(popup, ID_RCLK_MENU_EDIT_LINK, wxString(_("Edit")),
1158 wxEmptyString, wxITEM_NORMAL);
1159#ifdef __WXQT__
1160 menuItemEdit->SetFont(sFont);
1161#endif
1162 popup->Append(menuItemEdit);
1163 }
1164
1165 wxMenuItem* menuItemAdd =
1166 new wxMenuItem(popup, ID_RCLK_MENU_ADD_LINK, wxString(_("Add New")),
1167 wxEmptyString, wxITEM_NORMAL);
1168#ifdef __WXQT__
1169 menuItemAdd->SetFont(sFont);
1170#endif
1171 popup->Append(menuItemAdd);
1172
1173 m_contextObject = event.GetEventObject();
1174 popup->Connect(
1175 wxEVT_COMMAND_MENU_SELECTED,
1176 wxCommandEventHandler(MarkInfoDlg::On_html_link_popupmenu_Click), NULL,
1177 this);
1178 wxPoint p = m_scrolledWindowLinks->GetPosition();
1179 p.x += m_scrolledWindowLinks->GetSize().x / 2;
1180 PopupMenu(popup, p);
1181 delete popup;
1182
1183 // m_scrolledWindowLinks->PopupMenu( m_menuLink,
1184 // m_pEditedLink->GetPosition().x /*+ event.GetPosition().x*/,
1185 // m_pEditedLink->GetPosition().y /*+ event.GetPosition().y*/ );
1186 }
1187/*
1188 wxPoint pos = event.GetPosition();
1189 i_htmlList_item = -1;
1190 for( int i=0; i < (int)GetSimpleBox()->GetCount(); i++ )
1191 {
1192 wxRect rect = GetSimpleBox()->GetItemRect( i );
1193 if( rect.Contains( pos) ){
1194 i_htmlList_item = i;
1195 break;
1196 }
1197 }
1198
1199 */
1200#endif
1201}
1202
1203void MarkInfoDlg::OnAddLink(wxCommandEvent& event) {
1204 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED);
1205 evt.SetId(ID_RCLK_MENU_ADD_LINK);
1206
1207 On_html_link_popupmenu_Click(evt);
1208}
1209
1210void MarkInfoDlg::On_html_link_popupmenu_Click(wxCommandEvent& event) {
1211 switch (event.GetId()) {
1212 case ID_RCLK_MENU_DELETE_LINK: {
1213 wxHyperlinkListNode* node =
1214 m_pRoutePoint->m_HyperlinkList->Item(i_htmlList_item);
1215 m_pRoutePoint->m_HyperlinkList->DeleteNode(node);
1216 UpdateHtmlList();
1217 break;
1218 }
1219 case ID_RCLK_MENU_EDIT_LINK: {
1220 Hyperlink* link =
1221 m_pRoutePoint->m_HyperlinkList->Item(i_htmlList_item)->GetData();
1222 LinkPropImpl* LinkPropDlg = new LinkPropImpl(this);
1223 LinkPropDlg->m_textCtrlLinkDescription->SetValue(link->DescrText);
1224 LinkPropDlg->m_textCtrlLinkUrl->SetValue(link->Link);
1225 DimeControl(LinkPropDlg);
1226 LinkPropDlg->ShowWindowModalThenDo([this, LinkPropDlg,
1227 link](int retcode) {
1228 if (retcode == wxID_OK) {
1229 link->DescrText = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1230 link->Link = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1231 m_pRoutePoint->m_HyperlinkList->Item(i_htmlList_item)->SetData(link);
1232 UpdateHtmlList();
1233 }
1234 });
1235 break;
1236 }
1237 case ID_RCLK_MENU_ADD_LINK: {
1238 LinkPropImpl* LinkPropDlg = new LinkPropImpl(this);
1239 LinkPropDlg->m_textCtrlLinkDescription->SetValue(wxEmptyString);
1240 LinkPropDlg->m_textCtrlLinkUrl->SetValue(wxEmptyString);
1241 DimeControl(LinkPropDlg);
1242 LinkPropDlg->ShowWindowModalThenDo([this, LinkPropDlg](int retcode) {
1243 if (retcode == wxID_OK) {
1244 Hyperlink* link = new Hyperlink;
1245 link->DescrText = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1246 link->Link = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1247 // Check if decent
1248 if (link->DescrText == wxEmptyString) {
1249 link->DescrText = link->Link;
1250 }
1251 if (link->Link == wxEmptyString) {
1252 delete link;
1253 } else {
1254 m_pRoutePoint->m_HyperlinkList->Append(link);
1255 }
1256 UpdateHtmlList();
1257 }
1258 });
1259 break;
1260 }
1261 }
1262 event.Skip();
1263}
1264
1265void MarkInfoDlg::OnRightClickLatLon(wxCommandEvent& event) {
1266 wxMenu* popup = new wxMenu();
1267 popup->Append(ID_RCLK_MENU_COPY, _("Copy"));
1268 popup->Append(ID_RCLK_MENU_COPY_LL, _("Copy lat/long"));
1269 popup->Append(ID_RCLK_MENU_PASTE, _("Paste"));
1270 popup->Append(ID_RCLK_MENU_PASTE_LL, _("Paste lat/long"));
1271 m_contextObject = event.GetEventObject();
1272 popup->Connect(wxEVT_COMMAND_MENU_SELECTED,
1273 wxCommandEventHandler(MarkInfoDlg::OnCopyPasteLatLon), NULL,
1274 this);
1275
1276 PopupMenu(popup);
1277 delete popup;
1278}
1279
1280void MarkInfoDlg::OnCopyPasteLatLon(wxCommandEvent& event) {
1281 // Fetch the control values, convert to degrees
1282 double lat = fromDMM(m_textLatitude->GetValue());
1283 double lon = fromDMM(m_textLongitude->GetValue());
1284
1285 wxString result;
1286
1287 switch (event.GetId()) {
1288 case ID_RCLK_MENU_PASTE: {
1289 if (wxTheClipboard->Open()) {
1290 wxTextDataObject data;
1291 wxTheClipboard->GetData(data);
1292 result = data.GetText();
1293 ((wxTextCtrl*)m_contextObject)->SetValue(result);
1294 wxTheClipboard->Close();
1295 }
1296 return;
1297 }
1298 case ID_RCLK_MENU_PASTE_LL: {
1299 if (wxTheClipboard->Open()) {
1300 wxTextDataObject data;
1301 wxTheClipboard->GetData(data);
1302 result = data.GetText();
1303
1304 PositionParser pparse(result);
1305
1306 if (pparse.IsOk()) {
1307 m_textLatitude->SetValue(pparse.GetLatitudeString());
1308 m_textLongitude->SetValue(pparse.GetLongitudeString());
1309 }
1310 wxTheClipboard->Close();
1311 }
1312 return;
1313 }
1314 case ID_RCLK_MENU_COPY: {
1315 result = ((wxTextCtrl*)m_contextObject)->GetValue();
1316 break;
1317 }
1318 case ID_RCLK_MENU_COPY_LL: {
1319 result << toSDMM(1, lat, true) << _T('\t');
1320 result << toSDMM(2, lon, true);
1321 break;
1322 }
1323 }
1324
1325 if (wxTheClipboard->Open()) {
1326 wxTextDataObject* data = new wxTextDataObject;
1327 data->SetText(result);
1328 wxTheClipboard->SetData(data);
1329 wxTheClipboard->Close();
1330 }
1331}
1332
1333void MarkInfoDlg::DefautlBtnClicked(wxCommandEvent& event) {
1334 m_SaveDefaultDlg = new SaveDefaultsDialog(this);
1335 m_SaveDefaultDlg->Center();
1336 DimeControl(m_SaveDefaultDlg);
1337 int retcode = m_SaveDefaultDlg->ShowModal();
1338
1339 {
1340 if (retcode == wxID_OK) {
1341 double value;
1342 if (m_SaveDefaultDlg->IconCB->GetValue()) {
1343 g_default_wp_icon =
1344 *pWayPointMan->GetIconKey(m_bcomboBoxIcon->GetSelection());
1345 }
1346 if (m_SaveDefaultDlg->RangRingsCB->GetValue()) {
1347 g_iWaypointRangeRingsNumber =
1348 m_ChoiceWaypointRangeRingsNumber->GetSelection();
1349 if (m_textWaypointRangeRingsStep->GetValue().ToDouble(&value))
1350 g_fWaypointRangeRingsStep = fromUsrDistance(value, -1);
1351 g_colourWaypointRangeRingsColour = m_PickColor->GetColour();
1352 }
1353 if (m_SaveDefaultDlg->ArrivalRCB->GetValue())
1354 if (m_textArrivalRadius->GetValue().ToDouble(&value))
1355 g_n_arrival_circle_radius = fromUsrDistance(value, -1);
1356 if (m_SaveDefaultDlg->ScaleCB->GetValue()) {
1357 g_iWpt_ScaMin = wxAtoi(m_textScaMin->GetValue());
1358 g_bUseWptScaMin = m_checkBoxScaMin->GetValue();
1359 }
1360 if (m_SaveDefaultDlg->NameCB->GetValue()) {
1361 g_bShowWptName = m_checkBoxShowName->GetValue();
1362 }
1363 }
1364 m_SaveDefaultDlg = NULL;
1365 }
1366}
1367
1368void MarkInfoDlg::OnMarkInfoCancelClick(wxCommandEvent& event) {
1369 if (m_pRoutePoint) {
1370 m_pRoutePoint->SetVisible(m_bIsVisible_save);
1371 m_pRoutePoint->SetNameShown(m_bShowName_save);
1372 m_pRoutePoint->SetPosition(m_lat_save, m_lon_save);
1373 m_pRoutePoint->SetIconName(m_IconName_save);
1374 m_pRoutePoint->ReLoadIcon();
1375 m_pRoutePoint->SetName(m_Name_save);
1376 m_pRoutePoint->m_MarkDescription = m_Description_save;
1377 m_pRoutePoint->SetUseSca(m_bUseScaMin_save);
1378 m_pRoutePoint->SetScaMin(m_iScaminVal_save);
1379
1380 m_pRoutePoint->m_HyperlinkList->Clear();
1381
1382 int NbrOfLinks = m_pMyLinkList->GetCount();
1383 if (NbrOfLinks > 0) {
1384 wxHyperlinkListNode* linknode = m_pMyLinkList->GetFirst();
1385 while (linknode) {
1386 Hyperlink* link = linknode->GetData();
1387 Hyperlink* h = new Hyperlink();
1388 h->DescrText = link->DescrText;
1389 h->Link = link->Link;
1390 h->LType = link->LType;
1391
1392 m_pRoutePoint->m_HyperlinkList->Append(h);
1393
1394 linknode = linknode->GetNext();
1395 }
1396 }
1397 }
1398
1399 m_lasttspos.Clear();
1400
1401#ifdef __WXGTK__
1402 gFrame->Raise();
1403#endif
1404
1405 Show(false);
1406 delete m_pMyLinkList;
1407 m_pMyLinkList = NULL;
1408 SetClientSize(m_defaultClientSize);
1409
1410#ifdef __ANDROID__
1411 androidEnableBackButton(true);
1412#endif
1413
1414 event.Skip();
1415}
1416
1417void MarkInfoDlg::OnMarkInfoOKClick(wxCommandEvent& event) {
1418 if (m_pRoutePoint) {
1419 m_pRoutePoint->m_wxcWaypointRangeRingsColour = m_PickColor->GetColour();
1420
1421 OnPositionCtlUpdated(event);
1422 SaveChanges(); // write changes to globals and update config
1423 }
1424
1425#ifdef __WXGTK__
1426 gFrame->Raise();
1427#endif
1428
1429 Show(false);
1430
1431 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
1432 pRouteManagerDialog->UpdateWptListCtrl();
1433
1434 if (pRoutePropDialog && pRoutePropDialog->IsShown())
1435 pRoutePropDialog->UpdatePoints();
1436
1437 SetClientSize(m_defaultClientSize);
1438
1439#ifdef __ANDROID__
1440 androidEnableBackButton(true);
1441#endif
1442
1443 event.Skip();
1444}
1445
1446bool MarkInfoDlg::UpdateProperties(bool positionOnly) {
1447 if (m_pRoutePoint) {
1448 m_textLatitude->SetValue(::toSDMM(1, m_pRoutePoint->m_lat));
1449 m_textLongitude->SetValue(::toSDMM(2, m_pRoutePoint->m_lon));
1450 m_lat_save = m_pRoutePoint->m_lat;
1451 m_lon_save = m_pRoutePoint->m_lon;
1452 m_textName->SetValue(m_pRoutePoint->GetName());
1453 m_textDescription->ChangeValue(m_pRoutePoint->m_MarkDescription);
1454 m_textCtrlExtDescription->ChangeValue(m_pRoutePoint->m_MarkDescription);
1455 m_checkBoxShowName->SetValue(m_pRoutePoint->m_bShowName);
1456 m_checkBoxShowNameExt->SetValue(m_pRoutePoint->m_bShowName);
1457 m_checkBoxVisible->SetValue(m_pRoutePoint->m_bIsVisible);
1458 m_checkBoxScaMin->SetValue(m_pRoutePoint->GetUseSca());
1459 m_textScaMin->SetValue(
1460 wxString::Format("%i", (int)m_pRoutePoint->GetScaMin()));
1461 m_textCtrlGuid->SetValue(m_pRoutePoint->m_GUID);
1462 m_ChoiceWaypointRangeRingsNumber->SetSelection(
1463 m_pRoutePoint->GetWaypointRangeRingsNumber());
1464 wxString buf;
1465 buf.Printf("%.3f",
1466 toUsrDistance(m_pRoutePoint->GetWaypointRangeRingsStep(), -1));
1467 m_textWaypointRangeRingsStep->SetValue(buf);
1468 m_staticTextArrivalUnits->SetLabel(getUsrDistanceUnit());
1469 buf.Printf("%.3f",
1470 toUsrDistance(m_pRoutePoint->GetWaypointArrivalRadius(), -1));
1471 m_textArrivalRadius->SetValue(buf);
1472
1473 int nUnits = m_pRoutePoint->GetWaypointRangeRingsStepUnits();
1474 m_RangeRingUnits->SetSelection(nUnits);
1475
1476 wxColour col = m_pRoutePoint->m_wxcWaypointRangeRingsColour;
1477 m_PickColor->SetColour(col);
1478
1479 if (m_pRoutePoint->m_bIsInRoute) {
1480 if (m_name_validator) m_name_validator.reset();
1481 m_name_validator =
1482 std::make_unique<RoutePointNameValidator>(m_pRoutePoint);
1483 m_textName->SetValidator(*m_name_validator);
1484 m_textName->Bind(wxEVT_TEXT, &TextField::OnTextChanged, m_textName);
1485 m_textName->Bind(wxEVT_KILL_FOCUS, &MarkInfoDlg::OnFocusEvent, this);
1486 } else {
1487 m_textName->SetValidator();
1488 m_textName->Unbind(wxEVT_TEXT, &TextField::OnTextChanged, m_textName);
1489 m_textName->Unbind(wxEVT_KILL_FOCUS, &MarkInfoDlg::OnFocusEvent, this);
1490 }
1491
1492 if (m_comboBoxTideStation->GetStringSelection() !=
1493 m_pRoutePoint->m_TideStation) {
1494 m_comboBoxTideStation->Clear();
1495 m_comboBoxTideStation->Append(wxEmptyString);
1496 if (!m_pRoutePoint->m_TideStation.IsEmpty()) {
1497 m_comboBoxTideStation->Append(m_pRoutePoint->m_TideStation);
1498 m_comboBoxTideStation->SetSelection(1);
1499 }
1500 }
1501
1502 m_staticTextPlSpeedUnits->SetLabel(getUsrSpeedUnit());
1503 if (m_pRoutePoint->GetPlannedSpeed() > .01) {
1504 m_textCtrlPlSpeed->SetValue(wxString::Format(
1505 "%.1f", toUsrSpeed(m_pRoutePoint->GetPlannedSpeed())));
1506 } else {
1507 m_textCtrlPlSpeed->SetValue(wxEmptyString);
1508 }
1509
1510 bool isLastWaypoint = false;
1511 if (m_pRoutePoint && m_pRoutePoint->m_bIsInRoute) {
1512 // Get routes containing this waypoint
1513 wxArrayPtrVoid* pRouteArray =
1514 g_pRouteMan->GetRouteArrayContaining(m_pRoutePoint);
1515 if (pRouteArray) {
1516 isLastWaypoint = true;
1517 // Check if this waypoint is the last across all routes.
1518 for (unsigned int i = 0; i < pRouteArray->GetCount(); i++) {
1519 Route* route = (Route*)pRouteArray->Item(i);
1520 if (route->GetLastPoint()->m_GUID != m_pRoutePoint->m_GUID) {
1521 isLastWaypoint = false;
1522 break;
1523 }
1524 }
1525 delete pRouteArray;
1526 }
1527 }
1528 wxDateTime etd;
1529 etd = m_pRoutePoint->GetManualETD();
1530 if (isLastWaypoint) {
1531 // If this is the last waypoint in a route, uncheck the checkbox and set
1532 // the date/time to empty, as the ETD is meaningless.
1533 etd = wxDateTime();
1534 }
1535 if (etd.IsValid()) {
1536 m_cbEtdPresent->SetValue(true);
1537 wxString dtFormat = ocpn::getUsrDateTimeFormat();
1538 if (dtFormat == "Local Time") {
1539 // The ETD is in UTC and needs to be converted to local time for display
1540 // purpose.
1541 etd.MakeFromUTC();
1542 } else if (dtFormat == "UTC") {
1543 // The date/time is already in UTC.
1544 } else {
1545 // This code path is not expected to be reached, unless
1546 // the global date/time format is enhanced in the future
1547 // to include new format options.
1548 wxLogError(
1549 "MarkInfoDlg::UpdateProperties. Unexpected date/time format: %s",
1550 dtFormat);
1551 etd = wxInvalidDateTime;
1552 }
1553 m_EtdDatePickerCtrl->SetValue(etd.GetDateOnly());
1554 m_EtdTimePickerCtrl->SetValue(etd);
1555 } else {
1556 m_cbEtdPresent->SetValue(false);
1557 }
1558 // Inherit the date/time format from the user settings.
1559 m_staticTextEtd->SetLabel(
1560 wxString::Format("%s (%s)", _("ETD"), ocpn::getUsrDateTimeFormat()));
1561
1562 m_staticTextPlSpeed->Show(m_pRoutePoint->m_bIsInRoute);
1563 m_textCtrlPlSpeed->Show(m_pRoutePoint->m_bIsInRoute);
1564 m_staticTextEtd->Show(m_pRoutePoint->m_bIsInRoute);
1565 m_EtdDatePickerCtrl->Show(m_pRoutePoint->m_bIsInRoute);
1566 m_EtdTimePickerCtrl->Show(m_pRoutePoint->m_bIsInRoute);
1567 m_cbEtdPresent->Show(m_pRoutePoint->m_bIsInRoute);
1568 m_staticTextPlSpeedUnits->Show(m_pRoutePoint->m_bIsInRoute);
1569 m_staticTextArrivalRadius->Show(m_pRoutePoint->m_bIsInRoute);
1570 m_staticTextArrivalUnits->Show(m_pRoutePoint->m_bIsInRoute);
1571 m_textArrivalRadius->Show(m_pRoutePoint->m_bIsInRoute);
1572
1573 if (positionOnly) return true;
1574
1575 // Layer or not?
1576 if (m_pRoutePoint->m_bIsInLayer) {
1577 m_staticTextLayer->Enable();
1578 m_staticTextLayer->Show(true);
1579 m_textName->SetEditable(false);
1580 m_textDescription->SetEditable(false);
1581 m_textCtrlExtDescription->SetEditable(false);
1582 m_textLatitude->SetEditable(false);
1583 m_textLongitude->SetEditable(false);
1584 m_bcomboBoxIcon->Enable(false);
1585 m_checkBoxShowName->Enable(false);
1586 m_checkBoxVisible->Enable(false);
1587 m_textArrivalRadius->SetEditable(false);
1588 m_checkBoxScaMin->Enable(false);
1589 m_textScaMin->SetEditable(false);
1590 m_checkBoxShowNameExt->Enable(false);
1591 m_ChoiceWaypointRangeRingsNumber->Enable(false);
1592 m_textWaypointRangeRingsStep->SetEditable(false);
1593 m_PickColor->Enable(false);
1594 DefaultsBtn->Enable(false);
1595 m_EtdDatePickerCtrl->Enable(false);
1596 m_EtdTimePickerCtrl->Enable(false);
1597 m_cbEtdPresent->Enable(false);
1598 m_notebookProperties->SetSelection(0); // Show Basic page
1599 m_comboBoxTideStation->Enable(false);
1600 } else {
1601 m_staticTextLayer->Enable(false);
1602 m_staticTextLayer->Show(false);
1603 m_textName->SetEditable(true);
1604 m_textDescription->SetEditable(true);
1605 m_textCtrlExtDescription->SetEditable(true);
1606 m_textLatitude->SetEditable(true);
1607 m_textLongitude->SetEditable(true);
1608 m_bcomboBoxIcon->Enable(true);
1609 m_checkBoxShowName->Enable(true);
1610 m_checkBoxVisible->Enable(true);
1611 m_textArrivalRadius->SetEditable(true);
1612 m_checkBoxScaMin->Enable(true);
1613 m_textScaMin->SetEditable(true);
1614 m_checkBoxShowNameExt->Enable(true);
1615 m_ChoiceWaypointRangeRingsNumber->Enable(true);
1616 m_textWaypointRangeRingsStep->SetEditable(true);
1617 m_PickColor->Enable(true);
1618 DefaultsBtn->Enable(true);
1619 m_notebookProperties->SetSelection(0);
1620 m_comboBoxTideStation->Enable(true);
1621
1622 // If this is the last waypoint in a route, disable the ETD as it does not
1623 // make sense to have an ETD for the last waypoint in a route.
1624 m_EtdDatePickerCtrl->Enable(!isLastWaypoint);
1625 m_EtdTimePickerCtrl->Enable(!isLastWaypoint);
1626 m_cbEtdPresent->Enable(!isLastWaypoint);
1627 }
1628
1629 // Fill the icon selector combo box
1630 m_bcomboBoxIcon->Clear();
1631 // Iterate on the Icon Descriptions, filling in the combo control
1632 bool fillCombo = m_bcomboBoxIcon->GetCount() == 0;
1633
1634 if (fillCombo) {
1635 for (int i = 0; i < pWayPointMan->GetNumIcons(); i++) {
1636 wxString* ps = pWayPointMan->GetIconDescription(i);
1637 wxBitmap bmp =
1638 pWayPointMan->GetIconBitmapForList(i, 2 * GetCharHeight());
1639
1640 m_bcomboBoxIcon->Append(*ps, bmp);
1641 }
1642 }
1643 // find the correct item in the combo box
1644 int iconToSelect = -1;
1645 for (int i = 0; i < pWayPointMan->GetNumIcons(); i++) {
1646 if (*pWayPointMan->GetIconKey(i) == m_pRoutePoint->GetIconName()) {
1647 iconToSelect = i;
1648 m_bcomboBoxIcon->Select(iconToSelect);
1649 break;
1650 }
1651 }
1652 wxCommandEvent ev;
1653 OnShowWaypointNameSelectBasic(ev);
1654 OnWptRangeRingsNoChange(ev);
1655 OnSelectScaMinExt(ev);
1656 UpdateHtmlList();
1657 }
1658
1659#ifdef __ANDROID__
1660 androidEnableBackButton(false);
1661#endif
1662
1663 Fit();
1664 // SetMinSize(wxSize(-1, 600));
1665 RecalculateSize();
1666
1667 return true;
1668}
1669
1670// Focus event handler to validate the dialog.
1671void MarkInfoDlg::OnFocusEvent(wxFocusEvent& event) {
1672 bool is_valid = Validate();
1673 m_buttonOkay->Enable(is_valid);
1674 event.Skip();
1675}
1676
1677void MarkInfoDlg::OnBitmapCombClick(wxCommandEvent& event) {
1678 wxString* icon_name =
1679 pWayPointMan->GetIconKey(m_bcomboBoxIcon->GetSelection());
1680 if (icon_name && icon_name->Length()) m_pRoutePoint->SetIconName(*icon_name);
1681 m_pRoutePoint->ReLoadIcon();
1682 SaveChanges();
1683 // pConfig->UpdateWayPoint( m_pRoutePoint );
1684}
1685
1686void MarkInfoDlg::ValidateMark(void) {
1687 // Look in the master list of Waypoints to see if the currently selected
1688 // waypoint is still valid It may have been deleted as part of a route
1689 wxRoutePointListNode* node = pWayPointMan->GetWaypointList()->GetFirst();
1690
1691 bool b_found = false;
1692 while (node) {
1693 RoutePoint* rp = node->GetData();
1694 if (m_pRoutePoint == rp) {
1695 b_found = true;
1696 break;
1697 }
1698 node = node->GetNext();
1699 }
1700 if (!b_found) m_pRoutePoint = NULL;
1701}
1702
1703bool MarkInfoDlg::SaveChanges() {
1704 if (m_pRoutePoint) {
1705 if (m_pRoutePoint->m_bIsInLayer) return true;
1706 if (!this->Validate()) return false; // prevent invalid save
1707
1708 // Get User input Text Fields
1709 m_pRoutePoint->SetName(m_textName->GetValue());
1710 m_pRoutePoint->SetWaypointArrivalRadius(m_textArrivalRadius->GetValue());
1711 m_pRoutePoint->SetScaMin(m_textScaMin->GetValue());
1712 m_pRoutePoint->SetUseSca(m_checkBoxScaMin->GetValue());
1713 m_pRoutePoint->m_MarkDescription = m_textDescription->GetValue();
1714 m_pRoutePoint->SetVisible(m_checkBoxVisible->GetValue());
1715 m_pRoutePoint->m_bShowName = m_checkBoxShowName->GetValue();
1716 m_pRoutePoint->SetPosition(fromDMM(m_textLatitude->GetValue()),
1717 fromDMM(m_textLongitude->GetValue()));
1718 wxString* icon_name =
1719 pWayPointMan->GetIconKey(m_bcomboBoxIcon->GetSelection());
1720 if (icon_name && icon_name->Length())
1721 m_pRoutePoint->SetIconName(*icon_name);
1722 m_pRoutePoint->ReLoadIcon();
1723 m_pRoutePoint->SetShowWaypointRangeRings(
1724 (bool)(m_ChoiceWaypointRangeRingsNumber->GetSelection() != 0));
1725 m_pRoutePoint->SetWaypointRangeRingsNumber(
1726 m_ChoiceWaypointRangeRingsNumber->GetSelection());
1727 double value;
1728 if (m_textWaypointRangeRingsStep->GetValue().ToDouble(&value))
1729 m_pRoutePoint->SetWaypointRangeRingsStep(fromUsrDistance(value, -1));
1730 if (m_textArrivalRadius->GetValue().ToDouble(&value))
1731 m_pRoutePoint->SetWaypointArrivalRadius(fromUsrDistance(value, -1));
1732
1733 if (m_RangeRingUnits->GetSelection() != wxNOT_FOUND)
1734 m_pRoutePoint->SetWaypointRangeRingsStepUnits(
1735 m_RangeRingUnits->GetSelection());
1736
1737 m_pRoutePoint->m_TideStation = m_comboBoxTideStation->GetStringSelection();
1738 if (m_textCtrlPlSpeed->GetValue() == wxEmptyString) {
1739 m_pRoutePoint->SetPlannedSpeed(0.0);
1740 } else {
1741 double spd;
1742 if (m_textCtrlPlSpeed->GetValue().ToDouble(&spd)) {
1743 m_pRoutePoint->SetPlannedSpeed(fromUsrSpeed(spd));
1744 }
1745 }
1746
1747 if (m_cbEtdPresent->GetValue()) {
1748 wxDateTime dt = m_EtdDatePickerCtrl->GetValue();
1749 wxDateTime t = m_EtdTimePickerCtrl->GetValue();
1750 int hour = t.GetHour();
1751 dt.SetHour(hour);
1752 dt.SetMinute(m_EtdTimePickerCtrl->GetValue().GetMinute());
1753 dt.SetSecond(m_EtdTimePickerCtrl->GetValue().GetSecond());
1754 if (dt.IsValid()) {
1755 // The date/time in the UI is specified according to the global settings
1756 // in Options -> Date/Time format. The date/time format is either "Local
1757 // Time" or "UTC". If the date/time format is "Local Time", convert to
1758 // UTC. Otherwise, it is already in UTC.
1759 wxString dtFormat = ocpn::getUsrDateTimeFormat();
1760 if (dtFormat == "Local Time") {
1761 m_pRoutePoint->SetETD(dt.MakeUTC());
1762 } else if (dtFormat == "UTC") {
1763 m_pRoutePoint->SetETD(dt);
1764 } else {
1765 // This code path should never be reached, as the date/time format is
1766 // either "Local Time" or "UTC".
1767 // In the future, other date/time formats may be supported in
1768 // global settings (Options -> Display -> Date/Time Format).
1769 // When/if this happens, this code will need to be updated to
1770 // handle the new formats.
1771 wxLogError(
1772 "Failed to configured ETD. Unsupported date/time format: %s",
1773 dtFormat);
1774 m_pRoutePoint->SetETD(wxInvalidDateTime);
1775 }
1776 }
1777 } else {
1778 m_pRoutePoint->SetETD(wxInvalidDateTime);
1779 }
1780
1781 if (m_pRoutePoint->m_bIsInRoute) {
1782 // Update the route segment selectables
1783 pSelect->UpdateSelectableRouteSegments(m_pRoutePoint);
1784
1785 // Get an array of all routes using this point
1786 wxArrayPtrVoid* pEditRouteArray =
1787 g_pRouteMan->GetRouteArrayContaining(m_pRoutePoint);
1788
1789 if (pEditRouteArray) {
1790 for (unsigned int ir = 0; ir < pEditRouteArray->GetCount(); ir++) {
1791 Route* pr = (Route*)pEditRouteArray->Item(ir);
1792 pr->FinalizeForRendering();
1793 pr->UpdateSegmentDistances();
1794
1795 // pConfig->UpdateRoute(pr);
1796 NavObj_dB::GetInstance().UpdateRoute(pr);
1797 }
1798 delete pEditRouteArray;
1799 }
1800 } else {
1801 // pConfig->UpdateWayPoint(m_pRoutePoint);
1802 NavObj_dB::GetInstance().UpdateRoutePoint(m_pRoutePoint);
1803 }
1804 }
1805 return true;
1806}
1807
1808SaveDefaultsDialog::SaveDefaultsDialog(MarkInfoDlg* parent)
1809 : wxDialog(parent, wxID_ANY, _("Save some defaults")) {
1810 //(*Initialize(SaveDefaultsDialog)
1811 this->SetSizeHints(wxDefaultSize, wxDefaultSize);
1812
1813 wxBoxSizer* bSizer1 = new wxBoxSizer(wxVERTICAL);
1814 wxStdDialogButtonSizer* StdDialogButtonSizer1;
1815
1816 StaticText1 =
1817 new wxStaticText(this, wxID_ANY,
1818 _("Check which properties of current waypoint\n should "
1819 "be set as default for NEW waypoints."));
1820 bSizer1->Add(StaticText1, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, 5);
1821
1822 wxFlexGridSizer* fgSizer1 = new wxFlexGridSizer(2);
1823
1824 wxString s =
1825 (g_pMarkInfoDialog->m_checkBoxShowName->GetValue() ? _("Do use")
1826 : _("Don't use"));
1827 NameCB =
1828 new wxCheckBox(this, wxID_ANY, _("Show Waypoint Name"), wxDefaultPosition,
1829 wxDefaultSize, 0, wxDefaultValidator);
1830 fgSizer1->Add(NameCB, 0, wxALL, 5);
1831 stName = new wxStaticText(this, wxID_ANY, "[" + s + "]", wxDefaultPosition,
1832 wxDefaultSize, 0);
1833 stName->Wrap(-1);
1834 fgSizer1->Add(stName, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 5);
1835
1836 s = g_pMarkInfoDialog->m_pRoutePoint->GetIconName();
1837 IconCB = new wxCheckBox(this, wxID_ANY, _("Icon"));
1838 fgSizer1->Add(IconCB, 0, wxALL, 5);
1839 stIcon = new wxStaticText(this, wxID_ANY, "[" + s + "]", wxDefaultPosition,
1840 wxDefaultSize, 0);
1841 stIcon->Wrap(-1);
1842 fgSizer1->Add(stIcon, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 5);
1843
1844 s = (g_pMarkInfoDialog->m_ChoiceWaypointRangeRingsNumber->GetSelection()
1845 ? _("Do use") +
1846 wxString::Format(
1847 " (%i) ",
1848 g_pMarkInfoDialog->m_ChoiceWaypointRangeRingsNumber
1849 ->GetSelection())
1850 : _("Don't use"));
1851 RangRingsCB = new wxCheckBox(this, wxID_ANY, _("Range rings"));
1852 fgSizer1->Add(RangRingsCB, 0, wxALL, 5);
1853 stRR = new wxStaticText(this, wxID_ANY, "[" + s + "]", wxDefaultPosition,
1854 wxDefaultSize, 0);
1855 stRR->Wrap(-1);
1856 fgSizer1->Add(stRR, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 5);
1857
1858 s = (g_pMarkInfoDialog->m_textArrivalRadius->GetValue());
1859 ArrivalRCB = new wxCheckBox(this, wxID_ANY, _("Arrival radius"));
1860 fgSizer1->Add(ArrivalRCB, 0, wxALL, 5);
1861 stArrivalR = new wxStaticText(
1862 this, wxID_ANY,
1863 wxString::Format("[%s %s]", s.c_str(), getUsrDistanceUnit().c_str()),
1864 wxDefaultPosition, wxDefaultSize, 0);
1865 stArrivalR->Wrap(-1);
1866 fgSizer1->Add(stArrivalR, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL,
1867 5);
1868
1869 s = (g_pMarkInfoDialog->m_checkBoxScaMin->GetValue()
1870 ? _("Show only if") + " < " +
1871 g_pMarkInfoDialog->m_textScaMin->GetValue()
1872 : _("Show always"));
1873 ScaleCB = new wxCheckBox(this, wxID_ANY, _("Show only at scale"));
1874 fgSizer1->Add(ScaleCB, 0, wxALL, 5);
1875 stScale = new wxStaticText(this, wxID_ANY, "[" + s + "]", wxDefaultPosition,
1876 wxDefaultSize, 0);
1877 stScale->Wrap(-1);
1878 fgSizer1->Add(stScale, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 5);
1879
1880 bSizer1->Add(fgSizer1, 0, wxALL | wxEXPAND, 5);
1881
1882 StdDialogButtonSizer1 = new wxStdDialogButtonSizer();
1883 StdDialogButtonSizer1->AddButton(new wxButton(this, wxID_OK));
1884 StdDialogButtonSizer1->AddButton(
1885 new wxButton(this, wxID_CANCEL, _("Cancel")));
1886 StdDialogButtonSizer1->Realize();
1887 bSizer1->Add(StdDialogButtonSizer1, 0, wxALL | wxEXPAND, 5);
1888
1889 SetSizer(bSizer1);
1890 Fit();
1891 Layout();
1892
1893#ifdef __ANDROID__
1894 SetSize(parent->GetSize());
1895#endif
1896
1897 Center();
1898}
1899
1900void MarkInfoDlg::ShowTidesBtnClicked(wxCommandEvent& event) {
1901 if (m_comboBoxTideStation->GetSelection() < 1) {
1902 return;
1903 }
1904 IDX_entry* pIDX = (IDX_entry*)ptcmgr->GetIDX_entry(
1905 ptcmgr->GetStationIDXbyName(m_comboBoxTideStation->GetStringSelection(),
1906 fromDMM(m_textLatitude->GetValue()),
1907 fromDMM(m_textLongitude->GetValue())));
1908 if (pIDX) {
1909 TCWin* pCwin = new TCWin(gFrame->GetPrimaryCanvas(), 0, 0, pIDX);
1910 pCwin->Show();
1911 } else {
1912 wxString msg(_("Tide Station not found"));
1913 msg += ":\n";
1914 msg += m_comboBoxTideStation->GetStringSelection();
1915 OCPNMessageBox(NULL, msg, _("OpenCPN Info"), wxOK | wxCENTER, 10);
1916 }
1917}
Generic Chart canvas base.
Grid layout with 2 columns for form labels and fields.
Definition form_grid.h:28
Represents an index entry for tidal and current data.
Definition IDX_entry.h:49
Class LinkPropImpl.
Definition LinkPropDlg.h:89
Dialog for displaying and editing waypoint properties.
Definition MarkInfo.h:216
wxDatePickerCtrl * m_EtdDatePickerCtrl
Date picker control for setting the Estimated Time of Departure (ETD).
Definition MarkInfo.h:385
wxStaticText * m_staticTextEtd
Label for the Estimated Time of Departure field.
Definition MarkInfo.h:340
wxCheckBox * m_cbEtdPresent
Checkbox control that enables/disables manual ETD setting for a waypoint.
Definition MarkInfo.h:298
wxTextCtrl * m_textCtrlPlSpeed
Text control for waypoint planned speed.
Definition MarkInfo.h:373
wxTimePickerCtrl * m_EtdTimePickerCtrl
Time picker control for setting the Estimated Time of Departure (ETD).
Definition MarkInfo.h:396
Main application frame.
Definition ocpn_frame.h:138
Custom combobox for selecting waypoint icons.
Definition MarkInfo.h:163
Provides platform-specific support utilities for OpenCPN.
Represents a waypoint or mark within the navigation system.
Definition route_point.h:70
HyperlinkList * m_HyperlinkList
List of hyperlinks associated with this waypoint.
wxColour m_wxcWaypointRangeRingsColour
Color for the range rings display.
wxString m_MarkDescription
Description text for the waypoint.
bool m_bRPIsBeingEdited
Flag indicating if this waypoint is currently being edited.
wxString m_GUID
Globally Unique Identifier for the waypoint.
wxDateTime GetManualETD()
Retrieves the manually set Estimated Time of Departure for this waypoint, in UTC.
bool m_bIsInRoute
Flag indicating if this waypoint is part of a route.
bool m_bShowName
Flag indicating if the waypoint name should be shown.
double GetPlannedSpeed()
Return the planned speed associated with this waypoint.
bool m_bIsVisible
Flag indicating if the waypoint should be drawn on the chart.
bool m_bIsInLayer
Flag indicating if the waypoint belongs to a layer.
wxString m_TideStation
Associated tide station identifier.
void SetETD(const wxDateTime &etd)
Sets the Estimated Time of Departure for this waypoint, in UTC.
Represents a navigational route in the navigation system.
Definition route.h:98
wxArrayPtrVoid * GetRouteArrayContaining(RoutePoint *pWP)
Find all routes that contain the given waypoint.
Definition routeman.cpp:178
Dialog for saving default waypoint properties.
Definition MarkInfo.h:469
Definition tcmgr.h:91
Definition TCWin.h:45
Text field with validator and error handler.
Definition field_text.h:38
void OnTextChanged(wxCommandEvent &event)
Text changed event handler.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
Definition gui_lib.cpp:56
wxFont GetOCPNGUIScaledFont(wxString item)
Retrieves a font optimized for touch and high-resolution interfaces.
Definition gui_lib.cpp:85
General purpose GUI support.
wxString getUsrDateTimeFormat()
Return the date/time format to use when formatting date/time strings.
Definition datetime.cpp:37
Class NavObj_dB.
PlugInManager and helper classes – Mostly gui parts (dialogs) and plugin API stuff.
SVG utilities.
GUI library utils and events.