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