34#if defined(__linux__) && !defined(__ANDROID__)
40#include <wx/filename.h>
41#include <wx/aui/aui.h>
42#include <wx/platinfo.h>
43#include <wx/popupwin.h>
44#include <wx/progdlg.h>
45#include <wx/statline.h>
46#include <wx/tokenzr.h>
47#include <wx/tooltip.h>
49#include <wx/hashset.h>
50#include <wx/hashmap.h>
51#include <wx/jsonval.h>
53#include <wx/zipstrm.h>
54#include <wx/zstream.h>
55#include <wx/tarstrm.h>
56#include <wx/textwrapper.h>
78#include <unordered_map>
80#include <archive_entry.h>
81typedef __LA_INT64_T la_int64_t;
90#include "ais_decoder.h"
92#include "ais_target_data.h"
93#include "canvasMenu.h"
94#include "catalog_handler.h"
95#include "cat_settings.h"
100#include "comm_navmsg_bus.h"
101#include "comm_vars.h"
103#include "config_vars.h"
104#include "downloader.h"
105#include "download_mgr.h"
109#include "ocpn_pixel.h"
111#include "json_event.h"
113#include "multiplexer.h"
115#include "nav_object_database.h"
117#include "navutil_base.h"
118#include "observable_confvar.h"
119#include "observable_globvar.h"
120#include "OCPN_AUIManager.h"
122#include "ocpn_pixel.h"
123#include "OCPNPlatform.h"
124#include "OCPNRegion.h"
125#include "ocpn_utils.h"
128#include "plugin_cache.h"
129#include "plugin_handler.h"
130#include "plugin_loader.h"
131#include "pluginmanager.h"
132#include "plugin_paths.h"
134#include "routemanagerdialog.h"
136#include "routeman_gui.h"
139#include "safe_mode.h"
140#include "semantic_vers.h"
141#include "SoundFactory.h"
142#include "SystemCmdSound.h"
146#include "update_mgr.h"
147#include "waypointman_gui.h"
148#include "svg_utils.h"
149#include "ocpn_frame.h"
150#include "comm_drv_registry.h"
151#include "comm_drv_n0183_serial.h"
152#include "comm_drv_n0183_net.h"
153#include "comm_drv_registry.h"
154#include "comm_drv_n2k.h"
157#ifdef __OCPN__ANDROID__
159#include "androidUTIL.h"
163#include "glChartCanvas.h"
170struct sigaction sa_all_PIM;
171struct sigaction sa_all_PIM_previous;
175void catch_signals_PIM(
int signo) {
178 siglongjmp(env_PIM, 1);
192#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
193extern wxLocale *plocale_def_lang;
202extern bool g_bShowChartBar;
207extern RouteList *pRouteList;
208extern std::vector<Track*> g_TrackList;
210extern s52plib *ps52plib;
211extern wxString ChartListFileName;
212extern bool g_boptionsactive;
214extern ColorScheme global_color_scheme;
215extern wxArrayString g_locale_catalog_array;
216extern int g_GUIScaleFactor;
217extern int g_ChartScaleFactor;
218extern wxString g_locale;
222extern int g_chart_zoom_modifier_raster;
223extern int g_chart_zoom_modifier_vector;
224extern double g_display_size_mm;
225extern bool g_bopengl;
227extern ChartGroupArray *g_pGroupArray;
228extern unsigned int g_canvasConfig;
230extern wxString g_CmdSoundString;
232extern int g_iSDMMFormat;
234unsigned int gs_plib_flags;
235wxString g_lastPluginMessage;
238extern bool g_bquiting;
239extern wxString g_catalog_channel;
240extern wxString g_catalog_custom_url;
242WX_DEFINE_ARRAY_PTR(
ChartCanvas *, arrayofCanvasPtr);
243extern arrayofCanvasPtr g_canvasArray;
245const char *
const LINUX_LOAD_PATH =
"~/.local/lib:/usr/local/lib:/usr/lib";
246const char *
const FLATPAK_LOAD_PATH =
"~/.var/app/org.opencpn.OpenCPN/lib";
250enum { CurlThreadId = wxID_HIGHEST + 1 };
252#include <wx/listimpl.cpp>
253WX_DEFINE_LIST(Plugin_WaypointList);
254WX_DEFINE_LIST(Plugin_HyperlinkList);
261static void SendAisJsonMessage(std::shared_ptr<const AisTargetData> pTarget) {
263 if (!g_pi_manager->GetJSONMessageTargetCount())
return;
268 wxLongLong t = ::wxGetLocalTimeMillis();
270 jMsg[wxS(
"Source")] = wxS(
"AisDecoder");
271 jMsg[wxT(
"Type")] = wxT(
"Information");
272 jMsg[wxT(
"Msg")] = wxS(
"AIS Target");
273 jMsg[wxT(
"MsgId")] = t.GetValue();
274 jMsg[wxS(
"lat")] = pTarget->Lat;
275 jMsg[wxS(
"lon")] = pTarget->Lon;
276 jMsg[wxS(
"sog")] = pTarget->SOG;
277 jMsg[wxS(
"cog")] = pTarget->COG;
278 jMsg[wxS(
"hdg")] = pTarget->HDG;
279 jMsg[wxS(
"mmsi")] = pTarget->MMSI;
280 jMsg[wxS(
"class")] = pTarget->Class;
281 jMsg[wxS(
"ownship")] = pTarget->b_OwnShip;
282 jMsg[wxS(
"active")] = pTarget->b_active;
283 jMsg[wxS(
"lost")] = pTarget->b_lost;
284 wxString l_ShipName = wxString::FromUTF8(pTarget->ShipName);
285 for (
size_t i = 0; i < l_ShipName.Len(); i++) {
286 if (l_ShipName.GetChar(i) ==
'@') l_ShipName.SetChar(i,
'\n');
288 jMsg[wxS(
"shipname")] = l_ShipName;
289 wxString l_CallSign = wxString::FromUTF8(pTarget->CallSign);
290 for (
size_t i = 0; i < l_CallSign.Len(); i++) {
291 if (l_CallSign.GetChar(i) ==
'@') l_CallSign.SetChar(i,
'\n');
293 jMsg[wxS(
"callsign")] = l_CallSign;
294 jMsg[wxS(
"removed")] = pTarget->b_removed;
295 g_pi_manager->SendJSONMessageToAllPlugins(wxT(
"AIS"), jMsg);
306 void message(
const std::string& message) {
308 m_deferred_messages.push_back(message);
313 void show_deferred_messages() {
314 for (
auto m : m_deferred_messages) show_msg(m);
321 void show_msg(wxString msg) {
322 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
323 wxICON_INFORMATION | wxOK, 10);
327 std::vector<wxString> m_deferred_messages;
334 Wrap(win, text, widthMax);
336 wxString
const &GetWrapped()
const {
return m_wrapped; }
337 int const GetLineCount()
const {
return m_lineCount; }
338 wxArrayString GetLineArray() {
return m_array; }
341 virtual void OnOutputLine(
const wxString &line) {
345 virtual void OnNewLine() {
353 wxArrayString m_array;
356static const std::vector<std::string> SYSTEM_PLUGINS = {
357 "chartdownloader",
"wmm",
"dashboard",
"grib"};
360 template <
typename T>
361 std::size_t operator()(T t)
const {
362 return static_cast<std::size_t
>(t);
366wxString message_by_status(PluginStatus stat) {
368 case PluginStatus::System:
369 return _(
"Plugin is a standard system plugin");
370 case PluginStatus::Managed:
371 return _(
"Plugin is managed by OpenCPN");
372 case PluginStatus::Unmanaged:
373 return _(
"Plugin is not managed by OpenCPN");
374 case PluginStatus::Ghost:
376 case PluginStatus::Unknown:
377 return _(
"Plugin status unknown");
378 case PluginStatus::LegacyUpdateAvailable:
379 return _(
"Update to managed Plugin is available");
380 case PluginStatus::ManagedInstallAvailable:
381 return _(
"New managed Plugin installation available");
382 case PluginStatus::ManagedInstalledUpdateAvailable:
383 return _(
"Update to installed Plugin is available");
384 case PluginStatus::ManagedInstalledCurrentVersion:
385 return _(
"Plugin is latest available");
386 case PluginStatus::ManagedInstalledDowngradeAvailable:
388 case PluginStatus::PendingListRemoval:
395static std::unordered_map<PluginStatus, const char *, EnumClassHash>
397 {{PluginStatus::System,
"emblem-system.svg"},
398 {PluginStatus::Managed,
"emblem-default.svg"},
399 {PluginStatus::Unmanaged,
"emblem-unmanaged.svg"},
400 {PluginStatus::Ghost,
"ghost.svg"},
401 {PluginStatus::Unknown,
"emblem-unmanaged.svg"},
402 {PluginStatus::LegacyUpdateAvailable,
"emblem-legacy-update.svg"},
403 {PluginStatus::ManagedInstallAvailable,
"emblem-default.svg"},
404 {PluginStatus::ManagedInstalledUpdateAvailable,
405 "emblem-legacy-update.svg"},
406 {PluginStatus::ManagedInstalledCurrentVersion,
"emblem-default.svg"},
407 {PluginStatus::ManagedInstalledDowngradeAvailable,
408 "emblem-default.svg"},
409 {PluginStatus::PendingListRemoval,
"emblem-default.svg"}
413static std::unordered_map<PluginStatus, const char *, EnumClassHash>
414 literalstatus_by_status(
415 {{PluginStatus::System,
"System"},
416 {PluginStatus::Managed,
"Managed"},
417 {PluginStatus::Unmanaged,
"Unmanaged"},
418 {PluginStatus::Ghost,
"Ghost"},
419 {PluginStatus::Unknown,
"Unknown"},
420 {PluginStatus::LegacyUpdateAvailable,
"LegacyUpdateAvailable"},
421 {PluginStatus::ManagedInstallAvailable,
"ManagedInstallAvailable"},
422 {PluginStatus::ManagedInstalledUpdateAvailable,
423 "ManagedInstalledUpdateAvailable"},
424 {PluginStatus::ManagedInstalledCurrentVersion,
425 "ManagedInstalledCurrentVersion"},
426 {PluginStatus::ManagedInstalledDowngradeAvailable,
427 "ManagedInstalledDowngradeAvailable"},
428 {PluginStatus::PendingListRemoval,
"PendingListRemoval"}
436static std::vector<PluginMetadata> getCompatiblePlugins() {
438 struct metadata_compare {
441 return lhs.key() < rhs.key();
445 std::vector<PluginMetadata> returnArray;
447 std::set<PluginMetadata, metadata_compare> unique_plugins;
448 for (
auto plugin : PluginHandler::getInstance()->getAvailable()) {
449 unique_plugins.insert(plugin);
451 for (
auto plugin : unique_plugins) {
453 returnArray.push_back(plugin);
470 std::string installed;
472 if (path ==
"" || !wxFileName::IsFileReadable(path)) {
475 std::ifstream stream;
476 stream.open(path, std::ifstream::in);
485static std::vector<PluginMetadata> getUpdates(
const char *name) {
486 auto updates = getCompatiblePlugins();
488 std::remove_if(updates.begin(), updates.end(),
492 auto inst_vers = getInstalledVersion(name);
493 if (inst_vers.major == -1) {
498 updates.erase(std::remove_if(updates.begin(), updates.end(),
500 return metadata_version(m) == inst_vers;
510static int count_files_in_dirs(
const char *filename,
511 const std::vector<std::string> dirs) {
513 for (
auto dir : dirs) {
514 const std::string sep(1, wxFileName::GetPathSeparator());
515 auto path = dir + sep + filename;
516 if (ocpn::exists(path)) {
524 auto updates = getCompatiblePlugins();
525 if (updates.size() == 0) {
529 std::sort(updates.begin(), updates.end(),
531 return !(m1.version < m2.version);
538 g_Platform->ShowBusySpinner();
539 PluginLoader::getInstance()->DeactivatePlugIn(pic);
540 pic->m_bEnabled =
false;
541 PluginLoader::getInstance()->UpdatePlugIns();
543 wxLogMessage(
"Uninstalling %s", plugin);
544 PluginHandler::getInstance()->
uninstall(plugin);
545 PluginLoader::getInstance()->UpdatePlugIns();
546 g_Platform->HideBusySpinner();
549static bool LoadAllPlugIns(
bool load_enabled) {
550 g_Platform->ShowBusySpinner();
551 bool b = PluginLoader::getInstance()->LoadAllPlugIns(load_enabled);
552 g_Platform->HideBusySpinner();
557 bool uninstall,
const char *name = 0,
558 bool b_forceEnable =
false) {
559 wxString pluginName = pic->m_common_name;
560 const char *plugin = name == 0 ? pic->m_common_name.mb_str().data() : name;
561 auto updates = getUpdates(plugin);
562 auto parent_dlg =
dynamic_cast<wxScrolledWindow *
>(parent);
563 wxASSERT(parent_dlg != 0);
565 auto status = dialog.ShowModal();
566 status = dialog.GetReturnCode();
567 if (status != wxID_OK) {
571 auto update = dialog.GetUpdate();
572 if (!g_pi_manager->CheckBlacklistedPlugin(update)) {
576 wxLogMessage(
"Installing %s", update.name.c_str());
578 auto pluginHandler = PluginHandler::getInstance();
580 if (uninstall && path !=
"") {
581 gui_uninstall(pic, update.name.c_str());
583 bool cacheResult = pluginHandler->installPluginFromCache(update);
586 g_Platform->ShowBusySpinner();
590 std::string tempTarballPath = downloader->run(parent_dlg, uninstall);
592 if (!tempTarballPath.size())
598 if (!isRegularFile(manifestPath.c_str())) {
599 wxLogMessage(
"Installation of %s failed", update.name.c_str());
600 PluginHandler::cleanupFiles(manifestPath, update.name);
606 wxLogMessage(
"Installation of %s successful", update.name.c_str());
607 wxURI uri(wxString(update.tarball_url.c_str()));
608 wxFileName fn(uri.GetPath());
609 std::string basename = fn.GetFullName().ToStdString();
612 wxLogDebug(
"Copied %s to local cache at %s", tempTarballPath.c_str(),
614 remove(tempTarballPath.c_str());
622 wxString pispec = _T(
"_pi.dll");
623#elif defined(__WXOSX__)
624 wxString pispec = _T(
"_pi.dylib");
626 wxString pispec = _T(
"_pi.so");
630 wxTextFile manifest_file(manifestPath);
632 if (manifest_file.Open()) {
634 for (wxString str = manifest_file.GetFirstLine(); !manifest_file.Eof();
635 str = manifest_file.GetNextLine()) {
636 if (str.Contains(pispec)) {
637 if (getenv(
"OCPN_KEEP_PLUGINS")) {
641 auto loader = PluginLoader::getInstance();
642 if (!loader->CheckPluginCompatibility(str)) {
644 _(
"The plugin is not compatible with this version of OpenCPN, "
645 "and will be uninstalled.");
646 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
647 wxICON_INFORMATION | wxOK, 10);
649 PluginHandler::cleanupFiles(manifestPath, update.name);
658 if (b_forceEnable && pluginFile.Length()) {
659 wxString config_section = (_T (
"/PlugIns/" ));
660 wxFileName fn(pluginFile);
661 config_section += fn.GetFullName();
662 pConfig->SetPath(config_section);
663 pConfig->Write(_T (
"bEnabled" ),
true);
667 LoadAllPlugIns(
false);
671 bool b_newOptions =
false;
672 auto loader = PluginLoader::getInstance();
673 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount();
676 wxString cname = pic->m_common_name;
677 if (pic->m_bInitState && (pluginName == cname)) {
678 if ((pic->m_cap_flag & INSTALLS_TOOLBOX_PAGE)) {
679 g_options->SetNeedNew(
true);
681 NotifySetupOptionsPlugin(pic);
700 pivp.clat = tvp.clat;
701 pivp.clon = tvp.clon;
702 pivp.view_scale_ppm = tvp.view_scale_ppm;
703 pivp.skew = tvp.skew;
704 pivp.rotation = tvp.rotation;
705 pivp.chart_scale = tvp.chart_scale;
706 pivp.pix_width = tvp.pix_width;
707 pivp.pix_height = tvp.pix_height;
708 pivp.rv_rect = tvp.rv_rect;
709 pivp.b_quilt = tvp.b_quilt;
710 pivp.m_projection_type = tvp.m_projection_type;
712 pivp.lat_min = tvp.GetBBox().GetMinLat();
713 pivp.lat_max = tvp.GetBBox().GetMaxLat();
714 pivp.lon_min = tvp.GetBBox().GetMinLon();
715 pivp.lon_max = tvp.GetBBox().GetMaxLon();
717 pivp.bValid = tvp.IsValid();
728 vp.view_scale_ppm = pivp.view_scale_ppm;
730 vp.rotation = pivp.rotation;
731 vp.chart_scale = pivp.chart_scale;
732 vp.pix_width = pivp.pix_width;
733 vp.pix_height = pivp.pix_height;
734 vp.rv_rect = pivp.rv_rect;
735 vp.b_quilt = pivp.b_quilt;
736 vp.m_projection_type = pivp.m_projection_type;
738 if (gFrame->GetPrimaryCanvas())
739 vp.ref_scale = gFrame->GetPrimaryCanvas()->GetVP().ref_scale;
741 vp.ref_scale = vp.chart_scale;
754 void OnPluginUtilAction(wxCommandEvent &event);
756 DECLARE_EVENT_TABLE()
760EVT_BUTTON(ID_CMD_BUTTON_PERFORM_ACTION, pluginUtilHandler::OnPluginUtilAction)
765void pluginUtilHandler::OnPluginUtilAction(wxCommandEvent &event) {
766 auto panel =
static_cast<PluginPanel *
>(
event.GetClientData());
769 wxASSERT(plugin_list_panel != 0);
771 auto actionPIC = panel->GetPlugin();
772 wxString name = actionPIC->m_common_name;
775 switch (panel->GetAction()) {
776 case ActionVerb::UPGRADE_TO_MANAGED_VERSION: {
777 auto loader = PluginLoader::getInstance();
780 std::string pluginName = actionPIC->m_ManagedMetadata.name;
782 wxLogMessage(
"Installing managed plugin: %s", pluginName.c_str());
784 new GuiDownloader(plugin_list_panel, actionPIC->m_ManagedMetadata);
785 downloader->run(plugin_list_panel,
false);
789 if (isRegularFile(manifestPath.c_str())) {
791 for (
unsigned i = 0; i < loader->GetPlugInArray()->GetCount();
793 if (actionPIC->m_ManagedMetadata.name ==
794 loader->GetPlugInArray()
796 ->m_common_name.ToStdString()) {
797 loader->UnLoadPlugIn(i);
803 LoadAllPlugIns(
false);
805 PluginHandler::cleanupFiles(manifestPath,
806 actionPIC->m_ManagedMetadata.name);
809 plugin_list_panel->SelectByName(name);
814 case ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION:
815 case ActionVerb::REINSTALL_MANAGED_VERSION:
816 case ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION: {
818 auto metaSave = actionPIC->m_ManagedMetadata;
819 run_update_dialog(plugin_list_panel, actionPIC,
true,
820 metaSave.name.c_str());
824 case ActionVerb::INSTALL_MANAGED_VERSION: {
825 wxLogMessage(
"Installing new managed plugin.");
826 run_update_dialog(plugin_list_panel, actionPIC,
false);
830 case ActionVerb::UNINSTALL_MANAGED_VERSION: {
831 PluginLoader::getInstance()->DeactivatePlugIn(actionPIC);
835 message.Printf(
"%s %s\n", actionPIC->m_ManagedMetadata.name.c_str(),
836 actionPIC->m_ManagedMetadata.version.c_str());
837 message += _(
"successfully un-installed");
839 wxLogMessage(
"Uninstalling %s",
840 actionPIC->m_ManagedMetadata.name.c_str());
843 actionPIC->m_ManagedMetadata.name);
846 auto loader = PluginLoader::getInstance();
847 LoadAllPlugIns(
false);
850 OCPNMessageBox(gFrame, message, _(
"Un-Installation complete"),
851 wxICON_INFORMATION | wxOK);
856 case ActionVerb::NOP:
871class StatusIconPanel:
public wxPanel
879 m_stat = pic->m_pluginStatus;
880 SetToolTip(message_by_status[m_stat]);
881 m_icon_name = icon_by_status[m_stat];
883 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
884 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
889 SetMinSize(wxSize(GetCharWidth() * 5, -1));
890 Bind(wxEVT_PAINT, &StatusIconPanel::OnPaint,
this);
891 Bind(wxEVT_LEFT_DOWN, &StatusIconPanel::OnIconSelected,
this);
896 void OnPaint(wxPaintEvent& event)
898 auto size = GetClientSize();
899 int minsize = GetCharWidth() * 3;
900 auto offset = minsize / 4;
902 LoadIcon(m_icon_name.c_str(), m_bitmap, wxMax(1, minsize));
904 if (!m_bitmap.IsOk()) {
905 wxLogMessage(
"StatusPluginPanel: bitmap is not OK!");
909 int penWidth = m_penWidthUnselected;
910 wxColour border = GetDialogColor(DLG_UNSELECTED_ACCENT);
912 if(m_parent->GetSelected()){
913 penWidth = m_penWidthSelected;
914 border = GetDialogColor(DLG_SELECTED_ACCENT);
917 wxBrush b(m_parent->GetBackgroundColour(), wxSOLID);
919 dc.SetPen( wxPen(border, penWidth) );
921 dc.DrawRoundedRectangle(-20, 5, 20 + GetSize().x-10, GetSize().y-10, 5);
923 dc.DrawBitmap(m_bitmap, offset * 3 / 4, offset*3,
true);
930 void SetStatus(PluginStatus stat)
933 SetToolTip(message_by_status[m_stat]);
934 m_icon_name = icon_by_status[m_stat];
938 void OnIconSelected( wxMouseEvent &event )
941 m_parent->OnPluginSelected(event);
948 std::string m_icon_name;
951 int m_penWidthUnselected;
952 int m_penWidthSelected;
954 void LoadIcon(
const char* icon_name, wxBitmap& bitmap,
int size=32)
956 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
957 path.AppendDir(
"uidata");
958 path.AppendDir(
"traditional");
962 if (path.IsFileReadable()) {
963 bitmap = LoadSVG(path.GetFullPath(), size, size);
968 auto style = g_StyleManager->GetCurrentStyle();
969 bitmap = wxBitmap(style->GetIcon( _T(
"default_pi"), size, size));
970 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
981const wxEventType wxEVT_OCPN_MSG = wxNewEventType();
983OCPN_MsgEvent::OCPN_MsgEvent(wxEventType commandType,
int id)
984 : wxEvent(id, commandType) {}
986OCPN_MsgEvent::~OCPN_MsgEvent() {}
988wxEvent *OCPN_MsgEvent::Clone()
const {
990 newevent->m_MessageID =
993 newevent->m_MessageText = this->m_MessageText.c_str();
1002PlugInToolbarToolContainer::PlugInToolbarToolContainer() {
1004 bitmap_night = NULL;
1006 bitmap_Rollover_day = NULL;
1007 bitmap_Rollover_dusk = NULL;
1008 bitmap_Rollover_night = NULL;
1011PlugInToolbarToolContainer::~PlugInToolbarToolContainer() {
1013 delete bitmap_night;
1015 delete bitmap_Rollover_day;
1016 delete bitmap_Rollover_dusk;
1017 delete bitmap_Rollover_night;
1028#if !defined(__OCPN__ANDROID__) && defined(OCPN_USE_CURL)
1029EVT_CURL_END_PERFORM(CurlThreadId, PlugInManager::OnEndPerformCurlDownload)
1030EVT_CURL_DOWNLOAD(CurlThreadId, PlugInManager::OnCurlDownload)
1034static
void event_message_box(const wxString& msg) {
1035 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
1036 wxICON_INFORMATION | wxOK, 0);
1039static void event_message_box(
const wxString& msg, wxCommandEvent ev) {
1040 auto s = wxString::Format(msg, ev.GetString());
1041 event_message_box(s);
1046 if ((pic->m_cap_flag & INSTALLS_TOOLBOX_PAGE)) {
1047 if (!pic->m_bToolboxPanel) NotifySetupOptionsPlugin(pic);
1053PlugInManager::PlugInManager(
MyFrame *parent) {
1054#if !defined(__OCPN__ANDROID__) && defined(OCPN_USE_CURL)
1055 m_pCurlThread = NULL;
1061 MyFrame *pFrame = GetParentFrame();
1063 m_plugin_menu_item_id_next = CanvasMenuHandler::GetNextContextMenuId();
1064 m_plugin_tool_id_next = pFrame->GetNextToolbarToolId();
1067#ifdef __OCPN__ANDROID__
1075 as.Add(_T(
"Item0"));
1077 new wxRadioBox(pFrame, -1, _T(
""), wxPoint(0, 0), wxSize(-1, -1), as);
1083#if !defined(__OCPN__ANDROID__) && defined (OCPN_USE_CURL)
1085 m_last_online =
false;
1086 m_last_online_chk = -1;
1091 m_blacklist = blacklist_factory();
1092 m_blacklist_ui = std::unique_ptr<BlacklistUI>(
new BlacklistUI());
1094 wxDEFINE_EVENT(EVT_JSON_TO_ALL_PLUGINS,
ObservedEvt);
1095 evt_json_to_all_plugins_listener.
Listen(g_pRouteMan->
json_msg,
this,
1096 EVT_JSON_TO_ALL_PLUGINS);
1097 Bind(EVT_JSON_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
1098 auto json = std::static_pointer_cast<const wxJSONValue>(ev.GetSharedPtr());
1099 SendJSONMessageToAllPlugins(ev.GetString(), *json); });
1101 wxDEFINE_EVENT(EVT_LEGINFO_TO_ALL_PLUGINS,
ObservedEvt);
1103 EVT_LEGINFO_TO_ALL_PLUGINS);
1104 Bind(EVT_LEGINFO_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
1105 auto ptr = UnpackEvtPointer<ActiveLegDat>(ev);
1106 SendActiveLegInfoToAllPlugIns(ptr.get()); });
1108 HandlePluginLoaderEvents();
1109 InitCommListeners();
1111PlugInManager::~PlugInManager() {
1112#if !defined(__OCPN__ANDROID__) && defined (OCPN_USE_CURL)
1113 wxCurlBase::Shutdown();
1117void PlugInManager::InitCommListeners(
void) {
1122 auto& msgbus = NavMsgBus::GetInstance();
1127 auto ptr = ev.GetSharedPtr();
1128 auto n0183_msg = std::static_pointer_cast<const Nmea0183Msg>(ptr);
1129 HandleN0183(n0183_msg); });
1132 m_listener_SignalK.
Listen(sk_msg,
this, EVT_SIGNALK);
1135 HandleSignalK(UnpackEvtPointer<SignalkMsg>(ev));
1140void PlugInManager::HandleN0183( std::shared_ptr <const Nmea0183Msg> n0183_msg ) {
1142 std::string s = n0183_msg->payload;
1143 wxString sentence(s.c_str());
1146 const auto& drivers = CommDriverRegistry::GetInstance().
GetDrivers();
1147 auto target_driver = FindDriver(drivers, n0183_msg->source->iface);
1149 bool bpass_input_filter =
true;
1154 std::dynamic_pointer_cast<CommDriverN0183Serial>(target_driver);
1156 params = drv_serial->GetParams();
1158 auto drv_net = std::dynamic_pointer_cast<CommDriverN0183Net>(target_driver);
1160 params = drv_net->GetParams();
1165 bpass_input_filter = params.SentencePassesFilter(sentence,
1168 if (bpass_input_filter)
1169 SendNMEASentenceToAllPlugIns(sentence);
1171 else if (s[0] ==
'!'){
1173 SendAISSentenceToAllPlugIns(sentence);
1177void PlugInManager::HandleSignalK(std::shared_ptr<const SignalkMsg> sK_msg){
1178 wxJSONReader jsonReader;
1181 std::string msgTerminated = sK_msg->raw_message;;
1183 int errors = jsonReader.Parse(msgTerminated, &root);
1185 SendJSONMessageToAllPlugins(wxT(
"OCPN_CORE_SIGNALK"), root);
1195wxDEFINE_EVENT(EVT_PLUGMGR_ROUTEMAN_MSG,
ObservedEvt);
1196wxDEFINE_EVENT(EVT_BLACKLISTED_PLUGIN, wxCommandEvent);
1197wxDEFINE_EVENT(EVT_DEACTIVATE_PLUGIN, wxCommandEvent);
1198wxDEFINE_EVENT(EVT_INCOMPATIBLE_PLUGIN, wxCommandEvent);
1199wxDEFINE_EVENT(EVT_LOAD_DIRECTORY, wxCommandEvent);
1200wxDEFINE_EVENT(EVT_LOAD_PLUGIN, wxCommandEvent);
1201wxDEFINE_EVENT(EVT_PLUGIN_UNLOAD, wxCommandEvent);
1202wxDEFINE_EVENT(EVT_PLUGLIST_CHANGE, wxCommandEvent);
1203wxDEFINE_EVENT(EVT_UNREADABLE_PLUGIN, wxCommandEvent);
1204wxDEFINE_EVENT(EVT_UPDATE_CHART_TYPES, wxCommandEvent);
1205wxDEFINE_EVENT(EVT_PLUGIN_LOADALL_FINALIZE, wxCommandEvent);
1206wxDEFINE_EVENT(EVT_VERSION_INCOMPATIBLE_PLUGIN, wxCommandEvent);
1209void PlugInManager::HandlePluginLoaderEvents() {
1210 auto loader = PluginLoader::getInstance();
1212 evt_blacklisted_plugin_listener.
Listen(loader->evt_blacklisted_plugin,
1213 this, EVT_BLACKLISTED_PLUGIN);
1214 Bind(EVT_BLACKLISTED_PLUGIN, [&](wxCommandEvent& ev) {
1215 m_blacklist_ui->message(ev.GetString().ToStdString()); });
1217 evt_deactivate_plugin_listener.
Listen(loader->evt_deactivate_plugin,
1218 this, EVT_DEACTIVATE_PLUGIN);
1219 Bind(EVT_DEACTIVATE_PLUGIN, [&](wxCommandEvent& ev) {
1221 OnPluginDeactivate(pic); });
1223 evt_incompatible_plugin_listener.
Listen(loader->evt_incompatible_plugin,
1224 this, EVT_INCOMPATIBLE_PLUGIN);
1225 Bind(EVT_INCOMPATIBLE_PLUGIN,
1226 [&](wxCommandEvent& ev) { event_message_box(ev.GetString()); });
1228 evt_pluglist_change_listener.
Listen(loader->evt_pluglist_change,
1229 this, EVT_PLUGLIST_CHANGE);
1230 Bind(EVT_PLUGLIST_CHANGE, [&](wxCommandEvent&) {
1232 g_options->itemBoxSizerPanelPlugins->Layout(); });
1234 evt_load_directory_listener.
Listen(loader->evt_load_directory,
this,
1235 EVT_LOAD_DIRECTORY);
1236 Bind(EVT_LOAD_DIRECTORY, [&](wxCommandEvent&) {
1237 pConfig->SetPath(
"/PlugIns/");
1238 SetPluginOrder(pConfig->Read(
"PluginOrder", wxEmptyString)); });
1240 evt_load_plugin_listener.
Listen(loader->evt_load_plugin,
this,
1242 Bind(EVT_LOAD_PLUGIN, [&](wxCommandEvent& ev) {
1244 OnLoadPlugin(pic); });
1246 evt_version_incompatible_plugin_listener.
Listen(
1247 loader->evt_version_incompatible_plugin,
this,
1248 EVT_VERSION_INCOMPATIBLE_PLUGIN);
1249 Bind(EVT_VERSION_INCOMPATIBLE_PLUGIN, [&](wxCommandEvent& ev) {
1250 static const wxString msg =
1251 _(
"The plugin %s is not compatible with this version "
1252 "of OpenCPN, please get an updated version.");
1253 event_message_box(msg, ev); });
1255 evt_unreadable_plugin_listener.
Listen(loader->evt_blacklisted_plugin,
1256 this, EVT_UNREADABLE_PLUGIN);
1257 Bind(EVT_UNREADABLE_PLUGIN, [&](wxCommandEvent& ev) {
1258 static const wxString msg =
1259 _(
"Unreadable Plugin library %s detected, check file permissions:\n\n");
1260 event_message_box(msg, ev); });
1262 evt_incompatible_plugin_listener.
Listen(loader->evt_incompatible_plugin,
1263 this, EVT_INCOMPATIBLE_PLUGIN);
1264 Bind(EVT_INCOMPATIBLE_PLUGIN,
1265 [&](wxCommandEvent& ev) { event_message_box(ev.GetString()); });
1267 evt_update_chart_types_listener.
Listen(loader->evt_update_chart_types,
1268 this, EVT_UPDATE_CHART_TYPES);
1269 Bind(EVT_UPDATE_CHART_TYPES,
1270 [&](wxCommandEvent& ev) { UpDateChartDataTypes(); });
1272 evt_plugin_loadall_finalize_listener.
Listen(
1273 loader->evt_plugin_loadall_finalize,
this,
1274 EVT_PLUGIN_LOADALL_FINALIZE);
1275 Bind(EVT_PLUGIN_LOADALL_FINALIZE,
1276 [&](wxCommandEvent& ev) { FinalizePluginLoadall(); });
1279 EVT_PLUGMGR_AIS_MSG);
1281 EVT_PLUGMGR_ROUTEMAN_MSG);
1283 auto pTarget = UnpackEvtPointer<AisTargetData>(ev);
1284 SendAisJsonMessage(pTarget); });
1285 Bind(EVT_PLUGMGR_ROUTEMAN_MSG, [&](
ObservedEvt& ev) {
1286 auto msg = UnpackEvtPointer<wxJSONValue>(ev);
1287 SendJSONMessageToAllPlugins(ev.GetString(), *msg); });
1294wxDEFINE_EVENT(EVT_DOWNLOAD_FAILED, wxCommandEvent);
1295wxDEFINE_EVENT(EVT_DOWNLOAD_OK, wxCommandEvent);
1297void PlugInManager::HandlePluginHandlerEvents() {
1298 auto loader = PluginLoader::getInstance();
1300 evt_download_failed_listener.
Listen(loader->evt_update_chart_types,
1301 this, EVT_DOWNLOAD_FAILED);
1302 Bind(EVT_DOWNLOAD_FAILED, [&](wxCommandEvent& ev) {
1303 wxString message = _(
"Please check system log for more info.");
1304 OCPNMessageBox(gFrame, message, _(
"Installation error"),
1305 wxICON_ERROR | wxOK | wxCENTRE); });
1307 evt_download_ok_listener.
Listen(loader->evt_update_chart_types,
this,
1309 Bind(EVT_DOWNLOAD_OK, [&](wxCommandEvent& ev) {
1310 wxString message(ev.GetString());
1311 message += _(
" successfully installed from cache");
1312 OCPNMessageBox(gFrame, message, _(
"Installation complete"),
1313 wxICON_INFORMATION | wxOK | wxCENTRE); });
1323static void setLoadPath() {
1324 using namespace std;
1326 auto const osSystemId = wxPlatformInfo::Get().GetOperatingSystemId();
1328 if (osSystemId & wxOS_UNIX_LINUX) {
1329 string path = ocpn::join(dirs,
':');
1331 if (wxGetEnv(
"LD_LIBRARY_PATH", &envPath)) {
1332 path = path +
":" + envPath.ToStdString();
1334 wxLogMessage(
"Using LD_LIBRARY_PATH: %s", path.c_str());
1335 wxSetEnv(
"LD_LIBRARY_PATH", path.c_str());
1336 }
else if (osSystemId & wxOS_WINDOWS) {
1338 string path = ocpn::join(dirs,
';');
1340 if (wxGetEnv(
"PATH", &envPath)) {
1341 path = path +
";" + envPath.ToStdString();
1343 wxLogMessage(
"Using PATH: %s", path);
1344 wxSetEnv(
"PATH", path);
1345 }
else if (osSystemId & wxOS_MAC) {
1346 string path = ocpn::join(dirs,
':');
1348 if (wxGetEnv(
"DYLD_LIBRARY_PATH", &envPath)) {
1349 path = path +
":" + envPath.ToStdString();
1351 wxLogMessage(
"Using DYLD_LIBRARY_PATH: %s", path.c_str());
1352 wxSetEnv(
"DYLD_LIBRARY_PATH", path.c_str());
1354 wxString os_name = wxPlatformInfo::Get().GetPortIdName();
1355 if (os_name.Contains(_T(
"wxQT"))) {
1356 wxLogMessage(_T(
"setLoadPath() using Android library path"));
1358 wxLogWarning(
"SetLoadPath: Unsupported platform.");
1360 if (osSystemId & wxOS_MAC || osSystemId & wxOS_UNIX_LINUX) {
1362 string path = ocpn::join(dirs,
':');
1364 wxGetEnv(
"PATH", &envPath);
1365 path = path +
":" + envPath.ToStdString();
1366 wxLogMessage(
"Using PATH: %s", path);
1367 wxSetEnv(
"PATH", path);
1371bool PlugInManager::CallLateInit(
void) {
1374 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1375 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1378 switch (pic->m_api_version) {
1388 ProcessLateInit(pic);
1397 if (pic->m_cap_flag & WANTS_LATE_INIT) {
1398 wxString msg(_T(
"PlugInManager: Calling LateInit PlugIn: "));
1399 msg += pic->m_plugin_file;
1404 if (ppi) ppi->LateInit();
1410 if ((pic->m_cap_flag & INSTALLS_PLUGIN_CHART) ||
1411 (pic->m_cap_flag & INSTALLS_PLUGIN_CHART_GL)) {
1412 ChartData->PurgeCachePlugins();
1413 gFrame->InvalidateAllQuilts();
1417 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1420 if (pttc->m_pplugin == pic->m_pplugin) {
1421 m_PlugInToolbarTools.Remove(pttc);
1427 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1429 if (pimis->m_pplugin == pic->m_pplugin) {
1430 m_PlugInMenuItems.Remove(pimis);
1439void PlugInManager::SendVectorChartObjectInfo(
const wxString &chart,
1440 const wxString &feature,
1441 const wxString &objname,
1442 double &lat,
double &lon,
1443 double &
scale,
int &nativescale) {
1444 wxString decouple_chart(chart);
1445 wxString decouple_feature(feature);
1446 wxString decouple_objname(objname);
1447 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1448 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1450 if (pic->m_bEnabled && pic->m_bInitState) {
1451 if (pic->m_cap_flag & WANTS_VECTOR_CHART_OBJECT_INFO) {
1452 switch (pic->m_api_version) {
1463 ppi->SendVectorChartObjectInfo(decouple_chart, decouple_feature,
1464 decouple_objname, lat, lon,
scale,
1476bool PlugInManager::IsAnyPlugInChartEnabled() {
1479 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1480 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1482 if (pic->m_bEnabled && pic->m_bInitState) {
1483 if ((pic->m_cap_flag & INSTALLS_PLUGIN_CHART) ||
1484 (pic->m_cap_flag & INSTALLS_PLUGIN_CHART_GL))
1491void PlugInManager::UpdateManagedPlugins() {
1493 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1495 for (
size_t i = 0; i < plugin_array->GetCount(); i++) {
1496 pict = plugin_array->Item(i);
1497 plugin_array->Item(i)->m_pluginStatus = PluginStatus::Unmanaged;
1501 std::find(SYSTEM_PLUGINS.begin(), SYSTEM_PLUGINS.end(),
1502 plugin_array->Item(i)->m_common_name.Lower().ToStdString());
1503 if (r != SYSTEM_PLUGINS.end())
1504 plugin_array->Item(i)->m_pluginStatus = PluginStatus::System;
1507 std::vector<PluginMetadata> available = getCompatiblePlugins();
1513 for (
size_t i = 0; i < plugin_array->GetCount(); i++) {
1514 pict = plugin_array->Item(i);
1515 if (pict->m_ManagedMetadata.name
1517 bool bfound =
false;
1518 for (
auto plugin : available) {
1519 if (pict->m_common_name.IsSameAs(wxString(plugin.name.c_str()))) {
1525 if (!pict->m_pplugin) {
1526 plugin_array->Item(i)->m_pluginStatus =
1527 PluginStatus::PendingListRemoval;
1535 while ((i >= 0) && (i < plugin_array->GetCount())) {
1536 pict = plugin_array->Item(i);
1537 if (pict->m_pluginStatus == PluginStatus::PendingListRemoval) {
1538 plugin_array->RemoveAt(i);
1544 for (
size_t i = 0; i < plugin_array->GetCount(); i++) {
1545 pict = plugin_array->Item(i);
1550 for (
auto plugin : available) {
1553 bool bfound =
false;
1554 for (
size_t i = 0; i < plugin_array->GetCount(); i++) {
1555 pic = plugin_array->Item(i);
1556 if (plugin_array->Item(i)->m_common_name.IsSameAs(
1557 wxString(plugin.name.c_str()))) {
1566 new_pic->m_common_name = wxString(plugin.name.c_str());
1567 new_pic->m_pluginStatus = PluginStatus::ManagedInstallAvailable;
1568 new_pic->m_ManagedMetadata = plugin;
1569 new_pic->m_version_major = 0;
1570 new_pic->m_version_minor = 0;
1575 if (safe_mode::get_mode()) {
1576 std::string installed;
1580 if (path !=
"" && wxFileName::IsFileReadable(path)) {
1581 std::ifstream stream;
1582 stream.open(path, std::ifstream::in);
1583 stream >> installed;
1586 if (!installed.empty())
1587 new_pic->m_pluginStatus =
1588 PluginStatus::ManagedInstalledCurrentVersion;
1590 new_pic->m_pluginStatus = PluginStatus::Unknown;
1593 plugin_array->Add(new_pic);
1602 std::string installed;
1604 if (path !=
"" && wxFileName::IsFileReadable(path)) {
1605 std::ifstream stream;
1606 stream.open(path, std::ifstream::in);
1607 stream >> installed;
1609 pic->m_InstalledManagedVersion = installed;
1614 if (installedVersion < metaVersion)
1615 pic->m_pluginStatus = PluginStatus::ManagedInstalledUpdateAvailable;
1616 else if (installedVersion == metaVersion)
1617 pic->m_pluginStatus = PluginStatus::ManagedInstalledCurrentVersion;
1618 else if (installedVersion > metaVersion)
1619 pic->m_pluginStatus =
1620 PluginStatus::ManagedInstalledDowngradeAvailable;
1622 pic->m_ManagedMetadata = plugin;
1631 if (pic->m_api_version) {
1632 pic->m_pluginStatus = PluginStatus::LegacyUpdateAvailable;
1633 pic->m_ManagedMetadata = plugin;
1637 pic->m_pluginStatus = PluginStatus::ManagedInstallAvailable;
1646 std::map<std::string, PlugInContainer *> sortmap;
1647 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1649 if (pic->m_pluginStatus == PluginStatus::ManagedInstallAvailable) {
1650 plugin_array->Remove(pic);
1653 std::string name = pic->m_ManagedMetadata.name;
1654 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
1655 sortmap[name] = pic;
1662 for (std::map<std::string, PlugInContainer *>::iterator i = sortmap.begin();
1663 i != sortmap.end(); i++) {
1665 plugin_array->Insert(pic, 0);
1670 g_options->itemBoxSizerPanelPlugins->Layout();
1673bool PlugInManager::UpDateChartDataTypes() {
1675 if (NULL == ChartData)
return bret;
1677 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1678 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1681 if (pic->m_bInitState) {
1682 if ((pic->m_cap_flag & INSTALLS_PLUGIN_CHART) ||
1683 (pic->m_cap_flag & INSTALLS_PLUGIN_CHART_GL))
1688 if (bret) ChartData->UpdateChartClassDescriptorArray();
1693void PlugInManager::FinalizePluginLoadall() {
1698 SetColorSchemeForAllPlugIns( global_color_scheme );
1701 SendBaseConfigToAllPlugIns();
1702 SendS52ConfigToAllPlugIns(
true );
1703 SendSKConfigToAllPlugIns();
1707 if(gFrame->GetPrimaryCanvas()->GetglCanvas())
1708 gFrame->GetPrimaryCanvas()->GetglCanvas()->SendJSONConfigMessage();
1716void PlugInManager::SetPluginOrder(wxString serialized_names) {
1717 m_plugin_order.Empty();
1718 wxStringTokenizer tokenizer(serialized_names, _T(
";"));
1719 while (tokenizer.HasMoreTokens()) {
1720 m_plugin_order.Add(tokenizer.GetNextToken());
1724wxString PlugInManager::GetPluginOrder() {
1725 wxString plugins = wxEmptyString;
1726 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1727 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1728 plugins.Append(plugin_array->Item(i)->m_common_name);
1729 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1734bool PlugInManager::UpdateConfig() {
1738 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1739 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1743 wxString config_section = (_T (
"/PlugIns/" ));
1744 config_section += pic->m_plugin_filename;
1745 pConfig->SetPath(config_section);
1746 pConfig->Write(_T (
"bEnabled" ), pic->m_bEnabled);
1753void PlugInManager::ShowDeferredBlacklistMessages() {
1754 m_blacklist_ui->show_deferred_messages();
1757bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1759 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1762bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin *plugin) {
1763 int major = plugin->GetPlugInVersionMajor();
1764 int minor = plugin->GetPlugInVersionMinor();
1767 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1768 name.Replace(
"class ", wxEmptyString);
1770 const std::type_info &ti =
typeid(*plugin);
1772 char *realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1773 wxString name = wxString::FromAscii(realname);
1776 return CheckBlacklistedPlugin(name, major, minor);
1779bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
int minor) {
1780 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1781 if (block_status == plug_status::unblocked)
return true;
1782 plug_data data(name.ToStdString(), major, minor);
1783 auto msg = m_blacklist->get_message(block_status, data);
1784 m_blacklist_ui->message(msg);
1788bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC &dc,
1790 int canvasIndex,
int priority) {
1791 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1792 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1794 if (pic->m_bEnabled && pic->m_bInitState) {
1795 if (pic->m_cap_flag & WANTS_OVERLAY_CALLBACK) {
1798 wxDC *pdc = dc.GetDC();
1801 switch (pic->m_api_version) {
1807 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1815 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1830 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1840 ppi->RenderOverlay(*pdc, &pivp);
1845 ppi116->RenderOverlayMultiCanvas(*pdc, &pivp, canvasIndex);
1849 if (priority <= 0) {
1853 ppi->RenderOverlay(*pdc, &pivp);
1868 if (pic->m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1870 if ((m_cached_overlay_bm.GetWidth() != vp.pix_width) ||
1871 (m_cached_overlay_bm.GetHeight() != vp.pix_height))
1872 m_cached_overlay_bm.Create(vp.pix_width, vp.pix_height, -1);
1875 mdc.SelectObject(m_cached_overlay_bm);
1876 mdc.SetBackground(*wxBLACK_BRUSH);
1879 bool b_rendered =
false;
1881 switch (pic->m_api_version) {
1887 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1895 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1910 if (ppi) b_rendered = ppi->RenderOverlay(*pdc, &pivp);
1920 b_rendered = ppi->RenderOverlay(*pdc, &pivp);
1925 b_rendered = ppi116->RenderOverlayMultiCanvas(*pdc, &pivp,
1930 if (priority <= 0) {
1934 b_rendered = ppi->RenderOverlay(*pdc, &pivp);
1946 b_rendered = pic->m_pplugin->RenderOverlay(&mdc, &pivp);
1951 mdc.SelectObject(wxNullBitmap);
1954 wxMask *p_msk =
new wxMask(m_cached_overlay_bm, wxColour(0, 0, 0));
1955 m_cached_overlay_bm.SetMask(p_msk);
1957 dc.DrawBitmap(m_cached_overlay_bm, 0, 0,
true);
1960 }
else if (pic->m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1968bool PlugInManager::RenderAllGLCanvasOverlayPlugIns(wxGLContext *pcontext,
1970 int canvasIndex,
int priority) {
1971 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1972 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1974 if (pic->m_bEnabled && pic->m_bInitState) {
1975 if (pic->m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1978 switch (pic->m_api_version) {
1984 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
2000 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
2010 ppi->RenderGLOverlay(pcontext, &pivp);
2015 ppi116->RenderGLOverlayMultiCanvas(pcontext, &pivp, canvasIndex);
2020 if (priority <= 0) {
2024 ppi->RenderGLOverlay(pcontext, &pivp);
2044bool PlugInManager::SendMouseEventToPlugins(wxMouseEvent &event) {
2046 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2047 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2049 if (pic->m_bEnabled && pic->m_bInitState) {
2050 if (pic->m_cap_flag & WANTS_MOUSE_EVENTS) {
2051 switch (pic->m_api_version) {
2062 if (ppi->MouseEventHook(event)) bret =
true;
2075bool PlugInManager::SendKeyEventToPlugins(wxKeyEvent &event) {
2077 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2078 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2080 if (pic->m_bEnabled && pic->m_bInitState) {
2081 if (pic->m_cap_flag & WANTS_KEYBOARD_EVENTS) {
2083 switch (pic->m_api_version) {
2092 if (ppi && ppi->KeyboardEventHook(event)) bret =
true;
2107void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort &vp) {
2108 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2109 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2111 if (pic->m_bEnabled && pic->m_bInitState) {
2112 if (pic->m_cap_flag & WANTS_ONPAINT_VIEWPORT) {
2114 if (pic->m_pplugin) pic->m_pplugin->SetCurrentViewPort(pivp);
2120void PlugInManager::SendCursorLatLonToAllPlugIns(
double lat,
double lon) {
2121 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2122 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2124 if (pic->m_bEnabled && pic->m_bInitState) {
2125 if (pic->m_cap_flag & WANTS_CURSOR_LATLON)
2126 if (pic->m_pplugin) pic->m_pplugin->SetCursorLatLon(lat, lon);
2132 if (pic->m_bEnabled && pic->m_bInitState) {
2133 if (pic->m_cap_flag & INSTALLS_TOOLBOX_PAGE) {
2134 switch (pic->m_api_version) {
2148 ppi->OnSetupOptions();
2160void PlugInManager::NotifySetupOptions() {
2161 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2162 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2164 NotifySetupOptionsPlugin(pic);
2169 int ok_apply_cancel) {
2170 if (pic->m_bEnabled && pic->m_bInitState) {
2171 if ((pic->m_cap_flag & INSTALLS_TOOLBOX_PAGE) && pic->m_bToolboxPanel) {
2172 pic->m_pplugin->OnCloseToolboxPanel(0, ok_apply_cancel);
2173 pic->m_bToolboxPanel =
false;
2178void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
2179 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2180 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2183 ClosePlugInPanel(pic, ok_apply_cancel);
2188int PlugInManager::AddCanvasContextMenuItem(wxMenuItem *pitem,
2192 pmic->pmenu_item = pitem;
2193 pmic->m_pplugin = pplugin;
2194 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
2195 : m_plugin_menu_item_id_next;
2197 pmic->b_grey =
false;
2198 pmic->m_in_menu = name;
2200 m_PlugInMenuItems.Add(pmic);
2202 m_plugin_menu_item_id_next++;
2207void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char *name) {
2208 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
2211 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
2212 m_PlugInMenuItems.Remove(pimis);
2220void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
2222 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
2225 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
2233void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
2235 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
2238 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
2239 pimis->b_grey = grey;
2246void PlugInManager::SendNMEASentenceToAllPlugIns(
const wxString &sentence) {
2247 wxString decouple_sentence(
2252 sigaction(SIGSEGV, NULL, &sa_all_PIM_previous);
2254 struct sigaction temp;
2255 sigaction(SIGSEGV, NULL, &temp);
2257 temp.sa_handler = catch_signals_PIM;
2258 sigemptyset(&temp.sa_mask);
2263 sigaction(SIGSEGV, &temp, NULL);
2265 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2266 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2268 if (pic->m_bEnabled && pic->m_bInitState) {
2269 if (pic->m_cap_flag & WANTS_NMEA_SENTENCES) {
2271 if (sigsetjmp(env_PIM,
2276 sigaction(SIGSEGV, &sa_all_PIM_previous,
2285 pic->m_pplugin->SetNMEASentence(decouple_sentence);
2292 sigaction(SIGSEGV, &sa_all_PIM_previous, NULL);
2296int PlugInManager::GetJSONMessageTargetCount() {
2298 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2299 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2301 if (pic->m_bEnabled && pic->m_bInitState &&
2302 (pic->m_cap_flag & WANTS_PLUGIN_MESSAGING))
2308void PlugInManager::SendJSONMessageToAllPlugins(
const wxString &message_id,
2313 SendMessageToAllPlugins(message_id, out);
2314 wxLogDebug(message_id);
2318void PlugInManager::SendMessageToAllPlugins(
const wxString &message_id,
2319 const wxString &message_body) {
2320 g_lastPluginMessage = message_body;
2322 wxString decouple_message_id(
2325 wxString decouple_message_body(
2328 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2329 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2331 if (pic->m_bEnabled && pic->m_bInitState) {
2332 if (pic->m_cap_flag & WANTS_PLUGIN_MESSAGING) {
2333 switch (pic->m_api_version) {
2338 ppi->SetPluginMessage(decouple_message_id, decouple_message_body);
2345 ppi->SetPluginMessage(decouple_message_id, decouple_message_body);
2362 ppi->SetPluginMessage(decouple_message_id, decouple_message_body);
2373void PlugInManager::SendAISSentenceToAllPlugIns(
const wxString &sentence) {
2374 wxString decouple_sentence(
2377 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2378 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2380 if (pic->m_bEnabled && pic->m_bInitState) {
2381 if (pic->m_cap_flag & WANTS_AIS_SENTENCES)
2382 pic->m_pplugin->SetAISSentence(decouple_sentence);
2387void PlugInManager::SendPositionFixToAllPlugIns(
GenericPosDatEx *ppos) {
2390 pfix.Lat = ppos->kLat;
2391 pfix.Lon = ppos->kLon;
2392 pfix.Cog = ppos->kCog;
2393 pfix.Sog = ppos->kSog;
2394 pfix.Var = ppos->kVar;
2395 pfix.FixTime = ppos->FixTime;
2396 pfix.nSats = ppos->nSats;
2398 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2399 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2401 if (pic->m_bEnabled && pic->m_bInitState) {
2402 if (pic->m_cap_flag & WANTS_NMEA_EVENTS)
2403 if (pic->m_pplugin) pic->m_pplugin->SetPositionFix(pfix);
2409 pfix_ex.Lat = ppos->kLat;
2410 pfix_ex.Lon = ppos->kLon;
2411 pfix_ex.Cog = ppos->kCog;
2412 pfix_ex.Sog = ppos->kSog;
2413 pfix_ex.Var = ppos->kVar;
2414 pfix_ex.FixTime = ppos->FixTime;
2415 pfix_ex.nSats = ppos->nSats;
2416 pfix_ex.Hdt = ppos->kHdt;
2417 pfix_ex.Hdm = ppos->kHdm;
2419 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2421 if (pic->m_bEnabled && pic->m_bInitState) {
2422 if (pic->m_cap_flag & WANTS_NMEA_EVENTS) {
2423 switch (pic->m_api_version) {
2437 if (ppi) ppi->SetPositionFixEx(pfix_ex);
2448void PlugInManager::SendActiveLegInfoToAllPlugIns(
const ActiveLegDat *leg_info) {
2450 leg.Btw = leg_info->Btw;
2451 leg.Dtw = leg_info->Dtw;
2452 leg.wp_name = leg_info->wp_name;
2453 leg.Xte = leg_info->Xte;
2454 leg.arrival = leg_info->arrival;
2455 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2456 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2458 if (pic->m_bEnabled && pic->m_bInitState) {
2459 if (pic->m_cap_flag & WANTS_NMEA_EVENTS) {
2460 switch (pic->m_api_version) {
2475 if (ppi) ppi->SetActiveLegInfo(leg);
2486void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
2487 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2488 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2490 if (pic->m_bEnabled && pic->m_bInitState)
2491 pic->m_pplugin->ProcessParentResize(x, y);
2495void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
2496 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2497 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2499 if (pic->m_bEnabled && pic->m_bInitState)
2500 pic->m_pplugin->SetColorScheme((PI_ColorScheme)cs);
2504void PlugInManager::PrepareAllPluginContextMenus() {
2505 int canvasIndex = gFrame->GetCanvasIndexUnderMouse();
2506 if (canvasIndex < 0)
return;
2508 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2509 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2511 if (pic->m_bEnabled && pic->m_bInitState) {
2512 if (pic->m_cap_flag & INSTALLS_CONTEXTMENU_ITEMS) {
2513 switch (pic->m_api_version) {
2519 if (ppi) ppi->PrepareContextMenu(canvasIndex);
2532void PlugInManager::SendSKConfigToAllPlugIns() {
2535 v[_T(
"self")] = g_ownshipMMSI_SK;
2539 SendMessageToAllPlugins(wxString(_T(
"OCPN_CORE_SIGNALK")), out);
2542void PlugInManager::SendBaseConfigToAllPlugIns() {
2545 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
2546 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
2547 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
2548 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
2549 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
2552 if (g_MainToolbar) {
2553 v[_T(
"OpenCPN Toolbar Width")] = g_MainToolbar->GetSize().x;
2554 v[_T(
"OpenCPN Toolbar Height")] = g_MainToolbar->GetSize().y;
2555 v[_T(
"OpenCPN Toolbar PosnX")] = g_MainToolbar->GetPosition().x;
2556 v[_T(
"OpenCPN Toolbar PosnY")] = g_MainToolbar->GetPosition().y;
2560 v[_T(
"OpenCPN Zoom Mod Vector")] = g_chart_zoom_modifier_vector;
2561 v[_T(
"OpenCPN Zoom Mod Other")] = g_chart_zoom_modifier_raster;
2562 v[_T(
"OpenCPN Scale Factor Exp")] = g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
2563 v[_T(
"OpenCPN Display Width")] = (int)g_display_size_mm;
2564 v[_T(
"OpenCPN Content Scale Factor")] = OCPN_GetDisplayContentScaleFactor();
2565 v[_T(
"OpenCPN Display DIP Scale Factor")] = OCPN_GetWinDIPScaleFactor();
2570 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
2573void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
2576 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
2577 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
2578 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
2579 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
2580 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
2588 v[_T(
"OpenCPN S52PLIB ShowAnchorConditions")] = ps52plib->GetAnchorOn();
2589 v[_T(
"OpenCPN S52PLIB ShowQualityOfData")] = ps52plib->GetQualityOfData();
2594 v[_T(
"OpenCPN S52PLIB MetaDisplay")] = ps52plib->m_bShowMeta;
2595 v[_T(
"OpenCPN S52PLIB DeclutterText")] = ps52plib->m_bDeClutterText;
2596 v[_T(
"OpenCPN S52PLIB ShowNationalText")] = ps52plib->m_bShowNationalTexts;
2597 v[_T(
"OpenCPN S52PLIB ShowImportantTextOnly")] =
2598 ps52plib->m_bShowS57ImportantTextOnly;
2599 v[_T(
"OpenCPN S52PLIB UseSCAMIN")] = ps52plib->m_bUseSCAMIN;
2600 v[_T(
"OpenCPN S52PLIB UseSUPER_SCAMIN")] = ps52plib->m_bUseSUPER_SCAMIN;
2601 v[_T(
"OpenCPN S52PLIB SymbolStyle")] = ps52plib->m_nSymbolStyle;
2602 v[_T(
"OpenCPN S52PLIB BoundaryStyle")] = ps52plib->m_nBoundaryStyle;
2603 v[_T(
"OpenCPN S52PLIB ColorShades")] = S52_getMarinerParam(S52_MAR_TWO_SHADES);
2604 v[_T(
"OpenCPN S52PLIB Safety Depth")] = (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
2605 v[_T(
"OpenCPN S52PLIB Shallow Contour")] = (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
2606 v[_T(
"OpenCPN S52PLIB Deep Contour")] = (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
2610 v[_T(
"OpenCPN S52PLIB GlobalReconfig")] = bReconfig;
2615 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
2618void PlugInManager::NotifyAuiPlugIns(
void) {
2619 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2620 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2622 if (pic->m_bEnabled && pic->m_bInitState &&
2623 (pic->m_cap_flag & USES_AUI_MANAGER))
2624 pic->m_pplugin->UpdateAuiStatus();
2628int PlugInManager::AddToolbarTool(wxString label, wxBitmap *bitmap,
2629 wxBitmap *bmpRollover, wxItemKind kind,
2630 wxString shortHelp, wxString longHelp,
2631 wxObject *clientData,
int position,
2634 pttc->label = label;
2636 if (!bitmap->IsOk()) {
2638 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
2641 pttc->bitmap_day =
new wxBitmap(*bitmap);
2642 pttc->bitmap_day->UnShare();
2645 if (!bmpRollover->IsOk()) {
2647 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
2650 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
2651 pttc->bitmap_Rollover_day->UnShare();
2654 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
2655 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
2656 pttc->bitmap_Rollover_dusk =
2657 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
2658 pttc->bitmap_Rollover_night =
2659 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
2662 pttc->shortHelp = shortHelp;
2663 pttc->longHelp = longHelp;
2664 pttc->clientData = clientData;
2665 pttc->position = position;
2666 pttc->m_pplugin = pplugin;
2667 pttc->tool_sel = tool_sel;
2669 pttc->b_toggle =
false;
2670 pttc->id = m_plugin_tool_id_next;
2672 m_PlugInToolbarTools.Add(pttc);
2674 m_plugin_tool_id_next++;
2679int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
2680 wxString SVGRolloverfile,
2681 wxString SVGToggledfile, wxItemKind kind,
2682 wxString shortHelp, wxString longHelp,
2683 wxObject *clientData,
int position,
2686 pttc->label = label;
2688 pttc->pluginNormalIconSVG = SVGfile;
2689 pttc->pluginRolloverIconSVG = SVGRolloverfile;
2690 pttc->pluginToggledIconSVG = SVGToggledfile;
2695 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
2696 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
2698 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
2699 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
2700 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
2701 pttc->bitmap_Rollover_dusk =
2702 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
2703 pttc->bitmap_Rollover_night =
2704 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
2707 pttc->shortHelp = shortHelp;
2708 pttc->longHelp = longHelp;
2709 pttc->clientData = clientData;
2710 pttc->position = position;
2711 pttc->m_pplugin = pplugin;
2712 pttc->tool_sel = tool_sel;
2714 pttc->b_toggle =
false;
2715 pttc->id = m_plugin_tool_id_next;
2717 m_PlugInToolbarTools.Add(pttc);
2719 m_plugin_tool_id_next++;
2724void PlugInManager::RemoveToolbarTool(
int tool_id) {
2725 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2728 if (pttc->id == tool_id) {
2729 m_PlugInToolbarTools.Remove(pttc);
2736 pParent->RequestNewToolbars();
2739void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
2740 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2743 if (pttc->id == item) {
2747 pParent->RequestNewToolbars();
2755void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
2756 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2759 if (pttc->id == item) {
2760 pttc->b_toggle = toggle;
2761 pParent->SetMasterToolbarItemState(item, toggle);
2768void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap *bitmap,
2769 wxBitmap *bmpRollover) {
2770 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2773 if (pttc->id == item) {
2774 delete pttc->bitmap_day;
2775 delete pttc->bitmap_dusk;
2776 delete pttc->bitmap_night;
2777 delete pttc->bitmap_Rollover_day;
2779 if (!bitmap->IsOk()) {
2781 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
2784 pttc->bitmap_day =
new wxBitmap(*bitmap);
2785 pttc->bitmap_day->UnShare();
2788 if (!bmpRollover->IsOk()) {
2790 pttc->bitmap_Rollover_day =
2791 new wxBitmap(style->GetIcon(_T(
"default_pi")));
2794 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
2795 pttc->bitmap_Rollover_day->UnShare();
2798 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
2799 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
2801 pParent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
2802 pttc->bitmap_Rollover_day);
2809void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2810 wxString SVGfileRollover,
2811 wxString SVGfileToggled) {
2812 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2815 if (pttc->id == item) {
2816 pttc->pluginNormalIconSVG = SVGfile;
2817 pttc->pluginRolloverIconSVG = SVGfileRollover;
2818 pttc->pluginToggledIconSVG = SVGfileToggled;
2819 pParent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2820 pttc->pluginRolloverIconSVG,
2821 pttc->pluginToggledIconSVG);
2829 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2831 if (
id == pc->id)
return pc->m_pplugin;
2837wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2840 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2841 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2843 if (pic && (pic->m_pplugin == ppi))
return pic->m_common_name;
2847 return wxEmptyString;
2850wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2852wxBitmap *PlugInManager::BuildDimmedToolBitmap(wxBitmap *pbmp_normal,
2853 unsigned char dim_ratio) {
2854 wxImage img_dup = pbmp_normal->ConvertToImage();
2856 if (!img_dup.IsOk())
return NULL;
2858 if (dim_ratio < 200) {
2860 int gimg_width = img_dup.GetWidth();
2861 int gimg_height = img_dup.GetHeight();
2863 double factor = (double)(dim_ratio) / 256.0;
2865 for (
int iy = 0; iy < gimg_height; iy++) {
2866 for (
int ix = 0; ix < gimg_width; ix++) {
2867 if (!img_dup.IsTransparent(ix, iy)) {
2868 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2869 img_dup.GetGreen(ix, iy),
2870 img_dup.GetBlue(ix, iy));
2871 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2872 hsv.value = hsv.value * factor;
2873 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2874 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2881 wxBitmap *ptoolBarBitmap;
2884 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2886 dwxdc.SelectObject(tbmp);
2888 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC &)dwxdc);
2890 ptoolBarBitmap =
new wxBitmap(img_dup);
2894 return ptoolBarBitmap;
2897wxArrayString PlugInManager::GetPlugInChartClassNameArray(
void) {
2898 wxArrayString array;
2899 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2900 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2902 if (pic->m_bEnabled && pic->m_bInitState &&
2903 ((pic->m_cap_flag & INSTALLS_PLUGIN_CHART) ||
2904 (pic->m_cap_flag & INSTALLS_PLUGIN_CHART_GL))) {
2905 wxArrayString carray = pic->m_pplugin->GetDynamicChartClassNameArray();
2907 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2908 array.Add(carray[j]);
2916 while (j < array.GetCount()) {
2917 wxString test = array[j];
2918 unsigned int k = j + 1;
2919 while (k < array.GetCount()) {
2920 if (test == array[k]) {
2939int InsertPlugInTool(wxString label, wxBitmap *bitmap, wxBitmap *bmpRollover,
2940 wxItemKind kind, wxString shortHelp, wxString longHelp,
2941 wxObject *clientData,
int position,
int tool_sel,
2944 return s_ppim->AddToolbarTool(label, bitmap, bmpRollover, kind, shortHelp,
2945 longHelp, clientData, position, tool_sel,
2951void RemovePlugInTool(
int tool_id) {
2952 if (s_ppim) s_ppim->RemoveToolbarTool(tool_id);
2955void SetToolbarToolViz(
int item,
bool viz) {
2956 if (s_ppim) s_ppim->SetToolbarToolViz(item, viz);
2959void SetToolbarItemState(
int item,
bool toggle) {
2960 if (s_ppim) s_ppim->SetToolbarItemState(item, toggle);
2963void SetToolbarToolBitmaps(
int item, wxBitmap *bitmap, wxBitmap *bmpRollover) {
2964 if (s_ppim) s_ppim->SetToolbarItemBitmaps(item, bitmap, bmpRollover);
2967int InsertPlugInToolSVG(wxString label, wxString SVGfile,
2968 wxString SVGfileRollover, wxString SVGfileToggled,
2969 wxItemKind kind, wxString shortHelp, wxString longHelp,
2970 wxObject *clientData,
int position,
int tool_sel,
2973 return s_ppim->AddToolbarTool(label, SVGfile, SVGfileRollover,
2974 SVGfileToggled, kind, shortHelp, longHelp,
2975 clientData, position, tool_sel, pplugin);
2980void SetToolbarToolBitmapsSVG(
int item, wxString SVGfile,
2981 wxString SVGfileRollover,
2982 wxString SVGfileToggled) {
2984 s_ppim->SetToolbarItemBitmaps(item, SVGfile, SVGfileRollover,
2991 return s_ppim->AddCanvasContextMenuItem(pitem, pplugin, name);
2996void SetCanvasMenuItemViz(
int item,
bool viz,
const char *name) {
2997 if (s_ppim) s_ppim->SetCanvasContextMenuItemViz(item, viz, name);
3000void SetCanvasMenuItemGrey(
int item,
bool grey,
const char *name) {
3001 if (s_ppim) s_ppim->SetCanvasContextMenuItemGrey(item, grey, name);
3004void RemoveCanvasMenuItem(
int item,
const char *name) {
3005 if (s_ppim) s_ppim->RemoveCanvasContextMenuItem(item, name);
3008int AddCanvasContextMenuItem(wxMenuItem *pitem,
opencpn_plugin *pplugin) {
3010 return AddCanvasMenuItem(pitem, pplugin,
"");
3013void SetCanvasContextMenuItemViz(
int item,
bool viz) {
3014 SetCanvasMenuItemViz(item, viz);
3017void SetCanvasContextMenuItemGrey(
int item,
bool grey) {
3018 SetCanvasMenuItemGrey(item, grey);
3021void RemoveCanvasContextMenuItem(
int item) { RemoveCanvasMenuItem(item); }
3023wxFileConfig *GetOCPNConfigObject(
void) {
3030wxWindow *GetOCPNCanvasWindow() {
3031 wxWindow *pret = NULL;
3033 MyFrame *pFrame = s_ppim->GetParentFrame();
3034 pret = (wxWindow *)pFrame->GetPrimaryCanvas();
3039void RequestRefresh(wxWindow *win) {
3040 if (win) win->Refresh();
3043void GetCanvasPixLL(
PlugIn_ViewPort *vp, wxPoint *pp,
double lat,
double lon) {
3046 ocpn_vp.clat = vp->clat;
3047 ocpn_vp.clon = vp->clon;
3048 ocpn_vp.m_projection_type = vp->m_projection_type;
3049 ocpn_vp.view_scale_ppm = vp->view_scale_ppm;
3050 ocpn_vp.skew = vp->skew;
3051 ocpn_vp.rotation = vp->rotation;
3052 ocpn_vp.pix_width = vp->pix_width;
3053 ocpn_vp.pix_height = vp->pix_height;
3055 wxPoint ret = ocpn_vp.GetPixFromLL(lat, lon);
3060void GetDoubleCanvasPixLL(
PlugIn_ViewPort *vp, wxPoint2DDouble *pp,
double lat,
3064 ocpn_vp.clat = vp->clat;
3065 ocpn_vp.clon = vp->clon;
3066 ocpn_vp.m_projection_type = vp->m_projection_type;
3067 ocpn_vp.view_scale_ppm = vp->view_scale_ppm;
3068 ocpn_vp.skew = vp->skew;
3069 ocpn_vp.rotation = vp->rotation;
3070 ocpn_vp.pix_width = vp->pix_width;
3071 ocpn_vp.pix_height = vp->pix_height;
3073 *pp = ocpn_vp.GetDoublePixFromLL(lat, lon);
3080 ocpn_vp.clat = vp->clat;
3081 ocpn_vp.clon = vp->clon;
3082 ocpn_vp.m_projection_type = vp->m_projection_type;
3083 ocpn_vp.view_scale_ppm = vp->view_scale_ppm;
3084 ocpn_vp.skew = vp->skew;
3085 ocpn_vp.rotation = vp->rotation;
3086 ocpn_vp.pix_width = vp->pix_width;
3087 ocpn_vp.pix_height = vp->pix_height;
3089 return ocpn_vp.GetLLFromPix(p, plat, plon);
3092bool GetGlobalColor(wxString colorName, wxColour *pcolour) {
3093 wxColour c = GetGlobalColor(colorName);
3099wxFont *OCPNGetFont(wxString TextElement,
int default_size) {
3100 return FontMgr::Get().GetFont(TextElement, default_size);
3103wxFont *GetOCPNScaledFont_PlugIn(wxString TextElement,
int default_size) {
3104 return GetOCPNScaledFont(TextElement, default_size);
3107double GetOCPNGUIToolScaleFactor_PlugIn(
int GUIScaleFactor) {
3108 return g_Platform->GetToolbarScaleFactor(GUIScaleFactor);
3111double GetOCPNGUIToolScaleFactor_PlugIn() {
3112 return g_Platform->GetToolbarScaleFactor(g_GUIScaleFactor);
3115float GetOCPNChartScaleFactor_Plugin() {
3116 return g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
3119wxFont GetOCPNGUIScaledFont_PlugIn(wxString item) {
3120 return GetOCPNGUIScaledFont(item);
3123bool AddPersistentFontKey(wxString TextElement) {
3124 return FontMgr::Get().AddAuxKey(TextElement);
3127wxString GetActiveStyleName() {
3129 return g_StyleManager->GetCurrentStyle()->name;
3134wxBitmap GetBitmapFromSVGFile(wxString filename,
unsigned int width,
3135 unsigned int height) {
3136 wxBitmap bmp = LoadSVG(filename, width, height);
3144 SVGDocumentPixelSize(filename, w, h);
3145 return LoadSVG(filename, w, h);
3149bool IsTouchInterface_PlugIn(
void) {
return g_btouch; }
3151wxColour GetFontColour_PlugIn(wxString TextElement) {
3152 return FontMgr::Get().GetFontColor(TextElement);
3155wxString *GetpSharedDataLocation(
void) {
3156 return g_Platform->GetSharedDataDirPtr();
3159wxString *GetpPrivateApplicationDataLocation(
void) {
3160 return g_Platform->GetPrivateDataDirPtr();
3163ArrayOfPlugIn_AIS_Targets *GetAISTargetArray(
void) {
3164 if (!g_pAIS)
return NULL;
3166 ArrayOfPlugIn_AIS_Targets *pret =
new ArrayOfPlugIn_AIS_Targets;
3169 for (
const auto &it : g_pAIS->GetTargetList()) {
3170 auto td = it.second;
3178 td.n_alarm_state = AIS_ALARM_SET;
3185wxAuiManager *GetFrameAuiManager(
void) {
return g_pauimgr; }
3187bool AddLocaleCatalog(wxString catalog) {
3188#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
3190 if (plocale_def_lang) {
3192 g_locale_catalog_array.Add(catalog);
3194 return plocale_def_lang->AddCatalog(catalog);
3200void PushNMEABuffer(wxString buf) {
3202 std::string full_sentence = buf.ToStdString();
3204 if ((full_sentence[0] ==
'$') || (full_sentence[0] ==
'!')) {
3205 std::string identifier;
3207 identifier = full_sentence.substr(1, 5);
3211 auto address = std::make_shared<NavAddr0183>(
"virtual");
3212 auto msg = std::make_shared<const Nmea0183Msg>(identifier, full_sentence,
3214 auto msg_all = std::make_shared<const Nmea0183Msg>(*msg,
"ALL");
3216 auto& msgbus = NavMsgBus::GetInstance();
3218 msgbus.Notify(std::move(msg));
3219 msgbus.Notify(std::move(msg_all));
3223wxXmlDocument GetChartDatabaseEntryXML(
int dbIndex,
bool b_getGeom) {
3224 wxXmlDocument doc = ChartData->GetXMLDescription(dbIndex, b_getGeom);
3229bool UpdateChartDBInplace(wxArrayString dir_array,
bool b_force_update,
3230 bool b_ProgressDialog) {
3232 ArrayOfCDI ChartDirArray;
3233 for (
unsigned int i = 0; i < dir_array.GetCount(); i++) {
3234 wxString dirname = dir_array[i];
3236 cdi.fullpath = dirname;
3237 cdi.magic_number = _T(
"");
3238 ChartDirArray.Add(cdi);
3241 bool b_ret = gFrame->UpdateChartDatabaseInplace(ChartDirArray, b_force_update,
3243 ChartData->GetDBFileName());
3245 gFrame->ChartsRefresh();
3250wxArrayString GetChartDBDirArrayString() {
3251 return ChartData->GetChartDirArrayString();
3254int AddChartToDBInPlace(wxString &full_path,
bool b_RefreshCanvas) {
3256 wxFileName fn(full_path);
3257 wxString fdir = fn.GetPath();
3261 bret = ChartData->AddSingleChart(full_path);
3265 pConfig->UpdateChartDirs(ChartData->GetChartDirArray());
3266 ChartData->SaveBinary(ChartListFileName);
3269 ArrayOfCDI XnewChartDirArray;
3270 pConfig->LoadChartDirArray(XnewChartDirArray);
3273 ChartData->LoadBinary(ChartListFileName, XnewChartDirArray);
3276 if (g_pGroupArray) ChartData->ApplyGroupArray(g_pGroupArray);
3278 if (g_boptionsactive) {
3279 g_options->UpdateDisplayedChartDirList(ChartData->GetChartDirArray());
3282 if (b_RefreshCanvas || !gFrame->GetPrimaryCanvas()->GetQuiltMode()) {
3283 gFrame->ChartsRefresh();
3290int RemoveChartFromDBInPlace(wxString &full_path) {
3293 bret = ChartData->RemoveSingleChart(full_path);
3296 pConfig->UpdateChartDirs(ChartData->GetChartDirArray());
3297 ChartData->SaveBinary(ChartListFileName);
3300 ArrayOfCDI XnewChartDirArray;
3301 pConfig->LoadChartDirArray(XnewChartDirArray);
3304 ChartData->LoadBinary(ChartListFileName, XnewChartDirArray);
3307 if (g_pGroupArray) ChartData->ApplyGroupArray(g_pGroupArray);
3309 if (g_boptionsactive) {
3310 g_options->UpdateDisplayedChartDirList(ChartData->GetChartDirArray());
3313 gFrame->ChartsRefresh();
3319wxString GetLocaleCanonicalName() {
return g_locale; }
3321void SendPluginMessage(wxString message_id, wxString message_body) {
3322 s_ppim->SendMessageToAllPlugins(message_id, message_body);
3330 Nevent.SetID(message_id);
3331 Nevent.SetJSONText(message_body);
3332 gFrame->GetEventHandler()->AddPendingEvent(Nevent);
3335void DimeWindow(wxWindow *win) { DimeControl(win); }
3337void JumpToPosition(
double lat,
double lon,
double scale) {
3338 gFrame->JumpToPosition(gFrame->GetFocusCanvas(), lat, lon,
scale);
3342wxScrolledWindow *AddOptionsPage(OptionsParentPI parent, wxString title) {
3343 if (!g_pOptions)
return NULL;
3347 case PI_OPTIONS_PARENT_DISPLAY:
3348 parentid = g_pOptions->m_pageDisplay;
3350 case PI_OPTIONS_PARENT_CONNECTIONS:
3351 parentid = g_pOptions->m_pageConnections;
3353 case PI_OPTIONS_PARENT_CHARTS:
3354 parentid = g_pOptions->m_pageCharts;
3356 case PI_OPTIONS_PARENT_SHIPS:
3357 parentid = g_pOptions->m_pageShips;
3359 case PI_OPTIONS_PARENT_UI:
3360 parentid = g_pOptions->m_pageUI;
3362 case PI_OPTIONS_PARENT_PLUGINS:
3363 parentid = g_pOptions->m_pagePlugins;
3367 _T(
"Error in PluginManager::AddOptionsPage: Unknown parent"));
3372 return g_pOptions->AddPage(parentid, title);
3375bool DeleteOptionsPage(wxScrolledWindow *page) {
3376 if (!g_pOptions)
return false;
3377 return g_pOptions->DeletePluginPage(page);
3381 wxString *accumulator) {
3382 if (!pos)
return false;
3385 AisError nerr = AIS_GENERIC_ERROR;
3386 if (g_pAIS) nerr = g_pAIS->DecodeSingleVDO(str, &gpd, accumulator);
3387 if (nerr == AIS_NoError) {
3388 pos->Lat = gpd.kLat;
3389 pos->Lon = gpd.kLon;
3390 pos->Cog = gpd.kCog;
3391 pos->Sog = gpd.kSog;
3392 pos->Hdt = gpd.kHdt;
3406int GetChartbarHeight(
void) {
3408 if (g_bShowChartBar) {
3410 if (cc && cc->GetPiano()) {
3411 val = cc->GetPiano()->GetHeight();
3417bool GetRoutepointGPX(
RoutePoint *pRoutePoint,
char *buffer,
3418 unsigned int buffer_length) {
3422 pgpx->AddGPXWaypoint(pRoutePoint);
3423 wxString gpxfilename = wxFileName::CreateTempFileName(wxT(
"gpx"));
3424 pgpx->SaveFile(gpxfilename);
3427 wxFFile gpxfile(gpxfilename);
3429 if (gpxfile.ReadAll(&s)) {
3430 if (s.Length() < buffer_length) {
3431 strncpy(buffer, (
const char *)s.mb_str(wxConvUTF8), buffer_length - 1);
3437 ::wxRemoveFile(gpxfilename);
3442bool GetActiveRoutepointGPX(
char *buffer,
unsigned int buffer_length) {
3443 if (g_pRouteMan->IsAnyRouteActive())
3444 return GetRoutepointGPX(g_pRouteMan->GetpActivePoint(), buffer,
3450void PositionBearingDistanceMercator_Plugin(
double lat,
double lon,
double brg,
3451 double dist,
double *dlat,
3453 PositionBearingDistanceMercator(lat, lon, brg, dist, dlat, dlon);
3456void DistanceBearingMercator_Plugin(
double lat0,
double lon0,
double lat1,
3457 double lon1,
double *brg,
double *dist) {
3458 DistanceBearingMercator(lat0, lon0, lat1, lon1, brg, dist);
3461double DistGreatCircle_Plugin(
double slat,
double slon,
double dlat,
3463 return DistGreatCircle(slat, slon, dlat, dlon);
3466void toTM_Plugin(
float lat,
float lon,
float lat0,
float lon0,
double *x,
3468 toTM(lat, lon, lat0, lon0, x, y);
3471void fromTM_Plugin(
double x,
double y,
double lat0,
double lon0,
double *lat,
3473 fromTM(x, y, lat0, lon0, lat, lon);
3476void toSM_Plugin(
double lat,
double lon,
double lat0,
double lon0,
double *x,
3478 toSM(lat, lon, lat0, lon0, x, y);
3481void fromSM_Plugin(
double x,
double y,
double lat0,
double lon0,
double *lat,
3483 fromSM(x, y, lat0, lon0, lat, lon);
3486void toSM_ECC_Plugin(
double lat,
double lon,
double lat0,
double lon0,
3487 double *x,
double *y) {
3488 toSM_ECC(lat, lon, lat0, lon0, x, y);
3491void fromSM_ECC_Plugin(
double x,
double y,
double lat0,
double lon0,
3492 double *lat,
double *lon) {
3493 fromSM_ECC(x, y, lat0, lon0, lat, lon);
3496double toUsrDistance_Plugin(
double nm_distance,
int unit) {
3497 return toUsrDistance(nm_distance,
unit);
3500double fromUsrDistance_Plugin(
double usr_distance,
int unit) {
3501 return fromUsrDistance(usr_distance,
unit);
3504double toUsrSpeed_Plugin(
double kts_speed,
int unit) {
3505 return toUsrSpeed(kts_speed,
unit);
3508double fromUsrSpeed_Plugin(
double usr_speed,
int unit) {
3509 return fromUsrSpeed(usr_speed,
unit);
3512double toUsrTemp_Plugin(
double cel_temp,
int unit) {
3513 return toUsrTemp(cel_temp,
unit);
3516double fromUsrTemp_Plugin(
double usr_temp,
int unit) {
3517 return fromUsrTemp(usr_temp,
unit);
3520wxString getUsrDistanceUnit_Plugin(
int unit) {
3521 return getUsrDistanceUnit(
unit);
3524wxString getUsrSpeedUnit_Plugin(
int unit) {
return getUsrSpeedUnit(
unit); }
3526wxString getUsrTempUnit_Plugin(
int unit) {
return getUsrTempUnit(
unit); }
3528bool PlugIn_GSHHS_CrossesLand(
double lat1,
double lon1,
double lat2,
3530 static bool loaded =
false;
3532 gshhsCrossesLandInit();
3536 return gshhsCrossesLand(lat1, lon1, lat2, lon2);
3539void PlugInPlaySound(wxString &sound_file) {
3540 PlugInPlaySoundEx(sound_file, -1);
3547PlugIn_Waypoint::PlugIn_Waypoint() { m_HyperlinkList = NULL; }
3549PlugIn_Waypoint::PlugIn_Waypoint(
double lat,
double lon,
3550 const wxString &icon_ident,
3551 const wxString &wp_name,
3552 const wxString &GUID) {
3553 wxDateTime now = wxDateTime::Now();
3554 m_CreateTime = now.ToUTC();
3555 m_HyperlinkList = NULL;
3559 m_IconName = icon_ident;
3560 m_MarkName = wp_name;
3564PlugIn_Waypoint::~PlugIn_Waypoint() {}
3567PlugIn_Route::PlugIn_Route(
void) { pWaypointList =
new Plugin_WaypointList; }
3569PlugIn_Route::~PlugIn_Route(
void) {
3570 pWaypointList->DeleteContents(
false);
3571 pWaypointList->Clear();
3573 delete pWaypointList;
3577PlugIn_Track::PlugIn_Track(
void) { pWaypointList =
new Plugin_WaypointList; }
3579PlugIn_Track::~PlugIn_Track(
void) {
3580 pWaypointList->DeleteContents(
false);
3581 pWaypointList->Clear();
3583 delete pWaypointList;
3586wxString GetNewGUID(
void) {
return GpxDocument::GetUUID(); }
3588bool AddCustomWaypointIcon(wxBitmap *pimage, wxString key,
3589 wxString description) {
3590 WayPointmanGui(*pWayPointMan).ProcessIcon(*pimage, key, description);
3596 if (src->m_HyperlinkList ==
nullptr)
return;
3598 if (src->m_HyperlinkList->GetCount() > 0) {
3599 wxPlugin_HyperlinkListNode *linknode = src->m_HyperlinkList->GetFirst();
3604 h->DescrText = link->DescrText;
3605 h->Link = link->Link;
3606 h->LType = link->Type;
3608 dst->m_HyperlinkList->Append(h);
3610 linknode = linknode->GetNext();
3620 bool b_unique =
true;
3621 wxRoutePointListNode *prpnode = pWayPointMan->GetWaypointList()->GetFirst();
3625 if (prp->m_GUID == pwaypoint->m_GUID) {
3629 prpnode = prpnode->GetNext();
3632 if (!b_unique)
return false;
3635 new RoutePoint(pwaypoint->m_lat, pwaypoint->m_lon, pwaypoint->m_IconName,
3636 pwaypoint->m_MarkName, pwaypoint->m_GUID);
3638 pWP->m_bIsolatedMark =
true;
3640 cloneHyperlinkList(pWP, pwaypoint);
3642 pWP->m_MarkDescription = pwaypoint->m_MarkDescription;
3644 if (pwaypoint->m_CreateTime.IsValid())
3645 pWP->SetCreateTime(pwaypoint->m_CreateTime);
3647 wxDateTime dtnow(wxDateTime::Now());
3648 pWP->SetCreateTime(dtnow);
3651 pWP->m_btemp = (b_permanent ==
false);
3653 pSelect->AddSelectableRoutePoint(pwaypoint->m_lat, pwaypoint->m_lon, pWP);
3654 if (b_permanent) pConfig->AddNewWayPoint(pWP, -1);
3656 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
3657 pRouteManagerDialog->UpdateWptListCtrl();
3662bool DeleteSingleWaypoint(wxString &GUID) {
3664 bool b_found =
false;
3665 RoutePoint *prp = pWayPointMan->FindRoutePointByGUID(GUID);
3667 if (prp) b_found =
true;
3670 pWayPointMan->DestroyWaypoint(prp);
3671 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
3672 pRouteManagerDialog->UpdateWptListCtrl();
3680 bool b_found =
false;
3681 RoutePoint *prp = pWayPointMan->FindRoutePointByGUID(pwaypoint->m_GUID);
3683 if (prp) b_found =
true;
3686 double lat_save = prp->m_lat;
3687 double lon_save = prp->m_lon;
3689 prp->m_lat = pwaypoint->m_lat;
3690 prp->m_lon = pwaypoint->m_lon;
3691 prp->SetIconName(pwaypoint->m_IconName);
3692 prp->SetName(pwaypoint->m_MarkName);
3693 prp->m_MarkDescription = pwaypoint->m_MarkDescription;
3694 prp->SetVisible(pwaypoint->m_IsVisible);
3695 if (pwaypoint->m_CreateTime.IsValid())
3696 prp->SetCreateTime(pwaypoint->m_CreateTime);
3700 if (pwaypoint->m_HyperlinkList) {
3701 prp->m_HyperlinkList->Clear();
3702 if (pwaypoint->m_HyperlinkList->GetCount() > 0) {
3703 wxPlugin_HyperlinkListNode *linknode =
3704 pwaypoint->m_HyperlinkList->GetFirst();
3709 h->DescrText = link->DescrText;
3710 h->Link = link->Link;
3711 h->LType = link->Type;
3713 prp->m_HyperlinkList->Append(h);
3715 linknode = linknode->GetNext();
3720 if (prp) prp->ReLoadIcon();
3722 auto canvas = gFrame->GetPrimaryCanvas();
3723 SelectCtx ctx(canvas->m_bShowNavobjects, canvas->GetCanvasTrueScale());
3724 SelectItem *pFind = pSelect->FindSelection(ctx, lat_save, lon_save,
3725 SELTYPE_ROUTEPOINT);
3727 pFind->m_slat = pwaypoint->m_lat;
3728 pFind->m_slon = pwaypoint->m_lon;
3731 if (!prp->m_btemp) pConfig->UpdateWayPoint(prp);
3733 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
3734 pRouteManagerDialog->UpdateWptListCtrl();
3743 dst->m_lat = src->m_lat;
3744 dst->m_lon = src->m_lon;
3745 dst->m_IconName = src->GetIconName();
3746 dst->m_MarkName = src->GetName();
3747 dst->m_MarkDescription = src->m_MarkDescription;
3748 dst->m_IsVisible = src->IsVisible();
3749 dst->m_CreateTime = src->GetCreateTime();
3750 dst->m_GUID = src->m_GUID;
3753 if (src->m_HyperlinkList ==
nullptr)
return;
3755 delete dst->m_HyperlinkList;
3756 dst->m_HyperlinkList =
nullptr;
3758 if (src->m_HyperlinkList->GetCount() > 0) {
3759 dst->m_HyperlinkList =
new Plugin_HyperlinkList;
3761 wxHyperlinkListNode *linknode = src->m_HyperlinkList->GetFirst();
3766 h->DescrText = link->DescrText;
3767 h->Link = link->Link;
3768 h->Type = link->LType;
3770 dst->m_HyperlinkList->Append(h);
3772 linknode = linknode->GetNext();
3779 RoutePoint *prp = pWayPointMan->FindRoutePointByGUID(GUID);
3781 if (!prp)
return false;
3783 PlugInFromRoutePoint(pwaypoint, prp);
3788wxArrayString GetWaypointGUIDArray(
void) {
3789 wxArrayString result;
3790 RoutePointList *list = pWayPointMan->GetWaypointList();
3792 wxRoutePointListNode *prpnode = list->GetFirst();
3795 result.Add(prp->m_GUID);
3797 prpnode = prpnode->GetNext();
3803wxArrayString GetRouteGUIDArray(
void) {
3804 wxArrayString result;
3805 RouteList *list = pRouteList;
3807 wxRouteListNode *prpnode = list->GetFirst();
3809 Route *proute = prpnode->GetData();
3810 result.Add(proute->m_GUID);
3812 prpnode = prpnode->GetNext();
3818wxArrayString GetTrackGUIDArray(
void) {
3819 wxArrayString result;
3820 for (
Track *ptrack : g_TrackList) {
3821 result.Add(ptrack->m_GUID);
3827wxArrayString GetIconNameArray(
void) {
3828 wxArrayString result;
3830 for (
int i = 0; i < pWayPointMan->GetNumIcons(); i++) {
3831 wxString *ps = pWayPointMan->GetIconKey(i);
3837bool AddPlugInRoute(
PlugIn_Route *proute,
bool b_permanent) {
3843 wxDateTime plannedDeparture;
3845 wxPlugin_WaypointListNode *pwpnode = proute->pWaypointList->GetFirst();
3847 pwp = pwpnode->GetData();
3850 pwp->m_MarkName, pwp->m_GUID);
3853 cloneHyperlinkList(pWP, pwp);
3854 pWP->m_MarkDescription = pwp->m_MarkDescription;
3855 pWP->m_bShowName =
false;
3856 pWP->SetCreateTime(pwp->m_CreateTime);
3858 route->AddPoint(pWP);
3860 pSelect->AddSelectableRoutePoint(pWP->m_lat, pWP->m_lon, pWP);
3863 pSelect->AddSelectableRouteSegment(pWP_src->m_lat, pWP_src->m_lon,
3864 pWP->m_lat, pWP->m_lon, pWP_src, pWP,
3867 plannedDeparture = pwp->m_CreateTime;
3871 pwpnode = pwpnode->GetNext();
3874 route->m_PlannedDeparture = plannedDeparture;
3876 route->m_RouteNameString = proute->m_NameString;
3877 route->m_RouteStartString = proute->m_StartString;
3878 route->m_RouteEndString = proute->m_EndString;
3879 if (!proute->m_GUID.IsEmpty()) {
3880 route->m_GUID = proute->m_GUID;
3882 route->m_btemp = (b_permanent ==
false);
3884 pRouteList->Append(route);
3886 if (b_permanent) pConfig->AddNewRoute(route);
3888 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
3889 pRouteManagerDialog->UpdateRouteListCtrl();
3894bool DeletePlugInRoute(wxString &GUID) {
3895 bool b_found =
false;
3898 Route *pRoute = g_pRouteMan->FindRouteByGUID(GUID);
3900 g_pRouteMan->
DeleteRoute(pRoute, NavObjectChanges::getInstance());
3907 bool b_found =
false;
3910 Route *pRoute = g_pRouteMan->FindRouteByGUID(proute->m_GUID);
3911 if (pRoute) b_found =
true;
3914 bool b_permanent = (pRoute->m_btemp ==
false);
3915 g_pRouteMan->
DeleteRoute(pRoute, NavObjectChanges::getInstance());
3917 b_found = AddPlugInRoute(proute, b_permanent);
3923bool AddPlugInTrack(
PlugIn_Track *ptrack,
bool b_permanent) {
3930 wxPlugin_WaypointListNode *pwpnode = ptrack->pWaypointList->GetFirst();
3932 pwp = pwpnode->GetData();
3935 pWP->SetCreateTime(pwp->m_CreateTime);
3937 track->AddPoint(pWP);
3940 pSelect->AddSelectableTrackSegment(pWP_src->m_lat, pWP_src->m_lon,
3941 pWP->m_lat, pWP->m_lon, pWP_src, pWP,
3946 pwpnode = pwpnode->GetNext();
3949 track->SetName(ptrack->m_NameString);
3950 track->m_TrackStartString = ptrack->m_StartString;
3951 track->m_TrackEndString = ptrack->m_EndString;
3952 track->m_GUID = ptrack->m_GUID;
3953 track->m_btemp = (b_permanent ==
false);
3955 g_TrackList.push_back(track);
3957 if (b_permanent) pConfig->AddNewTrack(track);
3959 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
3960 pRouteManagerDialog->UpdateTrkListCtrl();
3965bool DeletePlugInTrack(wxString &GUID) {
3966 bool b_found =
false;
3969 Track *pTrack = g_pRouteMan->FindTrackByGUID(GUID);
3975 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
3976 pRouteManagerDialog->UpdateTrkListCtrl();
3982 bool b_found =
false;
3985 Track *pTrack = g_pRouteMan->FindTrackByGUID(ptrack->m_GUID);
3986 if (pTrack) b_found =
true;
3989 bool b_permanent = (pTrack->m_btemp ==
false);
3992 b_found = AddPlugInTrack(ptrack, b_permanent);
4001 ocpn_vp.m_projection_type = vp->m_projection_type;
4003 return glChartCanvas::HasNormalizedViewPort(ocpn_vp);
4009void PlugInMultMatrixViewport(
PlugIn_ViewPort *vp,
float lat,
float lon) {
4012 ocpn_vp.clat = vp->clat;
4013 ocpn_vp.clon = vp->clon;
4014 ocpn_vp.m_projection_type = vp->m_projection_type;
4015 ocpn_vp.view_scale_ppm = vp->view_scale_ppm;
4016 ocpn_vp.skew = vp->skew;
4017 ocpn_vp.rotation = vp->rotation;
4018 ocpn_vp.pix_width = vp->pix_width;
4019 ocpn_vp.pix_height = vp->pix_height;
4026void PlugInNormalizeViewport(
PlugIn_ViewPort *vp,
float lat,
float lon) {
4029 glChartCanvas::NormalizedViewPort(ocpn_vp, lat, lon);
4031 vp->clat = ocpn_vp.clat;
4032 vp->clon = ocpn_vp.clon;
4033 vp->view_scale_ppm = ocpn_vp.view_scale_ppm;
4034 vp->rotation = ocpn_vp.rotation;
4035 vp->skew = ocpn_vp.skew;
4048 pret->MMSI = ptarget->MMSI;
4049 pret->Class = ptarget->Class;
4050 pret->NavStatus = ptarget->NavStatus;
4051 pret->SOG = ptarget->SOG;
4052 pret->COG = ptarget->COG;
4053 pret->HDG = ptarget->HDG;
4054 pret->Lon = ptarget->Lon;
4055 pret->Lat = ptarget->Lat;
4056 pret->ROTAIS = ptarget->ROTAIS;
4057 pret->ShipType = ptarget->ShipType;
4058 pret->IMO = ptarget->IMO;
4060 pret->Range_NM = ptarget->Range_NM;
4061 pret->Brg = ptarget->Brg;
4064 pret->bCPA_Valid = ptarget->bCPA_Valid;
4065 pret->TCPA = ptarget->TCPA;
4066 pret->CPA = ptarget->CPA;
4068 pret->alarm_state = (plugin_ais_alarm_type)ptarget->n_alert_state;
4070 memcpy(pret->CallSign, ptarget->CallSign, CALL_SIGN_LEN);
4071 memcpy(pret->ShipName, ptarget->ShipName, SHIP_NAME_LEN);
4080#define DISABLED_SETTINGS_MSG \
4081 _("These settings might destabilize OpenCPN and are by default disabled." \
4082 " To despite the dangers enable them manually add a CatalogExpert=1" \
4083 " line in the [PlugIns] section in the configuration file.")
4088CatalogMgrPanel::CatalogMgrPanel(wxWindow *parent)
4089 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
4091 wxBoxSizer *topSizer =
new wxBoxSizer(wxVERTICAL);
4094 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
4096 wxStaticBox *itemStaticBoxSizer4Static =
4097 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
4098 wxStaticBoxSizer *itemStaticBoxSizer4 =
4099 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
4100 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
4104 m_catalogText =
new wxStaticText(
this, wxID_STATIC, _T(
""));
4105 itemStaticBoxSizer4->Add(m_catalogText,
4106 wxSizerFlags().Border().Proportion(1));
4107 m_catalogText->SetLabel(GetCatalogText(
false));
4110 wxBoxSizer *rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
4111 itemStaticBoxSizer4->Add(rowSizer2,
4112 wxSizerFlags().Expand().Border().Proportion(1));
4114 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
4115 wxDefaultPosition, wxDefaultSize, 0);
4116 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
4117 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
4118 &CatalogMgrPanel::OnUpdateButton,
this);
4119 rowSizer2->AddSpacer(4 * GetCharWidth());
4120 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
4121 wxDefaultPosition, wxDefaultSize, 0);
4122 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
4123 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
4124 &CatalogMgrPanel::OnTarballButton,
this);
4126 rowSizer2->AddSpacer(4 * GetCharWidth());
4127 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
4128 wxDefaultPosition, wxDefaultSize, 0);
4130 if (expert.Get(
false)) {
4131 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
4132 &CatalogMgrPanel::OnPluginSettingsButton,
this);
4134 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent &) {
4135 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
4138 rowSizer2->AddSpacer(4 * GetCharWidth());
4139 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
4141 SetUpdateButtonLabel();
4144 wxBoxSizer *rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
4145 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
4147 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
4151 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
4152 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
4153 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent &) { SetUpdateButtonLabel(); });
4156 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
4158 if (!expert.Get(
false)) {
4160 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
4161 wxDefaultPosition, wxDefaultSize, 0);
4162 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
4163 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
4164 &CatalogMgrPanel::OnUpdateButton,
this);
4165 SetUpdateButtonLabel();
4166 m_tarballButton = NULL;
4167 m_adv_button = NULL;
4170 m_catalogText =
new wxStaticText(
this, wxID_STATIC, _T(
""));
4171 itemStaticBoxSizer4->Add(m_catalogText,
4172 wxSizerFlags().Border().Proportion(1));
4173 m_catalogText->SetLabel(GetCatalogText(
false));
4176 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog:master"),
4177 wxDefaultPosition, wxDefaultSize, 0);
4178 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
4179 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
4180 &CatalogMgrPanel::OnUpdateButton,
this);
4181 SetUpdateButtonLabel();
4184 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
4185 wxDefaultPosition, wxDefaultSize, 0);
4186 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT);
4187 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
4188 &CatalogMgrPanel::OnPluginSettingsButton,
this);
4191 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
4192 wxDefaultPosition, wxDefaultSize, 0);
4193 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT,
4194 2 * GetCharWidth());
4195 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
4196 &CatalogMgrPanel::OnTarballButton,
this);
4202CatalogMgrPanel::~CatalogMgrPanel() {
4203 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
4204 &CatalogMgrPanel::OnUpdateButton,
this);
4205 if (m_tarballButton)
4206 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
4207 &CatalogMgrPanel::OnTarballButton,
this);
4210static const char *
const DOWNLOAD_REPO_PROTO =
4211 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
4214void CatalogMgrPanel::OnUpdateButton(wxCommandEvent &event) {
4216 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
4217 std::string url(g_catalog_custom_url);
4218 if (catalog !=
"custom") {
4219 url = std::string(DOWNLOAD_REPO_PROTO);
4220 ocpn::replace(url,
"@branch@", catalog);
4223 std::string filePath =
4224 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
4226 auto catalogHdlr = CatalogHandler::getInstance();
4228 g_Platform->ShowBusySpinner();
4229 auto status = catalogHdlr->DownloadCatalog(filePath, url);
4230 g_Platform->HideBusySpinner();
4232 std::string message;
4233 if (status != CatalogHandler::ServerStatus::OK) {
4234 message = _(
"Cannot download data from url");
4235 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
4236 wxICON_ERROR | wxOK);
4241#ifdef __OCPN__ANDROID__
4242 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
4243 g_Platform->GetPrivateDataDir() +
4244 wxFileName::GetPathSeparator() +
4245 _T(
"ocpn-plugins.xml"))) {
4246 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
4247 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
4252 if (!wxCopyFile(wxString(filePath.c_str()),
4253 g_Platform->GetPrivateDataDir() +
4254 wxFileName::GetPathSeparator() +
4255 _T(
"ocpn-plugins.xml"))) {
4256 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
4257 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
4263 if (catalog ==
"master") {
4265 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
4266 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
4272 pConfig->SetPath(_T(
"/PlugIns/"));
4273 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
4279 auto pluginHandler = PluginHandler::getInstance();
4280 pluginHandler->setMetadata(
"");
4283 LoadAllPlugIns(
false);
4286#ifndef __OCPN__ANDROID__
4287 m_catalogText->SetLabel(GetCatalogText(
true));
4289 if (m_PluginListPanel)
4291 OCPNMessageBox(
this, _(
"Catalog update successful"),
4292 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
4295static bool parsePluginNode(pugi::xml_node &pluginRoot,
4297 for (pugi::xml_node element = pluginRoot.first_child(); element;
4298 element = element.next_sibling()) {
4299 if (!strcmp(element.name(),
"name")) {
4300 plugin.name = element.first_child().value();
4301 }
else if (!strcmp(element.name(),
"version")) {
4302 plugin.version = element.first_child().value();
4303 }
else if (!strcmp(element.name(),
"release")) {
4304 plugin.release = element.first_child().value();
4305 }
else if (!strcmp(element.name(),
"summary")) {
4306 plugin.summary = element.first_child().value();
4307 }
else if (!strcmp(element.name(),
"api-version")) {
4308 plugin.api_version = element.first_child().value();
4309 }
else if (!strcmp(element.name(),
"open-source")) {
4310 plugin.openSource = element.first_child().value();
4311 }
else if (!strcmp(element.name(),
"author")) {
4312 plugin.author = element.first_child().value();
4313 }
else if (!strcmp(element.name(),
"source")) {
4314 plugin.source = element.first_child().value();
4315 }
else if (!strcmp(element.name(),
"info-url")) {
4316 plugin.info_url = element.first_child().value();
4317 }
else if (!strcmp(element.name(),
"description")) {
4318 plugin.description = element.first_child().value();
4319 }
else if (!strcmp(element.name(),
"target")) {
4320 plugin.target = element.first_child().value();
4321 }
else if (!strcmp(element.name(),
"target-version")) {
4322 plugin.target_version = element.first_child().value();
4323 }
else if (!strcmp(element.name(),
"target-arch")) {
4324 plugin.target_arch = element.first_child().value();
4325 }
else if (!strcmp(element.name(),
"tarball-url")) {
4326 plugin.tarball_url = element.first_child().value();
4327 }
else if (!strcmp(element.name(),
"build-gtk")) {
4328 plugin.build_gtk = element.first_child().value();
4335static void populatePluginNode(pugi::xml_node &pluginNode,
4337 pugi::xml_node child;
4339 child = pluginNode.append_child(
"name");
4340 child.append_child(pugi::node_pcdata).set_value(workingMetadata.name.c_str());
4342 child = pluginNode.append_child(
"version");
4343 child.append_child(pugi::node_pcdata)
4344 .set_value(workingMetadata.version.c_str());
4346 child = pluginNode.append_child(
"release");
4347 child.append_child(pugi::node_pcdata)
4348 .set_value(workingMetadata.release.c_str());
4350 child = pluginNode.append_child(
"summary");
4351 child.append_child(pugi::node_pcdata)
4352 .set_value(workingMetadata.summary.c_str());
4354 child = pluginNode.append_child(
"api-version");
4355 child.append_child(pugi::node_pcdata)
4356 .set_value(workingMetadata.api_version.c_str());
4358 child = pluginNode.append_child(
"open-source");
4360 sprintf(b,
"%1d", workingMetadata.openSource);
4361 child.append_child(pugi::node_pcdata).set_value(b);
4363 child = pluginNode.append_child(
"author");
4364 child.append_child(pugi::node_pcdata)
4365 .set_value(workingMetadata.author.c_str());
4367 child = pluginNode.append_child(
"source");
4368 child.append_child(pugi::node_pcdata)
4369 .set_value(workingMetadata.source.c_str());
4371 child = pluginNode.append_child(
"info-url");
4372 child.append_child(pugi::node_pcdata)
4373 .set_value(workingMetadata.info_url.c_str());
4375 child = pluginNode.append_child(
"description");
4376 child.append_child(pugi::node_pcdata)
4377 .set_value(workingMetadata.description.c_str());
4379 child = pluginNode.append_child(
"target");
4380 child.append_child(pugi::node_pcdata)
4381 .set_value(workingMetadata.target.c_str());
4383 child = pluginNode.append_child(
"target-version");
4384 child.append_child(pugi::node_pcdata)
4385 .set_value(workingMetadata.target_version.c_str());
4387 child = pluginNode.append_child(
"target-arch");
4388 child.append_child(pugi::node_pcdata)
4389 .set_value(workingMetadata.target_arch.c_str());
4391 child = pluginNode.append_child(
"tarball-url");
4392 child.append_child(pugi::node_pcdata)
4393 .set_value(workingMetadata.tarball_url.c_str());
4396void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent &event) {
4399#ifdef __OCPN__ANDROID__
4400 androidDisableRotation();
4403 dialog->ShowModal();
4405#ifdef __OCPN__ANDROID__
4406 androidEnableRotation();
4410void CatalogMgrPanel::OnTarballButton(wxCommandEvent &event) {
4412 wxString tarballPath;
4413 int response = g_Platform->DoFileSelectorDialog(
4414 this, &tarballPath, _(
"Select tarball file"), GetImportInitDir(),
4415 wxEmptyString, wxT(
"tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*"));
4417 if (response == wxID_OK) {
4419 wxFileName f = tarballPath;
4420 wxString used_path = f.GetPath(wxPATH_GET_VOLUME | wxPATH_NO_SEPARATOR);
4421 if (used_path != wxEmptyString) {
4422 pConfig->SetPath(_T(
"/PlugIns/"));
4423 pConfig->Write(
"LatestImportDir", used_path);
4430 wxString tmpMetadata = wxFileName::CreateTempFileName(
"meta");
4432 struct archive *src = archive_read_new();
4433 archive_read_support_filter_gzip(src);
4434 archive_read_support_format_tar(src);
4435 int r = archive_read_open_filename(src, tarballPath.ToStdString().c_str(),
4437 if (r != ARCHIVE_OK) {
4438 std::ostringstream os;
4440 wxLogWarning(os.str().c_str());
4445 struct archive *dest = archive_write_disk_new();
4446 archive_write_disk_set_options(dest, ARCHIVE_EXTRACT_TIME);
4448 bool bFoundMetadata =
false;
4449 struct archive_entry *entry = 0;
4451 int r = archive_read_next_header(src, &entry);
4452 if (r == ARCHIVE_EOF) {
4455 if (r < ARCHIVE_OK) {
4460 std::string path = archive_entry_pathname(entry);
4461 if (std::string::npos != path.find(
"metadata.xml")) {
4462 bFoundMetadata =
true;
4463 archive_entry_set_pathname(entry, tmpMetadata.mb_str());
4465 if (r >= ARCHIVE_OK && archive_entry_size(entry) > 0) {
4470 r = archive_write_header(dest, entry);
4471 if (r < ARCHIVE_OK) {
4476 r = archive_read_data_block(src, &buff, &size, &offset);
4477 if (r == ARCHIVE_EOF) {
4480 if (r < ARCHIVE_OK) {
4483 r = archive_write_data_block(dest, buff, size, offset);
4484 if (r < ARCHIVE_OK) {
4485 wxLogWarning(
"Error copying install data: %s",
4486 archive_error_string(dest));
4491 if (r < ARCHIVE_OK) {
4495 r = archive_write_finish_entry(dest);
4496 if (r < ARCHIVE_OK) {
4504 archive_read_free(src);
4505 archive_write_free(dest);
4508 if (r < ARCHIVE_OK) {
4509 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
4510 _(
"OpenCPN Plugin Import Error"));
4515 if (!bFoundMetadata) {
4518 _(
"Error, import plugin tarball does not contain required metadata."),
4519 _(
"OpenCPN Plugin Import Error"));
4526 pugi::xml_document doc;
4527 bool ret = doc.load_file(tmpMetadata.mb_str());
4529 pugi::xml_node pluginRoot = doc.first_child();
4531 if (!parsePluginNode(pluginRoot, importPlugin)) {
4532 OCPNMessageBox(
this, _(
"Error processing import plugin metadata."),
4533 _(
"OpenCPN Plugin Import Error"));
4540 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
4541 _(
"OpenCPN Plugin Import Error"));
4546 std::vector<PluginMetadata> pluginArray;
4548 pugi::xml_document catalog;
4549 wxString currentCatalog = g_Platform->GetPrivateDataDir() +
4550 wxFileName::GetPathSeparator() +
4551 _T(
"ocpn-plugins.xml");
4552 bool badCatalog =
false;
4553 if (!wxFileExists(currentCatalog)) {
4556 ret = catalog.load_file(currentCatalog.mb_str());
4566 if (wxFileExists(currentCatalog)) wxRemoveFile(currentCatalog);
4568 wxTextFile stubCatalog(currentCatalog);
4569 stubCatalog.Create();
4570 stubCatalog.AddLine(_T(
"<?xml version=\"1.0\" ?>"));
4571 stubCatalog.AddLine(_T(
"<plugins>"));
4572 stubCatalog.AddLine(_T(
"<version>0.0.0</version>"));
4573 stubCatalog.AddLine(_T(
"<date>2021-06-01 00:01</date>"));
4574 stubCatalog.AddLine(_T(
"</plugins>"));
4575 stubCatalog.Write();
4576 stubCatalog.Close();
4578 catalog.load_file(currentCatalog.mb_str());
4581 pugi::xml_node catalogRoot = catalog.first_child();
4582 for (pugi::xml_node element = catalogRoot.first_child(); element;
4583 element = element.next_sibling()) {
4584 if (!strcmp(element.name(),
"plugin")) {
4586 parsePluginNode(element, catalogPlugin);
4587 pluginArray.push_back(catalogPlugin);
4597 bool bmerge =
false;
4598 for (
size_t i = 0; i < pluginArray.size(); i++) {
4600 if (importPlugin.name == candidate.name) {
4601 if (importPlugin.target == candidate.target) {
4602 if (importPlugin.target_version == candidate.target_version) {
4604 pluginArray[i].version = importPlugin.version;
4605 pluginArray[i].release = importPlugin.release;
4606 pluginArray[i].summary = importPlugin.summary;
4607 pluginArray[i].description = importPlugin.description;
4608 pluginArray[i].tarball_url = importPlugin.tarball_url;
4616 if (!bmerge) pluginArray.push_back(importPlugin);
4620 pugi::xml_document newCatalog;
4621 pugi::xml_node pluginsNode = newCatalog.append_child(
"plugins");
4623 pugi::xml_node childT = pluginsNode.append_child(
"version");
4624 childT.append_child(pugi::node_pcdata).set_value(
"0.0.0");
4625 childT = pluginsNode.append_child(
"date");
4626 wxDateTime now = wxDateTime::GetTimeNow();
4627 wxString timeFormat = now.FormatISOCombined(
' ');
4628 childT.append_child(pugi::node_pcdata).set_value(timeFormat.mb_str());
4630 for (
size_t i = 0; i < pluginArray.size(); i++) {
4633 pugi::xml_node pluginNode = pluginsNode.append_child(
"plugin");
4634 pugi::xml_attribute version = pluginNode.append_attribute(
"version");
4635 version.set_value(
"1");
4637 populatePluginNode(pluginNode, workingMetadata);
4640 wxString catalogName = g_Platform->GetPrivateDataDir() +
4641 wxFileName::GetPathSeparator() +
4642 _T(
"ocpn-plugins.xml");
4643 newCatalog.save_file(catalogName.mb_str(),
" ");
4647 wxFileName fn(tarballPath);
4649 fn.GetFullName().ToStdString().c_str())) {
4650 wxLogMessage(
"Copied %s to local cache",
4651 tarballPath.ToStdString().c_str());
4659 auto pluginHandler = PluginHandler::getInstance();
4660 pluginHandler->setMetadata(
"");
4663 LoadAllPlugIns(
false);
4666 if (m_PluginListPanel) {
4667 auto loader = PluginLoader::getInstance();
4672 wxString msg = _(
"Plugin imported successfully");
4674 msg += _(
"Active catalog updated.");
4676 msg += _(
"Plugin may be installed or updated now.");
4677 OCPNMessageBox(
this, msg, _(
"OpenCPN Plugin Import Successful"));
4681wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
4683 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
4684 catalog += _T(
": ");
4687 pConfig->SetPath(_T(
"/PlugIns/"));
4688 wxString latestCatalog =
4689 pConfig->Read(_T(
"LatestCatalogDownloaded"), _T(
"default"));
4690 catalog += latestCatalog;
4694 auto pluginHandler = PluginHandler::getInstance();
4695 std::string date = pluginHandler->GetCatalogData()->date;
4697 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
4698 if (!updated) catalog += _T(
" : ") + _(
"Please Update Plugin Catalog.");
4703void CatalogMgrPanel::SetUpdateButtonLabel() {
4704 wxString label = _(
"Update Plugin Catalog");
4706 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
4707 m_updateButton->SetLabel(label);
4711wxString CatalogMgrPanel::GetImportInitDir() {
4713 pConfig->SetPath(_T(
"/PlugIns/"));
4714 wxString lastImportDir;
4715 lastImportDir = pConfig->Read(_T(
"LatestImportDir"),
4716 g_Platform->GetWritableDocumentsDir());
4717 if (wxDirExists(lastImportDir)) {
4718 return lastImportDir;
4720 return (g_Platform->GetWritableDocumentsDir());
4729 const wxPoint &pos, const wxSize &size,
4730 ArrayOfPlugIns *pPluginArray)
4731 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
4732 m_PluginSelected(0) {
4733 SetSizer(
new wxBoxSizer(wxVERTICAL));
4734 ReloadPluginPanels();
4738void PluginListPanel::SelectByName(wxString &name) {
4739 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
4740 auto pluginPanel =
dynamic_cast<PluginPanel *
>(it->GetData());
4742 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
4743 pluginPanel->SetSelected(
true);
4744 pluginPanel->Layout();
4745 SelectPlugin(pluginPanel);
4753 auto plugins = PluginLoader::getInstance()->GetPlugInArray();
4754 m_pPluginArray = plugins;
4755 m_PluginItems.Clear();
4757 wxWindowList kids = GetChildren();
4758 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
4759 wxWindowListNode *node = kids.Item(i);
4760 wxWindow *win = node->GetData();
4762 if (pp) win->Destroy();
4765 GetSizer()->Clear();
4768 m_PluginSelected = 0;
4769 for (
size_t i = m_pPluginArray->GetCount(); i > 0; i -= 1) {
4782 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
4783 pPluginPanel->SetSelected(
false);
4784 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
4785 m_PluginItems.Add(pPluginPanel);
4787 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
4788 GetSizer()->AddSpacer(m_pluginSpacer);
4801int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
4802 wxBoxSizer *sizer) {
4804 for (
size_t i = 0; i < plugins.GetCount(); i++) {
4805 auto panel = plugins.Item(i);
4806 bool was_selected = panel->GetSelected();
4807 panel->SetSelected(
false);
4809 wxSize unselected = panel->GetSize();
4811 panel->SetSelected(
true);
4813 wxSize selected = panel->GetSize();
4815 int dy = selected.GetHeight() - unselected.GetHeight();
4816 max_dy = wxMax(max_dy, dy);
4817 panel->SetSelected(was_selected);
4822void PluginListPanel::UpdatePluginsOrder() {
4823 m_pPluginArray->Clear();
4824 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
4825 m_pPluginArray->Insert(m_PluginItems[i]->GetPluginPtr(), 0);
4829PluginListPanel::~PluginListPanel() {}
4831void PluginListPanel::UpdateSelections() {
4832 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
4835 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
4840void PluginListPanel::SelectPlugin(
PluginPanel *pi) {
4842 GetViewStart(&xs, &ys);
4845 if (m_PluginSelected) {
4846 m_PluginSelected->SetSelected(
false);
4847 m_PluginSelected->Layout();
4850 if (pi == NULL) m_PluginSelected->SetSelected(
false);
4852 m_PluginSelected = pi;
4854 GetSizer()->Layout();
4856 wxSize size = GetBestVirtualSize();
4857 SetVirtualSize(size);
4862 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
4864 int yd = pPluginPanel->GetSize().y;
4866 htop += m_pluginSpacer;
4867 if (pPluginPanel == pi) {
4868 int piBottom = htop - (ys * g_options->GetScrollRate());
4869 if (piBottom > GetClientSize().y) {
4870 ys += (piBottom - GetClientSize().y) / g_options->GetScrollRate();
4880 int pos = m_PluginItems.Index(pi);
4883 m_PluginItems.RemoveAt(pos);
4886 m_PluginItems.Insert(pi, pos - 1);
4887 wxStaticLine *itemStaticLine =
new wxStaticLine(
4888 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
4893 m_PluginSelected = pi;
4895 GetSizer()->Layout();
4901 int pos = m_PluginItems.Index(pi);
4902 if (pos == (
int)m_PluginItems.Count() -
4905 m_PluginItems.RemoveAt(pos);
4908 m_PluginItems.Insert(pi, pos + 1);
4909 wxStaticLine *itemStaticLine =
new wxStaticLine(
4910 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
4915 m_PluginSelected = pi;
4917 GetSizer()->Layout();
4922static bool canUninstall(std::string name) {
4923 PluginHandler *pluginHandler = PluginHandler::getInstance();
4927 if (plugin.name == name) {
4928 if (safe_mode::get_mode())
4931 return !plugin.readonly;
4938EVT_PAINT(PluginPanel::OnPaint)
4943 : wxPanel(parent,
id, pos, size, wxBORDER_NONE) {
4946 wxASSERT(m_PluginListPanel != 0);
4948 m_pPlugin = p_plugin;
4949 m_bSelected =
false;
4950 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
4951 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
4953 wxBoxSizer *topSizer =
new wxBoxSizer(wxVERTICAL);
4956 wxBoxSizer *itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
4957 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
4958 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
4959 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
4961 double iconSize = GetCharWidth() * 4;
4962 double dpi_mult = g_Platform->GetDisplayDIPMult(
this);
4963 int icon_scale = iconSize * dpi_mult;
4965 wxImage plugin_icon;
4967 if (m_pPlugin->m_bitmap && m_pPlugin->m_bitmap->IsOk()) {
4968 plugin_icon = m_pPlugin->m_bitmap->ConvertToImage();
4971 if (plugin_icon.IsOk()) {
4972 int nowSize = plugin_icon.GetWidth();
4973 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
4974 bitmap = wxBitmap(plugin_icon);
4975 }
else if (m_pPlugin->m_pluginStatus ==
4976 PluginStatus::ManagedInstallAvailable) {
4977 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
4978 path.AppendDir(
"uidata");
4979 path.AppendDir(
"traditional");
4980 bitmap = LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
4982 bitmap = wxBitmap(style->GetIcon(_T(
"default_pi"), icon_scale, icon_scale));
4984 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
4986 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
4987 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
4989 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
4992 wxBoxSizer *itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
4993 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
4996 int nChars = g_options->GetSize().x / GetCharWidth();
4997 bool bCompact =
false;
5003 wxString nameString = m_pPlugin->m_common_name;
5004 int maxWidth = g_Platform->getDisplaySize().x * 3 / 10;
5007 dc.GetTextExtent(m_pPlugin->m_common_name, &nameWidth, NULL);
5008 if (nameWidth > maxWidth) {
5009 nameString = wxControl::Ellipsize(m_pPlugin->m_common_name, dc,
5010 wxELLIPSIZE_END, maxWidth);
5012 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
5013 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5014 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
5015 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
5017 wxFlexGridSizer *sl1 =
new wxFlexGridSizer(2, 0, 0);
5018 sl1->AddGrowableCol(1);
5019 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
5021 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
5022 sl1->Add(m_pVersion, 0, wxALL, 5);
5023 if (m_pPlugin->m_pluginStatus == PluginStatus::ManagedInstallAvailable) {
5026 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5027 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
5029 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
5030 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
5031 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
5034 wxString descriptionString = m_pPlugin->m_short_description;
5035 int maxDescriptionWidth = g_Platform->getDisplaySize().x - (iconSize * 4);
5036 int descriptionWidth;
5037 dc.GetTextExtent(m_pPlugin->m_short_description, &descriptionWidth, NULL);
5038 if (descriptionWidth > maxDescriptionWidth)
5040 wxControl::Ellipsize(m_pPlugin->m_short_description, dc,
5041 wxELLIPSIZE_END, maxDescriptionWidth);
5046 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
5047 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
5048 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
5049 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5050 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
5053 wxFlexGridSizer *itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
5054 itemBoxSizer03->AddGrowableCol(2);
5055 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
5057 wxString nameString = m_pPlugin->m_common_name;
5058 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
5059 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5060 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
5064 wxFont font = GetFont();
5065 font.SetWeight(wxFONTWEIGHT_BOLD);
5066 m_pName->SetFont(font);
5069 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
5071 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
5072 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
5073 if (m_pPlugin->m_pluginStatus == PluginStatus::ManagedInstallAvailable) {
5076 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5077 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
5079 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
5080 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
5081 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
5083 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
5085 m_pDescription =
new wxStaticText(
5086 this, wxID_ANY, m_pPlugin->m_short_description, wxDefaultPosition,
5088 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
5089 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5090 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
5094 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
5096 itemBoxSizer02->Add(m_info_btn, 0);
5098 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
5099 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
5100 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
5101 wxDefaultPosition, wxDefaultSize, 0);
5102 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
5104 m_pButtons->AddSpacer(3 * GetCharWidth());
5107 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
5108 wxDefaultPosition, wxDefaultSize, 0);
5109 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
5111 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
5112 wxDefaultPosition, wxDefaultSize, 0);
5113 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
5115 m_pButtons =
new wxBoxSizer(wxVERTICAL);
5116 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
5118 wxBoxSizer *tline =
new wxBoxSizer(wxHORIZONTAL);
5119 m_pButtons->Add(tline, 0, wxALL, 2);
5121 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
5122 wxDefaultPosition, wxDefaultSize, 0);
5123 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
5125 tline->AddSpacer(3 * GetCharWidth());
5127 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
5129 tline->Add(m_info_btn, 0);
5132 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
5133 wxDefaultPosition, wxDefaultSize);
5134 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
5136 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
5137 wxDefaultPosition, wxDefaultSize, 0);
5138 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
5141 wxBitmap statusBitmap;
5142 auto stat = p_plugin->m_pluginStatus;
5143 auto icon_name = icon_by_status[stat];
5145 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
5146 path.AppendDir(
"uidata");
5147 path.AppendDir(
"traditional");
5149 int bmsize = GetCharWidth() * 3 * dpi_mult;
5150 if (path.IsFileReadable()) {
5151 statusBitmap = LoadSVG(path.GetFullPath(), bmsize, bmsize);
5152 ok = statusBitmap.IsOk();
5155 auto style = g_StyleManager->GetCurrentStyle();
5156 statusBitmap = wxBitmap(style->GetIcon(_T(
"default_pi"), bmsize, bmsize));
5157 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
5160 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
5161 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
5163 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
5165 itemBoxSizer02->AddSpacer(GetCharWidth());
5167 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
5168 &PluginPanel::OnPluginPreferences,
this);
5169 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
5170 &PluginPanel::OnPluginUninstall,
this);
5171 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
5172 &PluginPanel::OnPluginAction,
this);
5174 SetSelected(m_bSelected);
5175 SetAutoLayout(
true);
5180PluginPanel::~PluginPanel() {
5181 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5182 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
5184 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5185 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5186 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
5187 if (m_pButtonAction) {
5188 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
5189 &PluginPanel::OnPluginAction,
this);
5191 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
5192 &PluginPanel::OnPluginPreferences,
this);
5193 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
5194 &PluginPanel::OnPluginEnableToggle,
this);
5197void PluginPanel::SetActionLabel(wxString &label) {
5198 m_pButtonAction->SetLabel(label);
5202static wxStopWatch swclick;
5203static int downx, downy;
5205void PluginPanel::OnPluginSelected(wxMouseEvent &event) {
5206#ifdef __OCPN__ANDROID__
5208 event.GetPosition(&downx, &downy);
5214void PluginPanel::OnPluginSelectedUp(wxMouseEvent &event) {
5215#ifdef __OCPN__ANDROID__
5216 qDebug() << swclick.Time();
5217 if (swclick.Time() < 200) {
5219 event.GetPosition(&upx, &upy);
5220 if ((fabs(upx - downx) < GetCharWidth()) &&
5221 (fabs(upy - downy) < GetCharWidth())) {
5229void PluginPanel::DoPluginSelect() {
5230 if (m_pPlugin->m_pluginStatus == PluginStatus::ManagedInstallAvailable) {
5236 run_update_dialog(m_PluginListPanel, m_pPlugin,
false, 0,
true);
5237 }
else if (m_bSelected) {
5239 m_PluginListPanel->SelectPlugin(NULL);
5242 m_PluginListPanel->SelectPlugin(
this);
5246void PluginPanel::SetSelected(
bool selected) {
5247 m_bSelected = selected;
5251 if (m_pPlugin->m_ManagedMetadata.version.size()) {
5257 if (m_pPlugin->m_pluginStatus ==
5258 PluginStatus::ManagedInstalledCurrentVersion)
5259 m_pVersion->SetLabel(m_pPlugin->m_ManagedMetadata.version);
5261 if (m_pPlugin->m_pluginStatus ==
5262 PluginStatus::ManagedInstalledUpdateAvailable)
5263 m_pVersion->SetLabel(wxString(m_pPlugin->m_InstalledManagedVersion));
5267 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
5268 m_pButtons->Show(
true);
5269 bool unInstallPossible =
5270 canUninstall(m_pPlugin->m_common_name.ToStdString());
5273 if (m_pPlugin->m_pluginStatus == PluginStatus::LegacyUpdateAvailable ||
5274 m_pPlugin->m_pluginStatus == PluginStatus::Unmanaged ||
5275 m_pPlugin->m_pluginStatus == PluginStatus::System)
5276 unInstallPossible =
false;
5278 m_pButtonUninstall->Show(unInstallPossible);
5280 if (m_pPlugin->m_ManagedMetadata.info_url.size()) {
5281 m_info_btn->SetURL(m_pPlugin->m_ManagedMetadata.info_url.c_str());
5285 m_cbEnable->Show(
true);
5290 switch (m_pPlugin->m_pluginStatus) {
5291 case PluginStatus::LegacyUpdateAvailable:
5292 label = _(
"Upgrade to Version ");
5293 label += wxString(m_pPlugin->m_ManagedMetadata.version.c_str());
5294 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
5295 m_pButtonAction->Enable();
5298 case PluginStatus::ManagedInstallAvailable:
5299 label = _(
"Install...");
5300 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
5301 m_pButtonAction->Enable();
5304 case PluginStatus::ManagedInstalledUpdateAvailable:
5305 label = _(
"Update to ");
5306 label += wxString(m_pPlugin->m_ManagedMetadata.version.c_str());
5307 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
5308 m_pButtonAction->Enable();
5311 case PluginStatus::ManagedInstalledCurrentVersion:
5312 label = _(
"Reinstall");
5313 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
5314 m_pButtonAction->Enable();
5317 case PluginStatus::ManagedInstalledDowngradeAvailable:
5318 label = _(
"Downgrade");
5319 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
5320 m_pButtonAction->Enable();
5323 case PluginStatus::Unmanaged:
5324 m_action = ActionVerb::NOP;
5325 m_pButtonAction->Hide();
5328 case PluginStatus::System:
5329 m_action = ActionVerb::NOP;
5330 m_pButtonAction->Hide();
5335 m_action = ActionVerb::NOP;
5338 SetActionLabel(label);
5342 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
5351 m_pButtons->Show(
false);
5354 if (m_pPlugin->m_pluginStatus == PluginStatus::ManagedInstallAvailable)
5355 m_cbEnable->Show(
false);
5362#ifdef __OCPN__ANDROID__
5371 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
5373 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
5376 SetEnabled(m_pPlugin->m_bEnabled);
5378#ifdef __OCPN__ANDROID__
5391void PluginPanel::OnPaint(wxPaintEvent &event) {
5394 int penWidth = m_penWidthUnselected;
5395 wxColour color = GetDialogColor(DLG_UNSELECTED_BACKGROUND);
5396 wxColour border = GetDialogColor(DLG_UNSELECTED_ACCENT);
5399 penWidth = m_penWidthSelected;
5400 color = GetDialogColor(DLG_SELECTED_BACKGROUND);
5401 border = GetDialogColor(DLG_SELECTED_ACCENT);
5404 wxBrush b(color, wxBRUSHSTYLE_SOLID);
5406 dc.SetPen(wxPen(border, penWidth));
5408 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
5411void PluginPanel::OnPluginPreferences(wxCommandEvent &event) {
5412 if (m_pPlugin->m_bEnabled && m_pPlugin->m_bInitState &&
5413 (m_pPlugin->m_cap_flag & WANTS_PREFERENCES)) {
5414#ifdef __OCPN__ANDROID__
5415 androidDisableRotation();
5416 m_pPlugin->m_pplugin->ShowPreferencesDialog(
5421 m_pPlugin->m_pplugin->ShowPreferencesDialog(
this);
5426void PluginPanel::OnPluginEnableToggle(wxCommandEvent &event) {
5427 SetEnabled(!m_pPlugin->m_bEnabled);
5428 if (m_pVersion->GetLabel().IsEmpty())
5432void PluginPanel::OnPluginUninstall(wxCommandEvent &event) {
5433 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
5436 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
5437 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
5438 actionEvent.SetClientData(
this);
5439 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
5442void PluginPanel::OnPluginAction(wxCommandEvent &event) {
5444 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
5445 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
5446 actionEvent.SetClientData(
this);
5447 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
5452void PluginPanel::SetEnabled(
bool enabled) {
5453 if (m_pPlugin->m_bEnabled != enabled) {
5454 m_pPlugin->m_bEnabled = enabled;
5455 PluginLoader::getInstance()->UpdatePlugIns();
5456 NotifySetupOptionsPlugin(m_pPlugin);
5458 if (!enabled && !m_bSelected) {
5459 m_pName->SetForegroundColour(
5460 wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
5461 m_pVersion->SetForegroundColour(
5462 wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
5463 m_pDescription->SetForegroundColour(
5464 wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
5465#ifdef x__OCPN__ANDROID__
5467 m_pVersion->Disable();
5468 m_pDescription->Disable();
5471 m_pName->SetForegroundColour(
5472 wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
5473 m_pVersion->SetForegroundColour(
5474 wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
5475 m_pDescription->SetForegroundColour(
5476 wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
5477#ifdef x__OCPN__ANDROID__
5479 m_pVersion->Enable();
5480 m_pDescription->Enable();
5484#ifdef __OCPN__ANDROID__
5485 m_pName->Enable(enabled || m_bSelected);
5486 m_pVersion->Enable(enabled || m_bSelected);
5487 m_pDescription->Enable(enabled || m_bSelected);
5491 wxString description = m_pPlugin->m_long_description;
5492 if (description.IsEmpty())
5493 description = wxString(m_pPlugin->m_ManagedMetadata.description.c_str());
5496 g_options->GetSize().x * 7 / 10);
5497 m_pDescription->SetLabel(wrapper.GetWrapped());
5498 if (m_pPlugin->m_ManagedMetadata.info_url.size()) {
5499 m_info_btn->SetURL(m_pPlugin->m_ManagedMetadata.info_url.c_str());
5503 wxString description = m_pPlugin->m_short_description;
5504 if (description.IsEmpty())
5505 description = wxString(m_pPlugin->m_ManagedMetadata.summary.c_str());
5507 g_options->GetSize().x * 7 / 10);
5508 m_pDescription->SetLabel(wrapper.GetWrapped());
5511 m_pButtonPreferences->Enable(enabled &&
5512 (m_pPlugin->m_cap_flag & WANTS_PREFERENCES));
5513 m_cbEnable->SetValue(enabled);
5516void PluginPanel::OnPluginUp(wxCommandEvent &event) {
5517 m_PluginListPanel->MoveUp(
this);
5520void PluginPanel::OnPluginDown(wxCommandEvent &event) {
5521 m_PluginListPanel->MoveDown(
this);
5526 : wxPanel(parent), m_url(url) {
5527 auto vbox =
new wxBoxSizer(wxVERTICAL);
5528 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
5529 button->Enable(strlen(url) > 0);
5532 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
5533 [=](wxCommandEvent &) { wxLaunchDefaultBrowser(m_url); });
5541PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
5543PlugInChartBase::~PlugInChartBase() {}
5545wxString PlugInChartBase::GetFileSearchMask(
void) {
return _T(
""); }
5547int PlugInChartBase::Init(
const wxString &name,
int init_flags) {
return 0; }
5551double PlugInChartBase::GetNormalScaleMin(
double canvas_scale_factor,
5552 bool b_allow_overzoom) {
5556double PlugInChartBase::GetNormalScaleMax(
double canvas_scale_factor,
5561bool PlugInChartBase::GetChartExtent(
ExtentPI *pext) {
return false; }
5563wxBitmap &PlugInChartBase::RenderRegionView(
const PlugIn_ViewPort &VPoint,
5564 const wxRegion &Region) {
5565 return wxNullBitmap;
5573void PlugInChartBase::GetValidCanvasRegion(
const PlugIn_ViewPort &VPoint,
5574 wxRegion *pValidRegion) {}
5576void PlugInChartBase::SetColorScheme(
int cs,
bool bApplyImmediate) {}
5578double PlugInChartBase::GetNearestPreferredScalePPM(
double target_scale_ppm) {
5582wxBitmap *PlugInChartBase::GetThumbnail(
int tnx,
int tny,
int cs) {
5586void PlugInChartBase::ComputeSourceRectangle(
const PlugIn_ViewPort &vp,
5587 wxRect *pSourceRect) {}
5589double PlugInChartBase::GetRasterScaleFactor() {
return 1.0; }
5591bool PlugInChartBase::GetChartBits(wxRect &source,
unsigned char *pPix,
5596int PlugInChartBase::GetSize_X() {
return 1; }
5598int PlugInChartBase::GetSize_Y() {
return 1; }
5600void PlugInChartBase::latlong_to_chartpix(
double lat,
double lon,
double &pixx,
5603void PlugInChartBase::chartpix_to_latlong(
double pixx,
double pixy,
5604 double *plat,
double *plon) {}
5611PlugInChartBaseGL::PlugInChartBaseGL() {}
5613PlugInChartBaseGL::~PlugInChartBaseGL() {}
5615int PlugInChartBaseGL::RenderRegionViewOnGL(
const wxGLContext &glc,
5617 const wxRegion &Region,
5618 bool b_use_stencil) {
5622ListOfPI_S57Obj *PlugInChartBaseGL::GetObjRuleListAtLatLon(
5627wxString PlugInChartBaseGL::CreateObjDescriptions(ListOfPI_S57Obj *obj_list) {
5631int PlugInChartBaseGL::GetNoCOVREntries() {
return 0; }
5633int PlugInChartBaseGL::GetNoCOVRTablePoints(
int iTable) {
return 0; }
5635int PlugInChartBaseGL::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
5637float *PlugInChartBaseGL::GetNoCOVRTableHead(
int iTable) {
return 0; }
5644PlugInChartBaseExtended::PlugInChartBaseExtended() {}
5646PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
5648int PlugInChartBaseExtended::RenderRegionViewOnGL(
const wxGLContext &glc,
5650 const wxRegion &Region,
5651 bool b_use_stencil) {
5655int PlugInChartBaseExtended::RenderRegionViewOnGLNoText(
5657 const wxRegion &Region,
bool b_use_stencil) {
5661int PlugInChartBaseExtended::RenderRegionViewOnGLTextOnly(
5663 const wxRegion &Region,
bool b_use_stencil) {
5667wxBitmap &PlugInChartBaseExtended::RenderRegionViewOnDCNoText(
5669 return wxNullBitmap;
5672bool PlugInChartBaseExtended::RenderRegionViewOnDCTextOnly(
5673 wxMemoryDC &dc,
const PlugIn_ViewPort &VPoint,
const wxRegion &Region) {
5677ListOfPI_S57Obj *PlugInChartBaseExtended::GetObjRuleListAtLatLon(
5682wxString PlugInChartBaseExtended::CreateObjDescriptions(
5683 ListOfPI_S57Obj *obj_list) {
5687int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
5689int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
5691int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
5693float *PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
5695void PlugInChartBaseExtended::ClearPLIBTextList() {}
5702PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
5704PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
5707PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
5717PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
5719PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
5721ListOfPI_S57Obj *PlugInChartBaseGLPlus2::GetLightsObjRuleListVisibleAtLatLon(
5731ChartPlugInWrapper::ChartPlugInWrapper() {}
5733ChartPlugInWrapper::ChartPlugInWrapper(
const wxString &chart_class) {
5734 m_ppo = ::wxCreateDynamicObject(chart_class);
5738ChartPlugInWrapper::~ChartPlugInWrapper() {
5739 if (m_ppicb)
delete m_ppicb;
5742wxString ChartPlugInWrapper::GetFileSearchMask(
void) {
5744 return m_ppicb->GetFileSearchMask();
5749InitReturn ChartPlugInWrapper::Init(
const wxString &name,
5750 ChartInitFlag init_flags) {
5752 wxWindow *pa = wxWindow::FindFocus();
5754 InitReturn ret_val = (InitReturn)m_ppicb->Init(name, (
int)init_flags);
5758 if (ret_val == INIT_OK) {
5759 m_FullPath = m_ppicb->GetFullPath();
5760 m_ChartType = (ChartTypeEnum)m_ppicb->GetChartType();
5761 m_ChartFamily = (ChartFamilyEnum)m_ppicb->GetChartFamily();
5762 m_projection = (OcpnProjType)m_ppicb->GetChartProjection();
5763 m_EdDate = m_ppicb->GetEditionDate();
5764 m_Name = m_ppicb->GetName();
5765 m_ID = m_ppicb->GetID();
5766 m_DepthUnits = m_ppicb->GetDepthUnits();
5767 m_SoundingsDatum = m_ppicb->GetSoundingsDatum();
5768 m_datum_str = m_ppicb->GetDatumString();
5769 m_SE = m_ppicb->GetSE();
5770 m_EdDate = m_ppicb->GetEditionDate();
5771 m_ExtraInfo = m_ppicb->GetExtraInfo();
5772 Chart_Error_Factor = m_ppicb->GetChartErrorFactor();
5773 m_depth_unit_id = (ChartDepthUnitType)m_ppicb->GetDepthUnitId();
5774 m_Chart_Skew = m_ppicb->GetChartSkew();
5775 m_Chart_Scale = m_ppicb->GetNativeScale();
5780 m_ppm_avg = 10000. / m_ppicb->GetNativeScale();
5783 if ((fabs(m_Chart_Skew) < .01) &&
5784 (CHART_FAMILY_RASTER == m_ChartFamily)) {
5786 if (GetChartExtent(&extent)) {
5787 double lon_range = extent.ELON - extent.WLON;
5788 if ((lon_range > 0) &&
5790 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
5794 m_overlayENC =
false;
5795 if (m_ChartFamily == (ChartFamilyEnum)PI_CHART_FAMILY_VECTOR) {
5796 wxCharBuffer buf = m_FullPath.ToUTF8();
5797 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
5800 bReadyToRender = m_ppicb->IsReadyToRender();
5803 m_ChartType = CHART_TYPE_UNKNOWN;
5804 m_ChartFamily = CHART_FAMILY_UNKNOWN;
5810 if (pc) pc->SetFocus();
5814 return INIT_FAIL_REMOVE;
5818int ChartPlugInWrapper::GetCOVREntries() {
5820 return m_ppicb->GetCOVREntries();
5825int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
5827 return m_ppicb->GetCOVRTablePoints(iTable);
5832int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
5834 return m_ppicb->GetCOVRTablenPoints(iTable);
5839float *ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
5841 return m_ppicb->GetCOVRTableHead(iTable);
5851int ChartPlugInWrapper::GetNoCOVREntries() {
5855 return ppicbgl->GetNoCOVREntries();
5861int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
5865 return ppicbgl->GetNoCOVRTablePoints(iTable);
5871int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
5875 return ppicbgl->GetNoCOVRTablenPoints(iTable);
5881float *ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
5885 return ppicbgl->GetNoCOVRTableHead(iTable);
5891bool ChartPlugInWrapper::GetChartExtent(
Extent *pext) {
5894 if (m_ppicb->GetChartExtent(&xpi)) {
5895 pext->NLAT = xpi.NLAT;
5896 pext->SLAT = xpi.SLAT;
5897 pext->ELON = xpi.ELON;
5898 pext->WLON = xpi.WLON;
5907ThumbData *ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
5912 if (!pThumbData->pDIBThumb) {
5913 wxBitmap *pBMPOwnedByChart =
5914 m_ppicb->GetThumbnail(tnx, tny, m_global_color_scheme);
5915 if (pBMPOwnedByChart) {
5916 wxImage img = pBMPOwnedByChart->ConvertToImage();
5917 pThumbData->pDIBThumb =
new wxBitmap(img);
5919 pThumbData->pDIBThumb = NULL;
5922 pThumbData->Thumb_Size_X = tnx;
5923 pThumbData->Thumb_Size_Y = tny;
5950 pThumbData->ShipX = 0;
5951 pThumbData->ShipY = 0;
5958ThumbData *ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
5960bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
5964double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
5965 bool b_allow_overzoom) {
5967 return m_ppicb->GetNormalScaleMin(canvas_scale_factor, b_allow_overzoom);
5972double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
5975 return m_ppicb->GetNormalScaleMax(canvas_scale_factor, canvas_width);
5994void RenderRotateToViewPort(
const ViewPort &VPoint) {
5995 float xt = VPoint.pix_width / 2.0, yt = VPoint.pix_height / 2.0;
5996 glTranslatef(xt, yt, 0);
5997 glRotatef(VPoint.rotation * 180. / PI, 0, 0, 1);
5998 glTranslatef(-xt, -yt, 0);
6001void UndoRenderRotateToViewPort(
const ViewPort &VPoint) {
6002 float xt = VPoint.pix_width / 2.0, yt = VPoint.pix_height / 2.0;
6003 glTranslatef(xt, yt, 0);
6004 glRotatef(-VPoint.rotation * 180. / PI, 0, 0, 1);
6005 glTranslatef(-xt, -yt, 0);
6008bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext &glc,
6011 const LLRegion &Region) {
6020 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
6021 wxRegion *r = RectRegion.GetNew_wxRegion();
6024 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
6025 chart_region.Intersect(Region);
6027 if (!chart_region.Empty()) {
6028 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
6030 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
6034#ifndef USE_ANDROID_GLES2
6037 RenderRotateToViewPort(VPoint);
6041 ppicb_x->RenderRegionViewOnGL(glc, pivp, *r,
6042 glChartCanvas::s_b_useStencil);
6044 ppicb_gl->RenderRegionViewOnGL(glc, pivp, *r,
6045 glChartCanvas::s_b_useStencil);
6046 UndoRenderRotateToViewPort(VPoint);
6048#ifndef USE_ANDROID_GLES2
6051 glChartCanvas::DisableClipRegion();
6065bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
6066 const wxGLContext &glc,
const ViewPort &VPoint,
6067 const OCPNRegion &RectRegion,
const LLRegion &Region) {
6076 if (!Region.Empty() && ppicb_x) {
6079 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
6080 glChartCanvas::DisableClipRegion();
6083 RenderRotateToViewPort(VPoint);
6086 wxRegion *r = RectRegion.GetNew_wxRegion();
6088 ppicb_x->RenderRegionViewOnGLNoText(glc, pivp, *r,
6089 glChartCanvas::s_b_useStencil);
6092 UndoRenderRotateToViewPort(VPoint);
6097 else if (!Region.Empty() &&
6101 wxRegion *r = RectRegion.GetNew_wxRegion();
6104 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
6105 chart_region.Intersect(Region);
6107 if (!chart_region.Empty()) {
6108 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
6110 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
6112 RenderRotateToViewPort(VPoint);
6115 ppicb->RenderRegionViewOnGL(glc, pivp, *r,
6116 glChartCanvas::s_b_useStencil);
6119 UndoRenderRotateToViewPort(VPoint);
6121 glChartCanvas::DisableClipRegion();
6134bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
6141 if (!Region.Empty() && ppicb_x) {
6142 wxRegion *r = Region.GetNew_wxRegion();
6144#ifndef USE_ANDROID_GLES2
6147 RenderRotateToViewPort(VPoint);
6150 ppicb_x->RenderRegionViewOnGLTextOnly(glc, pivp, *r,
6151 glChartCanvas::s_b_useStencil);
6152 UndoRenderRotateToViewPort(VPoint);
6154#ifndef USE_ANDROID_GLES2
6167bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC &dc,
6173 if (Region.IsOk()) {
6174 wxRegion *r = Region.GetNew_wxRegion();
6176 dc.SelectObject(m_ppicb->RenderRegionView(pivp, *r));
6178 wxBitmap &obmp = m_ppicb->RenderRegionView(pivp, *r);
6181 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
6182 wxColour nodat_sub = nodat;
6184#ifdef ocpnUSE_ocpnBitmap
6185 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
6187 m_pMask =
new wxMask(obmp, nodat_sub);
6188 obmp.SetMask(m_pMask);
6190 dc.SelectObject(obmp);
6201bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC &dc,
6212 if (Region.IsOk() && (pCBx || ppicb)) {
6213 wxRegion *r = Region.GetNew_wxRegion();
6216 dc.SelectObject(pCBx->RenderRegionViewOnDCNoText(pivp, *r));
6218 dc.SelectObject(ppicb->RenderRegionView(pivp, *r));
6228bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
6231 bool ret_val =
false;
6234 if (Region.IsOk()) {
6235 wxRegion *r = Region.GetNew_wxRegion();
6239 if (pCBx) ret_val = pCBx->RenderRegionViewOnDCTextOnly(dc, pivp, *r);
6249void ChartPlugInWrapper::ClearPLIBTextList() {
6253 if (pCBx) pCBx->ClearPLIBTextList();
6257bool ChartPlugInWrapper::AdjustVP(
ViewPort &vp_last,
ViewPort &vp_proposed) {
6261 return m_ppicb->AdjustVP(pivp_last, pivp_proposed);
6266void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort &VPoint,
6274 m_ppicb->GetValidCanvasRegion(pivp, ®ion);
6281void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
6283 m_ppicb->SetColorScheme(cs, bApplyImmediate);
6285 m_global_color_scheme = cs;
6287 if (pThumbData) pThumbData->pDIBThumb = NULL;
6290double ChartPlugInWrapper::GetNearestPreferredScalePPM(
6291 double target_scale_ppm) {
6293 return m_ppicb->GetNearestPreferredScalePPM(target_scale_ppm);
6298void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort &VPoint,
6299 wxRect *pSourceRect) {
6302 m_ppicb->ComputeSourceRectangle(pivp, pSourceRect);
6306double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort &vp) {
6308 return (wxRound(100000 * GetPPM() / vp.view_scale_ppm)) / 100000.;
6313bool ChartPlugInWrapper::GetChartBits(wxRect &source,
unsigned char *pPix,
6315 wxCriticalSectionLocker locker(m_critSect);
6319 return m_ppicb->GetChartBits(source, pPix, sub_samp);
6324int ChartPlugInWrapper::GetSize_X() {
6326 return m_ppicb->GetSize_X();
6331int ChartPlugInWrapper::GetSize_Y() {
6333 return m_ppicb->GetSize_Y();
6338void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
6339 double &pixx,
double &pixy) {
6340 if (m_ppicb) m_ppicb->latlong_to_chartpix(lat, lon, pixx, pixy);
6343void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
6344 double *plat,
double *plon) {
6345 if (m_ppicb) m_ppicb->chartpix_to_latlong(pixx, pixy, plat, plon);
6353wxString toSDMM_PlugIn(
int NEflag,
double a,
bool hi_precision) {
6354 return toSDMM(NEflag, a, hi_precision);
6357wxColour GetBaseGlobalColor(wxString colorName) {
6358 return GetGlobalColor(colorName);
6361int OCPNMessageBox_PlugIn(wxWindow *parent,
const wxString &message,
6362 const wxString &caption,
int style,
int x,
int y) {
6363 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
6366wxString GetOCPN_ExePath(
void) {
return g_Platform->GetExePath(); }
6368wxString *GetpPlugInLocation() {
return g_Platform->GetPluginDirPtr(); }
6370wxString GetWritableDocumentsDir(
void) {
6371 return g_Platform->GetWritableDocumentsDir();
6376 ArrayOfPlugIns *pi_array = PluginLoader::getInstance()->GetPlugInArray();
6377 for (
unsigned int i = 0; i < pi_array->GetCount(); i++) {
6379 if (pic->m_pplugin == pplugin) {
6380 ret_val = pic->m_plugin_file;
6390ListOfPI_S57Obj *PlugInManager::GetPlugInObjRuleListAtLatLon(
6393 ListOfPI_S57Obj *list = NULL;
6399 list = picbgl->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
6407 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
6417 ListOfPI_S57Obj *rule_list) {
6423 ret_str = picbgl->CreateObjDescriptions(rule_list);
6428 ret_str = picbx->CreateObjDescriptions(rule_list);
6436wxString PI_GetPLIBColorScheme() {
6440int PI_GetPLIBDepthUnitInt() {
6442 return ps52plib->m_nDepthUnitDisplay;
6447int PI_GetPLIBSymbolStyle() {
6449 return ps52plib->m_nSymbolStyle;
6454int PI_GetPLIBBoundaryStyle() {
6456 return ps52plib->m_nBoundaryStyle;
6466 CreateCompatibleS57Object(pObj, &cobj, &ctx);
6468 ViewPort cvp = CreateCompatibleViewport(*vp);
6473 ObjRazRules rzRules;
6474 rzRules.obj = &cobj;
6475 rzRules.LUP = pContext->LUP;
6476 rzRules.sm_transform_parms = 0;
6477 rzRules.child = NULL;
6478 rzRules.next = NULL;
6481 ps52plib->SetVPointCompat(
6492 GetOCPNCanvasWindow()->GetContentScaleFactor()
6494 ps52plib->PrepareForRender();
6496 return ps52plib->ObjectRenderCheck(&rzRules);
6504int PI_GetPLIBStateHash() {
6506 return ps52plib->GetStateHash();
6511void CreateCompatibleS57Object(
PI_S57Obj *pObj, S57Obj *cobj,
6512 chart_context *pctx) {
6513 strncpy(cobj->FeatureName, pObj->FeatureName, 8);
6514 cobj->Primitive_type = (GeoPrim_t)pObj->Primitive_type;
6515 cobj->att_array = pObj->att_array;
6516 cobj->attVal = pObj->attVal;
6517 cobj->n_attr = pObj->n_attr;
6522 cobj->npt = pObj->npt;
6524 cobj->iOBJL = pObj->iOBJL;
6525 cobj->Index = pObj->Index;
6527 cobj->geoPt = (pt *)pObj->geoPt;
6528 cobj->geoPtz = pObj->geoPtz;
6529 cobj->geoPtMulti = pObj->geoPtMulti;
6531 cobj->m_lat = pObj->m_lat;
6532 cobj->m_lon = pObj->m_lon;
6534 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
6535 cobj->x_rate = pObj->x_rate;
6536 cobj->y_rate = pObj->y_rate;
6537 cobj->x_origin = pObj->x_origin;
6538 cobj->y_origin = pObj->y_origin;
6540 cobj->Scamin = pObj->Scamin;
6541 cobj->nRef = pObj->nRef;
6542 cobj->bIsAton = pObj->bIsAton;
6543 cobj->bIsAssociable = pObj->bIsAssociable;
6545 cobj->m_n_lsindex = pObj->m_n_lsindex;
6546 cobj->m_lsindex_array = pObj->m_lsindex_array;
6547 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
6549 if (gs_plib_flags & PLIB_CAPS_OBJSEGLIST) {
6550 cobj->m_ls_list_legacy =
6554 cobj->m_ls_list_legacy = 0;
6555 cobj->m_ls_list = 0;
6557 if (gs_plib_flags & PLIB_CAPS_OBJCATMUTATE)
6558 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
6560 cobj->m_bcategory_mutable =
true;
6563 if (gs_plib_flags & PLIB_CAPS_OBJCATMUTATE) {
6564 if (pObj->m_DPRI == -1) {
6566 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
6568 cobj->m_DPRI = pObj->m_DPRI;
6571 cobj->pPolyTessGeo = (PolyTessGeo *)pObj->pPolyTessGeo;
6572 cobj->m_chart_context = (chart_context *)pObj->m_chart_context;
6574 if (pObj->auxParm3 != 1234) {
6575 pObj->auxParm3 = 1234;
6576 pObj->auxParm0 = -99;
6579 cobj->auxParm0 = pObj->auxParm0;
6586 if (pContext->bBBObj_valid)
6588 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
6589 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
6591 cobj->CSrules = pContext->CSrules;
6592 cobj->bCS_Added = pContext->bCS_Added;
6594 cobj->FText = pContext->FText;
6595 cobj->bFText_Added = pContext->bFText_Added;
6596 cobj->rText = pContext->rText;
6598 cobj->bIsClone =
true;
6601 cobj->m_chart_context = pctx;
6602 chart_context *ppctx = (chart_context *)pObj->m_chart_context;
6605 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
6606 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
6607 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
6608 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
6609 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
6610 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
6611 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
6612 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
6614 cobj->m_chart_context->chart =
6616 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
6621bool PI_PLIBSetContext(
PI_S57Obj *pObj) {
6623 if (!pObj->S52_Context) {
6625 pObj->S52_Context = ctx;
6631 CreateCompatibleS57Object(pObj, &cobj, NULL);
6633 LUPname LUP_Name = PAPER_CHART;
6636 ctx->CSrules = NULL;
6637 ctx->bCS_Added =
false;
6640 if (ctx->bFText_Added) {
6641 ctx->bFText_Added =
false;
6647 ctx->bBBObj_valid =
true;
6648 ctx->BBObj.SetMin(pObj->lon_min, pObj->lat_min);
6649 ctx->BBObj.SetMax(pObj->lon_max, pObj->lat_max);
6652 switch (cobj.Primitive_type) {
6657 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
6658 LUP_Name = PAPER_CHART;
6660 LUP_Name = SIMPLIFIED;
6669 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
6670 LUP_Name = PLAIN_BOUNDARIES;
6672 LUP_Name = SYMBOLIZED_BOUNDARIES;
6677 LUPrec *lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
6681 ps52plib->_LUP2rules(lup, &cobj);
6683 ctx->MPSRulesList = NULL;
6691 pContext->bBBObj_valid =
true;
6692 pContext->BBObj.SetMin(pObj->lon_min, pObj->lat_min);
6693 pContext->BBObj.SetMax(pObj->lon_max, pObj->lat_max);
6697void UpdatePIObjectPlibContext(
PI_S57Obj *pObj, S57Obj *cobj,
6698 ObjRazRules *rzRules) {
6702 pContext->CSrules = cobj->CSrules;
6703 pContext->bCS_Added = cobj->bCS_Added;
6705 pContext->FText = cobj->FText;
6706 pContext->bFText_Added = cobj->bFText_Added;
6707 pContext->rText = cobj->rText;
6709 if (cobj->BBObj.GetValid()) {
6712 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
6713 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
6714 pContext->bBBObj_valid =
true;
6719 pObj->m_DisplayCat = (PI_DisCat)cobj->m_DisplayCat;
6721 if (gs_plib_flags & PLIB_CAPS_OBJCATMUTATE) pObj->m_DPRI = cobj->m_DPRI;
6723 pContext->ChildRazRules = rzRules->child;
6724 pContext->MPSRulesList = rzRules->mps;
6726 pObj->auxParm0 = cobj->auxParm0;
6729bool PI_GetObjectRenderBox(
PI_S57Obj *pObj,
double *lat_min,
double *lat_max,
6730 double *lon_min,
double *lon_max) {
6733 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
6734 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
6735 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
6736 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
6737 return pContext->bBBObj_valid;
6742PI_LUPname PI_GetObjectLUPName(
PI_S57Obj *pObj) {
6745 LUPrec *lup = pContext->LUP;
6746 if (lup)
return (PI_LUPname)(lup->TNAM);
6748 return (PI_LUPname)(-1);
6751PI_DisPrio PI_GetObjectDisplayPriority(
PI_S57Obj *pObj) {
6754 LUPrec *lup = pContext->LUP;
6755 if (lup)
return (PI_DisPrio)(lup->DPRI);
6758 return (PI_DisPrio)(-1);
6761PI_DisCat PI_GetObjectDisplayCategory(
PI_S57Obj *pObj) {
6764 LUPrec *lup = pContext->LUP;
6765 if (lup)
return (PI_DisCat)(lup->DISC);
6767 return (PI_DisCat)(-1);
6769double PI_GetPLIBMarinerSafetyContour() {
6770 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
6773void PI_PLIBSetLineFeaturePriority(
PI_S57Obj *pObj,
int prio) {
6777 CreateCompatibleS57Object(pObj, &cobj, &ctx);
6782 ObjRazRules rzRules;
6783 rzRules.obj = &cobj;
6784 rzRules.LUP = pContext->LUP;
6785 rzRules.sm_transform_parms = 0;
6786 rzRules.child = NULL;
6787 rzRules.next = NULL;
6788 rzRules.mps = pContext->MPSRulesList;
6790 if (pContext->LUP) {
6791 ps52plib->SetLineFeaturePriority(&rzRules, prio);
6794 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
6798void PI_PLIBPrepareForNewRender(
void) {
6800 ps52plib->PrepareForRender();
6801 ps52plib->ClearTextList();
6803 if (gs_plib_flags & PLIB_CAPS_LINE_BUFFER)
6804 ps52plib->EnableGLLS(
true);
6806 ps52plib->EnableGLLS(
false);
6810void PI_PLIBSetRenderCaps(
unsigned int flags) { gs_plib_flags = flags; }
6812void PI_PLIBFreeContext(
void *pContext) {
6815 if (pctx->ChildRazRules) {
6816 ObjRazRules *ctop = pctx->ChildRazRules;
6820 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
6823 ObjRazRules *cnxx = ctop->next;
6829 if (pctx->MPSRulesList) {
6830 if (ps52plib && pctx->MPSRulesList->cs_rules) {
6831 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
6833 Rules *top = pctx->MPSRulesList->cs_rules->Item(i);
6834 ps52plib->DestroyRulesChain(top);
6836 delete pctx->MPSRulesList->cs_rules;
6838 free(pctx->MPSRulesList);
6850 CreateCompatibleS57Object(pObj, &cobj, &ctx);
6856 toSM(vp->clat, vp->clon, pObj->chart_ref_lat, pObj->chart_ref_lon,
6857 &transform.easting_vp_center, &transform.northing_vp_center);
6860 ObjRazRules rzRules;
6861 rzRules.obj = &cobj;
6862 rzRules.LUP = pContext->LUP;
6863 rzRules.sm_transform_parms = &transform;
6864 rzRules.child = pContext->ChildRazRules;
6865 rzRules.next = NULL;
6866 rzRules.mps = pContext->MPSRulesList;
6868 if (pContext->LUP) {
6869 ViewPort cvp = CreateCompatibleViewport(*vp);
6873 ps52plib->SetVPointCompat(
6884 GetOCPNCanvasWindow()->GetContentScaleFactor()
6886 ps52plib->PrepareForRender();
6888 ps52plib->RenderObjectToDC(pdc, &rzRules);
6891 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
6898 wxRect rect,
unsigned char *pixbuf) {
6900 render_canvas_parms pb_spec;
6902 pb_spec.depth = BPP;
6903 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
6904 pb_spec.lclip = rect.x;
6905 pb_spec.rclip = rect.x + rect.width - 1;
6906 pb_spec.pix_buff = pixbuf;
6907 pb_spec.width = rect.width;
6908 pb_spec.height = rect.height;
6911#ifdef ocpnUSE_ocpnBitmap
6912 pb_spec.b_revrgb =
true;
6914 pb_spec.b_revrgb =
false;
6917 pb_spec.b_revrgb =
false;
6922 CreateCompatibleS57Object(pObj, &cobj, &ctx);
6928 toSM(vp->clat, vp->clon, pObj->chart_ref_lat, pObj->chart_ref_lon,
6929 &transform.easting_vp_center, &transform.northing_vp_center);
6932 ObjRazRules rzRules;
6933 rzRules.obj = &cobj;
6934 rzRules.LUP = pContext->LUP;
6935 rzRules.sm_transform_parms = &transform;
6936 rzRules.child = pContext->ChildRazRules;
6937 rzRules.next = NULL;
6938 rzRules.mps = pContext->MPSRulesList;
6940 ViewPort cvp = CreateCompatibleViewport(*vp);
6944 if (!(gs_plib_flags & PLIB_CAPS_SINGLEGEO_BUFFER)) {
6945 if (!pObj->geoPtMulti) {
6946 PolyTessGeo *tess = (PolyTessGeo *)pObj->pPolyTessGeo;
6948 if (!tess)
return 1;
6950 PolyTriGroup *ptg =
new PolyTriGroup;
6951 ptg->tri_prim_head =
6952 tess->Get_PolyTriGroup_head()->tri_prim_head;
6953 ptg->bsingle_alloc =
false;
6954 ptg->data_type = DATA_TYPE_DOUBLE;
6955 tess->Set_PolyTriGroup_head(ptg);
6957 double *pd = (
double *)malloc(
sizeof(
double));
6958 pObj->geoPtMulti = pd;
6962 if (pContext->LUP) {
6965 ps52plib->SetVPointCompat(
6976 GetOCPNCanvasWindow()->GetContentScaleFactor()
6978 ps52plib->PrepareForRender();
6980 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
6983 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
6989int PI_PLIBRenderAreaToGL(
const wxGLContext &glcc,
PI_S57Obj *pObj,
6995 CreateCompatibleS57Object(pObj, &cobj, &ctx);
7002 if (!(gs_plib_flags & PLIB_CAPS_SINGLEGEO_BUFFER)) {
7003 if (!pObj->geoPtMulti) {
7004 PolyTessGeo *tess = (PolyTessGeo *)pObj->pPolyTessGeo;
7006 if (!tess)
return 1;
7010 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
7011 ptg->bsingle_alloc =
false;
7012 ptg->data_type = DATA_TYPE_DOUBLE;
7013 tess->Set_PolyTriGroup_head(ptg);
7017 double *pd = (
double *)malloc(
sizeof(
double));
7018 pObj->geoPtMulti = pd;
7024 if (pObj->auxParm0 < 1)
7033 toSM(vp->clat, vp->clon, pObj->chart_ref_lat, pObj->chart_ref_lon,
7034 &transform.easting_vp_center, &transform.northing_vp_center);
7037 ObjRazRules rzRules;
7038 rzRules.obj = &cobj;
7039 rzRules.LUP = pContext->LUP;
7040 rzRules.sm_transform_parms = &transform;
7041 rzRules.child = pContext->ChildRazRules;
7042 rzRules.next = NULL;
7043 rzRules.mps = pContext->MPSRulesList;
7045 if (pContext->LUP) {
7046 ViewPort cvp = CreateCompatibleViewport(*vp);
7050 ps52plib->SetVPointCompat(
7061 GetOCPNCanvasWindow()->GetContentScaleFactor()
7063 ps52plib->PrepareForRender();
7065 ps52plib->RenderAreaToGL(glcc, &rzRules);
7068 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
7075int PI_PLIBRenderObjectToGL(
const wxGLContext &glcc,
PI_S57Obj *pObj,
7080 CreateCompatibleS57Object(pObj, &cobj, &ctx);
7086 toSM(vp->clat, vp->clon, pObj->chart_ref_lat, pObj->chart_ref_lon,
7087 &transform.easting_vp_center, &transform.northing_vp_center);
7090 ObjRazRules rzRules;
7091 rzRules.obj = &cobj;
7092 rzRules.LUP = pContext->LUP;
7093 rzRules.sm_transform_parms = &transform;
7094 rzRules.child = pContext->ChildRazRules;
7095 rzRules.next = NULL;
7096 rzRules.mps = pContext->MPSRulesList;
7098 if (pContext->LUP) {
7099 ViewPort cvp = CreateCompatibleViewport(*vp);
7103 ps52plib->SetVPointCompat(
7114 GetOCPNCanvasWindow()->GetContentScaleFactor()
7116 ps52plib->PrepareForRender();
7118 ps52plib->RenderObjectToGL(glcc, &rzRules);
7121 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
7132double fromDMM_Plugin(wxString sdms) {
return fromDMM(sdms); }
7134void SetCanvasRotation(
double rotation) {
7135 gFrame->GetPrimaryCanvas()->DoRotateCanvas(rotation);
7138double GetCanvasTilt() {
return gFrame->GetPrimaryCanvas()->GetVPTilt(); }
7140void SetCanvasTilt(
double tilt) {
7141 gFrame->GetPrimaryCanvas()->DoTiltCanvas(tilt);
7144void SetCanvasProjection(
int projection) {
7145 gFrame->GetPrimaryCanvas()->SetVPProjection(projection);
7148OcpnSound *g_PluginSound = SoundFactory();
7149static void onPlugInPlaySoundExFinished(
void *ptr) {}
7152bool PlugInPlaySoundEx(wxString &sound_file,
int deviceIndex) {
7153 bool ok = g_PluginSound->Load(sound_file, deviceIndex);
7155 wxLogWarning(
"Cannot load sound file: %s", sound_file);
7158 auto cmd_sound =
dynamic_cast<SystemCmdSound *
>(g_PluginSound);
7159 if (cmd_sound) cmd_sound->SetCmd(g_CmdSoundString.mb_str(wxConvUTF8));
7161 g_PluginSound->SetFinishedCallback(onPlugInPlaySoundExFinished, NULL);
7162 ok = g_PluginSound->Play();
7164 wxLogWarning(
"Cannot play sound file: %s", sound_file);
7169bool CheckEdgePan_PlugIn(
int x,
int y,
bool dragging,
int margin,
int delta) {
7170 return gFrame->GetPrimaryCanvas()->CheckEdgePan(x, y, dragging, margin,
7174wxBitmap GetIcon_PlugIn(
const wxString &name) {
7176 return style->GetIcon(name);
7179void SetCursor_PlugIn(wxCursor *pCursor) {
7180 gFrame->GetPrimaryCanvas()->pPlugIn_Cursor = pCursor;
7183void AddChartDirectory(wxString &path) {
7185 g_options->AddChartDir(path);
7189void ForceChartDBUpdate() {
7191 g_options->pScanCheckBox->SetValue(
true);
7192 g_options->pUpdateCheckBox->SetValue(
true);
7196void ForceChartDBRebuild() {
7198 g_options->pUpdateCheckBox->SetValue(
true);
7202wxDialog *GetActiveOptionsDialog() {
return g_options; }
7204int PlatformDirSelectorDialog(wxWindow *parent, wxString *file_spec,
7205 wxString Title, wxString initDir) {
7206 return g_Platform->DoDirSelectorDialog(parent, file_spec, Title, initDir);
7209int PlatformFileSelectorDialog(wxWindow *parent, wxString *file_spec,
7210 wxString Title, wxString initDir,
7211 wxString suggestedName, wxString wildcard) {
7212 return g_Platform->DoFileSelectorDialog(parent, file_spec, Title, initDir,
7213 suggestedName, wildcard);
7220OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
7221 : wxEvent(id, commandType) {
7222 m_stat = OCPN_DL_UNKNOWN;
7223 m_condition = OCPN_DL_EVENT_TYPE_UNKNOWN;
7224 m_b_complete =
false;
7228OCPN_downloadEvent::~OCPN_downloadEvent() {}
7230wxEvent *OCPN_downloadEvent::Clone()
const {
7232 newevent->m_stat = this->m_stat;
7233 newevent->m_condition = this->m_condition;
7235 newevent->m_totalBytes = this->m_totalBytes;
7236 newevent->m_sofarBytes = this->m_sofarBytes;
7237 newevent->m_b_complete = this->m_b_complete;
7243DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
7245_OCPN_DLStatus g_download_status;
7246_OCPN_DLCondition g_download_condition;
7248#define DL_EVENT_TIMER 4388
7256 void setBackgroundMode(
long ID, wxEvtHandler *handler);
7257 void clearBackgroundMode();
7258 void onTimerEvent(wxTimerEvent &event);
7261 wxTimer m_eventTimer;
7262 wxEvtHandler *m_download_evHandler;
7268PI_DLEvtHandler::PI_DLEvtHandler() {
7269 g_download_status = OCPN_DL_UNKNOWN;
7270 g_download_condition = OCPN_DL_EVENT_TYPE_UNKNOWN;
7272 m_download_evHandler = NULL;
7278PI_DLEvtHandler::~PI_DLEvtHandler() {
7279 m_eventTimer.Stop();
7282 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
7289 g_download_status =
event.getDLEventStatus();
7290 g_download_condition =
event.getDLEventCondition();
7293 if (m_download_evHandler &&
7294 (OCPN_DL_EVENT_TYPE_END == event.getDLEventCondition())) {
7296 ev.setComplete(
true);
7297 ev.setTransferred(m_sofarBytes);
7298 ev.setTotal(m_totalBytes);
7300 ev.setDLEventStatus(event.getDLEventStatus());
7301 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
7303 m_download_evHandler->AddPendingEvent(ev);
7304 m_eventTimer.Stop();
7305#ifdef __OCPN__ANDROID__
7306 finishAndroidFileDownload();
7313void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler *handler) {
7315 m_download_evHandler = handler;
7317 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
7321 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
7322 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
7325void PI_DLEvtHandler::clearBackgroundMode() {
7326 m_download_evHandler = NULL;
7327 m_eventTimer.Stop();
7330void PI_DLEvtHandler::onTimerEvent(wxTimerEvent &event) {
7331#ifdef __OCPN__ANDROID__
7336 int stat = queryAndroidFileDownload(m_id, &sstat);
7339 long sofarBytes = 0;
7340 long totalBytes = -1;
7344 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
7345 ev.setComplete(
true);
7346 ev.setTransferred(sofarBytes);
7347 ev.setTotal(totalBytes);
7349 ev.setDLEventStatus(OCPN_DL_FAILED);
7350 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
7352 wxStringTokenizer tk(sstat, _T(
";"));
7353 if (tk.HasMoreTokens()) {
7354 wxString token = tk.GetNextToken();
7355 token.ToLong(&state);
7356 token = tk.GetNextToken();
7357 token.ToLong(&sofarBytes);
7358 token = tk.GetNextToken();
7359 token.ToLong(&totalBytes);
7362 qDebug() << state << sofarBytes << totalBytes;
7364 m_sofarBytes = sofarBytes;
7365 m_totalBytes = totalBytes;
7367 ev.setTransferred(sofarBytes);
7368 ev.setTotal(totalBytes);
7371 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
7372 ev.setComplete(
true);
7373 ev.setDLEventStatus(OCPN_DL_FAILED);
7374 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
7375 }
else if (state == 8) {
7376 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
7377 ev.setComplete(
true);
7378 ev.setDLEventStatus(OCPN_DL_NO_ERROR);
7379 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
7381 ev.setComplete(
false);
7382 ev.setDLEventStatus(OCPN_DL_UNKNOWN);
7383 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_PROGRESS);
7389 if (m_download_evHandler) {
7391 m_download_evHandler->AddPendingEvent(ev);
7395 if (OCPN_DL_EVENT_TYPE_END == ev.getDLEventCondition()) {
7396 m_eventTimer.Stop();
7397 finishAndroidFileDownload();
7406_OCPN_DLStatus OCPN_downloadFile(
const wxString &url,
7407 const wxString &outputFile,
7408 const wxString &title,
const wxString &message,
7409 const wxBitmap &bitmap, wxWindow *parent,
7410 long style,
int timeout_secs) {
7411#ifdef __OCPN__ANDROID__
7413 wxString msg = _T(
"Downloading file synchronously: ");
7420 int vres = validateAndroidWriteLocation(outputFile);
7422 return OCPN_DL_ABORTED;
7428 g_download_status = OCPN_DL_UNKNOWN;
7429 g_download_condition = OCPN_DL_EVENT_TYPE_UNKNOWN;
7432 g_piEventHandler->Connect(
7433 wxEVT_DOWNLOAD_EVENT,
7434 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
7439 wxString fURI = outputFile;
7440 if (!fURI.StartsWith(_T(
"file://"))) {
7441 fURI.Prepend(_T(
"file://"));
7444 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
7447 finishAndroidFileDownload();
7448 g_piEventHandler->Disconnect(
7449 wxEVT_DOWNLOAD_EVENT,
7450 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
7452 return OCPN_DL_FAILED;
7455 wxDateTime dl_start_time = wxDateTime::Now();
7459 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
7460 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
7462 if (dt.GetSeconds() > timeout_secs) {
7463 qDebug() <<
"USER_TIMOUT";
7464 finishAndroidFileDownload();
7465 g_piEventHandler->Disconnect(
7466 wxEVT_DOWNLOAD_EVENT,
7467 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
7469 return (OCPN_DL_USER_TIMEOUT);
7472 if (g_download_condition != OCPN_DL_EVENT_TYPE_UNKNOWN) {
7473 if (OCPN_DL_EVENT_TYPE_END == g_download_condition) {
7474 _OCPN_DLStatus ss = g_download_status;
7475 finishAndroidFileDownload();
7476 g_piEventHandler->Disconnect(
7477 wxEVT_DOWNLOAD_EVENT,
7481 qDebug() <<
"RETURN DL_END" << (int)ss;
7487 int stat = queryAndroidFileDownload(dl_ID, &sstat);
7489 qDebug() <<
"Error on queryAndroidFileDownload";
7490 finishAndroidFileDownload();
7491 g_piEventHandler->Disconnect(
7492 wxEVT_DOWNLOAD_EVENT,
7493 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
7496 return OCPN_DL_FAILED;
7503#elif defined(OCPN_USE_CURL)
7504 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
7505 wxFileOutputStream output(tfn.GetFullPath());
7507 wxCurlDownloadDialog ddlg(url, &output, title, message + url, bitmap, parent,
7509 wxCurlDialogReturnFlag ret = ddlg.RunModal();
7512 _OCPN_DLStatus result = OCPN_DL_UNKNOWN;
7515 case wxCDRF_SUCCESS: {
7516 if (wxCopyFile(tfn.GetFullPath(), outputFile))
7517 result = OCPN_DL_NO_ERROR;
7519 result = OCPN_DL_FAILED;
7522 case wxCDRF_FAILED: {
7523 result = OCPN_DL_FAILED;
7526 case wxCDRF_USER_ABORTED: {
7527 result = OCPN_DL_ABORTED;
7534 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
7538 return OCPN_DL_FAILED;
7543_OCPN_DLStatus OCPN_downloadFileBackground(
const wxString &url,
7544 const wxString &outputFile,
7545 wxEvtHandler *handler,
7547#ifdef __OCPN__ANDROID__
7548 wxString msg = _T(
"Downloading file asynchronously: ");
7560 int res = startAndroidFileDownload(url, outputFile, NULL ,
7564 finishAndroidFileDownload();
7565 return OCPN_DL_FAILED;
7569 g_piEventHandler->setBackgroundMode(dl_ID, handler);
7571 if (handle) *handle = dl_ID;
7573 return OCPN_DL_STARTED;
7575#elif defined(OCPN_USE_CURL)
7576 if (g_pi_manager->m_pCurlThread)
7579 return OCPN_DL_FAILED;
7580 g_pi_manager->m_pCurlThread =
7581 new wxCurlDownloadThread(g_pi_manager, CurlThreadId);
7582 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
7584 if (http && g_pi_manager->m_pCurl &&
7585 dynamic_cast<wxCurlHTTP *
>(g_pi_manager->m_pCurl.get())) {
7589 g_pi_manager->m_pCurl = 0;
7592 bool failed =
false;
7593 if (!g_pi_manager->HandleCurlThreadError(
7594 g_pi_manager->m_pCurlThread->SetURL(url, g_pi_manager->m_pCurl),
7595 g_pi_manager->m_pCurlThread, url))
7598 g_pi_manager->m_pCurl = g_pi_manager->m_pCurlThread->GetCurlSharedPtr();
7599 if (!g_pi_manager->HandleCurlThreadError(
7600 g_pi_manager->m_pCurlThread->SetOutputStream(
7601 new wxFileOutputStream(outputFile)),
7602 g_pi_manager->m_pCurlThread))
7606 g_pi_manager->m_download_evHandler = handler;
7607 g_pi_manager->m_downloadHandle = handle;
7609 wxCurlThreadError err = g_pi_manager->m_pCurlThread->Download();
7610 if (err != wxCTE_NO_ERROR) {
7611 g_pi_manager->HandleCurlThreadError(
7612 err, g_pi_manager->m_pCurlThread);
7613 g_pi_manager->m_pCurlThread->Abort();
7618 if (!failed)
return OCPN_DL_STARTED;
7620 if (g_pi_manager->m_pCurlThread) {
7621 if (g_pi_manager->m_pCurlThread->IsAlive())
7622 g_pi_manager->m_pCurlThread->Abort();
7623 if (g_pi_manager->m_pCurlThread->GetOutputStream())
7624 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
7625 wxDELETE(g_pi_manager->m_pCurlThread);
7626 g_pi_manager->m_download_evHandler = NULL;
7627 g_pi_manager->m_downloadHandle = NULL;
7628 return OCPN_DL_STARTED;
7630 g_pi_manager->m_pCurl = 0;
7631 return OCPN_DL_FAILED;
7634 return OCPN_DL_FAILED;
7638void OCPN_cancelDownloadFileBackground(
long handle) {
7641#ifdef __OCPN__ANDROID__
7642 cancelAndroidFileDownload(handle);
7643 finishAndroidFileDownload();
7644 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
7646 if (g_pi_manager->m_pCurlThread) {
7647 g_pi_manager->m_pCurlThread->Abort();
7648 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
7649 wxDELETE(g_pi_manager->m_pCurlThread);
7650 g_pi_manager->m_download_evHandler = NULL;
7651 g_pi_manager->m_downloadHandle = NULL;
7653 g_pi_manager->m_pCurl = 0;
7658_OCPN_DLStatus OCPN_postDataHttp(
const wxString &url,
7659 const wxString ¶meters, wxString &result,
7662#ifdef __OCPN__ANDROID__
7663 wxString lparms = parameters;
7664 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
7665 if (postResult.IsSameAs(_T(
"NOK")))
return OCPN_DL_FAILED;
7667 result = postResult;
7668 return OCPN_DL_NO_ERROR;
7670#elif defined(OCPN_USE_CURL)
7672 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
7673 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
7676 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
7677 return OCPN_DL_NO_ERROR;
7679 result = wxEmptyString;
7681 return OCPN_DL_FAILED;
7684 return OCPN_DL_FAILED;
7688bool OCPN_isOnline() {
7689#ifdef __OCPN__ANDROID__
7690 return androidCheckOnline();
7693#if !defined(__OCPN__ANDROID__) && defined(OCPN_USE_CURL)
7694 if (wxDateTime::GetTimeNow() >
7695 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
7697 get.Head(_T(
"http://yahoo.com/"));
7698 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
7700 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
7702 return g_pi_manager->m_last_online;
7708#if !defined(__OCPN__ANDROID__) && defined(OCPN_USE_CURL)
7709void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent &ev) {
7711 if (ev.IsSuccessful()) {
7712 event.setDLEventStatus(OCPN_DL_NO_ERROR);
7714 g_pi_manager->m_pCurl = 0;
7715 event.setDLEventStatus(OCPN_DL_FAILED);
7717 event.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
7718 event.setComplete(
true);
7720 if (m_download_evHandler) {
7721 m_download_evHandler->AddPendingEvent(event);
7722 m_download_evHandler = NULL;
7723 m_downloadHandle = NULL;
7726 if (m_pCurlThread) {
7727 m_pCurlThread->Wait();
7728 if (!m_pCurlThread->IsAborting()) {
7729 delete (m_pCurlThread->GetOutputStream());
7730 wxDELETE(m_pCurlThread);
7735void PlugInManager::OnCurlDownload(wxCurlDownloadEvent &ev) {
7737 event.setDLEventStatus(OCPN_DL_UNKNOWN);
7738 event.setDLEventCondition(OCPN_DL_EVENT_TYPE_PROGRESS);
7739 event.setTotal(ev.GetTotalBytes());
7740 event.setTransferred(ev.GetDownloadedBytes());
7741 event.setComplete(
false);
7743 if (m_download_evHandler) {
7744 m_download_evHandler->AddPendingEvent(event);
7748bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
7749 wxCurlBaseThread *p,
7750 const wxString &url) {
7752 case wxCTE_NO_ERROR:
7755 case wxCTE_NO_RESOURCE:
7757 wxS(
"Insufficient resources for correct execution of the program."));
7760 case wxCTE_ALREADY_RUNNING:
7764 case wxCTE_INVALID_PROTOCOL:
7765 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
7769 case wxCTE_NO_VALID_STREAM:
7776 case wxCTE_CURL_ERROR: {
7777 wxString err = wxS(
"unknown");
7778 if (p->GetCurlSession())
7780 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
7781 wxLogError(wxS(
"Network error: %s"), err.c_str());
7786 if (p->IsAlive()) p->Abort();
7793bool LaunchDefaultBrowser_Plugin(wxString url) {
7794 if (g_Platform) g_Platform->platformLaunchDefaultBrowser(url);
7801void PlugInAISDrawGL(wxGLCanvas *glcanvas,
const PlugIn_ViewPort &vp) {
7802 ViewPort ocpn_vp = CreateCompatibleViewport(vp);
7806 AISDraw(dc, ocpn_vp, NULL);
7809bool PlugInSetFontColor(
const wxString TextElement,
const wxColour color) {
7810 return FontMgr::Get().SetFontColor(TextElement, color);
7815double PlugInGetDisplaySizeMM() {
return g_Platform->GetDisplaySizeMM(); }
7817wxFont *FindOrCreateFont_PlugIn(
int point_size, wxFontFamily family,
7818 wxFontStyle style, wxFontWeight weight,
7819 bool underline,
const wxString &facename,
7820 wxFontEncoding encoding) {
7821 return FontMgr::Get().FindOrCreateFont(point_size, family, style, weight,
7822 underline, facename, encoding);
7825int PluginGetMinAvailableGshhgQuality() {
7826 return gFrame->GetPrimaryCanvas()->GetMinAvailableGshhgQuality();
7828int PluginGetMaxAvailableGshhgQuality() {
7829 return gFrame->GetPrimaryCanvas()->GetMaxAvailableGshhgQuality();
7833void PlugInHandleAutopilotRoute(
bool enable) {
7834 g_bPluginHandleAutopilotRoute = enable;
7838wxString GetSelectedWaypointGUID_Plugin() {
7840 if (cc && cc->GetSelectedRoutePoint()) {
7841 return cc->GetSelectedRoutePoint()->m_GUID;
7843 return wxEmptyString;
7846wxString GetSelectedRouteGUID_Plugin() {
7848 if (cc && cc->GetSelectedRoute()) {
7849 return cc->GetSelectedRoute()->m_GUID;
7851 return wxEmptyString;
7854wxString GetSelectedTrackGUID_Plugin() {
7856 if (cc && cc->GetSelectedTrack()) {
7857 return cc->GetSelectedTrack()->m_GUID;
7859 return wxEmptyString;
7862std::unique_ptr<PlugIn_Waypoint> GetWaypoint_Plugin(
const wxString &GUID) {
7864 GetSingleWaypoint(GUID, w.get());
7868std::unique_ptr<PlugIn_Route> GetRoute_Plugin(
const wxString &GUID) {
7869 std::unique_ptr<PlugIn_Route> r;
7870 Route *route = g_pRouteMan->FindRouteByGUID(GUID);
7871 if (route ==
nullptr)
return r;
7878 wxRoutePointListNode *node = route->pRoutePointList->GetFirst();
7881 src_wp = node->GetData();
7884 PlugInFromRoutePoint(dst_wp, src_wp);
7886 dst_route->pWaypointList->Append(dst_wp);
7888 node = node->GetNext();
7890 dst_route->m_NameString = route->m_RouteNameString;
7891 dst_route->m_StartString = route->m_RouteStartString;
7892 dst_route->m_EndString = route->m_RouteEndString;
7893 dst_route->m_GUID = route->m_GUID;
7898std::unique_ptr<PlugIn_Track> GetTrack_Plugin(
const wxString &GUID) {
7899 std::unique_ptr<PlugIn_Track> t;
7901 Track *pTrack = g_pRouteMan->FindTrackByGUID(GUID);
7902 if (!pTrack)
return t;
7904 std::unique_ptr<PlugIn_Track> tk =
7907 dst_track->m_NameString = pTrack->GetName();
7908 dst_track->m_StartString = pTrack->m_TrackStartString;
7909 dst_track->m_EndString = pTrack->m_TrackEndString;
7910 dst_track->m_GUID = pTrack->m_GUID;
7912 for (
int i = 0; i < pTrack->GetnPoints(); i++) {
7917 dst_wp->m_lat = ptp->m_lat;
7918 dst_wp->m_lon = ptp->m_lon;
7919 dst_wp->m_CreateTime = ptp->GetCreateTime();
7921 dst_track->pWaypointList->Append(dst_wp);
7927wxWindow *PluginGetFocusCanvas() {
return g_focusCanvas; }
7929wxWindow *PluginGetOverlayRenderCanvas() {
7931 return g_overlayCanvas;
7935void CanvasJumpToPosition(wxWindow *canvas,
double lat,
double lon,
7938 if (oCanvas) gFrame->JumpToPosition(oCanvas, lat, lon,
scale);
7941bool ShuttingDown(
void) {
return g_bquiting; }
7943wxWindow *GetCanvasUnderMouse(
void) {
return gFrame->GetCanvasUnderMouse(); }
7945int GetCanvasIndexUnderMouse(
void) {
7946 ChartCanvas *l_canvas = gFrame->GetCanvasUnderMouse();
7948 for (
unsigned int i = 0; i < g_canvasArray.GetCount(); ++i) {
7949 if (l_canvas == g_canvasArray[i])
return i;
7966wxWindow *GetCanvasByIndex(
int canvasIndex) {
7967 if (g_canvasConfig == 0)
7968 return gFrame->GetPrimaryCanvas();
7970 if ((canvasIndex >= 0) && g_canvasArray[canvasIndex]) {
7971 return g_canvasArray[canvasIndex];
7977bool CheckMUIEdgePan_PlugIn(
int x,
int y,
bool dragging,
int margin,
int delta,
7979 if (g_canvasConfig == 0)
7980 return gFrame->GetPrimaryCanvas()->CheckEdgePan(x, y, dragging, margin,
7983 if ((canvasIndex >= 0) && g_canvasArray[canvasIndex]) {
7984 return g_canvasArray[canvasIndex]->CheckEdgePan(x, y, dragging, margin,
7992void SetMUICursor_PlugIn(wxCursor *pCursor,
int canvasIndex) {
7993 if (g_canvasConfig == 0)
7994 gFrame->GetPrimaryCanvas()->pPlugIn_Cursor = pCursor;
7996 if ((canvasIndex >= 0) && g_canvasArray[canvasIndex]) {
7997 g_canvasArray[canvasIndex]->pPlugIn_Cursor = pCursor;
8002int GetCanvasCount() {
8003 if (g_canvasConfig == 1)
return 2;
8008int GetLatLonFormat() {
return g_iSDMMFormat; }
8010wxRect GetMasterToolbarRect() {
8012 return g_MainToolbar->GetRect();
8014 return wxRect(0, 0, 1, 1);
8021 g_pRouteMan->ZeroCurrentXTEToActivePoint();
8025ListOfPI_S57Obj *PlugInManager::GetLightsObjRuleListVisibleAtLatLon(
8027 ListOfPI_S57Obj *list = NULL;
8033 list = picbgl->GetLightsObjRuleListVisibleAtLatLon(zlat, zlon, &pi_vp);
8041 list = picbx->GetLightsObjRuleListVisibleAtLatLon(zlat, zlon, &pi_vp);
8051WX_DEFINE_LIST(Plugin_WaypointExList);
8054PlugIn_Waypoint_Ex::PlugIn_Waypoint_Ex() { InitDefaults(); }
8056PlugIn_Waypoint_Ex::PlugIn_Waypoint_Ex(
8057 double lat,
double lon,
const wxString &icon_ident,
const wxString &wp_name,
8058 const wxString &GUID,
const double ScaMin,
const bool bNameVisible,
8059 const int nRangeRings,
const double RangeDistance,
8060 const wxColor RangeColor) {
8063 wxDateTime now = wxDateTime::Now();
8064 m_CreateTime = now.ToUTC();
8065 m_HyperlinkList = NULL;
8069 IconName = icon_ident;
8070 m_MarkName = wp_name;
8073 IsNameVisible = bNameVisible;
8074 nrange_rings = nRangeRings;
8075 RangeRingSpace = RangeDistance;
8076 RangeRingColor = RangeColor;
8079void PlugIn_Waypoint_Ex::InitDefaults() {
8080 m_HyperlinkList = NULL;
8082 b_useScamin =
false;
8085 IsNameVisible =
false;
8087 RangeRingColor = *wxBLACK;
8088 m_CreateTime = wxDateTime::Now();
8094bool PlugIn_Waypoint_Ex::GetFSStatus() {
8095 RoutePoint *prp = pWayPointMan->FindRoutePointByGUID(m_GUID);
8096 if (!prp)
return false;
8098 if (prp->m_bIsInRoute && !prp->IsShared())
return false;
8103int PlugIn_Waypoint_Ex::GetRouteMembershipCount() {
8105 RoutePoint *pWP = pWayPointMan->FindRoutePointByGUID(m_GUID);
8109 wxRouteListNode *node = pRouteList->GetFirst();
8111 Route *proute = node->GetData();
8112 wxRoutePointListNode *pnode = (proute->pRoutePointList)->GetFirst();
8115 if (prp == pWP) nCount++;
8116 pnode = pnode->GetNext();
8119 node = node->GetNext();
8125PlugIn_Waypoint_Ex::~PlugIn_Waypoint_Ex() {}
8128PlugIn_Route_Ex::PlugIn_Route_Ex(
void) {
8129 pWaypointList =
new Plugin_WaypointExList;
8132PlugIn_Route_Ex::~PlugIn_Route_Ex(
void) {
8133 pWaypointList->DeleteContents(
false);
8134 pWaypointList->Clear();
8136 delete pWaypointList;
8144 dst->m_lat = src->m_lat;
8145 dst->m_lon = src->m_lon;
8146 dst->IconName = src->GetIconName();
8147 dst->m_MarkName = src->GetName();
8148 dst->m_MarkDescription = src->GetDescription();
8149 dst->IconDescription = pWayPointMan->GetIconDescription(src->GetIconName());
8150 dst->IsVisible = src->IsVisible();
8151 dst->m_CreateTime = src->GetCreateTime();
8152 dst->m_GUID = src->m_GUID;
8155 if (src->m_HyperlinkList ==
nullptr)
return;
8157 delete dst->m_HyperlinkList;
8158 dst->m_HyperlinkList =
nullptr;
8160 if (src->m_HyperlinkList->GetCount() > 0) {
8161 dst->m_HyperlinkList =
new Plugin_HyperlinkList;
8163 wxHyperlinkListNode *linknode = src->m_HyperlinkList->GetFirst();
8168 h->DescrText = link->DescrText;
8169 h->Link = link->Link;
8170 h->Type = link->LType;
8172 dst->m_HyperlinkList->Append(h);
8174 linknode = linknode->GetNext();
8179 dst->nrange_rings = src->m_iWaypointRangeRingsNumber;
8180 dst->RangeRingSpace = src->m_fWaypointRangeRingsStep;
8181 dst->RangeRingColor = src->m_wxcWaypointRangeRingsColour;
8184 dst->IsNameVisible = src->m_bShowName;
8185 dst->scamin = src->GetScaMin();
8186 dst->b_useScamin = src->GetUseSca();
8187 dst->IsActive = src->m_bIsActive;
8190static void cloneHyperlinkListEx(
RoutePoint *dst,
8193 if (src->m_HyperlinkList ==
nullptr)
return;
8195 if (src->m_HyperlinkList->GetCount() > 0) {
8196 wxPlugin_HyperlinkListNode *linknode = src->m_HyperlinkList->GetFirst();
8201 h->DescrText = link->DescrText;
8202 h->Link = link->Link;
8203 h->LType = link->Type;
8205 dst->m_HyperlinkList->Append(h);
8207 linknode = linknode->GetNext();
8214 src->m_MarkName, src->m_GUID);
8216 pWP->m_bIsolatedMark =
true;
8218 cloneHyperlinkListEx(pWP, src);
8220 pWP->m_MarkDescription = src->m_MarkDescription;
8222 if (src->m_CreateTime.IsValid())
8223 pWP->SetCreateTime(src->m_CreateTime);
8225 wxDateTime dtnow(wxDateTime::Now());
8226 pWP->SetCreateTime(dtnow);
8229 pWP->m_btemp = (b_permanent ==
false);
8232 pWP->SetIconName(src->IconName);
8233 pWP->SetWaypointRangeRingsNumber(src->nrange_rings);
8234 pWP->SetWaypointRangeRingsStep(src->RangeRingSpace);
8235 pWP->SetWaypointRangeRingsColour(src->RangeRingColor);
8236 pWP->SetScaMin(src->scamin);
8237 pWP->SetUseSca(src->b_useScamin);
8238 pWP->SetNameShown(src->IsNameVisible);
8239 pWP->SetVisible(src->IsVisible);
8245 RoutePoint *prp = pWayPointMan->FindRoutePointByGUID(GUID);
8247 if (!prp)
return false;
8249 PlugInExFromRoutePoint(pwaypoint, prp);
8259 bool b_unique =
true;
8260 wxRoutePointListNode *prpnode = pWayPointMan->GetWaypointList()->GetFirst();
8264 if (prp->m_GUID == pwaypointex->m_GUID) {
8268 prpnode = prpnode->GetNext();
8271 if (!b_unique)
return false;
8273 RoutePoint *pWP = CreateNewPoint(pwaypointex, b_permanent);
8275 pWP->SetShowWaypointRangeRings(pwaypointex->nrange_rings > 0);
8277 pSelect->AddSelectableRoutePoint(pWP->m_lat, pWP->m_lon, pWP);
8278 if (b_permanent) pConfig->AddNewWayPoint(pWP, -1);
8280 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
8281 pRouteManagerDialog->UpdateWptListCtrl();
8288 bool b_found =
false;
8289 RoutePoint *prp = pWayPointMan->FindRoutePointByGUID(pwaypoint->m_GUID);
8291 if (prp) b_found =
true;
8294 double lat_save = prp->m_lat;
8295 double lon_save = prp->m_lon;
8297 prp->m_lat = pwaypoint->m_lat;
8298 prp->m_lon = pwaypoint->m_lon;
8299 prp->SetIconName(pwaypoint->IconName);
8300 prp->SetName(pwaypoint->m_MarkName);
8301 prp->m_MarkDescription = pwaypoint->m_MarkDescription;
8302 prp->SetVisible(pwaypoint->IsVisible);
8303 if (pwaypoint->m_CreateTime.IsValid())
8304 prp->SetCreateTime(pwaypoint->m_CreateTime);
8308 if (pwaypoint->m_HyperlinkList) {
8309 prp->m_HyperlinkList->Clear();
8310 if (pwaypoint->m_HyperlinkList->GetCount() > 0) {
8311 wxPlugin_HyperlinkListNode *linknode =
8312 pwaypoint->m_HyperlinkList->GetFirst();
8317 h->DescrText = link->DescrText;
8318 h->Link = link->Link;
8319 h->LType = link->Type;
8321 prp->m_HyperlinkList->Append(h);
8323 linknode = linknode->GetNext();
8329 prp->SetWaypointRangeRingsNumber(pwaypoint->nrange_rings);
8330 prp->SetWaypointRangeRingsStep(pwaypoint->RangeRingSpace);
8331 prp->SetWaypointRangeRingsColour(pwaypoint->RangeRingColor);
8332 prp->SetScaMin(pwaypoint->scamin);
8333 prp->SetUseSca(pwaypoint->b_useScamin);
8334 prp->SetNameShown(pwaypoint->IsNameVisible);
8336 prp->SetShowWaypointRangeRings(pwaypoint->nrange_rings > 0);
8338 if (prp) prp->ReLoadIcon();
8340 auto canvas = gFrame->GetPrimaryCanvas();
8341 SelectCtx ctx(canvas->m_bShowNavobjects, canvas->GetCanvasTrueScale());
8342 SelectItem *pFind = pSelect->FindSelection(ctx, lat_save, lon_save,
8343 SELTYPE_ROUTEPOINT);
8345 pFind->m_slat = pwaypoint->m_lat;
8346 pFind->m_slon = pwaypoint->m_lon;
8349 if (!prp->m_btemp) pConfig->UpdateWayPoint(prp);
8351 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
8352 pRouteManagerDialog->UpdateWptListCtrl();
8364 wxDateTime plannedDeparture;
8366 wxPlugin_WaypointExListNode *pwpnode = proute->pWaypointList->GetFirst();
8368 pwaypointex = pwpnode->GetData();
8370 pWP = pWayPointMan->FindRoutePointByGUID(pwaypointex->m_GUID);
8372 pWP = CreateNewPoint(pwaypointex, b_permanent);
8373 pWP->m_bIsolatedMark =
false;
8376 route->AddPoint(pWP);
8378 pSelect->AddSelectableRoutePoint(pWP->m_lat, pWP->m_lon, pWP);
8381 pSelect->AddSelectableRouteSegment(pWP_src->m_lat, pWP_src->m_lon,
8382 pWP->m_lat, pWP->m_lon, pWP_src, pWP,
8385 plannedDeparture = pwaypointex->m_CreateTime;
8389 pwpnode = pwpnode->GetNext();
8392 route->m_PlannedDeparture = plannedDeparture;
8394 route->m_RouteNameString = proute->m_NameString;
8395 route->m_RouteStartString = proute->m_StartString;
8396 route->m_RouteEndString = proute->m_EndString;
8397 if (!proute->m_GUID.IsEmpty()) {
8398 route->m_GUID = proute->m_GUID;
8400 route->m_btemp = (b_permanent ==
false);
8402 pRouteList->Append(route);
8404 if (b_permanent) pConfig->AddNewRoute(route);
8406 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
8407 pRouteManagerDialog->UpdateRouteListCtrl();
8413 bool b_found =
false;
8416 Route *pRoute = g_pRouteMan->FindRouteByGUID(proute->m_GUID);
8417 if (pRoute) b_found =
true;
8420 bool b_permanent = (pRoute->m_btemp ==
false);
8421 g_pRouteMan->
DeleteRoute(pRoute, NavObjectChanges::getInstance());
8423 b_found = AddPlugInRouteEx(proute, b_permanent);
8437std::unique_ptr<PlugIn_Waypoint_Ex> GetWaypointEx_Plugin(
const wxString &GUID) {
8439 GetSingleWaypointEx(GUID, w.get());
8443std::unique_ptr<PlugIn_Route_Ex> GetRouteEx_Plugin(
const wxString &GUID) {
8444 std::unique_ptr<PlugIn_Route_Ex> r;
8445 Route *route = g_pRouteMan->FindRouteByGUID(GUID);
8446 if (route ==
nullptr)
return r;
8453 wxRoutePointListNode *node = route->pRoutePointList->GetFirst();
8456 src_wp = node->GetData();
8459 PlugInExFromRoutePoint(dst_wp, src_wp);
8461 dst_route->pWaypointList->Append(dst_wp);
8463 node = node->GetNext();
8465 dst_route->m_NameString = route->m_RouteNameString;
8466 dst_route->m_StartString = route->m_RouteStartString;
8467 dst_route->m_EndString = route->m_RouteEndString;
8468 dst_route->m_GUID = route->m_GUID;
8469 dst_route->m_isActive = g_pRouteMan->GetpActiveRoute() == route;
8474wxString GetActiveWaypointGUID(
8476 RoutePoint *rp = g_pRouteMan->GetpActivePoint();
8478 return wxEmptyString;
8483wxString GetActiveRouteGUID(
8485 Route *rt = g_pRouteMan->GetpActiveRoute();
8487 return wxEmptyString;
8493int GetGlobalWatchdogTimoutSeconds(){
8494 return gps_watchdog_timeout_ticks;
8498std::vector<std::string> GetPriorityMaps() {
8499 MyApp& app = wxGetApp();
8500 return (app.m_comm_bridge.GetPriorityMaps());
8503std::vector<std::string> GetActivePriorityIdentifiers() {
8504 std::vector<std::string> result;
8506 MyApp& app = wxGetApp();
8508 std::string
id = app.m_comm_bridge.GetPriorityContainer(
"position").active_source;
8509 result.push_back(
id);
8510 id = app.m_comm_bridge.GetPriorityContainer(
"velocity").active_source;
8511 result.push_back(
id);
8512 id = app.m_comm_bridge.GetPriorityContainer(
"heading").active_source;
8513 result.push_back(
id);
8514 id = app.m_comm_bridge.GetPriorityContainer(
"variation").active_source;
8515 result.push_back(
id);
8516 id = app.m_comm_bridge.GetPriorityContainer(
"satellites").active_source;
8517 result.push_back(
id);
8522double OCPN_GetDisplayContentScaleFactor() {
8524#if defined(__WXOSX__) || defined(__WXGTK3__)
8527 rv = gFrame->GetContentScaleFactor();
8531double OCPN_GetWinDIPScaleFactor() {
8532 double scaler = 1.0;
8535 scaler = (double)(gFrame->ToDIP(100))/100.;
8542std::vector<DriverHandle> GetActiveDrivers() {
8544 std::vector<DriverHandle> result;
8546 auto& registry = CommDriverRegistry::GetInstance();
8547 const std::vector<std::shared_ptr<AbstractCommDriver>>& drivers = registry.GetDrivers();
8549 for (
auto& driver : drivers)
8550 result.push_back(driver->Key());
8556const std::unordered_map<std::string, std::string> GetAttributes(DriverHandle handle) {
8557 auto& registry = CommDriverRegistry::GetInstance();
8558 auto drivers = registry.GetDrivers();
8559 auto func = [handle](
const DriverPtr d) {
return d->Key() == handle; };
8560 auto found = std::find_if(drivers.begin(), drivers.end(), func);
8562 std::unordered_map<std::string, std::string> rv;
8563 if (found == drivers.end()){
8567 return found->get()->GetAttributes();
8570CommDriverResult WriteCommDriverN2K( DriverHandle handle,
int PGN,
8571 int destinationCANAddress,
int priority,
8572 const std::shared_ptr <std::vector<uint8_t>> &payload){
8578 auto& registry = CommDriverRegistry::GetInstance();
8579 auto drivers = registry.GetDrivers();
8580 auto func = [handle](
const DriverPtr d) {
return d->Key() == handle; };
8581 auto driver = std::find_if(drivers.begin(), drivers.end(), func);
8583 if (driver == drivers.end()){
8584 return RESULT_COMM_INVALID_HANDLE;
8587 auto dest_addr = std::make_shared<const NavAddr2000>(driver->get()->iface, destinationCANAddress);
8589 const std::vector<uint8_t> load;
8590 size_t data_len = payload.get()->size();
8592 auto msg = std::make_shared<const Nmea2000Msg>(_PGN, *(payload), dest_addr);
8594 bool result = driver->get()->SendMessage(msg, dest_addr);
8596 return RESULT_COMM_NO_ERROR;
8599CommDriverResult RegisterTXPGNs( DriverHandle handle, std::vector<int> &pgn_list) {
8600 if (!pgn_list.size())
8601 return RESULT_COMM_INVALID_PARMS;
8604 auto& registry = CommDriverRegistry::GetInstance();
8605 auto drivers = registry.GetDrivers();
8606 auto func = [handle](
const DriverPtr d) {
return d->Key() == handle; };
8607 auto driver = std::find_if(drivers.begin(), drivers.end(), func);
8609 if (driver == drivers.end()){
8610 return RESULT_COMM_INVALID_HANDLE;
8613 std::shared_ptr<CommDriverN2K> dn2k = std::dynamic_pointer_cast<CommDriverN2K>(*driver);
8616 for (
size_t i=0 ; i < pgn_list.size() ; i++){
8620 while (nTry && iresult < 0) {
8621 iresult = dn2k->SetTXPGN( pgn_list[i]);
8627 printf(
"####TXPGN Fail\n");
8628 return RESULT_COMM_REGISTER_PGN_ERROR;
8632 printf(
"----TXPGN PASS nloop: %d \n", nloop);
8633 return RESULT_COMM_NO_ERROR;
EventVar plugin_msg
A JSON message should be sent.
Handle messages for blacklisted plugins.
Modal dialog, displays settings for plugin catalog.
const std::vector< DriverPtr > & GetDrivers()
Wrapper for configuration variables which lives in a wxBaseConfig object.
Wrapper for global variable, supports notification events when value changes.
Add progress and final message dialogs to the basic Downloader.
static std::string MessageKey(const char *type="ALL")
Return key which should be used to listen to given message type.
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listener on changes in key.
Adds a std::shared<void> element to wxCommandEvent.
SemanticVersion GetVersion()
Return version from plugin API.
const std::vector< PluginMetadata > getInstalled()
Return list of all installed plugins.
static std::string fileListPath(std::string name)
Return path to installation manifest for given plugin.
static std::string versionPath(std::string name)
Return path to file containing version for given plugin.
bool uninstall(const std::string plugin)
Uninstall an installed plugin.
static bool isCompatible(const PluginMetadata &metadata, const char *os=PKG_TARGET, const char *os_version=PKG_TARGET_VERSION)
Return true if given plugin is loadable on given os/version.
void ReloadPluginPanels()
Complete reload from plugins array.
std::vector< std::string > Libdirs()
List of directories from which we load plugins.
std::vector< std::string > Bindirs()
'List of directories for plugin binary helpers.
static PluginPaths * getInstance()
Return the singleton instance.
bool DeleteRoute(Route *pRoute, NavObjectChanges *nav_obj_changes)
EventVar json_msg
Notified with message targeting all plugins.
EventVar json_leg_info
Notified with a shared_ptr<ActiveLegDat>, leg info to all plugins.
A parsed, raw SignalK message.
Modal dialog, displays available updates (possibly just one) and lets user select and eventually conf...
virtual bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvasIndex, int priority=-1)
Render plugin overlay over chart canvas in non-OpenGL mode.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex, int priority=-1)
Render plugin overlay over chart canvas in OpenGL mode.
std::string lookup_tarball(const char *uri)
Get path to tarball in cache for given filename.
bool store_metadata(const char *path)
Store metadata in metadata cache, return success/fail.
bool store_tarball(const char *path, const char *basename)
Store a tarball in tarball cache, return success/fail.
Versions uses a modified semantic versioning scheme: major.minor.revision.post-tag+build.
static SemanticVersion parse(std::string s)
Parse a version string, sets major == -1 on errors.
std::string to_string()
Return printable representation.