24#include <wx/clipbrd.h>
52#define GLOBAL_SETTINGS_INPUT 3
54#define ID_RCLK_MENU_COPY_TEXT 7013
55#define ID_RCLK_MENU_EDIT_WP 7014
56#define ID_RCLK_MENU_DELETE 7015
57#define ID_RCLK_MENU_MOVEUP_WP 7026
58#define ID_RCLK_MENU_MOVEDOWN_WP 7027
60#define COLUMN_PLANNED_SPEED 9
64#define PI (4. * atan(1.0))
67#define DEGS (180. / PI)
68#define RADS (PI / 180.)
80extern wxString GetLayerName(
int id);
88static wxString GetDaylightString(
int index) {
93 return _(
"MoTwilight");
101 return _(
"EvTwilight");
103 return _(
"Nighttime");
110static double sign(
double x) {
117static double FNipart(
double x) {
return (sign(x) * (
int)(fabs(x))); }
119static double FNday(
int y,
int m,
int d,
int h) {
120 long fd = (367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9 + d);
121 return ((
double)fd - 730531.5 + h / 24.);
124static double FNrange(
double x) {
126 double a = TPI * (b - FNipart(b));
127 if (a < 0.) a = TPI + a;
131static double getDaylightEvent(
double glat,
double glong,
int riset,
132 double altitude,
int y,
int m,
int d) {
133 double day = FNday(y, m, d, 0);
134 double days, correction;
138 sin(altitude * RADS);
139 double sinphi = sin(glat * RADS);
140 double cosphi = cos(glat * RADS);
141 double g = glong * RADS;
142 double t, L, G, ec, lambda, E, obl, delta, GHA, cosc;
144 while ((fabs(utold - utnew) > .001)) {
145 if (limit-- <= 0)
return (-1.);
146 days = day + utnew / TPI;
149 L = FNrange(4.8949504201433 + 628.331969753199 * t);
150 G = FNrange(6.2400408 + 628.3019501 * t);
151 ec = .033423 * sin(G) + .00034907 * sin(2 * G);
153 E = -1. * ec + .0430398 * sin(2 * lambda) - .00092502 * sin(4. * lambda);
154 obl = .409093 - .0002269 * t;
155 delta = asin(sin(obl) * sin(lambda));
156 GHA = utold - PI + E;
157 cosc = (sinalt - sinphi * sin(delta)) / (cosphi * cos(delta));
163 correction = acos(cosc);
165 utnew = FNrange(utold - (GHA + g + riset * correction));
168 return (utnew * DEGS / 15.);
171static double getLMT(
double ut,
double lon) {
172 double t = ut + lon / 15.;
185static wxString getDatetimeTimezoneSelector(
int selection) {
199static int getDaylightStatus(
double lat,
double lon, wxDateTime utcDateTime) {
200 if (fabs(lat) > 60.)
return (0);
201 int y = utcDateTime.GetYear();
202 int m = utcDateTime.GetMonth() + 1;
203 int d = utcDateTime.GetDay();
204 int h = utcDateTime.GetHour();
205 int n = utcDateTime.GetMinute();
206 int s = utcDateTime.GetSecond();
207 if (y < 2000 || y > 2100)
return (0);
209 double ut = (double)h + (
double)n / 60. + (double)s / 3600.;
210 double lt = getLMT(ut, lon);
211 double rsalt = -0.833;
215 double sunrise = getDaylightEvent(lat, lon, +1, rsalt, y, m, d);
219 sunrise = getLMT(sunrise, lon);
221 if (fabs(lt - sunrise) < 0.15)
return (SUNRISE);
222 if (lt > sunrise)
return (DAY);
223 double twilight = getDaylightEvent(lat, lon, +1, twalt, y, m, d);
227 twilight = getLMT(twilight, lon);
233 double sunset = getDaylightEvent(lat, lon, -1, rsalt, y, m, d);
237 sunset = getLMT(sunset, lon);
238 if (fabs(lt - sunset) < 0.15)
return (SUNSET);
239 if (lt < sunset)
return (DAY);
240 double twilight = getDaylightEvent(lat, lon, -1, twalt, y, m, d);
244 twilight = getLMT(twilight, lon);
252RoutePropDlgImpl::RoutePropDlgImpl(wxWindow* parent, wxWindowID
id,
253 const wxString& title,
const wxPoint& pos,
254 const wxSize& size,
long style)
258 SetColorScheme(global_color_scheme);
260 if (g_route_prop_sx > 0 && g_route_prop_sy > 0 &&
261 g_route_prop_sx < wxGetDisplaySize().x &&
262 g_route_prop_sy < wxGetDisplaySize().y) {
263 SetSize(g_route_prop_sx, g_route_prop_sy);
266 if (g_route_prop_x > 0 && g_route_prop_y > 0 &&
267 g_route_prop_x < wxGetDisplaySize().x &&
268 g_route_prop_y < wxGetDisplaySize().y) {
269 SetPosition(wxPoint(10, 10));
273 Connect(wxEVT_COMMAND_MENU_SELECTED,
274 wxCommandEventHandler(RoutePropDlgImpl::OnRoutePropMenuSelected),
278 Connect(wxEVT_ACTIVATE, wxActivateEventHandler(RoutePropDlgImpl::OnActivate),
283RoutePropDlgImpl::~RoutePropDlgImpl() {
284 Disconnect(wxEVT_COMMAND_MENU_SELECTED,
285 wxCommandEventHandler(RoutePropDlgImpl::OnRoutePropMenuSelected),
287 instanceFlag =
false;
290bool RoutePropDlgImpl::instanceFlag =
false;
291bool RoutePropDlgImpl::getInstanceFlag() {
292 return RoutePropDlgImpl::instanceFlag;
304void RoutePropDlgImpl::OnActivate(wxActivateEvent& event) {
305 auto pWin =
dynamic_cast<wxFrame*
>(
event.GetEventObject());
306 long int style = pWin->GetWindowStyle();
307 if (event.GetActive())
308 pWin->SetWindowStyle(style | wxSTAY_ON_TOP);
310 pWin->SetWindowStyle(style ^ wxSTAY_ON_TOP);
313void RoutePropDlgImpl::RecalculateSize() {
315 esize.x = GetCharWidth() * 110;
316 esize.y = GetCharHeight() * 40;
318 wxSize dsize = GetParent()->GetSize();
319 esize.y = wxMin(esize.y, dsize.y - 0 );
320 esize.x = wxMin(esize.x, dsize.x - 0 );
323 wxSize fsize = GetSize();
324 wxSize canvas_size = GetParent()->GetSize();
325 wxPoint screen_pos = GetParent()->GetScreenPosition();
326 int xp = (canvas_size.x - fsize.x) / 2;
327 int yp = (canvas_size.y - fsize.y) / 2;
328 Move(screen_pos.x + xp, screen_pos.y + yp);
331void RoutePropDlgImpl::UpdatePoints() {
332 if (!m_pRoute)
return;
333 wxDataViewItem selection = m_dvlcWaypoints->GetSelection();
334 int selected_row = m_dvlcWaypoints->GetSelectedRow();
335 m_dvlcWaypoints->DeleteAllItems();
337 wxVector<wxVariant> data;
339 m_pRoute->UpdateSegmentDistances(
341 m_tcDistance->SetValue(
342 wxString::Format(
"%5.1f " + getUsrDistanceUnit(),
344 m_tcEnroute->SetValue(formatTimeDelta(wxLongLong(m_pRoute->
m_route_time)));
347 wxString slen, eta, ete;
348 double bearing, distance, speed;
349 double totalDistance = 0;
350 wxDateTime eta_dt = wxInvalidDateTime;
353 speed = (*pnode)->GetPlannedSpeed();
358 DistanceBearingMercator((*pnode)->GetLatitude(), (*pnode)->GetLongitude(),
363 .
SetTimezone(getDatetimeTimezoneSelector(m_tz_selection))
365 eta = wxString::Format(
366 "Start: %s", ocpn::toUsrDateTimeFormat(
368 eta.Append(wxString::Format(
369 " (%s)", GetDaylightString(
370 getDaylightStatus((*pnode)->m_lat, (*pnode)->m_lon,
378 ete = formatTimeDelta(wxLongLong(3600. * distance / speed));
383 distance = (*pnode)->GetDistance();
384 bearing = (*pnode)->GetCourse();
385 if ((*pnode)->GetETA().IsValid()) {
388 .
SetTimezone(getDatetimeTimezoneSelector(m_tz_selection))
390 eta = ocpn::toUsrDateTimeFormat((*pnode)->GetETA().FromUTC(), opts);
391 eta.Append(wxString::Format(
392 " (%s)", GetDaylightString(getDaylightStatus((*pnode)->m_lat,
396 eta_dt = (*pnode)->GetETA();
400 ete = (*pnode)->GetETE();
401 totalDistance += distance;
403 wxString name = (*pnode)->GetName();
404 double lat = (*pnode)->GetLatitude();
405 double lon = (*pnode)->GetLongitude();
406 wxString tide_station = (*pnode)->m_TideStation;
407 wxString desc = (*pnode)->GetDescription();
409 if ((*pnode)->GetManualETD().IsValid()) {
414 .
SetTimezone(getDatetimeTimezoneSelector(m_tz_selection))
416 etd = ocpn::toUsrDateTimeFormat(rt->
GetManualETD().FromUTC(), opts);
427 crs = formatAngle((*pnode)->GetCourse());
433 data.push_back(wxVariant(
"---"));
435 std::ostringstream stm;
437 data.push_back(wxVariant(stm.str()));
442 schar = wxString(
" ");
444 data.push_back(wxVariant(name + schar));
445 slen.Printf(
"%5.1f " + getUsrDistanceUnit(),
toUsrDistance(distance));
446 data.push_back(wxVariant(schar + slen + schar));
447 data.push_back(wxVariant(schar + formatAngle(bearing)));
448 slen.Printf(
"%5.1f " + getUsrDistanceUnit(),
toUsrDistance(totalDistance));
449 data.push_back(wxVariant(schar + slen + schar));
450 data.push_back(wxVariant(schar + ::toSDMM(1, lat, FALSE) + schar));
451 data.push_back(wxVariant(schar + ::toSDMM(2, lon, FALSE) + schar));
452 data.push_back(wxVariant(schar + ete + schar));
453 data.push_back(schar + eta + schar);
455 wxVariant(wxString::FromDouble(toUsrSpeed(speed))));
456 data.push_back(wxVariant(
457 MakeTideInfo(tide_station, lat, lon, eta_dt)));
458 data.push_back(wxVariant(desc));
459 data.push_back(wxVariant(crs));
460 data.push_back(wxVariant(etd));
464 m_dvlcWaypoints->AppendItem(data);
468 if (selected_row > 0) {
469 m_dvlcWaypoints->SelectRow(selected_row);
470 m_dvlcWaypoints->EnsureVisible(selection);
474void RoutePropDlgImpl::SetRouteAndUpdate(
Route* pR,
bool only_points) {
475 if (NULL == pR)
return;
484 wxString title = pR->GetName() ==
"" ? _(
"Route Properties") : pR->GetName();
488 wxString caption(wxString::Format(
"%s, %s: %s", title, _(
"Layer"),
500 if (pR != m_pRoute) {
505 m_pEnroutePoint = NULL;
511 m_tcPlanSpeed->SetValue(
514 if (m_scrolledWindowLinks) {
515 wxWindowList kids = m_scrolledWindowLinks->GetChildren();
516 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
517 wxWindowListNode* node = kids.Item(i);
518 wxWindow* win = node->GetData();
519 auto link_win =
dynamic_cast<wxHyperlinkCtrl*
>(win);
521 link_win->Disconnect(
522 wxEVT_COMMAND_HYPERLINK,
523 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick));
524 link_win->Disconnect(
526 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu));
532 for (
Hyperlink* link : *m_pRoute->m_HyperlinkList) {
533 wxString Link = link->Link;
534 wxString Descr = link->DescrText;
536 wxHyperlinkCtrl* ctrl =
new wxHyperlinkCtrl(
537 m_scrolledWindowLinks, wxID_ANY, Descr, Link, wxDefaultPosition,
538 wxDefaultSize, wxHL_DEFAULT_STYLE);
540 wxEVT_COMMAND_HYPERLINK,
541 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick), NULL,
546 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu), NULL,
549 bSizerLinks->Add(ctrl, 0, wxALL, 5);
551 m_scrolledWindowLinks->InvalidateBestSize();
552 m_scrolledWindowLinks->Layout();
553 bSizerLinks->Layout();
556 m_choiceTimezone->SetSelection(m_tz_selection);
564 m_tcName->SetFocus();
581 m_btnSplit->Enable(
false);
582 if (!m_pRoute)
return;
585 m_choiceColor->Select(0);
587 for (
unsigned int i = 0; i <
sizeof(::GpxxColorNames) /
sizeof(wxString);
589 if (m_pRoute->
m_Colour == ::GpxxColorNames[i]) {
590 m_choiceColor->Select(i + 1);
596 for (
unsigned int i = 0; i <
sizeof(::StyleValues) /
sizeof(
int); i++) {
597 if (m_pRoute->
m_style == ::StyleValues[i]) {
598 m_choiceStyle->Select(i);
603 for (
unsigned int i = 0; i <
sizeof(::WidthValues) /
sizeof(
int); i++) {
604 if (m_pRoute->
m_width == ::WidthValues[i]) {
605 m_choiceWidth->Select(i);
612 m_btnExtend->Enable(IsThisRouteExtendable());
615void RoutePropDlgImpl::DepartureDateOnDateChanged(wxDateEvent& event) {
616 if (!m_pRoute)
return;
622void RoutePropDlgImpl::DepartureTimeOnTimeChanged(wxDateEvent& event) {
623 if (!m_pRoute)
return;
629void RoutePropDlgImpl::TimezoneOnChoice(wxCommandEvent& event) {
630 if (!m_pRoute)
return;
631 m_tz_selection = m_choiceTimezone->GetSelection();
640void RoutePropDlgImpl::PlanSpeedOnTextEnter(wxCommandEvent& event) {
641 if (!m_pRoute)
return;
643 if (m_tcPlanSpeed->GetValue().ToDouble(&spd)) {
649 m_tcPlanSpeed->SetValue(
654void RoutePropDlgImpl::PlanSpeedOnKillFocus(wxFocusEvent& event) {
655 if (!m_pRoute)
return;
657 if (m_tcPlanSpeed->GetValue().ToDouble(&spd)) {
663 m_tcPlanSpeed->SetValue(
670void RoutePropDlgImpl::WaypointsOnDataViewListCtrlItemEditingDone(
671 wxDataViewEvent& event) {
675 ev_col =
event.GetColumn();
678void RoutePropDlgImpl::WaypointsOnDataViewListCtrlItemValueChanged(
679 wxDataViewEvent& event) {
680#if wxCHECK_VERSION(3, 1, 2)
682 if (!m_pRoute)
return;
683 wxDataViewModel*
const model =
event.GetModel();
685 model->GetValue(value, event.GetItem(), ev_col);
687 static_cast<int>(
reinterpret_cast<long long>(event.GetItem().GetID())));
688 if (ev_col == COLUMN_PLANNED_SPEED) {
690 if (!value.GetString().ToDouble(&spd)) {
693 p->SetPlannedSpeed(fromUsrSpeed(spd));
694 }
else if (ev_col == COLUMN_ETD) {
695 wxString::const_iterator end;
698 wxString ts = value.GetString();
699 if (ts.StartsWith(
"!")) {
700 ts.Replace(
"!",
"",
true);
706 if (!etd.ParseDateTime(ts, &end)) {
707 p->
SetETD(wxInvalidDateTime);
713 p->
SetETD(wxInvalidDateTime);
720void RoutePropDlgImpl::WaypointsOnDataViewListCtrlSelectionChanged(
721 wxDataViewEvent& event) {
722 long selected_row = m_dvlcWaypoints->GetSelectedRow();
723 if (selected_row > 0 && selected_row < m_dvlcWaypoints->GetItemCount() - 1) {
724 m_btnSplit->Enable(
true);
726 m_btnSplit->Enable(
false);
728 if (IsThisRouteExtendable()) {
729 m_btnExtend->Enable(
true);
731 m_btnExtend->Enable(
false);
733 if (selected_row >= 0 && selected_row < m_dvlcWaypoints->GetItemCount()) {
734 RoutePoint* prp = m_pRoute->GetPoint(selected_row + 1);
736 if (gFrame->GetFocusCanvas()) {
737 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), prp->m_lat, prp->m_lon,
741 if (m_dvlcWaypoints) m_dvlcWaypoints->SetFocus();
757void RoutePropDlgImpl::OnRoutepropCopyTxtClick(wxCommandEvent& event) {
758 wxString tab(
"\t", wxConvUTF8);
759 wxString eol(
"\n", wxConvUTF8);
762 csvString << this->GetTitle() << eol << _(
"Name") << tab
766 << m_tcDistance->GetValue() << eol << _(
"Speed (Kts)") << tab
767 << m_tcPlanSpeed->GetValue() << eol
768 << _(
"Departure Time") +
" (" + ETA_FORMAT_STR +
")" << tab
770 << _(
"Time enroute") << tab << m_tcEnroute->GetValue() << eol
775 noCols = m_dvlcWaypoints->GetColumnCount();
776 noRows = m_dvlcWaypoints->GetItemCount();
778 item.SetMask(wxLIST_MASK_TEXT);
780 for (
int i = 0; i < noCols; i++) {
781 wxDataViewColumn* col = m_dvlcWaypoints->GetColumn(i);
782 csvString << col->GetTitle() << tab;
787 for (
int j = 0; j < noRows; j++) {
788 for (
int i = 0; i < noCols; i++) {
789 m_dvlcWaypoints->GetValue(value, j, i);
790 csvString << value.MakeString() << tab;
795 if (wxTheClipboard->Open()) {
796 wxTextDataObject* data =
new wxTextDataObject;
797 data->SetText(csvString);
798 wxTheClipboard->SetData(data);
799 wxTheClipboard->Close();
803void RoutePropDlgImpl::OnRoutePropMenuSelected(wxCommandEvent& event) {
805 switch (event.GetId()) {
806 case ID_RCLK_MENU_COPY_TEXT: {
807 OnRoutepropCopyTxtClick(event);
810 case ID_RCLK_MENU_MOVEUP_WP: {
813 case ID_RCLK_MENU_MOVEDOWN_WP: {
815 moveup ? _(
"Are you sure you want to move Up this waypoint?")
816 : _(
"Are you sure you want to move Down this waypoint?");
818 OCPNMessageBox(
this, mess, _(
"OpenCPN Move Waypoint"),
819 (
long)wxYES_NO | wxCANCEL | wxYES_DEFAULT);
821 if (dlg_return == wxID_YES) {
822 wxDataViewItem selection = m_dvlcWaypoints->GetSelection();
824 static_cast<int>(
reinterpret_cast<long long>(selection.GetID())));
826 auto pos = std::find(list->begin(), list->end(), pRP);
828 pSelect->DeleteAllSelectableRoutePoints(m_pRoute);
829 pSelect->DeleteAllSelectableRouteSegments(m_pRoute);
832 pos += moveup ? -1 : 1;
835 pSelect->AddAllSelectableRouteSegments(m_pRoute);
836 pSelect->AddAllSelectableRoutePoints(m_pRoute);
839 NavObj_dB::GetInstance().UpdateRoute(m_pRoute);
841 m_pRoute->FinalizeForRendering();
842 m_pRoute->UpdateSegmentDistances();
845 gFrame->InvalidateAllGL();
847 m_dvlcWaypoints->SelectRow(pos - list->begin());
849 SetRouteAndUpdate(m_pRoute,
true);
853 case ID_RCLK_MENU_DELETE: {
854 int dlg_return = OCPNMessageBox(
855 this, _(
"Are you sure you want to remove this waypoint?"),
856 _(
"OpenCPN Remove Waypoint"),
857 (
long)wxYES_NO | wxCANCEL | wxYES_DEFAULT);
859 if (dlg_return == wxID_YES) {
860 int sel = m_dvlcWaypoints->GetSelectedRow();
861 m_dvlcWaypoints->SelectRow(sel);
863 wxDataViewItem selection = m_dvlcWaypoints->GetSelection();
865 static_cast<int>(
reinterpret_cast<long long>(selection.GetID())));
867 g_pRouteMan->RemovePointFromRoute(pRP, m_pRoute, 0);
869 gFrame->InvalidateAllGL();
874 case ID_RCLK_MENU_EDIT_WP: {
875 wxDataViewItem selection = m_dvlcWaypoints->GetSelection();
877 static_cast<int>(
reinterpret_cast<long long>(selection.GetID())));
879 RouteManagerDialog::WptShowPropertiesDialog(pRP,
this);
885void RoutePropDlgImpl::WaypointsOnDataViewListCtrlItemContextMenu(
886 wxDataViewEvent& event) {
889 wxMenuItem* editItem =
new wxMenuItem(&menu, ID_RCLK_MENU_EDIT_WP,
890 _(
"Waypoint Properties") +
"...");
891 wxMenuItem* moveUpItem =
892 new wxMenuItem(&menu, ID_RCLK_MENU_MOVEUP_WP, _(
"Move Up"));
893 wxMenuItem* moveDownItem =
894 new wxMenuItem(&menu, ID_RCLK_MENU_MOVEDOWN_WP, _(
"Move Down"));
895 wxMenuItem* delItem =
896 new wxMenuItem(&menu, ID_RCLK_MENU_DELETE, _(
"Remove Selected"));
899 editItem->SetFont(*pf);
900 moveUpItem->SetFont(*pf);
901 moveDownItem->SetFont(*pf);
902 delItem->SetFont(*pf);
904#if defined(__WXMSW__)
906 editItem->SetFont(*pf);
907 moveUpItem->SetFont(*pf);
908 moveDownItem->SetFont(*pf);
909 delItem->SetFont(*pf);
912 menu.Append(editItem);
913 if (g_btouch) menu.AppendSeparator();
914 menu.Append(moveUpItem);
915 if (g_btouch) menu.AppendSeparator();
916 menu.Append(moveDownItem);
917 if (g_btouch) menu.AppendSeparator();
918 menu.Append(delItem);
920 editItem->Enable(m_dvlcWaypoints->GetSelectedRow() >= 0);
921 moveUpItem->Enable(m_dvlcWaypoints->GetSelectedRow() >= 1 &&
922 m_dvlcWaypoints->GetItemCount() > 2);
923 moveDownItem->Enable(m_dvlcWaypoints->GetSelectedRow() >= 0 &&
924 m_dvlcWaypoints->GetSelectedRow() <
925 m_dvlcWaypoints->GetItemCount() - 1 &&
926 m_dvlcWaypoints->GetItemCount() > 2);
927 delItem->Enable(m_dvlcWaypoints->GetSelectedRow() >= 0 &&
928 m_dvlcWaypoints->GetItemCount() > 2);
931 wxMenuItem* copyItem =
932 new wxMenuItem(&menu, ID_RCLK_MENU_COPY_TEXT, _(
"&Copy all as text"));
934#if defined(__WXMSW__)
936 copyItem->SetFont(*qFont);
939 if (g_btouch) menu.AppendSeparator();
940 menu.Append(copyItem);
946void RoutePropDlgImpl::ResetChanges() {
947 if (!m_pRoute)
return;
953void RoutePropDlgImpl::SaveChanges() {
960 if (m_choiceColor->GetSelection() == 0) {
963 m_pRoute->
m_Colour = ::GpxxColorNames[m_choiceColor->GetSelection() - 1];
966 (wxPenStyle)::StyleValues[m_choiceStyle->GetSelection()];
967 m_pRoute->
m_width = ::WidthValues[m_choiceWidth->GetSelection()];
968 switch (m_tz_selection) {
984 NavObj_dB::GetInstance().UpdateRoute(m_pRoute);
985 pConfig->UpdateSettings();
990void RoutePropDlgImpl::SetColorScheme(ColorScheme cs) { DimeControl(
this); }
992void RoutePropDlgImpl::SaveGeometry() {
993 GetSize(&g_route_prop_sx, &g_route_prop_sy);
994 GetPosition(&g_route_prop_x, &g_route_prop_y);
997void RoutePropDlgImpl::BtnsOnOKButtonClick(wxCommandEvent& event) {
999 if (pRouteManagerDialog && pRouteManagerDialog->IsShown()) {
1000 pRouteManagerDialog->UpdateRouteListCtrl();
1006void RoutePropDlgImpl::SplitOnButtonClick(wxCommandEvent& event) {
1007 m_btnSplit->Enable(
false);
1011 int nSelected = m_dvlcWaypoints->GetSelectedRow() + 1;
1012 if ((nSelected > 1) && (nSelected < m_pRoute->GetnPoints())) {
1013 m_pHead =
new Route();
1014 m_pTail =
new Route();
1015 m_pHead->CloneRoute(m_pRoute, 1, nSelected, _(
"_A"));
1016 m_pTail->CloneRoute(m_pRoute, nSelected, m_pRoute->GetnPoints(), _(
"_B"),
1020 NavObj_dB::GetInstance().InsertRoute(m_pHead);
1024 NavObj_dB::GetInstance().InsertRoute(m_pTail);
1027 NavObj_dB::GetInstance().DeleteRoute(m_pRoute);
1029 pSelect->DeleteAllSelectableRoutePoints(m_pRoute);
1030 pSelect->DeleteAllSelectableRouteSegments(m_pRoute);
1032 pSelect->AddAllSelectableRouteSegments(m_pTail);
1033 pSelect->AddAllSelectableRoutePoints(m_pTail);
1034 pSelect->AddAllSelectableRouteSegments(m_pHead);
1035 pSelect->AddAllSelectableRoutePoints(m_pHead);
1037 SetRouteAndUpdate(m_pTail);
1040 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
1041 pRouteManagerDialog->UpdateRouteListCtrl();
1045void RoutePropDlgImpl::PrintOnButtonClick(wxCommandEvent& event) {
1046 static std::set<int> s_options;
1048 int result = dlg.ShowModal();
1050 if (result == wxID_OK) {
1051 dlg.GetSelected(s_options);
1052 RoutePrintout printout(m_pRoute, s_options, m_tz_selection);
1054 printer.Initialize(wxPORTRAIT);
1055 printer.EnablePageNumbers(
true);
1056 printer.Print(
this, &printout);
1062void RoutePropDlgImpl::ExtendOnButtonClick(wxCommandEvent& event) {
1063 m_btnExtend->Enable(
false);
1065 if (IsThisRouteExtendable()) {
1066 int fm = m_pExtendRoute->GetIndexOf(m_pExtendPoint) + 1;
1067 int to = m_pExtendRoute->GetnPoints();
1069 pSelect->DeleteAllSelectableRouteSegments(m_pRoute);
1070 m_pRoute->CloneRoute(m_pExtendRoute, fm, to, _(
"_plus"));
1071 pSelect->AddAllSelectableRouteSegments(m_pRoute);
1072 SetRouteAndUpdate(m_pRoute);
1076 m_btnExtend->Enable(
true);
1079bool RoutePropDlgImpl::IsThisRouteExtendable() {
1080 m_pExtendRoute = NULL;
1081 m_pExtendPoint = NULL;
1085 RoutePoint* pLastPoint = m_pRoute->GetLastPoint();
1086 wxArrayPtrVoid* pEditRouteArray;
1091 for (i = pEditRouteArray->GetCount(); i > 0; i--) {
1092 Route* p = (
Route*)pEditRouteArray->Item(i - 1);
1093 if (!p->IsVisible() || (p->
m_GUID == m_pRoute->
m_GUID))
1094 pEditRouteArray->RemoveAt(i - 1);
1096 if (pEditRouteArray->GetCount() == 1) {
1097 m_pExtendPoint = pLastPoint;
1099 if (pEditRouteArray->GetCount() == 0) {
1100 int nearby_radius_meters =
1101 (int)(8. / gFrame->GetPrimaryCanvas()->GetCanvasTrueScale());
1102 double rlat = pLastPoint->m_lat;
1103 double rlon = pLastPoint->m_lon;
1105 m_pExtendPoint = pWayPointMan->GetOtherNearbyWaypoint(
1106 rlat, rlon, nearby_radius_meters, pLastPoint->
m_GUID);
1107 if (m_pExtendPoint) {
1108 wxArrayPtrVoid* pCloseWPRouteArray =
1110 if (pCloseWPRouteArray) {
1111 pEditRouteArray = pCloseWPRouteArray;
1114 for (i = pEditRouteArray->GetCount(); i > 0; i--) {
1115 Route* p = (
Route*)pEditRouteArray->Item(i - 1);
1116 if (!p->IsVisible() || (p->
m_GUID == m_pRoute->
m_GUID))
1117 pEditRouteArray->RemoveAt(i - 1);
1123 if (pEditRouteArray->GetCount() == 1) {
1125 int fm = p->GetIndexOf(m_pExtendPoint) + 1;
1126 int to = p->GetnPoints();
1129 delete pEditRouteArray;
1133 delete pEditRouteArray;
1138wxString RoutePropDlgImpl::MakeTideInfo(wxString stationName,
double lat,
1139 double lon, wxDateTime utcTime) {
1140 if (stationName.Find(
"lind") != wxNOT_FOUND)
int yyp = 4;
1142 if (stationName.IsEmpty()) {
1145 if (!utcTime.IsValid()) {
1146 return _(
"Invalid date/time!");
1148 int stationID =
ptcmgr->GetStationIDXbyName(stationName, lat, lon);
1149 if (stationID == 0) {
1150 return _(
"Unknown station!");
1152 time_t dtmtt = utcTime.FromUTC().GetTicks();
1153 int ev =
ptcmgr->GetNextBigEvent(&dtmtt, stationID);
1156 dtm.Set(dtmtt).MakeUTC();
1158 wxString tide_form =
"";
1161 tide_form.Append(
"LW: ");
1162 }
else if (ev == 2) {
1163 tide_form.Append(
"HW: ");
1164 }
else if (ev == 0) {
1165 tide_form.Append(_(
"Unavailable: "));
1172 .
SetTimezone(getDatetimeTimezoneSelector(m_tz_selection))
1174 wxString tideDateTime = ocpn::toUsrDateTimeFormat(dtm.FromUTC(), opts);
1175 tide_form.Append(tideDateTime);
1176 dtm.Add(wxTimeSpan(0, offset, 0));
1179 tide_form.Append(wxString::Format(
" (" + _(
"Local") +
": %s%+03d:%02d) @ %s",
1180 dtm.Format(
"%a %x %H:%M:%S"), (offset / 60),
1181 abs(offset) % 60, stationName.c_str()));
1185void RoutePropDlgImpl::ItemEditOnMenuSelection(wxCommandEvent& event) {
1186 wxString findurl = m_pEditedLink->GetURL();
1187 wxString findlabel = m_pEditedLink->GetLabel();
1190 LinkPropDlg->m_textCtrlLinkDescription->SetValue(findlabel);
1191 LinkPropDlg->m_textCtrlLinkUrl->SetValue(findurl);
1192 DimeControl(LinkPropDlg);
1193 LinkPropDlg->ShowWindowModalThenDo([
this, LinkPropDlg, findurl,
1194 findlabel](
int retcode) {
1195 if (retcode == wxID_OK) {
1196 for (
Hyperlink* link : *m_pRoute->m_HyperlinkList) {
1197 wxString Link = link->Link;
1198 wxString Descr = link->DescrText;
1199 if (Link == findurl &&
1200 (Descr == findlabel || (Link == findlabel && Descr ==
""))) {
1201 link->Link = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1202 link->DescrText = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1203 wxHyperlinkCtrl* h =
1204 (wxHyperlinkCtrl*)m_scrolledWindowLinks->FindWindowByLabel(
1207 h->SetLabel(LinkPropDlg->m_textCtrlLinkDescription->GetValue());
1208 h->SetURL(LinkPropDlg->m_textCtrlLinkUrl->GetValue());
1213 m_scrolledWindowLinks->InvalidateBestSize();
1214 m_scrolledWindowLinks->Layout();
1215 bSizerLinks->Layout();
1221void RoutePropDlgImpl::ItemAddOnMenuSelection(wxCommandEvent& event) {
1222 AddLinkOnButtonClick(event);
1226 wxString findurl = m_pEditedLink->GetURL();
1227 wxString findlabel = m_pEditedLink->GetLabel();
1229 wxWindowList kids = m_scrolledWindowLinks->GetChildren();
1230 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
1231 wxWindowListNode* node = kids.Item(i);
1232 wxWindow* win = node->GetData();
1234 auto link_win =
dynamic_cast<wxHyperlinkCtrl*
>(win);
1236 link_win->Disconnect(
1237 wxEVT_COMMAND_HYPERLINK,
1238 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick));
1239 link_win->Disconnect(
1241 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu));
1250 auto nodeToDelete = hyperlinklist->end();
1251 if (NbrOfLinks > 0) {
1252 auto it = hyperlinklist->begin();
1253 while (it != hyperlinklist->end()) {
1255 wxString Link = link->Link;
1256 wxString Descr = link->DescrText;
1257 if (Link == findurl &&
1258 (Descr == findlabel || (Link == findlabel && Descr ==
"")))
1261 wxHyperlinkCtrl* ctrl =
new wxHyperlinkCtrl(
1262 m_scrolledWindowLinks, wxID_ANY, Descr, Link, wxDefaultPosition,
1263 wxDefaultSize, wxHL_DEFAULT_STYLE);
1265 wxEVT_COMMAND_HYPERLINK,
1266 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick), NULL,
1270 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu), NULL,
1273 bSizerLinks->Add(ctrl, 0, wxALL, 5);
1278 if (nodeToDelete != hyperlinklist->end()) {
1279 hyperlinklist->erase(nodeToDelete);
1281 m_scrolledWindowLinks->InvalidateBestSize();
1282 m_scrolledWindowLinks->Layout();
1283 bSizerLinks->Layout();
1287void RoutePropDlgImpl::AddLinkOnButtonClick(wxCommandEvent& event) {
1289 LinkPropDlg->m_textCtrlLinkDescription->SetValue(
"");
1290 LinkPropDlg->m_textCtrlLinkUrl->SetValue(
"");
1291 DimeControl(LinkPropDlg);
1292 LinkPropDlg->ShowWindowModalThenDo([
this, LinkPropDlg](
int retcode) {
1293 if (retcode == wxID_OK) {
1294 wxString desc = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1295 if (desc ==
"") desc = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1296 wxHyperlinkCtrl* ctrl =
new wxHyperlinkCtrl(
1297 m_scrolledWindowLinks, wxID_ANY, desc,
1298 LinkPropDlg->m_textCtrlLinkUrl->GetValue(), wxDefaultPosition,
1299 wxDefaultSize, wxHL_DEFAULT_STYLE);
1300 ctrl->Connect(wxEVT_COMMAND_HYPERLINK,
1301 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick),
1303 ctrl->Connect(wxEVT_RIGHT_DOWN,
1304 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu),
1307 bSizerLinks->Add(ctrl, 0, wxALL, 5);
1308 m_scrolledWindowLinks->InvalidateBestSize();
1309 m_scrolledWindowLinks->Layout();
1310 bSizerLinks->Layout();
1313 h->DescrText = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1314 h->Link = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1321void RoutePropDlgImpl::BtnEditOnToggleButton(wxCommandEvent& event) {
1322 if (m_toggleBtnEdit->GetValue()) {
1323 m_stEditEnabled->SetLabel(_(
"Links are opened for editing."));
1325 m_stEditEnabled->SetLabel(_(
"Links are opened in the default browser."));
1330void RoutePropDlgImpl::OnHyperlinkClick(wxHyperlinkEvent& event) {
1331 if (m_toggleBtnEdit->GetValue()) {
1332 m_pEditedLink = (wxHyperlinkCtrl*)event.GetEventObject();
1333 ItemEditOnMenuSelection(event);
1346 wxString cc =
event.GetURL();
1347 if (cc.Find(
"#") != wxNOT_FOUND) {
1348 wxRegKey RegKey(wxString(
"HKEY_CLASSES_ROOT\\HTTP\\shell\\open\\command"));
1349 if (RegKey.Exists()) {
1350 wxString command_line;
1351 RegKey.QueryValue(wxString(
""), command_line);
1354 command_line.Replace(wxString(
"\""), wxString(
""));
1357 int l = command_line.Find(
".exe");
1358 if (wxNOT_FOUND == l) l = command_line.Find(
".EXE");
1360 if (wxNOT_FOUND != l) {
1361 wxString cl = command_line.Mid(0, l + 4);
1372 wxString url =
event.GetURL();
1373 url.Replace(
" ",
"%20");
1374 ::wxLaunchDefaultBrowser(url);
1378void RoutePropDlgImpl::HyperlinkContextMenu(wxMouseEvent& event) {
1379 m_pEditedLink = (wxHyperlinkCtrl*)event.GetEventObject();
1380 m_scrolledWindowLinks->PopupMenu(
1381 m_menuLink, m_pEditedLink->GetPosition().x +
event.GetPosition().x,
1382 m_pEditedLink->GetPosition().y +
event.GetPosition().y);
Generic Chart canvas base.
float GetVPScale()
Return the ViewPort scale factor, in physical pixels per meter.
Represents an index entry for tidal and current data.
static PrintDialog & GetInstance()
Get instance to handle the print process,.
Represents a waypoint or mark within the navigation system.
wxString m_GUID
Globally Unique Identifier for the waypoint.
wxDateTime GetManualETD()
Retrieves the manually set Estimated Time of Departure for this waypoint, in UTC.
void SetETD(const wxDateTime &etd)
Sets the Estimated Time of Departure for this waypoint, in UTC.
wxDateTime GetETA()
Retrieves the Estimated Time of Arrival for this waypoint, in UTC.
Input dialog with route print selection.
Printout route information and a table with selected route point information.
void ItemDeleteOnMenuSelection(wxCommandEvent &event)
wxDateTime GetDepartureTS()
Returns the departure time of the route, in UTC.
wxTimePickerCtrl * m_tpDepartureTime
The time picker for the departure time of the route.
wxDatePickerCtrl * m_dpDepartureDate
The date picker for the departure date of the route.
Represents a navigational route in the navigation system.
double m_PlannedSpeed
Default planned speed for the route in knots.
wxString m_RouteStartString
Name or description of the route's starting point.
wxString m_RouteDescription
Additional descriptive information about the route.
RoutePointList * pRoutePointList
Ordered list of waypoints (RoutePoints) that make up this route.
double m_route_length
Total length of the route in nautical miles, calculated using rhumb line (Mercator) distances.
bool m_bRtIsActive
Flag indicating whether this route is currently active for navigation.
wxString m_Colour
Color name for rendering the route on the chart.
wxString m_RouteEndString
Name or description of the route's ending point.
wxPenStyle m_style
Style of the route line when rendered on the chart.
wxString m_TimeDisplayFormat
Format for displaying times in the UI.
int m_width
Width of the route line in pixels when rendered on the chart.
wxString m_RouteNameString
User-assigned name for the route.
wxString m_GUID
Globally unique identifier for this route.
wxDateTime m_PlannedDeparture
Planned departure time for the route, in UTC.
bool m_bIsInLayer
Flag indicating whether this route belongs to a layer.
double m_route_time
Total estimated time to complete the route in seconds.
void SetDepartureDate(const wxDateTime &dt)
Set the departure time of the route.
HyperlinkList * m_HyperlinkList
List of hyperlinks associated with this route.
int m_LayerID
Identifier of the layer containing this route.
wxArrayPtrVoid * GetRouteArrayContaining(RoutePoint *pWP)
Find all routes that contain the given waypoint.
bool DeleteRoute(Route *pRoute)
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
General purpose GUI support.
Waypoint properties maintenance dialog.
MySQL based storage for routes, tracks, etc.
wxDateTime toUsrDateTime(const wxDateTime ts, const int format, const double lon)
Converts a timestamp from UTC to the user's preferred time format.
wxDateTime fromUsrDateTime(const wxDateTime ts, const int format, const double lon)
Converts a timestamp from a user's preferred time format to UTC.
double toUsrDistance(double nm_distance, int unit)
Convert a distance from nautical miles (NMi) to user display units.
Navigation Utility Functions without GUI dependencies.
PlugIn Object Definition/API.
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
double gLat
Vessel's current latitude in decimal degrees.
double gLon
Vessel's current longitude in decimal degrees.
Position, course, speed, etc.
Generic, styled prit dialog.
#define LMTINPUT
Format date/time using the remote location LMT time.
#define GLOBAL_SETTINGS_INPUT
Format date/time according to global OpenCPN settings.
RoutePropDlgImpl * pRoutePropDialog
Global instance.
#define UTCINPUT
Format date/time in UTC.
#define LTINPUT
Format date/time using timezone configured in the operating system./*#end#*/.
Routeman * g_pRouteMan
Global instance.
RouteList * pRouteList
Global instance.
Select * pSelect
Global instance.
Selected route, segment, waypoint, etc.
TCMgr * ptcmgr
Global instance.
Tide and Current Manager @TODO Add original author copyright.