OpenCPN Partial API docs
Loading...
Searching...
No Matches
canvasMenu.cpp
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#include <wx/aui/aui.h>
30#include <wx/clipbrd.h>
31#include <wx/dynarray.h>
32#include <wx/event.h>
33#include <wx/font.h>
34#include <wx/gdicmn.h>
35#include <wx/graphics.h>
36#include <wx/image.h>
37#include <wx/listbook.h>
38#include <wx/listimpl.cpp>
39#include <wx/menu.h>
40
41#include "model/ais_decoder.h"
43#include "model/ais_target_data.h"
44#include "model/config_vars.h"
45#include "model/cutil.h"
46#include "model/georef.h"
47#include "model/gui.h"
48#include "model/mdns_cache.h"
49#include "model/mdns_query.h"
50#include "model/nav_object_database.h"
51#include "model/own_ship.h"
52#include "model/own_ship.h"
53#include "model/plugin_comm.h"
54#include "model/route.h"
55#include "model/routeman.h"
56#include "model/select.h"
57#include "model/track.h"
58
59#include "ais.h"
60#include "canvasMenu.h"
61#include "chartdb.h"
62#include "chcanv.h"
63#include "cm93.h" // for chart outline draw
64#include "config.h"
65#include "FontMgr.h"
66#include "kml.h"
67#include "MarkInfo.h"
68#include "navutil.h"
69#include "ocpn_frame.h"
70#include "OCPNPlatform.h"
71#include "peer_client_dlg.h"
72#include "pluginmanager.h"
73#include "Quilt.h"
74#include "route_gui.h"
75#include "routemanagerdialog.h"
76#include "routeman_gui.h"
77#include "route_point_gui.h"
78#include "RoutePropDlgImpl.h"
79#include "s52plib.h"
80#include "s52s57.h"
81#include "s57chart.h" // for ArrayOfS57Obj
82#include "SendToGpsDlg.h"
83#include "SendToPeerDlg.h"
84#include "styles.h"
85#include "tcmgr.h"
86#include "TCWin.h"
87#include "tide_time.h"
88#include "track_gui.h"
89#include "TrackPropDlg.h"
90#include "undo.h"
91
92#ifdef __ANDROID__
93#include "androidUTIL.h"
94#endif
95
96// ----------------------------------------------------------------------------
97// Useful Prototypes
98// ----------------------------------------------------------------------------
99extern void pupHandler_PasteRoute();
100extern void pupHandler_PasteTrack();
101extern void pupHandler_PasteWaypoint();
102
103extern Routeman *g_pRouteMan;
104extern bool g_bskew_comp;
105extern double vLat, vLon;
106extern MyFrame *gFrame;
107extern ChartGroupArray *g_pGroupArray;
108extern PlugInManager *g_pi_manager;
109extern int g_nAWMax;
110extern int g_nAWDefault;
111extern wxString g_AW1GUID;
112extern wxString g_AW2GUID;
113extern int g_click_stop;
114extern RouteManagerDialog *pRouteManagerDialog;
115extern MarkInfoDlg *g_pMarkInfoDialog;
116extern RoutePropDlgImpl *pRoutePropDialog;
117extern ActiveTrack *g_pActiveTrack;
118extern bool g_bConfirmObjectDelete;
119extern MyConfig *pConfig;
120extern OCPNPlatform *g_Platform;
121
122extern CM93OffsetDialog *g_pCM93OffsetDialog;
123
124extern GoToPositionDialog *pGoToPositionDialog;
125extern RouteList *pRouteList;
126extern wxString g_default_wp_icon;
127extern bool g_bBasicMenus;
128extern TrackPropDlg *pTrackPropDialog;
129extern bool g_FlushNavobjChanges;
130extern ColorScheme global_color_scheme;
131
132// Constants for right click menus
133enum {
134 ID_DEF_MENU_MAX_DETAIL = 1,
135 ID_DEF_MENU_SCALE_IN,
136 ID_DEF_MENU_SCALE_OUT,
137 ID_DEF_MENU_DROP_WP,
138 ID_DEF_MENU_NEW_RT,
139 ID_DEF_MENU_QUERY,
140 ID_DEF_MENU_MOVE_BOAT_HERE,
141 ID_DEF_MENU_GOTO_HERE,
142 ID_DEF_MENU_GOTOPOSITION,
143
144 ID_WP_MENU_GOTO,
145 ID_WP_MENU_DELPOINT,
146 ID_WP_MENU_PROPERTIES,
147 ID_RT_MENU_ACTIVATE,
148 ID_RT_MENU_DEACTIVATE,
149 ID_RT_MENU_INSERT,
150 ID_RT_MENU_APPEND,
151 ID_RT_MENU_COPY,
152 ID_RT_MENU_SPLIT_LEG,
153 ID_RT_MENU_SPLIT_WPT,
154 ID_TK_MENU_COPY,
155 ID_WPT_MENU_COPY,
156 ID_WPT_MENU_SENDTOGPS,
157 ID_WPT_MENU_SENDTONEWGPS,
158 ID_WPT_MENU_SENDTOPEER,
159 ID_PASTE_WAYPOINT,
160 ID_PASTE_ROUTE,
161 ID_PASTE_TRACK,
162 ID_RT_MENU_DELETE,
163 ID_RT_MENU_REVERSE,
164 ID_RT_MENU_DELPOINT,
165 ID_RT_MENU_ACTPOINT,
166 ID_RT_MENU_DEACTPOINT,
167 ID_RT_MENU_ACTNXTPOINT,
168 ID_RT_MENU_REMPOINT,
169 ID_RT_MENU_PROPERTIES,
170 ID_RT_MENU_SENDTOGPS,
171 ID_RT_MENU_SENDTONEWGPS,
172 ID_RT_MENU_SHOWNAMES,
173 ID_RT_MENU_RESEQUENCE,
174 ID_RT_MENU_SENDTOPEER,
175 ID_WP_MENU_SET_ANCHORWATCH,
176 ID_WP_MENU_CLEAR_ANCHORWATCH,
177 ID_DEF_MENU_AISTARGETLIST,
178 ID_DEF_MENU_AIS_CPAWARNING,
179
180 ID_RC_MENU_SCALE_IN,
181 ID_RC_MENU_SCALE_OUT,
182 ID_RC_MENU_ZOOM_IN,
183 ID_RC_MENU_ZOOM_OUT,
184 ID_RC_MENU_FINISH,
185 ID_DEF_MENU_AIS_QUERY,
186 ID_DEF_MENU_AIS_CPA,
187 ID_DEF_MENU_AISSHOWTRACK,
188 ID_DEF_MENU_ACTIVATE_MEASURE,
189 ID_DEF_MENU_DEACTIVATE_MEASURE,
190 ID_DEF_MENU_COPY_MMSI,
191
192 ID_UNDO,
193 ID_REDO,
194
195 ID_DEF_MENU_CM93OFFSET_DIALOG,
196
197 ID_TK_MENU_PROPERTIES,
198 ID_TK_MENU_DELETE,
199 ID_TK_MENU_SENDTOPEER,
200 ID_WP_MENU_ADDITIONAL_INFO,
201
202 ID_DEF_MENU_QUILTREMOVE,
203 ID_DEF_MENU_COGUP,
204 ID_DEF_MENU_NORTHUP,
205 ID_DEF_MENU_HEADUP,
206 ID_DEF_MENU_TOGGLE_FULL,
207 ID_DEF_MENU_TIDEINFO,
208 ID_DEF_MENU_CURRENTINFO,
209 ID_DEF_ZERO_XTE,
210
211 ID_DEF_MENU_DEBUG,
212 ID_DGB_MENU_NMEA_WINDOW,
213
214 ID_DEF_MENU_GROUPBASE, // Must be last entry, as chart group identifiers are
215 // created dynamically
216
217 ID_DEF_MENU_LAST
218};
219
220//------------------------------------------------------------------------------
221// CanvasMenuHandler Implementation
222//------------------------------------------------------------------------------
223int CanvasMenuHandler::GetNextContextMenuId() {
224 return ID_DEF_MENU_LAST +
225 100; // Allowing for 100 dynamic menu item identifiers
226}
227
228wxFont CanvasMenuHandler::m_scaledFont;
229
230// Define a constructor for my canvas
231CanvasMenuHandler::CanvasMenuHandler(ChartCanvas *parentCanvas,
232 Route *selectedRoute, Track *selectedTrack,
233 RoutePoint *selectedPoint,
234 int selectedAIS_MMSI,
235 void *selectedTCIndex, wxWindow *nmea_log)
236 : m_nmea_log(nmea_log) {
237 parent = parentCanvas;
238 m_pSelectedRoute = selectedRoute;
239 m_pSelectedTrack = selectedTrack;
240 m_pFoundRoutePoint = selectedPoint;
241 m_FoundAIS_MMSI = selectedAIS_MMSI;
242 m_pIDXCandidate = selectedTCIndex;
243 if (!m_scaledFont.IsOk()) {
244 wxFont *qFont = GetOCPNScaledFont(_("Menu"));
245 m_scaledFont = *qFont;
246 }
247
248 m_DIPFactor = g_Platform->GetDisplayDIPMult(gFrame);
249}
250
251CanvasMenuHandler::~CanvasMenuHandler() {}
252
253//-------------------------------------------------------------------------------
254// Popup Menu Handling
255//-------------------------------------------------------------------------------
256
257void CanvasMenuHandler::PrepareMenuItem(wxMenuItem *item) {
258#if defined(__WXMSW__)
259 wxColour ctrl_back_color = GetGlobalColor(_T("DILG1")); // Control Background
260 item->SetBackgroundColour(ctrl_back_color);
261 wxColour menu_text_color = GetGlobalColor(_T ( "UITX1" ));
262 item->SetTextColour(menu_text_color);
263#endif
264}
265
266void CanvasMenuHandler::MenuPrepend1(wxMenu *menu, int id, wxString label) {
267 wxMenuItem *item = new wxMenuItem(menu, id, label);
268#if defined(__WXMSW__)
269 item->SetFont(m_scaledFont);
270#endif
271
272#ifdef __ANDROID__
273 wxFont sFont = GetOCPNGUIScaledFont(_("Menu"));
274 item->SetFont(sFont);
275#endif
276
277 PrepareMenuItem(item);
278
279 if (g_btouch) menu->InsertSeparator(0);
280 menu->Prepend(item);
281}
282
283void CanvasMenuHandler::MenuAppend1(wxMenu *menu, int id, wxString label) {
284 wxMenuItem *item = new wxMenuItem(menu, id, label);
285#if defined(__WXMSW__)
286 item->SetFont(m_scaledFont);
287#endif
288
289#ifdef __ANDROID__
290 wxFont sFont = GetOCPNGUIScaledFont(_("Menu"));
291 item->SetFont(sFont);
292#endif
293
294 PrepareMenuItem(item);
295
296 menu->Append(item);
297 if (g_btouch) menu->AppendSeparator();
298}
299
300void CanvasMenuHandler::SetMenuItemFont1(wxMenuItem *item) {
301#if defined(__WXMSW__)
302 item->SetFont(m_scaledFont);
303#endif
304
305#if defined(__ANDROID__)
306 wxFont *qFont = GetOCPNScaledFont(_("Menu"));
307 item->SetFont(*qFont);
308#endif
309
310 PrepareMenuItem(item);
311}
312
313void CanvasMenuHandler::CanvasPopupMenu(int x, int y, int seltype) {
314 wxMenu *contextMenu = new wxMenu;
315 wxMenu *menuWaypoint = NULL;
316 wxMenu *menuRoute = NULL;
317 wxMenu *menuTrack = NULL;
318 wxMenu *menuAIS = NULL;
319
320 wxMenu *subMenuChart = new wxMenu;
321 wxMenu *subMenuUndo = new wxMenu("Undo...Ctrl-Z");
322
323#ifdef __WXOSX__
324 wxMenu *subMenuRedo = new wxMenu("Redo...Shift-Ctrl-Z");
325#else
326 wxMenu *subMenuRedo = new wxMenu("Redo...Ctrl-Y");
327#endif
328 wxMenu *subMenuDebug = new wxMenu("");
329 MenuAppend1(subMenuDebug, ID_DGB_MENU_NMEA_WINDOW, _("Show Data Monitor"));
330
331 wxMenu *menuFocus = contextMenu; // This is the one that will be shown
332
333 popx = x;
334 popy = y;
335
336 if (!g_bBasicMenus || (seltype != SELTYPE_ROUTECREATE)) {
337 bool bsubMenus = false;
338
339 if (bsubMenus) {
340 if (parent->undo->AnythingToUndo()) {
341 // Undo SubMenu
342 wxMenuItem *subMenuItemundo =
343 contextMenu->AppendSubMenu(subMenuUndo, _("Undo"));
344
345 wxString undoItem;
346 undoItem << _("Undo") << _T(" ")
347 << parent->undo->GetNextUndoableAction()->Description();
348 MenuAppend1(subMenuUndo, ID_UNDO, undoItem);
349 }
350 if (parent->undo->AnythingToRedo()) {
351 // Redo SubMenu
352 wxMenuItem *subMenuItemRedo =
353 contextMenu->AppendSubMenu(subMenuRedo, _("Redo"));
354
355 wxString redoItem;
356 redoItem << _("Redo") << _T(" ")
357 << parent->undo->GetNextRedoableAction()->Description();
358 MenuAppend1(subMenuRedo, ID_REDO, redoItem);
359 }
360 } else {
361 if (parent->undo->AnythingToUndo()) {
362 wxString undoItem;
363 undoItem << _("Undo") << _T(" ")
364 << parent->undo->GetNextUndoableAction()->Description();
365 MenuAppend1(contextMenu, ID_UNDO, _menuText(undoItem, _T("Ctrl-Z")));
366 }
367
368 if (parent->undo->AnythingToRedo()) {
369 wxString redoItem;
370 redoItem << _("Redo") << _T(" ")
371 << parent->undo->GetNextRedoableAction()->Description();
372#ifdef __WXOSX__
373 MenuAppend1(contextMenu, ID_REDO,
374 _menuText(redoItem, _T("Shift-Ctrl-Z")));
375#else
376 MenuAppend1(contextMenu, ID_REDO, _menuText(redoItem, _T("Ctrl-Y")));
377#endif
378 }
379 }
380 }
381
382 if (seltype == SELTYPE_ROUTECREATE) {
383 MenuAppend1(contextMenu, ID_RC_MENU_FINISH,
384 _menuText(_("End Route"), _T("Esc")));
385 }
386
387 if (!parent->m_pMouseRoute) {
388 if (parent->m_bMeasure_Active)
389 MenuAppend1(contextMenu, ID_DEF_MENU_DEACTIVATE_MEASURE,
390 _menuText(_("Measure Off"), _T("Esc")));
391 else
392 MenuAppend1(contextMenu, ID_DEF_MENU_ACTIVATE_MEASURE,
393 _menuText(_("Measure"), _T("M")));
394 }
395
396 bool ais_areanotice = false;
397 if (g_pAIS && parent->GetShowAIS() && g_bShowAreaNotices) {
398 float vp_scale = parent->GetVPScale();
399
400 for (const auto &target : g_pAIS->GetAreaNoticeSourcesList()) {
401 auto target_data = target.second;
402 if (!target_data->area_notices.empty()) {
403 for (auto &ani : target_data->area_notices) {
404 Ais8_001_22 &area_notice = ani.second;
405 BoundingBox bbox;
406
407 for (Ais8_001_22_SubAreaList::iterator sa =
408 area_notice.sub_areas.begin();
409 sa != area_notice.sub_areas.end(); ++sa) {
410 switch (sa->shape) {
411 case AIS8_001_22_SHAPE_CIRCLE: {
412 wxPoint target_point;
413 parent->GetCanvasPointPix(sa->latitude, sa->longitude,
414 &target_point);
415 bbox.Expand(target_point);
416 if (sa->radius_m > 0.0) bbox.EnLarge(sa->radius_m * vp_scale);
417 break;
418 }
419 case AIS8_001_22_SHAPE_RECT:
420 case AIS8_001_22_SHAPE_POLYGON:
421 case AIS8_001_22_SHAPE_POLYLINE: {
422 double lat = sa->latitude;
423 double lon = sa->longitude;
424 for (int i = 0; i < 4; ++i) {
425 ll_gc_ll(lat, lon, sa->angles[i], sa->dists_m[i] / 1852.0,
426 &lat, &lon);
427 wxPoint target_point;
428 parent->GetCanvasPointPix(lat, lon, &target_point);
429 bbox.Expand(target_point);
430 }
431 break;
432 }
433 case AIS8_001_22_SHAPE_SECTOR: {
434 double lat1 = sa->latitude;
435 double lon1 = sa->longitude;
436 double lat, lon;
437 wxPoint target_point;
438 parent->GetCanvasPointPix(lat1, lon1, &target_point);
439 bbox.Expand(target_point);
440 for (int i = 0; i < 18; ++i) {
441 ll_gc_ll(
442 lat1, lon1,
443 sa->left_bound_deg +
444 i * (sa->right_bound_deg - sa->left_bound_deg) / 18,
445 sa->radius_m / 1852.0, &lat, &lon);
446 parent->GetCanvasPointPix(lat, lon, &target_point);
447 bbox.Expand(target_point);
448 }
449 ll_gc_ll(lat1, lon1, sa->right_bound_deg, sa->radius_m / 1852.0,
450 &lat, &lon);
451 parent->GetCanvasPointPix(lat, lon, &target_point);
452 bbox.Expand(target_point);
453 break;
454 }
455 }
456 }
457
458 if (bbox.GetValid() && bbox.PointInBox(x, y)) {
459 ais_areanotice = true;
460 break;
461 }
462 }
463 }
464 }
465 }
466
467 int nChartStack = 0;
468 if (parent->GetpCurrentStack())
469 nChartStack = parent->GetpCurrentStack()->nEntry;
470
471 if (!parent->GetVP().b_quilt) {
472 if (nChartStack > 1) {
473 MenuAppend1(contextMenu, ID_DEF_MENU_MAX_DETAIL, _("Max Detail Here"));
474 MenuAppend1(contextMenu, ID_DEF_MENU_SCALE_IN,
475 _menuText(_("Scale In"), _T("Ctrl-Left")));
476 MenuAppend1(contextMenu, ID_DEF_MENU_SCALE_OUT,
477 _menuText(_("Scale Out"), _T("Ctrl-Right")));
478 }
479
480 if ((parent->m_singleChart &&
481 (parent->m_singleChart->GetChartFamily() == CHART_FAMILY_VECTOR)) ||
482 ais_areanotice) {
483 MenuAppend1(contextMenu, ID_DEF_MENU_QUERY,
484 _("Object Query") + _T( "..." ));
485 }
486
487 } else {
488 ChartBase *pChartTest =
489 parent->m_pQuilt->GetChartAtPix(parent->GetVP(), wxPoint(x, y));
490 if ((pChartTest && (pChartTest->GetChartFamily() == CHART_FAMILY_VECTOR)) ||
491 ais_areanotice) {
492 MenuAppend1(contextMenu, ID_DEF_MENU_QUERY,
493 _("Object Query") + _T( "..." ));
494 } else {
495#ifndef __ANDROID__
496 if (!g_bBasicMenus && (nChartStack > 1)) {
497 MenuAppend1(contextMenu, ID_DEF_MENU_SCALE_IN,
498 _menuText(_("Scale In"), _T("Ctrl-Left")));
499 MenuAppend1(contextMenu, ID_DEF_MENU_SCALE_OUT,
500 _menuText(_("Scale Out"), _T("Ctrl-Right")));
501 }
502#endif
503 }
504 }
505
506 if (!g_bBasicMenus || (seltype != SELTYPE_ROUTECREATE)) {
507 bool b_dm_add = true;
508 if (g_btouch && parent->IsMeasureActive()) b_dm_add = false;
509
510 if (b_dm_add) {
511 MenuAppend1(contextMenu, ID_DEF_MENU_DROP_WP,
512 _menuText(_("Drop Mark"), _T("Ctrl-M")));
513 MenuAppend1(contextMenu, ID_DEF_MENU_NEW_RT,
514 _menuText(_("New Route..."), _T("Ctrl-R")));
515 }
516
517 if (!bGPSValid)
518 MenuAppend1(contextMenu, ID_DEF_MENU_MOVE_BOAT_HERE, _("Move Boat Here"));
519 }
520
521 if (!g_bBasicMenus &&
522 (!(g_pRouteMan->GetpActiveRoute() || (seltype & SELTYPE_MARKPOINT))))
523 MenuAppend1(contextMenu, ID_DEF_MENU_GOTO_HERE, _("Navigate To Here"));
524
525 if (!g_bBasicMenus)
526 MenuAppend1(contextMenu, ID_DEF_MENU_GOTOPOSITION,
527 _("Center view") + _T("..."));
528
529 if (!g_bBasicMenus) {
530 if (parent->GetVP().b_quilt) {
531 if (parent->GetUpMode() == NORTH_UP_MODE) {
532 MenuAppend1(contextMenu, ID_DEF_MENU_COGUP, _("Course Up Mode"));
533 if (!std::isnan(gHdt))
534 MenuAppend1(contextMenu, ID_DEF_MENU_HEADUP, _("Heading Up Mode"));
535 } else {
536 MenuAppend1(contextMenu, ID_DEF_MENU_NORTHUP, _("North Up Mode"));
537 }
538 } else {
539 if (parent->m_singleChart &&
540 (fabs(parent->m_singleChart->GetChartSkew()) > .01) && !g_bskew_comp)
541 MenuAppend1(contextMenu, ID_DEF_MENU_NORTHUP, _("Chart Up Mode"));
542 else
543 MenuAppend1(contextMenu, ID_DEF_MENU_NORTHUP, _("North Up Mode"));
544 }
545 }
546
547 if (!g_bBasicMenus) {
548 bool full_toggle_added = false;
549#ifndef __ANDROID__
550 if (g_btouch) {
551 MenuAppend1(contextMenu, ID_DEF_MENU_TOGGLE_FULL,
552 _("Toggle Full Screen"));
553 full_toggle_added = true;
554 }
555
556 if (!full_toggle_added) {
557 // if(gFrame->IsFullScreen())
558 MenuAppend1(contextMenu, ID_DEF_MENU_TOGGLE_FULL,
559 _("Toggle Full Screen"));
560 }
561#endif
562
563 if (g_pRouteMan->IsAnyRouteActive() &&
564 g_pRouteMan->GetCurrentXTEToActivePoint() > 0.)
565 MenuAppend1(contextMenu, ID_DEF_ZERO_XTE, _("Zero XTE"));
566
567 Kml *kml = new Kml;
568 int pasteBuffer = kml->ParsePasteBuffer();
569 if (pasteBuffer != KML_PASTE_INVALID) {
570 switch (pasteBuffer) {
571 case KML_PASTE_WAYPOINT: {
572 MenuAppend1(contextMenu, ID_PASTE_WAYPOINT, _("Paste Waypoint"));
573 break;
574 }
575 case KML_PASTE_ROUTE: {
576 MenuAppend1(contextMenu, ID_PASTE_ROUTE, _("Paste Route"));
577 break;
578 }
579 case KML_PASTE_TRACK: {
580 MenuAppend1(contextMenu, ID_PASTE_TRACK, _("Paste Track"));
581 break;
582 }
583 case KML_PASTE_ROUTE_TRACK: {
584 MenuAppend1(contextMenu, ID_PASTE_ROUTE, _("Paste Route"));
585 MenuAppend1(contextMenu, ID_PASTE_TRACK, _("Paste Track"));
586 break;
587 }
588 }
589 }
590 delete kml;
591
592 if (!parent->GetVP().b_quilt && parent->m_singleChart &&
593 (parent->m_singleChart->GetChartType() == CHART_TYPE_CM93COMP)) {
594 MenuAppend1(contextMenu, ID_DEF_MENU_CM93OFFSET_DIALOG,
595 _("CM93 Offset Dialog..."));
596 }
597
598 } // if( !g_bBasicMenus){
599
600#ifndef __ANDROID__
601// TODO stack
602// if( ( parent->GetVP().b_quilt ) && ( pCurrentStack &&
603// pCurrentStack->b_valid ) ) {
604// int dbIndex = parent->m_pQuilt->GetChartdbIndexAtPix(
605// parent->GetVP(), wxPoint( popx, popy ) ); if( dbIndex != -1 )
606// MenuAppend1( contextMenu, ID_DEF_MENU_QUILTREMOVE, _( "Hide This
607// Chart" ) );
608// }
609#endif
610
611#ifdef __WXMSW__
612 // If we dismiss the context menu without action, we need to discard some
613 // mouse events.... Eat the next 2 button events, which happen as down-up on
614 // MSW XP
615 g_click_stop = 2;
616#endif
617
618 // ChartGroup SubMenu
619 wxMenuItem *subItemChart =
620 contextMenu->AppendSubMenu(subMenuChart, _("Chart Groups"));
621 if (g_btouch) contextMenu->AppendSeparator();
622
623 SetMenuItemFont1(subItemChart);
624
625 if (g_pGroupArray->GetCount()) {
626#ifdef __WXMSW__
627 MenuAppend1(subMenuChart, wxID_CANCEL, _("temporary"));
628#endif
629 wxMenuItem *subItem0 = subMenuChart->AppendRadioItem(
630 ID_DEF_MENU_GROUPBASE, _("All Active Charts"));
631
632 SetMenuItemFont1(subItem0);
633
634 for (unsigned int i = 0; i < g_pGroupArray->GetCount(); i++) {
635 subItem0 = subMenuChart->AppendRadioItem(
636 ID_DEF_MENU_GROUPBASE + i + 1, g_pGroupArray->Item(i)->m_group_name);
637 SetMenuItemFont1(subItem0);
638 }
639
640#ifdef __WXMSW__
641 subMenuChart->Remove(wxID_CANCEL);
642#endif
643 subMenuChart->Check(ID_DEF_MENU_GROUPBASE + parent->m_groupIndex, true);
644 }
645
646 // This is the default context menu
647 menuFocus = contextMenu;
648
649 wxString name;
650 if (!g_bBasicMenus || (seltype != SELTYPE_ROUTECREATE)) {
651 if (g_pAIS) {
652 if (parent->GetShowAIS() && (seltype & SELTYPE_AISTARGET)) {
653 auto myptarget = g_pAIS->Get_Target_Data_From_MMSI(m_FoundAIS_MMSI);
654 if (!g_bBasicMenus && myptarget) {
655 name = myptarget->GetFullName();
656 if (name.IsEmpty()) name.Printf(_T("%d"), m_FoundAIS_MMSI);
657 name.Prepend(_T(" ( ")).Append(_T(" )"));
658 } else
659 name = wxEmptyString;
660 menuAIS = new wxMenu(_("AIS") + name);
661 MenuAppend1(menuAIS, ID_DEF_MENU_AIS_QUERY, _("Target Query..."));
662 if (myptarget && myptarget->bCPA_Valid &&
663 (myptarget->n_alert_state != AIS_ALERT_SET)) {
664 if (myptarget->b_show_AIS_CPA)
665 MenuAppend1(menuAIS, ID_DEF_MENU_AIS_CPA, _("Hide Target CPA"));
666 else
667 MenuAppend1(menuAIS, ID_DEF_MENU_AIS_CPA, _("Show Target CPA"));
668 }
669 MenuAppend1(menuAIS, ID_DEF_MENU_AISTARGETLIST, _("Target List..."));
670 if (myptarget->Class != AIS_METEO /*g_bAISShowTracks*/) {
671 if (myptarget && !myptarget->b_PersistTrack) {
672 if (myptarget->b_show_track)
673 MenuAppend1(menuAIS, ID_DEF_MENU_AISSHOWTRACK,
674 _("Hide Target Track"));
675 else
676 MenuAppend1(menuAIS, ID_DEF_MENU_AISSHOWTRACK,
677 _("Show Target Track"));
678 }
679 }
680
681 MenuAppend1(menuAIS, ID_DEF_MENU_COPY_MMSI, _("Copy Target MMSI"));
682 menuAIS->AppendSeparator();
683
684 if (!parent->GetVP().b_quilt) {
685 if ((parent->m_singleChart &&
686 (parent->m_singleChart->GetChartFamily() ==
687 CHART_FAMILY_VECTOR))) {
688 MenuAppend1(menuAIS, ID_DEF_MENU_QUERY, _("Object Query..."));
689 }
690
691 } else {
692 ChartBase *pChartTest =
693 parent->m_pQuilt->GetChartAtPix(parent->GetVP(), wxPoint(x, y));
694 if ((pChartTest &&
695 (pChartTest->GetChartFamily() == CHART_FAMILY_VECTOR))) {
696 MenuAppend1(menuAIS, ID_DEF_MENU_QUERY, _("Object Query..."));
697 }
698 }
699
700 menuFocus = menuAIS;
701 } else {
702 MenuAppend1(contextMenu, ID_DEF_MENU_AISTARGETLIST,
703 _("AIS target list") + _T("..."));
704
705 wxString nextCPAstatus = g_bCPAWarn ? _("Hide") : _("Show");
706 MenuAppend1(contextMenu, ID_DEF_MENU_AIS_CPAWARNING,
707 _menuText(nextCPAstatus + " " + _("CPA alarm "), "W"));
708 }
709 }
710 }
711 if (g_enable_root_menu_debug)
712 contextMenu->AppendSubMenu(subMenuDebug, _("Debug"));
713
714 if (seltype & SELTYPE_ROUTESEGMENT) {
715 if (!g_bBasicMenus && m_pSelectedRoute) {
716 name = m_pSelectedRoute->m_RouteNameString;
717 if (name.IsEmpty()) name = _("Unnamed Route");
718 name.Prepend(_T(" ( ")).Append(_T(" )"));
719 } else
720 name = wxEmptyString;
721 bool blay = false;
722 if (m_pSelectedRoute && m_pSelectedRoute->m_bIsInLayer) blay = true;
723
724 if (blay) {
725 menuRoute = new wxMenu(_("Layer Route") + name);
726 MenuAppend1(menuRoute, ID_RT_MENU_PROPERTIES,
727 _("Properties") + _T( "..." ));
728 if (m_pSelectedRoute) {
729 if (m_pSelectedRoute->IsActive()) {
730 int indexActive = m_pSelectedRoute->GetIndexOf(
731 m_pSelectedRoute->m_pRouteActivePoint);
732 if ((indexActive + 1) <= m_pSelectedRoute->GetnPoints()) {
733 MenuAppend1(menuRoute, ID_RT_MENU_ACTNXTPOINT,
734 _("Activate Next Waypoint"));
735 }
736 MenuAppend1(menuRoute, ID_RT_MENU_DEACTIVATE, _("Deactivate"));
737 MenuAppend1(menuRoute, ID_DEF_ZERO_XTE, _("Zero XTE"));
738 } else {
739 MenuAppend1(menuRoute, ID_RT_MENU_ACTIVATE, _("Activate"));
740 }
741 }
742 } else {
743 menuRoute = new wxMenu(_("Route") + name);
744 MenuAppend1(menuRoute, ID_RT_MENU_PROPERTIES,
745 _("Properties") + _T( "..." ));
746 if (m_pSelectedRoute) {
747 if (m_pSelectedRoute->IsActive()) {
748 int indexActive = m_pSelectedRoute->GetIndexOf(
749 m_pSelectedRoute->m_pRouteActivePoint);
750 if ((indexActive + 1) <= m_pSelectedRoute->GetnPoints()) {
751 MenuAppend1(menuRoute, ID_RT_MENU_ACTNXTPOINT,
752 _("Activate Next Waypoint"));
753 }
754 MenuAppend1(menuRoute, ID_RT_MENU_DEACTIVATE, _("Deactivate"));
755 MenuAppend1(menuRoute, ID_DEF_ZERO_XTE, _("Zero XTE"));
756 } else {
757 MenuAppend1(menuRoute, ID_RT_MENU_ACTIVATE, _("Activate"));
758 }
759 }
760 MenuAppend1(menuRoute, ID_RT_MENU_INSERT, _("Insert Waypoint"));
761 MenuAppend1(menuRoute, ID_RT_MENU_APPEND, _("Append Waypoint"));
762 if (!(seltype & SELTYPE_ROUTEPOINT) && m_pSelectedRoute) {
763 m_SelectedIdx = m_pSelectedRoute->GetIndexOf(m_pFoundRoutePoint);
764 if (m_SelectedIdx > 1 &&
765 m_SelectedIdx < m_pSelectedRoute->GetnPoints() - 1)
766 MenuAppend1(menuRoute, ID_RT_MENU_SPLIT_LEG, _("Split around Leg"));
767 }
768 MenuAppend1(menuRoute, ID_RT_MENU_COPY, _("Copy as KML") + _T( "..." ));
769 MenuAppend1(menuRoute, ID_RT_MENU_DELETE, _("Delete") + _T( "..." ));
770 MenuAppend1(menuRoute, ID_RT_MENU_REVERSE, _("Reverse..."));
771 if (m_pSelectedRoute) {
772 if (m_pSelectedRoute->AreWaypointNamesVisible())
773 MenuAppend1(menuRoute, ID_RT_MENU_SHOWNAMES,
774 _("Hide Waypoint Names"));
775 else
776 MenuAppend1(menuRoute, ID_RT_MENU_SHOWNAMES,
777 _("Show Waypoint Names"));
778 }
779 MenuAppend1(menuRoute, ID_RT_MENU_RESEQUENCE,
780 _("Resequence Waypoints..."));
781
782 // #ifndef __ANDROID__
783 wxString port = parent->FindValidUploadPort();
784 parent->m_active_upload_port = port;
785 wxString item = _("Send to GPS");
786 if (!port.IsEmpty()) {
787 item.Append(_T(" ( "));
788 item.Append(port);
789 item.Append(_T(" )"));
790 }
791 MenuAppend1(menuRoute, ID_RT_MENU_SENDTOGPS, item);
792
793 if (!port.IsEmpty()) {
794 wxString item = _("Send to new GPS");
795 MenuAppend1(menuRoute, ID_RT_MENU_SENDTONEWGPS, item);
796 }
797 // #endif
798 wxString itemstp = SYMBOL_STP_TITLE; // Send to Peer
799 MenuAppend1(menuRoute, ID_RT_MENU_SENDTOPEER, itemstp);
800 }
801 // Eventually set this menu as the "focused context menu"
802 if (menuFocus != menuAIS) menuFocus = menuRoute;
803 }
804
805 if (seltype & SELTYPE_TRACKSEGMENT) {
806 name = wxEmptyString;
807 if (!g_bBasicMenus && m_pSelectedTrack)
808 name = _T(" ( ") + m_pSelectedTrack->GetName(true) + _T(" )");
809 else
810 name = wxEmptyString;
811 bool blay = false;
812 if (m_pSelectedTrack && m_pSelectedTrack->m_bIsInLayer) blay = true;
813
814 if (blay) {
815 menuTrack = new wxMenu(_("Layer Track") + name);
816 MenuAppend1(menuTrack, ID_TK_MENU_PROPERTIES,
817 _("Properties") + _T( "..." ));
818 } else {
819 menuTrack = new wxMenu(_("Track") + name);
820 MenuAppend1(menuTrack, ID_TK_MENU_PROPERTIES,
821 _("Properties") + _T( "..." ));
822 MenuAppend1(menuTrack, ID_TK_MENU_COPY, _("Copy as KML"));
823 MenuAppend1(menuTrack, ID_TK_MENU_DELETE, _("Delete") + _T( "..." ));
824 }
825
826 wxString itemstp = SYMBOL_STP_TITLE; // Send to Peer
827 MenuAppend1(menuTrack, ID_TK_MENU_SENDTOPEER, itemstp);
828
829 // Eventually set this menu as the "focused context menu"
830 if (menuFocus != menuAIS) menuFocus = menuTrack;
831 }
832
833 if (seltype & SELTYPE_ROUTEPOINT) {
834 if (!g_bBasicMenus && m_pFoundRoutePoint) {
835 name = m_pFoundRoutePoint->GetName();
836 if (name.IsEmpty()) name = _("Unnamed Waypoint");
837 name.Prepend(_T(" ( ")).Append(_T(" )"));
838 } else
839 name = wxEmptyString;
840 bool blay = false;
841 if (m_pFoundRoutePoint && m_pFoundRoutePoint->m_bIsInLayer) blay = true;
842
843 if (blay) {
844 menuWaypoint = new wxMenu(_("Layer Waypoint") + name);
845 MenuAppend1(menuWaypoint, ID_WP_MENU_PROPERTIES,
846 _("Properties") + _T( "..." ));
847
848 if (m_pSelectedRoute && m_pSelectedRoute->IsActive())
849 MenuAppend1(menuWaypoint, ID_RT_MENU_ACTPOINT, _("Activate"));
850 } else {
851 menuWaypoint = new wxMenu(_("Waypoint") + name);
852 MenuAppend1(menuWaypoint, ID_WP_MENU_PROPERTIES,
853 _("Properties") + _T( "..." ));
854 if (m_pSelectedRoute && m_pSelectedRoute->IsActive()) {
855 if (m_pSelectedRoute->m_pRouteActivePoint != m_pFoundRoutePoint)
856 MenuAppend1(menuWaypoint, ID_RT_MENU_ACTPOINT, _("Activate"));
857 }
858
859 if (m_pSelectedRoute && m_pSelectedRoute->IsActive()) {
860 if (m_pSelectedRoute->m_pRouteActivePoint == m_pFoundRoutePoint) {
861 int indexActive = m_pSelectedRoute->GetIndexOf(
862 m_pSelectedRoute->m_pRouteActivePoint);
863 if ((indexActive + 1) <= m_pSelectedRoute->GetnPoints())
864 MenuAppend1(menuWaypoint, ID_RT_MENU_ACTNXTPOINT,
865 _("Activate Next Waypoint"));
866 }
867 }
868 if (m_pSelectedRoute && m_pSelectedRoute->GetnPoints() > 2) {
869 MenuAppend1(menuWaypoint, ID_RT_MENU_REMPOINT, _("Remove from Route"));
870
871 m_SelectedIdx = m_pSelectedRoute->GetIndexOf(m_pFoundRoutePoint);
872 if (m_SelectedIdx > 1 && m_SelectedIdx < m_pSelectedRoute->GetnPoints())
873 MenuAppend1(menuWaypoint, ID_RT_MENU_SPLIT_WPT,
874 _("Split Route at Waypoint"));
875 }
876
877 MenuAppend1(menuWaypoint, ID_WPT_MENU_COPY, _("Copy as KML"));
878
879 if (m_pFoundRoutePoint && m_pFoundRoutePoint->GetIconName() != _T("mob"))
880 MenuAppend1(menuWaypoint, ID_RT_MENU_DELPOINT, _("Delete"));
881
882 // #ifndef __ANDROID__
883 wxString port = parent->FindValidUploadPort();
884 parent->m_active_upload_port = port;
885 wxString item = _("Send to GPS");
886 if (!port.IsEmpty()) {
887 item.Append(_T(" ( "));
888 item.Append(port);
889 item.Append(_T(" )"));
890 }
891 MenuAppend1(menuWaypoint, ID_WPT_MENU_SENDTOGPS, item);
892
893 if (!port.IsEmpty()) {
894 wxString item = _("Send to new GPS");
895 MenuAppend1(menuWaypoint, ID_WPT_MENU_SENDTONEWGPS, item);
896 }
897
898 MenuAppend1(menuWaypoint, ID_WPT_MENU_SENDTOPEER,
899 SYMBOL_STP_TITLE); // Send to Peer
900 }
901
902 // Eventually set this menu as the "focused context menu"
903 if (menuFocus != menuAIS) menuFocus = menuWaypoint;
904 }
905
906 if (seltype & SELTYPE_MARKPOINT) {
907 if (!g_bBasicMenus && m_pFoundRoutePoint) {
908 name = m_pFoundRoutePoint->GetName();
909 if (name.IsEmpty()) name = _("Unnamed Mark");
910 name.Prepend(_T(" ( ")).Append(_T(" )"));
911 } else
912 name = wxEmptyString;
913 bool blay = false;
914 if (m_pFoundRoutePoint && m_pFoundRoutePoint->m_bIsInLayer) blay = true;
915
916 if (blay) {
917 menuWaypoint = new wxMenu(_("Layer Waypoint") + name);
918 MenuAppend1(menuWaypoint, ID_WP_MENU_PROPERTIES,
919 _("Properties") + _T( "..." ));
920 } else {
921 menuWaypoint = new wxMenu(_("Mark") + name);
922 MenuAppend1(menuWaypoint, ID_WP_MENU_PROPERTIES,
923 _("Properties") + _T( "..." ));
924
925 if (!g_pRouteMan->GetpActiveRoute())
926 MenuAppend1(menuWaypoint, ID_WP_MENU_GOTO, _("Navigate To This"));
927
928 MenuAppend1(menuWaypoint, ID_WPT_MENU_COPY, _("Copy as KML"));
929
930 if (m_pFoundRoutePoint && m_pFoundRoutePoint->GetIconName() != _T("mob"))
931 MenuAppend1(menuWaypoint, ID_WP_MENU_DELPOINT, _("Delete"));
932
933 // #ifndef __ANDROID__
934 wxString port = parent->FindValidUploadPort();
935 parent->m_active_upload_port = port;
936 wxString item = _("Send to GPS");
937 if (!port.IsEmpty()) {
938 item.Append(_T(" ( "));
939 item.Append(port);
940 item.Append(_T(" )"));
941 }
942 MenuAppend1(menuWaypoint, ID_WPT_MENU_SENDTOGPS, item);
943
944 MenuAppend1(menuWaypoint, ID_WPT_MENU_SENDTOPEER,
945 SYMBOL_STP_TITLE); // Send to Peer
946 // #endif
947
948 if ((m_pFoundRoutePoint == pAnchorWatchPoint1) ||
949 (m_pFoundRoutePoint == pAnchorWatchPoint2))
950 MenuAppend1(menuWaypoint, ID_WP_MENU_CLEAR_ANCHORWATCH,
951 _("Clear Anchor Watch"));
952 else {
953 if (m_pFoundRoutePoint && !(m_pFoundRoutePoint->m_bIsInLayer) &&
954 ((NULL == pAnchorWatchPoint1) || (NULL == pAnchorWatchPoint2))) {
955 double dist;
956 double brg;
957 DistanceBearingMercator(m_pFoundRoutePoint->m_lat,
958 m_pFoundRoutePoint->m_lon, gLat, gLon, &brg,
959 &dist);
960 if (dist * 1852. <= g_nAWMax)
961 MenuAppend1(menuWaypoint, ID_WP_MENU_SET_ANCHORWATCH,
962 _("Set Anchor Watch"));
963 }
964 }
965 }
966 // Eventually set this menu as the "focused context menu"
967 if (menuFocus != menuAIS) menuFocus = menuWaypoint;
968 }
969 /*add the relevant submenus*/
970 enum { WPMENU = 1, TKMENU = 2, RTMENU = 4, MMMENU = 8 };
971 int sub_menu = 0;
972 if (!g_bBasicMenus && menuFocus != contextMenu) {
973 if (global_color_scheme != GLOBAL_COLOR_SCHEME_DUSK &&
974 global_color_scheme != GLOBAL_COLOR_SCHEME_NIGHT) {
975 menuFocus->AppendSeparator();
976 }
977 wxMenuItem *subMenu1;
978 if (menuWaypoint && menuFocus != menuWaypoint) {
979 subMenu1 =
980 menuFocus->AppendSubMenu(menuWaypoint, menuWaypoint->GetTitle());
981 SetMenuItemFont1(subMenu1);
982 sub_menu |= WPMENU;
983#ifdef __WXMSW__
984 menuWaypoint->SetTitle(wxEmptyString);
985#endif
986 }
987 if (menuTrack && menuFocus != menuTrack) {
988 subMenu1 = menuFocus->AppendSubMenu(menuTrack, menuTrack->GetTitle());
989 SetMenuItemFont1(subMenu1);
990 sub_menu |= TKMENU;
991#ifdef __WXMSW__
992 menuTrack->SetTitle(wxEmptyString);
993#endif
994 }
995 if (menuRoute && menuFocus != menuRoute) {
996 subMenu1 = menuFocus->AppendSubMenu(menuRoute, menuRoute->GetTitle());
997 SetMenuItemFont1(subMenu1);
998 sub_menu |= RTMENU;
999#ifdef __WXMSW__
1000 menuRoute->SetTitle(wxEmptyString);
1001#endif
1002 }
1003 subMenu1 = menuFocus->AppendSubMenu(contextMenu, _("Main Menu"));
1004 SetMenuItemFont1(subMenu1);
1005 sub_menu |= MMMENU;
1006 }
1007
1008 if (!subMenuChart->GetMenuItemCount()) contextMenu->Destroy(subItemChart);
1009
1010 // Add the Tide/Current selections if the item was not activated by shortcut
1011 // in right-click handlers
1012 bool bsep = false;
1013 if (seltype & SELTYPE_TIDEPOINT) {
1014 menuFocus->AppendSeparator();
1015 bsep = true;
1016 MenuAppend1(menuFocus, ID_DEF_MENU_TIDEINFO, _("Show Tide Information"));
1017 }
1018
1019 if (seltype & SELTYPE_CURRENTPOINT) {
1020 if (!bsep) menuFocus->AppendSeparator();
1021 MenuAppend1(menuFocus, ID_DEF_MENU_CURRENTINFO,
1022 _("Show Current Information"));
1023 }
1024
1025 // Give the plugins a chance to update their menu items
1026 g_pi_manager->PrepareAllPluginContextMenus();
1027
1028 // Add PlugIn Context Menu items
1029 ArrayOfPlugInMenuItems item_array =
1030 g_pi_manager->GetPluginContextMenuItemArray();
1031
1032 for (unsigned int i = 0; i < item_array.GetCount(); i++) {
1033 PlugInMenuItemContainer *pimis = item_array[i];
1034 if (!pimis->b_viz) continue;
1035
1036 wxMenu *submenu = NULL;
1037 if (pimis->pmenu_item->GetSubMenu()) {
1038 submenu = new wxMenu();
1039 const wxMenuItemList &items =
1040 pimis->pmenu_item->GetSubMenu()->GetMenuItems();
1041 for (wxMenuItemList::const_iterator it = items.begin(); it != items.end();
1042 ++it) {
1043 int id = -1;
1044 for (unsigned int j = 0; j < item_array.GetCount(); j++) {
1045 PlugInMenuItemContainer *pimis = item_array[j];
1046 if (pimis->pmenu_item == *it) id = pimis->id;
1047 }
1048
1049 wxMenuItem *pmi = new wxMenuItem(submenu, id,
1050#if wxCHECK_VERSION(3, 0, 0)
1051 (*it)->GetItemLabelText(),
1052#else
1053 (*it)->GetLabel(),
1054#endif
1055 (*it)->GetHelp(), (*it)->GetKind());
1056
1057#ifdef __WXMSW__
1058 pmi->SetFont(m_scaledFont);
1059#endif
1060
1061#ifdef __ANDROID__
1062 wxFont sFont = GetOCPNGUIScaledFont(_("Menu"));
1063 pmi->SetFont(sFont);
1064#endif
1065
1066 PrepareMenuItem(pmi);
1067 submenu->Append(pmi);
1068 pmi->Check((*it)->IsChecked());
1069 }
1070 }
1071
1072 wxMenuItem *pmi = new wxMenuItem(contextMenu, pimis->id,
1073#if wxCHECK_VERSION(3, 0, 0)
1074 pimis->pmenu_item->GetItemLabelText(),
1075#else
1076 pimis->pmenu_item->GetLabel(),
1077#endif
1078 pimis->pmenu_item->GetHelp(),
1079 pimis->pmenu_item->GetKind(), submenu);
1080#ifdef __WXMSW__
1081 pmi->SetFont(m_scaledFont);
1082#endif
1083
1084#ifdef __ANDROID__
1085 wxFont sFont = GetOCPNGUIScaledFont(_("Menu"));
1086 pmi->SetFont(sFont);
1087#endif
1088
1089 PrepareMenuItem(pmi);
1090
1091 wxMenu *dst = contextMenu;
1092 if (pimis->m_in_menu == "Waypoint")
1093 dst = menuWaypoint;
1094 else if (pimis->m_in_menu == "Route")
1095 dst = menuRoute;
1096 else if (pimis->m_in_menu == "Track")
1097 dst = menuTrack;
1098 else if (pimis->m_in_menu == "AIS")
1099 dst = menuAIS;
1100
1101 if (dst != NULL) {
1102 dst->Append(pmi);
1103 dst->Enable(pimis->id, !pimis->b_grey);
1104 }
1105 }
1106
1107 // Invoke the correct focused drop-down menu
1108
1109#ifdef __ANDROID__
1110 androidEnableBackButton(false);
1111 androidEnableOptionsMenu(false);
1112
1113 setMenuStyleSheet(menuRoute, GetOCPNGUIScaledFont(_("Menu")));
1114 setMenuStyleSheet(menuWaypoint, GetOCPNGUIScaledFont(_("Menu")));
1115 setMenuStyleSheet(menuTrack, GetOCPNGUIScaledFont(_("Menu")));
1116 setMenuStyleSheet(menuAIS, GetOCPNGUIScaledFont(_("Menu")));
1117#endif
1118
1119 parent->PopupMenu(menuFocus, x, y);
1120
1121#ifdef __ANDROID__
1122 androidEnableBackButton(true);
1123 androidEnableOptionsMenu(true);
1124#endif
1125
1126 /* Cleanup if necessary.
1127 Do not delete menus witch are submenu as they will be deleted by their parent
1128 menu. This could create a crash*/
1129 delete menuAIS;
1130 if (!(sub_menu & MMMENU)) delete contextMenu;
1131 if (!(sub_menu & RTMENU)) delete menuRoute;
1132 if (!(sub_menu & TKMENU)) delete menuTrack;
1133 if (!(sub_menu & WPMENU)) delete menuWaypoint;
1134}
1135
1136void CanvasMenuHandler::PopupMenuHandler(wxCommandEvent &event) {
1137 RoutePoint *pLast;
1138
1139 wxPoint r;
1140 double zlat, zlon;
1141
1142 int splitMode = 0; // variables for split
1143 bool dupFirstWpt = true, showRPD;
1144
1145 parent->GetCanvasPixPoint(popx * parent->GetDisplayScale(),
1146 popy * parent->GetDisplayScale(), zlat, zlon);
1147
1148 switch (event.GetId()) {
1149 case ID_DEF_MENU_MAX_DETAIL:
1150 vLat = zlat;
1151 vLon = zlon;
1152 parent->ClearbFollow();
1153
1154 parent->parent_frame->DoChartUpdate();
1155
1156 parent->SelectChartFromStack(0, false, CHART_TYPE_DONTCARE,
1157 CHART_FAMILY_RASTER);
1158 break;
1159
1160 case ID_DEF_MENU_SCALE_IN:
1161 parent->DoCanvasStackDelta(-1);
1162 break;
1163
1164 case ID_DEF_MENU_SCALE_OUT:
1165 parent->DoCanvasStackDelta(1);
1166 break;
1167
1168 case ID_UNDO:
1169 parent->undo->UndoLastAction();
1170 parent->InvalidateGL();
1171 parent->Refresh(false);
1172 break;
1173
1174 case ID_REDO:
1175 parent->undo->RedoNextAction();
1176 parent->InvalidateGL();
1177 parent->Refresh(false);
1178 break;
1179
1180 case ID_DEF_MENU_MOVE_BOAT_HERE:
1181 gLat = zlat;
1182 gLon = zlon;
1183 gFrame->UpdateStatusBar();
1184 break;
1185
1186 case ID_DEF_MENU_GOTO_HERE: {
1187 RoutePoint *pWP_dest = new RoutePoint(zlat, zlon, g_default_wp_icon,
1188 wxEmptyString, wxEmptyString);
1189 pSelect->AddSelectableRoutePoint(zlat, zlon, pWP_dest);
1190
1191 RoutePoint *pWP_src = new RoutePoint(gLat, gLon, g_default_wp_icon,
1192 wxEmptyString, wxEmptyString);
1193 pSelect->AddSelectableRoutePoint(gLat, gLon, pWP_src);
1194
1195 Route *temp_route = new Route();
1196 pRouteList->Append(temp_route);
1197
1198 temp_route->AddPoint(pWP_src);
1199 temp_route->AddPoint(pWP_dest);
1200
1201 pSelect->AddSelectableRouteSegment(gLat, gLon, zlat, zlon, pWP_src,
1202 pWP_dest, temp_route);
1203
1204 temp_route->m_RouteNameString = _("Temporary GOTO Route");
1205 temp_route->m_RouteStartString = _("Here");
1206 ;
1207 temp_route->m_RouteEndString = _("There");
1208
1209 temp_route->m_bDeleteOnArrival = true;
1210
1211 if (g_pRouteMan->GetpActiveRoute()) g_pRouteMan->DeactivateRoute();
1212
1213 g_pRouteMan->ActivateRoute(temp_route, pWP_dest);
1214
1215 break;
1216 }
1217
1218 case ID_DEF_MENU_DROP_WP: {
1219 RoutePoint *pWP = new RoutePoint(zlat, zlon, g_default_wp_icon,
1220 wxEmptyString, wxEmptyString);
1221 pWP->m_bIsolatedMark = true; // This is an isolated mark
1222 pSelect->AddSelectableRoutePoint(zlat, zlon, pWP);
1223 pConfig->AddNewWayPoint(pWP, -1); // use auto next num
1224 if (!RoutePointGui(*pWP).IsVisibleSelectable(this->parent))
1225 RoutePointGui(*pWP).ShowScaleWarningMessage(parent);
1226
1227 if (RouteManagerDialog::getInstanceFlag()) {
1228 if (pRouteManagerDialog && pRouteManagerDialog->IsShown()) {
1229 pRouteManagerDialog->UpdateWptListCtrl();
1230 }
1231 }
1232
1233 parent->undo->BeforeUndoableAction(Undo_CreateWaypoint, pWP,
1234 Undo_HasParent, NULL);
1235 parent->undo->AfterUndoableAction(NULL);
1236 gFrame->RefreshAllCanvas(false);
1237 gFrame->InvalidateAllGL();
1238 g_FlushNavobjChanges = true;
1239 break;
1240 }
1241
1242 case ID_DEF_MENU_NEW_RT: {
1243 parent->StartRoute();
1244 break;
1245 }
1246
1247 case ID_DEF_MENU_AISTARGETLIST:
1248 parent->ShowAISTargetList();
1249 break;
1250
1251 case ID_DEF_MENU_AIS_CPAWARNING:
1252 parent->ToggleCPAWarn();
1253 break;
1254
1255 case ID_WP_MENU_GOTO: {
1256 RoutePoint *pWP_src = new RoutePoint(gLat, gLon, g_default_wp_icon,
1257 wxEmptyString, wxEmptyString);
1258 pSelect->AddSelectableRoutePoint(gLat, gLon, pWP_src);
1259
1260 Route *temp_route = new Route();
1261 pRouteList->Append(temp_route);
1262
1263 temp_route->AddPoint(pWP_src);
1264 temp_route->AddPoint(m_pFoundRoutePoint);
1265 m_pFoundRoutePoint->SetShared(true);
1266
1267 pSelect->AddSelectableRouteSegment(gLat, gLon, m_pFoundRoutePoint->m_lat,
1268 m_pFoundRoutePoint->m_lon, pWP_src,
1269 m_pFoundRoutePoint, temp_route);
1270
1271 wxString name = m_pFoundRoutePoint->GetName();
1272 if (name.IsEmpty()) name = _("(Unnamed Waypoint)");
1273 wxString rteName = _("Go to ");
1274 rteName.Append(name);
1275 temp_route->m_RouteNameString = rteName;
1276 temp_route->m_RouteStartString = _("Here");
1277 ;
1278 temp_route->m_RouteEndString = name;
1279 temp_route->m_bDeleteOnArrival = true;
1280
1281 if (g_pRouteMan->GetpActiveRoute()) g_pRouteMan->DeactivateRoute();
1282
1283 g_pRouteMan->ActivateRoute(temp_route, m_pFoundRoutePoint);
1284
1285 break;
1286 }
1287
1288 case ID_DEF_MENU_COGUP:
1289 parent->SetUpMode(COURSE_UP_MODE);
1290 break;
1291
1292 case ID_DEF_MENU_HEADUP:
1293 parent->SetUpMode(HEAD_UP_MODE);
1294 break;
1295
1296 case ID_DEF_MENU_NORTHUP:
1297 parent->SetUpMode(NORTH_UP_MODE);
1298 break;
1299
1300 case ID_DEF_MENU_TOGGLE_FULL:
1301 gFrame->ToggleFullScreen();
1302 break;
1303
1304 case ID_DEF_MENU_GOTOPOSITION:
1305 if (NULL == pGoToPositionDialog) // There is one global instance of the
1306 // Go To Position Dialog
1307 pGoToPositionDialog = new GoToPositionDialog(parent);
1308 pGoToPositionDialog->SetCanvas(parent);
1309 pGoToPositionDialog->CheckPasteBufferForPosition();
1310 pGoToPositionDialog->Show();
1311 break;
1312
1313 case ID_WP_MENU_DELPOINT: {
1314 if (m_pFoundRoutePoint == pAnchorWatchPoint1) {
1315 pAnchorWatchPoint1 = NULL;
1316 g_AW1GUID.Clear();
1317 } else if (m_pFoundRoutePoint == pAnchorWatchPoint2) {
1318 pAnchorWatchPoint2 = NULL;
1319 g_AW2GUID.Clear();
1320 }
1321
1322 if (m_pFoundRoutePoint && !(m_pFoundRoutePoint->m_bIsInLayer) &&
1323 (m_pFoundRoutePoint->GetIconName() != _T("mob"))) {
1324 // If the WP belongs to an invisible route, we come here instead of to
1325 // ID_RT_MENU_DELPOINT
1326 // Check it, and if so then remove the point from its routes
1327 wxArrayPtrVoid *proute_array =
1328 g_pRouteMan->GetRouteArrayContaining(m_pFoundRoutePoint);
1329 if (proute_array) {
1330 pWayPointMan->DestroyWaypoint(m_pFoundRoutePoint);
1331 delete proute_array;
1332 } else {
1333 parent->undo->BeforeUndoableAction(
1334 Undo_DeleteWaypoint, m_pFoundRoutePoint, Undo_IsOrphanded,
1335 NULL /*m_pFoundPoint*/);
1336 pConfig->DeleteWayPoint(m_pFoundRoutePoint);
1337 pSelect->DeleteSelectablePoint(m_pFoundRoutePoint,
1338 SELTYPE_ROUTEPOINT);
1339 if (NULL != pWayPointMan)
1340 pWayPointMan->RemoveRoutePoint(m_pFoundRoutePoint);
1341 parent->undo->AfterUndoableAction(NULL);
1342 }
1343
1344 if (g_pMarkInfoDialog) {
1345 g_pMarkInfoDialog->ClearData();
1346 }
1347
1348 if (RouteManagerDialog::getInstanceFlag()) {
1349 if (pRouteManagerDialog) {
1350 if (pRouteManagerDialog->IsShown())
1351 pRouteManagerDialog->UpdateWptListCtrl();
1352 }
1353 }
1354
1355 gFrame->RefreshAllCanvas(false);
1356 gFrame->InvalidateAllGL();
1357 }
1358 break;
1359 }
1360 case ID_WP_MENU_PROPERTIES:
1361 parent->ShowMarkPropertiesDialog(m_pFoundRoutePoint);
1362 break;
1363
1364 case ID_WP_MENU_CLEAR_ANCHORWATCH: {
1365 wxString guid = wxEmptyString;
1366 if (pAnchorWatchPoint1 == m_pFoundRoutePoint) {
1367 pAnchorWatchPoint1 = NULL;
1368 guid = g_AW1GUID;
1369 g_AW1GUID.Clear();
1370 } else if (pAnchorWatchPoint2 == m_pFoundRoutePoint) {
1371 pAnchorWatchPoint2 = NULL;
1372 guid = g_AW2GUID;
1373 g_AW2GUID.Clear();
1374 }
1375 if (!guid.IsEmpty()) {
1376 wxJSONValue v;
1377 v[_T("GUID")] = guid;
1378 wxString msg_id(_T("OCPN_ANCHOR_WATCH_CLEARED"));
1379 SendJSONMessageToAllPlugins(msg_id, v);
1380 }
1381 break;
1382 }
1383
1384 case ID_WP_MENU_SET_ANCHORWATCH: {
1385 wxString guid = wxEmptyString;
1386 if (pAnchorWatchPoint1 == NULL) {
1387 pAnchorWatchPoint1 = m_pFoundRoutePoint;
1388 g_AW1GUID = pAnchorWatchPoint1->m_GUID;
1389 guid = g_AW1GUID;
1390 wxString nn;
1391 nn = m_pFoundRoutePoint->GetName();
1392 if (nn.IsNull()) {
1393 nn.Printf(_T("%d m"), g_nAWDefault);
1394 m_pFoundRoutePoint->SetName(nn);
1395 }
1396 } else if (pAnchorWatchPoint2 == NULL) {
1397 pAnchorWatchPoint2 = m_pFoundRoutePoint;
1398 g_AW2GUID = pAnchorWatchPoint2->m_GUID;
1399 guid = g_AW2GUID;
1400 wxString nn;
1401 nn = m_pFoundRoutePoint->GetName();
1402 if (nn.IsNull()) {
1403 nn.Printf(_T("%d m"), g_nAWDefault);
1404 m_pFoundRoutePoint->SetName(nn);
1405 }
1406 }
1407 if (!guid.IsEmpty()) {
1408 wxJSONValue v;
1409 v[_T("GUID")] = guid;
1410 wxString msg_id(_T("OCPN_ANCHOR_WATCH_SET"));
1411 SendJSONMessageToAllPlugins(msg_id, v);
1412 }
1413 break;
1414 }
1415
1416 case ID_DEF_MENU_ACTIVATE_MEASURE:
1417 parent->StartMeasureRoute();
1418 break;
1419
1420 case ID_DEF_MENU_DEACTIVATE_MEASURE:
1421 parent->CancelMeasureRoute();
1422 // gFrame->SurfaceAllCanvasToolbars();
1423 parent->InvalidateGL();
1424 parent->Refresh(false);
1425 break;
1426
1427 case ID_DEF_MENU_CM93OFFSET_DIALOG: {
1428 if (NULL == g_pCM93OffsetDialog) {
1429 g_pCM93OffsetDialog = new CM93OffsetDialog(parent->parent_frame);
1430 }
1431
1432 cm93compchart *pch = NULL;
1433 if (!parent->GetVP().b_quilt && parent->m_singleChart &&
1434 (parent->m_singleChart->GetChartType() == CHART_TYPE_CM93COMP)) {
1435 pch = (cm93compchart *)parent->m_singleChart;
1436 }
1437
1438 if (g_pCM93OffsetDialog) {
1439 g_pCM93OffsetDialog->SetCM93Chart(pch);
1440 g_pCM93OffsetDialog->Show();
1441 g_pCM93OffsetDialog->UpdateMCOVRList(parent->GetVP());
1442 }
1443
1444 break;
1445 }
1446 case ID_DEF_MENU_QUERY: {
1447 parent->ShowObjectQueryWindow(popx, popy, zlat, zlon);
1448 break;
1449 }
1450 case ID_DEF_MENU_AIS_QUERY: {
1451 ShowAISTargetQueryDialog(parent, m_FoundAIS_MMSI);
1452 break;
1453 }
1454
1455 case ID_DEF_MENU_AIS_CPA: {
1456 auto myptarget = g_pAIS->Get_Target_Data_From_MMSI(m_FoundAIS_MMSI);
1457 if (myptarget) myptarget->Toggle_AIS_CPA();
1458 break;
1459 }
1460
1461 case ID_DEF_MENU_AISSHOWTRACK: {
1462 auto myptarget = g_pAIS->Get_Target_Data_From_MMSI(m_FoundAIS_MMSI);
1463 if (myptarget) myptarget->ToggleShowTrack();
1464 break;
1465 }
1466
1467 case ID_DEF_MENU_COPY_MMSI: {
1468 // Write MMSI # as text to the clipboard
1469 if (wxTheClipboard->Open()) {
1470 wxTheClipboard->SetData(new wxTextDataObject(
1471 wxString::Format(wxT("%09d"), m_FoundAIS_MMSI)));
1472 wxTheClipboard->Close();
1473 }
1474 break;
1475 }
1476
1477 case ID_DEF_MENU_QUILTREMOVE: {
1478 if (parent->GetVP().b_quilt) {
1479 int dbIndex = parent->m_pQuilt->GetChartdbIndexAtPix(
1480 parent->GetVP(), wxPoint(popx, popy));
1481 parent->RemoveChartFromQuilt(dbIndex);
1482
1483 parent->ReloadVP();
1484 }
1485
1486 break;
1487 }
1488
1489 case ID_DEF_MENU_CURRENTINFO: {
1490 parent->DrawTCWindow(popx, popy, (void *)m_pIDXCandidate);
1491 parent->Refresh(false);
1492
1493 break;
1494 }
1495
1496 case ID_DEF_MENU_TIDEINFO: {
1497 parent->DrawTCWindow(popx, popy, (void *)m_pIDXCandidate);
1498 parent->Refresh(false);
1499
1500 break;
1501 }
1502
1503 case ID_DGB_MENU_NMEA_WINDOW:
1504 m_nmea_log->Show();
1505 m_nmea_log->Raise();
1506 break;
1507
1508 case ID_RT_MENU_REVERSE: {
1509 if (m_pSelectedRoute->m_bIsInLayer) break;
1510
1511 int ask_return =
1512 OCPNMessageBox(parent, g_pRouteMan->GetRouteReverseMessage(),
1513 _("Rename Waypoints?"), wxYES_NO | wxCANCEL);
1514
1515 if (ask_return != wxID_CANCEL) {
1516 pSelect->DeleteAllSelectableRouteSegments(m_pSelectedRoute);
1517 m_pSelectedRoute->Reverse(ask_return == wxID_YES);
1518 pSelect->AddAllSelectableRouteSegments(m_pSelectedRoute);
1519
1520 pConfig->UpdateRoute(m_pSelectedRoute);
1521
1522 if (pRoutePropDialog && (pRoutePropDialog->IsShown())) {
1523 pRoutePropDialog->SetRouteAndUpdate(m_pSelectedRoute);
1524 // pNew->UpdateProperties();
1525 }
1526 gFrame->InvalidateAllGL();
1527 gFrame->RefreshAllCanvas();
1528 }
1529 break;
1530 }
1531
1532 case ID_RT_MENU_SHOWNAMES: {
1533 if (m_pSelectedRoute) {
1534 m_pSelectedRoute->ShowWaypointNames(
1535 !m_pSelectedRoute->AreWaypointNamesVisible());
1536 }
1537
1538 break;
1539 }
1540
1541 case ID_RT_MENU_RESEQUENCE: {
1542 if (m_pSelectedRoute) {
1543 if (m_pSelectedRoute->m_bIsInLayer) break;
1544
1545 int ask_return =
1546 OCPNMessageBox(parent, g_pRouteMan->GetRouteResequenceMessage(),
1547 _("Rename Waypoints?"), wxYES_NO | wxCANCEL);
1548
1549 if (ask_return != wxID_CANCEL) {
1550 m_pSelectedRoute->RenameRoutePoints();
1551 }
1552
1553 gFrame->InvalidateAllGL();
1554 gFrame->RefreshAllCanvas();
1555 }
1556
1557 break;
1558 }
1559
1560 case ID_RT_MENU_DELETE: {
1561 bool confirmed = RouteGui::OnDelete(parent);
1562
1563 if (confirmed) {
1564 if (g_pRouteMan->GetpActiveRoute() == m_pSelectedRoute)
1565 g_pRouteMan->DeactivateRoute();
1566
1567 if (m_pSelectedRoute->m_bIsInLayer) break;
1568
1569 if (!g_pRouteMan->DeleteRoute(m_pSelectedRoute,
1570 NavObjectChanges::getInstance()))
1571 break;
1572
1573 if (RouteManagerDialog::getInstanceFlag()) {
1574 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
1575 pRouteManagerDialog->UpdateRouteListCtrl();
1576 }
1577
1578 if (g_pMarkInfoDialog && g_pMarkInfoDialog->IsShown()) {
1579 g_pMarkInfoDialog->ValidateMark();
1580 g_pMarkInfoDialog->UpdateProperties();
1581 }
1582
1583 parent->undo->InvalidateUndo();
1584
1585 gFrame->InvalidateAllGL();
1586 gFrame->RefreshAllCanvas();
1587 }
1588 break;
1589 }
1590
1591 case ID_RT_MENU_ACTIVATE: {
1592 if (g_pRouteMan->GetpActiveRoute()) g_pRouteMan->DeactivateRoute();
1593
1594 // If this is an auto-created MOB route, always select the second point
1595 // (the MOB)
1596 // as the destination.
1597 RoutePoint *best_point;
1598 if (m_pSelectedRoute) {
1599 if (wxNOT_FOUND ==
1600 m_pSelectedRoute->m_RouteNameString.Find(_T("MOB"))) {
1601 best_point = g_pRouteMan->FindBestActivatePoint(
1602 m_pSelectedRoute, gLat, gLon, gCog, gSog);
1603 } else
1604 best_point = m_pSelectedRoute->GetPoint(2);
1605
1606 g_pRouteMan->ActivateRoute(m_pSelectedRoute, best_point);
1607 m_pSelectedRoute->m_bRtIsSelected = false;
1608 }
1609
1610 break;
1611 }
1612
1613 case ID_RT_MENU_DEACTIVATE:
1614 g_pRouteMan->DeactivateRoute();
1615 m_pSelectedRoute->m_bRtIsSelected = false;
1616
1617 break;
1618
1619 case ID_RT_MENU_INSERT: {
1620 if (m_pSelectedRoute->m_bIsInLayer) break;
1621 bool rename = false;
1622 m_pSelectedRoute->InsertPointAfter(m_pFoundRoutePoint, zlat, zlon,
1623 rename);
1624
1625 pSelect->DeleteAllSelectableRoutePoints(m_pSelectedRoute);
1626 pSelect->DeleteAllSelectableRouteSegments(m_pSelectedRoute);
1627
1628 pSelect->AddAllSelectableRouteSegments(m_pSelectedRoute);
1629 pSelect->AddAllSelectableRoutePoints(m_pSelectedRoute);
1630
1631 // As a special case (which comes up often)...
1632 // If the inserted waypoint is on the active leg of an active route
1633 /* if(m_pSelectedRoute->m_bRtIsActive)
1634 {
1635 if(m_pSelectedRoute->m_nRouteActivePoint == np + 1)
1636 {
1637 pNew_Point = m_pSelectedRoute->GetPoint(np + 2);
1638 pRouteMan->ActivateRoutePoint(m_pSelectedRoute, pNew_Point);
1639 }
1640 }
1641 */
1642 pConfig->UpdateRoute(m_pSelectedRoute);
1643
1644 if (pRoutePropDialog && (pRoutePropDialog->IsShown())) {
1645 pRoutePropDialog->SetRouteAndUpdate(m_pSelectedRoute, true);
1646 }
1647
1648 break;
1649 }
1650
1651 case ID_RT_MENU_APPEND:
1652
1653 if (m_pSelectedRoute->m_bIsInLayer) break;
1654
1655 parent->m_pMouseRoute = m_pSelectedRoute;
1656 parent->m_routeState = m_pSelectedRoute->GetnPoints() + 1;
1657 parent->m_pMouseRoute->m_lastMousePointIndex =
1658 m_pSelectedRoute->GetnPoints();
1659 parent->m_pMouseRoute->SetHiLite(50);
1660
1661 pLast = m_pSelectedRoute->GetLastPoint();
1662
1663 parent->m_prev_rlat = pLast->m_lat;
1664 parent->m_prev_rlon = pLast->m_lon;
1665 parent->m_prev_pMousePoint = pLast;
1666
1667 parent->m_bAppendingRoute = true;
1668
1669 parent->SetCursor(*parent->pCursorPencil);
1670#ifdef __ANDROID__
1671 androidSetRouteAnnunciator(true);
1672#endif
1673
1674 parent->HideGlobalToolbar();
1675
1676 break;
1677
1678 case ID_RT_MENU_SPLIT_LEG: // split route around a leg
1679 splitMode++;
1680 dupFirstWpt = false;
1681 case ID_RT_MENU_SPLIT_WPT: // split route at a wpt
1682
1683 showRPD = (pRoutePropDialog && pRoutePropDialog->IsShown());
1684
1685 if (g_pRouteMan->GetpActiveRoute() == m_pSelectedRoute)
1686 g_pRouteMan->DeactivateRoute();
1687
1688 m_pHead = new Route();
1689 m_pTail = new Route();
1690 m_pHead->CloneRoute(m_pSelectedRoute, 1, m_SelectedIdx, _("_A"));
1691 m_pTail->CloneRoute(m_pSelectedRoute, m_SelectedIdx + splitMode,
1692 m_pSelectedRoute->GetnPoints(), _("_B"), dupFirstWpt);
1693 pRouteList->Append(m_pHead);
1694 pConfig->AddNewRoute(m_pHead);
1695
1696 pRouteList->Append(m_pTail);
1697 pConfig->AddNewRoute(m_pTail);
1698
1699 pConfig->DeleteConfigRoute(m_pSelectedRoute);
1700
1701 pSelect->DeleteAllSelectableRoutePoints(m_pSelectedRoute);
1702 pSelect->DeleteAllSelectableRouteSegments(m_pSelectedRoute);
1703 g_pRouteMan->DeleteRoute(m_pSelectedRoute,
1704 NavObjectChanges::getInstance());
1705 pSelect->AddAllSelectableRouteSegments(m_pTail);
1706 pSelect->AddAllSelectableRoutePoints(m_pTail);
1707 pSelect->AddAllSelectableRouteSegments(m_pHead);
1708 pSelect->AddAllSelectableRoutePoints(m_pHead);
1709
1710 if (showRPD) {
1711 pRoutePropDialog->SetRouteAndUpdate(m_pHead);
1712 pRoutePropDialog->Show();
1713 }
1714 if (RouteManagerDialog::getInstanceFlag() && pRouteManagerDialog &&
1715 (pRouteManagerDialog->IsShown()))
1716 pRouteManagerDialog->UpdateRouteListCtrl();
1717 break;
1718
1719 case ID_RT_MENU_COPY:
1720 if (m_pSelectedRoute) Kml::CopyRouteToClipboard(m_pSelectedRoute);
1721 break;
1722
1723 case ID_TK_MENU_COPY:
1724 if (m_pSelectedTrack) Kml::CopyTrackToClipboard(m_pSelectedTrack);
1725 break;
1726
1727 case ID_WPT_MENU_COPY:
1728 if (m_pFoundRoutePoint) Kml::CopyWaypointToClipboard(m_pFoundRoutePoint);
1729 break;
1730
1731 case ID_WPT_MENU_SENDTOGPS:
1732 if (m_pFoundRoutePoint) {
1733 if (parent->m_active_upload_port.Length())
1734 RoutePointGui(*m_pFoundRoutePoint)
1735 .SendToGPS(parent->m_active_upload_port.BeforeFirst(' '), NULL);
1736 else {
1737 SendToGpsDlg dlg;
1738 dlg.SetWaypoint(m_pFoundRoutePoint);
1739 wxFont fo = GetOCPNGUIScaledFont(_("Dialog"));
1740 dlg.SetFont(fo);
1741
1742 dlg.Create(NULL, -1, _("Send to GPS") + _T( "..." ), _T(""));
1743 dlg.ShowModal();
1744 }
1745 }
1746 break;
1747
1748 case ID_WPT_MENU_SENDTONEWGPS:
1749 if (m_pFoundRoutePoint) {
1750 SendToGpsDlg dlg;
1751 dlg.SetWaypoint(m_pFoundRoutePoint);
1752
1753 dlg.Create(NULL, -1, _("Send to GPS") + _T( "..." ), _T(""));
1754 dlg.ShowModal();
1755 }
1756 break;
1757
1758 case ID_WPT_MENU_SENDTOPEER:
1759 if (m_pFoundRoutePoint) {
1760 SendToPeerDlg dlg;
1761 dlg.SetWaypoint(m_pFoundRoutePoint);
1762
1763 // Perform initial scan, if necessary
1764
1765 // Check for stale cache...
1766 MdnsCache::GetInstance().Validate();
1767 if (MdnsCache::GetInstance().GetCache().empty())
1768 dlg.SetScanOnCreate(true);
1769
1770 dlg.SetScanTime(5); // seconds
1771 dlg.Create(NULL, -1, _("Send Waypoint to OpenCPN Peer") + _T( "..." ),
1772 _T(""));
1773 dlg.ShowModal();
1774 }
1775 break;
1776
1777 case ID_RT_MENU_SENDTOGPS:
1778 if (m_pSelectedRoute) {
1779 if (parent->m_active_upload_port.Length())
1780 RouteGui(*m_pSelectedRoute)
1781 .SendToGPS(parent->m_active_upload_port.BeforeFirst(' '), true,
1782 NULL);
1783 else {
1784 SendToGpsDlg dlg;
1785 dlg.SetRoute(m_pSelectedRoute);
1786
1787 dlg.Create(NULL, -1, _("Send to GPS") + _T( "..." ), _T(""));
1788 dlg.ShowModal();
1789 }
1790 }
1791 break;
1792
1793 case ID_RT_MENU_SENDTONEWGPS:
1794 if (m_pSelectedRoute) {
1795 SendToGpsDlg dlg;
1796 dlg.SetRoute(m_pSelectedRoute);
1797
1798 dlg.Create(NULL, -1, _("Send to GPS") + _T( "..." ), _T(""));
1799 dlg.ShowModal();
1800 }
1801 break;
1802
1803 case ID_RT_MENU_SENDTOPEER:
1804 if (m_pSelectedRoute) {
1805 SendToPeerDlg dlg;
1806 dlg.SetRoute(m_pSelectedRoute);
1807
1808 // Perform initial scan, if necessary
1809
1810 // Check for stale cache...
1811 MdnsCache::GetInstance().Validate();
1812 if (MdnsCache::GetInstance().GetCache().empty())
1813 dlg.SetScanOnCreate(true);
1814
1815 dlg.SetScanTime(5); // seconds
1816 dlg.Create(NULL, -1, _("Send Route to OpenCPN Peer") + _T( "..." ),
1817 _T(""));
1818 dlg.ShowModal();
1819 }
1820 break;
1821
1822 case ID_PASTE_WAYPOINT:
1823 pupHandler_PasteWaypoint();
1824 break;
1825
1826 case ID_PASTE_ROUTE:
1827 pupHandler_PasteRoute();
1828 break;
1829
1830 case ID_PASTE_TRACK:
1831 pupHandler_PasteTrack();
1832 break;
1833
1834 case ID_RT_MENU_DELPOINT:
1835 if (m_pSelectedRoute) {
1836 if (m_pSelectedRoute->m_bIsInLayer) break;
1837
1838 pWayPointMan->DestroyWaypoint(m_pFoundRoutePoint);
1839
1840 if (pRoutePropDialog && (pRoutePropDialog->IsShown())) {
1841 // Selected route may have been deleted as one-point route, so
1842 // check it
1843 if (g_pRouteMan->IsRouteValid(m_pSelectedRoute)) {
1844 pRoutePropDialog->SetRouteAndUpdate(m_pSelectedRoute, true);
1845 } else
1846 pRoutePropDialog->Hide();
1847 }
1848
1849 if (RouteManagerDialog::getInstanceFlag()) {
1850 if (pRouteManagerDialog && pRouteManagerDialog->IsShown()) {
1851 pRouteManagerDialog->UpdateWptListCtrl();
1852 pRouteManagerDialog->UpdateRouteListCtrl();
1853 }
1854 }
1855
1856 gFrame->InvalidateAllGL();
1857 gFrame->RefreshAllCanvas(true);
1858 }
1859
1860 break;
1861
1862 case ID_RT_MENU_REMPOINT:
1863 if (m_pSelectedRoute) {
1864 if (m_pSelectedRoute->m_bIsInLayer) break;
1865 g_pRouteMan->RemovePointFromRoute(m_pFoundRoutePoint, m_pSelectedRoute,
1866 parent->m_routeState);
1867 gFrame->InvalidateAllGL();
1868 gFrame->RefreshAllCanvas();
1869 }
1870 break;
1871
1872 case ID_RT_MENU_ACTPOINT:
1873 if (g_pRouteMan->GetpActiveRoute() == m_pSelectedRoute) {
1874 g_pRouteMan->ActivateRoutePoint(m_pSelectedRoute, m_pFoundRoutePoint);
1875 m_pSelectedRoute->m_bRtIsSelected = false;
1876 }
1877
1878 break;
1879
1880 case ID_RT_MENU_DEACTPOINT:
1881 break;
1882
1883 case ID_RT_MENU_ACTNXTPOINT:
1884 if (g_pRouteMan->GetpActiveRoute() == m_pSelectedRoute) {
1885 g_pRouteMan->ActivateNextPoint(m_pSelectedRoute, true);
1886 m_pSelectedRoute->m_bRtIsSelected = false;
1887 }
1888
1889 break;
1890
1891 case ID_RT_MENU_PROPERTIES: {
1892 parent->ShowRoutePropertiesDialog(_("Route Properties"),
1893 m_pSelectedRoute);
1894 break;
1895 }
1896
1897 case ID_TK_MENU_PROPERTIES: {
1898 parent->ShowTrackPropertiesDialog(m_pSelectedTrack);
1899 break;
1900 }
1901
1902 case ID_TK_MENU_DELETE: {
1903 int dlg_return = wxID_YES;
1904 if (g_bConfirmObjectDelete) {
1905 dlg_return = OCPNMessageBox(
1906 parent, _("Are you sure you want to delete this track?"),
1907 _("OpenCPN Track Delete"),
1908 (long)wxYES_NO | wxCANCEL | wxYES_DEFAULT);
1909 }
1910
1911 if (dlg_return == wxID_YES) {
1912 if (m_pSelectedTrack == g_pActiveTrack)
1913 m_pSelectedTrack = parent->parent_frame->TrackOff();
1914 g_pAIS->DeletePersistentTrack(m_pSelectedTrack);
1915 pConfig->DeleteConfigTrack(m_pSelectedTrack);
1916
1917 RoutemanGui(*g_pRouteMan).DeleteTrack(m_pSelectedTrack);
1918
1919 if (TrackPropDlg::getInstanceFlag() && pTrackPropDialog &&
1920 (pTrackPropDialog->IsShown()) &&
1921 (m_pSelectedTrack == pTrackPropDialog->GetTrack())) {
1922 pTrackPropDialog->Hide();
1923 }
1924
1925 if (RoutePropDlgImpl::getInstanceFlag() && pRouteManagerDialog &&
1926 pRouteManagerDialog->IsShown()) {
1927 pRouteManagerDialog->UpdateTrkListCtrl();
1928 pRouteManagerDialog->UpdateRouteListCtrl();
1929 }
1930 gFrame->InvalidateAllGL();
1931 gFrame->RefreshAllCanvas();
1932 }
1933 break;
1934 }
1935
1936 case ID_TK_MENU_SENDTOPEER:
1937 if (m_pSelectedTrack) {
1938 SendToPeerDlg dlg;
1939 dlg.SetTrack(m_pSelectedTrack);
1940
1941 // Perform initial scan, if necessary
1942
1943 // Check for stale cache...
1944 MdnsCache::GetInstance().Validate();
1945 if (MdnsCache::GetInstance().GetCache().empty())
1946 dlg.SetScanOnCreate(true);
1947
1948 dlg.SetScanTime(5); // seconds
1949 dlg.Create(NULL, -1, _("Send Track to OpenCPN Peer") + _T( "..." ),
1950 _T(""));
1951 dlg.ShowModal();
1952 }
1953 break;
1954
1955 case ID_RC_MENU_SCALE_IN:
1956 parent->parent_frame->DoStackDown(parent);
1957 parent->GetCanvasPointPix(zlat, zlon, &r);
1958 parent->WarpPointer(r.x, r.y);
1959 break;
1960
1961 case ID_RC_MENU_SCALE_OUT:
1962 parent->parent_frame->DoStackUp(parent);
1963 parent->GetCanvasPointPix(zlat, zlon, &r);
1964 parent->WarpPointer(r.x, r.y);
1965 break;
1966
1967 case ID_RC_MENU_ZOOM_IN:
1968 parent->SetVPScale(parent->GetVPScale() * 2);
1969 parent->GetCanvasPointPix(zlat, zlon, &r);
1970 parent->WarpPointer(r.x, r.y);
1971 break;
1972
1973 case ID_RC_MENU_ZOOM_OUT:
1974 parent->SetVPScale(parent->GetVPScale() / 2);
1975 parent->GetCanvasPointPix(zlat, zlon, &r);
1976 parent->WarpPointer(r.x, r.y);
1977 break;
1978
1979 case ID_RC_MENU_FINISH:
1980 parent->FinishRoute();
1981 // gFrame->SurfaceAllCanvasToolbars();
1982 parent->Refresh(false);
1983 g_FlushNavobjChanges = true;
1984 break;
1985
1986 case ID_DEF_ZERO_XTE:
1987 g_pRouteMan->ZeroCurrentXTEToActivePoint();
1988 break;
1989
1990 default: {
1991 // Look for PlugIn Context Menu selections
1992 // If found, make the callback
1993 ArrayOfPlugInMenuItems item_array =
1994 g_pi_manager->GetPluginContextMenuItemArray();
1995
1996 for (unsigned int i = 0; i < item_array.GetCount(); i++) {
1997 PlugInMenuItemContainer *pimis = item_array[i];
1998 {
1999 if (pimis->id == event.GetId()) {
2000 if (pimis->m_pplugin)
2001 pimis->m_pplugin->OnContextMenuItemCallback(pimis->id);
2002 }
2003 }
2004 }
2005
2006 break;
2007 }
2008 } // switch
2009
2010 // Chart Groups....
2011 if ((event.GetId() >= ID_DEF_MENU_GROUPBASE) &&
2012 (event.GetId() <=
2013 ID_DEF_MENU_GROUPBASE + (int)g_pGroupArray->GetCount())) {
2014 parent->SetGroupIndex(event.GetId() - ID_DEF_MENU_GROUPBASE);
2015 }
2016
2017 parent->InvalidateGL();
2018
2019 g_click_stop = 0; // Context menu was processed, all is well
2020}
Global state for AIS decoder.
double GetDisplayDIPMult(wxWindow *win)
Get the display scaling factor for DPI-aware rendering.
Represents an active track that is currently being recorded.
Definition track.h:226
Dialog for managing CM93 chart offsets.
Definition cm93.h:547
Base class for all chart types.
Definition chartbase.h:119
ChartCanvas - Main chart display and interaction component.
Definition chcanv.h:151
bool GetCanvasPointPix(double rlat, double rlon, wxPoint *r)
Convert latitude/longitude to canvas pixel coordinates (physical pixels) rounded to nearest integer.
Definition chcanv.cpp:4565
double GetDisplayScale()
Get the ratio of physical to logical pixel for the display.
Definition chcanv.h:824
float GetVPScale()
Return the ViewPort scale factor, in physical pixels per meter.
Definition chcanv.h:450
bool SetVPScale(double sc, bool b_refresh=true)
Sets the viewport scale while maintaining the center point.
Definition chcanv.cpp:5345
void GetCanvasPixPoint(double x, double y, double &lat, double &lon)
Convert canvas pixel coordinates (physical pixels) to latitude/longitude.
Definition chcanv.cpp:4590
Definition kml.h:54
Dialog for displaying and editing waypoint properties.
Definition MarkInfo.h:212
void Validate()
Check that all entries are accessible, remove stale ones.
Main application frame.
Definition ocpn_frame.h:136
Provides platform-specific support utilities for OpenCPN.
Represents a waypoint or mark within the navigation system.
Definition route_point.h:70
bool m_bIsolatedMark
Flag indicating if the waypoint is a standalone mark.
Represents a navigational route in the navigation system.
Definition route.h:98
bool m_bRtIsSelected
Flag indicating whether this route is currently selected in the UI.
Definition route.h:202
wxString m_RouteStartString
Name or description of the route's starting point.
Definition route.h:251
bool m_bDeleteOnArrival
Flag indicating whether the route should be deleted once navigation reaches the end.
Definition route.h:267
wxString m_RouteEndString
Name or description of the route's ending point.
Definition route.h:256
RoutePoint * m_pRouteActivePoint
Pointer to the currently active waypoint within this route.
Definition route.h:213
wxString m_RouteNameString
User-assigned name for the route.
Definition route.h:246
bool m_bIsInLayer
Flag indicating whether this route belongs to a layer.
Definition route.h:277
int m_lastMousePointIndex
Index of the most recently interacted with route point.
Definition route.h:297
bool ActivateRoutePoint(Route *pA, RoutePoint *pRP)
Activates a specific waypoint within a route for navigation.
Definition routeman.cpp:319
wxArrayPtrVoid * GetRouteArrayContaining(RoutePoint *pWP)
Find all routes that contain the given waypoint.
Definition routeman.cpp:174
bool ActivateNextPoint(Route *pr, bool skipped)
Activates the next waypoint in a route when the current waypoint is reached.
Definition routeman.cpp:394
bool DeleteRoute(Route *pRoute, NavObjectChanges *nav_obj_changes)
Definition routeman.cpp:835
bool ActivateRoute(Route *pRouteToActivate, RoutePoint *pStartPoint=NULL)
Activates a route for navigation.
Definition routeman.cpp:260
Dialog for sending routes/waypoints to a GPS device.
Dialog for sending navigation objects to peer devices.
Class TrackPropDlg.
Represents a track, which is a series of connected track points.
Definition track.h:111
bool RemoveRoutePoint(RoutePoint *prp)
Remove a routepoint from list if present, deallocate it all cases.
Represents a composite CM93 chart covering multiple scales.
Definition cm93.h:424
virtual void OnContextMenuItemCallback(int id)
Handles context menu item selection.
The JSON value class implementation.
Definition jsonval.h:84
Hooks into gui available in model.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
Definition gui_lib.cpp:54
wxFont GetOCPNGUIScaledFont(wxString item)
Retrieves a font optimized for touch and high-resolution interfaces.
Definition gui_lib.cpp:83
MdnsCache mDNS host lookups cache.
mDNS lookup wrappers.
Tools to send data to plugins.