OpenCPN Partial API docs
Loading...
Searching...
No Matches
routemanagerdialog.cpp
1/*
2 This program is free software; you can redistribute it and/or
3 modify it under the terms of the GNU General Public License
4 as published by the Free Software Foundation; either version 2
5 of the License, or (at your option) any later version.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor,
15 Boston, MA 02110-1301, USA.
16
17 ---
18 Copyright (C) 2010, Anders Lund <anders@alweb.dk>
19 Copyright (c) 2025 NoCodeHummel
20 */
21
22#include "config.h"
23
24#include "routemanagerdialog.h"
25#include "route_gui.h"
26
27// For compilers that support precompilation, includes "wx/wx.h".
28#include <wx/wxprec.h>
29
30#ifndef WX_PRECOMP
31#include <wx/wx.h>
32#endif
33
34#include <wx/filename.h>
35#include <wx/stdpaths.h>
36#include <wx/progdlg.h>
37#include <wx/clipbrd.h>
38#include <wx/statline.h>
39
40#include <iostream>
41#include <vector>
42#include <algorithm>
43
44#include "model/ais_decoder.h"
45#include "model/config_vars.h"
46#include "model/georef.h"
47#include "model/mdns_cache.h"
48#include "model/mdns_query.h"
49#include "model/navobj_db.h"
50#include "model/navutil_base.h"
51#include "model/own_ship.h"
52#include "model/route.h"
53#include "model/routeman.h"
54#include "model/select.h"
55#include "model/track.h"
56
57#include "chartbase.h"
58#include "chcanv.h"
59#include "dychart.h"
60#include "Layer.h"
61#include "MarkInfo.h"
62#include "navutil.h"
63#include "ocpn_frame.h"
64#include "OCPNPlatform.h"
65#include "routeman_gui.h"
66#include "route_point_gui.h"
67#include "RoutePropDlgImpl.h"
68#include "SendToGpsDlg.h"
69#include "SendToPeerDlg.h"
70#include "styles.h"
71#include "svg_utils.h"
72#include "TrackPropDlg.h"
73
74#ifdef __ANDROID__
75#include "androidUTIL.h"
76#endif
77
78#define DIALOG_MARGIN 10
79
80enum { rmVISIBLE = 0, rmROUTENAME, rmROUTEDESC }; // RMColumns;
81enum { colTRKVISIBLE = 0, colTRKNAME, colTRKLENGTH, colTRKDATE };
82enum { colLAYVISIBLE = 0, colLAYNAME, colLAYITEMS, colLAYPERSIST };
83enum { colWPTICON = 0, colWPTSCALE, colWPTNAME, colWPTDIST };
84
85// GLOBALS :0
86extern RouteList *pRouteList;
87extern std::vector<Track *> g_TrackList;
88extern LayerList *pLayerList;
89extern wxString GetLayerName(int id);
90extern RoutePropDlgImpl *pRoutePropDialog;
91extern TrackPropDlg *pTrackPropDialog;
92extern Routeman *g_pRouteMan;
93extern MyConfig *pConfig;
94extern ActiveTrack *g_pActiveTrack;
95extern MarkInfoDlg *g_pMarkInfoDialog;
96extern MyFrame *gFrame;
97extern bool g_bShowLayers;
98extern wxString g_default_wp_icon;
99extern OCPNPlatform *g_Platform;
100
101// Helper for conditional file name separator
102void appendOSDirSlash(wxString *pString);
103
104static int SortRouteTrack(const int order, const wxString &it1,
105 const wxString &it2) {
106 if (order & 1) return it2.CmpNoCase(it1);
107
108 return it1.CmpNoCase(it2);
109}
110
111// sort callback. Sort by route name.
112static int sort_route_name_dir;
113#if wxCHECK_VERSION(2, 9, 0)
114static int wxCALLBACK SortRoutesOnName(wxIntPtr item1, wxIntPtr item2,
115 wxIntPtr list)
116#else
117int wxCALLBACK SortRoutesOnName(long item1, long item2, long list)
118#endif
119{
120 return SortRouteTrack(sort_route_name_dir, ((Route *)item1)->GetName(),
121 ((Route *)item2)->GetName());
122}
123
124// sort callback. Sort by route Destination.
125static int sort_route_to_dir;
126#if wxCHECK_VERSION(2, 9, 0)
127static int wxCALLBACK SortRoutesOnTo(wxIntPtr item1, wxIntPtr item2,
128 wxIntPtr list)
129#else
130int wxCALLBACK SortRoutesOnTo(long item1, long item2, long list)
131#endif
132{
133 return SortRouteTrack(sort_route_to_dir, ((Route *)item1)->GetTo(),
134 ((Route *)item2)->GetTo());
135}
136
137// sort callback. Sort by track name.
138static int sort_track_name_dir;
139#if wxCHECK_VERSION(2, 9, 0)
140static int wxCALLBACK SortTracksOnName(wxIntPtr item1, wxIntPtr item2,
141 wxIntPtr list)
142#else
143int wxCALLBACK SortTracksOnName(long item1, long item2, long list)
144#endif
145{
146 return SortRouteTrack(sort_track_name_dir, ((Track *)item1)->GetName(),
147 ((Track *)item2)->GetName());
148}
149
150static int SortDouble(const int order, const double &it1, const double &it2) {
151 double l1;
152 double l2;
153
154 if (order & 1) {
155 l1 = it2;
156 l2 = it1;
157 } else {
158 l1 = it1;
159 l2 = it2;
160 }
161
162 if (l1 == l2) return 0;
163 if (l2 < l1) return 1;
164 return -1;
165}
166
167// sort callback. Sort by track length.
168static int sort_track_len_dir;
169#if wxCHECK_VERSION(2, 9, 0)
170static int wxCALLBACK SortTracksOnDistance(wxIntPtr item1, wxIntPtr item2,
171 wxIntPtr list)
172#else
173int wxCALLBACK SortTracksOnDistance(long item1, long item2, long list)
174#endif
175{
176 return SortDouble(sort_track_len_dir, ((Track *)item1)->Length(),
177 ((Track *)item2)->Length());
178}
179
180// sort callback. Sort by track start date.
181static int sort_track_date_dir;
182#if wxCHECK_VERSION(2, 9, 0)
183static int wxCALLBACK SortTracksOnDate(wxIntPtr item1, wxIntPtr item2,
184 wxIntPtr list)
185#else
186int wxCALLBACK SortTracksOnDate(long item1, long item2, long list)
187#endif
188{
189 // Sort date/time using ISO format, which is sortable as a string.
190 return SortRouteTrack(sort_track_date_dir, ((Track *)item1)->GetIsoDateTime(),
191 ((Track *)item2)->GetIsoDateTime());
192}
193
194static int sort_wp_key;
195static int sort_track_key;
196
197// sort callback. Sort by wpt name.
198static int sort_wp_name_dir;
199#if wxCHECK_VERSION(2, 9, 0)
200static int wxCALLBACK SortWaypointsOnName(wxIntPtr item1, wxIntPtr item2,
201 wxIntPtr list)
202#else
203int wxCALLBACK SortWaypointsOnName(long item1, long item2, long list)
204#endif
205
206{
207 RoutePoint *pRP1 = (RoutePoint *)item1;
208 RoutePoint *pRP2 = (RoutePoint *)item2;
209
210 if (pRP1 && pRP2) {
211 if (sort_wp_name_dir & 1)
212 return pRP2->GetName().CmpNoCase(pRP1->GetName());
213 else
214 return pRP1->GetName().CmpNoCase(pRP2->GetName());
215 } else
216 return 0;
217}
218
219// sort callback. Sort by wpt distance.
220static int sort_wp_len_dir;
221#if wxCHECK_VERSION(2, 9, 0)
222static int wxCALLBACK SortWaypointsOnDistance(wxIntPtr item1, wxIntPtr item2,
223 wxIntPtr list)
224#else
225int wxCALLBACK SortWaypointsOnDistance(long item1, long item2, long list)
226#endif
227{
228 double dst1, dst2;
229 DistanceBearingMercator(((RoutePoint *)item1)->m_lat,
230 ((RoutePoint *)item1)->m_lon, gLat, gLon, NULL,
231 &dst1);
232 DistanceBearingMercator(((RoutePoint *)item2)->m_lat,
233 ((RoutePoint *)item2)->m_lon, gLat, gLon, NULL,
234 &dst2);
235 return SortDouble(sort_wp_len_dir, dst1, dst2);
236}
237
238// sort callback. Sort by layer name.
239static int sort_layer_name_dir;
240#if wxCHECK_VERSION(2, 9, 0)
241static int wxCALLBACK SortLayersOnName(wxIntPtr item1, wxIntPtr item2,
242 wxIntPtr list)
243#else
244int wxCALLBACK SortLayersOnName(long item1, long item2, long list)
245#endif
246{
247 return SortRouteTrack(sort_layer_name_dir, ((Layer *)item1)->m_LayerName,
248 ((Layer *)item2)->m_LayerName);
249}
250
251// sort callback. Sort by layer size.
252static int sort_layer_len_dir;
253#if wxCHECK_VERSION(2, 9, 0)
254static int wxCALLBACK SortLayersOnSize(wxIntPtr item1, wxIntPtr item2,
255 wxIntPtr list)
256#else
257int wxCALLBACK SortLayersOnSize(long item1, long item2, long list)
258#endif
259{
260 return SortDouble(sort_layer_len_dir, ((Layer *)item1)->m_NoOfItems,
261 ((Layer *)item2)->m_NoOfItems);
262}
263
264// event table. Mostly empty, because I find it much easier to see what is
265// connected to what using Connect() where possible, so that it is visible in
266// the code.
267BEGIN_EVENT_TABLE(RouteManagerDialog, wxFrame)
268EVT_NOTEBOOK_PAGE_CHANGED(
269 wxID_ANY,
270 RouteManagerDialog::OnTabSwitch) // This should work under Windows :-(
271EVT_CLOSE(RouteManagerDialog::OnClose)
272EVT_COMMAND(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, RouteManagerDialog::OnOK)
273EVT_CHAR_HOOK(RouteManagerDialog::OnKey)
274END_EVENT_TABLE()
275
276void RouteManagerDialog::OnKey(wxKeyEvent &ke) {
277 if (ke.GetKeyCode() == WXK_ESCAPE)
278 Close(true);
279 else
280 ke.Skip();
281}
282
283void RouteManagerDialog::OnTabSwitch(wxNotebookEvent &event) {
284 if (!m_pNotebook) return;
285 int current_page = m_pNotebook->GetSelection();
286 if (current_page == 3) {
287 if (btnImport) btnImport->Enable(false);
288 if (btnExport) btnExport->Enable(false);
289 if (btnExportViz) btnExportViz->Enable(false);
290 } else {
291 if (btnImport) btnImport->Enable(true);
292 if (btnExport) btnExport->Enable(true);
293 if (btnExportViz) btnExportViz->Enable(true);
294 }
295 event.Skip(); // remove if using event table... why?
296}
297
298// implementation
299
300bool RouteManagerDialog::instanceFlag = false;
301RouteManagerDialog *RouteManagerDialog::single = NULL;
302
303RouteManagerDialog *RouteManagerDialog::getInstance(wxWindow *parent) {
304 if (!instanceFlag) {
305 single = new RouteManagerDialog(parent);
306 instanceFlag = true;
307 return single;
308 } else {
309 return single;
310 }
311}
312
313RouteManagerDialog::RouteManagerDialog(wxWindow *parent) {
314 long style =
315 wxDEFAULT_FRAME_STYLE | wxRESIZE_BORDER | wxFRAME_FLOAT_ON_PARENT;
316
317 wxFrame::Create(parent, -1, wxString(_("Route & Mark Manager")),
318 wxDefaultPosition, wxDefaultSize, style);
319
320 wxFont *qFont = GetOCPNScaledFont(_("Dialog"));
321 SetFont(*qFont);
322
323 m_lastWptItem = -1;
324 m_lastTrkItem = -1;
325 m_lastRteItem = -1;
326 sort_wp_key = SORT_ON_NAME;
327 sort_track_key = SORT_ON_NAME;
328
329 btnImport = NULL;
330 btnExport = NULL;
331 btnExportViz = NULL;
332
333 Create();
334 routes_update_listener.Init(g_pRouteMan->on_routes_update,
335 [&](wxCommandEvent) { UpdateRouteListCtrl(); });
336}
337
338void RouteManagerDialog::Create() {
339 // Get a text height metric for reference
340 int char_width, char_height;
341 GetTextExtent(_T("W"), &char_width, &char_height);
342 m_charWidth = char_width;
343
344 wxBoxSizer *itemBoxSizer1 = new wxBoxSizer(wxVERTICAL);
345 SetSizer(itemBoxSizer1);
346
347 m_pNotebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition,
348 wxSize(-1, -1), wxNB_TOP);
349 itemBoxSizer1->Add(m_pNotebook, 1, wxALL | wxEXPAND, 5);
350
351 // Create "Routes" panel
352 m_pPanelRte = new wxPanel(m_pNotebook, wxID_ANY, wxDefaultPosition,
353 wxDefaultSize, wxNO_BORDER | wxTAB_TRAVERSAL);
354
355 wxBoxSizer *sbsRoutes = new wxBoxSizer(wxHORIZONTAL);
356 m_pPanelRte->SetSizer(sbsRoutes);
357 m_pNotebook->AddPage(m_pPanelRte, _("Routes"));
358
359 sort_wp_len_dir = 1;
360 sort_wp_name_dir = 0;
361 sort_track_len_dir = 1;
362 sort_route_to_dir = 0;
363 sort_track_name_dir = 0;
364 sort_route_name_dir = 0;
365 sort_layer_name_dir = 0;
366 sort_layer_len_dir = 1;
367
368 m_listIconSize = 2 * GetCharHeight();
369
370 // Setup GUI
371 wxBoxSizer *bSizerRteContents;
372 bSizerRteContents = new wxBoxSizer(wxVERTICAL);
373
374 wxFlexGridSizer *fgSizerFilterRte;
375 fgSizerFilterRte = new wxFlexGridSizer(0, 2, 0, 0);
376 fgSizerFilterRte->AddGrowableCol(1);
377 fgSizerFilterRte->SetFlexibleDirection(wxBOTH);
378 fgSizerFilterRte->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
379
380 m_stFilterRte = new wxStaticText(m_pPanelRte, wxID_ANY, _("Filter"),
381 wxDefaultPosition, wxDefaultSize, 0);
382 m_stFilterRte->Wrap(-1);
383 fgSizerFilterRte->Add(m_stFilterRte, 0, wxALL, 5);
384
385 m_tFilterRte = new wxTextCtrl(m_pPanelRte, wxID_ANY, wxEmptyString,
386 wxDefaultPosition, wxDefaultSize, 0);
387 fgSizerFilterRte->Add(m_tFilterRte, 1, wxALL | wxEXPAND, 5);
388
389 bSizerRteContents->Add(fgSizerFilterRte, 0, wxEXPAND, 5);
390 m_tFilterRte->Connect(
391 wxEVT_COMMAND_TEXT_UPDATED,
392 wxCommandEventHandler(RouteManagerDialog::OnFilterChanged), NULL, this);
393
394 m_cbShowAllRte = new wxCheckBox(m_pPanelRte, wxID_ANY, _("Show all routes"));
395 bSizerRteContents->Add(m_cbShowAllRte, 0, wxEXPAND | wxLEFT, 5);
396 m_cbShowAllRte->Connect(
397 wxEVT_COMMAND_CHECKBOX_CLICKED,
398 wxCommandEventHandler(RouteManagerDialog::OnShowAllRteCBClicked), NULL,
399 this);
400
401 m_pRouteListCtrl =
402 new wxListCtrl(m_pPanelRte, -1, wxDefaultPosition, wxSize(-1, -1),
403 wxLC_REPORT | wxLC_SORT_ASCENDING | wxLC_HRULES |
404 wxBORDER_SUNKEN /*|wxLC_VRULES*/);
405#ifdef __ANDROID__
406 m_pRouteListCtrl->GetHandle()->setStyleSheet(getAdjustedDialogStyleSheet());
407#endif
408
409 m_pRouteListCtrl->Connect(
410 wxEVT_COMMAND_LIST_ITEM_SELECTED,
411 wxListEventHandler(RouteManagerDialog::OnRteSelected), NULL, this);
412 m_pRouteListCtrl->Connect(
413 wxEVT_COMMAND_LIST_ITEM_DESELECTED,
414 wxListEventHandler(RouteManagerDialog::OnRteSelected), NULL, this);
415 m_pRouteListCtrl->Connect(
416 wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
417 wxListEventHandler(RouteManagerDialog::OnRteDefaultAction), NULL, this);
418 m_pRouteListCtrl->Connect(
419 wxEVT_LEFT_DOWN,
420 wxMouseEventHandler(RouteManagerDialog::OnRteToggleVisibility), NULL,
421 this);
422 m_pRouteListCtrl->Connect(
423 wxEVT_COMMAND_LIST_COL_CLICK,
424 wxListEventHandler(RouteManagerDialog::OnRteColumnClicked), NULL, this);
425 bSizerRteContents->Add(m_pRouteListCtrl, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
426 sbsRoutes->Add(bSizerRteContents, 1, wxEXPAND, 5);
427
428 // Columns: visibility ctrl, name
429 // note that under MSW for SetColumnWidth() to work we need to create the
430 // items with images initially even if we specify dummy image id
431 m_pRouteListCtrl->InsertColumn(rmVISIBLE, _("Show"), wxLIST_FORMAT_LEFT,
432 10 /*4 * char_width*/);
433 m_pRouteListCtrl->InsertColumn(rmROUTENAME, _("Route Name"),
434 wxLIST_FORMAT_LEFT, 15 * char_width);
435 m_pRouteListCtrl->InsertColumn(rmROUTEDESC, _("From <-> To"),
436 wxLIST_FORMAT_LEFT, 10 * char_width);
437
438 // Buttons: Delete, Properties...
439 wxBoxSizer *bsRouteButtons = new wxBoxSizer(wxVERTICAL);
440 sbsRoutes->Add(bsRouteButtons, 0, wxEXPAND);
441
442 wxScrolledWindow *winr = new wxScrolledWindow(
443 m_pPanelRte, wxID_ANY, wxDefaultPosition, wxDefaultSize,
444 wxNO_BORDER | wxTAB_TRAVERSAL | wxVSCROLL);
445 winr->SetScrollRate(0, 5);
446
447 bsRouteButtons->Add(winr, 1, wxALL | wxEXPAND, DIALOG_MARGIN);
448
449 wxBoxSizer *bsRouteButtonsInner = new wxBoxSizer(wxVERTICAL);
450 winr->SetSizer(bsRouteButtonsInner);
451
452 btnRteProperties = new wxButton(winr, -1, _("&Properties") + _T("..."));
453 bsRouteButtonsInner->Add(btnRteProperties, 0, wxALL | wxEXPAND,
454 DIALOG_MARGIN);
455 btnRteProperties->Connect(
456 wxEVT_COMMAND_BUTTON_CLICKED,
457 wxCommandEventHandler(RouteManagerDialog::OnRtePropertiesClick), NULL,
458 this);
459
460 btnRteActivate = new wxButton(winr, -1, _("&Activate"));
461 bsRouteButtonsInner->Add(btnRteActivate, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
462 btnRteActivate->Connect(
463 wxEVT_COMMAND_BUTTON_CLICKED,
464 wxCommandEventHandler(RouteManagerDialog::OnRteActivateClick), NULL,
465 this);
466 btnRteActivate->Connect(
467 wxEVT_LEFT_DOWN,
468 wxMouseEventHandler(RouteManagerDialog::OnRteBtnLeftDown), NULL, this);
469
470 btnRteZoomto = new wxButton(winr, -1, _("&Center View"));
471 bsRouteButtonsInner->Add(btnRteZoomto, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
472 btnRteZoomto->Connect(
473 wxEVT_COMMAND_BUTTON_CLICKED,
474 wxCommandEventHandler(RouteManagerDialog::OnRteZoomtoClick), NULL, this);
475 btnRteZoomto->Connect(
476 wxEVT_LEFT_DOWN,
477 wxMouseEventHandler(RouteManagerDialog::OnRteBtnLeftDown), NULL, this);
478
479 btnRteReverse = new wxButton(winr, -1, _("&Reverse"));
480 bsRouteButtonsInner->Add(btnRteReverse, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
481 btnRteReverse->Connect(
482 wxEVT_COMMAND_BUTTON_CLICKED,
483 wxCommandEventHandler(RouteManagerDialog::OnRteReverseClick), NULL, this);
484
485 btnRteDelete = new wxButton(winr, -1, _("&Delete"));
486 bsRouteButtonsInner->Add(btnRteDelete, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
487 btnRteDelete->Connect(
488 wxEVT_COMMAND_BUTTON_CLICKED,
489 wxCommandEventHandler(RouteManagerDialog::OnRteDeleteClick), NULL, this);
490
491 wxString reseq_label(_("&Resequence Waypoints"));
492 wxString export_label(_("&Export selected..."));
493 wxString send_to_gps_label(_("&Send to GPS..."));
494 wxString send_to_peer_label(_("Send to &Peer..."));
495
496#ifdef __ANDROID__
497 reseq_label = wxString(_("Resequence"));
498 export_label = wxString(_("Export"));
499 send_to_gps_label = wxString(_("Send to GPS"));
500 send_to_peer_label = wxString(_("Send to Peer"));
501#endif
502
503 btnRteExport = new wxButton(winr, -1, export_label);
504 bsRouteButtonsInner->Add(btnRteExport, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
505 btnRteExport->Connect(
506 wxEVT_COMMAND_BUTTON_CLICKED,
507 wxCommandEventHandler(RouteManagerDialog::OnRteExportClick), NULL, this);
508
509 btnRteResequence = new wxButton(winr, -1, reseq_label);
510 bsRouteButtonsInner->Add(btnRteResequence, 0, wxALL | wxEXPAND,
511 DIALOG_MARGIN);
512 btnRteResequence->Connect(
513 wxEVT_COMMAND_BUTTON_CLICKED,
514 wxCommandEventHandler(RouteManagerDialog::OnRteResequenceClick), NULL,
515 this);
516
517 btnRteSendToPeer = new wxButton(winr, -1, send_to_peer_label);
518 bsRouteButtonsInner->Add(btnRteSendToPeer, 0, wxALL | wxEXPAND,
519 DIALOG_MARGIN);
520 btnRteSendToPeer->Connect(
521 wxEVT_COMMAND_BUTTON_CLICKED,
522 wxCommandEventHandler(RouteManagerDialog::OnRteSendToPeerClick), NULL,
523 this);
524
525 btnRteSendToGPS = new wxButton(winr, -1, send_to_gps_label);
526 bsRouteButtonsInner->Add(btnRteSendToGPS, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
527 btnRteSendToGPS->Connect(
528 wxEVT_COMMAND_BUTTON_CLICKED,
529 wxCommandEventHandler(RouteManagerDialog::OnRteSendToGPSClick), NULL,
530 this);
531
532 bsRouteButtonsInner->AddSpacer(10);
533
534 btnRteDeleteAll = new wxButton(winr, -1, _("&Delete All"));
535 bsRouteButtonsInner->Add(btnRteDeleteAll, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
536 btnRteDeleteAll->Connect(
537 wxEVT_COMMAND_BUTTON_CLICKED,
538 wxCommandEventHandler(RouteManagerDialog::OnRteDeleteAllClick), NULL,
539 this);
540
541 // Create "Tracks" panel
542 m_pPanelTrk = new wxPanel(m_pNotebook, wxID_ANY, wxDefaultPosition,
543 wxDefaultSize, wxNO_BORDER | wxTAB_TRAVERSAL);
544 wxBoxSizer *sbsTracks = new wxBoxSizer(wxHORIZONTAL);
545 m_pPanelTrk->SetSizer(sbsTracks);
546 m_pNotebook->AddPage(m_pPanelTrk, _("Tracks"));
547
548 wxBoxSizer *bSizerTrkContents;
549 bSizerTrkContents = new wxBoxSizer(wxVERTICAL);
550
551 wxFlexGridSizer *fgSizerFilterTrk;
552 fgSizerFilterTrk = new wxFlexGridSizer(0, 2, 0, 0);
553 fgSizerFilterTrk->AddGrowableCol(1);
554 fgSizerFilterTrk->SetFlexibleDirection(wxBOTH);
555 fgSizerFilterTrk->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
556
557 m_stFilterTrk = new wxStaticText(m_pPanelTrk, wxID_ANY, _("Filter"),
558 wxDefaultPosition, wxDefaultSize, 0);
559 m_stFilterTrk->Wrap(-1);
560 fgSizerFilterTrk->Add(m_stFilterTrk, 0, wxALL, 5);
561
562 m_tFilterTrk = new wxTextCtrl(m_pPanelTrk, wxID_ANY, wxEmptyString,
563 wxDefaultPosition, wxDefaultSize, 0);
564 fgSizerFilterTrk->Add(m_tFilterTrk, 1, wxALL | wxEXPAND, 5);
565
566 bSizerTrkContents->Add(fgSizerFilterTrk, 0, wxEXPAND, 5);
567 m_tFilterTrk->Connect(
568 wxEVT_COMMAND_TEXT_UPDATED,
569 wxCommandEventHandler(RouteManagerDialog::OnFilterChanged), NULL, this);
570
571 m_cbShowAllTrk = new wxCheckBox(m_pPanelTrk, wxID_ANY, _("Show all tracks"));
572 bSizerTrkContents->Add(m_cbShowAllTrk, 0, wxEXPAND | wxLEFT, 5);
573 m_cbShowAllTrk->Connect(
574 wxEVT_COMMAND_CHECKBOX_CLICKED,
575 wxCommandEventHandler(RouteManagerDialog::OnShowAllTrkCBClicked), NULL,
576 this);
577
578 m_pTrkListCtrl =
579 new wxListCtrl(m_pPanelTrk, -1, wxDefaultPosition, wxDefaultSize,
580 wxLC_REPORT | wxLC_SORT_ASCENDING | wxLC_HRULES |
581 wxBORDER_SUNKEN /*|wxLC_VRULES*/);
582
583#ifdef __ANDROID__
584 m_pTrkListCtrl->GetHandle()->setStyleSheet(getAdjustedDialogStyleSheet());
585#endif
586
587 m_pTrkListCtrl->Connect(wxEVT_COMMAND_LIST_ITEM_SELECTED,
588 wxListEventHandler(RouteManagerDialog::OnTrkSelected),
589 NULL, this);
590 m_pTrkListCtrl->Connect(wxEVT_COMMAND_LIST_ITEM_DESELECTED,
591 wxListEventHandler(RouteManagerDialog::OnTrkSelected),
592 NULL, this);
593 m_pTrkListCtrl->Connect(
594 wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
595 wxListEventHandler(RouteManagerDialog::OnTrkDefaultAction), NULL, this);
596 m_pTrkListCtrl->Connect(
597 wxEVT_LEFT_DOWN,
598 wxMouseEventHandler(RouteManagerDialog::OnTrkToggleVisibility), NULL,
599 this);
600 m_pTrkListCtrl->Connect(
601 wxEVT_COMMAND_LIST_COL_CLICK,
602 wxListEventHandler(RouteManagerDialog::OnTrkColumnClicked), NULL, this);
603 m_pTrkListCtrl->Connect(
604 wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK,
605 wxListEventHandler(RouteManagerDialog::OnTrkRightClick), NULL, this);
606 this->Connect(wxEVT_COMMAND_MENU_SELECTED,
607 wxCommandEventHandler(RouteManagerDialog::OnTrkMenuSelected),
608 NULL, this);
609
610 bSizerTrkContents->Add(m_pTrkListCtrl, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
611 sbsTracks->Add(bSizerTrkContents, 1, wxEXPAND, 5);
612
613 m_pTrkListCtrl->InsertColumn(colTRKVISIBLE, _("Show"), wxLIST_FORMAT_LEFT,
614 4 * char_width);
615 m_pTrkListCtrl->InsertColumn(colTRKNAME, _("Track Name"), wxLIST_FORMAT_LEFT,
616 20 * char_width);
617 m_pTrkListCtrl->InsertColumn(colTRKDATE, _("Start Date"), wxLIST_FORMAT_LEFT,
618 20 * char_width);
619 m_pTrkListCtrl->InsertColumn(colTRKLENGTH, _("Length"), wxLIST_FORMAT_LEFT,
620 5 * char_width);
621
622 wxBoxSizer *bsTrkButtons = new wxBoxSizer(wxVERTICAL);
623 sbsTracks->Add(bsTrkButtons, 0, wxEXPAND);
624
625 wxScrolledWindow *wint = new wxScrolledWindow(
626 m_pPanelTrk, wxID_ANY, wxDefaultPosition, wxDefaultSize,
627 wxNO_BORDER | wxTAB_TRAVERSAL | wxVSCROLL);
628 wint->SetScrollRate(0, 5);
629
630 bsTrkButtons->Add(wint, 1, wxALL | wxEXPAND, DIALOG_MARGIN);
631
632 wxBoxSizer *bsTrkButtonsInner = new wxBoxSizer(wxVERTICAL);
633 wint->SetSizer(bsTrkButtonsInner);
634
635 btnTrkNew = new wxButton(wint, -1, _("&Start Track"));
636 bsTrkButtonsInner->Add(btnTrkNew, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
637 btnTrkNew->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
638 wxCommandEventHandler(RouteManagerDialog::OnTrkNewClick),
639 NULL, this);
640
641 btnTrkProperties = new wxButton(wint, -1, _("&Properties"));
642 bsTrkButtonsInner->Add(btnTrkProperties, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
643 btnTrkProperties->Connect(
644 wxEVT_COMMAND_BUTTON_CLICKED,
645 wxCommandEventHandler(RouteManagerDialog::OnTrkPropertiesClick), NULL,
646 this);
647
648 btnTrkDelete = new wxButton(wint, -1, _("&Delete"));
649 bsTrkButtonsInner->Add(btnTrkDelete, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
650 btnTrkDelete->Connect(
651 wxEVT_COMMAND_BUTTON_CLICKED,
652 wxCommandEventHandler(RouteManagerDialog::OnTrkDeleteClick), NULL, this);
653
654 btnTrkExport = new wxButton(wint, -1, _("&Export selected..."));
655 bsTrkButtonsInner->Add(btnTrkExport, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
656 btnTrkExport->Connect(
657 wxEVT_COMMAND_BUTTON_CLICKED,
658 wxCommandEventHandler(RouteManagerDialog::OnTrkExportClick), NULL, this);
659
660 btnTrkRouteFromTrack = new wxButton(wint, -1, _("Route from Track"));
661 bsTrkButtonsInner->Add(btnTrkRouteFromTrack, 0, wxALL | wxEXPAND,
662 DIALOG_MARGIN);
663 btnTrkRouteFromTrack->Connect(
664 wxEVT_COMMAND_BUTTON_CLICKED,
665 wxCommandEventHandler(RouteManagerDialog::OnTrkRouteFromTrackClick), NULL,
666 this);
667
668 btnTrkSendToPeer = new wxButton(wint, -1, _("Send to &Peer"));
669 bsTrkButtonsInner->Add(btnTrkSendToPeer, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
670 btnTrkSendToPeer->Connect(
671 wxEVT_COMMAND_BUTTON_CLICKED,
672 wxCommandEventHandler(RouteManagerDialog::OnTrkSendToPeerClick), NULL,
673 this);
674
675 bsTrkButtonsInner->AddSpacer(10);
676
677 btnTrkDeleteAll = new wxButton(wint, -1, _("&Delete All"));
678 bsTrkButtonsInner->Add(btnTrkDeleteAll, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
679 btnTrkDeleteAll->Connect(
680 wxEVT_COMMAND_BUTTON_CLICKED,
681 wxCommandEventHandler(RouteManagerDialog::OnTrkDeleteAllClick), NULL,
682 this);
683
684 // Create "Marks" panel
685 m_pPanelWpt = new wxPanel(m_pNotebook, wxID_ANY, wxDefaultPosition,
686 wxDefaultSize, wxNO_BORDER | wxTAB_TRAVERSAL);
687 wxBoxSizer *sbsWpts = new wxBoxSizer(wxHORIZONTAL);
688 m_pPanelWpt->SetSizer(sbsWpts);
689 m_pNotebook->AddPage(m_pPanelWpt, _("Marks"));
690
691 wxBoxSizer *bSizerWptContents;
692 bSizerWptContents = new wxBoxSizer(wxVERTICAL);
693
694 wxFlexGridSizer *fgSizerFilterWpt;
695 fgSizerFilterWpt = new wxFlexGridSizer(0, 2, 0, 0);
696 fgSizerFilterWpt->AddGrowableCol(1);
697 fgSizerFilterWpt->SetFlexibleDirection(wxBOTH);
698 fgSizerFilterWpt->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
699
700 m_stFilterWpt = new wxStaticText(m_pPanelWpt, wxID_ANY, _("Filter"),
701 wxDefaultPosition, wxDefaultSize, 0);
702 m_stFilterWpt->Wrap(-1);
703 fgSizerFilterWpt->Add(m_stFilterWpt, 0, wxALL, 5);
704
705 m_tFilterWpt = new wxTextCtrl(m_pPanelWpt, wxID_ANY, wxEmptyString,
706 wxDefaultPosition, wxDefaultSize, 0);
707 fgSizerFilterWpt->Add(m_tFilterWpt, 1, wxALL | wxEXPAND, 5);
708
709 bSizerWptContents->Add(fgSizerFilterWpt, 0, wxEXPAND, 5);
710 m_tFilterWpt->Connect(
711 wxEVT_COMMAND_TEXT_UPDATED,
712 wxCommandEventHandler(RouteManagerDialog::OnFilterChanged), NULL, this);
713
714 m_cbShowAllWP = new wxCheckBox(m_pPanelWpt, wxID_ANY, _("Show all marks"));
715 bSizerWptContents->Add(m_cbShowAllWP, 0, wxEXPAND | wxLEFT, 5);
716 m_cbShowAllWP->Connect(
717 wxEVT_COMMAND_CHECKBOX_CLICKED,
718 wxCommandEventHandler(RouteManagerDialog::OnShowAllWpCBClicked), NULL,
719 this);
720
721 m_pWptListCtrl =
722 new wxListCtrl(m_pPanelWpt, -1, wxDefaultPosition, wxDefaultSize,
723 wxLC_REPORT | wxLC_SORT_ASCENDING | wxLC_HRULES |
724 wxBORDER_SUNKEN /*|wxLC_VRULES*/);
725#ifdef __ANDROID__
726 m_pWptListCtrl->GetHandle()->setStyleSheet(getAdjustedDialogStyleSheet());
727#endif
728
729 m_pWptListCtrl->Connect(wxEVT_COMMAND_LIST_ITEM_SELECTED,
730 wxListEventHandler(RouteManagerDialog::OnWptSelected),
731 NULL, this);
732 m_pWptListCtrl->Connect(wxEVT_COMMAND_LIST_ITEM_DESELECTED,
733 wxListEventHandler(RouteManagerDialog::OnWptSelected),
734 NULL, this);
735 m_pWptListCtrl->Connect(
736 wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
737 wxListEventHandler(RouteManagerDialog::OnWptDefaultAction), NULL, this);
738 m_pWptListCtrl->Connect(
739 wxEVT_LEFT_DOWN,
740 wxMouseEventHandler(RouteManagerDialog::OnWptToggleVisibility), NULL,
741 this);
742 m_pWptListCtrl->Connect(
743 wxEVT_COMMAND_LIST_COL_CLICK,
744 wxListEventHandler(RouteManagerDialog::OnWptColumnClicked), NULL, this);
745 bSizerWptContents->Add(m_pWptListCtrl, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
746 sbsWpts->Add(bSizerWptContents, 1, wxEXPAND, 5);
747
748 m_pWptListCtrl->InsertColumn(colWPTICON, _("Icon"), wxLIST_FORMAT_LEFT,
749 4 * char_width);
750 m_pWptListCtrl->InsertColumn(colWPTSCALE, _("Scale"), wxLIST_FORMAT_LEFT,
751 8 * char_width);
752 m_pWptListCtrl->InsertColumn(colWPTNAME, _("Mark Name"), wxLIST_FORMAT_LEFT,
753 15 * char_width);
754 m_pWptListCtrl->InsertColumn(colWPTDIST, _("Distance from own ship"),
755 wxLIST_FORMAT_LEFT, 14 * char_width);
756
757 wxBoxSizer *bsWptButtons = new wxBoxSizer(wxVERTICAL);
758 sbsWpts->Add(bsWptButtons, 0, wxEXPAND);
759
760 wxScrolledWindow *winw = new wxScrolledWindow(
761 m_pPanelWpt, wxID_ANY, wxDefaultPosition, wxDefaultSize,
762 wxNO_BORDER | wxTAB_TRAVERSAL | wxVSCROLL);
763 winw->SetScrollRate(0, 5);
764
765 bsWptButtons->Add(winw, 1, wxALL | wxEXPAND, DIALOG_MARGIN);
766
767 wxBoxSizer *bsWptButtonsInner = new wxBoxSizer(wxVERTICAL);
768 winw->SetSizer(bsWptButtonsInner);
769
770 btnWptNew = new wxButton(winw, -1, _("&New"));
771 bsWptButtonsInner->Add(btnWptNew, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
772 btnWptNew->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
773 wxCommandEventHandler(RouteManagerDialog::OnWptNewClick),
774 NULL, this);
775
776 btnWptProperties = new wxButton(winw, -1, _("&Properties"));
777 bsWptButtonsInner->Add(btnWptProperties, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
778 btnWptProperties->Connect(
779 wxEVT_COMMAND_BUTTON_CLICKED,
780 wxCommandEventHandler(RouteManagerDialog::OnWptPropertiesClick), NULL,
781 this);
782
783 btnWptZoomto = new wxButton(winw, -1, _("&Center View"));
784 bsWptButtonsInner->Add(btnWptZoomto, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
785 btnWptZoomto->Connect(
786 wxEVT_COMMAND_BUTTON_CLICKED,
787 wxCommandEventHandler(RouteManagerDialog::OnWptZoomtoClick), NULL, this);
788
789 btnWptDelete = new wxButton(winw, -1, _("&Delete"));
790 bsWptButtonsInner->Add(btnWptDelete, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
791 btnWptDelete->Connect(
792 wxEVT_COMMAND_BUTTON_CLICKED,
793 wxCommandEventHandler(RouteManagerDialog::OnWptDeleteClick), NULL, this);
794
795 btnWptGoTo = new wxButton(winw, -1, _("&Go To"));
796 bsWptButtonsInner->Add(btnWptGoTo, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
797 btnWptGoTo->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
798 wxCommandEventHandler(RouteManagerDialog::OnWptGoToClick),
799 NULL, this);
800
801 btnWptExport = new wxButton(winw, -1, _("&Export selected..."));
802 bsWptButtonsInner->Add(btnWptExport, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
803 btnWptExport->Connect(
804 wxEVT_COMMAND_BUTTON_CLICKED,
805 wxCommandEventHandler(RouteManagerDialog::OnWptExportClick), NULL, this);
806
807 btnWptSendToGPS = new wxButton(winw, -1, _("&Send to GPS"));
808 bsWptButtonsInner->Add(btnWptSendToGPS, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
809 btnWptSendToGPS->Connect(
810 wxEVT_COMMAND_BUTTON_CLICKED,
811 wxCommandEventHandler(RouteManagerDialog::OnWptSendToGPSClick), NULL,
812 this);
813
814 btnWptSendToPeer = new wxButton(winw, -1, _("Send to &Peer"));
815 bsWptButtonsInner->Add(btnWptSendToPeer, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
816 btnWptSendToPeer->Connect(
817 wxEVT_COMMAND_BUTTON_CLICKED,
818 wxCommandEventHandler(RouteManagerDialog::OnWptSendToPeerClick), NULL,
819 this);
820
821 bsWptButtonsInner->AddSpacer(10);
822
823 btnWptDeleteAll = new wxButton(winw, -1, _("Delete All"));
824 bsWptButtonsInner->Add(btnWptDeleteAll, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
825 btnWptDeleteAll->Connect(
826 wxEVT_COMMAND_BUTTON_CLICKED,
827 wxCommandEventHandler(RouteManagerDialog::OnWptDeleteAllClick), NULL,
828 this);
829
830 wxBoxSizer *itemBoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
831 itemBoxSizer1->Add(itemBoxSizer5, 0, wxALL | wxEXPAND);
832
833 wxBoxSizer *itemBoxSizer6 = new wxBoxSizer(wxHORIZONTAL);
834 itemBoxSizer5->Add(itemBoxSizer6, 1, wxALL | wxEXPAND);
835
836 btnImport = new wxButton(this, -1, _("I&mport GPX..."));
837 itemBoxSizer6->Add(btnImport, 0, wxALL | wxALIGN_LEFT, DIALOG_MARGIN);
838 btnImport->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
839 wxCommandEventHandler(RouteManagerDialog::OnImportClick),
840 NULL, this);
841 /*
842 * btnExport = new wxButton( this, -1, _("E&xport All...") );
843 * itemBoxSizer6->Add( btnExport, 0, wxALL | wxALIGN_LEFT, DIALOG_MARGIN );
844 * btnExport->Connect( wxEVT_COMMAND_BUTTON_CLICKED,
845 * wxCommandEventHandler(RouteManagerDialog::OnExportClick), NULL,
846 * this );
847 */
848 btnExportViz = new wxButton(this, -1, _("Export All Visible..."));
849 itemBoxSizer6->Add(btnExportViz, 0, wxALL | wxALIGN_LEFT, DIALOG_MARGIN);
850 btnExportViz->Connect(
851 wxEVT_COMMAND_BUTTON_CLICKED,
852 wxCommandEventHandler(RouteManagerDialog::OnExportVizClick), NULL, this);
853
854 // Dialog OK button
855 wxSize sz = ::wxGetDisplaySize();
856 if (sz.y < sz.x) { // landscape
857 itemBoxSizer6->Add(0, 0, 1, wxEXPAND, 5); // Spacer
858 itemBoxSizer6->Add(new wxButton(this, wxID_OK), 0, wxALL, DIALOG_MARGIN);
859 } else {
860 wxStaticLine *staticLine121 = new wxStaticLine(
861 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
862 itemBoxSizer1->Add(staticLine121, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
863
864 wxBoxSizer *itemBoxSizer7 = new wxBoxSizer(wxHORIZONTAL);
865 itemBoxSizer1->Add(itemBoxSizer7, 0, wxEXPAND);
866
867 wxBoxSizer *itemBoxSizer7a = new wxBoxSizer(wxHORIZONTAL);
868 itemBoxSizer7->Add(itemBoxSizer7a, 1, wxEXPAND);
869
870 itemBoxSizer7a->AddStretchSpacer();
871 itemBoxSizer7a->Add(new wxButton(this, wxID_OK), 0, wxRIGHT | wxALIGN_RIGHT,
872 DIALOG_MARGIN * 4);
873 }
874
875 // Create "Layers" panel
876 m_pPanelLay = new wxPanel(m_pNotebook, wxID_ANY, wxDefaultPosition,
877 wxDefaultSize, wxNO_BORDER | wxTAB_TRAVERSAL);
878 wxBoxSizer *sbsLayers = new wxBoxSizer(wxHORIZONTAL);
879 m_pPanelLay->SetSizer(sbsLayers);
880 m_pNotebook->AddPage(m_pPanelLay, _("Layers"));
881
882 wxBoxSizer *bSizerLayContents;
883 bSizerLayContents = new wxBoxSizer(wxVERTICAL);
884
885 wxFlexGridSizer *fgSizerFilterLay;
886 fgSizerFilterLay = new wxFlexGridSizer(0, 2, 0, 0);
887 fgSizerFilterLay->AddGrowableCol(1);
888 fgSizerFilterLay->SetFlexibleDirection(wxBOTH);
889 fgSizerFilterLay->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
890
891 m_stFilterLay = new wxStaticText(m_pPanelLay, wxID_ANY, _("Filter"),
892 wxDefaultPosition, wxDefaultSize, 0);
893 m_stFilterLay->Wrap(-1);
894 fgSizerFilterLay->Add(m_stFilterLay, 0, wxALL, 5);
895
896 m_tFilterLay = new wxTextCtrl(m_pPanelLay, wxID_ANY, wxEmptyString,
897 wxDefaultPosition, wxDefaultSize, 0);
898 fgSizerFilterLay->Add(m_tFilterLay, 1, wxALL | wxEXPAND, 5);
899
900 bSizerLayContents->Add(fgSizerFilterLay, 0, wxEXPAND, 5);
901 m_tFilterLay->Connect(
902 wxEVT_COMMAND_TEXT_UPDATED,
903 wxCommandEventHandler(RouteManagerDialog::OnFilterChanged), NULL, this);
904
905 m_cbShowAllLay = new wxCheckBox(m_pPanelLay, wxID_ANY, _("Show all layers"));
906 bSizerLayContents->Add(m_cbShowAllLay, 0, wxEXPAND | wxLEFT, 5);
907 m_cbShowAllLay->Connect(
908 wxEVT_COMMAND_CHECKBOX_CLICKED,
909 wxCommandEventHandler(RouteManagerDialog::OnShowAllLayCBClicked), NULL,
910 this);
911
912 m_pLayListCtrl =
913 new wxListCtrl(m_pPanelLay, -1, wxDefaultPosition, wxDefaultSize,
914 wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING |
915 wxLC_HRULES | wxBORDER_SUNKEN /*|wxLC_VRULES*/);
916#ifdef __ANDROID__
917 m_pLayListCtrl->GetHandle()->setStyleSheet(getAdjustedDialogStyleSheet());
918#endif
919
920 m_pLayListCtrl->Connect(wxEVT_COMMAND_LIST_ITEM_SELECTED,
921 wxListEventHandler(RouteManagerDialog::OnLaySelected),
922 NULL, this);
923 m_pLayListCtrl->Connect(wxEVT_COMMAND_LIST_ITEM_DESELECTED,
924 wxListEventHandler(RouteManagerDialog::OnLaySelected),
925 NULL, this);
926 m_pLayListCtrl->Connect(
927 wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
928 wxListEventHandler(RouteManagerDialog::OnLayDefaultAction), NULL, this);
929 m_pLayListCtrl->Connect(
930 wxEVT_LEFT_DOWN,
931 wxMouseEventHandler(RouteManagerDialog::OnLayToggleVisibility), NULL,
932 this);
933 m_pLayListCtrl->Connect(
934 wxEVT_COMMAND_LIST_COL_CLICK,
935 wxListEventHandler(RouteManagerDialog::OnLayColumnClicked), NULL, this);
936 bSizerLayContents->Add(m_pLayListCtrl, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
937 sbsLayers->Add(bSizerLayContents, 1, wxEXPAND, 5);
938
939 m_pLayListCtrl->InsertColumn(colLAYVISIBLE, _T(""), wxLIST_FORMAT_LEFT,
940 4 * char_width);
941 m_pLayListCtrl->InsertColumn(colLAYNAME, _("Layer Name"), wxLIST_FORMAT_LEFT,
942 14 * char_width);
943 m_pLayListCtrl->InsertColumn(colLAYITEMS, _("No. of items"),
944 wxLIST_FORMAT_LEFT, 10 * char_width);
945 m_pLayListCtrl->InsertColumn(colLAYPERSIST, _("Layer type"),
946 wxLIST_FORMAT_LEFT, 10 * char_width);
947
948 wxBoxSizer *bsLayButtons = new wxBoxSizer(wxVERTICAL);
949 sbsLayers->Add(bsLayButtons, 0, wxEXPAND);
950
951 wxScrolledWindow *winl = new wxScrolledWindow(
952 m_pPanelLay, wxID_ANY, wxDefaultPosition, wxDefaultSize,
953 wxNO_BORDER | wxTAB_TRAVERSAL | wxVSCROLL);
954 winl->SetScrollRate(0, 5);
955
956 bsLayButtons->Add(winl, 1, wxALL | wxEXPAND, DIALOG_MARGIN);
957
958 wxBoxSizer *bsLayButtonsInner = new wxBoxSizer(wxVERTICAL);
959 winl->SetSizer(bsLayButtonsInner);
960
961 btnLayNew = new wxButton(winl, -1, _("Create Temporary layer"));
962 bsLayButtonsInner->Add(btnLayNew, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
963 btnLayNew->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
964 wxCommandEventHandler(RouteManagerDialog::OnLayNewClick),
965 NULL, this);
966
967 btnPerLayNew = new wxButton(winl, -1, _("Create Persistent layer"));
968 bsLayButtonsInner->Add(btnPerLayNew, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
969 btnPerLayNew->Connect(
970 wxEVT_COMMAND_BUTTON_CLICKED,
971 wxCommandEventHandler(RouteManagerDialog::OnPerLayNewClick), NULL, this);
972
973 btnLayDelete = new wxButton(winl, -1, _("&Delete"));
974 bsLayButtonsInner->Add(btnLayDelete, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
975 btnLayDelete->Connect(
976 wxEVT_COMMAND_BUTTON_CLICKED,
977 wxCommandEventHandler(RouteManagerDialog::OnLayDeleteClick), NULL, this);
978
979 cbLayToggleChart = new wxCheckBox(winl, -1, _("Show on chart"));
980 bsLayButtonsInner->Add(cbLayToggleChart, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
981 cbLayToggleChart->Connect(
982 wxEVT_COMMAND_CHECKBOX_CLICKED,
983 wxCommandEventHandler(RouteManagerDialog::OnLayToggleChartClick), NULL,
984 this);
985
986 cbLayToggleNames =
987 new wxCheckBox(winl, -1, _("Show WPT names"), wxDefaultPosition,
988 wxDefaultSize, wxCHK_3STATE);
989
990 bsLayButtonsInner->Add(cbLayToggleNames, 0, wxALL | wxEXPAND, DIALOG_MARGIN);
991 cbLayToggleNames->Connect(
992 wxEVT_COMMAND_CHECKBOX_CLICKED,
993 wxCommandEventHandler(RouteManagerDialog::OnLayToggleNamesClick), NULL,
994 this);
995
996 cbLayToggleListing = new wxCheckBox(winl, -1, _("List contents"));
997 bsLayButtonsInner->Add(cbLayToggleListing, 0, wxALL | wxEXPAND,
998 DIALOG_MARGIN);
999 cbLayToggleListing->Connect(
1000 wxEVT_COMMAND_CHECKBOX_CLICKED,
1001 wxCommandEventHandler(RouteManagerDialog::OnLayToggleListingClick), NULL,
1002 this);
1003
1004 RecalculateSize();
1005
1006 int imageRefSize = m_charWidth * 2; // g_Platform->GetDisplayDPmm() * 4;
1007 wxImageList *imglist = new wxImageList(imageRefSize, imageRefSize, true, 1);
1008
1009 // Load eye icons
1010 wxString UserIconPath = g_Platform->GetSharedDataDir() + _T("uidata") +
1011 wxFileName::GetPathSeparator();
1012 wxImage iconSVG =
1013 LoadSVG(UserIconPath + _T("eye.svg"), imageRefSize, imageRefSize)
1014 .ConvertToImage();
1015 if (iconSVG.IsOk()) {
1016 iconSVG.Resize(wxSize(imageRefSize, imageRefSize),
1017 wxPoint(0, 0)); // Avoid wxImageList size asserts
1018 imglist->Add(wxBitmap(iconSVG));
1019 }
1020
1021 iconSVG = LoadSVG(UserIconPath + _T("eyex.svg"), imageRefSize, imageRefSize)
1022 .ConvertToImage();
1023 if (iconSVG.IsOk()) {
1024 iconSVG.Resize(wxSize(imageRefSize, imageRefSize), wxPoint(0, 0));
1025 imglist->Add(wxBitmap(iconSVG));
1026 }
1027
1028 iconSVG =
1029 LoadSVG(UserIconPath + _T("eyeGray.svg"), imageRefSize, imageRefSize)
1030 .ConvertToImage();
1031 if (iconSVG.IsOk()) {
1032 iconSVG.Resize(wxSize(imageRefSize, imageRefSize), wxPoint(0, 0));
1033 imglist->Add(wxBitmap(iconSVG));
1034 }
1035
1036 m_pRouteListCtrl->AssignImageList(imglist, wxIMAGE_LIST_SMALL);
1037
1038#ifdef __ANDROID__
1039 m_pRouteListCtrl->GetHandle()->setIconSize(QSize(imageRefSize, imageRefSize));
1040#endif
1041
1042 // Assign will handle destroy, Set will not. It's OK, that's what we want
1043 m_pTrkListCtrl->SetImageList(imglist, wxIMAGE_LIST_SMALL);
1044 m_pWptListCtrl->SetImageList(
1045 pWayPointMan->Getpmarkicon_image_list(m_listIconSize),
1046 wxIMAGE_LIST_SMALL);
1047 m_pLayListCtrl->SetImageList(imglist, wxIMAGE_LIST_SMALL);
1048
1049 SetColorScheme();
1050
1051 UpdateLists();
1052
1053 // This should work under Linux :-(
1054 // m_pNotebook->Connect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
1055 // wxNotebookEventHandler(RouteManagerDialog::OnTabSwitch), NULL, this);
1056
1057 m_bNeedConfigFlush = false;
1058}
1059
1060RouteManagerDialog::~RouteManagerDialog() {
1061 delete m_pRouteListCtrl;
1062 delete m_pTrkListCtrl;
1063 delete m_pWptListCtrl;
1064 delete m_pLayListCtrl;
1065
1066 delete btnRteDelete;
1067 delete btnRteResequence;
1068 delete btnRteExport;
1069 delete btnRteZoomto;
1070 delete btnRteProperties;
1071 delete btnRteActivate;
1072 delete btnRteReverse;
1073 delete btnRteSendToGPS;
1074 delete btnRteDeleteAll;
1075 delete btnTrkNew;
1076 delete btnTrkProperties;
1077 delete btnTrkDelete;
1078 delete btnTrkExport;
1079 delete btnTrkRouteFromTrack;
1080 delete btnTrkDeleteAll;
1081 delete btnWptNew;
1082 delete btnWptProperties;
1083 delete btnWptZoomto;
1084 delete btnWptDelete;
1085 delete btnWptGoTo;
1086 delete btnWptExport;
1087 delete btnWptSendToGPS;
1088 delete btnWptDeleteAll;
1089 delete btnLayNew;
1090 // delete btnLayProperties;
1091 delete cbLayToggleChart;
1092 delete cbLayToggleListing;
1093 delete cbLayToggleNames;
1094 delete btnLayDelete;
1095 delete btnImport;
1096 delete btnExport;
1097 delete btnExportViz;
1098 btnImport = NULL;
1099 btnExport = NULL;
1100 btnExportViz = NULL;
1101
1102 delete m_pNotebook;
1103 instanceFlag = false;
1104}
1105
1106void RouteManagerDialog::RecalculateSize() {
1107 // All of this dialog layout is expandable, so we need to set a specific size
1108 // target for the onscreen display. The size will then be adjusted so that it
1109 // fits within the parent's client area, with some padding
1110
1111 // Get a text height metric for reference
1112 int char_width, char_height;
1113 GetTextExtent(_T("W"), &char_width, &char_height);
1114
1115 wxSize sz;
1116 sz.x = 60 * char_width;
1117 sz.y = 30 * char_height;
1118
1119 wxSize dsize = GetParent()->GetClientSize();
1120 sz.y = wxMin(sz.y, dsize.y);
1121 sz.x = wxMin(sz.x, dsize.x);
1122 SetClientSize(sz);
1123
1124 wxSize fsize = GetSize();
1125 fsize.y = wxMin(fsize.y, dsize.y);
1126 fsize.x = wxMin(fsize.x, dsize.x);
1127 SetSize(fsize);
1128
1129 CentreOnParent();
1130}
1131
1132void RouteManagerDialog::OnClose(wxCloseEvent &event) {
1133#ifdef __WXGTK__
1134 gFrame->Raise();
1135#endif
1136 Hide();
1137 // pRouteManagerDialog = NULL;
1138}
1139
1140void RouteManagerDialog::OnOK(wxCommandEvent &event) {
1141#ifdef __WXGTK__
1142 gFrame->Raise();
1143#endif
1144 Hide();
1145}
1146
1147void RouteManagerDialog::SetColorScheme() { DimeControl(this); }
1148
1149void RouteManagerDialog::OnShowAllRteCBClicked(wxCommandEvent &event) {
1150 bool viz = m_cbShowAllRte->GetValue();
1151 long item = -1;
1152 int item_count = m_pRouteListCtrl->GetItemCount();
1153 bool busy = false;
1154 if (item_count > 50) {
1155 busy = true;
1156 ::wxBeginBusyCursor();
1157 }
1158 for (;;) {
1159 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1160 wxLIST_STATE_DONTCARE);
1161 if (item == -1) break;
1162
1163 Route *pR = (Route *)m_pRouteListCtrl->GetItemData(item);
1164
1165 pR->SetVisible(viz, viz);
1166 pR->SetSharedWPViz(viz);
1167
1168 m_pRouteListCtrl->SetItemImage(item, !viz); // visible
1169
1170 NavObj_dB::GetInstance().UpdateRouteViz(pR);
1171 }
1172
1173 if (busy) ::wxEndBusyCursor();
1174
1175 UpdateWptListCtrlViz();
1176 gFrame->RefreshAllCanvas();
1177}
1178
1179void RouteManagerDialog::OnShowAllWpCBClicked(wxCommandEvent &event) {
1180 bool viz = m_cbShowAllWP->GetValue();
1181 long item = -1;
1182 int item_count = m_pWptListCtrl->GetItemCount();
1183 bool busy = false;
1184 if (item_count > 100) {
1185 busy = true;
1186 ::wxBeginBusyCursor();
1187 }
1188
1189 for (;;) {
1190 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1191 wxLIST_STATE_DONTCARE);
1192 if (item == -1) break;
1193
1194 RoutePoint *pRP = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
1195
1196 if (!pRP->IsSharedInVisibleRoute()) {
1197 pRP->SetVisible(viz);
1198 } else
1199 pRP->SetVisible(true);
1200
1201 m_pWptListCtrl->SetItemImage(item, RoutePointGui(*pRP).GetIconImageIndex());
1202 NavObj_dB::GetInstance().UpdateDBRoutePointViz(pRP);
1203 }
1204
1205 if (busy) ::wxEndBusyCursor();
1206
1207 gFrame->RefreshAllCanvas();
1208}
1209
1210void RouteManagerDialog::OnShowAllTrkCBClicked(wxCommandEvent &event) {
1211 bool viz = m_cbShowAllTrk->GetValue();
1212 long item = -1;
1213 for (;;) {
1214 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1215 wxLIST_STATE_DONTCARE);
1216 if (item == -1) break;
1217
1218 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
1219
1220 track->SetVisible(viz);
1221 NavObj_dB::GetInstance().UpdateDBTrackAttributes(track);
1222 m_pTrkListCtrl->SetItemImage(item, track->IsVisible() ? 0 : 1);
1223 }
1224
1225 gFrame->RefreshAllCanvas();
1226}
1227
1228void RouteManagerDialog::OnShowAllLayCBClicked(wxCommandEvent &event) {
1229 bool viz = m_cbShowAllLay->GetValue();
1230 long item = -1;
1231 for (;;) {
1232 item = m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1233 wxLIST_STATE_DONTCARE);
1234 if (item == -1) break;
1235
1236 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
1237
1238 layer->SetVisibleOnChart(viz);
1239 m_pLayListCtrl->SetItemImage(item, layer->IsVisibleOnChart() ? 0 : 1);
1240
1241 ToggleLayerContentsOnChart(layer);
1242 }
1243
1244 gFrame->RefreshAllCanvas();
1245}
1246
1247void RouteManagerDialog::UpdateRouteListCtrl() {
1248 // if an item was selected, make it selected again if it still exist
1249 long item = -1;
1250 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1251 wxLIST_STATE_SELECTED);
1252 wxUIntPtr selected_id = wxUIntPtr(0);
1253 if (item != -1) selected_id = m_pRouteListCtrl->GetItemData(item);
1254
1255 // Delete existing items
1256 m_pRouteListCtrl->DeleteAllItems();
1257
1258 // then add routes to the listctrl
1259 RouteList::iterator it;
1260 int index = 0;
1261 int list_index = 0;
1262 bool bpartialViz = false;
1263
1264 for (it = (*pRouteList).begin(); it != (*pRouteList).end(); ++it, ++index) {
1265 if (!(*it)->IsListed()) continue;
1266
1267 if (!(*it)->GetName().Upper().Contains(m_tFilterRte->GetValue().Upper())) {
1268 continue;
1269 }
1270
1271 wxListItem li;
1272 li.SetId(list_index);
1273 li.SetImage((*it)->IsVisible() ? 0 : 1);
1274 li.SetData(*it);
1275 li.SetText(_T(""));
1276 li.SetAlign(wxLIST_FORMAT_LEFT);
1277
1278 if ((*it)->m_bRtIsActive) {
1279 wxFont font = *wxNORMAL_FONT;
1280 font.SetWeight(wxFONTWEIGHT_BOLD);
1281 li.SetFont(font);
1282 }
1283
1284 long idx = m_pRouteListCtrl->InsertItem(li);
1285
1286 wxString name = (*it)->m_RouteNameString;
1287 if (name.IsEmpty()) name = _("(Unnamed Route)");
1288 m_pRouteListCtrl->SetItem(idx, rmROUTENAME, name);
1289
1290 wxString startend = (*it)->m_RouteStartString;
1291 if (!(*it)->m_RouteEndString.IsEmpty())
1292 startend.append(_(" - ") + (*it)->m_RouteEndString);
1293 m_pRouteListCtrl->SetItem(idx, rmROUTEDESC, startend);
1294
1295 wxListItem lic;
1296 lic.SetId(list_index);
1297 lic.SetColumn(1);
1298 lic.SetAlign(wxLIST_FORMAT_LEFT);
1299 m_pRouteListCtrl->SetItem(lic);
1300
1301 lic.SetColumn(2);
1302 lic.SetAlign(wxLIST_FORMAT_LEFT);
1303 m_pRouteListCtrl->SetItem(lic);
1304
1305 // Keep track if any are invisible
1306 if (!(*it)->IsVisible()) bpartialViz = true;
1307
1308 list_index++;
1309 }
1310
1311 m_pRouteListCtrl->SortItems(SortRoutesOnName, (wxIntPtr)NULL);
1312
1313 m_pRouteListCtrl->SetColumnWidth(0, 4 * m_charWidth);
1314
1315 // restore selection if possible
1316 // NOTE this will select a different item, if one is deleted
1317 // (the next route will get that index).
1318 if (selected_id != wxUIntPtr(0)) {
1319 item = m_pRouteListCtrl->FindItem(-1, selected_id);
1320 m_pRouteListCtrl->SetItemState(
1321 item, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
1322 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
1323 }
1324
1325 if ((m_lastRteItem >= 0) && (m_pRouteListCtrl->GetItemCount()))
1326 m_pRouteListCtrl->EnsureVisible(m_lastRteItem);
1327 UpdateRteButtons();
1328
1329 // If any route is invisible, then "show all" cb must be clear.
1330 m_cbShowAllRte->SetValue(!bpartialViz);
1331}
1332
1333void RouteManagerDialog::UpdateRteButtons() {
1334 // enable/disable buttons
1335 long selected_index_index =
1336 m_pRouteListCtrl->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1337 bool enable1 = m_pRouteListCtrl->GetSelectedItemCount() == 1;
1338 bool enablemultiple = m_pRouteListCtrl->GetSelectedItemCount() >= 1;
1339
1340 m_lastRteItem = selected_index_index;
1341
1342 btnRteDelete->Enable(m_pRouteListCtrl->GetSelectedItemCount() > 0);
1343 btnRteZoomto->Enable(enable1);
1344 btnRteProperties->Enable(enable1);
1345 btnRteReverse->Enable(enable1);
1346 btnRteExport->Enable(enablemultiple);
1347 btnRteResequence->Enable(enable1);
1348 btnRteSendToGPS->Enable(enable1);
1349 btnRteDeleteAll->Enable(m_pRouteListCtrl->GetItemCount() > 0);
1350 btnRteSendToPeer->Enable(enablemultiple);
1351
1352 // set activate button text
1353 Route *route = NULL;
1354 if (enable1)
1355 route = (Route *)m_pRouteListCtrl->GetItemData(selected_index_index);
1356
1357 if (!g_pRouteMan->IsAnyRouteActive()) {
1358 btnRteActivate->Enable(enable1);
1359 if (enable1) btnRteActivate->SetLabel(_("Activate"));
1360
1361 } else {
1362 if (enable1) {
1363 if (route && route->m_bRtIsActive) {
1364 btnRteActivate->Enable(enable1);
1365 btnRteActivate->SetLabel(_("Deactivate"));
1366 } else
1367 btnRteActivate->Enable(false);
1368 } else
1369 btnRteActivate->Enable(false);
1370 }
1371}
1372
1373void RouteManagerDialog::MakeAllRoutesInvisible() {
1374 RouteList::iterator it;
1375 long index = 0;
1376 for (it = (*pRouteList).begin(); it != (*pRouteList).end(); ++it, ++index) {
1377 if ((*it)->IsVisible()) { // avoid config updating as much as possible!
1378 (*it)->SetVisible(false);
1379 m_pRouteListCtrl->SetItemImage(m_pRouteListCtrl->FindItem(-1, index),
1380 1); // Likely not same order :0
1381 NavObj_dB::GetInstance().UpdateRoute(*it);
1382 }
1383 }
1384}
1385
1386void RouteManagerDialog::ZoomtoRoute(Route *route) {
1387 // Calculate bbox center
1388 LLBBox RBBox = route->GetBBox();
1389 double clat = (RBBox.GetMinLat() + RBBox.GetMaxLat()) / 2;
1390 double clon = (RBBox.GetMinLon() + RBBox.GetMaxLon()) / 2;
1391
1392 // Calculate ppm
1393 double rw, rh, ppm; // route width, height, final ppm scale to use
1394 int ww, wh; // chart window width, height
1395 // route bbox width in nm
1396 DistanceBearingMercator(RBBox.GetMinLat(), RBBox.GetMinLon(),
1397 RBBox.GetMinLat(), RBBox.GetMaxLon(), NULL, &rw);
1398 // route bbox height in nm
1399 DistanceBearingMercator(RBBox.GetMinLat(), RBBox.GetMinLon(),
1400 RBBox.GetMaxLat(), RBBox.GetMinLon(), NULL, &rh);
1401
1402 if (gFrame->GetFocusCanvas()) {
1403 gFrame->GetFocusCanvas()->GetSize(&ww, &wh);
1404 ppm = wxMin(ww / (rw * 1852), wh / (rh * 1852)) * (100 - fabs(clat)) / 90;
1405 ppm = wxMin(ppm, 1.0);
1406
1407 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), clat, clon, ppm);
1408 }
1409
1410 m_bNeedConfigFlush = true;
1411}
1412
1413// BEGIN Event handlers
1414void RouteManagerDialog::OnRteDeleteClick(wxCommandEvent &event) {
1415 int count = m_pRouteListCtrl->GetSelectedItemCount();
1416 bool confirmed = RouteGui::OnDelete(this, count);
1417
1418 if (confirmed && count > 0) {
1419 ::wxBeginBusyCursor();
1420 RouteList list;
1421
1422 gFrame->CancelAllMouseRoute();
1423 m_bNeedConfigFlush = true;
1424
1425 long item = -1;
1426 for (;;) {
1427 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1428 wxLIST_STATE_SELECTED);
1429 if (item == -1) break;
1430
1431 Route *proute_to_delete = (Route *)m_pRouteListCtrl->GetItemData(item);
1432
1433 if (proute_to_delete) list.Append(proute_to_delete);
1434 }
1435
1436 for (unsigned int i = 0; i < list.GetCount(); i++) {
1437 Route *route = list.Item(i)->GetData();
1438 if (route) {
1439 NavObj_dB::GetInstance().DeleteRoute(route);
1440 g_pRouteMan->DeleteRoute(route);
1441 }
1442 }
1443
1444 m_lastRteItem = -1;
1445 UpdateRouteListCtrl();
1446 UpdateTrkListCtrl();
1447
1448 gFrame->InvalidateAllCanvasUndo();
1449 gFrame->RefreshAllCanvas();
1450 ::wxEndBusyCursor();
1451 }
1452}
1453
1454void RouteManagerDialog::OnRteDeleteAllClick(wxCommandEvent &event) {
1455 int dialog_ret =
1456 OCPNMessageBox(this, _("Are you sure you want to delete <ALL> routes?"),
1457 wxString(_("OpenCPN Alert")), wxYES_NO);
1458
1459 if (dialog_ret == wxID_YES) {
1460 if (g_pRouteMan->GetpActiveRoute()) g_pRouteMan->DeactivateRoute();
1461
1462 gFrame->CancelAllMouseRoute();
1463
1464 g_pRouteMan->DeleteAllRoutes();
1465
1466 m_lastRteItem = -1;
1467 UpdateRouteListCtrl();
1468
1469 // Also need to update the track list control, since routes and tracks
1470 // share a common global list (pRouteList)
1471 UpdateTrkListCtrl();
1472
1473 if (pRoutePropDialog) pRoutePropDialog->Hide();
1474 gFrame->InvalidateAllCanvasUndo();
1475 gFrame->RefreshAllCanvas();
1476
1477 m_bNeedConfigFlush = true;
1478 }
1479}
1480
1481void RouteManagerDialog::OnRtePropertiesClick(wxCommandEvent &event) {
1482 // Show routeproperties dialog for selected route
1483 long item = -1;
1484 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1485 wxLIST_STATE_SELECTED);
1486 if (item == -1) return;
1487
1488 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1489
1490 if (!route) return;
1491
1492 pRoutePropDialog = RoutePropDlgImpl::getInstance(GetParent());
1493
1494 pRoutePropDialog->SetRouteAndUpdate(route);
1495
1496 if (!pRoutePropDialog->IsShown()) pRoutePropDialog->Show();
1497
1498 pRoutePropDialog->Raise();
1499
1500 m_bNeedConfigFlush = true;
1501}
1502
1503void RouteManagerDialog::OnRteZoomtoClick(wxCommandEvent &event) {
1504 // Zoom into the bounding box of the selected route
1505 long item = -1;
1506 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1507 wxLIST_STATE_SELECTED);
1508 if (item == -1) return;
1509
1510 // optionally make this route exclusively visible
1511 if (m_bCtrlDown) MakeAllRoutesInvisible();
1512
1513 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1514
1515 if (!route) return;
1516
1517 // Ensure route is visible
1518 if (!route->IsVisible()) {
1519 route->SetVisible(true);
1520 m_pRouteListCtrl->SetItemImage(item, route->IsVisible() ? 0 : 1);
1521 NavObj_dB::GetInstance().UpdateRoute(route);
1522 }
1523
1524 ZoomtoRoute(route);
1525}
1526
1527void RouteManagerDialog::OnRteReverseClick(wxCommandEvent &event) {
1528 // Reverse selected route
1529 long item = -1;
1530 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1531 wxLIST_STATE_SELECTED);
1532 if (item == -1) return;
1533
1534 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1535
1536 if (!route) return;
1537 if (route->m_bIsInLayer) return;
1538
1539 int ask_return = OCPNMessageBox(this, g_pRouteMan->GetRouteReverseMessage(),
1540 _("Rename Waypoints?"), wxYES_NO | wxCANCEL);
1541 if (ask_return != wxID_CANCEL) {
1542 bool rename = (ask_return == wxID_YES);
1543
1544 pSelect->DeleteAllSelectableRouteSegments(route);
1545 route->Reverse(rename);
1546 pSelect->AddAllSelectableRouteSegments(route);
1547
1548 // update column 2 - create a UpdateRouteItem(index) instead?
1549 wxString startend = route->m_RouteStartString;
1550 if (!route->m_RouteEndString.IsEmpty())
1551 startend.append(_(" - ") + route->m_RouteEndString);
1552 m_pRouteListCtrl->SetItem(item, 2, startend);
1553
1554 NavObj_dB::GetInstance().UpdateRoute(route);
1555
1556 gFrame->RefreshAllCanvas();
1557 }
1558
1559 m_bNeedConfigFlush = true;
1560}
1561
1562void RouteManagerDialog::OnRteExportClick(wxCommandEvent &event) {
1563 RouteList list;
1564
1565 wxString suggested_name = _T("routes");
1566
1567 long item = -1;
1568 for (;;) {
1569 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1570 wxLIST_STATE_SELECTED);
1571 if (item == -1) break;
1572
1573 Route *proute_to_export = (Route *)m_pRouteListCtrl->GetItemData(item);
1574
1575 if (proute_to_export) {
1576 list.Append(proute_to_export);
1577 if (proute_to_export->m_RouteNameString != wxEmptyString)
1578 suggested_name = proute_to_export->m_RouteNameString;
1579 }
1580 }
1581
1582 ExportGPXRoutes(this, &list, suggested_name);
1583}
1584
1585void RouteManagerDialog::OnRteResequenceClick(wxCommandEvent &event) {
1586 long item = -1;
1587 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1588 wxLIST_STATE_SELECTED);
1589 if (item == -1) return;
1590
1591 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1592
1593 if (!route) return;
1594 if (route->m_bIsInLayer) return;
1595 route->RenameRoutePoints();
1596}
1597
1598void RouteManagerDialog::OnRteSendToPeerClick(wxCommandEvent &event) {
1599 std::vector<Route *> list;
1600 long item = -1;
1601 for (;;) {
1602 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1603 wxLIST_STATE_SELECTED);
1604 if (item == -1) break;
1605
1606 Route *proute = (Route *)m_pRouteListCtrl->GetItemData(item);
1607
1608 if (proute) {
1609 list.push_back(proute);
1610 }
1611 }
1612 if (!list.empty()) {
1613 SendToPeerDlg dlg;
1614 for (auto r : list) {
1615 dlg.SetRoute(r);
1616 }
1617
1618 // Perform initial scan, if necessary
1619
1620 // Check for stale cache...
1621 MdnsCache::GetInstance().Validate();
1622 if (MdnsCache::GetInstance().GetCache().empty()) dlg.SetScanOnCreate(true);
1623
1624 dlg.SetScanTime(5); // seconds
1625 dlg.Create(NULL, -1, _("Send Route(s) to OpenCPN Peer") + _T( "..." ),
1626 _T(""));
1627 dlg.ShowModal();
1628 }
1629}
1630
1631void RouteManagerDialog::OnWptSendToPeerClick(wxCommandEvent &event) {
1632 std::vector<RoutePoint *> list;
1633 long item = -1;
1634 for (;;) {
1635 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1636 wxLIST_STATE_SELECTED);
1637 if (item == -1) break;
1638
1639 RoutePoint *proutep = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
1640
1641 if (proutep) {
1642 list.push_back(proutep);
1643 }
1644 }
1645 if (!list.empty()) {
1646 SendToPeerDlg dlg;
1647 for (auto r : list) {
1648 dlg.SetWaypoint(r);
1649 }
1650
1651 // Perform initial scan, if necessary
1652
1653 // Check for stale cache...
1654 MdnsCache::GetInstance().Validate();
1655 if (MdnsCache::GetInstance().GetCache().empty()) dlg.SetScanOnCreate(true);
1656
1657 dlg.SetScanTime(5); // seconds
1658 dlg.Create(NULL, -1, _("Send Waypoint(s) to OpenCPN Peer") + _T( "..." ),
1659 _T(""));
1660 dlg.ShowModal();
1661 }
1662}
1663
1664void RouteManagerDialog::OnTrkSendToPeerClick(wxCommandEvent &event) {
1665 std::vector<Track *> list;
1666 long item = -1;
1667 for (;;) {
1668 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1669 wxLIST_STATE_SELECTED);
1670 if (item == -1) break;
1671
1672 Track *ptrk = (Track *)m_pTrkListCtrl->GetItemData(item);
1673
1674 if (ptrk) {
1675 list.push_back(ptrk);
1676 }
1677 }
1678 if (!list.empty()) {
1679 SendToPeerDlg dlg;
1680 for (auto r : list) {
1681 dlg.SetTrack(r);
1682 }
1683
1684 // Perform initial scan, if necessary
1685
1686 // Check for stale cache...
1687 MdnsCache::GetInstance().Validate();
1688 if (MdnsCache::GetInstance().GetCache().empty()) dlg.SetScanOnCreate(true);
1689
1690 dlg.SetScanTime(5); // seconds
1691 dlg.Create(NULL, -1, _("Send Track(s) to OpenCPN Peer") + _T( "..." ),
1692 _T(""));
1693 dlg.ShowModal();
1694 }
1695}
1696
1697void RouteManagerDialog::OnRteActivateClick(wxCommandEvent &event) {
1698 // Activate the selected route, unless it already is
1699 long item = -1;
1700 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1701 wxLIST_STATE_SELECTED);
1702 if (item == -1) return;
1703
1704 if (m_bCtrlDown) MakeAllRoutesInvisible();
1705
1706 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1707
1708 if (!route) return;
1709
1710 if (!route->m_bRtIsActive) {
1711 if (!route->IsVisible()) {
1712 route->SetVisible(true);
1713 m_pRouteListCtrl->SetItemImage(item, 0, 0);
1714 }
1715
1716 ZoomtoRoute(route);
1717
1718 RoutePoint *best_point =
1719 g_pRouteMan->FindBestActivatePoint(route, gLat, gLon, gCog, gSog);
1720 g_pRouteMan->ActivateRoute(route, best_point);
1721 // g_pRouteMan->ActivateRoute(route);
1722 } else
1723 g_pRouteMan->DeactivateRoute();
1724
1725 UpdateRouteListCtrl();
1726
1727 NavObj_dB::GetInstance().UpdateRoute(route);
1728
1729 gFrame->RefreshAllCanvas();
1730
1731 // btnRteActivate->SetLabel(route->m_bRtIsActive ? _("Deactivate") :
1732 // _("Activate"));
1733
1734 m_bNeedConfigFlush = true;
1735}
1736
1737void RouteManagerDialog::OnRteToggleVisibility(wxMouseEvent &event) {
1738 wxPoint pos = event.GetPosition();
1739 int flags = 0;
1740 long clicked_index = m_pRouteListCtrl->HitTest(pos, flags);
1741
1742 // Clicking Visibility column?
1743 if (clicked_index > -1 &&
1744 event.GetX() < m_pRouteListCtrl->GetColumnWidth(rmVISIBLE)) {
1745 // Process the clicked item
1746 Route *route = (Route *)m_pRouteListCtrl->GetItemData(clicked_index);
1747
1748 route->SetVisible(!route->IsVisible());
1749
1750 m_pRouteListCtrl->SetItemImage(clicked_index, route->IsVisible() ? 0 : 1);
1751
1752 ::wxBeginBusyCursor();
1753
1754 NavObj_dB::GetInstance().UpdateRoute(route);
1755
1756 gFrame->RefreshAllCanvas();
1757
1758 // We need to update the waypoint list control since the visibility of
1759 // shared waypoints might have changed.
1760 if (g_pRouteMan->DoesRouteContainSharedPoints(route))
1761 UpdateWptListCtrlViz();
1762
1763 // Manage "show all" checkbox
1764 bool viz = true;
1765 long item = -1;
1766 for (;;) {
1767 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1768 wxLIST_STATE_DONTCARE);
1769 if (item == -1) break;
1770
1771 Route *pR = (Route *)m_pRouteListCtrl->GetItemData(item);
1772
1773 if (!pR->IsVisible()) {
1774 viz = false;
1775 break;
1776 }
1777 }
1778 m_cbShowAllRte->SetValue(viz);
1779
1780 ::wxEndBusyCursor();
1781 }
1782
1783 // Allow wx to process...
1784 event.Skip();
1785}
1786
1787void RouteManagerDialog::OnRteBtnLeftDown(wxMouseEvent &event) {
1788 m_bCtrlDown = event.ControlDown();
1789 event.Skip();
1790}
1791
1792void RouteManagerDialog::OnRteSelected(wxListEvent &event) {
1793 long clicked_index = event.m_itemIndex;
1794 // Process the clicked item
1795 Route *route = (Route *)m_pRouteListCtrl->GetItemData(clicked_index);
1796 // route->SetVisible(!route->IsVisible());
1797 m_pRouteListCtrl->SetItemImage(clicked_index, route->IsVisible() ? 0 : 1);
1798
1799 gFrame->RefreshAllCanvas();
1800
1801 UpdateRteButtons();
1802}
1803
1804void RouteManagerDialog::OnRteColumnClicked(wxListEvent &event) {
1805 if (event.m_col == 1) {
1806 sort_route_name_dir++;
1807
1808 m_pRouteListCtrl->SortItems(SortRoutesOnName, (wxIntPtr)NULL);
1809 } else if (event.m_col == 2) {
1810 sort_route_to_dir++;
1811 m_pRouteListCtrl->SortItems(SortRoutesOnTo, (wxIntPtr)NULL);
1812 }
1813}
1814
1815void RouteManagerDialog::OnRteSendToGPSClick(wxCommandEvent &event) {
1816 long item = -1;
1817 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1818 wxLIST_STATE_SELECTED);
1819 if (item == -1) return;
1820
1821 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1822
1823 if (!route) return;
1824
1825 SendToGpsDlg *pdlg = new SendToGpsDlg();
1826 pdlg->SetRoute(route);
1827
1828 wxFont fo = GetOCPNGUIScaledFont(_("Dialog"));
1829 pdlg->SetFont(fo);
1830
1831 wxString source;
1832 pdlg->Create(NULL, -1, _("Send to GPS") + _T( "..." ), source);
1833
1834#ifdef __WXOSX__
1835 HideWithEffect(wxSHOW_EFFECT_BLEND);
1836#endif
1837
1838 pdlg->ShowModal();
1839
1840#ifdef __WXOSX__
1841 ShowWithEffect(wxSHOW_EFFECT_BLEND);
1842#endif
1843
1844 pdlg->Destroy();
1845}
1846
1847void RouteManagerDialog::OnRteDefaultAction(wxListEvent &event) {
1848 wxCommandEvent evt;
1849 OnRtePropertiesClick(evt);
1850}
1851
1852void RouteManagerDialog::OnTrkDefaultAction(wxListEvent &event) {
1853 wxCommandEvent evt;
1854 OnTrkPropertiesClick(evt);
1855}
1856
1857void RouteManagerDialog::OnTrkRightClick(wxListEvent &event) {
1858 wxMenu menu;
1859 wxMenuItem *mergeItem = menu.Append(TRACK_MERGE, _("&Merge Selected Tracks"));
1860 mergeItem->Enable(m_pTrkListCtrl->GetSelectedItemCount() > 1);
1861 wxMenuItem *cleanItem = menu.Append(TRACK_CLEAN, _("Reduce Data..."));
1862 cleanItem->Enable(m_pTrkListCtrl->GetSelectedItemCount() == 1);
1863 wxMenuItem *copyItem = menu.Append(TRACK_COPY_TEXT, _("&Copy as text"));
1864 copyItem->Enable(m_pTrkListCtrl->GetSelectedItemCount() > 0);
1865 PopupMenu(&menu);
1866}
1867
1868static bool CompareTracks(Track *track1, Track *track2) {
1869 TrackPoint *start1 = track1->GetPoint(0);
1870 TrackPoint *start2 = track2->GetPoint(0);
1871 return start1->GetCreateTime() < start2->GetCreateTime();
1872}
1873
1874void RouteManagerDialog::OnTrkMenuSelected(wxCommandEvent &event) {
1875 int item = -1;
1876
1877 switch (event.GetId()) {
1878 case TRACK_CLEAN: {
1879 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1880 wxLIST_STATE_SELECTED);
1881 if (item == -1) break;
1882 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
1883 if (track->IsRunning()) {
1884 wxBell();
1885 break;
1886 }
1887
1888 const wxString choices[] = {_T("5.0"), _T("10.0"), _T("20.0"), _T("50.0"),
1889 _T("100.0")};
1890
1891 wxSingleChoiceDialog precisionDlg(this,
1892 _("Select the maximum error allowed "
1893 "(in meters)\nafter data reduction:"),
1894 _("Reduce Data Precision"), 5, choices);
1895#ifdef __WXOSX__
1896 precisionDlg.ShowWindowModal();
1897 while (precisionDlg.IsShown()) {
1898 wxMilliSleep(10);
1899 wxYield();
1900 }
1901 int result = precisionDlg.GetReturnCode();
1902#else
1903 int result = precisionDlg.ShowModal();
1904#endif
1905 if (result == wxID_CANCEL) break;
1906 double precision = 5.0;
1907 switch (precisionDlg.GetSelection()) {
1908 case 0:
1909 precision = 5.0;
1910 break;
1911 case 1:
1912 precision = 10.0;
1913 break;
1914 case 2:
1915 precision = 20.0;
1916 break;
1917 case 3:
1918 precision = 50.0;
1919 break;
1920 case 4:
1921 precision = 100.0;
1922 break;
1923 }
1924
1925 int pointsBefore = track->GetnPoints();
1926
1927 int reduction = track->Simplify(precision);
1928 gFrame->Refresh(false);
1929
1930 reduction = 100 * reduction / pointsBefore;
1931 wxString msg = wxString::Format(
1932 _("The amount of data used by the track\n was reduced by %d%%."),
1933 reduction);
1934 OCPNMessageBox(this, msg, _("OpenCPN info"), wxICON_INFORMATION | wxOK);
1935
1936 UpdateTrkListCtrl();
1937 UpdateRouteListCtrl();
1938
1939 break;
1940 }
1941
1942 case TRACK_COPY_TEXT: {
1943 wxString csvString;
1944 while (1) {
1945 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1946 wxLIST_STATE_SELECTED);
1947 if (item == -1) break;
1948 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
1949 csvString << track->GetName() << _T("\t")
1950 << wxString::Format(_T("%.1f"), track->Length()) << _T("\t")
1951 << _T("\n");
1952 }
1953
1954 if (wxTheClipboard->Open()) {
1955 wxTextDataObject *data = new wxTextDataObject;
1956 data->SetText(csvString);
1957 wxTheClipboard->SetData(data);
1958 wxTheClipboard->Close();
1959 }
1960
1961 break;
1962 }
1963
1964 case TRACK_MERGE: {
1965 Track *targetTrack = NULL;
1966 TrackPoint *tPoint;
1967 TrackPoint *newPoint;
1968 TrackPoint *lastPoint;
1969 std::vector<Track *> mergeList;
1970 std::vector<Track *> deleteList;
1971 bool runningSkipped = false;
1972
1973 ::wxBeginBusyCursor();
1974
1975 while (1) {
1976 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1977 wxLIST_STATE_SELECTED);
1978 if (item == -1) break;
1979 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
1980 mergeList.push_back(track);
1981 }
1982
1983 if (!mergeList.size()) {
1984 ::wxEndBusyCursor();
1985 break;
1986 }
1987
1988 std::sort(mergeList.begin(), mergeList.end(), CompareTracks);
1989
1990 targetTrack = mergeList[0];
1991 lastPoint = targetTrack->GetLastPoint();
1992
1993 for (auto const &mergeTrack : mergeList) {
1994 if (mergeTrack == *mergeList.begin()) continue;
1995
1996 if (mergeTrack->IsRunning()) {
1997 runningSkipped = true;
1998 continue;
1999 }
2000
2001 for (int i = 0; i < mergeTrack->GetnPoints(); i++) {
2002 tPoint = mergeTrack->GetPoint(i);
2003 newPoint = new TrackPoint(tPoint->m_lat, tPoint->m_lon,
2004 tPoint->GetCreateTime());
2005
2006 targetTrack->AddPoint(newPoint);
2007 NavObj_dB::GetInstance().AddTrackPoint(targetTrack, newPoint);
2008
2009 pSelect->AddSelectableTrackSegment(lastPoint->m_lat, lastPoint->m_lon,
2010 newPoint->m_lat, newPoint->m_lon,
2011 lastPoint, newPoint, targetTrack);
2012 lastPoint = newPoint;
2013 }
2014 deleteList.push_back(mergeTrack);
2015 }
2016
2017 for (auto const &deleteTrack : deleteList) {
2018 g_pAIS->DeletePersistentTrack(deleteTrack);
2019 NavObj_dB::GetInstance().DeleteTrack(deleteTrack);
2020 RoutemanGui(*g_pRouteMan).DeleteTrack(deleteTrack);
2021 }
2022
2023 mergeList.clear();
2024 deleteList.clear();
2025
2026 ::wxEndBusyCursor();
2027
2028 UpdateTrkListCtrl();
2029 UpdateRouteListCtrl();
2030 gFrame->RefreshAllCanvas();
2031
2032 if (runningSkipped) {
2033 wxMessageDialog skipWarning(
2034 this,
2035 _("The currently running Track was not merged.\nYou can merge it "
2036 "later when it is completed."),
2037 _T("Warning"), wxCANCEL | wxICON_WARNING);
2038 skipWarning.ShowModal();
2039 }
2040
2041 break;
2042 }
2043 }
2044}
2045
2046void RouteManagerDialog::UpdateTrkListCtrl() {
2047 // if an item was selected, make it selected again if it still exist
2048 long item = -1;
2049 item =
2050 m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2051
2052 wxUIntPtr selected_id = wxUIntPtr(0);
2053 if (item != -1) selected_id = m_pTrkListCtrl->GetItemData(item);
2054
2055 // Delete existing items
2056 m_pTrkListCtrl->DeleteAllItems();
2057
2058 // then add tracks to the listctrl
2059 std::vector<Track *>::iterator it;
2060 int index = 0;
2061 int list_index = 0;
2062 bool bpartialViz = false;
2063
2064 for (Track *trk : g_TrackList) {
2065 if (!trk->IsVisible()) bpartialViz = true;
2066
2067 if (!trk->IsListed()) continue;
2068
2069 if (!trk->GetName(true).Upper().Contains(
2070 m_tFilterTrk->GetValue().Upper())) {
2071 continue;
2072 }
2073
2074 wxListItem li;
2075 li.SetId(list_index);
2076 li.SetImage(trk->IsVisible() ? 0 : 1);
2077 li.SetData(trk);
2078 li.SetText(_T(""));
2079
2080 if (g_pActiveTrack == trk) {
2081 wxFont font = *wxNORMAL_FONT;
2082 font.SetWeight(wxFONTWEIGHT_BOLD);
2083 li.SetFont(font);
2084 }
2085 long idx = m_pTrkListCtrl->InsertItem(li);
2086
2087 m_pTrkListCtrl->SetItem(idx, colTRKNAME, trk->GetName(true));
2088 // Populate the track start date/time, formatted using the global timezone
2089 // settings.
2090 m_pTrkListCtrl->SetItem(idx, colTRKDATE, trk->GetDateTime());
2091
2092 wxString len;
2093 len.Printf(wxT("%5.2f"), trk->Length());
2094 m_pTrkListCtrl->SetItem(idx, colTRKLENGTH, len);
2095
2096 wxListItem lic;
2097 lic.SetId(list_index);
2098 lic.SetColumn(1);
2099 lic.SetAlign(wxLIST_FORMAT_LEFT);
2100 m_pTrkListCtrl->SetItem(lic);
2101
2102 lic.SetColumn(2);
2103 lic.SetAlign(wxLIST_FORMAT_LEFT);
2104 m_pTrkListCtrl->SetItem(lic);
2105
2106 list_index++;
2107 }
2108
2109 switch (sort_track_key) {
2110 case SORT_ON_DISTANCE:
2111 m_pTrkListCtrl->SortItems(SortTracksOnDistance, (wxIntPtr)NULL);
2112 break;
2113 case SORT_ON_DATE:
2114 m_pTrkListCtrl->SortItems(SortTracksOnDate, (wxIntPtr)NULL);
2115 break;
2116 case SORT_ON_NAME:
2117 default:
2118 m_pTrkListCtrl->SortItems(SortTracksOnName, (wxIntPtr)NULL);
2119 break;
2120 }
2121
2122 m_pTrkListCtrl->SetColumnWidth(0, 4 * m_charWidth);
2123
2124 // restore selection if possible
2125 // NOTE this will select a different item, if one is deleted
2126 // (the next route will get that index).
2127 if (selected_id != wxUIntPtr(0)) {
2128 item = m_pTrkListCtrl->FindItem(-1, selected_id);
2129 m_pTrkListCtrl->SetItemState(item,
2130 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
2131 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
2132 }
2133
2134 if ((m_lastTrkItem >= 0) && (m_pTrkListCtrl->GetItemCount()))
2135 m_pTrkListCtrl->EnsureVisible(m_lastTrkItem);
2136
2137 m_cbShowAllTrk->SetValue(!bpartialViz);
2138 UpdateTrkButtons();
2139}
2140
2141void RouteManagerDialog::OnTrkSelected(wxListEvent &event) {
2142 UpdateTrkButtons();
2143}
2144
2145void RouteManagerDialog::OnTrkColumnClicked(wxListEvent &event) {
2146 if (event.m_col == 1) {
2147 sort_track_key = SORT_ON_NAME;
2148 sort_track_name_dir++;
2149 m_pTrkListCtrl->SortItems(SortTracksOnName, (wxIntPtr)NULL);
2150 } else if (event.m_col == 2) {
2151 sort_track_key = SORT_ON_DISTANCE;
2152 sort_track_len_dir++;
2153 m_pTrkListCtrl->SortItems(SortTracksOnDistance, (wxIntPtr)NULL);
2154 } else if (event.m_col == 3) {
2155 sort_track_key = SORT_ON_DATE;
2156 sort_track_date_dir++;
2157 m_pTrkListCtrl->SortItems(SortTracksOnDate, (wxIntPtr)NULL);
2158 }
2159}
2160
2161void RouteManagerDialog::UpdateTrkButtons() {
2162 long item = -1;
2163 item =
2164 m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2165 int items = m_pTrkListCtrl->GetSelectedItemCount();
2166
2167 m_lastTrkItem = item;
2168
2169 btnTrkProperties->Enable(items == 1);
2170 btnTrkDelete->Enable(items >= 1);
2171 btnTrkExport->Enable(items >= 1);
2172 btnTrkRouteFromTrack->Enable(items == 1);
2173 btnTrkDeleteAll->Enable(m_pTrkListCtrl->GetItemCount() > 0);
2174 btnTrkSendToPeer->Enable(items >= 1);
2175}
2176
2177void RouteManagerDialog::OnTrkToggleVisibility(wxMouseEvent &event) {
2178 wxPoint pos = event.GetPosition();
2179 int flags = 0;
2180 long clicked_index = m_pTrkListCtrl->HitTest(pos, flags);
2181
2182 // Clicking Visibility column?
2183 if (clicked_index > -1 &&
2184 event.GetX() < m_pTrkListCtrl->GetColumnWidth(colTRKVISIBLE)) {
2185 // Process the clicked item
2186 Track *track = (Track *)m_pTrkListCtrl->GetItemData(clicked_index);
2187 if (track) {
2188 track->SetVisible(!track->IsVisible());
2189 NavObj_dB::GetInstance().UpdateDBTrackAttributes(track);
2190 m_pTrkListCtrl->SetItemImage(clicked_index, track->IsVisible() ? 0 : 1);
2191 }
2192
2193 // Manage "show all" checkbox
2194 bool viz = true;
2195 long item = -1;
2196 for (;;) {
2197 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2198 wxLIST_STATE_DONTCARE);
2199 if (item == -1) break;
2200
2201 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
2202
2203 if (!track->IsVisible()) {
2204 viz = false;
2205 break;
2206 }
2207 }
2208 m_cbShowAllTrk->SetValue(viz);
2209
2210 gFrame->RefreshAllCanvas();
2211 }
2212
2213 // Allow wx to process...
2214 event.Skip();
2215}
2216
2217void RouteManagerDialog::OnTrkNewClick(wxCommandEvent &event) {
2218 gFrame->TrackOff();
2219 gFrame->TrackOn();
2220
2221 UpdateTrkListCtrl();
2222}
2223
2224void RouteManagerDialog::OnTrkPropertiesClick(wxCommandEvent &event) {
2225 // Show trackproperties dialog for selected track
2226 long item = -1;
2227 item =
2228 m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2229 if (item == -1) return;
2230
2231 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
2232
2233 if (!track) return;
2234
2235 pTrackPropDialog = TrackPropDlg::getInstance(GetParent());
2236 pTrackPropDialog->SetTrackAndUpdate(track);
2237
2238 if (!pTrackPropDialog->IsShown()) pTrackPropDialog->Show();
2239 UpdateTrkListCtrl();
2240
2241 m_bNeedConfigFlush = true;
2242}
2243
2244void RouteManagerDialog::OnTrkDeleteClick(wxCommandEvent &event) {
2245 std::vector<Track *> list;
2246
2247 int answer = OCPNMessageBox(
2248 this, _("Are you sure you want to delete the selected object(s)"),
2249 wxString(_("OpenCPN Alert")), wxYES_NO);
2250 if (answer != wxID_YES) return;
2251
2252 bool busy = false;
2253 if (m_pTrkListCtrl->GetSelectedItemCount()) {
2254 ::wxBeginBusyCursor();
2255 // m_bNeedConfigFlush = true;
2256 busy = true;
2257 }
2258
2259 long item = -1;
2260 for (;;) {
2261 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2262 wxLIST_STATE_SELECTED);
2263 if (item == -1) break;
2264
2265 Track *ptrack_to_delete = (Track *)m_pTrkListCtrl->GetItemData(item);
2266
2267 if (ptrack_to_delete) list.push_back(ptrack_to_delete);
2268 }
2269
2270 if (busy) {
2271 for (unsigned int i = 0; i < list.size(); i++) {
2272 Track *track = list.at(i);
2273 if (track) {
2274 g_pAIS->DeletePersistentTrack(track);
2275 NavObj_dB::GetInstance().DeleteTrack(track);
2276 RoutemanGui(*g_pRouteMan).DeleteTrack(track);
2277 }
2278 }
2279
2280 m_lastTrkItem = -1;
2281 // UpdateRouteListCtrl();
2282 UpdateTrkListCtrl();
2283
2284 gFrame->InvalidateAllCanvasUndo();
2285 gFrame->RefreshAllCanvas();
2286 ::wxEndBusyCursor();
2287 }
2288}
2289
2290void RouteManagerDialog::OnTrkExportClick(wxCommandEvent &event) {
2291 std::vector<Track *> list;
2292 wxString suggested_name = _T("tracks");
2293
2294 long item = -1;
2295 for (;;) {
2296 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2297 wxLIST_STATE_SELECTED);
2298 if (item == -1) break;
2299
2300 Track *ptrack_to_export = (Track *)m_pTrkListCtrl->GetItemData(item);
2301
2302 if (ptrack_to_export) {
2303 list.push_back(ptrack_to_export);
2304 if (ptrack_to_export->GetName() != wxEmptyString)
2305 suggested_name = ptrack_to_export->GetName();
2306 }
2307 }
2308
2309 ExportGPXTracks(this, &list, suggested_name);
2310}
2311
2312void RouteManagerDialog::TrackToRoute(Track *track) {
2313 if (!track) return;
2314 if (track->m_bIsInLayer) return;
2315
2316 wxGenericProgressDialog pprog(_("OpenCPN Converting Track to Route...."),
2317 _("Processing Waypoints..."), 101, NULL,
2318 wxPD_AUTO_HIDE | wxPD_SMOOTH |
2319 wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
2320 wxPD_REMAINING_TIME);
2321
2322 ::wxBeginBusyCursor();
2323
2324 Route *route = track->RouteFromTrack(&pprog);
2325
2326 pRouteList->Append(route);
2327
2328 pprog.Update(101, _("Done."));
2329
2330 gFrame->RefreshAllCanvas();
2331
2332 ::wxEndBusyCursor();
2333}
2334
2335void RouteManagerDialog::OnTrkRouteFromTrackClick(wxCommandEvent &event) {
2336 long item = -1;
2337 item =
2338 m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2339 if (item == -1) return;
2340
2341 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
2342
2343 TrackToRoute(track);
2344
2345 UpdateRouteListCtrl();
2346}
2347
2348void RouteManagerDialog::OnTrkDeleteAllClick(wxCommandEvent &event) {
2349 int dialog_ret =
2350 OCPNMessageBox(this, _("Are you sure you want to delete <ALL> tracks?"),
2351 wxString(_("OpenCPN Alert")), wxYES_NO);
2352
2353 if (dialog_ret == wxID_YES) {
2354 RoutemanGui(*g_pRouteMan).DeleteAllTracks();
2355 }
2356
2357 m_lastTrkItem = -1;
2358 m_lastRteItem = -1;
2359
2360 UpdateTrkListCtrl();
2361
2362 // Also need to update the route list control, since routes and tracks
2363 // share a common global list (pRouteList)
2364 UpdateRouteListCtrl();
2365
2366 if (pRoutePropDialog) pRoutePropDialog->Hide();
2367
2368 gFrame->RefreshAllCanvas();
2369
2370 m_bNeedConfigFlush = true;
2371}
2372
2373void RouteManagerDialog::UpdateWptListCtrl(RoutePoint *rp_select,
2374 bool b_retain_sort) {
2375 wxIntPtr selected_id = wxUIntPtr(0);
2376 long item = -1;
2377
2378 if (NULL == rp_select) {
2379 // if an item was selected, make it selected again if it still exists
2380 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2381 wxLIST_STATE_SELECTED);
2382
2383 if (item != -1) selected_id = m_pWptListCtrl->GetItemData(item);
2384 }
2385
2386 // Freshen the image list
2387 m_pWptListCtrl->SetImageList(
2388 pWayPointMan->Getpmarkicon_image_list(m_listIconSize),
2389 wxIMAGE_LIST_SMALL);
2390
2391 m_pWptListCtrl->DeleteAllItems();
2392
2393 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
2394
2395 int index = 0;
2396 bool b_anyHidden = false;
2397 while (node) {
2398 RoutePoint *rp = node->GetData();
2399 if (rp && rp->IsListed()) {
2400 if (rp->m_bIsInRoute && !rp->IsShared()) {
2401 node = node->GetNext();
2402 continue;
2403 }
2404
2405 if (!rp->GetName().Upper().Contains(m_tFilterWpt->GetValue().Upper())) {
2406 node = node->GetNext();
2407 continue;
2408 }
2409
2410 wxListItem li;
2411 li.SetId(index);
2412 li.SetImage(RoutePointGui(*rp).GetIconImageIndex());
2413 li.SetData(rp);
2414 li.SetText(_T(""));
2415 long idx = m_pWptListCtrl->InsertItem(li);
2416
2417 wxString scamin = wxString::Format(_T("%i"), (int)rp->GetScaMin());
2418 if (!rp->GetUseSca()) scamin = _("Always");
2419 if (g_bOverruleScaMin) scamin = _("Overruled");
2420 m_pWptListCtrl->SetItem(idx, colWPTSCALE, scamin);
2421
2422 wxString name = rp->GetName();
2423 if (name.IsEmpty()) name = _("(Unnamed Waypoint)");
2424 m_pWptListCtrl->SetItem(idx, colWPTNAME, name);
2425
2426 double dst;
2427 DistanceBearingMercator(rp->m_lat, rp->m_lon, gLat, gLon, NULL, &dst);
2428 wxString dist;
2429 dist.Printf(_T("%5.2f ") + getUsrDistanceUnit(), toUsrDistance(dst));
2430 m_pWptListCtrl->SetItem(idx, colWPTDIST, dist);
2431
2432 if (rp == rp_select) selected_id = (wxIntPtr)rp_select;
2433
2434 wxListItem lic;
2435 lic.SetId(index);
2436 lic.SetColumn(1);
2437 lic.SetAlign(wxLIST_FORMAT_LEFT);
2438 m_pWptListCtrl->SetItem(lic);
2439
2440 lic.SetColumn(2);
2441 lic.SetAlign(wxLIST_FORMAT_LEFT);
2442 m_pWptListCtrl->SetItem(lic);
2443
2444 if (!rp->IsVisible()) b_anyHidden = true;
2445
2446 index++;
2447 }
2448
2449 node = node->GetNext();
2450 }
2451
2452 if (!b_retain_sort) {
2453 m_pWptListCtrl->SortItems(SortWaypointsOnName,
2454 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2455 sort_wp_key = SORT_ON_NAME;
2456 } else {
2457 switch (sort_wp_key) {
2458 case SORT_ON_NAME:
2459 m_pWptListCtrl->SortItems(SortWaypointsOnName,
2460 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2461 break;
2462 case SORT_ON_DISTANCE:
2463 m_pWptListCtrl->SortItems(SortWaypointsOnDistance,
2464 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2465 break;
2466 }
2467 }
2468
2469 if (selected_id != wxUIntPtr(0)) {
2470 item = m_pWptListCtrl->FindItem(-1, selected_id);
2471 m_pWptListCtrl->SetItemState(item,
2472 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
2473 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
2474 }
2475
2476 if ((m_lastWptItem >= 0) && (m_pWptListCtrl->GetItemCount()))
2477 m_pWptListCtrl->EnsureVisible(m_lastWptItem);
2478
2479 if (pWayPointMan->Getpmarkicon_image_list(m_listIconSize)->GetImageCount()) {
2480 int iwidth, iheight;
2481 pWayPointMan->Getpmarkicon_image_list(m_listIconSize)
2482 ->GetSize(0, iwidth, iheight);
2483
2484 m_pWptListCtrl->SetColumnWidth(0, wxMax(iwidth + 4, 4 * m_charWidth));
2485 }
2486
2487 UpdateWptButtons();
2488
2489 m_cbShowAllWP->SetValue(!b_anyHidden);
2490}
2491
2492void RouteManagerDialog::UpdateWptListCtrlViz() {
2493 long item = -1;
2494 for (;;) {
2495 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2496 wxLIST_STATE_DONTCARE);
2497 if (item == -1) break;
2498
2499 RoutePoint *pRP = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2500 int imageIndex = RoutePointGui(*pRP).GetIconImageIndex();
2501
2502 m_pWptListCtrl->SetItemImage(item, imageIndex);
2503 }
2504}
2505
2506void RouteManagerDialog::OnWptDefaultAction(wxListEvent &event) {
2507 wxCommandEvent evt;
2508 OnWptPropertiesClick(evt);
2509}
2510
2511void RouteManagerDialog::OnWptSelected(wxListEvent &event) {
2512 UpdateWptButtons();
2513}
2514
2515void RouteManagerDialog::OnWptColumnClicked(wxListEvent &event) {
2516 if (event.m_col == NAME_COLUMN) {
2517 sort_wp_name_dir++;
2518 m_pWptListCtrl->SortItems(SortWaypointsOnName,
2519 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2520 sort_wp_key = SORT_ON_NAME;
2521 } else {
2522 if (event.m_col == DISTANCE_COLUMN) {
2523 sort_wp_len_dir++;
2524 m_pWptListCtrl->SortItems(SortWaypointsOnDistance,
2525 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2526 sort_wp_key = SORT_ON_DISTANCE;
2527 }
2528 }
2529 UpdateWptListCtrl();
2530}
2531
2532void RouteManagerDialog::UpdateWptButtons() {
2533 long item = -1;
2534 item =
2535 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2536 bool enable1 = (m_pWptListCtrl->GetSelectedItemCount() == 1);
2537 bool enablemultiple = (m_pWptListCtrl->GetSelectedItemCount() >= 1);
2538
2539 if (enable1)
2540 m_lastWptItem = item;
2541 else
2542 m_lastWptItem = -1;
2543
2544 // Check selection to see if it is in a layer
2545 // If so, disable the "delete" button
2546 bool b_delete_enable = true;
2547 item = -1;
2548 for (;;) {
2549 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2550 wxLIST_STATE_SELECTED);
2551 if (item == -1) break;
2552
2553 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2554
2555 if (wp && wp->m_bIsInLayer) {
2556 b_delete_enable = false;
2557 break;
2558 }
2559 }
2560
2561 btnWptProperties->Enable(enablemultiple);
2562 btnWptZoomto->Enable(enable1);
2563 btnWptDeleteAll->Enable(m_pWptListCtrl->GetItemCount() > 0);
2564 btnWptDelete->Enable(b_delete_enable && enablemultiple);
2565 btnWptGoTo->Enable(enable1);
2566 btnWptExport->Enable(enablemultiple);
2567 btnWptSendToGPS->Enable(enable1);
2568 btnWptSendToPeer->Enable(enablemultiple);
2569}
2570
2571void RouteManagerDialog::OnWptToggleVisibility(wxMouseEvent &event) {
2572 wxPoint pos = event.GetPosition();
2573 int flags = 0;
2574 long clicked_index = m_pWptListCtrl->HitTest(pos, flags);
2575
2576 // Clicking Visibility column?
2577 if (clicked_index > -1 &&
2578 event.GetX() < m_pWptListCtrl->GetColumnWidth(colTRKVISIBLE)) {
2579 // Process the clicked item
2580 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(clicked_index);
2581
2582 if (!wp->IsSharedInVisibleRoute()) {
2583 wp->SetVisible(!wp->IsVisible());
2584 m_pWptListCtrl->SetItemImage(clicked_index,
2585 RoutePointGui(*wp).GetIconImageIndex());
2586
2587 NavObj_dB::GetInstance().UpdateRoutePoint(wp);
2588 }
2589
2590 // Manage "show all" checkbox
2591 bool viz = true;
2592 long item = -1;
2593 for (;;) {
2594 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2595 wxLIST_STATE_DONTCARE);
2596 if (item == -1) break;
2597
2598 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2599
2600 if (!wp->IsVisible()) {
2601 viz = false;
2602 break;
2603 }
2604 }
2605 m_cbShowAllWP->SetValue(viz);
2606
2607 gFrame->RefreshAllCanvas();
2608 } else // clicked on ScaMin column??
2609 if (clicked_index > -1 &&
2610 event.GetX() > m_pWptListCtrl->GetColumnWidth(colTRKVISIBLE) &&
2611 event.GetX() < (m_pWptListCtrl->GetColumnWidth(colTRKVISIBLE) +
2612 m_pWptListCtrl->GetColumnWidth(colWPTSCALE)) &&
2613 !g_bOverruleScaMin) {
2614 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(clicked_index);
2615 wp->SetUseSca(!wp->GetUseSca());
2616 NavObj_dB::GetInstance().UpdateRoutePoint(wp);
2617 gFrame->RefreshAllCanvas();
2618 wxString scamin = wxString::Format(_T("%i"), (int)wp->GetScaMin());
2619 if (!wp->GetUseSca()) scamin = _("Always");
2620 m_pWptListCtrl->SetItem(clicked_index, colWPTSCALE, scamin);
2621 }
2622
2623 // Allow wx to process...
2624 event.Skip();
2625}
2626
2627void RouteManagerDialog::OnWptNewClick(wxCommandEvent &event) {
2628 RoutePoint *pWP = new RoutePoint(gLat, gLon, g_default_wp_icon, wxEmptyString,
2629 wxEmptyString);
2630 pWP->m_bIsolatedMark = true; // This is an isolated mark
2631 pSelect->AddSelectableRoutePoint(gLat, gLon, pWP);
2632 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
2633
2634 gFrame->RefreshAllCanvas();
2635
2636 // g_pMarkInfoDialog = MarkInfoImpl::GetInstance( GetParent() );
2637 // There is on global instance of the MarkProp Dialog
2638 if (!g_pMarkInfoDialog) g_pMarkInfoDialog = new MarkInfoDlg(GetParent());
2639
2640 WptShowPropertiesDialog(pWP, GetParent());
2641}
2642
2643void RouteManagerDialog::OnWptPropertiesClick(wxCommandEvent &event) {
2644 long item = wxNOT_FOUND;
2645 item =
2646 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2647 if (item == wxNOT_FOUND) return;
2648
2649 auto pWP = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2650 WptShowPropertiesDialog(pWP, GetParent());
2651
2652 UpdateWptListCtrl();
2653 m_bNeedConfigFlush = true;
2654}
2655
2656void RouteManagerDialog::WptShowPropertiesDialog(RoutePoint *pWP,
2657 wxWindow *parent) {
2658 if (!g_pMarkInfoDialog) // There is one global instance of the MarkProp
2659 // Dialog
2660 g_pMarkInfoDialog = new MarkInfoDlg(parent);
2661
2662 g_pMarkInfoDialog->SetRoutePoint(pWP);
2663 g_pMarkInfoDialog->UpdateProperties();
2664
2665 wxString base_title = _("Waypoint Properties");
2666
2667 if (pWP->m_bIsInLayer) {
2668 wxString caption(wxString::Format(_T("%s, %s: %s"), base_title, _("Layer"),
2669 GetLayerName(pWP->m_LayerID)));
2670 g_pMarkInfoDialog->SetDialogTitle(caption);
2671 } else {
2672 g_pMarkInfoDialog->SetDialogTitle(base_title);
2673 }
2674
2675 if (!g_pMarkInfoDialog->IsShown()) g_pMarkInfoDialog->Show();
2676 g_pMarkInfoDialog->Raise();
2677}
2678
2679void RouteManagerDialog::OnWptZoomtoClick(wxCommandEvent &event) {
2680 long item = -1;
2681 item =
2682 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2683 if (item == -1) return;
2684
2685 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2686
2687 if (!wp) return;
2688
2689 if (gFrame->GetFocusCanvas()) {
2690 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), wp->m_lat, wp->m_lon,
2691 gFrame->GetFocusCanvas()->GetVPScale());
2692 }
2693}
2694
2695void RouteManagerDialog::OnWptDeleteClick(wxCommandEvent &event) {
2696 RoutePointList list;
2697
2698 int answer = OCPNMessageBox(
2699 this, _("Are you sure you want to delete the selected object(s)"),
2700 wxString(_("OpenCPN Alert")), wxYES_NO);
2701 if (answer != wxID_YES) return;
2702
2703 bool busy = false;
2704 if (m_pWptListCtrl->GetSelectedItemCount()) {
2705 ::wxBeginBusyCursor();
2706 m_bNeedConfigFlush = true;
2707 busy = true;
2708 }
2709
2710 long item = -1;
2711 long item_last_selected = -1;
2712 for (;;) {
2713 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2714 wxLIST_STATE_SELECTED);
2715 if (item == -1) break;
2716
2717 item_last_selected = item;
2718 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2719
2720 if (wp && !wp->m_bIsInLayer) list.Append(wp);
2721 }
2722
2723 if (busy) {
2724 for (unsigned int i = 0; i < list.GetCount(); i++) {
2725 RoutePoint *wp = list.Item(i)->GetData();
2726 if (wp) {
2727 if (wp->m_bIsInRoute) {
2728 if (wxID_YES ==
2729 OCPNMessageBox(this,
2730 _("The waypoint you want to delete is used in a "
2731 "route, do you really want to delete it?"),
2732 _("OpenCPN Alert"), wxYES_NO)) {
2733 NavObj_dB::GetInstance().DeleteRoutePoint(wp);
2734 pWayPointMan->DestroyWaypoint(wp);
2735 }
2736 } else {
2737 NavObj_dB::GetInstance().DeleteRoutePoint(wp);
2738 pWayPointMan->DestroyWaypoint(wp);
2739 }
2740 }
2741 }
2742
2743 long item_next =
2744 m_pWptListCtrl->GetNextItem(item_last_selected); // next in list
2745 RoutePoint *wp_next = NULL;
2746 if (item_next > -1)
2747 wp_next = (RoutePoint *)m_pWptListCtrl->GetItemData(item_next);
2748
2749 m_lastWptItem = item_next;
2750
2751 UpdateRouteListCtrl();
2752 UpdateTrkListCtrl();
2753 UpdateWptListCtrl(wp_next, true);
2754
2755 if (g_pMarkInfoDialog) {
2756 g_pMarkInfoDialog->ClearData();
2757 }
2758
2759 gFrame->InvalidateAllCanvasUndo();
2760 gFrame->RefreshAllCanvas();
2761 ::wxEndBusyCursor();
2762 }
2763}
2764
2765void RouteManagerDialog::OnWptGoToClick(wxCommandEvent &event) {
2766 long item = -1;
2767 item =
2768 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2769 if (item == -1) return;
2770
2771 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2772
2773 if (!wp) return;
2774
2775 RoutePoint *pWP_src = new RoutePoint(gLat, gLon, g_default_wp_icon,
2776 wxEmptyString, wxEmptyString);
2777 pSelect->AddSelectableRoutePoint(gLat, gLon, pWP_src);
2778
2779 Route *temp_route = new Route();
2780 pRouteList->Append(temp_route);
2781
2782 temp_route->AddPoint(pWP_src);
2783 temp_route->AddPoint(wp);
2784
2785 pSelect->AddSelectableRouteSegment(gLat, gLon, wp->m_lat, wp->m_lon, pWP_src,
2786 wp, temp_route);
2787
2788 wxString name = wp->GetName();
2789 if (name.IsEmpty()) name = _("(Unnamed Waypoint)");
2790 wxString rteName = _("Go to ");
2791 rteName.Append(name);
2792 temp_route->m_RouteNameString = rteName;
2793 temp_route->m_RouteStartString = _("Here");
2794
2795 temp_route->m_RouteEndString = name;
2796 temp_route->m_bDeleteOnArrival = true;
2797
2798 if (g_pRouteMan->GetpActiveRoute()) g_pRouteMan->DeactivateRoute();
2799
2800 g_pRouteMan->ActivateRoute(temp_route, wp);
2801
2802 UpdateRouteListCtrl();
2803}
2804
2805void RouteManagerDialog::OnWptExportClick(wxCommandEvent &event) {
2806 RoutePointList list;
2807
2808 wxString suggested_name = _T("waypoints");
2809
2810 long item = -1;
2811 for (;;) {
2812 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2813 wxLIST_STATE_SELECTED);
2814 if (item == -1) break;
2815
2816 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2817
2818 if (wp && !wp->m_bIsInLayer) {
2819 list.Append(wp);
2820 if (wp->GetName() != wxEmptyString) suggested_name = wp->GetName();
2821 }
2822 }
2823
2824 ExportGPXWaypoints(this, &list, suggested_name);
2825}
2826
2827void RouteManagerDialog::OnWptSendToGPSClick(wxCommandEvent &event) {
2828 long item = -1;
2829 item =
2830 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2831 if (item == -1) return;
2832
2833 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2834
2835 if (!wp) return;
2836
2837 SendToGpsDlg *pdlg = new SendToGpsDlg();
2838 pdlg->SetWaypoint(wp);
2839
2840 wxString source;
2841 pdlg->Create(NULL, -1, _("Send to GPS") + _T( "..." ), source);
2842
2843#ifdef __WXOSX__
2844 HideWithEffect(wxSHOW_EFFECT_BLEND);
2845#endif
2846 pdlg->ShowModal();
2847#ifdef __WXOSX__
2848 ShowWithEffect(wxSHOW_EFFECT_BLEND);
2849#endif
2850
2851 delete pdlg;
2852}
2853
2854void RouteManagerDialog::OnWptDeleteAllClick(wxCommandEvent &event) {
2855 wxString prompt;
2856 int buttons, type;
2857 if (!pWayPointMan->SharedWptsExist()) {
2858 prompt = _("Are you sure you want to delete <ALL> waypoints?");
2859 buttons = wxYES_NO;
2860 type = 1;
2861 } else {
2862 prompt =
2863 _("There are some waypoints used in routes or anchor alarms.\n Do you "
2864 "want to delete them as well?\n This will change the routes and "
2865 "disable the anchor alarms.\n Answering No keeps the waypoints used "
2866 "in routes or alarms.");
2867 buttons = wxYES_NO | wxCANCEL;
2868 type = 2;
2869 }
2870 int answer =
2871 OCPNMessageBox(this, prompt, wxString(_("OpenCPN Alert")), buttons);
2872 if (answer == wxID_YES) pWayPointMan->DeleteAllWaypoints(true);
2873 if (answer == wxID_NO && type == 2)
2874 pWayPointMan->DeleteAllWaypoints(false); // only delete unused waypoints
2875
2876 if (g_pMarkInfoDialog) {
2877 g_pMarkInfoDialog->ClearData();
2878 }
2879
2880 m_lastWptItem = -1;
2881 UpdateRouteListCtrl();
2882 UpdateWptListCtrl();
2883 gFrame->InvalidateAllCanvasUndo();
2884 gFrame->RefreshAllCanvas();
2885}
2886
2887void RouteManagerDialog::OnLaySelected(wxListEvent &event) {
2888 UpdateLayButtons();
2889}
2890
2891void RouteManagerDialog::OnLayColumnClicked(wxListEvent &event) {
2892 if (event.m_col == 1) {
2893 sort_layer_name_dir++;
2894 m_pLayListCtrl->SortItems(SortLayersOnName, (wxIntPtr)NULL);
2895 } else if (event.m_col == 2) {
2896 sort_layer_len_dir++;
2897 m_pLayListCtrl->SortItems(SortLayersOnSize, (wxIntPtr)NULL);
2898 }
2899}
2900
2901void RouteManagerDialog::UpdateLayButtons() {
2902 long item = -1;
2903 item =
2904 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2905 bool enable = (item != -1);
2906
2907 // btnLayProperties->Enable(false);
2908 btnLayDelete->Enable(enable);
2909 cbLayToggleChart->Enable(enable);
2910 cbLayToggleListing->Enable(enable);
2911 cbLayToggleNames->Enable(enable);
2912
2913 if (item >= 0) {
2914 cbLayToggleChart->SetValue(
2915 ((Layer *)m_pLayListCtrl->GetItemData(item))->IsVisibleOnChart());
2916
2917 cbLayToggleNames->Set3StateValue(
2918 ((Layer *)m_pLayListCtrl->GetItemData(item))->HasVisibleNames());
2919
2920 cbLayToggleListing->SetValue(
2921 ((Layer *)m_pLayListCtrl->GetItemData(item))->IsVisibleOnListing());
2922
2923 } else {
2924 cbLayToggleChart->SetValue(true);
2925 cbLayToggleNames->Set3StateValue(wxCHK_UNDETERMINED);
2926 cbLayToggleListing->SetValue(true);
2927 }
2928}
2929
2930void RouteManagerDialog::OnLayToggleVisibility(wxMouseEvent &event) {
2931 wxPoint pos = event.GetPosition();
2932 int flags = 0;
2933 long clicked_index = m_pLayListCtrl->HitTest(pos, flags);
2934
2935 // Clicking Visibility column?
2936 if (clicked_index > -1 &&
2937 event.GetX() < m_pLayListCtrl->GetColumnWidth(colLAYVISIBLE)) {
2938 // Process the clicked item
2939 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(clicked_index);
2940
2941 layer->SetVisibleOnChart(!layer->IsVisibleOnChart());
2942 m_pLayListCtrl->SetItemImage(clicked_index,
2943 layer->IsVisibleOnChart() ? 0 : 1);
2944
2945 // Manage "show all" checkbox
2946 bool viz = true;
2947 long item = -1;
2948 for (;;) {
2949 item = m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2950 wxLIST_STATE_DONTCARE);
2951 if (item == -1) break;
2952
2953 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
2954
2955 if (!layer->IsVisibleOnChart()) {
2956 viz = false;
2957 break;
2958 }
2959 }
2960 m_cbShowAllLay->SetValue(viz);
2961
2962 ToggleLayerContentsOnChart(layer);
2963 }
2964
2965 // Allow wx to process...
2966 event.Skip();
2967}
2968
2969void RouteManagerDialog::UpdateLists() {
2970 UpdateRouteListCtrl();
2971 UpdateTrkListCtrl();
2972 UpdateWptListCtrl();
2973 UpdateLayListCtrl();
2974}
2975
2976void RouteManagerDialog::OnLayNewClick(wxCommandEvent &event) {
2977 AddNewLayer(false); // Temporary layer
2978}
2979
2980void RouteManagerDialog::OnPerLayNewClick(wxCommandEvent &event) {
2981 AddNewLayer(true); // Persistent layer
2982}
2983
2984void RouteManagerDialog::AddNewLayer(bool isPersistent) {
2985 bool show_flag = g_bShowLayers;
2986 g_bShowLayers = true;
2987
2988 UI_ImportGPX(this, true, _T(""), true, isPersistent);
2989
2990 g_bShowLayers = show_flag;
2991 UpdateLists();
2992 gFrame->RefreshAllCanvas();
2993}
2994
2995void RouteManagerDialog::OnLayPropertiesClick(wxCommandEvent &event) {
2996 // Show layer properties dialog for selected layer - todo
2997 long item = -1;
2998 item =
2999 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3000 if (item == -1) return;
3001}
3002
3003void RouteManagerDialog::OnLayDeleteClick(wxCommandEvent &event) {
3004 long item = -1;
3005 item =
3006 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3007 if (item == -1) return;
3008
3009 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
3010
3011 if (!layer) return;
3012 // Check if this file is a persistent layer.
3013 // If added in this session the listctrl file path is origin dir and not yet
3014 // /layers
3015 bool ispers = false;
3016 wxString destf, f, name, ext;
3017 f = layer->m_LayerFileName;
3018 wxFileName::SplitPath(f, NULL, NULL, &name, &ext);
3019 destf = g_Platform->GetPrivateDataDir();
3020 appendOSDirSlash(&destf);
3021 destf.Append(_T("layers"));
3022 appendOSDirSlash(&destf);
3023 destf << name << _T(".") << ext;
3024
3025 wxString prompt = _(
3026 "Are you sure you want to delete this layer and <ALL> of its contents?");
3027 if (wxFileExists(destf)) {
3028 prompt.Append(_T("\n"));
3029 prompt.Append(
3030 _("The file will also be deleted from OpenCPN's layer directory."));
3031 prompt.Append(_T("\n (") + destf + _T(")" ));
3032 ispers = true;
3033 }
3034 int answer =
3035 OCPNMessageBox(this, prompt, wxString(_("OpenCPN Alert")), wxYES_NO);
3036 if (answer == wxID_NO) return;
3037
3038 // Delete a persistent layer file if present
3039 if (ispers) {
3040 wxString remMSG;
3041 if (wxRemoveFile(destf))
3042 remMSG.sprintf(_T("Layer file: %s is deleted"), destf);
3043 else
3044 remMSG.sprintf(_T("Error deleting Layer file: %s"), destf);
3045
3046 wxLogMessage(remMSG);
3047 }
3048
3049 // Process Tracks and Routes in this layer
3050 wxRouteListNode *node1 = pRouteList->GetFirst();
3051 while (node1) {
3052 Route *pRoute = node1->GetData();
3053 wxRouteListNode *next_node = node1->GetNext();
3054 if (pRoute->m_bIsInLayer && (pRoute->m_LayerID == layer->m_LayerID)) {
3055 pRoute->m_bIsInLayer = false;
3056 pRoute->m_LayerID = 0;
3057 g_pRouteMan->DeleteRoute(pRoute);
3058 }
3059 node1 = next_node;
3060 }
3061
3062 for (Track *pTrack : g_TrackList) {
3063 if (pTrack->m_bIsInLayer && (pTrack->m_LayerID == layer->m_LayerID)) {
3064 pTrack->m_bIsInLayer = false;
3065 pTrack->m_LayerID = 0;
3066 NavObj_dB::GetInstance().DeleteTrack(pTrack);
3067 RoutemanGui(*g_pRouteMan).DeleteTrack(pTrack);
3068 }
3069 }
3070
3071 // Process waypoints in this layer
3072 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
3073 wxRoutePointListNode *node3;
3074
3075 while (node) {
3076 node3 = node->GetNext();
3077 RoutePoint *rp = node->GetData();
3078 if (rp && (rp->m_LayerID == layer->m_LayerID)) {
3079 rp->m_bIsInLayer = false;
3080 rp->m_LayerID = 0;
3081 pWayPointMan->DestroyWaypoint(
3082 rp, false); // no need to update the change set on layer ops
3083 }
3084
3085 node = node3;
3086 node3 = NULL;
3087 }
3088
3089 if (g_pMarkInfoDialog) {
3090 g_pMarkInfoDialog->ClearData();
3091 }
3092
3093 pLayerList->DeleteObject(layer);
3094
3095 UpdateLists();
3096
3097 gFrame->RefreshAllCanvas();
3098
3099 m_bNeedConfigFlush = false;
3100}
3101
3102void RouteManagerDialog::OnLayToggleChartClick(wxCommandEvent &event) {
3103 // Toggle visibility on chart for selected layer
3104 long item = -1;
3105 item =
3106 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3107 if (item == -1) return;
3108
3109 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
3110
3111 if (!layer) return;
3112
3113 layer->SetVisibleOnChart(!layer->IsVisibleOnChart());
3114 m_pLayListCtrl->SetItemImage(item, layer->IsVisibleOnChart() ? 0 : 1);
3115
3116 ToggleLayerContentsOnChart(layer);
3117}
3118
3119void RouteManagerDialog::ToggleLayerContentsOnChart(Layer *layer) {
3120 // Process Tracks and Routes in this layer
3121 wxRouteListNode *node1 = pRouteList->GetFirst();
3122 while (node1) {
3123 Route *pRoute = node1->GetData();
3124 if (pRoute->m_bIsInLayer && (pRoute->m_LayerID == layer->m_LayerID)) {
3125 pRoute->SetVisible(layer->IsVisibleOnChart());
3126 }
3127 node1 = node1->GetNext();
3128 }
3129
3130 for (Track *pTrack : g_TrackList) {
3131 if (pTrack->m_bIsInLayer && (pTrack->m_LayerID == layer->m_LayerID)) {
3132 pTrack->SetVisible(layer->IsVisibleOnChart());
3133 NavObj_dB::GetInstance().UpdateDBTrackAttributes(pTrack);
3134 }
3135 }
3136
3137 // Process waypoints in this layer
3138 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
3139
3140 while (node) {
3141 RoutePoint *rp = node->GetData();
3142 if (rp && (rp->m_LayerID == layer->m_LayerID)) {
3143 rp->SetVisible(layer->IsVisibleOnChart());
3144 }
3145
3146 node = node->GetNext();
3147 }
3148 UpdateLists();
3149
3150 UpdateLayButtons();
3151
3152 gFrame->RefreshAllCanvas();
3153}
3154
3155void RouteManagerDialog::OnLayToggleNamesClick(wxCommandEvent &event) {
3156 // Toggle WPT names visibility on chart for selected layer
3157 long item = -1;
3158 item =
3159 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3160 if (item == -1) return;
3161
3162 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
3163
3164 if (!layer) return;
3165
3166 layer->SetVisibleNames(cbLayToggleNames->Get3StateValue());
3167
3168 ToggleLayerContentsNames(layer);
3169}
3170
3171void RouteManagerDialog::ToggleLayerContentsNames(Layer *layer) {
3172 // Process Tracks and Routes in this layer
3173 wxRouteListNode *node1 = pRouteList->GetFirst();
3174 while (node1) {
3175 Route *pRoute = node1->GetData();
3176 if (pRoute->m_bIsInLayer && (pRoute->m_LayerID == layer->m_LayerID)) {
3177 wxRoutePointListNode *node = pRoute->pRoutePointList->GetFirst();
3178 RoutePoint *prp1 = node->GetData();
3179 while (node) {
3180 if (layer->HasVisibleNames() == wxCHK_UNDETERMINED) {
3181 prp1->m_bShowName = prp1->m_bShowNameData;
3182 } else {
3183 prp1->m_bShowName = (layer->HasVisibleNames() == wxCHK_CHECKED);
3184 }
3185 node = node->GetNext();
3186 }
3187 }
3188 node1 = node1->GetNext();
3189 }
3190
3191 // Process waypoints in this layer
3192 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
3193
3194 while (node) {
3195 RoutePoint *rp = node->GetData();
3196 if (rp && (rp->m_LayerID == layer->m_LayerID)) {
3197 rp->SetNameShown(layer->HasVisibleNames() == wxCHK_CHECKED ||
3198 (rp->m_bShowNameData &&
3199 layer->HasVisibleNames() == wxCHK_UNDETERMINED));
3200 }
3201
3202 node = node->GetNext();
3203 }
3204
3205 UpdateLayButtons();
3206
3207 gFrame->RefreshAllCanvas();
3208}
3209
3210void RouteManagerDialog::OnLayToggleListingClick(wxCommandEvent &event) {
3211 // Toggle visibility on listing for selected layer
3212 long item = -1;
3213 item =
3214 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3215 if (item == -1) return;
3216
3217 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
3218
3219 if (!layer) return;
3220
3221 layer->SetVisibleOnListing(!layer->IsVisibleOnListing());
3222
3223 ToggleLayerContentsOnListing(layer);
3224}
3225
3226void RouteManagerDialog::ToggleLayerContentsOnListing(Layer *layer) {
3227 ::wxBeginBusyCursor();
3228
3229 // Process Tracks and Routes in this layer
3230 wxRouteListNode *node1 = pRouteList->GetFirst();
3231 while (node1) {
3232 Route *pRoute = node1->GetData();
3233 if (pRoute->m_bIsInLayer && (pRoute->m_LayerID == layer->m_LayerID)) {
3234 pRoute->SetListed(layer->IsVisibleOnListing());
3235 }
3236 node1 = node1->GetNext();
3237 }
3238
3239 for (Track *pTrack : g_TrackList) {
3240 if (pTrack->m_bIsInLayer && (pTrack->m_LayerID == layer->m_LayerID))
3241 pTrack->SetListed(layer->IsVisibleOnListing());
3242 }
3243
3244 // Process waypoints in this layer
3245 // n.b. If the waypoint belongs to a track, and is not shared, then do not
3246 // list it. This is a performance optimization, allowing large track support.
3247
3248 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
3249
3250 while (node) {
3251 RoutePoint *rp = node->GetData();
3252 if (rp && rp->m_bIsolatedMark && (rp->m_LayerID == layer->m_LayerID)) {
3253 rp->SetListed(layer->IsVisibleOnListing());
3254 }
3255
3256 node = node->GetNext();
3257 }
3258
3259 UpdateLists();
3260
3261 ::wxEndBusyCursor();
3262
3263 gFrame->RefreshAllCanvas();
3264}
3265
3266void RouteManagerDialog::OnLayDefaultAction(wxListEvent &event) {
3267 wxCommandEvent evt;
3268 OnLayPropertiesClick(evt);
3269}
3270
3271void RouteManagerDialog::UpdateLayListCtrl() {
3272 // if an item was selected, make it selected again if it still exist
3273 long item = -1;
3274 item =
3275 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3276
3277 wxUIntPtr selected_id = wxUIntPtr(0);
3278 if (item != -1) selected_id = m_pLayListCtrl->GetItemData(item);
3279
3280 // Delete existing items
3281 m_pLayListCtrl->DeleteAllItems();
3282
3283 // then add routes to the listctrl
3284 LayerList::iterator it;
3285 int index = 0;
3286 bool b_anyHidden = false;
3287 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
3288 Layer *lay = (Layer *)(*it);
3289
3290 if (!lay->m_LayerName.Upper().Contains(m_tFilterLay->GetValue().Upper())) {
3291 continue;
3292 }
3293
3294 wxListItem li;
3295 li.SetId(index);
3296 li.SetImage(lay->IsVisibleOnChart() ? 0 : 1);
3297 li.SetData(lay);
3298 li.SetText(_T(""));
3299
3300 long idx = m_pLayListCtrl->InsertItem(li);
3301
3302 wxString name = lay->m_LayerName;
3303 if (name.IsEmpty()) {
3304 // RoutePoint *rp = trk->GetPoint(1);
3305 // if (rp)
3306 // name = rp->m_CreateTime.FormatISODate() + _T(" ") +
3307 // rp->m_CreateTime.FormatISOTime(); //name =
3308 // rp->m_CreateTime.Format();
3309 // else
3310 name = _("(Unnamed Layer)");
3311 }
3312 m_pLayListCtrl->SetItem(idx, colLAYNAME, name);
3313
3314 wxString len;
3315 len.Printf(wxT("%d"), (int)lay->m_NoOfItems);
3316 m_pLayListCtrl->SetItem(idx, colLAYITEMS, len);
3317 m_pLayListCtrl->SetItem(idx, colLAYPERSIST, lay->m_LayerType);
3318
3319 wxListItem lic;
3320 lic.SetId(index);
3321 lic.SetColumn(1);
3322 lic.SetAlign(wxLIST_FORMAT_LEFT);
3323 m_pLayListCtrl->SetItem(lic);
3324
3325 lic.SetColumn(2);
3326 lic.SetAlign(wxLIST_FORMAT_LEFT);
3327 m_pLayListCtrl->SetItem(lic);
3328
3329 if (!lay->IsVisibleOnChart()) b_anyHidden = true;
3330 }
3331
3332 m_pLayListCtrl->SortItems(SortLayersOnName,
3333 reinterpret_cast<wxIntPtr>(m_pLayListCtrl));
3334 m_pLayListCtrl->SetColumnWidth(0, 4 * m_charWidth);
3335
3336 // restore selection if possible
3337 // NOTE this will select a different item, if one is deleted
3338 // (the next route will get that index).
3339 if (selected_id != wxUIntPtr(0)) {
3340 item = m_pLayListCtrl->FindItem(-1, selected_id);
3341 m_pLayListCtrl->SetItemState(item,
3342 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
3343 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
3344 }
3345 UpdateLayButtons();
3346
3347 m_cbShowAllLay->SetValue(!b_anyHidden);
3348}
3349
3350void RouteManagerDialog::OnImportClick(wxCommandEvent &event) {
3351 // Import routes
3352 // FIXME there is no way to instruct this function about what to import.
3353 // Suggest to add that!
3354
3355 UI_ImportGPX(this);
3356
3357 UpdateLists();
3358
3359 gFrame->RefreshAllCanvas();
3360}
3361void RouteManagerDialog::OnExportClick(wxCommandEvent &event) {
3362 ExportGPX(this);
3363}
3364
3365void RouteManagerDialog::OnExportVizClick(wxCommandEvent &event) {
3366 ExportGPX(this, true, true); // only visible objects, layers included
3367}
3368
3369void RouteManagerDialog::OnFilterChanged(wxCommandEvent &event) {
3370 if (event.GetEventObject() == m_tFilterWpt) {
3371 UpdateWptListCtrl(NULL, true);
3372 } else if (event.GetEventObject() == m_tFilterRte) {
3373 UpdateRouteListCtrl();
3374 } else if (event.GetEventObject() == m_tFilterTrk) {
3375 UpdateTrkListCtrl();
3376 } else if (event.GetEventObject() == m_tFilterLay) {
3377 UpdateLayListCtrl();
3378 }
3379}
3380
3381// END Event handlers
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
Represents an active track that is currently being recorded.
Definition track.h:221
Represents a layer of chart objects in OpenCPN.
Definition Layer.h:38
Dialog for displaying and editing waypoint properties.
Definition MarkInfo.h:212
void Validate()
Check that all entries are accessible, remove stale ones.
Main application frame.
Definition ocpn_frame.h:136
Provides platform-specific support utilities for OpenCPN.
void Init(const KeyProvider &kp, std::function< void(ObservedEvt &ev)> action)
Initiate an object yet not listening.
Definition observable.h:255
Represents a waypoint or mark within the navigation system.
Definition route_point.h:70
bool m_bIsolatedMark
Flag indicating if the waypoint is a standalone mark.
bool m_bShowNameData
Flag indicating if waypoint data should be shown with the name.
bool m_bIsInRoute
Flag indicating if this waypoint is part of a route.
bool m_bShowName
Flag indicating if the waypoint name should be shown.
bool m_bIsInLayer
Flag indicating if the waypoint belongs to a layer.
int m_LayerID
Layer identifier if the waypoint belongs to a layer.
Represents a navigational route in the navigation system.
Definition route.h:98
wxString m_RouteStartString
Name or description of the route's starting point.
Definition route.h:251
RoutePointList * pRoutePointList
Ordered list of waypoints (RoutePoints) that make up this route.
Definition route.h:335
bool m_bRtIsActive
Flag indicating whether this route is currently active for navigation.
Definition route.h:207
bool m_bDeleteOnArrival
Flag indicating whether the route should be deleted once navigation reaches the end.
Definition route.h:267
wxString m_RouteEndString
Name or description of the route's ending point.
Definition route.h:256
wxString m_RouteNameString
User-assigned name for the route.
Definition route.h:246
bool m_bIsInLayer
Flag indicating whether this route belongs to a layer.
Definition route.h:277
int m_LayerID
Identifier of the layer containing this route.
Definition route.h:282
bool DeleteRoute(Route *pRoute)
Definition routeman.cpp:856
EventVar on_routes_update
Notified when list of routes is updated (no data in event)
Definition routeman.h:269
bool ActivateRoute(Route *pRouteToActivate, RoutePoint *pStartPoint=NULL)
Activates a route for navigation.
Definition routeman.cpp:279
Dialog for sending routes/waypoints to a GPS device.
Dialog for sending navigation objects to peer devices.
Represents a single point in a track.
Definition track.h:53
wxDateTime GetCreateTime(void)
Retrieves the creation timestamp of a track point as a wxDateTime object.
Definition track.cpp:140
Class TrackPropDlg.
Represents a track, which is a series of connected track points.
Definition track.h:111
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
Definition gui_lib.cpp:54
wxFont GetOCPNGUIScaledFont(wxString item)
Retrieves a font optimized for touch and high-resolution interfaces.
Definition gui_lib.cpp:83
MdnsCache mDNS host lookups cache.
mDNS lookup wrappers.
Class NavObj_dB.