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_frame, -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);
1162 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1165 if (pttc->m_pplugin == pic->m_pplugin) {
1166 m_PlugInToolbarTools.Remove(pttc);
1172 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1174 if (pimis->m_pplugin == pic->m_pplugin) {
1175 m_PlugInMenuItems.Remove(pimis);
1181bool PlugInManager::IsAnyPlugInChartEnabled() {
1184 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1185 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1187 if (pic->m_enabled && pic->m_init_state) {
1196void PlugInManager::UpdateManagedPlugins() {
1198 PluginLoader::GetInstance()->
SortPlugins(ComparePlugins);
1201 g_options->itemBoxSizerPanelPlugins->Layout();
1204bool PlugInManager::UpDateChartDataTypes() {
1208 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1209 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1212 if (pic->m_init_state) {
1220 if (bret)
ChartData->UpdateChartClassDescriptorArray();
1225void PlugInManager::FinalizePluginLoadall() {
1229 SetColorSchemeForAllPlugIns(global_color_scheme);
1232 SendBaseConfigToAllPlugIns();
1233 SendS52ConfigToAllPlugIns(
true);
1234 SendSKConfigToAllPlugIns();
1239 top_frame::Get()->SendGlJsonConfigMsg();
1247void PlugInManager::SetPluginOrder(wxString serialized_names) {
1248 m_plugin_order.Empty();
1249 wxStringTokenizer tokenizer(serialized_names,
";");
1250 while (tokenizer.HasMoreTokens()) {
1251 m_plugin_order.Add(tokenizer.GetNextToken());
1255wxString PlugInManager::GetPluginOrder() {
1256 wxString plugins = wxEmptyString;
1257 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1258 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1259 plugins.Append(plugin_array->Item(i)->m_common_name);
1260 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1265bool PlugInManager::UpdateConfig() {
1269 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1270 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1274 wxString config_section = (_T (
"/PlugIns/" ));
1276 pConfig->SetPath(config_section);
1277 pConfig->Write(_T (
"bEnabled" ), pic->m_enabled);
1284void PlugInManager::ShowDeferredBlacklistMessages() {
1285 m_blacklist_ui->show_deferred_messages();
1288bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1290 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1293bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin* plugin) {
1298 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1299 name.Replace(
"class ", wxEmptyString);
1301 const std::type_info& ti =
typeid(*plugin);
1303 char* realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1304 wxString name = wxString::FromAscii(realname);
1307 return CheckBlacklistedPlugin(name, major, minor);
1310bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
1312 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1313 if (block_status == plug_status::unblocked)
return true;
1314 plug_data data(name.ToStdString(), major, minor);
1315 auto msg = m_blacklist->get_message(block_status, data);
1316 m_blacklist_ui->message(msg);
1320bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC& dc,
1324 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1325 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1327 if (pic->m_enabled && pic->m_init_state) {
1331 wxDC* pdc = dc.GetDC();
1334 switch (pic->m_api_version) {
1336 if (priority > 0)
break;
1343 if (priority > 0)
break;
1346 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1357 if (priority > 0)
break;
1360 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1365 if (priority > 0)
break;
1369 ppi->RenderOverlay(*pdc, &pivp);
1381 if (priority <= 0) {
1385 ppi->RenderOverlay(*pdc, &pivp);
1401 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1403 if ((m_cached_overlay_bm.GetWidth() != vp.
pix_width) ||
1404 (m_cached_overlay_bm.GetHeight() != vp.
pix_height))
1408 mdc.SelectObject(m_cached_overlay_bm);
1409 mdc.SetBackground(*wxBLACK_BRUSH);
1412 bool b_rendered =
false;
1414 switch (pic->m_api_version) {
1416 if (priority > 0)
break;
1423 if (priority > 0)
break;
1426 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1437 if (priority > 0)
break;
1440 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1445 if (priority > 0)
break;
1449 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1462 if (priority <= 0) {
1466 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1473 mdc, &pivp, g_canvasConfig, priority);
1482 mdc.SelectObject(wxNullBitmap);
1485 wxMask* p_msk =
new wxMask(m_cached_overlay_bm, wxColour(0, 0, 0));
1486 m_cached_overlay_bm.SetMask(p_msk);
1488 dc.DrawBitmap(m_cached_overlay_bm, 0, 0,
true);
1491 }
else if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1499bool PlugInManager::RenderAllGLCanvasOverlayPlugIns(wxGLContext* pcontext,
1503 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1504 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1506 if (pic->m_enabled && pic->m_init_state) {
1507 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1510 switch (pic->m_api_version) {
1512 if (priority > 0)
break;
1515 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
1527 if (priority > 0)
break;
1535 if (priority > 0)
break;
1552 if (priority <= 0) {
1577void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort& vp) {
1578 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1579 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1581 if (pic->m_enabled && pic->m_init_state) {
1590void NotifySetupOptionsPlugin(
const PlugInData* pd) {
1591 PluginLoader::GetInstance()->NotifySetupOptionsPlugin(pd);
1594void PlugInManager::NotifySetupOptions() {
1595 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1596 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1598 NotifySetupOptionsPlugin(pic);
1603 int ok_apply_cancel) {
1604 if (pic->m_enabled && pic->m_init_state) {
1607 auto loader = PluginLoader::GetInstance();
1614void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
1615 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1616 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1619 ClosePlugInPanel(pic, ok_apply_cancel);
1624int PlugInManager::AddCanvasContextMenuItemPIM(wxMenuItem* pitem,
1629 pmic->pmenu_item = pitem;
1630 pmic->m_pplugin = pplugin;
1631 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
1632 : m_plugin_menu_item_id_next;
1634 pmic->b_grey =
false;
1635 pmic->m_in_menu = name;
1636 pmic->extended = is_extended;
1638 m_PlugInMenuItems.Add(pmic);
1640 m_plugin_menu_item_id_next++;
1645void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char* name) {
1646 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1649 if (pimis->id == item) {
1650 m_PlugInMenuItems.Remove(pimis);
1658void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
1660 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1663 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1671void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
1673 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1676 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1677 pimis->b_grey = grey;
1684void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
1685 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1686 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1688 if (pic->m_enabled && pic->m_init_state)
1693void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
1694 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1695 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1697 if (pic->m_enabled && pic->m_init_state)
1702void PlugInManager::PrepareAllPluginContextMenus() {
1703 int canvasIndex = top_frame::Get()->GetCanvasIndexUnderMouse();
1704 if (canvasIndex < 0)
return;
1706 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1707 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1709 if (pic->m_enabled && pic->m_init_state) {
1711 switch (pic->m_api_version) {
1731void PlugInManager::SendSKConfigToAllPlugIns() {
1734 v[
"self"] = g_ownshipMMSI_SK;
1738 SendMessageToAllPlugins(wxString(
"OCPN_CORE_SIGNALK"), out);
1741void PlugInManager::SendBaseConfigToAllPlugIns() {
1744 v[
"OpenCPN Version Major"] = VERSION_MAJOR;
1745 v[
"OpenCPN Version Minor"] = VERSION_MINOR;
1746 v[
"OpenCPN Version Patch"] = VERSION_PATCH;
1747 v[
"OpenCPN Version Date"] = VERSION_DATE;
1748 v[
"OpenCPN Version Full"] = VERSION_FULL;
1752 v[
"OpenCPN Toolbar Width"] =
g_MainToolbar->GetToolbarRect().width;
1753 v[
"OpenCPN Toolbar Height"] =
g_MainToolbar->GetToolbarRect().height;
1754 v[
"OpenCPN Toolbar PosnX"] =
g_MainToolbar->GetToolbarRect().x;
1755 v[
"OpenCPN Toolbar PosnY"] =
g_MainToolbar->GetToolbarRect().y;
1759 v[
"OpenCPN Zoom Mod Vector"] = g_chart_zoom_modifier_vector;
1760 v[
"OpenCPN Zoom Mod Other"] = g_chart_zoom_modifier_raster;
1761 v[
"OpenCPN Scale Factor Exp"] =
1762 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1770 SendMessageToAllPlugins(wxString(
"OpenCPN Config"), out);
1773void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1776 v[
"OpenCPN Version Major"] = VERSION_MAJOR;
1777 v[
"OpenCPN Version Minor"] = VERSION_MINOR;
1778 v[
"OpenCPN Version Patch"] = VERSION_PATCH;
1779 v[
"OpenCPN Version Date"] = VERSION_DATE;
1780 v[
"OpenCPN Version Full"] = VERSION_FULL;
1788 v[
"OpenCPN S52PLIB ShowAnchorConditions"] = ps52plib->GetAnchorOn();
1789 v[
"OpenCPN S52PLIB ShowQualityOfData"] = ps52plib->GetQualityOfData();
1794 v[
"OpenCPN S52PLIB MetaDisplay"] = ps52plib->m_bShowMeta;
1795 v[
"OpenCPN S52PLIB DeclutterText"] = ps52plib->m_bDeClutterText;
1796 v[
"OpenCPN S52PLIB ShowNationalText"] = ps52plib->m_bShowNationalTexts;
1797 v[
"OpenCPN S52PLIB ShowImportantTextOnly"] =
1798 ps52plib->m_bShowS57ImportantTextOnly;
1799 v[
"OpenCPN S52PLIB UseSCAMIN"] = ps52plib->m_bUseSCAMIN;
1800 v[
"OpenCPN S52PLIB UseSUPER_SCAMIN"] = ps52plib->m_bUseSUPER_SCAMIN;
1801 v[
"OpenCPN S52PLIB SymbolStyle"] = ps52plib->m_nSymbolStyle;
1802 v[
"OpenCPN S52PLIB BoundaryStyle"] = ps52plib->m_nBoundaryStyle;
1803 v[
"OpenCPN S52PLIB ColorShades"] = S52_getMarinerParam(S52_MAR_TWO_SHADES);
1804 v[
"OpenCPN S52PLIB Safety Depth"] =
1805 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1806 v[
"OpenCPN S52PLIB Shallow Contour"] =
1807 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1808 v[
"OpenCPN S52PLIB Deep Contour"] =
1809 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1813 v[
"OpenCPN S52PLIB GlobalReconfig"] = bReconfig;
1818 SendMessageToAllPlugins(wxString(
"OpenCPN Config"), out);
1821void PlugInManager::NotifyAuiPlugIns() {
1822 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1823 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1825 if (pic->m_enabled && pic->m_init_state &&
1831int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1832 wxBitmap* bmpRollover, wxItemKind kind,
1833 wxString shortHelp, wxString longHelp,
1834 wxObject* clientData,
int position,
1837 pttc->label = label;
1839 if (!bitmap->IsOk()) {
1841 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1844 pttc->bitmap_day =
new wxBitmap(*bitmap);
1845 pttc->bitmap_day->UnShare();
1848 if (!bmpRollover->IsOk()) {
1850 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1853 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1854 pttc->bitmap_Rollover_day->UnShare();
1857 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1858 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1859 pttc->bitmap_Rollover_dusk =
1860 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1861 pttc->bitmap_Rollover_night =
1862 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1865 pttc->shortHelp = shortHelp;
1866 pttc->longHelp = longHelp;
1867 pttc->clientData = clientData;
1868 pttc->position = position;
1869 pttc->m_pplugin = pplugin;
1870 pttc->tool_sel = tool_sel;
1872 pttc->b_toggle =
false;
1873 pttc->id = m_plugin_tool_id_next;
1875 m_PlugInToolbarTools.Add(pttc);
1877 m_plugin_tool_id_next++;
1882int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1883 wxString SVGRolloverfile,
1884 wxString SVGToggledfile, wxItemKind kind,
1885 wxString shortHelp, wxString longHelp,
1886 wxObject* clientData,
int position,
1889 pttc->label = label;
1891 pttc->pluginNormalIconSVG = SVGfile;
1892 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1893 pttc->pluginToggledIconSVG = SVGToggledfile;
1898 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1899 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1900 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1901 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1902 pttc->bitmap_Rollover_dusk =
1903 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1904 pttc->bitmap_Rollover_night =
1905 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1908 pttc->shortHelp = shortHelp;
1909 pttc->longHelp = longHelp;
1910 pttc->clientData = clientData;
1911 pttc->position = position;
1912 pttc->m_pplugin = pplugin;
1913 pttc->tool_sel = tool_sel;
1915 pttc->b_toggle =
false;
1916 pttc->id = m_plugin_tool_id_next;
1918 m_PlugInToolbarTools.Add(pttc);
1920 m_plugin_tool_id_next++;
1925void PlugInManager::RemoveToolbarTool(
int tool_id) {
1926 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1929 if (pttc->id == tool_id) {
1930 m_PlugInToolbarTools.Remove(pttc);
1936 m_parent->RequestNewToolbars();
1939void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1940 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1943 if (pttc->id == item) {
1945 m_parent->RequestNewToolbars();
1952void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1953 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1956 if (pttc->id == item) {
1957 pttc->b_toggle = toggle;
1958 m_parent->SetMasterToolbarItemState(item, toggle);
1965void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1966 wxBitmap* bmpRollover) {
1967 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1970 if (pttc->id == item) {
1971 delete pttc->bitmap_day;
1972 delete pttc->bitmap_dusk;
1973 delete pttc->bitmap_night;
1974 delete pttc->bitmap_Rollover_day;
1976 if (!bitmap->IsOk()) {
1978 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1981 pttc->bitmap_day =
new wxBitmap(*bitmap);
1982 pttc->bitmap_day->UnShare();
1985 if (!bmpRollover->IsOk()) {
1987 pttc->bitmap_Rollover_day =
1988 new wxBitmap(style->GetIcon(
"default_pi"));
1991 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1992 pttc->bitmap_Rollover_day->UnShare();
1995 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1996 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1998 m_parent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
1999 pttc->bitmap_Rollover_day);
2006void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2007 wxString SVGfileRollover,
2008 wxString SVGfileToggled) {
2009 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2012 if (pttc->id == item) {
2013 pttc->pluginNormalIconSVG = SVGfile;
2014 pttc->pluginRolloverIconSVG = SVGfileRollover;
2015 pttc->pluginToggledIconSVG = SVGfileToggled;
2016 m_parent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2017 pttc->pluginRolloverIconSVG,
2018 pttc->pluginToggledIconSVG);
2026 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2028 if (
id == pc->id)
return pc->m_pplugin;
2034wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2037 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2038 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2040 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2044 return wxEmptyString;
2047wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2049wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2050 unsigned char dim_ratio) {
2051 wxImage img_dup = pbmp_normal->ConvertToImage();
2053 if (!img_dup.IsOk())
return NULL;
2055 if (dim_ratio < 200) {
2057 int gimg_width = img_dup.GetWidth();
2058 int gimg_height = img_dup.GetHeight();
2060 double factor = (double)(dim_ratio) / 256.0;
2062 for (
int iy = 0; iy < gimg_height; iy++) {
2063 for (
int ix = 0; ix < gimg_width; ix++) {
2064 if (!img_dup.IsTransparent(ix, iy)) {
2065 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2066 img_dup.GetGreen(ix, iy),
2067 img_dup.GetBlue(ix, iy));
2068 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2069 hsv.value = hsv.value * factor;
2070 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2071 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2077 wxBitmap* ptoolBarBitmap;
2080 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2082 dwxdc.SelectObject(tbmp);
2084 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2086 ptoolBarBitmap =
new wxBitmap(img_dup);
2090 return ptoolBarBitmap;
2093wxArrayString PlugInManager::GetPlugInChartClassNameArray() {
2094 wxArrayString array;
2095 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2096 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2098 if (pic && pic->m_enabled && pic->m_init_state &&
2103 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2104 array.Add(carray[j]);
2112 while (j < array.GetCount()) {
2113 wxString test = array[j];
2114 unsigned int k = j + 1;
2115 while (k < array.GetCount()) {
2116 if (test == array[k]) {
2131 const wxString& ChartClassName) {
2133 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2134 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2136 if (pic && pic->m_enabled && pic->m_init_state &&
2141 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2142 if (carray[j].IsSameAs(ChartClassName)) {
2143 plugin = pic->m_pplugin;
2157#define DISABLED_SETTINGS_MSG \
2158 _("These settings might destabilize OpenCPN and are by default disabled." \
2159 " To despite the dangers enable them manually add a CatalogExpert=1" \
2160 " line in the [PlugIns] section in the configuration file.")
2165CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2166 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2168 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2171 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2173 wxStaticBox* itemStaticBoxSizer4Static =
2174 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2175 wxStaticBoxSizer* itemStaticBoxSizer4 =
2176 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2177 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2181 m_catalogText =
new wxStaticText(
this, wxID_STATIC,
"");
2182 itemStaticBoxSizer4->Add(m_catalogText,
2183 wxSizerFlags().Border().Proportion(1));
2184 m_catalogText->SetLabel(GetCatalogText(
false));
2187 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2188 itemStaticBoxSizer4->Add(rowSizer2,
2189 wxSizerFlags().Expand().Border().Proportion(1));
2191 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2192 wxDefaultPosition, wxDefaultSize, 0);
2193 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2194 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2195 &CatalogMgrPanel::OnUpdateButton,
this);
2196 rowSizer2->AddSpacer(4 * GetCharWidth());
2197 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2198 wxDefaultPosition, wxDefaultSize, 0);
2199 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2200 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2201 &CatalogMgrPanel::OnTarballButton,
this);
2203 rowSizer2->AddSpacer(4 * GetCharWidth());
2204 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2205 wxDefaultPosition, wxDefaultSize, 0);
2207 if (expert.Get(
false)) {
2208 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2209 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2211 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2212 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2215 rowSizer2->AddSpacer(4 * GetCharWidth());
2216 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2218 SetUpdateButtonLabel();
2221 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2222 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2224 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2228 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2229 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2230 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2233 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2235 if (!expert.Get(
false)) {
2237 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2238 wxDefaultPosition, wxDefaultSize, 0);
2239 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2240 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2241 &CatalogMgrPanel::OnUpdateButton,
this);
2242 SetUpdateButtonLabel();
2243 m_tarballButton = NULL;
2244 m_adv_button = NULL;
2247 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2248 itemStaticBoxSizer4->Add(m_catalogText,
2249 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2252 m_updateButton =
new wxButton(
2253 this, wxID_ANY,
"Update Plugin Catalog:master ",
2254 wxDefaultPosition, wxDefaultSize, 0);
2255 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2256 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2257 &CatalogMgrPanel::OnUpdateButton,
this);
2258 SetUpdateButtonLabel();
2261 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2262 wxDefaultPosition, wxDefaultSize, 0);
2263 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2265 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2266 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2269 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2270 wxDefaultPosition, wxDefaultSize, 0);
2271 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2272 2 * GetCharWidth());
2273 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2274 &CatalogMgrPanel::OnTarballButton,
this);
2280CatalogMgrPanel::~CatalogMgrPanel() {
2281 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2282 &CatalogMgrPanel::OnUpdateButton,
this);
2283 if (m_tarballButton)
2284 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2285 &CatalogMgrPanel::OnTarballButton,
this);
2288static const char*
const DOWNLOAD_REPO_PROTO =
2289 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2292void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2294 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2295 std::string url(g_catalog_custom_url);
2296 if (catalog !=
"custom") {
2297 url = std::string(DOWNLOAD_REPO_PROTO);
2301 std::string filePath =
2302 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2304 auto catalogHdlr = CatalogHandler::GetInstance();
2306 g_Platform->ShowBusySpinner();
2307 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2308 g_Platform->HideBusySpinner();
2310 std::string message;
2311 if (status != CatalogHandler::ServerStatus::OK) {
2312 message = _(
"Cannot download data from url");
2313 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2314 wxICON_ERROR | wxOK);
2320 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2322 wxFileName::GetPathSeparator() +
2323 "ocpn-plugins.xml")) {
2324 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2325 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2330 if (!wxCopyFile(wxString(filePath.c_str()),
2332 wxFileName::GetPathSeparator() +
"ocpn-plugins.xml")) {
2333 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2334 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2340 if (catalog ==
"master") {
2342 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2343 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2349 pConfig->SetPath(
"/PlugIns/");
2350 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2357 pluginHandler->setMetadata(
"");
2361 auto cataloghdlr = CatalogHandler::GetInstance();
2362 cataloghdlr->ClearCatalogData();
2365 LoadAllPlugIns(
false);
2369 m_catalogText->SetLabel(GetCatalogText(
true));
2372 OCPNMessageBox(
this, _(
"Catalog update successful"),
2373 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2376void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2380 androidDisableRotation();
2383 dialog->ShowModal();
2386 androidEnableRotation();
2390void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2393 int response = g_Platform->DoFileSelectorDialog(
2394 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2395 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2397 if (response != wxID_OK) {
2402 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2406 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2407 _(
"OpenCPN Plugin Import Error"));
2411 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2412 _(
"OpenCPN Plugin Import Error"));
2413 handler->Uninstall(metadata.name);
2416 UninstallPlugin(metadata.name);
2417 ok = handler->InstallPlugin(metadata, path.ToStdString());
2419 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2420 _(
"OpenCPN Plugin Import Error"));
2423 metadata.is_imported =
true;
2425 std::ofstream file(metadata_path);
2428 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2429 <<
" for imported plugin: " << metadata.name;
2431 LoadAllPlugIns(
false,
true);
2434 wxString ws(_(
"Plugin"));
2435 ws += metadata.name + _(
" successfully imported");
2436 OCPNMessageBox(wxTheApp->GetTopWindow(), ws, _(
"Installation complete"),
2437 wxICON_INFORMATION | wxOK | wxCENTRE);
2440wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2442 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2446 pConfig->SetPath(
"/PlugIns/");
2447 wxString latestCatalog =
pConfig->Read(
"LatestCatalogDownloaded",
"default");
2448 catalog += latestCatalog;
2454 std::string date = pluginHandler->GetCatalogData()->date;
2456 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2457 if (!updated) catalog +=
" : " + _(
"Please Update Plugin Catalog.");
2463void CatalogMgrPanel::SetUpdateButtonLabel() {
2464 wxString label = _(
"Update Plugin Catalog");
2466 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2467 m_updateButton->SetLabel(label);
2471wxString CatalogMgrPanel::GetImportInitDir() {
2473 pConfig->SetPath(
"/PlugIns/");
2474 wxString lastImportDir;
2476 pConfig->Read(
"LatestImportDir", g_Platform->GetWritableDocumentsDir());
2477 if (wxDirExists(lastImportDir)) {
2478 return lastImportDir;
2480 return (g_Platform->GetWritableDocumentsDir());
2489 const wxPoint& pos, const wxSize& size)
2490 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2491 m_PluginSelected(0) {
2492 m_is_loading.clear();
2493 SetSizer(
new wxBoxSizer(wxVERTICAL));
2494 ReloadPluginPanels();
2497void PluginListPanel::SelectByName(wxString& name) {
2498 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2499 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2501 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2502 pluginPanel->SetSelected(
true);
2503 pluginPanel->Layout();
2504 SelectPlugin(pluginPanel);
2513 std::vector<const PlugInData*> result;
2514 auto loader = PluginLoader::GetInstance();
2515 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2516 auto const item = loader->GetPlugInArray()->Item(i);
2517 if (item->m_managed_metadata.name.empty()) {
2518 const auto name = item->m_common_name.ToStdString();
2522 result.push_back(item);
2525 std::string slhs, srhs;
2526 for (
auto& cl : lhs->
Key()) slhs += toupper(cl);
2527 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2528 return slhs.compare(srhs) < 0;
2530 std::sort(result.begin(), result.end(), compare);
2535static bool IsPluginLoaded(
const std::string& name) {
2536 if (safe_mode::get_mode()) {
2539 std::find(installed.begin(), installed.end(),
ocpn::tolower(name));
2540 return found != installed.end();
2543 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2544 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2551 if (m_is_loading.test_and_set()) {
2553 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2558 m_PluginItems.Clear();
2560 wxWindowList kids = GetChildren();
2561 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2562 wxWindowListNode* node = kids.Item(i);
2563 wxWindow* win = node->GetData();
2565 if (pp) win->Destroy();
2567 GetSizer()->Clear();
2570 m_PluginSelected = 0;
2572 if (safe_mode::get_mode()) {
2575 for (
const auto& name : installed) AddPlugin(name);
2578 auto available = getCompatiblePlugins();
2582 return IsPluginLoaded(md.name);
2584 auto end = std::remove_if(available.begin(), available.end(), predicate);
2585 available.erase(end, available.end());
2591 std::string slhs, srhs;
2592 for (
auto& cl : lhs.name) slhs += toupper(cl);
2593 for (
auto& cr : rhs.name) srhs += toupper(cr);
2594 return slhs.compare(srhs) < 0;
2598 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2599 for (
const auto& p : available) unique_sorted_entries.insert(p);
2605 if (p->m_enabled) AddPlugin(*p);
2609 if (!p->m_enabled) AddPlugin(*p);
2612 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2620 m_is_loading.clear();
2623void PluginListPanel::AddPlugin(
const std::string& name) {
2626 panel->SetSelected(
false);
2627 GetSizer()->Add(panel, 0, wxEXPAND);
2628 m_PluginItems.Add(panel);
2629 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2630 GetSizer()->AddSpacer(m_pluginSpacer);
2633void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2635 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2636 pPluginPanel->SetSelected(
false);
2637 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2638 m_PluginItems.Add(pPluginPanel);
2640 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2641 GetSizer()->AddSpacer(m_pluginSpacer);
2654int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2655 wxBoxSizer* sizer) {
2657 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2658 auto panel = plugins.Item(i);
2659 bool was_selected = panel->GetSelected();
2660 panel->SetSelected(
false);
2662 wxSize unselected = panel->GetSize();
2664 panel->SetSelected(
true);
2666 wxSize selected = panel->GetSize();
2668 int dy = selected.GetHeight() - unselected.GetHeight();
2669 max_dy = wxMax(max_dy, dy);
2670 panel->SetSelected(was_selected);
2675PluginListPanel::~PluginListPanel() {}
2677void PluginListPanel::UpdateSelections() {
2678 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2681 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2686void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2688 GetViewStart(&xs, &ys);
2691 if (m_PluginSelected) {
2692 m_PluginSelected->SetSelected(
false);
2693 m_PluginSelected->Layout();
2696 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2698 m_PluginSelected = pi;
2700 GetSizer()->Layout();
2702 wxSize size = GetBestVirtualSize();
2703 SetVirtualSize(size);
2708 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2710 int yd = pPluginPanel->GetSize().y;
2712 htop += m_pluginSpacer;
2713 if (pPluginPanel == pi) {
2714 int piBottom = htop - (ys *
g_options->GetScrollRate());
2715 if (piBottom > GetClientSize().y) {
2716 ys += (piBottom - GetClientSize().y) /
g_options->GetScrollRate();
2726 int pos = m_PluginItems.Index(pi);
2729 m_PluginItems.RemoveAt(pos);
2732 m_PluginItems.Insert(pi, pos - 1);
2733 wxStaticLine* itemStaticLine =
new wxStaticLine(
2734 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2739 m_PluginSelected = pi;
2741 GetSizer()->Layout();
2747 int pos = m_PluginItems.Index(pi);
2748 if (pos == (
int)m_PluginItems.Count() -
2751 m_PluginItems.RemoveAt(pos);
2754 m_PluginItems.Insert(pi, pos + 1);
2755 wxStaticLine* itemStaticLine =
new wxStaticLine(
2756 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2761 m_PluginSelected = pi;
2763 GetSizer()->Layout();
2768static bool canUninstall(std::string name) {
2773 if (plugin.name == name) {
2774 if (safe_mode::get_mode())
2777 return !plugin.readonly;
2784 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2786 m_is_safe_panel(true) {
2788 wxASSERT(m_PluginListPanel != 0);
2789 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2790 SetSizer(top_sizer);
2791 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2792 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2794 double iconSize = GetCharWidth() * 4;
2796 int icon_scale = iconSize * dpi_mult;
2798 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2799 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2800 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2802 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2803 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2804 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2805 top_horizontal->Add(m_pVersion);
2808 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2809 top_horizontal->Add(m_pButtons);
2810 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2811 top_horizontal->Add(m_info_btn);
2812 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2813 wxDefaultPosition, wxDefaultSize, 0);
2814 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2816 auto uninstall = [&](wxCommandEvent ev) {
2817 auto n = m_pName->GetLabel().ToStdString();
2818 int result = OCPNMessageBox(
2819 wxTheApp->GetTopWindow(), std::string(_(
"Uninstall plugin ")) + n +
"?",
2820 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2821 if (result != wxID_OK)
return;
2825 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2829EVT_PAINT(PluginPanel::OnPaint)
2834 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2836 m_is_safe_panel(false) {
2839 wxASSERT(m_PluginListPanel != 0);
2841 m_bSelected =
false;
2842 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2843 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2845 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2848 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2849 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2850 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2851 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2853 double iconSize = GetCharWidth() * 4;
2855 int icon_scale = iconSize * dpi_mult;
2857 wxImage plugin_icon;
2859 if (m_plugin.m_bitmap.IsOk()) {
2860 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2863 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2864 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2865 path.AppendDir(
"uidata");
2866 path.AppendDir(
"traditional");
2867 bitmap =
LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2868 }
else if (plugin_icon.IsOk()) {
2869 int nowSize = plugin_icon.GetWidth();
2870 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2871 bitmap = wxBitmap(plugin_icon);
2873 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2875 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2877 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2878 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2880 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2883 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2884 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2887 int nChars =
g_options->GetSize().x / GetCharWidth();
2888 bool bCompact =
false;
2894 wxString nameString = m_plugin.m_common_name;
2898 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2899 if (nameWidth > maxWidth) {
2900 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2901 wxELLIPSIZE_END, maxWidth);
2903 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2904 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2905 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2906 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2908 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2909 sl1->AddGrowableCol(1);
2910 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2912 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"X.YY.ZZ.AA");
2913 sl1->Add(m_pVersion, 0, wxALL, 5);
2914 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2917 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2918 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2920 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2921 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2922 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2925 wxString descriptionString = m_plugin.m_short_description;
2926 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2927 int descriptionWidth;
2928 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2929 if (descriptionWidth > maxDescriptionWidth)
2931 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2932 wxELLIPSIZE_END, maxDescriptionWidth);
2937 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2938 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2939 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2940 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2941 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2944 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2945 itemBoxSizer03->AddGrowableCol(2);
2946 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2948 wxString nameString = m_plugin.m_common_name;
2949 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2950 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2951 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2955 wxFont font = GetFont();
2956 font.SetWeight(wxFONTWEIGHT_BOLD);
2957 m_pName->SetFont(font);
2960 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2962 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"X.YY.ZZ.AA");
2963 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2964 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2967 !m_plugin.m_managed_metadata.is_orphan)) {
2970 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2971 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2973 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2974 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2975 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2977 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2979 m_pDescription =
new wxStaticText(
2980 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2982 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2983 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2984 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2988 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2990 itemBoxSizer02->Add(m_info_btn, 0);
2992 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2993 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2994 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2995 wxDefaultPosition, wxDefaultSize, 0);
2996 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
2998 m_pButtons->AddSpacer(3 * GetCharWidth());
3001 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3002 wxDefaultPosition, wxDefaultSize, 0);
3003 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3005 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3006 wxDefaultPosition, wxDefaultSize, 0);
3007 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3009 m_pButtons =
new wxBoxSizer(wxVERTICAL);
3010 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
3012 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
3013 m_pButtons->Add(tline, 0, wxALL, 2);
3015 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
3016 wxDefaultPosition, wxDefaultSize, 0);
3017 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
3019 tline->AddSpacer(3 * GetCharWidth());
3021 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
3023 tline->Add(m_info_btn, 0);
3026 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3027 wxDefaultPosition, wxDefaultSize);
3028 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3030 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3031 wxDefaultPosition, wxDefaultSize, 0);
3032 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3035 wxBitmap statusBitmap;
3036 const auto stat = m_plugin.m_status;
3037 auto icon_name = icon_by_status.at(stat);
3038 if (stat == PluginStatus::Imported &&
3039 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3041 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3044 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3045 path.AppendDir(
"uidata");
3046 path.AppendDir(
"traditional");
3048 int bmsize = GetCharWidth() * 3 * dpi_mult;
3049 if (path.IsFileReadable()) {
3050 statusBitmap =
LoadSVG(path.GetFullPath(), bmsize, bmsize);
3051 ok = statusBitmap.IsOk();
3054 auto style = g_StyleManager->GetCurrentStyle();
3055 statusBitmap = wxBitmap(style->GetIcon(
"default_pi", bmsize, bmsize));
3056 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3059 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3060 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3061 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3063 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3066 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3068 itemBoxSizer02->AddSpacer(GetCharWidth());
3070 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3071 &PluginPanel::OnPluginPreferences,
this);
3072 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3073 &PluginPanel::OnPluginUninstall,
this);
3074 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3075 &PluginPanel::OnPluginAction,
this);
3077 SetSelected(m_bSelected);
3078 SetAutoLayout(
true);
3086PluginPanel::~PluginPanel() {
3087 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3088 if (m_is_safe_panel)
return;
3089 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3091 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3092 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3093 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3094 if (m_pButtonAction) {
3095 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3096 &PluginPanel::OnPluginAction,
this);
3098 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3099 &PluginPanel::OnPluginPreferences,
this);
3100 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3101 &PluginPanel::OnPluginEnableToggle,
this);
3104void PluginPanel::SetActionLabel(wxString& label) {
3105 m_pButtonAction->SetLabel(label);
3109static wxStopWatch swclick;
3110static int downx, downy;
3112void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3115 event.GetPosition(&downx, &downy);
3121void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3123 qDebug() << swclick.Time();
3124 if (swclick.Time() < 200) {
3126 event.GetPosition(&upx, &upy);
3127 if ((fabs(upx - downx) < GetCharWidth()) &&
3128 (fabs(upy - downy) < GetCharWidth())) {
3136void PluginPanel::DoPluginSelect() {
3137 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3143 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3144 }
else if (m_bSelected) {
3146 m_PluginListPanel->SelectPlugin(NULL);
3149 m_PluginListPanel->SelectPlugin(
this);
3157static PluginMetadata GetMetadataByName(
const std::string& name) {
3159 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3160 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3161 if (found == plugins.end()) {
3162 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3167void PluginPanel::SetSelected(
bool selected) {
3168 m_bSelected = selected;
3170 m_pVersion->SetLabel(
3174 m_pButtons->Show(
true);
3175 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3178 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3181 unInstallPossible =
false;
3184 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3186 m_pButtonUninstall->Show(unInstallPossible);
3188 if (m_plugin.m_managed_metadata.info_url.size()) {
3189 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3193 m_cbEnable->Show(
true);
3198 switch (m_plugin.m_status) {
3199 case PluginStatus::LegacyUpdateAvailable:
3200 label = _(
"Upgrade to Version ");
3201 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3202 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3203 m_pButtonAction->Enable();
3206 case PluginStatus::ManagedInstallAvailable:
3207 label = _(
"Install...");
3208 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3209 m_pButtonAction->Enable();
3212 case PluginStatus::ManagedInstalledUpdateAvailable:
3213 label = _(
"Update to ");
3214 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3215 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3216 m_pButtonAction->Enable();
3219 case PluginStatus::ManagedInstalledCurrentVersion:
3220 label = _(
"Reinstall");
3221 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3222 m_pButtonAction->Enable();
3225 case PluginStatus::ManagedInstalledDowngradeAvailable:
3226 label = _(
"Downgrade");
3227 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3228 m_pButtonAction->Enable();
3231 case PluginStatus::Imported:
3232 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3233 label = _(
"Update");
3234 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3236 m_pButtonAction->Hide();
3237 m_action = ActionVerb::NOP;
3242 m_action = ActionVerb::NOP;
3243 m_pButtonAction->Hide();
3247 m_action = ActionVerb::NOP;
3248 m_pButtonAction->Hide();
3253 m_action = ActionVerb::NOP;
3256 SetActionLabel(label);
3268 m_pButtons->Show(
false);
3271 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3272 m_cbEnable->Show(
false);
3293 SetEnabled(m_plugin.m_enabled);
3308void PluginPanel::OnPaint(wxPaintEvent& event) {
3311 int penWidth = m_penWidthUnselected;
3316 penWidth = m_penWidthSelected;
3321 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3323 dc.SetPen(wxPen(border, penWidth));
3325 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3328void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3329 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3332 androidDisableRotation();
3343void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3344 g_Platform->ShowBusySpinner();
3345 SetEnabled(event.IsChecked());
3346 m_pVersion->SetLabel(
3353 g_Platform->HideBusySpinner();
3356void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3357 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
3360 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3361 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3362 actionEvent.SetClientData(
this);
3363 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3366void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3368 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3369 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3370 actionEvent.SetClientData(
this);
3371 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3376static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3377 auto font = window->GetFont();
3378 font.SetStyle(style);
3379 window->SetFont(font);
3382void PluginPanel::SetEnabled(
bool enabled) {
3383 if (m_is_safe_panel)
return;
3386 if (enabled) NotifySetupOptionsPlugin(&m_plugin);
3387 if (!enabled && !m_bSelected) {
3388 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3389 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3390 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3393 m_pVersion->Disable();
3394 m_pDescription->Disable();
3397 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3398 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3399 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3402 m_pVersion->Enable();
3403 m_pDescription->Enable();
3408 m_pName->Enable(enabled || m_bSelected);
3409 m_pVersion->Enable(enabled || m_bSelected);
3410 m_pDescription->Enable(enabled || m_bSelected);
3414 wxString description = m_plugin.m_long_description;
3415 if (description.IsEmpty())
3416 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3420 m_pDescription->SetLabel(wrapper.GetWrapped());
3421 if (m_plugin.m_managed_metadata.info_url.size()) {
3422 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3426 wxString description = m_plugin.m_short_description;
3427 if (description.IsEmpty())
3428 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3431 m_pDescription->SetLabel(wrapper.GetWrapped());
3434 m_pButtonPreferences->Enable(enabled &&
3436 m_cbEnable->SetValue(enabled);
3439void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3440 m_PluginListPanel->MoveUp(
this);
3443void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3444 m_PluginListPanel->MoveDown(
this);
3449 : wxPanel(parent), m_url(url) {
3450 auto vbox =
new wxBoxSizer(wxVERTICAL);
3451 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3452 button->Enable(strlen(url) > 0);
3455 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3456 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3464PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3466PlugInChartBase::~PlugInChartBase() {}
3475 bool b_allow_overzoom) {
3487 const wxRegion& Region) {
3488 return wxNullBitmap;
3497 wxRegion* pValidRegion) {}
3510 wxRect* pSourceRect) {}
3527 double* plat,
double* plon) {}
3534PlugInChartBaseGL::PlugInChartBaseGL() {}
3536PlugInChartBaseGL::~PlugInChartBaseGL() {}
3540 const wxRegion& Region,
3541 bool b_use_stencil) {
3567PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3569PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3573 const wxRegion& Region,
3574 bool b_use_stencil) {
3580 const wxRegion& Region,
bool b_use_stencil) {
3586 const wxRegion& Region,
bool b_use_stencil) {
3592 return wxNullBitmap;
3596 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3600ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3605wxString PlugInChartBaseExtended::CreateObjDescriptions(
3606 ListOfPI_S57Obj* obj_list) {
3610int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3612int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3614int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3616float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3625PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3627PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3630PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3640PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3642PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3654ChartPlugInWrapper::ChartPlugInWrapper() {}
3656ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3657 m_ppo = ::wxCreateDynamicObject(chart_class);
3661ChartPlugInWrapper::~ChartPlugInWrapper() {
3662 if (m_ppicb)
delete m_ppicb;
3665wxString ChartPlugInWrapper::GetFileSearchMask() {
3672InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3673 ChartInitFlag init_flags) {
3675 wxWindow* pa = wxWindow::FindFocus();
3677 InitReturn ret_val = (InitReturn)m_ppicb->
Init(name, (
int)init_flags);
3681 if (ret_val == INIT_OK) {
3688 m_ID = m_ppicb->
GetID();
3692 m_SE = m_ppicb->
GetSE();
3706 if ((fabs(m_Chart_Skew) < .01) &&
3707 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3709 if (GetChartExtent(&extent)) {
3710 double lon_range = extent.ELON - extent.WLON;
3711 if ((lon_range > 0) &&
3713 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3717 m_overlayENC =
false;
3719 wxCharBuffer buf = m_FullPath.ToUTF8();
3720 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3726 m_ChartType = CHART_TYPE_UNKNOWN;
3727 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3733 if (pc) pc->SetFocus();
3737 return INIT_FAIL_REMOVE;
3741int ChartPlugInWrapper::GetCOVREntries() {
3748int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3755int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3762float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3774int ChartPlugInWrapper::GetNoCOVREntries() {
3784int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3794int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3804float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3814bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3818 pext->NLAT = xpi.
NLAT;
3819 pext->SLAT = xpi.
SLAT;
3820 pext->ELON = xpi.
ELON;
3821 pext->WLON = xpi.
WLON;
3830ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3835 if (!pThumbData->pDIBThumb) {
3836 wxBitmap* pBMPOwnedByChart =
3837 m_ppicb->
GetThumbnail(tnx, tny, m_global_color_scheme);
3838 if (pBMPOwnedByChart) {
3839 wxImage img = pBMPOwnedByChart->ConvertToImage();
3840 pThumbData->pDIBThumb =
new wxBitmap(img);
3842 pThumbData->pDIBThumb = NULL;
3845 pThumbData->Thumb_Size_X = tnx;
3846 pThumbData->Thumb_Size_Y = tny;
3873 pThumbData->ShipX = 0;
3874 pThumbData->ShipY = 0;
3881ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3883bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3887double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3888 bool b_allow_overzoom) {
3895double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3917void RenderRotateToViewPort(
const ViewPort& VPoint) {
3918#ifndef USE_ANDROID_GLES2
3920 glTranslatef(xt, yt, 0);
3921 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3922 glTranslatef(-xt, -yt, 0);
3926void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3927#ifndef USE_ANDROID_GLES2
3929 glTranslatef(xt, yt, 0);
3930 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3931 glTranslatef(-xt, -yt, 0);
3935bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3938 const LLRegion& Region) {
3947 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3948 wxRegion* r = RectRegion.GetNew_wxRegion();
3951 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3952 chart_region.Intersect(Region);
3954 if (!chart_region.Empty()) {
3955 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3957 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3961#ifndef USE_ANDROID_GLES2
3964 RenderRotateToViewPort(VPoint);
3969 glChartCanvas::s_b_useStencil);
3972 glChartCanvas::s_b_useStencil);
3973 UndoRenderRotateToViewPort(VPoint);
3975#ifndef USE_ANDROID_GLES2
3978 glChartCanvas::DisableClipRegion();
3992bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
3993 const wxGLContext& glc,
const ViewPort& VPoint,
3994 const OCPNRegion& RectRegion,
const LLRegion& Region) {
4003 if (!Region.Empty() && ppicb_x) {
4005 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
4006 glChartCanvas::DisableClipRegion();
4009 RenderRotateToViewPort(VPoint);
4012 wxRegion* r = RectRegion.GetNew_wxRegion();
4015 glChartCanvas::s_b_useStencil);
4018 UndoRenderRotateToViewPort(VPoint);
4023 else if (!Region.Empty() &&
4027 wxRegion* r = RectRegion.GetNew_wxRegion();
4030 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4031 chart_region.Intersect(Region);
4033 if (!chart_region.Empty()) {
4034 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4036 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4038 RenderRotateToViewPort(VPoint);
4042 glChartCanvas::s_b_useStencil);
4045 UndoRenderRotateToViewPort(VPoint);
4047 glChartCanvas::DisableClipRegion();
4060bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4067 if (!Region.Empty() && ppicb_x) {
4068 wxRegion* r = Region.GetNew_wxRegion();
4070#ifndef USE_ANDROID_GLES2
4073 RenderRotateToViewPort(VPoint);
4077 glChartCanvas::s_b_useStencil);
4078 UndoRenderRotateToViewPort(VPoint);
4080#ifndef USE_ANDROID_GLES2
4093bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4099 if (Region.IsOk()) {
4100 wxRegion* r = Region.GetNew_wxRegion();
4107 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4108 wxColour nodat_sub = nodat;
4110#ifdef ocpnUSE_ocpnBitmap
4111 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4113 m_pMask =
new wxMask(obmp, nodat_sub);
4114 obmp.SetMask(m_pMask);
4116 dc.SelectObject(obmp);
4127bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4138 if (Region.IsOk() && (pCBx || ppicb)) {
4139 wxRegion* r = Region.GetNew_wxRegion();
4154bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4157 bool ret_val =
false;
4160 if (Region.IsOk()) {
4161 wxRegion* r = Region.GetNew_wxRegion();
4175void ChartPlugInWrapper::ClearPLIBTextList() {
4183bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4187 return m_ppicb->
AdjustVP(pivp_last, pivp_proposed);
4192void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4207void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4211 m_global_color_scheme = cs;
4213 if (pThumbData) pThumbData->pDIBThumb = NULL;
4217 double target_scale_ppm) {
4224void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4225 wxRect* pSourceRect) {
4232double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4234 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4239bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4241 wxCriticalSectionLocker locker(m_critSect);
4250int ChartPlugInWrapper::GetSize_X() {
4257int ChartPlugInWrapper::GetSize_Y() {
4264void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4265 double& pixx,
double& pixy) {
4269void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4270 double* plat,
double* plon) {
4285 return toSDMM(NEflag, a, hi_precision);
4289 return GetGlobalColor(colorName);
4293 const wxString& caption,
int style,
int x,
int y) {
4294 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4302 return g_Platform->GetWritableDocumentsDir();
4307 auto loader = PluginLoader::GetInstance();
4308 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4310 if (pic->m_pplugin == pplugin) {
4320ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4323 ListOfPI_S57Obj* list = NULL;
4337 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4347 ListOfPI_S57Obj* rule_list) {
4358 ret_str = picbx->CreateObjDescriptions(rule_list);
4372 return ps52plib->m_nDepthUnitDisplay;
4379 return ps52plib->m_nSymbolStyle;
4386 return ps52plib->m_nBoundaryStyle;
4396 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4398 ViewPort cvp = CreateCompatibleViewport(*vp);
4403 ObjRazRules rzRules;
4404 rzRules.obj = &cobj;
4405 rzRules.LUP = pContext->LUP;
4406 rzRules.sm_transform_parms = 0;
4407 rzRules.child = NULL;
4408 rzRules.next = NULL;
4410 if (pContext->LUP) {
4411 ps52plib->SetVPointCompat(
4415 ps52plib->PrepareForRender();
4417 return ps52plib->ObjectRenderCheck(&rzRules);
4426 return ps52plib->GetStateHash();
4431void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4432 chart_context* pctx) {
4435 cobj->att_array = pObj->att_array;
4436 cobj->attVal = pObj->attVal;
4437 cobj->n_attr = pObj->n_attr;
4442 cobj->npt = pObj->npt;
4444 cobj->iOBJL = pObj->iOBJL;
4445 cobj->Index = pObj->Index;
4447 cobj->geoPt = (pt*)pObj->geoPt;
4448 cobj->geoPtz = pObj->geoPtz;
4449 cobj->geoPtMulti = pObj->geoPtMulti;
4451 cobj->m_lat = pObj->m_lat;
4452 cobj->m_lon = pObj->m_lon;
4454 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4455 cobj->x_rate = pObj->x_rate;
4456 cobj->y_rate = pObj->y_rate;
4457 cobj->x_origin = pObj->x_origin;
4458 cobj->y_origin = pObj->y_origin;
4460 cobj->Scamin = pObj->Scamin;
4461 cobj->nRef = pObj->nRef;
4462 cobj->bIsAton = pObj->bIsAton;
4463 cobj->bIsAssociable = pObj->bIsAssociable;
4465 cobj->m_n_lsindex = pObj->m_n_lsindex;
4466 cobj->m_lsindex_array = pObj->m_lsindex_array;
4467 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4470 cobj->m_ls_list_legacy =
4474 cobj->m_ls_list_legacy = 0;
4475 cobj->m_ls_list = 0;
4478 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4480 cobj->m_bcategory_mutable =
true;
4484 if (pObj->m_DPRI == -1) {
4486 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4488 cobj->m_DPRI = pObj->m_DPRI;
4491 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4492 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4494 if (pObj->auxParm3 != 1234) {
4495 pObj->auxParm3 = 1234;
4496 pObj->auxParm0 = -99;
4499 cobj->auxParm0 = pObj->auxParm0;
4506 if (pContext->bBBObj_valid)
4508 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4509 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4511 cobj->CSrules = pContext->CSrules;
4512 cobj->bCS_Added = pContext->bCS_Added;
4514 cobj->FText = pContext->FText;
4515 cobj->bFText_Added = pContext->bFText_Added;
4516 cobj->rText = pContext->rText;
4518 cobj->bIsClone =
true;
4521 cobj->m_chart_context = pctx;
4522 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4525 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4526 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4527 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4528 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4529 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4530 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4531 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4532 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4534 cobj->m_chart_context->chart =
4536 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4550 CreateCompatibleS57Object(pObj, &cobj, NULL);
4552 LUPname LUP_Name = PAPER_CHART;
4555 ctx->CSrules = NULL;
4556 ctx->bCS_Added =
false;
4559 if (ctx->bFText_Added) {
4560 ctx->bFText_Added =
false;
4566 ctx->bBBObj_valid =
true;
4571 switch (cobj.Primitive_type) {
4576 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4577 LUP_Name = PAPER_CHART;
4579 LUP_Name = SIMPLIFIED;
4588 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4589 LUP_Name = PLAIN_BOUNDARIES;
4591 LUP_Name = SYMBOLIZED_BOUNDARIES;
4596 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4600 ps52plib->_LUP2rules(lup, &cobj);
4602 ctx->MPSRulesList = NULL;
4610 pContext->bBBObj_valid =
true;
4616void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4617 ObjRazRules* rzRules) {
4621 pContext->CSrules = cobj->CSrules;
4622 pContext->bCS_Added = cobj->bCS_Added;
4624 pContext->FText = cobj->FText;
4625 pContext->bFText_Added = cobj->bFText_Added;
4626 pContext->rText = cobj->rText;
4628 if (cobj->BBObj.GetValid()) {
4631 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4632 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4633 pContext->bBBObj_valid =
true;
4638 pObj->m_DisplayCat = (
PI_DisCat)cobj->m_DisplayCat;
4642 pContext->ChildRazRules = rzRules->child;
4643 pContext->MPSRulesList = rzRules->mps;
4645 pObj->auxParm0 = cobj->auxParm0;
4649 double* lon_min,
double* lon_max) {
4652 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4653 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4654 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4655 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4656 return pContext->bBBObj_valid;
4664 LUPrec* lup = pContext->LUP;
4673 LUPrec* lup = pContext->LUP;
4683 LUPrec* lup = pContext->LUP;
4689 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4696 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4701 ObjRazRules rzRules;
4702 rzRules.obj = &cobj;
4703 rzRules.LUP = pContext->LUP;
4704 rzRules.sm_transform_parms = 0;
4705 rzRules.child = NULL;
4706 rzRules.next = NULL;
4707 rzRules.mps = pContext->MPSRulesList;
4709 if (pContext->LUP) {
4710 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4713 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4719 ps52plib->PrepareForRender();
4720 ps52plib->ClearTextList();
4723 ps52plib->EnableGLLS(
true);
4725 ps52plib->EnableGLLS(
false);
4734 if (pctx->ChildRazRules) {
4735 ObjRazRules* ctop = pctx->ChildRazRules;
4739 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4741 ObjRazRules* cnxx = ctop->next;
4747 if (pctx->MPSRulesList) {
4748 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4749 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4751 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4752 ps52plib->DestroyRulesChain(top);
4754 delete pctx->MPSRulesList->cs_rules;
4756 free(pctx->MPSRulesList);
4768 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4775 &transform.easting_vp_center, &transform.northing_vp_center);
4778 ObjRazRules rzRules;
4779 rzRules.obj = &cobj;
4780 rzRules.LUP = pContext->LUP;
4781 rzRules.sm_transform_parms = &transform;
4782 rzRules.child = pContext->ChildRazRules;
4783 rzRules.next = NULL;
4784 rzRules.mps = pContext->MPSRulesList;
4786 if (pContext->LUP) {
4787 ViewPort cvp = CreateCompatibleViewport(*vp);
4793 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4795 ps52plib->PrepareForRender();
4797 ps52plib->RenderObjectToDC(pdc, &rzRules);
4800 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4807 wxRect rect,
unsigned char* pixbuf) {
4809 render_canvas_parms pb_spec;
4811 pb_spec.depth = BPP;
4812 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4813 pb_spec.lclip = rect.x;
4814 pb_spec.rclip = rect.x + rect.width - 1;
4815 pb_spec.pix_buff = pixbuf;
4816 pb_spec.width = rect.width;
4817 pb_spec.height = rect.height;
4820#ifdef ocpnUSE_ocpnBitmap
4821 pb_spec.b_revrgb =
true;
4823 pb_spec.b_revrgb =
false;
4826 pb_spec.b_revrgb =
false;
4831 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4838 &transform.easting_vp_center, &transform.northing_vp_center);
4841 ObjRazRules rzRules;
4842 rzRules.obj = &cobj;
4843 rzRules.LUP = pContext->LUP;
4844 rzRules.sm_transform_parms = &transform;
4845 rzRules.child = pContext->ChildRazRules;
4846 rzRules.next = NULL;
4847 rzRules.mps = pContext->MPSRulesList;
4849 ViewPort cvp = CreateCompatibleViewport(*vp);
4857 if (!tess)
return 1;
4859 PolyTriGroup* ptg =
new PolyTriGroup;
4860 ptg->tri_prim_head =
4861 tess->Get_PolyTriGroup_head()->tri_prim_head;
4862 ptg->bsingle_alloc =
false;
4863 ptg->data_type = DATA_TYPE_DOUBLE;
4864 tess->Set_PolyTriGroup_head(ptg);
4866 double* pd = (
double*)malloc(
sizeof(
double));
4871 if (pContext->LUP) {
4876 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4878 ps52plib->PrepareForRender();
4880 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4883 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4895 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4906 if (!tess)
return 1;
4910 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4911 ptg->bsingle_alloc =
false;
4912 ptg->data_type = DATA_TYPE_DOUBLE;
4913 tess->Set_PolyTriGroup_head(ptg);
4917 double* pd = (
double*)malloc(
sizeof(
double));
4934 &transform.easting_vp_center, &transform.northing_vp_center);
4937 ObjRazRules rzRules;
4938 rzRules.obj = &cobj;
4939 rzRules.LUP = pContext->LUP;
4940 rzRules.sm_transform_parms = &transform;
4941 rzRules.child = pContext->ChildRazRules;
4942 rzRules.next = NULL;
4943 rzRules.mps = pContext->MPSRulesList;
4945 if (pContext->LUP) {
4946 ViewPort cvp = CreateCompatibleViewport(*vp);
4952 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4954 ps52plib->PrepareForRender();
4956 ps52plib->RenderAreaToGL(glcc, &rzRules);
4959 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4971 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4978 &transform.easting_vp_center, &transform.northing_vp_center);
4981 ObjRazRules rzRules;
4982 rzRules.obj = &cobj;
4983 rzRules.LUP = pContext->LUP;
4984 rzRules.sm_transform_parms = &transform;
4985 rzRules.child = pContext->ChildRazRules;
4986 rzRules.next = NULL;
4987 rzRules.mps = pContext->MPSRulesList;
4989 if (pContext->LUP) {
4990 ViewPort cvp = CreateCompatibleViewport(*vp);
4996 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4998 ps52plib->PrepareForRender();
5000 ps52plib->RenderObjectToGL(glcc, &rzRules);
5003 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
5013OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
5014 : wxEvent(id, commandType) {
5017 m_b_complete =
false;
5021OCPN_downloadEvent::~OCPN_downloadEvent() {}
5023wxEvent* OCPN_downloadEvent::Clone()
const {
5025 newevent->m_stat = this->m_stat;
5026 newevent->m_condition = this->m_condition;
5028 newevent->m_totalBytes = this->m_totalBytes;
5029 newevent->m_sofarBytes = this->m_sofarBytes;
5030 newevent->m_b_complete = this->m_b_complete;
5036DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5041#define DL_EVENT_TIMER 4388
5049 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5050 void clearBackgroundMode();
5051 void onTimerEvent(wxTimerEvent& event);
5054 wxTimer m_eventTimer;
5055 wxEvtHandler* m_download_evHandler;
5061PI_DLEvtHandler::PI_DLEvtHandler() {
5065 m_download_evHandler = NULL;
5071PI_DLEvtHandler::~PI_DLEvtHandler() {
5072 m_eventTimer.Stop();
5075 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5082 g_download_status =
event.getDLEventStatus();
5083 g_download_condition =
event.getDLEventCondition();
5086 if (m_download_evHandler &&
5089 ev.setComplete(
true);
5090 ev.setTransferred(m_sofarBytes);
5091 ev.setTotal(m_totalBytes);
5093 ev.setDLEventStatus(event.getDLEventStatus());
5096 m_download_evHandler->AddPendingEvent(ev);
5097 m_eventTimer.Stop();
5099 finishAndroidFileDownload();
5106void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5108 m_download_evHandler = handler;
5110 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5114 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5115 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5118void PI_DLEvtHandler::clearBackgroundMode() {
5119 m_download_evHandler = NULL;
5120 m_eventTimer.Stop();
5123void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5129 int stat = queryAndroidFileDownload(m_id, &sstat);
5132 long sofarBytes = 0;
5133 long totalBytes = -1;
5137 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5138 ev.setComplete(
true);
5139 ev.setTransferred(sofarBytes);
5140 ev.setTotal(totalBytes);
5145 wxStringTokenizer tk(sstat,
";");
5146 if (tk.HasMoreTokens()) {
5147 wxString token = tk.GetNextToken();
5148 token.ToLong(&state);
5149 token = tk.GetNextToken();
5150 token.ToLong(&sofarBytes);
5151 token = tk.GetNextToken();
5152 token.ToLong(&totalBytes);
5155 qDebug() << state << sofarBytes << totalBytes;
5157 m_sofarBytes = sofarBytes;
5158 m_totalBytes = totalBytes;
5160 ev.setTransferred(sofarBytes);
5161 ev.setTotal(totalBytes);
5164 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5165 ev.setComplete(
true);
5168 }
else if (state == 8) {
5169 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5170 ev.setComplete(
true);
5174 ev.setComplete(
false);
5182 if (m_download_evHandler) {
5184 m_download_evHandler->AddPendingEvent(ev);
5189 m_eventTimer.Stop();
5190 finishAndroidFileDownload();
5200 const wxString& outputFile,
5201 const wxString& title,
const wxString& message,
5202 const wxBitmap& bitmap, wxWindow* parent,
5203 long style,
int timeout_secs) {
5206 wxString msg =
"Downloading file synchronously: ";
5213 int vres = validateAndroidWriteLocation(outputFile);
5225 g_piEventHandler->Connect(
5226 wxEVT_DOWNLOAD_EVENT,
5227 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5232 wxString fURI = outputFile;
5233 if (!fURI.StartsWith(
"file://")) {
5234 fURI.Prepend(
"file://");
5237 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5240 finishAndroidFileDownload();
5241 g_piEventHandler->Disconnect(
5242 wxEVT_DOWNLOAD_EVENT,
5243 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5248 wxDateTime dl_start_time = wxDateTime::Now();
5252 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5253 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5255 if (dt.GetSeconds() > timeout_secs) {
5256 qDebug() <<
"USER_TIMOUT";
5257 finishAndroidFileDownload();
5258 g_piEventHandler->Disconnect(
5259 wxEVT_DOWNLOAD_EVENT,
5260 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5268 finishAndroidFileDownload();
5269 g_piEventHandler->Disconnect(
5270 wxEVT_DOWNLOAD_EVENT,
5274 qDebug() <<
"RETURN DL_END" << (int)ss;
5280 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5282 qDebug() <<
"Error on queryAndroidFileDownload";
5283 finishAndroidFileDownload();
5284 g_piEventHandler->Disconnect(
5285 wxEVT_DOWNLOAD_EVENT,
5286 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5296#elif defined(OCPN_USE_CURL)
5297 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5298 wxFileOutputStream output(tfn.GetFullPath());
5300 wxCurlDownloadDialog ddlg(url, &output, title, message + url, bitmap, parent,
5302 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5308 case wxCDRF_SUCCESS: {
5309 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5315 case wxCDRF_FAILED: {
5319 case wxCDRF_USER_ABORTED: {
5327 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5337 return ocpn::toUsrDateTimeFormat(date_time,
options);
5342 const wxString& outputFile,
5343 wxEvtHandler* handler,
5346 wxString msg =
"Downloading file asynchronously: ";
5358 int res = startAndroidFileDownload(url, outputFile, NULL ,
5362 finishAndroidFileDownload();
5367 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5369 if (handle) *handle = dl_ID;
5373#elif defined(OCPN_USE_CURL)
5380 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5383 dynamic_cast<wxCurlHTTP*
>(
g_pi_manager->m_pCurl.get())) {
5390 bool failed =
false;
5399 new wxFileOutputStream(outputFile)),
5407 wxCurlThreadError err =
g_pi_manager->m_pCurlThread->Download();
5408 if (err != wxCTE_NO_ERROR) {
5422 delete (
g_pi_manager->m_pCurlThread->GetOutputStream());
5440 cancelAndroidFileDownload(handle);
5441 finishAndroidFileDownload();
5442 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5446 delete (
g_pi_manager->m_pCurlThread->GetOutputStream());
5457 const wxString& parameters, wxString& result,
5460 wxString lparms = parameters;
5461 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5464 result = postResult;
5467#elif defined(OCPN_USE_CURL)
5469 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5470 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5473 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5476 result = wxEmptyString;
5487 return androidCheckOnline();
5490#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5491 if (wxDateTime::GetTimeNow() >
5492 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5494 get.Head(
"http://yahoo.com/");
5495 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5497 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5505#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5506void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5508 if (ev.IsSuccessful()) {
5515 event.setComplete(
true);
5517 if (m_download_evHandler) {
5518 m_download_evHandler->AddPendingEvent(event);
5519 m_download_evHandler = NULL;
5520 m_downloadHandle = NULL;
5523 if (m_pCurlThread) {
5524 m_pCurlThread->Wait();
5525 if (!m_pCurlThread->IsAborting()) {
5526 delete (m_pCurlThread->GetOutputStream());
5527 wxDELETE(m_pCurlThread);
5532void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5536 event.setTotal(ev.GetTotalBytes());
5537 event.setTransferred(ev.GetDownloadedBytes());
5538 event.setComplete(
false);
5540 if (m_download_evHandler) {
5541 m_download_evHandler->AddPendingEvent(event);
5545bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5546 wxCurlBaseThread* p,
5547 const wxString& url) {
5549 case wxCTE_NO_ERROR:
5552 case wxCTE_NO_RESOURCE:
5554 wxS(
"Insufficient resources for correct execution of the program."));
5557 case wxCTE_ALREADY_RUNNING:
5561 case wxCTE_INVALID_PROTOCOL:
5562 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5566 case wxCTE_NO_VALID_STREAM:
5573 case wxCTE_CURL_ERROR: {
5574 wxString ws = wxS(
"unknown");
5575 if (p->GetCurlSession())
5577 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5578 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5583 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 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.