39#include <unordered_map>
47#if defined(__linux__) && !defined(__ANDROID__)
53#include <wx/filename.h>
54#include <wx/aui/aui.h>
55#include <wx/platinfo.h>
56#include <wx/popupwin.h>
57#include <wx/progdlg.h>
58#include <wx/statline.h>
59#include <wx/tokenzr.h>
60#include <wx/tooltip.h>
62#include <wx/hashset.h>
63#include <wx/hashmap.h>
64#include <wx/jsonval.h>
65#include <wx/jsonreader.h>
67#include <wx/zipstrm.h>
68#include <wx/zstream.h>
69#include <wx/tarstrm.h>
70#include <wx/textwrapper.h>
77#include <archive_entry.h>
78typedef __LA_INT64_T la_int64_t;
88#include "model/ais_target_data.h"
92#include "model/comm_drv_n2k.h"
95#include "model/comm_vars.h"
96#include "model/config_vars.h"
97#include "model/datetime.h"
98#include "model/downloader.h"
99#include "model/georef.h"
100#include "model/json_event.h"
102#include "model/multiplexer.h"
103#include "model/nav_object_database.h"
104#include "model/navutil_base.h"
106#include "model/plugin_cache.h"
108#include "model/plugin_handler.h"
110#include "model/plugin_paths.h"
111#include "model/route.h"
112#include "model/routeman.h"
113#include "model/safe_mode.h"
114#include "model/select.h"
115#include "model/semantic_vers.h"
116#include "model/track.h"
119#include "canvasMenu.h"
120#include "cat_settings.h"
121#include "chartbase.h"
126#include "download_mgr.h"
130#include "model/ais_decoder.h"
133#include "observable_confvar.h"
134#include "observable_globvar.h"
136#include "OCPN_AUIManager.h"
138#include "ocpn_frame.h"
139#include "ocpn_pixel.h"
140#include "OCPNPlatform.h"
141#include "OCPNRegion.h"
144#include "pluginmanager.h"
145#include "routemanagerdialog.h"
146#include "routeman_gui.h"
149#include "SoundFactory.h"
151#include "svg_utils.h"
152#include "SystemCmdSound.h"
154#include "update_mgr.h"
155#include "waypointman_gui.h"
159#include "androidUTIL.h"
163#include "glChartCanvas.h"
168#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
169extern wxLocale* plocale_def_lang;
178extern bool g_bShowChartBar;
182extern RouteList* pRouteList;
183extern std::vector<Track*> g_TrackList;
185extern s52plib* ps52plib;
186extern wxString ChartListFileName;
188extern ColorScheme global_color_scheme;
189extern wxArrayString g_locale_catalog_array;
190extern int g_GUIScaleFactor;
191extern int g_ChartScaleFactor;
192extern wxString g_locale;
195extern int g_chart_zoom_modifier_raster;
196extern int g_chart_zoom_modifier_vector;
197extern double g_display_size_mm;
198extern bool g_bopengl;
200extern ChartGroupArray* g_pGroupArray;
201extern unsigned int g_canvasConfig;
203extern wxString g_CmdSoundString;
205extern unsigned int gs_plib_flags;
208extern bool g_bquiting;
210WX_DEFINE_ARRAY_PTR(
ChartCanvas*, arrayofCanvasPtr);
211extern arrayofCanvasPtr g_canvasArray;
213void NotifySetupOptionsPlugin(
const PlugInData* pic);
215enum { CurlThreadId = wxID_HIGHEST + 1 };
217#include <wx/listimpl.cpp>
218WX_DEFINE_LIST(Plugin_WaypointList);
219WX_DEFINE_LIST(Plugin_HyperlinkList);
224static void SendAisJsonMessage(std::shared_ptr<const AisTargetData> pTarget) {
226 if (!GetJSONMessageTargetCount())
return;
231 wxLongLong t = ::wxGetLocalTimeMillis();
233 jMsg[wxS(
"Source")] = wxS(
"AisDecoder");
234 jMsg[wxT(
"Type")] = wxT(
"Information");
235 jMsg[wxT(
"Msg")] = wxS(
"AIS Target");
236 jMsg[wxT(
"MsgId")] = t.GetValue();
237 jMsg[wxS(
"lat")] = pTarget->Lat;
238 jMsg[wxS(
"lon")] = pTarget->Lon;
239 jMsg[wxS(
"sog")] = pTarget->SOG;
240 jMsg[wxS(
"cog")] = pTarget->COG;
241 jMsg[wxS(
"hdg")] = pTarget->HDG;
242 jMsg[wxS(
"mmsi")] = pTarget->MMSI;
243 jMsg[wxS(
"class")] = pTarget->Class;
244 jMsg[wxS(
"ownship")] = pTarget->b_OwnShip;
245 jMsg[wxS(
"active")] = pTarget->b_active;
246 jMsg[wxS(
"lost")] = pTarget->b_lost;
247 wxString l_ShipName = wxString::FromUTF8(pTarget->ShipName);
248 for (
size_t i = 0; i < l_ShipName.Len(); i++) {
249 if (l_ShipName.GetChar(i) ==
'@') l_ShipName.SetChar(i,
'\n');
251 jMsg[wxS(
"shipname")] = l_ShipName;
252 wxString l_CallSign = wxString::FromUTF8(pTarget->CallSign);
253 for (
size_t i = 0; i < l_CallSign.Len(); i++) {
254 if (l_CallSign.GetChar(i) ==
'@') l_CallSign.SetChar(i,
'\n');
256 jMsg[wxS(
"callsign")] = l_CallSign;
257 jMsg[wxS(
"removed")] = pTarget->b_removed;
258 SendJSONMessageToAllPlugins(wxT(
"AIS"), jMsg);
262 return (*p1)->Key().compare((*p2)->Key());
266 auto version = metadata.version;
268 if (version[0] ==
'v') version = version.substr(1);
273 auto imported_version = ParseVersion(metadata);
274 for (
auto& md :
PluginHandler::getInstance()->getAvailable()) {
275 if (md.name != metadata.name)
continue;
276 if (md.is_imported)
continue;
277 if (!PluginHandler::getInstance()->isCompatible(md))
continue;
278 if (ParseVersion(md) >= imported_version)
return true;
289 void message(
const std::string& message) {
291 m_deferred_messages.push_back(message);
296 void show_deferred_messages() {
297 for (
auto m : m_deferred_messages) show_msg(m);
304 void show_msg(wxString msg) {
305 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
306 wxICON_INFORMATION | wxOK, 10);
310 std::vector<wxString> m_deferred_messages;
317 Wrap(win, text, widthMax);
319 wxString
const& GetWrapped()
const {
return m_wrapped; }
320 int const GetLineCount()
const {
return m_lineCount; }
321 wxArrayString GetLineArray() {
return m_array; }
324 virtual void OnOutputLine(
const wxString& line) {
328 virtual void OnNewLine() {
336 wxArrayString m_array;
340 template <
typename T>
341 std::size_t operator()(T t)
const {
342 return static_cast<std::size_t
>(t);
349 return _(
"Plugin is a standard system plugin");
351 return _(
"Plugin is managed by OpenCPN");
353 return _(
"Plugin is not managed by OpenCPN");
356 case PluginStatus::Unknown:
357 return _(
"Plugin status unknown");
358 case PluginStatus::LegacyUpdateAvailable:
359 return _(
"Update to managed Plugin is available");
360 case PluginStatus::ManagedInstallAvailable:
361 return _(
"New managed Plugin installation available");
362 case PluginStatus::ManagedInstalledUpdateAvailable:
363 return _(
"Update to installed Plugin is available");
364 case PluginStatus::ManagedInstalledCurrentVersion:
365 return _(
"Plugin is latest available");
366 case PluginStatus::Imported:
367 return _(
"Plugin is imported");
368 case PluginStatus::ManagedInstalledDowngradeAvailable:
370 case PluginStatus::PendingListRemoval:
377static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
383 {PluginStatus::Unknown,
"emblem-unmanaged.svg"},
384 {PluginStatus::LegacyUpdateAvailable,
"emblem-legacy-update.svg"},
385 {PluginStatus::ManagedInstallAvailable,
"emblem-download.svg"},
386 {PluginStatus::ManagedInstalledUpdateAvailable,
387 "emblem-legacy-update.svg"},
388 {PluginStatus::ManagedInstalledCurrentVersion,
"emblem-default.svg"},
389 {PluginStatus::ManagedInstalledDowngradeAvailable,
390 "emblem-default.svg"},
391 {PluginStatus::PendingListRemoval,
"emblem-default.svg"},
392 {PluginStatus::Imported,
"emblem-default.svg"}});
394static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
395 literalstatus_by_status(
400 {PluginStatus::Unknown,
"Unknown"},
401 {PluginStatus::LegacyUpdateAvailable,
"LegacyUpdateAvailable"},
402 {PluginStatus::ManagedInstallAvailable,
"ManagedInstallAvailable"},
403 {PluginStatus::ManagedInstalledUpdateAvailable,
404 "ManagedInstalledUpdateAvailable"},
405 {PluginStatus::ManagedInstalledCurrentVersion,
406 "ManagedInstalledCurrentVersion"},
407 {PluginStatus::ManagedInstalledDowngradeAvailable,
408 "ManagedInstalledDowngradeAvailable"},
409 {PluginStatus::PendingListRemoval,
"PendingListRemoval"},
410 {PluginStatus::Imported,
"Imported"}
418static std::vector<PluginMetadata> getCompatiblePlugins() {
420 struct metadata_compare {
423 return lhs.key() < rhs.key();
427 std::vector<PluginMetadata> returnArray;
429 std::set<PluginMetadata, metadata_compare> unique_plugins;
430 for (
auto plugin :
PluginHandler::getInstance()->getAvailable()) {
431 unique_plugins.insert(plugin);
433 for (
auto plugin : unique_plugins) {
435 returnArray.push_back(plugin);
452 std::string installed;
454 if (path ==
"" || !wxFileName::IsFileReadable(path)) {
457 std::ifstream stream;
458 stream.open(path, std::ifstream::in);
467static std::vector<PluginMetadata> getUpdates(
const char* name) {
468 auto updates = getCompatiblePlugins();
470 std::remove_if(updates.begin(), updates.end(),
474 auto inst_vers = getInstalledVersion(name);
475 if (inst_vers.major == -1) {
480 updates.erase(std::remove_if(updates.begin(), updates.end(),
482 return metadata_version(m) == inst_vers;
489static void gui_uninstall(
const PlugInData* pic,
const char* plugin) {
490 g_Platform->ShowBusySpinner();
491 PluginLoader::GetInstance()->DeactivatePlugIn(*pic);
493 PluginLoader::GetInstance()->UpdatePlugIns();
495 wxLogMessage(
"Uninstalling %s", plugin);
496 PluginHandler::getInstance()->
uninstall(plugin);
497 PluginLoader::GetInstance()->UpdatePlugIns();
498 g_Platform->HideBusySpinner();
501static bool LoadAllPlugIns(
bool load_enabled,
bool keep_orphans =
false) {
502 g_Platform->ShowBusySpinner();
504 PluginLoader::GetInstance()->
LoadAllPlugIns(load_enabled, keep_orphans);
505 g_Platform->HideBusySpinner();
510static void UninstallPlugin(
const std::string& name) {
511 auto handler = PluginHandler::getInstance();
512 auto loader = PluginLoader::GetInstance();
513 auto finder = [name](
const PluginMetadata pm) {
return pm.name == name; };
514 const auto& installed = handler->getInstalled();
515 auto found = std::find_if(installed.begin(), installed.end(), finder);
516 if (found != installed.end()) {
517 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
518 auto const& item = loader->GetPlugInArray()->Item(i);
519 if (item->m_common_name.ToStdString() == name) {
520 DEBUG_LOG <<
"Unloading plugin: " << name;
521 loader->UnLoadPlugIn(i);
525 handler->uninstall(found->name);
526 DEBUG_LOG <<
"Uninstalling: " << found->name;
531 bool uninstall,
const char* name = 0,
532 bool b_forceEnable =
false) {
534 const char* plugin = name == 0 ? pic->
m_common_name.mb_str().data() : name;
535 auto updates = getUpdates(plugin);
536 auto parent_dlg =
dynamic_cast<wxScrolledWindow*
>(parent);
537 wxASSERT(parent_dlg != 0);
539 auto status = dialog.ShowModal();
540 status = dialog.GetReturnCode();
541 if (status != wxID_OK) {
545 auto update = dialog.GetUpdate();
546 if (!g_pi_manager->CheckBlacklistedPlugin(update)) {
550 wxLogMessage(
"Installing %s", update.name.c_str());
552 auto pluginHandler = PluginHandler::getInstance();
554 if (uninstall && path !=
"") {
555 gui_uninstall(pic, update.name.c_str());
557 bool cacheResult = pluginHandler->installPluginFromCache(update);
560 g_Platform->ShowBusySpinner();
564 std::string tempTarballPath = downloader->run(parent_dlg, uninstall);
566 if (!tempTarballPath.size())
572 if (!isRegularFile(manifestPath.c_str())) {
573 wxLogMessage(
"Installation of %s failed", update.name.c_str());
574 PluginHandler::cleanupFiles(manifestPath, update.name);
580 wxLogMessage(
"Installation of %s successful", update.name.c_str());
581 wxURI uri(wxString(update.tarball_url.c_str()));
582 wxFileName fn(uri.GetPath());
583 std::string basename = fn.GetFullName().ToStdString();
586 wxLogDebug(
"Copied %s to local cache at %s", tempTarballPath.c_str(),
588 remove(tempTarballPath.c_str());
596 wxString pispec = _T(
"_pi.dll");
597#elif defined(__WXOSX__)
598 wxString pispec = _T(
"_pi.dylib");
600 wxString pispec = _T(
"_pi.so");
604 wxTextFile manifest_file(manifestPath);
606 if (manifest_file.Open()) {
608 for (wxString str = manifest_file.GetFirstLine(); !manifest_file.Eof();
609 str = manifest_file.GetNextLine()) {
610 if (str.Contains(pispec)) {
611 if (getenv(
"OCPN_KEEP_PLUGINS")) {
615 auto loader = PluginLoader::GetInstance();
616 if (!loader->CheckPluginCompatibility(str)) {
618 _(
"The plugin is not compatible with this version of OpenCPN, "
619 "and will be uninstalled.");
620 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
621 wxICON_INFORMATION | wxOK, 10);
623 PluginHandler::cleanupFiles(manifestPath, update.name);
632 if (b_forceEnable && pluginFile.Length()) {
633 wxString config_section = (_T (
"/PlugIns/" ));
634 wxFileName fn(pluginFile);
635 config_section += fn.GetFullName();
636 pConfig->SetPath(config_section);
637 pConfig->Write(_T (
"bEnabled" ),
true);
642 auto handler = PluginHandler::getInstance();
643 std::remove(handler->ImportedMetadataPath(update.name).c_str());
646 LoadAllPlugIns(
false);
668 pivp.
lat_min = tvp.GetBBox().GetMinLat();
669 pivp.
lat_max = tvp.GetBBox().GetMaxLat();
670 pivp.
lon_min = tvp.GetBBox().GetMinLon();
671 pivp.
lon_max = tvp.GetBBox().GetMaxLon();
673 pivp.
bValid = tvp.IsValid();
694 if (gFrame->GetPrimaryCanvas())
695 vp.
ref_scale = gFrame->GetPrimaryCanvas()->GetVP().ref_scale;
710 void OnPluginUtilAction(wxCommandEvent& event);
712 DECLARE_EVENT_TABLE()
716EVT_BUTTON(ID_CMD_BUTTON_PERFORM_ACTION, pluginUtilHandler::OnPluginUtilAction)
721void pluginUtilHandler::OnPluginUtilAction(wxCommandEvent& event) {
722 auto panel =
static_cast<PluginPanel*
>(
event.GetClientData());
725 wxASSERT(plugin_list_panel != 0);
727 auto actionPIC = panel->GetPlugin();
728 wxString name = actionPIC->m_common_name;
731 switch (panel->GetAction()) {
732 case ActionVerb::UPGRADE_TO_MANAGED_VERSION: {
733 auto loader = PluginLoader::GetInstance();
736 std::string pluginName = actionPIC->m_managed_metadata.name;
738 wxLogMessage(
"Installing managed plugin: %s", pluginName.c_str());
740 new GuiDownloader(plugin_list_panel, actionPIC->m_managed_metadata);
741 downloader->run(plugin_list_panel,
false);
745 if (isRegularFile(manifestPath.c_str())) {
747 for (
unsigned i = 0; i < loader->GetPlugInArray()->GetCount(); i += 1) {
748 if (actionPIC->m_managed_metadata.name ==
749 loader->GetPlugInArray()->Item(i)->m_common_name.ToStdString()) {
750 loader->UnLoadPlugIn(i);
756 LoadAllPlugIns(
false);
758 PluginHandler::cleanupFiles(manifestPath,
759 actionPIC->m_managed_metadata.name);
762 plugin_list_panel->SelectByName(name);
767 case ActionVerb::UPDATE_IMPORTED_VERSION:
768 case ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION:
769 case ActionVerb::REINSTALL_MANAGED_VERSION:
770 case ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION: {
772 auto metaSave = actionPIC->m_managed_metadata;
773 run_update_dialog(plugin_list_panel, actionPIC,
true,
774 metaSave.name.c_str());
778 case ActionVerb::INSTALL_MANAGED_VERSION: {
779 wxLogMessage(
"Installing new managed plugin.");
780 run_update_dialog(plugin_list_panel, actionPIC,
false);
784 case ActionVerb::UNINSTALL_MANAGED_VERSION: {
785 PluginLoader::GetInstance()->DeactivatePlugIn(*actionPIC);
789 message.Printf(
"%s %s\n", actionPIC->m_managed_metadata.name.c_str(),
790 actionPIC->m_managed_metadata.version.c_str());
791 message += _(
"successfully un-installed");
793 wxLogMessage(
"Uninstalling %s",
794 actionPIC->m_managed_metadata.name.c_str());
797 actionPIC->m_managed_metadata.name);
800 auto loader = PluginLoader::GetInstance();
801 LoadAllPlugIns(
false);
804 OCPNMessageBox(gFrame, message, _(
"Un-Installation complete"),
805 wxICON_INFORMATION | wxOK);
810 case ActionVerb::NOP:
821const wxEventType wxEVT_OCPN_MSG = wxNewEventType();
823OCPN_MsgEvent::OCPN_MsgEvent(wxEventType commandType,
int id)
824 : wxEvent(id, commandType) {}
826OCPN_MsgEvent::~OCPN_MsgEvent() {}
828wxEvent* OCPN_MsgEvent::Clone()
const {
830 newevent->m_MessageID =
833 newevent->m_MessageText = this->m_MessageText.c_str();
842PlugInToolbarToolContainer::PlugInToolbarToolContainer() {
846 bitmap_Rollover_day = NULL;
847 bitmap_Rollover_dusk = NULL;
848 bitmap_Rollover_night = NULL;
851PlugInToolbarToolContainer::~PlugInToolbarToolContainer() {
855 delete bitmap_Rollover_day;
856 delete bitmap_Rollover_dusk;
857 delete bitmap_Rollover_night;
868#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
869EVT_CURL_END_PERFORM(CurlThreadId, PlugInManager::OnEndPerformCurlDownload)
870EVT_CURL_DOWNLOAD(CurlThreadId, PlugInManager::OnCurlDownload)
874static
void event_message_box(const wxString& msg) {
875 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
876 wxICON_INFORMATION | wxOK, 0);
882 if (!pic->m_toolbox_panel) NotifySetupOptionsPlugin(pic);
887PlugInManager::PlugInManager(
MyFrame* parent) {
888#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
889 m_pCurlThread = NULL;
895 MyFrame* pFrame = GetParentFrame();
897 m_plugin_menu_item_id_next = CanvasMenuHandler::GetNextContextMenuId();
898 m_plugin_tool_id_next = pFrame->GetNextToolbarToolId();
911 new wxRadioBox(pFrame, -1, _T(
""), wxPoint(0, 0), wxSize(-1, -1), as);
917#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
919 m_last_online =
false;
920 m_last_online_chk = -1;
925 m_blacklist = blacklist_factory();
926 m_blacklist_ui = std::unique_ptr<BlacklistUI>(
new BlacklistUI());
928 wxDEFINE_EVENT(EVT_JSON_TO_ALL_PLUGINS,
ObservedEvt);
929 evt_json_to_all_plugins_listener.
Listen(g_pRouteMan->
json_msg,
this,
930 EVT_JSON_TO_ALL_PLUGINS);
931 Bind(EVT_JSON_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
932 auto json = std::static_pointer_cast<const wxJSONValue>(ev.
GetSharedPtr());
933 SendJSONMessageToAllPlugins(ev.GetString(), *json);
936 wxDEFINE_EVENT(EVT_LEGINFO_TO_ALL_PLUGINS,
ObservedEvt);
938 EVT_LEGINFO_TO_ALL_PLUGINS);
939 Bind(EVT_LEGINFO_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
940 auto ptr = UnpackEvtPointer<ActiveLegDat>(ev);
941 SendActiveLegInfoToAllPlugIns(ptr.get());
944 HandlePluginLoaderEvents();
951PlugInManager::~PlugInManager() {
952#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
953 wxCurlBase::Shutdown();
955 delete m_utilHandler;
958void PlugInManager::InitCommListeners(
void) {
962 auto& msgbus = NavMsgBus::GetInstance();
968 auto n0183_msg = std::static_pointer_cast<const Nmea0183Msg>(ptr);
973 m_listener_SignalK.
Listen(sk_msg,
this, EVT_SIGNALK);
981 std::string s = n0183_msg->payload;
982 wxString sentence(s.c_str());
985 const auto& drivers = CommDriverRegistry::GetInstance().
GetDrivers();
986 auto& target_driver =
FindDriver(drivers, n0183_msg->source->iface);
988 bool bpass_input_filter =
true;
994 params = drv_serial->GetParams();
998 params = drv_net->GetParams();
1003 bpass_input_filter = params.SentencePassesFilter(sentence, FILTER_INPUT);
1006 }
else if (s[0] ==
'!') {
1008 SendAISSentenceToAllPlugIns(sentence);
1013 g_ownshipMMSI_SK = sK_msg->context_self;
1018 std::string msgTerminated = sK_msg->raw_message;
1021 int errors = jsonReader.
Parse(msgTerminated, &root);
1022 if (errors == 0) SendJSONMessageToAllPlugins(wxT(
"OCPN_CORE_SIGNALK"), root);
1031wxDEFINE_EVENT(EVT_PLUGMGR_ROUTEMAN_MSG,
ObservedEvt);
1032wxDEFINE_EVENT(EVT_BLACKLISTED_PLUGIN, wxCommandEvent);
1033wxDEFINE_EVENT(EVT_LOAD_DIRECTORY, wxCommandEvent);
1034wxDEFINE_EVENT(EVT_LOAD_PLUGIN, wxCommandEvent);
1035wxDEFINE_EVENT(EVT_PLUGIN_UNLOAD, wxCommandEvent);
1036wxDEFINE_EVENT(EVT_PLUGLIST_CHANGE, wxCommandEvent);
1037wxDEFINE_EVENT(EVT_UPDATE_CHART_TYPES, wxCommandEvent);
1038wxDEFINE_EVENT(EVT_PLUGIN_LOADALL_FINALIZE, wxCommandEvent);
1040void PlugInManager::HandlePluginLoaderEvents() {
1041 auto loader = PluginLoader::GetInstance();
1043 evt_blacklisted_plugin_listener.
Listen(loader->evt_blacklisted_plugin,
this,
1044 EVT_BLACKLISTED_PLUGIN);
1045 Bind(EVT_BLACKLISTED_PLUGIN, [&](wxCommandEvent& ev) {
1046 m_blacklist_ui->message(ev.GetString().ToStdString());
1049 loader->SetOnDeactivateCb(
1051 evt_pluglist_change_listener.
Listen(loader->evt_pluglist_change,
this,
1052 EVT_PLUGLIST_CHANGE);
1053 Bind(EVT_PLUGLIST_CHANGE, [&](wxCommandEvent&) {
1055 if (g_options) g_options->itemBoxSizerPanelPlugins->Layout();
1058 evt_load_directory_listener.
Listen(loader->evt_load_directory,
this,
1059 EVT_LOAD_DIRECTORY);
1060 Bind(EVT_LOAD_DIRECTORY, [&](wxCommandEvent&) {
1061 pConfig->SetPath(
"/PlugIns/");
1062 SetPluginOrder(pConfig->Read(
"PluginOrder", wxEmptyString));
1065 evt_load_plugin_listener.
Listen(loader->evt_load_plugin,
this,
1067 Bind(EVT_LOAD_PLUGIN, [&](wxCommandEvent& ev) {
1072 evt_update_chart_types_listener.
Listen(loader->evt_update_chart_types,
this,
1073 EVT_UPDATE_CHART_TYPES);
1074 Bind(EVT_UPDATE_CHART_TYPES,
1075 [&](wxCommandEvent& ev) { UpDateChartDataTypes(); });
1077 evt_plugin_loadall_finalize_listener.
Listen(
1078 loader->evt_plugin_loadall_finalize,
this, EVT_PLUGIN_LOADALL_FINALIZE);
1079 Bind(EVT_PLUGIN_LOADALL_FINALIZE,
1080 [&](wxCommandEvent& ev) { FinalizePluginLoadall(); });
1082 evt_ais_json_listener.
Listen(g_pAIS->
plugin_msg,
this, EVT_PLUGMGR_AIS_MSG);
1084 EVT_PLUGMGR_ROUTEMAN_MSG);
1086 auto pTarget = UnpackEvtPointer<AisTargetData>(ev);
1087 SendAisJsonMessage(pTarget);
1089 Bind(EVT_PLUGMGR_ROUTEMAN_MSG, [&](
ObservedEvt& ev) {
1090 auto msg = UnpackEvtPointer<wxJSONValue>(ev);
1091 SendJSONMessageToAllPlugins(ev.GetString(), *msg);
1099wxDEFINE_EVENT(EVT_DOWNLOAD_FAILED, wxCommandEvent);
1100wxDEFINE_EVENT(EVT_DOWNLOAD_OK, wxCommandEvent);
1102void PlugInManager::HandlePluginHandlerEvents() {
1103 auto loader = PluginLoader::GetInstance();
1105 evt_download_failed_listener.
Listen(loader->evt_update_chart_types,
this,
1106 EVT_DOWNLOAD_FAILED);
1107 Bind(EVT_DOWNLOAD_FAILED, [&](wxCommandEvent& ev) {
1108 wxString message = _(
"Please check system log for more info.");
1109 OCPNMessageBox(gFrame, message, _(
"Installation error"),
1110 wxICON_ERROR | wxOK | wxCENTRE);
1113 evt_download_ok_listener.
Listen(loader->evt_update_chart_types,
this,
1115 Bind(EVT_DOWNLOAD_OK, [&](wxCommandEvent& ev) {
1116 wxString message(ev.GetString());
1117 message += _(
" successfully installed from cache");
1118 OCPNMessageBox(gFrame, message, _(
"Installation complete"),
1119 wxICON_INFORMATION | wxOK | wxCENTRE);
1123bool PlugInManager::CallLateInit(
void) {
1126 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1127 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1130 switch (pic->m_api_version) {
1142 ProcessLateInit(pic);
1152 wxString msg(
"PlugInManager: Calling LateInit PlugIn: ");
1157 if (ppi) ppi->LateInit();
1165 ChartData->PurgeCachePlugins();
1166 gFrame->InvalidateAllQuilts();
1169 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1172 if (pttc->m_pplugin == pic->m_pplugin) {
1173 m_PlugInToolbarTools.Remove(pttc);
1179 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1181 if (pimis->m_pplugin == pic->m_pplugin) {
1182 m_PlugInMenuItems.Remove(pimis);
1188bool PlugInManager::IsAnyPlugInChartEnabled() {
1191 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1192 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1194 if (pic->m_enabled && pic->m_init_state) {
1203void PlugInManager::UpdateManagedPlugins() {
1204 PluginLoader::GetInstance()->UpdateManagedPlugins(
false);
1205 PluginLoader::GetInstance()->
SortPlugins(ComparePlugins);
1208 g_options->itemBoxSizerPanelPlugins->Layout();
1211bool PlugInManager::UpDateChartDataTypes() {
1213 if (NULL == ChartData)
return bret;
1215 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1216 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1219 if (pic->m_init_state) {
1226 if (bret) ChartData->UpdateChartClassDescriptorArray();
1231void PlugInManager::FinalizePluginLoadall() {
1235 SetColorSchemeForAllPlugIns(global_color_scheme);
1238 SendBaseConfigToAllPlugIns();
1239 SendS52ConfigToAllPlugIns(
true);
1240 SendSKConfigToAllPlugIns();
1245 if (gFrame->GetPrimaryCanvas()->GetglCanvas())
1246 gFrame->GetPrimaryCanvas()->GetglCanvas()->SendJSONConfigMessage();
1254void PlugInManager::SetPluginOrder(wxString serialized_names) {
1255 m_plugin_order.Empty();
1256 wxStringTokenizer tokenizer(serialized_names,
";");
1257 while (tokenizer.HasMoreTokens()) {
1258 m_plugin_order.Add(tokenizer.GetNextToken());
1262wxString PlugInManager::GetPluginOrder() {
1263 wxString plugins = wxEmptyString;
1264 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1265 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1266 plugins.Append(plugin_array->Item(i)->m_common_name);
1267 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1272bool PlugInManager::UpdateConfig() {
1276 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1277 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1281 wxString config_section = (_T (
"/PlugIns/" ));
1283 pConfig->SetPath(config_section);
1284 pConfig->Write(_T (
"bEnabled" ), pic->m_enabled);
1291void PlugInManager::ShowDeferredBlacklistMessages() {
1292 m_blacklist_ui->show_deferred_messages();
1295bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1297 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1300bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin* plugin) {
1305 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1306 name.Replace(
"class ", wxEmptyString);
1308 const std::type_info& ti =
typeid(*plugin);
1310 char* realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1311 wxString name = wxString::FromAscii(realname);
1314 return CheckBlacklistedPlugin(name, major, minor);
1317bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
1319 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1320 if (block_status == plug_status::unblocked)
return true;
1321 plug_data data(name.ToStdString(), major, minor);
1322 auto msg = m_blacklist->get_message(block_status, data);
1323 m_blacklist_ui->message(msg);
1327bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC& dc,
1331 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1332 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1334 if (pic->m_enabled && pic->m_init_state) {
1338 wxDC* pdc = dc.GetDC();
1341 switch (pic->m_api_version) {
1343 if (priority > 0)
break;
1350 if (priority > 0)
break;
1353 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1364 if (priority > 0)
break;
1367 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1372 if (priority > 0)
break;
1376 ppi->RenderOverlay(*pdc, &pivp);
1387 if (priority <= 0) {
1391 ppi->RenderOverlay(*pdc, &pivp);
1407 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1409 if ((m_cached_overlay_bm.GetWidth() != vp.
pix_width) ||
1410 (m_cached_overlay_bm.GetHeight() != vp.
pix_height))
1414 mdc.SelectObject(m_cached_overlay_bm);
1415 mdc.SetBackground(*wxBLACK_BRUSH);
1418 bool b_rendered =
false;
1420 switch (pic->m_api_version) {
1422 if (priority > 0)
break;
1429 if (priority > 0)
break;
1432 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1443 if (priority > 0)
break;
1446 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1451 if (priority > 0)
break;
1455 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1467 if (priority <= 0) {
1471 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1478 mdc, &pivp, g_canvasConfig, priority);
1487 mdc.SelectObject(wxNullBitmap);
1490 wxMask* p_msk =
new wxMask(m_cached_overlay_bm, wxColour(0, 0, 0));
1491 m_cached_overlay_bm.SetMask(p_msk);
1493 dc.DrawBitmap(m_cached_overlay_bm, 0, 0,
true);
1496 }
else if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1504bool PlugInManager::RenderAllGLCanvasOverlayPlugIns(wxGLContext* pcontext,
1508 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1509 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1511 if (pic->m_enabled && pic->m_init_state) {
1512 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1515 switch (pic->m_api_version) {
1517 if (priority > 0)
break;
1520 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
1532 if (priority > 0)
break;
1540 if (priority > 0)
break;
1556 if (priority <= 0) {
1581void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort& vp) {
1582 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1583 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1585 if (pic->m_enabled && pic->m_init_state) {
1594void NotifySetupOptionsPlugin(
const PlugInData* pd) {
1595 PluginLoader::GetInstance()->NotifySetupOptionsPlugin(pd);
1598void PlugInManager::NotifySetupOptions() {
1599 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1600 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1602 NotifySetupOptionsPlugin(pic);
1607 int ok_apply_cancel) {
1608 if (pic->m_enabled && pic->m_init_state) {
1611 auto loader = PluginLoader::GetInstance();
1618void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
1619 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1620 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1623 ClosePlugInPanel(pic, ok_apply_cancel);
1628int PlugInManager::AddCanvasContextMenuItem(wxMenuItem* pitem,
1632 pmic->pmenu_item = pitem;
1633 pmic->m_pplugin = pplugin;
1634 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
1635 : m_plugin_menu_item_id_next;
1637 pmic->b_grey =
false;
1638 pmic->m_in_menu = name;
1640 m_PlugInMenuItems.Add(pmic);
1642 m_plugin_menu_item_id_next++;
1647void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char* name) {
1648 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1651 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1652 m_PlugInMenuItems.Remove(pimis);
1660void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
1662 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1665 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1673void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
1675 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1678 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1679 pimis->b_grey = grey;
1686void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
1687 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1688 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1690 if (pic->m_enabled && pic->m_init_state)
1695void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
1696 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1697 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1699 if (pic->m_enabled && pic->m_init_state)
1704void PlugInManager::PrepareAllPluginContextMenus() {
1705 int canvasIndex = gFrame->GetCanvasIndexUnderMouse();
1706 if (canvasIndex < 0)
return;
1708 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1709 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1711 if (pic->m_enabled && pic->m_init_state) {
1713 switch (pic->m_api_version) {
1732void PlugInManager::SendSKConfigToAllPlugIns() {
1735 v[_T(
"self")] = g_ownshipMMSI_SK;
1739 SendMessageToAllPlugins(wxString(_T(
"OCPN_CORE_SIGNALK")), out);
1742void PlugInManager::SendBaseConfigToAllPlugIns() {
1745 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1746 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1747 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1748 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1749 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1752 if (g_MainToolbar) {
1753 v[_T(
"OpenCPN Toolbar Width")] = g_MainToolbar->GetToolbarRect().width;
1754 v[_T(
"OpenCPN Toolbar Height")] = g_MainToolbar->GetToolbarRect().height;
1755 v[_T(
"OpenCPN Toolbar PosnX")] = g_MainToolbar->GetToolbarRect().x;
1756 v[_T(
"OpenCPN Toolbar PosnY")] = g_MainToolbar->GetToolbarRect().y;
1760 v[_T(
"OpenCPN Zoom Mod Vector")] = g_chart_zoom_modifier_vector;
1761 v[_T(
"OpenCPN Zoom Mod Other")] = g_chart_zoom_modifier_raster;
1762 v[_T(
"OpenCPN Scale Factor Exp")] =
1763 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1764 v[_T(
"OpenCPN Display Width")] = (int)g_display_size_mm;
1771 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1774void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1777 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1778 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1779 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1780 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1781 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1789 v[_T(
"OpenCPN S52PLIB ShowAnchorConditions")] = ps52plib->GetAnchorOn();
1790 v[_T(
"OpenCPN S52PLIB ShowQualityOfData")] = ps52plib->GetQualityOfData();
1795 v[_T(
"OpenCPN S52PLIB MetaDisplay")] = ps52plib->m_bShowMeta;
1796 v[_T(
"OpenCPN S52PLIB DeclutterText")] = ps52plib->m_bDeClutterText;
1797 v[_T(
"OpenCPN S52PLIB ShowNationalText")] = ps52plib->m_bShowNationalTexts;
1798 v[_T(
"OpenCPN S52PLIB ShowImportantTextOnly")] =
1799 ps52plib->m_bShowS57ImportantTextOnly;
1800 v[_T(
"OpenCPN S52PLIB UseSCAMIN")] = ps52plib->m_bUseSCAMIN;
1801 v[_T(
"OpenCPN S52PLIB UseSUPER_SCAMIN")] = ps52plib->m_bUseSUPER_SCAMIN;
1802 v[_T(
"OpenCPN S52PLIB SymbolStyle")] = ps52plib->m_nSymbolStyle;
1803 v[_T(
"OpenCPN S52PLIB BoundaryStyle")] = ps52plib->m_nBoundaryStyle;
1804 v[_T(
"OpenCPN S52PLIB ColorShades")] =
1805 S52_getMarinerParam(S52_MAR_TWO_SHADES);
1806 v[_T(
"OpenCPN S52PLIB Safety Depth")] =
1807 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1808 v[_T(
"OpenCPN S52PLIB Shallow Contour")] =
1809 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1810 v[_T(
"OpenCPN S52PLIB Deep Contour")] =
1811 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1815 v[_T(
"OpenCPN S52PLIB GlobalReconfig")] = bReconfig;
1820 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1823void PlugInManager::NotifyAuiPlugIns(
void) {
1824 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
1825 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1827 if (pic->m_enabled && pic->m_init_state &&
1833int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1834 wxBitmap* bmpRollover, wxItemKind kind,
1835 wxString shortHelp, wxString longHelp,
1836 wxObject* clientData,
int position,
1839 pttc->label = label;
1841 if (!bitmap->IsOk()) {
1843 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1846 pttc->bitmap_day =
new wxBitmap(*bitmap);
1847 pttc->bitmap_day->UnShare();
1850 if (!bmpRollover->IsOk()) {
1852 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1855 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1856 pttc->bitmap_Rollover_day->UnShare();
1859 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1860 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1861 pttc->bitmap_Rollover_dusk =
1862 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1863 pttc->bitmap_Rollover_night =
1864 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1867 pttc->shortHelp = shortHelp;
1868 pttc->longHelp = longHelp;
1869 pttc->clientData = clientData;
1870 pttc->position = position;
1871 pttc->m_pplugin = pplugin;
1872 pttc->tool_sel = tool_sel;
1874 pttc->b_toggle =
false;
1875 pttc->id = m_plugin_tool_id_next;
1877 m_PlugInToolbarTools.Add(pttc);
1879 m_plugin_tool_id_next++;
1884int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1885 wxString SVGRolloverfile,
1886 wxString SVGToggledfile, wxItemKind kind,
1887 wxString shortHelp, wxString longHelp,
1888 wxObject* clientData,
int position,
1891 pttc->label = label;
1893 pttc->pluginNormalIconSVG = SVGfile;
1894 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1895 pttc->pluginToggledIconSVG = SVGToggledfile;
1900 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1901 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1902 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1903 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1904 pttc->bitmap_Rollover_dusk =
1905 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1906 pttc->bitmap_Rollover_night =
1907 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1910 pttc->shortHelp = shortHelp;
1911 pttc->longHelp = longHelp;
1912 pttc->clientData = clientData;
1913 pttc->position = position;
1914 pttc->m_pplugin = pplugin;
1915 pttc->tool_sel = tool_sel;
1917 pttc->b_toggle =
false;
1918 pttc->id = m_plugin_tool_id_next;
1920 m_PlugInToolbarTools.Add(pttc);
1922 m_plugin_tool_id_next++;
1927void PlugInManager::RemoveToolbarTool(
int tool_id) {
1928 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1931 if (pttc->id == tool_id) {
1932 m_PlugInToolbarTools.Remove(pttc);
1938 pParent->RequestNewToolbars();
1941void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1942 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1945 if (pttc->id == item) {
1947 pParent->RequestNewToolbars();
1954void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1955 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1958 if (pttc->id == item) {
1959 pttc->b_toggle = toggle;
1960 pParent->SetMasterToolbarItemState(item, toggle);
1967void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1968 wxBitmap* bmpRollover) {
1969 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1972 if (pttc->id == item) {
1973 delete pttc->bitmap_day;
1974 delete pttc->bitmap_dusk;
1975 delete pttc->bitmap_night;
1976 delete pttc->bitmap_Rollover_day;
1978 if (!bitmap->IsOk()) {
1980 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1983 pttc->bitmap_day =
new wxBitmap(*bitmap);
1984 pttc->bitmap_day->UnShare();
1987 if (!bmpRollover->IsOk()) {
1989 pttc->bitmap_Rollover_day =
1990 new wxBitmap(style->GetIcon(_T(
"default_pi")));
1993 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1994 pttc->bitmap_Rollover_day->UnShare();
1997 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1998 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
2000 pParent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
2001 pttc->bitmap_Rollover_day);
2008void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2009 wxString SVGfileRollover,
2010 wxString SVGfileToggled) {
2011 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2014 if (pttc->id == item) {
2015 pttc->pluginNormalIconSVG = SVGfile;
2016 pttc->pluginRolloverIconSVG = SVGfileRollover;
2017 pttc->pluginToggledIconSVG = SVGfileToggled;
2018 pParent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2019 pttc->pluginRolloverIconSVG,
2020 pttc->pluginToggledIconSVG);
2028 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2030 if (
id == pc->id)
return pc->m_pplugin;
2036wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2039 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
2040 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2042 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2046 return wxEmptyString;
2049wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2051wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2052 unsigned char dim_ratio) {
2053 wxImage img_dup = pbmp_normal->ConvertToImage();
2055 if (!img_dup.IsOk())
return NULL;
2057 if (dim_ratio < 200) {
2059 int gimg_width = img_dup.GetWidth();
2060 int gimg_height = img_dup.GetHeight();
2062 double factor = (double)(dim_ratio) / 256.0;
2064 for (
int iy = 0; iy < gimg_height; iy++) {
2065 for (
int ix = 0; ix < gimg_width; ix++) {
2066 if (!img_dup.IsTransparent(ix, iy)) {
2067 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2068 img_dup.GetGreen(ix, iy),
2069 img_dup.GetBlue(ix, iy));
2070 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2071 hsv.value = hsv.value * factor;
2072 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2073 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2079 wxBitmap* ptoolBarBitmap;
2082 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2084 dwxdc.SelectObject(tbmp);
2086 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2088 ptoolBarBitmap =
new wxBitmap(img_dup);
2092 return ptoolBarBitmap;
2095wxArrayString PlugInManager::GetPlugInChartClassNameArray(
void) {
2096 wxArrayString array;
2097 auto plugin_array = PluginLoader::GetInstance()->GetPlugInArray();
2098 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2100 if (pic && pic->m_enabled && pic->m_init_state &&
2105 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2106 array.Add(carray[j]);
2114 while (j < array.GetCount()) {
2115 wxString test = array[j];
2116 unsigned int k = j + 1;
2117 while (k < array.GetCount()) {
2118 if (test == array[k]) {
2136#define DISABLED_SETTINGS_MSG \
2137 _("These settings might destabilize OpenCPN and are by default disabled." \
2138 " To despite the dangers enable them manually add a CatalogExpert=1" \
2139 " line in the [PlugIns] section in the configuration file.")
2144CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2145 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2147 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2150 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2152 wxStaticBox* itemStaticBoxSizer4Static =
2153 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2154 wxStaticBoxSizer* itemStaticBoxSizer4 =
2155 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2156 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2160 m_catalogText =
new wxStaticText(
this, wxID_STATIC, _T(
""));
2161 itemStaticBoxSizer4->Add(m_catalogText,
2162 wxSizerFlags().Border().Proportion(1));
2163 m_catalogText->SetLabel(GetCatalogText(
false));
2166 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2167 itemStaticBoxSizer4->Add(rowSizer2,
2168 wxSizerFlags().Expand().Border().Proportion(1));
2170 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2171 wxDefaultPosition, wxDefaultSize, 0);
2172 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2173 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2174 &CatalogMgrPanel::OnUpdateButton,
this);
2175 rowSizer2->AddSpacer(4 * GetCharWidth());
2176 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2177 wxDefaultPosition, wxDefaultSize, 0);
2178 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2179 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2180 &CatalogMgrPanel::OnTarballButton,
this);
2182 rowSizer2->AddSpacer(4 * GetCharWidth());
2183 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2184 wxDefaultPosition, wxDefaultSize, 0);
2186 if (expert.Get(
false)) {
2187 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2188 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2190 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2191 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2194 rowSizer2->AddSpacer(4 * GetCharWidth());
2195 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2197 SetUpdateButtonLabel();
2200 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2201 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2203 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2207 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2208 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2209 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2212 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2214 if (!expert.Get(
false)) {
2216 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2217 wxDefaultPosition, wxDefaultSize, 0);
2218 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2219 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2220 &CatalogMgrPanel::OnUpdateButton,
this);
2221 SetUpdateButtonLabel();
2222 m_tarballButton = NULL;
2223 m_adv_button = NULL;
2226 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2227 itemStaticBoxSizer4->Add(m_catalogText,
2228 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2231 m_updateButton =
new wxButton(
2232 this, wxID_ANY,
"Update Plugin Catalog:master ",
2233 wxDefaultPosition, wxDefaultSize, 0);
2234 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2235 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2236 &CatalogMgrPanel::OnUpdateButton,
this);
2237 SetUpdateButtonLabel();
2240 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2241 wxDefaultPosition, wxDefaultSize, 0);
2242 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2244 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2245 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2248 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2249 wxDefaultPosition, wxDefaultSize, 0);
2250 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2251 2 * GetCharWidth());
2252 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2253 &CatalogMgrPanel::OnTarballButton,
this);
2259CatalogMgrPanel::~CatalogMgrPanel() {
2260 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2261 &CatalogMgrPanel::OnUpdateButton,
this);
2262 if (m_tarballButton)
2263 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2264 &CatalogMgrPanel::OnTarballButton,
this);
2267static const char*
const DOWNLOAD_REPO_PROTO =
2268 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2271void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2273 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2274 std::string url(g_catalog_custom_url);
2275 if (catalog !=
"custom") {
2276 url = std::string(DOWNLOAD_REPO_PROTO);
2280 std::string filePath =
2281 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2283 auto catalogHdlr = CatalogHandler::getInstance();
2285 g_Platform->ShowBusySpinner();
2286 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2287 g_Platform->HideBusySpinner();
2289 std::string message;
2290 if (status != CatalogHandler::ServerStatus::OK) {
2291 message = _(
"Cannot download data from url");
2292 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2293 wxICON_ERROR | wxOK);
2299 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2301 wxFileName::GetPathSeparator() +
2302 _T(
"ocpn-plugins.xml"))) {
2303 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2304 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2309 if (!wxCopyFile(wxString(filePath.c_str()),
2311 wxFileName::GetPathSeparator() +
2312 _T(
"ocpn-plugins.xml"))) {
2313 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2314 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2320 if (catalog ==
"master") {
2322 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2323 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2329 pConfig->SetPath(_T(
"/PlugIns/"));
2330 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2336 auto pluginHandler = PluginHandler::getInstance();
2337 pluginHandler->setMetadata(
"");
2341 auto cataloghdlr = CatalogHandler::getInstance();
2342 cataloghdlr->ClearCatalogData();
2345 LoadAllPlugIns(
false);
2349 m_catalogText->SetLabel(GetCatalogText(
true));
2352 OCPNMessageBox(
this, _(
"Catalog update successful"),
2353 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2356void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2360 androidDisableRotation();
2363 dialog->ShowModal();
2366 androidEnableRotation();
2370void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2373 int response = g_Platform->DoFileSelectorDialog(
2374 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2375 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2377 if (response != wxID_OK) {
2380 auto handler = PluginHandler::getInstance();
2382 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2386 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2387 _(
"OpenCPN Plugin Import Error"));
2391 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2392 _(
"OpenCPN Plugin Import Error"));
2393 handler->uninstall(metadata.name);
2396 UninstallPlugin(metadata.name);
2397 ok = handler->installPlugin(metadata, path.ToStdString());
2399 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2400 _(
"OpenCPN Plugin Import Error"));
2403 metadata.is_imported =
true;
2405 std::ofstream file(metadata_path);
2408 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2409 <<
" for imported plugin: " << metadata.name;
2411 LoadAllPlugIns(
false,
true);
2414 wxString ws(_(
"Plugin"));
2415 ws += metadata.name + _(
" successfully imported");
2416 OCPNMessageBox(gFrame, ws, _(
"Installation complete"),
2417 wxICON_INFORMATION | wxOK | wxCENTRE);
2420wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2422 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2423 catalog += _T(
": ");
2426 pConfig->SetPath(_T(
"/PlugIns/"));
2427 wxString latestCatalog =
2428 pConfig->Read(_T(
"LatestCatalogDownloaded"), _T(
"default"));
2429 catalog += latestCatalog;
2434 auto pluginHandler = PluginHandler::getInstance();
2435 std::string date = pluginHandler->GetCatalogData()->date;
2437 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2438 if (!updated) catalog += _T(
" : ") + _(
"Please Update Plugin Catalog.");
2444void CatalogMgrPanel::SetUpdateButtonLabel() {
2445 wxString label = _(
"Update Plugin Catalog");
2447 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2448 m_updateButton->SetLabel(label);
2452wxString CatalogMgrPanel::GetImportInitDir() {
2454 pConfig->SetPath(_T(
"/PlugIns/"));
2455 wxString lastImportDir;
2456 lastImportDir = pConfig->Read(_T(
"LatestImportDir"),
2457 g_Platform->GetWritableDocumentsDir());
2458 if (wxDirExists(lastImportDir)) {
2459 return lastImportDir;
2461 return (g_Platform->GetWritableDocumentsDir());
2470 const wxPoint& pos, const wxSize& size)
2471 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2472 m_PluginSelected(0) {
2473 m_is_loading.clear();
2474 SetSizer(
new wxBoxSizer(wxVERTICAL));
2475 ReloadPluginPanels();
2478void PluginListPanel::SelectByName(wxString& name) {
2479 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2480 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2482 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2483 pluginPanel->SetSelected(
true);
2484 pluginPanel->Layout();
2485 SelectPlugin(pluginPanel);
2493std::vector<const PlugInData*> GetInstalled() {
2494 std::vector<const PlugInData*> result;
2495 auto loader = PluginLoader::GetInstance();
2496 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2497 auto const item = loader->GetPlugInArray()->Item(i);
2498 if (item->m_managed_metadata.name.empty()) {
2499 const auto name = item->m_common_name.ToStdString();
2503 result.push_back(item);
2506 std::string slhs, srhs;
2507 for (
auto& cl : lhs->Key()) slhs += toupper(cl);
2508 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2509 return slhs.compare(srhs) < 0;
2511 std::sort(result.begin(), result.end(), compare);
2516static bool IsPluginLoaded(
const std::string& name) {
2517 if (safe_mode::get_mode()) {
2520 std::find(installed.begin(), installed.end(),
ocpn::tolower(name));
2521 return found != installed.end();
2523 auto loaded = PluginLoader::GetInstance()->GetPlugInArray();
2524 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2525 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2532 if (m_is_loading.test_and_set()) {
2534 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2538 auto plugins = PluginLoader::GetInstance()->GetPlugInArray();
2539 m_PluginItems.Clear();
2541 wxWindowList kids = GetChildren();
2542 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2543 wxWindowListNode* node = kids.Item(i);
2544 wxWindow* win = node->GetData();
2546 if (pp) win->Destroy();
2548 GetSizer()->Clear();
2551 m_PluginSelected = 0;
2553 if (safe_mode::get_mode()) {
2556 for (
const auto& name : installed) AddPlugin(name);
2559 auto available = getCompatiblePlugins();
2563 return IsPluginLoaded(md.name);
2565 auto end = std::remove_if(available.begin(), available.end(), predicate);
2566 available.erase(end, available.end());
2572 std::string slhs, srhs;
2573 for (
auto& cl : lhs.name) slhs += toupper(cl);
2574 for (
auto& cr : rhs.name) srhs += toupper(cr);
2575 return slhs.compare(srhs) < 0;
2579 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2580 for (
const auto& p : available) unique_sorted_entries.insert(p);
2585 for (
const auto& p : GetInstalled())
2586 if (p->m_enabled) AddPlugin(*p);
2589 for (
const auto& p : GetInstalled())
2590 if (!p->m_enabled) AddPlugin(*p);
2593 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2601 m_is_loading.clear();
2604void PluginListPanel::AddPlugin(
const std::string& name) {
2607 panel->SetSelected(
false);
2608 GetSizer()->Add(panel, 0, wxEXPAND);
2609 m_PluginItems.Add(panel);
2610 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2611 GetSizer()->AddSpacer(m_pluginSpacer);
2614void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2616 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2617 pPluginPanel->SetSelected(
false);
2618 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2619 m_PluginItems.Add(pPluginPanel);
2621 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2622 GetSizer()->AddSpacer(m_pluginSpacer);
2635int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2636 wxBoxSizer* sizer) {
2638 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2639 auto panel = plugins.Item(i);
2640 bool was_selected = panel->GetSelected();
2641 panel->SetSelected(
false);
2643 wxSize unselected = panel->GetSize();
2645 panel->SetSelected(
true);
2647 wxSize selected = panel->GetSize();
2649 int dy = selected.GetHeight() - unselected.GetHeight();
2650 max_dy = wxMax(max_dy, dy);
2651 panel->SetSelected(was_selected);
2656PluginListPanel::~PluginListPanel() {}
2658void PluginListPanel::UpdateSelections() {
2659 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2662 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2667void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2669 GetViewStart(&xs, &ys);
2672 if (m_PluginSelected) {
2673 m_PluginSelected->SetSelected(
false);
2674 m_PluginSelected->Layout();
2677 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2679 m_PluginSelected = pi;
2681 GetSizer()->Layout();
2683 wxSize size = GetBestVirtualSize();
2684 SetVirtualSize(size);
2689 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2691 int yd = pPluginPanel->GetSize().y;
2693 htop += m_pluginSpacer;
2694 if (pPluginPanel == pi) {
2695 int piBottom = htop - (ys * g_options->GetScrollRate());
2696 if (piBottom > GetClientSize().y) {
2697 ys += (piBottom - GetClientSize().y) / g_options->GetScrollRate();
2707 int pos = m_PluginItems.Index(pi);
2710 m_PluginItems.RemoveAt(pos);
2713 m_PluginItems.Insert(pi, pos - 1);
2714 wxStaticLine* itemStaticLine =
new wxStaticLine(
2715 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2720 m_PluginSelected = pi;
2722 GetSizer()->Layout();
2728 int pos = m_PluginItems.Index(pi);
2729 if (pos == (
int)m_PluginItems.Count() -
2732 m_PluginItems.RemoveAt(pos);
2735 m_PluginItems.Insert(pi, pos + 1);
2736 wxStaticLine* itemStaticLine =
new wxStaticLine(
2737 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2742 m_PluginSelected = pi;
2744 GetSizer()->Layout();
2749static bool canUninstall(std::string name) {
2750 PluginHandler* pluginHandler = PluginHandler::getInstance();
2753 for (
auto plugin : pluginHandler->getInstalled()) {
2754 if (plugin.name == name) {
2755 if (safe_mode::get_mode())
2758 return !plugin.readonly;
2765 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2767 m_is_safe_panel(true) {
2769 wxASSERT(m_PluginListPanel != 0);
2770 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2771 SetSizer(top_sizer);
2772 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2773 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2775 double iconSize = GetCharWidth() * 4;
2777 int icon_scale = iconSize * dpi_mult;
2779 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2780 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2781 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2783 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2784 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2785 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2786 top_horizontal->Add(m_pVersion);
2789 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2790 top_horizontal->Add(m_pButtons);
2791 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2792 top_horizontal->Add(m_info_btn);
2793 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2794 wxDefaultPosition, wxDefaultSize, 0);
2795 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2797 auto uninstall = [&](wxCommandEvent ev) {
2798 auto n = m_pName->GetLabel().ToStdString();
2800 OCPNMessageBox(gFrame, std::string(_(
"Uninstall plugin ")) + n +
"?",
2801 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2802 if (result != wxID_OK)
return;
2806 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2810EVT_PAINT(PluginPanel::OnPaint)
2815 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2817 m_is_safe_panel(false) {
2820 wxASSERT(m_PluginListPanel != 0);
2822 m_bSelected =
false;
2823 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2824 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2826 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2829 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2830 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2831 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2832 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2834 double iconSize = GetCharWidth() * 4;
2836 int icon_scale = iconSize * dpi_mult;
2838 wxImage plugin_icon;
2840 if (m_plugin.m_bitmap.IsOk()) {
2841 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2844 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2845 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2846 path.AppendDir(
"uidata");
2847 path.AppendDir(
"traditional");
2848 bitmap = LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2849 }
else if (plugin_icon.IsOk()) {
2850 int nowSize = plugin_icon.GetWidth();
2851 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2852 bitmap = wxBitmap(plugin_icon);
2854 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2856 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2858 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2859 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2861 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2864 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2865 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2868 int nChars = g_options->GetSize().x / GetCharWidth();
2869 bool bCompact =
false;
2875 wxString nameString = m_plugin.m_common_name;
2879 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2880 if (nameWidth > maxWidth) {
2881 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2882 wxELLIPSIZE_END, maxWidth);
2884 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2885 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2886 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2887 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2889 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2890 sl1->AddGrowableCol(1);
2891 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2893 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2894 sl1->Add(m_pVersion, 0, wxALL, 5);
2895 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2898 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2899 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2901 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2902 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2903 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2906 wxString descriptionString = m_plugin.m_short_description;
2907 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2908 int descriptionWidth;
2909 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2910 if (descriptionWidth > maxDescriptionWidth)
2912 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2913 wxELLIPSIZE_END, maxDescriptionWidth);
2918 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2919 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2920 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2921 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2922 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2925 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2926 itemBoxSizer03->AddGrowableCol(2);
2927 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2929 wxString nameString = m_plugin.m_common_name;
2930 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2931 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2932 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2936 wxFont font = GetFont();
2937 font.SetWeight(wxFONTWEIGHT_BOLD);
2938 m_pName->SetFont(font);
2941 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2943 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2944 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2945 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2948 !m_plugin.m_managed_metadata.is_orphan)) {
2951 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2952 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2954 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2955 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2956 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2958 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2960 m_pDescription =
new wxStaticText(
2961 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2963 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2964 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2965 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2969 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2971 itemBoxSizer02->Add(m_info_btn, 0);
2973 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2974 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2975 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2976 wxDefaultPosition, wxDefaultSize, 0);
2977 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
2979 m_pButtons->AddSpacer(3 * GetCharWidth());
2982 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
2983 wxDefaultPosition, wxDefaultSize, 0);
2984 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
2986 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2987 wxDefaultPosition, wxDefaultSize, 0);
2988 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
2990 m_pButtons =
new wxBoxSizer(wxVERTICAL);
2991 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2993 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
2994 m_pButtons->Add(tline, 0, wxALL, 2);
2996 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2997 wxDefaultPosition, wxDefaultSize, 0);
2998 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
3000 tline->AddSpacer(3 * GetCharWidth());
3002 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
3004 tline->Add(m_info_btn, 0);
3007 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3008 wxDefaultPosition, wxDefaultSize);
3009 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3011 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3012 wxDefaultPosition, wxDefaultSize, 0);
3013 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3016 wxBitmap statusBitmap;
3017 const auto stat = m_plugin.m_status;
3018 auto icon_name = icon_by_status.at(stat);
3019 if (stat == PluginStatus::Imported &&
3020 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3022 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3025 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3026 path.AppendDir(
"uidata");
3027 path.AppendDir(
"traditional");
3029 int bmsize = GetCharWidth() * 3 * dpi_mult;
3030 if (path.IsFileReadable()) {
3031 statusBitmap = LoadSVG(path.GetFullPath(), bmsize, bmsize);
3032 ok = statusBitmap.IsOk();
3035 auto style = g_StyleManager->GetCurrentStyle();
3036 statusBitmap = wxBitmap(style->GetIcon(_T(
"default_pi"), bmsize, bmsize));
3037 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3040 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3041 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3042 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3044 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3047 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3049 itemBoxSizer02->AddSpacer(GetCharWidth());
3051 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3052 &PluginPanel::OnPluginPreferences,
this);
3053 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3054 &PluginPanel::OnPluginUninstall,
this);
3055 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3056 &PluginPanel::OnPluginAction,
this);
3058 SetSelected(m_bSelected);
3059 SetAutoLayout(
true);
3067PluginPanel::~PluginPanel() {
3068 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3069 if (m_is_safe_panel)
return;
3070 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3072 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3073 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3074 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3075 if (m_pButtonAction) {
3076 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3077 &PluginPanel::OnPluginAction,
this);
3079 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3080 &PluginPanel::OnPluginPreferences,
this);
3081 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3082 &PluginPanel::OnPluginEnableToggle,
this);
3085void PluginPanel::SetActionLabel(wxString& label) {
3086 m_pButtonAction->SetLabel(label);
3090static wxStopWatch swclick;
3091static int downx, downy;
3093void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3096 event.GetPosition(&downx, &downy);
3102void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3104 qDebug() << swclick.Time();
3105 if (swclick.Time() < 200) {
3107 event.GetPosition(&upx, &upy);
3108 if ((fabs(upx - downx) < GetCharWidth()) &&
3109 (fabs(upy - downy) < GetCharWidth())) {
3117void PluginPanel::DoPluginSelect() {
3118 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3124 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3125 }
else if (m_bSelected) {
3127 m_PluginListPanel->SelectPlugin(NULL);
3130 m_PluginListPanel->SelectPlugin(
this);
3138static PluginMetadata GetMetadataByName(
const std::string& name) {
3139 auto plugins = PluginHandler::getInstance()->
getInstalled();
3140 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3141 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3142 if (found == plugins.end()) {
3143 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3148void PluginPanel::SetSelected(
bool selected) {
3149 m_bSelected = selected;
3151 m_pVersion->SetLabel(
3154 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3155 m_pButtons->Show(
true);
3156 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3159 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3162 unInstallPossible =
false;
3165 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3167 m_pButtonUninstall->Show(unInstallPossible);
3169 if (m_plugin.m_managed_metadata.info_url.size()) {
3170 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3174 m_cbEnable->Show(
true);
3179 switch (m_plugin.m_status) {
3180 case PluginStatus::LegacyUpdateAvailable:
3181 label = _(
"Upgrade to Version ");
3182 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3183 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3184 m_pButtonAction->Enable();
3187 case PluginStatus::ManagedInstallAvailable:
3188 label = _(
"Install...");
3189 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3190 m_pButtonAction->Enable();
3193 case PluginStatus::ManagedInstalledUpdateAvailable:
3194 label = _(
"Update to ");
3195 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3196 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3197 m_pButtonAction->Enable();
3200 case PluginStatus::ManagedInstalledCurrentVersion:
3201 label = _(
"Reinstall");
3202 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3203 m_pButtonAction->Enable();
3206 case PluginStatus::ManagedInstalledDowngradeAvailable:
3207 label = _(
"Downgrade");
3208 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3209 m_pButtonAction->Enable();
3212 case PluginStatus::Imported:
3213 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3214 label = _(
"Update");
3215 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3217 m_pButtonAction->Hide();
3218 m_action = ActionVerb::NOP;
3223 m_action = ActionVerb::NOP;
3224 m_pButtonAction->Hide();
3228 m_action = ActionVerb::NOP;
3229 m_pButtonAction->Hide();
3234 m_action = ActionVerb::NOP;
3237 SetActionLabel(label);
3240 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3249 m_pButtons->Show(
false);
3252 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3253 m_cbEnable->Show(
false);
3269 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3271 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3274 SetEnabled(m_plugin.m_enabled);
3289void PluginPanel::OnPaint(wxPaintEvent& event) {
3292 int penWidth = m_penWidthUnselected;
3293 wxColour color = GetDialogColor(DLG_UNSELECTED_BACKGROUND);
3294 wxColour border = GetDialogColor(DLG_UNSELECTED_ACCENT);
3297 penWidth = m_penWidthSelected;
3298 color = GetDialogColor(DLG_SELECTED_BACKGROUND);
3299 border = GetDialogColor(DLG_SELECTED_ACCENT);
3302 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3304 dc.SetPen(wxPen(border, penWidth));
3306 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3309void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3310 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3313 androidDisableRotation();
3324void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3325 SetEnabled(event.IsChecked());
3326 m_pVersion->SetLabel(
3331 PluginLoader::GetInstance()->evt_pluglist_change.
Notify();
3335void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3336 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
3339 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3340 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3341 actionEvent.SetClientData(
this);
3342 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3345void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3347 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3348 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3349 actionEvent.SetClientData(
this);
3350 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3355static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3356 auto font = window->GetFont();
3357 font.SetStyle(style);
3358 window->SetFont(font);
3361void PluginPanel::SetEnabled(
bool enabled) {
3362 if (m_is_safe_panel)
return;
3364 PluginLoader::GetInstance()->UpdatePlugIns();
3365 NotifySetupOptionsPlugin(&m_plugin);
3366 if (!enabled && !m_bSelected) {
3367 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3368 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3369 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3372 m_pVersion->Disable();
3373 m_pDescription->Disable();
3376 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3377 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3378 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3381 m_pVersion->Enable();
3382 m_pDescription->Enable();
3387 m_pName->Enable(enabled || m_bSelected);
3388 m_pVersion->Enable(enabled || m_bSelected);
3389 m_pDescription->Enable(enabled || m_bSelected);
3393 wxString description = m_plugin.m_long_description;
3394 if (description.IsEmpty())
3395 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3398 g_options->GetSize().x * 7 / 10);
3399 m_pDescription->SetLabel(wrapper.GetWrapped());
3400 if (m_plugin.m_managed_metadata.info_url.size()) {
3401 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3405 wxString description = m_plugin.m_short_description;
3406 if (description.IsEmpty())
3407 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3409 g_options->GetSize().x * 7 / 10);
3410 m_pDescription->SetLabel(wrapper.GetWrapped());
3413 m_pButtonPreferences->Enable(enabled &&
3415 m_cbEnable->SetValue(enabled);
3418void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3419 m_PluginListPanel->MoveUp(
this);
3422void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3423 m_PluginListPanel->MoveDown(
this);
3428 : wxPanel(parent), m_url(url) {
3429 auto vbox =
new wxBoxSizer(wxVERTICAL);
3430 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3431 button->Enable(strlen(url) > 0);
3434 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3435 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3443PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3445PlugInChartBase::~PlugInChartBase() {}
3454 bool b_allow_overzoom) {
3466 const wxRegion& Region) {
3467 return wxNullBitmap;
3476 wxRegion* pValidRegion) {}
3489 wxRect* pSourceRect) {}
3506 double* plat,
double* plon) {}
3513PlugInChartBaseGL::PlugInChartBaseGL() {}
3515PlugInChartBaseGL::~PlugInChartBaseGL() {}
3519 const wxRegion& Region,
3520 bool b_use_stencil) {
3546PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3548PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3552 const wxRegion& Region,
3553 bool b_use_stencil) {
3559 const wxRegion& Region,
bool b_use_stencil) {
3565 const wxRegion& Region,
bool b_use_stencil) {
3571 return wxNullBitmap;
3575 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3579ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3584wxString PlugInChartBaseExtended::CreateObjDescriptions(
3585 ListOfPI_S57Obj* obj_list) {
3589int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3591int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3593int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3595float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3604PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3606PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3609PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3619PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3621PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3633ChartPlugInWrapper::ChartPlugInWrapper() {}
3635ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3636 m_ppo = ::wxCreateDynamicObject(chart_class);
3640ChartPlugInWrapper::~ChartPlugInWrapper() {
3641 if (m_ppicb)
delete m_ppicb;
3644wxString ChartPlugInWrapper::GetFileSearchMask(
void) {
3651InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3652 ChartInitFlag init_flags) {
3654 wxWindow* pa = wxWindow::FindFocus();
3656 InitReturn ret_val = (InitReturn)m_ppicb->
Init(name, (
int)init_flags);
3660 if (ret_val == INIT_OK) {
3667 m_ID = m_ppicb->
GetID();
3671 m_SE = m_ppicb->
GetSE();
3685 if ((fabs(m_Chart_Skew) < .01) &&
3686 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3688 if (GetChartExtent(&extent)) {
3689 double lon_range = extent.ELON - extent.WLON;
3690 if ((lon_range > 0) &&
3692 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3696 m_overlayENC =
false;
3698 wxCharBuffer buf = m_FullPath.ToUTF8();
3699 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3705 m_ChartType = CHART_TYPE_UNKNOWN;
3706 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3712 if (pc) pc->SetFocus();
3716 return INIT_FAIL_REMOVE;
3720int ChartPlugInWrapper::GetCOVREntries() {
3727int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3734int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3741float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3753int ChartPlugInWrapper::GetNoCOVREntries() {
3763int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3773int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3783float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3793bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3797 pext->NLAT = xpi.
NLAT;
3798 pext->SLAT = xpi.
SLAT;
3799 pext->ELON = xpi.
ELON;
3800 pext->WLON = xpi.
WLON;
3809ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3814 if (!pThumbData->pDIBThumb) {
3815 wxBitmap* pBMPOwnedByChart =
3816 m_ppicb->
GetThumbnail(tnx, tny, m_global_color_scheme);
3817 if (pBMPOwnedByChart) {
3818 wxImage img = pBMPOwnedByChart->ConvertToImage();
3819 pThumbData->pDIBThumb =
new wxBitmap(img);
3821 pThumbData->pDIBThumb = NULL;
3824 pThumbData->Thumb_Size_X = tnx;
3825 pThumbData->Thumb_Size_Y = tny;
3852 pThumbData->ShipX = 0;
3853 pThumbData->ShipY = 0;
3860ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3862bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3866double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3867 bool b_allow_overzoom) {
3874double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3896void RenderRotateToViewPort(
const ViewPort& VPoint) {
3897#ifndef USE_ANDROID_GLES2
3899 glTranslatef(xt, yt, 0);
3900 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3901 glTranslatef(-xt, -yt, 0);
3905void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3906#ifndef USE_ANDROID_GLES2
3908 glTranslatef(xt, yt, 0);
3909 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3910 glTranslatef(-xt, -yt, 0);
3914bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3917 const LLRegion& Region) {
3926 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3927 wxRegion* r = RectRegion.GetNew_wxRegion();
3930 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3931 chart_region.Intersect(Region);
3933 if (!chart_region.Empty()) {
3934 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3936 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3940#ifndef USE_ANDROID_GLES2
3943 RenderRotateToViewPort(VPoint);
3948 glChartCanvas::s_b_useStencil);
3951 glChartCanvas::s_b_useStencil);
3952 UndoRenderRotateToViewPort(VPoint);
3954#ifndef USE_ANDROID_GLES2
3957 glChartCanvas::DisableClipRegion();
3971bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
3972 const wxGLContext& glc,
const ViewPort& VPoint,
3973 const OCPNRegion& RectRegion,
const LLRegion& Region) {
3982 if (!Region.Empty() && ppicb_x) {
3984 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
3985 glChartCanvas::DisableClipRegion();
3988 RenderRotateToViewPort(VPoint);
3991 wxRegion* r = RectRegion.GetNew_wxRegion();
3994 glChartCanvas::s_b_useStencil);
3997 UndoRenderRotateToViewPort(VPoint);
4002 else if (!Region.Empty() &&
4006 wxRegion* r = RectRegion.GetNew_wxRegion();
4009 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4010 chart_region.Intersect(Region);
4012 if (!chart_region.Empty()) {
4013 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4015 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4017 RenderRotateToViewPort(VPoint);
4021 glChartCanvas::s_b_useStencil);
4024 UndoRenderRotateToViewPort(VPoint);
4026 glChartCanvas::DisableClipRegion();
4039bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4046 if (!Region.Empty() && ppicb_x) {
4047 wxRegion* r = Region.GetNew_wxRegion();
4049#ifndef USE_ANDROID_GLES2
4052 RenderRotateToViewPort(VPoint);
4056 glChartCanvas::s_b_useStencil);
4057 UndoRenderRotateToViewPort(VPoint);
4059#ifndef USE_ANDROID_GLES2
4072bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4078 if (Region.IsOk()) {
4079 wxRegion* r = Region.GetNew_wxRegion();
4086 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4087 wxColour nodat_sub = nodat;
4089#ifdef ocpnUSE_ocpnBitmap
4090 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4092 m_pMask =
new wxMask(obmp, nodat_sub);
4093 obmp.SetMask(m_pMask);
4095 dc.SelectObject(obmp);
4106bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4117 if (Region.IsOk() && (pCBx || ppicb)) {
4118 wxRegion* r = Region.GetNew_wxRegion();
4133bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4136 bool ret_val =
false;
4139 if (Region.IsOk()) {
4140 wxRegion* r = Region.GetNew_wxRegion();
4154void ChartPlugInWrapper::ClearPLIBTextList() {
4162bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4166 return m_ppicb->
AdjustVP(pivp_last, pivp_proposed);
4171void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4186void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4190 m_global_color_scheme = cs;
4192 if (pThumbData) pThumbData->pDIBThumb = NULL;
4196 double target_scale_ppm) {
4203void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4204 wxRect* pSourceRect) {
4211double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4213 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4218bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4220 wxCriticalSectionLocker locker(m_critSect);
4229int ChartPlugInWrapper::GetSize_X() {
4236int ChartPlugInWrapper::GetSize_Y() {
4243void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4244 double& pixx,
double& pixy) {
4248void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4249 double* plat,
double* plon) {
4263wxString toSDMM_PlugIn(
int NEflag,
double a,
bool hi_precision) {
4264 return toSDMM(NEflag, a, hi_precision);
4267wxColour GetBaseGlobalColor(wxString colorName) {
4268 return GetGlobalColor(colorName);
4271int OCPNMessageBox_PlugIn(wxWindow* parent,
const wxString& message,
4272 const wxString& caption,
int style,
int x,
int y) {
4273 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4276wxString GetOCPN_ExePath(
void) {
return g_Platform->GetExePath(); }
4278wxString* GetpPlugInLocation() {
return g_Platform->GetPluginDirPtr(); }
4280wxString GetWritableDocumentsDir(
void) {
4281 return g_Platform->GetWritableDocumentsDir();
4286 auto loader = PluginLoader::GetInstance();
4287 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4289 if (pic->m_pplugin == pplugin) {
4299ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4302 ListOfPI_S57Obj* list = NULL;
4316 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4326 ListOfPI_S57Obj* rule_list) {
4337 ret_str = picbx->CreateObjDescriptions(rule_list);
4345wxString PI_GetPLIBColorScheme() {
4349int PI_GetPLIBDepthUnitInt() {
4351 return ps52plib->m_nDepthUnitDisplay;
4356int PI_GetPLIBSymbolStyle() {
4358 return ps52plib->m_nSymbolStyle;
4363int PI_GetPLIBBoundaryStyle() {
4365 return ps52plib->m_nBoundaryStyle;
4375 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4377 ViewPort cvp = CreateCompatibleViewport(*vp);
4382 ObjRazRules rzRules;
4383 rzRules.obj = &cobj;
4384 rzRules.LUP = pContext->LUP;
4385 rzRules.sm_transform_parms = 0;
4386 rzRules.child = NULL;
4387 rzRules.next = NULL;
4389 if (pContext->LUP) {
4390 ps52plib->SetVPointCompat(
4394 ps52plib->PrepareForRender();
4396 return ps52plib->ObjectRenderCheck(&rzRules);
4403int PI_GetPLIBStateHash() {
4405 return ps52plib->GetStateHash();
4410void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4411 chart_context* pctx) {
4414 cobj->att_array = pObj->att_array;
4415 cobj->attVal = pObj->attVal;
4416 cobj->n_attr = pObj->n_attr;
4421 cobj->npt = pObj->npt;
4423 cobj->iOBJL = pObj->iOBJL;
4424 cobj->Index = pObj->Index;
4426 cobj->geoPt = (pt*)pObj->geoPt;
4427 cobj->geoPtz = pObj->geoPtz;
4428 cobj->geoPtMulti = pObj->geoPtMulti;
4430 cobj->m_lat = pObj->m_lat;
4431 cobj->m_lon = pObj->m_lon;
4433 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4434 cobj->x_rate = pObj->x_rate;
4435 cobj->y_rate = pObj->y_rate;
4436 cobj->x_origin = pObj->x_origin;
4437 cobj->y_origin = pObj->y_origin;
4439 cobj->Scamin = pObj->Scamin;
4440 cobj->nRef = pObj->nRef;
4441 cobj->bIsAton = pObj->bIsAton;
4442 cobj->bIsAssociable = pObj->bIsAssociable;
4444 cobj->m_n_lsindex = pObj->m_n_lsindex;
4445 cobj->m_lsindex_array = pObj->m_lsindex_array;
4446 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4449 cobj->m_ls_list_legacy =
4453 cobj->m_ls_list_legacy = 0;
4454 cobj->m_ls_list = 0;
4457 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4459 cobj->m_bcategory_mutable =
true;
4463 if (pObj->m_DPRI == -1) {
4465 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4467 cobj->m_DPRI = pObj->m_DPRI;
4470 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4471 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4473 if (pObj->auxParm3 != 1234) {
4474 pObj->auxParm3 = 1234;
4475 pObj->auxParm0 = -99;
4478 cobj->auxParm0 = pObj->auxParm0;
4485 if (pContext->bBBObj_valid)
4487 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4488 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4490 cobj->CSrules = pContext->CSrules;
4491 cobj->bCS_Added = pContext->bCS_Added;
4493 cobj->FText = pContext->FText;
4494 cobj->bFText_Added = pContext->bFText_Added;
4495 cobj->rText = pContext->rText;
4497 cobj->bIsClone =
true;
4500 cobj->m_chart_context = pctx;
4501 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4504 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4505 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4506 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4507 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4508 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4509 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4510 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4511 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4513 cobj->m_chart_context->chart =
4515 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4529 CreateCompatibleS57Object(pObj, &cobj, NULL);
4531 LUPname LUP_Name = PAPER_CHART;
4534 ctx->CSrules = NULL;
4535 ctx->bCS_Added =
false;
4538 if (ctx->bFText_Added) {
4539 ctx->bFText_Added =
false;
4545 ctx->bBBObj_valid =
true;
4550 switch (cobj.Primitive_type) {
4555 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4556 LUP_Name = PAPER_CHART;
4558 LUP_Name = SIMPLIFIED;
4567 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4568 LUP_Name = PLAIN_BOUNDARIES;
4570 LUP_Name = SYMBOLIZED_BOUNDARIES;
4575 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4579 ps52plib->_LUP2rules(lup, &cobj);
4581 ctx->MPSRulesList = NULL;
4589 pContext->bBBObj_valid =
true;
4595void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4596 ObjRazRules* rzRules) {
4600 pContext->CSrules = cobj->CSrules;
4601 pContext->bCS_Added = cobj->bCS_Added;
4603 pContext->FText = cobj->FText;
4604 pContext->bFText_Added = cobj->bFText_Added;
4605 pContext->rText = cobj->rText;
4607 if (cobj->BBObj.GetValid()) {
4610 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4611 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4612 pContext->bBBObj_valid =
true;
4617 pObj->m_DisplayCat = (
PI_DisCat)cobj->m_DisplayCat;
4621 pContext->ChildRazRules = rzRules->child;
4622 pContext->MPSRulesList = rzRules->mps;
4624 pObj->auxParm0 = cobj->auxParm0;
4627bool PI_GetObjectRenderBox(
PI_S57Obj* pObj,
double* lat_min,
double* lat_max,
4628 double* lon_min,
double* lon_max) {
4631 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4632 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4633 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4634 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4635 return pContext->bBBObj_valid;
4643 LUPrec* lup = pContext->LUP;
4652 LUPrec* lup = pContext->LUP;
4662 LUPrec* lup = pContext->LUP;
4667double PI_GetPLIBMarinerSafetyContour() {
4668 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4671void PI_PLIBSetLineFeaturePriority(
PI_S57Obj* pObj,
int prio) {
4675 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4680 ObjRazRules rzRules;
4681 rzRules.obj = &cobj;
4682 rzRules.LUP = pContext->LUP;
4683 rzRules.sm_transform_parms = 0;
4684 rzRules.child = NULL;
4685 rzRules.next = NULL;
4686 rzRules.mps = pContext->MPSRulesList;
4688 if (pContext->LUP) {
4689 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4692 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4696void PI_PLIBPrepareForNewRender(
void) {
4698 ps52plib->PrepareForRender();
4699 ps52plib->ClearTextList();
4702 ps52plib->EnableGLLS(
true);
4704 ps52plib->EnableGLLS(
false);
4708void PI_PLIBSetRenderCaps(
unsigned int flags) { gs_plib_flags = flags; }
4710void PI_PLIBFreeContext(
void* pContext) {
4713 if (pctx->ChildRazRules) {
4714 ObjRazRules* ctop = pctx->ChildRazRules;
4718 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4720 ObjRazRules* cnxx = ctop->next;
4726 if (pctx->MPSRulesList) {
4727 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4728 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4730 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4731 ps52plib->DestroyRulesChain(top);
4733 delete pctx->MPSRulesList->cs_rules;
4735 free(pctx->MPSRulesList);
4747 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4754 &transform.easting_vp_center, &transform.northing_vp_center);
4757 ObjRazRules rzRules;
4758 rzRules.obj = &cobj;
4759 rzRules.LUP = pContext->LUP;
4760 rzRules.sm_transform_parms = &transform;
4761 rzRules.child = pContext->ChildRazRules;
4762 rzRules.next = NULL;
4763 rzRules.mps = pContext->MPSRulesList;
4765 if (pContext->LUP) {
4766 ViewPort cvp = CreateCompatibleViewport(*vp);
4772 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4774 ps52plib->PrepareForRender();
4776 ps52plib->RenderObjectToDC(pdc, &rzRules);
4779 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4786 wxRect rect,
unsigned char* pixbuf) {
4788 render_canvas_parms pb_spec;
4790 pb_spec.depth = BPP;
4791 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4792 pb_spec.lclip = rect.x;
4793 pb_spec.rclip = rect.x + rect.width - 1;
4794 pb_spec.pix_buff = pixbuf;
4795 pb_spec.width = rect.width;
4796 pb_spec.height = rect.height;
4799#ifdef ocpnUSE_ocpnBitmap
4800 pb_spec.b_revrgb =
true;
4802 pb_spec.b_revrgb =
false;
4805 pb_spec.b_revrgb =
false;
4810 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4817 &transform.easting_vp_center, &transform.northing_vp_center);
4820 ObjRazRules rzRules;
4821 rzRules.obj = &cobj;
4822 rzRules.LUP = pContext->LUP;
4823 rzRules.sm_transform_parms = &transform;
4824 rzRules.child = pContext->ChildRazRules;
4825 rzRules.next = NULL;
4826 rzRules.mps = pContext->MPSRulesList;
4828 ViewPort cvp = CreateCompatibleViewport(*vp);
4836 if (!tess)
return 1;
4838 PolyTriGroup* ptg =
new PolyTriGroup;
4839 ptg->tri_prim_head =
4840 tess->Get_PolyTriGroup_head()->tri_prim_head;
4841 ptg->bsingle_alloc =
false;
4842 ptg->data_type = DATA_TYPE_DOUBLE;
4843 tess->Set_PolyTriGroup_head(ptg);
4845 double* pd = (
double*)malloc(
sizeof(
double));
4850 if (pContext->LUP) {
4855 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4857 ps52plib->PrepareForRender();
4859 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4862 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4868int PI_PLIBRenderAreaToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4874 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4885 if (!tess)
return 1;
4889 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4890 ptg->bsingle_alloc =
false;
4891 ptg->data_type = DATA_TYPE_DOUBLE;
4892 tess->Set_PolyTriGroup_head(ptg);
4896 double* pd = (
double*)malloc(
sizeof(
double));
4913 &transform.easting_vp_center, &transform.northing_vp_center);
4916 ObjRazRules rzRules;
4917 rzRules.obj = &cobj;
4918 rzRules.LUP = pContext->LUP;
4919 rzRules.sm_transform_parms = &transform;
4920 rzRules.child = pContext->ChildRazRules;
4921 rzRules.next = NULL;
4922 rzRules.mps = pContext->MPSRulesList;
4924 if (pContext->LUP) {
4925 ViewPort cvp = CreateCompatibleViewport(*vp);
4931 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4933 ps52plib->PrepareForRender();
4935 ps52plib->RenderAreaToGL(glcc, &rzRules);
4938 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4945int PI_PLIBRenderObjectToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4950 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4957 &transform.easting_vp_center, &transform.northing_vp_center);
4960 ObjRazRules rzRules;
4961 rzRules.obj = &cobj;
4962 rzRules.LUP = pContext->LUP;
4963 rzRules.sm_transform_parms = &transform;
4964 rzRules.child = pContext->ChildRazRules;
4965 rzRules.next = NULL;
4966 rzRules.mps = pContext->MPSRulesList;
4968 if (pContext->LUP) {
4969 ViewPort cvp = CreateCompatibleViewport(*vp);
4975 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4977 ps52plib->PrepareForRender();
4979 ps52plib->RenderObjectToGL(glcc, &rzRules);
4982 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4992OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
4993 : wxEvent(id, commandType) {
4996 m_b_complete =
false;
5000OCPN_downloadEvent::~OCPN_downloadEvent() {}
5002wxEvent* OCPN_downloadEvent::Clone()
const {
5004 newevent->m_stat = this->m_stat;
5005 newevent->m_condition = this->m_condition;
5007 newevent->m_totalBytes = this->m_totalBytes;
5008 newevent->m_sofarBytes = this->m_sofarBytes;
5009 newevent->m_b_complete = this->m_b_complete;
5015DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5020#define DL_EVENT_TIMER 4388
5028 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5029 void clearBackgroundMode();
5030 void onTimerEvent(wxTimerEvent& event);
5033 wxTimer m_eventTimer;
5034 wxEvtHandler* m_download_evHandler;
5040PI_DLEvtHandler::PI_DLEvtHandler() {
5044 m_download_evHandler = NULL;
5050PI_DLEvtHandler::~PI_DLEvtHandler() {
5051 m_eventTimer.Stop();
5054 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5061 g_download_status =
event.getDLEventStatus();
5062 g_download_condition =
event.getDLEventCondition();
5065 if (m_download_evHandler &&
5068 ev.setComplete(
true);
5069 ev.setTransferred(m_sofarBytes);
5070 ev.setTotal(m_totalBytes);
5072 ev.setDLEventStatus(event.getDLEventStatus());
5075 m_download_evHandler->AddPendingEvent(ev);
5076 m_eventTimer.Stop();
5078 finishAndroidFileDownload();
5085void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5087 m_download_evHandler = handler;
5089 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5093 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5094 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5097void PI_DLEvtHandler::clearBackgroundMode() {
5098 m_download_evHandler = NULL;
5099 m_eventTimer.Stop();
5102void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5108 int stat = queryAndroidFileDownload(m_id, &sstat);
5111 long sofarBytes = 0;
5112 long totalBytes = -1;
5116 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5117 ev.setComplete(
true);
5118 ev.setTransferred(sofarBytes);
5119 ev.setTotal(totalBytes);
5124 wxStringTokenizer tk(sstat, _T(
";"));
5125 if (tk.HasMoreTokens()) {
5126 wxString token = tk.GetNextToken();
5127 token.ToLong(&state);
5128 token = tk.GetNextToken();
5129 token.ToLong(&sofarBytes);
5130 token = tk.GetNextToken();
5131 token.ToLong(&totalBytes);
5134 qDebug() << state << sofarBytes << totalBytes;
5136 m_sofarBytes = sofarBytes;
5137 m_totalBytes = totalBytes;
5139 ev.setTransferred(sofarBytes);
5140 ev.setTotal(totalBytes);
5143 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5144 ev.setComplete(
true);
5147 }
else if (state == 8) {
5148 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5149 ev.setComplete(
true);
5153 ev.setComplete(
false);
5161 if (m_download_evHandler) {
5163 m_download_evHandler->AddPendingEvent(ev);
5168 m_eventTimer.Stop();
5169 finishAndroidFileDownload();
5179 const wxString& outputFile,
5180 const wxString& title,
const wxString& message,
5181 const wxBitmap& bitmap, wxWindow* parent,
5182 long style,
int timeout_secs) {
5185 wxString msg = _T(
"Downloading file synchronously: ");
5192 int vres = validateAndroidWriteLocation(outputFile);
5204 g_piEventHandler->Connect(
5205 wxEVT_DOWNLOAD_EVENT,
5206 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5211 wxString fURI = outputFile;
5212 if (!fURI.StartsWith(_T(
"file://"))) {
5213 fURI.Prepend(_T(
"file://"));
5216 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5219 finishAndroidFileDownload();
5220 g_piEventHandler->Disconnect(
5221 wxEVT_DOWNLOAD_EVENT,
5222 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5227 wxDateTime dl_start_time = wxDateTime::Now();
5231 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5232 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5234 if (dt.GetSeconds() > timeout_secs) {
5235 qDebug() <<
"USER_TIMOUT";
5236 finishAndroidFileDownload();
5237 g_piEventHandler->Disconnect(
5238 wxEVT_DOWNLOAD_EVENT,
5239 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5247 finishAndroidFileDownload();
5248 g_piEventHandler->Disconnect(
5249 wxEVT_DOWNLOAD_EVENT,
5253 qDebug() <<
"RETURN DL_END" << (int)ss;
5259 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5261 qDebug() <<
"Error on queryAndroidFileDownload";
5262 finishAndroidFileDownload();
5263 g_piEventHandler->Disconnect(
5264 wxEVT_DOWNLOAD_EVENT,
5265 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5275#elif defined(OCPN_USE_CURL)
5276 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5277 wxFileOutputStream output(tfn.GetFullPath());
5279 wxCurlDownloadDialog ddlg(url, &output, title, message + url, bitmap, parent,
5281 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5287 case wxCDRF_SUCCESS: {
5288 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5294 case wxCDRF_FAILED: {
5298 case wxCDRF_USER_ABORTED: {
5306 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5314wxString toUsrDateTimeFormat_Plugin(
const wxDateTime date_time,
5316 return ocpn::toUsrDateTimeFormat(date_time,
options);
5321 const wxString& outputFile,
5322 wxEvtHandler* handler,
5325 wxString msg = _T(
"Downloading file asynchronously: ");
5337 int res = startAndroidFileDownload(url, outputFile, NULL ,
5341 finishAndroidFileDownload();
5346 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5348 if (handle) *handle = dl_ID;
5352#elif defined(OCPN_USE_CURL)
5353 if (g_pi_manager->m_pCurlThread)
5357 g_pi_manager->m_pCurlThread =
5358 new wxCurlDownloadThread(g_pi_manager, CurlThreadId);
5359 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5361 if (http && g_pi_manager->m_pCurl &&
5362 dynamic_cast<wxCurlHTTP*
>(g_pi_manager->m_pCurl.get())) {
5366 g_pi_manager->m_pCurl = 0;
5369 bool failed =
false;
5370 if (!g_pi_manager->HandleCurlThreadError(
5371 g_pi_manager->m_pCurlThread->SetURL(url, g_pi_manager->m_pCurl),
5372 g_pi_manager->m_pCurlThread, url))
5375 g_pi_manager->m_pCurl = g_pi_manager->m_pCurlThread->GetCurlSharedPtr();
5376 if (!g_pi_manager->HandleCurlThreadError(
5377 g_pi_manager->m_pCurlThread->SetOutputStream(
5378 new wxFileOutputStream(outputFile)),
5379 g_pi_manager->m_pCurlThread))
5383 g_pi_manager->m_download_evHandler = handler;
5384 g_pi_manager->m_downloadHandle = handle;
5386 wxCurlThreadError err = g_pi_manager->m_pCurlThread->Download();
5387 if (err != wxCTE_NO_ERROR) {
5388 g_pi_manager->HandleCurlThreadError(
5389 err, g_pi_manager->m_pCurlThread);
5390 g_pi_manager->m_pCurlThread->Abort();
5397 if (g_pi_manager->m_pCurlThread) {
5398 if (g_pi_manager->m_pCurlThread->IsAlive())
5399 g_pi_manager->m_pCurlThread->Abort();
5400 if (g_pi_manager->m_pCurlThread->GetOutputStream())
5401 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5402 wxDELETE(g_pi_manager->m_pCurlThread);
5403 g_pi_manager->m_download_evHandler = NULL;
5404 g_pi_manager->m_downloadHandle = NULL;
5407 g_pi_manager->m_pCurl = 0;
5415void OCPN_cancelDownloadFileBackground(
long handle) {
5419 cancelAndroidFileDownload(handle);
5420 finishAndroidFileDownload();
5421 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5423 if (g_pi_manager->m_pCurlThread) {
5424 g_pi_manager->m_pCurlThread->Abort();
5425 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5426 wxDELETE(g_pi_manager->m_pCurlThread);
5427 g_pi_manager->m_download_evHandler = NULL;
5428 g_pi_manager->m_downloadHandle = NULL;
5430 g_pi_manager->m_pCurl = 0;
5436 const wxString& parameters, wxString& result,
5439 wxString lparms = parameters;
5440 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5443 result = postResult;
5446#elif defined(OCPN_USE_CURL)
5448 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5449 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5452 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5455 result = wxEmptyString;
5464bool OCPN_isOnline() {
5466 return androidCheckOnline();
5469#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5470 if (wxDateTime::GetTimeNow() >
5471 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5473 get.Head(_T(
"http://yahoo.com/"));
5474 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5476 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5478 return g_pi_manager->m_last_online;
5484#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5485void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5487 if (ev.IsSuccessful()) {
5490 g_pi_manager->m_pCurl = 0;
5494 event.setComplete(
true);
5496 if (m_download_evHandler) {
5497 m_download_evHandler->AddPendingEvent(event);
5498 m_download_evHandler = NULL;
5499 m_downloadHandle = NULL;
5502 if (m_pCurlThread) {
5503 m_pCurlThread->Wait();
5504 if (!m_pCurlThread->IsAborting()) {
5505 delete (m_pCurlThread->GetOutputStream());
5506 wxDELETE(m_pCurlThread);
5511void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5515 event.setTotal(ev.GetTotalBytes());
5516 event.setTransferred(ev.GetDownloadedBytes());
5517 event.setComplete(
false);
5519 if (m_download_evHandler) {
5520 m_download_evHandler->AddPendingEvent(event);
5524bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5525 wxCurlBaseThread* p,
5526 const wxString& url) {
5528 case wxCTE_NO_ERROR:
5531 case wxCTE_NO_RESOURCE:
5533 wxS(
"Insufficient resources for correct execution of the program."));
5536 case wxCTE_ALREADY_RUNNING:
5540 case wxCTE_INVALID_PROTOCOL:
5541 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5545 case wxCTE_NO_VALID_STREAM:
5552 case wxCTE_CURL_ERROR: {
5553 wxString ws = wxS(
"unknown");
5554 if (p->GetCurlSession())
5556 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5557 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5562 if (p->IsAlive()) p->Abort();
Plugin catalog management: Build the runtime catalog, handling downloads as required.
EventVar plugin_msg
A JSON message should be sent.
Handle messages for blacklisted plugins.
Modal dialog for plugin catalog settings.
ChartCanvas - Main chart display and interaction component.
Manages the chart database and provides access to chart data.
Wrapper class for plugin-based charts.
virtual double GetNearestPreferredScalePPM(double target_scale_ppm)
Find the nearest preferred viewport scale (in pixels/meter) for this chart.
const std::vector< DriverPtr > & GetDrivers() const
Wrapper for configuration variables which lives in a wxBaseConfig object.
const void Notify()
Notify all listeners, no data supplied.
Wrapper for global variable, supports notification events when value changes.
Downloader with progress and final message dialogs.
static std::string MessageKey(const char *type="ALL")
Return key which should be used to listen to given message type.
An iterator class for OCPNRegion.
A wrapper class for wxRegion with additional functionality.
void Init(const KeyProvider &kp, std::function< void(ObservedEvt &ev)> action)
Initiate an object yet not listening.
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listener on changes in key.
Custom event class for OpenCPN's notification system.
std::shared_ptr< const void > GetSharedPtr() const
Gets the event's payload data.
Class representing an S-57 chart object.
double lon_max
Bounding box maximum longitude.
double lon_min
Bounding box minimum longitude.
double lat_max
Bounding box maximum latitude.
int auxParm0
Auxiliary parameter 0.
void * pPolyTessGeo
Tesselated polygon geometry.
double chart_ref_lon
Chart reference longitude.
double * geoPtMulti
Lat/lon pairs for decomposed points.
void * S52_Context
S52 presentation data.
double chart_ref_lat
Chart reference latitude.
char FeatureName[8]
S-57 feature type code (e.g., "DEPARE")
double lat_min
Bounding box minimum latitude.
int Primitive_type
Geometry type (point, line, area)
Represents a line segment element for efficient vector chart rendering.
Extended chart base class with separated text rendering.
virtual wxBitmap & RenderRegionViewOnDCNoText(const PlugIn_ViewPort &VPoint, const wxRegion &Region)
Standard DC rendering without text.
virtual bool RenderRegionViewOnDCTextOnly(wxMemoryDC &dc, const PlugIn_ViewPort &VPoint, const wxRegion &Region)
Standard DC text-only rendering.
virtual void ClearPLIBTextList()
Clears any cached text elements.
virtual int RenderRegionViewOnGLNoText(const wxGLContext &glc, const PlugIn_ViewPort &VPoint, const wxRegion &Region, bool b_use_stencil)
OpenGL rendering without text.
virtual int RenderRegionViewOnGLTextOnly(const wxGLContext &glc, const PlugIn_ViewPort &VPoint, const wxRegion &Region, bool b_use_stencil)
OpenGL text-only rendering.
virtual int RenderRegionViewOnGL(const wxGLContext &glc, const PlugIn_ViewPort &VPoint, const wxRegion &Region, bool b_use_stencil)
OpenGL rendering with combined text and graphics.
virtual ListOfPI_S57Obj * GetLightsObjRuleListVisibleAtLatLon(float lat, float lon, PlugIn_ViewPort *VPoint)
Gets list of visible light objects at specified position.
OpenGL-optimized chart base class for plugin chart types.
virtual int GetNoCOVRTablenPoints(int iTable)
Alternative to GetNoCOVRTablePoints().
virtual int GetNoCOVREntries()
Gets number of no-coverage areas in chart.
virtual int GetNoCOVRTablePoints(int iTable)
Gets number of points in no-coverage area boundary.
virtual wxString CreateObjDescriptions(ListOfPI_S57Obj *obj_list)
Creates description text for chart objects.
virtual float * GetNoCOVRTableHead(int iTable)
Gets coordinate data for no-coverage area boundary.
virtual int RenderRegionViewOnGL(const wxGLContext &glc, const PlugIn_ViewPort &VPoint, const wxRegion &Region, bool b_use_stencil)
Renders chart content using OpenGL.
virtual ListOfPI_S57Obj * GetObjRuleListAtLatLon(float lat, float lon, float select_radius, PlugIn_ViewPort *VPoint)
Gets chart objects near specified position.
Base class for implementing custom chart types in OpenCPN plugins.
virtual void SetColorScheme(int cs, bool bApplyImmediate)
Sets the color scheme for chart display.
virtual bool GetChartExtent(ExtentPI *pext)
Gets the geographic boundaries of the chart.
virtual void chartpix_to_latlong(double pixx, double pixy, double *plat, double *plon)
Converts chart pixel coordinates to geographic coordinates.
virtual double GetNearestPreferredScalePPM(double target_scale_ppm)
Returns the nearest preferred scale value for this chart.
virtual double GetNormalScaleMin(double canvas_scale_factor, bool b_allow_overzoom)
Returns the minimum recommended scale for this chart.
virtual wxBitmap & RenderRegionView(const PlugIn_ViewPort &VPoint, const wxRegion &Region)
Renders a region of the chart for display.
virtual ChartFamilyEnumPI GetChartFamily()
Returns the chart family classification.
virtual wxString GetID()
Returns a unique identifier for the chart.
virtual wxString GetDatumString()
Returns the horizontal geodetic datum of the chart.
virtual wxString GetName()
Returns the chart's name or title.
virtual double GetRasterScaleFactor()
Returns the scale factor for raster chart rendering.
virtual wxDateTime GetEditionDate(void)
Returns the edition date of the chart.
virtual int GetCOVRTablenPoints(int iTable)
Alternative method to get the number of points in a coverage table entry.
virtual bool GetChartBits(wxRect &source, unsigned char *pPix, int sub_samp)
Gets pixel data for a portion of a raster chart.
virtual int GetCOVREntries()
Returns the number of coverage table entries for this chart.
virtual double GetNormalScaleMax(double canvas_scale_factor, int canvas_width)
Returns the maximum recommended scale for this chart.
virtual wxString GetSoundingsDatum()
Returns the vertical datum used for soundings in the chart.
virtual wxString GetExtraInfo()
Returns additional information about the chart.
virtual int GetSize_X()
Gets the width of the chart in pixels.
virtual wxString GetFullPath() const
Returns the full file path of the chart.
virtual wxString GetSE()
Returns the chart's source edition identifier.
virtual bool IsReadyToRender()
Indicates whether the chart is ready for rendering.
virtual int GetNativeScale()
Returns the native scale of the chart.
virtual double GetChartSkew()
Returns the skew/rotation angle of the chart.
virtual wxString GetDepthUnits()
Returns the depth units used in the chart.
virtual int Init(const wxString &full_path, int init_flags)
Initializes a chart instance from a file.
virtual wxString GetFileSearchMask(void)
Returns file pattern(s) for chart files this plugin can handle.
virtual int GetSize_Y()
Gets the height of the chart in pixels.
virtual void latlong_to_chartpix(double lat, double lon, double &pixx, double &pixy)
Converts geographic coordinates to chart pixel coordinates.
virtual void ComputeSourceRectangle(const PlugIn_ViewPort &vp, wxRect *pSourceRect)
Computes the source rectangle for the chart based on a given viewport.
virtual float * GetCOVRTableHead(int iTable)
Returns a pointer to the coverage table data for a specific entry.
virtual double GetChartErrorFactor()
Returns the error factor for the chart.
virtual OcpnProjTypePI GetChartProjection()
Returns the projection type used by the chart.
virtual wxBitmap * GetThumbnail(int tnx, int tny, int cs)
Generates a thumbnail image of the chart.
virtual ChartTypeEnumPI GetChartType()
Returns the chart type identifier.
virtual void GetValidCanvasRegion(const PlugIn_ViewPort &VPoint, wxRegion *pValidRegion)
Determines the valid display area for this chart.
virtual bool AdjustVP(PlugIn_ViewPort &vp_last, PlugIn_ViewPort &vp_proposed)
Adjusts viewport parameters for chart-specific requirements.
virtual int GetCOVRTablePoints(int iTable)
Returns the number of points in a specific coverage table entry.
virtual ChartDepthUnitTypePI GetDepthUnitId()
Returns the depth unit type identifier.
Data for a loaded plugin, including dl-loaded library.
Basic data for a loaded plugin, trivially copyable.
wxString m_plugin_filename
The short file path.
wxString m_plugin_file
The full file path.
int m_cap_flag
PlugIn Capabilities descriptor.
wxString m_common_name
A common name string for the plugin.
void HandleN0183(std::shared_ptr< const Nmea0183Msg > n0183_msg)
Process incoming NMEA 0183 messages from the message bus.
void HandleSignalK(std::shared_ptr< const SignalkMsg > sK_msg)
Process incoming SignalK messages from the message bus.
Contains view parameters and status information for a chart display viewport.
double view_scale_ppm
Display scale in pixels per meter.
wxRect rv_rect
Rectangle defining the rendered view area.
int pix_width
Viewport width in pixels.
double lon_max
Maximum longitude of the viewport.
double clon
Center longitude of the viewport in decimal degrees.
double lat_max
Maximum latitude of the viewport.
int pix_height
Viewport height in pixels.
double clat
Center latitude of the viewport in decimal degrees.
double skew
Display skew angle in radians.
double rotation
Display rotation angle in radians.
bool bValid
True if this viewport is valid and can be used for rendering.
double lon_min
Minimum longitude of the viewport.
double lat_min
Minimum latitude of the viewport.
int m_projection_type
Chart projection type (PROJECTION_MERCATOR, etc.)
bool b_quilt
True if the viewport is in quilt mode (showing multiple charts)
float chart_scale
Conventional chart displayed scale (e.g., 1:50000)
const std::vector< PluginMetadata > getInstalled()
Return list of all installed and loaded plugins.
static std::string ImportedMetadataPath(std::string name)
Return path to imported metadata for given plugin.
std::vector< std::string > GetInstalldataPlugins()
Return list of installed plugins lower case names, not necessarily loaded.
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 and loaded plugin.
bool ClearInstallData(const std::string plugin_name)
Remove installation data for not loaded plugin.
void SetInstalledMetadata(const PluginMetadata &pm)
Set metadata for 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.
bool LoadAllPlugIns(bool enabled_plugins, bool keep_orphans=false)
Update catalog with imported metadata and load all plugin library files.
static std::string GetPluginVersion(const PlugInData pd, std::function< const PluginMetadata(const std::string &)> get_metadata)
Return version string for a plugin, possibly with an "Imported" suffix.
void SortPlugins(int(*cmp_func)(PlugInContainer **, PlugInContainer **))
Sort GetPluginArray().
static void UpdatePlugin(PlugInContainer *plugin, const PluginMetadata &md)
Update PlugInContainer status using data from PluginMetadata and manifest.
void SetEnabled(const wxString &common_name, bool enabled)
Update enabled/disabled state for plugin with given name.
static PluginMetadata MetadataByName(const std::string &name)
Find metadata for given plugin.
void ShowPreferencesDialog(const PlugInData &pd, wxWindow *parent)
Display the preferences dialog for a plugin.
PluginPanel(wxPanel *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, const PlugInData plugin)
An entry in the list of plugins presented by Options | Plugins.
EventVar json_msg
Notified with message targeting all plugins.
EventVar json_leg_info
Notified with a shared_ptr<ActiveLegDat>, leg info to all plugins.
EventVar on_message_sent
Notified when a message available as GetString() is sent to garmin.
A parsed SignalK message over ipv4.
Modal dialog, displays available updates (possibly just one) and lets user select and eventually conf...
ViewPort - Core geographic projection and coordinate transformation engine.
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
double ref_scale
The nominal scale of the "reference chart" for this view.
int pix_height
Height of the viewport in physical pixels.
void SetBoxes(void)
Computes the bounding box coordinates for the current viewport.
double rotation
Rotation angle of the viewport in radians.
int pix_width
Width of the viewport in physical pixels.
double skew
Angular distortion (shear transform) applied to the viewport in radians.
double clon
Center longitude of the viewport in degrees.
double clat
Center latitude of the viewport in degrees.
double chart_scale
Chart scale denominator (e.g., 50000 for a 1:50000 scale).
Device context class that can use either wxDC or OpenGL for drawing.
virtual void PrepareContextMenu(int canvasIndex)
Prepares plugin context menu items.
virtual bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvasIndex)
Renders plugin overlay graphics with canvas selection.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex)
Renders plugin overlay graphics in OpenGL mode with canvas selection.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex, int priority)
Render plugin overlay over chart canvas in OpenGL mode.
virtual bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvas_ix, int priority)
Render plugin overlay over chart canvas in non-OpenGL mode.
virtual bool RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in standard (non-OpenGL) mode.
virtual bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in OpenGL mode.
Base class for OpenCPN plugins.
virtual void OnCloseToolboxPanel(int page_sel, int ok_apply_cancel)
Handles preference page closure.
virtual void SetCurrentViewPort(PlugIn_ViewPort &vp)
Notifies plugin of viewport changes.
virtual void UpdateAuiStatus(void)
Updates AUI manager status.
virtual void SetColorScheme(PI_ColorScheme cs)
Updates plugin color scheme.
virtual wxArrayString GetDynamicChartClassNameArray(void)
Returns array of dynamically loaded chart class names.
virtual int GetPlugInVersionMajor()
Returns the major version number of the plugin itself.
virtual bool RenderOverlay(wxMemoryDC *pmdc, PlugIn_ViewPort *vp)
Render plugin overlay graphics using standard device context.
virtual void ProcessParentResize(int x, int y)
Handles parent window resize events.
virtual int GetPlugInVersionMinor()
Returns the minor version number of the plugin itself.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
The JSON document writer.
void Write(const wxJSONValue &value, wxString &str)
Write the JSONvalue object to a JSON text.
DriverPtr & FindDriver(const std::vector< DriverPtr > &drivers, const std::string &iface, const NavAddr::Bus _bus)
Search list of drivers for a driver with given interface string.
Driver registration container, a singleton.
Raw messages layer, supports sending and recieving navmsg messages.
Enhanced logging interface on top of wx/log.h.
bool replace(std::string &str, const std::string &from, const std::string &to)
Perform in place substitution in str, replacing "from" with "to".
std::string lookup_tarball(const char *uri)
Get path to tarball in cache for given filename.
std::string tolower(const std::string &input)
Return copy of s with all characters converted to lower case.
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.
enum _PI_DisCat PI_DisCat
Display categories for S52 chart features.
#define INSTALLS_PLUGIN_CHART
Plugin provides new chart type for standard (non-GL) view.
enum _PI_DisPrio PI_DisPrio
Display priority levels for S52 chart objects.
#define PLIB_CAPS_OBJCATMUTATE
Support for object category mutation Allows dynamic changes to object display categories.
#define INSTALLS_CONTEXTMENU_ITEMS
Plugin will add items to chart context menu.
#define WANTS_LATE_INIT
Delay full plugin initialization until system is ready.
_OCPN_DLCondition
Event types for HTTP file download operations.
@ OCPN_DL_EVENT_TYPE_UNKNOWN
Unknown event type.
@ OCPN_DL_EVENT_TYPE_PROGRESS
Download progress update.
@ OCPN_DL_EVENT_TYPE_END
Download has completed.
PI_ColorScheme
Enumeration of color schemes.
#define PLIB_CAPS_SINGLEGEO_BUFFER
Support for single geometry buffers Allows combining multiple geometries into a single buffer.
#define PLIB_CAPS_LINE_BUFFER
Support for line vertex buffers Enables batched line rendering using vertex buffers.
_OCPN_DLStatus
Status codes for HTTP file download operations.
@ OCPN_DL_NO_ERROR
Download completed successfully.
@ OCPN_DL_USER_TIMEOUT
Download timed out waiting for user action.
@ OCPN_DL_STARTED
Download has begun but not yet complete.
@ OCPN_DL_FAILED
Download failed (general error)
@ OCPN_DL_UNKNOWN
Unknown or uninitialized status.
@ OCPN_DL_ABORTED
Download was cancelled by user.
@ PI_CHART_FAMILY_VECTOR
Vector chart formats (S-57, CM93, etc.)
#define INSTALLS_TOOLBOX_PAGE
Plugin will add pages to the toolbox/settings dialog.
enum _PI_LUPname PI_LUPname
Name identifiers for S57 lookup table sets.
#define USES_AUI_MANAGER
Plugin uses wxAuiManager for window management.
#define PLIB_CAPS_OBJSEGLIST
Support for object segment lists Enables breaking complex geometries into optimized segments.
#define INSTALLS_PLUGIN_CHART_GL
Plugin provides new chart type for OpenGL view.
#define WANTS_ONPAINT_VIEWPORT
Receive callbacks during chart viewport painting.
#define WANTS_PREFERENCES
Plugin will add page(s) to global preferences dialog.
#define WANTS_OVERLAY_CALLBACK
Receive callbacks to render custom overlay graphics on the chart.
wxWindow * GetOCPNCanvasWindow()
Gets OpenCPN's main canvas window.
double OCPN_GetDisplayContentScaleFactor()
Gets content scaling factor for current display.
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.
Miscellaneous utilities, many of which string related.
void SendNMEASentenceToAllPlugIns(const wxString &sentence)
Distribute a NMEA 0183 sentence to all plugins that have registered interest by setting the WANTS_NME...
Tools to send data to plugins.
Low level code to load plugins from disk, notably the PluginLoader class.
@ Ghost
Managed, shadowing another (packaged?) plugin.
@ Unmanaged
Unmanaged, probably a package.
@ Managed
Managed by installer.
@ System
One of the four system plugins, unmanaged.
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.
Geographic extent structure defining a bounding box.
double NLAT
Northern latitude boundary in decimal degrees.
double WLON
Western longitude boundary in decimal degrees.
double SLAT
Southern latitude boundary in decimal degrees.
double ELON
Eastern longitude boundary in decimal degrees.