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