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