25#include <wx/textctrl.h>
27#include <wx/tokenzr.h>
28#include <wx/clipbrd.h>
31#include "androidUTIL.h"
34#include "model/ais_decoder.h"
36#include "model/ais_target_data.h"
37#include "model/route_point.h"
38#include "model/select.h"
41#include "AISTargetListDialog.h"
43#include "ocpn_frame.h"
44#include "OCPNListCtrl.h"
45#include "OCPNPlatform.h"
46#include "routemanagerdialog.h"
52extern int g_AisTargetList_count;
53extern bool g_bAisTargetList_autosort;
58extern wxString g_default_wp_icon;
64EVT_CLOSE(AISTargetListDialog::OnClose)
67static
bool g_bsort_once;
73 bool b_cmptype_num =
false;
76 if (!g_bAisTargetList_autosort && !g_bsort_once)
return 0;
81 if (t1->Class == AIS_SART) {
82 if (t2->Class == AIS_DSC)
88 if (t2->Class == AIS_SART) {
89 if (t1->Class == AIS_DSC)
95 switch (g_AisTargetList_sortColumn) {
97 n1 = t1->b_show_track;
98 n2 = t2->b_show_track;
103 s1 = trimAISField(t1->ShipName);
104 if ((!t1->b_nameValid && (t1->Class == AIS_BASE)) ||
105 (t1->Class == AIS_SART))
108 s2 = trimAISField(t2->ShipName);
109 if ((!t2->b_nameValid && (t2->Class == AIS_BASE)) ||
110 (t2->Class == AIS_SART))
115 s1 = trimAISField(t1->CallSign);
116 s2 = trimAISField(t2->CallSign);
122 b_cmptype_num =
true;
126 s1 = t1->Get_class_string(
true);
127 s2 = t2->Get_class_string(
true);
131 s1 = t1->Get_vessel_type_string(
false);
132 if ((t1->Class == AIS_BASE) ||
133 (t1->Class == AIS_SART || (t1->Class == AIS_METEO)))
136 s2 = t2->Get_vessel_type_string(
false);
137 if ((t1->Class == AIS_BASE) || (t1->Class == AIS_SART) ||
138 (t1->Class == AIS_METEO))
143 s1 = t1->GetCountryCode(
true);
144 s2 = t2->GetCountryCode(
true);
147 if ((t1->NavStatus <= 15) && (t1->NavStatus >= 0)) {
148 if (t1->Class == AIS_SART) {
149 if (t1->NavStatus == RESERVED_14)
151 else if (t1->NavStatus == UNDEFINED)
154 s1 = ais_get_status(t1->NavStatus);
158 if ((t1->Class == AIS_ATON) || (t1->Class == AIS_BASE) ||
159 (t1->Class == AIS_CLASS_B) || (t1->Class == AIS_METEO))
162 if ((t2->NavStatus <= 15) && (t2->NavStatus >= 0)) {
163 if (t2->Class == AIS_SART) {
164 if (t2->NavStatus == RESERVED_14)
166 else if (t2->NavStatus == UNDEFINED)
169 s2 = ais_get_status(t2->NavStatus);
173 if ((t2->Class == AIS_ATON) || (t2->Class == AIS_BASE) ||
174 (t2->Class == AIS_CLASS_B) || (t2->Class == AIS_METEO))
181 int brg1 = wxRound(t1->Brg);
187 int brg2 = wxRound(t2->Brg);
193 b_cmptype_num =
true;
198 if ((t1->COG >= 360.0) || (t1->Class == AIS_ATON) ||
199 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
202 int crs = wxRound(t1->COG);
209 if ((t2->COG >= 360.0) || (t2->Class == AIS_ATON) ||
210 (t2->Class == AIS_BASE) || (t2->Class == AIS_METEO))
213 int crs = wxRound(t2->COG);
220 b_cmptype_num =
true;
225 if ((t1->SOG > 100.) || (t1->Class == AIS_ATON) ||
226 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
231 if ((t2->SOG > 100.) || (t2->Class == AIS_ATON) ||
232 (t2->Class == AIS_BASE) || (t2->Class == AIS_METEO))
237 b_cmptype_num =
true;
241 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
242 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
247 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
248 (t2->Class == AIS_BASE))
253 b_cmptype_num =
true;
257 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
258 (t1->Class == AIS_BASE) || (t1->Class == AIS_METEO))
263 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
264 (t2->Class == AIS_BASE) || (t2->Class == AIS_METEO))
269 b_cmptype_num =
true;
275 b_cmptype_num =
true;
283 if (!b_cmptype_num) {
284 if (g_bAisTargetList_sortReverse)
return s2.Cmp(s1);
288 if (g_bAisTargetList_sortReverse) {
294 return (t1->Range_NM > t2->Range_NM);
301 return (t1->Range_NM > t2->Range_NM);
306static int ArrayItemCompareMMSI(
int MMSI1,
int MMSI2) {
307 if (s_p_sort_decoder) {
308 std::shared_ptr<AisTargetData> pAISTarget1 =
309 s_p_sort_decoder->Get_Target_Data_From_MMSI(MMSI1);
310 std::shared_ptr<AisTargetData> pAISTarget2 =
311 s_p_sort_decoder->Get_Target_Data_From_MMSI(MMSI2);
313 if (pAISTarget1 && pAISTarget2)
314 return ItemCompare(pAISTarget1.get(), pAISTarget2.get());
321AISTargetListDialog::AISTargetListDialog(wxWindow *parent, wxAuiManager *auimgr,
323 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, -1 ),
326 m_pAuiManager = auimgr;
327 m_pdecoder = pdecoder;
328 g_bsort_once =
false;
329 m_bautosort_force =
false;
334 s_p_sort_decoder = pdecoder;
335 m_pMMSI_array =
new ArrayOfMMSI(ArrayItemCompareMMSI);
340 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
346 wxAuiPaneInfo paneproto = wxAuiPaneInfo()
347 .Name(_T(
"AISTargetList"))
348 .CaptionVisible(
true)
350 .FloatingPosition(50, 50)
351 .FloatingSize(400, 200)
352 .BestSize(700, GetCharHeight() * 10);
356 paneproto.Caption(wxGetTranslation(_(
"AIS target list")));
357 paneproto.Name(_T(
"AISTargetList"));
358 paneproto.DestroyOnClose(
true);
359 paneproto.TopDockable(
false)
360 .BottomDockable(
true)
362 .RightDockable(
false);
363 paneproto.Show(
true);
365 m_pAuiManager->AddPane(
this, paneproto);
367 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T(
"AISTargetList"));
369 if (g_AisTargetList_perspective.IsEmpty()) {
370 if (!g_btouch) RecalculateSize();
372 m_pAuiManager->LoadPaneInfo(g_AisTargetList_perspective, pane);
373 m_pAuiManager->Update();
377 m_pAuiManager->GetPane(_T(
"AISTargetList"));
382 pane.Dockable(
false);
384 wxSize screen_size = gFrame->GetClientSize();
385 pane.FloatingSize(screen_size.x * 8 / 10, screen_size.y * 8 / 10);
386 pane.FloatingPosition(screen_size.x * 1 / 10, screen_size.y * 1 / 10);
387 m_pAuiManager->Update();
390 bool b_reset_pos =
false;
391 if ((pane.floating_size.x != -1) && (pane.floating_size.y != -1)) {
396 RECT frame_title_rect;
397 frame_title_rect.left = pane.floating_pos.x;
398 frame_title_rect.top = pane.floating_pos.y;
399 frame_title_rect.right = pane.floating_pos.x + pane.floating_size.x;
400 frame_title_rect.bottom = pane.floating_pos.y + 30;
402 if (NULL == MonitorFromRect(&frame_title_rect, MONITOR_DEFAULTTONULL))
408 wxRect window_title_rect;
409 window_title_rect.x = pane.floating_pos.x;
410 window_title_rect.y = pane.floating_pos.y;
411 window_title_rect.width = pane.floating_size.x;
412 window_title_rect.height = 30;
414 wxRect ClientRect = wxGetClientDisplayRect();
417 if (!ClientRect.Intersects(window_title_rect)) b_reset_pos =
true;
422 pane.FloatingPosition(50, 50);
423 m_pAuiManager->Update();
429 if (pane.IsDocked() && (pane.dock_row == 0)) {
433 m_pAuiManager->Update();
437 m_pAuiManager->Update();
439 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
440 pConfig->UpdateSettings();
442 m_pAuiManager->Connect(
443 wxEVT_AUI_PANE_CLOSE,
444 wxAuiManagerEventHandler(AISTargetListDialog::OnPaneClose), NULL,
this);
451 esize.y = GetCharHeight() * 10;
456 Connect(wxEVT_CONTEXT_MENU,
457 wxCommandEventHandler(AISTargetListDialog::OnRightClickContext), NULL,
461AISTargetListDialog::~AISTargetListDialog() {
462 Disconnect_decoder();
463 g_pAISTargetList = NULL;
466void AISTargetListDialog::RecalculateSize() {
470 esize.x = GetCharWidth() * 110;
471 esize.y = GetCharHeight() * 40;
473 wxSize dsize = gFrame->GetClientSize();
474 esize.y = wxMin(esize.y, dsize.y - (4 * GetCharHeight()));
475 esize.x = wxMin(esize.x, dsize.x - (2 * GetCharHeight()));
476 SetClientSize(esize);
478 wxSize fsize = GetSize();
479 fsize.y = wxMin(fsize.y, dsize.y - (2 * GetCharHeight()));
480 fsize.x = wxMin(fsize.x, dsize.x - (2 * GetCharHeight()));
484 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T(
"AISTargetList"));
487 pane.FloatingSize(fsize.x, fsize.y);
488 wxPoint pos = gFrame->GetScreenPosition();
489 pane.FloatingPosition(pos.x + (dsize.x - fsize.x) / 2,
490 pos.y + (dsize.y - fsize.y) / 2);
493 m_pAuiManager->Update();
497void AISTargetListDialog::CreateControls() {
498 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
501 this->GetHandle()->setStyleSheet(getQtStyleSheet());
505 wxStringTokenizer tkz(g_AisTargetList_column_spec, _T(
";"));
506 wxString s_width = tkz.GetNextToken();
510 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
513 flags |= wxLC_VIRTUAL;
517 this, ID_AIS_TARGET_LIST, wxDefaultPosition, wxDefaultSize, flags);
519 wxImageList *imglist =
new wxImageList(16, 16,
true, 2);
522 imglist->Add(style->GetIcon(_T(
"sort_asc")));
523 imglist->Add(style->GetIcon(_T(
"sort_desc")));
525 m_pListCtrlAISTargets->AssignImageList(imglist, wxIMAGE_LIST_SMALL);
526 m_pListCtrlAISTargets->Connect(
527 wxEVT_COMMAND_LIST_ITEM_SELECTED,
528 wxListEventHandler(AISTargetListDialog::OnTargetSelected), NULL,
this);
529 m_pListCtrlAISTargets->Connect(
530 wxEVT_COMMAND_LIST_ITEM_DESELECTED,
531 wxListEventHandler(AISTargetListDialog::OnTargetSelected), NULL,
this);
532 m_pListCtrlAISTargets->Connect(
533 wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
534 wxListEventHandler(AISTargetListDialog::OnTargetDefaultAction), NULL,
536 m_pListCtrlAISTargets->Connect(
537 wxEVT_COMMAND_LIST_COL_CLICK,
538 wxListEventHandler(AISTargetListDialog::OnTargetListColumnClicked), NULL,
541 int dx = GetCharWidth();
544 if (s_width.ToLong(&lwidth)) {
545 width = wxMax(dx * 2, lwidth);
546 width = wxMin(width, dx * 30);
548 m_pListCtrlAISTargets->InsertColumn(tlTRK, _(
"Trk"), wxLIST_FORMAT_LEFT,
550 s_width = tkz.GetNextToken();
553 if (s_width.ToLong(&lwidth)) {
554 width = wxMax(dx * 2, lwidth);
555 width = wxMin(width, dx * 30);
557 m_pListCtrlAISTargets->InsertColumn(tlNAME, _(
"Name"), wxLIST_FORMAT_LEFT,
559 s_width = tkz.GetNextToken();
562 if (s_width.ToLong(&lwidth)) {
563 width = wxMax(dx * 2, lwidth);
564 width = wxMin(width, dx * 30);
566 m_pListCtrlAISTargets->InsertColumn(tlCALL, _(
"Call"), wxLIST_FORMAT_LEFT,
568 s_width = tkz.GetNextToken();
571 if (s_width.ToLong(&lwidth)) {
572 width = wxMax(dx * 2, lwidth);
573 width = wxMin(width, dx * 30);
575 m_pListCtrlAISTargets->InsertColumn(tlMMSI, _(
"MMSI"), wxLIST_FORMAT_LEFT,
577 s_width = tkz.GetNextToken();
580 if (s_width.ToLong(&lwidth)) {
581 width = wxMax(dx * 2, lwidth);
582 width = wxMin(width, dx * 30);
584 m_pListCtrlAISTargets->InsertColumn(tlCLASS, _(
"Class"), wxLIST_FORMAT_CENTER,
586 s_width = tkz.GetNextToken();
589 if (s_width.ToLong(&lwidth)) {
590 width = wxMax(dx * 2, lwidth);
591 width = wxMin(width, dx * 30);
593 m_pListCtrlAISTargets->InsertColumn(tlTYPE, _(
"Type"), wxLIST_FORMAT_LEFT,
595 s_width = tkz.GetNextToken();
598 if (s_width.ToLong(&lwidth)) {
599 width = wxMax(dx * 2, lwidth);
600 width = wxMin(width, dx * 30);
602 m_pListCtrlAISTargets->InsertColumn(tlNAVSTATUS, _(
"Flag"),
603 wxLIST_FORMAT_LEFT, width);
604 s_width = tkz.GetNextToken();
607 if (s_width.ToLong(&lwidth)) {
608 width = wxMax(dx * 2, lwidth);
609 width = wxMin(width, dx * 30);
611 m_pListCtrlAISTargets->InsertColumn(tlNAVSTATUS, _(
"Nav Status"),
612 wxLIST_FORMAT_LEFT, width);
613 s_width = tkz.GetNextToken();
616 if (s_width.ToLong(&lwidth)) {
617 width = wxMax(dx * 2, lwidth);
618 width = wxMin(width, dx * 30);
620 m_pListCtrlAISTargets->InsertColumn(tlBRG, _(
"Brg"), wxLIST_FORMAT_RIGHT,
622 s_width = tkz.GetNextToken();
625 if (s_width.ToLong(&lwidth)) {
626 width = wxMax(dx * 2, lwidth);
627 width = wxMin(width, dx * 30);
629 m_pListCtrlAISTargets->InsertColumn(tlRNG, _(
"Range"), wxLIST_FORMAT_RIGHT,
631 s_width = tkz.GetNextToken();
634 if (s_width.ToLong(&lwidth)) {
635 width = wxMax(dx * 2, lwidth);
636 width = wxMin(width, dx * 30);
638 m_pListCtrlAISTargets->InsertColumn(tlCOG, _(
"CoG"), wxLIST_FORMAT_RIGHT,
640 s_width = tkz.GetNextToken();
643 if (s_width.ToLong(&lwidth)) {
644 width = wxMax(dx * 2, lwidth);
645 width = wxMin(width, dx * 30);
647 m_pListCtrlAISTargets->InsertColumn(tlSOG, _(
"SoG"), wxLIST_FORMAT_RIGHT,
651 if (s_width.ToLong(&lwidth)) {
652 width = wxMax(dx * 2, lwidth);
653 width = wxMin(width, dx * 30);
655 m_pListCtrlAISTargets->InsertColumn(tlCPA, _(
"CPA"), wxLIST_FORMAT_RIGHT,
659 if (s_width.ToLong(&lwidth)) {
660 width = wxMax(dx * 2, lwidth);
661 width = wxMin(width, dx * 30);
663 m_pListCtrlAISTargets->InsertColumn(tlTCPA, _(
"TCPA"), wxLIST_FORMAT_RIGHT,
666 item.SetMask(wxLIST_MASK_IMAGE);
667 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
668 g_AisTargetList_sortColumn = wxMax(g_AisTargetList_sortColumn, 0);
669 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
671#ifdef wxHAS_LISTCTRL_COLUMN_ORDER
672 wxStringTokenizer tkz_order(g_AisTargetList_column_order, _T(
";"));
673 wxString s_order = tkz_order.GetNextToken();
674 int i_columns = m_pListCtrlAISTargets->GetColumnCount();
675 wxArrayInt a_order(i_columns);
676 for (
int i = 0; i < i_columns; i++) {
677 long l_order = (long)i;
678 s_order.ToLong(&l_order);
679 if (l_order < 0 || l_order > i_columns) {
682 a_order[i] = l_order;
683 s_order = tkz_order.GetNextToken();
686 m_pListCtrlAISTargets->SetColumnsOrder(a_order);
689 topSizer->Add(m_pListCtrlAISTargets, 1, wxEXPAND | wxALL, 0);
691 wxBoxSizer *boxSizer02 =
new wxBoxSizer(wxVERTICAL);
692 boxSizer02->AddSpacer(22);
693 topSizer->Add(boxSizer02, 0, wxEXPAND | wxALL, 2);
695 wxScrolledWindow *winr =
696 new wxScrolledWindow(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
697 wxNO_BORDER | wxTAB_TRAVERSAL | wxVSCROLL);
698 winr->SetScrollRate(0, 5);
700 boxSizer02->Add(winr, 1, wxALL | wxEXPAND, 3);
702 wxBoxSizer *bsRouteButtonsInner =
new wxBoxSizer(wxVERTICAL);
703 winr->SetSizer(bsRouteButtonsInner);
705 m_pButtonInfo =
new wxButton(winr, wxID_ANY, _(
"Target info"),
706 wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
707 m_pButtonInfo->Connect(
708 wxEVT_COMMAND_BUTTON_CLICKED,
709 wxCommandEventHandler(AISTargetListDialog::OnTargetQuery), NULL,
this);
710 bsRouteButtonsInner->Add(m_pButtonInfo, 0, wxEXPAND | wxALL, 2);
711 bsRouteButtonsInner->AddSpacer(5);
714 new wxButton(winr, wxID_ANY, _(
"Center view"), wxDefaultPosition,
715 wxDefaultSize, wxBU_AUTODRAW);
716 m_pButtonJumpTo->Connect(
717 wxEVT_COMMAND_BUTTON_CLICKED,
718 wxCommandEventHandler(AISTargetListDialog::OnTargetScrollTo), NULL,
this);
719 bsRouteButtonsInner->Add(m_pButtonJumpTo, 0, wxEXPAND | wxALL, 2);
721 m_pButtonJumpTo_Close =
722 new wxButton(winr, wxID_ANY, _(
"Center-Info-Close"), wxDefaultPosition,
723 wxDefaultSize, wxBU_AUTODRAW);
724 m_pButtonJumpTo_Close->Connect(
725 wxEVT_COMMAND_BUTTON_CLICKED,
726 wxCommandEventHandler(AISTargetListDialog::OnTargetScrollToClose), NULL,
728 bsRouteButtonsInner->Add(m_pButtonJumpTo_Close, 0, wxEXPAND | wxALL, 2);
731 new wxButton(winr, wxID_ANY, _(
"Create WPT"), wxDefaultPosition,
732 wxDefaultSize, wxBU_AUTODRAW);
733 m_pButtonCreateWpt->Connect(
734 wxEVT_COMMAND_BUTTON_CLICKED,
735 wxCommandEventHandler(AISTargetListDialog::OnTargetCreateWpt), NULL,
737 bsRouteButtonsInner->Add(m_pButtonCreateWpt, 0, wxEXPAND | wxALL, 0);
739 m_pButtonHideAllTracks =
740 new wxButton(winr, wxID_ANY, _(
"Hide All Tracks"), wxDefaultPosition,
741 wxDefaultSize, wxBU_AUTODRAW);
742 m_pButtonHideAllTracks->Connect(
743 wxEVT_COMMAND_BUTTON_CLICKED,
744 wxCommandEventHandler(AISTargetListDialog::OnHideAllTracks), NULL,
this);
745 bsRouteButtonsInner->Add(m_pButtonHideAllTracks, 0, wxEXPAND | wxALL, 2);
747 m_pButtonShowAllTracks =
748 new wxButton(winr, wxID_ANY, _(
"Show All Tracks"), wxDefaultPosition,
749 wxDefaultSize, wxBU_AUTODRAW);
750 m_pButtonShowAllTracks->Connect(
751 wxEVT_COMMAND_BUTTON_CLICKED,
752 wxCommandEventHandler(AISTargetListDialog::OnShowAllTracks), NULL,
this);
753 bsRouteButtonsInner->Add(m_pButtonShowAllTracks, 0, wxEXPAND | wxALL, 2);
755 m_pButtonToggleTrack =
756 new wxButton(winr, wxID_ANY, _(
"Toggle track"), wxDefaultPosition,
757 wxDefaultSize, wxBU_AUTODRAW);
758 m_pButtonToggleTrack->Connect(
759 wxEVT_COMMAND_BUTTON_CLICKED,
760 wxCommandEventHandler(AISTargetListDialog::OnToggleTrack), NULL,
this);
761 bsRouteButtonsInner->Add(m_pButtonToggleTrack, 0, wxEXPAND | wxALL, 2);
764 new wxButton(winr, wxID_ANY, _(
"Copy MMSI"), wxDefaultPosition,
765 wxDefaultSize, wxBU_AUTODRAW);
766 m_pButtonCopyMMSI->Connect(
767 wxEVT_COMMAND_BUTTON_CLICKED,
768 wxCommandEventHandler(AISTargetListDialog::OnCopyMMSI), NULL,
this);
769 bsRouteButtonsInner->Add(m_pButtonCopyMMSI, 0, wxEXPAND | wxALL, 2);
772 new wxCheckBox(winr, wxID_ANY, _(
"AutoSort"), wxDefaultPosition,
773 wxDefaultSize, wxBU_AUTODRAW);
774 m_pCBAutosort->Connect(
775 wxEVT_COMMAND_CHECKBOX_CLICKED,
776 wxCommandEventHandler(AISTargetListDialog::OnAutosortCB), NULL,
this);
777 bsRouteButtonsInner->Add(m_pCBAutosort, 0, wxEXPAND | wxALL, 2);
778 g_bAisTargetList_autosort =
true;
779 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
781 bsRouteButtonsInner->AddSpacer(10);
783 m_pStaticTextRange =
new wxStaticText(winr, wxID_ANY, _(
"Limit range: NM"),
784 wxDefaultPosition, wxDefaultSize, 0);
785 bsRouteButtonsInner->Add(m_pStaticTextRange, 0, wxALL, 2);
786 bsRouteButtonsInner->AddSpacer(2);
787 m_pSpinCtrlRange =
new wxSpinCtrl(
788 winr, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(50, -1),
789 wxSP_ARROW_KEYS, 1, 20000, g_AisTargetList_range);
790 m_pSpinCtrlRange->Connect(
791 wxEVT_COMMAND_SPINCTRL_UPDATED,
792 wxCommandEventHandler(AISTargetListDialog::OnLimitRange), NULL,
this);
793 m_pSpinCtrlRange->Connect(
794 wxEVT_COMMAND_TEXT_UPDATED,
795 wxCommandEventHandler(AISTargetListDialog::OnLimitRange), NULL,
this);
796 bsRouteButtonsInner->Add(m_pSpinCtrlRange, 0, wxEXPAND | wxALL, 0);
798 bsRouteButtonsInner->AddSpacer(10);
799 m_pStaticTextCount =
new wxStaticText(winr, wxID_ANY, _(
"Target Count"),
800 wxDefaultPosition, wxDefaultSize, 0);
801 bsRouteButtonsInner->Add(m_pStaticTextCount, 0, wxALL, 2);
803 bsRouteButtonsInner->AddSpacer(2);
804 m_pTextTargetCount =
new wxTextCtrl(winr, wxID_ANY, _T(
""), wxDefaultPosition,
805 wxDefaultSize, wxTE_READONLY);
806 m_pTextTargetCount->SetMinSize(wxSize(6 * GetCharWidth(), -1));
807 bsRouteButtonsInner->Add(m_pTextTargetCount, 0, wxALL, 2);
809 bsRouteButtonsInner->AddSpacer(10);
810 m_pButtonOK =
new wxButton(winr, wxID_ANY, _(
"Close"), wxDefaultPosition,
811 wxDefaultSize, wxBU_AUTODRAW);
812 m_pButtonOK->Connect(
813 wxEVT_COMMAND_BUTTON_CLICKED,
814 wxCommandEventHandler(AISTargetListDialog::OnCloseButton), NULL,
this);
815 bsRouteButtonsInner->Add(m_pButtonOK, 0, wxEXPAND | wxALL, 0);
822 SetSize(GetSize().x, GetSize().y - 1);
825void AISTargetListDialog::OnClose(wxCloseEvent &event) {
826 Disconnect_decoder();
828 g_pAISTargetList = NULL;
831void AISTargetListDialog::Disconnect_decoder() { m_pdecoder = NULL; }
833void AISTargetListDialog::SetColorScheme() { DimeControl(
this); }
835void AISTargetListDialog::OnPaneClose(wxAuiManagerEvent &event) {
836 if (event.pane->name == _T(
"AISTargetList")) {
837 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(*event.pane);
842void AISTargetListDialog::OnCloseButton(wxCommandEvent &event) { Shutdown(); }
844void AISTargetListDialog::Shutdown(
void) {
846 wxAuiPaneInfo pane = m_pAuiManager->GetPane(
this);
847 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
848 m_pAuiManager->DetachPane(
this);
849 Disconnect_decoder();
851 m_pAuiManager->Update();
853 GetParent()->Refresh(
true);
859void AISTargetListDialog::UpdateButtons() {
861 item = m_pListCtrlAISTargets->GetNextItem(item, wxLIST_NEXT_ALL,
862 wxLIST_STATE_SELECTED);
863 bool enable = (item != -1);
865 m_pButtonInfo->Enable(enable);
867 if (m_pdecoder && item != -1) {
869 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(item));
870 if (pAISTargetSel && (!pAISTargetSel->b_positionOnceValid)) enable =
false;
872 m_pButtonJumpTo->Enable(enable);
873 m_pButtonJumpTo_Close->Enable(enable);
874 m_pButtonCreateWpt->Enable(enable);
875 m_pButtonToggleTrack->Enable(enable);
876 m_pButtonCopyMMSI->Enable(enable);
879void AISTargetListDialog::OnTargetSelected(wxListEvent &event) {
883void AISTargetListDialog::DoTargetQuery(
int mmsi) {
884 ShowAISTargetQueryDialog(m_pparent, mmsi);
891void AISTargetListDialog::OnTargetDefaultAction(wxListEvent &event) {
893 if ((mmsi_no = event.GetData())) DoTargetQuery(mmsi_no);
896void AISTargetListDialog::OnTargetQuery(wxCommandEvent &event) {
898 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
899 wxLIST_STATE_SELECTED);
900 if (selItemID == -1)
return;
904 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
905 if (pAISTarget) DoTargetQuery(pAISTarget->MMSI);
909void AISTargetListDialog::OnAutosortCB(wxCommandEvent &event) {
910 g_bAisTargetList_autosort = m_pCBAutosort->GetValue();
912 m_bautosort_force = g_bAisTargetList_autosort;
914 if (!g_bAisTargetList_autosort) {
916 item.SetMask(wxLIST_MASK_IMAGE);
918 g_AisTargetList_sortColumn = wxMax(g_AisTargetList_sortColumn, 0);
919 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
922 item.SetMask(wxLIST_MASK_IMAGE);
923 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
925 if (g_AisTargetList_sortColumn >= 0) {
926 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
927 UpdateAISTargetList();
932void AISTargetListDialog::OnTargetListColumnClicked(wxListEvent &event) {
933 int key =
event.GetColumn();
935 item.SetMask(wxLIST_MASK_IMAGE);
936 if (key == g_AisTargetList_sortColumn)
937 g_bAisTargetList_sortReverse = !g_bAisTargetList_sortReverse;
940 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
941 g_bAisTargetList_sortReverse =
false;
942 g_AisTargetList_sortColumn = key;
944 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
946 if (!g_bAisTargetList_autosort) g_bsort_once =
true;
948 if (g_AisTargetList_sortColumn >= 0) {
949 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
950 UpdateAISTargetList();
954void AISTargetListDialog::OnTargetScrollTo(wxCommandEvent &event) {
955 CenterToTarget(
false);
958void AISTargetListDialog::OnTargetScrollToClose(wxCommandEvent &event) {
959 CenterToTarget(
true);
962void AISTargetListDialog::OnTargetCreateWpt(wxCommandEvent &event) {
964 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
965 wxLIST_STATE_SELECTED);
966 if (selItemID == -1)
return;
968 std::shared_ptr<AisTargetData> pAISTarget = NULL;
971 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
975 new RoutePoint(pAISTarget->Lat, pAISTarget->Lon, g_default_wp_icon,
976 wxEmptyString, wxEmptyString);
978 pSelect->AddSelectableRoutePoint(pAISTarget->Lat, pAISTarget->Lon, pWP);
980 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
982 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
983 pRouteManagerDialog->UpdateWptListCtrl();
984 gFrame->GetPrimaryCanvas()->undo->BeforeUndoableAction(
985 Undo_CreateWaypoint, pWP, Undo_HasParent, NULL);
986 gFrame->GetPrimaryCanvas()->undo->AfterUndoableAction(NULL);
991void AISTargetListDialog::OnShowAllTracks(wxCommandEvent &event) {
993 for (
const auto &it : m_pdecoder->GetTargetList()) {
994 auto pAISTarget = it.second;
995 if (NULL != pAISTarget) {
996 pAISTarget->b_show_track =
true;
999 UpdateAISTargetList();
1003void AISTargetListDialog::OnHideAllTracks(wxCommandEvent &event) {
1005 for (
const auto &it : m_pdecoder->GetTargetList()) {
1006 auto pAISTarget = it.second;
1007 if (NULL != pAISTarget) {
1008 pAISTarget->b_show_track =
false;
1011 std::map<int, Track *>::iterator it;
1012 it = g_pAIS->m_persistent_tracks.find(pAISTarget->MMSI);
1013 if (it != g_pAIS->m_persistent_tracks.end())
1014 pAISTarget->b_show_track =
true;
1017 UpdateAISTargetList();
1021void AISTargetListDialog::OnToggleTrack(wxCommandEvent &event) {
1022 long selItemID = -1;
1023 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1024 wxLIST_STATE_SELECTED);
1025 if (selItemID == -1)
return;
1027 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1030 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1033 pAISTarget->b_show_track = !pAISTarget->b_show_track;
1034 UpdateAISTargetList();
1038void AISTargetListDialog::OnCopyMMSI(wxCommandEvent &event) {
1039 long selItemID = -1;
1040 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1041 wxLIST_STATE_SELECTED);
1042 if (selItemID == -1)
return;
1043 CopyMMSItoClipBoard((
int)m_pMMSI_array->Item(selItemID));
1046void AISTargetListDialog::CenterToTarget(
bool close) {
1047 long selItemID = -1;
1048 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1049 wxLIST_STATE_SELECTED);
1050 if (selItemID == -1)
return;
1052 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1055 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1058 double scale = gFrame->GetFocusCanvas()->GetVPScale();
1060 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), pAISTarget->Lat,
1061 pAISTarget->Lon,
scale);
1066 double factor = cc->GetScaleValue() / 5000.0;
1067 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), pAISTarget->Lat,
1068 pAISTarget->Lon,
scale * factor);
1070 DoTargetQuery(pAISTarget->MMSI);
1077void AISTargetListDialog::CopyMMSItoClipBoard(
int mmsi) {
1079 if (wxTheClipboard->Open()) {
1080 wxTheClipboard->SetData(
1081 new wxTextDataObject(wxString::Format(wxT(
"%09d"), mmsi)));
1082 wxTheClipboard->Close();
1085void AISTargetListDialog::OnLimitRange(wxCommandEvent &event) {
1086 g_AisTargetList_range = m_pSpinCtrlRange->GetValue();
1087 UpdateAISTargetList();
1090std::shared_ptr<AisTargetData> AISTargetListDialog::GetpTarget(
1091 unsigned int list_item) {
1093 return m_pdecoder->Get_Target_Data_From_MMSI(
1094 m_pMMSI_array->Item(list_item));
1099void AISTargetListDialog::UpdateAISTargetList(
void) {
1100 if (m_pListCtrlAISTargets && !m_pListCtrlAISTargets->IsVirtual())
1101 return UpdateNVAISTargetList();
1103 if (m_pdecoder && m_pListCtrlAISTargets) {
1105 long selItemID = -1;
1106 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1107 wxLIST_STATE_SELECTED);
1110 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1112 const auto ¤t_targets = m_pdecoder->GetTargetList();
1116 m_pMMSI_array->Clear();
1118 for (
auto it = current_targets.begin(); it != current_targets.end();
1120 auto pAISTarget = it->second;
1123 if (NULL != pAISTarget) {
1125 if ((pAISTarget->b_positionOnceValid) &&
1126 (pAISTarget->Range_NM <= g_AisTargetList_range))
1128 else if (!pAISTarget->b_positionOnceValid)
1132 if (pAISTarget->b_lost) b_add =
false;
1135 m_pMMSI_array->Add(pAISTarget->MMSI);
1140 g_bsort_once =
false;
1142 m_pListCtrlAISTargets->SetItemCount(m_pMMSI_array->GetCount());
1144 g_AisTargetList_count = m_pMMSI_array->GetCount();
1146 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1147 g_bAisTargetList_autosort =
false;
1149 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1153 if ((selItemID != -1) && (selMMSI != -1)) {
1154 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1155 if (m_pMMSI_array->Item(i) == selMMSI) {
1162 if (m_pMMSI_array->GetCount())
1163 m_pListCtrlAISTargets->SetItemState(
1164 item_sel, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1165 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1167 m_pListCtrlAISTargets->DeleteAllItems();
1170 count.Printf(_T(
"%lu"), (
unsigned long)m_pMMSI_array->GetCount());
1171 m_pTextTargetCount->ChangeValue(count);
1174 m_pListCtrlAISTargets->Refresh(
false);
1179void AISTargetListDialog::UpdateNVAISTargetList(
void) {
1182 long selItemID = -1;
1183 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1184 wxLIST_STATE_SELECTED);
1187 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1189 const auto ¤t_targets = m_pdecoder->GetTargetList();
1193 m_pMMSI_array->Clear();
1195 for (
auto it = current_targets.begin(); it != current_targets.end();
1197 auto pAISTarget = it->second;
1200 if (NULL != pAISTarget) {
1202 if ((pAISTarget->b_positionOnceValid) &&
1203 (pAISTarget->Range_NM <= g_AisTargetList_range))
1205 else if (!pAISTarget->b_positionOnceValid)
1209 m_pMMSI_array->Add(pAISTarget->MMSI);
1214 g_bsort_once =
false;
1216 g_AisTargetList_count = m_pMMSI_array->GetCount();
1218 m_pListCtrlAISTargets->DeleteAllItems();
1220 for (
int i = 0; i < g_AisTargetList_count; i++) {
1223 m_pListCtrlAISTargets->InsertItem(item);
1224 for (
int j = 0; j < tlTCPA + 1; j++) {
1226 item.SetText(m_pListCtrlAISTargets->OnGetItemText(i, j));
1227 m_pListCtrlAISTargets->SetItem(item);
1231 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1232 g_bAisTargetList_autosort =
false;
1234 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1238 if ((selItemID != -1) && (selMMSI != -1)) {
1239 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1240 if (m_pMMSI_array->Item(i) == selMMSI) {
1247 if (m_pMMSI_array->GetCount())
1248 m_pListCtrlAISTargets->SetItemState(
1249 item_sel, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1250 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1252 m_pListCtrlAISTargets->DeleteAllItems();
1255 count.Printf(_T(
"%lu"), (
unsigned long)m_pMMSI_array->GetCount());
1256 m_pTextTargetCount->ChangeValue(count);
1259 m_pListCtrlAISTargets->Refresh(
false);
1264void AISTargetListDialog::OnRightClickContext(wxCommandEvent &event) {
1265 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T(
"AISTargetList"));
1266 if (pane.IsDocked()) {
1267 wxMenu *popup =
new wxMenu();
1268 popup->Append(ID_RCLK_UNDOCK, _(
"Undock Target List"));
1269 popup->Connect(wxEVT_COMMAND_MENU_SELECTED,
1270 wxCommandEventHandler(AISTargetListDialog::OnContextUndock),
1278void AISTargetListDialog::OnContextUndock(wxCommandEvent &event) {
1279 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T(
"AISTargetList"));
1281 m_pAuiManager->Update();
Global state for AIS decoder.
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.