1 /***************************************************************************
2  *
3  * Project:  OpenCPN
4  * Purpose:  CanvasMenuHandler
5  * Author:   David Register
6  *
7  ***************************************************************************
8  *   Copyright (C) 2015 by David S. Register                               *
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *   This program is distributed in the hope that it will be useful,       *
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  *   GNU General Public License for more details.                          *
19  *                                                                         *
20  *   You should have received a copy of the GNU General Public License     *
21  *   along with this program; if not, write to the                         *
22  *   Free Software Foundation, Inc.,                                       *
23  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
24  **************************************************************************/
25 
26 // For compilers that support precompilation, includes "wx.h".
27 #include "wx/wxprec.h"
28 
29 #ifndef  WX_PRECOMP
30 #include "wx/wx.h"
31 #endif //precompiled headers
32 #include "wx/image.h"
33 #include <wx/graphics.h>
34 #include <wx/listbook.h>
35 #include <wx/clipbrd.h>
36 #include <wx/aui/aui.h>
37 
38 #include "config.h"
39 #include "dychart.h"
40 
41 #include <wx/listimpl.cpp>
42 
43 #include "canvasMenu.h"
44 
45 #include "chcanv.h"
46 #include "TCWin.h"
47 #include "georef.h"
48 #include "styles.h"
49 #include "routeman.h"
50 #include "navutil.h"
51 #include "kml.h"
52 #include "chartdb.h"
53 #include "chart1.h"
54 #include "cutil.h"
55 #include "MarkInfo.h"
56 #include "RoutePropDlgImpl.h"
57 #include "TrackPropDlg.h"
58 #include "tcmgr.h"
59 #include "routemanagerdialog.h"
60 #include "pluginmanager.h"
61 #include "undo.h"
62 #include "tide_time.h"
63 #include "Quilt.h"
64 #include "FontMgr.h"
65 #include "AIS_Decoder.h"
66 #include "AIS_Target_Data.h"
67 #include "SendToGpsDlg.h"
68 #include "Track.h"
69 #include "Route.h"
70 
71 #include "cm93.h"                   // for chart outline draw
72 #include "s57chart.h"               // for ArrayOfS57Obj
73 #include "s52plib.h"
74 
75 #include "ais.h"
76 
77 #include <vector>
78 
79 #ifdef __OCPN__ANDROID__
80 #include "androidUTIL.h"
81 #endif
82 
83 // ----------------------------------------------------------------------------
84 // Useful Prototypes
85 // ----------------------------------------------------------------------------
86 extern void pupHandler_PasteRoute();
87 extern void pupHandler_PasteTrack();
88 extern void pupHandler_PasteWaypoint();
89 
90 
91 extern AIS_Decoder      *g_pAIS;
92 extern bool             g_bShowAreaNotices;
93 extern bool             bGPSValid;
94 extern Routeman         *g_pRouteMan;
95 extern bool             g_bskew_comp;
96 extern double           gLat, gLon, gSog, gCog, vLat, vLon;
97 extern MyFrame          *gFrame;
98 extern ChartGroupArray  *g_pGroupArray;
99 extern PlugInManager    *g_pi_manager;
100 extern int              g_nAWMax;
101 extern int              g_nAWDefault;
102 extern RoutePoint       *pAnchorWatchPoint1;
103 extern RoutePoint       *pAnchorWatchPoint2;
104 extern wxString         g_AW1GUID;
105 extern wxString         g_AW2GUID;
106 extern int              g_click_stop;
107 extern RouteManagerDialog *pRouteManagerDialog;
108 extern MarkInfoDlg     *g_pMarkInfoDialog;
109 extern RoutePropDlgImpl *pRoutePropDialog;
110 extern ActiveTrack      *g_pActiveTrack;
111 extern bool             g_bConfirmObjectDelete;
112 extern WayPointman      *pWayPointMan;
113 extern MyConfig         *pConfig;
114 extern Select           *pSelect;
115 
116 extern CM93OffsetDialog  *g_pCM93OffsetDialog;
117 
118 extern GoToPositionDialog *pGoToPositionDialog;
119 extern RouteList        *pRouteList;
120 extern wxString         g_default_wp_icon;
121 extern bool              g_btouch;
122 extern bool             g_bBasicMenus;
123 extern TrackPropDlg     *pTrackPropDialog;
124 extern double           gHdt;
125 extern bool             g_FlushNavobjChanges;
126 
127 
128 //    Constants for right click menus
129 enum
130 {
131     ID_DEF_MENU_MAX_DETAIL = 1,
132     ID_DEF_MENU_SCALE_IN,
133     ID_DEF_MENU_SCALE_OUT,
134     ID_DEF_MENU_DROP_WP,
135     ID_DEF_MENU_NEW_RT,
136     ID_DEF_MENU_QUERY,
137     ID_DEF_MENU_MOVE_BOAT_HERE,
138     ID_DEF_MENU_GOTO_HERE,
139     ID_DEF_MENU_GOTOPOSITION,
140 
141     ID_WP_MENU_GOTO,
142     ID_WP_MENU_DELPOINT,
143     ID_WP_MENU_PROPERTIES,
144     ID_RT_MENU_ACTIVATE,
145     ID_RT_MENU_DEACTIVATE,
146     ID_RT_MENU_INSERT,
147     ID_RT_MENU_APPEND,
148     ID_RT_MENU_COPY,
149     ID_TK_MENU_COPY,
150     ID_WPT_MENU_COPY,
151     ID_WPT_MENU_SENDTOGPS,
152     ID_WPT_MENU_SENDTONEWGPS,
153     ID_PASTE_WAYPOINT,
154     ID_PASTE_ROUTE,
155     ID_PASTE_TRACK,
156     ID_RT_MENU_DELETE,
157     ID_RT_MENU_REVERSE,
158     ID_RT_MENU_DELPOINT,
159     ID_RT_MENU_ACTPOINT,
160     ID_RT_MENU_DEACTPOINT,
161     ID_RT_MENU_ACTNXTPOINT,
162     ID_RT_MENU_REMPOINT,
163     ID_RT_MENU_PROPERTIES,
164     ID_RT_MENU_SENDTOGPS,
165     ID_RT_MENU_SENDTONEWGPS,
166     ID_WP_MENU_SET_ANCHORWATCH,
167     ID_WP_MENU_CLEAR_ANCHORWATCH,
168     ID_DEF_MENU_AISTARGETLIST,
169 
170     ID_RC_MENU_SCALE_IN,
171     ID_RC_MENU_SCALE_OUT,
172     ID_RC_MENU_ZOOM_IN,
173     ID_RC_MENU_ZOOM_OUT,
174     ID_RC_MENU_FINISH,
175     ID_DEF_MENU_AIS_QUERY,
176     ID_DEF_MENU_AIS_CPA,
177     ID_DEF_MENU_AISSHOWTRACK,
178     ID_DEF_MENU_ACTIVATE_MEASURE,
179     ID_DEF_MENU_DEACTIVATE_MEASURE,
180     ID_DEF_MENU_COPY_MMSI,
181 
182     ID_UNDO,
183     ID_REDO,
184 
185     ID_DEF_MENU_CM93OFFSET_DIALOG,
186 
187     ID_TK_MENU_PROPERTIES,
188     ID_TK_MENU_DELETE,
189     ID_WP_MENU_ADDITIONAL_INFO,
190 
191     ID_DEF_MENU_QUILTREMOVE,
192     ID_DEF_MENU_COGUP,
193     ID_DEF_MENU_NORTHUP,
194     ID_DEF_MENU_HEADUP,
195     ID_DEF_MENU_TOGGLE_FULL,
196     ID_DEF_MENU_TIDEINFO,
197     ID_DEF_MENU_CURRENTINFO,
198     ID_DEF_ZERO_XTE,
199 
200     ID_DEF_MENU_GROUPBASE,  // Must be last entry, as chart group identifiers are created dynamically
201 
202 
203     ID_DEF_MENU_LAST
204 };
205 
206 //------------------------------------------------------------------------------
207 //    CanvasMenuHandler Implementation
208 //------------------------------------------------------------------------------
GetNextContextMenuId()209 int CanvasMenuHandler::GetNextContextMenuId()
210 {
211     return ID_DEF_MENU_LAST + 100;  //Allowing for 100 dynamic menu item identifiers
212 }
213 
214 // Define a constructor for my canvas
CanvasMenuHandler(ChartCanvas * parentCanvas,Route * selectedRoute,Track * selectedTrack,RoutePoint * selectedPoint,int selectedAIS_MMSI,void * selectedTCIndex)215 CanvasMenuHandler::CanvasMenuHandler(ChartCanvas *parentCanvas,
216                   Route *selectedRoute,
217                   Track *selectedTrack,
218                   RoutePoint *selectedPoint,
219                   int selectedAIS_MMSI,
220                   void *selectedTCIndex )
221 
222 {
223     parent = parentCanvas;
224     m_pSelectedRoute = selectedRoute;
225     m_pSelectedTrack = selectedTrack;
226     m_pFoundRoutePoint = selectedPoint;
227     m_FoundAIS_MMSI = selectedAIS_MMSI;
228     m_pIDXCandidate = selectedTCIndex;
229 }
230 
~CanvasMenuHandler()231 CanvasMenuHandler::~CanvasMenuHandler()
232 {
233 
234 }
235 
236 
237 //-------------------------------------------------------------------------------
238 //          Popup Menu Handling
239 //-------------------------------------------------------------------------------
240 
MenuPrepend1(wxMenu * menu,int id,wxString label)241 void MenuPrepend1( wxMenu *menu, int id, wxString label)
242 {
243     wxMenuItem *item = new wxMenuItem(menu, id, label);
244 #if defined(__WXMSW__)
245     wxFont *qFont = GetOCPNScaledFont(_T("Menu"));
246     item->SetFont(*qFont);
247 #endif
248 
249 #ifdef __OCPN__ANDROID__
250     wxFont sFont = GetOCPNGUIScaledFont(_T("Menu"));
251     item->SetFont(sFont);
252 #endif
253 
254     if(g_btouch) menu->InsertSeparator(0);
255     menu->Prepend(item);
256 }
257 
MenuAppend1(wxMenu * menu,int id,wxString label)258 void MenuAppend1( wxMenu *menu, int id, wxString label)
259 {
260     wxMenuItem *item = new wxMenuItem(menu, id, label);
261 #if defined(__WXMSW__)
262 
263     wxFont *qFont = GetOCPNScaledFont(_("Menu"));
264     item->SetFont(*qFont);
265 #endif
266 
267 #ifdef __OCPN__ANDROID__
268     wxFont sFont = GetOCPNGUIScaledFont(_T("Menu"));
269     item->SetFont(sFont);
270 #endif
271 
272     menu->Append(item);
273     if(g_btouch) menu->AppendSeparator();
274 }
275 
SetMenuItemFont1(wxMenuItem * item)276 void SetMenuItemFont1(wxMenuItem *item)
277 {
278 #if defined(__WXMSW__) || defined(__OCPN__ANDROID__)
279 
280     wxFont *qFont = GetOCPNScaledFont(_("Menu"));
281     item->SetFont(*qFont);
282 #endif
283 }
284 
CanvasPopupMenu(int x,int y,int seltype)285 void CanvasMenuHandler::CanvasPopupMenu( int x, int y, int seltype )
286 {
287     wxMenu* contextMenu = new wxMenu;
288 	wxMenu* menuWaypoint = NULL;
289 	wxMenu* menuRoute = NULL;
290 	wxMenu* menuTrack = NULL;
291 	wxMenu* menuAIS = NULL;
292 
293     wxMenu *subMenuChart = new wxMenu;
294 
295     wxMenu *menuFocus = contextMenu;    // This is the one that will be shown
296 
297     popx = x;
298     popy = y;
299 
300     if( seltype == SELTYPE_ROUTECREATE ) {
301         MenuAppend1( contextMenu, ID_RC_MENU_FINISH, _menuText( _( "End Route" ), _T("Esc") ) );
302     }
303 
304     if( ! parent->m_pMouseRoute ) {
305         if( parent->m_bMeasure_Active )
306             MenuPrepend1( contextMenu, ID_DEF_MENU_DEACTIVATE_MEASURE, _menuText( _("Measure Off"), _T("Esc") ) );
307         else
308             MenuPrepend1( contextMenu, ID_DEF_MENU_ACTIVATE_MEASURE, _menuText( _( "Measure" ), _T("M") ) );
309 //            contextMenu->Prepend( ID_DEF_MENU_ACTIVATE_MEASURE, _menuText( _( "Measure" ), _T("F4") ) );
310     }
311 
312     if( !g_bBasicMenus || (seltype != SELTYPE_ROUTECREATE )) {
313         if( parent->undo->AnythingToUndo() ) {
314             wxString undoItem;
315             undoItem << _("Undo") << _T(" ") << parent->undo->GetNextUndoableAction()->Description();
316             MenuPrepend1( contextMenu, ID_UNDO, _menuText( undoItem, _T("Ctrl-Z") ) );
317         }
318 
319         if( parent->undo->AnythingToRedo() ) {
320             wxString redoItem;
321             redoItem << _("Redo") << _T(" ") << parent->undo->GetNextRedoableAction()->Description();
322 #ifdef __WXOSX__
323             MenuPrepend1( contextMenu, ID_REDO, _menuText( redoItem, _T("Shift-Ctrl-Z") ) );
324 #else
325             MenuPrepend1( contextMenu, ID_REDO, _menuText( redoItem, _T("Ctrl-Y") ) );
326 #endif
327         }
328     }
329 
330     bool ais_areanotice = false;
331     if( g_pAIS && parent->GetShowAIS() && g_bShowAreaNotices ) {
332 
333         AIS_Target_Hash* an_sources = g_pAIS->GetAreaNoticeSourcesList();
334 
335         float vp_scale = parent->GetVPScale();
336 
337         for( AIS_Target_Hash::iterator target = an_sources->begin(); target != an_sources->end(); ++target ) {
338             AIS_Target_Data* target_data = target->second;
339             if( !target_data->area_notices.empty() ) {
340                 for( AIS_Area_Notice_Hash::iterator ani = target_data->area_notices.begin(); ani != target_data->area_notices.end(); ++ani ) {
341                     Ais8_001_22& area_notice = ani->second;
342                     wxBoundingBox bbox;
343 
344                     for( Ais8_001_22_SubAreaList::iterator sa = area_notice.sub_areas.begin(); sa != area_notice.sub_areas.end(); ++sa ) {
345                         switch( sa->shape ) {
346                             case AIS8_001_22_SHAPE_CIRCLE: {
347                                 wxPoint target_point;
348                                 parent->GetCanvasPointPix( sa->latitude, sa->longitude, &target_point );
349                                 bbox.Expand( target_point );
350                                 if( sa->radius_m > 0.0 )
351                                     bbox.EnLarge( sa->radius_m * vp_scale );
352                                 break;
353                             }
354                             case AIS8_001_22_SHAPE_POLYGON:
355                             case AIS8_001_22_SHAPE_POLYLINE: {
356                                 double lat = sa->latitude;
357                                 double lon = sa->longitude;
358                                 for( int i = 0; i < 4; ++i ) {
359                                     ll_gc_ll( lat, lon, sa->angles[i], sa->dists_m[i] / 1852.0,
360                                               &lat, &lon );
361                                     wxPoint target_point;
362                                     parent->GetCanvasPointPix( lat, lon, &target_point );
363                                     bbox.Expand( target_point );
364                                 }
365                             }
366                         }
367                     }
368 
369                     if( bbox.PointInBox( x, y ) ) {
370                         ais_areanotice = true;
371                         break;
372                     }
373                 }
374             }
375         }
376     }
377 
378     int nChartStack = 0;
379     if(parent->GetpCurrentStack())
380         nChartStack = parent->GetpCurrentStack()->nEntry;
381 
382     if( !parent->GetVP().b_quilt ) {
383         if( nChartStack > 1 ) {
384             MenuAppend1( contextMenu, ID_DEF_MENU_MAX_DETAIL, _( "Max Detail Here" ) );
385             MenuAppend1( contextMenu, ID_DEF_MENU_SCALE_IN, _menuText( _( "Scale In" ), _T("Ctrl-Left") ) );
386             MenuAppend1( contextMenu, ID_DEF_MENU_SCALE_OUT, _menuText( _( "Scale Out" ), _T("Ctrl-Right") ) );
387         }
388 
389         if( ( parent->m_singleChart && ( parent->m_singleChart->GetChartFamily() == CHART_FAMILY_VECTOR ) ) || ais_areanotice ) {
390             MenuAppend1( contextMenu, ID_DEF_MENU_QUERY, _( "Object Query" ) + _T( "..." ) );
391         }
392 
393     } else {
394         ChartBase *pChartTest = parent->m_pQuilt->GetChartAtPix( parent->GetVP(), wxPoint( x, y ) );
395         if( ( pChartTest && ( pChartTest->GetChartFamily() == CHART_FAMILY_VECTOR ) ) || ais_areanotice ) {
396             MenuAppend1( contextMenu, ID_DEF_MENU_QUERY, _( "Object Query" ) + _T( "..." ) );
397         } else {
398 #ifndef __OCPN__ANDROID__
399 if( !g_bBasicMenus && (nChartStack > 1 ) ) {
400                 MenuAppend1( contextMenu, ID_DEF_MENU_SCALE_IN, _menuText( _( "Scale In" ), _T("Ctrl-Left") ) );
401                 MenuAppend1( contextMenu, ID_DEF_MENU_SCALE_OUT, _menuText( _( "Scale Out" ), _T("Ctrl-Right") ) );
402             }
403 #endif
404         }
405     }
406 
407     if( !g_bBasicMenus || (seltype != SELTYPE_ROUTECREATE )) {
408         MenuAppend1( contextMenu, ID_DEF_MENU_DROP_WP, _menuText( _( "Drop Mark" ), _T("Ctrl-M") ) );
409         MenuAppend1( contextMenu, ID_DEF_MENU_NEW_RT, _menuText( _( "New Route..." ), _T("Ctrl-R") ) );
410 
411         if( !bGPSValid )
412             MenuAppend1( contextMenu, ID_DEF_MENU_MOVE_BOAT_HERE, _( "Move Boat Here" ) );
413     }
414 
415     if( !g_bBasicMenus && (!( g_pRouteMan->GetpActiveRoute() || ( seltype & SELTYPE_MARKPOINT )) ) )
416         MenuAppend1( contextMenu, ID_DEF_MENU_GOTO_HERE, _( "Navigate To Here" ) );
417 
418     if( !g_bBasicMenus)
419         MenuAppend1( contextMenu, ID_DEF_MENU_GOTOPOSITION, _("Center view") + _T("...") );
420 
421     if( !g_bBasicMenus){
422         if( parent->GetVP().b_quilt){
423             if( parent->GetUpMode() == NORTH_UP_MODE ){
424                 MenuAppend1( contextMenu, ID_DEF_MENU_COGUP, _("Course Up Mode") );
425                 if(!std::isnan(gHdt))
426                     MenuAppend1( contextMenu, ID_DEF_MENU_HEADUP, _("Heading Up Mode") );
427             }
428             else{
429                 MenuAppend1( contextMenu, ID_DEF_MENU_NORTHUP, _("North Up Mode") );
430             }
431         }
432         else {
433             if( parent->m_singleChart && ( fabs( parent->m_singleChart->GetChartSkew() ) > .01 )
434                 && !g_bskew_comp ) MenuAppend1( contextMenu, ID_DEF_MENU_NORTHUP, _("Chart Up Mode") );
435             else
436                 MenuAppend1( contextMenu, ID_DEF_MENU_NORTHUP, _("North Up Mode") );
437         }
438     }
439 
440     if( !g_bBasicMenus){
441             bool full_toggle_added = false;
442 #ifndef __OCPN__ANDROID__
443         if(g_btouch){
444             MenuAppend1( contextMenu, ID_DEF_MENU_TOGGLE_FULL, _("Toggle Full Screen") );
445             full_toggle_added = true;
446         }
447 
448 
449         if(!full_toggle_added){
450             //if(gFrame->IsFullScreen())
451                 MenuAppend1( contextMenu, ID_DEF_MENU_TOGGLE_FULL, _("Toggle Full Screen") );
452         }
453 #endif
454 
455         if ( g_pRouteMan->IsAnyRouteActive() && g_pRouteMan->GetCurrentXTEToActivePoint() > 0. )
456             MenuAppend1( contextMenu, ID_DEF_ZERO_XTE, _("Zero XTE") );
457 
458         Kml* kml = new Kml;
459         int pasteBuffer = kml->ParsePasteBuffer();
460         if( pasteBuffer != KML_PASTE_INVALID ) {
461             switch( pasteBuffer ) {
462                 case KML_PASTE_WAYPOINT: {
463                     MenuAppend1( contextMenu, ID_PASTE_WAYPOINT, _( "Paste Waypoint" ) );
464                     break;
465                 }
466                 case KML_PASTE_ROUTE: {
467                     MenuAppend1( contextMenu, ID_PASTE_ROUTE, _( "Paste Route" ) );
468                     break;
469                 }
470                 case KML_PASTE_TRACK: {
471                     MenuAppend1( contextMenu, ID_PASTE_TRACK, _( "Paste Track" ) );
472                     break;
473                 }
474                 case KML_PASTE_ROUTE_TRACK: {
475                     MenuAppend1( contextMenu, ID_PASTE_ROUTE, _( "Paste Route" ) );
476                     MenuAppend1( contextMenu, ID_PASTE_TRACK, _( "Paste Track" ) );
477                     break;
478                 }
479             }
480         }
481         delete kml;
482 
483         if( !parent->GetVP().b_quilt && parent->m_singleChart && ( parent->m_singleChart->GetChartType() == CHART_TYPE_CM93COMP ) ) {
484             MenuAppend1( contextMenu, ID_DEF_MENU_CM93OFFSET_DIALOG, _( "CM93 Offset Dialog..." ) );
485         }
486 
487     }   //if( !g_bBasicMenus){
488 
489 
490 #ifndef __OCPN__ANDROID__
491 //TODO stack
492 //     if( ( parent->GetVP().b_quilt ) && ( pCurrentStack && pCurrentStack->b_valid ) ) {
493 //         int dbIndex = parent->m_pQuilt->GetChartdbIndexAtPix( parent->GetVP(), wxPoint( popx, popy ) );
494 //         if( dbIndex != -1 )
495 //             MenuAppend1( contextMenu, ID_DEF_MENU_QUILTREMOVE, _( "Hide This Chart" ) );
496 //     }
497 #endif
498 
499 
500 #ifdef __WXMSW__
501     //  If we dismiss the context menu without action, we need to discard some mouse events....
502     //  Eat the next 2 button events, which happen as down-up on MSW XP
503     g_click_stop = 2;
504 #endif
505 
506     //  ChartGroup SubMenu
507     wxMenuItem* subItemChart = contextMenu->AppendSubMenu( subMenuChart, _("Chart Groups") );
508     if(g_btouch) contextMenu->AppendSeparator();
509 
510     SetMenuItemFont1(subItemChart);
511 
512     if( g_pGroupArray->GetCount() ) {
513 
514 #ifdef __WXMSW__
515 		MenuAppend1(subMenuChart, wxID_CANCEL, _("temporary"));
516 #endif
517           wxMenuItem* subItem0 = subMenuChart->AppendRadioItem( ID_DEF_MENU_GROUPBASE ,
518                   _("All Active Charts") );
519 
520 
521 
522         SetMenuItemFont1(subItem0);
523 
524         for( unsigned int i = 0; i < g_pGroupArray->GetCount(); i++ ) {
525             subItem0 = subMenuChart->AppendRadioItem( ID_DEF_MENU_GROUPBASE + i + 1,
526                      g_pGroupArray->Item( i )->m_group_name );
527             SetMenuItemFont1(subItem0);
528         }
529 
530 #ifdef __WXMSW__
531     subMenuChart->Remove( wxID_CANCEL );
532 #endif
533         subMenuChart->Check( ID_DEF_MENU_GROUPBASE + parent->m_groupIndex, true );
534     }
535 
536 
537 
538     //  This is the default context menu
539     menuFocus = contextMenu;
540 
541 	wxString name;
542     if( !g_bBasicMenus || (seltype != SELTYPE_ROUTECREATE )) {
543         if( g_pAIS ) {
544             if( parent->GetShowAIS() && (seltype & SELTYPE_AISTARGET) ) {
545                 AIS_Target_Data *myptarget = g_pAIS->Get_Target_Data_From_MMSI( m_FoundAIS_MMSI );
546 				if (!g_bBasicMenus && myptarget) {
547 					name = myptarget->GetFullName();
548 					if (name.IsEmpty())
549 						 name.Printf(_T("%d"), m_FoundAIS_MMSI);
550 					name.Prepend(_T(" ( ")).Append(_T(" )"));
551 				}
552 				else
553 					name = wxEmptyString;
554 				menuAIS = new wxMenu(_("AIS") + name);
555 				MenuAppend1(menuAIS, ID_DEF_MENU_AIS_QUERY, _("Target Query..."));
556                 if( myptarget && myptarget->bCPA_Valid && (myptarget->n_alert_state != AIS_ALERT_SET) ) {
557                     if( myptarget->b_show_AIS_CPA )
558                         MenuAppend1( menuAIS, ID_DEF_MENU_AIS_CPA, _( "Hide Target CPA" ) );
559                     else
560                         MenuAppend1( menuAIS, ID_DEF_MENU_AIS_CPA, _( "Show Target CPA" ) );
561                 }
562                 MenuAppend1( menuAIS, ID_DEF_MENU_AISTARGETLIST, _("Target List...") );
563                 if ( 1 /*g_bAISShowTracks*/ ) {
564                     if( myptarget && myptarget->b_show_track )
565                         MenuAppend1( menuAIS, ID_DEF_MENU_AISSHOWTRACK, _("Hide Target Track") );
566                     else
567                         MenuAppend1( menuAIS, ID_DEF_MENU_AISSHOWTRACK, _("Show Target Track") );
568                 }
569 
570                 MenuAppend1( menuAIS, ID_DEF_MENU_COPY_MMSI, _("Copy Target MMSI") );
571                 menuAIS->AppendSeparator();
572 
573                 if( !parent->GetVP().b_quilt ) {
574                     if( ( parent->m_singleChart && ( parent->m_singleChart->GetChartFamily() == CHART_FAMILY_VECTOR ) ) ) {
575                         MenuAppend1( menuAIS, ID_DEF_MENU_QUERY, _( "Object Query..." ) );
576                     }
577 
578                 } else {
579                     ChartBase *pChartTest = parent->m_pQuilt->GetChartAtPix( parent->GetVP(), wxPoint( x, y ) );
580                     if( ( pChartTest && ( pChartTest->GetChartFamily() == CHART_FAMILY_VECTOR ) ) ) {
581                         MenuAppend1( menuAIS, ID_DEF_MENU_QUERY, _( "Object Query..." ) );
582                     }
583                 }
584 
585 
586                 menuFocus = menuAIS;
587             }
588 			else
589 				MenuAppend1(contextMenu, ID_DEF_MENU_AISTARGETLIST, _("AIS target list") + _T("..."));
590         }
591     }
592 
593     if( seltype & SELTYPE_ROUTESEGMENT ) {
594 		if (!g_bBasicMenus && m_pSelectedRoute) {
595 			name = m_pSelectedRoute->m_RouteNameString;
596 			if (name.IsEmpty())
597 				name = _("Unnamed Route");
598 			name.Prepend(_T(" ( ")).Append(_T(" )"));
599 		} else
600 			name = wxEmptyString;
601         bool blay = false;
602         if( m_pSelectedRoute && m_pSelectedRoute->m_bIsInLayer )
603             blay = true;
604 
605         if( blay ){
606 			menuRoute = new wxMenu(_("Layer Route") + name);
607             MenuAppend1( menuRoute, ID_RT_MENU_PROPERTIES, _( "Properties" ) + _T( "..." ) );
608             if( m_pSelectedRoute ) {
609                 if( m_pSelectedRoute->IsActive() ) {
610                     int indexActive = m_pSelectedRoute->GetIndexOf( m_pSelectedRoute->m_pRouteActivePoint );
611                     if( ( indexActive + 1 ) <= m_pSelectedRoute->GetnPoints() ) {
612                         MenuAppend1( menuRoute, ID_RT_MENU_ACTNXTPOINT, _( "Activate Next Waypoint" ) );
613                     }
614                     MenuAppend1( menuRoute, ID_RT_MENU_DEACTIVATE, _( "Deactivate" ) );
615                     MenuAppend1( menuRoute, ID_DEF_ZERO_XTE, _( "Zero XTE" ) );
616                 }
617                 else {
618                     MenuAppend1( menuRoute, ID_RT_MENU_ACTIVATE, _( "Activate" ) );
619                 }
620             }
621         }
622         else {
623 			menuRoute = new wxMenu(_("Route") + name);
624             MenuAppend1( menuRoute, ID_RT_MENU_PROPERTIES, _( "Properties" ) + _T( "..." ) );
625             if( m_pSelectedRoute ) {
626                 if( m_pSelectedRoute->IsActive() ) {
627                     int indexActive = m_pSelectedRoute->GetIndexOf( m_pSelectedRoute->m_pRouteActivePoint );
628                     if( ( indexActive + 1 ) <= m_pSelectedRoute->GetnPoints() ) {
629                         MenuAppend1( menuRoute, ID_RT_MENU_ACTNXTPOINT, _( "Activate Next Waypoint" ) );
630                     }
631                     MenuAppend1( menuRoute, ID_RT_MENU_DEACTIVATE, _( "Deactivate" ) );
632                     MenuAppend1( menuRoute, ID_DEF_ZERO_XTE, _( "Zero XTE" ) );
633                 }
634                 else {
635                     MenuAppend1( menuRoute, ID_RT_MENU_ACTIVATE, _( "Activate" ) );
636                 }
637             }
638             MenuAppend1( menuRoute, ID_RT_MENU_INSERT, _( "Insert Waypoint" ) );
639             MenuAppend1( menuRoute, ID_RT_MENU_APPEND, _( "Append Waypoint" ) );
640             MenuAppend1( menuRoute, ID_RT_MENU_COPY, _( "Copy as KML" ) + _T( "..." ) );
641             MenuAppend1( menuRoute, ID_RT_MENU_DELETE, _( "Delete" ) + _T( "..." ) );
642             MenuAppend1( menuRoute, ID_RT_MENU_REVERSE, _( "Reverse..." ) );
643 
644 //#ifndef __OCPN__ANDROID__
645             wxString port = parent->FindValidUploadPort();
646             parent->m_active_upload_port = port;
647             wxString item = _( "Send to GPS" );
648             if( !port.IsEmpty() ) {
649                 item.Append( _T(" ( ") );
650                 item.Append( port );
651                 item.Append(_T(" )") );
652             }
653             MenuAppend1( menuRoute, ID_RT_MENU_SENDTOGPS, item );
654 
655             if( !port.IsEmpty() ) {
656                 wxString item = _( "Send to new GPS" );
657                 MenuAppend1( menuRoute, ID_RT_MENU_SENDTONEWGPS, item );
658             }
659 //#endif
660 		}
661         //Eventually set this menu as the "focused context menu"
662 		if (menuFocus != menuAIS)
663 			menuFocus = menuRoute;
664     }
665 
666     if( seltype & SELTYPE_TRACKSEGMENT ) {
667 		name = wxEmptyString;
668 		if ( !g_bBasicMenus && m_pSelectedTrack)
669 			name = _T(" ( ") + m_pSelectedTrack->GetName(true) + _T(" )");
670 		else
671 			name = wxEmptyString;
672         bool blay = false;
673         if( m_pSelectedTrack && m_pSelectedTrack->m_bIsInLayer )
674             blay = true;
675 
676         if( blay ) {
677 			menuTrack = new wxMenu(_("Layer Track") + name);
678             MenuAppend1( menuTrack, ID_TK_MENU_PROPERTIES, _( "Properties" ) + _T( "..." ) );
679         }
680         else {
681 			menuTrack = new wxMenu(_("Track") + name);
682             MenuAppend1( menuTrack, ID_TK_MENU_PROPERTIES, _( "Properties" ) + _T( "..." ) );
683             MenuAppend1( menuTrack, ID_TK_MENU_COPY, _( "Copy as KML" ) );
684             MenuAppend1( menuTrack, ID_TK_MENU_DELETE, _( "Delete" ) + _T( "..." ) );
685         }
686         //Eventually set this menu as the "focused context menu"
687 		if ( menuFocus != menuAIS )
688 			menuFocus = menuTrack;
689     }
690 
691     if( seltype & SELTYPE_ROUTEPOINT ) {
692 		if ( !g_bBasicMenus && m_pFoundRoutePoint ) {
693 			name = m_pFoundRoutePoint->GetName();
694 			if ( name.IsEmpty() )
695 				name = _("Unnamed Waypoint");
696 			name.Prepend(_T(" ( ")).Append(_T(" )"));
697 		} else
698 			name = wxEmptyString;
699         bool blay = false;
700         if( m_pFoundRoutePoint && m_pFoundRoutePoint->m_bIsInLayer )
701             blay = true;
702 
703         if( blay ){
704 			menuWaypoint = new wxMenu(_("Layer Waypoint") + name);
705             MenuAppend1( menuWaypoint, ID_WP_MENU_PROPERTIES, _( "Properties" ) + _T( "..." ) );
706 
707             if( m_pSelectedRoute && m_pSelectedRoute->IsActive() )
708                 MenuAppend1( menuWaypoint, ID_RT_MENU_ACTPOINT, _( "Activate" ) );
709         }
710         else {
711 			menuWaypoint = new wxMenu(_("Waypoint") + name);
712             MenuAppend1( menuWaypoint, ID_WP_MENU_PROPERTIES, _( "Properties" ) + _T( "..." ) );
713             if( m_pSelectedRoute && m_pSelectedRoute->IsActive() ) {
714                 if(m_pSelectedRoute->m_pRouteActivePoint != m_pFoundRoutePoint )
715                     MenuAppend1( menuWaypoint, ID_RT_MENU_ACTPOINT, _( "Activate" ) );
716             }
717 
718             if( m_pSelectedRoute && m_pSelectedRoute->IsActive() ) {
719                 if(m_pSelectedRoute->m_pRouteActivePoint == m_pFoundRoutePoint ) {
720                     int indexActive = m_pSelectedRoute->GetIndexOf( m_pSelectedRoute->m_pRouteActivePoint );
721                     if( ( indexActive + 1 ) <= m_pSelectedRoute->GetnPoints() )
722                         MenuAppend1( menuWaypoint, ID_RT_MENU_ACTNXTPOINT, _( "Activate Next Waypoint" ) );
723                 }
724             }
725             if( m_pSelectedRoute && m_pSelectedRoute->GetnPoints() > 2 )
726                 MenuAppend1( menuWaypoint, ID_RT_MENU_REMPOINT, _( "Remove from Route" ) );
727 
728             MenuAppend1( menuWaypoint, ID_WPT_MENU_COPY, _( "Copy as KML" ) );
729 
730             if( m_pFoundRoutePoint && m_pFoundRoutePoint->GetIconName() != _T("mob") )
731                 MenuAppend1( menuWaypoint, ID_RT_MENU_DELPOINT,  _( "Delete" ) );
732 
733 //#ifndef __OCPN__ANDROID__
734             wxString port = parent->FindValidUploadPort();
735             parent->m_active_upload_port = port;
736             wxString item = _( "Send to GPS" );
737             if( !port.IsEmpty() ) {
738                 item.Append( _T(" ( ") );
739                 item.Append( port );
740                 item.Append(_T(" )") );
741             }
742             MenuAppend1( menuWaypoint, ID_WPT_MENU_SENDTOGPS, item );
743 
744             if( !port.IsEmpty() ) {
745                 wxString item = _( "Send to new GPS" );
746                 MenuAppend1( menuWaypoint, ID_WPT_MENU_SENDTONEWGPS, item );
747             }
748 //#endif
749 
750         }
751         //Eventually set this menu as the "focused context menu"
752 		if (menuFocus != menuAIS)
753 			menuFocus = menuWaypoint;
754     }
755 
756     if( seltype & SELTYPE_MARKPOINT ) {
757 		if (!g_bBasicMenus && m_pFoundRoutePoint) {
758 			name = m_pFoundRoutePoint->GetName();
759 			if (name.IsEmpty())
760 				name = _("Unnamed Waypoint");
761 			name.Prepend(_T(" ( ")).Append(_T(" )"));
762 		} else
763 			name = wxEmptyString;
764         bool blay = false;
765         if( m_pFoundRoutePoint && m_pFoundRoutePoint->m_bIsInLayer )
766             blay = true;
767 
768         if( blay ){
769 			menuWaypoint = new wxMenu(_("Layer Waypoint") + name);
770             MenuAppend1( menuWaypoint, ID_WP_MENU_PROPERTIES, _( "Properties" ) + _T( "..." ) );
771         }
772         else {
773 			menuWaypoint = new wxMenu(_("Waypoint") + name);
774             MenuAppend1( menuWaypoint, ID_WP_MENU_PROPERTIES, _( "Properties" ) + _T( "..." ) );
775 
776             if( !g_pRouteMan->GetpActiveRoute() )
777                 MenuAppend1( menuWaypoint, ID_WP_MENU_GOTO, _( "Navigate To This" ) );
778 
779             MenuAppend1( menuWaypoint, ID_WPT_MENU_COPY, _( "Copy as KML" ) );
780 
781             if( m_pFoundRoutePoint && m_pFoundRoutePoint->GetIconName() != _T("mob") )
782                 MenuAppend1( menuWaypoint, ID_WP_MENU_DELPOINT, _( "Delete" ) );
783 
784 //#ifndef __OCPN__ANDROID__
785             wxString port = parent->FindValidUploadPort();
786             parent->m_active_upload_port = port;
787             wxString item = _( "Send to GPS" );
788             if( !port.IsEmpty() ) {
789                 item.Append( _T(" ( ") );
790                 item.Append( port );
791                 item.Append(_T(" )") );
792             }
793             MenuAppend1( menuWaypoint, ID_WPT_MENU_SENDTOGPS, item );
794 //#endif
795 
796             if( ( m_pFoundRoutePoint == pAnchorWatchPoint1 ) || ( m_pFoundRoutePoint == pAnchorWatchPoint2 ) )
797                 MenuAppend1( menuWaypoint, ID_WP_MENU_CLEAR_ANCHORWATCH, _( "Clear Anchor Watch" ) );
798             else {
799                 if( m_pFoundRoutePoint && !( m_pFoundRoutePoint->m_bIsInLayer )
800                     && ( ( NULL == pAnchorWatchPoint1 ) || ( NULL == pAnchorWatchPoint2 ) ) ) {
801 
802                     double dist;
803                     double brg;
804                     DistanceBearingMercator( m_pFoundRoutePoint->m_lat, m_pFoundRoutePoint->m_lon, gLat,
805                                          gLon, &brg, &dist );
806                     if( dist * 1852. <= g_nAWMax )
807                         MenuAppend1( menuWaypoint,  ID_WP_MENU_SET_ANCHORWATCH,  _( "Set Anchor Watch" ) );
808                 }
809             }
810         }
811         //Eventually set this menu as the "focused context menu"
812 		if (menuFocus != menuAIS)
813 			menuFocus = menuWaypoint;
814     }
815 	/*add the relevant submenus*/
816 	enum { WPMENU = 1, TKMENU = 2, RTMENU = 4, MMMENU = 8 };
817 	int sub_menu = 0;
818 	if ( !g_bBasicMenus && menuFocus != contextMenu) {
819 		menuFocus->AppendSeparator();
820 		wxMenuItem * subMenu1;
821 		if ( menuWaypoint && menuFocus != menuWaypoint ) {
822 			subMenu1 = menuFocus->AppendSubMenu(menuWaypoint, menuWaypoint->GetTitle());
823 			SetMenuItemFont1(subMenu1);
824 			sub_menu |= WPMENU;
825 #ifdef __WXMSW__
826 			menuWaypoint->SetTitle(wxEmptyString);
827 #endif
828 		}
829 		if ( menuTrack && menuFocus != menuTrack ) {
830 			subMenu1 = menuFocus->AppendSubMenu(menuTrack, menuTrack->GetTitle());
831 			SetMenuItemFont1(subMenu1);
832 			sub_menu |= TKMENU;
833 #ifdef __WXMSW__
834 			menuTrack->SetTitle(wxEmptyString);
835 #endif
836 		}
837 		if ( menuRoute && menuFocus != menuRoute ) {
838 			subMenu1 = menuFocus->AppendSubMenu(menuRoute, menuRoute->GetTitle());
839 			SetMenuItemFont1(subMenu1);
840 			sub_menu |= RTMENU;
841 #ifdef __WXMSW__
842 			menuRoute->SetTitle(wxEmptyString);
843 #endif
844 		}
845 		subMenu1 = menuFocus->AppendSubMenu(contextMenu, _("Main Menu"));
846 		SetMenuItemFont1(subMenu1);
847 		sub_menu |= MMMENU;
848 	}
849 
850     if( ! subMenuChart->GetMenuItemCount() ) contextMenu->Destroy( subItemChart );
851 
852     //  Add the Tide/Current selections if the item was not activated by shortcut in right-click handlers
853     bool bsep = false;
854     if( seltype & SELTYPE_TIDEPOINT ){
855         menuFocus->AppendSeparator();
856         bsep = true;
857         MenuAppend1( menuFocus, ID_DEF_MENU_TIDEINFO, _( "Show Tide Information" ) );
858     }
859 
860     if( seltype & SELTYPE_CURRENTPOINT ) {
861         if( !bsep )
862             menuFocus->AppendSeparator();
863         MenuAppend1( menuFocus,  ID_DEF_MENU_CURRENTINFO, _( "Show Current Information" ) );
864     }
865 
866     // Give the plugins a chance to update their menu items
867     g_pi_manager->PrepareAllPluginContextMenus();
868 
869     //  Add PlugIn Context Menu items
870     ArrayOfPlugInMenuItems item_array = g_pi_manager->GetPluginContextMenuItemArray();
871 
872     for( unsigned int i = 0; i < item_array.GetCount(); i++ ) {
873         PlugInMenuItemContainer *pimis = item_array[i];
874         if( !pimis->b_viz )
875             continue;
876 
877         wxMenu *submenu = NULL;
878         if(pimis->pmenu_item->GetSubMenu()) {
879             submenu = new wxMenu();
880             const wxMenuItemList &items = pimis->pmenu_item->GetSubMenu()->GetMenuItems();
881             for( wxMenuItemList::const_iterator it = items.begin(); it != items.end(); ++it ) {
882                 int id = -1;
883                 for( unsigned int j = 0; j < item_array.GetCount(); j++ ) {
884                     PlugInMenuItemContainer *pimis = item_array[j];
885                     if(pimis->pmenu_item == *it)
886                         id = pimis->id;
887                 }
888 
889                 wxMenuItem *pmi = new wxMenuItem( submenu, id,
890 #if wxCHECK_VERSION(3,0,0)
891                                                         (*it)->GetItemLabelText(),
892 #else
893                                                         (*it)->GetLabel(),
894 #endif
895                                                         (*it)->GetHelp(),
896                                                           (*it)->GetKind());
897                 submenu->Append(pmi);
898                 pmi->Check((*it)->IsChecked());
899             }
900         }
901 
902         wxMenuItem *pmi = new wxMenuItem( contextMenu, pimis->id,
903 #if wxCHECK_VERSION(3,0,0)
904                                                   pimis->pmenu_item->GetItemLabelText(),
905 #else
906                                                   pimis->pmenu_item->GetLabel(),
907 #endif
908                                                   pimis->pmenu_item->GetHelp(),
909                                                   pimis->pmenu_item->GetKind(),
910                                                   submenu );
911 #ifdef __WXMSW__
912         pmi->SetFont(pimis->pmenu_item->GetFont());
913 #endif
914         wxMenu *dst = contextMenu;
915         if (pimis->m_in_menu == "Waypoint")
916             dst = menuWaypoint;
917         else if (pimis->m_in_menu == "Route" )
918             dst = menuRoute;
919         else if (pimis->m_in_menu == "Track" )
920             dst = menuTrack;
921         else if (pimis->m_in_menu == "AIS" )
922             dst = menuAIS;
923 
924         if (dst != NULL) {
925             dst->Append( pmi );
926             dst->Enable( pimis->id, !pimis->b_grey );
927         }
928     }
929 
930     //        Invoke the correct focused drop-down menu
931 
932 #ifdef __OCPN__ANDROID__
933     androidEnableBackButton( false );
934     androidEnableOptionsMenu( false );
935 
936     setMenuStyleSheet(menuRoute, GetOCPNGUIScaledFont(_T("Menu")));
937     setMenuStyleSheet(menuWaypoint, GetOCPNGUIScaledFont(_T("Menu")));
938     setMenuStyleSheet(menuTrack, GetOCPNGUIScaledFont(_T("Menu")));
939     setMenuStyleSheet(menuAIS, GetOCPNGUIScaledFont(_T("Menu")));
940 #endif
941 
942 
943     parent->PopupMenu( menuFocus, x, y );
944 
945 #ifdef __OCPN__ANDROID__
946     androidEnableBackButton( true );
947     androidEnableOptionsMenu( true );
948 #endif
949 
950     /* Cleanup if necessary.
951 	Do not delete menus witch are submenu as they will be deleted by their parent menu.
952 	This could create a crash*/
953 	delete menuAIS;
954 	if (!(sub_menu & MMMENU) ) delete contextMenu;
955 	if (!(sub_menu & RTMENU) ) delete menuRoute;
956 	if (!(sub_menu & TKMENU) ) delete menuTrack;
957 	if (!(sub_menu & WPMENU) ) delete menuWaypoint;
958 }
959 
960 
PopupMenuHandler(wxCommandEvent & event)961 void CanvasMenuHandler::PopupMenuHandler( wxCommandEvent& event )
962 {
963     RoutePoint *pLast;
964 
965     wxPoint r;
966     double zlat, zlon;
967 
968     parent->GetCanvasPixPoint( popx, popy, zlat, zlon );
969 
970     switch( event.GetId() ) {
971     case ID_DEF_MENU_MAX_DETAIL:
972         vLat = zlat;
973         vLon = zlon;
974         parent->ClearbFollow();
975 
976         parent->parent_frame->DoChartUpdate();
977 
978         parent->SelectChartFromStack( 0, false, CHART_TYPE_DONTCARE,
979                                             CHART_FAMILY_RASTER );
980         break;
981 
982     case ID_DEF_MENU_SCALE_IN:
983         parent->DoCanvasStackDelta( -1 );
984 	break;
985 
986     case ID_DEF_MENU_SCALE_OUT:
987         parent->DoCanvasStackDelta( 1 );
988         break;
989 
990     case ID_UNDO:
991         parent->undo->UndoLastAction();
992         parent->InvalidateGL();
993         parent->Refresh( false );
994         break;
995 
996     case ID_REDO:
997         parent->undo->RedoNextAction();
998         parent->InvalidateGL();
999         parent->Refresh( false );
1000         break;
1001 
1002     case ID_DEF_MENU_MOVE_BOAT_HERE:
1003         gLat = zlat;
1004         gLon = zlon;
1005         break;
1006 
1007     case ID_DEF_MENU_GOTO_HERE: {
1008         RoutePoint *pWP_dest = new RoutePoint( zlat, zlon, g_default_wp_icon, wxEmptyString,
1009                                                wxEmptyString );
1010         pSelect->AddSelectableRoutePoint( zlat, zlon, pWP_dest );
1011 
1012         RoutePoint *pWP_src = new RoutePoint( gLat, gLon, g_default_wp_icon, wxEmptyString,
1013                                               wxEmptyString );
1014         pSelect->AddSelectableRoutePoint( gLat, gLon, pWP_src );
1015 
1016         Route *temp_route = new Route();
1017         pRouteList->Append( temp_route );
1018 
1019         temp_route->AddPoint( pWP_src );
1020         temp_route->AddPoint( pWP_dest );
1021 
1022         pSelect->AddSelectableRouteSegment( gLat, gLon, zlat, zlon, pWP_src, pWP_dest,
1023                                             temp_route );
1024 
1025         temp_route->m_RouteNameString = _("Temporary GOTO Route");
1026         temp_route->m_RouteStartString = _("Here");
1027         ;
1028         temp_route->m_RouteEndString = _("There");
1029 
1030         temp_route->m_bDeleteOnArrival = true;
1031 
1032         if( g_pRouteMan->GetpActiveRoute() ) g_pRouteMan->DeactivateRoute();
1033 
1034         g_pRouteMan->ActivateRoute( temp_route, pWP_dest );
1035 
1036         break;
1037     }
1038 
1039     case ID_DEF_MENU_DROP_WP: {
1040         RoutePoint *pWP = new RoutePoint( zlat, zlon, g_default_wp_icon, wxEmptyString,
1041                                           wxEmptyString );
1042         pWP->m_bIsolatedMark = true;                      // This is an isolated mark
1043         pSelect->AddSelectableRoutePoint( zlat, zlon, pWP );
1044         pConfig->AddNewWayPoint( pWP, -1 );    // use auto next num
1045         if( !pWP->IsVisibleSelectable(this->parent) ) pWP->ShowScaleWarningMessage(parent);
1046 
1047         if(RouteManagerDialog::getInstanceFlag()){
1048             if( pRouteManagerDialog && pRouteManagerDialog->IsShown() ){
1049                 pRouteManagerDialog->UpdateWptListCtrl();
1050             }
1051         }
1052 
1053         parent->undo->BeforeUndoableAction( Undo_CreateWaypoint, pWP, Undo_HasParent, NULL );
1054         parent->undo->AfterUndoableAction( NULL );
1055         gFrame->RefreshAllCanvas( false );
1056         gFrame->InvalidateAllGL();
1057         g_FlushNavobjChanges = true;
1058         break;
1059     }
1060 
1061     case ID_DEF_MENU_NEW_RT: {
1062         parent->StartRoute();
1063         break;
1064     }
1065 
1066     case ID_DEF_MENU_AISTARGETLIST:
1067         parent->ShowAISTargetList();
1068         break;
1069 
1070     case ID_WP_MENU_GOTO: {
1071         RoutePoint *pWP_src = new RoutePoint( gLat, gLon, g_default_wp_icon, wxEmptyString,
1072                                               wxEmptyString );
1073         pSelect->AddSelectableRoutePoint( gLat, gLon, pWP_src );
1074 
1075         Route *temp_route = new Route();
1076         pRouteList->Append( temp_route );
1077 
1078         temp_route->AddPoint( pWP_src );
1079         temp_route->AddPoint( m_pFoundRoutePoint );
1080         m_pFoundRoutePoint->m_bKeepXRoute = true;
1081 
1082         pSelect->AddSelectableRouteSegment( gLat, gLon, m_pFoundRoutePoint->m_lat,
1083                                             m_pFoundRoutePoint->m_lon, pWP_src, m_pFoundRoutePoint, temp_route );
1084 
1085         wxString name = m_pFoundRoutePoint->GetName();
1086         if( name.IsEmpty() ) name = _("(Unnamed Waypoint)");
1087         wxString rteName = _("Go to ");
1088         rteName.Append( name );
1089         temp_route->m_RouteNameString = rteName;
1090         temp_route->m_RouteStartString = _("Here");
1091         ;
1092         temp_route->m_RouteEndString = name;
1093         temp_route->m_bDeleteOnArrival = true;
1094 
1095         if( g_pRouteMan->GetpActiveRoute() ) g_pRouteMan->DeactivateRoute();
1096 
1097         g_pRouteMan->ActivateRoute( temp_route, m_pFoundRoutePoint );
1098 
1099         break;
1100     }
1101 
1102     case ID_DEF_MENU_COGUP:
1103         parent->SetUpMode(COURSE_UP_MODE);
1104         break;
1105 
1106    case ID_DEF_MENU_HEADUP:
1107         parent->SetUpMode(HEAD_UP_MODE);
1108         break;
1109 
1110     case ID_DEF_MENU_NORTHUP:
1111         parent->SetUpMode(NORTH_UP_MODE);
1112         break;
1113 
1114     case ID_DEF_MENU_TOGGLE_FULL:
1115         gFrame->ToggleFullScreen();
1116         break;
1117 
1118     case ID_DEF_MENU_GOTOPOSITION:
1119         if( NULL == pGoToPositionDialog ) // There is one global instance of the Go To Position Dialog
1120             pGoToPositionDialog = new GoToPositionDialog( parent );
1121         pGoToPositionDialog->SetCanvas(parent);
1122         pGoToPositionDialog->CheckPasteBufferForPosition();
1123         pGoToPositionDialog->Show();
1124         break;
1125 
1126     case ID_WP_MENU_DELPOINT: {
1127         if( m_pFoundRoutePoint == pAnchorWatchPoint1 ) {
1128             pAnchorWatchPoint1 = NULL;
1129             g_AW1GUID.Clear();
1130         } else if( m_pFoundRoutePoint == pAnchorWatchPoint2 ) {
1131             pAnchorWatchPoint2 = NULL;
1132             g_AW2GUID.Clear();
1133         }
1134 
1135         if( m_pFoundRoutePoint && !( m_pFoundRoutePoint->m_bIsInLayer )
1136                 && ( m_pFoundRoutePoint->GetIconName() != _T("mob") ) ) {
1137 
1138             // If the WP belongs to an invisible route, we come here instead of to ID_RT_MENU_DELPOINT
1139             //  Check it, and if so then remove the point from its routes
1140             wxArrayPtrVoid *proute_array = g_pRouteMan->GetRouteArrayContaining( m_pFoundRoutePoint );
1141             if( proute_array ) {
1142                 pWayPointMan->DestroyWaypoint( m_pFoundRoutePoint );
1143              }
1144             else {
1145                 parent->undo->BeforeUndoableAction( Undo_DeleteWaypoint, m_pFoundRoutePoint, Undo_IsOrphanded, NULL/*m_pFoundPoint*/ );
1146                 pConfig->DeleteWayPoint( m_pFoundRoutePoint );
1147                 pSelect->DeleteSelectablePoint( m_pFoundRoutePoint, SELTYPE_ROUTEPOINT );
1148                 if( NULL != pWayPointMan )
1149                     pWayPointMan->RemoveRoutePoint( m_pFoundRoutePoint );
1150                 parent->undo->AfterUndoableAction( NULL );
1151             }
1152 
1153             if( g_pMarkInfoDialog ) {
1154                 g_pMarkInfoDialog->SetRoutePoint( NULL );
1155                 g_pMarkInfoDialog->UpdateProperties();
1156             }
1157 
1158             if( pRouteManagerDialog ){
1159                 if( pRouteManagerDialog->IsShown() )
1160                 pRouteManagerDialog->UpdateWptListCtrl();
1161             }
1162 
1163             gFrame->RefreshAllCanvas( false );
1164             gFrame->InvalidateAllGL();
1165         }
1166         break;
1167     }
1168     case ID_WP_MENU_PROPERTIES:
1169         parent->ShowMarkPropertiesDialog( m_pFoundRoutePoint );
1170         break;
1171 
1172     case ID_WP_MENU_CLEAR_ANCHORWATCH:
1173         if( pAnchorWatchPoint1 == m_pFoundRoutePoint ) {
1174             pAnchorWatchPoint1 = NULL;
1175             g_AW1GUID.Clear();
1176         } else if( pAnchorWatchPoint2 == m_pFoundRoutePoint ) {
1177             pAnchorWatchPoint2 = NULL;
1178             g_AW2GUID.Clear();
1179         }
1180         break;
1181 
1182     case ID_WP_MENU_SET_ANCHORWATCH:
1183         if( pAnchorWatchPoint1 == NULL ) {
1184             pAnchorWatchPoint1 = m_pFoundRoutePoint;
1185             g_AW1GUID = pAnchorWatchPoint1->m_GUID;
1186             wxString nn;
1187             nn = m_pFoundRoutePoint->GetName();
1188             if( nn.IsNull() ) {
1189                 nn.Printf( _T("%d m"), g_nAWDefault );
1190                 m_pFoundRoutePoint->SetName( nn );
1191             }
1192         } else if( pAnchorWatchPoint2 == NULL ) {
1193             pAnchorWatchPoint2 = m_pFoundRoutePoint;
1194             g_AW2GUID = pAnchorWatchPoint2->m_GUID;
1195             wxString nn;
1196             nn = m_pFoundRoutePoint->GetName();
1197             if( nn.IsNull() ) {
1198                 nn.Printf( _T("%d m"), g_nAWDefault );
1199                 m_pFoundRoutePoint->SetName( nn );
1200             }
1201         }
1202         break;
1203 
1204     case ID_DEF_MENU_ACTIVATE_MEASURE:
1205         parent->StartMeasureRoute();
1206         break;
1207 
1208     case ID_DEF_MENU_DEACTIVATE_MEASURE:
1209         parent->CancelMeasureRoute();
1210         gFrame->SurfaceAllCanvasToolbars();
1211         parent->InvalidateGL();
1212         parent->Refresh( false );
1213         break;
1214 
1215     case ID_DEF_MENU_CM93OFFSET_DIALOG:
1216     {
1217         if( NULL == g_pCM93OffsetDialog ) {
1218             g_pCM93OffsetDialog = new CM93OffsetDialog( parent->parent_frame );
1219         }
1220 
1221         cm93compchart *pch = NULL;
1222         if( !parent->GetVP().b_quilt && parent->m_singleChart  && ( parent->m_singleChart->GetChartType() == CHART_TYPE_CM93COMP ) ) {
1223             pch = (cm93compchart *) parent->m_singleChart;
1224         }
1225 
1226         if( g_pCM93OffsetDialog ){
1227             g_pCM93OffsetDialog->SetCM93Chart( pch );
1228             g_pCM93OffsetDialog->Show();
1229             g_pCM93OffsetDialog->UpdateMCOVRList( parent->GetVP() );
1230         }
1231 
1232         break;
1233     }
1234     case ID_DEF_MENU_QUERY: {
1235         parent->ShowObjectQueryWindow( popx, popy, zlat, zlon );
1236         break;
1237     }
1238     case ID_DEF_MENU_AIS_QUERY: {
1239         wxWindow *pwin = wxDynamicCast(parent, wxWindow);
1240         ShowAISTargetQueryDialog( pwin, m_FoundAIS_MMSI );
1241         break;
1242     }
1243 
1244     case ID_DEF_MENU_AIS_CPA: {
1245         AIS_Target_Data *myptarget = g_pAIS->Get_Target_Data_From_MMSI(m_FoundAIS_MMSI);
1246         if ( myptarget )
1247             myptarget->Toggle_AIS_CPA();
1248         break;
1249     }
1250 
1251     case ID_DEF_MENU_AISSHOWTRACK: {
1252         AIS_Target_Data *myptarget = g_pAIS->Get_Target_Data_From_MMSI(m_FoundAIS_MMSI);
1253         if ( myptarget )
1254             myptarget->ToggleShowTrack();
1255         break;
1256     }
1257 
1258     case ID_DEF_MENU_COPY_MMSI:
1259     {
1260         // Write MMSI # as text to the clipboard
1261         if (wxTheClipboard->Open())
1262         {
1263             wxTheClipboard->SetData(new wxTextDataObject(wxString::Format(wxT("%09d"), m_FoundAIS_MMSI)));
1264             wxTheClipboard->Close();
1265         }
1266         break;
1267     }
1268 
1269     case ID_DEF_MENU_QUILTREMOVE: {
1270         if( parent->GetVP().b_quilt ) {
1271             int dbIndex = parent->m_pQuilt->GetChartdbIndexAtPix( parent->GetVP(), wxPoint( popx, popy ) );
1272             parent->RemoveChartFromQuilt( dbIndex );
1273 
1274             parent->ReloadVP();
1275 
1276         }
1277 
1278         break;
1279     }
1280 
1281     case ID_DEF_MENU_CURRENTINFO: {
1282         parent->DrawTCWindow( popx, popy, (void *) m_pIDXCandidate );
1283         parent->Refresh( false );
1284 
1285         break;
1286     }
1287 
1288     case ID_DEF_MENU_TIDEINFO: {
1289         parent->DrawTCWindow( popx, popy, (void *) m_pIDXCandidate );
1290         parent->Refresh( false );
1291 
1292         break;
1293     }
1294     case ID_RT_MENU_REVERSE: {
1295         if( m_pSelectedRoute->m_bIsInLayer ) break;
1296 
1297         int ask_return = OCPNMessageBox( parent, g_pRouteMan->GetRouteReverseMessage(),
1298                                _("Rename Waypoints?"), wxYES_NO | wxCANCEL );
1299 
1300         if( ask_return != wxID_CANCEL ) {
1301             pSelect->DeleteAllSelectableRouteSegments( m_pSelectedRoute );
1302             m_pSelectedRoute->Reverse( ask_return == wxID_YES );
1303             pSelect->AddAllSelectableRouteSegments( m_pSelectedRoute );
1304 
1305             pConfig->UpdateRoute( m_pSelectedRoute );
1306 
1307             if( pRoutePropDialog && ( pRoutePropDialog->IsShown() ) ) {
1308                 pRoutePropDialog->SetRouteAndUpdate( m_pSelectedRoute );
1309                 //pNew->UpdateProperties();
1310             }
1311             gFrame->InvalidateAllGL();
1312             gFrame->RefreshAllCanvas();
1313 
1314         }
1315         break;
1316     }
1317 
1318     case ID_RT_MENU_DELETE: {
1319         int dlg_return = wxID_YES;
1320         if( g_bConfirmObjectDelete ) {
1321             dlg_return = OCPNMessageBox( parent,  _("Are you sure you want to delete this route?"),
1322                 _("OpenCPN Route Delete"), (long) wxYES_NO | wxCANCEL | wxYES_DEFAULT );
1323         }
1324 
1325         if( dlg_return == wxID_YES ) {
1326             if( g_pRouteMan->GetpActiveRoute() == m_pSelectedRoute ) g_pRouteMan->DeactivateRoute();
1327 
1328             if( m_pSelectedRoute->m_bIsInLayer )
1329                 break;
1330 
1331             if( !g_pRouteMan->DeleteRoute( m_pSelectedRoute ) )
1332                 break;
1333 
1334             if( pRouteManagerDialog && pRouteManagerDialog->IsShown() )
1335                 pRouteManagerDialog->UpdateRouteListCtrl();
1336 
1337             if( g_pMarkInfoDialog && g_pMarkInfoDialog->IsShown() ) {
1338                 g_pMarkInfoDialog->ValidateMark();
1339                 g_pMarkInfoDialog->UpdateProperties();
1340             }
1341 
1342             parent->undo->InvalidateUndo();
1343 
1344             gFrame->InvalidateAllGL();
1345             gFrame->RefreshAllCanvas();
1346         }
1347         break;
1348     }
1349 
1350     case ID_RT_MENU_ACTIVATE: {
1351         if( g_pRouteMan->GetpActiveRoute() )
1352             g_pRouteMan->DeactivateRoute();
1353 
1354         //  If this is an auto-created MOB route, always select the second point (the MOB)
1355         // as the destination.
1356         RoutePoint *best_point;
1357         if(m_pSelectedRoute){
1358             if(wxNOT_FOUND == m_pSelectedRoute->m_RouteNameString.Find(_T("MOB")) ){
1359                 best_point = g_pRouteMan->FindBestActivatePoint( m_pSelectedRoute, gLat,
1360                                  gLon, gCog, gSog );
1361             }
1362             else
1363                 best_point = m_pSelectedRoute->GetPoint( 2 );
1364 
1365             g_pRouteMan->ActivateRoute( m_pSelectedRoute, best_point );
1366             m_pSelectedRoute->m_bRtIsSelected = false;
1367         }
1368 
1369 
1370         break;
1371     }
1372 
1373     case ID_RT_MENU_DEACTIVATE:
1374         g_pRouteMan->DeactivateRoute();
1375         m_pSelectedRoute->m_bRtIsSelected = false;
1376 
1377         break;
1378 
1379     case ID_RT_MENU_INSERT:
1380 
1381         if( m_pSelectedRoute->m_bIsInLayer ) break;
1382 
1383         m_pSelectedRoute->InsertPointAfter( m_pFoundRoutePoint, zlat, zlon );
1384 
1385         pSelect->DeleteAllSelectableRoutePoints( m_pSelectedRoute );
1386         pSelect->DeleteAllSelectableRouteSegments( m_pSelectedRoute );
1387 
1388         pSelect->AddAllSelectableRouteSegments( m_pSelectedRoute );
1389         pSelect->AddAllSelectableRoutePoints( m_pSelectedRoute );
1390 
1391         //    As a special case (which comes up often)...
1392         //    If the inserted waypoint is on the active leg of an active route
1393         /*            if(m_pSelectedRoute->m_bRtIsActive)
1394          {
1395          if(m_pSelectedRoute->m_nRouteActivePoint == np + 1)
1396          {
1397          pNew_Point = m_pSelectedRoute->GetPoint(np + 2);
1398          pRouteMan->ActivateRoutePoint(m_pSelectedRoute, pNew_Point);
1399          }
1400          }
1401          */
1402         pConfig->UpdateRoute( m_pSelectedRoute );
1403 
1404         if( pRoutePropDialog && ( pRoutePropDialog->IsShown() ) ) {
1405             pRoutePropDialog->SetRouteAndUpdate( m_pSelectedRoute, true );
1406         }
1407 
1408         break;
1409 
1410     case ID_RT_MENU_APPEND:
1411 
1412         if( m_pSelectedRoute->m_bIsInLayer ) break;
1413 
1414         parent->m_pMouseRoute = m_pSelectedRoute;
1415         parent->m_routeState = m_pSelectedRoute->GetnPoints() + 1;
1416         parent->m_pMouseRoute->m_lastMousePointIndex = m_pSelectedRoute->GetnPoints();
1417         parent->m_pMouseRoute->SetHiLite(50);
1418 
1419         pLast = m_pSelectedRoute->GetLastPoint();
1420 
1421         parent->m_prev_rlat = pLast->m_lat;
1422         parent->m_prev_rlon = pLast->m_lon;
1423         parent->m_prev_pMousePoint = pLast;
1424 
1425         parent->m_bAppendingRoute = true;
1426 
1427         parent->SetCursor( *parent->pCursorPencil );
1428         #ifdef __OCPN__ANDROID__
1429         androidSetRouteAnnunciator( true );
1430         #endif
1431 
1432         parent->HideGlobalToolbar();
1433 
1434         break;
1435 
1436     case ID_RT_MENU_COPY:
1437         if( m_pSelectedRoute ) Kml::CopyRouteToClipboard( m_pSelectedRoute );
1438         break;
1439 
1440     case ID_TK_MENU_COPY:
1441         if( m_pSelectedTrack ) Kml::CopyTrackToClipboard( m_pSelectedTrack );
1442         break;
1443 
1444     case ID_WPT_MENU_COPY:
1445         if( m_pFoundRoutePoint ) Kml::CopyWaypointToClipboard( m_pFoundRoutePoint );
1446         break;
1447 
1448     case ID_WPT_MENU_SENDTOGPS:
1449         if( m_pFoundRoutePoint ) {
1450             if( parent->m_active_upload_port.Length() )
1451                 m_pFoundRoutePoint->SendToGPS( parent->m_active_upload_port.BeforeFirst(' '), NULL );
1452              else {
1453                  SendToGpsDlg dlg;
1454                  dlg.SetWaypoint( m_pFoundRoutePoint );
1455                  wxFont fo = GetOCPNGUIScaledFont(_T("Dialog"));
1456                  dlg.SetFont(fo);
1457 
1458                  dlg.Create( NULL, -1, _( "Send to GPS" ) + _T( "..." ), _T("") );
1459                  dlg.ShowModal();
1460              }
1461         }
1462         break;
1463 
1464     case ID_WPT_MENU_SENDTONEWGPS:
1465         if( m_pFoundRoutePoint ) {
1466             SendToGpsDlg dlg;
1467             dlg.SetWaypoint( m_pFoundRoutePoint );
1468 
1469             dlg.Create( NULL, -1, _( "Send to GPS" ) + _T( "..." ), _T("") );
1470             dlg.ShowModal();
1471         }
1472         break;
1473 
1474     case ID_RT_MENU_SENDTOGPS:
1475         if( m_pSelectedRoute ) {
1476             if( parent->m_active_upload_port.Length() )
1477                 m_pSelectedRoute->SendToGPS( parent->m_active_upload_port.BeforeFirst(' '), true, NULL );
1478             else {
1479                 SendToGpsDlg dlg;
1480                 dlg.SetRoute( m_pSelectedRoute );
1481 
1482                 dlg.Create( NULL, -1, _( "Send to GPS" ) + _T( "..." ), _T("") );
1483                 dlg.ShowModal();
1484             }
1485 
1486         }
1487         break;
1488 
1489     case ID_RT_MENU_SENDTONEWGPS:
1490         if( m_pSelectedRoute ) {
1491             SendToGpsDlg dlg;
1492             dlg.SetRoute( m_pSelectedRoute );
1493 
1494             dlg.Create( NULL, -1, _( "Send to GPS" ) + _T( "..." ), _T("") );
1495             dlg.ShowModal();
1496         }
1497         break;
1498 
1499     case ID_PASTE_WAYPOINT:
1500         pupHandler_PasteWaypoint();
1501         break;
1502 
1503     case ID_PASTE_ROUTE:
1504         pupHandler_PasteRoute();
1505         break;
1506 
1507     case ID_PASTE_TRACK:
1508         pupHandler_PasteTrack();
1509         break;
1510 
1511     case ID_RT_MENU_DELPOINT:
1512         if( m_pSelectedRoute ) {
1513             if( m_pSelectedRoute->m_bIsInLayer ) break;
1514 
1515             pWayPointMan->DestroyWaypoint( m_pFoundRoutePoint );
1516 
1517             if( pRoutePropDialog && ( pRoutePropDialog->IsShown() ) ) {
1518                 //    Selected route may have been deleted as one-point route, so check it
1519                 if( g_pRouteMan->IsRouteValid( m_pSelectedRoute ) ){
1520                     pRoutePropDialog->SetRouteAndUpdate( m_pSelectedRoute, true );
1521                 }
1522                 else
1523                     pRoutePropDialog->Hide();
1524 
1525             }
1526 
1527             if( pRouteManagerDialog && pRouteManagerDialog->IsShown() ) {
1528                 pRouteManagerDialog->UpdateWptListCtrl();
1529                 pRouteManagerDialog->UpdateRouteListCtrl();
1530             }
1531 
1532             gFrame->InvalidateAllGL();
1533             gFrame->RefreshAllCanvas( true );
1534         }
1535 
1536         break;
1537 
1538     case ID_RT_MENU_REMPOINT:
1539         if( m_pSelectedRoute ) {
1540             if( m_pSelectedRoute->m_bIsInLayer ) break;
1541             g_pRouteMan->RemovePointFromRoute( m_pFoundRoutePoint, m_pSelectedRoute, parent );
1542             gFrame->InvalidateAllGL();
1543             gFrame->RefreshAllCanvas();
1544         }
1545         break;
1546 
1547     case ID_RT_MENU_ACTPOINT:
1548         if( g_pRouteMan->GetpActiveRoute() == m_pSelectedRoute ) {
1549             g_pRouteMan->ActivateRoutePoint( m_pSelectedRoute, m_pFoundRoutePoint );
1550             m_pSelectedRoute->m_bRtIsSelected = false;
1551         }
1552 
1553         break;
1554 
1555     case ID_RT_MENU_DEACTPOINT:
1556         break;
1557 
1558     case ID_RT_MENU_ACTNXTPOINT:
1559         if( g_pRouteMan->GetpActiveRoute() == m_pSelectedRoute ) {
1560             g_pRouteMan->ActivateNextPoint( m_pSelectedRoute, true );
1561             m_pSelectedRoute->m_bRtIsSelected = false;
1562         }
1563 
1564         break;
1565 
1566     case ID_RT_MENU_PROPERTIES: {
1567         parent->ShowRoutePropertiesDialog( _("Route Properties"), m_pSelectedRoute );
1568         break;
1569     }
1570 
1571     case ID_TK_MENU_PROPERTIES: {
1572         parent->ShowTrackPropertiesDialog( m_pSelectedTrack );
1573         break;
1574     }
1575 
1576     case ID_TK_MENU_DELETE: {
1577         int dlg_return = wxID_YES;
1578         if( g_bConfirmObjectDelete ) {
1579             dlg_return = OCPNMessageBox( parent, _("Are you sure you want to delete this track?"),
1580                 _("OpenCPN Track Delete"), (long) wxYES_NO | wxCANCEL | wxYES_DEFAULT );
1581         }
1582 
1583         if( dlg_return == wxID_YES ) {
1584 
1585             if( m_pSelectedTrack == g_pActiveTrack )
1586                 parent->parent_frame->TrackOff();
1587             g_pAIS->DeletePersistentTrack( m_pSelectedTrack );
1588             pConfig->DeleteConfigTrack( m_pSelectedTrack );
1589             g_pRouteMan->DeleteTrack( m_pSelectedTrack );
1590 
1591             if( TrackPropDlg::getInstanceFlag() && pTrackPropDialog &&
1592                 ( pTrackPropDialog->IsShown()) && (m_pSelectedTrack == pTrackPropDialog->GetTrack()) ) {
1593                 pTrackPropDialog->Hide();
1594             }
1595 
1596             if( RoutePropDlgImpl::getInstanceFlag() && pRouteManagerDialog && pRouteManagerDialog->IsShown() ) {
1597                 pRouteManagerDialog->UpdateTrkListCtrl();
1598                 pRouteManagerDialog->UpdateRouteListCtrl();
1599             }
1600             gFrame->InvalidateAllGL();
1601             gFrame->RefreshAllCanvas();
1602         }
1603         break;
1604     }
1605 
1606     case ID_RC_MENU_SCALE_IN:
1607         parent->parent_frame->DoStackDown( parent );
1608         parent->GetCanvasPointPix( zlat, zlon, &r );
1609         parent->WarpPointer( r.x, r.y );
1610         break;
1611 
1612     case ID_RC_MENU_SCALE_OUT:
1613         parent->parent_frame->DoStackUp( parent );
1614         parent->GetCanvasPointPix( zlat, zlon, &r );
1615         parent->WarpPointer( r.x, r.y );
1616         break;
1617 
1618     case ID_RC_MENU_ZOOM_IN:
1619         parent->SetVPScale( parent->GetVPScale() * 2 );
1620         parent->GetCanvasPointPix( zlat, zlon, &r );
1621         parent->WarpPointer( r.x, r.y );
1622         break;
1623 
1624     case ID_RC_MENU_ZOOM_OUT:
1625         parent->SetVPScale( parent->GetVPScale() / 2 );
1626         parent->GetCanvasPointPix( zlat, zlon, &r );
1627         parent->WarpPointer( r.x, r.y );
1628         break;
1629 
1630     case ID_RC_MENU_FINISH:
1631         parent->FinishRoute();
1632         gFrame->SurfaceAllCanvasToolbars();
1633         parent->Refresh( false );
1634         g_FlushNavobjChanges = true;
1635         break;
1636 
1637     case ID_DEF_ZERO_XTE:
1638         g_pRouteMan->ZeroCurrentXTEToActivePoint();
1639         break;
1640 
1641     default: {
1642         //  Look for PlugIn Context Menu selections
1643         //  If found, make the callback
1644         ArrayOfPlugInMenuItems item_array = g_pi_manager->GetPluginContextMenuItemArray();
1645 
1646         for( unsigned int i = 0; i < item_array.GetCount(); i++ ) {
1647             PlugInMenuItemContainer *pimis = item_array[i];
1648             {
1649                 if( pimis->id == event.GetId() ) {
1650                     if( pimis->m_pplugin )
1651                         pimis->m_pplugin->OnContextMenuItemCallback( pimis->id );
1652                 }
1653             }
1654         }
1655 
1656         break;
1657     }
1658     }           // switch
1659 
1660     //  Chart Groups....
1661     if( ( event.GetId() >= ID_DEF_MENU_GROUPBASE )
1662             && ( event.GetId() <= ID_DEF_MENU_GROUPBASE + (int) g_pGroupArray->GetCount() ) ) {
1663         parent->SetGroupIndex( event.GetId() - ID_DEF_MENU_GROUPBASE );
1664     }
1665 
1666     parent->InvalidateGL();
1667 
1668     g_click_stop = 0;    // Context menu was processed, all is well
1669 
1670 }
1671 
1672