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