24#include <wx/clipbrd.h>
53#define GLOBAL_SETTINGS_INPUT 3
55#define ID_RCLK_MENU_COPY_TEXT 7013
56#define ID_RCLK_MENU_EDIT_WP 7014
57#define ID_RCLK_MENU_DELETE 7015
58#define ID_RCLK_MENU_MOVEUP_WP 7026
59#define ID_RCLK_MENU_MOVEDOWN_WP 7027
61#define COLUMN_PLANNED_SPEED 9
65#define PI (4. * atan(1.0))
68#define DEGS (180. / PI)
69#define RADS (PI / 180.)
81extern wxString GetLayerName(
int id);
89static wxString GetDaylightString(
int index) {
94 return _(
"MoTwilight");
102 return _(
"EvTwilight");
104 return _(
"Nighttime");
111static double sign(
double x) {
118static double FNipart(
double x) {
return (sign(x) * (
int)(fabs(x))); }
120static double FNday(
int y,
int m,
int d,
int h) {
121 long fd = (367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9 + d);
122 return ((
double)fd - 730531.5 + h / 24.);
125static double FNrange(
double x) {
127 double a = TPI * (b - FNipart(b));
128 if (a < 0.) a = TPI + a;
132static double getDaylightEvent(
double glat,
double glong,
int riset,
133 double altitude,
int y,
int m,
int d) {
134 double day = FNday(y, m, d, 0);
135 double days, correction;
139 sin(altitude * RADS);
140 double sinphi = sin(glat * RADS);
141 double cosphi = cos(glat * RADS);
142 double g = glong * RADS;
143 double t, L, G, ec, lambda, E, obl, delta, GHA, cosc;
145 while ((fabs(utold - utnew) > .001)) {
146 if (limit-- <= 0)
return (-1.);
147 days = day + utnew / TPI;
150 L = FNrange(4.8949504201433 + 628.331969753199 * t);
151 G = FNrange(6.2400408 + 628.3019501 * t);
152 ec = .033423 * sin(G) + .00034907 * sin(2 * G);
154 E = -1. * ec + .0430398 * sin(2 * lambda) - .00092502 * sin(4. * lambda);
155 obl = .409093 - .0002269 * t;
156 delta = asin(sin(obl) * sin(lambda));
157 GHA = utold - PI + E;
158 cosc = (sinalt - sinphi * sin(delta)) / (cosphi * cos(delta));
164 correction = acos(cosc);
166 utnew = FNrange(utold - (GHA + g + riset * correction));
169 return (utnew * DEGS / 15.);
172static double getLMT(
double ut,
double lon) {
173 double t = ut + lon / 15.;
186static wxString getDatetimeTimezoneSelector(
int selection) {
200static int getDaylightStatus(
double lat,
double lon, wxDateTime utcDateTime) {
201 if (fabs(lat) > 60.)
return (0);
202 int y = utcDateTime.GetYear();
203 int m = utcDateTime.GetMonth() + 1;
204 int d = utcDateTime.GetDay();
205 int h = utcDateTime.GetHour();
206 int n = utcDateTime.GetMinute();
207 int s = utcDateTime.GetSecond();
208 if (y < 2000 || y > 2100)
return (0);
210 double ut = (double)h + (
double)n / 60. + (double)s / 3600.;
211 double lt = getLMT(ut, lon);
212 double rsalt = -0.833;
216 double sunrise = getDaylightEvent(lat, lon, +1, rsalt, y, m, d);
220 sunrise = getLMT(sunrise, lon);
222 if (fabs(lt - sunrise) < 0.15)
return (SUNRISE);
223 if (lt > sunrise)
return (DAY);
224 double twilight = getDaylightEvent(lat, lon, +1, twalt, y, m, d);
228 twilight = getLMT(twilight, lon);
234 double sunset = getDaylightEvent(lat, lon, -1, rsalt, y, m, d);
238 sunset = getLMT(sunset, lon);
239 if (fabs(lt - sunset) < 0.15)
return (SUNSET);
240 if (lt < sunset)
return (DAY);
241 double twilight = getDaylightEvent(lat, lon, -1, twalt, y, m, d);
245 twilight = getLMT(twilight, lon);
253RoutePropDlgImpl::RoutePropDlgImpl(wxWindow* parent, wxWindowID
id,
254 const wxString& title,
const wxPoint& pos,
255 const wxSize& size,
long style)
259 SetColorScheme(global_color_scheme);
261 if (g_route_prop_sx > 0 && g_route_prop_sy > 0 &&
262 g_route_prop_sx < wxGetDisplaySize().x &&
263 g_route_prop_sy < wxGetDisplaySize().y) {
264 SetSize(g_route_prop_sx, g_route_prop_sy);
267 if (g_route_prop_x > 0 && g_route_prop_y > 0 &&
268 g_route_prop_x < wxGetDisplaySize().x &&
269 g_route_prop_y < wxGetDisplaySize().y) {
270 SetPosition(wxPoint(10, 10));
274 Connect(wxEVT_COMMAND_MENU_SELECTED,
275 wxCommandEventHandler(RoutePropDlgImpl::OnRoutePropMenuSelected),
279 Connect(wxEVT_ACTIVATE, wxActivateEventHandler(RoutePropDlgImpl::OnActivate),
284RoutePropDlgImpl::~RoutePropDlgImpl() {
285 Disconnect(wxEVT_COMMAND_MENU_SELECTED,
286 wxCommandEventHandler(RoutePropDlgImpl::OnRoutePropMenuSelected),
288 instanceFlag =
false;
291bool RoutePropDlgImpl::instanceFlag =
false;
292bool RoutePropDlgImpl::getInstanceFlag() {
293 return RoutePropDlgImpl::instanceFlag;
305void RoutePropDlgImpl::OnActivate(wxActivateEvent& event) {
306 auto pWin =
dynamic_cast<wxFrame*
>(
event.GetEventObject());
307 long int style = pWin->GetWindowStyle();
308 if (event.GetActive())
309 pWin->SetWindowStyle(style | wxSTAY_ON_TOP);
311 pWin->SetWindowStyle(style ^ wxSTAY_ON_TOP);
314void RoutePropDlgImpl::RecalculateSize() {
316 esize.x = GetCharWidth() * 110;
317 esize.y = GetCharHeight() * 40;
319 wxSize dsize = GetParent()->GetSize();
320 esize.y = wxMin(esize.y, dsize.y - 0 );
321 esize.x = wxMin(esize.x, dsize.x - 0 );
324 wxSize fsize = GetSize();
325 wxSize canvas_size = GetParent()->GetSize();
326 wxPoint screen_pos = GetParent()->GetScreenPosition();
327 int xp = (canvas_size.x - fsize.x) / 2;
328 int yp = (canvas_size.y - fsize.y) / 2;
329 Move(screen_pos.x + xp, screen_pos.y + yp);
332void RoutePropDlgImpl::UpdatePoints() {
333 if (!m_pRoute)
return;
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);
471 int count = m_dvlcWaypoints->GetItemCount();
472 if (selected_row >= 0 && count > 0) {
473 m_dvlcWaypoints->SelectRow(selected_row < count ? selected_row : count - 1);
474 wxDataViewItem selection = m_dvlcWaypoints->GetSelection();
475 if (selection.IsOk()) m_dvlcWaypoints->EnsureVisible(selection);
479void RoutePropDlgImpl::SetRouteAndUpdate(
Route* pR,
bool only_points) {
480 if (NULL == pR)
return;
489 wxString title = pR->GetName() ==
"" ? _(
"Route Properties") : pR->GetName();
493 wxString caption(wxString::Format(
"%s, %s: %s", title, _(
"Layer"),
504 if (pR != m_pRoute) {
513 m_pEnroutePoint = NULL;
519 m_tcPlanSpeed->SetValue(
522 if (m_scrolledWindowLinks) {
523 wxWindowList kids = m_scrolledWindowLinks->GetChildren();
524 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
525 wxWindowListNode* node = kids.Item(i);
526 wxWindow* win = node->GetData();
527 auto link_win =
dynamic_cast<wxHyperlinkCtrl*
>(win);
529 link_win->Disconnect(
530 wxEVT_COMMAND_HYPERLINK,
531 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick));
532 link_win->Disconnect(
534 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu));
540 for (
Hyperlink* link : *m_pRoute->m_HyperlinkList) {
541 wxString Link = link->Link;
542 wxString Descr = link->DescrText;
544 wxHyperlinkCtrl* ctrl =
new wxHyperlinkCtrl(
545 m_scrolledWindowLinks, wxID_ANY, Descr, Link, wxDefaultPosition,
546 wxDefaultSize, wxHL_DEFAULT_STYLE);
548 wxEVT_COMMAND_HYPERLINK,
549 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick), NULL,
554 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu), NULL,
557 bSizerLinks->Add(ctrl, 0, wxALL, 5);
559 m_scrolledWindowLinks->InvalidateBestSize();
560 m_scrolledWindowLinks->Layout();
561 bSizerLinks->Layout();
564 m_choiceTimezone->SetSelection(m_tz_selection);
572 m_tcName->SetFocus();
589 m_btnSplit->Enable(
false);
590 if (!m_pRoute)
return;
593 m_choiceColor->Select(0);
595 for (
unsigned int i = 0; i <
sizeof(::GpxxColorNames) /
sizeof(wxString);
597 if (m_pRoute->
m_Colour == ::GpxxColorNames[i]) {
598 m_choiceColor->Select(i + 1);
604 for (
unsigned int i = 0; i <
sizeof(::StyleValues) /
sizeof(
int); i++) {
605 if (m_pRoute->
m_style == ::StyleValues[i]) {
606 m_choiceStyle->Select(i);
611 for (
unsigned int i = 0; i <
sizeof(::WidthValues) /
sizeof(
int); i++) {
612 if (m_pRoute->
m_width == ::WidthValues[i]) {
613 m_choiceWidth->Select(i);
620 m_btnExtend->Enable(IsThisRouteExtendable());
623void RoutePropDlgImpl::DepartureDateOnDateChanged(wxDateEvent& event) {
624 if (!m_pRoute)
return;
630void RoutePropDlgImpl::DepartureTimeOnTimeChanged(wxDateEvent& event) {
631 if (!m_pRoute)
return;
637void RoutePropDlgImpl::TimezoneOnChoice(wxCommandEvent& event) {
638 if (!m_pRoute)
return;
639 m_tz_selection = m_choiceTimezone->GetSelection();
648void RoutePropDlgImpl::PlanSpeedOnTextEnter(wxCommandEvent& event) {
649 if (!m_pRoute)
return;
651 if (m_tcPlanSpeed->GetValue().ToDouble(&spd)) {
657 m_tcPlanSpeed->SetValue(
662void RoutePropDlgImpl::PlanSpeedOnKillFocus(wxFocusEvent& event) {
663 if (!m_pRoute)
return;
665 if (m_tcPlanSpeed->GetValue().ToDouble(&spd)) {
671 m_tcPlanSpeed->SetValue(
678void RoutePropDlgImpl::WaypointsOnDataViewListCtrlItemEditingDone(
679 wxDataViewEvent& event) {
683 ev_col =
event.GetColumn();
686void RoutePropDlgImpl::WaypointsOnDataViewListCtrlItemValueChanged(
687 wxDataViewEvent& event) {
688#if wxCHECK_VERSION(3, 1, 2)
690 if (!m_pRoute)
return;
691 wxDataViewModel*
const model =
event.GetModel();
693 model->GetValue(value, event.GetItem(), ev_col);
695 static_cast<int>(
reinterpret_cast<long long>(event.GetItem().GetID())));
696 if (ev_col == COLUMN_PLANNED_SPEED) {
698 if (!value.GetString().ToDouble(&spd)) {
701 p->SetPlannedSpeed(fromUsrSpeed(spd));
702 }
else if (ev_col == COLUMN_ETD) {
703 wxString::const_iterator end;
706 wxString ts = value.GetString();
707 if (ts.StartsWith(
"!")) {
708 ts.Replace(
"!",
"",
true);
714 if (!etd.ParseDateTime(ts, &end)) {
715 p->
SetETD(wxInvalidDateTime);
721 p->
SetETD(wxInvalidDateTime);
728void RoutePropDlgImpl::WaypointsOnDataViewListCtrlSelectionChanged(
729 wxDataViewEvent& event) {
730 long selected_row = m_dvlcWaypoints->GetSelectedRow();
731 if (selected_row > 0 && selected_row < m_dvlcWaypoints->GetItemCount() - 1) {
732 m_btnSplit->Enable(
true);
734 m_btnSplit->Enable(
false);
736 if (IsThisRouteExtendable()) {
737 m_btnExtend->Enable(
true);
739 m_btnExtend->Enable(
false);
741 if (selected_row >= 0 && selected_row < m_dvlcWaypoints->GetItemCount()) {
742 RoutePoint* prp = m_pRoute->GetPoint(selected_row + 1);
744 top_frame::Get()->JumpToPosition(prp->m_lat, prp->m_lon);
746 if (m_dvlcWaypoints) m_dvlcWaypoints->SetFocus();
762void RoutePropDlgImpl::OnRoutepropCopyTxtClick(wxCommandEvent& event) {
763 wxString tab(
"\t", wxConvUTF8);
764 wxString eol(
"\n", wxConvUTF8);
767 csvString << this->GetTitle() << eol << _(
"Name") << tab
771 << m_tcDistance->GetValue() << eol << _(
"Speed (Kts)") << tab
772 << m_tcPlanSpeed->GetValue() << eol
773 << _(
"Departure Time") +
" (" + ETA_FORMAT_STR +
")" << tab
775 << _(
"Time enroute") << tab << m_tcEnroute->GetValue() << eol
780 noCols = m_dvlcWaypoints->GetColumnCount();
781 noRows = m_dvlcWaypoints->GetItemCount();
783 item.SetMask(wxLIST_MASK_TEXT);
785 for (
int i = 0; i < noCols; i++) {
786 wxDataViewColumn* col = m_dvlcWaypoints->GetColumn(i);
787 csvString << col->GetTitle() << tab;
792 for (
int j = 0; j < noRows; j++) {
793 for (
int i = 0; i < noCols; i++) {
794 m_dvlcWaypoints->GetValue(value, j, i);
795 csvString << value.MakeString() << tab;
800 if (wxTheClipboard->Open()) {
801 wxTextDataObject* data =
new wxTextDataObject;
802 data->SetText(csvString);
803 wxTheClipboard->SetData(data);
804 wxTheClipboard->Close();
808void RoutePropDlgImpl::OnRoutePropMenuSelected(wxCommandEvent& event) {
810 switch (event.GetId()) {
811 case ID_RCLK_MENU_COPY_TEXT: {
812 OnRoutepropCopyTxtClick(event);
815 case ID_RCLK_MENU_MOVEUP_WP: {
818 case ID_RCLK_MENU_MOVEDOWN_WP: {
820 moveup ? _(
"Are you sure you want to move Up this waypoint?")
821 : _(
"Are you sure you want to move Down this waypoint?");
823 OCPNMessageBox(
this, mess, _(
"OpenCPN Move Waypoint"),
824 (
long)wxYES_NO | wxCANCEL | wxYES_DEFAULT);
826 if (dlg_return == wxID_YES) {
827 wxDataViewItem selection = m_dvlcWaypoints->GetSelection();
829 static_cast<int>(
reinterpret_cast<long long>(selection.GetID())));
831 auto pos = std::find(list->begin(), list->end(), pRP);
833 pSelect->DeleteAllSelectableRoutePoints(m_pRoute);
834 pSelect->DeleteAllSelectableRouteSegments(m_pRoute);
837 pos += moveup ? -1 : 1;
840 pSelect->AddAllSelectableRouteSegments(m_pRoute);
841 pSelect->AddAllSelectableRoutePoints(m_pRoute);
844 NavObj_dB::GetInstance().UpdateRoute(m_pRoute);
846 m_pRoute->FinalizeForRendering();
847 m_pRoute->UpdateSegmentDistances();
850 top_frame::Get()->InvalidateAllGL();
852 m_dvlcWaypoints->SelectRow(pos - list->begin());
854 SetRouteAndUpdate(m_pRoute,
true);
858 case ID_RCLK_MENU_DELETE: {
859 int dlg_return = OCPNMessageBox(
860 this, _(
"Are you sure you want to remove this waypoint?"),
861 _(
"OpenCPN Remove Waypoint"),
862 (
long)wxYES_NO | wxCANCEL | wxYES_DEFAULT);
864 if (dlg_return == wxID_YES) {
865 int sel = m_dvlcWaypoints->GetSelectedRow();
866 m_dvlcWaypoints->SelectRow(sel);
868 wxDataViewItem selection = m_dvlcWaypoints->GetSelection();
870 static_cast<int>(
reinterpret_cast<long long>(selection.GetID())));
872 g_pRouteMan->RemovePointFromRoute(pRP, m_pRoute, 0);
874 top_frame::Get()->InvalidateAllGL();
879 case ID_RCLK_MENU_EDIT_WP: {
880 wxDataViewItem selection = m_dvlcWaypoints->GetSelection();
882 static_cast<int>(
reinterpret_cast<long long>(selection.GetID())));
884 RouteManagerDialog::WptShowPropertiesDialog(pRP,
this);
890void RoutePropDlgImpl::WaypointsOnDataViewListCtrlItemContextMenu(
891 wxDataViewEvent& event) {
894 wxMenuItem* editItem =
new wxMenuItem(&menu, ID_RCLK_MENU_EDIT_WP,
895 _(
"Waypoint Properties") +
"...");
896 wxMenuItem* moveUpItem =
897 new wxMenuItem(&menu, ID_RCLK_MENU_MOVEUP_WP, _(
"Move Up"));
898 wxMenuItem* moveDownItem =
899 new wxMenuItem(&menu, ID_RCLK_MENU_MOVEDOWN_WP, _(
"Move Down"));
900 wxMenuItem* delItem =
901 new wxMenuItem(&menu, ID_RCLK_MENU_DELETE, _(
"Remove Selected"));
904 editItem->SetFont(*pf);
905 moveUpItem->SetFont(*pf);
906 moveDownItem->SetFont(*pf);
907 delItem->SetFont(*pf);
909#if defined(__WXMSW__)
911 editItem->SetFont(*pf);
912 moveUpItem->SetFont(*pf);
913 moveDownItem->SetFont(*pf);
914 delItem->SetFont(*pf);
917 menu.Append(editItem);
918 if (g_btouch) menu.AppendSeparator();
919 menu.Append(moveUpItem);
920 if (g_btouch) menu.AppendSeparator();
921 menu.Append(moveDownItem);
922 if (g_btouch) menu.AppendSeparator();
923 menu.Append(delItem);
925 editItem->Enable(m_dvlcWaypoints->GetSelectedRow() >= 0);
926 moveUpItem->Enable(m_dvlcWaypoints->GetSelectedRow() >= 1 &&
927 m_dvlcWaypoints->GetItemCount() > 2);
928 moveDownItem->Enable(m_dvlcWaypoints->GetSelectedRow() >= 0 &&
929 m_dvlcWaypoints->GetSelectedRow() <
930 m_dvlcWaypoints->GetItemCount() - 1 &&
931 m_dvlcWaypoints->GetItemCount() > 2);
932 delItem->Enable(m_dvlcWaypoints->GetSelectedRow() >= 0 &&
933 m_dvlcWaypoints->GetItemCount() > 2);
936 wxMenuItem* copyItem =
937 new wxMenuItem(&menu, ID_RCLK_MENU_COPY_TEXT, _(
"&Copy all as text"));
939#if defined(__WXMSW__)
941 copyItem->SetFont(*qFont);
944 if (g_btouch) menu.AppendSeparator();
945 menu.Append(copyItem);
951void RoutePropDlgImpl::ResetChanges() {
952 if (!m_pRoute)
return;
958void RoutePropDlgImpl::SaveChanges() {
965 if (m_choiceColor->GetSelection() == 0) {
968 m_pRoute->
m_Colour = ::GpxxColorNames[m_choiceColor->GetSelection() - 1];
971 (wxPenStyle)::StyleValues[m_choiceStyle->GetSelection()];
972 m_pRoute->
m_width = ::WidthValues[m_choiceWidth->GetSelection()];
973 switch (m_tz_selection) {
989 NavObj_dB::GetInstance().UpdateRoute(m_pRoute);
995void RoutePropDlgImpl::SetColorScheme(ColorScheme cs) { DimeControl(
this); }
997void RoutePropDlgImpl::SaveGeometry() {
998 GetSize(&g_route_prop_sx, &g_route_prop_sy);
999 GetPosition(&g_route_prop_x, &g_route_prop_y);
1002void RoutePropDlgImpl::BtnsOnOKButtonClick(wxCommandEvent& event) {
1011void RoutePropDlgImpl::SplitOnButtonClick(wxCommandEvent& event) {
1012 m_btnSplit->Enable(
false);
1016 int nSelected = m_dvlcWaypoints->GetSelectedRow() + 1;
1017 if ((nSelected > 1) && (nSelected < m_pRoute->GetnPoints())) {
1018 m_pHead =
new Route();
1019 m_pTail =
new Route();
1020 m_pHead->CloneRoute(m_pRoute, 1, nSelected, _(
"_A"));
1021 m_pTail->CloneRoute(m_pRoute, nSelected, m_pRoute->GetnPoints(), _(
"_B"),
1025 NavObj_dB::GetInstance().InsertRoute(m_pHead);
1029 NavObj_dB::GetInstance().InsertRoute(m_pTail);
1032 NavObj_dB::GetInstance().DeleteRoute(m_pRoute);
1034 pSelect->DeleteAllSelectableRoutePoints(m_pRoute);
1035 pSelect->DeleteAllSelectableRouteSegments(m_pRoute);
1037 pSelect->AddAllSelectableRouteSegments(m_pTail);
1038 pSelect->AddAllSelectableRoutePoints(m_pTail);
1039 pSelect->AddAllSelectableRouteSegments(m_pHead);
1040 pSelect->AddAllSelectableRoutePoints(m_pHead);
1042 SetRouteAndUpdate(m_pTail);
1050void RoutePropDlgImpl::PrintOnButtonClick(wxCommandEvent& event) {
1052 int result = dlg.ShowModal();
1054 if (result == wxID_OK) {
1057 printer.Initialize(wxPORTRAIT);
1058 printer.EnablePageNumbers(
true);
1059 printer.Print(
this, &printout);
1065void RoutePropDlgImpl::ExtendOnButtonClick(wxCommandEvent& event) {
1066 m_btnExtend->Enable(
false);
1068 if (IsThisRouteExtendable()) {
1069 int extend_idx = m_pExtendRoute->GetIndexOf(m_pExtendPoint);
1070 if (extend_idx < 0) {
1071 m_btnExtend->Enable(
true);
1074 int fm = extend_idx + 1;
1075 int to = m_pExtendRoute->GetnPoints();
1077 pSelect->DeleteAllSelectableRouteSegments(m_pRoute);
1078 m_pRoute->CloneRoute(m_pExtendRoute, fm, to, _(
"_plus"));
1079 pSelect->AddAllSelectableRouteSegments(m_pRoute);
1080 SetRouteAndUpdate(m_pRoute);
1084 m_btnExtend->Enable(
true);
1087bool RoutePropDlgImpl::IsThisRouteExtendable() {
1088 m_pExtendRoute = NULL;
1089 m_pExtendPoint = NULL;
1093 RoutePoint* pLastPoint = m_pRoute->GetLastPoint();
1094 wxArrayPtrVoid* pEditRouteArray;
1099 for (i = pEditRouteArray->GetCount(); i > 0; i--) {
1100 Route* p = (
Route*)pEditRouteArray->Item(i - 1);
1101 if (!p->IsVisible() || (p->
m_GUID == m_pRoute->
m_GUID))
1102 pEditRouteArray->RemoveAt(i - 1);
1104 if (pEditRouteArray->GetCount() == 1) {
1105 m_pExtendPoint = pLastPoint;
1107 if (pEditRouteArray->GetCount() == 0) {
1108 int nearby_radius_meters =
1109 (int)(8. / top_frame::Get()->GetCanvasTrueScale());
1110 double rlat = pLastPoint->m_lat;
1111 double rlon = pLastPoint->m_lon;
1113 m_pExtendPoint = pWayPointMan->GetOtherNearbyWaypoint(
1114 rlat, rlon, nearby_radius_meters, pLastPoint->
m_GUID);
1115 if (m_pExtendPoint) {
1116 wxArrayPtrVoid* pCloseWPRouteArray =
1118 if (pCloseWPRouteArray) {
1119 pEditRouteArray = pCloseWPRouteArray;
1122 for (i = pEditRouteArray->GetCount(); i > 0; i--) {
1123 Route* p = (
Route*)pEditRouteArray->Item(i - 1);
1124 if (!p->IsVisible() || (p->
m_GUID == m_pRoute->
m_GUID))
1125 pEditRouteArray->RemoveAt(i - 1);
1131 if (pEditRouteArray->GetCount() == 1) {
1133 int extend_idx = p->GetIndexOf(m_pExtendPoint);
1134 if (extend_idx < 0) {
1135 delete pEditRouteArray;
1138 int fm = extend_idx + 1;
1139 int to = p->GetnPoints();
1142 delete pEditRouteArray;
1146 delete pEditRouteArray;
1151wxString RoutePropDlgImpl::MakeTideInfo(wxString stationName,
double lat,
1152 double lon, wxDateTime utcTime) {
1153 if (stationName.Find(
"lind") != wxNOT_FOUND)
int yyp = 4;
1155 if (stationName.IsEmpty()) {
1158 if (!utcTime.IsValid()) {
1159 return _(
"Invalid date/time!");
1161 int stationID =
ptcmgr->GetStationIDXbyName(stationName, lat, lon);
1162 if (stationID == 0) {
1163 return _(
"Unknown station!");
1165 time_t dtmtt = utcTime.FromUTC().GetTicks();
1166 int ev =
ptcmgr->GetNextBigEvent(&dtmtt, stationID);
1169 dtm.Set(dtmtt).MakeUTC();
1171 wxString tide_form =
"";
1174 tide_form.Append(
"LW: ");
1175 }
else if (ev == 2) {
1176 tide_form.Append(
"HW: ");
1177 }
else if (ev == 0) {
1178 tide_form.Append(_(
"Unavailable: "));
1185 .
SetTimezone(getDatetimeTimezoneSelector(m_tz_selection))
1187 wxString tideDateTime = ocpn::toUsrDateTimeFormat(dtm.FromUTC(), opts);
1188 tide_form.Append(tideDateTime);
1189 dtm.Add(wxTimeSpan(0, offset, 0));
1192 tide_form.Append(wxString::Format(
" (" + _(
"Local") +
": %s%+03d:%02d) @ %s",
1193 dtm.Format(
"%a %x %H:%M:%S"), (offset / 60),
1194 abs(offset) % 60, stationName.c_str()));
1198void RoutePropDlgImpl::ItemEditOnMenuSelection(wxCommandEvent& event) {
1199 wxString findurl = m_pEditedLink->GetURL();
1200 wxString findlabel = m_pEditedLink->GetLabel();
1203 LinkPropDlg->m_textCtrlLinkDescription->SetValue(findlabel);
1204 LinkPropDlg->m_textCtrlLinkUrl->SetValue(findurl);
1205 DimeControl(LinkPropDlg);
1206 LinkPropDlg->ShowWindowModalThenDo([
this, LinkPropDlg, findurl,
1207 findlabel](
int retcode) {
1208 if (retcode == wxID_OK) {
1209 for (
Hyperlink* link : *m_pRoute->m_HyperlinkList) {
1210 wxString Link = link->Link;
1211 wxString Descr = link->DescrText;
1212 if (Link == findurl &&
1213 (Descr == findlabel || (Link == findlabel && Descr ==
""))) {
1214 link->Link = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1215 link->DescrText = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1216 wxHyperlinkCtrl* h =
1217 (wxHyperlinkCtrl*)m_scrolledWindowLinks->FindWindowByLabel(
1220 h->SetLabel(LinkPropDlg->m_textCtrlLinkDescription->GetValue());
1221 h->SetURL(LinkPropDlg->m_textCtrlLinkUrl->GetValue());
1226 m_scrolledWindowLinks->InvalidateBestSize();
1227 m_scrolledWindowLinks->Layout();
1228 bSizerLinks->Layout();
1234void RoutePropDlgImpl::ItemAddOnMenuSelection(wxCommandEvent& event) {
1235 AddLinkOnButtonClick(event);
1239 wxString findurl = m_pEditedLink->GetURL();
1240 wxString findlabel = m_pEditedLink->GetLabel();
1242 wxWindowList kids = m_scrolledWindowLinks->GetChildren();
1243 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
1244 wxWindowListNode* node = kids.Item(i);
1245 wxWindow* win = node->GetData();
1247 auto link_win =
dynamic_cast<wxHyperlinkCtrl*
>(win);
1249 link_win->Disconnect(
1250 wxEVT_COMMAND_HYPERLINK,
1251 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick));
1252 link_win->Disconnect(
1254 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu));
1263 auto nodeToDelete = hyperlinklist->end();
1264 if (NbrOfLinks > 0) {
1265 auto it = hyperlinklist->begin();
1266 while (it != hyperlinklist->end()) {
1268 wxString Link = link->Link;
1269 wxString Descr = link->DescrText;
1270 if (Link == findurl &&
1271 (Descr == findlabel || (Link == findlabel && Descr ==
"")))
1274 wxHyperlinkCtrl* ctrl =
new wxHyperlinkCtrl(
1275 m_scrolledWindowLinks, wxID_ANY, Descr, Link, wxDefaultPosition,
1276 wxDefaultSize, wxHL_DEFAULT_STYLE);
1278 wxEVT_COMMAND_HYPERLINK,
1279 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick), NULL,
1283 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu), NULL,
1286 bSizerLinks->Add(ctrl, 0, wxALL, 5);
1291 if (nodeToDelete != hyperlinklist->end()) {
1292 hyperlinklist->erase(nodeToDelete);
1294 m_scrolledWindowLinks->InvalidateBestSize();
1295 m_scrolledWindowLinks->Layout();
1296 bSizerLinks->Layout();
1300void RoutePropDlgImpl::AddLinkOnButtonClick(wxCommandEvent& event) {
1302 LinkPropDlg->m_textCtrlLinkDescription->SetValue(
"");
1303 LinkPropDlg->m_textCtrlLinkUrl->SetValue(
"");
1304 DimeControl(LinkPropDlg);
1305 LinkPropDlg->ShowWindowModalThenDo([
this, LinkPropDlg](
int retcode) {
1306 if (retcode == wxID_OK) {
1307 wxString desc = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1308 if (desc ==
"") desc = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1309 wxHyperlinkCtrl* ctrl =
new wxHyperlinkCtrl(
1310 m_scrolledWindowLinks, wxID_ANY, desc,
1311 LinkPropDlg->m_textCtrlLinkUrl->GetValue(), wxDefaultPosition,
1312 wxDefaultSize, wxHL_DEFAULT_STYLE);
1313 ctrl->Connect(wxEVT_COMMAND_HYPERLINK,
1314 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick),
1316 ctrl->Connect(wxEVT_RIGHT_DOWN,
1317 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu),
1320 bSizerLinks->Add(ctrl, 0, wxALL, 5);
1321 m_scrolledWindowLinks->InvalidateBestSize();
1322 m_scrolledWindowLinks->Layout();
1323 bSizerLinks->Layout();
1326 h->DescrText = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1327 h->Link = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1334void RoutePropDlgImpl::BtnEditOnToggleButton(wxCommandEvent& event) {
1335 if (m_toggleBtnEdit->GetValue()) {
1336 m_stEditEnabled->SetLabel(_(
"Links are opened for editing."));
1338 m_stEditEnabled->SetLabel(_(
"Links are opened in the default browser."));
1343void RoutePropDlgImpl::OnHyperlinkClick(wxHyperlinkEvent& event) {
1344 if (m_toggleBtnEdit->GetValue()) {
1345 m_pEditedLink = (wxHyperlinkCtrl*)event.GetEventObject();
1346 ItemEditOnMenuSelection(event);
1359 wxString cc =
event.GetURL();
1360 if (cc.Find(
"#") != wxNOT_FOUND) {
1361 wxRegKey RegKey(wxString(
"HKEY_CLASSES_ROOT\\HTTP\\shell\\open\\command"));
1362 if (RegKey.Exists()) {
1363 wxString command_line;
1364 RegKey.QueryValue(wxString(
""), command_line);
1367 command_line.Replace(wxString(
"\""), wxString(
""));
1370 int l = command_line.Find(
".exe");
1371 if (wxNOT_FOUND == l) l = command_line.Find(
".EXE");
1373 if (wxNOT_FOUND != l) {
1374 wxString cl = command_line.Mid(0, l + 4);
1385 wxString url =
event.GetURL();
1386 url.Replace(
" ",
"%20");
1387 ::wxLaunchDefaultBrowser(url);
1391void RoutePropDlgImpl::HyperlinkContextMenu(wxMouseEvent& event) {
1392 m_pEditedLink = (wxHyperlinkCtrl*)event.GetEventObject();
1393 m_scrolledWindowLinks->PopupMenu(
1394 m_menuLink, m_pEditedLink->GetPosition().x +
event.GetPosition().x,
1395 m_pEditedLink->GetPosition().y +
event.GetPosition().y);
Generic Chart canvas base.
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.
MyConfig * pConfig
Global instance.
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.
RouteManagerDialog * pRouteManagerDialog
Global instance.
Select * pSelect
Global instance.
Selected route, segment, waypoint, etc.
TCMgr * ptcmgr
Global instance.
Tide and Current Manager @TODO Add original author copyright.
Abstract gFrame/MyFrame interface.