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"
109#include "model/plugin_loader.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);
346wxString message_by_status(PluginStatus stat) {
348 case PluginStatus::System:
349 return _(
"Plugin is a standard system plugin");
350 case PluginStatus::Managed:
351 return _(
"Plugin is managed by OpenCPN");
352 case PluginStatus::Unmanaged:
353 return _(
"Plugin is not managed by OpenCPN");
354 case PluginStatus::Ghost:
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>
379 {{PluginStatus::System,
"emblem-default.svg"},
380 {PluginStatus::Managed,
"emblem-default.svg"},
381 {PluginStatus::Unmanaged,
"emblem-unmanaged.svg"},
382 {PluginStatus::Ghost,
"ghost.svg"},
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(
396 {{PluginStatus::System,
"System"},
397 {PluginStatus::Managed,
"Managed"},
398 {PluginStatus::Unmanaged,
"Unmanaged"},
399 {PluginStatus::Ghost,
"Ghost"},
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) {
1141 ProcessLateInit(pic);
1151 wxString msg(
"PlugInManager: Calling LateInit PlugIn: ");
1156 if (ppi) ppi->LateInit();
1164 ChartData->PurgeCachePlugins();
1165 gFrame->InvalidateAllQuilts();
1168 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1171 if (pttc->m_pplugin == pic->m_pplugin) {
1172 m_PlugInToolbarTools.Remove(pttc);
1178 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1180 if (pimis->m_pplugin == pic->m_pplugin) {
1181 m_PlugInMenuItems.Remove(pimis);
1187bool PlugInManager::IsAnyPlugInChartEnabled() {
1190 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1191 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1193 if (pic->m_enabled && pic->m_init_state) {
1202void PlugInManager::UpdateManagedPlugins() {
1203 PluginLoader::getInstance()->UpdateManagedPlugins(
false);
1204 PluginLoader::getInstance()->
SortPlugins(ComparePlugins);
1207 g_options->itemBoxSizerPanelPlugins->Layout();
1210bool PlugInManager::UpDateChartDataTypes() {
1212 if (NULL == ChartData)
return bret;
1214 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1215 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1218 if (pic->m_init_state) {
1225 if (bret) ChartData->UpdateChartClassDescriptorArray();
1230void PlugInManager::FinalizePluginLoadall() {
1234 SetColorSchemeForAllPlugIns(global_color_scheme);
1237 SendBaseConfigToAllPlugIns();
1238 SendS52ConfigToAllPlugIns(
true);
1239 SendSKConfigToAllPlugIns();
1244 if (gFrame->GetPrimaryCanvas()->GetglCanvas())
1245 gFrame->GetPrimaryCanvas()->GetglCanvas()->SendJSONConfigMessage();
1253void PlugInManager::SetPluginOrder(wxString serialized_names) {
1254 m_plugin_order.Empty();
1255 wxStringTokenizer tokenizer(serialized_names,
";");
1256 while (tokenizer.HasMoreTokens()) {
1257 m_plugin_order.Add(tokenizer.GetNextToken());
1261wxString PlugInManager::GetPluginOrder() {
1262 wxString plugins = wxEmptyString;
1263 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1264 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1265 plugins.Append(plugin_array->Item(i)->m_common_name);
1266 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1271bool PlugInManager::UpdateConfig() {
1275 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1276 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1280 wxString config_section = (_T (
"/PlugIns/" ));
1282 pConfig->SetPath(config_section);
1283 pConfig->Write(_T (
"bEnabled" ), pic->m_enabled);
1290void PlugInManager::ShowDeferredBlacklistMessages() {
1291 m_blacklist_ui->show_deferred_messages();
1294bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1296 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1299bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin* plugin) {
1304 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1305 name.Replace(
"class ", wxEmptyString);
1307 const std::type_info& ti =
typeid(*plugin);
1309 char* realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1310 wxString name = wxString::FromAscii(realname);
1313 return CheckBlacklistedPlugin(name, major, minor);
1316bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
1318 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1319 if (block_status == plug_status::unblocked)
return true;
1320 plug_data data(name.ToStdString(), major, minor);
1321 auto msg = m_blacklist->get_message(block_status, data);
1322 m_blacklist_ui->message(msg);
1326bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC& dc,
1330 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1331 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1333 if (pic->m_enabled && pic->m_init_state) {
1337 wxDC* pdc = dc.GetDC();
1340 switch (pic->m_api_version) {
1342 if (priority > 0)
break;
1349 if (priority > 0)
break;
1352 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1363 if (priority > 0)
break;
1366 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1371 if (priority > 0)
break;
1375 ppi->RenderOverlay(*pdc, &pivp);
1385 if (priority <= 0) {
1389 ppi->RenderOverlay(*pdc, &pivp);
1405 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1407 if ((m_cached_overlay_bm.GetWidth() != vp.
pix_width) ||
1408 (m_cached_overlay_bm.GetHeight() != vp.
pix_height))
1412 mdc.SelectObject(m_cached_overlay_bm);
1413 mdc.SetBackground(*wxBLACK_BRUSH);
1416 bool b_rendered =
false;
1418 switch (pic->m_api_version) {
1420 if (priority > 0)
break;
1427 if (priority > 0)
break;
1430 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1441 if (priority > 0)
break;
1444 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1449 if (priority > 0)
break;
1453 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1464 if (priority <= 0) {
1468 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1475 mdc, &pivp, g_canvasConfig, priority);
1484 mdc.SelectObject(wxNullBitmap);
1487 wxMask* p_msk =
new wxMask(m_cached_overlay_bm, wxColour(0, 0, 0));
1488 m_cached_overlay_bm.SetMask(p_msk);
1490 dc.DrawBitmap(m_cached_overlay_bm, 0, 0,
true);
1493 }
else if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1501bool PlugInManager::RenderAllGLCanvasOverlayPlugIns(wxGLContext* pcontext,
1505 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1506 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1508 if (pic->m_enabled && pic->m_init_state) {
1509 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1512 switch (pic->m_api_version) {
1514 if (priority > 0)
break;
1517 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
1529 if (priority > 0)
break;
1537 if (priority > 0)
break;
1552 if (priority <= 0) {
1577void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort& vp) {
1578 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1579 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1581 if (pic->m_enabled && pic->m_init_state) {
1590void NotifySetupOptionsPlugin(
const PlugInData* pd) {
1591 PluginLoader::getInstance()->NotifySetupOptionsPlugin(pd);
1594void PlugInManager::NotifySetupOptions() {
1595 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1596 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1598 NotifySetupOptionsPlugin(pic);
1603 int ok_apply_cancel) {
1604 if (pic->m_enabled && pic->m_init_state) {
1607 auto loader = PluginLoader::getInstance();
1614void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
1615 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1616 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1619 ClosePlugInPanel(pic, ok_apply_cancel);
1624int PlugInManager::AddCanvasContextMenuItem(wxMenuItem* pitem,
1628 pmic->pmenu_item = pitem;
1629 pmic->m_pplugin = pplugin;
1630 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
1631 : m_plugin_menu_item_id_next;
1633 pmic->b_grey =
false;
1634 pmic->m_in_menu = name;
1636 m_PlugInMenuItems.Add(pmic);
1638 m_plugin_menu_item_id_next++;
1643void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char* name) {
1644 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1647 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1648 m_PlugInMenuItems.Remove(pimis);
1656void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
1658 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1661 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1669void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
1671 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1674 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1675 pimis->b_grey = grey;
1682void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
1683 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1684 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1686 if (pic->m_enabled && pic->m_init_state)
1691void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
1692 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1693 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1695 if (pic->m_enabled && pic->m_init_state)
1700void PlugInManager::PrepareAllPluginContextMenus() {
1701 int canvasIndex = gFrame->GetCanvasIndexUnderMouse();
1702 if (canvasIndex < 0)
return;
1704 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1705 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1707 if (pic->m_enabled && pic->m_init_state) {
1709 switch (pic->m_api_version) {
1727void PlugInManager::SendSKConfigToAllPlugIns() {
1730 v[_T(
"self")] = g_ownshipMMSI_SK;
1734 SendMessageToAllPlugins(wxString(_T(
"OCPN_CORE_SIGNALK")), out);
1737void PlugInManager::SendBaseConfigToAllPlugIns() {
1740 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1741 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1742 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1743 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1744 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1747 if (g_MainToolbar) {
1748 v[_T(
"OpenCPN Toolbar Width")] = g_MainToolbar->GetToolbarRect().width;
1749 v[_T(
"OpenCPN Toolbar Height")] = g_MainToolbar->GetToolbarRect().height;
1750 v[_T(
"OpenCPN Toolbar PosnX")] = g_MainToolbar->GetToolbarRect().x;
1751 v[_T(
"OpenCPN Toolbar PosnY")] = g_MainToolbar->GetToolbarRect().y;
1755 v[_T(
"OpenCPN Zoom Mod Vector")] = g_chart_zoom_modifier_vector;
1756 v[_T(
"OpenCPN Zoom Mod Other")] = g_chart_zoom_modifier_raster;
1757 v[_T(
"OpenCPN Scale Factor Exp")] =
1758 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1759 v[_T(
"OpenCPN Display Width")] = (int)g_display_size_mm;
1766 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1769void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1772 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1773 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1774 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1775 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1776 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1784 v[_T(
"OpenCPN S52PLIB ShowAnchorConditions")] = ps52plib->GetAnchorOn();
1785 v[_T(
"OpenCPN S52PLIB ShowQualityOfData")] = ps52plib->GetQualityOfData();
1790 v[_T(
"OpenCPN S52PLIB MetaDisplay")] = ps52plib->m_bShowMeta;
1791 v[_T(
"OpenCPN S52PLIB DeclutterText")] = ps52plib->m_bDeClutterText;
1792 v[_T(
"OpenCPN S52PLIB ShowNationalText")] = ps52plib->m_bShowNationalTexts;
1793 v[_T(
"OpenCPN S52PLIB ShowImportantTextOnly")] =
1794 ps52plib->m_bShowS57ImportantTextOnly;
1795 v[_T(
"OpenCPN S52PLIB UseSCAMIN")] = ps52plib->m_bUseSCAMIN;
1796 v[_T(
"OpenCPN S52PLIB UseSUPER_SCAMIN")] = ps52plib->m_bUseSUPER_SCAMIN;
1797 v[_T(
"OpenCPN S52PLIB SymbolStyle")] = ps52plib->m_nSymbolStyle;
1798 v[_T(
"OpenCPN S52PLIB BoundaryStyle")] = ps52plib->m_nBoundaryStyle;
1799 v[_T(
"OpenCPN S52PLIB ColorShades")] =
1800 S52_getMarinerParam(S52_MAR_TWO_SHADES);
1801 v[_T(
"OpenCPN S52PLIB Safety Depth")] =
1802 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1803 v[_T(
"OpenCPN S52PLIB Shallow Contour")] =
1804 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1805 v[_T(
"OpenCPN S52PLIB Deep Contour")] =
1806 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1810 v[_T(
"OpenCPN S52PLIB GlobalReconfig")] = bReconfig;
1815 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1818void PlugInManager::NotifyAuiPlugIns(
void) {
1819 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1820 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1822 if (pic->m_enabled && pic->m_init_state &&
1828int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1829 wxBitmap* bmpRollover, wxItemKind kind,
1830 wxString shortHelp, wxString longHelp,
1831 wxObject* clientData,
int position,
1834 pttc->label = label;
1836 if (!bitmap->IsOk()) {
1838 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1841 pttc->bitmap_day =
new wxBitmap(*bitmap);
1842 pttc->bitmap_day->UnShare();
1845 if (!bmpRollover->IsOk()) {
1847 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1850 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1851 pttc->bitmap_Rollover_day->UnShare();
1854 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1855 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1856 pttc->bitmap_Rollover_dusk =
1857 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1858 pttc->bitmap_Rollover_night =
1859 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1862 pttc->shortHelp = shortHelp;
1863 pttc->longHelp = longHelp;
1864 pttc->clientData = clientData;
1865 pttc->position = position;
1866 pttc->m_pplugin = pplugin;
1867 pttc->tool_sel = tool_sel;
1869 pttc->b_toggle =
false;
1870 pttc->id = m_plugin_tool_id_next;
1872 m_PlugInToolbarTools.Add(pttc);
1874 m_plugin_tool_id_next++;
1879int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1880 wxString SVGRolloverfile,
1881 wxString SVGToggledfile, wxItemKind kind,
1882 wxString shortHelp, wxString longHelp,
1883 wxObject* clientData,
int position,
1886 pttc->label = label;
1888 pttc->pluginNormalIconSVG = SVGfile;
1889 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1890 pttc->pluginToggledIconSVG = SVGToggledfile;
1895 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1896 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1897 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1898 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1899 pttc->bitmap_Rollover_dusk =
1900 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1901 pttc->bitmap_Rollover_night =
1902 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1905 pttc->shortHelp = shortHelp;
1906 pttc->longHelp = longHelp;
1907 pttc->clientData = clientData;
1908 pttc->position = position;
1909 pttc->m_pplugin = pplugin;
1910 pttc->tool_sel = tool_sel;
1912 pttc->b_toggle =
false;
1913 pttc->id = m_plugin_tool_id_next;
1915 m_PlugInToolbarTools.Add(pttc);
1917 m_plugin_tool_id_next++;
1922void PlugInManager::RemoveToolbarTool(
int tool_id) {
1923 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1926 if (pttc->id == tool_id) {
1927 m_PlugInToolbarTools.Remove(pttc);
1933 pParent->RequestNewToolbars();
1936void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1937 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1940 if (pttc->id == item) {
1942 pParent->RequestNewToolbars();
1949void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1950 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1953 if (pttc->id == item) {
1954 pttc->b_toggle = toggle;
1955 pParent->SetMasterToolbarItemState(item, toggle);
1962void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1963 wxBitmap* bmpRollover) {
1964 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1967 if (pttc->id == item) {
1968 delete pttc->bitmap_day;
1969 delete pttc->bitmap_dusk;
1970 delete pttc->bitmap_night;
1971 delete pttc->bitmap_Rollover_day;
1973 if (!bitmap->IsOk()) {
1975 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1978 pttc->bitmap_day =
new wxBitmap(*bitmap);
1979 pttc->bitmap_day->UnShare();
1982 if (!bmpRollover->IsOk()) {
1984 pttc->bitmap_Rollover_day =
1985 new wxBitmap(style->GetIcon(_T(
"default_pi")));
1988 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1989 pttc->bitmap_Rollover_day->UnShare();
1992 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1993 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1995 pParent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
1996 pttc->bitmap_Rollover_day);
2003void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2004 wxString SVGfileRollover,
2005 wxString SVGfileToggled) {
2006 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2009 if (pttc->id == item) {
2010 pttc->pluginNormalIconSVG = SVGfile;
2011 pttc->pluginRolloverIconSVG = SVGfileRollover;
2012 pttc->pluginToggledIconSVG = SVGfileToggled;
2013 pParent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2014 pttc->pluginRolloverIconSVG,
2015 pttc->pluginToggledIconSVG);
2023 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2025 if (
id == pc->id)
return pc->m_pplugin;
2031wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2034 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2035 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2037 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2041 return wxEmptyString;
2044wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2046wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2047 unsigned char dim_ratio) {
2048 wxImage img_dup = pbmp_normal->ConvertToImage();
2050 if (!img_dup.IsOk())
return NULL;
2052 if (dim_ratio < 200) {
2054 int gimg_width = img_dup.GetWidth();
2055 int gimg_height = img_dup.GetHeight();
2057 double factor = (double)(dim_ratio) / 256.0;
2059 for (
int iy = 0; iy < gimg_height; iy++) {
2060 for (
int ix = 0; ix < gimg_width; ix++) {
2061 if (!img_dup.IsTransparent(ix, iy)) {
2062 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2063 img_dup.GetGreen(ix, iy),
2064 img_dup.GetBlue(ix, iy));
2065 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2066 hsv.value = hsv.value * factor;
2067 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2068 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2074 wxBitmap* ptoolBarBitmap;
2077 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2079 dwxdc.SelectObject(tbmp);
2081 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2083 ptoolBarBitmap =
new wxBitmap(img_dup);
2087 return ptoolBarBitmap;
2090wxArrayString PlugInManager::GetPlugInChartClassNameArray(
void) {
2091 wxArrayString array;
2092 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2093 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2095 if (pic && pic->m_enabled && pic->m_init_state &&
2100 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2101 array.Add(carray[j]);
2109 while (j < array.GetCount()) {
2110 wxString test = array[j];
2111 unsigned int k = j + 1;
2112 while (k < array.GetCount()) {
2113 if (test == array[k]) {
2131#define DISABLED_SETTINGS_MSG \
2132 _("These settings might destabilize OpenCPN and are by default disabled." \
2133 " To despite the dangers enable them manually add a CatalogExpert=1" \
2134 " line in the [PlugIns] section in the configuration file.")
2139CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2140 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2142 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2145 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2147 wxStaticBox* itemStaticBoxSizer4Static =
2148 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2149 wxStaticBoxSizer* itemStaticBoxSizer4 =
2150 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2151 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2155 m_catalogText =
new wxStaticText(
this, wxID_STATIC, _T(
""));
2156 itemStaticBoxSizer4->Add(m_catalogText,
2157 wxSizerFlags().Border().Proportion(1));
2158 m_catalogText->SetLabel(GetCatalogText(
false));
2161 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2162 itemStaticBoxSizer4->Add(rowSizer2,
2163 wxSizerFlags().Expand().Border().Proportion(1));
2165 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2166 wxDefaultPosition, wxDefaultSize, 0);
2167 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2168 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2169 &CatalogMgrPanel::OnUpdateButton,
this);
2170 rowSizer2->AddSpacer(4 * GetCharWidth());
2171 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2172 wxDefaultPosition, wxDefaultSize, 0);
2173 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2174 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2175 &CatalogMgrPanel::OnTarballButton,
this);
2177 rowSizer2->AddSpacer(4 * GetCharWidth());
2178 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2179 wxDefaultPosition, wxDefaultSize, 0);
2181 if (expert.Get(
false)) {
2182 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2183 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2185 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2186 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2189 rowSizer2->AddSpacer(4 * GetCharWidth());
2190 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2192 SetUpdateButtonLabel();
2195 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2196 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2198 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2202 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2203 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2204 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2207 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2209 if (!expert.Get(
false)) {
2211 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2212 wxDefaultPosition, wxDefaultSize, 0);
2213 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2214 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2215 &CatalogMgrPanel::OnUpdateButton,
this);
2216 SetUpdateButtonLabel();
2217 m_tarballButton = NULL;
2218 m_adv_button = NULL;
2221 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2222 itemStaticBoxSizer4->Add(m_catalogText,
2223 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2226 m_updateButton =
new wxButton(
2227 this, wxID_ANY,
"Update Plugin Catalog:master ",
2228 wxDefaultPosition, wxDefaultSize, 0);
2229 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2230 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2231 &CatalogMgrPanel::OnUpdateButton,
this);
2232 SetUpdateButtonLabel();
2235 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2236 wxDefaultPosition, wxDefaultSize, 0);
2237 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2239 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2240 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2243 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2244 wxDefaultPosition, wxDefaultSize, 0);
2245 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2246 2 * GetCharWidth());
2247 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2248 &CatalogMgrPanel::OnTarballButton,
this);
2254CatalogMgrPanel::~CatalogMgrPanel() {
2255 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2256 &CatalogMgrPanel::OnUpdateButton,
this);
2257 if (m_tarballButton)
2258 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2259 &CatalogMgrPanel::OnTarballButton,
this);
2262static const char*
const DOWNLOAD_REPO_PROTO =
2263 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2266void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2268 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2269 std::string url(g_catalog_custom_url);
2270 if (catalog !=
"custom") {
2271 url = std::string(DOWNLOAD_REPO_PROTO);
2275 std::string filePath =
2276 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2278 auto catalogHdlr = CatalogHandler::getInstance();
2280 g_Platform->ShowBusySpinner();
2281 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2282 g_Platform->HideBusySpinner();
2284 std::string message;
2285 if (status != CatalogHandler::ServerStatus::OK) {
2286 message = _(
"Cannot download data from url");
2287 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2288 wxICON_ERROR | wxOK);
2294 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2296 wxFileName::GetPathSeparator() +
2297 _T(
"ocpn-plugins.xml"))) {
2298 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2299 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2304 if (!wxCopyFile(wxString(filePath.c_str()),
2306 wxFileName::GetPathSeparator() +
2307 _T(
"ocpn-plugins.xml"))) {
2308 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2309 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2315 if (catalog ==
"master") {
2317 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2318 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2324 pConfig->SetPath(_T(
"/PlugIns/"));
2325 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2331 auto pluginHandler = PluginHandler::getInstance();
2332 pluginHandler->setMetadata(
"");
2336 auto cataloghdlr = CatalogHandler::getInstance();
2337 cataloghdlr->ClearCatalogData();
2340 LoadAllPlugIns(
false);
2344 m_catalogText->SetLabel(GetCatalogText(
true));
2347 OCPNMessageBox(
this, _(
"Catalog update successful"),
2348 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2351void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2355 androidDisableRotation();
2358 dialog->ShowModal();
2361 androidEnableRotation();
2365void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2368 int response = g_Platform->DoFileSelectorDialog(
2369 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2370 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2372 if (response != wxID_OK) {
2375 auto handler = PluginHandler::getInstance();
2377 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2381 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2382 _(
"OpenCPN Plugin Import Error"));
2386 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2387 _(
"OpenCPN Plugin Import Error"));
2388 handler->uninstall(metadata.name);
2391 UninstallPlugin(metadata.name);
2392 ok = handler->installPlugin(metadata, path.ToStdString());
2394 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2395 _(
"OpenCPN Plugin Import Error"));
2398 metadata.is_imported =
true;
2400 std::ofstream file(metadata_path);
2403 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2404 <<
" for imported plugin: " << metadata.name;
2406 LoadAllPlugIns(
false,
true);
2409 wxString ws(_(
"Plugin"));
2410 ws += metadata.name + _(
" successfully imported");
2411 OCPNMessageBox(gFrame, ws, _(
"Installation complete"),
2412 wxICON_INFORMATION | wxOK | wxCENTRE);
2415wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2417 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2418 catalog += _T(
": ");
2421 pConfig->SetPath(_T(
"/PlugIns/"));
2422 wxString latestCatalog =
2423 pConfig->Read(_T(
"LatestCatalogDownloaded"), _T(
"default"));
2424 catalog += latestCatalog;
2429 auto pluginHandler = PluginHandler::getInstance();
2430 std::string date = pluginHandler->GetCatalogData()->date;
2432 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2433 if (!updated) catalog += _T(
" : ") + _(
"Please Update Plugin Catalog.");
2439void CatalogMgrPanel::SetUpdateButtonLabel() {
2440 wxString label = _(
"Update Plugin Catalog");
2442 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2443 m_updateButton->SetLabel(label);
2447wxString CatalogMgrPanel::GetImportInitDir() {
2449 pConfig->SetPath(_T(
"/PlugIns/"));
2450 wxString lastImportDir;
2451 lastImportDir = pConfig->Read(_T(
"LatestImportDir"),
2452 g_Platform->GetWritableDocumentsDir());
2453 if (wxDirExists(lastImportDir)) {
2454 return lastImportDir;
2456 return (g_Platform->GetWritableDocumentsDir());
2465 const wxPoint& pos, const wxSize& size)
2466 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2467 m_PluginSelected(0) {
2468 m_is_loading.clear();
2469 SetSizer(
new wxBoxSizer(wxVERTICAL));
2470 ReloadPluginPanels();
2473void PluginListPanel::SelectByName(wxString& name) {
2474 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2475 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2477 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2478 pluginPanel->SetSelected(
true);
2479 pluginPanel->Layout();
2480 SelectPlugin(pluginPanel);
2488std::vector<const PlugInData*> GetInstalled() {
2489 std::vector<const PlugInData*> result;
2490 auto loader = PluginLoader::getInstance();
2491 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2492 auto const item = loader->GetPlugInArray()->Item(i);
2493 if (item->m_managed_metadata.name.empty()) {
2494 const auto name = item->m_common_name.ToStdString();
2498 result.push_back(item);
2501 std::string slhs, srhs;
2502 for (
auto& cl : lhs->Key()) slhs += toupper(cl);
2503 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2504 return slhs.compare(srhs) < 0;
2506 std::sort(result.begin(), result.end(), compare);
2511static bool IsPluginLoaded(
const std::string& name) {
2512 if (safe_mode::get_mode()) {
2515 std::find(installed.begin(), installed.end(),
ocpn::tolower(name));
2516 return found != installed.end();
2518 auto loaded = PluginLoader::getInstance()->GetPlugInArray();
2519 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2520 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2527 if (m_is_loading.test_and_set()) {
2529 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2533 auto plugins = PluginLoader::getInstance()->GetPlugInArray();
2534 m_PluginItems.Clear();
2536 wxWindowList kids = GetChildren();
2537 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2538 wxWindowListNode* node = kids.Item(i);
2539 wxWindow* win = node->GetData();
2541 if (pp) win->Destroy();
2543 GetSizer()->Clear();
2546 m_PluginSelected = 0;
2548 if (safe_mode::get_mode()) {
2551 for (
const auto& name : installed) AddPlugin(name);
2554 auto available = getCompatiblePlugins();
2558 return IsPluginLoaded(md.name);
2560 auto end = std::remove_if(available.begin(), available.end(), predicate);
2561 available.erase(end, available.end());
2567 std::string slhs, srhs;
2568 for (
auto& cl : lhs.name) slhs += toupper(cl);
2569 for (
auto& cr : rhs.name) srhs += toupper(cr);
2570 return slhs.compare(srhs) < 0;
2574 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2575 for (
const auto& p : available) unique_sorted_entries.insert(p);
2580 for (
const auto& p : GetInstalled())
2581 if (p->m_enabled) AddPlugin(*p);
2584 for (
const auto& p : GetInstalled())
2585 if (!p->m_enabled) AddPlugin(*p);
2588 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2596 m_is_loading.clear();
2599void PluginListPanel::AddPlugin(
const std::string& name) {
2602 panel->SetSelected(
false);
2603 GetSizer()->Add(panel, 0, wxEXPAND);
2604 m_PluginItems.Add(panel);
2605 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2606 GetSizer()->AddSpacer(m_pluginSpacer);
2609void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2611 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2612 pPluginPanel->SetSelected(
false);
2613 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2614 m_PluginItems.Add(pPluginPanel);
2616 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2617 GetSizer()->AddSpacer(m_pluginSpacer);
2630int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2631 wxBoxSizer* sizer) {
2633 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2634 auto panel = plugins.Item(i);
2635 bool was_selected = panel->GetSelected();
2636 panel->SetSelected(
false);
2638 wxSize unselected = panel->GetSize();
2640 panel->SetSelected(
true);
2642 wxSize selected = panel->GetSize();
2644 int dy = selected.GetHeight() - unselected.GetHeight();
2645 max_dy = wxMax(max_dy, dy);
2646 panel->SetSelected(was_selected);
2651PluginListPanel::~PluginListPanel() {}
2653void PluginListPanel::UpdateSelections() {
2654 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2657 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2662void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2664 GetViewStart(&xs, &ys);
2667 if (m_PluginSelected) {
2668 m_PluginSelected->SetSelected(
false);
2669 m_PluginSelected->Layout();
2672 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2674 m_PluginSelected = pi;
2676 GetSizer()->Layout();
2678 wxSize size = GetBestVirtualSize();
2679 SetVirtualSize(size);
2684 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2686 int yd = pPluginPanel->GetSize().y;
2688 htop += m_pluginSpacer;
2689 if (pPluginPanel == pi) {
2690 int piBottom = htop - (ys * g_options->GetScrollRate());
2691 if (piBottom > GetClientSize().y) {
2692 ys += (piBottom - GetClientSize().y) / g_options->GetScrollRate();
2702 int pos = m_PluginItems.Index(pi);
2705 m_PluginItems.RemoveAt(pos);
2708 m_PluginItems.Insert(pi, pos - 1);
2709 wxStaticLine* itemStaticLine =
new wxStaticLine(
2710 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2715 m_PluginSelected = pi;
2717 GetSizer()->Layout();
2723 int pos = m_PluginItems.Index(pi);
2724 if (pos == (
int)m_PluginItems.Count() -
2727 m_PluginItems.RemoveAt(pos);
2730 m_PluginItems.Insert(pi, pos + 1);
2731 wxStaticLine* itemStaticLine =
new wxStaticLine(
2732 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2737 m_PluginSelected = pi;
2739 GetSizer()->Layout();
2744static bool canUninstall(std::string name) {
2745 PluginHandler* pluginHandler = PluginHandler::getInstance();
2748 for (
auto plugin : pluginHandler->getInstalled()) {
2749 if (plugin.name == name) {
2750 if (safe_mode::get_mode())
2753 return !plugin.readonly;
2760 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2762 m_is_safe_panel(true) {
2764 wxASSERT(m_PluginListPanel != 0);
2765 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2766 SetSizer(top_sizer);
2767 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2768 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2770 double iconSize = GetCharWidth() * 4;
2772 int icon_scale = iconSize * dpi_mult;
2774 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2775 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2776 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2778 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2779 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2780 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2781 top_horizontal->Add(m_pVersion);
2784 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2785 top_horizontal->Add(m_pButtons);
2786 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2787 top_horizontal->Add(m_info_btn);
2788 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2789 wxDefaultPosition, wxDefaultSize, 0);
2790 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2792 auto uninstall = [&](wxCommandEvent ev) {
2793 auto n = m_pName->GetLabel().ToStdString();
2795 OCPNMessageBox(gFrame, std::string(_(
"Uninstall plugin ")) + n +
"?",
2796 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2797 if (result != wxID_OK)
return;
2801 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2805EVT_PAINT(PluginPanel::OnPaint)
2810 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2812 m_is_safe_panel(false) {
2815 wxASSERT(m_PluginListPanel != 0);
2817 m_bSelected =
false;
2818 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2819 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2821 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2824 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2825 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2826 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2827 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2829 double iconSize = GetCharWidth() * 4;
2831 int icon_scale = iconSize * dpi_mult;
2833 wxImage plugin_icon;
2835 if (m_plugin.m_bitmap.IsOk()) {
2836 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2839 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2840 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2841 path.AppendDir(
"uidata");
2842 path.AppendDir(
"traditional");
2843 bitmap = LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2844 }
else if (plugin_icon.IsOk()) {
2845 int nowSize = plugin_icon.GetWidth();
2846 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2847 bitmap = wxBitmap(plugin_icon);
2849 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2851 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2853 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2854 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2856 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2859 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2860 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2863 int nChars = g_options->GetSize().x / GetCharWidth();
2864 bool bCompact =
false;
2870 wxString nameString = m_plugin.m_common_name;
2874 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2875 if (nameWidth > maxWidth) {
2876 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2877 wxELLIPSIZE_END, maxWidth);
2879 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2880 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2881 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2882 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2884 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2885 sl1->AddGrowableCol(1);
2886 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2888 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2889 sl1->Add(m_pVersion, 0, wxALL, 5);
2890 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2893 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2894 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2896 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2897 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2898 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2901 wxString descriptionString = m_plugin.m_short_description;
2902 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2903 int descriptionWidth;
2904 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2905 if (descriptionWidth > maxDescriptionWidth)
2907 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2908 wxELLIPSIZE_END, maxDescriptionWidth);
2913 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2914 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2915 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2916 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2917 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2920 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2921 itemBoxSizer03->AddGrowableCol(2);
2922 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2924 wxString nameString = m_plugin.m_common_name;
2925 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2926 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2927 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2931 wxFont font = GetFont();
2932 font.SetWeight(wxFONTWEIGHT_BOLD);
2933 m_pName->SetFont(font);
2936 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2938 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2939 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2940 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2941 m_plugin.m_status == PluginStatus::System ||
2942 (m_plugin.m_status == PluginStatus::Unmanaged &&
2943 !m_plugin.m_managed_metadata.is_orphan)) {
2946 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2947 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2949 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2950 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2951 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2953 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2955 m_pDescription =
new wxStaticText(
2956 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2958 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2959 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2960 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2964 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2966 itemBoxSizer02->Add(m_info_btn, 0);
2968 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2969 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2970 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2971 wxDefaultPosition, wxDefaultSize, 0);
2972 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
2974 m_pButtons->AddSpacer(3 * GetCharWidth());
2977 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
2978 wxDefaultPosition, wxDefaultSize, 0);
2979 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
2981 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2982 wxDefaultPosition, wxDefaultSize, 0);
2983 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
2985 m_pButtons =
new wxBoxSizer(wxVERTICAL);
2986 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2988 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
2989 m_pButtons->Add(tline, 0, wxALL, 2);
2991 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2992 wxDefaultPosition, wxDefaultSize, 0);
2993 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
2995 tline->AddSpacer(3 * GetCharWidth());
2997 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2999 tline->Add(m_info_btn, 0);
3002 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3003 wxDefaultPosition, wxDefaultSize);
3004 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3006 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3007 wxDefaultPosition, wxDefaultSize, 0);
3008 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3011 wxBitmap statusBitmap;
3012 const auto stat = m_plugin.m_status;
3013 auto icon_name = icon_by_status.at(stat);
3014 if (stat == PluginStatus::Imported &&
3015 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3017 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3020 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3021 path.AppendDir(
"uidata");
3022 path.AppendDir(
"traditional");
3024 int bmsize = GetCharWidth() * 3 * dpi_mult;
3025 if (path.IsFileReadable()) {
3026 statusBitmap = LoadSVG(path.GetFullPath(), bmsize, bmsize);
3027 ok = statusBitmap.IsOk();
3030 auto style = g_StyleManager->GetCurrentStyle();
3031 statusBitmap = wxBitmap(style->GetIcon(_T(
"default_pi"), bmsize, bmsize));
3032 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3035 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3036 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3037 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3039 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3042 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3044 itemBoxSizer02->AddSpacer(GetCharWidth());
3046 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3047 &PluginPanel::OnPluginPreferences,
this);
3048 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3049 &PluginPanel::OnPluginUninstall,
this);
3050 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3051 &PluginPanel::OnPluginAction,
this);
3053 SetSelected(m_bSelected);
3054 SetAutoLayout(
true);
3062PluginPanel::~PluginPanel() {
3063 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3064 if (m_is_safe_panel)
return;
3065 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3067 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3068 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3069 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3070 if (m_pButtonAction) {
3071 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3072 &PluginPanel::OnPluginAction,
this);
3074 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3075 &PluginPanel::OnPluginPreferences,
this);
3076 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3077 &PluginPanel::OnPluginEnableToggle,
this);
3080void PluginPanel::SetActionLabel(wxString& label) {
3081 m_pButtonAction->SetLabel(label);
3085static wxStopWatch swclick;
3086static int downx, downy;
3088void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3091 event.GetPosition(&downx, &downy);
3097void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3099 qDebug() << swclick.Time();
3100 if (swclick.Time() < 200) {
3102 event.GetPosition(&upx, &upy);
3103 if ((fabs(upx - downx) < GetCharWidth()) &&
3104 (fabs(upy - downy) < GetCharWidth())) {
3112void PluginPanel::DoPluginSelect() {
3113 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3119 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3120 }
else if (m_bSelected) {
3122 m_PluginListPanel->SelectPlugin(NULL);
3125 m_PluginListPanel->SelectPlugin(
this);
3133static PluginMetadata GetMetadataByName(
const std::string& name) {
3134 auto plugins = PluginHandler::getInstance()->
getInstalled();
3135 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3136 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3137 if (found == plugins.end()) {
3138 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3143void PluginPanel::SetSelected(
bool selected) {
3144 m_bSelected = selected;
3146 m_pVersion->SetLabel(
3149 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3150 m_pButtons->Show(
true);
3151 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3154 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3155 m_plugin.m_status == PluginStatus::Unmanaged ||
3156 m_plugin.m_status == PluginStatus::System)
3157 unInstallPossible =
false;
3160 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3162 m_pButtonUninstall->Show(unInstallPossible);
3164 if (m_plugin.m_managed_metadata.info_url.size()) {
3165 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3169 m_cbEnable->Show(
true);
3174 switch (m_plugin.m_status) {
3175 case PluginStatus::LegacyUpdateAvailable:
3176 label = _(
"Upgrade to Version ");
3177 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3178 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3179 m_pButtonAction->Enable();
3182 case PluginStatus::ManagedInstallAvailable:
3183 label = _(
"Install...");
3184 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3185 m_pButtonAction->Enable();
3188 case PluginStatus::ManagedInstalledUpdateAvailable:
3189 label = _(
"Update to ");
3190 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3191 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3192 m_pButtonAction->Enable();
3195 case PluginStatus::ManagedInstalledCurrentVersion:
3196 label = _(
"Reinstall");
3197 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3198 m_pButtonAction->Enable();
3201 case PluginStatus::ManagedInstalledDowngradeAvailable:
3202 label = _(
"Downgrade");
3203 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3204 m_pButtonAction->Enable();
3207 case PluginStatus::Imported:
3208 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3209 label = _(
"Update");
3210 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3212 m_pButtonAction->Hide();
3213 m_action = ActionVerb::NOP;
3217 case PluginStatus::Unmanaged:
3218 m_action = ActionVerb::NOP;
3219 m_pButtonAction->Hide();
3222 case PluginStatus::System:
3223 m_action = ActionVerb::NOP;
3224 m_pButtonAction->Hide();
3229 m_action = ActionVerb::NOP;
3232 SetActionLabel(label);
3235 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3244 m_pButtons->Show(
false);
3247 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3248 m_cbEnable->Show(
false);
3264 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3266 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3269 SetEnabled(m_plugin.m_enabled);
3284void PluginPanel::OnPaint(wxPaintEvent& event) {
3287 int penWidth = m_penWidthUnselected;
3288 wxColour color = GetDialogColor(DLG_UNSELECTED_BACKGROUND);
3289 wxColour border = GetDialogColor(DLG_UNSELECTED_ACCENT);
3292 penWidth = m_penWidthSelected;
3293 color = GetDialogColor(DLG_SELECTED_BACKGROUND);
3294 border = GetDialogColor(DLG_SELECTED_ACCENT);
3297 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3299 dc.SetPen(wxPen(border, penWidth));
3301 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3304void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3305 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3308 androidDisableRotation();
3319void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3320 SetEnabled(event.IsChecked());
3321 m_pVersion->SetLabel(
3323 if (m_plugin.m_status == PluginStatus::System) {
3326 PluginLoader::getInstance()->evt_pluglist_change.
Notify();
3330void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3331 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
3334 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3335 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3336 actionEvent.SetClientData(
this);
3337 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3340void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3342 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3343 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3344 actionEvent.SetClientData(
this);
3345 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3350static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3351 auto font = window->GetFont();
3352 font.SetStyle(style);
3353 window->SetFont(font);
3356void PluginPanel::SetEnabled(
bool enabled) {
3357 if (m_is_safe_panel)
return;
3359 PluginLoader::getInstance()->UpdatePlugIns();
3360 NotifySetupOptionsPlugin(&m_plugin);
3361 if (!enabled && !m_bSelected) {
3362 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3363 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3364 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3367 m_pVersion->Disable();
3368 m_pDescription->Disable();
3371 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3372 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3373 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3376 m_pVersion->Enable();
3377 m_pDescription->Enable();
3382 m_pName->Enable(enabled || m_bSelected);
3383 m_pVersion->Enable(enabled || m_bSelected);
3384 m_pDescription->Enable(enabled || m_bSelected);
3388 wxString description = m_plugin.m_long_description;
3389 if (description.IsEmpty())
3390 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3393 g_options->GetSize().x * 7 / 10);
3394 m_pDescription->SetLabel(wrapper.GetWrapped());
3395 if (m_plugin.m_managed_metadata.info_url.size()) {
3396 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3400 wxString description = m_plugin.m_short_description;
3401 if (description.IsEmpty())
3402 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3404 g_options->GetSize().x * 7 / 10);
3405 m_pDescription->SetLabel(wrapper.GetWrapped());
3408 m_pButtonPreferences->Enable(enabled &&
3410 m_cbEnable->SetValue(enabled);
3413void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3414 m_PluginListPanel->MoveUp(
this);
3417void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3418 m_PluginListPanel->MoveDown(
this);
3423 : wxPanel(parent), m_url(url) {
3424 auto vbox =
new wxBoxSizer(wxVERTICAL);
3425 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3426 button->Enable(strlen(url) > 0);
3429 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3430 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3438PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3440PlugInChartBase::~PlugInChartBase() {}
3449 bool b_allow_overzoom) {
3461 const wxRegion& Region) {
3462 return wxNullBitmap;
3471 wxRegion* pValidRegion) {}
3484 wxRect* pSourceRect) {}
3501 double* plat,
double* plon) {}
3508PlugInChartBaseGL::PlugInChartBaseGL() {}
3510PlugInChartBaseGL::~PlugInChartBaseGL() {}
3514 const wxRegion& Region,
3515 bool b_use_stencil) {
3541PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3543PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3547 const wxRegion& Region,
3548 bool b_use_stencil) {
3554 const wxRegion& Region,
bool b_use_stencil) {
3560 const wxRegion& Region,
bool b_use_stencil) {
3566 return wxNullBitmap;
3570 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3574ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3579wxString PlugInChartBaseExtended::CreateObjDescriptions(
3580 ListOfPI_S57Obj* obj_list) {
3584int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3586int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3588int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3590float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3599PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3601PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3604PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3614PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3616PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3628ChartPlugInWrapper::ChartPlugInWrapper() {}
3630ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3631 m_ppo = ::wxCreateDynamicObject(chart_class);
3635ChartPlugInWrapper::~ChartPlugInWrapper() {
3636 if (m_ppicb)
delete m_ppicb;
3639wxString ChartPlugInWrapper::GetFileSearchMask(
void) {
3646InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3647 ChartInitFlag init_flags) {
3649 wxWindow* pa = wxWindow::FindFocus();
3651 InitReturn ret_val = (InitReturn)m_ppicb->
Init(name, (
int)init_flags);
3655 if (ret_val == INIT_OK) {
3662 m_ID = m_ppicb->
GetID();
3666 m_SE = m_ppicb->
GetSE();
3680 if ((fabs(m_Chart_Skew) < .01) &&
3681 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3683 if (GetChartExtent(&extent)) {
3684 double lon_range = extent.ELON - extent.WLON;
3685 if ((lon_range > 0) &&
3687 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3691 m_overlayENC =
false;
3693 wxCharBuffer buf = m_FullPath.ToUTF8();
3694 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3700 m_ChartType = CHART_TYPE_UNKNOWN;
3701 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3707 if (pc) pc->SetFocus();
3711 return INIT_FAIL_REMOVE;
3715int ChartPlugInWrapper::GetCOVREntries() {
3722int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3729int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3736float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3748int ChartPlugInWrapper::GetNoCOVREntries() {
3758int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3768int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3778float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3788bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3792 pext->NLAT = xpi.
NLAT;
3793 pext->SLAT = xpi.
SLAT;
3794 pext->ELON = xpi.
ELON;
3795 pext->WLON = xpi.
WLON;
3804ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3809 if (!pThumbData->pDIBThumb) {
3810 wxBitmap* pBMPOwnedByChart =
3811 m_ppicb->
GetThumbnail(tnx, tny, m_global_color_scheme);
3812 if (pBMPOwnedByChart) {
3813 wxImage img = pBMPOwnedByChart->ConvertToImage();
3814 pThumbData->pDIBThumb =
new wxBitmap(img);
3816 pThumbData->pDIBThumb = NULL;
3819 pThumbData->Thumb_Size_X = tnx;
3820 pThumbData->Thumb_Size_Y = tny;
3847 pThumbData->ShipX = 0;
3848 pThumbData->ShipY = 0;
3855ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3857bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3861double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3862 bool b_allow_overzoom) {
3869double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3891void RenderRotateToViewPort(
const ViewPort& VPoint) {
3892#ifndef USE_ANDROID_GLES2
3894 glTranslatef(xt, yt, 0);
3895 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3896 glTranslatef(-xt, -yt, 0);
3900void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3901#ifndef USE_ANDROID_GLES2
3903 glTranslatef(xt, yt, 0);
3904 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3905 glTranslatef(-xt, -yt, 0);
3909bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3912 const LLRegion& Region) {
3921 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3922 wxRegion* r = RectRegion.GetNew_wxRegion();
3925 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3926 chart_region.Intersect(Region);
3928 if (!chart_region.Empty()) {
3929 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3931 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3935#ifndef USE_ANDROID_GLES2
3938 RenderRotateToViewPort(VPoint);
3943 glChartCanvas::s_b_useStencil);
3946 glChartCanvas::s_b_useStencil);
3947 UndoRenderRotateToViewPort(VPoint);
3949#ifndef USE_ANDROID_GLES2
3952 glChartCanvas::DisableClipRegion();
3966bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
3967 const wxGLContext& glc,
const ViewPort& VPoint,
3968 const OCPNRegion& RectRegion,
const LLRegion& Region) {
3977 if (!Region.Empty() && ppicb_x) {
3979 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
3980 glChartCanvas::DisableClipRegion();
3983 RenderRotateToViewPort(VPoint);
3986 wxRegion* r = RectRegion.GetNew_wxRegion();
3989 glChartCanvas::s_b_useStencil);
3992 UndoRenderRotateToViewPort(VPoint);
3997 else if (!Region.Empty() &&
4001 wxRegion* r = RectRegion.GetNew_wxRegion();
4004 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4005 chart_region.Intersect(Region);
4007 if (!chart_region.Empty()) {
4008 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4010 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4012 RenderRotateToViewPort(VPoint);
4016 glChartCanvas::s_b_useStencil);
4019 UndoRenderRotateToViewPort(VPoint);
4021 glChartCanvas::DisableClipRegion();
4034bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4041 if (!Region.Empty() && ppicb_x) {
4042 wxRegion* r = Region.GetNew_wxRegion();
4044#ifndef USE_ANDROID_GLES2
4047 RenderRotateToViewPort(VPoint);
4051 glChartCanvas::s_b_useStencil);
4052 UndoRenderRotateToViewPort(VPoint);
4054#ifndef USE_ANDROID_GLES2
4067bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4073 if (Region.IsOk()) {
4074 wxRegion* r = Region.GetNew_wxRegion();
4081 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4082 wxColour nodat_sub = nodat;
4084#ifdef ocpnUSE_ocpnBitmap
4085 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4087 m_pMask =
new wxMask(obmp, nodat_sub);
4088 obmp.SetMask(m_pMask);
4090 dc.SelectObject(obmp);
4101bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4112 if (Region.IsOk() && (pCBx || ppicb)) {
4113 wxRegion* r = Region.GetNew_wxRegion();
4128bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4131 bool ret_val =
false;
4134 if (Region.IsOk()) {
4135 wxRegion* r = Region.GetNew_wxRegion();
4149void ChartPlugInWrapper::ClearPLIBTextList() {
4157bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4161 return m_ppicb->
AdjustVP(pivp_last, pivp_proposed);
4166void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4181void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4185 m_global_color_scheme = cs;
4187 if (pThumbData) pThumbData->pDIBThumb = NULL;
4191 double target_scale_ppm) {
4198void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4199 wxRect* pSourceRect) {
4206double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4208 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4213bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4215 wxCriticalSectionLocker locker(m_critSect);
4224int ChartPlugInWrapper::GetSize_X() {
4231int ChartPlugInWrapper::GetSize_Y() {
4238void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4239 double& pixx,
double& pixy) {
4243void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4244 double* plat,
double* plon) {
4258wxString toSDMM_PlugIn(
int NEflag,
double a,
bool hi_precision) {
4259 return toSDMM(NEflag, a, hi_precision);
4262wxColour GetBaseGlobalColor(wxString colorName) {
4263 return GetGlobalColor(colorName);
4266int OCPNMessageBox_PlugIn(wxWindow* parent,
const wxString& message,
4267 const wxString& caption,
int style,
int x,
int y) {
4268 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4271wxString GetOCPN_ExePath(
void) {
return g_Platform->GetExePath(); }
4273wxString* GetpPlugInLocation() {
return g_Platform->GetPluginDirPtr(); }
4275wxString GetWritableDocumentsDir(
void) {
4276 return g_Platform->GetWritableDocumentsDir();
4281 auto loader = PluginLoader::getInstance();
4282 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4284 if (pic->m_pplugin == pplugin) {
4294ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4297 ListOfPI_S57Obj* list = NULL;
4311 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4321 ListOfPI_S57Obj* rule_list) {
4332 ret_str = picbx->CreateObjDescriptions(rule_list);
4340wxString PI_GetPLIBColorScheme() {
4344int PI_GetPLIBDepthUnitInt() {
4346 return ps52plib->m_nDepthUnitDisplay;
4351int PI_GetPLIBSymbolStyle() {
4353 return ps52plib->m_nSymbolStyle;
4358int PI_GetPLIBBoundaryStyle() {
4360 return ps52plib->m_nBoundaryStyle;
4370 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4372 ViewPort cvp = CreateCompatibleViewport(*vp);
4377 ObjRazRules rzRules;
4378 rzRules.obj = &cobj;
4379 rzRules.LUP = pContext->LUP;
4380 rzRules.sm_transform_parms = 0;
4381 rzRules.child = NULL;
4382 rzRules.next = NULL;
4384 if (pContext->LUP) {
4385 ps52plib->SetVPointCompat(
4389 ps52plib->PrepareForRender();
4391 return ps52plib->ObjectRenderCheck(&rzRules);
4398int PI_GetPLIBStateHash() {
4400 return ps52plib->GetStateHash();
4405void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4406 chart_context* pctx) {
4409 cobj->att_array = pObj->att_array;
4410 cobj->attVal = pObj->attVal;
4411 cobj->n_attr = pObj->n_attr;
4416 cobj->npt = pObj->npt;
4418 cobj->iOBJL = pObj->iOBJL;
4419 cobj->Index = pObj->Index;
4421 cobj->geoPt = (pt*)pObj->geoPt;
4422 cobj->geoPtz = pObj->geoPtz;
4423 cobj->geoPtMulti = pObj->geoPtMulti;
4425 cobj->m_lat = pObj->m_lat;
4426 cobj->m_lon = pObj->m_lon;
4428 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4429 cobj->x_rate = pObj->x_rate;
4430 cobj->y_rate = pObj->y_rate;
4431 cobj->x_origin = pObj->x_origin;
4432 cobj->y_origin = pObj->y_origin;
4434 cobj->Scamin = pObj->Scamin;
4435 cobj->nRef = pObj->nRef;
4436 cobj->bIsAton = pObj->bIsAton;
4437 cobj->bIsAssociable = pObj->bIsAssociable;
4439 cobj->m_n_lsindex = pObj->m_n_lsindex;
4440 cobj->m_lsindex_array = pObj->m_lsindex_array;
4441 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4444 cobj->m_ls_list_legacy =
4448 cobj->m_ls_list_legacy = 0;
4449 cobj->m_ls_list = 0;
4452 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4454 cobj->m_bcategory_mutable =
true;
4458 if (pObj->m_DPRI == -1) {
4460 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4462 cobj->m_DPRI = pObj->m_DPRI;
4465 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4466 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4468 if (pObj->auxParm3 != 1234) {
4469 pObj->auxParm3 = 1234;
4470 pObj->auxParm0 = -99;
4473 cobj->auxParm0 = pObj->auxParm0;
4480 if (pContext->bBBObj_valid)
4482 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4483 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4485 cobj->CSrules = pContext->CSrules;
4486 cobj->bCS_Added = pContext->bCS_Added;
4488 cobj->FText = pContext->FText;
4489 cobj->bFText_Added = pContext->bFText_Added;
4490 cobj->rText = pContext->rText;
4492 cobj->bIsClone =
true;
4495 cobj->m_chart_context = pctx;
4496 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4499 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4500 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4501 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4502 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4503 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4504 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4505 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4506 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4508 cobj->m_chart_context->chart =
4510 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4524 CreateCompatibleS57Object(pObj, &cobj, NULL);
4526 LUPname LUP_Name = PAPER_CHART;
4529 ctx->CSrules = NULL;
4530 ctx->bCS_Added =
false;
4533 if (ctx->bFText_Added) {
4534 ctx->bFText_Added =
false;
4540 ctx->bBBObj_valid =
true;
4545 switch (cobj.Primitive_type) {
4550 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4551 LUP_Name = PAPER_CHART;
4553 LUP_Name = SIMPLIFIED;
4562 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4563 LUP_Name = PLAIN_BOUNDARIES;
4565 LUP_Name = SYMBOLIZED_BOUNDARIES;
4570 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4574 ps52plib->_LUP2rules(lup, &cobj);
4576 ctx->MPSRulesList = NULL;
4584 pContext->bBBObj_valid =
true;
4590void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4591 ObjRazRules* rzRules) {
4595 pContext->CSrules = cobj->CSrules;
4596 pContext->bCS_Added = cobj->bCS_Added;
4598 pContext->FText = cobj->FText;
4599 pContext->bFText_Added = cobj->bFText_Added;
4600 pContext->rText = cobj->rText;
4602 if (cobj->BBObj.GetValid()) {
4605 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4606 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4607 pContext->bBBObj_valid =
true;
4612 pObj->m_DisplayCat = (
PI_DisCat)cobj->m_DisplayCat;
4616 pContext->ChildRazRules = rzRules->child;
4617 pContext->MPSRulesList = rzRules->mps;
4619 pObj->auxParm0 = cobj->auxParm0;
4622bool PI_GetObjectRenderBox(
PI_S57Obj* pObj,
double* lat_min,
double* lat_max,
4623 double* lon_min,
double* lon_max) {
4626 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4627 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4628 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4629 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4630 return pContext->bBBObj_valid;
4638 LUPrec* lup = pContext->LUP;
4647 LUPrec* lup = pContext->LUP;
4657 LUPrec* lup = pContext->LUP;
4662double PI_GetPLIBMarinerSafetyContour() {
4663 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4666void PI_PLIBSetLineFeaturePriority(
PI_S57Obj* pObj,
int prio) {
4670 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4675 ObjRazRules rzRules;
4676 rzRules.obj = &cobj;
4677 rzRules.LUP = pContext->LUP;
4678 rzRules.sm_transform_parms = 0;
4679 rzRules.child = NULL;
4680 rzRules.next = NULL;
4681 rzRules.mps = pContext->MPSRulesList;
4683 if (pContext->LUP) {
4684 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4687 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4691void PI_PLIBPrepareForNewRender(
void) {
4693 ps52plib->PrepareForRender();
4694 ps52plib->ClearTextList();
4697 ps52plib->EnableGLLS(
true);
4699 ps52plib->EnableGLLS(
false);
4703void PI_PLIBSetRenderCaps(
unsigned int flags) { gs_plib_flags = flags; }
4705void PI_PLIBFreeContext(
void* pContext) {
4708 if (pctx->ChildRazRules) {
4709 ObjRazRules* ctop = pctx->ChildRazRules;
4713 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4715 ObjRazRules* cnxx = ctop->next;
4721 if (pctx->MPSRulesList) {
4722 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4723 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4725 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4726 ps52plib->DestroyRulesChain(top);
4728 delete pctx->MPSRulesList->cs_rules;
4730 free(pctx->MPSRulesList);
4742 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4749 &transform.easting_vp_center, &transform.northing_vp_center);
4752 ObjRazRules rzRules;
4753 rzRules.obj = &cobj;
4754 rzRules.LUP = pContext->LUP;
4755 rzRules.sm_transform_parms = &transform;
4756 rzRules.child = pContext->ChildRazRules;
4757 rzRules.next = NULL;
4758 rzRules.mps = pContext->MPSRulesList;
4760 if (pContext->LUP) {
4761 ViewPort cvp = CreateCompatibleViewport(*vp);
4767 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4769 ps52plib->PrepareForRender();
4771 ps52plib->RenderObjectToDC(pdc, &rzRules);
4774 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4781 wxRect rect,
unsigned char* pixbuf) {
4783 render_canvas_parms pb_spec;
4785 pb_spec.depth = BPP;
4786 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4787 pb_spec.lclip = rect.x;
4788 pb_spec.rclip = rect.x + rect.width - 1;
4789 pb_spec.pix_buff = pixbuf;
4790 pb_spec.width = rect.width;
4791 pb_spec.height = rect.height;
4794#ifdef ocpnUSE_ocpnBitmap
4795 pb_spec.b_revrgb =
true;
4797 pb_spec.b_revrgb =
false;
4800 pb_spec.b_revrgb =
false;
4805 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4812 &transform.easting_vp_center, &transform.northing_vp_center);
4815 ObjRazRules rzRules;
4816 rzRules.obj = &cobj;
4817 rzRules.LUP = pContext->LUP;
4818 rzRules.sm_transform_parms = &transform;
4819 rzRules.child = pContext->ChildRazRules;
4820 rzRules.next = NULL;
4821 rzRules.mps = pContext->MPSRulesList;
4823 ViewPort cvp = CreateCompatibleViewport(*vp);
4831 if (!tess)
return 1;
4833 PolyTriGroup* ptg =
new PolyTriGroup;
4834 ptg->tri_prim_head =
4835 tess->Get_PolyTriGroup_head()->tri_prim_head;
4836 ptg->bsingle_alloc =
false;
4837 ptg->data_type = DATA_TYPE_DOUBLE;
4838 tess->Set_PolyTriGroup_head(ptg);
4840 double* pd = (
double*)malloc(
sizeof(
double));
4845 if (pContext->LUP) {
4850 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4852 ps52plib->PrepareForRender();
4854 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4857 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4863int PI_PLIBRenderAreaToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4869 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4880 if (!tess)
return 1;
4884 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4885 ptg->bsingle_alloc =
false;
4886 ptg->data_type = DATA_TYPE_DOUBLE;
4887 tess->Set_PolyTriGroup_head(ptg);
4891 double* pd = (
double*)malloc(
sizeof(
double));
4908 &transform.easting_vp_center, &transform.northing_vp_center);
4911 ObjRazRules rzRules;
4912 rzRules.obj = &cobj;
4913 rzRules.LUP = pContext->LUP;
4914 rzRules.sm_transform_parms = &transform;
4915 rzRules.child = pContext->ChildRazRules;
4916 rzRules.next = NULL;
4917 rzRules.mps = pContext->MPSRulesList;
4919 if (pContext->LUP) {
4920 ViewPort cvp = CreateCompatibleViewport(*vp);
4926 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4928 ps52plib->PrepareForRender();
4930 ps52plib->RenderAreaToGL(glcc, &rzRules);
4933 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4940int PI_PLIBRenderObjectToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4945 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4952 &transform.easting_vp_center, &transform.northing_vp_center);
4955 ObjRazRules rzRules;
4956 rzRules.obj = &cobj;
4957 rzRules.LUP = pContext->LUP;
4958 rzRules.sm_transform_parms = &transform;
4959 rzRules.child = pContext->ChildRazRules;
4960 rzRules.next = NULL;
4961 rzRules.mps = pContext->MPSRulesList;
4963 if (pContext->LUP) {
4964 ViewPort cvp = CreateCompatibleViewport(*vp);
4970 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4972 ps52plib->PrepareForRender();
4974 ps52plib->RenderObjectToGL(glcc, &rzRules);
4977 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4987OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
4988 : wxEvent(id, commandType) {
4991 m_b_complete =
false;
4995OCPN_downloadEvent::~OCPN_downloadEvent() {}
4997wxEvent* OCPN_downloadEvent::Clone()
const {
4999 newevent->m_stat = this->m_stat;
5000 newevent->m_condition = this->m_condition;
5002 newevent->m_totalBytes = this->m_totalBytes;
5003 newevent->m_sofarBytes = this->m_sofarBytes;
5004 newevent->m_b_complete = this->m_b_complete;
5010DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5015#define DL_EVENT_TIMER 4388
5023 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5024 void clearBackgroundMode();
5025 void onTimerEvent(wxTimerEvent& event);
5028 wxTimer m_eventTimer;
5029 wxEvtHandler* m_download_evHandler;
5035PI_DLEvtHandler::PI_DLEvtHandler() {
5039 m_download_evHandler = NULL;
5045PI_DLEvtHandler::~PI_DLEvtHandler() {
5046 m_eventTimer.Stop();
5049 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5056 g_download_status =
event.getDLEventStatus();
5057 g_download_condition =
event.getDLEventCondition();
5060 if (m_download_evHandler &&
5063 ev.setComplete(
true);
5064 ev.setTransferred(m_sofarBytes);
5065 ev.setTotal(m_totalBytes);
5067 ev.setDLEventStatus(event.getDLEventStatus());
5070 m_download_evHandler->AddPendingEvent(ev);
5071 m_eventTimer.Stop();
5073 finishAndroidFileDownload();
5080void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5082 m_download_evHandler = handler;
5084 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5088 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5089 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5092void PI_DLEvtHandler::clearBackgroundMode() {
5093 m_download_evHandler = NULL;
5094 m_eventTimer.Stop();
5097void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5103 int stat = queryAndroidFileDownload(m_id, &sstat);
5106 long sofarBytes = 0;
5107 long totalBytes = -1;
5111 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5112 ev.setComplete(
true);
5113 ev.setTransferred(sofarBytes);
5114 ev.setTotal(totalBytes);
5119 wxStringTokenizer tk(sstat, _T(
";"));
5120 if (tk.HasMoreTokens()) {
5121 wxString token = tk.GetNextToken();
5122 token.ToLong(&state);
5123 token = tk.GetNextToken();
5124 token.ToLong(&sofarBytes);
5125 token = tk.GetNextToken();
5126 token.ToLong(&totalBytes);
5129 qDebug() << state << sofarBytes << totalBytes;
5131 m_sofarBytes = sofarBytes;
5132 m_totalBytes = totalBytes;
5134 ev.setTransferred(sofarBytes);
5135 ev.setTotal(totalBytes);
5138 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5139 ev.setComplete(
true);
5142 }
else if (state == 8) {
5143 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5144 ev.setComplete(
true);
5148 ev.setComplete(
false);
5156 if (m_download_evHandler) {
5158 m_download_evHandler->AddPendingEvent(ev);
5163 m_eventTimer.Stop();
5164 finishAndroidFileDownload();
5174 const wxString& outputFile,
5175 const wxString& title,
const wxString& message,
5176 const wxBitmap& bitmap, wxWindow* parent,
5177 long style,
int timeout_secs) {
5180 wxString msg = _T(
"Downloading file synchronously: ");
5187 int vres = validateAndroidWriteLocation(outputFile);
5199 g_piEventHandler->Connect(
5200 wxEVT_DOWNLOAD_EVENT,
5201 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5206 wxString fURI = outputFile;
5207 if (!fURI.StartsWith(_T(
"file://"))) {
5208 fURI.Prepend(_T(
"file://"));
5211 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5214 finishAndroidFileDownload();
5215 g_piEventHandler->Disconnect(
5216 wxEVT_DOWNLOAD_EVENT,
5217 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5222 wxDateTime dl_start_time = wxDateTime::Now();
5226 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5227 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5229 if (dt.GetSeconds() > timeout_secs) {
5230 qDebug() <<
"USER_TIMOUT";
5231 finishAndroidFileDownload();
5232 g_piEventHandler->Disconnect(
5233 wxEVT_DOWNLOAD_EVENT,
5234 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5242 finishAndroidFileDownload();
5243 g_piEventHandler->Disconnect(
5244 wxEVT_DOWNLOAD_EVENT,
5248 qDebug() <<
"RETURN DL_END" << (int)ss;
5254 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5256 qDebug() <<
"Error on queryAndroidFileDownload";
5257 finishAndroidFileDownload();
5258 g_piEventHandler->Disconnect(
5259 wxEVT_DOWNLOAD_EVENT,
5260 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5270#elif defined(OCPN_USE_CURL)
5271 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5272 wxFileOutputStream output(tfn.GetFullPath());
5274 wxCurlDownloadDialog ddlg(url, &output, title, message + url, bitmap, parent,
5276 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5282 case wxCDRF_SUCCESS: {
5283 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5289 case wxCDRF_FAILED: {
5293 case wxCDRF_USER_ABORTED: {
5301 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5309wxString toUsrDateTimeFormat_Plugin(
const wxDateTime date_time,
5311 return ocpn::toUsrDateTimeFormat(date_time,
options);
5316 const wxString& outputFile,
5317 wxEvtHandler* handler,
5320 wxString msg = _T(
"Downloading file asynchronously: ");
5332 int res = startAndroidFileDownload(url, outputFile, NULL ,
5336 finishAndroidFileDownload();
5341 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5343 if (handle) *handle = dl_ID;
5347#elif defined(OCPN_USE_CURL)
5348 if (g_pi_manager->m_pCurlThread)
5352 g_pi_manager->m_pCurlThread =
5353 new wxCurlDownloadThread(g_pi_manager, CurlThreadId);
5354 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5356 if (http && g_pi_manager->m_pCurl &&
5357 dynamic_cast<wxCurlHTTP*
>(g_pi_manager->m_pCurl.get())) {
5361 g_pi_manager->m_pCurl = 0;
5364 bool failed =
false;
5365 if (!g_pi_manager->HandleCurlThreadError(
5366 g_pi_manager->m_pCurlThread->SetURL(url, g_pi_manager->m_pCurl),
5367 g_pi_manager->m_pCurlThread, url))
5370 g_pi_manager->m_pCurl = g_pi_manager->m_pCurlThread->GetCurlSharedPtr();
5371 if (!g_pi_manager->HandleCurlThreadError(
5372 g_pi_manager->m_pCurlThread->SetOutputStream(
5373 new wxFileOutputStream(outputFile)),
5374 g_pi_manager->m_pCurlThread))
5378 g_pi_manager->m_download_evHandler = handler;
5379 g_pi_manager->m_downloadHandle = handle;
5381 wxCurlThreadError err = g_pi_manager->m_pCurlThread->Download();
5382 if (err != wxCTE_NO_ERROR) {
5383 g_pi_manager->HandleCurlThreadError(
5384 err, g_pi_manager->m_pCurlThread);
5385 g_pi_manager->m_pCurlThread->Abort();
5392 if (g_pi_manager->m_pCurlThread) {
5393 if (g_pi_manager->m_pCurlThread->IsAlive())
5394 g_pi_manager->m_pCurlThread->Abort();
5395 if (g_pi_manager->m_pCurlThread->GetOutputStream())
5396 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5397 wxDELETE(g_pi_manager->m_pCurlThread);
5398 g_pi_manager->m_download_evHandler = NULL;
5399 g_pi_manager->m_downloadHandle = NULL;
5402 g_pi_manager->m_pCurl = 0;
5410void OCPN_cancelDownloadFileBackground(
long handle) {
5414 cancelAndroidFileDownload(handle);
5415 finishAndroidFileDownload();
5416 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5418 if (g_pi_manager->m_pCurlThread) {
5419 g_pi_manager->m_pCurlThread->Abort();
5420 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5421 wxDELETE(g_pi_manager->m_pCurlThread);
5422 g_pi_manager->m_download_evHandler = NULL;
5423 g_pi_manager->m_downloadHandle = NULL;
5425 g_pi_manager->m_pCurl = 0;
5431 const wxString& parameters, wxString& result,
5434 wxString lparms = parameters;
5435 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5438 result = postResult;
5441#elif defined(OCPN_USE_CURL)
5443 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5444 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5447 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5450 result = wxEmptyString;
5459bool OCPN_isOnline() {
5461 return androidCheckOnline();
5464#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5465 if (wxDateTime::GetTimeNow() >
5466 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5468 get.Head(_T(
"http://yahoo.com/"));
5469 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5471 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5473 return g_pi_manager->m_last_online;
5479#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5480void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5482 if (ev.IsSuccessful()) {
5485 g_pi_manager->m_pCurl = 0;
5489 event.setComplete(
true);
5491 if (m_download_evHandler) {
5492 m_download_evHandler->AddPendingEvent(event);
5493 m_download_evHandler = NULL;
5494 m_downloadHandle = NULL;
5497 if (m_pCurlThread) {
5498 m_pCurlThread->Wait();
5499 if (!m_pCurlThread->IsAborting()) {
5500 delete (m_pCurlThread->GetOutputStream());
5501 wxDELETE(m_pCurlThread);
5506void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5510 event.setTotal(ev.GetTotalBytes());
5511 event.setTransferred(ev.GetDownloadedBytes());
5512 event.setComplete(
false);
5514 if (m_download_evHandler) {
5515 m_download_evHandler->AddPendingEvent(event);
5519bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5520 wxCurlBaseThread* p,
5521 const wxString& url) {
5523 case wxCTE_NO_ERROR:
5526 case wxCTE_NO_RESOURCE:
5528 wxS(
"Insufficient resources for correct execution of the program."));
5531 case wxCTE_ALREADY_RUNNING:
5535 case wxCTE_INVALID_PROTOCOL:
5536 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5540 case wxCTE_NO_VALID_STREAM:
5547 case wxCTE_CURL_ERROR: {
5548 wxString ws = wxS(
"unknown");
5549 if (p->GetCurlSession())
5551 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5552 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5557 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.
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.