35#include <unordered_map>
58#if defined(__linux__) && !defined(__ANDROID__)
63#include <archive_entry.h>
69#include <wx/aui/aui.h>
72#include <wx/filename.h>
73#include <wx/hashmap.h>
74#include <wx/hashset.h>
75#include <wx/jsonreader.h>
76#include <wx/jsonval.h>
77#include <wx/listimpl.cpp>
78#include <wx/platinfo.h>
79#include <wx/popupwin.h>
80#include <wx/progdlg.h>
81#include <wx/statline.h>
82#include <wx/tarstrm.h>
83#include <wx/textwrapper.h>
84#include <wx/tokenzr.h>
85#include <wx/tooltip.h>
88#include <wx/zipstrm.h>
89#include <wx/zstream.h>
94#include "o_sound/o_sound.h"
113#include "model/nav_object_database.h"
160#include "user_colors.h"
165#include "androidUTIL.h"
172typedef __LA_INT64_T la_int64_t;
173enum { CurlThreadId = wxID_HIGHEST + 1 };
175#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
176extern wxLocale* plocale_def_lang;
181void NotifySetupOptionsPlugin(
const PlugInData* pic);
183WX_DEFINE_LIST(Plugin_WaypointList);
184WX_DEFINE_LIST(Plugin_HyperlinkList);
191 explicit RawKey(
const std::string& key) : m_key(key) {}
192 [[nodiscard]] std::string
GetKey()
const override {
return m_key; }
198static void SendAisJsonMessage(std::shared_ptr<const AisTargetData> pTarget) {
200 if (!GetJSONMessageTargetCount())
return;
205 wxLongLong t = ::wxGetLocalTimeMillis();
207 jMsg[wxS(
"Source")] = wxS(
"AisDecoder");
208 jMsg[
"Type"] =
"Information";
209 jMsg[
"Msg"] = wxS(
"AIS Target");
210 jMsg[
"MsgId"] = t.GetValue();
211 jMsg[wxS(
"lat")] = pTarget->Lat;
212 jMsg[wxS(
"lon")] = pTarget->Lon;
213 jMsg[wxS(
"sog")] = pTarget->SOG;
214 jMsg[wxS(
"cog")] = pTarget->COG;
215 jMsg[wxS(
"hdg")] = pTarget->HDG;
216 jMsg[wxS(
"mmsi")] = pTarget->MMSI;
217 jMsg[wxS(
"class")] = pTarget->Class;
218 jMsg[wxS(
"ownship")] = pTarget->b_OwnShip;
219 jMsg[wxS(
"active")] = pTarget->b_active;
220 jMsg[wxS(
"lost")] = pTarget->b_lost;
221 wxString l_ShipName = wxString::FromUTF8(pTarget->ShipName);
222 for (
size_t i = 0; i < l_ShipName.Len(); i++) {
223 if (l_ShipName.GetChar(i) ==
'@') l_ShipName.SetChar(i,
'\n');
225 jMsg[wxS(
"shipname")] = l_ShipName;
226 wxString l_CallSign = wxString::FromUTF8(pTarget->CallSign);
227 for (
size_t i = 0; i < l_CallSign.Len(); i++) {
228 if (l_CallSign.GetChar(i) ==
'@') l_CallSign.SetChar(i,
'\n');
230 jMsg[wxS(
"callsign")] = l_CallSign;
231 jMsg[wxS(
"removed")] = pTarget->b_removed;
232 SendJSONMessageToAllPlugins(
"AIS", jMsg);
235static bool ReloadLocale() {
240 (!g_Platform->ChangeLocale(g_locale, plocale_def_lang, &plocale_def_lang)
247 return (*p1)->Key().compare((*p2)->Key());
251 auto version = metadata.version;
253 if (version[0] ==
'v') version = version.substr(1);
258 auto imported_version = ParseVersion(metadata);
259 for (
auto& md :
PluginHandler::GetInstance()->GetAvailable()) {
260 if (md.name != metadata.name)
continue;
261 if (md.is_imported)
continue;
263 if (ParseVersion(md) >= imported_version)
return true;
274 void message(
const std::string& message) {
276 m_deferred_messages.push_back(message);
281 void show_deferred_messages() {
282 for (
auto m : m_deferred_messages) show_msg(m);
289 void show_msg(wxString msg) {
290 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
291 wxICON_INFORMATION | wxOK, 10);
295 std::vector<wxString> m_deferred_messages;
302 Wrap(win, text, widthMax);
304 wxString
const& GetWrapped()
const {
return m_wrapped; }
305 int const GetLineCount()
const {
return m_lineCount; }
306 wxArrayString GetLineArray() {
return m_array; }
309 virtual void OnOutputLine(
const wxString& line) {
313 virtual void OnNewLine() {
321 wxArrayString m_array;
325 template <
typename T>
326 std::size_t operator()(T t)
const {
327 return static_cast<std::size_t
>(t);
334 return _(
"Plugin is a standard system plugin");
336 return _(
"Plugin is managed by OpenCPN");
338 return _(
"Plugin is not managed by OpenCPN");
341 case PluginStatus::Unknown:
342 return _(
"Plugin status unknown");
343 case PluginStatus::LegacyUpdateAvailable:
344 return _(
"Update to managed Plugin is available");
345 case PluginStatus::ManagedInstallAvailable:
346 return _(
"New managed Plugin installation available");
347 case PluginStatus::ManagedInstalledUpdateAvailable:
348 return _(
"Update to installed Plugin is available");
349 case PluginStatus::ManagedInstalledCurrentVersion:
350 return _(
"Plugin is latest available");
351 case PluginStatus::Imported:
352 return _(
"Plugin is imported");
353 case PluginStatus::ManagedInstalledDowngradeAvailable:
355 case PluginStatus::PendingListRemoval:
362static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
368 {PluginStatus::Unknown,
"emblem-unmanaged.svg"},
369 {PluginStatus::LegacyUpdateAvailable,
"emblem-legacy-update.svg"},
370 {PluginStatus::ManagedInstallAvailable,
"emblem-download.svg"},
371 {PluginStatus::ManagedInstalledUpdateAvailable,
372 "emblem-legacy-update.svg"},
373 {PluginStatus::ManagedInstalledCurrentVersion,
"emblem-default.svg"},
374 {PluginStatus::ManagedInstalledDowngradeAvailable,
375 "emblem-default.svg"},
376 {PluginStatus::PendingListRemoval,
"emblem-default.svg"},
377 {PluginStatus::Imported,
"emblem-default.svg"}});
379static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
380 literalstatus_by_status(
385 {PluginStatus::Unknown,
"Unknown"},
386 {PluginStatus::LegacyUpdateAvailable,
"LegacyUpdateAvailable"},
387 {PluginStatus::ManagedInstallAvailable,
"ManagedInstallAvailable"},
388 {PluginStatus::ManagedInstalledUpdateAvailable,
389 "ManagedInstalledUpdateAvailable"},
390 {PluginStatus::ManagedInstalledCurrentVersion,
391 "ManagedInstalledCurrentVersion"},
392 {PluginStatus::ManagedInstalledDowngradeAvailable,
393 "ManagedInstalledDowngradeAvailable"},
394 {PluginStatus::PendingListRemoval,
"PendingListRemoval"},
395 {PluginStatus::Imported,
"Imported"}
403static std::vector<PluginMetadata> getCompatiblePlugins() {
405 struct metadata_compare {
408 return lhs.key() < rhs.key();
412 std::vector<PluginMetadata> returnArray;
414 std::set<PluginMetadata, metadata_compare> unique_plugins;
415 for (
auto plugin :
PluginHandler::GetInstance()->GetAvailable()) {
416 unique_plugins.insert(plugin);
418 for (
auto plugin : unique_plugins) {
420 returnArray.push_back(plugin);
437 std::string installed;
439 if (path ==
"" || !wxFileName::IsFileReadable(path)) {
442 std::ifstream stream;
443 stream.open(path, std::ifstream::in);
452static std::vector<PluginMetadata> getUpdates(
const char* name) {
453 auto updates = getCompatiblePlugins();
455 std::remove_if(updates.begin(), updates.end(),
459 auto inst_vers = getInstalledVersion(name);
460 if (inst_vers.major == -1) {
465 updates.erase(std::remove_if(updates.begin(), updates.end(),
467 return metadata_version(m) == inst_vers;
474static void gui_uninstall(
const PlugInData* pic,
const char* plugin) {
475 g_Platform->ShowBusySpinner();
480 wxLogMessage(
"Uninstalling %s", plugin);
483 g_Platform->HideBusySpinner();
486static bool LoadAllPlugIns(
bool load_enabled,
bool keep_orphans =
false) {
487 g_Platform->ShowBusySpinner();
489 PluginLoader::GetInstance()->
LoadAllPlugIns(load_enabled, keep_orphans);
490 g_Platform->HideBusySpinner();
495static void UninstallPlugin(
const std::string& name) {
497 auto loader = PluginLoader::GetInstance();
498 auto finder = [name](
const PluginMetadata pm) {
return pm.name == name; };
499 const auto& installed = handler->GetInstalled();
500 auto found = std::find_if(installed.begin(), installed.end(), finder);
501 if (found != installed.end()) {
502 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
503 auto const& item = loader->GetPlugInArray()->Item(i);
504 if (item->m_common_name.ToStdString() == name) {
505 DEBUG_LOG <<
"Unloading plugin: " << name;
506 loader->UnLoadPlugIn(i);
510 handler->Uninstall(found->name);
511 DEBUG_LOG <<
"Uninstalling: " << found->name;
516 bool uninstall,
const char* name = 0,
517 bool b_forceEnable =
false) {
519 const char* plugin = name == 0 ? pic->
m_common_name.mb_str().data() : name;
520 auto updates = getUpdates(plugin);
521 auto parent_dlg =
dynamic_cast<wxScrolledWindow*
>(parent);
522 wxASSERT(parent_dlg != 0);
524 auto status = dialog.ShowModal();
525 status = dialog.GetReturnCode();
526 if (status != wxID_OK) {
530 auto update = dialog.GetUpdate();
535 wxLogMessage(
"Installing %s", update.name.c_str());
537 g_Platform->ShowBusySpinner();
541 if (uninstall && path !=
"") {
542 gui_uninstall(pic, update.name.c_str());
544 bool cacheResult = pluginHandler->InstallPluginFromCache(update);
547 g_Platform->ShowBusySpinner();
551 std::string tempTarballPath = downloader->run(parent_dlg, uninstall);
553 if (!tempTarballPath.size())
559 if (!isRegularFile(manifestPath.c_str())) {
560 wxLogMessage(
"Installation of %s failed", update.name.c_str());
561 PluginHandler::CleanupFiles(manifestPath, update.name);
567 wxLogMessage(
"Installation of %s successful", update.name.c_str());
568 wxURI uri(wxString(update.tarball_url.c_str()));
569 wxFileName fn(uri.GetPath());
570 std::string basename = fn.GetFullName().ToStdString();
573 wxLogDebug(
"Copied %s to local cache at %s", tempTarballPath.c_str(),
575 remove(tempTarballPath.c_str());
583 wxString pispec =
"_pi.dll";
584#elif defined(__WXOSX__)
585 wxString pispec =
"_pi.dylib";
587 wxString pispec =
"_pi.so";
591 wxTextFile manifest_file(manifestPath);
593 if (manifest_file.Open()) {
595 for (wxString str = manifest_file.GetFirstLine(); !manifest_file.Eof();
596 str = manifest_file.GetNextLine()) {
597 if (str.Contains(pispec)) {
598 if (getenv(
"OCPN_KEEP_PLUGINS")) {
602 auto loader = PluginLoader::GetInstance();
603 if (!loader->CheckPluginCompatibility(str)) {
605 _(
"The plugin is not compatible with this version of OpenCPN, "
606 "and will be uninstalled.");
607 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
608 wxICON_INFORMATION | wxOK, 10);
610 PluginHandler::CleanupFiles(manifestPath, update.name);
619 if (b_forceEnable && pluginFile.Length()) {
620 wxString config_section = (_T (
"/PlugIns/" ));
621 wxFileName fn(pluginFile);
622 config_section += fn.GetFullName();
623 pConfig->SetPath(config_section);
624 pConfig->Write(_T (
"bEnabled" ),
true);
630 std::remove(handler->ImportedMetadataPath(update.name).c_str());
633 LoadAllPlugIns(
false);
636 g_Platform->HideBusySpinner();
656 pivp.
lat_min = tvp.GetBBox().GetMinLat();
657 pivp.
lat_max = tvp.GetBBox().GetMaxLat();
658 pivp.
lon_min = tvp.GetBBox().GetMinLon();
659 pivp.
lon_max = tvp.GetBBox().GetMaxLon();
661 pivp.
bValid = tvp.IsValid();
682 if (top_frame::Get()->GetAbstractPrimaryCanvas())
683 vp.
ref_scale = top_frame::Get()->GetCanvasRefScale();
698 void OnPluginUtilAction(wxCommandEvent& event);
700 DECLARE_EVENT_TABLE()
704EVT_BUTTON(ID_CMD_BUTTON_PERFORM_ACTION, pluginUtilHandler::OnPluginUtilAction)
709void pluginUtilHandler::OnPluginUtilAction(wxCommandEvent& event) {
710 auto panel =
static_cast<PluginPanel*
>(
event.GetClientData());
713 wxASSERT(plugin_list_panel != 0);
715 auto actionPIC = panel->GetPlugin();
716 wxString name = actionPIC->m_common_name;
719 switch (panel->GetAction()) {
720 case ActionVerb::UPGRADE_TO_MANAGED_VERSION: {
721 auto loader = PluginLoader::GetInstance();
724 std::string pluginName = actionPIC->m_managed_metadata.name;
726 wxLogMessage(
"Installing managed plugin: %s", pluginName.c_str());
728 new GuiDownloader(plugin_list_panel, actionPIC->m_managed_metadata);
729 downloader->run(plugin_list_panel,
false);
733 if (isRegularFile(manifestPath.c_str())) {
735 for (
unsigned i = 0; i < loader->GetPlugInArray()->GetCount(); i += 1) {
736 if (actionPIC->m_managed_metadata.name ==
737 loader->GetPlugInArray()->Item(i)->m_common_name.ToStdString()) {
738 loader->UnLoadPlugIn(i);
744 LoadAllPlugIns(
false);
746 PluginHandler::CleanupFiles(manifestPath,
747 actionPIC->m_managed_metadata.name);
750 plugin_list_panel->SelectByName(name);
755 case ActionVerb::UPDATE_IMPORTED_VERSION:
756 case ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION:
757 case ActionVerb::REINSTALL_MANAGED_VERSION:
758 case ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION: {
760 auto metaSave = actionPIC->m_managed_metadata;
761 run_update_dialog(plugin_list_panel, actionPIC,
true,
762 metaSave.name.c_str());
766 case ActionVerb::INSTALL_MANAGED_VERSION: {
767 wxLogMessage(
"Installing new managed plugin.");
768 run_update_dialog(plugin_list_panel, actionPIC,
false);
772 case ActionVerb::UNINSTALL_MANAGED_VERSION: {
775 message.Printf(
"%s %s\n", actionPIC->m_managed_metadata.name.c_str(),
776 actionPIC->m_managed_metadata.version.c_str());
777 message += _(
"successfully un-installed");
779 wxLogMessage(
"Uninstalling %s",
780 actionPIC->m_managed_metadata.name.c_str());
783 actionPIC->m_managed_metadata.name);
786 LoadAllPlugIns(
false);
788 OCPNMessageBox(wxTheApp->GetTopWindow(), message,
789 _(
"Un-Installation complete"), wxICON_INFORMATION | wxOK);
793 case ActionVerb::NOP:
804const wxEventType wxEVT_OCPN_MSG = wxNewEventType();
806OCPN_MsgEvent::OCPN_MsgEvent(wxEventType commandType,
int id)
807 : wxEvent(id, commandType) {}
809OCPN_MsgEvent::~OCPN_MsgEvent() {}
811wxEvent* OCPN_MsgEvent::Clone()
const {
813 newevent->m_MessageID =
816 newevent->m_MessageText = this->m_MessageText.c_str();
825PlugInToolbarToolContainer::PlugInToolbarToolContainer() {
829 bitmap_Rollover_day = NULL;
830 bitmap_Rollover_dusk = NULL;
831 bitmap_Rollover_night = NULL;
834PlugInToolbarToolContainer::~PlugInToolbarToolContainer() {
838 delete bitmap_Rollover_day;
839 delete bitmap_Rollover_dusk;
840 delete bitmap_Rollover_night;
851#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
852EVT_CURL_END_PERFORM(CurlThreadId, PlugInManager::OnEndPerformCurlDownload)
853EVT_CURL_DOWNLOAD(CurlThreadId, PlugInManager::OnCurlDownload)
857static
void event_message_box(const wxString& msg) {
858 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
859 wxICON_INFORMATION | wxOK, 0);
865 if (!pic->m_toolbox_panel) NotifySetupOptionsPlugin(pic);
871#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
872 m_pCurlThread = NULL;
878 m_plugin_menu_item_id_next = CanvasMenuHandler::GetNextContextMenuId();
879 m_plugin_tool_id_next = top_frame::Get()->GetNextToolbarToolId();
892 new wxRadioBox(parent, -1,
"", wxPoint(0, 0), wxSize(-1, -1), as);
898#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
900 m_last_online =
false;
901 m_last_online_chk = -1;
906 m_blacklist = blacklist_factory();
907 m_blacklist_ui = std::unique_ptr<BlacklistUI>(
new BlacklistUI());
909 wxDEFINE_EVENT(EVT_JSON_TO_ALL_PLUGINS,
ObservedEvt);
911 EVT_JSON_TO_ALL_PLUGINS);
912 Bind(EVT_JSON_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
913 auto json = std::static_pointer_cast<const wxJSONValue>(ev.
GetSharedPtr());
914 SendJSONMessageToAllPlugins(ev.GetString(), *json);
917 wxDEFINE_EVENT(EVT_LEGINFO_TO_ALL_PLUGINS,
ObservedEvt);
919 EVT_LEGINFO_TO_ALL_PLUGINS);
920 Bind(EVT_LEGINFO_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
921 auto ptr = UnpackEvtPointer<ActiveLegDat>(ev);
922 SendActiveLegInfoToAllPlugIns(ptr.get());
925 HandlePluginLoaderEvents();
931 m_new_msgtype_lstnr.
Init(NavMsgBus::GetInstance().new_msg_event,
934PlugInManager::~PlugInManager() {
935#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
936 wxCurlBase::Shutdown();
938 delete m_utilHandler;
941void PlugInManager::InitCommListeners() {
945 auto& msgbus = NavMsgBus::GetInstance();
948 m_listener_SignalK.
Listen(sk_msg,
this, EVT_SIGNALK);
955void PlugInManager::OnNewMessageType() {
956 for (
auto msg_key :
NavMsgBus::GetInstance().GetActiveMessages()) {
957 if (m_0183_listeners.find(msg_key) != m_0183_listeners.end())
continue;
958 if (msg_key.find(
"::") == std::string::npos)
continue;
960 if (key_parts.size() < 2)
continue;
965 m_0183_listeners[msg_key] = std::move(ol);
970 assert(n0183_msg->bus == NavAddr::Bus::N0183);
971 const std::string& payload = n0183_msg->payload;
973 if (payload[0] ==
'$') {
974 const auto& drivers = CommDriverRegistry::GetInstance().
GetDrivers();
975 auto& target_driver =
FindDriver(drivers, n0183_msg->source->iface);
979 bool passes_input_filter =
true;
983 passes_input_filter =
984 params.SentencePassesFilter(payload.c_str(), FILTER_INPUT);
987 }
else if (payload[0] ==
'!') {
988 SendAISSentenceToAllPlugIns(payload.c_str());
993 g_ownshipMMSI_SK = sK_msg->context_self;
998 std::string msgTerminated = sK_msg->raw_message;
1001 int errors = jsonReader.
Parse(msgTerminated, &root);
1002 if (errors == 0) SendJSONMessageToAllPlugins(
"OCPN_CORE_SIGNALK", root);
1011wxDEFINE_EVENT(EVT_PLUGMGR_ROUTEMAN_MSG,
ObservedEvt);
1012wxDEFINE_EVENT(EVT_BLACKLISTED_PLUGIN, wxCommandEvent);
1013wxDEFINE_EVENT(EVT_LOAD_DIRECTORY, wxCommandEvent);
1014wxDEFINE_EVENT(EVT_LOAD_PLUGIN, wxCommandEvent);
1015wxDEFINE_EVENT(EVT_PLUGIN_UNLOAD, wxCommandEvent);
1016wxDEFINE_EVENT(EVT_PLUGLIST_CHANGE, wxCommandEvent);
1017wxDEFINE_EVENT(EVT_UPDATE_CHART_TYPES, wxCommandEvent);
1018wxDEFINE_EVENT(EVT_PLUGIN_LOADALL_FINALIZE, wxCommandEvent);
1020void PlugInManager::HandlePluginLoaderEvents() {
1021 auto loader = PluginLoader::GetInstance();
1023 loader->SetOnActivateCb(
1025 loader->SetOnDeactivateCb(
1028 evt_pluglist_change_listener.
Listen(loader->evt_pluglist_change,
this,
1029 EVT_PLUGLIST_CHANGE);
1030 Bind(EVT_PLUGLIST_CHANGE, [&](wxCommandEvent&) {
1035 evt_load_directory_listener.
Listen(loader->evt_load_directory,
this,
1036 EVT_LOAD_DIRECTORY);
1037 Bind(EVT_LOAD_DIRECTORY, [&](wxCommandEvent&) {
1038 pConfig->SetPath(
"/PlugIns/");
1039 SetPluginOrder(
pConfig->Read(
"PluginOrder", wxEmptyString));
1042 evt_load_plugin_listener.
Listen(loader->evt_load_plugin,
this,
1044 Bind(EVT_LOAD_PLUGIN, [&](wxCommandEvent& ev) {
1049 evt_update_chart_types_listener.
Listen(loader->evt_update_chart_types,
this,
1050 EVT_UPDATE_CHART_TYPES);
1051 Bind(EVT_UPDATE_CHART_TYPES,
1052 [&](wxCommandEvent& ev) { UpDateChartDataTypes(); });
1054 evt_plugin_loadall_finalize_listener.
Listen(
1055 loader->evt_plugin_loadall_finalize,
this, EVT_PLUGIN_LOADALL_FINALIZE);
1056 Bind(EVT_PLUGIN_LOADALL_FINALIZE,
1057 [&](wxCommandEvent& ev) { FinalizePluginLoadall(); });
1061 EVT_PLUGMGR_ROUTEMAN_MSG);
1063 auto pTarget = UnpackEvtPointer<AisTargetData>(ev);
1064 SendAisJsonMessage(pTarget);
1066 Bind(EVT_PLUGMGR_ROUTEMAN_MSG, [&](
ObservedEvt& ev) {
1067 auto msg = UnpackEvtPointer<wxJSONValue>(ev);
1068 SendJSONMessageToAllPlugins(ev.GetString(), *msg);
1076wxDEFINE_EVENT(EVT_DOWNLOAD_FAILED, wxCommandEvent);
1077wxDEFINE_EVENT(EVT_DOWNLOAD_OK, wxCommandEvent);
1079void PlugInManager::HandlePluginHandlerEvents() {
1080 auto loader = PluginLoader::GetInstance();
1082 evt_download_failed_listener.
Listen(loader->evt_update_chart_types,
this,
1083 EVT_DOWNLOAD_FAILED);
1084 Bind(EVT_DOWNLOAD_FAILED, [&](wxCommandEvent& ev) {
1085 wxString message = _(
"Please check system log for more info.");
1086 OCPNMessageBox(wxTheApp->GetTopWindow(), message, _(
"Installation error"),
1087 wxICON_ERROR | wxOK | wxCENTRE);
1090 evt_download_ok_listener.
Listen(loader->evt_update_chart_types,
this,
1092 Bind(EVT_DOWNLOAD_OK, [&](wxCommandEvent& ev) {
1093 wxString message(ev.GetString());
1094 message += _(
" successfully installed from cache");
1095 OCPNMessageBox(wxTheApp->GetTopWindow(), message,
1096 _(
"Installation complete"),
1097 wxICON_INFORMATION | wxOK | wxCENTRE);
1101bool PlugInManager::CallLateInit() {
1104 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1105 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1108 switch (pic->m_api_version) {
1121 ProcessLateInit(pic);
1131 wxString msg(
"PlugInManager: Calling LateInit PlugIn: ");
1136 if (ppi) ppi->LateInit();
1145 if (top_frame::Get()->GetWxGlCanvas()) {
1146 top_frame::Get()->SendGlJsonConfigMsg();
1147 SendS52ConfigToAllPlugIns(
true);
1157 auto api_impl =
dynamic_cast<Api122Impl*
>(wxTheApp);
1158 assert(api_impl &&
"wxTheApp does not implement Api122Impl");
1159 api_impl->RegisterApiEventCallback(name,
nullptr);
1167 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1170 if (pttc->m_pplugin == pic->m_pplugin) {
1171 m_PlugInToolbarTools.Remove(pttc);
1177 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1179 if (pimis->m_pplugin == pic->m_pplugin) {
1180 m_PlugInMenuItems.Remove(pimis);
1186bool PlugInManager::IsAnyPlugInChartEnabled() {
1189 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1190 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1192 if (pic->m_enabled && pic->m_init_state) {
1201void PlugInManager::UpdateManagedPlugins() {
1203 PluginLoader::GetInstance()->
SortPlugins(ComparePlugins);
1206 g_options->itemBoxSizerPanelPlugins->Layout();
1209bool PlugInManager::UpDateChartDataTypes() {
1213 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1214 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1217 if (pic->m_init_state) {
1225 if (bret)
ChartData->UpdateChartClassDescriptorArray();
1230void PlugInManager::FinalizePluginLoadall() {
1234 SetColorSchemeForAllPlugIns(global_color_scheme);
1237 SendBaseConfigToAllPlugIns();
1238 SendS52ConfigToAllPlugIns(
true);
1239 SendSKConfigToAllPlugIns();
1244 top_frame::Get()->SendGlJsonConfigMsg();
1252void PlugInManager::SetPluginOrder(wxString serialized_names) {
1253 m_plugin_order.Empty();
1254 wxStringTokenizer tokenizer(serialized_names,
";");
1255 while (tokenizer.HasMoreTokens()) {
1256 m_plugin_order.Add(tokenizer.GetNextToken());
1260wxString PlugInManager::GetPluginOrder() {
1261 wxString plugins = wxEmptyString;
1262 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1263 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1264 plugins.Append(plugin_array->Item(i)->m_common_name);
1265 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1270bool PlugInManager::UpdateConfig() {
1274 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1275 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1279 wxString config_section = (_T (
"/PlugIns/" ));
1281 pConfig->SetPath(config_section);
1282 pConfig->Write(_T (
"bEnabled" ), pic->m_enabled);
1289void PlugInManager::ShowDeferredBlacklistMessages() {
1290 m_blacklist_ui->show_deferred_messages();
1293bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1295 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1298bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin* plugin) {
1303 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1304 name.Replace(
"class ", wxEmptyString);
1306 const std::type_info& ti =
typeid(*plugin);
1308 char* realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1309 wxString name = wxString::FromAscii(realname);
1312 return CheckBlacklistedPlugin(name, major, minor);
1315bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
1317 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1318 if (block_status == plug_status::unblocked)
return true;
1319 plug_data data(name.ToStdString(), major, minor);
1320 auto msg = m_blacklist->get_message(block_status, data);
1321 m_blacklist_ui->message(msg);
1325bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC& dc,
1329 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1330 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1332 if (pic->m_enabled && pic->m_init_state) {
1336 wxDC* pdc = dc.GetDC();
1339 switch (pic->m_api_version) {
1341 if (priority > 0)
break;
1348 if (priority > 0)
break;
1351 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1362 if (priority > 0)
break;
1365 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1370 if (priority > 0)
break;
1374 ppi->RenderOverlay(*pdc, &pivp);
1386 if (priority <= 0) {
1390 ppi->RenderOverlay(*pdc, &pivp);
1406 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1408 if ((m_cached_overlay_bm.GetWidth() != vp.
pix_width) ||
1409 (m_cached_overlay_bm.GetHeight() != vp.
pix_height))
1413 mdc.SelectObject(m_cached_overlay_bm);
1414 mdc.SetBackground(*wxBLACK_BRUSH);
1417 bool b_rendered =
false;
1419 switch (pic->m_api_version) {
1421 if (priority > 0)
break;
1428 if (priority > 0)
break;
1431 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1442 if (priority > 0)
break;
1445 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1450 if (priority > 0)
break;
1454 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1467 if (priority <= 0) {
1471 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1478 mdc, &pivp, g_canvasConfig, priority);
1487 mdc.SelectObject(wxNullBitmap);
1490 wxMask* p_msk =
new wxMask(m_cached_overlay_bm, wxColour(0, 0, 0));
1491 m_cached_overlay_bm.SetMask(p_msk);
1493 dc.DrawBitmap(m_cached_overlay_bm, 0, 0,
true);
1496 }
else if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1504bool PlugInManager::RenderAllGLCanvasOverlayPlugIns(wxGLContext* pcontext,
1508 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1509 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1511 if (pic->m_enabled && pic->m_init_state) {
1512 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1515 switch (pic->m_api_version) {
1517 if (priority > 0)
break;
1520 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
1532 if (priority > 0)
break;
1540 if (priority > 0)
break;
1557 if (priority <= 0) {
1582void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort& vp) {
1583 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1584 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1586 if (pic->m_enabled && pic->m_init_state) {
1595void NotifySetupOptionsPlugin(
const PlugInData* pd) {
1596 PluginLoader::GetInstance()->NotifySetupOptionsPlugin(pd);
1599void PlugInManager::NotifySetupOptions() {
1600 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1601 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1603 NotifySetupOptionsPlugin(pic);
1608 int ok_apply_cancel) {
1609 if (pic->m_enabled && pic->m_init_state) {
1612 auto loader = PluginLoader::GetInstance();
1619void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
1620 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1621 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1624 ClosePlugInPanel(pic, ok_apply_cancel);
1629int PlugInManager::AddCanvasContextMenuItemPIM(wxMenuItem* pitem,
1634 pmic->pmenu_item = pitem;
1635 pmic->m_pplugin = pplugin;
1636 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
1637 : m_plugin_menu_item_id_next;
1639 pmic->b_grey =
false;
1640 pmic->m_in_menu = name;
1641 pmic->extended = is_extended;
1643 m_PlugInMenuItems.Add(pmic);
1645 m_plugin_menu_item_id_next++;
1650void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char* name) {
1651 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1654 if (pimis->id == item) {
1655 m_PlugInMenuItems.Remove(pimis);
1663void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
1665 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1668 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1676void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
1678 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1681 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1682 pimis->b_grey = grey;
1689void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
1690 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1691 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1693 if (pic->m_enabled && pic->m_init_state)
1698void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
1699 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1700 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1702 if (pic->m_enabled && pic->m_init_state)
1707void PlugInManager::PrepareAllPluginContextMenus() {
1708 int canvasIndex = top_frame::Get()->GetCanvasIndexUnderMouse();
1709 if (canvasIndex < 0)
return;
1711 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1712 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1714 if (pic->m_enabled && pic->m_init_state) {
1716 switch (pic->m_api_version) {
1736void PlugInManager::SendSKConfigToAllPlugIns() {
1739 v[
"self"] = g_ownshipMMSI_SK;
1743 SendMessageToAllPlugins(wxString(
"OCPN_CORE_SIGNALK"), out);
1746void PlugInManager::SendBaseConfigToAllPlugIns() {
1749 v[
"OpenCPN Version Major"] = VERSION_MAJOR;
1750 v[
"OpenCPN Version Minor"] = VERSION_MINOR;
1751 v[
"OpenCPN Version Patch"] = VERSION_PATCH;
1752 v[
"OpenCPN Version Date"] = VERSION_DATE;
1753 v[
"OpenCPN Version Full"] = VERSION_FULL;
1757 v[
"OpenCPN Toolbar Width"] =
g_MainToolbar->GetToolbarRect().width;
1758 v[
"OpenCPN Toolbar Height"] =
g_MainToolbar->GetToolbarRect().height;
1759 v[
"OpenCPN Toolbar PosnX"] =
g_MainToolbar->GetToolbarRect().x;
1760 v[
"OpenCPN Toolbar PosnY"] =
g_MainToolbar->GetToolbarRect().y;
1764 v[
"OpenCPN Zoom Mod Vector"] = g_chart_zoom_modifier_vector;
1765 v[
"OpenCPN Zoom Mod Other"] = g_chart_zoom_modifier_raster;
1766 v[
"OpenCPN Scale Factor Exp"] =
1767 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1775 SendMessageToAllPlugins(wxString(
"OpenCPN Config"), out);
1778void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1781 v[
"OpenCPN Version Major"] = VERSION_MAJOR;
1782 v[
"OpenCPN Version Minor"] = VERSION_MINOR;
1783 v[
"OpenCPN Version Patch"] = VERSION_PATCH;
1784 v[
"OpenCPN Version Date"] = VERSION_DATE;
1785 v[
"OpenCPN Version Full"] = VERSION_FULL;
1793 v[
"OpenCPN S52PLIB ShowAnchorConditions"] = ps52plib->GetAnchorOn();
1794 v[
"OpenCPN S52PLIB ShowQualityOfData"] = ps52plib->GetQualityOfData();
1799 v[
"OpenCPN S52PLIB MetaDisplay"] = ps52plib->m_bShowMeta;
1800 v[
"OpenCPN S52PLIB DeclutterText"] = ps52plib->m_bDeClutterText;
1801 v[
"OpenCPN S52PLIB ShowNationalText"] = ps52plib->m_bShowNationalTexts;
1802 v[
"OpenCPN S52PLIB ShowImportantTextOnly"] =
1803 ps52plib->m_bShowS57ImportantTextOnly;
1804 v[
"OpenCPN S52PLIB UseSCAMIN"] = ps52plib->m_bUseSCAMIN;
1805 v[
"OpenCPN S52PLIB UseSUPER_SCAMIN"] = ps52plib->m_bUseSUPER_SCAMIN;
1806 v[
"OpenCPN S52PLIB SymbolStyle"] = ps52plib->m_nSymbolStyle;
1807 v[
"OpenCPN S52PLIB BoundaryStyle"] = ps52plib->m_nBoundaryStyle;
1808 v[
"OpenCPN S52PLIB ColorShades"] = S52_getMarinerParam(S52_MAR_TWO_SHADES);
1809 v[
"OpenCPN S52PLIB Safety Depth"] =
1810 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1811 v[
"OpenCPN S52PLIB Shallow Contour"] =
1812 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1813 v[
"OpenCPN S52PLIB Deep Contour"] =
1814 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1818 v[
"OpenCPN S52PLIB GlobalReconfig"] = bReconfig;
1823 SendMessageToAllPlugins(wxString(
"OpenCPN Config"), out);
1826void PlugInManager::NotifyAuiPlugIns() {
1827 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1828 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1830 if (pic->m_enabled && pic->m_init_state &&
1836int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1837 wxBitmap* bmpRollover, wxItemKind kind,
1838 wxString shortHelp, wxString longHelp,
1839 wxObject* clientData,
int position,
1842 pttc->label = label;
1844 if (!bitmap->IsOk()) {
1846 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1849 pttc->bitmap_day =
new wxBitmap(*bitmap);
1850 pttc->bitmap_day->UnShare();
1853 if (!bmpRollover->IsOk()) {
1855 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1858 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1859 pttc->bitmap_Rollover_day->UnShare();
1862 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1863 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1864 pttc->bitmap_Rollover_dusk =
1865 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1866 pttc->bitmap_Rollover_night =
1867 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1870 pttc->shortHelp = shortHelp;
1871 pttc->longHelp = longHelp;
1872 pttc->clientData = clientData;
1873 pttc->position = position;
1874 pttc->m_pplugin = pplugin;
1875 pttc->tool_sel = tool_sel;
1877 pttc->b_toggle =
false;
1878 pttc->id = m_plugin_tool_id_next;
1880 m_PlugInToolbarTools.Add(pttc);
1882 m_plugin_tool_id_next++;
1887int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1888 wxString SVGRolloverfile,
1889 wxString SVGToggledfile, wxItemKind kind,
1890 wxString shortHelp, wxString longHelp,
1891 wxObject* clientData,
int position,
1894 pttc->label = label;
1896 pttc->pluginNormalIconSVG = SVGfile;
1897 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1898 pttc->pluginToggledIconSVG = SVGToggledfile;
1903 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1904 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1905 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1906 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1907 pttc->bitmap_Rollover_dusk =
1908 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1909 pttc->bitmap_Rollover_night =
1910 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1913 pttc->shortHelp = shortHelp;
1914 pttc->longHelp = longHelp;
1915 pttc->clientData = clientData;
1916 pttc->position = position;
1917 pttc->m_pplugin = pplugin;
1918 pttc->tool_sel = tool_sel;
1920 pttc->b_toggle =
false;
1921 pttc->id = m_plugin_tool_id_next;
1923 m_PlugInToolbarTools.Add(pttc);
1925 m_plugin_tool_id_next++;
1930void PlugInManager::RemoveToolbarTool(
int tool_id) {
1931 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1934 if (pttc->id == tool_id) {
1935 m_PlugInToolbarTools.Remove(pttc);
1941 m_parent->RequestNewToolbars();
1944void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1945 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1948 if (pttc->id == item) {
1950 m_parent->RequestNewToolbars();
1957void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1958 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1961 if (pttc->id == item) {
1962 pttc->b_toggle = toggle;
1963 m_parent->SetMasterToolbarItemState(item, toggle);
1970void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1971 wxBitmap* bmpRollover) {
1972 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1975 if (pttc->id == item) {
1976 delete pttc->bitmap_day;
1977 delete pttc->bitmap_dusk;
1978 delete pttc->bitmap_night;
1979 delete pttc->bitmap_Rollover_day;
1981 if (!bitmap->IsOk()) {
1983 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1986 pttc->bitmap_day =
new wxBitmap(*bitmap);
1987 pttc->bitmap_day->UnShare();
1990 if (!bmpRollover->IsOk()) {
1992 pttc->bitmap_Rollover_day =
1993 new wxBitmap(style->GetIcon(
"default_pi"));
1996 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1997 pttc->bitmap_Rollover_day->UnShare();
2000 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
2001 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
2003 m_parent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
2004 pttc->bitmap_Rollover_day);
2011void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2012 wxString SVGfileRollover,
2013 wxString SVGfileToggled) {
2014 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2017 if (pttc->id == item) {
2018 pttc->pluginNormalIconSVG = SVGfile;
2019 pttc->pluginRolloverIconSVG = SVGfileRollover;
2020 pttc->pluginToggledIconSVG = SVGfileToggled;
2021 m_parent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2022 pttc->pluginRolloverIconSVG,
2023 pttc->pluginToggledIconSVG);
2031 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2033 if (
id == pc->id)
return pc->m_pplugin;
2039wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2042 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2043 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2045 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2049 return wxEmptyString;
2052wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2054wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2055 unsigned char dim_ratio) {
2056 wxImage img_dup = pbmp_normal->ConvertToImage();
2058 if (!img_dup.IsOk())
return NULL;
2060 if (dim_ratio < 200) {
2062 int gimg_width = img_dup.GetWidth();
2063 int gimg_height = img_dup.GetHeight();
2065 double factor = (double)(dim_ratio) / 256.0;
2067 for (
int iy = 0; iy < gimg_height; iy++) {
2068 for (
int ix = 0; ix < gimg_width; ix++) {
2069 if (!img_dup.IsTransparent(ix, iy)) {
2070 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2071 img_dup.GetGreen(ix, iy),
2072 img_dup.GetBlue(ix, iy));
2073 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2074 hsv.value = hsv.value * factor;
2075 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2076 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2082 wxBitmap* ptoolBarBitmap;
2085 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2087 dwxdc.SelectObject(tbmp);
2089 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2091 ptoolBarBitmap =
new wxBitmap(img_dup);
2095 return ptoolBarBitmap;
2098wxArrayString PlugInManager::GetPlugInChartClassNameArray() {
2099 wxArrayString array;
2100 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2101 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2103 if (pic && pic->m_enabled && pic->m_init_state &&
2108 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2109 array.Add(carray[j]);
2117 while (j < array.GetCount()) {
2118 wxString test = array[j];
2119 unsigned int k = j + 1;
2120 while (k < array.GetCount()) {
2121 if (test == array[k]) {
2136 const wxString& ChartClassName) {
2138 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2139 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2141 if (pic && pic->m_enabled && pic->m_init_state &&
2146 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2147 if (carray[j].IsSameAs(ChartClassName)) {
2148 plugin = pic->m_pplugin;
2162#define DISABLED_SETTINGS_MSG \
2163 _("These settings might destabilize OpenCPN and are by default disabled." \
2164 " To despite the dangers enable them manually add a CatalogExpert=1" \
2165 " line in the [PlugIns] section in the configuration file.")
2170CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2171 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2173 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2176 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2178 wxStaticBox* itemStaticBoxSizer4Static =
2179 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2180 wxStaticBoxSizer* itemStaticBoxSizer4 =
2181 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2182 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2186 m_catalogText =
new wxStaticText(
this, wxID_STATIC,
"");
2187 itemStaticBoxSizer4->Add(m_catalogText,
2188 wxSizerFlags().Border().Proportion(1));
2189 m_catalogText->SetLabel(GetCatalogText(
false));
2192 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2193 itemStaticBoxSizer4->Add(rowSizer2,
2194 wxSizerFlags().Expand().Border().Proportion(1));
2196 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2197 wxDefaultPosition, wxDefaultSize, 0);
2198 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2199 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2200 &CatalogMgrPanel::OnUpdateButton,
this);
2201 rowSizer2->AddSpacer(4 * GetCharWidth());
2202 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2203 wxDefaultPosition, wxDefaultSize, 0);
2204 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2205 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2206 &CatalogMgrPanel::OnTarballButton,
this);
2208 rowSizer2->AddSpacer(4 * GetCharWidth());
2209 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2210 wxDefaultPosition, wxDefaultSize, 0);
2212 if (expert.Get(
false)) {
2213 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2214 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2216 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2217 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2220 rowSizer2->AddSpacer(4 * GetCharWidth());
2221 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2223 SetUpdateButtonLabel();
2226 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2227 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2229 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2233 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2234 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2235 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2238 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2240 if (!expert.Get(
false)) {
2242 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2243 wxDefaultPosition, wxDefaultSize, 0);
2244 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2245 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2246 &CatalogMgrPanel::OnUpdateButton,
this);
2247 SetUpdateButtonLabel();
2248 m_tarballButton = NULL;
2249 m_adv_button = NULL;
2252 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2253 itemStaticBoxSizer4->Add(m_catalogText,
2254 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2257 m_updateButton =
new wxButton(
2258 this, wxID_ANY,
"Update Plugin Catalog:master ",
2259 wxDefaultPosition, wxDefaultSize, 0);
2260 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2261 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2262 &CatalogMgrPanel::OnUpdateButton,
this);
2263 SetUpdateButtonLabel();
2266 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2267 wxDefaultPosition, wxDefaultSize, 0);
2268 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2270 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2271 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2274 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2275 wxDefaultPosition, wxDefaultSize, 0);
2276 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2277 2 * GetCharWidth());
2278 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2279 &CatalogMgrPanel::OnTarballButton,
this);
2285CatalogMgrPanel::~CatalogMgrPanel() {
2286 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2287 &CatalogMgrPanel::OnUpdateButton,
this);
2288 if (m_tarballButton)
2289 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2290 &CatalogMgrPanel::OnTarballButton,
this);
2293static const char*
const DOWNLOAD_REPO_PROTO =
2294 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2297void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2299 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2300 std::string url(g_catalog_custom_url);
2301 if (catalog !=
"custom") {
2302 url = std::string(DOWNLOAD_REPO_PROTO);
2306 std::string filePath =
2307 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2309 auto catalogHdlr = CatalogHandler::GetInstance();
2311 g_Platform->ShowBusySpinner();
2312 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2313 g_Platform->HideBusySpinner();
2315 std::string message;
2316 if (status != CatalogHandler::ServerStatus::OK) {
2317 message = _(
"Cannot download data from url");
2318 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2319 wxICON_ERROR | wxOK);
2325 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2327 wxFileName::GetPathSeparator() +
2328 "ocpn-plugins.xml")) {
2329 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2330 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2335 if (!wxCopyFile(wxString(filePath.c_str()),
2337 wxFileName::GetPathSeparator() +
"ocpn-plugins.xml")) {
2338 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2339 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2345 if (catalog ==
"master") {
2347 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2348 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2354 pConfig->SetPath(
"/PlugIns/");
2355 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2362 pluginHandler->setMetadata(
"");
2366 auto cataloghdlr = CatalogHandler::GetInstance();
2367 cataloghdlr->ClearCatalogData();
2370 LoadAllPlugIns(
false);
2374 m_catalogText->SetLabel(GetCatalogText(
true));
2377 OCPNMessageBox(
this, _(
"Catalog update successful"),
2378 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2381void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2385 androidDisableRotation();
2388 dialog->ShowModal();
2391 androidEnableRotation();
2395void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2398 int response = g_Platform->DoFileSelectorDialog(
2399 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2400 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2402 if (response != wxID_OK) {
2407 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2411 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2412 _(
"OpenCPN Plugin Import Error"));
2416 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2417 _(
"OpenCPN Plugin Import Error"));
2418 handler->Uninstall(metadata.name);
2421 UninstallPlugin(metadata.name);
2422 ok = handler->InstallPlugin(metadata, path.ToStdString());
2424 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2425 _(
"OpenCPN Plugin Import Error"));
2428 metadata.is_imported =
true;
2430 std::ofstream file(metadata_path);
2433 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2434 <<
" for imported plugin: " << metadata.name;
2436 LoadAllPlugIns(
false,
true);
2439 wxString ws(_(
"Plugin"));
2440 ws += metadata.name + _(
" successfully imported");
2441 OCPNMessageBox(wxTheApp->GetTopWindow(), ws, _(
"Installation complete"),
2442 wxICON_INFORMATION | wxOK | wxCENTRE);
2445wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2447 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2451 pConfig->SetPath(
"/PlugIns/");
2452 wxString latestCatalog =
pConfig->Read(
"LatestCatalogDownloaded",
"default");
2453 catalog += latestCatalog;
2459 std::string date = pluginHandler->GetCatalogData()->date;
2461 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2462 if (!updated) catalog +=
" : " + _(
"Please Update Plugin Catalog.");
2468void CatalogMgrPanel::SetUpdateButtonLabel() {
2469 wxString label = _(
"Update Plugin Catalog");
2471 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2472 m_updateButton->SetLabel(label);
2476wxString CatalogMgrPanel::GetImportInitDir() {
2478 pConfig->SetPath(
"/PlugIns/");
2479 wxString lastImportDir;
2481 pConfig->Read(
"LatestImportDir", g_Platform->GetWritableDocumentsDir());
2482 if (wxDirExists(lastImportDir)) {
2483 return lastImportDir;
2485 return (g_Platform->GetWritableDocumentsDir());
2494 const wxPoint& pos, const wxSize& size)
2495 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2496 m_PluginSelected(0) {
2497 m_is_loading.clear();
2498 SetSizer(
new wxBoxSizer(wxVERTICAL));
2499 ReloadPluginPanels();
2502void PluginListPanel::SelectByName(wxString& name) {
2503 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2504 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2506 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2507 pluginPanel->SetSelected(
true);
2508 pluginPanel->Layout();
2509 SelectPlugin(pluginPanel);
2518 std::vector<const PlugInData*> result;
2519 auto loader = PluginLoader::GetInstance();
2520 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2521 auto const item = loader->GetPlugInArray()->Item(i);
2522 if (item->m_managed_metadata.name.empty()) {
2523 const auto name = item->m_common_name.ToStdString();
2527 result.push_back(item);
2530 std::string slhs, srhs;
2531 for (
auto& cl : lhs->
Key()) slhs += toupper(cl);
2532 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2533 return slhs.compare(srhs) < 0;
2535 std::sort(result.begin(), result.end(), compare);
2540static bool IsPluginLoaded(
const std::string& name) {
2541 if (safe_mode::get_mode()) {
2544 std::find(installed.begin(), installed.end(),
ocpn::tolower(name));
2545 return found != installed.end();
2548 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2549 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2556 if (m_is_loading.test_and_set()) {
2558 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2563 m_PluginItems.Clear();
2565 wxWindowList kids = GetChildren();
2566 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2567 wxWindowListNode* node = kids.Item(i);
2568 wxWindow* win = node->GetData();
2570 if (pp) win->Destroy();
2572 GetSizer()->Clear();
2575 m_PluginSelected = 0;
2577 if (safe_mode::get_mode()) {
2580 for (
const auto& name : installed) AddPlugin(name);
2583 auto available = getCompatiblePlugins();
2587 return IsPluginLoaded(md.name);
2589 auto end = std::remove_if(available.begin(), available.end(), predicate);
2590 available.erase(end, available.end());
2596 std::string slhs, srhs;
2597 for (
auto& cl : lhs.name) slhs += toupper(cl);
2598 for (
auto& cr : rhs.name) srhs += toupper(cr);
2599 return slhs.compare(srhs) < 0;
2603 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2604 for (
const auto& p : available) unique_sorted_entries.insert(p);
2610 if (p->m_enabled) AddPlugin(*p);
2614 if (!p->m_enabled) AddPlugin(*p);
2617 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2625 m_is_loading.clear();
2628void PluginListPanel::AddPlugin(
const std::string& name) {
2631 panel->SetSelected(
false);
2632 GetSizer()->Add(panel, 0, wxEXPAND);
2633 m_PluginItems.Add(panel);
2634 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2635 GetSizer()->AddSpacer(m_pluginSpacer);
2638void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2640 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2641 pPluginPanel->SetSelected(
false);
2642 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2643 m_PluginItems.Add(pPluginPanel);
2645 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2646 GetSizer()->AddSpacer(m_pluginSpacer);
2659int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2660 wxBoxSizer* sizer) {
2662 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2663 auto panel = plugins.Item(i);
2664 bool was_selected = panel->GetSelected();
2665 panel->SetSelected(
false);
2667 wxSize unselected = panel->GetSize();
2669 panel->SetSelected(
true);
2671 wxSize selected = panel->GetSize();
2673 int dy = selected.GetHeight() - unselected.GetHeight();
2674 max_dy = wxMax(max_dy, dy);
2675 panel->SetSelected(was_selected);
2680PluginListPanel::~PluginListPanel() {}
2682void PluginListPanel::UpdateSelections() {
2683 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2686 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2691void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2693 GetViewStart(&xs, &ys);
2696 if (m_PluginSelected) {
2697 m_PluginSelected->SetSelected(
false);
2698 m_PluginSelected->Layout();
2701 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2703 m_PluginSelected = pi;
2705 GetSizer()->Layout();
2707 wxSize size = GetBestVirtualSize();
2708 SetVirtualSize(size);
2713 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2715 int yd = pPluginPanel->GetSize().y;
2717 htop += m_pluginSpacer;
2718 if (pPluginPanel == pi) {
2719 int piBottom = htop - (ys *
g_options->GetScrollRate());
2720 if (piBottom > GetClientSize().y) {
2721 ys += (piBottom - GetClientSize().y) /
g_options->GetScrollRate();
2731 int pos = m_PluginItems.Index(pi);
2734 m_PluginItems.RemoveAt(pos);
2737 m_PluginItems.Insert(pi, pos - 1);
2738 wxStaticLine* itemStaticLine =
new wxStaticLine(
2739 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2744 m_PluginSelected = pi;
2746 GetSizer()->Layout();
2752 int pos = m_PluginItems.Index(pi);
2753 if (pos == (
int)m_PluginItems.Count() -
2756 m_PluginItems.RemoveAt(pos);
2759 m_PluginItems.Insert(pi, pos + 1);
2760 wxStaticLine* itemStaticLine =
new wxStaticLine(
2761 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2766 m_PluginSelected = pi;
2768 GetSizer()->Layout();
2773static bool canUninstall(std::string name) {
2778 if (plugin.name == name) {
2779 if (safe_mode::get_mode())
2782 return !plugin.readonly;
2789 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2791 m_is_safe_panel(true) {
2793 wxASSERT(m_PluginListPanel != 0);
2794 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2795 SetSizer(top_sizer);
2796 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2797 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2799 double iconSize = GetCharWidth() * 4;
2801 int icon_scale = iconSize * dpi_mult;
2803 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2804 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2805 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2807 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2808 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2809 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2810 top_horizontal->Add(m_pVersion);
2813 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2814 top_horizontal->Add(m_pButtons);
2815 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2816 top_horizontal->Add(m_info_btn);
2817 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2818 wxDefaultPosition, wxDefaultSize, 0);
2819 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2821 auto uninstall = [&](wxCommandEvent ev) {
2822 auto n = m_pName->GetLabel().ToStdString();
2823 int result = OCPNMessageBox(
2824 wxTheApp->GetTopWindow(), std::string(_(
"Uninstall plugin ")) + n +
"?",
2825 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2826 if (result != wxID_OK)
return;
2830 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2834EVT_PAINT(PluginPanel::OnPaint)
2839 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2841 m_is_safe_panel(false) {
2844 wxASSERT(m_PluginListPanel != 0);
2846 m_bSelected =
false;
2847 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2848 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2850 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2853 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2854 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2855 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2856 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2858 double iconSize = GetCharWidth() * 4;
2860 int icon_scale = iconSize * dpi_mult;
2862 wxImage plugin_icon;
2864 if (m_plugin.m_bitmap.IsOk()) {
2865 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2868 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2869 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2870 path.AppendDir(
"uidata");
2871 path.AppendDir(
"traditional");
2872 bitmap =
LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2873 }
else if (plugin_icon.IsOk()) {
2874 int nowSize = plugin_icon.GetWidth();
2875 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2876 bitmap = wxBitmap(plugin_icon);
2878 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2880 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2882 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2883 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2885 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2888 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2889 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2892 int nChars =
g_options->GetSize().x / GetCharWidth();
2893 bool bCompact =
false;
2899 wxString nameString = m_plugin.m_common_name;
2903 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2904 if (nameWidth > maxWidth) {
2905 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2906 wxELLIPSIZE_END, maxWidth);
2908 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2909 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2910 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2911 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2913 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2914 sl1->AddGrowableCol(1);
2915 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2917 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"X.YY.ZZ.AA");
2918 sl1->Add(m_pVersion, 0, wxALL, 5);
2919 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2922 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2923 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2925 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2926 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2927 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2930 wxString descriptionString = m_plugin.m_short_description;
2931 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2932 int descriptionWidth;
2933 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2934 if (descriptionWidth > maxDescriptionWidth)
2936 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2937 wxELLIPSIZE_END, maxDescriptionWidth);
2942 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2943 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2944 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2945 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2946 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2949 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2950 itemBoxSizer03->AddGrowableCol(2);
2951 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2953 wxString nameString = m_plugin.m_common_name;
2954 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2955 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2956 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2960 wxFont font = GetFont();
2961 font.SetWeight(wxFONTWEIGHT_BOLD);
2962 m_pName->SetFont(font);
2965 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2967 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"X.YY.ZZ.AA");
2968 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2969 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2972 !m_plugin.m_managed_metadata.is_orphan)) {
2975 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2976 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2978 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2979 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2980 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2982 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2984 m_pDescription =
new wxStaticText(
2985 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2987 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2988 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2989 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2993 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2995 itemBoxSizer02->Add(m_info_btn, 0);
2997 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2998 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2999 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
3000 wxDefaultPosition, wxDefaultSize, 0);
3001 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
3003 m_pButtons->AddSpacer(3 * GetCharWidth());
3006 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3007 wxDefaultPosition, wxDefaultSize, 0);
3008 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3010 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3011 wxDefaultPosition, wxDefaultSize, 0);
3012 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3014 m_pButtons =
new wxBoxSizer(wxVERTICAL);
3015 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
3017 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
3018 m_pButtons->Add(tline, 0, wxALL, 2);
3020 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
3021 wxDefaultPosition, wxDefaultSize, 0);
3022 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
3024 tline->AddSpacer(3 * GetCharWidth());
3026 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
3028 tline->Add(m_info_btn, 0);
3031 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3032 wxDefaultPosition, wxDefaultSize);
3033 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3035 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3036 wxDefaultPosition, wxDefaultSize, 0);
3037 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3040 wxBitmap statusBitmap;
3041 const auto stat = m_plugin.m_status;
3042 auto icon_name = icon_by_status.at(stat);
3043 if (stat == PluginStatus::Imported &&
3044 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3046 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3049 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3050 path.AppendDir(
"uidata");
3051 path.AppendDir(
"traditional");
3053 int bmsize = GetCharWidth() * 3 * dpi_mult;
3054 if (path.IsFileReadable()) {
3055 statusBitmap =
LoadSVG(path.GetFullPath(), bmsize, bmsize);
3056 ok = statusBitmap.IsOk();
3059 auto style = g_StyleManager->GetCurrentStyle();
3060 statusBitmap = wxBitmap(style->GetIcon(
"default_pi", bmsize, bmsize));
3061 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3064 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3065 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3066 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3068 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3071 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3073 itemBoxSizer02->AddSpacer(GetCharWidth());
3075 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3076 &PluginPanel::OnPluginPreferences,
this);
3077 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3078 &PluginPanel::OnPluginUninstall,
this);
3079 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3080 &PluginPanel::OnPluginAction,
this);
3082 SetSelected(m_bSelected);
3083 SetAutoLayout(
true);
3091PluginPanel::~PluginPanel() {
3092 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3093 if (m_is_safe_panel)
return;
3094 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3096 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3097 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3098 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3099 if (m_pButtonAction) {
3100 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3101 &PluginPanel::OnPluginAction,
this);
3103 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3104 &PluginPanel::OnPluginPreferences,
this);
3105 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3106 &PluginPanel::OnPluginEnableToggle,
this);
3109void PluginPanel::SetActionLabel(wxString& label) {
3110 m_pButtonAction->SetLabel(label);
3114static wxStopWatch swclick;
3115static int downx, downy;
3117void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3120 event.GetPosition(&downx, &downy);
3126void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3128 qDebug() << swclick.Time();
3129 if (swclick.Time() < 200) {
3131 event.GetPosition(&upx, &upy);
3132 if ((fabs(upx - downx) < GetCharWidth()) &&
3133 (fabs(upy - downy) < GetCharWidth())) {
3141void PluginPanel::DoPluginSelect() {
3142 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3148 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3149 }
else if (m_bSelected) {
3151 m_PluginListPanel->SelectPlugin(NULL);
3154 m_PluginListPanel->SelectPlugin(
this);
3162static PluginMetadata GetMetadataByName(
const std::string& name) {
3164 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3165 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3166 if (found == plugins.end()) {
3167 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3172void PluginPanel::SetSelected(
bool selected) {
3173 m_bSelected = selected;
3175 m_pVersion->SetLabel(
3179 m_pButtons->Show(
true);
3180 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3183 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3186 unInstallPossible =
false;
3189 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3191 m_pButtonUninstall->Show(unInstallPossible);
3193 if (m_plugin.m_managed_metadata.info_url.size()) {
3194 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3198 m_cbEnable->Show(
true);
3203 switch (m_plugin.m_status) {
3204 case PluginStatus::LegacyUpdateAvailable:
3205 label = _(
"Upgrade to Version ");
3206 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3207 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3208 m_pButtonAction->Enable();
3211 case PluginStatus::ManagedInstallAvailable:
3212 label = _(
"Install...");
3213 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3214 m_pButtonAction->Enable();
3217 case PluginStatus::ManagedInstalledUpdateAvailable:
3218 label = _(
"Update to ");
3219 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3220 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3221 m_pButtonAction->Enable();
3224 case PluginStatus::ManagedInstalledCurrentVersion:
3225 label = _(
"Reinstall");
3226 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3227 m_pButtonAction->Enable();
3230 case PluginStatus::ManagedInstalledDowngradeAvailable:
3231 label = _(
"Downgrade");
3232 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3233 m_pButtonAction->Enable();
3236 case PluginStatus::Imported:
3237 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3238 label = _(
"Update");
3239 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3241 m_pButtonAction->Hide();
3242 m_action = ActionVerb::NOP;
3247 m_action = ActionVerb::NOP;
3248 m_pButtonAction->Hide();
3252 m_action = ActionVerb::NOP;
3253 m_pButtonAction->Hide();
3258 m_action = ActionVerb::NOP;
3261 SetActionLabel(label);
3273 m_pButtons->Show(
false);
3276 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3277 m_cbEnable->Show(
false);
3298 SetEnabled(m_plugin.m_enabled);
3313void PluginPanel::OnPaint(wxPaintEvent& event) {
3316 int penWidth = m_penWidthUnselected;
3321 penWidth = m_penWidthSelected;
3326 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3328 dc.SetPen(wxPen(border, penWidth));
3330 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3333void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3334 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3337 androidDisableRotation();
3348void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3349 g_Platform->ShowBusySpinner();
3350 SetEnabled(event.IsChecked());
3351 m_pVersion->SetLabel(
3358 g_Platform->HideBusySpinner();
3361void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3362 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
3365 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3366 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3367 actionEvent.SetClientData(
this);
3368 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3371void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3373 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3374 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3375 actionEvent.SetClientData(
this);
3376 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3381static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3382 auto font = window->GetFont();
3383 font.SetStyle(style);
3384 window->SetFont(font);
3387void PluginPanel::SetEnabled(
bool enabled) {
3388 if (m_is_safe_panel)
return;
3391 if (enabled) NotifySetupOptionsPlugin(&m_plugin);
3392 if (!enabled && !m_bSelected) {
3393 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3394 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3395 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3398 m_pVersion->Disable();
3399 m_pDescription->Disable();
3402 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3403 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3404 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3407 m_pVersion->Enable();
3408 m_pDescription->Enable();
3413 m_pName->Enable(enabled || m_bSelected);
3414 m_pVersion->Enable(enabled || m_bSelected);
3415 m_pDescription->Enable(enabled || m_bSelected);
3419 wxString description = m_plugin.m_long_description;
3420 if (description.IsEmpty())
3421 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3425 m_pDescription->SetLabel(wrapper.GetWrapped());
3426 if (m_plugin.m_managed_metadata.info_url.size()) {
3427 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3431 wxString description = m_plugin.m_short_description;
3432 if (description.IsEmpty())
3433 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3436 m_pDescription->SetLabel(wrapper.GetWrapped());
3439 m_pButtonPreferences->Enable(enabled &&
3441 m_cbEnable->SetValue(enabled);
3444void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3445 m_PluginListPanel->MoveUp(
this);
3448void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3449 m_PluginListPanel->MoveDown(
this);
3454 : wxPanel(parent), m_url(url) {
3455 auto vbox =
new wxBoxSizer(wxVERTICAL);
3456 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3457 button->Enable(strlen(url) > 0);
3460 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3461 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3469PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3471PlugInChartBase::~PlugInChartBase() {}
3480 bool b_allow_overzoom) {
3492 const wxRegion& Region) {
3493 return wxNullBitmap;
3502 wxRegion* pValidRegion) {}
3515 wxRect* pSourceRect) {}
3532 double* plat,
double* plon) {}
3539PlugInChartBaseGL::PlugInChartBaseGL() {}
3541PlugInChartBaseGL::~PlugInChartBaseGL() {}
3545 const wxRegion& Region,
3546 bool b_use_stencil) {
3572PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3574PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3578 const wxRegion& Region,
3579 bool b_use_stencil) {
3585 const wxRegion& Region,
bool b_use_stencil) {
3591 const wxRegion& Region,
bool b_use_stencil) {
3597 return wxNullBitmap;
3601 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3605ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3610wxString PlugInChartBaseExtended::CreateObjDescriptions(
3611 ListOfPI_S57Obj* obj_list) {
3615int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3617int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3619int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3621float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3630PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3632PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3635PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3645PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3647PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3659ChartPlugInWrapper::ChartPlugInWrapper() {}
3661ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3662 m_ppo = ::wxCreateDynamicObject(chart_class);
3666ChartPlugInWrapper::~ChartPlugInWrapper() {
3667 if (m_ppicb)
delete m_ppicb;
3670wxString ChartPlugInWrapper::GetFileSearchMask() {
3677InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3678 ChartInitFlag init_flags) {
3680 wxWindow* pa = wxWindow::FindFocus();
3682 InitReturn ret_val = (InitReturn)m_ppicb->
Init(name, (
int)init_flags);
3686 if (ret_val == INIT_OK) {
3693 m_ID = m_ppicb->
GetID();
3697 m_SE = m_ppicb->
GetSE();
3711 if ((fabs(m_Chart_Skew) < .01) &&
3712 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3714 if (GetChartExtent(&extent)) {
3715 double lon_range = extent.ELON - extent.WLON;
3716 if ((lon_range > 0) &&
3718 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3722 m_overlayENC =
false;
3724 wxCharBuffer buf = m_FullPath.ToUTF8();
3725 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3731 m_ChartType = CHART_TYPE_UNKNOWN;
3732 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3738 if (pc) pc->SetFocus();
3742 return INIT_FAIL_REMOVE;
3746int ChartPlugInWrapper::GetCOVREntries() {
3753int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3760int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3767float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3779int ChartPlugInWrapper::GetNoCOVREntries() {
3789int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3799int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3809float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3819bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3823 pext->NLAT = xpi.
NLAT;
3824 pext->SLAT = xpi.
SLAT;
3825 pext->ELON = xpi.
ELON;
3826 pext->WLON = xpi.
WLON;
3835ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3840 if (!pThumbData->pDIBThumb) {
3841 wxBitmap* pBMPOwnedByChart =
3842 m_ppicb->
GetThumbnail(tnx, tny, m_global_color_scheme);
3843 if (pBMPOwnedByChart) {
3844 wxImage img = pBMPOwnedByChart->ConvertToImage();
3845 pThumbData->pDIBThumb =
new wxBitmap(img);
3847 pThumbData->pDIBThumb = NULL;
3850 pThumbData->Thumb_Size_X = tnx;
3851 pThumbData->Thumb_Size_Y = tny;
3878 pThumbData->ShipX = 0;
3879 pThumbData->ShipY = 0;
3886ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3888bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3892double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3893 bool b_allow_overzoom) {
3900double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3922void RenderRotateToViewPort(
const ViewPort& VPoint) {
3923#ifndef USE_ANDROID_GLES2
3925 glTranslatef(xt, yt, 0);
3926 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3927 glTranslatef(-xt, -yt, 0);
3931void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3932#ifndef USE_ANDROID_GLES2
3934 glTranslatef(xt, yt, 0);
3935 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3936 glTranslatef(-xt, -yt, 0);
3940bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3943 const LLRegion& Region) {
3952 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3953 wxRegion* r = RectRegion.GetNew_wxRegion();
3956 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3957 chart_region.Intersect(Region);
3959 if (!chart_region.Empty()) {
3960 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3962 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3966#ifndef USE_ANDROID_GLES2
3969 RenderRotateToViewPort(VPoint);
3974 glChartCanvas::s_b_useStencil);
3977 glChartCanvas::s_b_useStencil);
3978 UndoRenderRotateToViewPort(VPoint);
3980#ifndef USE_ANDROID_GLES2
3983 glChartCanvas::DisableClipRegion();
3997bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
3998 const wxGLContext& glc,
const ViewPort& VPoint,
3999 const OCPNRegion& RectRegion,
const LLRegion& Region) {
4008 if (!Region.Empty() && ppicb_x) {
4010 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
4011 glChartCanvas::DisableClipRegion();
4014 RenderRotateToViewPort(VPoint);
4017 wxRegion* r = RectRegion.GetNew_wxRegion();
4020 glChartCanvas::s_b_useStencil);
4023 UndoRenderRotateToViewPort(VPoint);
4028 else if (!Region.Empty() &&
4032 wxRegion* r = RectRegion.GetNew_wxRegion();
4035 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4036 chart_region.Intersect(Region);
4038 if (!chart_region.Empty()) {
4039 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4041 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4043 RenderRotateToViewPort(VPoint);
4047 glChartCanvas::s_b_useStencil);
4050 UndoRenderRotateToViewPort(VPoint);
4052 glChartCanvas::DisableClipRegion();
4065bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4072 if (!Region.Empty() && ppicb_x) {
4073 wxRegion* r = Region.GetNew_wxRegion();
4075#ifndef USE_ANDROID_GLES2
4078 RenderRotateToViewPort(VPoint);
4082 glChartCanvas::s_b_useStencil);
4083 UndoRenderRotateToViewPort(VPoint);
4085#ifndef USE_ANDROID_GLES2
4098bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4104 if (Region.IsOk()) {
4105 wxRegion* r = Region.GetNew_wxRegion();
4112 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4113 wxColour nodat_sub = nodat;
4115#ifdef ocpnUSE_ocpnBitmap
4116 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4118 m_pMask =
new wxMask(obmp, nodat_sub);
4119 obmp.SetMask(m_pMask);
4121 dc.SelectObject(obmp);
4132bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4143 if (Region.IsOk() && (pCBx || ppicb)) {
4144 wxRegion* r = Region.GetNew_wxRegion();
4159bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4162 bool ret_val =
false;
4165 if (Region.IsOk()) {
4166 wxRegion* r = Region.GetNew_wxRegion();
4180void ChartPlugInWrapper::ClearPLIBTextList() {
4188bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4192 return m_ppicb->
AdjustVP(pivp_last, pivp_proposed);
4197void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4212void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4216 m_global_color_scheme = cs;
4218 if (pThumbData) pThumbData->pDIBThumb = NULL;
4222 double target_scale_ppm) {
4229void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4230 wxRect* pSourceRect) {
4237double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4239 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4244bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4246 wxCriticalSectionLocker locker(m_critSect);
4255int ChartPlugInWrapper::GetSize_X() {
4262int ChartPlugInWrapper::GetSize_Y() {
4269void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4270 double& pixx,
double& pixy) {
4274void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4275 double* plat,
double* plon) {
4290 return toSDMM(NEflag, a, hi_precision);
4294 return GetGlobalColor(colorName);
4298 const wxString& caption,
int style,
int x,
int y) {
4299 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4307 return g_Platform->GetWritableDocumentsDir();
4312 auto loader = PluginLoader::GetInstance();
4313 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4315 if (pic->m_pplugin == pplugin) {
4325ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4328 ListOfPI_S57Obj* list = NULL;
4342 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4352 ListOfPI_S57Obj* rule_list) {
4363 ret_str = picbx->CreateObjDescriptions(rule_list);
4377 return ps52plib->m_nDepthUnitDisplay;
4384 return ps52plib->m_nSymbolStyle;
4391 return ps52plib->m_nBoundaryStyle;
4401 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4403 ViewPort cvp = CreateCompatibleViewport(*vp);
4408 ObjRazRules rzRules;
4409 rzRules.obj = &cobj;
4410 rzRules.LUP = pContext->LUP;
4411 rzRules.sm_transform_parms = 0;
4412 rzRules.child = NULL;
4413 rzRules.next = NULL;
4415 if (pContext->LUP) {
4416 ps52plib->SetVPointCompat(
4420 ps52plib->PrepareForRender();
4422 return ps52plib->ObjectRenderCheck(&rzRules);
4431 return ps52plib->GetStateHash();
4436void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4437 chart_context* pctx) {
4440 cobj->att_array = pObj->att_array;
4441 cobj->attVal = pObj->attVal;
4442 cobj->n_attr = pObj->n_attr;
4447 cobj->npt = pObj->npt;
4449 cobj->iOBJL = pObj->iOBJL;
4450 cobj->Index = pObj->Index;
4452 cobj->geoPt = (pt*)pObj->geoPt;
4453 cobj->geoPtz = pObj->geoPtz;
4454 cobj->geoPtMulti = pObj->geoPtMulti;
4456 cobj->m_lat = pObj->m_lat;
4457 cobj->m_lon = pObj->m_lon;
4459 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4460 cobj->x_rate = pObj->x_rate;
4461 cobj->y_rate = pObj->y_rate;
4462 cobj->x_origin = pObj->x_origin;
4463 cobj->y_origin = pObj->y_origin;
4465 cobj->Scamin = pObj->Scamin;
4466 cobj->nRef = pObj->nRef;
4467 cobj->bIsAton = pObj->bIsAton;
4468 cobj->bIsAssociable = pObj->bIsAssociable;
4470 cobj->m_n_lsindex = pObj->m_n_lsindex;
4471 cobj->m_lsindex_array = pObj->m_lsindex_array;
4472 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4475 cobj->m_ls_list_legacy =
4479 cobj->m_ls_list_legacy = 0;
4480 cobj->m_ls_list = 0;
4483 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4485 cobj->m_bcategory_mutable =
true;
4489 if (pObj->m_DPRI == -1) {
4491 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4493 cobj->m_DPRI = pObj->m_DPRI;
4496 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4497 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4499 if (pObj->auxParm3 != 1234) {
4500 pObj->auxParm3 = 1234;
4501 pObj->auxParm0 = -99;
4504 cobj->auxParm0 = pObj->auxParm0;
4511 if (pContext->bBBObj_valid)
4513 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4514 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4516 cobj->CSrules = pContext->CSrules;
4517 cobj->bCS_Added = pContext->bCS_Added;
4519 cobj->FText = pContext->FText;
4520 cobj->bFText_Added = pContext->bFText_Added;
4521 cobj->rText = pContext->rText;
4523 cobj->bIsClone =
true;
4526 cobj->m_chart_context = pctx;
4527 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4530 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4531 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4532 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4533 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4534 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4535 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4536 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4537 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4539 cobj->m_chart_context->chart =
4541 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4555 CreateCompatibleS57Object(pObj, &cobj, NULL);
4557 LUPname LUP_Name = PAPER_CHART;
4560 ctx->CSrules = NULL;
4561 ctx->bCS_Added =
false;
4564 if (ctx->bFText_Added) {
4565 ctx->bFText_Added =
false;
4571 ctx->bBBObj_valid =
true;
4576 switch (cobj.Primitive_type) {
4581 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4582 LUP_Name = PAPER_CHART;
4584 LUP_Name = SIMPLIFIED;
4593 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4594 LUP_Name = PLAIN_BOUNDARIES;
4596 LUP_Name = SYMBOLIZED_BOUNDARIES;
4601 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4605 ps52plib->_LUP2rules(lup, &cobj);
4607 ctx->MPSRulesList = NULL;
4615 pContext->bBBObj_valid =
true;
4621void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4622 ObjRazRules* rzRules) {
4626 pContext->CSrules = cobj->CSrules;
4627 pContext->bCS_Added = cobj->bCS_Added;
4629 pContext->FText = cobj->FText;
4630 pContext->bFText_Added = cobj->bFText_Added;
4631 pContext->rText = cobj->rText;
4633 if (cobj->BBObj.GetValid()) {
4636 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4637 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4638 pContext->bBBObj_valid =
true;
4643 pObj->m_DisplayCat = (
PI_DisCat)cobj->m_DisplayCat;
4647 pContext->ChildRazRules = rzRules->child;
4648 pContext->MPSRulesList = rzRules->mps;
4650 pObj->auxParm0 = cobj->auxParm0;
4654 double* lon_min,
double* lon_max) {
4657 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4658 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4659 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4660 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4661 return pContext->bBBObj_valid;
4669 LUPrec* lup = pContext->LUP;
4678 LUPrec* lup = pContext->LUP;
4688 LUPrec* lup = pContext->LUP;
4694 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4701 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4706 ObjRazRules rzRules;
4707 rzRules.obj = &cobj;
4708 rzRules.LUP = pContext->LUP;
4709 rzRules.sm_transform_parms = 0;
4710 rzRules.child = NULL;
4711 rzRules.next = NULL;
4712 rzRules.mps = pContext->MPSRulesList;
4714 if (pContext->LUP) {
4715 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4718 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4724 ps52plib->PrepareForRender();
4725 ps52plib->ClearTextList();
4728 ps52plib->EnableGLLS(
true);
4730 ps52plib->EnableGLLS(
false);
4739 if (pctx->ChildRazRules) {
4740 ObjRazRules* ctop = pctx->ChildRazRules;
4744 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4746 ObjRazRules* cnxx = ctop->next;
4752 if (pctx->MPSRulesList) {
4753 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4754 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4756 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4757 ps52plib->DestroyRulesChain(top);
4759 delete pctx->MPSRulesList->cs_rules;
4761 free(pctx->MPSRulesList);
4773 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4780 &transform.easting_vp_center, &transform.northing_vp_center);
4783 ObjRazRules rzRules;
4784 rzRules.obj = &cobj;
4785 rzRules.LUP = pContext->LUP;
4786 rzRules.sm_transform_parms = &transform;
4787 rzRules.child = pContext->ChildRazRules;
4788 rzRules.next = NULL;
4789 rzRules.mps = pContext->MPSRulesList;
4791 if (pContext->LUP) {
4792 ViewPort cvp = CreateCompatibleViewport(*vp);
4798 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4800 ps52plib->PrepareForRender();
4802 ps52plib->RenderObjectToDC(pdc, &rzRules);
4805 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4812 wxRect rect,
unsigned char* pixbuf) {
4814 render_canvas_parms pb_spec;
4816 pb_spec.depth = BPP;
4817 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4818 pb_spec.lclip = rect.x;
4819 pb_spec.rclip = rect.x + rect.width - 1;
4820 pb_spec.pix_buff = pixbuf;
4821 pb_spec.width = rect.width;
4822 pb_spec.height = rect.height;
4825#ifdef ocpnUSE_ocpnBitmap
4826 pb_spec.b_revrgb =
true;
4828 pb_spec.b_revrgb =
false;
4831 pb_spec.b_revrgb =
false;
4836 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4843 &transform.easting_vp_center, &transform.northing_vp_center);
4846 ObjRazRules rzRules;
4847 rzRules.obj = &cobj;
4848 rzRules.LUP = pContext->LUP;
4849 rzRules.sm_transform_parms = &transform;
4850 rzRules.child = pContext->ChildRazRules;
4851 rzRules.next = NULL;
4852 rzRules.mps = pContext->MPSRulesList;
4854 ViewPort cvp = CreateCompatibleViewport(*vp);
4862 if (!tess)
return 1;
4864 PolyTriGroup* ptg =
new PolyTriGroup;
4865 ptg->tri_prim_head =
4866 tess->Get_PolyTriGroup_head()->tri_prim_head;
4867 ptg->bsingle_alloc =
false;
4868 ptg->data_type = DATA_TYPE_DOUBLE;
4869 tess->Set_PolyTriGroup_head(ptg);
4871 double* pd = (
double*)malloc(
sizeof(
double));
4876 if (pContext->LUP) {
4881 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4883 ps52plib->PrepareForRender();
4885 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4888 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4900 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4911 if (!tess)
return 1;
4915 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4916 ptg->bsingle_alloc =
false;
4917 ptg->data_type = DATA_TYPE_DOUBLE;
4918 tess->Set_PolyTriGroup_head(ptg);
4922 double* pd = (
double*)malloc(
sizeof(
double));
4939 &transform.easting_vp_center, &transform.northing_vp_center);
4942 ObjRazRules rzRules;
4943 rzRules.obj = &cobj;
4944 rzRules.LUP = pContext->LUP;
4945 rzRules.sm_transform_parms = &transform;
4946 rzRules.child = pContext->ChildRazRules;
4947 rzRules.next = NULL;
4948 rzRules.mps = pContext->MPSRulesList;
4950 if (pContext->LUP) {
4951 ViewPort cvp = CreateCompatibleViewport(*vp);
4957 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4959 ps52plib->PrepareForRender();
4961 ps52plib->RenderAreaToGL(glcc, &rzRules);
4964 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4976 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4983 &transform.easting_vp_center, &transform.northing_vp_center);
4986 ObjRazRules rzRules;
4987 rzRules.obj = &cobj;
4988 rzRules.LUP = pContext->LUP;
4989 rzRules.sm_transform_parms = &transform;
4990 rzRules.child = pContext->ChildRazRules;
4991 rzRules.next = NULL;
4992 rzRules.mps = pContext->MPSRulesList;
4994 if (pContext->LUP) {
4995 ViewPort cvp = CreateCompatibleViewport(*vp);
5001 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
5003 ps52plib->PrepareForRender();
5005 ps52plib->RenderObjectToGL(glcc, &rzRules);
5008 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
5018OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
5019 : wxEvent(id, commandType) {
5022 m_b_complete =
false;
5026OCPN_downloadEvent::~OCPN_downloadEvent() {}
5028wxEvent* OCPN_downloadEvent::Clone()
const {
5030 newevent->m_stat = this->m_stat;
5031 newevent->m_condition = this->m_condition;
5033 newevent->m_totalBytes = this->m_totalBytes;
5034 newevent->m_sofarBytes = this->m_sofarBytes;
5035 newevent->m_b_complete = this->m_b_complete;
5041DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5046#define DL_EVENT_TIMER 4388
5054 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5055 void clearBackgroundMode();
5056 void onTimerEvent(wxTimerEvent& event);
5059 wxTimer m_eventTimer;
5060 wxEvtHandler* m_download_evHandler;
5066PI_DLEvtHandler::PI_DLEvtHandler() {
5070 m_download_evHandler = NULL;
5076PI_DLEvtHandler::~PI_DLEvtHandler() {
5077 m_eventTimer.Stop();
5080 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5087 g_download_status =
event.getDLEventStatus();
5088 g_download_condition =
event.getDLEventCondition();
5091 if (m_download_evHandler &&
5094 ev.setComplete(
true);
5095 ev.setTransferred(m_sofarBytes);
5096 ev.setTotal(m_totalBytes);
5098 ev.setDLEventStatus(event.getDLEventStatus());
5101 m_download_evHandler->AddPendingEvent(ev);
5102 m_eventTimer.Stop();
5104 finishAndroidFileDownload();
5111void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5113 m_download_evHandler = handler;
5115 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5119 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5120 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5123void PI_DLEvtHandler::clearBackgroundMode() {
5124 m_download_evHandler = NULL;
5125 m_eventTimer.Stop();
5128void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5134 int stat = queryAndroidFileDownload(m_id, &sstat);
5137 long sofarBytes = 0;
5138 long totalBytes = -1;
5142 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5143 ev.setComplete(
true);
5144 ev.setTransferred(sofarBytes);
5145 ev.setTotal(totalBytes);
5150 wxStringTokenizer tk(sstat,
";");
5151 if (tk.HasMoreTokens()) {
5152 wxString token = tk.GetNextToken();
5153 token.ToLong(&state);
5154 token = tk.GetNextToken();
5155 token.ToLong(&sofarBytes);
5156 token = tk.GetNextToken();
5157 token.ToLong(&totalBytes);
5160 qDebug() << state << sofarBytes << totalBytes;
5162 m_sofarBytes = sofarBytes;
5163 m_totalBytes = totalBytes;
5165 ev.setTransferred(sofarBytes);
5166 ev.setTotal(totalBytes);
5169 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5170 ev.setComplete(
true);
5173 }
else if (state == 8) {
5174 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5175 ev.setComplete(
true);
5179 ev.setComplete(
false);
5187 if (m_download_evHandler) {
5189 m_download_evHandler->AddPendingEvent(ev);
5194 m_eventTimer.Stop();
5195 finishAndroidFileDownload();
5205 const wxString& outputFile,
5206 const wxString& title,
const wxString& message,
5207 const wxBitmap& bitmap, wxWindow* parent,
5208 long style,
int timeout_secs) {
5211 wxString msg =
"Downloading file synchronously: ";
5218 int vres = validateAndroidWriteLocation(outputFile);
5230 g_piEventHandler->Connect(
5231 wxEVT_DOWNLOAD_EVENT,
5232 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5237 wxString fURI = outputFile;
5238 if (!fURI.StartsWith(
"file://")) {
5239 fURI.Prepend(
"file://");
5242 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5245 finishAndroidFileDownload();
5246 g_piEventHandler->Disconnect(
5247 wxEVT_DOWNLOAD_EVENT,
5248 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5253 wxDateTime dl_start_time = wxDateTime::Now();
5257 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5258 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5260 if (dt.GetSeconds() > timeout_secs) {
5261 qDebug() <<
"USER_TIMOUT";
5262 finishAndroidFileDownload();
5263 g_piEventHandler->Disconnect(
5264 wxEVT_DOWNLOAD_EVENT,
5265 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5273 finishAndroidFileDownload();
5274 g_piEventHandler->Disconnect(
5275 wxEVT_DOWNLOAD_EVENT,
5279 qDebug() <<
"RETURN DL_END" << (int)ss;
5285 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5287 qDebug() <<
"Error on queryAndroidFileDownload";
5288 finishAndroidFileDownload();
5289 g_piEventHandler->Disconnect(
5290 wxEVT_DOWNLOAD_EVENT,
5291 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5301#elif defined(OCPN_USE_CURL)
5302 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5303 wxFileOutputStream output(tfn.GetFullPath());
5305 wxCurlDownloadDialog ddlg(url, &output, title, message + url, bitmap, parent,
5307 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5313 case wxCDRF_SUCCESS: {
5314 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5320 case wxCDRF_FAILED: {
5324 case wxCDRF_USER_ABORTED: {
5332 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5342 return ocpn::toUsrDateTimeFormat(date_time,
options);
5347 const wxString& outputFile,
5348 wxEvtHandler* handler,
5351 wxString msg =
"Downloading file asynchronously: ";
5363 int res = startAndroidFileDownload(url, outputFile, NULL ,
5367 finishAndroidFileDownload();
5372 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5374 if (handle) *handle = dl_ID;
5378#elif defined(OCPN_USE_CURL)
5385 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5388 dynamic_cast<wxCurlHTTP*
>(
g_pi_manager->m_pCurl.get())) {
5395 bool failed =
false;
5404 new wxFileOutputStream(outputFile)),
5412 wxCurlThreadError err =
g_pi_manager->m_pCurlThread->Download();
5413 if (err != wxCTE_NO_ERROR) {
5427 delete (
g_pi_manager->m_pCurlThread->GetOutputStream());
5445 cancelAndroidFileDownload(handle);
5446 finishAndroidFileDownload();
5447 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5451 delete (
g_pi_manager->m_pCurlThread->GetOutputStream());
5462 const wxString& parameters, wxString& result,
5465 wxString lparms = parameters;
5466 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5469 result = postResult;
5472#elif defined(OCPN_USE_CURL)
5474 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5475 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5478 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5481 result = wxEmptyString;
5492 return androidCheckOnline();
5495#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5496 if (wxDateTime::GetTimeNow() >
5497 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5499 get.Head(
"http://yahoo.com/");
5500 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5502 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5510#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5511void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5513 if (ev.IsSuccessful()) {
5520 event.setComplete(
true);
5522 if (m_download_evHandler) {
5523 m_download_evHandler->AddPendingEvent(event);
5524 m_download_evHandler = NULL;
5525 m_downloadHandle = NULL;
5528 if (m_pCurlThread) {
5529 m_pCurlThread->Wait();
5530 if (!m_pCurlThread->IsAborting()) {
5531 delete (m_pCurlThread->GetOutputStream());
5532 wxDELETE(m_pCurlThread);
5537void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5541 event.setTotal(ev.GetTotalBytes());
5542 event.setTransferred(ev.GetDownloadedBytes());
5543 event.setComplete(
false);
5545 if (m_download_evHandler) {
5546 m_download_evHandler->AddPendingEvent(event);
5550bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5551 wxCurlBaseThread* p,
5552 const wxString& url) {
5554 case wxCTE_NO_ERROR:
5557 case wxCTE_NO_RESOURCE:
5559 wxS(
"Insufficient resources for correct execution of the program."));
5562 case wxCTE_ALREADY_RUNNING:
5566 case wxCTE_INVALID_PROTOCOL:
5567 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5571 case wxCTE_NO_VALID_STREAM:
5578 case wxCTE_CURL_ERROR: {
5579 wxString ws = wxS(
"unknown");
5580 if (p->GetCurlSession())
5582 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5583 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5588 if (p->IsAlive()) p->Abort();
AisDecoder * g_pAIS
Global instance.
Class AisDecoder and helpers.
Plugin catalog settings dialog.
Plugin catalog management: Build the runtime catalog, handling downloads as required.
General chart base definitions.
ChartDB * ChartData
Global instance.
Charts database management
Basic chart info storage.
Generic Chart canvas base.
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.
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.
NMEA0183 basic parsing common parts:
const std::vector< DriverPtr > & GetDrivers() const
Wrapper for configuration variables which lives in a wxBaseConfig object.
void Notify() override
Notify all listeners, no data supplied.
Wrapper for global variable, supports notification events when value changes.
Downloader with progress and final message dialogs.
Interface implemented by classes which listens.
The raw message layer, a singleton.
static NavAddr::Bus GetBusByKey(const std::string &key)
Return bus corresponding to given key.
An iterator class for OCPNRegion.
A wrapper class for wxRegion with additional functionality.
Define an action to be performed when a KeyProvider is notified.
void Init(const KeyProvider &kp, const 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.
std::string Key() const
sort key.
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.
KeyProvider wrapper for a plain key string.
std::string GetKey() const override
Get the Key object from the Key Provider.
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.
void SetBoxes()
Computes the bounding box coordinates for the current viewport.
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.
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 in standard DC mode for multi-canvas support.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex)
Renders plugin overlay graphics in OpenGL mode for multi-canvas support.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex, int priority)
Renders plugin overlay graphics in OpenGL mode with priority control.
virtual bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvas_ix, int priority)
Renders plugin overlay graphics in standard DC mode with priority control.
virtual bool RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in standard DC mode for single canvas.
virtual bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in OpenGL mode for single canvas.
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 wxString GetCommonName()
Get the plugin's common (short) name.
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.
wxColour GetDialogColor(DialogColor color)
Retrieves a dialog color based on its role in the application's dialogs.
@ DLG_SELECTED_ACCENT
Accent color for selected items.
@ DLG_SELECTED_BACKGROUND
Background color for selected items.
@ DLG_UNSELECTED_ACCENT
Accent color for unselected items.
@ DLG_UNSELECTED_BACKGROUND
Background color for unselected items.
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.
Variables maintained by comm stack, read-only access for others.
double g_display_size_mm
Physical display width (mm)
Global variables stored in configuration file.
Generic GUI downloads tool.
Handle downloading of files from remote urls.
OpenGL chart rendering canvas.
GSHHS Chart Object (Global Self-consistent, Hierarchical, High-resolution Shoreline) Derived from htt...
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
JSON event definition used in internal communications to/from plugins.
Enhanced logging interface on top of wx/log.h.
Multiplexer class and helpers.
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.
std::vector< std::string > split(const char *token_string, const std::string &delimiter)
Return vector of items in s separated by delimiter.
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.
MyConfig * pConfig
Global instance.
Navigation Utility Functions without GUI dependencies.
Notify()/Listen() configuration variable wrapper.
Global variables Listen()/Notify() wrapper.
Optimized wxBitmap Object.
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
Color schemes for different lighting conditions.
#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.
Layer to use wxDC or opengl.
options * g_options
Global instance.
Downloaded plugins cache.
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.
wxString toSDMM_PlugIn(int NEflag, double a, bool hi_precision)
Convert decimal degrees to a formatted string.
bool PI_GetObjectRenderBox(PI_S57Obj *pObj, double *lat_min, double *lat_max, double *lon_min, double *lon_max)
Gets geographic bounding box of S57 object.
void PI_PLIBFreeContext(void *pContext)
Frees S52 PLIB context.
_OCPN_DLStatus OCPN_postDataHttp(const wxString &url, const wxString ¶meters, wxString &result, int timeout_secs)
Performs HTTP POST request.
int PI_GetPLIBSymbolStyle()
Gets configured S52 symbol style.
void OCPN_cancelDownloadFileBackground(long handle)
Cancels a background download.
wxString GetPlugInPath(opencpn_plugin *pplugin)
Gets the installation path for a specific plugin.
int PI_GetPLIBStateHash()
Gets hash value representing current PLIB state.
int PI_PLIBRenderAreaToDC(wxDC *pdc, PI_S57Obj *pObj, PlugIn_ViewPort *vp, wxRect rect, unsigned char *pixbuf)
Renders an S57 area object using standard device context.
wxColour GetBaseGlobalColor(wxString colorName)
Gets a global system color.
wxString PI_GetPLIBColorScheme()
Gets current color scheme used by S52 PLIB.
double PI_GetPLIBMarinerSafetyContour()
Gets configured safety contour depth.
bool PI_PLIBObjectRenderCheck(PI_S57Obj *pObj, PlugIn_ViewPort *vp)
Checks if object should be rendered.
PlugInManager * g_pi_manager
Global instance.
std::vector< const PlugInData * > GetInstalled()
Return sorted list of all installed plugins.
int PI_GetPLIBDepthUnitInt()
Gets configured depth unit for S52 display.
bool PI_PLIBSetContext(PI_S57Obj *pObj)
Sets S52 PLIB rendering context for an object.
void PI_PLIBSetLineFeaturePriority(PI_S57Obj *pObj, int prio)
Sets rendering priority for line feature.
void PI_PLIBPrepareForNewRender()
Prepares PLIB for new rendering pass.
PI_DisCat PI_GetObjectDisplayCategory(PI_S57Obj *pObj)
Gets display category for object.
PI_LUPname PI_GetObjectLUPName(PI_S57Obj *pObj)
Gets Look-Up Table (LUP) name for object.
int OCPNMessageBox_PlugIn(wxWindow *parent, const wxString &message, const wxString &caption, int style, int x, int y)
Shows a message box dialog.
int PI_PLIBRenderObjectToGL(const wxGLContext &glcc, PI_S57Obj *pObj, PlugIn_ViewPort *vp, wxRect &render_rect)
Renders any S57 object using OpenGL.
int PI_PLIBRenderAreaToGL(const wxGLContext &glcc, PI_S57Obj *pObj, PlugIn_ViewPort *vp, wxRect &render_rect)
Renders an S57 area object using OpenGL.
_OCPN_DLStatus OCPN_downloadFileBackground(const wxString &url, const wxString &outputFile, wxEvtHandler *handler, long *handle)
Asynchronously downloads a file in the background.
wxString toUsrDateTimeFormat_Plugin(const wxDateTime date_time, const DateTimeFormatOptions &options)
Format a date/time to a localized string representation, conforming to the global date/time format an...
int PI_PLIBRenderObjectToDC(wxDC *pdc, PI_S57Obj *pObj, PlugIn_ViewPort *vp)
Renders an S57 object using standard device context.
void PI_UpdateContext(PI_S57Obj *pObj)
Updates rendering context for S57 object.
wxString GetOCPN_ExePath()
Gets OpenCPN executable path.
_OCPN_DLStatus OCPN_downloadFile(const wxString &url, const wxString &outputFile, const wxString &title, const wxString &message, const wxBitmap &bitmap, wxWindow *parent, long style, int timeout_secs)
Synchronously download a file with progress dialog.
wxString * GetpPlugInLocation()
Gets plugins directory location.
int PI_GetPLIBBoundaryStyle()
Gets configured S52 boundary style.
bool OCPN_isOnline()
Checks internet connectivity.
void PI_PLIBSetRenderCaps(unsigned int flags)
Sets rendering capability flags.
PI_DisPrio PI_GetObjectDisplayPriority(PI_S57Obj *pObj)
Gets display priority for object.
wxString GetWritableDocumentsDir()
Returns the platform-specific default documents directory.
PlugInManager and helper classes – Mostly gui parts (dialogs) and plugin API stuff.
PlugInManager * g_pi_manager
Global instance.
Routeman * g_pRouteMan
Global instance.
Safe mode non-gui handling.
Selected route, segment, waypoint, etc.
Semantic version encode/decode object.
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.
wxBitmap LoadSVG(const wxString filename, const unsigned int width, const unsigned int height, wxBitmap *default_bitmap, bool use_cache)
Load SVG file and return it's bitmap representation of requested size In case file can't be loaded an...
Abstract gFrame/MyFrame interface.
Recorded track abstraction.
WaypointMan drawing stuff.