OpenCPN Partial API docs
Loading...
Searching...
No Matches
AISTargetListDialog.cpp
1/***************************************************************************
2 *
3 * Project: OpenCPN
4 *
5 ***************************************************************************
6 * Copyright (C) 2010 by David S. Register *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
22 ***************************************************************************
23 */
24
25#include <wx/textctrl.h>
26#include <wx/sizer.h>
27#include <wx/tokenzr.h>
28#include <wx/clipbrd.h>
29
30#ifdef __OCPN__ANDROID__
31#include "androidUTIL.h"
32#endif
33
34#include "AISTargetListDialog.h"
35#include "ais.h"
36#include "ais_decoder.h"
37#include "ais_target_data.h"
38#include "OCPNListCtrl.h"
39#include "styles.h"
40#include "select.h"
41#include "routemanagerdialog.h"
42#include "OCPNPlatform.h"
43#include "route_point.h"
44#include "chcanv.h"
45#include "ocpn_frame.h"
46
47static AisDecoder *s_p_sort_decoder;
48
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;
55extern ocpnStyle::StyleManager *g_StyleManager;
56extern int g_AisTargetList_range;
57extern wxString g_AisTargetList_perspective;
58extern MyConfig *pConfig;
59extern AISTargetListDialog *g_pAISTargetList;
60extern MyFrame *gFrame;
61extern wxString g_default_wp_icon;
62extern Select *pSelect;
63extern RouteManagerDialog *pRouteManagerDialog;
64extern bool g_btouch;
65
66IMPLEMENT_CLASS(AISTargetListDialog, wxPanel)
67
68BEGIN_EVENT_TABLE(AISTargetListDialog, wxPanel)
69EVT_CLOSE(AISTargetListDialog::OnClose)
70END_EVENT_TABLE()
71
72static bool g_bsort_once;
73
74static int ItemCompare(AisTargetData *pAISTarget1,
75 AisTargetData *pAISTarget2) {
76 wxString s1, s2;
77 double n1 = 0.;
78 double n2 = 0.;
79 bool b_cmptype_num = false;
80
81 // Don't sort unless requested
82 if (!g_bAisTargetList_autosort && !g_bsort_once) return 0;
83
84 AisTargetData *t1 = pAISTarget1;
85 AisTargetData *t2 = pAISTarget2;
86
87 if (t1->Class == AIS_SART) {
88 if (t2->Class == AIS_DSC)
89 return 0;
90 else
91 return -1;
92 }
93
94 if (t2->Class == AIS_SART) {
95 if (t1->Class == AIS_DSC)
96 return 0;
97 else
98 return 1;
99 }
100
101 switch (g_AisTargetList_sortColumn) {
102 case tlTRK:
103 n1 = t1->b_show_track;
104 n2 = t2->b_show_track;
105 b_cmptype_num = true;
106 break;
107
108 case tlNAME:
109 s1 = trimAISField(t1->ShipName);
110 if ((!t1->b_nameValid && (t1->Class == AIS_BASE)) ||
111 (t1->Class == AIS_SART))
112 s1 = _T("-");
113
114 s2 = trimAISField(t2->ShipName);
115 if ((!t2->b_nameValid && (t2->Class == AIS_BASE)) ||
116 (t2->Class == AIS_SART))
117 s2 = _T("-");
118 break;
119
120 case tlCALL:
121 s1 = trimAISField(t1->CallSign);
122 s2 = trimAISField(t2->CallSign);
123 break;
124
125 case tlMMSI:
126 n1 = t1->MMSI;
127 n2 = t2->MMSI;
128 b_cmptype_num = true;
129 break;
130
131 case tlCLASS:
132 s1 = t1->Get_class_string(true);
133 s2 = t2->Get_class_string(true);
134 break;
135
136 case tlTYPE:
137 s1 = t1->Get_vessel_type_string(false);
138 if ((t1->Class == AIS_BASE) || (t1->Class == AIS_SART)) s1 = _T("-");
139
140 s2 = t2->Get_vessel_type_string(false);
141 if ((t1->Class == AIS_BASE) || (t1->Class == AIS_SART)) s2 = _T("-");
142 break;
143
144 case tlNAVSTATUS: {
145 if ((t1->NavStatus <= 15) && (t1->NavStatus >= 0)) {
146 if (t1->Class == AIS_SART) {
147 if (t1->NavStatus == RESERVED_14)
148 s1 = _("Active");
149 else if (t1->NavStatus == UNDEFINED)
150 s1 = _("Testing");
151 } else
152 s1 = ais_get_status(t1->NavStatus);
153 } else
154 s1 = _("-");
155
156 if ((t1->Class == AIS_ATON) || (t1->Class == AIS_BASE) ||
157 (t1->Class == AIS_CLASS_B))
158 s1 = _T("-");
159
160 if ((t2->NavStatus <= 15) && (t2->NavStatus >= 0)) {
161 if (t2->Class == AIS_SART) {
162 if (t2->NavStatus == RESERVED_14)
163 s2 = _("Active");
164 else if (t2->NavStatus == UNDEFINED)
165 s2 = _("Testing");
166 } else
167 s2 = ais_get_status(t2->NavStatus);
168 } else
169 s2 = _("-");
170
171 if ((t2->Class == AIS_ATON) || (t2->Class == AIS_BASE) ||
172 (t2->Class == AIS_CLASS_B))
173 s2 = _T("-");
174
175 break;
176 }
177
178 case tlBRG: {
179 int brg1 = wxRound(t1->Brg);
180 if (brg1 == 360)
181 n1 = 0.;
182 else
183 n1 = brg1;
184
185 int brg2 = wxRound(t2->Brg);
186 if (brg2 == 360)
187 n2 = 0.;
188 else
189 n2 = brg2;
190
191 b_cmptype_num = true;
192 break;
193 }
194
195 case tlCOG: {
196 if ((t1->COG >= 360.0) || (t1->Class == AIS_ATON) ||
197 (t1->Class == AIS_BASE))
198 n1 = -1.0;
199 else {
200 int crs = wxRound(t1->COG);
201 if (crs == 360)
202 n1 = 0.;
203 else
204 n1 = crs;
205 }
206
207 if ((t2->COG >= 360.0) || (t2->Class == AIS_ATON) ||
208 (t2->Class == AIS_BASE))
209 n2 = -1.0;
210 else {
211 int crs = wxRound(t2->COG);
212 if (crs == 360)
213 n2 = 0.;
214 else
215 n2 = crs;
216 }
217
218 b_cmptype_num = true;
219 break;
220 }
221
222 case tlSOG: {
223 if ((t1->SOG > 100.) || (t1->Class == AIS_ATON) ||
224 (t1->Class == AIS_BASE))
225 n1 = -1.0;
226 else
227 n1 = t1->SOG;
228
229 if ((t2->SOG > 100.) || (t2->Class == AIS_ATON) ||
230 (t2->Class == AIS_BASE))
231 n2 = -1.0;
232 else
233 n2 = t2->SOG;
234
235 b_cmptype_num = true;
236 break;
237 }
238 case tlCPA: {
239 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
240 (t1->Class == AIS_BASE))
241 n1 = 99999.0;
242 else
243 n1 = t1->CPA;
244
245 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
246 (t2->Class == AIS_BASE))
247 n2 = 99999.0;
248 else
249 n2 = t2->CPA;
250
251 b_cmptype_num = true;
252 break;
253 }
254 case tlTCPA: {
255 if ((!t1->bCPA_Valid) || (t1->Class == AIS_ATON) ||
256 (t1->Class == AIS_BASE))
257 n1 = 99999.0;
258 else
259 n1 = t1->TCPA;
260
261 if ((!t2->bCPA_Valid) || (t2->Class == AIS_ATON) ||
262 (t2->Class == AIS_BASE))
263 n2 = 99999.0;
264 else
265 n2 = t2->TCPA;
266
267 b_cmptype_num = true;
268 break;
269 }
270 case tlRNG: {
271 n1 = t1->Range_NM;
272 n2 = t2->Range_NM;
273 b_cmptype_num = true;
274 break;
275 }
276
277 default:
278 break;
279 }
280
281 if (!b_cmptype_num) {
282 if (g_bAisTargetList_sortReverse) return s2.Cmp(s1);
283 return s1.Cmp(s2);
284 } else {
285 // If numeric sort values are equal, secondary sort is on Range_NM
286 if (g_bAisTargetList_sortReverse) {
287 if (n2 > n1)
288 return 1;
289 else if (n2 < n1)
290 return -1;
291 else
292 return (t1->Range_NM > t2->Range_NM); // 0;
293 } else {
294 if (n2 > n1)
295 return -1;
296 else if (n2 < n1)
297 return 1;
298 else
299 return (t1->Range_NM > t2->Range_NM); // 0;
300 }
301 }
302}
303
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);
310
311 if (pAISTarget1 && pAISTarget2)
312 return ItemCompare(pAISTarget1.get(), pAISTarget2.get());
313 else
314 return 0;
315 } else
316 return 0;
317}
318
319AISTargetListDialog::AISTargetListDialog(wxWindow *parent, wxAuiManager *auimgr,
320 AisDecoder *pdecoder)
321 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, -1 /*780, 250*/),
322 wxBORDER_NONE) {
323 m_pparent = parent;
324 m_pAuiManager = auimgr;
325 m_pdecoder = pdecoder;
326 g_bsort_once = false;
327 m_bautosort_force = false;
328
329 wxFont *qFont = GetOCPNScaledFont(_("Dialog"));
330 SetFont(*qFont);
331
332 s_p_sort_decoder = pdecoder;
333 m_pMMSI_array = new ArrayOfMMSI(ArrayItemCompareMMSI);
334
335 CreateControls();
336
337 // Set default color for panel, respecting Dark mode if enabled
338 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
339 SetColorScheme();
340
341 UpdateButtons();
342
343 if (m_pAuiManager) {
344 wxAuiPaneInfo paneproto = wxAuiPaneInfo()
345 .Name(_T("AISTargetList"))
346 .CaptionVisible(true)
347 .Float()
348 .FloatingPosition(50, 50)
349 .FloatingSize(400, 200)
350 .BestSize(700, GetCharHeight() * 10);
351
352 // Force and/or override any perspective information that is not
353 // applicable
354 paneproto.Caption(wxGetTranslation(_("AIS target list")));
355 paneproto.Name(_T("AISTargetList"));
356 paneproto.DestroyOnClose(true);
357 paneproto.TopDockable(false)
358 .BottomDockable(true)
359 .LeftDockable(false)
360 .RightDockable(false);
361 paneproto.Show(true);
362
363 m_pAuiManager->AddPane(this, paneproto);
364
365 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T("AISTargetList"));
366
367 if (g_AisTargetList_perspective.IsEmpty()) {
368 if (!g_btouch) RecalculateSize();
369 } else {
370 m_pAuiManager->LoadPaneInfo(g_AisTargetList_perspective, pane);
371 m_pAuiManager->Update();
372 }
373
374 pane =
375 m_pAuiManager->GetPane(_T("AISTargetList")); // Refresh the reference
376
377 // Some special setup for touch screens
378 if (g_btouch) {
379 pane.Float();
380 pane.Dockable(false);
381
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();
386 }
387
388 bool b_reset_pos = false;
389 if ((pane.floating_size.x != -1) && (pane.floating_size.y != -1)) {
390#ifdef __WXMSW__
391 // Support MultiMonitor setups which an allow negative window positions.
392 // If the requested window title bar does not intersect any installed
393 // monitor, then default to simple primary monitor positioning.
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;
399
400 if (NULL == MonitorFromRect(&frame_title_rect, MONITOR_DEFAULTTONULL))
401 b_reset_pos = true;
402#else
403
404 // Make sure drag bar (title bar) of window intersects wxClient Area of
405 // screen, with a little slop...
406 wxRect window_title_rect; // conservative estimate
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;
411
412 wxRect ClientRect = wxGetClientDisplayRect();
413 ClientRect.Deflate(
414 60, 60); // Prevent the new window from being too close to the edge
415 if (!ClientRect.Intersects(window_title_rect)) b_reset_pos = true;
416
417#endif
418
419 if (b_reset_pos) {
420 pane.FloatingPosition(50, 50);
421 m_pAuiManager->Update();
422 }
423 }
424
425 // If the list got accidentally dropped on top of the chart bar, move it
426 // away....
427 if (pane.IsDocked() && (pane.dock_row == 0)) {
428 pane.Float();
429 pane.Row(1);
430 pane.Position(0);
431 m_pAuiManager->Update();
432 }
433
434 pane.Show(true);
435 m_pAuiManager->Update();
436
437 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
438 pConfig->UpdateSettings();
439
440 m_pAuiManager->Connect(
441 wxEVT_AUI_PANE_CLOSE,
442 wxAuiManagerEventHandler(AISTargetListDialog::OnPaneClose), NULL, this);
443
444 } else {
445 // Make an estimate of the default dialog size
446 // for the case when the AUI Perspective for this dialog is undefined
447 wxSize esize;
448 esize.x = 700;
449 esize.y = GetCharHeight() * 10; // 18;
450 SetSize(esize);
451 }
452
453 // Connect Events
454 Connect(wxEVT_CONTEXT_MENU,
455 wxCommandEventHandler(AISTargetListDialog::OnRightClickContext), NULL,
456 this);
457}
458
459AISTargetListDialog::~AISTargetListDialog() {
460 Disconnect_decoder();
461 g_pAISTargetList = NULL;
462}
463
464void AISTargetListDialog::RecalculateSize() {
465 // Make an estimate of the dialog size
466
467 wxSize esize;
468 esize.x = GetCharWidth() * 110;
469 esize.y = GetCharHeight() * 40;
470
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);
475
476 wxSize fsize = GetSize();
477 fsize.y = wxMin(fsize.y, dsize.y - (2 * GetCharHeight()));
478 fsize.x = wxMin(fsize.x, dsize.x - (2 * GetCharHeight()));
479 SetSize(fsize);
480
481 if (m_pAuiManager) {
482 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T("AISTargetList"));
483
484 if (pane.IsOk()) {
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);
489 }
490
491 m_pAuiManager->Update();
492 }
493}
494
495void AISTargetListDialog::CreateControls() {
496 wxBoxSizer *topSizer = new wxBoxSizer(wxHORIZONTAL);
497 SetSizer(topSizer);
498#ifdef __OCPN__ANDROID__
499 this->GetHandle()->setStyleSheet(getQtStyleSheet());
500#endif
501
502 // Parse the global column width string as read from config file
503 wxStringTokenizer tkz(g_AisTargetList_column_spec, _T(";"));
504 wxString s_width = tkz.GetNextToken();
505 int width;
506 long lwidth;
507
508 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
509 wxBORDER_SUNKEN;
510#ifndef __WXQT__
511 flags |= wxLC_VIRTUAL;
512#endif
513
514 m_pListCtrlAISTargets = new OCPNListCtrl(
515 this, ID_AIS_TARGET_LIST, wxDefaultPosition, wxDefaultSize, flags);
516
517 wxImageList *imglist = new wxImageList(16, 16, true, 2);
518
519 ocpnStyle::Style *style = g_StyleManager->GetCurrentStyle();
520 imglist->Add(style->GetIcon(_T("sort_asc")));
521 imglist->Add(style->GetIcon(_T("sort_desc")));
522
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,
533 this);
534 m_pListCtrlAISTargets->Connect(
535 wxEVT_COMMAND_LIST_COL_CLICK,
536 wxListEventHandler(AISTargetListDialog::OnTargetListColumnClicked), NULL,
537 this);
538
539 int dx = GetCharWidth();
540
541 width = dx * 4;
542 if (s_width.ToLong(&lwidth)) {
543 width = wxMax(dx * 2, lwidth);
544 width = wxMin(width, dx * 30);
545 }
546 m_pListCtrlAISTargets->InsertColumn(tlTRK, _("Trk"), wxLIST_FORMAT_LEFT,
547 width);
548 s_width = tkz.GetNextToken();
549
550 width = dx * 12;
551 if (s_width.ToLong(&lwidth)) {
552 width = wxMax(dx * 2, lwidth);
553 width = wxMin(width, dx * 30);
554 }
555 m_pListCtrlAISTargets->InsertColumn(tlNAME, _("Name"), wxLIST_FORMAT_LEFT,
556 width);
557 s_width = tkz.GetNextToken();
558
559 width = dx * 7;
560 if (s_width.ToLong(&lwidth)) {
561 width = wxMax(dx * 2, lwidth);
562 width = wxMin(width, dx * 30);
563 }
564 m_pListCtrlAISTargets->InsertColumn(tlCALL, _("Call"), wxLIST_FORMAT_LEFT,
565 width);
566 s_width = tkz.GetNextToken();
567
568 width = dx * 10;
569 if (s_width.ToLong(&lwidth)) {
570 width = wxMax(dx * 2, lwidth);
571 width = wxMin(width, dx * 30);
572 }
573 m_pListCtrlAISTargets->InsertColumn(tlMMSI, _("MMSI"), wxLIST_FORMAT_LEFT,
574 width);
575 s_width = tkz.GetNextToken();
576
577 width = dx * 7;
578 if (s_width.ToLong(&lwidth)) {
579 width = wxMax(dx * 2, lwidth);
580 width = wxMin(width, dx * 30);
581 }
582 m_pListCtrlAISTargets->InsertColumn(tlCLASS, _("Class"), wxLIST_FORMAT_CENTER,
583 width);
584 s_width = tkz.GetNextToken();
585
586 width = dx * 10;
587 if (s_width.ToLong(&lwidth)) {
588 width = wxMax(dx * 2, lwidth);
589 width = wxMin(width, dx * 30);
590 }
591 m_pListCtrlAISTargets->InsertColumn(tlTYPE, _("Type"), wxLIST_FORMAT_LEFT,
592 width);
593 s_width = tkz.GetNextToken();
594
595 width = dx * 12;
596 if (s_width.ToLong(&lwidth)) {
597 width = wxMax(dx * 2, lwidth);
598 width = wxMin(width, dx * 30);
599 }
600 m_pListCtrlAISTargets->InsertColumn(tlNAVSTATUS, _("Nav Status"),
601 wxLIST_FORMAT_LEFT, width);
602 s_width = tkz.GetNextToken();
603
604 width = dx * 6;
605 if (s_width.ToLong(&lwidth)) {
606 width = wxMax(dx * 2, lwidth);
607 width = wxMin(width, dx * 30);
608 }
609 m_pListCtrlAISTargets->InsertColumn(tlBRG, _("Brg"), wxLIST_FORMAT_RIGHT,
610 width);
611 s_width = tkz.GetNextToken();
612
613 width = dx * 8;
614 if (s_width.ToLong(&lwidth)) {
615 width = wxMax(dx * 2, lwidth);
616 width = wxMin(width, dx * 30);
617 }
618 m_pListCtrlAISTargets->InsertColumn(tlRNG, _("Range"), wxLIST_FORMAT_RIGHT,
619 width);
620 s_width = tkz.GetNextToken();
621
622 width = dx * 6;
623 if (s_width.ToLong(&lwidth)) {
624 width = wxMax(dx * 2, lwidth);
625 width = wxMin(width, dx * 30);
626 }
627 m_pListCtrlAISTargets->InsertColumn(tlCOG, _("CoG"), wxLIST_FORMAT_RIGHT,
628 width);
629 s_width = tkz.GetNextToken();
630
631 width = dx * 6;
632 if (s_width.ToLong(&lwidth)) {
633 width = wxMax(dx * 2, lwidth);
634 width = wxMin(width, dx * 30);
635 }
636 m_pListCtrlAISTargets->InsertColumn(tlSOG, _("SoG"), wxLIST_FORMAT_RIGHT,
637 width);
638
639 width = dx * 7;
640 if (s_width.ToLong(&lwidth)) {
641 width = wxMax(dx * 2, lwidth);
642 width = wxMin(width, dx * 30);
643 }
644 m_pListCtrlAISTargets->InsertColumn(tlCPA, _("CPA"), wxLIST_FORMAT_RIGHT,
645 width);
646
647 width = dx * 8;
648 if (s_width.ToLong(&lwidth)) {
649 width = wxMax(dx * 2, lwidth);
650 width = wxMin(width, dx * 30);
651 }
652 m_pListCtrlAISTargets->InsertColumn(tlTCPA, _("TCPA"), wxLIST_FORMAT_RIGHT,
653 width);
654 wxListItem item;
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);
659
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) {
669 l_order = i;
670 }
671 a_order[i] = l_order;
672 s_order = tkz_order.GetNextToken();
673 }
674
675 m_pListCtrlAISTargets->SetColumnsOrder(a_order);
676#endif
677
678 topSizer->Add(m_pListCtrlAISTargets, 1, wxEXPAND | wxALL, 0);
679
680 wxBoxSizer *boxSizer02 = new wxBoxSizer(wxVERTICAL);
681 boxSizer02->AddSpacer(22);
682 topSizer->Add(boxSizer02, 0, wxEXPAND | wxALL, 2);
683
684 wxScrolledWindow *winr =
685 new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
686 wxNO_BORDER | wxTAB_TRAVERSAL | wxVSCROLL);
687 winr->SetScrollRate(0, 5);
688
689 boxSizer02->Add(winr, 1, wxALL | wxEXPAND, 3);
690
691 wxBoxSizer *bsRouteButtonsInner = new wxBoxSizer(wxVERTICAL);
692 winr->SetSizer(bsRouteButtonsInner);
693
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);
701
702 m_pButtonJumpTo =
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);
709
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);
717
718 m_pButtonCreateWpt =
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,
724 this);
725 bsRouteButtonsInner->Add(m_pButtonCreateWpt, 0, wxEXPAND | wxALL, 0);
726
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);
734
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);
742
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);
750
751 m_pButtonCopyMMSI =
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);
758
759 m_pCBAutosort =
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);
768
769 bsRouteButtonsInner->AddSpacer(10);
770
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);
785
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);
790
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);
796
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);
804
805 topSizer->Layout();
806
807 // This is silly, but seems to be required for __WXMSW__ build
808 // If not done, the SECOND invocation of AISTargetList fails to expand the
809 // list to the full wxSizer size....
810 SetSize(GetSize().x, GetSize().y - 1);
811}
812
813void AISTargetListDialog::OnClose(wxCloseEvent &event) {
814 Disconnect_decoder();
815 Hide();
816 g_pAISTargetList = NULL;
817}
818
819void AISTargetListDialog::Disconnect_decoder() { m_pdecoder = NULL; }
820
821void AISTargetListDialog::SetColorScheme() { DimeControl(this); }
822
823void AISTargetListDialog::OnPaneClose(wxAuiManagerEvent &event) {
824 if (event.pane->name == _T("AISTargetList")) {
825 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(*event.pane);
826 }
827 event.Skip();
828}
829
830void AISTargetListDialog::OnCloseButton(wxCommandEvent &event) { Shutdown(); }
831
832void AISTargetListDialog::Shutdown(void) {
833 if (m_pAuiManager) {
834 wxAuiPaneInfo pane = m_pAuiManager->GetPane(this);
835 g_AisTargetList_perspective = m_pAuiManager->SavePaneInfo(pane);
836 m_pAuiManager->DetachPane(this);
837 Disconnect_decoder();
838 pane.Show(false);
839 m_pAuiManager->Update();
840#ifdef __OCPN__ANDROID__
841 GetParent()->Refresh(true);
842#endif
843 Destroy();
844 }
845}
846
847void AISTargetListDialog::UpdateButtons() {
848 long item = -1;
849 item = m_pListCtrlAISTargets->GetNextItem(item, wxLIST_NEXT_ALL,
850 wxLIST_STATE_SELECTED);
851 bool enable = (item != -1);
852
853 m_pButtonInfo->Enable(enable);
854
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;
858 }
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);
864}
865
866void AISTargetListDialog::OnTargetSelected(wxListEvent &event) {
867 UpdateButtons();
868}
869
870void AISTargetListDialog::DoTargetQuery(int mmsi) {
871 ShowAISTargetQueryDialog(m_pparent, mmsi);
872}
873
874/*
875 ** When an item is activated in AIS TArget List then opens the AIS Target Query
876 *Dialog
877 */
878void AISTargetListDialog::OnTargetDefaultAction(wxListEvent &event) {
879 long mmsi_no;
880 if ((mmsi_no = event.GetData())) DoTargetQuery(mmsi_no);
881}
882
883void AISTargetListDialog::OnTargetQuery(wxCommandEvent &event) {
884 long selItemID = -1;
885 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
886 wxLIST_STATE_SELECTED);
887 if (selItemID == -1) return;
888
889 if (m_pdecoder) {
890 auto pAISTarget = m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
891 if (pAISTarget) DoTargetQuery(pAISTarget->MMSI);
892 }
893}
894
895void AISTargetListDialog::OnAutosortCB(wxCommandEvent &event) {
896 g_bAisTargetList_autosort = m_pCBAutosort->GetValue();
897
898 m_bautosort_force = g_bAisTargetList_autosort;
899
900 if (!g_bAisTargetList_autosort) {
901 wxListItem item;
902 item.SetMask(wxLIST_MASK_IMAGE);
903 item.SetImage(-1);
904 g_AisTargetList_sortColumn = wxMax(g_AisTargetList_sortColumn, 0);
905 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
906 } else {
907 wxListItem item;
908 item.SetMask(wxLIST_MASK_IMAGE);
909 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
910
911 if (g_AisTargetList_sortColumn >= 0) {
912 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
913 UpdateAISTargetList();
914 }
915 }
916}
917
918void AISTargetListDialog::OnTargetListColumnClicked(wxListEvent &event) {
919 int key = event.GetColumn();
920 wxListItem item;
921 item.SetMask(wxLIST_MASK_IMAGE);
922 if (key == g_AisTargetList_sortColumn)
923 g_bAisTargetList_sortReverse = !g_bAisTargetList_sortReverse;
924 else {
925 item.SetImage(-1);
926 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
927 g_bAisTargetList_sortReverse = false;
928 g_AisTargetList_sortColumn = key;
929 }
930 item.SetImage(g_bAisTargetList_sortReverse ? 1 : 0);
931
932 if (!g_bAisTargetList_autosort) g_bsort_once = true;
933
934 if (g_AisTargetList_sortColumn >= 0) {
935 m_pListCtrlAISTargets->SetColumn(g_AisTargetList_sortColumn, item);
936 UpdateAISTargetList();
937 }
938}
939
940void AISTargetListDialog::OnTargetScrollTo(wxCommandEvent &event) {
941 CenterToTarget(false);
942}
943
944void AISTargetListDialog::OnTargetScrollToClose(wxCommandEvent &event) {
945 CenterToTarget(true);
946}
947
948void AISTargetListDialog::OnTargetCreateWpt(wxCommandEvent &event) {
949 long selItemID = -1;
950 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
951 wxLIST_STATE_SELECTED);
952 if (selItemID == -1) return;
953
954 std::shared_ptr<AisTargetData> pAISTarget = NULL;
955 if (m_pdecoder)
956 pAISTarget =
957 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
958
959 if (pAISTarget) {
960 RoutePoint *pWP =
961 new RoutePoint(pAISTarget->Lat, pAISTarget->Lon, g_default_wp_icon,
962 wxEmptyString, wxEmptyString);
963 pWP->m_bIsolatedMark = true; // This is an isolated mark
964 pSelect->AddSelectableRoutePoint(pAISTarget->Lat, pAISTarget->Lon, pWP);
965 pConfig->AddNewWayPoint(pWP, -1); // use auto next num
966
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);
972 Refresh(false);
973 }
974}
975
976void AISTargetListDialog::OnShowAllTracks(wxCommandEvent &event) {
977 if (m_pdecoder) {
978 for (const auto &it : m_pdecoder->GetTargetList()) {
979 auto pAISTarget = it.second;
980 if (NULL != pAISTarget) {
981 pAISTarget->b_show_track = true;
982 }
983 }
984 UpdateAISTargetList();
985 }
986}
987
988void AISTargetListDialog::OnHideAllTracks(wxCommandEvent &event) {
989 if (m_pdecoder) {
990 for (const auto &it : m_pdecoder->GetTargetList()) {
991 auto pAISTarget = it.second;
992 if (NULL != pAISTarget) {
993 pAISTarget->b_show_track = false;
994 }
995 }
996 UpdateAISTargetList();
997 }
998}
999
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;
1005
1006 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1007 if (m_pdecoder)
1008 pAISTarget =
1009 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1010
1011 if (pAISTarget) {
1012 pAISTarget->b_show_track = !pAISTarget->b_show_track;
1013 UpdateAISTargetList();
1014 }
1015}
1016
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));
1023}
1024
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;
1030
1031 std::shared_ptr<AisTargetData> pAISTarget = NULL;
1032 if (m_pdecoder)
1033 pAISTarget =
1034 m_pdecoder->Get_Target_Data_From_MMSI(m_pMMSI_array->Item(selItemID));
1035
1036 if (pAISTarget) {
1037 double scale = gFrame->GetFocusCanvas()->GetVPScale();
1038 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), pAISTarget->Lat,
1039 pAISTarget->Lon, scale);
1040 if (close) {
1041 // Set a resonable (1:5000) chart scale to see the target.
1042 if (scale < 0.7) { // Don't zoom if already close.
1043 ChartCanvas* cc = gFrame->GetFocusCanvas();
1044 double factor = cc->GetScaleValue() / 5000.0;
1045 cc->DoZoomCanvas(factor, false);
1046 }
1047 DoTargetQuery(pAISTarget->MMSI);
1048 // Close AIS target list
1049 Shutdown();
1050 }
1051 }
1052}
1053
1054void AISTargetListDialog::CopyMMSItoClipBoard(int mmsi) {
1055 // Write MMSI # as text to the clipboard
1056 if (wxTheClipboard->Open()) {
1057 wxTheClipboard->SetData(
1058 new wxTextDataObject(wxString::Format(wxT("%09d"), mmsi)));
1059 wxTheClipboard->Close();
1060 }
1061}
1062void AISTargetListDialog::OnLimitRange(wxCommandEvent &event) {
1063 g_AisTargetList_range = m_pSpinCtrlRange->GetValue();
1064 UpdateAISTargetList();
1065}
1066
1067std::shared_ptr<AisTargetData> AISTargetListDialog::GetpTarget(unsigned int list_item) {
1068 if (m_pdecoder)
1069 return m_pdecoder->Get_Target_Data_From_MMSI(
1070 m_pMMSI_array->Item(list_item));
1071 else
1072 return NULL;
1073}
1074
1075void AISTargetListDialog::UpdateAISTargetList(void) {
1076 if (m_pListCtrlAISTargets && !m_pListCtrlAISTargets->IsVirtual())
1077 return UpdateNVAISTargetList();
1078
1079 if (m_pdecoder && m_pListCtrlAISTargets) {
1080 // Capture the MMSI of the curently selected list item
1081 long selItemID = -1;
1082 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1083 wxLIST_STATE_SELECTED);
1084
1085 int selMMSI = -1;
1086 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1087
1088 const auto &current_targets = m_pdecoder->GetTargetList();
1089 wxListItem item;
1090
1091 int index = 0;
1092 m_pMMSI_array->Clear();
1093
1094 for (auto it = current_targets.begin(); it != current_targets.end();
1095 ++it, ++index) {
1096 auto pAISTarget = it->second;
1097 item.SetId(index);
1098
1099 if (NULL != pAISTarget) {
1100 bool b_add = false;
1101 if ((pAISTarget->b_positionOnceValid) &&
1102 (pAISTarget->Range_NM <= g_AisTargetList_range))
1103 b_add = true;
1104 else if (!pAISTarget->b_positionOnceValid)
1105 b_add = true;
1106
1107 if (b_add) {
1108 m_pMMSI_array->Add(pAISTarget->MMSI);
1109 }
1110 }
1111 }
1112
1113 g_bsort_once = false;
1114
1115 m_pListCtrlAISTargets->SetItemCount(m_pMMSI_array->GetCount());
1116
1117 g_AisTargetList_count = m_pMMSI_array->GetCount();
1118
1119 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1120 g_bAisTargetList_autosort = false;
1121
1122 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1123
1124 // Restore selected item
1125 long item_sel = 0;
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) {
1129 item_sel = i;
1130 break;
1131 }
1132 }
1133 }
1134
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);
1139 else
1140 m_pListCtrlAISTargets->DeleteAllItems();
1141
1142 wxString count;
1143 count.Printf(_T("%lu"), (unsigned long)m_pMMSI_array->GetCount());
1144 m_pTextTargetCount->ChangeValue(count);
1145
1146#ifdef __WXMSW__
1147 m_pListCtrlAISTargets->Refresh(false);
1148#endif
1149 }
1150}
1151
1152void AISTargetListDialog::UpdateNVAISTargetList(void) {
1153 if (m_pdecoder) {
1154 // Capture the MMSI of the curently selected list item
1155 long selItemID = -1;
1156 selItemID = m_pListCtrlAISTargets->GetNextItem(selItemID, wxLIST_NEXT_ALL,
1157 wxLIST_STATE_SELECTED);
1158
1159 int selMMSI = -1;
1160 if (selItemID != -1) selMMSI = m_pMMSI_array->Item(selItemID);
1161
1162 const auto &current_targets = m_pdecoder->GetTargetList();
1163 wxListItem item;
1164
1165 int index = 0;
1166 m_pMMSI_array->Clear();
1167
1168 for (auto it = current_targets.begin(); it != current_targets.end();
1169 ++it, ++index) {
1170 auto pAISTarget = it->second;
1171 item.SetId(index);
1172
1173 if (NULL != pAISTarget) {
1174 bool b_add = false;
1175 if ((pAISTarget->b_positionOnceValid) &&
1176 (pAISTarget->Range_NM <= g_AisTargetList_range))
1177 b_add = true;
1178 else if (!pAISTarget->b_positionOnceValid)
1179 b_add = true;
1180
1181 if (b_add) {
1182 m_pMMSI_array->Add(pAISTarget->MMSI);
1183 }
1184 }
1185 }
1186
1187 g_bsort_once = false;
1188
1189 g_AisTargetList_count = m_pMMSI_array->GetCount();
1190
1191 m_pListCtrlAISTargets->DeleteAllItems();
1192
1193 for (int i = 0; i < g_AisTargetList_count; i++) {
1194 wxListItem item;
1195 item.SetId(i);
1196 m_pListCtrlAISTargets->InsertItem(item);
1197 for (int j = 0; j < tlTCPA + 1; j++) {
1198 item.SetColumn(j);
1199 item.SetText(m_pListCtrlAISTargets->OnGetItemText(i, j));
1200 m_pListCtrlAISTargets->SetItem(item);
1201 }
1202 }
1203
1204 if ((g_AisTargetList_count > 1000) && !m_bautosort_force)
1205 g_bAisTargetList_autosort = false;
1206
1207 m_pCBAutosort->SetValue(g_bAisTargetList_autosort);
1208
1209 // Restore selected item
1210 long item_sel = 0;
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) {
1214 item_sel = i;
1215 break;
1216 }
1217 }
1218 }
1219
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);
1224 else
1225 m_pListCtrlAISTargets->DeleteAllItems();
1226
1227 wxString count;
1228 count.Printf(_T("%lu"), (unsigned long)m_pMMSI_array->GetCount());
1229 m_pTextTargetCount->ChangeValue(count);
1230
1231#ifdef __WXMSW__
1232 m_pListCtrlAISTargets->Refresh(false);
1233#endif
1234 }
1235}
1236
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),
1244 NULL, this);
1245
1246 PopupMenu(popup);
1247 delete popup;
1248 }
1249}
1250
1251void AISTargetListDialog::OnContextUndock(wxCommandEvent &event) {
1252 wxAuiPaneInfo &pane = m_pAuiManager->GetPane(_T("AISTargetList"));
1253 pane.Float();
1254 m_pAuiManager->Update();
1255}
Definition: select.h:51
Definition: Quilt.cpp:864