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