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_platform.h"
72#include "routeman_gui.h"
73#include "route_gui.h"
74#include "route_point_gui.h"
75#include "route_prop_dlg_impl.h"
76#include "send_to_gps_dlg.h"
77#include "send_to_peer_dlg.h"
78#include "styles.h"
79#include "top_frame.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 top_frame::Get()->Raise();
1134#endif
1135 Hide();
1136 // pRouteManagerDialog = NULL;
1137}
1138
1139void RouteManagerDialog::OnOK(wxCommandEvent &event) {
1140#ifdef __WXGTK__
1141 top_frame::Get()->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 top_frame::Get()->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 top_frame::Get()->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 top_frame::Get()->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 top_frame::Get()->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 (top_frame::Get()->GetFocusCanvasSize() != wxSize(0, 0)) {
1402 wxSize size = top_frame::Get()->GetFocusCanvasSize();
1403 ww = size.GetWidth();
1404 wh = size.GetHeight();
1405 ppm = wxMin(ww / (rw * 1852), wh / (rh * 1852)) * (100 - fabs(clat)) / 90;
1406 ppm = wxMin(ppm, 1.0);
1407
1408 top_frame::Get()->JumpToPosition(clat, clon, ppm);
1409 }
1410
1411 m_bNeedConfigFlush = true;
1412}
1413
1414// BEGIN Event handlers
1415void RouteManagerDialog::OnRteDeleteClick(wxCommandEvent &event) {
1416 int count = m_pRouteListCtrl->GetSelectedItemCount();
1417 bool confirmed = RouteGui::OnDelete(this, count);
1418
1419 if (confirmed && count > 0) {
1420 ::wxBeginBusyCursor();
1421 RouteList list;
1422
1423 top_frame::Get()->CancelAllMouseRoute();
1424 m_bNeedConfigFlush = true;
1425
1426 long item = -1;
1427 for (;;) {
1428 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1429 wxLIST_STATE_SELECTED);
1430 if (item == -1) break;
1431
1432 Route *proute_to_delete = (Route *)m_pRouteListCtrl->GetItemData(item);
1433
1434 if (proute_to_delete) list.push_back(proute_to_delete);
1435 }
1436 for (Route *route : list) {
1437 if (route) {
1438 NavObj_dB::GetInstance().DeleteRoute(route);
1439 g_pRouteMan->DeleteRoute(route);
1440 }
1441 }
1442
1443 m_lastRteItem = -1;
1444 UpdateRouteListCtrl();
1445 UpdateTrkListCtrl();
1446
1447 top_frame::Get()->InvalidateAllCanvasUndo();
1448 top_frame::Get()->RefreshAllCanvas();
1449 ::wxEndBusyCursor();
1450 }
1451}
1452
1453void RouteManagerDialog::OnRteDeleteAllClick(wxCommandEvent &event) {
1454 int dialog_ret =
1455 OCPNMessageBox(this, _("Are you sure you want to delete <ALL> routes?"),
1456 wxString(_("OpenCPN Alert")), wxYES_NO);
1457
1458 if (dialog_ret == wxID_YES) {
1459 if (g_pRouteMan->GetpActiveRoute()) g_pRouteMan->DeactivateRoute();
1460
1461 top_frame::Get()->CancelAllMouseRoute();
1462
1463 g_pRouteMan->DeleteAllRoutes();
1464
1465 m_lastRteItem = -1;
1466 UpdateRouteListCtrl();
1467
1468 // Also need to update the track list control, since routes and tracks
1469 // share a common global list (pRouteList)
1470 UpdateTrkListCtrl();
1471
1473 top_frame::Get()->InvalidateAllCanvasUndo();
1474 top_frame::Get()->RefreshAllCanvas();
1475
1476 m_bNeedConfigFlush = true;
1477 }
1478}
1479
1480void RouteManagerDialog::OnRtePropertiesClick(wxCommandEvent &event) {
1481 // Show routeproperties dialog for selected route
1482 long item = -1;
1483 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1484 wxLIST_STATE_SELECTED);
1485 if (item == -1) return;
1486
1487 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1488
1489 if (!route) return;
1490
1491 pRoutePropDialog = RoutePropDlgImpl::getInstance(GetParent());
1492
1493 pRoutePropDialog->SetRouteAndUpdate(route);
1494
1495 if (!pRoutePropDialog->IsShown()) pRoutePropDialog->Show();
1496
1497 pRoutePropDialog->Raise();
1498
1499 m_bNeedConfigFlush = true;
1500}
1501
1502void RouteManagerDialog::OnRteZoomtoClick(wxCommandEvent &event) {
1503 // Zoom into the bounding box of the selected route
1504 long item = -1;
1505 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1506 wxLIST_STATE_SELECTED);
1507 if (item == -1) return;
1508
1509 // optionally make this route exclusively visible
1510 if (m_bCtrlDown) MakeAllRoutesInvisible();
1511
1512 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1513
1514 if (!route) return;
1515
1516 // Ensure route is visible
1517 if (!route->IsVisible()) {
1518 route->SetVisible(true);
1519 m_pRouteListCtrl->SetItemImage(item, route->IsVisible() ? 0 : 1);
1520 NavObj_dB::GetInstance().UpdateRoute(route);
1521 }
1522
1523 ZoomtoRoute(route);
1524}
1525
1526void RouteManagerDialog::OnRteReverseClick(wxCommandEvent &event) {
1527 // Reverse selected route
1528 long item = -1;
1529 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1530 wxLIST_STATE_SELECTED);
1531 if (item == -1) return;
1532
1533 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1534
1535 if (!route) return;
1536 if (route->m_bIsInLayer) return;
1537
1538 int ask_return = OCPNMessageBox(this, g_pRouteMan->GetRouteReverseMessage(),
1539 _("Rename Waypoints?"), wxYES_NO | wxCANCEL);
1540 if (ask_return != wxID_CANCEL) {
1541 bool rename = (ask_return == wxID_YES);
1542
1543 pSelect->DeleteAllSelectableRouteSegments(route);
1544 route->Reverse(rename);
1545 pSelect->AddAllSelectableRouteSegments(route);
1546
1547 // update column 2 - create a UpdateRouteItem(index) instead?
1548 wxString startend = route->m_RouteStartString;
1549 if (!route->m_RouteEndString.IsEmpty())
1550 startend.append(_(" - ") + route->m_RouteEndString);
1551 m_pRouteListCtrl->SetItem(item, 2, startend);
1552
1553 NavObj_dB::GetInstance().UpdateRoute(route);
1554
1555 top_frame::Get()->RefreshAllCanvas();
1556 }
1557
1558 m_bNeedConfigFlush = true;
1559}
1560
1561void RouteManagerDialog::OnRteExportClick(wxCommandEvent &event) {
1562 RouteList list;
1563
1564 wxString suggested_name = "routes";
1565
1566 long item = -1;
1567 for (;;) {
1568 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1569 wxLIST_STATE_SELECTED);
1570 if (item == -1) break;
1571
1572 Route *proute_to_export = (Route *)m_pRouteListCtrl->GetItemData(item);
1573
1574 if (proute_to_export) {
1575 list.push_back(proute_to_export);
1576 if (proute_to_export->m_RouteNameString != "")
1577 suggested_name = proute_to_export->m_RouteNameString;
1578 }
1579 }
1580
1581 ExportGPXRoutes(this, &list, suggested_name);
1582}
1583
1584void RouteManagerDialog::OnRteResequenceClick(wxCommandEvent &event) {
1585 long item = -1;
1586 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1587 wxLIST_STATE_SELECTED);
1588 if (item == -1) return;
1589
1590 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1591
1592 if (!route) return;
1593 if (route->m_bIsInLayer) return;
1594 route->RenameRoutePoints();
1595}
1596
1597void RouteManagerDialog::OnRteSendToPeerClick(wxCommandEvent &event) {
1598 std::vector<Route *> list;
1599 long item = -1;
1600 for (;;) {
1601 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1602 wxLIST_STATE_SELECTED);
1603 if (item == -1) break;
1604
1605 Route *proute = (Route *)m_pRouteListCtrl->GetItemData(item);
1606
1607 if (proute) {
1608 list.push_back(proute);
1609 }
1610 }
1611 if (!list.empty()) {
1612 SendToPeerDlg dlg;
1613 for (auto r : list) {
1614 dlg.SetRoute(r);
1615 }
1616
1617 // Perform initial scan, if necessary
1618
1619 // Check for stale cache...
1620 MdnsCache::GetInstance().Validate();
1621 if (MdnsCache::GetInstance().GetCache().empty()) dlg.SetScanOnCreate(true);
1622
1623 dlg.SetScanTime(5); // seconds
1624 dlg.Create(NULL, -1, _("Send Route(s) to OpenCPN Peer") + "...", "");
1625 dlg.ShowModal();
1626 }
1627}
1628
1629void RouteManagerDialog::OnWptSendToPeerClick(wxCommandEvent &event) {
1630 std::vector<RoutePoint *> list;
1631 long item = -1;
1632 for (;;) {
1633 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1634 wxLIST_STATE_SELECTED);
1635 if (item == -1) break;
1636
1637 RoutePoint *proutep = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
1638
1639 if (proutep) {
1640 list.push_back(proutep);
1641 }
1642 }
1643 if (!list.empty()) {
1644 SendToPeerDlg dlg;
1645 for (auto r : list) {
1646 dlg.SetWaypoint(r);
1647 }
1648
1649 // Perform initial scan, if necessary
1650
1651 // Check for stale cache...
1652 MdnsCache::GetInstance().Validate();
1653 if (MdnsCache::GetInstance().GetCache().empty()) dlg.SetScanOnCreate(true);
1654
1655 dlg.SetScanTime(5); // seconds
1656 dlg.Create(NULL, -1, _("Send Waypoint(s) to OpenCPN Peer") + "...", "");
1657 dlg.ShowModal();
1658 }
1659}
1660
1661void RouteManagerDialog::OnTrkSendToPeerClick(wxCommandEvent &event) {
1662 std::vector<Track *> list;
1663 long item = -1;
1664 for (;;) {
1665 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1666 wxLIST_STATE_SELECTED);
1667 if (item == -1) break;
1668
1669 Track *ptrk = (Track *)m_pTrkListCtrl->GetItemData(item);
1670
1671 if (ptrk) {
1672 list.push_back(ptrk);
1673 }
1674 }
1675 if (!list.empty()) {
1676 SendToPeerDlg dlg;
1677 for (auto r : list) {
1678 dlg.SetTrack(r);
1679 }
1680
1681 // Perform initial scan, if necessary
1682
1683 // Check for stale cache...
1684 MdnsCache::GetInstance().Validate();
1685 if (MdnsCache::GetInstance().GetCache().empty()) dlg.SetScanOnCreate(true);
1686
1687 dlg.SetScanTime(5); // seconds
1688 dlg.Create(NULL, -1, _("Send Track(s) to OpenCPN Peer") + "...", "");
1689 dlg.ShowModal();
1690 }
1691}
1692
1693void RouteManagerDialog::OnRteActivateClick(wxCommandEvent &event) {
1694 // Activate the selected route, unless it already is
1695 long item = -1;
1696 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1697 wxLIST_STATE_SELECTED);
1698 if (item == -1) return;
1699
1700 if (m_bCtrlDown) MakeAllRoutesInvisible();
1701
1702 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1703
1704 if (!route) return;
1705
1706 if (!route->m_bRtIsActive) {
1707 if (!route->IsVisible()) {
1708 route->SetVisible(true);
1709 m_pRouteListCtrl->SetItemImage(item, 0, 0);
1710 }
1711
1712 ZoomtoRoute(route);
1713
1714 RoutePoint *best_point =
1715 g_pRouteMan->FindBestActivatePoint(route, gLat, gLon, gCog, gSog);
1716 g_pRouteMan->ActivateRoute(route, best_point);
1717 // g_pRouteMan->ActivateRoute(route);
1718 } else
1719 g_pRouteMan->DeactivateRoute();
1720
1721 UpdateRouteListCtrl();
1722
1723 NavObj_dB::GetInstance().UpdateRoute(route);
1724
1725 top_frame::Get()->RefreshAllCanvas();
1726
1727 // btnRteActivate->SetLabel(route->m_bRtIsActive ? _("Deactivate") :
1728 // _("Activate"));
1729
1730 m_bNeedConfigFlush = true;
1731}
1732
1733void RouteManagerDialog::OnRteToggleVisibility(wxMouseEvent &event) {
1734 wxPoint pos = event.GetPosition();
1735 int flags = 0;
1736 long clicked_index = m_pRouteListCtrl->HitTest(pos, flags);
1737
1738 // Clicking Visibility column?
1739 if (clicked_index > -1 &&
1740 event.GetX() < m_pRouteListCtrl->GetColumnWidth(rmVISIBLE)) {
1741 // Process the clicked item
1742 Route *route = (Route *)m_pRouteListCtrl->GetItemData(clicked_index);
1743
1744 route->SetVisible(!route->IsVisible());
1745
1746 m_pRouteListCtrl->SetItemImage(clicked_index, route->IsVisible() ? 0 : 1);
1747
1748 ::wxBeginBusyCursor();
1749
1750 NavObj_dB::GetInstance().UpdateRoute(route);
1751
1752 top_frame::Get()->RefreshAllCanvas();
1753
1754 // We need to update the waypoint list control since the visibility of
1755 // shared waypoints might have changed.
1756 if (g_pRouteMan->DoesRouteContainSharedPoints(route))
1757 UpdateWptListCtrlViz();
1758
1759 // Manage "show all" checkbox
1760 bool viz = true;
1761 long item = -1;
1762 for (;;) {
1763 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1764 wxLIST_STATE_DONTCARE);
1765 if (item == -1) break;
1766
1767 Route *pR = (Route *)m_pRouteListCtrl->GetItemData(item);
1768
1769 if (!pR->IsVisible()) {
1770 viz = false;
1771 break;
1772 }
1773 }
1774 m_cbShowAllRte->SetValue(viz);
1775
1776 ::wxEndBusyCursor();
1777 }
1778
1779 // Allow wx to process...
1780 event.Skip();
1781}
1782
1783void RouteManagerDialog::OnRteBtnLeftDown(wxMouseEvent &event) {
1784 m_bCtrlDown = event.ControlDown();
1785 event.Skip();
1786}
1787
1788void RouteManagerDialog::OnRteSelected(wxListEvent &event) {
1789 long clicked_index = event.m_itemIndex;
1790 // Process the clicked item
1791 Route *route = (Route *)m_pRouteListCtrl->GetItemData(clicked_index);
1792 // route->SetVisible(!route->IsVisible());
1793 m_pRouteListCtrl->SetItemImage(clicked_index, route->IsVisible() ? 0 : 1);
1794
1795 top_frame::Get()->RefreshAllCanvas();
1796
1797 UpdateRteButtons();
1798}
1799
1800void RouteManagerDialog::OnRteColumnClicked(wxListEvent &event) {
1801 if (event.m_col == 1) {
1802 sort_route_name_dir++;
1803
1804 m_pRouteListCtrl->SortItems(SortRoutesOnName, (wxIntPtr)NULL);
1805 } else if (event.m_col == 2) {
1806 sort_route_to_dir++;
1807 m_pRouteListCtrl->SortItems(SortRoutesOnTo, (wxIntPtr)NULL);
1808 }
1809}
1810
1811void RouteManagerDialog::OnRteSendToGPSClick(wxCommandEvent &event) {
1812 long item = -1;
1813 item = m_pRouteListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1814 wxLIST_STATE_SELECTED);
1815 if (item == -1) return;
1816
1817 Route *route = (Route *)m_pRouteListCtrl->GetItemData(item);
1818
1819 if (!route) return;
1820
1821 SendToGpsDlg *pdlg = new SendToGpsDlg();
1822 pdlg->SetRoute(route);
1823
1824 wxFont fo = GetOCPNGUIScaledFont(_("Dialog"));
1825 pdlg->SetFont(fo);
1826
1827 wxString source;
1828 pdlg->Create(NULL, -1, _("Send to GPS") + "...", source);
1829
1830#ifdef __WXOSX__
1831 HideWithEffect(wxSHOW_EFFECT_BLEND);
1832#endif
1833
1834 pdlg->ShowModal();
1835
1836#ifdef __WXOSX__
1837 ShowWithEffect(wxSHOW_EFFECT_BLEND);
1838#endif
1839
1840 pdlg->Destroy();
1841}
1842
1843void RouteManagerDialog::OnRteDefaultAction(wxListEvent &event) {
1844 wxCommandEvent evt;
1845 OnRtePropertiesClick(evt);
1846}
1847
1848void RouteManagerDialog::OnTrkDefaultAction(wxListEvent &event) {
1849 wxCommandEvent evt;
1850 OnTrkPropertiesClick(evt);
1851}
1852
1853void RouteManagerDialog::OnTrkRightClick(wxListEvent &event) {
1854 wxMenu menu;
1855 wxMenuItem *mergeItem = menu.Append(TRACK_MERGE, _("&Merge Selected Tracks"));
1856 mergeItem->Enable(m_pTrkListCtrl->GetSelectedItemCount() > 1);
1857 wxMenuItem *cleanItem = menu.Append(TRACK_CLEAN, _("Reduce Data..."));
1858 cleanItem->Enable(m_pTrkListCtrl->GetSelectedItemCount() == 1);
1859 wxMenuItem *copyItem = menu.Append(TRACK_COPY_TEXT, _("&Copy as text"));
1860 copyItem->Enable(m_pTrkListCtrl->GetSelectedItemCount() > 0);
1861 PopupMenu(&menu);
1862}
1863
1864static bool CompareTracks(Track *track1, Track *track2) {
1865 TrackPoint *start1 = track1->GetPoint(0);
1866 TrackPoint *start2 = track2->GetPoint(0);
1867 return start1->GetCreateTime() < start2->GetCreateTime();
1868}
1869
1870void RouteManagerDialog::OnTrkMenuSelected(wxCommandEvent &event) {
1871 int item = -1;
1872
1873 switch (event.GetId()) {
1874 case TRACK_CLEAN: {
1875 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1876 wxLIST_STATE_SELECTED);
1877 if (item == -1) break;
1878 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
1879 if (track->IsRunning()) {
1880 wxBell();
1881 break;
1882 }
1883
1884 const wxString choices[] = {"5.0", "10.0", "20.0", "50.0", "100.0"};
1885
1886 wxSingleChoiceDialog precisionDlg(this,
1887 _("Select the maximum error allowed "
1888 "(in meters)\nafter data reduction:"),
1889 _("Reduce Data Precision"), 5, choices);
1890#ifdef __WXOSX__
1891 precisionDlg.ShowWindowModal();
1892 while (precisionDlg.IsShown()) {
1893 wxMilliSleep(10);
1894 wxYield();
1895 }
1896 int result = precisionDlg.GetReturnCode();
1897#else
1898 int result = precisionDlg.ShowModal();
1899#endif
1900 if (result == wxID_CANCEL) break;
1901 double precision = 5.0;
1902 switch (precisionDlg.GetSelection()) {
1903 case 0:
1904 precision = 5.0;
1905 break;
1906 case 1:
1907 precision = 10.0;
1908 break;
1909 case 2:
1910 precision = 20.0;
1911 break;
1912 case 3:
1913 precision = 50.0;
1914 break;
1915 case 4:
1916 precision = 100.0;
1917 break;
1918 }
1919
1920 int pointsBefore = track->GetnPoints();
1921
1922 int reduction = track->Simplify(precision);
1923 top_frame::Get()->Refresh(false);
1924
1925 reduction = 100 * reduction / pointsBefore;
1926 wxString msg = wxString::Format(
1927 _("The amount of data used by the track\n was reduced by %d%%."),
1928 reduction);
1929 OCPNMessageBox(this, msg, _("OpenCPN info"), wxICON_INFORMATION | wxOK);
1930
1931 UpdateTrkListCtrl();
1932 UpdateRouteListCtrl();
1933
1934 break;
1935 }
1936
1937 case TRACK_COPY_TEXT: {
1938 wxString csvString;
1939 while (1) {
1940 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1941 wxLIST_STATE_SELECTED);
1942 if (item == -1) break;
1943 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
1944 csvString << track->GetName() << "\t"
1945 << wxString::Format("%.1f", track->Length()) << "\t"
1946 << "\n";
1947 }
1948
1949 if (wxTheClipboard->Open()) {
1950 wxTextDataObject *data = new wxTextDataObject;
1951 data->SetText(csvString);
1952 wxTheClipboard->SetData(data);
1953 wxTheClipboard->Close();
1954 }
1955
1956 break;
1957 }
1958
1959 case TRACK_MERGE: {
1960 Track *targetTrack = NULL;
1961 TrackPoint *tPoint;
1962 TrackPoint *newPoint;
1963 TrackPoint *lastPoint;
1964 std::vector<Track *> mergeList;
1965 std::vector<Track *> deleteList;
1966 bool runningSkipped = false;
1967
1968 ::wxBeginBusyCursor();
1969
1970 while (1) {
1971 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
1972 wxLIST_STATE_SELECTED);
1973 if (item == -1) break;
1974 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
1975 mergeList.push_back(track);
1976 }
1977
1978 if (!mergeList.size()) {
1979 ::wxEndBusyCursor();
1980 break;
1981 }
1982
1983 std::sort(mergeList.begin(), mergeList.end(), CompareTracks);
1984
1985 targetTrack = mergeList[0];
1986 lastPoint = targetTrack->GetLastPoint();
1987
1988 for (auto const &mergeTrack : mergeList) {
1989 if (mergeTrack == *mergeList.begin()) continue;
1990
1991 if (mergeTrack->IsRunning()) {
1992 runningSkipped = true;
1993 continue;
1994 }
1995
1996 for (int i = 0; i < mergeTrack->GetnPoints(); i++) {
1997 tPoint = mergeTrack->GetPoint(i);
1998 newPoint = new TrackPoint(tPoint->m_lat, tPoint->m_lon,
1999 tPoint->GetCreateTime());
2000
2001 targetTrack->AddPoint(newPoint);
2002 NavObj_dB::GetInstance().AddTrackPoint(targetTrack, newPoint);
2003
2004 pSelect->AddSelectableTrackSegment(lastPoint->m_lat, lastPoint->m_lon,
2005 newPoint->m_lat, newPoint->m_lon,
2006 lastPoint, newPoint, targetTrack);
2007 lastPoint = newPoint;
2008 }
2009 deleteList.push_back(mergeTrack);
2010 }
2011
2012 for (auto const &deleteTrack : deleteList) {
2013 g_pAIS->DeletePersistentTrack(deleteTrack);
2014 NavObj_dB::GetInstance().DeleteTrack(deleteTrack);
2015 RoutemanGui(*g_pRouteMan).DeleteTrack(deleteTrack);
2016 }
2017
2018 mergeList.clear();
2019 deleteList.clear();
2020
2021 ::wxEndBusyCursor();
2022
2023 UpdateTrkListCtrl();
2024 UpdateRouteListCtrl();
2025 top_frame::Get()->RefreshAllCanvas();
2026
2027 if (runningSkipped) {
2028 wxMessageDialog skipWarning(
2029 this,
2030 _("The currently running Track was not merged.\nYou can merge it "
2031 "later when it is completed."),
2032 "Warning", wxCANCEL | wxICON_WARNING);
2033 skipWarning.ShowModal();
2034 }
2035
2036 break;
2037 }
2038 }
2039}
2040
2041void RouteManagerDialog::UpdateTrkListCtrl() {
2042 // if an item was selected, make it selected again if it still exist
2043 long item = -1;
2044 item =
2045 m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2046
2047 wxUIntPtr selected_id = wxUIntPtr(0);
2048 if (item != -1) selected_id = m_pTrkListCtrl->GetItemData(item);
2049
2050 // Delete existing items
2051 m_pTrkListCtrl->DeleteAllItems();
2052
2053 // then add tracks to the listctrl
2054 std::vector<Track *>::iterator it;
2055 int index = 0;
2056 int list_index = 0;
2057 bool bpartialViz = false;
2058
2059 for (Track *trk : g_TrackList) {
2060 if (!trk->IsVisible()) bpartialViz = true;
2061
2062 if (!trk->IsListed()) continue;
2063
2064 if (!trk->GetName(true).Upper().Contains(
2065 m_tFilterTrk->GetValue().Upper())) {
2066 continue;
2067 }
2068
2069 wxListItem li;
2070 li.SetId(list_index);
2071 li.SetImage(trk->IsVisible() ? 0 : 1);
2072 li.SetData(trk);
2073 li.SetText("");
2074
2075 if (g_pActiveTrack == trk) {
2076 wxFont font = *wxNORMAL_FONT;
2077 font.SetWeight(wxFONTWEIGHT_BOLD);
2078 li.SetFont(font);
2079 }
2080 long idx = m_pTrkListCtrl->InsertItem(li);
2081
2082 m_pTrkListCtrl->SetItem(idx, colTRKNAME, trk->GetName(true));
2083 // Populate the track start date/time, formatted using the global timezone
2084 // settings.
2085 m_pTrkListCtrl->SetItem(idx, colTRKDATE, trk->GetDateTime());
2086
2087 wxString len;
2088 len.Printf("%5.2f", trk->Length());
2089 m_pTrkListCtrl->SetItem(idx, colTRKLENGTH, len);
2090
2091 wxListItem lic;
2092 lic.SetId(list_index);
2093 lic.SetColumn(1);
2094 lic.SetAlign(wxLIST_FORMAT_LEFT);
2095 m_pTrkListCtrl->SetItem(lic);
2096
2097 lic.SetColumn(2);
2098 lic.SetAlign(wxLIST_FORMAT_LEFT);
2099 m_pTrkListCtrl->SetItem(lic);
2100
2101 list_index++;
2102 }
2103
2104 switch (sort_track_key) {
2105 case SORT_ON_DISTANCE:
2106 m_pTrkListCtrl->SortItems(SortTracksOnDistance, (wxIntPtr)NULL);
2107 break;
2108 case SORT_ON_DATE:
2109 m_pTrkListCtrl->SortItems(SortTracksOnDate, (wxIntPtr)NULL);
2110 break;
2111 case SORT_ON_NAME:
2112 default:
2113 m_pTrkListCtrl->SortItems(SortTracksOnName, (wxIntPtr)NULL);
2114 break;
2115 }
2116
2117 m_pTrkListCtrl->SetColumnWidth(0, 4 * m_charWidth);
2118
2119 // restore selection if possible
2120 // NOTE this will select a different item, if one is deleted
2121 // (the next route will get that index).
2122 if (selected_id != wxUIntPtr(0)) {
2123 item = m_pTrkListCtrl->FindItem(-1, selected_id);
2124 m_pTrkListCtrl->SetItemState(item,
2125 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
2126 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
2127 }
2128
2129 if ((m_lastTrkItem >= 0) && (m_pTrkListCtrl->GetItemCount()))
2130 m_pTrkListCtrl->EnsureVisible(m_lastTrkItem);
2131
2132 m_cbShowAllTrk->SetValue(!bpartialViz);
2133 UpdateTrkButtons();
2134}
2135
2136void RouteManagerDialog::OnTrkSelected(wxListEvent &event) {
2137 UpdateTrkButtons();
2138}
2139
2140void RouteManagerDialog::OnTrkColumnClicked(wxListEvent &event) {
2141 if (event.m_col == 1) {
2142 sort_track_key = SORT_ON_NAME;
2143 sort_track_name_dir++;
2144 m_pTrkListCtrl->SortItems(SortTracksOnName, (wxIntPtr)NULL);
2145 } else if (event.m_col == 2) {
2146 sort_track_key = SORT_ON_DISTANCE;
2147 sort_track_len_dir++;
2148 m_pTrkListCtrl->SortItems(SortTracksOnDistance, (wxIntPtr)NULL);
2149 } else if (event.m_col == 3) {
2150 sort_track_key = SORT_ON_DATE;
2151 sort_track_date_dir++;
2152 m_pTrkListCtrl->SortItems(SortTracksOnDate, (wxIntPtr)NULL);
2153 }
2154}
2155
2156void RouteManagerDialog::UpdateTrkButtons() {
2157 long item = -1;
2158 item =
2159 m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2160 int items = m_pTrkListCtrl->GetSelectedItemCount();
2161
2162 m_lastTrkItem = item;
2163
2164 btnTrkProperties->Enable(items == 1);
2165 btnTrkDelete->Enable(items >= 1);
2166 btnTrkExport->Enable(items >= 1);
2167 btnTrkRouteFromTrack->Enable(items == 1);
2168 btnTrkDeleteAll->Enable(m_pTrkListCtrl->GetItemCount() > 0);
2169 btnTrkSendToPeer->Enable(items >= 1);
2170}
2171
2172void RouteManagerDialog::OnTrkToggleVisibility(wxMouseEvent &event) {
2173 wxPoint pos = event.GetPosition();
2174 int flags = 0;
2175 long clicked_index = m_pTrkListCtrl->HitTest(pos, flags);
2176
2177 // Clicking Visibility column?
2178 if (clicked_index > -1 &&
2179 event.GetX() < m_pTrkListCtrl->GetColumnWidth(colTRKVISIBLE)) {
2180 // Process the clicked item
2181 Track *track = (Track *)m_pTrkListCtrl->GetItemData(clicked_index);
2182 if (track) {
2183 track->SetVisible(!track->IsVisible());
2184 NavObj_dB::GetInstance().UpdateDBTrackAttributes(track);
2185 m_pTrkListCtrl->SetItemImage(clicked_index, track->IsVisible() ? 0 : 1);
2186 }
2187
2188 // Manage "show all" checkbox
2189 bool viz = true;
2190 long item = -1;
2191 for (;;) {
2192 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2193 wxLIST_STATE_DONTCARE);
2194 if (item == -1) break;
2195
2196 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
2197
2198 if (!track->IsVisible()) {
2199 viz = false;
2200 break;
2201 }
2202 }
2203 m_cbShowAllTrk->SetValue(viz);
2204
2205 top_frame::Get()->RefreshAllCanvas();
2206 }
2207
2208 // Allow wx to process...
2209 event.Skip();
2210}
2211
2212void RouteManagerDialog::OnTrkNewClick(wxCommandEvent &event) {
2213 top_frame::Get()->TrackOff();
2214 top_frame::Get()->TrackOn();
2215
2216 UpdateTrkListCtrl();
2217}
2218
2219void RouteManagerDialog::OnTrkPropertiesClick(wxCommandEvent &event) {
2220 // Show trackproperties dialog for selected track
2221 long item = -1;
2222 item =
2223 m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2224 if (item == -1) return;
2225
2226 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
2227
2228 if (!track) return;
2229
2230 pTrackPropDialog = TrackPropDlg::getInstance(GetParent());
2231 pTrackPropDialog->SetTrackAndUpdate(track);
2232
2233 if (!pTrackPropDialog->IsShown()) pTrackPropDialog->Show();
2234 UpdateTrkListCtrl();
2235
2236 m_bNeedConfigFlush = true;
2237}
2238
2239void RouteManagerDialog::OnTrkDeleteClick(wxCommandEvent &event) {
2240 std::vector<Track *> list;
2241
2242 int answer = OCPNMessageBox(
2243 this, _("Are you sure you want to delete the selected object(s)"),
2244 wxString(_("OpenCPN Alert")), wxYES_NO);
2245 if (answer != wxID_YES) return;
2246
2247 bool busy = false;
2248 if (m_pTrkListCtrl->GetSelectedItemCount()) {
2249 ::wxBeginBusyCursor();
2250 // m_bNeedConfigFlush = true;
2251 busy = true;
2252 }
2253
2254 long item = -1;
2255 for (;;) {
2256 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2257 wxLIST_STATE_SELECTED);
2258 if (item == -1) break;
2259
2260 Track *ptrack_to_delete = (Track *)m_pTrkListCtrl->GetItemData(item);
2261
2262 if (ptrack_to_delete) list.push_back(ptrack_to_delete);
2263 }
2264
2265 if (busy) {
2266 for (unsigned int i = 0; i < list.size(); i++) {
2267 Track *track = list.at(i);
2268 if (track) {
2269 g_pAIS->DeletePersistentTrack(track);
2270 NavObj_dB::GetInstance().DeleteTrack(track);
2271 RoutemanGui(*g_pRouteMan).DeleteTrack(track);
2272 }
2273 }
2274
2275 m_lastTrkItem = -1;
2276 // UpdateRouteListCtrl();
2277 UpdateTrkListCtrl();
2278
2279 top_frame::Get()->InvalidateAllCanvasUndo();
2280 top_frame::Get()->RefreshAllCanvas();
2281 ::wxEndBusyCursor();
2282 }
2283}
2284
2285void RouteManagerDialog::OnTrkExportClick(wxCommandEvent &event) {
2286 std::vector<Track *> list;
2287 wxString suggested_name = "tracks";
2288
2289 long item = -1;
2290 for (;;) {
2291 item = m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2292 wxLIST_STATE_SELECTED);
2293 if (item == -1) break;
2294
2295 Track *ptrack_to_export = (Track *)m_pTrkListCtrl->GetItemData(item);
2296
2297 if (ptrack_to_export) {
2298 list.push_back(ptrack_to_export);
2299 if (ptrack_to_export->GetName() != "")
2300 suggested_name = ptrack_to_export->GetName();
2301 }
2302 }
2303
2304 ExportGPXTracks(this, &list, suggested_name);
2305}
2306
2307void RouteManagerDialog::TrackToRoute(Track *track) {
2308 if (!track) return;
2309 if (track->m_bIsInLayer) return;
2310
2311 wxGenericProgressDialog pprog(_("OpenCPN Converting Track to Route...."),
2312 _("Processing Waypoints..."), 101, NULL,
2313 wxPD_AUTO_HIDE | wxPD_SMOOTH |
2314 wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
2315 wxPD_REMAINING_TIME);
2316
2317 ::wxBeginBusyCursor();
2318
2319 Route *route = track->RouteFromTrack(&pprog);
2320
2321 pRouteList->push_back(route);
2322
2323 pprog.Update(101, _("Done."));
2324
2325 top_frame::Get()->RefreshAllCanvas();
2326
2327 ::wxEndBusyCursor();
2328}
2329
2330void RouteManagerDialog::OnTrkRouteFromTrackClick(wxCommandEvent &event) {
2331 long item = -1;
2332 item =
2333 m_pTrkListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2334 if (item == -1) return;
2335
2336 Track *track = (Track *)m_pTrkListCtrl->GetItemData(item);
2337
2338 TrackToRoute(track);
2339
2340 UpdateRouteListCtrl();
2341}
2342
2343void RouteManagerDialog::OnTrkDeleteAllClick(wxCommandEvent &event) {
2344 int dialog_ret =
2345 OCPNMessageBox(this, _("Are you sure you want to delete <ALL> tracks?"),
2346 wxString(_("OpenCPN Alert")), wxYES_NO);
2347
2348 if (dialog_ret == wxID_YES) {
2349 RoutemanGui(*g_pRouteMan).DeleteAllTracks();
2350 }
2351
2352 m_lastTrkItem = -1;
2353 m_lastRteItem = -1;
2354
2355 UpdateTrkListCtrl();
2356
2357 // Also need to update the route list control, since routes and tracks
2358 // share a common global list (pRouteList)
2359 UpdateRouteListCtrl();
2360
2362
2363 top_frame::Get()->RefreshAllCanvas();
2364
2365 m_bNeedConfigFlush = true;
2366}
2367
2368void RouteManagerDialog::UpdateWptListCtrl(RoutePoint *rp_select,
2369 bool b_retain_sort) {
2370 wxIntPtr selected_id = wxUIntPtr(0);
2371 long item = -1;
2372
2373 if (NULL == rp_select) {
2374 // if an item was selected, make it selected again if it still exists
2375 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2376 wxLIST_STATE_SELECTED);
2377
2378 if (item != -1) selected_id = m_pWptListCtrl->GetItemData(item);
2379 }
2380
2381 // Freshen the image list
2382 m_pWptListCtrl->SetImageList(
2383 pWayPointMan->Getpmarkicon_image_list(m_listIconSize),
2384 wxIMAGE_LIST_SMALL);
2385
2386 m_pWptListCtrl->DeleteAllItems();
2387
2388 int index = 0;
2389 bool b_anyHidden = false;
2390
2391 auto node = pWayPointMan->GetWaypointList()->begin();
2392
2393 while (node != pWayPointMan->GetWaypointList()->end()) {
2394 RoutePoint *rp = *node;
2395 if (rp && rp->IsListed()) {
2396 if (rp->m_bIsInRoute && !rp->IsShared()) {
2397 ++node;
2398 continue;
2399 }
2400
2401 if (!rp->GetName().Upper().Contains(m_tFilterWpt->GetValue().Upper())) {
2402 ++node;
2403 continue;
2404 }
2405
2406 wxListItem li;
2407 li.SetId(index);
2408 li.SetImage(RoutePointGui(*rp).GetIconImageIndex());
2409 li.SetData(rp);
2410 li.SetText("");
2411 long idx = m_pWptListCtrl->InsertItem(li);
2412
2413 wxString scamin = wxString::Format("%i", (int)rp->GetScaMin());
2414 if (!rp->GetUseSca()) scamin = _("Always");
2415 if (g_bOverruleScaMin) scamin = _("Overruled");
2416 m_pWptListCtrl->SetItem(idx, colWPTSCALE, scamin);
2417
2418 wxString name = rp->GetName();
2419 if (name.IsEmpty()) name = _("(Unnamed Waypoint)");
2420 m_pWptListCtrl->SetItem(idx, colWPTNAME, name);
2421
2422 double dst;
2423 DistanceBearingMercator(rp->m_lat, rp->m_lon, gLat, gLon, NULL, &dst);
2424 wxString dist;
2425 dist.Printf("%5.2f " + getUsrDistanceUnit(), toUsrDistance(dst));
2426 m_pWptListCtrl->SetItem(idx, colWPTDIST, dist);
2427
2428 if (rp == rp_select) selected_id = (wxIntPtr)rp_select;
2429
2430 wxListItem lic;
2431 lic.SetId(index);
2432 lic.SetColumn(1);
2433 lic.SetAlign(wxLIST_FORMAT_LEFT);
2434 m_pWptListCtrl->SetItem(lic);
2435
2436 lic.SetColumn(2);
2437 lic.SetAlign(wxLIST_FORMAT_LEFT);
2438 m_pWptListCtrl->SetItem(lic);
2439
2440 if (!rp->IsVisible()) b_anyHidden = true;
2441
2442 index++;
2443 }
2444 ++node;
2445 }
2446
2447 if (!b_retain_sort) {
2448 m_pWptListCtrl->SortItems(SortWaypointsOnName,
2449 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2450 sort_wp_key = SORT_ON_NAME;
2451 } else {
2452 switch (sort_wp_key) {
2453 case SORT_ON_NAME:
2454 m_pWptListCtrl->SortItems(SortWaypointsOnName,
2455 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2456 break;
2457 case SORT_ON_DISTANCE:
2458 m_pWptListCtrl->SortItems(SortWaypointsOnDistance,
2459 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2460 break;
2461 }
2462 }
2463
2464 if (selected_id != wxUIntPtr(0)) {
2465 item = m_pWptListCtrl->FindItem(-1, selected_id);
2466 m_pWptListCtrl->SetItemState(item,
2467 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
2468 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
2469 }
2470
2471 if ((m_lastWptItem >= 0) && (m_pWptListCtrl->GetItemCount()))
2472 m_pWptListCtrl->EnsureVisible(m_lastWptItem);
2473
2474 if (pWayPointMan->Getpmarkicon_image_list(m_listIconSize)->GetImageCount()) {
2475 int iwidth, iheight;
2476 pWayPointMan->Getpmarkicon_image_list(m_listIconSize)
2477 ->GetSize(0, iwidth, iheight);
2478
2479 m_pWptListCtrl->SetColumnWidth(0, wxMax(iwidth + 4, 4 * m_charWidth));
2480 }
2481
2482 UpdateWptButtons();
2483
2484 m_cbShowAllWP->SetValue(!b_anyHidden);
2485}
2486
2487void RouteManagerDialog::UpdateWptListCtrlViz() {
2488 long item = -1;
2489 for (;;) {
2490 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2491 wxLIST_STATE_DONTCARE);
2492 if (item == -1) break;
2493
2494 RoutePoint *pRP = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2495 int imageIndex = RoutePointGui(*pRP).GetIconImageIndex();
2496
2497 m_pWptListCtrl->SetItemImage(item, imageIndex);
2498 }
2499}
2500
2501void RouteManagerDialog::OnWptDefaultAction(wxListEvent &event) {
2502 wxCommandEvent evt;
2503 OnWptPropertiesClick(evt);
2504}
2505
2506void RouteManagerDialog::OnWptSelected(wxListEvent &event) {
2507 UpdateWptButtons();
2508}
2509
2510void RouteManagerDialog::OnWptColumnClicked(wxListEvent &event) {
2511 if (event.m_col == NAME_COLUMN) {
2512 sort_wp_name_dir++;
2513 m_pWptListCtrl->SortItems(SortWaypointsOnName,
2514 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2515 sort_wp_key = SORT_ON_NAME;
2516 } else {
2517 if (event.m_col == DISTANCE_COLUMN) {
2518 sort_wp_len_dir++;
2519 m_pWptListCtrl->SortItems(SortWaypointsOnDistance,
2520 reinterpret_cast<wxIntPtr>(m_pWptListCtrl));
2521 sort_wp_key = SORT_ON_DISTANCE;
2522 }
2523 }
2524 UpdateWptListCtrl();
2525}
2526
2527void RouteManagerDialog::UpdateWptButtons() {
2528 long item = -1;
2529 item =
2530 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2531 bool enable1 = (m_pWptListCtrl->GetSelectedItemCount() == 1);
2532 bool enablemultiple = (m_pWptListCtrl->GetSelectedItemCount() >= 1);
2533
2534 if (enable1)
2535 m_lastWptItem = item;
2536 else
2537 m_lastWptItem = -1;
2538
2539 // Check selection to see if it is in a layer
2540 // If so, disable the "delete" button
2541 bool b_delete_enable = true;
2542 item = -1;
2543 for (;;) {
2544 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2545 wxLIST_STATE_SELECTED);
2546 if (item == -1) break;
2547
2548 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2549
2550 if (wp && wp->m_bIsInLayer) {
2551 b_delete_enable = false;
2552 break;
2553 }
2554 }
2555
2556 btnWptProperties->Enable(enablemultiple);
2557 btnWptZoomto->Enable(enable1);
2558 btnWptDeleteAll->Enable(m_pWptListCtrl->GetItemCount() > 0);
2559 btnWptDelete->Enable(b_delete_enable && enablemultiple);
2560 btnWptGoTo->Enable(enable1);
2561 btnWptExport->Enable(enablemultiple);
2562 btnWptSendToGPS->Enable(enable1);
2563 btnWptSendToPeer->Enable(enablemultiple);
2564}
2565
2566void RouteManagerDialog::OnWptToggleVisibility(wxMouseEvent &event) {
2567 wxPoint pos = event.GetPosition();
2568 int flags = 0;
2569 long clicked_index = m_pWptListCtrl->HitTest(pos, flags);
2570
2571 // Clicking Visibility column?
2572 if (clicked_index > -1 &&
2573 event.GetX() < m_pWptListCtrl->GetColumnWidth(colTRKVISIBLE)) {
2574 // Process the clicked item
2575 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(clicked_index);
2576
2577 if (!wp->IsSharedInVisibleRoute()) {
2578 wp->SetVisible(!wp->IsVisible());
2579 m_pWptListCtrl->SetItemImage(clicked_index,
2580 RoutePointGui(*wp).GetIconImageIndex());
2581
2582 NavObj_dB::GetInstance().UpdateRoutePoint(wp);
2583 }
2584
2585 // Manage "show all" checkbox
2586 bool viz = true;
2587 long item = -1;
2588 for (;;) {
2589 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2590 wxLIST_STATE_DONTCARE);
2591 if (item == -1) break;
2592
2593 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2594
2595 if (!wp->IsVisible()) {
2596 viz = false;
2597 break;
2598 }
2599 }
2600 m_cbShowAllWP->SetValue(viz);
2601
2602 top_frame::Get()->RefreshAllCanvas();
2603 } else // clicked on ScaMin column??
2604 if (clicked_index > -1 &&
2605 event.GetX() > m_pWptListCtrl->GetColumnWidth(colTRKVISIBLE) &&
2606 event.GetX() < (m_pWptListCtrl->GetColumnWidth(colTRKVISIBLE) +
2607 m_pWptListCtrl->GetColumnWidth(colWPTSCALE)) &&
2608 !g_bOverruleScaMin) {
2609 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(clicked_index);
2610 wp->SetUseSca(!wp->GetUseSca());
2611 NavObj_dB::GetInstance().UpdateRoutePoint(wp);
2612 top_frame::Get()->RefreshAllCanvas();
2613 wxString scamin = wxString::Format("%i", (int)wp->GetScaMin());
2614 if (!wp->GetUseSca()) scamin = _("Always");
2615 m_pWptListCtrl->SetItem(clicked_index, colWPTSCALE, scamin);
2616 }
2617
2618 // Allow wx to process...
2619 event.Skip();
2620}
2621
2622void RouteManagerDialog::OnWptNewClick(wxCommandEvent &event) {
2623 RoutePoint *pWP = new RoutePoint(gLat, gLon, g_default_wp_icon, "", "");
2624 pWP->m_bIsolatedMark = true; // This is an isolated mark
2625 pSelect->AddSelectableRoutePoint(gLat, gLon, pWP);
2626 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
2627
2628 top_frame::Get()->RefreshAllCanvas();
2629
2630 // g_pMarkInfoDialog = MarkInfoImpl::GetInstance( GetParent() );
2631 // There is on global instance of the MarkProp Dialog
2632 if (!g_pMarkInfoDialog) g_pMarkInfoDialog = new MarkInfoDlg(GetParent());
2633
2634 WptShowPropertiesDialog(pWP, GetParent());
2635}
2636
2637void RouteManagerDialog::OnWptPropertiesClick(wxCommandEvent &event) {
2638 long item = wxNOT_FOUND;
2639 item =
2640 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2641 if (item == wxNOT_FOUND) return;
2642
2643 auto pWP = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2644 WptShowPropertiesDialog(pWP, GetParent());
2645
2646 UpdateWptListCtrl();
2647 m_bNeedConfigFlush = true;
2648}
2649
2650void RouteManagerDialog::WptShowPropertiesDialog(RoutePoint *pWP,
2651 wxWindow *parent) {
2652 if (!g_pMarkInfoDialog) // There is one global instance of the MarkProp
2653 // Dialog
2654 g_pMarkInfoDialog = new MarkInfoDlg(parent);
2655
2656 g_pMarkInfoDialog->SetRoutePoint(pWP);
2657 g_pMarkInfoDialog->UpdateProperties();
2658
2659 wxString base_title = _("Waypoint Properties");
2660
2661 if (pWP->m_bIsInLayer) {
2662 wxString caption(wxString::Format("%s, %s: %s", base_title, _("Layer"),
2663 GetLayerName(pWP->m_LayerID)));
2664 g_pMarkInfoDialog->SetDialogTitle(caption);
2665 } else {
2666 g_pMarkInfoDialog->SetDialogTitle(base_title);
2667 }
2668
2669 if (!g_pMarkInfoDialog->IsShown()) g_pMarkInfoDialog->Show();
2670 g_pMarkInfoDialog->Raise();
2671}
2672
2673void RouteManagerDialog::OnWptZoomtoClick(wxCommandEvent &event) {
2674 long item = -1;
2675 item =
2676 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2677 if (item == -1) return;
2678
2679 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2680
2681 if (!wp) return;
2682
2683 if (top_frame::Get()->GetFocusCanvasSize() != wxSize(0, 0)) {
2684 top_frame::Get()->JumpToPosition(wp->m_lat, wp->m_lon);
2685 }
2686}
2687
2688void RouteManagerDialog::OnWptDeleteClick(wxCommandEvent &event) {
2689 RoutePointList list;
2690
2691 int answer = OCPNMessageBox(
2692 this, _("Are you sure you want to delete the selected object(s)"),
2693 wxString(_("OpenCPN Alert")), wxYES_NO);
2694 if (answer != wxID_YES) return;
2695
2696 bool busy = false;
2697 if (m_pWptListCtrl->GetSelectedItemCount()) {
2698 ::wxBeginBusyCursor();
2699 m_bNeedConfigFlush = true;
2700 busy = true;
2701 }
2702
2703 long item = -1;
2704 long item_last_selected = -1;
2705 for (;;) {
2706 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2707 wxLIST_STATE_SELECTED);
2708 if (item == -1) break;
2709
2710 item_last_selected = item;
2711 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2712
2713 if (wp && !wp->m_bIsInLayer) list.push_back(wp);
2714 }
2715
2716 if (busy) {
2717 for (RoutePoint *wp : list) {
2718 if (wp) {
2719 if (wp->m_bIsInRoute) {
2720 if (wxID_YES ==
2721 OCPNMessageBox(this,
2722 _("The waypoint you want to delete is used in a "
2723 "route, do you really want to delete it?"),
2724 _("OpenCPN Alert"), wxYES_NO)) {
2725 NavObj_dB::GetInstance().DeleteRoutePoint(wp);
2726 pWayPointMan->DestroyWaypoint(wp);
2727 }
2728 } else {
2729 NavObj_dB::GetInstance().DeleteRoutePoint(wp);
2730 pWayPointMan->DestroyWaypoint(wp);
2731 }
2732 }
2733 }
2734
2735 long item_next =
2736 m_pWptListCtrl->GetNextItem(item_last_selected); // next in list
2737 RoutePoint *wp_next = NULL;
2738 if (item_next > -1)
2739 wp_next = (RoutePoint *)m_pWptListCtrl->GetItemData(item_next);
2740
2741 m_lastWptItem = item_next;
2742
2743 UpdateRouteListCtrl();
2744 UpdateTrkListCtrl();
2745 UpdateWptListCtrl(wp_next, true);
2746
2747 if (g_pMarkInfoDialog) {
2748 g_pMarkInfoDialog->ClearData();
2749 }
2750
2751 top_frame::Get()->InvalidateAllCanvasUndo();
2752 top_frame::Get()->RefreshAllCanvas();
2753 ::wxEndBusyCursor();
2754 }
2755}
2756
2757void RouteManagerDialog::OnWptGoToClick(wxCommandEvent &event) {
2758 long item = -1;
2759 item =
2760 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2761 if (item == -1) return;
2762
2763 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2764
2765 if (!wp) return;
2766
2767 RoutePoint *pWP_src = new RoutePoint(gLat, gLon, g_default_wp_icon, "", "");
2768 pSelect->AddSelectableRoutePoint(gLat, gLon, pWP_src);
2769
2770 Route *temp_route = new Route();
2771 pRouteList->push_back(temp_route);
2772
2773 temp_route->AddPoint(pWP_src);
2774 temp_route->AddPoint(wp);
2775
2776 pSelect->AddSelectableRouteSegment(gLat, gLon, wp->m_lat, wp->m_lon, pWP_src,
2777 wp, temp_route);
2778
2779 wxString name = wp->GetName();
2780 if (name.IsEmpty()) name = _("(Unnamed Waypoint)");
2781 wxString rteName = _("Go to ");
2782 rteName.Append(name);
2783 temp_route->m_RouteNameString = rteName;
2784 temp_route->m_RouteStartString = _("Here");
2785
2786 temp_route->m_RouteEndString = name;
2787 temp_route->m_bDeleteOnArrival = true;
2788
2789 if (g_pRouteMan->GetpActiveRoute()) g_pRouteMan->DeactivateRoute();
2790
2791 g_pRouteMan->ActivateRoute(temp_route, wp);
2792
2793 UpdateRouteListCtrl();
2794}
2795
2796void RouteManagerDialog::OnWptExportClick(wxCommandEvent &event) {
2797 RoutePointList list;
2798
2799 wxString suggested_name = "waypoints";
2800
2801 long item = -1;
2802 for (;;) {
2803 item = m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2804 wxLIST_STATE_SELECTED);
2805 if (item == -1) break;
2806
2807 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2808
2809 if (wp && !wp->m_bIsInLayer) {
2810 list.push_back(wp);
2811 if (wp->GetName() != "") suggested_name = wp->GetName();
2812 }
2813 }
2814
2815 ExportGPXWaypoints(this, &list, suggested_name);
2816}
2817
2818void RouteManagerDialog::OnWptSendToGPSClick(wxCommandEvent &event) {
2819 long item = -1;
2820 item =
2821 m_pWptListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2822 if (item == -1) return;
2823
2824 RoutePoint *wp = (RoutePoint *)m_pWptListCtrl->GetItemData(item);
2825
2826 if (!wp) return;
2827
2828 SendToGpsDlg *pdlg = new SendToGpsDlg();
2829 pdlg->SetWaypoint(wp);
2830
2831 wxString source;
2832 pdlg->Create(NULL, -1, _("Send to GPS") + "...", source);
2833
2834#ifdef __WXOSX__
2835 HideWithEffect(wxSHOW_EFFECT_BLEND);
2836#endif
2837 pdlg->ShowModal();
2838#ifdef __WXOSX__
2839 ShowWithEffect(wxSHOW_EFFECT_BLEND);
2840#endif
2841
2842 delete pdlg;
2843}
2844
2845void RouteManagerDialog::OnWptDeleteAllClick(wxCommandEvent &event) {
2846 wxString prompt;
2847 int buttons, type;
2848 if (!pWayPointMan->SharedWptsExist()) {
2849 prompt = _("Are you sure you want to delete <ALL> waypoints?");
2850 buttons = wxYES_NO;
2851 type = 1;
2852 } else {
2853 prompt =
2854 _("There are some waypoints used in routes or anchor alarms.\n Do you "
2855 "want to delete them as well?\n This will change the routes and "
2856 "disable the anchor alarms.\n Answering No keeps the waypoints used "
2857 "in routes or alarms.");
2858 buttons = wxYES_NO | wxCANCEL;
2859 type = 2;
2860 }
2861 int answer =
2862 OCPNMessageBox(this, prompt, wxString(_("OpenCPN Alert")), buttons);
2863 if (answer == wxID_YES) pWayPointMan->DeleteAllWaypoints(true);
2864 if (answer == wxID_NO && type == 2)
2865 pWayPointMan->DeleteAllWaypoints(false); // only delete unused waypoints
2866
2867 if (g_pMarkInfoDialog) {
2868 g_pMarkInfoDialog->ClearData();
2869 }
2870
2871 m_lastWptItem = -1;
2872 UpdateRouteListCtrl();
2873 UpdateWptListCtrl();
2874 top_frame::Get()->InvalidateAllCanvasUndo();
2875 top_frame::Get()->RefreshAllCanvas();
2876}
2877
2878void RouteManagerDialog::OnLaySelected(wxListEvent &event) {
2879 UpdateLayButtons();
2880}
2881
2882void RouteManagerDialog::OnLayColumnClicked(wxListEvent &event) {
2883 if (event.m_col == 1) {
2884 sort_layer_name_dir++;
2885 m_pLayListCtrl->SortItems(SortLayersOnName, (wxIntPtr)NULL);
2886 } else if (event.m_col == 2) {
2887 sort_layer_len_dir++;
2888 m_pLayListCtrl->SortItems(SortLayersOnSize, (wxIntPtr)NULL);
2889 }
2890}
2891
2892void RouteManagerDialog::UpdateLayButtons() {
2893 long item = -1;
2894 item =
2895 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2896 bool enable = (item != -1);
2897
2898 // btnLayProperties->Enable(false);
2899 btnLayDelete->Enable(enable);
2900 cbLayToggleChart->Enable(enable);
2901 cbLayToggleListing->Enable(enable);
2902 cbLayToggleNames->Enable(enable);
2903
2904 if (item >= 0) {
2905 cbLayToggleChart->SetValue(
2906 ((Layer *)m_pLayListCtrl->GetItemData(item))->IsVisibleOnChart());
2907
2908 cbLayToggleNames->Set3StateValue(
2909 ((Layer *)m_pLayListCtrl->GetItemData(item))->HasVisibleNames());
2910
2911 cbLayToggleListing->SetValue(
2912 ((Layer *)m_pLayListCtrl->GetItemData(item))->IsVisibleOnListing());
2913
2914 } else {
2915 cbLayToggleChart->SetValue(true);
2916 cbLayToggleNames->Set3StateValue(wxCHK_UNDETERMINED);
2917 cbLayToggleListing->SetValue(true);
2918 }
2919}
2920
2921void RouteManagerDialog::OnLayToggleVisibility(wxMouseEvent &event) {
2922 wxPoint pos = event.GetPosition();
2923 int flags = 0;
2924 long clicked_index = m_pLayListCtrl->HitTest(pos, flags);
2925
2926 // Clicking Visibility column?
2927 if (clicked_index > -1 &&
2928 event.GetX() < m_pLayListCtrl->GetColumnWidth(colLAYVISIBLE)) {
2929 // Process the clicked item
2930 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(clicked_index);
2931
2932 layer->SetVisibleOnChart(!layer->IsVisibleOnChart());
2933 m_pLayListCtrl->SetItemImage(clicked_index,
2934 layer->IsVisibleOnChart() ? 0 : 1);
2935
2936 // Manage "show all" checkbox
2937 bool viz = true;
2938 long item = -1;
2939 for (;;) {
2940 item = m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL,
2941 wxLIST_STATE_DONTCARE);
2942 if (item == -1) break;
2943
2944 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
2945
2946 if (!layer->IsVisibleOnChart()) {
2947 viz = false;
2948 break;
2949 }
2950 }
2951 m_cbShowAllLay->SetValue(viz);
2952
2953 ToggleLayerContentsOnChart(layer);
2954 }
2955
2956 // Allow wx to process...
2957 event.Skip();
2958}
2959
2960void RouteManagerDialog::UpdateLists() {
2961 UpdateRouteListCtrl();
2962 UpdateTrkListCtrl();
2963 UpdateWptListCtrl();
2964 UpdateLayListCtrl();
2965}
2966
2967void RouteManagerDialog::OnLayNewClick(wxCommandEvent &event) {
2968 AddNewLayer(false); // Temporary layer
2969}
2970
2971void RouteManagerDialog::OnPerLayNewClick(wxCommandEvent &event) {
2972 AddNewLayer(true); // Persistent layer
2973}
2974
2975void RouteManagerDialog::AddNewLayer(bool isPersistent) {
2976 bool show_flag = g_bShowLayers;
2977 g_bShowLayers = true;
2978
2979 UI_ImportGPX(this, true, "", true, isPersistent);
2980
2981 g_bShowLayers = show_flag;
2982 UpdateLists();
2983 top_frame::Get()->RefreshAllCanvas();
2984}
2985
2986void RouteManagerDialog::OnLayPropertiesClick(wxCommandEvent &event) {
2987 // Show layer properties dialog for selected layer - todo
2988 long item = -1;
2989 item =
2990 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2991 if (item == -1) return;
2992}
2993
2994void RouteManagerDialog::OnLayDeleteClick(wxCommandEvent &event) {
2995 long item = -1;
2996 item =
2997 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
2998 if (item == -1) return;
2999
3000 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
3001
3002 if (!layer) return;
3003 // Check if this file is a persistent layer.
3004 // If added in this session the listctrl file path is origin dir and not yet
3005 // /layers
3006 bool ispers = false;
3007 wxString destf, f, name, ext;
3008 f = layer->m_LayerFileName;
3009 wxFileName::SplitPath(f, NULL, NULL, &name, &ext);
3010 destf = g_Platform->GetPrivateDataDir();
3011 appendOSDirSlash(&destf);
3012 destf.Append("layers");
3013 appendOSDirSlash(&destf);
3014 destf << name << "." << ext;
3015
3016 wxString prompt = _(
3017 "Are you sure you want to delete this layer and <ALL> of its contents?");
3018 if (wxFileExists(destf)) {
3019 prompt.Append("\n");
3020 prompt.Append(
3021 _("The file will also be deleted from OpenCPN's layer directory."));
3022 prompt.Append("\n (" + destf + ")");
3023 ispers = true;
3024 }
3025 int answer =
3026 OCPNMessageBox(this, prompt, wxString(_("OpenCPN Alert")), wxYES_NO);
3027 if (answer == wxID_NO) return;
3028
3029 // Delete a persistent layer file if present
3030 if (ispers) {
3031 wxString remMSG;
3032 if (wxRemoveFile(destf))
3033 remMSG.sprintf("Layer file: %s is deleted", destf);
3034 else
3035 remMSG.sprintf("Error deleting Layer file: %s", destf);
3036
3037 wxLogMessage(remMSG);
3038 }
3039
3040 // Process Tracks and Routes in this layer
3041 for (Route *pRoute : *pRouteList) {
3042 if (pRoute->m_bIsInLayer && (pRoute->m_LayerID == layer->m_LayerID)) {
3043 pRoute->m_bIsInLayer = false;
3044 pRoute->m_LayerID = 0;
3045 g_pRouteMan->DeleteRoute(pRoute);
3046 }
3047 }
3048
3049 for (Track *pTrack : g_TrackList) {
3050 if (pTrack->m_bIsInLayer && (pTrack->m_LayerID == layer->m_LayerID)) {
3051 pTrack->m_bIsInLayer = false;
3052 pTrack->m_LayerID = 0;
3053 NavObj_dB::GetInstance().DeleteTrack(pTrack);
3054 RoutemanGui(*g_pRouteMan).DeleteTrack(pTrack);
3055 }
3056 }
3057
3058 // Process waypoints in this layer
3059 std::vector<RoutePoint *> to_be_destroyed;
3060 auto node = pWayPointMan->GetWaypointList()->begin();
3061 while (node != pWayPointMan->GetWaypointList()->end()) {
3062 RoutePoint *rp = *node;
3063 if (rp && (rp->m_LayerID == layer->m_LayerID)) {
3064 rp->m_bIsInLayer = false;
3065 rp->m_LayerID = 0;
3066 // no need to update the change set on layer ops
3067 to_be_destroyed.push_back(rp);
3068 }
3069 ++node;
3070 }
3071 for (auto rp : to_be_destroyed) pWayPointMan->DestroyWaypoint(rp, false);
3072
3073 if (g_pMarkInfoDialog) {
3074 g_pMarkInfoDialog->ClearData();
3075 }
3076
3077 auto found = std::find(pLayerList->begin(), pLayerList->end(), layer);
3078 if (found != pLayerList->end()) pLayerList->erase(found);
3079
3080 UpdateLists();
3081
3082 top_frame::Get()->RefreshAllCanvas();
3083
3084 m_bNeedConfigFlush = false;
3085}
3086
3087void RouteManagerDialog::OnLayToggleChartClick(wxCommandEvent &event) {
3088 // Toggle visibility on chart for selected layer
3089 long item = -1;
3090 item =
3091 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3092 if (item == -1) return;
3093
3094 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
3095
3096 if (!layer) return;
3097
3098 layer->SetVisibleOnChart(!layer->IsVisibleOnChart());
3099 m_pLayListCtrl->SetItemImage(item, layer->IsVisibleOnChart() ? 0 : 1);
3100
3101 ToggleLayerContentsOnChart(layer);
3102}
3103
3104void RouteManagerDialog::ToggleLayerContentsOnChart(Layer *layer) {
3105 // Process Tracks and Routes in this layer
3106 for (Route *pRoute : *pRouteList) {
3107 if (pRoute->m_bIsInLayer && (pRoute->m_LayerID == layer->m_LayerID)) {
3108 pRoute->SetVisible(layer->IsVisibleOnChart());
3109 }
3110 }
3111
3112 for (Track *pTrack : g_TrackList) {
3113 if (pTrack->m_bIsInLayer && (pTrack->m_LayerID == layer->m_LayerID)) {
3114 pTrack->SetVisible(layer->IsVisibleOnChart());
3115 NavObj_dB::GetInstance().UpdateDBTrackAttributes(pTrack);
3116 }
3117 }
3118
3119 // Process waypoints in this layer
3120 for (RoutePoint *rp : *pWayPointMan->GetWaypointList()) {
3121 if (rp && (rp->m_LayerID == layer->m_LayerID)) {
3122 rp->SetVisible(layer->IsVisibleOnChart());
3123 }
3124 }
3125 UpdateLists();
3126
3127 UpdateLayButtons();
3128
3129 top_frame::Get()->RefreshAllCanvas();
3130}
3131
3132void RouteManagerDialog::OnLayToggleNamesClick(wxCommandEvent &event) {
3133 // Toggle WPT names visibility on chart for selected layer
3134 long item = -1;
3135 item =
3136 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3137 if (item == -1) return;
3138
3139 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
3140
3141 if (!layer) return;
3142
3143 layer->SetVisibleNames(cbLayToggleNames->Get3StateValue());
3144
3145 ToggleLayerContentsNames(layer);
3146}
3147
3148void RouteManagerDialog::ToggleLayerContentsNames(Layer *layer) {
3149 // Process Tracks and Routes in this layer
3150 for (Route *pRoute : *pRouteList) {
3151 if (pRoute->m_bIsInLayer && (pRoute->m_LayerID == layer->m_LayerID)) {
3152 for (RoutePoint *prp1 : *pRoute->pRoutePointList) {
3153 if (layer->HasVisibleNames() == wxCHK_UNDETERMINED) {
3154 prp1->m_bShowName = prp1->m_bShowNameData;
3155 } else {
3156 prp1->m_bShowName = (layer->HasVisibleNames() == wxCHK_CHECKED);
3157 }
3158 }
3159 }
3160 }
3161
3162 // Process waypoints in this layer
3163 for (RoutePoint *rp : *pWayPointMan->GetWaypointList()) {
3164 if (rp && (rp->m_LayerID == layer->m_LayerID)) {
3165 rp->SetNameShown(layer->HasVisibleNames() == wxCHK_CHECKED ||
3166 (rp->m_bShowNameData &&
3167 layer->HasVisibleNames() == wxCHK_UNDETERMINED));
3168 }
3169 }
3170
3171 UpdateLayButtons();
3172
3173 top_frame::Get()->RefreshAllCanvas();
3174}
3175
3176void RouteManagerDialog::OnLayToggleListingClick(wxCommandEvent &event) {
3177 // Toggle visibility on listing for selected layer
3178 long item = -1;
3179 item =
3180 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3181 if (item == -1) return;
3182
3183 Layer *layer = (Layer *)m_pLayListCtrl->GetItemData(item);
3184
3185 if (!layer) return;
3186
3187 layer->SetVisibleOnListing(!layer->IsVisibleOnListing());
3188
3189 ToggleLayerContentsOnListing(layer);
3190}
3191
3192void RouteManagerDialog::ToggleLayerContentsOnListing(Layer *layer) {
3193 ::wxBeginBusyCursor();
3194
3195 // Process Tracks and Routes in this layer
3196 for (Route *pRoute : *pRouteList) {
3197 if (pRoute->m_bIsInLayer && (pRoute->m_LayerID == layer->m_LayerID)) {
3198 pRoute->SetListed(layer->IsVisibleOnListing());
3199 }
3200 }
3201
3202 for (Track *pTrack : g_TrackList) {
3203 if (pTrack->m_bIsInLayer && (pTrack->m_LayerID == layer->m_LayerID))
3204 pTrack->SetListed(layer->IsVisibleOnListing());
3205 }
3206
3207 // Process waypoints in this layer
3208 // n.b. If the waypoint belongs to a track, and is not shared, then do not
3209 // list it. This is a performance optimization, allowing large track support.
3210 for (RoutePoint *rp : *pWayPointMan->GetWaypointList()) {
3211 if (rp && rp->m_bIsolatedMark && (rp->m_LayerID == layer->m_LayerID)) {
3212 rp->SetListed(layer->IsVisibleOnListing());
3213 }
3214 }
3215
3216 UpdateLists();
3217
3218 ::wxEndBusyCursor();
3219
3220 top_frame::Get()->RefreshAllCanvas();
3221}
3222
3223void RouteManagerDialog::OnLayDefaultAction(wxListEvent &event) {
3224 wxCommandEvent evt;
3225 OnLayPropertiesClick(evt);
3226}
3227
3228void RouteManagerDialog::UpdateLayListCtrl() {
3229 // if an item was selected, make it selected again if it still exist
3230 long item = -1;
3231 item =
3232 m_pLayListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3233
3234 wxUIntPtr selected_id = wxUIntPtr(0);
3235 if (item != -1) selected_id = m_pLayListCtrl->GetItemData(item);
3236
3237 // Delete existing items
3238 m_pLayListCtrl->DeleteAllItems();
3239
3240 // then add routes to the listctrl
3241 LayerList::iterator it;
3242 int index = 0;
3243 bool b_anyHidden = false;
3244 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
3245 Layer *lay = (Layer *)(*it);
3246
3247 if (!lay->m_LayerName.Upper().Contains(m_tFilterLay->GetValue().Upper())) {
3248 continue;
3249 }
3250
3251 wxListItem li;
3252 li.SetId(index);
3253 li.SetImage(lay->IsVisibleOnChart() ? 0 : 1);
3254 li.SetData(lay);
3255 li.SetText("");
3256
3257 long idx = m_pLayListCtrl->InsertItem(li);
3258
3259 wxString name = lay->m_LayerName;
3260 if (name.IsEmpty()) {
3261 // RoutePoint *rp = trk->GetPoint(1);
3262 // if (rp)
3263 // name = rp->m_CreateTime.FormatISODate() + " " +
3264 // rp->m_CreateTime.FormatISOTime(); //name =
3265 // rp->m_CreateTime.Format();
3266 // else
3267 name = _("(Unnamed Layer)");
3268 }
3269 m_pLayListCtrl->SetItem(idx, colLAYNAME, name);
3270
3271 wxString len;
3272 len.Printf("%d", (int)lay->m_NoOfItems);
3273 m_pLayListCtrl->SetItem(idx, colLAYITEMS, len);
3274 m_pLayListCtrl->SetItem(idx, colLAYPERSIST, lay->m_LayerType);
3275
3276 wxListItem lic;
3277 lic.SetId(index);
3278 lic.SetColumn(1);
3279 lic.SetAlign(wxLIST_FORMAT_LEFT);
3280 m_pLayListCtrl->SetItem(lic);
3281
3282 lic.SetColumn(2);
3283 lic.SetAlign(wxLIST_FORMAT_LEFT);
3284 m_pLayListCtrl->SetItem(lic);
3285
3286 if (!lay->IsVisibleOnChart()) b_anyHidden = true;
3287 }
3288
3289 m_pLayListCtrl->SortItems(SortLayersOnName,
3290 reinterpret_cast<wxIntPtr>(m_pLayListCtrl));
3291 m_pLayListCtrl->SetColumnWidth(0, 4 * m_charWidth);
3292
3293 // restore selection if possible
3294 // NOTE this will select a different item, if one is deleted
3295 // (the next route will get that index).
3296 if (selected_id != wxUIntPtr(0)) {
3297 item = m_pLayListCtrl->FindItem(-1, selected_id);
3298 m_pLayListCtrl->SetItemState(item,
3299 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
3300 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
3301 }
3302 UpdateLayButtons();
3303
3304 m_cbShowAllLay->SetValue(!b_anyHidden);
3305}
3306
3307void RouteManagerDialog::OnImportClick(wxCommandEvent &event) {
3308 // Import routes
3309 // FIXME there is no way to instruct this function about what to import.
3310 // Suggest to add that!
3311
3312 UI_ImportGPX(this);
3313
3314 UpdateLists();
3315
3316 top_frame::Get()->RefreshAllCanvas();
3317}
3318void RouteManagerDialog::OnExportClick(wxCommandEvent &event) {
3319 ExportGPX(this);
3320}
3321
3322#include "navutil.h"
3323void RouteManagerDialog::OnBackupClick(wxCommandEvent &event) {
3324 int result = BackupDatabase(this);
3325 if (result == wxID_YES) {
3326 OCPNMessageBox(NULL, _("Backup successful"), _("Backup result"),
3327 wxICON_INFORMATION | wxOK);
3328 } else if (result == wxID_NO) {
3329 OCPNMessageBox(NULL, _("Backup Failed\nCheck the OpenCPN Logs"),
3330 _("Backup result"), wxICON_INFORMATION | wxOK);
3331 }
3332 // If the backup was cancelled the result is wxID_ABORT
3333}
3334
3335void RouteManagerDialog::OnExportVizClick(wxCommandEvent &event) {
3336 ExportGPX(this, true, true); // only visible objects, layers included
3337}
3338
3339void RouteManagerDialog::OnFilterChanged(wxCommandEvent &event) {
3340 if (event.GetEventObject() == m_tFilterWpt) {
3341 UpdateWptListCtrl(NULL, true);
3342 } else if (event.GetEventObject() == m_tFilterRte) {
3343 UpdateRouteListCtrl();
3344 } else if (event.GetEventObject() == m_tFilterTrk) {
3345 UpdateTrkListCtrl();
3346 } else if (event.GetEventObject() == m_tFilterLay) {
3347 UpdateLayListCtrl();
3348 }
3349}
3350
3351// 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.
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:76
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 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.
Abstract gFrame/MyFrame interface.
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.