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