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) {
1136 ProcessLateInit(pic);
1146 wxString msg(
"PlugInManager: Calling LateInit PlugIn: ");
1151 if (ppi) ppi->LateInit();
1159 ChartData->PurgeCachePlugins();
1160 gFrame->InvalidateAllQuilts();
1163 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1166 if (pttc->m_pplugin == pic->m_pplugin) {
1167 m_PlugInToolbarTools.Remove(pttc);
1173 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1175 if (pimis->m_pplugin == pic->m_pplugin) {
1176 m_PlugInMenuItems.Remove(pimis);
1182bool PlugInManager::IsAnyPlugInChartEnabled() {
1185 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1186 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1188 if (pic->m_enabled && pic->m_init_state) {
1197void PlugInManager::UpdateManagedPlugins() {
1199 PluginLoader::GetInstance()->
SortPlugins(ComparePlugins);
1202 g_options->itemBoxSizerPanelPlugins->Layout();
1205bool PlugInManager::UpDateChartDataTypes() {
1207 if (NULL == ChartData)
return bret;
1209 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1210 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1213 if (pic->m_init_state) {
1220 if (bret) ChartData->UpdateChartClassDescriptorArray();
1225void PlugInManager::FinalizePluginLoadall() {
1229 SetColorSchemeForAllPlugIns(global_color_scheme);
1232 SendBaseConfigToAllPlugIns();
1233 SendS52ConfigToAllPlugIns(
true);
1234 SendSKConfigToAllPlugIns();
1239 if (gFrame->GetPrimaryCanvas()->GetglCanvas())
1240 gFrame->GetPrimaryCanvas()->GetglCanvas()->SendJSONConfigMessage();
1248void PlugInManager::SetPluginOrder(wxString serialized_names) {
1249 m_plugin_order.Empty();
1250 wxStringTokenizer tokenizer(serialized_names,
";");
1251 while (tokenizer.HasMoreTokens()) {
1252 m_plugin_order.Add(tokenizer.GetNextToken());
1256wxString PlugInManager::GetPluginOrder() {
1257 wxString plugins = wxEmptyString;
1258 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1259 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1260 plugins.Append(plugin_array->Item(i)->m_common_name);
1261 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1266bool PlugInManager::UpdateConfig() {
1270 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1271 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1275 wxString config_section = (_T (
"/PlugIns/" ));
1277 pConfig->SetPath(config_section);
1278 pConfig->Write(_T (
"bEnabled" ), pic->m_enabled);
1285void PlugInManager::ShowDeferredBlacklistMessages() {
1286 m_blacklist_ui->show_deferred_messages();
1289bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1291 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1294bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin* plugin) {
1299 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1300 name.Replace(
"class ", wxEmptyString);
1302 const std::type_info& ti =
typeid(*plugin);
1304 char* realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1305 wxString name = wxString::FromAscii(realname);
1308 return CheckBlacklistedPlugin(name, major, minor);
1311bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
1313 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1314 if (block_status == plug_status::unblocked)
return true;
1315 plug_data data(name.ToStdString(), major, minor);
1316 auto msg = m_blacklist->get_message(block_status, data);
1317 m_blacklist_ui->message(msg);
1321bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC& dc,
1325 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1326 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1328 if (pic->m_enabled && pic->m_init_state) {
1332 wxDC* pdc = dc.GetDC();
1335 switch (pic->m_api_version) {
1337 if (priority > 0)
break;
1344 if (priority > 0)
break;
1347 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1358 if (priority > 0)
break;
1361 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1366 if (priority > 0)
break;
1370 ppi->RenderOverlay(*pdc, &pivp);
1381 if (priority <= 0) {
1385 ppi->RenderOverlay(*pdc, &pivp);
1401 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1403 if ((m_cached_overlay_bm.GetWidth() != vp.
pix_width) ||
1404 (m_cached_overlay_bm.GetHeight() != vp.
pix_height))
1408 mdc.SelectObject(m_cached_overlay_bm);
1409 mdc.SetBackground(*wxBLACK_BRUSH);
1412 bool b_rendered =
false;
1414 switch (pic->m_api_version) {
1416 if (priority > 0)
break;
1423 if (priority > 0)
break;
1426 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1437 if (priority > 0)
break;
1440 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1445 if (priority > 0)
break;
1449 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1461 if (priority <= 0) {
1465 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1472 mdc, &pivp, g_canvasConfig, priority);
1481 mdc.SelectObject(wxNullBitmap);
1484 wxMask* p_msk =
new wxMask(m_cached_overlay_bm, wxColour(0, 0, 0));
1485 m_cached_overlay_bm.SetMask(p_msk);
1487 dc.DrawBitmap(m_cached_overlay_bm, 0, 0,
true);
1490 }
else if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1498bool PlugInManager::RenderAllGLCanvasOverlayPlugIns(wxGLContext* pcontext,
1502 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1503 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1505 if (pic->m_enabled && pic->m_init_state) {
1506 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1509 switch (pic->m_api_version) {
1511 if (priority > 0)
break;
1514 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
1526 if (priority > 0)
break;
1534 if (priority > 0)
break;
1550 if (priority <= 0) {
1575void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort& vp) {
1576 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1577 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1579 if (pic->m_enabled && pic->m_init_state) {
1588void NotifySetupOptionsPlugin(
const PlugInData* pd) {
1589 PluginLoader::GetInstance()->NotifySetupOptionsPlugin(pd);
1592void PlugInManager::NotifySetupOptions() {
1593 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1594 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1596 NotifySetupOptionsPlugin(pic);
1601 int ok_apply_cancel) {
1602 if (pic->m_enabled && pic->m_init_state) {
1605 auto loader = PluginLoader::GetInstance();
1612void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
1613 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1614 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1617 ClosePlugInPanel(pic, ok_apply_cancel);
1622int PlugInManager::AddCanvasContextMenuItemPIM(wxMenuItem* pitem,
1627 pmic->pmenu_item = pitem;
1628 pmic->m_pplugin = pplugin;
1629 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
1630 : m_plugin_menu_item_id_next;
1632 pmic->b_grey =
false;
1633 pmic->m_in_menu = name;
1634 pmic->extended = is_extended;
1636 m_PlugInMenuItems.Add(pmic);
1638 m_plugin_menu_item_id_next++;
1643void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char* name) {
1644 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1647 if (pimis->id == item) {
1648 m_PlugInMenuItems.Remove(pimis);
1656void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
1658 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1661 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1669void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
1671 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1674 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1675 pimis->b_grey = grey;
1682void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
1683 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1684 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1686 if (pic->m_enabled && pic->m_init_state)
1691void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
1692 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1693 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1695 if (pic->m_enabled && pic->m_init_state)
1700void PlugInManager::PrepareAllPluginContextMenus() {
1701 int canvasIndex = gFrame->GetCanvasIndexUnderMouse();
1702 if (canvasIndex < 0)
return;
1704 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1705 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1707 if (pic->m_enabled && pic->m_init_state) {
1709 switch (pic->m_api_version) {
1728void PlugInManager::SendSKConfigToAllPlugIns() {
1731 v[_T(
"self")] = g_ownshipMMSI_SK;
1735 SendMessageToAllPlugins(wxString(_T(
"OCPN_CORE_SIGNALK")), out);
1738void PlugInManager::SendBaseConfigToAllPlugIns() {
1741 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1742 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1743 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1744 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1745 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1748 if (g_MainToolbar) {
1749 v[_T(
"OpenCPN Toolbar Width")] = g_MainToolbar->GetToolbarRect().width;
1750 v[_T(
"OpenCPN Toolbar Height")] = g_MainToolbar->GetToolbarRect().height;
1751 v[_T(
"OpenCPN Toolbar PosnX")] = g_MainToolbar->GetToolbarRect().x;
1752 v[_T(
"OpenCPN Toolbar PosnY")] = g_MainToolbar->GetToolbarRect().y;
1756 v[_T(
"OpenCPN Zoom Mod Vector")] = g_chart_zoom_modifier_vector;
1757 v[_T(
"OpenCPN Zoom Mod Other")] = g_chart_zoom_modifier_raster;
1758 v[_T(
"OpenCPN Scale Factor Exp")] =
1759 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1760 v[_T(
"OpenCPN Display Width")] = (int)g_display_size_mm;
1767 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1770void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1773 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1774 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1775 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1776 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1777 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1785 v[_T(
"OpenCPN S52PLIB ShowAnchorConditions")] = ps52plib->GetAnchorOn();
1786 v[_T(
"OpenCPN S52PLIB ShowQualityOfData")] = ps52plib->GetQualityOfData();
1791 v[_T(
"OpenCPN S52PLIB MetaDisplay")] = ps52plib->m_bShowMeta;
1792 v[_T(
"OpenCPN S52PLIB DeclutterText")] = ps52plib->m_bDeClutterText;
1793 v[_T(
"OpenCPN S52PLIB ShowNationalText")] = ps52plib->m_bShowNationalTexts;
1794 v[_T(
"OpenCPN S52PLIB ShowImportantTextOnly")] =
1795 ps52plib->m_bShowS57ImportantTextOnly;
1796 v[_T(
"OpenCPN S52PLIB UseSCAMIN")] = ps52plib->m_bUseSCAMIN;
1797 v[_T(
"OpenCPN S52PLIB UseSUPER_SCAMIN")] = ps52plib->m_bUseSUPER_SCAMIN;
1798 v[_T(
"OpenCPN S52PLIB SymbolStyle")] = ps52plib->m_nSymbolStyle;
1799 v[_T(
"OpenCPN S52PLIB BoundaryStyle")] = ps52plib->m_nBoundaryStyle;
1800 v[_T(
"OpenCPN S52PLIB ColorShades")] =
1801 S52_getMarinerParam(S52_MAR_TWO_SHADES);
1802 v[_T(
"OpenCPN S52PLIB Safety Depth")] =
1803 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1804 v[_T(
"OpenCPN S52PLIB Shallow Contour")] =
1805 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1806 v[_T(
"OpenCPN S52PLIB Deep Contour")] =
1807 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1811 v[_T(
"OpenCPN S52PLIB GlobalReconfig")] = bReconfig;
1816 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1819void PlugInManager::NotifyAuiPlugIns(
void) {
1820 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1821 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1823 if (pic->m_enabled && pic->m_init_state &&
1829int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1830 wxBitmap* bmpRollover, wxItemKind kind,
1831 wxString shortHelp, wxString longHelp,
1832 wxObject* clientData,
int position,
1835 pttc->label = label;
1837 if (!bitmap->IsOk()) {
1839 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1842 pttc->bitmap_day =
new wxBitmap(*bitmap);
1843 pttc->bitmap_day->UnShare();
1846 if (!bmpRollover->IsOk()) {
1848 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1851 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1852 pttc->bitmap_Rollover_day->UnShare();
1855 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1856 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1857 pttc->bitmap_Rollover_dusk =
1858 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1859 pttc->bitmap_Rollover_night =
1860 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1863 pttc->shortHelp = shortHelp;
1864 pttc->longHelp = longHelp;
1865 pttc->clientData = clientData;
1866 pttc->position = position;
1867 pttc->m_pplugin = pplugin;
1868 pttc->tool_sel = tool_sel;
1870 pttc->b_toggle =
false;
1871 pttc->id = m_plugin_tool_id_next;
1873 m_PlugInToolbarTools.Add(pttc);
1875 m_plugin_tool_id_next++;
1880int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1881 wxString SVGRolloverfile,
1882 wxString SVGToggledfile, wxItemKind kind,
1883 wxString shortHelp, wxString longHelp,
1884 wxObject* clientData,
int position,
1887 pttc->label = label;
1889 pttc->pluginNormalIconSVG = SVGfile;
1890 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1891 pttc->pluginToggledIconSVG = SVGToggledfile;
1896 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1897 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1898 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1899 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1900 pttc->bitmap_Rollover_dusk =
1901 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1902 pttc->bitmap_Rollover_night =
1903 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1906 pttc->shortHelp = shortHelp;
1907 pttc->longHelp = longHelp;
1908 pttc->clientData = clientData;
1909 pttc->position = position;
1910 pttc->m_pplugin = pplugin;
1911 pttc->tool_sel = tool_sel;
1913 pttc->b_toggle =
false;
1914 pttc->id = m_plugin_tool_id_next;
1916 m_PlugInToolbarTools.Add(pttc);
1918 m_plugin_tool_id_next++;
1923void PlugInManager::RemoveToolbarTool(
int tool_id) {
1924 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1927 if (pttc->id == tool_id) {
1928 m_PlugInToolbarTools.Remove(pttc);
1934 pParent->RequestNewToolbars();
1937void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1938 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1941 if (pttc->id == item) {
1943 pParent->RequestNewToolbars();
1950void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1951 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1954 if (pttc->id == item) {
1955 pttc->b_toggle = toggle;
1956 pParent->SetMasterToolbarItemState(item, toggle);
1963void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1964 wxBitmap* bmpRollover) {
1965 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1968 if (pttc->id == item) {
1969 delete pttc->bitmap_day;
1970 delete pttc->bitmap_dusk;
1971 delete pttc->bitmap_night;
1972 delete pttc->bitmap_Rollover_day;
1974 if (!bitmap->IsOk()) {
1976 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1979 pttc->bitmap_day =
new wxBitmap(*bitmap);
1980 pttc->bitmap_day->UnShare();
1983 if (!bmpRollover->IsOk()) {
1985 pttc->bitmap_Rollover_day =
1986 new wxBitmap(style->GetIcon(_T(
"default_pi")));
1989 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1990 pttc->bitmap_Rollover_day->UnShare();
1993 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1994 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1996 pParent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
1997 pttc->bitmap_Rollover_day);
2004void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2005 wxString SVGfileRollover,
2006 wxString SVGfileToggled) {
2007 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2010 if (pttc->id == item) {
2011 pttc->pluginNormalIconSVG = SVGfile;
2012 pttc->pluginRolloverIconSVG = SVGfileRollover;
2013 pttc->pluginToggledIconSVG = SVGfileToggled;
2014 pParent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2015 pttc->pluginRolloverIconSVG,
2016 pttc->pluginToggledIconSVG);
2024 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2026 if (
id == pc->id)
return pc->m_pplugin;
2032wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2035 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2036 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2038 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2042 return wxEmptyString;
2045wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2047wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2048 unsigned char dim_ratio) {
2049 wxImage img_dup = pbmp_normal->ConvertToImage();
2051 if (!img_dup.IsOk())
return NULL;
2053 if (dim_ratio < 200) {
2055 int gimg_width = img_dup.GetWidth();
2056 int gimg_height = img_dup.GetHeight();
2058 double factor = (double)(dim_ratio) / 256.0;
2060 for (
int iy = 0; iy < gimg_height; iy++) {
2061 for (
int ix = 0; ix < gimg_width; ix++) {
2062 if (!img_dup.IsTransparent(ix, iy)) {
2063 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2064 img_dup.GetGreen(ix, iy),
2065 img_dup.GetBlue(ix, iy));
2066 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2067 hsv.value = hsv.value * factor;
2068 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2069 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2075 wxBitmap* ptoolBarBitmap;
2078 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2080 dwxdc.SelectObject(tbmp);
2082 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2084 ptoolBarBitmap =
new wxBitmap(img_dup);
2088 return ptoolBarBitmap;
2091wxArrayString PlugInManager::GetPlugInChartClassNameArray(
void) {
2092 wxArrayString array;
2093 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2094 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2096 if (pic && pic->m_enabled && pic->m_init_state &&
2101 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2102 array.Add(carray[j]);
2110 while (j < array.GetCount()) {
2111 wxString test = array[j];
2112 unsigned int k = j + 1;
2113 while (k < array.GetCount()) {
2114 if (test == array[k]) {
2132#define DISABLED_SETTINGS_MSG \
2133 _("These settings might destabilize OpenCPN and are by default disabled." \
2134 " To despite the dangers enable them manually add a CatalogExpert=1" \
2135 " line in the [PlugIns] section in the configuration file.")
2140CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2141 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2143 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2146 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2148 wxStaticBox* itemStaticBoxSizer4Static =
2149 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2150 wxStaticBoxSizer* itemStaticBoxSizer4 =
2151 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2152 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2156 m_catalogText =
new wxStaticText(
this, wxID_STATIC, _T(
""));
2157 itemStaticBoxSizer4->Add(m_catalogText,
2158 wxSizerFlags().Border().Proportion(1));
2159 m_catalogText->SetLabel(GetCatalogText(
false));
2162 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2163 itemStaticBoxSizer4->Add(rowSizer2,
2164 wxSizerFlags().Expand().Border().Proportion(1));
2166 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2167 wxDefaultPosition, wxDefaultSize, 0);
2168 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2169 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2170 &CatalogMgrPanel::OnUpdateButton,
this);
2171 rowSizer2->AddSpacer(4 * GetCharWidth());
2172 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2173 wxDefaultPosition, wxDefaultSize, 0);
2174 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2175 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2176 &CatalogMgrPanel::OnTarballButton,
this);
2178 rowSizer2->AddSpacer(4 * GetCharWidth());
2179 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2180 wxDefaultPosition, wxDefaultSize, 0);
2182 if (expert.Get(
false)) {
2183 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2184 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2186 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2187 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2190 rowSizer2->AddSpacer(4 * GetCharWidth());
2191 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2193 SetUpdateButtonLabel();
2196 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2197 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2199 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2203 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2204 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2205 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2208 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2210 if (!expert.Get(
false)) {
2212 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2213 wxDefaultPosition, wxDefaultSize, 0);
2214 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2215 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2216 &CatalogMgrPanel::OnUpdateButton,
this);
2217 SetUpdateButtonLabel();
2218 m_tarballButton = NULL;
2219 m_adv_button = NULL;
2222 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2223 itemStaticBoxSizer4->Add(m_catalogText,
2224 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2227 m_updateButton =
new wxButton(
2228 this, wxID_ANY,
"Update Plugin Catalog:master ",
2229 wxDefaultPosition, wxDefaultSize, 0);
2230 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2231 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2232 &CatalogMgrPanel::OnUpdateButton,
this);
2233 SetUpdateButtonLabel();
2236 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2237 wxDefaultPosition, wxDefaultSize, 0);
2238 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2240 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2241 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2244 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2245 wxDefaultPosition, wxDefaultSize, 0);
2246 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2247 2 * GetCharWidth());
2248 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2249 &CatalogMgrPanel::OnTarballButton,
this);
2255CatalogMgrPanel::~CatalogMgrPanel() {
2256 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2257 &CatalogMgrPanel::OnUpdateButton,
this);
2258 if (m_tarballButton)
2259 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2260 &CatalogMgrPanel::OnTarballButton,
this);
2263static const char*
const DOWNLOAD_REPO_PROTO =
2264 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2267void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2269 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2270 std::string url(g_catalog_custom_url);
2271 if (catalog !=
"custom") {
2272 url = std::string(DOWNLOAD_REPO_PROTO);
2276 std::string filePath =
2277 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2279 auto catalogHdlr = CatalogHandler::GetInstance();
2281 g_Platform->ShowBusySpinner();
2282 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2283 g_Platform->HideBusySpinner();
2285 std::string message;
2286 if (status != CatalogHandler::ServerStatus::OK) {
2287 message = _(
"Cannot download data from url");
2288 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2289 wxICON_ERROR | wxOK);
2295 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2297 wxFileName::GetPathSeparator() +
2298 _T(
"ocpn-plugins.xml"))) {
2299 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2300 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2305 if (!wxCopyFile(wxString(filePath.c_str()),
2307 wxFileName::GetPathSeparator() +
2308 _T(
"ocpn-plugins.xml"))) {
2309 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2310 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2316 if (catalog ==
"master") {
2318 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2319 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2325 pConfig->SetPath(_T(
"/PlugIns/"));
2326 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2333 pluginHandler->setMetadata(
"");
2337 auto cataloghdlr = CatalogHandler::GetInstance();
2338 cataloghdlr->ClearCatalogData();
2341 LoadAllPlugIns(
false);
2345 m_catalogText->SetLabel(GetCatalogText(
true));
2348 OCPNMessageBox(
this, _(
"Catalog update successful"),
2349 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2352void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2356 androidDisableRotation();
2359 dialog->ShowModal();
2362 androidEnableRotation();
2366void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2369 int response = g_Platform->DoFileSelectorDialog(
2370 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2371 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2373 if (response != wxID_OK) {
2378 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2382 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2383 _(
"OpenCPN Plugin Import Error"));
2387 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2388 _(
"OpenCPN Plugin Import Error"));
2389 handler->Uninstall(metadata.name);
2392 UninstallPlugin(metadata.name);
2393 ok = handler->InstallPlugin(metadata, path.ToStdString());
2395 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2396 _(
"OpenCPN Plugin Import Error"));
2399 metadata.is_imported =
true;
2401 std::ofstream file(metadata_path);
2404 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2405 <<
" for imported plugin: " << metadata.name;
2407 LoadAllPlugIns(
false,
true);
2410 wxString ws(_(
"Plugin"));
2411 ws += metadata.name + _(
" successfully imported");
2412 OCPNMessageBox(gFrame, ws, _(
"Installation complete"),
2413 wxICON_INFORMATION | wxOK | wxCENTRE);
2416wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2418 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2419 catalog += _T(
": ");
2422 pConfig->SetPath(_T(
"/PlugIns/"));
2423 wxString latestCatalog =
2424 pConfig->Read(_T(
"LatestCatalogDownloaded"), _T(
"default"));
2425 catalog += latestCatalog;
2431 std::string date = pluginHandler->GetCatalogData()->date;
2433 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2434 if (!updated) catalog += _T(
" : ") + _(
"Please Update Plugin Catalog.");
2440void CatalogMgrPanel::SetUpdateButtonLabel() {
2441 wxString label = _(
"Update Plugin Catalog");
2443 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2444 m_updateButton->SetLabel(label);
2448wxString CatalogMgrPanel::GetImportInitDir() {
2450 pConfig->SetPath(_T(
"/PlugIns/"));
2451 wxString lastImportDir;
2452 lastImportDir = pConfig->Read(_T(
"LatestImportDir"),
2453 g_Platform->GetWritableDocumentsDir());
2454 if (wxDirExists(lastImportDir)) {
2455 return lastImportDir;
2457 return (g_Platform->GetWritableDocumentsDir());
2466 const wxPoint& pos, const wxSize& size)
2467 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2468 m_PluginSelected(0) {
2469 m_is_loading.clear();
2470 SetSizer(
new wxBoxSizer(wxVERTICAL));
2471 ReloadPluginPanels();
2474void PluginListPanel::SelectByName(wxString& name) {
2475 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2476 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2478 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2479 pluginPanel->SetSelected(
true);
2480 pluginPanel->Layout();
2481 SelectPlugin(pluginPanel);
2489std::vector<const PlugInData*> GetInstalled() {
2490 std::vector<const PlugInData*> result;
2491 auto loader = PluginLoader::GetInstance();
2492 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2493 auto const item = loader->GetPlugInArray()->Item(i);
2494 if (item->m_managed_metadata.name.empty()) {
2495 const auto name = item->m_common_name.ToStdString();
2499 result.push_back(item);
2502 std::string slhs, srhs;
2503 for (
auto& cl : lhs->Key()) slhs += toupper(cl);
2504 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2505 return slhs.compare(srhs) < 0;
2507 std::sort(result.begin(), result.end(), compare);
2512static bool IsPluginLoaded(
const std::string& name) {
2513 if (safe_mode::get_mode()) {
2516 std::find(installed.begin(), installed.end(),
ocpn::tolower(name));
2517 return found != installed.end();
2520 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2521 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2528 if (m_is_loading.test_and_set()) {
2530 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2535 m_PluginItems.Clear();
2537 wxWindowList kids = GetChildren();
2538 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2539 wxWindowListNode* node = kids.Item(i);
2540 wxWindow* win = node->GetData();
2542 if (pp) win->Destroy();
2544 GetSizer()->Clear();
2547 m_PluginSelected = 0;
2549 if (safe_mode::get_mode()) {
2552 for (
const auto& name : installed) AddPlugin(name);
2555 auto available = getCompatiblePlugins();
2559 return IsPluginLoaded(md.name);
2561 auto end = std::remove_if(available.begin(), available.end(), predicate);
2562 available.erase(end, available.end());
2568 std::string slhs, srhs;
2569 for (
auto& cl : lhs.name) slhs += toupper(cl);
2570 for (
auto& cr : rhs.name) srhs += toupper(cr);
2571 return slhs.compare(srhs) < 0;
2575 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2576 for (
const auto& p : available) unique_sorted_entries.insert(p);
2581 for (
const auto& p : GetInstalled())
2582 if (p->m_enabled) AddPlugin(*p);
2585 for (
const auto& p : GetInstalled())
2586 if (!p->m_enabled) AddPlugin(*p);
2589 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2597 m_is_loading.clear();
2600void PluginListPanel::AddPlugin(
const std::string& name) {
2603 panel->SetSelected(
false);
2604 GetSizer()->Add(panel, 0, wxEXPAND);
2605 m_PluginItems.Add(panel);
2606 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2607 GetSizer()->AddSpacer(m_pluginSpacer);
2610void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2612 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2613 pPluginPanel->SetSelected(
false);
2614 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2615 m_PluginItems.Add(pPluginPanel);
2617 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2618 GetSizer()->AddSpacer(m_pluginSpacer);
2631int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2632 wxBoxSizer* sizer) {
2634 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2635 auto panel = plugins.Item(i);
2636 bool was_selected = panel->GetSelected();
2637 panel->SetSelected(
false);
2639 wxSize unselected = panel->GetSize();
2641 panel->SetSelected(
true);
2643 wxSize selected = panel->GetSize();
2645 int dy = selected.GetHeight() - unselected.GetHeight();
2646 max_dy = wxMax(max_dy, dy);
2647 panel->SetSelected(was_selected);
2652PluginListPanel::~PluginListPanel() {}
2654void PluginListPanel::UpdateSelections() {
2655 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2658 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2663void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2665 GetViewStart(&xs, &ys);
2668 if (m_PluginSelected) {
2669 m_PluginSelected->SetSelected(
false);
2670 m_PluginSelected->Layout();
2673 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2675 m_PluginSelected = pi;
2677 GetSizer()->Layout();
2679 wxSize size = GetBestVirtualSize();
2680 SetVirtualSize(size);
2685 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2687 int yd = pPluginPanel->GetSize().y;
2689 htop += m_pluginSpacer;
2690 if (pPluginPanel == pi) {
2691 int piBottom = htop - (ys * g_options->GetScrollRate());
2692 if (piBottom > GetClientSize().y) {
2693 ys += (piBottom - GetClientSize().y) / g_options->GetScrollRate();
2703 int pos = m_PluginItems.Index(pi);
2706 m_PluginItems.RemoveAt(pos);
2709 m_PluginItems.Insert(pi, pos - 1);
2710 wxStaticLine* itemStaticLine =
new wxStaticLine(
2711 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2716 m_PluginSelected = pi;
2718 GetSizer()->Layout();
2724 int pos = m_PluginItems.Index(pi);
2725 if (pos == (
int)m_PluginItems.Count() -
2728 m_PluginItems.RemoveAt(pos);
2731 m_PluginItems.Insert(pi, pos + 1);
2732 wxStaticLine* itemStaticLine =
new wxStaticLine(
2733 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2738 m_PluginSelected = pi;
2740 GetSizer()->Layout();
2745static bool canUninstall(std::string name) {
2749 for (
auto plugin : pluginHandler->GetInstalled()) {
2750 if (plugin.name == name) {
2751 if (safe_mode::get_mode())
2754 return !plugin.readonly;
2761 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2763 m_is_safe_panel(true) {
2765 wxASSERT(m_PluginListPanel != 0);
2766 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2767 SetSizer(top_sizer);
2768 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2769 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2771 double iconSize = GetCharWidth() * 4;
2773 int icon_scale = iconSize * dpi_mult;
2775 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2776 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2777 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2779 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2780 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2781 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2782 top_horizontal->Add(m_pVersion);
2785 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2786 top_horizontal->Add(m_pButtons);
2787 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2788 top_horizontal->Add(m_info_btn);
2789 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2790 wxDefaultPosition, wxDefaultSize, 0);
2791 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2793 auto uninstall = [&](wxCommandEvent ev) {
2794 auto n = m_pName->GetLabel().ToStdString();
2796 OCPNMessageBox(gFrame, std::string(_(
"Uninstall plugin ")) + n +
"?",
2797 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2798 if (result != wxID_OK)
return;
2802 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2806EVT_PAINT(PluginPanel::OnPaint)
2811 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2813 m_is_safe_panel(false) {
2816 wxASSERT(m_PluginListPanel != 0);
2818 m_bSelected =
false;
2819 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2820 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2822 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2825 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2826 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2827 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2828 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2830 double iconSize = GetCharWidth() * 4;
2832 int icon_scale = iconSize * dpi_mult;
2834 wxImage plugin_icon;
2836 if (m_plugin.m_bitmap.IsOk()) {
2837 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2840 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2841 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2842 path.AppendDir(
"uidata");
2843 path.AppendDir(
"traditional");
2844 bitmap = LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2845 }
else if (plugin_icon.IsOk()) {
2846 int nowSize = plugin_icon.GetWidth();
2847 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2848 bitmap = wxBitmap(plugin_icon);
2850 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2852 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2854 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2855 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2857 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2860 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2861 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2864 int nChars = g_options->GetSize().x / GetCharWidth();
2865 bool bCompact =
false;
2871 wxString nameString = m_plugin.m_common_name;
2875 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2876 if (nameWidth > maxWidth) {
2877 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2878 wxELLIPSIZE_END, maxWidth);
2880 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2881 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2882 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2883 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2885 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2886 sl1->AddGrowableCol(1);
2887 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2889 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2890 sl1->Add(m_pVersion, 0, wxALL, 5);
2891 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2894 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2895 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2897 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2898 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2899 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2902 wxString descriptionString = m_plugin.m_short_description;
2903 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2904 int descriptionWidth;
2905 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2906 if (descriptionWidth > maxDescriptionWidth)
2908 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2909 wxELLIPSIZE_END, maxDescriptionWidth);
2914 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2915 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2916 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2917 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2918 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2921 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2922 itemBoxSizer03->AddGrowableCol(2);
2923 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2925 wxString nameString = m_plugin.m_common_name;
2926 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2927 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2928 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2932 wxFont font = GetFont();
2933 font.SetWeight(wxFONTWEIGHT_BOLD);
2934 m_pName->SetFont(font);
2937 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2939 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2940 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2941 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2944 !m_plugin.m_managed_metadata.is_orphan)) {
2947 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2948 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2950 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2951 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2952 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2954 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2956 m_pDescription =
new wxStaticText(
2957 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2959 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2960 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2961 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2965 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2967 itemBoxSizer02->Add(m_info_btn, 0);
2969 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2970 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2971 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2972 wxDefaultPosition, wxDefaultSize, 0);
2973 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
2975 m_pButtons->AddSpacer(3 * GetCharWidth());
2978 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
2979 wxDefaultPosition, wxDefaultSize, 0);
2980 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
2982 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2983 wxDefaultPosition, wxDefaultSize, 0);
2984 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
2986 m_pButtons =
new wxBoxSizer(wxVERTICAL);
2987 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2989 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
2990 m_pButtons->Add(tline, 0, wxALL, 2);
2992 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2993 wxDefaultPosition, wxDefaultSize, 0);
2994 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
2996 tline->AddSpacer(3 * GetCharWidth());
2998 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
3000 tline->Add(m_info_btn, 0);
3003 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3004 wxDefaultPosition, wxDefaultSize);
3005 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3007 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3008 wxDefaultPosition, wxDefaultSize, 0);
3009 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3012 wxBitmap statusBitmap;
3013 const auto stat = m_plugin.m_status;
3014 auto icon_name = icon_by_status.at(stat);
3015 if (stat == PluginStatus::Imported &&
3016 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3018 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3021 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3022 path.AppendDir(
"uidata");
3023 path.AppendDir(
"traditional");
3025 int bmsize = GetCharWidth() * 3 * dpi_mult;
3026 if (path.IsFileReadable()) {
3027 statusBitmap = LoadSVG(path.GetFullPath(), bmsize, bmsize);
3028 ok = statusBitmap.IsOk();
3031 auto style = g_StyleManager->GetCurrentStyle();
3032 statusBitmap = wxBitmap(style->GetIcon(_T(
"default_pi"), bmsize, bmsize));
3033 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3036 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3037 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3038 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3040 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3043 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3045 itemBoxSizer02->AddSpacer(GetCharWidth());
3047 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3048 &PluginPanel::OnPluginPreferences,
this);
3049 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3050 &PluginPanel::OnPluginUninstall,
this);
3051 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3052 &PluginPanel::OnPluginAction,
this);
3054 SetSelected(m_bSelected);
3055 SetAutoLayout(
true);
3063PluginPanel::~PluginPanel() {
3064 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3065 if (m_is_safe_panel)
return;
3066 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3068 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3069 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3070 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3071 if (m_pButtonAction) {
3072 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3073 &PluginPanel::OnPluginAction,
this);
3075 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3076 &PluginPanel::OnPluginPreferences,
this);
3077 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3078 &PluginPanel::OnPluginEnableToggle,
this);
3081void PluginPanel::SetActionLabel(wxString& label) {
3082 m_pButtonAction->SetLabel(label);
3086static wxStopWatch swclick;
3087static int downx, downy;
3089void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3092 event.GetPosition(&downx, &downy);
3098void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3100 qDebug() << swclick.Time();
3101 if (swclick.Time() < 200) {
3103 event.GetPosition(&upx, &upy);
3104 if ((fabs(upx - downx) < GetCharWidth()) &&
3105 (fabs(upy - downy) < GetCharWidth())) {
3113void PluginPanel::DoPluginSelect() {
3114 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3120 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3121 }
else if (m_bSelected) {
3123 m_PluginListPanel->SelectPlugin(NULL);
3126 m_PluginListPanel->SelectPlugin(
this);
3134static PluginMetadata GetMetadataByName(
const std::string& name) {
3136 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3137 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3138 if (found == plugins.end()) {
3139 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3144void PluginPanel::SetSelected(
bool selected) {
3145 m_bSelected = selected;
3147 m_pVersion->SetLabel(
3150 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3151 m_pButtons->Show(
true);
3152 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3155 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3158 unInstallPossible =
false;
3161 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3163 m_pButtonUninstall->Show(unInstallPossible);
3165 if (m_plugin.m_managed_metadata.info_url.size()) {
3166 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3170 m_cbEnable->Show(
true);
3175 switch (m_plugin.m_status) {
3176 case PluginStatus::LegacyUpdateAvailable:
3177 label = _(
"Upgrade to Version ");
3178 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3179 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3180 m_pButtonAction->Enable();
3183 case PluginStatus::ManagedInstallAvailable:
3184 label = _(
"Install...");
3185 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3186 m_pButtonAction->Enable();
3189 case PluginStatus::ManagedInstalledUpdateAvailable:
3190 label = _(
"Update to ");
3191 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3192 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3193 m_pButtonAction->Enable();
3196 case PluginStatus::ManagedInstalledCurrentVersion:
3197 label = _(
"Reinstall");
3198 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3199 m_pButtonAction->Enable();
3202 case PluginStatus::ManagedInstalledDowngradeAvailable:
3203 label = _(
"Downgrade");
3204 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3205 m_pButtonAction->Enable();
3208 case PluginStatus::Imported:
3209 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3210 label = _(
"Update");
3211 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3213 m_pButtonAction->Hide();
3214 m_action = ActionVerb::NOP;
3219 m_action = ActionVerb::NOP;
3220 m_pButtonAction->Hide();
3224 m_action = ActionVerb::NOP;
3225 m_pButtonAction->Hide();
3230 m_action = ActionVerb::NOP;
3233 SetActionLabel(label);
3236 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3245 m_pButtons->Show(
false);
3248 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3249 m_cbEnable->Show(
false);
3265 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3267 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3270 SetEnabled(m_plugin.m_enabled);
3285void PluginPanel::OnPaint(wxPaintEvent& event) {
3288 int penWidth = m_penWidthUnselected;
3289 wxColour color = GetDialogColor(DLG_UNSELECTED_BACKGROUND);
3290 wxColour border = GetDialogColor(DLG_UNSELECTED_ACCENT);
3293 penWidth = m_penWidthSelected;
3294 color = GetDialogColor(DLG_SELECTED_BACKGROUND);
3295 border = GetDialogColor(DLG_SELECTED_ACCENT);
3298 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3300 dc.SetPen(wxPen(border, penWidth));
3302 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3305void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3306 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3309 androidDisableRotation();
3320void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3321 SetEnabled(event.IsChecked());
3322 m_pVersion->SetLabel(
3331void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3332 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
3335 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3336 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3337 actionEvent.SetClientData(
this);
3338 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3341void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3343 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3344 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3345 actionEvent.SetClientData(
this);
3346 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3351static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3352 auto font = window->GetFont();
3353 font.SetStyle(style);
3354 window->SetFont(font);
3357void PluginPanel::SetEnabled(
bool enabled) {
3358 if (m_is_safe_panel)
return;
3361 if (enabled) NotifySetupOptionsPlugin(&m_plugin);
3362 if (!enabled && !m_bSelected) {
3363 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3364 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3365 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3368 m_pVersion->Disable();
3369 m_pDescription->Disable();
3372 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3373 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3374 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3377 m_pVersion->Enable();
3378 m_pDescription->Enable();
3383 m_pName->Enable(enabled || m_bSelected);
3384 m_pVersion->Enable(enabled || m_bSelected);
3385 m_pDescription->Enable(enabled || m_bSelected);
3389 wxString description = m_plugin.m_long_description;
3390 if (description.IsEmpty())
3391 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3394 g_options->GetSize().x * 7 / 10);
3395 m_pDescription->SetLabel(wrapper.GetWrapped());
3396 if (m_plugin.m_managed_metadata.info_url.size()) {
3397 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3401 wxString description = m_plugin.m_short_description;
3402 if (description.IsEmpty())
3403 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3405 g_options->GetSize().x * 7 / 10);
3406 m_pDescription->SetLabel(wrapper.GetWrapped());
3409 m_pButtonPreferences->Enable(enabled &&
3411 m_cbEnable->SetValue(enabled);
3414void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3415 m_PluginListPanel->MoveUp(
this);
3418void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3419 m_PluginListPanel->MoveDown(
this);
3424 : wxPanel(parent), m_url(url) {
3425 auto vbox =
new wxBoxSizer(wxVERTICAL);
3426 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3427 button->Enable(strlen(url) > 0);
3430 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3431 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3439PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3441PlugInChartBase::~PlugInChartBase() {}
3450 bool b_allow_overzoom) {
3462 const wxRegion& Region) {
3463 return wxNullBitmap;
3472 wxRegion* pValidRegion) {}
3485 wxRect* pSourceRect) {}
3502 double* plat,
double* plon) {}
3509PlugInChartBaseGL::PlugInChartBaseGL() {}
3511PlugInChartBaseGL::~PlugInChartBaseGL() {}
3515 const wxRegion& Region,
3516 bool b_use_stencil) {
3542PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3544PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3548 const wxRegion& Region,
3549 bool b_use_stencil) {
3555 const wxRegion& Region,
bool b_use_stencil) {
3561 const wxRegion& Region,
bool b_use_stencil) {
3567 return wxNullBitmap;
3571 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3575ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3580wxString PlugInChartBaseExtended::CreateObjDescriptions(
3581 ListOfPI_S57Obj* obj_list) {
3585int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3587int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3589int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3591float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3600PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3602PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3605PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3615PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3617PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3629ChartPlugInWrapper::ChartPlugInWrapper() {}
3631ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3632 m_ppo = ::wxCreateDynamicObject(chart_class);
3636ChartPlugInWrapper::~ChartPlugInWrapper() {
3637 if (m_ppicb)
delete m_ppicb;
3640wxString ChartPlugInWrapper::GetFileSearchMask(
void) {
3647InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3648 ChartInitFlag init_flags) {
3650 wxWindow* pa = wxWindow::FindFocus();
3652 InitReturn ret_val = (InitReturn)m_ppicb->
Init(name, (
int)init_flags);
3656 if (ret_val == INIT_OK) {
3663 m_ID = m_ppicb->
GetID();
3667 m_SE = m_ppicb->
GetSE();
3681 if ((fabs(m_Chart_Skew) < .01) &&
3682 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3684 if (GetChartExtent(&extent)) {
3685 double lon_range = extent.ELON - extent.WLON;
3686 if ((lon_range > 0) &&
3688 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3692 m_overlayENC =
false;
3694 wxCharBuffer buf = m_FullPath.ToUTF8();
3695 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3701 m_ChartType = CHART_TYPE_UNKNOWN;
3702 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3708 if (pc) pc->SetFocus();
3712 return INIT_FAIL_REMOVE;
3716int ChartPlugInWrapper::GetCOVREntries() {
3723int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3730int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3737float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3749int ChartPlugInWrapper::GetNoCOVREntries() {
3759int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3769int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3779float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3789bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3793 pext->NLAT = xpi.
NLAT;
3794 pext->SLAT = xpi.
SLAT;
3795 pext->ELON = xpi.
ELON;
3796 pext->WLON = xpi.
WLON;
3805ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3810 if (!pThumbData->pDIBThumb) {
3811 wxBitmap* pBMPOwnedByChart =
3812 m_ppicb->
GetThumbnail(tnx, tny, m_global_color_scheme);
3813 if (pBMPOwnedByChart) {
3814 wxImage img = pBMPOwnedByChart->ConvertToImage();
3815 pThumbData->pDIBThumb =
new wxBitmap(img);
3817 pThumbData->pDIBThumb = NULL;
3820 pThumbData->Thumb_Size_X = tnx;
3821 pThumbData->Thumb_Size_Y = tny;
3848 pThumbData->ShipX = 0;
3849 pThumbData->ShipY = 0;
3856ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3858bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3862double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3863 bool b_allow_overzoom) {
3870double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3892void RenderRotateToViewPort(
const ViewPort& VPoint) {
3893#ifndef USE_ANDROID_GLES2
3895 glTranslatef(xt, yt, 0);
3896 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3897 glTranslatef(-xt, -yt, 0);
3901void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3902#ifndef USE_ANDROID_GLES2
3904 glTranslatef(xt, yt, 0);
3905 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3906 glTranslatef(-xt, -yt, 0);
3910bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3913 const LLRegion& Region) {
3922 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3923 wxRegion* r = RectRegion.GetNew_wxRegion();
3926 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3927 chart_region.Intersect(Region);
3929 if (!chart_region.Empty()) {
3930 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3932 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3936#ifndef USE_ANDROID_GLES2
3939 RenderRotateToViewPort(VPoint);
3944 glChartCanvas::s_b_useStencil);
3947 glChartCanvas::s_b_useStencil);
3948 UndoRenderRotateToViewPort(VPoint);
3950#ifndef USE_ANDROID_GLES2
3953 glChartCanvas::DisableClipRegion();
3967bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
3968 const wxGLContext& glc,
const ViewPort& VPoint,
3969 const OCPNRegion& RectRegion,
const LLRegion& Region) {
3978 if (!Region.Empty() && ppicb_x) {
3980 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
3981 glChartCanvas::DisableClipRegion();
3984 RenderRotateToViewPort(VPoint);
3987 wxRegion* r = RectRegion.GetNew_wxRegion();
3990 glChartCanvas::s_b_useStencil);
3993 UndoRenderRotateToViewPort(VPoint);
3998 else if (!Region.Empty() &&
4002 wxRegion* r = RectRegion.GetNew_wxRegion();
4005 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4006 chart_region.Intersect(Region);
4008 if (!chart_region.Empty()) {
4009 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4011 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4013 RenderRotateToViewPort(VPoint);
4017 glChartCanvas::s_b_useStencil);
4020 UndoRenderRotateToViewPort(VPoint);
4022 glChartCanvas::DisableClipRegion();
4035bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4042 if (!Region.Empty() && ppicb_x) {
4043 wxRegion* r = Region.GetNew_wxRegion();
4045#ifndef USE_ANDROID_GLES2
4048 RenderRotateToViewPort(VPoint);
4052 glChartCanvas::s_b_useStencil);
4053 UndoRenderRotateToViewPort(VPoint);
4055#ifndef USE_ANDROID_GLES2
4068bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4074 if (Region.IsOk()) {
4075 wxRegion* r = Region.GetNew_wxRegion();
4082 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4083 wxColour nodat_sub = nodat;
4085#ifdef ocpnUSE_ocpnBitmap
4086 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4088 m_pMask =
new wxMask(obmp, nodat_sub);
4089 obmp.SetMask(m_pMask);
4091 dc.SelectObject(obmp);
4102bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4113 if (Region.IsOk() && (pCBx || ppicb)) {
4114 wxRegion* r = Region.GetNew_wxRegion();
4129bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4132 bool ret_val =
false;
4135 if (Region.IsOk()) {
4136 wxRegion* r = Region.GetNew_wxRegion();
4150void ChartPlugInWrapper::ClearPLIBTextList() {
4158bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4162 return m_ppicb->
AdjustVP(pivp_last, pivp_proposed);
4167void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4182void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4186 m_global_color_scheme = cs;
4188 if (pThumbData) pThumbData->pDIBThumb = NULL;
4192 double target_scale_ppm) {
4199void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4200 wxRect* pSourceRect) {
4207double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4209 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4214bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4216 wxCriticalSectionLocker locker(m_critSect);
4225int ChartPlugInWrapper::GetSize_X() {
4232int ChartPlugInWrapper::GetSize_Y() {
4239void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4240 double& pixx,
double& pixy) {
4244void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4245 double* plat,
double* plon) {
4259wxString toSDMM_PlugIn(
int NEflag,
double a,
bool hi_precision) {
4260 return toSDMM(NEflag, a, hi_precision);
4263wxColour GetBaseGlobalColor(wxString colorName) {
4264 return GetGlobalColor(colorName);
4267int OCPNMessageBox_PlugIn(wxWindow* parent,
const wxString& message,
4268 const wxString& caption,
int style,
int x,
int y) {
4269 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4272wxString GetOCPN_ExePath(
void) {
return g_Platform->GetExePath(); }
4274wxString* GetpPlugInLocation() {
return g_Platform->GetPluginDirPtr(); }
4276wxString GetWritableDocumentsDir(
void) {
4277 return g_Platform->GetWritableDocumentsDir();
4282 auto loader = PluginLoader::GetInstance();
4283 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4285 if (pic->m_pplugin == pplugin) {
4295ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4298 ListOfPI_S57Obj* list = NULL;
4312 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4322 ListOfPI_S57Obj* rule_list) {
4333 ret_str = picbx->CreateObjDescriptions(rule_list);
4341wxString PI_GetPLIBColorScheme() {
4345int PI_GetPLIBDepthUnitInt() {
4347 return ps52plib->m_nDepthUnitDisplay;
4352int PI_GetPLIBSymbolStyle() {
4354 return ps52plib->m_nSymbolStyle;
4359int PI_GetPLIBBoundaryStyle() {
4361 return ps52plib->m_nBoundaryStyle;
4371 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4373 ViewPort cvp = CreateCompatibleViewport(*vp);
4378 ObjRazRules rzRules;
4379 rzRules.obj = &cobj;
4380 rzRules.LUP = pContext->LUP;
4381 rzRules.sm_transform_parms = 0;
4382 rzRules.child = NULL;
4383 rzRules.next = NULL;
4385 if (pContext->LUP) {
4386 ps52plib->SetVPointCompat(
4390 ps52plib->PrepareForRender();
4392 return ps52plib->ObjectRenderCheck(&rzRules);
4399int PI_GetPLIBStateHash() {
4401 return ps52plib->GetStateHash();
4406void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4407 chart_context* pctx) {
4410 cobj->att_array = pObj->att_array;
4411 cobj->attVal = pObj->attVal;
4412 cobj->n_attr = pObj->n_attr;
4417 cobj->npt = pObj->npt;
4419 cobj->iOBJL = pObj->iOBJL;
4420 cobj->Index = pObj->Index;
4422 cobj->geoPt = (pt*)pObj->geoPt;
4423 cobj->geoPtz = pObj->geoPtz;
4424 cobj->geoPtMulti = pObj->geoPtMulti;
4426 cobj->m_lat = pObj->m_lat;
4427 cobj->m_lon = pObj->m_lon;
4429 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4430 cobj->x_rate = pObj->x_rate;
4431 cobj->y_rate = pObj->y_rate;
4432 cobj->x_origin = pObj->x_origin;
4433 cobj->y_origin = pObj->y_origin;
4435 cobj->Scamin = pObj->Scamin;
4436 cobj->nRef = pObj->nRef;
4437 cobj->bIsAton = pObj->bIsAton;
4438 cobj->bIsAssociable = pObj->bIsAssociable;
4440 cobj->m_n_lsindex = pObj->m_n_lsindex;
4441 cobj->m_lsindex_array = pObj->m_lsindex_array;
4442 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4445 cobj->m_ls_list_legacy =
4449 cobj->m_ls_list_legacy = 0;
4450 cobj->m_ls_list = 0;
4453 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4455 cobj->m_bcategory_mutable =
true;
4459 if (pObj->m_DPRI == -1) {
4461 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4463 cobj->m_DPRI = pObj->m_DPRI;
4466 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4467 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4469 if (pObj->auxParm3 != 1234) {
4470 pObj->auxParm3 = 1234;
4471 pObj->auxParm0 = -99;
4474 cobj->auxParm0 = pObj->auxParm0;
4481 if (pContext->bBBObj_valid)
4483 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4484 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4486 cobj->CSrules = pContext->CSrules;
4487 cobj->bCS_Added = pContext->bCS_Added;
4489 cobj->FText = pContext->FText;
4490 cobj->bFText_Added = pContext->bFText_Added;
4491 cobj->rText = pContext->rText;
4493 cobj->bIsClone =
true;
4496 cobj->m_chart_context = pctx;
4497 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4500 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4501 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4502 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4503 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4504 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4505 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4506 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4507 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4509 cobj->m_chart_context->chart =
4511 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4525 CreateCompatibleS57Object(pObj, &cobj, NULL);
4527 LUPname LUP_Name = PAPER_CHART;
4530 ctx->CSrules = NULL;
4531 ctx->bCS_Added =
false;
4534 if (ctx->bFText_Added) {
4535 ctx->bFText_Added =
false;
4541 ctx->bBBObj_valid =
true;
4546 switch (cobj.Primitive_type) {
4551 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4552 LUP_Name = PAPER_CHART;
4554 LUP_Name = SIMPLIFIED;
4563 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4564 LUP_Name = PLAIN_BOUNDARIES;
4566 LUP_Name = SYMBOLIZED_BOUNDARIES;
4571 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4575 ps52plib->_LUP2rules(lup, &cobj);
4577 ctx->MPSRulesList = NULL;
4585 pContext->bBBObj_valid =
true;
4591void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4592 ObjRazRules* rzRules) {
4596 pContext->CSrules = cobj->CSrules;
4597 pContext->bCS_Added = cobj->bCS_Added;
4599 pContext->FText = cobj->FText;
4600 pContext->bFText_Added = cobj->bFText_Added;
4601 pContext->rText = cobj->rText;
4603 if (cobj->BBObj.GetValid()) {
4606 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4607 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4608 pContext->bBBObj_valid =
true;
4613 pObj->m_DisplayCat = (
PI_DisCat)cobj->m_DisplayCat;
4617 pContext->ChildRazRules = rzRules->child;
4618 pContext->MPSRulesList = rzRules->mps;
4620 pObj->auxParm0 = cobj->auxParm0;
4623bool PI_GetObjectRenderBox(
PI_S57Obj* pObj,
double* lat_min,
double* lat_max,
4624 double* lon_min,
double* lon_max) {
4627 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4628 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4629 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4630 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4631 return pContext->bBBObj_valid;
4639 LUPrec* lup = pContext->LUP;
4648 LUPrec* lup = pContext->LUP;
4658 LUPrec* lup = pContext->LUP;
4663double PI_GetPLIBMarinerSafetyContour() {
4664 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4667void PI_PLIBSetLineFeaturePriority(
PI_S57Obj* pObj,
int prio) {
4671 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4676 ObjRazRules rzRules;
4677 rzRules.obj = &cobj;
4678 rzRules.LUP = pContext->LUP;
4679 rzRules.sm_transform_parms = 0;
4680 rzRules.child = NULL;
4681 rzRules.next = NULL;
4682 rzRules.mps = pContext->MPSRulesList;
4684 if (pContext->LUP) {
4685 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4688 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4692void PI_PLIBPrepareForNewRender(
void) {
4694 ps52plib->PrepareForRender();
4695 ps52plib->ClearTextList();
4698 ps52plib->EnableGLLS(
true);
4700 ps52plib->EnableGLLS(
false);
4704void PI_PLIBSetRenderCaps(
unsigned int flags) { gs_plib_flags = flags; }
4706void PI_PLIBFreeContext(
void* pContext) {
4709 if (pctx->ChildRazRules) {
4710 ObjRazRules* ctop = pctx->ChildRazRules;
4714 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4716 ObjRazRules* cnxx = ctop->next;
4722 if (pctx->MPSRulesList) {
4723 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4724 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4726 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4727 ps52plib->DestroyRulesChain(top);
4729 delete pctx->MPSRulesList->cs_rules;
4731 free(pctx->MPSRulesList);
4743 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4750 &transform.easting_vp_center, &transform.northing_vp_center);
4753 ObjRazRules rzRules;
4754 rzRules.obj = &cobj;
4755 rzRules.LUP = pContext->LUP;
4756 rzRules.sm_transform_parms = &transform;
4757 rzRules.child = pContext->ChildRazRules;
4758 rzRules.next = NULL;
4759 rzRules.mps = pContext->MPSRulesList;
4761 if (pContext->LUP) {
4762 ViewPort cvp = CreateCompatibleViewport(*vp);
4768 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4770 ps52plib->PrepareForRender();
4772 ps52plib->RenderObjectToDC(pdc, &rzRules);
4775 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4782 wxRect rect,
unsigned char* pixbuf) {
4784 render_canvas_parms pb_spec;
4786 pb_spec.depth = BPP;
4787 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4788 pb_spec.lclip = rect.x;
4789 pb_spec.rclip = rect.x + rect.width - 1;
4790 pb_spec.pix_buff = pixbuf;
4791 pb_spec.width = rect.width;
4792 pb_spec.height = rect.height;
4795#ifdef ocpnUSE_ocpnBitmap
4796 pb_spec.b_revrgb =
true;
4798 pb_spec.b_revrgb =
false;
4801 pb_spec.b_revrgb =
false;
4806 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4813 &transform.easting_vp_center, &transform.northing_vp_center);
4816 ObjRazRules rzRules;
4817 rzRules.obj = &cobj;
4818 rzRules.LUP = pContext->LUP;
4819 rzRules.sm_transform_parms = &transform;
4820 rzRules.child = pContext->ChildRazRules;
4821 rzRules.next = NULL;
4822 rzRules.mps = pContext->MPSRulesList;
4824 ViewPort cvp = CreateCompatibleViewport(*vp);
4832 if (!tess)
return 1;
4834 PolyTriGroup* ptg =
new PolyTriGroup;
4835 ptg->tri_prim_head =
4836 tess->Get_PolyTriGroup_head()->tri_prim_head;
4837 ptg->bsingle_alloc =
false;
4838 ptg->data_type = DATA_TYPE_DOUBLE;
4839 tess->Set_PolyTriGroup_head(ptg);
4841 double* pd = (
double*)malloc(
sizeof(
double));
4846 if (pContext->LUP) {
4851 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4853 ps52plib->PrepareForRender();
4855 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4858 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4864int PI_PLIBRenderAreaToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4870 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4881 if (!tess)
return 1;
4885 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4886 ptg->bsingle_alloc =
false;
4887 ptg->data_type = DATA_TYPE_DOUBLE;
4888 tess->Set_PolyTriGroup_head(ptg);
4892 double* pd = (
double*)malloc(
sizeof(
double));
4909 &transform.easting_vp_center, &transform.northing_vp_center);
4912 ObjRazRules rzRules;
4913 rzRules.obj = &cobj;
4914 rzRules.LUP = pContext->LUP;
4915 rzRules.sm_transform_parms = &transform;
4916 rzRules.child = pContext->ChildRazRules;
4917 rzRules.next = NULL;
4918 rzRules.mps = pContext->MPSRulesList;
4920 if (pContext->LUP) {
4921 ViewPort cvp = CreateCompatibleViewport(*vp);
4927 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4929 ps52plib->PrepareForRender();
4931 ps52plib->RenderAreaToGL(glcc, &rzRules);
4934 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4941int PI_PLIBRenderObjectToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4946 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4953 &transform.easting_vp_center, &transform.northing_vp_center);
4956 ObjRazRules rzRules;
4957 rzRules.obj = &cobj;
4958 rzRules.LUP = pContext->LUP;
4959 rzRules.sm_transform_parms = &transform;
4960 rzRules.child = pContext->ChildRazRules;
4961 rzRules.next = NULL;
4962 rzRules.mps = pContext->MPSRulesList;
4964 if (pContext->LUP) {
4965 ViewPort cvp = CreateCompatibleViewport(*vp);
4971 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4973 ps52plib->PrepareForRender();
4975 ps52plib->RenderObjectToGL(glcc, &rzRules);
4978 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4988OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
4989 : wxEvent(id, commandType) {
4992 m_b_complete =
false;
4996OCPN_downloadEvent::~OCPN_downloadEvent() {}
4998wxEvent* OCPN_downloadEvent::Clone()
const {
5000 newevent->m_stat = this->m_stat;
5001 newevent->m_condition = this->m_condition;
5003 newevent->m_totalBytes = this->m_totalBytes;
5004 newevent->m_sofarBytes = this->m_sofarBytes;
5005 newevent->m_b_complete = this->m_b_complete;
5011DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5016#define DL_EVENT_TIMER 4388
5024 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5025 void clearBackgroundMode();
5026 void onTimerEvent(wxTimerEvent& event);
5029 wxTimer m_eventTimer;
5030 wxEvtHandler* m_download_evHandler;
5036PI_DLEvtHandler::PI_DLEvtHandler() {
5040 m_download_evHandler = NULL;
5046PI_DLEvtHandler::~PI_DLEvtHandler() {
5047 m_eventTimer.Stop();
5050 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5057 g_download_status =
event.getDLEventStatus();
5058 g_download_condition =
event.getDLEventCondition();
5061 if (m_download_evHandler &&
5064 ev.setComplete(
true);
5065 ev.setTransferred(m_sofarBytes);
5066 ev.setTotal(m_totalBytes);
5068 ev.setDLEventStatus(event.getDLEventStatus());
5071 m_download_evHandler->AddPendingEvent(ev);
5072 m_eventTimer.Stop();
5074 finishAndroidFileDownload();
5081void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5083 m_download_evHandler = handler;
5085 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5089 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5090 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5093void PI_DLEvtHandler::clearBackgroundMode() {
5094 m_download_evHandler = NULL;
5095 m_eventTimer.Stop();
5098void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5104 int stat = queryAndroidFileDownload(m_id, &sstat);
5107 long sofarBytes = 0;
5108 long totalBytes = -1;
5112 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5113 ev.setComplete(
true);
5114 ev.setTransferred(sofarBytes);
5115 ev.setTotal(totalBytes);
5120 wxStringTokenizer tk(sstat, _T(
";"));
5121 if (tk.HasMoreTokens()) {
5122 wxString token = tk.GetNextToken();
5123 token.ToLong(&state);
5124 token = tk.GetNextToken();
5125 token.ToLong(&sofarBytes);
5126 token = tk.GetNextToken();
5127 token.ToLong(&totalBytes);
5130 qDebug() << state << sofarBytes << totalBytes;
5132 m_sofarBytes = sofarBytes;
5133 m_totalBytes = totalBytes;
5135 ev.setTransferred(sofarBytes);
5136 ev.setTotal(totalBytes);
5139 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5140 ev.setComplete(
true);
5143 }
else if (state == 8) {
5144 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5145 ev.setComplete(
true);
5149 ev.setComplete(
false);
5157 if (m_download_evHandler) {
5159 m_download_evHandler->AddPendingEvent(ev);
5164 m_eventTimer.Stop();
5165 finishAndroidFileDownload();
5175 const wxString& outputFile,
5176 const wxString& title,
const wxString& message,
5177 const wxBitmap& bitmap, wxWindow* parent,
5178 long style,
int timeout_secs) {
5181 wxString msg = _T(
"Downloading file synchronously: ");
5188 int vres = validateAndroidWriteLocation(outputFile);
5200 g_piEventHandler->Connect(
5201 wxEVT_DOWNLOAD_EVENT,
5202 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5207 wxString fURI = outputFile;
5208 if (!fURI.StartsWith(_T(
"file://"))) {
5209 fURI.Prepend(_T(
"file://"));
5212 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5215 finishAndroidFileDownload();
5216 g_piEventHandler->Disconnect(
5217 wxEVT_DOWNLOAD_EVENT,
5218 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5223 wxDateTime dl_start_time = wxDateTime::Now();
5227 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5228 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5230 if (dt.GetSeconds() > timeout_secs) {
5231 qDebug() <<
"USER_TIMOUT";
5232 finishAndroidFileDownload();
5233 g_piEventHandler->Disconnect(
5234 wxEVT_DOWNLOAD_EVENT,
5235 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5243 finishAndroidFileDownload();
5244 g_piEventHandler->Disconnect(
5245 wxEVT_DOWNLOAD_EVENT,
5249 qDebug() <<
"RETURN DL_END" << (int)ss;
5255 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5257 qDebug() <<
"Error on queryAndroidFileDownload";
5258 finishAndroidFileDownload();
5259 g_piEventHandler->Disconnect(
5260 wxEVT_DOWNLOAD_EVENT,
5261 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5271#elif defined(OCPN_USE_CURL)
5272 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5273 wxFileOutputStream output(tfn.GetFullPath());
5275 wxCurlDownloadDialog ddlg(url, &output, title, message + url, bitmap, parent,
5277 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5283 case wxCDRF_SUCCESS: {
5284 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5290 case wxCDRF_FAILED: {
5294 case wxCDRF_USER_ABORTED: {
5302 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5310wxString toUsrDateTimeFormat_Plugin(
const wxDateTime date_time,
5312 return ocpn::toUsrDateTimeFormat(date_time,
options);
5317 const wxString& outputFile,
5318 wxEvtHandler* handler,
5321 wxString msg = _T(
"Downloading file asynchronously: ");
5333 int res = startAndroidFileDownload(url, outputFile, NULL ,
5337 finishAndroidFileDownload();
5342 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5344 if (handle) *handle = dl_ID;
5348#elif defined(OCPN_USE_CURL)
5349 if (g_pi_manager->m_pCurlThread)
5353 g_pi_manager->m_pCurlThread =
5354 new wxCurlDownloadThread(g_pi_manager, CurlThreadId);
5355 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5357 if (http && g_pi_manager->m_pCurl &&
5358 dynamic_cast<wxCurlHTTP*
>(g_pi_manager->m_pCurl.get())) {
5362 g_pi_manager->m_pCurl = 0;
5365 bool failed =
false;
5366 if (!g_pi_manager->HandleCurlThreadError(
5367 g_pi_manager->m_pCurlThread->SetURL(url, g_pi_manager->m_pCurl),
5368 g_pi_manager->m_pCurlThread, url))
5371 g_pi_manager->m_pCurl = g_pi_manager->m_pCurlThread->GetCurlSharedPtr();
5372 if (!g_pi_manager->HandleCurlThreadError(
5373 g_pi_manager->m_pCurlThread->SetOutputStream(
5374 new wxFileOutputStream(outputFile)),
5375 g_pi_manager->m_pCurlThread))
5379 g_pi_manager->m_download_evHandler = handler;
5380 g_pi_manager->m_downloadHandle = handle;
5382 wxCurlThreadError err = g_pi_manager->m_pCurlThread->Download();
5383 if (err != wxCTE_NO_ERROR) {
5384 g_pi_manager->HandleCurlThreadError(
5385 err, g_pi_manager->m_pCurlThread);
5386 g_pi_manager->m_pCurlThread->Abort();
5393 if (g_pi_manager->m_pCurlThread) {
5394 if (g_pi_manager->m_pCurlThread->IsAlive())
5395 g_pi_manager->m_pCurlThread->Abort();
5396 if (g_pi_manager->m_pCurlThread->GetOutputStream())
5397 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5398 wxDELETE(g_pi_manager->m_pCurlThread);
5399 g_pi_manager->m_download_evHandler = NULL;
5400 g_pi_manager->m_downloadHandle = NULL;
5403 g_pi_manager->m_pCurl = 0;
5411void OCPN_cancelDownloadFileBackground(
long handle) {
5415 cancelAndroidFileDownload(handle);
5416 finishAndroidFileDownload();
5417 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5419 if (g_pi_manager->m_pCurlThread) {
5420 g_pi_manager->m_pCurlThread->Abort();
5421 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5422 wxDELETE(g_pi_manager->m_pCurlThread);
5423 g_pi_manager->m_download_evHandler = NULL;
5424 g_pi_manager->m_downloadHandle = NULL;
5426 g_pi_manager->m_pCurl = 0;
5432 const wxString& parameters, wxString& result,
5435 wxString lparms = parameters;
5436 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5439 result = postResult;
5442#elif defined(OCPN_USE_CURL)
5444 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5445 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5448 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5451 result = wxEmptyString;
5460bool OCPN_isOnline() {
5462 return androidCheckOnline();
5465#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5466 if (wxDateTime::GetTimeNow() >
5467 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5469 get.Head(_T(
"http://yahoo.com/"));
5470 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5472 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5474 return g_pi_manager->m_last_online;
5480#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5481void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5483 if (ev.IsSuccessful()) {
5486 g_pi_manager->m_pCurl = 0;
5490 event.setComplete(
true);
5492 if (m_download_evHandler) {
5493 m_download_evHandler->AddPendingEvent(event);
5494 m_download_evHandler = NULL;
5495 m_downloadHandle = NULL;
5498 if (m_pCurlThread) {
5499 m_pCurlThread->Wait();
5500 if (!m_pCurlThread->IsAborting()) {
5501 delete (m_pCurlThread->GetOutputStream());
5502 wxDELETE(m_pCurlThread);
5507void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5511 event.setTotal(ev.GetTotalBytes());
5512 event.setTransferred(ev.GetDownloadedBytes());
5513 event.setComplete(
false);
5515 if (m_download_evHandler) {
5516 m_download_evHandler->AddPendingEvent(event);
5520bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5521 wxCurlBaseThread* p,
5522 const wxString& url) {
5524 case wxCTE_NO_ERROR:
5527 case wxCTE_NO_RESOURCE:
5529 wxS(
"Insufficient resources for correct execution of the program."));
5532 case wxCTE_ALREADY_RUNNING:
5536 case wxCTE_INVALID_PROTOCOL:
5537 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5541 case wxCTE_NO_VALID_STREAM:
5548 case wxCTE_CURL_ERROR: {
5549 wxString ws = wxS(
"unknown");
5550 if (p->GetCurlSession())
5552 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5553 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5558 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.