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