25#include <wx/textctrl.h>
27#include <wx/tokenzr.h>
28#include <wx/clipbrd.h>
30#ifdef __OCPN__ANDROID__
31#include "androidUTIL.h"
34#include "AISTargetListDialog.h"
36#include "ais_decoder.h"
37#include "ais_target_data.h"
38#include "OCPNListCtrl.h"
41#include "routemanagerdialog.h"
42#include "OCPNPlatform.h"
43#include "route_point.h"
45#include "ocpn_frame.h"
49extern int g_AisTargetList_count;
50extern bool g_bAisTargetList_sortReverse;
51extern bool g_bAisTargetList_autosort;
52extern int g_AisTargetList_sortColumn;
53extern wxString g_AisTargetList_column_spec;
54extern wxString g_AisTargetList_column_order;
56extern int g_AisTargetList_range;
57extern wxString g_AisTargetList_perspective;
61extern wxString g_default_wp_icon;
69EVT_CLOSE(AISTargetListDialog::OnClose)
72static
bool g_bsort_once;
79 bool b_cmptype_num =
false;
82 if (!g_bAisTargetList_autosort && !g_bsort_once)
return 0;
87 if (t1->Class == AIS_SART) {
88 if (t2->Class == AIS_DSC)
94 if (t2->Class == AIS_SART) {
95 if (t1->Class == AIS_DSC)
101 switch (g_AisTargetList_sortColumn) {
103 n1 = t1->b_show_track;
104 n2 = t2->b_show_track;
105 b_cmptype_num =
true;
109 s1 = trimAISField(t1->ShipName);
110 if ((!t1->b_nameValid && (t1->Class == AIS_BASE)) ||
111 (t1->Class == AIS_SART))
114 s2 = trimAISField(t2->ShipName);
115 if ((!t2->b_nameValid && (t2->Class == AIS_BASE)) ||
116 (t2->Class == AIS_SART))
121 s1 = trimAISField(t1->CallSign);
122 s2 = trimAISField(t2->CallSign);
128 b_cmptype_num =
true;
132 s1 = t1->Get_class_string(
true);
133 s2 = t2->Get_class_string(
true);
137 s1 = t1->Get_vessel_type_string(
false);
138 if ((t1->Class == AIS_BASE) || (t1->Class == AIS_SART)) s1 = _T(
"-");
140 s2 = t2->Get_vessel_type_string(
false);
141 if ((t1->Class == AIS_BASE) || (t1->Class == AIS_SART)) s2 = _T(
"-");
145 if ((t1->NavStatus <= 15) && (t1->NavStatus >= 0)) {
146 if (t1->Class == AIS_SART) {
147 if (t1->NavStatus == RESERVED_14)
149 else if (t1->NavStatus == UNDEFINED)
152 s1 = ais_get_status(t1->NavStatus);
156 if ((t1->Class == AIS_ATON) || (t1->Class == AIS_BASE) ||
157 (t1->Class == AIS_CLASS_B))
160 if ((t2->NavStatus <= 15) && (t2->NavStatus >= 0)) {
161 if (t2->Class == AIS_SART) {
162 if (t2->NavStatus == RESERVED_14)
164 else if (t2->NavStatus == UNDEFINED)
167 s2 = ais_get_status(t2->NavStatus);
171 if ((t2->Class == AIS_ATON) || (t2->Class == AIS_BASE) ||
172 (t2->Class == AIS_CLASS_B))
179 int brg1 = wxRound(t1->Brg);
185 int brg2 = wxRound(t2->Brg);
191 b_cmptype_num =
true;
196 if ((t1->COG >= 360.0) || (t1->Class == AIS_ATON) ||
197 (t1->Class == AIS_BASE))
200 int crs = wxRound(t1->COG);
207 if ((t2->COG >= 360.0) || (t2->Class == AIS_ATON) ||
208 (t2->Class == AIS_BASE))
211 int crs = wxRound(t2->COG);
218 b_cmptype_num =
true;
223 if ((t1->SOG > 100.) || (t1->Class == AIS_ATON) ||
224 (t1->Class == AIS_BASE))
229 if ((t2->SOG > 100.) || (t2->Class == AIS_ATON) ||
230 (t2->Class == AIS_BASE))
235 b_cmptype_num =
true;
239 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
240 (t1->Class == AIS_BASE))
245 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
246 (t2->Class == AIS_BASE))
251 b_cmptype_num =
true;
255 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
256 (t1->Class == AIS_BASE))
261 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
262 (t2->Class == AIS_BASE))
267 b_cmptype_num =
true;
273 b_cmptype_num =
true;
281 if (!b_cmptype_num) {
282 if (g_bAisTargetList_sortReverse)
return s2.Cmp(s1);
286 if (g_bAisTargetList_sortReverse) {
292 return (t1->Range_NM > t2->Range_NM);
299 return (t1->Range_NM > t2->Range_NM);
304static int ArrayItemCompareMMSI(
int MMSI1,
int MMSI2) {
305 if (s_p_sort_decoder) {
306 std::shared_ptr<AisTargetData> pAISTarget1 =
307 s_p_sort_decoder->Get_Target_Data_From_MMSI(MMSI1);
308 std::shared_ptr<AisTargetData> pAISTarget2 =
309 s_p_sort_decoder->Get_Target_Data_From_MMSI(MMSI2);
311 if (pAISTarget1 && pAISTarget2)
312 return ItemCompare(pAISTarget1.get(), pAISTarget2.get());
319AISTargetListDialog::AISTargetListDialog(wxWindow *parent, wxAuiManager *auimgr,
321 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, -1 ),
324 m_pAuiManager = auimgr;
325 m_pdecoder = pdecoder;
326 g_bsort_once =
false;
327 m_bautosort_force =
false;
329 wxFont *qFont = GetOCPNScaledFont(_(
"Dialog"));
332 s_p_sort_decoder = pdecoder;
333 m_pMMSI_array =
new ArrayOfMMSI(ArrayItemCompareMMSI);
338 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
344 wxAuiPaneInfo paneproto = wxAuiPaneInfo()
345 .Name(_T(
"AISTargetList"))
346 .CaptionVisible(
true)
348 .FloatingPosition(50, 50)
349 .FloatingSize(400, 200)
350 .BestSize(700, GetCharHeight() * 10);
354 paneproto.Caption(wxGetTranslation(_(
"AIS target list")));
355 paneproto.Name(_T(
"AISTargetList"));
356 paneproto.DestroyOnClose(
true);
357 paneproto.TopDockable(
false)
358 .BottomDockable(
true)
360 .RightDockable(
false);
361 paneproto.Show(
true);
363 m_pAuiManager->AddPane(
this, paneproto);
365 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T(
"AISTargetList"));
367 if (g_AisTargetList_perspective.IsEmpty()) {
368 if (!g_btouch) RecalculateSize();
370 m_pAuiManager->LoadPaneInfo(g_AisTargetList_perspective, pane);
371 m_pAuiManager->Update();
375 m_pAuiManager->GetPane(_T(
"AISTargetList"));
380 pane.Dockable(
false);
382 wxSize screen_size = gFrame->GetClientSize();
383 pane.FloatingSize(screen_size.x * 8 / 10, screen_size.y * 8 / 10);
384 pane.FloatingPosition(screen_size.x * 1 / 10, screen_size.y * 1 / 10);
385 m_pAuiManager->Update();
388 bool b_reset_pos =
false;
389 if ((pane.floating_size.x != -1) && (pane.floating_size.y != -1)) {
394 RECT frame_title_rect;
395 frame_title_rect.left = pane.floating_pos.x;
396 frame_title_rect.top = pane.floating_pos.y;
397 frame_title_rect.right = pane.floating_pos.x + pane.floating_size.x;
398 frame_title_rect.bottom = pane.floating_pos.y + 30;
400 if (NULL == MonitorFromRect(&frame_title_rect, MONITOR_DEFAULTTONULL))
406 wxRect window_title_rect;
407 window_title_rect.x = pane.floating_pos.x;
408 window_title_rect.y = pane.floating_pos.y;
409 window_title_rect.width = pane.floating_size.x;
410 window_title_rect.height = 30;
412 wxRect ClientRect = wxGetClientDisplayRect();
415 if (!ClientRect.Intersects(window_title_rect)) b_reset_pos =
true;
420 pane.FloatingPosition(50, 50);
421 m_pAuiManager->Update();
427 if (pane.IsDocked() && (pane.dock_row == 0)) {
431 m_pAuiManager->Update();
435 m_pAuiManager->Update();
437 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
438 pConfig->UpdateSettings();
440 m_pAuiManager->Connect(
441 wxEVT_AUI_PANE_CLOSE,
442 wxAuiManagerEventHandler(AISTargetListDialog::OnPaneClose), NULL,
this);
449 esize.y = GetCharHeight() * 10;
454 Connect(wxEVT_CONTEXT_MENU,
455 wxCommandEventHandler(AISTargetListDialog::OnRightClickContext), NULL,
459AISTargetListDialog::~AISTargetListDialog() {
460 Disconnect_decoder();
461 g_pAISTargetList = NULL;
464void AISTargetListDialog::RecalculateSize() {
468 esize.x = GetCharWidth() * 110;
469 esize.y = GetCharHeight() * 40;
471 wxSize dsize = gFrame->GetClientSize();
472 esize.y = wxMin(esize.y, dsize.y - (4 * GetCharHeight()));
473 esize.x = wxMin(esize.x, dsize.x - (2 * GetCharHeight()));
474 SetClientSize(esize);
476 wxSize fsize = GetSize();
477 fsize.y = wxMin(fsize.y, dsize.y - (2 * GetCharHeight()));
478 fsize.x = wxMin(fsize.x, dsize.x - (2 * GetCharHeight()));
482 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T(
"AISTargetList"));
485 pane.FloatingSize(fsize.x, fsize.y);
486 wxPoint pos = gFrame->GetScreenPosition();
487 pane.FloatingPosition(pos.x + (dsize.x - fsize.x) / 2,
488 pos.y + (dsize.y - fsize.y) / 2);
491 m_pAuiManager->Update();
495void AISTargetListDialog::CreateControls() {
496 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
498#ifdef __OCPN__ANDROID__
499 this->GetHandle()->setStyleSheet(getQtStyleSheet());
503 wxStringTokenizer tkz(g_AisTargetList_column_spec, _T(
";"));
504 wxString s_width = tkz.GetNextToken();
508 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
511 flags |= wxLC_VIRTUAL;
515 this, ID_AIS_TARGET_LIST, wxDefaultPosition, wxDefaultSize, flags);
517 wxImageList *imglist =
new wxImageList(16, 16,
true, 2);
520 imglist->Add(style->GetIcon(_T(
"sort_asc")));
521 imglist->Add(style->GetIcon(_T(
"sort_desc")));
523 m_pListCtrlAISTargets->AssignImageList(imglist, wxIMAGE_LIST_SMALL);
524 m_pListCtrlAISTargets->Connect(
525 wxEVT_COMMAND_LIST_ITEM_SELECTED,
526 wxListEventHandler(AISTargetListDialog::OnTargetSelected), NULL,
this);
527 m_pListCtrlAISTargets->Connect(
528 wxEVT_COMMAND_LIST_ITEM_DESELECTED,
529 wxListEventHandler(AISTargetListDialog::OnTargetSelected), NULL,
this);
530 m_pListCtrlAISTargets->Connect(
531 wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
532 wxListEventHandler(AISTargetListDialog::OnTargetDefaultAction), NULL,
534 m_pListCtrlAISTargets->Connect(
535 wxEVT_COMMAND_LIST_COL_CLICK,
536 wxListEventHandler(AISTargetListDialog::OnTargetListColumnClicked), NULL,
539 int dx = GetCharWidth();
542 if (s_width.ToLong(&lwidth)) {
543 width = wxMax(dx * 2, lwidth);
544 width = wxMin(width, dx * 30);
546 m_pListCtrlAISTargets->InsertColumn(tlTRK, _(
"Trk"), 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(tlNAME, _(
"Name"), 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(tlCALL, _(
"Call"), 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(tlMMSI, _(
"MMSI"), wxLIST_FORMAT_LEFT,
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(tlCLASS, _(
"Class"), wxLIST_FORMAT_CENTER,
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(tlTYPE, _(
"Type"), wxLIST_FORMAT_LEFT,
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, _T(
";"));
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,
this);
716 bsRouteButtonsInner->Add(m_pButtonJumpTo_Close, 0, wxEXPAND | wxALL, 2);
719 new wxButton(winr, wxID_ANY, _(
"Create WPT"), wxDefaultPosition,
720 wxDefaultSize, wxBU_AUTODRAW);
721 m_pButtonCreateWpt->Connect(
722 wxEVT_COMMAND_BUTTON_CLICKED,
723 wxCommandEventHandler(AISTargetListDialog::OnTargetCreateWpt), NULL,
725 bsRouteButtonsInner->Add(m_pButtonCreateWpt, 0, wxEXPAND | wxALL, 0);
727 m_pButtonHideAllTracks =
728 new wxButton(winr, wxID_ANY, _(
"Hide All Tracks"), wxDefaultPosition,
729 wxDefaultSize, wxBU_AUTODRAW);
730 m_pButtonHideAllTracks->Connect(
731 wxEVT_COMMAND_BUTTON_CLICKED,
732 wxCommandEventHandler(AISTargetListDialog::OnHideAllTracks), NULL,
this);
733 bsRouteButtonsInner->Add(m_pButtonHideAllTracks, 0, wxEXPAND | wxALL, 2);
735 m_pButtonShowAllTracks =
736 new wxButton(winr, wxID_ANY, _(
"Show All Tracks"), wxDefaultPosition,
737 wxDefaultSize, wxBU_AUTODRAW);
738 m_pButtonShowAllTracks->Connect(
739 wxEVT_COMMAND_BUTTON_CLICKED,
740 wxCommandEventHandler(AISTargetListDialog::OnShowAllTracks), NULL,
this);
741 bsRouteButtonsInner->Add(m_pButtonShowAllTracks, 0, wxEXPAND | wxALL, 2);
743 m_pButtonToggleTrack =
744 new wxButton(winr, wxID_ANY, _(
"Toggle track"), wxDefaultPosition,
745 wxDefaultSize, wxBU_AUTODRAW);
746 m_pButtonToggleTrack->Connect(
747 wxEVT_COMMAND_BUTTON_CLICKED,
748 wxCommandEventHandler(AISTargetListDialog::OnToggleTrack), NULL,
this);
749 bsRouteButtonsInner->Add(m_pButtonToggleTrack, 0, wxEXPAND | wxALL, 2);
752 new wxButton(winr, wxID_ANY, _(
"Copy MMSI"), wxDefaultPosition,
753 wxDefaultSize, wxBU_AUTODRAW);
754 m_pButtonCopyMMSI->Connect(
755 wxEVT_COMMAND_BUTTON_CLICKED,
756 wxCommandEventHandler(AISTargetListDialog::OnCopyMMSI), NULL,
this);
757 bsRouteButtonsInner->Add(m_pButtonCopyMMSI, 0, wxEXPAND | wxALL, 2);
760 new wxCheckBox(winr, wxID_ANY, _(
"AutoSort"), wxDefaultPosition,
761 wxDefaultSize, wxBU_AUTODRAW);
762 m_pCBAutosort->Connect(
763 wxEVT_COMMAND_CHECKBOX_CLICKED,
764 wxCommandEventHandler(AISTargetListDialog::OnAutosortCB), NULL,
this);
765 bsRouteButtonsInner->Add(m_pCBAutosort, 0, wxEXPAND | wxALL, 2);
766 g_bAisTargetList_autosort =
true;
767 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
769 bsRouteButtonsInner->AddSpacer(10);
771 m_pStaticTextRange =
new wxStaticText(winr, wxID_ANY, _(
"Limit range: NM"),
772 wxDefaultPosition, wxDefaultSize, 0);
773 bsRouteButtonsInner->Add(m_pStaticTextRange, 0, wxALL, 2);
774 bsRouteButtonsInner->AddSpacer(2);
775 m_pSpinCtrlRange =
new wxSpinCtrl(
776 winr, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(50, -1),
777 wxSP_ARROW_KEYS, 1, 20000, g_AisTargetList_range);
778 m_pSpinCtrlRange->Connect(
779 wxEVT_COMMAND_SPINCTRL_UPDATED,
780 wxCommandEventHandler(AISTargetListDialog::OnLimitRange), NULL,
this);
781 m_pSpinCtrlRange->Connect(
782 wxEVT_COMMAND_TEXT_UPDATED,
783 wxCommandEventHandler(AISTargetListDialog::OnLimitRange), NULL,
this);
784 bsRouteButtonsInner->Add(m_pSpinCtrlRange, 0, wxEXPAND | wxALL, 0);
786 bsRouteButtonsInner->AddSpacer(10);
787 m_pStaticTextCount =
new wxStaticText(winr, wxID_ANY, _(
"Target Count"),
788 wxDefaultPosition, wxDefaultSize, 0);
789 bsRouteButtonsInner->Add(m_pStaticTextCount, 0, wxALL, 2);
791 bsRouteButtonsInner->AddSpacer(2);
792 m_pTextTargetCount =
new wxTextCtrl(winr, wxID_ANY, _T(
""), wxDefaultPosition,
793 wxDefaultSize, wxTE_READONLY);
794 m_pTextTargetCount->SetMinSize(wxSize(6 * GetCharWidth(), -1));
795 bsRouteButtonsInner->Add(m_pTextTargetCount, 0, wxALL, 2);
797 bsRouteButtonsInner->AddSpacer(10);
798 m_pButtonOK =
new wxButton(winr, wxID_ANY, _(
"Close"), wxDefaultPosition,
799 wxDefaultSize, wxBU_AUTODRAW);
800 m_pButtonOK->Connect(
801 wxEVT_COMMAND_BUTTON_CLICKED,
802 wxCommandEventHandler(AISTargetListDialog::OnCloseButton), NULL,
this);
803 bsRouteButtonsInner->Add(m_pButtonOK, 0, wxEXPAND | wxALL, 0);
810 SetSize(GetSize().x, GetSize().y - 1);
813void AISTargetListDialog::OnClose(wxCloseEvent &event) {
814 Disconnect_decoder();
816 g_pAISTargetList = NULL;
819void AISTargetListDialog::Disconnect_decoder() { m_pdecoder = NULL; }
821void AISTargetListDialog::SetColorScheme() { DimeControl(
this); }
823void AISTargetListDialog::OnPaneClose(wxAuiManagerEvent &event) {
824 if (event.pane->name == _T(
"AISTargetList")) {
825 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(*event.pane);
830void AISTargetListDialog::OnCloseButton(wxCommandEvent &event) { Shutdown(); }
832void AISTargetListDialog::Shutdown(
void) {
834 wxAuiPaneInfo pane = m_pAuiManager->GetPane(
this);
835 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
836 m_pAuiManager->DetachPane(
this);
837 Disconnect_decoder();
839 m_pAuiManager->Update();
840#ifdef __OCPN__ANDROID__
841 GetParent()->Refresh(
true);
847void AISTargetListDialog::UpdateButtons() {
849 item = m_pListCtrlAISTargets->GetNextItem(item, wxLIST_NEXT_ALL,
850 wxLIST_STATE_SELECTED);
851 bool enable = (item != -1);
853 m_pButtonInfo->Enable(enable);
855 if (m_pdecoder && item != -1) {
856 auto pAISTargetSel = m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(item));
857 if (pAISTargetSel && (!pAISTargetSel->b_positionOnceValid)) enable =
false;
859 m_pButtonJumpTo->Enable(enable);
860 m_pButtonJumpTo_Close->Enable(enable);
861 m_pButtonCreateWpt->Enable(enable);
862 m_pButtonToggleTrack->Enable(enable);
863 m_pButtonCopyMMSI->Enable(enable);
866void AISTargetListDialog::OnTargetSelected(wxListEvent &event) {
870void AISTargetListDialog::DoTargetQuery(
int mmsi) {
871 ShowAISTargetQueryDialog(m_pparent, mmsi);
878void AISTargetListDialog::OnTargetDefaultAction(wxListEvent &event) {
880 if ((mmsi_no = event.GetData())) DoTargetQuery(mmsi_no);
883void AISTargetListDialog::OnTargetQuery(wxCommandEvent &event) {
885 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
886 wxLIST_STATE_SELECTED);
887 if (selItemID == -1)
return;
890 auto pAISTarget = m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
891 if (pAISTarget) DoTargetQuery(pAISTarget->MMSI);
895void AISTargetListDialog::OnAutosortCB(wxCommandEvent &event) {
896 g_bAisTargetList_autosort = m_pCBAutosort->GetValue();
898 m_bautosort_force = g_bAisTargetList_autosort;
900 if (!g_bAisTargetList_autosort) {
902 item.SetMask(wxLIST_MASK_IMAGE);
904 g_AisTargetList_sortColumn = wxMax(g_AisTargetList_sortColumn, 0);
905 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
908 item.SetMask(wxLIST_MASK_IMAGE);
909 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
911 if (g_AisTargetList_sortColumn >= 0) {
912 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
913 UpdateAISTargetList();
918void AISTargetListDialog::OnTargetListColumnClicked(wxListEvent &event) {
919 int key =
event.GetColumn();
921 item.SetMask(wxLIST_MASK_IMAGE);
922 if (key == g_AisTargetList_sortColumn)
923 g_bAisTargetList_sortReverse = !g_bAisTargetList_sortReverse;
926 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
927 g_bAisTargetList_sortReverse =
false;
928 g_AisTargetList_sortColumn = key;
930 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
932 if (!g_bAisTargetList_autosort) g_bsort_once =
true;
934 if (g_AisTargetList_sortColumn >= 0) {
935 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
936 UpdateAISTargetList();
940void AISTargetListDialog::OnTargetScrollTo(wxCommandEvent &event) {
941 CenterToTarget(
false);
944void AISTargetListDialog::OnTargetScrollToClose(wxCommandEvent &event) {
945 CenterToTarget(
true);
948void AISTargetListDialog::OnTargetCreateWpt(wxCommandEvent &event) {
950 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
951 wxLIST_STATE_SELECTED);
952 if (selItemID == -1)
return;
954 std::shared_ptr<AisTargetData> pAISTarget = NULL;
957 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
961 new RoutePoint(pAISTarget->Lat, pAISTarget->Lon, g_default_wp_icon,
962 wxEmptyString, wxEmptyString);
963 pWP->m_bIsolatedMark =
true;
964 pSelect->AddSelectableRoutePoint(pAISTarget->Lat, pAISTarget->Lon, pWP);
965 pConfig->AddNewWayPoint(pWP, -1);
967 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
968 pRouteManagerDialog->UpdateWptListCtrl();
969 gFrame->GetPrimaryCanvas()->undo->BeforeUndoableAction(
970 Undo_CreateWaypoint, pWP, Undo_HasParent, NULL);
971 gFrame->GetPrimaryCanvas()->undo->AfterUndoableAction(NULL);
976void AISTargetListDialog::OnShowAllTracks(wxCommandEvent &event) {
978 for (
const auto &it : m_pdecoder->GetTargetList()) {
979 auto pAISTarget = it.second;
980 if (NULL != pAISTarget) {
981 pAISTarget->b_show_track =
true;
984 UpdateAISTargetList();
988void AISTargetListDialog::OnHideAllTracks(wxCommandEvent &event) {
990 for (
const auto &it : m_pdecoder->GetTargetList()) {
991 auto pAISTarget = it.second;
992 if (NULL != pAISTarget) {
993 pAISTarget->b_show_track =
false;
996 UpdateAISTargetList();
1000void AISTargetListDialog::OnToggleTrack(wxCommandEvent &event) {
1001 long selItemID = -1;
1002 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1003 wxLIST_STATE_SELECTED);
1004 if (selItemID == -1)
return;
1006 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1009 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1012 pAISTarget->b_show_track = !pAISTarget->b_show_track;
1013 UpdateAISTargetList();
1017void AISTargetListDialog::OnCopyMMSI(wxCommandEvent &event) {
1018 long selItemID = -1;
1019 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1020 wxLIST_STATE_SELECTED);
1021 if (selItemID == -1)
return;
1022 CopyMMSItoClipBoard((
int)m_pMMSI_array->Item(selItemID));
1025void AISTargetListDialog::CenterToTarget(
bool close) {
1026 long selItemID = -1;
1027 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1028 wxLIST_STATE_SELECTED);
1029 if (selItemID == -1)
return;
1031 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1034 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1037 double scale = gFrame->GetFocusCanvas()->GetVPScale();
1038 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), pAISTarget->Lat,
1039 pAISTarget->Lon,
scale);
1044 double factor = cc->GetScaleValue() / 5000.0;
1045 cc->DoZoomCanvas(factor,
false);
1047 DoTargetQuery(pAISTarget->MMSI);
1054void AISTargetListDialog::CopyMMSItoClipBoard(
int mmsi) {
1056 if (wxTheClipboard->Open()) {
1057 wxTheClipboard->SetData(
1058 new wxTextDataObject(wxString::Format(wxT(
"%09d"), mmsi)));
1059 wxTheClipboard->Close();
1062void AISTargetListDialog::OnLimitRange(wxCommandEvent &event) {
1063 g_AisTargetList_range = m_pSpinCtrlRange->GetValue();
1064 UpdateAISTargetList();
1067std::shared_ptr<AisTargetData> AISTargetListDialog::GetpTarget(
unsigned int list_item) {
1069 return m_pdecoder->Get_Target_Data_From_MMSI(
1070 m_pMMSI_array->Item(list_item));
1075void AISTargetListDialog::UpdateAISTargetList(
void) {
1076 if (m_pListCtrlAISTargets && !m_pListCtrlAISTargets->IsVirtual())
1077 return UpdateNVAISTargetList();
1079 if (m_pdecoder && m_pListCtrlAISTargets) {
1081 long selItemID = -1;
1082 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1083 wxLIST_STATE_SELECTED);
1086 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1088 const auto ¤t_targets = m_pdecoder->GetTargetList();
1092 m_pMMSI_array->Clear();
1094 for (
auto it = current_targets.begin(); it != current_targets.end();
1096 auto pAISTarget = it->second;
1099 if (NULL != pAISTarget) {
1101 if ((pAISTarget->b_positionOnceValid) &&
1102 (pAISTarget->Range_NM <= g_AisTargetList_range))
1104 else if (!pAISTarget->b_positionOnceValid)
1108 m_pMMSI_array->Add(pAISTarget->MMSI);
1113 g_bsort_once =
false;
1115 m_pListCtrlAISTargets->SetItemCount(m_pMMSI_array->GetCount());
1117 g_AisTargetList_count = m_pMMSI_array->GetCount();
1119 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1120 g_bAisTargetList_autosort =
false;
1122 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1126 if ((selItemID != -1) && (selMMSI != -1)) {
1127 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1128 if (m_pMMSI_array->Item(i) == selMMSI) {
1135 if (m_pMMSI_array->GetCount())
1136 m_pListCtrlAISTargets->SetItemState(
1137 item_sel, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1138 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1140 m_pListCtrlAISTargets->DeleteAllItems();
1143 count.Printf(_T(
"%lu"), (
unsigned long)m_pMMSI_array->GetCount());
1144 m_pTextTargetCount->ChangeValue(count);
1147 m_pListCtrlAISTargets->Refresh(
false);
1152void AISTargetListDialog::UpdateNVAISTargetList(
void) {
1155 long selItemID = -1;
1156 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1157 wxLIST_STATE_SELECTED);
1160 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1162 const auto ¤t_targets = m_pdecoder->GetTargetList();
1166 m_pMMSI_array->Clear();
1168 for (
auto it = current_targets.begin(); it != current_targets.end();
1170 auto pAISTarget = it->second;
1173 if (NULL != pAISTarget) {
1175 if ((pAISTarget->b_positionOnceValid) &&
1176 (pAISTarget->Range_NM <= g_AisTargetList_range))
1178 else if (!pAISTarget->b_positionOnceValid)
1182 m_pMMSI_array->Add(pAISTarget->MMSI);
1187 g_bsort_once =
false;
1189 g_AisTargetList_count = m_pMMSI_array->GetCount();
1191 m_pListCtrlAISTargets->DeleteAllItems();
1193 for (
int i = 0; i < g_AisTargetList_count; i++) {
1196 m_pListCtrlAISTargets->InsertItem(item);
1197 for (
int j = 0; j < tlTCPA + 1; j++) {
1199 item.SetText(m_pListCtrlAISTargets->OnGetItemText(i, j));
1200 m_pListCtrlAISTargets->SetItem(item);
1204 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1205 g_bAisTargetList_autosort =
false;
1207 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1211 if ((selItemID != -1) && (selMMSI != -1)) {
1212 for (
unsigned int i = 0; i < m_pMMSI_array->GetCount(); i++) {
1213 if (m_pMMSI_array->Item(i) == selMMSI) {
1220 if (m_pMMSI_array->GetCount())
1221 m_pListCtrlAISTargets->SetItemState(
1222 item_sel, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1223 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1225 m_pListCtrlAISTargets->DeleteAllItems();
1228 count.Printf(_T(
"%lu"), (
unsigned long)m_pMMSI_array->GetCount());
1229 m_pTextTargetCount->ChangeValue(count);
1232 m_pListCtrlAISTargets->Refresh(
false);
1237void AISTargetListDialog::OnRightClickContext(wxCommandEvent &event) {
1238 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T(
"AISTargetList"));
1239 if (pane.IsDocked()) {
1240 wxMenu *popup =
new wxMenu();
1241 popup->Append(ID_RCLK_UNDOCK, _(
"Undock Target List"));
1242 popup->Connect(wxEVT_COMMAND_MENU_SELECTED,
1243 wxCommandEventHandler(AISTargetListDialog::OnContextUndock),
1251void AISTargetListDialog::OnContextUndock(wxCommandEvent &event) {
1252 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T(
"AISTargetList"));
1254 m_pAuiManager->Update();