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