25#include <wx/textctrl.h>
27#include <wx/tokenzr.h>
28#include <wx/clipbrd.h>
31#include "androidUTIL.h"
36#include "model/ais_target_data.h"
37#include "model/route_point.h"
38#include "model/select.h"
43#include "ocpn_frame.h"
44#include "OCPNListCtrl.h"
45#include "OCPNPlatform.h"
46#include "routemanagerdialog.h"
50extern int g_AisTargetList_count;
51extern bool g_bAisTargetList_autosort;
56extern wxString g_default_wp_icon;
66EVT_CLOSE(AISTargetListDialog::OnClose)
69static
bool g_bsort_once;
75 bool b_cmptype_num =
false;
78 if (!g_bAisTargetList_autosort && !g_bsort_once)
return 0;
83 if (t1->Class == AIS_SART) {
84 if (t2->Class == AIS_DSC)
90 if (t2->Class == AIS_SART) {
91 if (t1->Class == AIS_DSC)
97 switch (g_AisTargetList_sortColumn) {
99 n1 = t1->b_show_track;
100 n2 = t2->b_show_track;
101 b_cmptype_num =
true;
105 s1 = trimAISField(t1->ShipName);
106 if ((!t1->b_nameValid && (t1->Class == AIS_BASE)) ||
107 (t1->Class == AIS_SART))
110 s2 = trimAISField(t2->ShipName);
111 if ((!t2->b_nameValid && (t2->Class == AIS_BASE)) ||
112 (t2->Class == AIS_SART))
117 s1 = trimAISField(t1->CallSign);
118 s2 = trimAISField(t2->CallSign);
124 b_cmptype_num =
true;
128 s1 = t1->Get_class_string(
true);
129 s2 = t2->Get_class_string(
true);
133 s1 = t1->Get_vessel_type_string(
false);
134 if ((t1->Class == AIS_BASE) ||
135 (t1->Class == AIS_SART || (t1->Class == AIS_METEO)))
138 s2 = t2->Get_vessel_type_string(
false);
139 if ((t1->Class == AIS_BASE) || (t1->Class == AIS_SART) ||
140 (t1->Class == AIS_METEO))
145 s1 = t1->GetCountryCode(
true);
146 s2 = t2->GetCountryCode(
true);
149 if ((t1->NavStatus <= 15) && (t1->NavStatus >= 0)) {
150 if (t1->Class == AIS_SART) {
151 if (t1->NavStatus == RESERVED_14)
153 else if (t1->NavStatus == UNDEFINED)
156 s1 = ais_get_status(t1->NavStatus);
160 if ((t1->Class == AIS_ATON) || (t1->Class == AIS_BASE) ||
161 (t1->Class == AIS_CLASS_B) || (t1->Class == AIS_METEO))
164 if ((t2->NavStatus <= 15) && (t2->NavStatus >= 0)) {
165 if (t2->Class == AIS_SART) {
166 if (t2->NavStatus == RESERVED_14)
168 else if (t2->NavStatus == UNDEFINED)
171 s2 = ais_get_status(t2->NavStatus);
175 if ((t2->Class == AIS_ATON) || (t2->Class == AIS_BASE) ||
176 (t2->Class == AIS_CLASS_B) || (t2->Class == AIS_METEO))
183 int brg1 = wxRound(t1->Brg);
189 int brg2 = wxRound(t2->Brg);
195 b_cmptype_num =
true;
200 if ((t1->COG >= 360.0) || (t1->Class == AIS_ATON) ||
201 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
204 int crs = wxRound(t1->COG);
211 if ((t2->COG >= 360.0) || (t2->Class == AIS_ATON) ||
212 (t2->Class == AIS_BASE) || (t2->Class == AIS_METEO))
215 int crs = wxRound(t2->COG);
222 b_cmptype_num =
true;
227 if ((t1->SOG > 100.) || (t1->Class == AIS_ATON) ||
228 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
233 if ((t2->SOG > 100.) || (t2->Class == AIS_ATON) ||
234 (t2->Class == AIS_BASE) || (t2->Class == AIS_METEO))
239 b_cmptype_num =
true;
243 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
244 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
249 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
250 (t2->Class == AIS_BASE))
255 b_cmptype_num =
true;
259 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
260 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
265 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
266 (t2->Class == AIS_BASE) || (t2->Class == AIS_METEO))
271 b_cmptype_num =
true;
277 b_cmptype_num =
true;
285 if (!b_cmptype_num) {
286 if (g_bAisTargetList_sortReverse)
return s2.Cmp(s1);
290 if (g_bAisTargetList_sortReverse) {
296 return (t1->Range_NM > t2->Range_NM);
303 return (t1->Range_NM > t2->Range_NM);
308static int ArrayItemCompareMMSI(
int MMSI1,
int MMSI2) {
309 if (s_p_sort_decoder) {
310 std::shared_ptr<AisTargetData> pAISTarget1 =
311 s_p_sort_decoder->Get_Target_Data_From_MMSI(MMSI1);
312 std::shared_ptr<AisTargetData> pAISTarget2 =
313 s_p_sort_decoder->Get_Target_Data_From_MMSI(MMSI2);
315 if (pAISTarget1 && pAISTarget2)
316 return ItemCompare(pAISTarget1.get(), pAISTarget2.get());
323AISTargetListDialog::AISTargetListDialog(wxWindow *parent, wxAuiManager *auimgr,
325 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, -1 ),
328 m_pAuiManager = auimgr;
329 m_pdecoder = pdecoder;
330 g_bsort_once =
false;
331 m_bautosort_force =
false;
336 s_p_sort_decoder = pdecoder;
337 m_pMMSI_array =
new ArrayOfMMSI(ArrayItemCompareMMSI);
342 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
348 wxAuiPaneInfo paneproto = wxAuiPaneInfo()
349 .Name(
"AISTargetList")
350 .CaptionVisible(
true)
352 .FloatingPosition(50, 50)
353 .FloatingSize(400, 200)
354 .BestSize(700, GetCharHeight() * 10);
358 paneproto.Caption(wxGetTranslation(_(
"AIS target list")));
359 paneproto.Name(
"AISTargetList");
360 paneproto.DestroyOnClose(
true);
361 paneproto.TopDockable(
false)
362 .BottomDockable(
true)
364 .RightDockable(
false);
365 paneproto.Show(
true);
367 m_pAuiManager->AddPane(
this, paneproto);
369 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(
"AISTargetList");
371 if (g_AisTargetList_perspective.IsEmpty()) {
372 if (!g_btouch) RecalculateSize();
374 m_pAuiManager->LoadPaneInfo(g_AisTargetList_perspective, pane);
375 m_pAuiManager->Update();
378 pane = m_pAuiManager->GetPane(
"AISTargetList");
383 pane.Dockable(
false);
385 wxSize screen_size = gFrame->GetClientSize();
386 pane.FloatingSize(screen_size.x * 8 / 10, screen_size.y * 8 / 10);
387 pane.FloatingPosition(screen_size.x * 1 / 10, screen_size.y * 1 / 10);
388 m_pAuiManager->Update();
391 bool b_reset_pos =
false;
392 if ((pane.floating_size.x != -1) && (pane.floating_size.y != -1)) {
397 RECT frame_title_rect;
398 frame_title_rect.left = pane.floating_pos.x;
399 frame_title_rect.top = pane.floating_pos.y;
400 frame_title_rect.right = pane.floating_pos.x + pane.floating_size.x;
401 frame_title_rect.bottom = pane.floating_pos.y + 30;
403 if (NULL == MonitorFromRect(&frame_title_rect, MONITOR_DEFAULTTONULL))
409 wxRect window_title_rect;
410 window_title_rect.x = pane.floating_pos.x;
411 window_title_rect.y = pane.floating_pos.y;
412 window_title_rect.width = pane.floating_size.x;
413 window_title_rect.height = 30;
415 wxRect ClientRect = wxGetClientDisplayRect();
418 if (!ClientRect.Intersects(window_title_rect)) b_reset_pos =
true;
423 pane.FloatingPosition(50, 50);
424 m_pAuiManager->Update();
430 if (pane.IsDocked() && (pane.dock_row == 0)) {
434 m_pAuiManager->Update();
438 m_pAuiManager->Update();
440 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
441 pConfig->UpdateSettings();
443 m_pAuiManager->Connect(
444 wxEVT_AUI_PANE_CLOSE,
445 wxAuiManagerEventHandler(AISTargetListDialog::OnPaneClose), NULL,
this);
452 esize.y = GetCharHeight() * 10;
457 Connect(wxEVT_CONTEXT_MENU,
458 wxCommandEventHandler(AISTargetListDialog::OnRightClickContext), NULL,
462AISTargetListDialog::~AISTargetListDialog() {
463 Disconnect_decoder();
467void AISTargetListDialog::RecalculateSize() {
471 esize.x = GetCharWidth() * 110;
472 esize.y = GetCharHeight() * 40;
474 wxSize dsize = gFrame->GetClientSize();
475 esize.y = wxMin(esize.y, dsize.y - (4 * GetCharHeight()));
476 esize.x = wxMin(esize.x, dsize.x - (2 * GetCharHeight()));
477 SetClientSize(esize);
479 wxSize fsize = GetSize();
480 fsize.y = wxMin(fsize.y, dsize.y - (2 * GetCharHeight()));
481 fsize.x = wxMin(fsize.x, dsize.x - (2 * GetCharHeight()));
485 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(
"AISTargetList");
488 pane.FloatingSize(fsize.x, fsize.y);
489 wxPoint pos = gFrame->GetScreenPosition();
490 pane.FloatingPosition(pos.x + (dsize.x - fsize.x) / 2,
491 pos.y + (dsize.y - fsize.y) / 2);
494 m_pAuiManager->Update();
498void AISTargetListDialog::CreateControls() {
499 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
502 this->GetHandle()->setStyleSheet(getQtStyleSheet());
506 wxStringTokenizer tkz(g_AisTargetList_column_spec,
";");
507 wxString s_width = tkz.GetNextToken();
511 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
514 flags |= wxLC_VIRTUAL;
518 this, ID_AIS_TARGET_LIST, wxDefaultPosition, wxDefaultSize, flags);
520 wxImageList *imglist =
new wxImageList(16, 16,
true, 2);
523 imglist->Add(style->GetIcon(
"sort_asc"));
524 imglist->Add(style->GetIcon(
"sort_desc"));
526 m_pListCtrlAISTargets->AssignImageList(imglist, wxIMAGE_LIST_SMALL);
527 m_pListCtrlAISTargets->Connect(
528 wxEVT_COMMAND_LIST_ITEM_SELECTED,
529 wxListEventHandler(AISTargetListDialog::OnTargetSelected), NULL,
this);
530 m_pListCtrlAISTargets->Connect(
531 wxEVT_COMMAND_LIST_ITEM_DESELECTED,
532 wxListEventHandler(AISTargetListDialog::OnTargetSelected), NULL,
this);
533 m_pListCtrlAISTargets->Connect(
534 wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
535 wxListEventHandler(AISTargetListDialog::OnTargetDefaultAction), NULL,
537 m_pListCtrlAISTargets->Connect(
538 wxEVT_COMMAND_LIST_COL_CLICK,
539 wxListEventHandler(AISTargetListDialog::OnTargetListColumnClicked), NULL,
542 int dx = GetCharWidth();
545 if (s_width.ToLong(&lwidth)) {
546 width = wxMax(dx * 2, lwidth);
547 width = wxMin(width, dx * 30);
549 m_pListCtrlAISTargets->InsertColumn(tlTRK, _(
"Trk"), wxLIST_FORMAT_LEFT,
551 s_width = tkz.GetNextToken();
554 if (s_width.ToLong(&lwidth)) {
555 width = wxMax(dx * 2, lwidth);
556 width = wxMin(width, dx * 30);
558 m_pListCtrlAISTargets->InsertColumn(tlNAME, _(
"Name"), wxLIST_FORMAT_LEFT,
560 s_width = tkz.GetNextToken();
563 if (s_width.ToLong(&lwidth)) {
564 width = wxMax(dx * 2, lwidth);
565 width = wxMin(width, dx * 30);
567 m_pListCtrlAISTargets->InsertColumn(tlCALL, _(
"Call"), wxLIST_FORMAT_LEFT,
569 s_width = tkz.GetNextToken();
572 if (s_width.ToLong(&lwidth)) {
573 width = wxMax(dx * 2, lwidth);
574 width = wxMin(width, dx * 30);
576 m_pListCtrlAISTargets->InsertColumn(tlMMSI, _(
"MMSI"), wxLIST_FORMAT_LEFT,
578 s_width = tkz.GetNextToken();
581 if (s_width.ToLong(&lwidth)) {
582 width = wxMax(dx * 2, lwidth);
583 width = wxMin(width, dx * 30);
585 m_pListCtrlAISTargets->InsertColumn(tlCLASS, _(
"Class"), wxLIST_FORMAT_CENTER,
587 s_width = tkz.GetNextToken();
590 if (s_width.ToLong(&lwidth)) {
591 width = wxMax(dx * 2, lwidth);
592 width = wxMin(width, dx * 30);
594 m_pListCtrlAISTargets->InsertColumn(tlTYPE, _(
"Type"), wxLIST_FORMAT_LEFT,
596 s_width = tkz.GetNextToken();
599 if (s_width.ToLong(&lwidth)) {
600 width = wxMax(dx * 2, lwidth);
601 width = wxMin(width, dx * 30);
603 m_pListCtrlAISTargets->InsertColumn(tlNAVSTATUS, _(
"Flag"),
604 wxLIST_FORMAT_LEFT, width);
605 s_width = tkz.GetNextToken();
608 if (s_width.ToLong(&lwidth)) {
609 width = wxMax(dx * 2, lwidth);
610 width = wxMin(width, dx * 30);
612 m_pListCtrlAISTargets->InsertColumn(tlNAVSTATUS, _(
"Nav Status"),
613 wxLIST_FORMAT_LEFT, width);
614 s_width = tkz.GetNextToken();
617 if (s_width.ToLong(&lwidth)) {
618 width = wxMax(dx * 2, lwidth);
619 width = wxMin(width, dx * 30);
621 m_pListCtrlAISTargets->InsertColumn(tlBRG, _(
"Brg"), wxLIST_FORMAT_RIGHT,
623 s_width = tkz.GetNextToken();
626 if (s_width.ToLong(&lwidth)) {
627 width = wxMax(dx * 2, lwidth);
628 width = wxMin(width, dx * 30);
630 m_pListCtrlAISTargets->InsertColumn(tlRNG, _(
"Range"), wxLIST_FORMAT_RIGHT,
632 s_width = tkz.GetNextToken();
635 if (s_width.ToLong(&lwidth)) {
636 width = wxMax(dx * 2, lwidth);
637 width = wxMin(width, dx * 30);
639 m_pListCtrlAISTargets->InsertColumn(tlCOG, _(
"CoG"), wxLIST_FORMAT_RIGHT,
641 s_width = tkz.GetNextToken();
644 if (s_width.ToLong(&lwidth)) {
645 width = wxMax(dx * 2, lwidth);
646 width = wxMin(width, dx * 30);
648 m_pListCtrlAISTargets->InsertColumn(tlSOG, _(
"SoG"), wxLIST_FORMAT_RIGHT,
652 if (s_width.ToLong(&lwidth)) {
653 width = wxMax(dx * 2, lwidth);
654 width = wxMin(width, dx * 30);
656 m_pListCtrlAISTargets->InsertColumn(tlCPA, _(
"CPA"), wxLIST_FORMAT_RIGHT,
660 if (s_width.ToLong(&lwidth)) {
661 width = wxMax(dx * 2, lwidth);
662 width = wxMin(width, dx * 30);
664 m_pListCtrlAISTargets->InsertColumn(tlTCPA, _(
"TCPA"), wxLIST_FORMAT_RIGHT,
667 item.SetMask(wxLIST_MASK_IMAGE);
668 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
669 g_AisTargetList_sortColumn = wxMax(g_AisTargetList_sortColumn, 0);
670 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
672#ifdef wxHAS_LISTCTRL_COLUMN_ORDER
673 wxStringTokenizer tkz_order(g_AisTargetList_column_order,
";");
674 wxString s_order = tkz_order.GetNextToken();
675 int i_columns = m_pListCtrlAISTargets->GetColumnCount();
676 wxArrayInt a_order(i_columns);
677 for (
int i = 0; i < i_columns; i++) {
678 long l_order = (long)i;
679 s_order.ToLong(&l_order);
680 if (l_order < 0 || l_order > i_columns) {
683 a_order[i] = l_order;
684 s_order = tkz_order.GetNextToken();
687 m_pListCtrlAISTargets->SetColumnsOrder(a_order);
690 topSizer->Add(m_pListCtrlAISTargets, 1, wxEXPAND | wxALL, 0);
692 wxBoxSizer *boxSizer02 =
new wxBoxSizer(wxVERTICAL);
693 boxSizer02->AddSpacer(22);
694 topSizer->Add(boxSizer02, 0, wxEXPAND | wxALL, 2);
696 wxScrolledWindow *winr =
697 new wxScrolledWindow(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
698 wxNO_BORDER | wxTAB_TRAVERSAL | wxVSCROLL);
699 winr->SetScrollRate(0, 5);
701 boxSizer02->Add(winr, 1, wxALL | wxEXPAND, 3);
703 wxBoxSizer *bsRouteButtonsInner =
new wxBoxSizer(wxVERTICAL);
704 winr->SetSizer(bsRouteButtonsInner);
706 m_pButtonInfo =
new wxButton(winr, wxID_ANY, _(
"Target info"),
707 wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
708 m_pButtonInfo->Connect(
709 wxEVT_COMMAND_BUTTON_CLICKED,
710 wxCommandEventHandler(AISTargetListDialog::OnTargetQuery), NULL,
this);
711 bsRouteButtonsInner->Add(m_pButtonInfo, 0, wxEXPAND | wxALL, 2);
712 bsRouteButtonsInner->AddSpacer(5);
715 new wxButton(winr, wxID_ANY, _(
"Center view"), wxDefaultPosition,
716 wxDefaultSize, wxBU_AUTODRAW);
717 m_pButtonJumpTo->Connect(
718 wxEVT_COMMAND_BUTTON_CLICKED,
719 wxCommandEventHandler(AISTargetListDialog::OnTargetScrollTo), NULL,
this);
720 bsRouteButtonsInner->Add(m_pButtonJumpTo, 0, wxEXPAND | wxALL, 2);
722 m_pButtonJumpTo_Close =
723 new wxButton(winr, wxID_ANY, _(
"Center-Info-Close"), wxDefaultPosition,
724 wxDefaultSize, wxBU_AUTODRAW);
725 m_pButtonJumpTo_Close->Connect(
726 wxEVT_COMMAND_BUTTON_CLICKED,
727 wxCommandEventHandler(AISTargetListDialog::OnTargetScrollToClose), NULL,
729 bsRouteButtonsInner->Add(m_pButtonJumpTo_Close, 0, wxEXPAND | wxALL, 2);
732 new wxButton(winr, wxID_ANY, _(
"Create WPT"), wxDefaultPosition,
733 wxDefaultSize, wxBU_AUTODRAW);
734 m_pButtonCreateWpt->Connect(
735 wxEVT_COMMAND_BUTTON_CLICKED,
736 wxCommandEventHandler(AISTargetListDialog::OnTargetCreateWpt), NULL,
738 bsRouteButtonsInner->Add(m_pButtonCreateWpt, 0, wxEXPAND | wxALL, 0);
740 m_pButtonHideAllTracks =
741 new wxButton(winr, wxID_ANY, _(
"Hide All Tracks"), wxDefaultPosition,
742 wxDefaultSize, wxBU_AUTODRAW);
743 m_pButtonHideAllTracks->Connect(
744 wxEVT_COMMAND_BUTTON_CLICKED,
745 wxCommandEventHandler(AISTargetListDialog::OnHideAllTracks), NULL,
this);
746 bsRouteButtonsInner->Add(m_pButtonHideAllTracks, 0, wxEXPAND | wxALL, 2);
748 m_pButtonShowAllTracks =
749 new wxButton(winr, wxID_ANY, _(
"Show All Tracks"), wxDefaultPosition,
750 wxDefaultSize, wxBU_AUTODRAW);
751 m_pButtonShowAllTracks->Connect(
752 wxEVT_COMMAND_BUTTON_CLICKED,
753 wxCommandEventHandler(AISTargetListDialog::OnShowAllTracks), NULL,
this);
754 bsRouteButtonsInner->Add(m_pButtonShowAllTracks, 0, wxEXPAND | wxALL, 2);
756 m_pButtonToggleTrack =
757 new wxButton(winr, wxID_ANY, _(
"Toggle track"), wxDefaultPosition,
758 wxDefaultSize, wxBU_AUTODRAW);
759 m_pButtonToggleTrack->Connect(
760 wxEVT_COMMAND_BUTTON_CLICKED,
761 wxCommandEventHandler(AISTargetListDialog::OnToggleTrack), NULL,
this);
762 bsRouteButtonsInner->Add(m_pButtonToggleTrack, 0, wxEXPAND | wxALL, 2);
765 new wxButton(winr, wxID_ANY, _(
"Copy MMSI"), wxDefaultPosition,
766 wxDefaultSize, wxBU_AUTODRAW);
767 m_pButtonCopyMMSI->Connect(
768 wxEVT_COMMAND_BUTTON_CLICKED,
769 wxCommandEventHandler(AISTargetListDialog::OnCopyMMSI), NULL,
this);
770 bsRouteButtonsInner->Add(m_pButtonCopyMMSI, 0, wxEXPAND | wxALL, 2);
773 new wxCheckBox(winr, wxID_ANY, _(
"AutoSort"), wxDefaultPosition,
774 wxDefaultSize, wxBU_AUTODRAW);
775 m_pCBAutosort->Connect(
776 wxEVT_COMMAND_CHECKBOX_CLICKED,
777 wxCommandEventHandler(AISTargetListDialog::OnAutosortCB), NULL,
this);
778 bsRouteButtonsInner->Add(m_pCBAutosort, 0, wxEXPAND | wxALL, 2);
779 g_bAisTargetList_autosort =
true;
780 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
782 bsRouteButtonsInner->AddSpacer(10);
784 m_pStaticTextRange =
new wxStaticText(winr, wxID_ANY, _(
"Limit range: NM"),
785 wxDefaultPosition, wxDefaultSize, 0);
786 bsRouteButtonsInner->Add(m_pStaticTextRange, 0, wxALL, 2);
787 bsRouteButtonsInner->AddSpacer(2);
788 m_pSpinCtrlRange =
new wxSpinCtrl(
789 winr, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(50, -1),
790 wxSP_ARROW_KEYS, 1, 20000, g_AisTargetList_range);
791 m_pSpinCtrlRange->Connect(
792 wxEVT_COMMAND_SPINCTRL_UPDATED,
793 wxCommandEventHandler(AISTargetListDialog::OnLimitRange), NULL,
this);
794 m_pSpinCtrlRange->Connect(
795 wxEVT_COMMAND_TEXT_UPDATED,
796 wxCommandEventHandler(AISTargetListDialog::OnLimitRange), NULL,
this);
797 bsRouteButtonsInner->Add(m_pSpinCtrlRange, 0, wxEXPAND | wxALL, 0);
799 bsRouteButtonsInner->AddSpacer(10);
800 m_pStaticTextCount =
new wxStaticText(winr, wxID_ANY, _(
"Target Count"),
801 wxDefaultPosition, wxDefaultSize, 0);
802 bsRouteButtonsInner->Add(m_pStaticTextCount, 0, wxALL, 2);
804 bsRouteButtonsInner->AddSpacer(2);
805 m_pTextTargetCount =
new wxTextCtrl(winr, wxID_ANY,
"", wxDefaultPosition,
806 wxDefaultSize, wxTE_READONLY);
807 m_pTextTargetCount->SetMinSize(wxSize(6 * GetCharWidth(), -1));
808 bsRouteButtonsInner->Add(m_pTextTargetCount, 0, wxALL, 2);
810 bsRouteButtonsInner->AddSpacer(10);
811 m_pButtonOK =
new wxButton(winr, wxID_ANY, _(
"Close"), wxDefaultPosition,
812 wxDefaultSize, wxBU_AUTODRAW);
813 m_pButtonOK->Connect(
814 wxEVT_COMMAND_BUTTON_CLICKED,
815 wxCommandEventHandler(AISTargetListDialog::OnCloseButton), NULL,
this);
816 bsRouteButtonsInner->Add(m_pButtonOK, 0, wxEXPAND | wxALL, 0);
823 SetSize(GetSize().x, GetSize().y - 1);
826void AISTargetListDialog::OnClose(wxCloseEvent &event) {
827 Disconnect_decoder();
832void AISTargetListDialog::Disconnect_decoder() { m_pdecoder = NULL; }
834void AISTargetListDialog::SetColorScheme() { DimeControl(
this); }
836void AISTargetListDialog::OnPaneClose(wxAuiManagerEvent &event) {
837 if (event.pane->name ==
"AISTargetList") {
838 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(*event.pane);
843void AISTargetListDialog::OnCloseButton(wxCommandEvent &event) { Shutdown(); }
845void AISTargetListDialog::Shutdown(
void) {
847 wxAuiPaneInfo pane = m_pAuiManager->GetPane(
this);
848 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
849 m_pAuiManager->DetachPane(
this);
850 Disconnect_decoder();
852 m_pAuiManager->Update();
854 GetParent()->Refresh(
true);
860void AISTargetListDialog::UpdateButtons() {
862 item = m_pListCtrlAISTargets->GetNextItem(item, wxLIST_NEXT_ALL,
863 wxLIST_STATE_SELECTED);
864 bool enable = (item != -1);
866 m_pButtonInfo->Enable(enable);
868 if (m_pdecoder && item != -1) {
870 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(item));
871 if (pAISTargetSel && (!pAISTargetSel->b_positionOnceValid)) enable =
false;
873 m_pButtonJumpTo->Enable(enable);
874 m_pButtonJumpTo_Close->Enable(enable);
875 m_pButtonCreateWpt->Enable(enable);
876 m_pButtonToggleTrack->Enable(enable);
877 m_pButtonCopyMMSI->Enable(enable);
880void AISTargetListDialog::OnTargetSelected(wxListEvent &event) {
884void AISTargetListDialog::DoTargetQuery(
int mmsi) {
885 ShowAISTargetQueryDialog(m_pparent, mmsi);
892void AISTargetListDialog::OnTargetDefaultAction(wxListEvent &event) {
894 if ((mmsi_no = event.GetData())) DoTargetQuery(mmsi_no);
897void AISTargetListDialog::OnTargetQuery(wxCommandEvent &event) {
899 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
900 wxLIST_STATE_SELECTED);
901 if (selItemID == -1)
return;
905 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
906 if (pAISTarget) DoTargetQuery(pAISTarget->MMSI);
910void AISTargetListDialog::OnAutosortCB(wxCommandEvent &event) {
911 g_bAisTargetList_autosort = m_pCBAutosort->GetValue();
913 m_bautosort_force = g_bAisTargetList_autosort;
915 if (!g_bAisTargetList_autosort) {
917 item.SetMask(wxLIST_MASK_IMAGE);
919 g_AisTargetList_sortColumn = wxMax(g_AisTargetList_sortColumn, 0);
920 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
923 item.SetMask(wxLIST_MASK_IMAGE);
924 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
926 if (g_AisTargetList_sortColumn >= 0) {
927 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
928 UpdateAISTargetList();
933void AISTargetListDialog::OnTargetListColumnClicked(wxListEvent &event) {
934 int key =
event.GetColumn();
936 item.SetMask(wxLIST_MASK_IMAGE);
937 if (key == g_AisTargetList_sortColumn)
938 g_bAisTargetList_sortReverse = !g_bAisTargetList_sortReverse;
941 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
942 g_bAisTargetList_sortReverse =
false;
943 g_AisTargetList_sortColumn = key;
945 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
947 if (!g_bAisTargetList_autosort) g_bsort_once =
true;
949 if (g_AisTargetList_sortColumn >= 0) {
950 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
951 UpdateAISTargetList();
955void AISTargetListDialog::OnTargetScrollTo(wxCommandEvent &event) {
956 CenterToTarget(
false);
959void AISTargetListDialog::OnTargetScrollToClose(wxCommandEvent &event) {
960 CenterToTarget(
true);
963void AISTargetListDialog::OnTargetCreateWpt(wxCommandEvent &event) {
965 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
966 wxLIST_STATE_SELECTED);
967 if (selItemID == -1)
return;
969 std::shared_ptr<AisTargetData> pAISTarget = NULL;
972 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
976 new RoutePoint(pAISTarget->Lat, pAISTarget->Lon, g_default_wp_icon,
977 wxEmptyString, wxEmptyString);
979 pSelect->AddSelectableRoutePoint(pAISTarget->Lat, pAISTarget->Lon, pWP);
981 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
983 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
984 pRouteManagerDialog->UpdateWptListCtrl();
985 gFrame->GetPrimaryCanvas()->undo->BeforeUndoableAction(
986 Undo_CreateWaypoint, pWP, Undo_HasParent, NULL);
987 gFrame->GetPrimaryCanvas()->undo->AfterUndoableAction(NULL);
992void AISTargetListDialog::OnShowAllTracks(wxCommandEvent &event) {
994 for (
const auto &it : m_pdecoder->GetTargetList()) {
995 auto pAISTarget = it.second;
996 if (NULL != pAISTarget) {
997 pAISTarget->b_show_track =
true;
1000 std::map<int, Track *>::iterator it;
1001 it = g_pAIS->m_persistent_tracks.find(pAISTarget->MMSI);
1002 if (it != g_pAIS->m_persistent_tracks.end()) {
1003 pAISTarget->b_show_track_old =
true;
1007 UpdateAISTargetList();
1011void AISTargetListDialog::OnHideAllTracks(wxCommandEvent &event) {
1013 for (
const auto &it : m_pdecoder->GetTargetList()) {
1014 auto pAISTarget = it.second;
1015 if (NULL != pAISTarget) {
1016 pAISTarget->b_show_track =
false;
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 =
true;
1023 pAISTarget->b_show_track_old =
false;
1027 UpdateAISTargetList();
1031void AISTargetListDialog::OnToggleTrack(wxCommandEvent &event) {
1032 long selItemID = -1;
1033 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1034 wxLIST_STATE_SELECTED);
1035 if (selItemID == -1)
return;
1037 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1040 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1043 pAISTarget->b_show_track_old =
1044 pAISTarget->b_show_track;
1045 pAISTarget->b_show_track = !pAISTarget->b_show_track;
1046 UpdateAISTargetList();
1050void AISTargetListDialog::OnCopyMMSI(wxCommandEvent &event) {
1051 long selItemID = -1;
1052 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1053 wxLIST_STATE_SELECTED);
1054 if (selItemID == -1)
return;
1055 CopyMMSItoClipBoard((
int)m_pMMSI_array->Item(selItemID));
1058void AISTargetListDialog::CenterToTarget(
bool close) {
1059 long selItemID = -1;
1060 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1061 wxLIST_STATE_SELECTED);
1062 if (selItemID == -1)
return;
1064 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1067 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1070 double scale = gFrame->GetFocusCanvas()->GetVPScale();
1072 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), pAISTarget->Lat,
1073 pAISTarget->Lon,
scale);
1078 double factor = cc->GetScaleValue() / 5000.0;
1079 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), pAISTarget->Lat,
1080 pAISTarget->Lon,
scale * factor);
1082 DoTargetQuery(pAISTarget->MMSI);
1089void AISTargetListDialog::CopyMMSItoClipBoard(
int mmsi) {
1091 if (wxTheClipboard->Open()) {
1092 wxTheClipboard->SetData(
1093 new wxTextDataObject(wxString::Format(
"%09d", mmsi)));
1094 wxTheClipboard->Close();
1097void AISTargetListDialog::OnLimitRange(wxCommandEvent &event) {
1098 g_AisTargetList_range = m_pSpinCtrlRange->GetValue();
1099 UpdateAISTargetList();
1102std::shared_ptr<AisTargetData> AISTargetListDialog::GetpTarget(
1103 unsigned int list_item) {
1105 return m_pdecoder->Get_Target_Data_From_MMSI(
1106 m_pMMSI_array->Item(list_item));
1111void AISTargetListDialog::UpdateAISTargetList(
void) {
1112 if (m_pListCtrlAISTargets && !m_pListCtrlAISTargets->IsVirtual())
1113 return UpdateNVAISTargetList();
1115 if (m_pdecoder && m_pListCtrlAISTargets) {
1117 long selItemID = -1;
1118 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1119 wxLIST_STATE_SELECTED);
1122 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1124 const auto ¤t_targets = m_pdecoder->GetTargetList();
1128 m_pMMSI_array->Clear();
1130 for (
auto it = current_targets.begin(); it != current_targets.end();
1132 auto pAISTarget = it->second;
1135 if (NULL != pAISTarget) {
1137 if ((pAISTarget->b_positionOnceValid) &&
1138 (pAISTarget->Range_NM <= g_AisTargetList_range))
1140 else if (!pAISTarget->b_positionOnceValid)
1144 if (pAISTarget->b_lost) b_add =
false;
1147 m_pMMSI_array->Add(pAISTarget->MMSI);
1152 g_bsort_once =
false;
1154 m_pListCtrlAISTargets->SetItemCount(m_pMMSI_array->GetCount());
1156 g_AisTargetList_count = m_pMMSI_array->GetCount();
1158 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1159 g_bAisTargetList_autosort =
false;
1161 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1165 if ((selItemID != -1) && (selMMSI != -1)) {
1166 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1167 if (m_pMMSI_array->Item(i) == selMMSI) {
1174 if (m_pMMSI_array->GetCount())
1175 m_pListCtrlAISTargets->SetItemState(
1176 item_sel, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1177 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1179 m_pListCtrlAISTargets->DeleteAllItems();
1182 count.Printf(
"%lu", (
unsigned long)m_pMMSI_array->GetCount());
1183 m_pTextTargetCount->ChangeValue(count);
1186 m_pListCtrlAISTargets->Refresh(
false);
1191void AISTargetListDialog::UpdateNVAISTargetList(
void) {
1194 long selItemID = -1;
1195 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1196 wxLIST_STATE_SELECTED);
1199 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1201 const auto ¤t_targets = m_pdecoder->GetTargetList();
1205 m_pMMSI_array->Clear();
1207 for (
auto it = current_targets.begin(); it != current_targets.end();
1209 auto pAISTarget = it->second;
1212 if (NULL != pAISTarget) {
1214 if ((pAISTarget->b_positionOnceValid) &&
1215 (pAISTarget->Range_NM <= g_AisTargetList_range))
1217 else if (!pAISTarget->b_positionOnceValid)
1221 m_pMMSI_array->Add(pAISTarget->MMSI);
1226 g_bsort_once =
false;
1228 g_AisTargetList_count = m_pMMSI_array->GetCount();
1230 m_pListCtrlAISTargets->DeleteAllItems();
1232 for (
int i = 0; i < g_AisTargetList_count; i++) {
1235 m_pListCtrlAISTargets->InsertItem(item);
1236 for (
int j = 0; j < tlTCPA + 1; j++) {
1238 item.SetText(m_pListCtrlAISTargets->OnGetItemText(i, j));
1239 m_pListCtrlAISTargets->SetItem(item);
1243 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1244 g_bAisTargetList_autosort =
false;
1246 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1250 if ((selItemID != -1) && (selMMSI != -1)) {
1251 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1252 if (m_pMMSI_array->Item(i) == selMMSI) {
1259 if (m_pMMSI_array->GetCount())
1260 m_pListCtrlAISTargets->SetItemState(
1261 item_sel, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1262 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1264 m_pListCtrlAISTargets->DeleteAllItems();
1267 count.Printf(
"%lu", (
unsigned long)m_pMMSI_array->GetCount());
1268 m_pTextTargetCount->ChangeValue(count);
1271 m_pListCtrlAISTargets->Refresh(
false);
1276void AISTargetListDialog::OnRightClickContext(wxCommandEvent &event) {
1277 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(
"AISTargetList");
1278 if (pane.IsDocked()) {
1279 wxMenu *popup =
new wxMenu();
1280 popup->Append(ID_RCLK_UNDOCK, _(
"Undock Target List"));
1281 popup->Connect(wxEVT_COMMAND_MENU_SELECTED,
1282 wxCommandEventHandler(AISTargetListDialog::OnContextUndock),
1290void AISTargetListDialog::OnContextUndock(wxCommandEvent &event) {
1291 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(
"AISTargetList");
1293 m_pAuiManager->Update();
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.
ChartCanvas - Main chart display and interaction component.
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.