20#include <wx/textctrl.h>
22#include <wx/tokenzr.h>
23#include <wx/clipbrd.h>
26#include "androidUTIL.h"
47static int g_AisTargetList_count;
49static bool g_bAisTargetList_autosort;
54EVT_CLOSE(AISTargetListDialog::OnClose)
57static
bool g_bsort_once;
63 bool b_cmptype_num =
false;
66 if (!g_bAisTargetList_autosort && !g_bsort_once)
return 0;
71 if (t1->Class == AIS_SART) {
72 if (t2->Class == AIS_DSC)
78 if (t2->Class == AIS_SART) {
79 if (t1->Class == AIS_DSC)
85 switch (g_AisTargetList_sortColumn) {
87 n1 = t1->b_show_track;
88 n2 = t2->b_show_track;
93 s1 = trimAISField(t1->ShipName);
94 if ((!t1->b_nameValid && (t1->Class == AIS_BASE)) ||
95 (t1->Class == AIS_SART))
98 s2 = trimAISField(t2->ShipName);
99 if ((!t2->b_nameValid && (t2->Class == AIS_BASE)) ||
100 (t2->Class == AIS_SART))
105 s1 = trimAISField(t1->CallSign);
106 s2 = trimAISField(t2->CallSign);
112 b_cmptype_num =
true;
116 s1 = t1->Get_class_string(
true);
117 s2 = t2->Get_class_string(
true);
121 s1 = t1->Get_vessel_type_string(
false);
122 if ((t1->Class == AIS_BASE) ||
123 (t1->Class == AIS_SART || (t1->Class == AIS_METEO)))
126 s2 = t2->Get_vessel_type_string(
false);
127 if ((t1->Class == AIS_BASE) || (t1->Class == AIS_SART) ||
128 (t1->Class == AIS_METEO))
133 s1 = t1->GetCountryCode(
true);
134 s2 = t2->GetCountryCode(
true);
137 if ((t1->NavStatus <= 15) && (t1->NavStatus >= 0)) {
138 if (t1->Class == AIS_SART) {
139 if (t1->NavStatus == RESERVED_14)
141 else if (t1->NavStatus == UNDEFINED)
144 s1 = ais_get_status(t1->NavStatus);
148 if ((t1->Class == AIS_ATON) || (t1->Class == AIS_BASE) ||
149 (t1->Class == AIS_CLASS_B) || (t1->Class == AIS_METEO))
152 if ((t2->NavStatus <= 15) && (t2->NavStatus >= 0)) {
153 if (t2->Class == AIS_SART) {
154 if (t2->NavStatus == RESERVED_14)
156 else if (t2->NavStatus == UNDEFINED)
159 s2 = ais_get_status(t2->NavStatus);
163 if ((t2->Class == AIS_ATON) || (t2->Class == AIS_BASE) ||
164 (t2->Class == AIS_CLASS_B) || (t2->Class == AIS_METEO))
171 int brg1 = wxRound(t1->Brg);
177 int brg2 = wxRound(t2->Brg);
183 b_cmptype_num =
true;
188 if ((t1->COG >= 360.0) || (t1->Class == AIS_ATON) ||
189 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
192 int crs = wxRound(t1->COG);
199 if ((t2->COG >= 360.0) || (t2->Class == AIS_ATON) ||
200 (t2->Class == AIS_BASE) || (t2->Class == AIS_METEO))
203 int crs = wxRound(t2->COG);
210 b_cmptype_num =
true;
215 if ((t1->SOG > 100.) || (t1->Class == AIS_ATON) ||
216 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
221 if ((t2->SOG > 100.) || (t2->Class == AIS_ATON) ||
222 (t2->Class == AIS_BASE) || (t2->Class == AIS_METEO))
227 b_cmptype_num =
true;
231 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
232 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
237 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
238 (t2->Class == AIS_BASE))
243 b_cmptype_num =
true;
247 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
248 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
253 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
254 (t2->Class == AIS_BASE) || (t2->Class == AIS_METEO))
259 b_cmptype_num =
true;
265 b_cmptype_num =
true;
273 if (!b_cmptype_num) {
274 if (g_bAisTargetList_sortReverse)
return s2.Cmp(s1);
278 if (g_bAisTargetList_sortReverse) {
284 return (t1->Range_NM > t2->Range_NM);
291 return (t1->Range_NM > t2->Range_NM);
296static int ArrayItemCompareMMSI(
int MMSI1,
int MMSI2) {
297 if (s_p_sort_decoder) {
298 std::shared_ptr<AisTargetData> pAISTarget1 =
299 s_p_sort_decoder->Get_Target_Data_From_MMSI(MMSI1);
300 std::shared_ptr<AisTargetData> pAISTarget2 =
301 s_p_sort_decoder->Get_Target_Data_From_MMSI(MMSI2);
303 if (pAISTarget1 && pAISTarget2)
304 return ItemCompare(pAISTarget1.get(), pAISTarget2.get());
311AISTargetListDialog::AISTargetListDialog(wxWindow *parent, wxAuiManager *auimgr,
313 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, -1 ),
316 m_pAuiManager = auimgr;
317 m_pdecoder = pdecoder;
318 g_bsort_once =
false;
319 m_bautosort_force =
false;
324 s_p_sort_decoder = pdecoder;
325 m_pMMSI_array =
new ArrayOfMMSI(ArrayItemCompareMMSI);
330 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
336 wxAuiPaneInfo paneproto = wxAuiPaneInfo()
337 .Name(
"AISTargetList")
338 .CaptionVisible(
true)
340 .FloatingPosition(50, 50)
341 .FloatingSize(400, 200)
342 .BestSize(700, GetCharHeight() * 10);
346 paneproto.Caption(wxGetTranslation(_(
"AIS target list")));
347 paneproto.Name(
"AISTargetList");
348 paneproto.DestroyOnClose(
true);
349 paneproto.TopDockable(
false)
350 .BottomDockable(
true)
352 .RightDockable(
false);
353 paneproto.Show(
true);
355 m_pAuiManager->AddPane(
this, paneproto);
357 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(
"AISTargetList");
359 if (g_AisTargetList_perspective.IsEmpty()) {
360 if (!g_btouch) RecalculateSize();
362 m_pAuiManager->LoadPaneInfo(g_AisTargetList_perspective, pane);
363 m_pAuiManager->Update();
366 pane = m_pAuiManager->GetPane(
"AISTargetList");
371 pane.Dockable(
false);
373 wxSize screen_size = top_frame::Get()->GetClientSize();
374 pane.FloatingSize(screen_size.x * 8 / 10, screen_size.y * 8 / 10);
375 pane.FloatingPosition(screen_size.x * 1 / 10, screen_size.y * 1 / 10);
376 m_pAuiManager->Update();
379 bool b_reset_pos =
false;
380 if ((pane.floating_size.x != -1) && (pane.floating_size.y != -1)) {
385 RECT frame_title_rect;
386 frame_title_rect.left = pane.floating_pos.x;
387 frame_title_rect.top = pane.floating_pos.y;
388 frame_title_rect.right = pane.floating_pos.x + pane.floating_size.x;
389 frame_title_rect.bottom = pane.floating_pos.y + 30;
391 if (NULL == MonitorFromRect(&frame_title_rect, MONITOR_DEFAULTTONULL))
397 wxRect window_title_rect;
398 window_title_rect.x = pane.floating_pos.x;
399 window_title_rect.y = pane.floating_pos.y;
400 window_title_rect.width = pane.floating_size.x;
401 window_title_rect.height = 30;
403 wxRect ClientRect = wxGetClientDisplayRect();
406 if (!ClientRect.Intersects(window_title_rect)) b_reset_pos =
true;
411 pane.FloatingPosition(50, 50);
412 m_pAuiManager->Update();
418 if (pane.IsDocked() && (pane.dock_row == 0)) {
422 m_pAuiManager->Update();
426 m_pAuiManager->Update();
428 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
431 m_pAuiManager->Connect(
432 wxEVT_AUI_PANE_CLOSE,
433 wxAuiManagerEventHandler(AISTargetListDialog::OnPaneClose), NULL,
this);
440 esize.y = GetCharHeight() * 10;
445 Connect(wxEVT_CONTEXT_MENU,
446 wxCommandEventHandler(AISTargetListDialog::OnRightClickContext), NULL,
450AISTargetListDialog::~AISTargetListDialog() {
451 Disconnect_decoder();
455void AISTargetListDialog::RecalculateSize() {
459 esize.x = GetCharWidth() * 110;
460 esize.y = GetCharHeight() * 40;
462 wxSize dsize = top_frame::Get()->GetClientSize();
463 esize.y = wxMin(esize.y, dsize.y - (4 * GetCharHeight()));
464 esize.x = wxMin(esize.x, dsize.x - (2 * GetCharHeight()));
465 SetClientSize(esize);
467 wxSize fsize = GetSize();
468 fsize.y = wxMin(fsize.y, dsize.y - (2 * GetCharHeight()));
469 fsize.x = wxMin(fsize.x, dsize.x - (2 * GetCharHeight()));
473 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(
"AISTargetList");
476 pane.FloatingSize(fsize.x, fsize.y);
477 wxPoint pos = top_frame::Get()->GetScreenPosition();
478 pane.FloatingPosition(pos.x + (dsize.x - fsize.x) / 2,
479 pos.y + (dsize.y - fsize.y) / 2);
482 m_pAuiManager->Update();
486void AISTargetListDialog::CreateControls() {
487 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
490 this->GetHandle()->setStyleSheet(getQtStyleSheet());
494 wxStringTokenizer tkz(g_AisTargetList_column_spec,
";");
495 wxString s_width = tkz.GetNextToken();
499 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
502 flags |= wxLC_VIRTUAL;
506 this, ID_AIS_TARGET_LIST, wxDefaultPosition, wxDefaultSize, flags);
508 wxImageList *imglist =
new wxImageList(16, 16,
true, 2);
511 imglist->Add(style->GetIcon(
"sort_asc"));
512 imglist->Add(style->GetIcon(
"sort_desc"));
514 m_pListCtrlAISTargets->AssignImageList(imglist, wxIMAGE_LIST_SMALL);
515 m_pListCtrlAISTargets->Connect(
516 wxEVT_COMMAND_LIST_ITEM_SELECTED,
517 wxListEventHandler(AISTargetListDialog::OnTargetSelected), NULL,
this);
518 m_pListCtrlAISTargets->Connect(
519 wxEVT_COMMAND_LIST_ITEM_DESELECTED,
520 wxListEventHandler(AISTargetListDialog::OnTargetSelected), NULL,
this);
521 m_pListCtrlAISTargets->Connect(
522 wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
523 wxListEventHandler(AISTargetListDialog::OnTargetDefaultAction), NULL,
525 m_pListCtrlAISTargets->Connect(
526 wxEVT_COMMAND_LIST_COL_CLICK,
527 wxListEventHandler(AISTargetListDialog::OnTargetListColumnClicked), NULL,
530 int dx = GetCharWidth();
533 if (s_width.ToLong(&lwidth)) {
534 width = wxMax(dx * 2, lwidth);
535 width = wxMin(width, dx * 30);
537 m_pListCtrlAISTargets->InsertColumn(tlTRK, _(
"Trk"), wxLIST_FORMAT_LEFT,
539 s_width = tkz.GetNextToken();
542 if (s_width.ToLong(&lwidth)) {
543 width = wxMax(dx * 2, lwidth);
544 width = wxMin(width, dx * 30);
546 m_pListCtrlAISTargets->InsertColumn(tlNAME, _(
"Name"), wxLIST_FORMAT_LEFT,
548 s_width = tkz.GetNextToken();
551 if (s_width.ToLong(&lwidth)) {
552 width = wxMax(dx * 2, lwidth);
553 width = wxMin(width, dx * 30);
555 m_pListCtrlAISTargets->InsertColumn(tlCALL, _(
"Call"), wxLIST_FORMAT_LEFT,
557 s_width = tkz.GetNextToken();
560 if (s_width.ToLong(&lwidth)) {
561 width = wxMax(dx * 2, lwidth);
562 width = wxMin(width, dx * 30);
564 m_pListCtrlAISTargets->InsertColumn(tlMMSI, _(
"MMSI"), wxLIST_FORMAT_LEFT,
566 s_width = tkz.GetNextToken();
569 if (s_width.ToLong(&lwidth)) {
570 width = wxMax(dx * 2, lwidth);
571 width = wxMin(width, dx * 30);
573 m_pListCtrlAISTargets->InsertColumn(tlCLASS, _(
"Class"), wxLIST_FORMAT_CENTER,
575 s_width = tkz.GetNextToken();
578 if (s_width.ToLong(&lwidth)) {
579 width = wxMax(dx * 2, lwidth);
580 width = wxMin(width, dx * 30);
582 m_pListCtrlAISTargets->InsertColumn(tlTYPE, _(
"Type"), wxLIST_FORMAT_LEFT,
584 s_width = tkz.GetNextToken();
587 if (s_width.ToLong(&lwidth)) {
588 width = wxMax(dx * 2, lwidth);
589 width = wxMin(width, dx * 30);
591 m_pListCtrlAISTargets->InsertColumn(tlNAVSTATUS, _(
"Flag"),
592 wxLIST_FORMAT_LEFT, width);
593 s_width = tkz.GetNextToken();
596 if (s_width.ToLong(&lwidth)) {
597 width = wxMax(dx * 2, lwidth);
598 width = wxMin(width, dx * 30);
600 m_pListCtrlAISTargets->InsertColumn(tlNAVSTATUS, _(
"Nav Status"),
601 wxLIST_FORMAT_LEFT, width);
602 s_width = tkz.GetNextToken();
605 if (s_width.ToLong(&lwidth)) {
606 width = wxMax(dx * 2, lwidth);
607 width = wxMin(width, dx * 30);
609 m_pListCtrlAISTargets->InsertColumn(tlBRG, _(
"Brg"), wxLIST_FORMAT_RIGHT,
611 s_width = tkz.GetNextToken();
614 if (s_width.ToLong(&lwidth)) {
615 width = wxMax(dx * 2, lwidth);
616 width = wxMin(width, dx * 30);
618 m_pListCtrlAISTargets->InsertColumn(tlRNG, _(
"Range"), wxLIST_FORMAT_RIGHT,
620 s_width = tkz.GetNextToken();
623 if (s_width.ToLong(&lwidth)) {
624 width = wxMax(dx * 2, lwidth);
625 width = wxMin(width, dx * 30);
627 m_pListCtrlAISTargets->InsertColumn(tlCOG, _(
"CoG"), wxLIST_FORMAT_RIGHT,
629 s_width = tkz.GetNextToken();
632 if (s_width.ToLong(&lwidth)) {
633 width = wxMax(dx * 2, lwidth);
634 width = wxMin(width, dx * 30);
636 m_pListCtrlAISTargets->InsertColumn(tlSOG, _(
"SoG"), wxLIST_FORMAT_RIGHT,
640 if (s_width.ToLong(&lwidth)) {
641 width = wxMax(dx * 2, lwidth);
642 width = wxMin(width, dx * 30);
644 m_pListCtrlAISTargets->InsertColumn(tlCPA, _(
"CPA"), wxLIST_FORMAT_RIGHT,
648 if (s_width.ToLong(&lwidth)) {
649 width = wxMax(dx * 2, lwidth);
650 width = wxMin(width, dx * 30);
652 m_pListCtrlAISTargets->InsertColumn(tlTCPA, _(
"TCPA"), wxLIST_FORMAT_RIGHT,
655 item.SetMask(wxLIST_MASK_IMAGE);
656 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
657 g_AisTargetList_sortColumn = wxMax(g_AisTargetList_sortColumn, 0);
658 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
660#ifdef wxHAS_LISTCTRL_COLUMN_ORDER
661 wxStringTokenizer tkz_order(g_AisTargetList_column_order,
";");
662 wxString s_order = tkz_order.GetNextToken();
663 int i_columns = m_pListCtrlAISTargets->GetColumnCount();
664 wxArrayInt a_order(i_columns);
665 for (
int i = 0; i < i_columns; i++) {
666 long l_order = (long)i;
667 s_order.ToLong(&l_order);
668 if (l_order < 0 || l_order > i_columns) {
671 a_order[i] = l_order;
672 s_order = tkz_order.GetNextToken();
675 m_pListCtrlAISTargets->SetColumnsOrder(a_order);
678 topSizer->Add(m_pListCtrlAISTargets, 1, wxEXPAND | wxALL, 0);
680 wxBoxSizer *boxSizer02 =
new wxBoxSizer(wxVERTICAL);
681 boxSizer02->AddSpacer(22);
682 topSizer->Add(boxSizer02, 0, wxEXPAND | wxALL, 2);
684 wxScrolledWindow *winr =
685 new wxScrolledWindow(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
686 wxNO_BORDER | wxTAB_TRAVERSAL | wxVSCROLL);
687 winr->SetScrollRate(0, 5);
689 boxSizer02->Add(winr, 1, wxALL | wxEXPAND, 3);
691 wxBoxSizer *bsRouteButtonsInner =
new wxBoxSizer(wxVERTICAL);
692 winr->SetSizer(bsRouteButtonsInner);
694 m_pButtonInfo =
new wxButton(winr, wxID_ANY, _(
"Target info"),
695 wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
696 m_pButtonInfo->Connect(
697 wxEVT_COMMAND_BUTTON_CLICKED,
698 wxCommandEventHandler(AISTargetListDialog::OnTargetQuery), NULL,
this);
699 bsRouteButtonsInner->Add(m_pButtonInfo, 0, wxEXPAND | wxALL, 2);
700 bsRouteButtonsInner->AddSpacer(5);
703 new wxButton(winr, wxID_ANY, _(
"Center view"), wxDefaultPosition,
704 wxDefaultSize, wxBU_AUTODRAW);
705 m_pButtonJumpTo->Connect(
706 wxEVT_COMMAND_BUTTON_CLICKED,
707 wxCommandEventHandler(AISTargetListDialog::OnTargetScrollTo), NULL,
this);
708 bsRouteButtonsInner->Add(m_pButtonJumpTo, 0, wxEXPAND | wxALL, 2);
710 m_pButtonJumpTo_Close =
711 new wxButton(winr, wxID_ANY, _(
"Center-Info-Close"), wxDefaultPosition,
712 wxDefaultSize, wxBU_AUTODRAW);
713 m_pButtonJumpTo_Close->Connect(
714 wxEVT_COMMAND_BUTTON_CLICKED,
715 wxCommandEventHandler(AISTargetListDialog::OnTargetScrollToClose), NULL,
717 bsRouteButtonsInner->Add(m_pButtonJumpTo_Close, 0, wxEXPAND | wxALL, 2);
720 new wxButton(winr, wxID_ANY, _(
"Create WPT"), wxDefaultPosition,
721 wxDefaultSize, wxBU_AUTODRAW);
722 m_pButtonCreateWpt->Connect(
723 wxEVT_COMMAND_BUTTON_CLICKED,
724 wxCommandEventHandler(AISTargetListDialog::OnTargetCreateWpt), NULL,
726 bsRouteButtonsInner->Add(m_pButtonCreateWpt, 0, wxEXPAND | wxALL, 0);
728 m_pButtonHideAllTracks =
729 new wxButton(winr, wxID_ANY, _(
"Hide All Tracks"), wxDefaultPosition,
730 wxDefaultSize, wxBU_AUTODRAW);
731 m_pButtonHideAllTracks->Connect(
732 wxEVT_COMMAND_BUTTON_CLICKED,
733 wxCommandEventHandler(AISTargetListDialog::OnHideAllTracks), NULL,
this);
734 bsRouteButtonsInner->Add(m_pButtonHideAllTracks, 0, wxEXPAND | wxALL, 2);
736 m_pButtonShowAllTracks =
737 new wxButton(winr, wxID_ANY, _(
"Show All Tracks"), wxDefaultPosition,
738 wxDefaultSize, wxBU_AUTODRAW);
739 m_pButtonShowAllTracks->Connect(
740 wxEVT_COMMAND_BUTTON_CLICKED,
741 wxCommandEventHandler(AISTargetListDialog::OnShowAllTracks), NULL,
this);
742 bsRouteButtonsInner->Add(m_pButtonShowAllTracks, 0, wxEXPAND | wxALL, 2);
744 m_pButtonToggleTrack =
745 new wxButton(winr, wxID_ANY, _(
"Toggle track"), wxDefaultPosition,
746 wxDefaultSize, wxBU_AUTODRAW);
747 m_pButtonToggleTrack->Connect(
748 wxEVT_COMMAND_BUTTON_CLICKED,
749 wxCommandEventHandler(AISTargetListDialog::OnToggleTrack), NULL,
this);
750 bsRouteButtonsInner->Add(m_pButtonToggleTrack, 0, wxEXPAND | wxALL, 2);
753 new wxButton(winr, wxID_ANY, _(
"Copy MMSI"), wxDefaultPosition,
754 wxDefaultSize, wxBU_AUTODRAW);
755 m_pButtonCopyMMSI->Connect(
756 wxEVT_COMMAND_BUTTON_CLICKED,
757 wxCommandEventHandler(AISTargetListDialog::OnCopyMMSI), NULL,
this);
758 bsRouteButtonsInner->Add(m_pButtonCopyMMSI, 0, wxEXPAND | wxALL, 2);
760 bool enable_find =
true;
763 auto *frame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
765 wxMenuBar *mb = frame->GetMenuBar();
766 if (mb !=
nullptr) enable_find =
false;
770 m_pStaticTextFind =
new wxStaticText(winr, wxID_ANY, _(
"Find target name"),
771 wxDefaultPosition, wxDefaultSize, 0);
772 bsRouteButtonsInner->Add(m_pStaticTextFind, 0, wxALL, 2);
775 new wxTextCtrl(winr, wxID_ANY,
"", wxDefaultPosition, wxDefaultSize, 0);
776 m_pFindTargetName->SetMinSize(wxSize(15 * GetCharWidth(), -1));
777 bsRouteButtonsInner->Add(m_pFindTargetName, 0, wxALL, 2);
779 m_pFindTargetName->Enable();
780 m_pFindTargetName->Connect(
782 wxCommandEventHandler(AISTargetListDialog::OnEditFindTarget), NULL,
785 m_pFindTargetName->Disable();
786 m_pFindTargetName->SetDefaultStyle(wxTextAttr(wxNullColour, *wxLIGHT_GREY));
787 m_pStaticTextFind->SetToolTip(
788 _(
"Disable OpenCPN MenuBar to search for AIS targets"));
792 new wxCheckBox(winr, wxID_ANY, _(
"AutoSort"), wxDefaultPosition,
793 wxDefaultSize, wxBU_AUTODRAW);
794 m_pCBAutosort->Connect(
795 wxEVT_COMMAND_CHECKBOX_CLICKED,
796 wxCommandEventHandler(AISTargetListDialog::OnAutosortCB), NULL,
this);
797 bsRouteButtonsInner->Add(m_pCBAutosort, 0, wxEXPAND | wxALL, 2);
798 g_bAisTargetList_autosort =
true;
799 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
801 bsRouteButtonsInner->AddSpacer(10);
803 m_pStaticTextRange =
new wxStaticText(winr, wxID_ANY, _(
"Limit range: NM"),
804 wxDefaultPosition, wxDefaultSize, 0);
805 bsRouteButtonsInner->Add(m_pStaticTextRange, 0, wxALL, 2);
806 bsRouteButtonsInner->AddSpacer(2);
807 m_pSpinCtrlRange =
new wxSpinCtrl(
808 winr, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(50, -1),
809 wxSP_ARROW_KEYS, 1, 20000, g_AisTargetList_range);
810 m_pSpinCtrlRange->Connect(
811 wxEVT_COMMAND_SPINCTRL_UPDATED,
812 wxCommandEventHandler(AISTargetListDialog::OnLimitRange), NULL,
this);
813 m_pSpinCtrlRange->Connect(
814 wxEVT_COMMAND_TEXT_UPDATED,
815 wxCommandEventHandler(AISTargetListDialog::OnLimitRange), NULL,
this);
816 bsRouteButtonsInner->Add(m_pSpinCtrlRange, 0, wxEXPAND | wxALL, 0);
818 bsRouteButtonsInner->AddSpacer(10);
819 m_pStaticTextCount =
new wxStaticText(winr, wxID_ANY, _(
"Target Count"),
820 wxDefaultPosition, wxDefaultSize, 0);
821 bsRouteButtonsInner->Add(m_pStaticTextCount, 0, wxALL, 2);
823 bsRouteButtonsInner->AddSpacer(2);
824 m_pTextTargetCount =
new wxTextCtrl(winr, wxID_ANY,
"", wxDefaultPosition,
825 wxDefaultSize, wxTE_READONLY);
826 m_pTextTargetCount->SetMinSize(wxSize(6 * GetCharWidth(), -1));
827 bsRouteButtonsInner->Add(m_pTextTargetCount, 0, wxALL, 2);
829 bsRouteButtonsInner->AddSpacer(10);
830 m_pButtonOK =
new wxButton(winr, wxID_ANY, _(
"Close"), wxDefaultPosition,
831 wxDefaultSize, wxBU_AUTODRAW);
832 m_pButtonOK->Connect(
833 wxEVT_COMMAND_BUTTON_CLICKED,
834 wxCommandEventHandler(AISTargetListDialog::OnCloseButton), NULL,
this);
835 bsRouteButtonsInner->Add(m_pButtonOK, 0, wxEXPAND | wxALL, 0);
842 SetSize(GetSize().x, GetSize().y - 1);
845void AISTargetListDialog::OnClose(wxCloseEvent &event) {
846 Disconnect_decoder();
851void AISTargetListDialog::Disconnect_decoder() { m_pdecoder = NULL; }
853void AISTargetListDialog::SetColorScheme() { DimeControl(
this); }
855void AISTargetListDialog::OnPaneClose(wxAuiManagerEvent &event) {
856 if (event.pane->name ==
"AISTargetList") {
857 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(*event.pane);
862void AISTargetListDialog::OnCloseButton(wxCommandEvent &event) { Shutdown(); }
864void AISTargetListDialog::Shutdown() {
866 wxAuiPaneInfo pane = m_pAuiManager->GetPane(
this);
867 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
868 m_pAuiManager->DetachPane(
this);
869 Disconnect_decoder();
871 m_pAuiManager->Update();
873 GetParent()->Refresh(
true);
879void AISTargetListDialog::UpdateButtons() {
881 item = m_pListCtrlAISTargets->GetNextItem(item, wxLIST_NEXT_ALL,
882 wxLIST_STATE_SELECTED);
883 bool enable = (item != -1);
885 m_pButtonInfo->Enable(enable);
887 if (m_pdecoder && item != -1) {
889 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(item));
890 if (pAISTargetSel && (!pAISTargetSel->b_positionOnceValid)) enable =
false;
892 m_pButtonJumpTo->Enable(enable);
893 m_pButtonJumpTo_Close->Enable(enable);
894 m_pButtonCreateWpt->Enable(enable);
895 m_pButtonToggleTrack->Enable(enable);
896 m_pButtonCopyMMSI->Enable(enable);
899void AISTargetListDialog::OnTargetSelected(wxListEvent &event) {
903void AISTargetListDialog::DoTargetQuery(
int mmsi) {
904 ShowAISTargetQueryDialog(m_pparent, mmsi);
911void AISTargetListDialog::OnTargetDefaultAction(wxListEvent &event) {
913 if ((mmsi_no = event.GetData())) DoTargetQuery(mmsi_no);
916void AISTargetListDialog::OnTargetQuery(wxCommandEvent &event) {
918 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
919 wxLIST_STATE_SELECTED);
920 if (selItemID == -1)
return;
924 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
925 if (pAISTarget) DoTargetQuery(pAISTarget->MMSI);
929void AISTargetListDialog::OnAutosortCB(wxCommandEvent &event) {
930 g_bAisTargetList_autosort = m_pCBAutosort->GetValue();
932 m_bautosort_force = g_bAisTargetList_autosort;
934 if (!g_bAisTargetList_autosort) {
936 item.SetMask(wxLIST_MASK_IMAGE);
938 g_AisTargetList_sortColumn = wxMax(g_AisTargetList_sortColumn, 0);
939 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
942 item.SetMask(wxLIST_MASK_IMAGE);
943 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
945 if (g_AisTargetList_sortColumn >= 0) {
946 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
947 UpdateAISTargetList();
952void AISTargetListDialog::OnTargetListColumnClicked(wxListEvent &event) {
953 int key =
event.GetColumn();
955 item.SetMask(wxLIST_MASK_IMAGE);
956 if (key == g_AisTargetList_sortColumn)
957 g_bAisTargetList_sortReverse = !g_bAisTargetList_sortReverse;
960 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
961 g_bAisTargetList_sortReverse =
false;
962 g_AisTargetList_sortColumn = key;
964 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
966 if (!g_bAisTargetList_autosort) g_bsort_once =
true;
968 if (g_AisTargetList_sortColumn >= 0) {
969 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
970 UpdateAISTargetList();
974void AISTargetListDialog::OnTargetScrollTo(wxCommandEvent &event) {
975 CenterToTarget(
false);
978void AISTargetListDialog::OnTargetScrollToClose(wxCommandEvent &event) {
979 CenterToTarget(
true);
982void AISTargetListDialog::OnTargetCreateWpt(wxCommandEvent &event) {
984 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
985 wxLIST_STATE_SELECTED);
986 if (selItemID == -1)
return;
988 std::shared_ptr<AisTargetData> pAISTarget = NULL;
991 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
995 new RoutePoint(pAISTarget->Lat, pAISTarget->Lon, g_default_wp_icon,
996 wxEmptyString, wxEmptyString);
998 pSelect->AddSelectableRoutePoint(pAISTarget->Lat, pAISTarget->Lon, pWP);
1000 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
1004 top_frame::Get()->BeforeUndoableAction(Undo_CreateWaypoint, pWP,
1005 Undo_HasParent, NULL);
1006 top_frame::Get()->AfterUndoableAction(NULL);
1011void AISTargetListDialog::OnShowAllTracks(wxCommandEvent &event) {
1013 for (
const auto &it : m_pdecoder->GetTargetList()) {
1014 auto pAISTarget = it.second;
1015 if (NULL != pAISTarget) {
1016 pAISTarget->b_show_track =
true;
1019 std::map<int, Track *>::iterator it;
1020 it =
g_pAIS->m_persistent_tracks.find(pAISTarget->MMSI);
1021 if (it !=
g_pAIS->m_persistent_tracks.end()) {
1022 pAISTarget->b_show_track_old =
true;
1026 UpdateAISTargetList();
1030void AISTargetListDialog::OnHideAllTracks(wxCommandEvent &event) {
1032 for (
const auto &it : m_pdecoder->GetTargetList()) {
1033 auto pAISTarget = it.second;
1034 if (NULL != pAISTarget) {
1035 pAISTarget->b_show_track =
false;
1038 std::map<int, Track *>::iterator it;
1039 it =
g_pAIS->m_persistent_tracks.find(pAISTarget->MMSI);
1040 if (it !=
g_pAIS->m_persistent_tracks.end()) {
1041 pAISTarget->b_show_track =
true;
1042 pAISTarget->b_show_track_old =
false;
1046 UpdateAISTargetList();
1050void AISTargetListDialog::OnToggleTrack(wxCommandEvent &event) {
1051 long selItemID = -1;
1052 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1053 wxLIST_STATE_SELECTED);
1054 if (selItemID == -1)
return;
1056 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1059 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1062 pAISTarget->b_show_track_old =
1063 pAISTarget->b_show_track;
1064 pAISTarget->b_show_track = !pAISTarget->b_show_track;
1065 UpdateAISTargetList();
1069void AISTargetListDialog::OnCopyMMSI(wxCommandEvent &event) {
1070 long selItemID = -1;
1071 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1072 wxLIST_STATE_SELECTED);
1073 if (selItemID == -1)
return;
1074 CopyMMSItoClipBoard((
int)m_pMMSI_array->Item(selItemID));
1077void AISTargetListDialog::OnEditFindTarget(wxCommandEvent &event) {
1078 wxString name = m_pFindTargetName->GetValue().MakeUpper();
1079 if (name.size() < 2 || name ==
" ") {
1080 event.StopPropagation();
1088 for (
const auto &it : m_pdecoder->GetTargetList()) {
1089 auto pAISTarget = it.second;
1090 if (NULL != pAISTarget) {
1091 wxString s = pAISTarget->GetFullName();
1094 int selMMSI = pAISTarget->MMSI;
1095 if (selMMSI != -1) {
1097 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1098 if (m_pMMSI_array->Item(i) == selMMSI) {
1110 for (
const auto &it : m_pdecoder->GetTargetList()) {
1111 auto pAISTarget = it.second;
1112 if (NULL != pAISTarget) {
1113 wxString s = pAISTarget->GetFullName();
1114 if (s.Find(name) != wxNOT_FOUND) {
1116 int selMMSI = pAISTarget->MMSI;
1117 if (selMMSI != -1) {
1119 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1120 if (m_pMMSI_array->Item(i) == selMMSI) {
1132 if (m_pMMSI_array->GetCount())
1133 m_pListCtrlAISTargets->SetItemState(
1134 item_sel, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1135 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1137 m_pListCtrlAISTargets->EnsureVisible(item_sel);
1138 UpdateAISTargetList();
1143void AISTargetListDialog::CenterToTarget(
bool close) {
1144 long selItemID = -1;
1145 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1146 wxLIST_STATE_SELECTED);
1147 if (selItemID == -1)
return;
1149 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1152 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1155 double scale = top_frame::Get()->GetAbstractFocusCanvas()->GetVPScale();
1157 top_frame::Get()->JumpToPosition(
1158 top_frame::Get()->GetAbstractFocusCanvas(), pAISTarget->Lat,
1159 pAISTarget->Lon,
scale);
1165 factor = acc->GetScaleValue() / 5000.0;
1167 top_frame::Get()->JumpToPosition(
1168 top_frame::Get()->GetAbstractFocusCanvas(), pAISTarget->Lat,
1169 pAISTarget->Lon,
scale * factor);
1170 DoTargetQuery(pAISTarget->MMSI);
1177void AISTargetListDialog::CopyMMSItoClipBoard(
int mmsi) {
1179 if (wxTheClipboard->Open()) {
1180 wxTheClipboard->SetData(
1181 new wxTextDataObject(wxString::Format(
"%09d", mmsi)));
1182 wxTheClipboard->Close();
1185void AISTargetListDialog::OnLimitRange(wxCommandEvent &event) {
1186 g_AisTargetList_range = m_pSpinCtrlRange->GetValue();
1187 UpdateAISTargetList();
1190std::shared_ptr<AisTargetData> AISTargetListDialog::GetpTarget(
1191 unsigned int list_item) {
1193 return m_pdecoder->Get_Target_Data_From_MMSI(
1194 m_pMMSI_array->Item(list_item));
1199void AISTargetListDialog::UpdateAISTargetList() {
1200 if (m_pListCtrlAISTargets && !m_pListCtrlAISTargets->IsVirtual())
1201 return UpdateNVAISTargetList();
1203 if (m_pdecoder && m_pListCtrlAISTargets) {
1205 long selItemID = -1;
1206 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1207 wxLIST_STATE_SELECTED);
1210 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1212 const auto ¤t_targets = m_pdecoder->GetTargetList();
1216 m_pMMSI_array->Clear();
1218 for (
auto it = current_targets.begin(); it != current_targets.end();
1220 auto pAISTarget = it->second;
1223 if (NULL != pAISTarget) {
1225 if ((pAISTarget->b_positionOnceValid) &&
1226 (pAISTarget->Range_NM <= g_AisTargetList_range))
1228 else if (!pAISTarget->b_positionOnceValid)
1232 if (pAISTarget->b_lost) b_add =
false;
1235 m_pMMSI_array->Add(pAISTarget->MMSI);
1240 g_bsort_once =
false;
1242 m_pListCtrlAISTargets->SetItemCount(m_pMMSI_array->GetCount());
1244 g_AisTargetList_count = m_pMMSI_array->GetCount();
1246 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1247 g_bAisTargetList_autosort =
false;
1249 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1253 if ((selItemID != -1) && (selMMSI != -1)) {
1254 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1255 if (m_pMMSI_array->Item(i) == selMMSI) {
1262 if (m_pMMSI_array->GetCount())
1263 m_pListCtrlAISTargets->SetItemState(
1264 item_sel, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1265 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1267 m_pListCtrlAISTargets->DeleteAllItems();
1270 count.Printf(
"%lu", (
unsigned long)m_pMMSI_array->GetCount());
1271 m_pTextTargetCount->ChangeValue(count);
1274 m_pListCtrlAISTargets->Refresh(
false);
1279void AISTargetListDialog::UpdateNVAISTargetList() {
1282 long selItemID = -1;
1283 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1284 wxLIST_STATE_SELECTED);
1287 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1289 const auto ¤t_targets = m_pdecoder->GetTargetList();
1293 m_pMMSI_array->Clear();
1295 for (
auto it = current_targets.begin(); it != current_targets.end();
1297 auto pAISTarget = it->second;
1300 if (NULL != pAISTarget) {
1302 if ((pAISTarget->b_positionOnceValid) &&
1303 (pAISTarget->Range_NM <= g_AisTargetList_range))
1305 else if (!pAISTarget->b_positionOnceValid)
1309 m_pMMSI_array->Add(pAISTarget->MMSI);
1314 g_bsort_once =
false;
1316 g_AisTargetList_count = m_pMMSI_array->GetCount();
1318 m_pListCtrlAISTargets->DeleteAllItems();
1320 for (
int i = 0; i < g_AisTargetList_count; i++) {
1323 m_pListCtrlAISTargets->InsertItem(item);
1324 for (
int j = 0; j < tlTCPA + 1; j++) {
1326 item.SetText(m_pListCtrlAISTargets->OnGetItemText(i, j));
1327 m_pListCtrlAISTargets->SetItem(item);
1331 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1332 g_bAisTargetList_autosort =
false;
1334 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1338 if ((selItemID != -1) && (selMMSI != -1)) {
1339 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1340 if (m_pMMSI_array->Item(i) == selMMSI) {
1347 if (m_pMMSI_array->GetCount())
1348 m_pListCtrlAISTargets->SetItemState(
1349 item_sel, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1350 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1352 m_pListCtrlAISTargets->DeleteAllItems();
1355 count.Printf(
"%lu", (
unsigned long)m_pMMSI_array->GetCount());
1356 m_pTextTargetCount->ChangeValue(count);
1359 m_pListCtrlAISTargets->Refresh(
false);
1364void AISTargetListDialog::OnRightClickContext(wxCommandEvent &event) {
1365 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(
"AISTargetList");
1366 if (pane.IsDocked()) {
1367 wxMenu *popup =
new wxMenu();
1368 popup->Append(ID_RCLK_UNDOCK, _(
"Undock Target List"));
1369 popup->Connect(wxEVT_COMMAND_MENU_SELECTED,
1370 wxCommandEventHandler(AISTargetListDialog::OnContextUndock),
1378void AISTargetListDialog::OnContextUndock(wxCommandEvent &event) {
1379 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(
"AISTargetList");
1381 m_pAuiManager->Update();
AisDecoder * g_pAIS
Global instance.
Class AisDecoder and helpers.
Global state for AIS decoder.
Class AISTargetListDialog.
AISTargetListDialog * g_pAISTargetList
Global instance.
Generic Chart canvas base.
Dialog for displaying a list of AIS targets.
Minimal ChartCAnvas interface with very little dependencies.
A custom list control for displaying AIS target information.
Represents a waypoint or mark within the navigation system.
bool m_bIsolatedMark
Flag indicating if the waypoint is a standalone mark.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
MySQL based storage for routes, tracks, etc.
MyConfig * pConfig
Global instance.
AIS info display component.
Waypoint or mark abstraction.
RouteManagerDialog * pRouteManagerDialog
Global instance.
Select * pSelect
Global instance.
Selected route, segment, waypoint, etc.
Abstract gFrame/MyFrame interface.