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) {
1051 static std::set<int> s_options;
1053 int result = dlg.ShowModal();
1055 if (result == wxID_OK) {
1056 dlg.GetSelected(s_options);
1057 RoutePrintout printout(m_pRoute, s_options, m_tz_selection);
1059 printer.Initialize(wxPORTRAIT);
1060 printer.EnablePageNumbers(
true);
1061 printer.Print(
this, &printout);
1067void RoutePropDlgImpl::ExtendOnButtonClick(wxCommandEvent& event) {
1068 m_btnExtend->Enable(
false);
1070 if (IsThisRouteExtendable()) {
1071 int extend_idx = m_pExtendRoute->GetIndexOf(m_pExtendPoint);
1072 if (extend_idx < 0) {
1073 m_btnExtend->Enable(
true);
1076 int fm = extend_idx + 1;
1077 int to = m_pExtendRoute->GetnPoints();
1079 pSelect->DeleteAllSelectableRouteSegments(m_pRoute);
1080 m_pRoute->CloneRoute(m_pExtendRoute, fm, to, _(
"_plus"));
1081 pSelect->AddAllSelectableRouteSegments(m_pRoute);
1082 SetRouteAndUpdate(m_pRoute);
1086 m_btnExtend->Enable(
true);
1089bool RoutePropDlgImpl::IsThisRouteExtendable() {
1090 m_pExtendRoute = NULL;
1091 m_pExtendPoint = NULL;
1095 RoutePoint* pLastPoint = m_pRoute->GetLastPoint();
1096 wxArrayPtrVoid* pEditRouteArray;
1101 for (i = pEditRouteArray->GetCount(); i > 0; i--) {
1102 Route* p = (
Route*)pEditRouteArray->Item(i - 1);
1103 if (!p->IsVisible() || (p->
m_GUID == m_pRoute->
m_GUID))
1104 pEditRouteArray->RemoveAt(i - 1);
1106 if (pEditRouteArray->GetCount() == 1) {
1107 m_pExtendPoint = pLastPoint;
1109 if (pEditRouteArray->GetCount() == 0) {
1110 int nearby_radius_meters =
1111 (int)(8. / top_frame::Get()->GetCanvasTrueScale());
1112 double rlat = pLastPoint->m_lat;
1113 double rlon = pLastPoint->m_lon;
1115 m_pExtendPoint = pWayPointMan->GetOtherNearbyWaypoint(
1116 rlat, rlon, nearby_radius_meters, pLastPoint->
m_GUID);
1117 if (m_pExtendPoint) {
1118 wxArrayPtrVoid* pCloseWPRouteArray =
1120 if (pCloseWPRouteArray) {
1121 pEditRouteArray = pCloseWPRouteArray;
1124 for (i = pEditRouteArray->GetCount(); i > 0; i--) {
1125 Route* p = (
Route*)pEditRouteArray->Item(i - 1);
1126 if (!p->IsVisible() || (p->
m_GUID == m_pRoute->
m_GUID))
1127 pEditRouteArray->RemoveAt(i - 1);
1133 if (pEditRouteArray->GetCount() == 1) {
1135 int extend_idx = p->GetIndexOf(m_pExtendPoint);
1136 if (extend_idx < 0) {
1137 delete pEditRouteArray;
1140 int fm = extend_idx + 1;
1141 int to = p->GetnPoints();
1144 delete pEditRouteArray;
1148 delete pEditRouteArray;
1153wxString RoutePropDlgImpl::MakeTideInfo(wxString stationName,
double lat,
1154 double lon, wxDateTime utcTime) {
1155 if (stationName.Find(
"lind") != wxNOT_FOUND)
int yyp = 4;
1157 if (stationName.IsEmpty()) {
1160 if (!utcTime.IsValid()) {
1161 return _(
"Invalid date/time!");
1163 int stationID =
ptcmgr->GetStationIDXbyName(stationName, lat, lon);
1164 if (stationID == 0) {
1165 return _(
"Unknown station!");
1167 time_t dtmtt = utcTime.FromUTC().GetTicks();
1168 int ev =
ptcmgr->GetNextBigEvent(&dtmtt, stationID);
1171 dtm.Set(dtmtt).MakeUTC();
1173 wxString tide_form =
"";
1176 tide_form.Append(
"LW: ");
1177 }
else if (ev == 2) {
1178 tide_form.Append(
"HW: ");
1179 }
else if (ev == 0) {
1180 tide_form.Append(_(
"Unavailable: "));
1187 .
SetTimezone(getDatetimeTimezoneSelector(m_tz_selection))
1189 wxString tideDateTime = ocpn::toUsrDateTimeFormat(dtm.FromUTC(), opts);
1190 tide_form.Append(tideDateTime);
1191 dtm.Add(wxTimeSpan(0, offset, 0));
1194 tide_form.Append(wxString::Format(
" (" + _(
"Local") +
": %s%+03d:%02d) @ %s",
1195 dtm.Format(
"%a %x %H:%M:%S"), (offset / 60),
1196 abs(offset) % 60, stationName.c_str()));
1200void RoutePropDlgImpl::ItemEditOnMenuSelection(wxCommandEvent& event) {
1201 wxString findurl = m_pEditedLink->GetURL();
1202 wxString findlabel = m_pEditedLink->GetLabel();
1205 LinkPropDlg->m_textCtrlLinkDescription->SetValue(findlabel);
1206 LinkPropDlg->m_textCtrlLinkUrl->SetValue(findurl);
1207 DimeControl(LinkPropDlg);
1208 LinkPropDlg->ShowWindowModalThenDo([
this, LinkPropDlg, findurl,
1209 findlabel](
int retcode) {
1210 if (retcode == wxID_OK) {
1211 for (
Hyperlink* link : *m_pRoute->m_HyperlinkList) {
1212 wxString Link = link->Link;
1213 wxString Descr = link->DescrText;
1214 if (Link == findurl &&
1215 (Descr == findlabel || (Link == findlabel && Descr ==
""))) {
1216 link->Link = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1217 link->DescrText = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1218 wxHyperlinkCtrl* h =
1219 (wxHyperlinkCtrl*)m_scrolledWindowLinks->FindWindowByLabel(
1222 h->SetLabel(LinkPropDlg->m_textCtrlLinkDescription->GetValue());
1223 h->SetURL(LinkPropDlg->m_textCtrlLinkUrl->GetValue());
1228 m_scrolledWindowLinks->InvalidateBestSize();
1229 m_scrolledWindowLinks->Layout();
1230 bSizerLinks->Layout();
1236void RoutePropDlgImpl::ItemAddOnMenuSelection(wxCommandEvent& event) {
1237 AddLinkOnButtonClick(event);
1241 wxString findurl = m_pEditedLink->GetURL();
1242 wxString findlabel = m_pEditedLink->GetLabel();
1244 wxWindowList kids = m_scrolledWindowLinks->GetChildren();
1245 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
1246 wxWindowListNode* node = kids.Item(i);
1247 wxWindow* win = node->GetData();
1249 auto link_win =
dynamic_cast<wxHyperlinkCtrl*
>(win);
1251 link_win->Disconnect(
1252 wxEVT_COMMAND_HYPERLINK,
1253 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick));
1254 link_win->Disconnect(
1256 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu));
1265 auto nodeToDelete = hyperlinklist->end();
1266 if (NbrOfLinks > 0) {
1267 auto it = hyperlinklist->begin();
1268 while (it != hyperlinklist->end()) {
1270 wxString Link = link->Link;
1271 wxString Descr = link->DescrText;
1272 if (Link == findurl &&
1273 (Descr == findlabel || (Link == findlabel && Descr ==
"")))
1276 wxHyperlinkCtrl* ctrl =
new wxHyperlinkCtrl(
1277 m_scrolledWindowLinks, wxID_ANY, Descr, Link, wxDefaultPosition,
1278 wxDefaultSize, wxHL_DEFAULT_STYLE);
1280 wxEVT_COMMAND_HYPERLINK,
1281 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick), NULL,
1285 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu), NULL,
1288 bSizerLinks->Add(ctrl, 0, wxALL, 5);
1293 if (nodeToDelete != hyperlinklist->end()) {
1294 hyperlinklist->erase(nodeToDelete);
1296 m_scrolledWindowLinks->InvalidateBestSize();
1297 m_scrolledWindowLinks->Layout();
1298 bSizerLinks->Layout();
1302void RoutePropDlgImpl::AddLinkOnButtonClick(wxCommandEvent& event) {
1304 LinkPropDlg->m_textCtrlLinkDescription->SetValue(
"");
1305 LinkPropDlg->m_textCtrlLinkUrl->SetValue(
"");
1306 DimeControl(LinkPropDlg);
1307 LinkPropDlg->ShowWindowModalThenDo([
this, LinkPropDlg](
int retcode) {
1308 if (retcode == wxID_OK) {
1309 wxString desc = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1310 if (desc ==
"") desc = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1311 wxHyperlinkCtrl* ctrl =
new wxHyperlinkCtrl(
1312 m_scrolledWindowLinks, wxID_ANY, desc,
1313 LinkPropDlg->m_textCtrlLinkUrl->GetValue(), wxDefaultPosition,
1314 wxDefaultSize, wxHL_DEFAULT_STYLE);
1315 ctrl->Connect(wxEVT_COMMAND_HYPERLINK,
1316 wxHyperlinkEventHandler(RoutePropDlgImpl::OnHyperlinkClick),
1318 ctrl->Connect(wxEVT_RIGHT_DOWN,
1319 wxMouseEventHandler(RoutePropDlgImpl::HyperlinkContextMenu),
1322 bSizerLinks->Add(ctrl, 0, wxALL, 5);
1323 m_scrolledWindowLinks->InvalidateBestSize();
1324 m_scrolledWindowLinks->Layout();
1325 bSizerLinks->Layout();
1328 h->DescrText = LinkPropDlg->m_textCtrlLinkDescription->GetValue();
1329 h->Link = LinkPropDlg->m_textCtrlLinkUrl->GetValue();
1336void RoutePropDlgImpl::BtnEditOnToggleButton(wxCommandEvent& event) {
1337 if (m_toggleBtnEdit->GetValue()) {
1338 m_stEditEnabled->SetLabel(_(
"Links are opened for editing."));
1340 m_stEditEnabled->SetLabel(_(
"Links are opened in the default browser."));
1345void RoutePropDlgImpl::OnHyperlinkClick(wxHyperlinkEvent& event) {
1346 if (m_toggleBtnEdit->GetValue()) {
1347 m_pEditedLink = (wxHyperlinkCtrl*)event.GetEventObject();
1348 ItemEditOnMenuSelection(event);
1361 wxString cc =
event.GetURL();
1362 if (cc.Find(
"#") != wxNOT_FOUND) {
1363 wxRegKey RegKey(wxString(
"HKEY_CLASSES_ROOT\\HTTP\\shell\\open\\command"));
1364 if (RegKey.Exists()) {
1365 wxString command_line;
1366 RegKey.QueryValue(wxString(
""), command_line);
1369 command_line.Replace(wxString(
"\""), wxString(
""));
1372 int l = command_line.Find(
".exe");
1373 if (wxNOT_FOUND == l) l = command_line.Find(
".EXE");
1375 if (wxNOT_FOUND != l) {
1376 wxString cl = command_line.Mid(0, l + 4);
1387 wxString url =
event.GetURL();
1388 url.Replace(
" ",
"%20");
1389 ::wxLaunchDefaultBrowser(url);
1393void RoutePropDlgImpl::HyperlinkContextMenu(wxMouseEvent& event) {
1394 m_pEditedLink = (wxHyperlinkCtrl*)event.GetEventObject();
1395 m_scrolledWindowLinks->PopupMenu(
1396 m_menuLink, m_pEditedLink->GetPosition().x +
event.GetPosition().x,
1397 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.