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"
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;
278 if (ParseVersion(md) >= imported_version)
return true;
289 void message(
const std::string& message) {
291 m_deferred_messages.push_back(message);
296 void show_deferred_messages() {
297 for (
auto m : m_deferred_messages) show_msg(m);
304 void show_msg(wxString msg) {
305 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
306 wxICON_INFORMATION | wxOK, 10);
310 std::vector<wxString> m_deferred_messages;
317 Wrap(win, text, widthMax);
319 wxString
const& GetWrapped()
const {
return m_wrapped; }
320 int const GetLineCount()
const {
return m_lineCount; }
321 wxArrayString GetLineArray() {
return m_array; }
324 virtual void OnOutputLine(
const wxString& line) {
328 virtual void OnNewLine() {
336 wxArrayString m_array;
340 template <
typename T>
341 std::size_t operator()(T t)
const {
342 return static_cast<std::size_t
>(t);
349 return _(
"Plugin is a standard system plugin");
351 return _(
"Plugin is managed by OpenCPN");
353 return _(
"Plugin is not managed by OpenCPN");
356 case PluginStatus::Unknown:
357 return _(
"Plugin status unknown");
358 case PluginStatus::LegacyUpdateAvailable:
359 return _(
"Update to managed Plugin is available");
360 case PluginStatus::ManagedInstallAvailable:
361 return _(
"New managed Plugin installation available");
362 case PluginStatus::ManagedInstalledUpdateAvailable:
363 return _(
"Update to installed Plugin is available");
364 case PluginStatus::ManagedInstalledCurrentVersion:
365 return _(
"Plugin is latest available");
366 case PluginStatus::Imported:
367 return _(
"Plugin is imported");
368 case PluginStatus::ManagedInstalledDowngradeAvailable:
370 case PluginStatus::PendingListRemoval:
377static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
383 {PluginStatus::Unknown,
"emblem-unmanaged.svg"},
384 {PluginStatus::LegacyUpdateAvailable,
"emblem-legacy-update.svg"},
385 {PluginStatus::ManagedInstallAvailable,
"emblem-download.svg"},
386 {PluginStatus::ManagedInstalledUpdateAvailable,
387 "emblem-legacy-update.svg"},
388 {PluginStatus::ManagedInstalledCurrentVersion,
"emblem-default.svg"},
389 {PluginStatus::ManagedInstalledDowngradeAvailable,
390 "emblem-default.svg"},
391 {PluginStatus::PendingListRemoval,
"emblem-default.svg"},
392 {PluginStatus::Imported,
"emblem-default.svg"}});
394static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
395 literalstatus_by_status(
400 {PluginStatus::Unknown,
"Unknown"},
401 {PluginStatus::LegacyUpdateAvailable,
"LegacyUpdateAvailable"},
402 {PluginStatus::ManagedInstallAvailable,
"ManagedInstallAvailable"},
403 {PluginStatus::ManagedInstalledUpdateAvailable,
404 "ManagedInstalledUpdateAvailable"},
405 {PluginStatus::ManagedInstalledCurrentVersion,
406 "ManagedInstalledCurrentVersion"},
407 {PluginStatus::ManagedInstalledDowngradeAvailable,
408 "ManagedInstalledDowngradeAvailable"},
409 {PluginStatus::PendingListRemoval,
"PendingListRemoval"},
410 {PluginStatus::Imported,
"Imported"}
418static std::vector<PluginMetadata> getCompatiblePlugins() {
420 struct metadata_compare {
423 return lhs.key() < rhs.key();
427 std::vector<PluginMetadata> returnArray;
429 std::set<PluginMetadata, metadata_compare> unique_plugins;
430 for (
auto plugin :
PluginHandler::GetInstance()->GetAvailable()) {
431 unique_plugins.insert(plugin);
433 for (
auto plugin : unique_plugins) {
435 returnArray.push_back(plugin);
452 std::string installed;
454 if (path ==
"" || !wxFileName::IsFileReadable(path)) {
457 std::ifstream stream;
458 stream.open(path, std::ifstream::in);
467static std::vector<PluginMetadata> getUpdates(
const char* name) {
468 auto updates = getCompatiblePlugins();
470 std::remove_if(updates.begin(), updates.end(),
474 auto inst_vers = getInstalledVersion(name);
475 if (inst_vers.major == -1) {
480 updates.erase(std::remove_if(updates.begin(), updates.end(),
482 return metadata_version(m) == inst_vers;
489static void gui_uninstall(
const PlugInData* pic,
const char* plugin) {
490 g_Platform->ShowBusySpinner();
495 wxLogMessage(
"Uninstalling %s", plugin);
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) {
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());
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);
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: {
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 loader->SetOnDeactivateCb(
1045 evt_pluglist_change_listener.
Listen(loader->evt_pluglist_change,
this,
1046 EVT_PLUGLIST_CHANGE);
1047 Bind(EVT_PLUGLIST_CHANGE, [&](wxCommandEvent&) {
1049 if (g_options) g_options->itemBoxSizerPanelPlugins->Layout();
1052 evt_load_directory_listener.
Listen(loader->evt_load_directory,
this,
1053 EVT_LOAD_DIRECTORY);
1054 Bind(EVT_LOAD_DIRECTORY, [&](wxCommandEvent&) {
1055 pConfig->SetPath(
"/PlugIns/");
1056 SetPluginOrder(pConfig->Read(
"PluginOrder", wxEmptyString));
1059 evt_load_plugin_listener.
Listen(loader->evt_load_plugin,
this,
1061 Bind(EVT_LOAD_PLUGIN, [&](wxCommandEvent& ev) {
1066 evt_update_chart_types_listener.
Listen(loader->evt_update_chart_types,
this,
1067 EVT_UPDATE_CHART_TYPES);
1068 Bind(EVT_UPDATE_CHART_TYPES,
1069 [&](wxCommandEvent& ev) { UpDateChartDataTypes(); });
1071 evt_plugin_loadall_finalize_listener.
Listen(
1072 loader->evt_plugin_loadall_finalize,
this, EVT_PLUGIN_LOADALL_FINALIZE);
1073 Bind(EVT_PLUGIN_LOADALL_FINALIZE,
1074 [&](wxCommandEvent& ev) { FinalizePluginLoadall(); });
1076 evt_ais_json_listener.
Listen(g_pAIS->
plugin_msg,
this, EVT_PLUGMGR_AIS_MSG);
1078 EVT_PLUGMGR_ROUTEMAN_MSG);
1080 auto pTarget = UnpackEvtPointer<AisTargetData>(ev);
1081 SendAisJsonMessage(pTarget);
1083 Bind(EVT_PLUGMGR_ROUTEMAN_MSG, [&](
ObservedEvt& ev) {
1084 auto msg = UnpackEvtPointer<wxJSONValue>(ev);
1085 SendJSONMessageToAllPlugins(ev.GetString(), *msg);
1093wxDEFINE_EVENT(EVT_DOWNLOAD_FAILED, wxCommandEvent);
1094wxDEFINE_EVENT(EVT_DOWNLOAD_OK, wxCommandEvent);
1096void PlugInManager::HandlePluginHandlerEvents() {
1097 auto loader = PluginLoader::GetInstance();
1099 evt_download_failed_listener.
Listen(loader->evt_update_chart_types,
this,
1100 EVT_DOWNLOAD_FAILED);
1101 Bind(EVT_DOWNLOAD_FAILED, [&](wxCommandEvent& ev) {
1102 wxString message = _(
"Please check system log for more info.");
1103 OCPNMessageBox(gFrame, message, _(
"Installation error"),
1104 wxICON_ERROR | wxOK | wxCENTRE);
1107 evt_download_ok_listener.
Listen(loader->evt_update_chart_types,
this,
1109 Bind(EVT_DOWNLOAD_OK, [&](wxCommandEvent& ev) {
1110 wxString message(ev.GetString());
1111 message += _(
" successfully installed from cache");
1112 OCPNMessageBox(gFrame, message, _(
"Installation complete"),
1113 wxICON_INFORMATION | wxOK | wxCENTRE);
1117bool PlugInManager::CallLateInit(
void) {
1120 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1121 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1124 switch (pic->m_api_version) {
1137 ProcessLateInit(pic);
1147 wxString msg(
"PlugInManager: Calling LateInit PlugIn: ");
1152 if (ppi) ppi->LateInit();
1160 ChartData->PurgeCachePlugins();
1161 gFrame->InvalidateAllQuilts();
1164 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1167 if (pttc->m_pplugin == pic->m_pplugin) {
1168 m_PlugInToolbarTools.Remove(pttc);
1174 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1176 if (pimis->m_pplugin == pic->m_pplugin) {
1177 m_PlugInMenuItems.Remove(pimis);
1183bool PlugInManager::IsAnyPlugInChartEnabled() {
1186 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1187 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1189 if (pic->m_enabled && pic->m_init_state) {
1198void PlugInManager::UpdateManagedPlugins() {
1200 PluginLoader::GetInstance()->
SortPlugins(ComparePlugins);
1203 g_options->itemBoxSizerPanelPlugins->Layout();
1206bool PlugInManager::UpDateChartDataTypes() {
1208 if (NULL == ChartData)
return bret;
1210 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1211 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1214 if (pic->m_init_state) {
1221 if (bret) ChartData->UpdateChartClassDescriptorArray();
1226void PlugInManager::FinalizePluginLoadall() {
1230 SetColorSchemeForAllPlugIns(global_color_scheme);
1233 SendBaseConfigToAllPlugIns();
1234 SendS52ConfigToAllPlugIns(
true);
1235 SendSKConfigToAllPlugIns();
1240 if (gFrame->GetPrimaryCanvas()->GetglCanvas())
1241 gFrame->GetPrimaryCanvas()->GetglCanvas()->SendJSONConfigMessage();
1249void PlugInManager::SetPluginOrder(wxString serialized_names) {
1250 m_plugin_order.Empty();
1251 wxStringTokenizer tokenizer(serialized_names,
";");
1252 while (tokenizer.HasMoreTokens()) {
1253 m_plugin_order.Add(tokenizer.GetNextToken());
1257wxString PlugInManager::GetPluginOrder() {
1258 wxString plugins = wxEmptyString;
1259 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1260 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1261 plugins.Append(plugin_array->Item(i)->m_common_name);
1262 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1267bool PlugInManager::UpdateConfig() {
1271 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1272 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1276 wxString config_section = (_T (
"/PlugIns/" ));
1278 pConfig->SetPath(config_section);
1279 pConfig->Write(_T (
"bEnabled" ), pic->m_enabled);
1286void PlugInManager::ShowDeferredBlacklistMessages() {
1287 m_blacklist_ui->show_deferred_messages();
1290bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1292 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1295bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin* plugin) {
1300 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1301 name.Replace(
"class ", wxEmptyString);
1303 const std::type_info& ti =
typeid(*plugin);
1305 char* realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1306 wxString name = wxString::FromAscii(realname);
1309 return CheckBlacklistedPlugin(name, major, minor);
1312bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
1314 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1315 if (block_status == plug_status::unblocked)
return true;
1316 plug_data data(name.ToStdString(), major, minor);
1317 auto msg = m_blacklist->get_message(block_status, data);
1318 m_blacklist_ui->message(msg);
1322bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC& dc,
1326 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1327 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1329 if (pic->m_enabled && pic->m_init_state) {
1333 wxDC* pdc = dc.GetDC();
1336 switch (pic->m_api_version) {
1338 if (priority > 0)
break;
1345 if (priority > 0)
break;
1348 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1359 if (priority > 0)
break;
1362 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1367 if (priority > 0)
break;
1371 ppi->RenderOverlay(*pdc, &pivp);
1383 if (priority <= 0) {
1387 ppi->RenderOverlay(*pdc, &pivp);
1403 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1405 if ((m_cached_overlay_bm.GetWidth() != vp.
pix_width) ||
1406 (m_cached_overlay_bm.GetHeight() != vp.
pix_height))
1410 mdc.SelectObject(m_cached_overlay_bm);
1411 mdc.SetBackground(*wxBLACK_BRUSH);
1414 bool b_rendered =
false;
1416 switch (pic->m_api_version) {
1418 if (priority > 0)
break;
1425 if (priority > 0)
break;
1428 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1439 if (priority > 0)
break;
1442 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1447 if (priority > 0)
break;
1451 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;
1554 if (priority <= 0) {
1579void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort& vp) {
1580 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1581 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1583 if (pic->m_enabled && pic->m_init_state) {
1592void NotifySetupOptionsPlugin(
const PlugInData* pd) {
1593 PluginLoader::GetInstance()->NotifySetupOptionsPlugin(pd);
1596void PlugInManager::NotifySetupOptions() {
1597 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1598 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1600 NotifySetupOptionsPlugin(pic);
1605 int ok_apply_cancel) {
1606 if (pic->m_enabled && pic->m_init_state) {
1609 auto loader = PluginLoader::GetInstance();
1616void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
1617 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1618 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1621 ClosePlugInPanel(pic, ok_apply_cancel);
1626int PlugInManager::AddCanvasContextMenuItemPIM(wxMenuItem* pitem,
1631 pmic->pmenu_item = pitem;
1632 pmic->m_pplugin = pplugin;
1633 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
1634 : m_plugin_menu_item_id_next;
1636 pmic->b_grey =
false;
1637 pmic->m_in_menu = name;
1638 pmic->extended = is_extended;
1640 m_PlugInMenuItems.Add(pmic);
1642 m_plugin_menu_item_id_next++;
1647void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char* name) {
1648 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1651 if (pimis->id == item) {
1652 m_PlugInMenuItems.Remove(pimis);
1660void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
1662 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1665 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1673void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
1675 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1678 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1679 pimis->b_grey = grey;
1686void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
1687 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1688 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1690 if (pic->m_enabled && pic->m_init_state)
1695void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
1696 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1697 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1699 if (pic->m_enabled && pic->m_init_state)
1704void PlugInManager::PrepareAllPluginContextMenus() {
1705 int canvasIndex = gFrame->GetCanvasIndexUnderMouse();
1706 if (canvasIndex < 0)
return;
1708 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1709 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1711 if (pic->m_enabled && pic->m_init_state) {
1713 switch (pic->m_api_version) {
1733void PlugInManager::SendSKConfigToAllPlugIns() {
1736 v[_T(
"self")] = g_ownshipMMSI_SK;
1740 SendMessageToAllPlugins(wxString(_T(
"OCPN_CORE_SIGNALK")), out);
1743void PlugInManager::SendBaseConfigToAllPlugIns() {
1746 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1747 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1748 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1749 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1750 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1753 if (g_MainToolbar) {
1754 v[_T(
"OpenCPN Toolbar Width")] = g_MainToolbar->GetToolbarRect().width;
1755 v[_T(
"OpenCPN Toolbar Height")] = g_MainToolbar->GetToolbarRect().height;
1756 v[_T(
"OpenCPN Toolbar PosnX")] = g_MainToolbar->GetToolbarRect().x;
1757 v[_T(
"OpenCPN Toolbar PosnY")] = g_MainToolbar->GetToolbarRect().y;
1761 v[_T(
"OpenCPN Zoom Mod Vector")] = g_chart_zoom_modifier_vector;
1762 v[_T(
"OpenCPN Zoom Mod Other")] = g_chart_zoom_modifier_raster;
1763 v[_T(
"OpenCPN Scale Factor Exp")] =
1764 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1765 v[_T(
"OpenCPN Display Width")] = (int)g_display_size_mm;
1772 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1775void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1778 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1779 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1780 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1781 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1782 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1790 v[_T(
"OpenCPN S52PLIB ShowAnchorConditions")] = ps52plib->GetAnchorOn();
1791 v[_T(
"OpenCPN S52PLIB ShowQualityOfData")] = ps52plib->GetQualityOfData();
1796 v[_T(
"OpenCPN S52PLIB MetaDisplay")] = ps52plib->m_bShowMeta;
1797 v[_T(
"OpenCPN S52PLIB DeclutterText")] = ps52plib->m_bDeClutterText;
1798 v[_T(
"OpenCPN S52PLIB ShowNationalText")] = ps52plib->m_bShowNationalTexts;
1799 v[_T(
"OpenCPN S52PLIB ShowImportantTextOnly")] =
1800 ps52plib->m_bShowS57ImportantTextOnly;
1801 v[_T(
"OpenCPN S52PLIB UseSCAMIN")] = ps52plib->m_bUseSCAMIN;
1802 v[_T(
"OpenCPN S52PLIB UseSUPER_SCAMIN")] = ps52plib->m_bUseSUPER_SCAMIN;
1803 v[_T(
"OpenCPN S52PLIB SymbolStyle")] = ps52plib->m_nSymbolStyle;
1804 v[_T(
"OpenCPN S52PLIB BoundaryStyle")] = ps52plib->m_nBoundaryStyle;
1805 v[_T(
"OpenCPN S52PLIB ColorShades")] =
1806 S52_getMarinerParam(S52_MAR_TWO_SHADES);
1807 v[_T(
"OpenCPN S52PLIB Safety Depth")] =
1808 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1809 v[_T(
"OpenCPN S52PLIB Shallow Contour")] =
1810 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1811 v[_T(
"OpenCPN S52PLIB Deep Contour")] =
1812 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1816 v[_T(
"OpenCPN S52PLIB GlobalReconfig")] = bReconfig;
1821 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1824void PlugInManager::NotifyAuiPlugIns(
void) {
1825 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1826 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1828 if (pic->m_enabled && pic->m_init_state &&
1834int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1835 wxBitmap* bmpRollover, wxItemKind kind,
1836 wxString shortHelp, wxString longHelp,
1837 wxObject* clientData,
int position,
1840 pttc->label = label;
1842 if (!bitmap->IsOk()) {
1844 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1847 pttc->bitmap_day =
new wxBitmap(*bitmap);
1848 pttc->bitmap_day->UnShare();
1851 if (!bmpRollover->IsOk()) {
1853 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1856 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1857 pttc->bitmap_Rollover_day->UnShare();
1860 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1861 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1862 pttc->bitmap_Rollover_dusk =
1863 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1864 pttc->bitmap_Rollover_night =
1865 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1868 pttc->shortHelp = shortHelp;
1869 pttc->longHelp = longHelp;
1870 pttc->clientData = clientData;
1871 pttc->position = position;
1872 pttc->m_pplugin = pplugin;
1873 pttc->tool_sel = tool_sel;
1875 pttc->b_toggle =
false;
1876 pttc->id = m_plugin_tool_id_next;
1878 m_PlugInToolbarTools.Add(pttc);
1880 m_plugin_tool_id_next++;
1885int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1886 wxString SVGRolloverfile,
1887 wxString SVGToggledfile, wxItemKind kind,
1888 wxString shortHelp, wxString longHelp,
1889 wxObject* clientData,
int position,
1892 pttc->label = label;
1894 pttc->pluginNormalIconSVG = SVGfile;
1895 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1896 pttc->pluginToggledIconSVG = SVGToggledfile;
1901 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1902 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1903 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1904 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1905 pttc->bitmap_Rollover_dusk =
1906 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1907 pttc->bitmap_Rollover_night =
1908 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1911 pttc->shortHelp = shortHelp;
1912 pttc->longHelp = longHelp;
1913 pttc->clientData = clientData;
1914 pttc->position = position;
1915 pttc->m_pplugin = pplugin;
1916 pttc->tool_sel = tool_sel;
1918 pttc->b_toggle =
false;
1919 pttc->id = m_plugin_tool_id_next;
1921 m_PlugInToolbarTools.Add(pttc);
1923 m_plugin_tool_id_next++;
1928void PlugInManager::RemoveToolbarTool(
int tool_id) {
1929 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1932 if (pttc->id == tool_id) {
1933 m_PlugInToolbarTools.Remove(pttc);
1939 pParent->RequestNewToolbars();
1942void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1943 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1946 if (pttc->id == item) {
1948 pParent->RequestNewToolbars();
1955void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1956 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1959 if (pttc->id == item) {
1960 pttc->b_toggle = toggle;
1961 pParent->SetMasterToolbarItemState(item, toggle);
1968void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1969 wxBitmap* bmpRollover) {
1970 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1973 if (pttc->id == item) {
1974 delete pttc->bitmap_day;
1975 delete pttc->bitmap_dusk;
1976 delete pttc->bitmap_night;
1977 delete pttc->bitmap_Rollover_day;
1979 if (!bitmap->IsOk()) {
1981 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1984 pttc->bitmap_day =
new wxBitmap(*bitmap);
1985 pttc->bitmap_day->UnShare();
1988 if (!bmpRollover->IsOk()) {
1990 pttc->bitmap_Rollover_day =
1991 new wxBitmap(style->GetIcon(_T(
"default_pi")));
1994 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1995 pttc->bitmap_Rollover_day->UnShare();
1998 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1999 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
2001 pParent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
2002 pttc->bitmap_Rollover_day);
2009void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2010 wxString SVGfileRollover,
2011 wxString SVGfileToggled) {
2012 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2015 if (pttc->id == item) {
2016 pttc->pluginNormalIconSVG = SVGfile;
2017 pttc->pluginRolloverIconSVG = SVGfileRollover;
2018 pttc->pluginToggledIconSVG = SVGfileToggled;
2019 pParent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2020 pttc->pluginRolloverIconSVG,
2021 pttc->pluginToggledIconSVG);
2029 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2031 if (
id == pc->id)
return pc->m_pplugin;
2037wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2040 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2041 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2043 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2047 return wxEmptyString;
2050wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2052wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2053 unsigned char dim_ratio) {
2054 wxImage img_dup = pbmp_normal->ConvertToImage();
2056 if (!img_dup.IsOk())
return NULL;
2058 if (dim_ratio < 200) {
2060 int gimg_width = img_dup.GetWidth();
2061 int gimg_height = img_dup.GetHeight();
2063 double factor = (double)(dim_ratio) / 256.0;
2065 for (
int iy = 0; iy < gimg_height; iy++) {
2066 for (
int ix = 0; ix < gimg_width; ix++) {
2067 if (!img_dup.IsTransparent(ix, iy)) {
2068 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2069 img_dup.GetGreen(ix, iy),
2070 img_dup.GetBlue(ix, iy));
2071 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2072 hsv.value = hsv.value * factor;
2073 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2074 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2080 wxBitmap* ptoolBarBitmap;
2083 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2085 dwxdc.SelectObject(tbmp);
2087 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2089 ptoolBarBitmap =
new wxBitmap(img_dup);
2093 return ptoolBarBitmap;
2096wxArrayString PlugInManager::GetPlugInChartClassNameArray(
void) {
2097 wxArrayString array;
2098 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2099 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2101 if (pic && pic->m_enabled && pic->m_init_state &&
2106 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2107 array.Add(carray[j]);
2115 while (j < array.GetCount()) {
2116 wxString test = array[j];
2117 unsigned int k = j + 1;
2118 while (k < array.GetCount()) {
2119 if (test == array[k]) {
2137#define DISABLED_SETTINGS_MSG \
2138 _("These settings might destabilize OpenCPN and are by default disabled." \
2139 " To despite the dangers enable them manually add a CatalogExpert=1" \
2140 " line in the [PlugIns] section in the configuration file.")
2145CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2146 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2148 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2151 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2153 wxStaticBox* itemStaticBoxSizer4Static =
2154 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2155 wxStaticBoxSizer* itemStaticBoxSizer4 =
2156 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2157 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2161 m_catalogText =
new wxStaticText(
this, wxID_STATIC, _T(
""));
2162 itemStaticBoxSizer4->Add(m_catalogText,
2163 wxSizerFlags().Border().Proportion(1));
2164 m_catalogText->SetLabel(GetCatalogText(
false));
2167 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2168 itemStaticBoxSizer4->Add(rowSizer2,
2169 wxSizerFlags().Expand().Border().Proportion(1));
2171 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2172 wxDefaultPosition, wxDefaultSize, 0);
2173 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2174 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2175 &CatalogMgrPanel::OnUpdateButton,
this);
2176 rowSizer2->AddSpacer(4 * GetCharWidth());
2177 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2178 wxDefaultPosition, wxDefaultSize, 0);
2179 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2180 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2181 &CatalogMgrPanel::OnTarballButton,
this);
2183 rowSizer2->AddSpacer(4 * GetCharWidth());
2184 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2185 wxDefaultPosition, wxDefaultSize, 0);
2187 if (expert.Get(
false)) {
2188 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2189 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2191 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2192 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2195 rowSizer2->AddSpacer(4 * GetCharWidth());
2196 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2198 SetUpdateButtonLabel();
2201 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2202 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2204 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2208 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2209 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2210 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2213 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2215 if (!expert.Get(
false)) {
2217 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2218 wxDefaultPosition, wxDefaultSize, 0);
2219 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2220 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2221 &CatalogMgrPanel::OnUpdateButton,
this);
2222 SetUpdateButtonLabel();
2223 m_tarballButton = NULL;
2224 m_adv_button = NULL;
2227 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2228 itemStaticBoxSizer4->Add(m_catalogText,
2229 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2232 m_updateButton =
new wxButton(
2233 this, wxID_ANY,
"Update Plugin Catalog:master ",
2234 wxDefaultPosition, wxDefaultSize, 0);
2235 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2236 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2237 &CatalogMgrPanel::OnUpdateButton,
this);
2238 SetUpdateButtonLabel();
2241 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2242 wxDefaultPosition, wxDefaultSize, 0);
2243 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2245 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2246 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2249 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2250 wxDefaultPosition, wxDefaultSize, 0);
2251 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2252 2 * GetCharWidth());
2253 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2254 &CatalogMgrPanel::OnTarballButton,
this);
2260CatalogMgrPanel::~CatalogMgrPanel() {
2261 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2262 &CatalogMgrPanel::OnUpdateButton,
this);
2263 if (m_tarballButton)
2264 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2265 &CatalogMgrPanel::OnTarballButton,
this);
2268static const char*
const DOWNLOAD_REPO_PROTO =
2269 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2272void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2274 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2275 std::string url(g_catalog_custom_url);
2276 if (catalog !=
"custom") {
2277 url = std::string(DOWNLOAD_REPO_PROTO);
2281 std::string filePath =
2282 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2284 auto catalogHdlr = CatalogHandler::GetInstance();
2286 g_Platform->ShowBusySpinner();
2287 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2288 g_Platform->HideBusySpinner();
2290 std::string message;
2291 if (status != CatalogHandler::ServerStatus::OK) {
2292 message = _(
"Cannot download data from url");
2293 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2294 wxICON_ERROR | wxOK);
2300 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2302 wxFileName::GetPathSeparator() +
2303 _T(
"ocpn-plugins.xml"))) {
2304 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2305 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2310 if (!wxCopyFile(wxString(filePath.c_str()),
2312 wxFileName::GetPathSeparator() +
2313 _T(
"ocpn-plugins.xml"))) {
2314 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2315 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2321 if (catalog ==
"master") {
2323 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2324 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2330 pConfig->SetPath(_T(
"/PlugIns/"));
2331 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2338 pluginHandler->setMetadata(
"");
2342 auto cataloghdlr = CatalogHandler::GetInstance();
2343 cataloghdlr->ClearCatalogData();
2346 LoadAllPlugIns(
false);
2350 m_catalogText->SetLabel(GetCatalogText(
true));
2353 OCPNMessageBox(
this, _(
"Catalog update successful"),
2354 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2357void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2361 androidDisableRotation();
2364 dialog->ShowModal();
2367 androidEnableRotation();
2371void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2374 int response = g_Platform->DoFileSelectorDialog(
2375 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2376 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2378 if (response != wxID_OK) {
2383 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2387 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2388 _(
"OpenCPN Plugin Import Error"));
2392 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2393 _(
"OpenCPN Plugin Import Error"));
2394 handler->Uninstall(metadata.name);
2397 UninstallPlugin(metadata.name);
2398 ok = handler->InstallPlugin(metadata, path.ToStdString());
2400 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2401 _(
"OpenCPN Plugin Import Error"));
2404 metadata.is_imported =
true;
2406 std::ofstream file(metadata_path);
2409 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2410 <<
" for imported plugin: " << metadata.name;
2412 LoadAllPlugIns(
false,
true);
2415 wxString ws(_(
"Plugin"));
2416 ws += metadata.name + _(
" successfully imported");
2417 OCPNMessageBox(gFrame, ws, _(
"Installation complete"),
2418 wxICON_INFORMATION | wxOK | wxCENTRE);
2421wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2423 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2424 catalog += _T(
": ");
2427 pConfig->SetPath(_T(
"/PlugIns/"));
2428 wxString latestCatalog =
2429 pConfig->Read(_T(
"LatestCatalogDownloaded"), _T(
"default"));
2430 catalog += latestCatalog;
2436 std::string date = pluginHandler->GetCatalogData()->date;
2438 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2439 if (!updated) catalog += _T(
" : ") + _(
"Please Update Plugin Catalog.");
2445void CatalogMgrPanel::SetUpdateButtonLabel() {
2446 wxString label = _(
"Update Plugin Catalog");
2448 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2449 m_updateButton->SetLabel(label);
2453wxString CatalogMgrPanel::GetImportInitDir() {
2455 pConfig->SetPath(_T(
"/PlugIns/"));
2456 wxString lastImportDir;
2457 lastImportDir = pConfig->Read(_T(
"LatestImportDir"),
2458 g_Platform->GetWritableDocumentsDir());
2459 if (wxDirExists(lastImportDir)) {
2460 return lastImportDir;
2462 return (g_Platform->GetWritableDocumentsDir());
2471 const wxPoint& pos, const wxSize& size)
2472 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2473 m_PluginSelected(0) {
2474 m_is_loading.clear();
2475 SetSizer(
new wxBoxSizer(wxVERTICAL));
2476 ReloadPluginPanels();
2479void PluginListPanel::SelectByName(wxString& name) {
2480 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2481 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2483 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2484 pluginPanel->SetSelected(
true);
2485 pluginPanel->Layout();
2486 SelectPlugin(pluginPanel);
2494std::vector<const PlugInData*> GetInstalled() {
2495 std::vector<const PlugInData*> result;
2496 auto loader = PluginLoader::GetInstance();
2497 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2498 auto const item = loader->GetPlugInArray()->Item(i);
2499 if (item->m_managed_metadata.name.empty()) {
2500 const auto name = item->m_common_name.ToStdString();
2504 result.push_back(item);
2507 std::string slhs, srhs;
2508 for (
auto& cl : lhs->Key()) slhs += toupper(cl);
2509 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2510 return slhs.compare(srhs) < 0;
2512 std::sort(result.begin(), result.end(), compare);
2517static bool IsPluginLoaded(
const std::string& name) {
2518 if (safe_mode::get_mode()) {
2521 std::find(installed.begin(), installed.end(),
ocpn::tolower(name));
2522 return found != installed.end();
2525 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2526 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2533 if (m_is_loading.test_and_set()) {
2535 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2540 m_PluginItems.Clear();
2542 wxWindowList kids = GetChildren();
2543 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2544 wxWindowListNode* node = kids.Item(i);
2545 wxWindow* win = node->GetData();
2547 if (pp) win->Destroy();
2549 GetSizer()->Clear();
2552 m_PluginSelected = 0;
2554 if (safe_mode::get_mode()) {
2557 for (
const auto& name : installed) AddPlugin(name);
2560 auto available = getCompatiblePlugins();
2564 return IsPluginLoaded(md.name);
2566 auto end = std::remove_if(available.begin(), available.end(), predicate);
2567 available.erase(end, available.end());
2573 std::string slhs, srhs;
2574 for (
auto& cl : lhs.name) slhs += toupper(cl);
2575 for (
auto& cr : rhs.name) srhs += toupper(cr);
2576 return slhs.compare(srhs) < 0;
2580 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2581 for (
const auto& p : available) unique_sorted_entries.insert(p);
2586 for (
const auto& p : GetInstalled())
2587 if (p->m_enabled) AddPlugin(*p);
2590 for (
const auto& p : GetInstalled())
2591 if (!p->m_enabled) AddPlugin(*p);
2594 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2602 m_is_loading.clear();
2605void PluginListPanel::AddPlugin(
const std::string& name) {
2608 panel->SetSelected(
false);
2609 GetSizer()->Add(panel, 0, wxEXPAND);
2610 m_PluginItems.Add(panel);
2611 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2612 GetSizer()->AddSpacer(m_pluginSpacer);
2615void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2617 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2618 pPluginPanel->SetSelected(
false);
2619 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2620 m_PluginItems.Add(pPluginPanel);
2622 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2623 GetSizer()->AddSpacer(m_pluginSpacer);
2636int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2637 wxBoxSizer* sizer) {
2639 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2640 auto panel = plugins.Item(i);
2641 bool was_selected = panel->GetSelected();
2642 panel->SetSelected(
false);
2644 wxSize unselected = panel->GetSize();
2646 panel->SetSelected(
true);
2648 wxSize selected = panel->GetSize();
2650 int dy = selected.GetHeight() - unselected.GetHeight();
2651 max_dy = wxMax(max_dy, dy);
2652 panel->SetSelected(was_selected);
2657PluginListPanel::~PluginListPanel() {}
2659void PluginListPanel::UpdateSelections() {
2660 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2663 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2668void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2670 GetViewStart(&xs, &ys);
2673 if (m_PluginSelected) {
2674 m_PluginSelected->SetSelected(
false);
2675 m_PluginSelected->Layout();
2678 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2680 m_PluginSelected = pi;
2682 GetSizer()->Layout();
2684 wxSize size = GetBestVirtualSize();
2685 SetVirtualSize(size);
2690 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2692 int yd = pPluginPanel->GetSize().y;
2694 htop += m_pluginSpacer;
2695 if (pPluginPanel == pi) {
2696 int piBottom = htop - (ys * g_options->GetScrollRate());
2697 if (piBottom > GetClientSize().y) {
2698 ys += (piBottom - GetClientSize().y) / g_options->GetScrollRate();
2708 int pos = m_PluginItems.Index(pi);
2711 m_PluginItems.RemoveAt(pos);
2714 m_PluginItems.Insert(pi, pos - 1);
2715 wxStaticLine* itemStaticLine =
new wxStaticLine(
2716 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2721 m_PluginSelected = pi;
2723 GetSizer()->Layout();
2729 int pos = m_PluginItems.Index(pi);
2730 if (pos == (
int)m_PluginItems.Count() -
2733 m_PluginItems.RemoveAt(pos);
2736 m_PluginItems.Insert(pi, pos + 1);
2737 wxStaticLine* itemStaticLine =
new wxStaticLine(
2738 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2743 m_PluginSelected = pi;
2745 GetSizer()->Layout();
2750static bool canUninstall(std::string name) {
2754 for (
auto plugin : pluginHandler->GetInstalled()) {
2755 if (plugin.name == name) {
2756 if (safe_mode::get_mode())
2759 return !plugin.readonly;
2766 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2768 m_is_safe_panel(true) {
2770 wxASSERT(m_PluginListPanel != 0);
2771 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2772 SetSizer(top_sizer);
2773 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2774 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2776 double iconSize = GetCharWidth() * 4;
2778 int icon_scale = iconSize * dpi_mult;
2780 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2781 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2782 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2784 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2785 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2786 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2787 top_horizontal->Add(m_pVersion);
2790 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2791 top_horizontal->Add(m_pButtons);
2792 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2793 top_horizontal->Add(m_info_btn);
2794 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2795 wxDefaultPosition, wxDefaultSize, 0);
2796 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2798 auto uninstall = [&](wxCommandEvent ev) {
2799 auto n = m_pName->GetLabel().ToStdString();
2801 OCPNMessageBox(gFrame, std::string(_(
"Uninstall plugin ")) + n +
"?",
2802 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2803 if (result != wxID_OK)
return;
2807 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2811EVT_PAINT(PluginPanel::OnPaint)
2816 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2818 m_is_safe_panel(false) {
2821 wxASSERT(m_PluginListPanel != 0);
2823 m_bSelected =
false;
2824 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2825 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2827 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2830 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2831 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2832 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2833 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2835 double iconSize = GetCharWidth() * 4;
2837 int icon_scale = iconSize * dpi_mult;
2839 wxImage plugin_icon;
2841 if (m_plugin.m_bitmap.IsOk()) {
2842 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2845 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2846 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2847 path.AppendDir(
"uidata");
2848 path.AppendDir(
"traditional");
2849 bitmap = LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2850 }
else if (plugin_icon.IsOk()) {
2851 int nowSize = plugin_icon.GetWidth();
2852 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2853 bitmap = wxBitmap(plugin_icon);
2855 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2857 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2859 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2860 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2862 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2865 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2866 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2869 int nChars = g_options->GetSize().x / GetCharWidth();
2870 bool bCompact =
false;
2876 wxString nameString = m_plugin.m_common_name;
2880 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2881 if (nameWidth > maxWidth) {
2882 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2883 wxELLIPSIZE_END, maxWidth);
2885 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2886 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2887 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2888 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2890 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2891 sl1->AddGrowableCol(1);
2892 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2894 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2895 sl1->Add(m_pVersion, 0, wxALL, 5);
2896 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2899 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2900 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2902 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2903 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2904 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2907 wxString descriptionString = m_plugin.m_short_description;
2908 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2909 int descriptionWidth;
2910 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2911 if (descriptionWidth > maxDescriptionWidth)
2913 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2914 wxELLIPSIZE_END, maxDescriptionWidth);
2919 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2920 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2921 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2922 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2923 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2926 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2927 itemBoxSizer03->AddGrowableCol(2);
2928 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2930 wxString nameString = m_plugin.m_common_name;
2931 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2932 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2933 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2937 wxFont font = GetFont();
2938 font.SetWeight(wxFONTWEIGHT_BOLD);
2939 m_pName->SetFont(font);
2942 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2944 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2945 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2946 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2949 !m_plugin.m_managed_metadata.is_orphan)) {
2952 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2953 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2955 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2956 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2957 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2959 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2961 m_pDescription =
new wxStaticText(
2962 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2964 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2965 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2966 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2970 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2972 itemBoxSizer02->Add(m_info_btn, 0);
2974 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2975 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2976 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2977 wxDefaultPosition, wxDefaultSize, 0);
2978 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
2980 m_pButtons->AddSpacer(3 * GetCharWidth());
2983 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
2984 wxDefaultPosition, wxDefaultSize, 0);
2985 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
2987 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2988 wxDefaultPosition, wxDefaultSize, 0);
2989 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
2991 m_pButtons =
new wxBoxSizer(wxVERTICAL);
2992 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2994 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
2995 m_pButtons->Add(tline, 0, wxALL, 2);
2997 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2998 wxDefaultPosition, wxDefaultSize, 0);
2999 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
3001 tline->AddSpacer(3 * GetCharWidth());
3003 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
3005 tline->Add(m_info_btn, 0);
3008 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3009 wxDefaultPosition, wxDefaultSize);
3010 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3012 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3013 wxDefaultPosition, wxDefaultSize, 0);
3014 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3017 wxBitmap statusBitmap;
3018 const auto stat = m_plugin.m_status;
3019 auto icon_name = icon_by_status.at(stat);
3020 if (stat == PluginStatus::Imported &&
3021 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3023 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3026 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3027 path.AppendDir(
"uidata");
3028 path.AppendDir(
"traditional");
3030 int bmsize = GetCharWidth() * 3 * dpi_mult;
3031 if (path.IsFileReadable()) {
3032 statusBitmap = LoadSVG(path.GetFullPath(), bmsize, bmsize);
3033 ok = statusBitmap.IsOk();
3036 auto style = g_StyleManager->GetCurrentStyle();
3037 statusBitmap = wxBitmap(style->GetIcon(_T(
"default_pi"), bmsize, bmsize));
3038 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3041 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3042 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3043 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3045 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3048 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3050 itemBoxSizer02->AddSpacer(GetCharWidth());
3052 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3053 &PluginPanel::OnPluginPreferences,
this);
3054 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3055 &PluginPanel::OnPluginUninstall,
this);
3056 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3057 &PluginPanel::OnPluginAction,
this);
3059 SetSelected(m_bSelected);
3060 SetAutoLayout(
true);
3068PluginPanel::~PluginPanel() {
3069 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3070 if (m_is_safe_panel)
return;
3071 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3073 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3074 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3075 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3076 if (m_pButtonAction) {
3077 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3078 &PluginPanel::OnPluginAction,
this);
3080 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3081 &PluginPanel::OnPluginPreferences,
this);
3082 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3083 &PluginPanel::OnPluginEnableToggle,
this);
3086void PluginPanel::SetActionLabel(wxString& label) {
3087 m_pButtonAction->SetLabel(label);
3091static wxStopWatch swclick;
3092static int downx, downy;
3094void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3097 event.GetPosition(&downx, &downy);
3103void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3105 qDebug() << swclick.Time();
3106 if (swclick.Time() < 200) {
3108 event.GetPosition(&upx, &upy);
3109 if ((fabs(upx - downx) < GetCharWidth()) &&
3110 (fabs(upy - downy) < GetCharWidth())) {
3118void PluginPanel::DoPluginSelect() {
3119 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3125 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3126 }
else if (m_bSelected) {
3128 m_PluginListPanel->SelectPlugin(NULL);
3131 m_PluginListPanel->SelectPlugin(
this);
3139static PluginMetadata GetMetadataByName(
const std::string& name) {
3141 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3142 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3143 if (found == plugins.end()) {
3144 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3149void PluginPanel::SetSelected(
bool selected) {
3150 m_bSelected = selected;
3152 m_pVersion->SetLabel(
3155 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3156 m_pButtons->Show(
true);
3157 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3160 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3163 unInstallPossible =
false;
3166 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3168 m_pButtonUninstall->Show(unInstallPossible);
3170 if (m_plugin.m_managed_metadata.info_url.size()) {
3171 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3175 m_cbEnable->Show(
true);
3180 switch (m_plugin.m_status) {
3181 case PluginStatus::LegacyUpdateAvailable:
3182 label = _(
"Upgrade to Version ");
3183 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3184 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3185 m_pButtonAction->Enable();
3188 case PluginStatus::ManagedInstallAvailable:
3189 label = _(
"Install...");
3190 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3191 m_pButtonAction->Enable();
3194 case PluginStatus::ManagedInstalledUpdateAvailable:
3195 label = _(
"Update to ");
3196 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3197 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3198 m_pButtonAction->Enable();
3201 case PluginStatus::ManagedInstalledCurrentVersion:
3202 label = _(
"Reinstall");
3203 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3204 m_pButtonAction->Enable();
3207 case PluginStatus::ManagedInstalledDowngradeAvailable:
3208 label = _(
"Downgrade");
3209 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3210 m_pButtonAction->Enable();
3213 case PluginStatus::Imported:
3214 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3215 label = _(
"Update");
3216 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3218 m_pButtonAction->Hide();
3219 m_action = ActionVerb::NOP;
3224 m_action = ActionVerb::NOP;
3225 m_pButtonAction->Hide();
3229 m_action = ActionVerb::NOP;
3230 m_pButtonAction->Hide();
3235 m_action = ActionVerb::NOP;
3238 SetActionLabel(label);
3241 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3250 m_pButtons->Show(
false);
3253 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3254 m_cbEnable->Show(
false);
3270 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3272 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3275 SetEnabled(m_plugin.m_enabled);
3290void PluginPanel::OnPaint(wxPaintEvent& event) {
3293 int penWidth = m_penWidthUnselected;
3294 wxColour color = GetDialogColor(DLG_UNSELECTED_BACKGROUND);
3295 wxColour border = GetDialogColor(DLG_UNSELECTED_ACCENT);
3298 penWidth = m_penWidthSelected;
3299 color = GetDialogColor(DLG_SELECTED_BACKGROUND);
3300 border = GetDialogColor(DLG_SELECTED_ACCENT);
3303 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3305 dc.SetPen(wxPen(border, penWidth));
3307 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3310void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3311 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3314 androidDisableRotation();
3325void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3326 SetEnabled(event.IsChecked());
3327 m_pVersion->SetLabel(
3336void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3337 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
3340 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3341 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3342 actionEvent.SetClientData(
this);
3343 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3346void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3348 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3349 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3350 actionEvent.SetClientData(
this);
3351 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3356static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3357 auto font = window->GetFont();
3358 font.SetStyle(style);
3359 window->SetFont(font);
3362void PluginPanel::SetEnabled(
bool enabled) {
3363 if (m_is_safe_panel)
return;
3366 if (enabled) NotifySetupOptionsPlugin(&m_plugin);
3367 if (!enabled && !m_bSelected) {
3368 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3369 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3370 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3373 m_pVersion->Disable();
3374 m_pDescription->Disable();
3377 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3378 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3379 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3382 m_pVersion->Enable();
3383 m_pDescription->Enable();
3388 m_pName->Enable(enabled || m_bSelected);
3389 m_pVersion->Enable(enabled || m_bSelected);
3390 m_pDescription->Enable(enabled || m_bSelected);
3394 wxString description = m_plugin.m_long_description;
3395 if (description.IsEmpty())
3396 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3399 g_options->GetSize().x * 7 / 10);
3400 m_pDescription->SetLabel(wrapper.GetWrapped());
3401 if (m_plugin.m_managed_metadata.info_url.size()) {
3402 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3406 wxString description = m_plugin.m_short_description;
3407 if (description.IsEmpty())
3408 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3410 g_options->GetSize().x * 7 / 10);
3411 m_pDescription->SetLabel(wrapper.GetWrapped());
3414 m_pButtonPreferences->Enable(enabled &&
3416 m_cbEnable->SetValue(enabled);
3419void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3420 m_PluginListPanel->MoveUp(
this);
3423void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3424 m_PluginListPanel->MoveDown(
this);
3429 : wxPanel(parent), m_url(url) {
3430 auto vbox =
new wxBoxSizer(wxVERTICAL);
3431 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3432 button->Enable(strlen(url) > 0);
3435 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3436 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3444PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3446PlugInChartBase::~PlugInChartBase() {}
3455 bool b_allow_overzoom) {
3467 const wxRegion& Region) {
3468 return wxNullBitmap;
3477 wxRegion* pValidRegion) {}
3490 wxRect* pSourceRect) {}
3507 double* plat,
double* plon) {}
3514PlugInChartBaseGL::PlugInChartBaseGL() {}
3516PlugInChartBaseGL::~PlugInChartBaseGL() {}
3520 const wxRegion& Region,
3521 bool b_use_stencil) {
3547PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3549PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3553 const wxRegion& Region,
3554 bool b_use_stencil) {
3560 const wxRegion& Region,
bool b_use_stencil) {
3566 const wxRegion& Region,
bool b_use_stencil) {
3572 return wxNullBitmap;
3576 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3580ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3585wxString PlugInChartBaseExtended::CreateObjDescriptions(
3586 ListOfPI_S57Obj* obj_list) {
3590int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3592int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3594int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3596float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3605PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3607PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3610PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3620PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3622PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3634ChartPlugInWrapper::ChartPlugInWrapper() {}
3636ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3637 m_ppo = ::wxCreateDynamicObject(chart_class);
3641ChartPlugInWrapper::~ChartPlugInWrapper() {
3642 if (m_ppicb)
delete m_ppicb;
3645wxString ChartPlugInWrapper::GetFileSearchMask(
void) {
3652InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3653 ChartInitFlag init_flags) {
3655 wxWindow* pa = wxWindow::FindFocus();
3657 InitReturn ret_val = (InitReturn)m_ppicb->
Init(name, (
int)init_flags);
3661 if (ret_val == INIT_OK) {
3668 m_ID = m_ppicb->
GetID();
3672 m_SE = m_ppicb->
GetSE();
3686 if ((fabs(m_Chart_Skew) < .01) &&
3687 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3689 if (GetChartExtent(&extent)) {
3690 double lon_range = extent.ELON - extent.WLON;
3691 if ((lon_range > 0) &&
3693 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3697 m_overlayENC =
false;
3699 wxCharBuffer buf = m_FullPath.ToUTF8();
3700 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3706 m_ChartType = CHART_TYPE_UNKNOWN;
3707 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3713 if (pc) pc->SetFocus();
3717 return INIT_FAIL_REMOVE;
3721int ChartPlugInWrapper::GetCOVREntries() {
3728int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3735int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3742float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3754int ChartPlugInWrapper::GetNoCOVREntries() {
3764int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3774int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3784float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3794bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3798 pext->NLAT = xpi.
NLAT;
3799 pext->SLAT = xpi.
SLAT;
3800 pext->ELON = xpi.
ELON;
3801 pext->WLON = xpi.
WLON;
3810ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3815 if (!pThumbData->pDIBThumb) {
3816 wxBitmap* pBMPOwnedByChart =
3817 m_ppicb->
GetThumbnail(tnx, tny, m_global_color_scheme);
3818 if (pBMPOwnedByChart) {
3819 wxImage img = pBMPOwnedByChart->ConvertToImage();
3820 pThumbData->pDIBThumb =
new wxBitmap(img);
3822 pThumbData->pDIBThumb = NULL;
3825 pThumbData->Thumb_Size_X = tnx;
3826 pThumbData->Thumb_Size_Y = tny;
3853 pThumbData->ShipX = 0;
3854 pThumbData->ShipY = 0;
3861ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3863bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3867double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3868 bool b_allow_overzoom) {
3875double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3897void RenderRotateToViewPort(
const ViewPort& VPoint) {
3898#ifndef USE_ANDROID_GLES2
3900 glTranslatef(xt, yt, 0);
3901 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3902 glTranslatef(-xt, -yt, 0);
3906void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3907#ifndef USE_ANDROID_GLES2
3909 glTranslatef(xt, yt, 0);
3910 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3911 glTranslatef(-xt, -yt, 0);
3915bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3918 const LLRegion& Region) {
3927 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3928 wxRegion* r = RectRegion.GetNew_wxRegion();
3931 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3932 chart_region.Intersect(Region);
3934 if (!chart_region.Empty()) {
3935 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3937 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3941#ifndef USE_ANDROID_GLES2
3944 RenderRotateToViewPort(VPoint);
3949 glChartCanvas::s_b_useStencil);
3952 glChartCanvas::s_b_useStencil);
3953 UndoRenderRotateToViewPort(VPoint);
3955#ifndef USE_ANDROID_GLES2
3958 glChartCanvas::DisableClipRegion();
3972bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
3973 const wxGLContext& glc,
const ViewPort& VPoint,
3974 const OCPNRegion& RectRegion,
const LLRegion& Region) {
3983 if (!Region.Empty() && ppicb_x) {
3985 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
3986 glChartCanvas::DisableClipRegion();
3989 RenderRotateToViewPort(VPoint);
3992 wxRegion* r = RectRegion.GetNew_wxRegion();
3995 glChartCanvas::s_b_useStencil);
3998 UndoRenderRotateToViewPort(VPoint);
4003 else if (!Region.Empty() &&
4007 wxRegion* r = RectRegion.GetNew_wxRegion();
4010 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4011 chart_region.Intersect(Region);
4013 if (!chart_region.Empty()) {
4014 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4016 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4018 RenderRotateToViewPort(VPoint);
4022 glChartCanvas::s_b_useStencil);
4025 UndoRenderRotateToViewPort(VPoint);
4027 glChartCanvas::DisableClipRegion();
4040bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4047 if (!Region.Empty() && ppicb_x) {
4048 wxRegion* r = Region.GetNew_wxRegion();
4050#ifndef USE_ANDROID_GLES2
4053 RenderRotateToViewPort(VPoint);
4057 glChartCanvas::s_b_useStencil);
4058 UndoRenderRotateToViewPort(VPoint);
4060#ifndef USE_ANDROID_GLES2
4073bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4079 if (Region.IsOk()) {
4080 wxRegion* r = Region.GetNew_wxRegion();
4087 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4088 wxColour nodat_sub = nodat;
4090#ifdef ocpnUSE_ocpnBitmap
4091 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4093 m_pMask =
new wxMask(obmp, nodat_sub);
4094 obmp.SetMask(m_pMask);
4096 dc.SelectObject(obmp);
4107bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4118 if (Region.IsOk() && (pCBx || ppicb)) {
4119 wxRegion* r = Region.GetNew_wxRegion();
4134bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4137 bool ret_val =
false;
4140 if (Region.IsOk()) {
4141 wxRegion* r = Region.GetNew_wxRegion();
4155void ChartPlugInWrapper::ClearPLIBTextList() {
4163bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4167 return m_ppicb->
AdjustVP(pivp_last, pivp_proposed);
4172void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4187void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4191 m_global_color_scheme = cs;
4193 if (pThumbData) pThumbData->pDIBThumb = NULL;
4197 double target_scale_ppm) {
4204void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4205 wxRect* pSourceRect) {
4212double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4214 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4219bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4221 wxCriticalSectionLocker locker(m_critSect);
4230int ChartPlugInWrapper::GetSize_X() {
4237int ChartPlugInWrapper::GetSize_Y() {
4244void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4245 double& pixx,
double& pixy) {
4249void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4250 double* plat,
double* plon) {
4264wxString toSDMM_PlugIn(
int NEflag,
double a,
bool hi_precision) {
4265 return toSDMM(NEflag, a, hi_precision);
4268wxColour GetBaseGlobalColor(wxString colorName) {
4269 return GetGlobalColor(colorName);
4272int OCPNMessageBox_PlugIn(wxWindow* parent,
const wxString& message,
4273 const wxString& caption,
int style,
int x,
int y) {
4274 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4277wxString GetOCPN_ExePath(
void) {
return g_Platform->GetExePath(); }
4279wxString* GetpPlugInLocation() {
return g_Platform->GetPluginDirPtr(); }
4281wxString GetWritableDocumentsDir(
void) {
4282 return g_Platform->GetWritableDocumentsDir();
4287 auto loader = PluginLoader::GetInstance();
4288 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4290 if (pic->m_pplugin == pplugin) {
4300ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4303 ListOfPI_S57Obj* list = NULL;
4317 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4327 ListOfPI_S57Obj* rule_list) {
4338 ret_str = picbx->CreateObjDescriptions(rule_list);
4346wxString PI_GetPLIBColorScheme() {
4350int PI_GetPLIBDepthUnitInt() {
4352 return ps52plib->m_nDepthUnitDisplay;
4357int PI_GetPLIBSymbolStyle() {
4359 return ps52plib->m_nSymbolStyle;
4364int PI_GetPLIBBoundaryStyle() {
4366 return ps52plib->m_nBoundaryStyle;
4376 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4378 ViewPort cvp = CreateCompatibleViewport(*vp);
4383 ObjRazRules rzRules;
4384 rzRules.obj = &cobj;
4385 rzRules.LUP = pContext->LUP;
4386 rzRules.sm_transform_parms = 0;
4387 rzRules.child = NULL;
4388 rzRules.next = NULL;
4390 if (pContext->LUP) {
4391 ps52plib->SetVPointCompat(
4395 ps52plib->PrepareForRender();
4397 return ps52plib->ObjectRenderCheck(&rzRules);
4404int PI_GetPLIBStateHash() {
4406 return ps52plib->GetStateHash();
4411void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4412 chart_context* pctx) {
4415 cobj->att_array = pObj->att_array;
4416 cobj->attVal = pObj->attVal;
4417 cobj->n_attr = pObj->n_attr;
4422 cobj->npt = pObj->npt;
4424 cobj->iOBJL = pObj->iOBJL;
4425 cobj->Index = pObj->Index;
4427 cobj->geoPt = (pt*)pObj->geoPt;
4428 cobj->geoPtz = pObj->geoPtz;
4429 cobj->geoPtMulti = pObj->geoPtMulti;
4431 cobj->m_lat = pObj->m_lat;
4432 cobj->m_lon = pObj->m_lon;
4434 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4435 cobj->x_rate = pObj->x_rate;
4436 cobj->y_rate = pObj->y_rate;
4437 cobj->x_origin = pObj->x_origin;
4438 cobj->y_origin = pObj->y_origin;
4440 cobj->Scamin = pObj->Scamin;
4441 cobj->nRef = pObj->nRef;
4442 cobj->bIsAton = pObj->bIsAton;
4443 cobj->bIsAssociable = pObj->bIsAssociable;
4445 cobj->m_n_lsindex = pObj->m_n_lsindex;
4446 cobj->m_lsindex_array = pObj->m_lsindex_array;
4447 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4450 cobj->m_ls_list_legacy =
4454 cobj->m_ls_list_legacy = 0;
4455 cobj->m_ls_list = 0;
4458 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4460 cobj->m_bcategory_mutable =
true;
4464 if (pObj->m_DPRI == -1) {
4466 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4468 cobj->m_DPRI = pObj->m_DPRI;
4471 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4472 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4474 if (pObj->auxParm3 != 1234) {
4475 pObj->auxParm3 = 1234;
4476 pObj->auxParm0 = -99;
4479 cobj->auxParm0 = pObj->auxParm0;
4486 if (pContext->bBBObj_valid)
4488 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4489 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4491 cobj->CSrules = pContext->CSrules;
4492 cobj->bCS_Added = pContext->bCS_Added;
4494 cobj->FText = pContext->FText;
4495 cobj->bFText_Added = pContext->bFText_Added;
4496 cobj->rText = pContext->rText;
4498 cobj->bIsClone =
true;
4501 cobj->m_chart_context = pctx;
4502 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4505 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4506 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4507 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4508 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4509 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4510 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4511 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4512 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4514 cobj->m_chart_context->chart =
4516 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4530 CreateCompatibleS57Object(pObj, &cobj, NULL);
4532 LUPname LUP_Name = PAPER_CHART;
4535 ctx->CSrules = NULL;
4536 ctx->bCS_Added =
false;
4539 if (ctx->bFText_Added) {
4540 ctx->bFText_Added =
false;
4546 ctx->bBBObj_valid =
true;
4551 switch (cobj.Primitive_type) {
4556 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4557 LUP_Name = PAPER_CHART;
4559 LUP_Name = SIMPLIFIED;
4568 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4569 LUP_Name = PLAIN_BOUNDARIES;
4571 LUP_Name = SYMBOLIZED_BOUNDARIES;
4576 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4580 ps52plib->_LUP2rules(lup, &cobj);
4582 ctx->MPSRulesList = NULL;
4590 pContext->bBBObj_valid =
true;
4596void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4597 ObjRazRules* rzRules) {
4601 pContext->CSrules = cobj->CSrules;
4602 pContext->bCS_Added = cobj->bCS_Added;
4604 pContext->FText = cobj->FText;
4605 pContext->bFText_Added = cobj->bFText_Added;
4606 pContext->rText = cobj->rText;
4608 if (cobj->BBObj.GetValid()) {
4611 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4612 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4613 pContext->bBBObj_valid =
true;
4618 pObj->m_DisplayCat = (
PI_DisCat)cobj->m_DisplayCat;
4622 pContext->ChildRazRules = rzRules->child;
4623 pContext->MPSRulesList = rzRules->mps;
4625 pObj->auxParm0 = cobj->auxParm0;
4628bool PI_GetObjectRenderBox(
PI_S57Obj* pObj,
double* lat_min,
double* lat_max,
4629 double* lon_min,
double* lon_max) {
4632 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4633 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4634 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4635 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4636 return pContext->bBBObj_valid;
4644 LUPrec* lup = pContext->LUP;
4653 LUPrec* lup = pContext->LUP;
4663 LUPrec* lup = pContext->LUP;
4668double PI_GetPLIBMarinerSafetyContour() {
4669 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4672void PI_PLIBSetLineFeaturePriority(
PI_S57Obj* pObj,
int prio) {
4676 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4681 ObjRazRules rzRules;
4682 rzRules.obj = &cobj;
4683 rzRules.LUP = pContext->LUP;
4684 rzRules.sm_transform_parms = 0;
4685 rzRules.child = NULL;
4686 rzRules.next = NULL;
4687 rzRules.mps = pContext->MPSRulesList;
4689 if (pContext->LUP) {
4690 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4693 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4697void PI_PLIBPrepareForNewRender(
void) {
4699 ps52plib->PrepareForRender();
4700 ps52plib->ClearTextList();
4703 ps52plib->EnableGLLS(
true);
4705 ps52plib->EnableGLLS(
false);
4709void PI_PLIBSetRenderCaps(
unsigned int flags) { gs_plib_flags = flags; }
4711void PI_PLIBFreeContext(
void* pContext) {
4714 if (pctx->ChildRazRules) {
4715 ObjRazRules* ctop = pctx->ChildRazRules;
4719 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4721 ObjRazRules* cnxx = ctop->next;
4727 if (pctx->MPSRulesList) {
4728 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4729 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4731 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4732 ps52plib->DestroyRulesChain(top);
4734 delete pctx->MPSRulesList->cs_rules;
4736 free(pctx->MPSRulesList);
4748 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4755 &transform.easting_vp_center, &transform.northing_vp_center);
4758 ObjRazRules rzRules;
4759 rzRules.obj = &cobj;
4760 rzRules.LUP = pContext->LUP;
4761 rzRules.sm_transform_parms = &transform;
4762 rzRules.child = pContext->ChildRazRules;
4763 rzRules.next = NULL;
4764 rzRules.mps = pContext->MPSRulesList;
4766 if (pContext->LUP) {
4767 ViewPort cvp = CreateCompatibleViewport(*vp);
4773 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4775 ps52plib->PrepareForRender();
4777 ps52plib->RenderObjectToDC(pdc, &rzRules);
4780 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4787 wxRect rect,
unsigned char* pixbuf) {
4789 render_canvas_parms pb_spec;
4791 pb_spec.depth = BPP;
4792 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4793 pb_spec.lclip = rect.x;
4794 pb_spec.rclip = rect.x + rect.width - 1;
4795 pb_spec.pix_buff = pixbuf;
4796 pb_spec.width = rect.width;
4797 pb_spec.height = rect.height;
4800#ifdef ocpnUSE_ocpnBitmap
4801 pb_spec.b_revrgb =
true;
4803 pb_spec.b_revrgb =
false;
4806 pb_spec.b_revrgb =
false;
4811 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4818 &transform.easting_vp_center, &transform.northing_vp_center);
4821 ObjRazRules rzRules;
4822 rzRules.obj = &cobj;
4823 rzRules.LUP = pContext->LUP;
4824 rzRules.sm_transform_parms = &transform;
4825 rzRules.child = pContext->ChildRazRules;
4826 rzRules.next = NULL;
4827 rzRules.mps = pContext->MPSRulesList;
4829 ViewPort cvp = CreateCompatibleViewport(*vp);
4837 if (!tess)
return 1;
4839 PolyTriGroup* ptg =
new PolyTriGroup;
4840 ptg->tri_prim_head =
4841 tess->Get_PolyTriGroup_head()->tri_prim_head;
4842 ptg->bsingle_alloc =
false;
4843 ptg->data_type = DATA_TYPE_DOUBLE;
4844 tess->Set_PolyTriGroup_head(ptg);
4846 double* pd = (
double*)malloc(
sizeof(
double));
4851 if (pContext->LUP) {
4856 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4858 ps52plib->PrepareForRender();
4860 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4863 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4869int PI_PLIBRenderAreaToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4875 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4886 if (!tess)
return 1;
4890 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4891 ptg->bsingle_alloc =
false;
4892 ptg->data_type = DATA_TYPE_DOUBLE;
4893 tess->Set_PolyTriGroup_head(ptg);
4897 double* pd = (
double*)malloc(
sizeof(
double));
4914 &transform.easting_vp_center, &transform.northing_vp_center);
4917 ObjRazRules rzRules;
4918 rzRules.obj = &cobj;
4919 rzRules.LUP = pContext->LUP;
4920 rzRules.sm_transform_parms = &transform;
4921 rzRules.child = pContext->ChildRazRules;
4922 rzRules.next = NULL;
4923 rzRules.mps = pContext->MPSRulesList;
4925 if (pContext->LUP) {
4926 ViewPort cvp = CreateCompatibleViewport(*vp);
4932 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4934 ps52plib->PrepareForRender();
4936 ps52plib->RenderAreaToGL(glcc, &rzRules);
4939 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4946int PI_PLIBRenderObjectToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4951 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4958 &transform.easting_vp_center, &transform.northing_vp_center);
4961 ObjRazRules rzRules;
4962 rzRules.obj = &cobj;
4963 rzRules.LUP = pContext->LUP;
4964 rzRules.sm_transform_parms = &transform;
4965 rzRules.child = pContext->ChildRazRules;
4966 rzRules.next = NULL;
4967 rzRules.mps = pContext->MPSRulesList;
4969 if (pContext->LUP) {
4970 ViewPort cvp = CreateCompatibleViewport(*vp);
4976 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4978 ps52plib->PrepareForRender();
4980 ps52plib->RenderObjectToGL(glcc, &rzRules);
4983 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4993OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
4994 : wxEvent(id, commandType) {
4997 m_b_complete =
false;
5001OCPN_downloadEvent::~OCPN_downloadEvent() {}
5003wxEvent* OCPN_downloadEvent::Clone()
const {
5005 newevent->m_stat = this->m_stat;
5006 newevent->m_condition = this->m_condition;
5008 newevent->m_totalBytes = this->m_totalBytes;
5009 newevent->m_sofarBytes = this->m_sofarBytes;
5010 newevent->m_b_complete = this->m_b_complete;
5016DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5021#define DL_EVENT_TIMER 4388
5029 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5030 void clearBackgroundMode();
5031 void onTimerEvent(wxTimerEvent& event);
5034 wxTimer m_eventTimer;
5035 wxEvtHandler* m_download_evHandler;
5041PI_DLEvtHandler::PI_DLEvtHandler() {
5045 m_download_evHandler = NULL;
5051PI_DLEvtHandler::~PI_DLEvtHandler() {
5052 m_eventTimer.Stop();
5055 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5062 g_download_status =
event.getDLEventStatus();
5063 g_download_condition =
event.getDLEventCondition();
5066 if (m_download_evHandler &&
5069 ev.setComplete(
true);
5070 ev.setTransferred(m_sofarBytes);
5071 ev.setTotal(m_totalBytes);
5073 ev.setDLEventStatus(event.getDLEventStatus());
5076 m_download_evHandler->AddPendingEvent(ev);
5077 m_eventTimer.Stop();
5079 finishAndroidFileDownload();
5086void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5088 m_download_evHandler = handler;
5090 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5094 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5095 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5098void PI_DLEvtHandler::clearBackgroundMode() {
5099 m_download_evHandler = NULL;
5100 m_eventTimer.Stop();
5103void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5109 int stat = queryAndroidFileDownload(m_id, &sstat);
5112 long sofarBytes = 0;
5113 long totalBytes = -1;
5117 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5118 ev.setComplete(
true);
5119 ev.setTransferred(sofarBytes);
5120 ev.setTotal(totalBytes);
5125 wxStringTokenizer tk(sstat, _T(
";"));
5126 if (tk.HasMoreTokens()) {
5127 wxString token = tk.GetNextToken();
5128 token.ToLong(&state);
5129 token = tk.GetNextToken();
5130 token.ToLong(&sofarBytes);
5131 token = tk.GetNextToken();
5132 token.ToLong(&totalBytes);
5135 qDebug() << state << sofarBytes << totalBytes;
5137 m_sofarBytes = sofarBytes;
5138 m_totalBytes = totalBytes;
5140 ev.setTransferred(sofarBytes);
5141 ev.setTotal(totalBytes);
5144 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5145 ev.setComplete(
true);
5148 }
else if (state == 8) {
5149 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5150 ev.setComplete(
true);
5154 ev.setComplete(
false);
5162 if (m_download_evHandler) {
5164 m_download_evHandler->AddPendingEvent(ev);
5169 m_eventTimer.Stop();
5170 finishAndroidFileDownload();
5180 const wxString& outputFile,
5181 const wxString& title,
const wxString& message,
5182 const wxBitmap& bitmap, wxWindow* parent,
5183 long style,
int timeout_secs) {
5186 wxString msg = _T(
"Downloading file synchronously: ");
5193 int vres = validateAndroidWriteLocation(outputFile);
5205 g_piEventHandler->Connect(
5206 wxEVT_DOWNLOAD_EVENT,
5207 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5212 wxString fURI = outputFile;
5213 if (!fURI.StartsWith(_T(
"file://"))) {
5214 fURI.Prepend(_T(
"file://"));
5217 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5220 finishAndroidFileDownload();
5221 g_piEventHandler->Disconnect(
5222 wxEVT_DOWNLOAD_EVENT,
5223 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5228 wxDateTime dl_start_time = wxDateTime::Now();
5232 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5233 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5235 if (dt.GetSeconds() > timeout_secs) {
5236 qDebug() <<
"USER_TIMOUT";
5237 finishAndroidFileDownload();
5238 g_piEventHandler->Disconnect(
5239 wxEVT_DOWNLOAD_EVENT,
5240 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5248 finishAndroidFileDownload();
5249 g_piEventHandler->Disconnect(
5250 wxEVT_DOWNLOAD_EVENT,
5254 qDebug() <<
"RETURN DL_END" << (int)ss;
5260 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5262 qDebug() <<
"Error on queryAndroidFileDownload";
5263 finishAndroidFileDownload();
5264 g_piEventHandler->Disconnect(
5265 wxEVT_DOWNLOAD_EVENT,
5266 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5276#elif defined(OCPN_USE_CURL)
5277 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5278 wxFileOutputStream output(tfn.GetFullPath());
5280 wxCurlDownloadDialog ddlg(url, &output, title, message + url, bitmap, parent,
5282 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5288 case wxCDRF_SUCCESS: {
5289 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5295 case wxCDRF_FAILED: {
5299 case wxCDRF_USER_ABORTED: {
5307 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5315wxString toUsrDateTimeFormat_Plugin(
const wxDateTime date_time,
5317 return ocpn::toUsrDateTimeFormat(date_time,
options);
5322 const wxString& outputFile,
5323 wxEvtHandler* handler,
5326 wxString msg = _T(
"Downloading file asynchronously: ");
5338 int res = startAndroidFileDownload(url, outputFile, NULL ,
5342 finishAndroidFileDownload();
5347 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5349 if (handle) *handle = dl_ID;
5353#elif defined(OCPN_USE_CURL)
5354 if (g_pi_manager->m_pCurlThread)
5358 g_pi_manager->m_pCurlThread =
5359 new wxCurlDownloadThread(g_pi_manager, CurlThreadId);
5360 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5362 if (http && g_pi_manager->m_pCurl &&
5363 dynamic_cast<wxCurlHTTP*
>(g_pi_manager->m_pCurl.get())) {
5367 g_pi_manager->m_pCurl = 0;
5370 bool failed =
false;
5371 if (!g_pi_manager->HandleCurlThreadError(
5372 g_pi_manager->m_pCurlThread->SetURL(url, g_pi_manager->m_pCurl),
5373 g_pi_manager->m_pCurlThread, url))
5376 g_pi_manager->m_pCurl = g_pi_manager->m_pCurlThread->GetCurlSharedPtr();
5377 if (!g_pi_manager->HandleCurlThreadError(
5378 g_pi_manager->m_pCurlThread->SetOutputStream(
5379 new wxFileOutputStream(outputFile)),
5380 g_pi_manager->m_pCurlThread))
5384 g_pi_manager->m_download_evHandler = handler;
5385 g_pi_manager->m_downloadHandle = handle;
5387 wxCurlThreadError err = g_pi_manager->m_pCurlThread->Download();
5388 if (err != wxCTE_NO_ERROR) {
5389 g_pi_manager->HandleCurlThreadError(
5390 err, g_pi_manager->m_pCurlThread);
5391 g_pi_manager->m_pCurlThread->Abort();
5398 if (g_pi_manager->m_pCurlThread) {
5399 if (g_pi_manager->m_pCurlThread->IsAlive())
5400 g_pi_manager->m_pCurlThread->Abort();
5401 if (g_pi_manager->m_pCurlThread->GetOutputStream())
5402 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5403 wxDELETE(g_pi_manager->m_pCurlThread);
5404 g_pi_manager->m_download_evHandler = NULL;
5405 g_pi_manager->m_downloadHandle = NULL;
5408 g_pi_manager->m_pCurl = 0;
5416void OCPN_cancelDownloadFileBackground(
long handle) {
5420 cancelAndroidFileDownload(handle);
5421 finishAndroidFileDownload();
5422 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5424 if (g_pi_manager->m_pCurlThread) {
5425 g_pi_manager->m_pCurlThread->Abort();
5426 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5427 wxDELETE(g_pi_manager->m_pCurlThread);
5428 g_pi_manager->m_download_evHandler = NULL;
5429 g_pi_manager->m_downloadHandle = NULL;
5431 g_pi_manager->m_pCurl = 0;
5437 const wxString& parameters, wxString& result,
5440 wxString lparms = parameters;
5441 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5444 result = postResult;
5447#elif defined(OCPN_USE_CURL)
5449 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5450 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5453 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5456 result = wxEmptyString;
5465bool OCPN_isOnline() {
5467 return androidCheckOnline();
5470#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5471 if (wxDateTime::GetTimeNow() >
5472 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5474 get.Head(_T(
"http://yahoo.com/"));
5475 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5477 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5479 return g_pi_manager->m_last_online;
5485#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5486void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5488 if (ev.IsSuccessful()) {
5491 g_pi_manager->m_pCurl = 0;
5495 event.setComplete(
true);
5497 if (m_download_evHandler) {
5498 m_download_evHandler->AddPendingEvent(event);
5499 m_download_evHandler = NULL;
5500 m_downloadHandle = NULL;
5503 if (m_pCurlThread) {
5504 m_pCurlThread->Wait();
5505 if (!m_pCurlThread->IsAborting()) {
5506 delete (m_pCurlThread->GetOutputStream());
5507 wxDELETE(m_pCurlThread);
5512void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5516 event.setTotal(ev.GetTotalBytes());
5517 event.setTransferred(ev.GetDownloadedBytes());
5518 event.setComplete(
false);
5520 if (m_download_evHandler) {
5521 m_download_evHandler->AddPendingEvent(event);
5525bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5526 wxCurlBaseThread* p,
5527 const wxString& url) {
5529 case wxCTE_NO_ERROR:
5532 case wxCTE_NO_RESOURCE:
5534 wxS(
"Insufficient resources for correct execution of the program."));
5537 case wxCTE_ALREADY_RUNNING:
5541 case wxCTE_INVALID_PROTOCOL:
5542 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5546 case wxCTE_NO_VALID_STREAM:
5553 case wxCTE_CURL_ERROR: {
5554 wxString ws = wxS(
"unknown");
5555 if (p->GetCurlSession())
5557 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5558 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5563 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)
Handle plugin install from remote repositories and local operations to Uninstall and list plugins.
bool Uninstall(const std::string plugin)
Uninstall an installed and loaded plugin.
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.
static std::string VersionPath(std::string name)
Return path to file containing version for given plugin.
std::vector< std::string > GetInstalldataPlugins()
Return list of installed plugins lower case names, not necessarily loaded.
bool ClearInstallData(const std::string plugin_name)
Remove installation data for not loaded 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.
static std::string FileListPath(std::string name)
Return path to installation manifest for given plugin.
void SetInstalledMetadata(const PluginMetadata &pm)
Set metadata for an installed plugin.
static PluginHandler * GetInstance()
Singleton factory.
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.
void UpdateManagedPlugins(bool keep_orphans)
Update all managed plugins i.
EventVar evt_pluglist_change
Notified without data when the GetPlugInArray() list is changed.
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.
bool DeactivatePlugIn(PlugInContainer *pic)
Deactivate given plugin.
bool UpdatePlugIns()
Update the GetPlugInArray() list by reloading all plugins from disk.
void ShowPreferencesDialog(const PlugInData &pd, wxWindow *parent)
Display the preferences dialog for a plugin.
const ArrayOfPlugIns * GetPlugInArray()
Return list of currently loaded plugins.
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.
PLugin remote repositories installation and Uninstall/list operations.
Low level code to load plugins from disk, notably the PluginLoader class.
@ Ghost
Managed, shadowing another (packaged?) plugin.
@ Unmanaged
Unmanaged, probably a package.
@ Managed
Managed by installer.
@ System
One of the four system plugins, unmanaged.
Plugin installation and data paths support.
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.