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_frame.h"
59#include "ocpn_platform.h"
60#include "pluginmanager.h"
61#include "routemanagerdialog.h"
62#include "route_prop_dlg_impl.h"
63#include "styles.h"
64#include "tcmgr.h"
65#include "tc_win.h"
66#include "ui_utils.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 gFrame->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 gFrame->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 gFrame->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 = new TCWin(gFrame->GetPrimaryCanvas(), 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:203
wxDatePickerCtrl * m_EtdDatePickerCtrl
Date picker control for setting the Estimated Time of Departure (ETD).
Definition mark_info.h:375
wxStaticText * m_staticTextEtd
Label for the Estimated Time of Departure field.
Definition mark_info.h:329
wxCheckBox * m_cbEtdPresent
Checkbox control that enables/disables manual ETD setting for a waypoint.
Definition mark_info.h:286
wxTextCtrl * m_textCtrlPlSpeed
Text control for waypoint planned speed.
Definition mark_info.h:363
wxTimePickerCtrl * m_EtdTimePickerCtrl
Time picker control for setting the Estimated Time of Departure (ETD).
Definition mark_info.h:386
Custom combobox for selecting waypoint icons.
Definition mark_info.h:151
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:459
Definition tc_win.h:44
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 top window.
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.
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.