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/listimpl.cpp>
76#include <wx/platinfo.h>
77#include <wx/popupwin.h>
78#include <wx/progdlg.h>
79#include <wx/statline.h>
80#include <wx/tarstrm.h>
81#include <wx/textwrapper.h>
82#include <wx/tokenzr.h>
83#include <wx/tooltip.h>
86#include <wx/zipstrm.h>
87#include <wx/zstream.h>
92#include "o_sound/o_sound.h"
113#include "model/nav_object_database.h"
158#include "user_colors.h"
163#include "androidUTIL.h"
170typedef __LA_INT64_T la_int64_t;
171enum { CurlThreadId = wxID_HIGHEST + 1 };
173#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
174extern wxLocale* plocale_def_lang;
179void NotifySetupOptionsPlugin(
const PlugInData* pic);
181WX_DEFINE_LIST(Plugin_WaypointList);
182WX_DEFINE_LIST(Plugin_HyperlinkList);
189 explicit RawKey(
const std::string& key) : m_key(key) {}
190 [[nodiscard]] std::string
GetKey()
const {
return m_key; }
196static void SendAisJsonMessage(std::shared_ptr<const AisTargetData> target) {
198 if (!GetJSONMessageTargetCount())
return;
201 nlohmann::json json_msg;
203 wxLongLong t = ::wxGetLocalTimeMillis();
205 json_msg[
"Source"] =
"AisDecoder";
206 json_msg[
"Type"] =
"Information";
207 json_msg[
"Msg"] =
"AIS Target";
208 json_msg[
"MsgId"] = t.GetValue();
209 json_msg[
"lat"] = target->Lat;
210 json_msg[
"lon"] = target->Lon;
211 json_msg[
"sog"] = target->SOG;
212 json_msg[
"cog"] = target->COG;
213 json_msg[
"hdg"] = target->HDG;
214 json_msg[
"mmsi"] = target->MMSI;
215 json_msg[
"class"] = target->Class;
216 json_msg[
"ownship"] = target->b_OwnShip;
217 json_msg[
"active"] = target->b_active;
218 json_msg[
"lost"] = target->b_lost;
219 wxString l_ShipName = wxString::FromUTF8(target->ShipName);
220 for (
size_t i = 0; i < l_ShipName.Len(); i++) {
221 if (l_ShipName.GetChar(i) ==
'@') l_ShipName.SetChar(i,
'\n');
223 json_msg[
"shipname"] = l_ShipName.ToStdString();
224 wxString l_CallSign = wxString::FromUTF8(target->CallSign);
225 for (
size_t i = 0; i < l_CallSign.Len(); i++) {
226 if (l_CallSign.GetChar(i) ==
'@') l_CallSign.SetChar(i,
'\n');
228 json_msg[
"callsign"] = l_CallSign.ToStdString();
229 json_msg[
"removed"] = target->b_removed;
230 SendJsonMessageToAllPlugins(
"AIS", json_msg);
233static bool ReloadLocale() {
238 (!g_Platform->ChangeLocale(g_locale, plocale_def_lang, &plocale_def_lang)
245 return (*p1)->Key().compare((*p2)->Key());
249 auto version = metadata.version;
251 if (version[0] ==
'v') version = version.substr(1);
256 auto imported_version = ParseVersion(metadata);
257 for (
auto& md :
PluginHandler::GetInstance()->GetAvailable()) {
258 if (md.name != metadata.name)
continue;
259 if (md.is_imported)
continue;
261 if (ParseVersion(md) >= imported_version)
return true;
272 void message(
const std::string& message) {
274 m_deferred_messages.push_back(message);
279 void show_deferred_messages() {
280 for (
const auto& m : m_deferred_messages) show_msg(m);
287 void show_msg(wxString msg) {
288 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
289 wxICON_INFORMATION | wxOK, 10);
293 std::vector<std::string> m_deferred_messages;
300 Wrap(win, text, widthMax);
302 wxString
const& GetWrapped()
const {
return m_wrapped; }
303 int const GetLineCount()
const {
return m_lineCount; }
304 wxArrayString GetLineArray() {
return m_array; }
307 virtual void OnOutputLine(
const wxString& line) {
311 virtual void OnNewLine() {
319 wxArrayString m_array;
323 template <
typename T>
324 std::size_t operator()(T t)
const {
325 return static_cast<std::size_t
>(t);
332 return _(
"Plugin is a standard system plugin");
334 return _(
"Plugin is managed by OpenCPN");
336 return _(
"Plugin is not managed by OpenCPN");
339 case PluginStatus::Unknown:
340 return _(
"Plugin status unknown");
341 case PluginStatus::LegacyUpdateAvailable:
342 return _(
"Update to managed Plugin is available");
343 case PluginStatus::ManagedInstallAvailable:
344 return _(
"New managed Plugin installation available");
345 case PluginStatus::ManagedInstalledUpdateAvailable:
346 return _(
"Update to installed Plugin is available");
347 case PluginStatus::ManagedInstalledCurrentVersion:
348 return _(
"Plugin is latest available");
349 case PluginStatus::Imported:
350 return _(
"Plugin is imported");
351 case PluginStatus::ManagedInstalledDowngradeAvailable:
353 case PluginStatus::PendingListRemoval:
360static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
366 {PluginStatus::Unknown,
"emblem-unmanaged.svg"},
367 {PluginStatus::LegacyUpdateAvailable,
"emblem-legacy-update.svg"},
368 {PluginStatus::ManagedInstallAvailable,
"emblem-download.svg"},
369 {PluginStatus::ManagedInstalledUpdateAvailable,
370 "emblem-legacy-update.svg"},
371 {PluginStatus::ManagedInstalledCurrentVersion,
"emblem-default.svg"},
372 {PluginStatus::ManagedInstalledDowngradeAvailable,
373 "emblem-default.svg"},
374 {PluginStatus::PendingListRemoval,
"emblem-default.svg"},
375 {PluginStatus::Imported,
"emblem-default.svg"}});
377static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
378 literalstatus_by_status(
383 {PluginStatus::Unknown,
"Unknown"},
384 {PluginStatus::LegacyUpdateAvailable,
"LegacyUpdateAvailable"},
385 {PluginStatus::ManagedInstallAvailable,
"ManagedInstallAvailable"},
386 {PluginStatus::ManagedInstalledUpdateAvailable,
387 "ManagedInstalledUpdateAvailable"},
388 {PluginStatus::ManagedInstalledCurrentVersion,
389 "ManagedInstalledCurrentVersion"},
390 {PluginStatus::ManagedInstalledDowngradeAvailable,
391 "ManagedInstalledDowngradeAvailable"},
392 {PluginStatus::PendingListRemoval,
"PendingListRemoval"},
393 {PluginStatus::Imported,
"Imported"}
401static std::vector<PluginMetadata> getCompatiblePlugins() {
403 struct metadata_compare {
406 return lhs.key() < rhs.key();
410 std::vector<PluginMetadata> returnArray;
412 std::set<PluginMetadata, metadata_compare> unique_plugins;
413 for (
auto plugin :
PluginHandler::GetInstance()->GetAvailable()) {
414 unique_plugins.insert(plugin);
416 for (
auto plugin : unique_plugins) {
418 returnArray.push_back(plugin);
435 std::string installed;
437 if (path ==
"" || !wxFileName::IsFileReadable(path)) {
440 std::ifstream stream;
441 stream.open(path, std::ifstream::in);
450static std::vector<PluginMetadata> getUpdates(
const char* name) {
451 auto updates = getCompatiblePlugins();
453 std::remove_if(updates.begin(), updates.end(),
457 auto inst_vers = getInstalledVersion(name);
458 if (inst_vers.major == -1) {
463 updates.erase(std::remove_if(updates.begin(), updates.end(),
465 return metadata_version(m) == inst_vers;
472static void gui_uninstall(
const PlugInData* pic,
const char* plugin) {
473 g_Platform->ShowBusySpinner();
478 wxLogMessage(
"Uninstalling %s", plugin);
481 g_Platform->HideBusySpinner();
484static bool LoadAllPlugIns(
bool load_enabled,
bool keep_orphans =
false) {
485 g_Platform->ShowBusySpinner();
487 PluginLoader::GetInstance()->
LoadAllPlugIns(load_enabled, keep_orphans);
488 g_Platform->HideBusySpinner();
493static void UninstallPlugin(
const std::string& name) {
495 auto loader = PluginLoader::GetInstance();
496 auto finder = [name](
const PluginMetadata pm) {
return pm.name == name; };
497 const auto& installed = handler->GetInstalled();
498 auto found = std::find_if(installed.begin(), installed.end(), finder);
499 if (found != installed.end()) {
500 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
501 auto const& item = loader->GetPlugInArray()->Item(i);
502 if (item->m_common_name.ToStdString() == name) {
503 DEBUG_LOG <<
"Unloading plugin: " << name;
504 loader->UnLoadPlugIn(i);
508 handler->Uninstall(found->name);
509 DEBUG_LOG <<
"Uninstalling: " << found->name;
514 bool uninstall,
const char* name = 0,
515 bool b_forceEnable =
false) {
517 const char* plugin = name == 0 ? pic->
m_common_name.mb_str().data() : name;
518 auto updates = getUpdates(plugin);
519 auto parent_dlg =
dynamic_cast<wxScrolledWindow*
>(parent);
520 wxASSERT(parent_dlg != 0);
522 auto status = dialog.ShowModal();
523 status = dialog.GetReturnCode();
524 if (status != wxID_OK) {
528 auto update = dialog.GetUpdate();
533 wxLogMessage(
"Installing %s", update.name.c_str());
535 g_Platform->ShowBusySpinner();
539 if (uninstall && path !=
"") {
540 gui_uninstall(pic, update.name.c_str());
542 bool cacheResult = pluginHandler->InstallPluginFromCache(update);
545 g_Platform->ShowBusySpinner();
549 std::string tempTarballPath = downloader->run(parent_dlg, uninstall);
551 if (!tempTarballPath.size())
557 if (!isRegularFile(manifestPath.c_str())) {
558 wxLogMessage(
"Installation of %s failed", update.name.c_str());
559 PluginHandler::CleanupFiles(manifestPath, update.name);
565 wxLogMessage(
"Installation of %s successful", update.name.c_str());
566 wxURI uri(wxString(update.tarball_url.c_str()));
567 wxFileName fn(uri.GetPath());
568 std::string basename = fn.GetFullName().ToStdString();
571 wxLogDebug(
"Copied %s to local cache at %s", tempTarballPath.c_str(),
573 remove(tempTarballPath.c_str());
581 wxString pispec =
"_pi.dll";
582#elif defined(__WXOSX__)
583 wxString pispec =
"_pi.dylib";
585 wxString pispec =
"_pi.so";
589 wxTextFile manifest_file(manifestPath);
591 if (manifest_file.Open()) {
593 for (wxString str = manifest_file.GetFirstLine(); !manifest_file.Eof();
594 str = manifest_file.GetNextLine()) {
595 if (str.Contains(pispec)) {
596 if (getenv(
"OCPN_KEEP_PLUGINS")) {
600 auto loader = PluginLoader::GetInstance();
601 if (!loader->CheckPluginCompatibility(str)) {
603 _(
"The plugin is not compatible with this version of OpenCPN, "
604 "and will be uninstalled.");
605 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
606 wxICON_INFORMATION | wxOK, 10);
608 PluginHandler::CleanupFiles(manifestPath, update.name);
617 if (b_forceEnable && pluginFile.Length()) {
618 wxString config_section = (_T (
"/PlugIns/" ));
619 wxFileName fn(pluginFile);
620 config_section += fn.GetFullName();
621 pConfig->SetPath(config_section);
622 pConfig->Write(_T (
"bEnabled" ),
true);
628 std::remove(handler->ImportedMetadataPath(update.name).c_str());
631 LoadAllPlugIns(
false);
634 g_Platform->HideBusySpinner();
654 pivp.
lat_min = tvp.GetBBox().GetMinLat();
655 pivp.
lat_max = tvp.GetBBox().GetMaxLat();
656 pivp.
lon_min = tvp.GetBBox().GetMinLon();
657 pivp.
lon_max = tvp.GetBBox().GetMaxLon();
659 pivp.
bValid = tvp.IsValid();
680 if (top_frame::Get()->GetAbstractPrimaryCanvas())
681 vp.
ref_scale = top_frame::Get()->GetCanvasRefScale();
696 void OnPluginUtilAction(wxCommandEvent& event);
698 DECLARE_EVENT_TABLE()
702EVT_BUTTON(ID_CMD_BUTTON_PERFORM_ACTION, pluginUtilHandler::OnPluginUtilAction)
707void pluginUtilHandler::OnPluginUtilAction(wxCommandEvent& event) {
708 auto panel =
static_cast<PluginPanel*
>(
event.GetClientData());
711 wxASSERT(plugin_list_panel != 0);
713 auto actionPIC = panel->GetPlugin();
714 wxString name = actionPIC->m_common_name;
717 switch (panel->GetAction()) {
718 case ActionVerb::UPGRADE_TO_MANAGED_VERSION: {
719 auto loader = PluginLoader::GetInstance();
722 std::string pluginName = actionPIC->m_managed_metadata.name;
724 wxLogMessage(
"Installing managed plugin: %s", pluginName.c_str());
726 new GuiDownloader(plugin_list_panel, actionPIC->m_managed_metadata);
727 downloader->run(plugin_list_panel,
false);
731 if (isRegularFile(manifestPath.c_str())) {
733 for (
unsigned i = 0; i < loader->GetPlugInArray()->GetCount(); i += 1) {
734 if (actionPIC->m_managed_metadata.name ==
735 loader->GetPlugInArray()->Item(i)->m_common_name.ToStdString()) {
736 loader->UnLoadPlugIn(i);
742 LoadAllPlugIns(
false);
744 PluginHandler::CleanupFiles(manifestPath,
745 actionPIC->m_managed_metadata.name);
748 plugin_list_panel->SelectByName(name);
753 case ActionVerb::UPDATE_IMPORTED_VERSION:
754 case ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION:
755 case ActionVerb::REINSTALL_MANAGED_VERSION:
756 case ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION: {
758 auto metaSave = actionPIC->m_managed_metadata;
759 run_update_dialog(plugin_list_panel, actionPIC,
true,
760 metaSave.name.c_str());
764 case ActionVerb::INSTALL_MANAGED_VERSION: {
765 wxLogMessage(
"Installing new managed plugin.");
766 run_update_dialog(plugin_list_panel, actionPIC,
false);
770 case ActionVerb::UNINSTALL_MANAGED_VERSION: {
773 message.Printf(
"%s %s\n", actionPIC->m_managed_metadata.name.c_str(),
774 actionPIC->m_managed_metadata.version.c_str());
775 message += _(
"successfully un-installed");
777 wxLogMessage(
"Uninstalling %s",
778 actionPIC->m_managed_metadata.name.c_str());
781 actionPIC->m_managed_metadata.name);
784 LoadAllPlugIns(
false);
786 OCPNMessageBox(wxTheApp->GetTopWindow(), message,
787 _(
"Un-Installation complete"), wxICON_INFORMATION | wxOK);
791 case ActionVerb::NOP:
802const wxEventType wxEVT_OCPN_MSG = wxNewEventType();
804OCPN_MsgEvent::OCPN_MsgEvent(wxEventType commandType,
int id)
805 : wxEvent(id, commandType) {}
807OCPN_MsgEvent::~OCPN_MsgEvent() {}
809wxEvent* OCPN_MsgEvent::Clone()
const {
811 newevent->m_MessageID =
814 newevent->m_MessageText = this->m_MessageText.c_str();
823PlugInToolbarToolContainer::PlugInToolbarToolContainer() {
827 bitmap_Rollover_day = NULL;
828 bitmap_Rollover_dusk = NULL;
829 bitmap_Rollover_night = NULL;
832PlugInToolbarToolContainer::~PlugInToolbarToolContainer() {
836 delete bitmap_Rollover_day;
837 delete bitmap_Rollover_dusk;
838 delete bitmap_Rollover_night;
849#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
850EVT_CURL_END_PERFORM(CurlThreadId, PlugInManager::OnEndPerformCurlDownload)
851EVT_CURL_DOWNLOAD(CurlThreadId, PlugInManager::OnCurlDownload)
855static
void event_message_box(const wxString& msg) {
856 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
857 wxICON_INFORMATION | wxOK, 0);
863 if (!pic->m_toolbox_panel) NotifySetupOptionsPlugin(pic);
869#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
870 m_pCurlThread = NULL;
876 m_plugin_menu_item_id_next = CanvasMenuHandler::GetNextContextMenuId();
877 m_plugin_tool_id_next = top_frame::Get()->GetNextToolbarToolId();
890 new wxRadioBox(parent, -1,
"", wxPoint(0, 0), wxSize(-1, -1), as);
896#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
898 m_last_online =
false;
899 m_last_online_chk = -1;
904 m_blacklist = blacklist_factory();
905 m_blacklist_ui = std::unique_ptr<BlacklistUI>(
new BlacklistUI());
907 wxDEFINE_EVENT(EVT_JSON_TO_ALL_PLUGINS,
ObservedEvt);
909 EVT_JSON_TO_ALL_PLUGINS);
910 Bind(EVT_JSON_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
912 std::static_pointer_cast<const nlohmann::json>(ev.
GetSharedPtr());
913 SendJsonMessageToAllPlugins(ev.GetString().ToStdString(), *json);
916 wxDEFINE_EVENT(EVT_LEGINFO_TO_ALL_PLUGINS,
ObservedEvt);
918 EVT_LEGINFO_TO_ALL_PLUGINS);
919 Bind(EVT_LEGINFO_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
920 auto ptr = obs::UnpackEvtPointer<ActiveLegDat>(ev);
921 SendActiveLegInfoToAllPlugIns(ptr.get());
924 HandlePluginLoaderEvents();
930 m_new_msgtype_lstnr.Init(NavMsgBus::GetInstance().new_msg_event,
933PlugInManager::~PlugInManager() {
934#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
935 wxCurlBase::Shutdown();
937 delete m_utilHandler;
940void PlugInManager::InitCommListeners() {
944 auto& msgbus = NavMsgBus::GetInstance();
947 m_listener_SignalK.
Listen(sk_msg,
this, EVT_SIGNALK);
954void PlugInManager::OnNewMessageType() {
955 for (
auto msg_key :
NavMsgBus::GetInstance().GetActiveMessages()) {
956 if (m_0183_listeners.find(msg_key) != m_0183_listeners.end())
continue;
957 if (msg_key.find(
"::") == std::string::npos)
continue;
959 if (key_parts.size() < 2)
continue;
962 HandleN0183(obs::UnpackEvtPointer<Nmea0183Msg>(ev));
964 m_0183_listeners[msg_key] = std::move(ol);
969 assert(n0183_msg->bus == NavAddr::Bus::N0183);
970 const std::string& payload = n0183_msg->payload;
972 if (payload[0] ==
'$') {
973 const auto& drivers = CommDriverRegistry::GetInstance().
GetDrivers();
974 auto& target_driver =
FindDriver(drivers, n0183_msg->source->iface);
978 bool passes_input_filter =
true;
982 passes_input_filter =
986 }
else if (payload[0] ==
'!') {
987 SendAISSentenceToAllPlugIns(payload.c_str());
992 g_ownshipMMSI_SK = sK_msg->context_self;
996 std::string msgTerminated = sK_msg->raw_message;
999 root = nlohmann::json::parse(msgTerminated);
1000 }
catch (nlohmann::json::exception&) {
1003 if (!failed) SendJsonMessageToAllPlugins(
"OCPN_CORE_SIGNALK", root);
1012wxDEFINE_EVENT(EVT_PLUGMGR_ROUTEMAN_MSG,
ObservedEvt);
1013wxDEFINE_EVENT(EVT_BLACKLISTED_PLUGIN, wxCommandEvent);
1014wxDEFINE_EVENT(EVT_LOAD_DIRECTORY, wxCommandEvent);
1015wxDEFINE_EVENT(EVT_LOAD_PLUGIN, wxCommandEvent);
1016wxDEFINE_EVENT(EVT_PLUGIN_UNLOAD, wxCommandEvent);
1017wxDEFINE_EVENT(EVT_PLUGLIST_CHANGE, wxCommandEvent);
1018wxDEFINE_EVENT(EVT_UPDATE_CHART_TYPES, wxCommandEvent);
1019wxDEFINE_EVENT(EVT_PLUGIN_LOADALL_FINALIZE, wxCommandEvent);
1021void PlugInManager::HandlePluginLoaderEvents() {
1022 auto loader = PluginLoader::GetInstance();
1024 loader->SetOnActivateCb(
1026 loader->SetOnDeactivateCb(
1029 evt_pluglist_change_listener.
Listen(loader->evt_pluglist_change,
this,
1030 EVT_PLUGLIST_CHANGE);
1031 Bind(EVT_PLUGLIST_CHANGE, [&](wxCommandEvent&) {
1036 evt_load_directory_listener.
Listen(loader->evt_load_directory,
this,
1037 EVT_LOAD_DIRECTORY);
1038 Bind(EVT_LOAD_DIRECTORY, [&](wxCommandEvent&) {
1039 pConfig->SetPath(
"/PlugIns/");
1040 SetPluginOrder(
pConfig->Read(
"PluginOrder", wxEmptyString));
1043 evt_load_plugin_listener.
Listen(loader->evt_load_plugin,
this,
1045 Bind(EVT_LOAD_PLUGIN, [&](wxCommandEvent& ev) {
1050 evt_update_chart_types_listener.
Listen(loader->evt_update_chart_types,
this,
1051 EVT_UPDATE_CHART_TYPES);
1052 Bind(EVT_UPDATE_CHART_TYPES,
1053 [&](wxCommandEvent& ev) { UpDateChartDataTypes(); });
1055 evt_plugin_loadall_finalize_listener.
Listen(
1056 loader->evt_plugin_loadall_finalize,
this, EVT_PLUGIN_LOADALL_FINALIZE);
1057 Bind(EVT_PLUGIN_LOADALL_FINALIZE,
1058 [&](wxCommandEvent& ev) { FinalizePluginLoadall(); });
1061 EVT_PLUGMGR_AIS_MSG);
1063 EVT_PLUGMGR_ROUTEMAN_MSG);
1065 auto target = obs::UnpackEvtPointer<AisTargetData>(ev);
1066 SendAisJsonMessage(target);
1068 Bind(EVT_PLUGMGR_ROUTEMAN_MSG, [&](
ObservedEvt& ev) {
1069 auto msg = obs::UnpackEvtPointer<nlohmann::json>(ev);
1070 SendJsonMessageToAllPlugins(ev.GetString().ToStdString(), *msg);
1078wxDEFINE_EVENT(EVT_DOWNLOAD_FAILED, wxCommandEvent);
1079wxDEFINE_EVENT(EVT_DOWNLOAD_OK, wxCommandEvent);
1081void PlugInManager::HandlePluginHandlerEvents() {
1082 auto loader = PluginLoader::GetInstance();
1084 evt_download_failed_listener.
Listen(loader->evt_update_chart_types,
this,
1085 EVT_DOWNLOAD_FAILED);
1086 Bind(EVT_DOWNLOAD_FAILED, [&](wxCommandEvent& ev) {
1087 wxString message = _(
"Please check system log for more info.");
1088 OCPNMessageBox(wxTheApp->GetTopWindow(), message, _(
"Installation error"),
1089 wxICON_ERROR | wxOK | wxCENTRE);
1092 evt_download_ok_listener.
Listen(loader->evt_update_chart_types,
this,
1094 Bind(EVT_DOWNLOAD_OK, [&](wxCommandEvent& ev) {
1095 wxString message(ev.GetString());
1096 message += _(
" successfully installed from cache");
1097 OCPNMessageBox(wxTheApp->GetTopWindow(), message,
1098 _(
"Installation complete"),
1099 wxICON_INFORMATION | wxOK | wxCENTRE);
1103bool PlugInManager::CallLateInit() {
1106 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1107 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1110 switch (pic->m_api_version) {
1123 ProcessLateInit(pic);
1133 wxString msg(
"PlugInManager: Calling LateInit PlugIn: ");
1138 if (ppi) ppi->LateInit();
1147 if (top_frame::Get()->GetWxGlCanvas()) {
1148 top_frame::Get()->SendGlJsonConfigMsg();
1149 SendS52ConfigToAllPlugIns(
true);
1159 auto api_impl =
dynamic_cast<Api122Impl*
>(wxTheApp);
1160 assert(api_impl &&
"wxTheApp does not implement Api122Impl");
1161 api_impl->RegisterApiEventCallback(name,
nullptr);
1169 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1172 if (pttc->m_pplugin == pic->m_pplugin) {
1173 m_PlugInToolbarTools.Remove(pttc);
1179 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1181 if (pimis->m_pplugin == pic->m_pplugin) {
1182 m_PlugInMenuItems.Remove(pimis);
1188bool PlugInManager::IsAnyPlugInChartEnabled() {
1191 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1192 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1194 if (pic->m_enabled && pic->m_init_state) {
1203void PlugInManager::UpdateManagedPlugins() {
1205 PluginLoader::GetInstance()->
SortPlugins(ComparePlugins);
1208 g_options->itemBoxSizerPanelPlugins->Layout();
1211bool PlugInManager::UpDateChartDataTypes() {
1215 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1216 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1219 if (pic->m_init_state) {
1227 if (bret)
ChartData->UpdateChartClassDescriptorArray();
1232void PlugInManager::FinalizePluginLoadall() {
1236 SetColorSchemeForAllPlugIns(global_color_scheme);
1239 SendBaseConfigToAllPlugIns();
1240 SendS52ConfigToAllPlugIns(
true);
1241 SendSKConfigToAllPlugIns();
1246 top_frame::Get()->SendGlJsonConfigMsg();
1254void PlugInManager::SetPluginOrder(wxString serialized_names) {
1255 m_plugin_order.Empty();
1256 wxStringTokenizer tokenizer(serialized_names,
";");
1257 while (tokenizer.HasMoreTokens()) {
1258 m_plugin_order.Add(tokenizer.GetNextToken());
1262wxString PlugInManager::GetPluginOrder() {
1263 wxString plugins = wxEmptyString;
1264 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1265 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1266 plugins.Append(plugin_array->Item(i)->m_common_name);
1267 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1272bool PlugInManager::UpdateConfig() {
1276 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1277 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1281 wxString config_section = (_T (
"/PlugIns/" ));
1283 pConfig->SetPath(config_section);
1284 pConfig->Write(_T (
"bEnabled" ), pic->m_enabled);
1291void PlugInManager::ShowDeferredBlacklistMessages() {
1292 m_blacklist_ui->show_deferred_messages();
1295bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1297 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1300bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin* plugin) {
1305 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1306 name.Replace(
"class ", wxEmptyString);
1308 const std::type_info& ti =
typeid(*plugin);
1310 char* realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1311 wxString name = wxString::FromAscii(realname);
1314 return CheckBlacklistedPlugin(name, major, minor);
1317bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
1319 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1320 if (block_status == plug_status::unblocked)
return true;
1321 plug_data data(name.ToStdString(), major, minor);
1322 auto msg = m_blacklist->get_message(block_status, data);
1323 m_blacklist_ui->message(msg);
1327bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC& dc,
1331 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1332 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1334 if (pic->m_enabled && pic->m_init_state) {
1338 wxDC* pdc = dc.GetDC();
1341 switch (pic->m_api_version) {
1343 if (priority > 0)
break;
1350 if (priority > 0)
break;
1353 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1364 if (priority > 0)
break;
1367 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1372 if (priority > 0)
break;
1376 ppi->RenderOverlay(*pdc, &pivp);
1388 if (priority <= 0) {
1392 ppi->RenderOverlay(*pdc, &pivp);
1408 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1410 if ((m_cached_overlay_bm.GetWidth() != vp.
pix_width) ||
1411 (m_cached_overlay_bm.GetHeight() != vp.
pix_height))
1415 mdc.SelectObject(m_cached_overlay_bm);
1416 mdc.SetBackground(*wxBLACK_BRUSH);
1419 bool b_rendered =
false;
1421 switch (pic->m_api_version) {
1423 if (priority > 0)
break;
1430 if (priority > 0)
break;
1433 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1444 if (priority > 0)
break;
1447 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1452 if (priority > 0)
break;
1456 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1469 if (priority <= 0) {
1473 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1480 mdc, &pivp, g_canvasConfig, priority);
1489 mdc.SelectObject(wxNullBitmap);
1492 wxMask* p_msk =
new wxMask(m_cached_overlay_bm, wxColour(0, 0, 0));
1493 m_cached_overlay_bm.SetMask(p_msk);
1495 dc.DrawBitmap(m_cached_overlay_bm, 0, 0,
true);
1498 }
else if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1506bool PlugInManager::RenderAllGLCanvasOverlayPlugIns(wxGLContext* pcontext,
1510 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1511 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1513 if (pic->m_enabled && pic->m_init_state) {
1514 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1517 switch (pic->m_api_version) {
1519 if (priority > 0)
break;
1522 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
1534 if (priority > 0)
break;
1542 if (priority > 0)
break;
1559 if (priority <= 0) {
1584void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort& vp) {
1585 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1586 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1588 if (pic->m_enabled && pic->m_init_state) {
1597void NotifySetupOptionsPlugin(
const PlugInData* pd) {
1598 PluginLoader::GetInstance()->NotifySetupOptionsPlugin(pd);
1601void PlugInManager::NotifySetupOptions() {
1602 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1603 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1605 NotifySetupOptionsPlugin(pic);
1610 int ok_apply_cancel) {
1611 if (pic->m_enabled && pic->m_init_state) {
1614 auto loader = PluginLoader::GetInstance();
1621void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
1622 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1623 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1626 ClosePlugInPanel(pic, ok_apply_cancel);
1631int PlugInManager::AddCanvasContextMenuItemPIM(wxMenuItem* pitem,
1636 pmic->pmenu_item = pitem;
1637 pmic->m_pplugin = pplugin;
1638 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
1639 : m_plugin_menu_item_id_next;
1641 pmic->b_grey =
false;
1642 pmic->m_in_menu = name;
1643 pmic->extended = is_extended;
1645 m_PlugInMenuItems.Add(pmic);
1647 m_plugin_menu_item_id_next++;
1652void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char* name) {
1653 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1656 if (pimis->id == item) {
1657 m_PlugInMenuItems.Remove(pimis);
1665void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
1667 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1670 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1678void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
1680 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1683 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1684 pimis->b_grey = grey;
1691void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
1692 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1693 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1695 if (pic->m_enabled && pic->m_init_state)
1700void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
1702 if (g_hicon_colors) {
1704 if (cs == GLOBAL_COLOR_SCHEME_DAY_HICON)
1705 s = GLOBAL_COLOR_SCHEME_DAY;
1706 else if (cs == GLOBAL_COLOR_SCHEME_NIGHT_HICON)
1707 s = GLOBAL_COLOR_SCHEME_DUSK;
1709 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1710 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1712 if (pic->m_enabled && pic->m_init_state)
1717void PlugInManager::PrepareAllPluginContextMenus() {
1718 int canvasIndex = top_frame::Get()->GetCanvasIndexUnderMouse();
1719 if (canvasIndex < 0)
return;
1721 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1722 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1724 if (pic->m_enabled && pic->m_init_state) {
1726 switch (pic->m_api_version) {
1746void PlugInManager::SendSKConfigToAllPlugIns() {
1749 v[
"self"] = g_ownshipMMSI_SK;
1750 std::string out = v.dump();
1751 SendMessageToAllPlugins(
"OCPN_CORE_SIGNALK", out);
1754void PlugInManager::SendBaseConfigToAllPlugIns() {
1757 v[
"OpenCPN Version Major"] = VERSION_MAJOR;
1758 v[
"OpenCPN Version Minor"] = VERSION_MINOR;
1759 v[
"OpenCPN Version Patch"] = VERSION_PATCH;
1760 v[
"OpenCPN Version Date"] = VERSION_DATE;
1761 v[
"OpenCPN Version Full"] = VERSION_FULL;
1765 v[
"OpenCPN Toolbar Width"] =
g_MainToolbar->GetToolbarRect().width;
1766 v[
"OpenCPN Toolbar Height"] =
g_MainToolbar->GetToolbarRect().height;
1767 v[
"OpenCPN Toolbar PosnX"] =
g_MainToolbar->GetToolbarRect().x;
1768 v[
"OpenCPN Toolbar PosnY"] =
g_MainToolbar->GetToolbarRect().y;
1772 v[
"OpenCPN Zoom Mod Vector"] = g_chart_zoom_modifier_vector;
1773 v[
"OpenCPN Zoom Mod Other"] = g_chart_zoom_modifier_raster;
1774 v[
"OpenCPN Scale Factor Exp"] =
1775 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1780 std::string out = v.dump();
1781 SendMessageToAllPlugins(
"OpenCPN Config", out);
1784void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1787 v[
"OpenCPN Version Major"] = VERSION_MAJOR;
1788 v[
"OpenCPN Version Minor"] = VERSION_MINOR;
1789 v[
"OpenCPN Version Patch"] = VERSION_PATCH;
1790 v[
"OpenCPN Version Date"] = VERSION_DATE;
1791 v[
"OpenCPN Version Full"] = VERSION_FULL;
1799 v[
"OpenCPN S52PLIB ShowAnchorConditions"] = ps52plib->GetAnchorOn();
1800 v[
"OpenCPN S52PLIB ShowQualityOfData"] = ps52plib->GetQualityOfData();
1805 v[
"OpenCPN S52PLIB MetaDisplay"] = ps52plib->m_bShowMeta;
1806 v[
"OpenCPN S52PLIB DeclutterText"] = ps52plib->m_bDeClutterText;
1807 v[
"OpenCPN S52PLIB ShowNationalText"] = ps52plib->m_bShowNationalTexts;
1808 v[
"OpenCPN S52PLIB ShowImportantTextOnly"] =
1809 ps52plib->m_bShowS57ImportantTextOnly;
1810 v[
"OpenCPN S52PLIB UseSCAMIN"] = ps52plib->m_bUseSCAMIN;
1811 v[
"OpenCPN S52PLIB UseSUPER_SCAMIN"] = ps52plib->m_bUseSUPER_SCAMIN;
1812 v[
"OpenCPN S52PLIB SymbolStyle"] = ps52plib->m_nSymbolStyle;
1813 v[
"OpenCPN S52PLIB BoundaryStyle"] = ps52plib->m_nBoundaryStyle;
1814 v[
"OpenCPN S52PLIB ColorShades"] = S52_getMarinerParam(S52_MAR_TWO_SHADES);
1815 v[
"OpenCPN S52PLIB Safety Depth"] =
1816 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1817 v[
"OpenCPN S52PLIB Shallow Contour"] =
1818 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1819 v[
"OpenCPN S52PLIB Deep Contour"] =
1820 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1824 v[
"OpenCPN S52PLIB GlobalReconfig"] = bReconfig;
1826 const std::string out = v.dump();
1827 SendMessageToAllPlugins(
"OpenCPN Config", out);
1830void PlugInManager::NotifyAuiPlugIns() {
1831 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1832 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1834 if (pic->m_enabled && pic->m_init_state &&
1840int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1841 wxBitmap* bmpRollover, wxItemKind kind,
1842 wxString shortHelp, wxString longHelp,
1843 wxObject* clientData,
int position,
1846 pttc->label = label;
1848 if (!bitmap->IsOk()) {
1850 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1853 pttc->bitmap_day =
new wxBitmap(*bitmap);
1854 pttc->bitmap_day->UnShare();
1857 if (!bmpRollover->IsOk()) {
1859 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1862 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1863 pttc->bitmap_Rollover_day->UnShare();
1866 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1867 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1868 pttc->bitmap_Rollover_dusk =
1869 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1870 pttc->bitmap_Rollover_night =
1871 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1874 pttc->shortHelp = shortHelp;
1875 pttc->longHelp = longHelp;
1876 pttc->clientData = clientData;
1877 pttc->position = position;
1878 pttc->m_pplugin = pplugin;
1879 pttc->tool_sel = tool_sel;
1881 pttc->b_toggle =
false;
1882 pttc->id = m_plugin_tool_id_next;
1884 m_PlugInToolbarTools.Add(pttc);
1886 m_plugin_tool_id_next++;
1891int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1892 wxString SVGRolloverfile,
1893 wxString SVGToggledfile, wxItemKind kind,
1894 wxString shortHelp, wxString longHelp,
1895 wxObject* clientData,
int position,
1898 pttc->label = label;
1900 pttc->pluginNormalIconSVG = SVGfile;
1901 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1902 pttc->pluginToggledIconSVG = SVGToggledfile;
1907 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1908 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1909 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1910 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1911 pttc->bitmap_Rollover_dusk =
1912 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1913 pttc->bitmap_Rollover_night =
1914 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1917 pttc->shortHelp = shortHelp;
1918 pttc->longHelp = longHelp;
1919 pttc->clientData = clientData;
1920 pttc->position = position;
1921 pttc->m_pplugin = pplugin;
1922 pttc->tool_sel = tool_sel;
1924 pttc->b_toggle =
false;
1925 pttc->id = m_plugin_tool_id_next;
1927 m_PlugInToolbarTools.Add(pttc);
1929 m_plugin_tool_id_next++;
1934void PlugInManager::RemoveToolbarTool(
int tool_id) {
1935 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1938 if (pttc->id == tool_id) {
1939 m_PlugInToolbarTools.Remove(pttc);
1945 m_parent->RequestNewToolbars();
1948void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1949 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1952 if (pttc->id == item) {
1954 m_parent->RequestNewToolbars();
1961void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1962 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1965 if (pttc->id == item) {
1966 pttc->b_toggle = toggle;
1967 m_parent->SetMasterToolbarItemState(item, toggle);
1974void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1975 wxBitmap* bmpRollover) {
1976 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1979 if (pttc->id == item) {
1980 delete pttc->bitmap_day;
1981 delete pttc->bitmap_dusk;
1982 delete pttc->bitmap_night;
1983 delete pttc->bitmap_Rollover_day;
1985 if (!bitmap->IsOk()) {
1987 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1990 pttc->bitmap_day =
new wxBitmap(*bitmap);
1991 pttc->bitmap_day->UnShare();
1994 if (!bmpRollover->IsOk()) {
1996 pttc->bitmap_Rollover_day =
1997 new wxBitmap(style->GetIcon(
"default_pi"));
2000 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
2001 pttc->bitmap_Rollover_day->UnShare();
2004 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
2005 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
2007 m_parent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
2008 pttc->bitmap_Rollover_day);
2015void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2016 wxString SVGfileRollover,
2017 wxString SVGfileToggled) {
2018 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2021 if (pttc->id == item) {
2022 pttc->pluginNormalIconSVG = SVGfile;
2023 pttc->pluginRolloverIconSVG = SVGfileRollover;
2024 pttc->pluginToggledIconSVG = SVGfileToggled;
2025 m_parent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2026 pttc->pluginRolloverIconSVG,
2027 pttc->pluginToggledIconSVG);
2035 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2037 if (
id == pc->id)
return pc->m_pplugin;
2043wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2046 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2047 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2049 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2053 return wxEmptyString;
2056wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2058wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2059 unsigned char dim_ratio) {
2060 wxImage img_dup = pbmp_normal->ConvertToImage();
2062 if (!img_dup.IsOk())
return NULL;
2064 if (dim_ratio < 200) {
2066 int gimg_width = img_dup.GetWidth();
2067 int gimg_height = img_dup.GetHeight();
2069 double factor = (double)(dim_ratio) / 256.0;
2071 for (
int iy = 0; iy < gimg_height; iy++) {
2072 for (
int ix = 0; ix < gimg_width; ix++) {
2073 if (!img_dup.IsTransparent(ix, iy)) {
2074 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2075 img_dup.GetGreen(ix, iy),
2076 img_dup.GetBlue(ix, iy));
2077 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2078 hsv.value = hsv.value * factor;
2079 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2080 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2086 wxBitmap* ptoolBarBitmap;
2089 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2091 dwxdc.SelectObject(tbmp);
2093 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2095 ptoolBarBitmap =
new wxBitmap(img_dup);
2099 return ptoolBarBitmap;
2102wxArrayString PlugInManager::GetPlugInChartClassNameArray() {
2103 wxArrayString array;
2104 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2105 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2107 if (pic && pic->m_enabled && pic->m_init_state &&
2112 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2113 array.Add(carray[j]);
2121 while (j < array.GetCount()) {
2122 wxString test = array[j];
2123 unsigned int k = j + 1;
2124 while (k < array.GetCount()) {
2125 if (test == array[k]) {
2140 const wxString& ChartClassName) {
2142 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2143 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2145 if (pic && pic->m_enabled && pic->m_init_state &&
2150 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2151 if (carray[j].IsSameAs(ChartClassName)) {
2152 plugin = pic->m_pplugin;
2166#define DISABLED_SETTINGS_MSG \
2167 _("These settings might destabilize OpenCPN and are by default disabled." \
2168 " To despite the dangers enable them manually add a CatalogExpert=1" \
2169 " line in the [PlugIns] section in the configuration file.")
2174CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2175 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2177 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2180 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2182 wxStaticBox* itemStaticBoxSizer4Static =
2183 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2184 wxStaticBoxSizer* itemStaticBoxSizer4 =
2185 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2186 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2190 m_catalogText =
new wxStaticText(
this, wxID_STATIC,
"");
2191 itemStaticBoxSizer4->Add(m_catalogText,
2192 wxSizerFlags().Border().Proportion(1));
2193 m_catalogText->SetLabel(GetCatalogText(
false));
2196 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2197 itemStaticBoxSizer4->Add(rowSizer2,
2198 wxSizerFlags().Expand().Border().Proportion(1));
2200 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2201 wxDefaultPosition, wxDefaultSize, 0);
2202 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2203 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2204 &CatalogMgrPanel::OnUpdateButton,
this);
2205 rowSizer2->AddSpacer(4 * GetCharWidth());
2206 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2207 wxDefaultPosition, wxDefaultSize, 0);
2208 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2209 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2210 &CatalogMgrPanel::OnTarballButton,
this);
2212 rowSizer2->AddSpacer(4 * GetCharWidth());
2213 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2214 wxDefaultPosition, wxDefaultSize, 0);
2216 if (expert.Get(
false)) {
2217 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2218 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2220 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2221 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2224 rowSizer2->AddSpacer(4 * GetCharWidth());
2225 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2227 SetUpdateButtonLabel();
2230 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2231 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2233 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2237 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2238 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2239 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2242 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2244 if (!expert.Get(
false)) {
2246 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2247 wxDefaultPosition, wxDefaultSize, 0);
2248 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2249 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2250 &CatalogMgrPanel::OnUpdateButton,
this);
2251 SetUpdateButtonLabel();
2252 m_tarballButton = NULL;
2253 m_adv_button = NULL;
2256 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2257 itemStaticBoxSizer4->Add(m_catalogText,
2258 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2261 m_updateButton =
new wxButton(
2262 this, wxID_ANY,
"Update Plugin Catalog:master ",
2263 wxDefaultPosition, wxDefaultSize, 0);
2264 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2265 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2266 &CatalogMgrPanel::OnUpdateButton,
this);
2267 SetUpdateButtonLabel();
2270 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2271 wxDefaultPosition, wxDefaultSize, 0);
2272 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2274 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2275 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2278 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2279 wxDefaultPosition, wxDefaultSize, 0);
2280 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2281 2 * GetCharWidth());
2282 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2283 &CatalogMgrPanel::OnTarballButton,
this);
2289CatalogMgrPanel::~CatalogMgrPanel() {
2290 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2291 &CatalogMgrPanel::OnUpdateButton,
this);
2292 if (m_tarballButton)
2293 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2294 &CatalogMgrPanel::OnTarballButton,
this);
2297static const char*
const DOWNLOAD_REPO_PROTO =
2298 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2301void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2303 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2304 std::string url(g_catalog_custom_url);
2305 if (catalog !=
"custom") {
2306 url = std::string(DOWNLOAD_REPO_PROTO);
2310 std::string filePath =
2311 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2313 auto catalogHdlr = CatalogHandler::GetInstance();
2315 g_Platform->ShowBusySpinner();
2316 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2317 g_Platform->HideBusySpinner();
2319 std::string message;
2320 if (status != CatalogHandler::ServerStatus::OK) {
2321 message = _(
"Cannot download data from url");
2322 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2323 wxICON_ERROR | wxOK);
2329 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2331 wxFileName::GetPathSeparator() +
2332 "ocpn-plugins.xml")) {
2333 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2334 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2339 if (!wxCopyFile(wxString(filePath.c_str()),
2341 wxFileName::GetPathSeparator() +
"ocpn-plugins.xml")) {
2342 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2343 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2349 if (catalog ==
"master") {
2351 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2352 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2358 pConfig->SetPath(
"/PlugIns/");
2359 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2366 pluginHandler->setMetadata(
"");
2370 auto cataloghdlr = CatalogHandler::GetInstance();
2371 cataloghdlr->ClearCatalogData();
2374 LoadAllPlugIns(
false);
2378 m_catalogText->SetLabel(GetCatalogText(
true));
2381 OCPNMessageBox(
this, _(
"Catalog update successful"),
2382 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2385void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2389 androidDisableRotation();
2392 dialog->ShowModal();
2395 androidEnableRotation();
2399void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2402 int response = g_Platform->DoFileSelectorDialog(
2403 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2404 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2406 if (response != wxID_OK) {
2411 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2415 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2416 _(
"OpenCPN Plugin Import Error"));
2420 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2421 _(
"OpenCPN Plugin Import Error"));
2422 handler->Uninstall(metadata.name);
2425 UninstallPlugin(metadata.name);
2426 ok = handler->InstallPlugin(metadata, path.ToStdString());
2428 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2429 _(
"OpenCPN Plugin Import Error"));
2432 metadata.is_imported =
true;
2434 std::ofstream file(metadata_path);
2437 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2438 <<
" for imported plugin: " << metadata.name;
2440 LoadAllPlugIns(
false,
true);
2443 wxString ws(_(
"Plugin"));
2444 ws += metadata.name + _(
" successfully imported");
2445 OCPNMessageBox(wxTheApp->GetTopWindow(), ws, _(
"Installation complete"),
2446 wxICON_INFORMATION | wxOK | wxCENTRE);
2449wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2451 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2455 pConfig->SetPath(
"/PlugIns/");
2456 wxString latestCatalog =
pConfig->Read(
"LatestCatalogDownloaded",
"default");
2457 catalog += latestCatalog;
2463 std::string date = pluginHandler->GetCatalogData()->date;
2465 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2466 if (!updated) catalog +=
" : " + _(
"Please Update Plugin Catalog.");
2472void CatalogMgrPanel::SetUpdateButtonLabel() {
2473 wxString label = _(
"Update Plugin Catalog");
2475 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2476 m_updateButton->SetLabel(label);
2480wxString CatalogMgrPanel::GetImportInitDir() {
2482 pConfig->SetPath(
"/PlugIns/");
2483 wxString lastImportDir;
2485 pConfig->Read(
"LatestImportDir", g_Platform->GetWritableDocumentsDir());
2486 if (wxDirExists(lastImportDir)) {
2487 return lastImportDir;
2489 return (g_Platform->GetWritableDocumentsDir());
2498 const wxPoint& pos, const wxSize& size)
2499 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2500 m_PluginSelected(0) {
2501 m_is_loading.clear();
2502 SetSizer(
new wxBoxSizer(wxVERTICAL));
2503 ReloadPluginPanels();
2506void PluginListPanel::SelectByName(wxString& name) {
2507 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2508 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2510 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2511 pluginPanel->SetSelected(
true);
2512 pluginPanel->Layout();
2513 SelectPlugin(pluginPanel);
2522 std::vector<const PlugInData*> result;
2523 auto loader = PluginLoader::GetInstance();
2524 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2525 auto const item = loader->GetPlugInArray()->Item(i);
2526 if (item->m_managed_metadata.name.empty()) {
2527 const auto name = item->m_common_name.ToStdString();
2531 result.push_back(item);
2534 std::string slhs, srhs;
2535 for (
auto& cl : lhs->
Key()) slhs += toupper(cl);
2536 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2537 return slhs.compare(srhs) < 0;
2539 std::sort(result.begin(), result.end(), compare);
2544static bool IsPluginLoaded(
const std::string& name) {
2548 std::find(installed.begin(), installed.end(),
ocpn::tolower(name));
2549 return found != installed.end();
2552 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2553 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2560 if (m_is_loading.test_and_set()) {
2562 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2567 m_PluginItems.Clear();
2569 wxWindowList kids = GetChildren();
2570 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2571 wxWindowList::compatibility_iterator node = kids.Item(i);
2572 wxWindow* win = node->GetData();
2574 if (pp) win->Destroy();
2576 GetSizer()->Clear();
2579 m_PluginSelected = 0;
2584 for (
const auto& name : installed) AddPlugin(name);
2587 auto available = getCompatiblePlugins();
2591 return IsPluginLoaded(md.name);
2593 auto end = std::remove_if(available.begin(), available.end(), predicate);
2594 available.erase(end, available.end());
2600 std::string slhs, srhs;
2601 for (
auto& cl : lhs.name) slhs += toupper(cl);
2602 for (
auto& cr : rhs.name) srhs += toupper(cr);
2603 return slhs.compare(srhs) < 0;
2607 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2608 for (
const auto& p : available) unique_sorted_entries.insert(p);
2614 if (p->m_enabled) AddPlugin(*p);
2618 if (!p->m_enabled) AddPlugin(*p);
2621 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2629 m_is_loading.clear();
2632void PluginListPanel::AddPlugin(
const std::string& name) {
2635 panel->SetSelected(
false);
2636 GetSizer()->Add(panel, 0, wxEXPAND);
2637 m_PluginItems.Add(panel);
2638 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2639 GetSizer()->AddSpacer(m_pluginSpacer);
2642void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2644 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2645 pPluginPanel->SetSelected(
false);
2646 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2647 m_PluginItems.Add(pPluginPanel);
2649 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2650 GetSizer()->AddSpacer(m_pluginSpacer);
2663int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2664 wxBoxSizer* sizer) {
2666 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2667 auto panel = plugins.Item(i);
2668 bool was_selected = panel->GetSelected();
2669 panel->SetSelected(
false);
2671 wxSize unselected = panel->GetSize();
2673 panel->SetSelected(
true);
2675 wxSize selected = panel->GetSize();
2677 int dy = selected.GetHeight() - unselected.GetHeight();
2678 max_dy = wxMax(max_dy, dy);
2679 panel->SetSelected(was_selected);
2684PluginListPanel::~PluginListPanel() {}
2686void PluginListPanel::UpdateSelections() {
2687 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2690 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2695void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2697 GetViewStart(&xs, &ys);
2700 if (m_PluginSelected) {
2701 m_PluginSelected->SetSelected(
false);
2702 m_PluginSelected->Layout();
2705 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2707 m_PluginSelected = pi;
2709 GetSizer()->Layout();
2711 wxSize size = GetBestVirtualSize();
2712 SetVirtualSize(size);
2717 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2719 int yd = pPluginPanel->GetSize().y;
2721 htop += m_pluginSpacer;
2722 if (pPluginPanel == pi) {
2723 int piBottom = htop - (ys *
g_options->GetScrollRate());
2724 if (piBottom > GetClientSize().y) {
2725 ys += (piBottom - GetClientSize().y) /
g_options->GetScrollRate();
2735 int pos = m_PluginItems.Index(pi);
2738 m_PluginItems.RemoveAt(pos);
2741 m_PluginItems.Insert(pi, pos - 1);
2742 wxStaticLine* itemStaticLine =
new wxStaticLine(
2743 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2748 m_PluginSelected = pi;
2750 GetSizer()->Layout();
2756 int pos = m_PluginItems.Index(pi);
2757 if (pos == (
int)m_PluginItems.Count() -
2760 m_PluginItems.RemoveAt(pos);
2763 m_PluginItems.Insert(pi, pos + 1);
2764 wxStaticLine* itemStaticLine =
new wxStaticLine(
2765 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2770 m_PluginSelected = pi;
2772 GetSizer()->Layout();
2777static bool canUninstall(std::string name) {
2782 if (plugin.name == name) {
2786 return !plugin.readonly;
2793 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2795 m_is_safe_panel(true) {
2797 wxASSERT(m_PluginListPanel != 0);
2798 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2799 SetSizer(top_sizer);
2800 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2801 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2803 double iconSize = GetCharWidth() * 4;
2805 int icon_scale = iconSize * dpi_mult;
2807 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2808 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2809 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2811 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2812 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2813 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2814 top_horizontal->Add(m_pVersion);
2817 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2818 top_horizontal->Add(m_pButtons);
2819 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2820 top_horizontal->Add(m_info_btn);
2821 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2822 wxDefaultPosition, wxDefaultSize, 0);
2823 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2825 auto uninstall = [&](wxCommandEvent ev) {
2826 auto n = m_pName->GetLabel().ToStdString();
2827 int result = OCPNMessageBox(
2828 wxTheApp->GetTopWindow(), std::string(_(
"Uninstall plugin ")) + n +
"?",
2829 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2830 if (result != wxID_OK)
return;
2834 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2838EVT_PAINT(PluginPanel::OnPaint)
2843 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2845 m_is_safe_panel(false) {
2848 wxASSERT(m_PluginListPanel != 0);
2850 m_bSelected =
false;
2851 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2852 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2854 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2857 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2858 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2859 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2860 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2862 double iconSize = GetCharWidth() * 4;
2864 int icon_scale = iconSize * dpi_mult;
2866 wxImage plugin_icon;
2868 if (m_plugin.m_bitmap.IsOk()) {
2869 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2872 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2873 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2874 path.AppendDir(
"uidata");
2875 path.AppendDir(
"traditional");
2876 bitmap =
LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2877 }
else if (plugin_icon.IsOk()) {
2878 int nowSize = plugin_icon.GetWidth();
2879 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2880 bitmap = wxBitmap(plugin_icon);
2882 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2884 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2886 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2887 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2889 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2892 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2893 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2896 int nChars =
g_options->GetSize().x / GetCharWidth();
2897 bool bCompact =
false;
2903 wxString nameString = m_plugin.m_common_name;
2907 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2908 if (nameWidth > maxWidth) {
2909 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2910 wxELLIPSIZE_END, maxWidth);
2912 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2913 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2914 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2915 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2917 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2918 sl1->AddGrowableCol(1);
2919 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2921 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"X.YY.ZZ.AA");
2922 sl1->Add(m_pVersion, 0, wxALL, 5);
2923 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2926 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2927 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2929 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2930 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2931 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2934 wxString descriptionString = m_plugin.m_short_description;
2935 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2936 int descriptionWidth;
2937 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2938 if (descriptionWidth > maxDescriptionWidth)
2940 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2941 wxELLIPSIZE_END, maxDescriptionWidth);
2946 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2947 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2948 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2949 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2950 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2953 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2954 itemBoxSizer03->AddGrowableCol(2);
2955 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2957 wxString nameString = m_plugin.m_common_name;
2958 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2959 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2960 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2964 wxFont font = GetFont();
2965 font.SetWeight(wxFONTWEIGHT_BOLD);
2966 m_pName->SetFont(font);
2969 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2971 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"X.YY.ZZ.AA");
2972 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2973 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2975 !m_plugin.m_managed_metadata.is_orphan)) {
2978 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2979 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2981 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2982 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2983 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2985 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2987 m_pDescription =
new wxStaticText(
2988 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2990 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2991 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2992 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2996 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2998 itemBoxSizer02->Add(m_info_btn, 0);
3000 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
3001 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
3002 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
3003 wxDefaultPosition, wxDefaultSize, 0);
3004 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
3006 m_pButtons->AddSpacer(3 * GetCharWidth());
3009 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3010 wxDefaultPosition, wxDefaultSize, 0);
3011 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3013 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3014 wxDefaultPosition, wxDefaultSize, 0);
3015 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3017 m_pButtons =
new wxBoxSizer(wxVERTICAL);
3018 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
3020 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
3021 m_pButtons->Add(tline, 0, wxALL, 2);
3023 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
3024 wxDefaultPosition, wxDefaultSize, 0);
3025 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
3027 tline->AddSpacer(3 * GetCharWidth());
3029 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
3031 tline->Add(m_info_btn, 0);
3034 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3035 wxDefaultPosition, wxDefaultSize);
3036 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3038 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3039 wxDefaultPosition, wxDefaultSize, 0);
3040 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3043 wxBitmap statusBitmap;
3044 const auto stat = m_plugin.m_status;
3045 auto icon_name = icon_by_status.at(stat);
3046 if (stat == PluginStatus::Imported &&
3047 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3049 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3052 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3053 path.AppendDir(
"uidata");
3054 path.AppendDir(
"traditional");
3056 int bmsize = GetCharWidth() * 3 * dpi_mult;
3057 if (path.IsFileReadable()) {
3058 statusBitmap =
LoadSVG(path.GetFullPath(), bmsize, bmsize);
3059 ok = statusBitmap.IsOk();
3062 auto style = g_StyleManager->GetCurrentStyle();
3063 statusBitmap = wxBitmap(style->GetIcon(
"default_pi", bmsize, bmsize));
3064 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3067 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3068 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3069 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3071 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3074 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3076 itemBoxSizer02->AddSpacer(GetCharWidth());
3078 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3079 &PluginPanel::OnPluginPreferences,
this);
3080 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3081 &PluginPanel::OnPluginUninstall,
this);
3082 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3083 &PluginPanel::OnPluginAction,
this);
3085 SetSelected(m_bSelected);
3086 SetAutoLayout(
true);
3094PluginPanel::~PluginPanel() {
3095 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3096 if (m_is_safe_panel)
return;
3097 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3099 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3100 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3101 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3102 if (m_pButtonAction) {
3103 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3104 &PluginPanel::OnPluginAction,
this);
3106 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3107 &PluginPanel::OnPluginPreferences,
this);
3108 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3109 &PluginPanel::OnPluginEnableToggle,
this);
3112void PluginPanel::SetActionLabel(wxString& label) {
3113 m_pButtonAction->SetLabel(label);
3117static wxStopWatch swclick;
3118static int downx, downy;
3120void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3123 event.GetPosition(&downx, &downy);
3129void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3131 qDebug() << swclick.Time();
3132 if (swclick.Time() < 200) {
3134 event.GetPosition(&upx, &upy);
3135 if ((fabs(upx - downx) < GetCharWidth()) &&
3136 (fabs(upy - downy) < GetCharWidth())) {
3144void PluginPanel::DoPluginSelect() {
3145 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3151 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3152 }
else if (m_bSelected) {
3154 m_PluginListPanel->SelectPlugin(NULL);
3157 m_PluginListPanel->SelectPlugin(
this);
3165static PluginMetadata GetMetadataByName(
const std::string& name) {
3167 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3168 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3169 if (found == plugins.end()) {
3170 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3175void PluginPanel::SetSelected(
bool selected) {
3176 m_bSelected = selected;
3178 m_pVersion->SetLabel(
3182 m_pButtons->Show(
true);
3183 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3186 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3189 unInstallPossible =
false;
3192 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3194 m_pButtonUninstall->Show(unInstallPossible);
3196 if (m_plugin.m_managed_metadata.info_url.size()) {
3197 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3201 m_cbEnable->Show(
true);
3206 switch (m_plugin.m_status) {
3207 case PluginStatus::LegacyUpdateAvailable:
3208 label = _(
"Upgrade to Version ");
3209 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3210 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3211 m_pButtonAction->Enable();
3214 case PluginStatus::ManagedInstallAvailable:
3215 label = _(
"Install...");
3216 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3217 m_pButtonAction->Enable();
3220 case PluginStatus::ManagedInstalledUpdateAvailable:
3221 label = _(
"Update to ");
3222 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3223 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3224 m_pButtonAction->Enable();
3227 case PluginStatus::ManagedInstalledCurrentVersion:
3228 label = _(
"Reinstall");
3229 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3230 m_pButtonAction->Enable();
3233 case PluginStatus::ManagedInstalledDowngradeAvailable:
3234 label = _(
"Downgrade");
3235 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3236 m_pButtonAction->Enable();
3239 case PluginStatus::Imported:
3240 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3241 label = _(
"Update");
3242 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3244 m_pButtonAction->Hide();
3245 m_action = ActionVerb::NOP;
3250 m_action = ActionVerb::NOP;
3251 m_pButtonAction->Hide();
3255 m_action = ActionVerb::NOP;
3256 m_pButtonAction->Hide();
3261 m_action = ActionVerb::NOP;
3264 SetActionLabel(label);
3276 m_pButtons->Show(
false);
3279 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3280 m_cbEnable->Show(
false);
3301 SetEnabled(m_plugin.m_enabled);
3316void PluginPanel::OnPaint(wxPaintEvent& event) {
3319 int penWidth = m_penWidthUnselected;
3324 penWidth = m_penWidthSelected;
3329 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3331 dc.SetPen(wxPen(border, penWidth));
3333 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3336void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3337 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3340 androidDisableRotation();
3351void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3352 g_Platform->ShowBusySpinner();
3353 SetEnabled(event.IsChecked());
3354 m_pVersion->SetLabel(
3361 g_Platform->HideBusySpinner();
3364void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3365 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
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);
3374void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3376 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3377 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3378 actionEvent.SetClientData(
this);
3379 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3384static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3385 auto font = window->GetFont();
3386 font.SetStyle(style);
3387 window->SetFont(font);
3390void PluginPanel::SetEnabled(
bool enabled) {
3391 if (m_is_safe_panel)
return;
3394 if (enabled) NotifySetupOptionsPlugin(&m_plugin);
3395 if (!enabled && !m_bSelected) {
3396 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3397 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3398 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3401 m_pVersion->Disable();
3402 m_pDescription->Disable();
3405 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3406 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3407 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3410 m_pVersion->Enable();
3411 m_pDescription->Enable();
3416 m_pName->Enable(enabled || m_bSelected);
3417 m_pVersion->Enable(enabled || m_bSelected);
3418 m_pDescription->Enable(enabled || m_bSelected);
3422 wxString description = m_plugin.m_long_description;
3423 if (description.IsEmpty())
3424 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3428 m_pDescription->SetLabel(wrapper.GetWrapped());
3429 if (m_plugin.m_managed_metadata.info_url.size()) {
3430 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3434 wxString description = m_plugin.m_short_description;
3435 if (description.IsEmpty())
3436 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3439 m_pDescription->SetLabel(wrapper.GetWrapped());
3442 m_pButtonPreferences->Enable(enabled &&
3444 m_cbEnable->SetValue(enabled);
3447void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3448 m_PluginListPanel->MoveUp(
this);
3451void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3452 m_PluginListPanel->MoveDown(
this);
3457 : wxPanel(parent), m_url(url) {
3458 auto vbox =
new wxBoxSizer(wxVERTICAL);
3459 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3460 button->Enable(strlen(url) > 0);
3463 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3464 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3472PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3474PlugInChartBase::~PlugInChartBase() {}
3483 bool b_allow_overzoom) {
3495 const wxRegion& Region) {
3496 return wxNullBitmap;
3505 wxRegion* pValidRegion) {}
3518 wxRect* pSourceRect) {}
3535 double* plat,
double* plon) {}
3542PlugInChartBaseGL::PlugInChartBaseGL() {}
3544PlugInChartBaseGL::~PlugInChartBaseGL() {}
3548 const wxRegion& Region,
3549 bool b_use_stencil) {
3575PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3577PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3581 const wxRegion& Region,
3582 bool b_use_stencil) {
3588 const wxRegion& Region,
bool b_use_stencil) {
3594 const wxRegion& Region,
bool b_use_stencil) {
3600 return wxNullBitmap;
3604 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3608ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3613wxString PlugInChartBaseExtended::CreateObjDescriptions(
3614 ListOfPI_S57Obj* obj_list) {
3618int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3620int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3622int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3624float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3633PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3635PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3638PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3648PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3650PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3662ChartPlugInWrapper::ChartPlugInWrapper() {}
3664ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3665 m_ppo = ::wxCreateDynamicObject(chart_class);
3669ChartPlugInWrapper::~ChartPlugInWrapper() {
3670 if (m_ppicb)
delete m_ppicb;
3673wxString ChartPlugInWrapper::GetFileSearchMask() {
3680InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3681 ChartInitFlag init_flags) {
3683 wxWindow* pa = wxWindow::FindFocus();
3685 InitReturn ret_val = (InitReturn)m_ppicb->
Init(name, (
int)init_flags);
3689 if (ret_val == INIT_OK) {
3696 m_ID = m_ppicb->
GetID();
3700 m_SE = m_ppicb->
GetSE();
3714 if ((fabs(m_Chart_Skew) < .01) &&
3715 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3717 if (GetChartExtent(&extent)) {
3718 double lon_range = extent.ELON - extent.WLON;
3719 if ((lon_range > 0) &&
3721 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3725 m_overlayENC =
false;
3727 wxCharBuffer buf = m_FullPath.ToUTF8();
3728 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3734 m_ChartType = CHART_TYPE_UNKNOWN;
3735 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3741 if (pc) pc->SetFocus();
3745 return INIT_FAIL_REMOVE;
3749int ChartPlugInWrapper::GetCOVREntries() {
3756int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3763int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3770float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3782int ChartPlugInWrapper::GetNoCOVREntries() {
3792int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3802int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3812float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3822bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3826 pext->NLAT = xpi.
NLAT;
3827 pext->SLAT = xpi.
SLAT;
3828 pext->ELON = xpi.
ELON;
3829 pext->WLON = xpi.
WLON;
3838ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3843 if (!pThumbData->pDIBThumb) {
3844 wxBitmap* pBMPOwnedByChart =
3845 m_ppicb->
GetThumbnail(tnx, tny, m_global_color_scheme);
3846 if (pBMPOwnedByChart) {
3847 wxImage img = pBMPOwnedByChart->ConvertToImage();
3848 pThumbData->pDIBThumb =
new wxBitmap(img);
3850 pThumbData->pDIBThumb = NULL;
3853 pThumbData->Thumb_Size_X = tnx;
3854 pThumbData->Thumb_Size_Y = tny;
3881 pThumbData->ShipX = 0;
3882 pThumbData->ShipY = 0;
3889ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3891bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3895double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3896 bool b_allow_overzoom) {
3903double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3925void RenderRotateToViewPort(
const ViewPort& VPoint) {
3926#ifndef USE_ANDROID_GLES2
3928 glTranslatef(xt, yt, 0);
3929 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3930 glTranslatef(-xt, -yt, 0);
3934void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3935#ifndef USE_ANDROID_GLES2
3937 glTranslatef(xt, yt, 0);
3938 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3939 glTranslatef(-xt, -yt, 0);
3943bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3946 const LLRegion& Region) {
3955 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3956 wxRegion* r = RectRegion.GetNew_wxRegion();
3959 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3960 chart_region.Intersect(Region);
3962 if (!chart_region.Empty()) {
3963 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3965 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3969#ifndef USE_ANDROID_GLES2
3972 RenderRotateToViewPort(VPoint);
3977 glChartCanvas::s_b_useStencil);
3980 glChartCanvas::s_b_useStencil);
3981 UndoRenderRotateToViewPort(VPoint);
3983#ifndef USE_ANDROID_GLES2
3986 glChartCanvas::DisableClipRegion();
4000bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
4001 const wxGLContext& glc,
const ViewPort& VPoint,
4002 const OCPNRegion& RectRegion,
const LLRegion& Region) {
4011 if (!Region.Empty() && ppicb_x) {
4013 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
4014 glChartCanvas::DisableClipRegion();
4017 RenderRotateToViewPort(VPoint);
4020 wxRegion* r = RectRegion.GetNew_wxRegion();
4023 glChartCanvas::s_b_useStencil);
4026 UndoRenderRotateToViewPort(VPoint);
4031 else if (!Region.Empty() &&
4035 wxRegion* r = RectRegion.GetNew_wxRegion();
4038 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4039 chart_region.Intersect(Region);
4041 if (!chart_region.Empty()) {
4042 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4044 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4046 RenderRotateToViewPort(VPoint);
4050 glChartCanvas::s_b_useStencil);
4053 UndoRenderRotateToViewPort(VPoint);
4055 glChartCanvas::DisableClipRegion();
4068bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4075 if (!Region.Empty() && ppicb_x) {
4076 wxRegion* r = Region.GetNew_wxRegion();
4078#ifndef USE_ANDROID_GLES2
4081 RenderRotateToViewPort(VPoint);
4085 glChartCanvas::s_b_useStencil);
4086 UndoRenderRotateToViewPort(VPoint);
4088#ifndef USE_ANDROID_GLES2
4101bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4107 if (Region.IsOk()) {
4108 wxRegion* r = Region.GetNew_wxRegion();
4115 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4116 wxColour nodat_sub = nodat;
4118#ifdef ocpnUSE_ocpnBitmap
4119 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4121 m_pMask =
new wxMask(obmp, nodat_sub);
4122 obmp.SetMask(m_pMask);
4124 dc.SelectObject(obmp);
4135bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4146 if (Region.IsOk() && (pCBx || ppicb)) {
4147 wxRegion* r = Region.GetNew_wxRegion();
4162bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4165 bool ret_val =
false;
4168 if (Region.IsOk()) {
4169 wxRegion* r = Region.GetNew_wxRegion();
4183void ChartPlugInWrapper::ClearPLIBTextList() {
4191bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4195 return m_ppicb->
AdjustVP(pivp_last, pivp_proposed);
4200void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4215void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4219 m_global_color_scheme = cs;
4221 if (pThumbData) pThumbData->pDIBThumb = NULL;
4225 double target_scale_ppm) {
4232void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4233 wxRect* pSourceRect) {
4240double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4242 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4247bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4249 wxCriticalSectionLocker locker(m_critSect);
4258int ChartPlugInWrapper::GetSize_X() {
4265int ChartPlugInWrapper::GetSize_Y() {
4272void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4273 double& pixx,
double& pixy) {
4277void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4278 double* plat,
double* plon) {
4293 return toSDMM(NEflag, a, hi_precision);
4297 return GetGlobalColor(colorName);
4301 const wxString& caption,
int style,
int x,
int y) {
4302 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4310 return g_Platform->GetWritableDocumentsDir();
4315 auto loader = PluginLoader::GetInstance();
4316 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4318 if (pic->m_pplugin == pplugin) {
4328ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4331 ListOfPI_S57Obj* list = NULL;
4345 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4355 ListOfPI_S57Obj* rule_list) {
4366 ret_str = picbx->CreateObjDescriptions(rule_list);
4380 return ps52plib->m_nDepthUnitDisplay;
4387 return ps52plib->m_nSymbolStyle;
4394 return ps52plib->m_nBoundaryStyle;
4404 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4406 ViewPort cvp = CreateCompatibleViewport(*vp);
4411 ObjRazRules rzRules;
4412 rzRules.obj = &cobj;
4413 rzRules.LUP = pContext->LUP;
4414 rzRules.sm_transform_parms = 0;
4415 rzRules.child = NULL;
4416 rzRules.next = NULL;
4418 if (pContext->LUP) {
4419 ps52plib->SetVPointCompat(
4423 ps52plib->PrepareForRender();
4425 return ps52plib->ObjectRenderCheck(&rzRules);
4434 return ps52plib->GetStateHash();
4439void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4440 chart_context* pctx) {
4443 cobj->att_array = pObj->att_array;
4444 cobj->attVal = pObj->attVal;
4445 cobj->n_attr = pObj->n_attr;
4450 cobj->npt = pObj->npt;
4452 cobj->iOBJL = pObj->iOBJL;
4453 cobj->Index = pObj->Index;
4455 cobj->geoPt = (pt*)pObj->geoPt;
4456 cobj->geoPtz = pObj->geoPtz;
4457 cobj->geoPtMulti = pObj->geoPtMulti;
4459 cobj->m_lat = pObj->m_lat;
4460 cobj->m_lon = pObj->m_lon;
4462 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4463 cobj->x_rate = pObj->x_rate;
4464 cobj->y_rate = pObj->y_rate;
4465 cobj->x_origin = pObj->x_origin;
4466 cobj->y_origin = pObj->y_origin;
4468 cobj->Scamin = pObj->Scamin;
4469 cobj->nRef = pObj->nRef;
4470 cobj->bIsAton = pObj->bIsAton;
4471 cobj->bIsAssociable = pObj->bIsAssociable;
4473 cobj->m_n_lsindex = pObj->m_n_lsindex;
4474 cobj->m_lsindex_array = pObj->m_lsindex_array;
4475 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4478 cobj->m_ls_list_legacy =
4482 cobj->m_ls_list_legacy = 0;
4483 cobj->m_ls_list = 0;
4486 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4488 cobj->m_bcategory_mutable =
true;
4492 if (pObj->m_DPRI == -1) {
4494 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4496 cobj->m_DPRI = pObj->m_DPRI;
4499 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4500 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4502 if (pObj->auxParm3 != 1234) {
4503 pObj->auxParm3 = 1234;
4504 pObj->auxParm0 = -99;
4507 cobj->auxParm0 = pObj->auxParm0;
4514 if (pContext->bBBObj_valid)
4516 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4517 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4519 cobj->CSrules = pContext->CSrules;
4520 cobj->bCS_Added = pContext->bCS_Added;
4522 cobj->FText = pContext->FText;
4523 cobj->bFText_Added = pContext->bFText_Added;
4524 cobj->rText = pContext->rText;
4526 cobj->bIsClone =
true;
4529 cobj->m_chart_context = pctx;
4530 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4533 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4534 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4535 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4536 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4537 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4538 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4539 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4540 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4542 cobj->m_chart_context->chart =
4544 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4558 CreateCompatibleS57Object(pObj, &cobj, NULL);
4560 LUPname LUP_Name = PAPER_CHART;
4563 ctx->CSrules = NULL;
4564 ctx->bCS_Added =
false;
4567 if (ctx->bFText_Added) {
4568 ctx->bFText_Added =
false;
4574 ctx->bBBObj_valid =
true;
4579 switch (cobj.Primitive_type) {
4584 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4585 LUP_Name = PAPER_CHART;
4587 LUP_Name = SIMPLIFIED;
4596 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4597 LUP_Name = PLAIN_BOUNDARIES;
4599 LUP_Name = SYMBOLIZED_BOUNDARIES;
4604 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4608 ps52plib->_LUP2rules(lup, &cobj);
4610 ctx->MPSRulesList = NULL;
4618 pContext->bBBObj_valid =
true;
4624void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4625 ObjRazRules* rzRules) {
4629 pContext->CSrules = cobj->CSrules;
4630 pContext->bCS_Added = cobj->bCS_Added;
4632 pContext->FText = cobj->FText;
4633 pContext->bFText_Added = cobj->bFText_Added;
4634 pContext->rText = cobj->rText;
4636 if (cobj->BBObj.GetValid()) {
4639 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4640 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4641 pContext->bBBObj_valid =
true;
4646 pObj->m_DisplayCat = (
PI_DisCat)cobj->m_DisplayCat;
4650 pContext->ChildRazRules = rzRules->child;
4651 pContext->MPSRulesList = rzRules->mps;
4653 pObj->auxParm0 = cobj->auxParm0;
4657 double* lon_min,
double* lon_max) {
4660 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4661 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4662 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4663 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4664 return pContext->bBBObj_valid;
4672 LUPrec* lup = pContext->LUP;
4681 LUPrec* lup = pContext->LUP;
4691 LUPrec* lup = pContext->LUP;
4697 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4704 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4709 ObjRazRules rzRules;
4710 rzRules.obj = &cobj;
4711 rzRules.LUP = pContext->LUP;
4712 rzRules.sm_transform_parms = 0;
4713 rzRules.child = NULL;
4714 rzRules.next = NULL;
4715 rzRules.mps = pContext->MPSRulesList;
4717 if (pContext->LUP) {
4718 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4721 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4727 ps52plib->PrepareForRender();
4728 ps52plib->ClearTextList();
4731 ps52plib->EnableGLLS(
true);
4733 ps52plib->EnableGLLS(
false);
4742 if (pctx->ChildRazRules) {
4743 ObjRazRules* ctop = pctx->ChildRazRules;
4747 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4749 ObjRazRules* cnxx = ctop->next;
4755 if (pctx->MPSRulesList) {
4756 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4757 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4759 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4760 ps52plib->DestroyRulesChain(top);
4762 delete pctx->MPSRulesList->cs_rules;
4764 free(pctx->MPSRulesList);
4776 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4783 &transform.easting_vp_center, &transform.northing_vp_center);
4786 ObjRazRules rzRules;
4787 rzRules.obj = &cobj;
4788 rzRules.LUP = pContext->LUP;
4789 rzRules.sm_transform_parms = &transform;
4790 rzRules.child = pContext->ChildRazRules;
4791 rzRules.next = NULL;
4792 rzRules.mps = pContext->MPSRulesList;
4794 if (pContext->LUP) {
4795 ViewPort cvp = CreateCompatibleViewport(*vp);
4801 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4803 ps52plib->PrepareForRender();
4805 ps52plib->RenderObjectToDC(pdc, &rzRules);
4808 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4815 wxRect rect,
unsigned char* pixbuf) {
4817 render_canvas_parms pb_spec;
4819 pb_spec.depth = BPP;
4820 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4821 pb_spec.lclip = rect.x;
4822 pb_spec.rclip = rect.x + rect.width - 1;
4823 pb_spec.pix_buff = pixbuf;
4824 pb_spec.width = rect.width;
4825 pb_spec.height = rect.height;
4828#ifdef ocpnUSE_ocpnBitmap
4829 pb_spec.b_revrgb =
true;
4831 pb_spec.b_revrgb =
false;
4834 pb_spec.b_revrgb =
false;
4839 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4846 &transform.easting_vp_center, &transform.northing_vp_center);
4849 ObjRazRules rzRules;
4850 rzRules.obj = &cobj;
4851 rzRules.LUP = pContext->LUP;
4852 rzRules.sm_transform_parms = &transform;
4853 rzRules.child = pContext->ChildRazRules;
4854 rzRules.next = NULL;
4855 rzRules.mps = pContext->MPSRulesList;
4857 ViewPort cvp = CreateCompatibleViewport(*vp);
4865 if (!tess)
return 1;
4867 PolyTriGroup* ptg =
new PolyTriGroup;
4868 ptg->tri_prim_head =
4869 tess->Get_PolyTriGroup_head()->tri_prim_head;
4870 ptg->bsingle_alloc =
false;
4871 ptg->data_type = DATA_TYPE_DOUBLE;
4872 tess->Set_PolyTriGroup_head(ptg);
4874 double* pd = (
double*)malloc(
sizeof(
double));
4879 if (pContext->LUP) {
4884 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4886 ps52plib->PrepareForRender();
4888 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4891 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4903 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4914 if (!tess)
return 1;
4918 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4919 ptg->bsingle_alloc =
false;
4920 ptg->data_type = DATA_TYPE_DOUBLE;
4921 tess->Set_PolyTriGroup_head(ptg);
4925 double* pd = (
double*)malloc(
sizeof(
double));
4942 &transform.easting_vp_center, &transform.northing_vp_center);
4945 ObjRazRules rzRules;
4946 rzRules.obj = &cobj;
4947 rzRules.LUP = pContext->LUP;
4948 rzRules.sm_transform_parms = &transform;
4949 rzRules.child = pContext->ChildRazRules;
4950 rzRules.next = NULL;
4951 rzRules.mps = pContext->MPSRulesList;
4953 if (pContext->LUP) {
4954 ViewPort cvp = CreateCompatibleViewport(*vp);
4960 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4962 ps52plib->PrepareForRender();
4964 ps52plib->RenderAreaToGL(glcc, &rzRules);
4967 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4979 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4986 &transform.easting_vp_center, &transform.northing_vp_center);
4989 ObjRazRules rzRules;
4990 rzRules.obj = &cobj;
4991 rzRules.LUP = pContext->LUP;
4992 rzRules.sm_transform_parms = &transform;
4993 rzRules.child = pContext->ChildRazRules;
4994 rzRules.next = NULL;
4995 rzRules.mps = pContext->MPSRulesList;
4997 if (pContext->LUP) {
4998 ViewPort cvp = CreateCompatibleViewport(*vp);
5004 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
5006 ps52plib->PrepareForRender();
5008 ps52plib->RenderObjectToGL(glcc, &rzRules);
5011 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
5021OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
5022 : wxEvent(id, commandType) {
5025 m_b_complete =
false;
5029OCPN_downloadEvent::~OCPN_downloadEvent() {}
5031wxEvent* OCPN_downloadEvent::Clone()
const {
5033 newevent->m_stat = this->m_stat;
5034 newevent->m_condition = this->m_condition;
5036 newevent->m_totalBytes = this->m_totalBytes;
5037 newevent->m_sofarBytes = this->m_sofarBytes;
5038 newevent->m_b_complete = this->m_b_complete;
5044DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5049#define DL_EVENT_TIMER 4388
5057 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5058 void clearBackgroundMode();
5059 void onTimerEvent(wxTimerEvent& event);
5062 wxTimer m_eventTimer;
5063 wxEvtHandler* m_download_evHandler;
5069PI_DLEvtHandler::PI_DLEvtHandler() {
5073 m_download_evHandler = NULL;
5079PI_DLEvtHandler::~PI_DLEvtHandler() {
5080 m_eventTimer.Stop();
5083 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5090 g_download_status =
event.getDLEventStatus();
5091 g_download_condition =
event.getDLEventCondition();
5094 if (m_download_evHandler &&
5097 ev.setComplete(
true);
5098 ev.setTransferred(m_sofarBytes);
5099 ev.setTotal(m_totalBytes);
5101 ev.setDLEventStatus(event.getDLEventStatus());
5104 m_download_evHandler->AddPendingEvent(ev);
5105 m_eventTimer.Stop();
5107 finishAndroidFileDownload();
5114void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5116 m_download_evHandler = handler;
5118 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5122 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5123 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5126void PI_DLEvtHandler::clearBackgroundMode() {
5127 m_download_evHandler = NULL;
5128 m_eventTimer.Stop();
5131void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5137 int stat = queryAndroidFileDownload(m_id, &sstat);
5140 long sofarBytes = 0;
5141 long totalBytes = -1;
5145 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5146 ev.setComplete(
true);
5147 ev.setTransferred(sofarBytes);
5148 ev.setTotal(totalBytes);
5153 wxStringTokenizer tk(sstat,
";");
5154 if (tk.HasMoreTokens()) {
5155 wxString token = tk.GetNextToken();
5156 token.ToLong(&state);
5157 token = tk.GetNextToken();
5158 token.ToLong(&sofarBytes);
5159 token = tk.GetNextToken();
5160 token.ToLong(&totalBytes);
5163 qDebug() << state << sofarBytes << totalBytes;
5165 m_sofarBytes = sofarBytes;
5166 m_totalBytes = totalBytes;
5168 ev.setTransferred(sofarBytes);
5169 ev.setTotal(totalBytes);
5172 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5173 ev.setComplete(
true);
5176 }
else if (state == 8) {
5177 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5178 ev.setComplete(
true);
5182 ev.setComplete(
false);
5190 if (m_download_evHandler) {
5192 m_download_evHandler->AddPendingEvent(ev);
5197 m_eventTimer.Stop();
5198 finishAndroidFileDownload();
5208 const wxString& outputFile,
5209 const wxString& title,
const wxString& message,
5210 const wxBitmap& bitmap, wxWindow* parent,
5211 long style,
int timeout_secs) {
5214 wxString msg =
"Downloading file synchronously: ";
5221 int vres = validateAndroidWriteLocation(outputFile);
5233 g_piEventHandler->Connect(
5234 wxEVT_DOWNLOAD_EVENT,
5235 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5240 wxString fURI = outputFile;
5241 if (!fURI.StartsWith(
"file://")) {
5242 fURI.Prepend(
"file://");
5245 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5248 finishAndroidFileDownload();
5249 g_piEventHandler->Disconnect(
5250 wxEVT_DOWNLOAD_EVENT,
5251 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5256 wxDateTime dl_start_time = wxDateTime::Now();
5260 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5261 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5263 if (dt.GetSeconds() > timeout_secs) {
5264 qDebug() <<
"USER_TIMOUT";
5265 finishAndroidFileDownload();
5266 g_piEventHandler->Disconnect(
5267 wxEVT_DOWNLOAD_EVENT,
5268 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5276 finishAndroidFileDownload();
5277 g_piEventHandler->Disconnect(
5278 wxEVT_DOWNLOAD_EVENT,
5282 qDebug() <<
"RETURN DL_END" << (int)ss;
5288 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5290 qDebug() <<
"Error on queryAndroidFileDownload";
5291 finishAndroidFileDownload();
5292 g_piEventHandler->Disconnect(
5293 wxEVT_DOWNLOAD_EVENT,
5294 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5304#elif defined(OCPN_USE_CURL)
5305 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5306 wxFileOutputStream output(tfn.GetFullPath());
5308 wxCurlDownloadDialog ddlg(url, &output, title, message, bitmap, parent,
5310 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5316 case wxCDRF_SUCCESS: {
5317 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5323 case wxCDRF_FAILED: {
5327 case wxCDRF_USER_ABORTED: {
5335 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5345 return ocpn::toUsrDateTimeFormat(date_time,
options);
5350 const wxString& outputFile,
5351 wxEvtHandler* handler,
5354 wxString msg =
"Downloading file asynchronously: ";
5366 int res = startAndroidFileDownload(url, outputFile, NULL ,
5370 finishAndroidFileDownload();
5375 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5377 if (handle) *handle = dl_ID;
5381#elif defined(OCPN_USE_CURL)
5388 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5391 dynamic_cast<wxCurlHTTP*
>(
g_pi_manager->m_pCurl.get())) {
5398 bool failed =
false;
5407 new wxFileOutputStream(outputFile)),
5415 wxCurlThreadError err =
g_pi_manager->m_pCurlThread->Download();
5416 if (err != wxCTE_NO_ERROR) {
5430 delete (
g_pi_manager->m_pCurlThread->GetOutputStream());
5448 cancelAndroidFileDownload(handle);
5449 finishAndroidFileDownload();
5450 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5454 delete (
g_pi_manager->m_pCurlThread->GetOutputStream());
5465 const wxString& parameters, wxString& result,
5468 wxString lparms = parameters;
5469 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5472 result = postResult;
5475#elif defined(OCPN_USE_CURL)
5477 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5478 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5481 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5484 result = wxEmptyString;
5495 return androidCheckOnline();
5498#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5499 if (wxDateTime::GetTimeNow() >
5500 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5502 get.Head(
"http://yahoo.com/");
5503 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5505 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5513#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5514void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5516 if (ev.IsSuccessful()) {
5523 event.setComplete(
true);
5525 if (m_download_evHandler) {
5526 m_download_evHandler->AddPendingEvent(event);
5527 m_download_evHandler = NULL;
5528 m_downloadHandle = NULL;
5531 if (m_pCurlThread) {
5532 m_pCurlThread->Wait();
5533 if (!m_pCurlThread->IsAborting()) {
5534 delete (m_pCurlThread->GetOutputStream());
5535 wxDELETE(m_pCurlThread);
5540void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5544 event.setTotal(ev.GetTotalBytes());
5545 event.setTransferred(ev.GetDownloadedBytes());
5546 event.setComplete(
false);
5548 if (m_download_evHandler) {
5549 m_download_evHandler->AddPendingEvent(event);
5553bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5554 wxCurlBaseThread* p,
5555 const wxString& url) {
5557 case wxCTE_NO_ERROR:
5560 case wxCTE_NO_RESOURCE:
5562 wxS(
"Insufficient resources for correct execution of the program."));
5565 case wxCTE_ALREADY_RUNNING:
5569 case wxCTE_INVALID_PROTOCOL:
5570 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5574 case wxCTE_NO_VALID_STREAM:
5581 case wxCTE_CURL_ERROR: {
5582 wxString ws = wxS(
"unknown");
5583 if (p->GetCurlSession())
5585 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5586 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5591 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.
obs::EventVar plugin_msg_evt
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
Connection data container close to a POD struct.
bool SentencePassesFilter(const wxString &sentence, FilterDirection direction) const
Return true if given sentence and direction passes connection filters.
Downloader with progress and final message dialogs.
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.
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listeners 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.
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.
obs::EventVar evt_pluglist_change
Notified without data when the GetPlugInArray() list is changed.
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
Return string used by Notify() and Listen().
obs::EventVar on_message_sent
Notified when a message available as GetString() is sent to garmin.
obs::EventVar json_leg_info
Notified with a shared_ptr<ActiveLegDat>, leg info to all plugins.
obs::EventVar json_msg_evt
Notified with message targeting all plugins.
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).
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.
Interface implemented by classes which listens.
Device context class that can use either wxDC or OpenGL for drawing.
virtual void PrepareContextMenu(int canvasIndex)
Prepares plugin context menu items.
virtual bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvasIndex)
Renders plugin overlay graphics in standard DC mode for multi-canvas support.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex)
Renders plugin overlay graphics in OpenGL mode for multi-canvas support.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex, int priority)
Renders plugin overlay graphics in OpenGL mode with priority control.
virtual bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvas_ix, int priority)
Renders plugin overlay graphics in standard DC mode with priority control.
virtual bool RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in standard DC mode for single canvas.
virtual bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in OpenGL mode for single canvas.
Base class for OpenCPN plugins.
virtual void OnCloseToolboxPanel(int page_sel, int ok_apply_cancel)
Handles preference page closure.
virtual void SetCurrentViewPort(PlugIn_ViewPort &vp)
Notifies plugin of viewport changes.
virtual void UpdateAuiStatus(void)
Updates AUI manager status.
virtual void SetColorScheme(PI_ColorScheme cs)
Updates plugin color scheme.
virtual wxArrayString GetDynamicChartClassNameArray(void)
Returns array of dynamically loaded chart class names.
virtual wxString GetCommonName()
Get the plugin's common (short) name.
virtual int GetPlugInVersionMajor()
Returns the major version number of the plugin itself.
virtual bool RenderOverlay(wxMemoryDC *pmdc, PlugIn_ViewPort *vp)
Render plugin overlay graphics using standard device context.
virtual void ProcessParentResize(int x, int y)
Handles parent window resize events.
virtual int GetPlugInVersionMinor()
Returns the minor version number of the plugin itself.
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.
Notify()/Listen() configuration variable wrapper.
Generic GUI downloads tool.
Handle downloading of files from remote urls.
OpenGL chart rendering canvas.
Global variables Listen()/Notify() wrapper.
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.
bool GetMode()
Return true if we are running in safe mode.
MyConfig * pConfig
Global instance.
Navigation Utility Functions without GUI dependencies.
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.