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"
93#include "observable/configvar.h"
94#include "observable/global_var.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);
187class RawKey :
public obs::KeyProvider {
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 (
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<wxString> 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 =
983 params.SentencePassesFilter(payload.c_str(), FILTER_INPUT);
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) {
1701 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1702 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1704 if (pic->m_enabled && pic->m_init_state)
1709void PlugInManager::PrepareAllPluginContextMenus() {
1710 int canvasIndex = top_frame::Get()->GetCanvasIndexUnderMouse();
1711 if (canvasIndex < 0)
return;
1713 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1714 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1716 if (pic->m_enabled && pic->m_init_state) {
1718 switch (pic->m_api_version) {
1738void PlugInManager::SendSKConfigToAllPlugIns() {
1741 v[
"self"] = g_ownshipMMSI_SK;
1742 std::string out = v.dump();
1743 SendMessageToAllPlugins(
"OCPN_CORE_SIGNALK", out);
1746void PlugInManager::SendBaseConfigToAllPlugIns() {
1749 v[
"OpenCPN Version Major"] = VERSION_MAJOR;
1750 v[
"OpenCPN Version Minor"] = VERSION_MINOR;
1751 v[
"OpenCPN Version Patch"] = VERSION_PATCH;
1752 v[
"OpenCPN Version Date"] = VERSION_DATE;
1753 v[
"OpenCPN Version Full"] = VERSION_FULL;
1757 v[
"OpenCPN Toolbar Width"] =
g_MainToolbar->GetToolbarRect().width;
1758 v[
"OpenCPN Toolbar Height"] =
g_MainToolbar->GetToolbarRect().height;
1759 v[
"OpenCPN Toolbar PosnX"] =
g_MainToolbar->GetToolbarRect().x;
1760 v[
"OpenCPN Toolbar PosnY"] =
g_MainToolbar->GetToolbarRect().y;
1764 v[
"OpenCPN Zoom Mod Vector"] = g_chart_zoom_modifier_vector;
1765 v[
"OpenCPN Zoom Mod Other"] = g_chart_zoom_modifier_raster;
1766 v[
"OpenCPN Scale Factor Exp"] =
1767 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1772 std::string out = v.dump();
1773 SendMessageToAllPlugins(
"OpenCPN Config", out);
1776void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1779 v[
"OpenCPN Version Major"] = VERSION_MAJOR;
1780 v[
"OpenCPN Version Minor"] = VERSION_MINOR;
1781 v[
"OpenCPN Version Patch"] = VERSION_PATCH;
1782 v[
"OpenCPN Version Date"] = VERSION_DATE;
1783 v[
"OpenCPN Version Full"] = VERSION_FULL;
1791 v[
"OpenCPN S52PLIB ShowAnchorConditions"] = ps52plib->GetAnchorOn();
1792 v[
"OpenCPN S52PLIB ShowQualityOfData"] = ps52plib->GetQualityOfData();
1797 v[
"OpenCPN S52PLIB MetaDisplay"] = ps52plib->m_bShowMeta;
1798 v[
"OpenCPN S52PLIB DeclutterText"] = ps52plib->m_bDeClutterText;
1799 v[
"OpenCPN S52PLIB ShowNationalText"] = ps52plib->m_bShowNationalTexts;
1800 v[
"OpenCPN S52PLIB ShowImportantTextOnly"] =
1801 ps52plib->m_bShowS57ImportantTextOnly;
1802 v[
"OpenCPN S52PLIB UseSCAMIN"] = ps52plib->m_bUseSCAMIN;
1803 v[
"OpenCPN S52PLIB UseSUPER_SCAMIN"] = ps52plib->m_bUseSUPER_SCAMIN;
1804 v[
"OpenCPN S52PLIB SymbolStyle"] = ps52plib->m_nSymbolStyle;
1805 v[
"OpenCPN S52PLIB BoundaryStyle"] = ps52plib->m_nBoundaryStyle;
1806 v[
"OpenCPN S52PLIB ColorShades"] = S52_getMarinerParam(S52_MAR_TWO_SHADES);
1807 v[
"OpenCPN S52PLIB Safety Depth"] =
1808 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1809 v[
"OpenCPN S52PLIB Shallow Contour"] =
1810 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1811 v[
"OpenCPN S52PLIB Deep Contour"] =
1812 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1816 v[
"OpenCPN S52PLIB GlobalReconfig"] = bReconfig;
1818 const std::string out = v.dump();
1819 SendMessageToAllPlugins(
"OpenCPN Config", out);
1822void PlugInManager::NotifyAuiPlugIns() {
1823 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1824 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1826 if (pic->m_enabled && pic->m_init_state &&
1832int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1833 wxBitmap* bmpRollover, wxItemKind kind,
1834 wxString shortHelp, wxString longHelp,
1835 wxObject* clientData,
int position,
1838 pttc->label = label;
1840 if (!bitmap->IsOk()) {
1842 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1845 pttc->bitmap_day =
new wxBitmap(*bitmap);
1846 pttc->bitmap_day->UnShare();
1849 if (!bmpRollover->IsOk()) {
1851 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1854 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1855 pttc->bitmap_Rollover_day->UnShare();
1858 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1859 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1860 pttc->bitmap_Rollover_dusk =
1861 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1862 pttc->bitmap_Rollover_night =
1863 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1866 pttc->shortHelp = shortHelp;
1867 pttc->longHelp = longHelp;
1868 pttc->clientData = clientData;
1869 pttc->position = position;
1870 pttc->m_pplugin = pplugin;
1871 pttc->tool_sel = tool_sel;
1873 pttc->b_toggle =
false;
1874 pttc->id = m_plugin_tool_id_next;
1876 m_PlugInToolbarTools.Add(pttc);
1878 m_plugin_tool_id_next++;
1883int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1884 wxString SVGRolloverfile,
1885 wxString SVGToggledfile, wxItemKind kind,
1886 wxString shortHelp, wxString longHelp,
1887 wxObject* clientData,
int position,
1890 pttc->label = label;
1892 pttc->pluginNormalIconSVG = SVGfile;
1893 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1894 pttc->pluginToggledIconSVG = SVGToggledfile;
1899 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1900 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1901 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1902 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1903 pttc->bitmap_Rollover_dusk =
1904 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1905 pttc->bitmap_Rollover_night =
1906 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1909 pttc->shortHelp = shortHelp;
1910 pttc->longHelp = longHelp;
1911 pttc->clientData = clientData;
1912 pttc->position = position;
1913 pttc->m_pplugin = pplugin;
1914 pttc->tool_sel = tool_sel;
1916 pttc->b_toggle =
false;
1917 pttc->id = m_plugin_tool_id_next;
1919 m_PlugInToolbarTools.Add(pttc);
1921 m_plugin_tool_id_next++;
1926void PlugInManager::RemoveToolbarTool(
int tool_id) {
1927 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1930 if (pttc->id == tool_id) {
1931 m_PlugInToolbarTools.Remove(pttc);
1937 m_parent->RequestNewToolbars();
1940void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1941 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1944 if (pttc->id == item) {
1946 m_parent->RequestNewToolbars();
1953void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1954 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1957 if (pttc->id == item) {
1958 pttc->b_toggle = toggle;
1959 m_parent->SetMasterToolbarItemState(item, toggle);
1966void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1967 wxBitmap* bmpRollover) {
1968 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1971 if (pttc->id == item) {
1972 delete pttc->bitmap_day;
1973 delete pttc->bitmap_dusk;
1974 delete pttc->bitmap_night;
1975 delete pttc->bitmap_Rollover_day;
1977 if (!bitmap->IsOk()) {
1979 pttc->bitmap_day =
new wxBitmap(style->GetIcon(
"default_pi"));
1982 pttc->bitmap_day =
new wxBitmap(*bitmap);
1983 pttc->bitmap_day->UnShare();
1986 if (!bmpRollover->IsOk()) {
1988 pttc->bitmap_Rollover_day =
1989 new wxBitmap(style->GetIcon(
"default_pi"));
1992 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1993 pttc->bitmap_Rollover_day->UnShare();
1996 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1997 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1999 m_parent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
2000 pttc->bitmap_Rollover_day);
2007void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2008 wxString SVGfileRollover,
2009 wxString SVGfileToggled) {
2010 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2013 if (pttc->id == item) {
2014 pttc->pluginNormalIconSVG = SVGfile;
2015 pttc->pluginRolloverIconSVG = SVGfileRollover;
2016 pttc->pluginToggledIconSVG = SVGfileToggled;
2017 m_parent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2018 pttc->pluginRolloverIconSVG,
2019 pttc->pluginToggledIconSVG);
2027 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2029 if (
id == pc->id)
return pc->m_pplugin;
2035wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2038 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2039 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2041 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2045 return wxEmptyString;
2048wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2050wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2051 unsigned char dim_ratio) {
2052 wxImage img_dup = pbmp_normal->ConvertToImage();
2054 if (!img_dup.IsOk())
return NULL;
2056 if (dim_ratio < 200) {
2058 int gimg_width = img_dup.GetWidth();
2059 int gimg_height = img_dup.GetHeight();
2061 double factor = (double)(dim_ratio) / 256.0;
2063 for (
int iy = 0; iy < gimg_height; iy++) {
2064 for (
int ix = 0; ix < gimg_width; ix++) {
2065 if (!img_dup.IsTransparent(ix, iy)) {
2066 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2067 img_dup.GetGreen(ix, iy),
2068 img_dup.GetBlue(ix, iy));
2069 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2070 hsv.value = hsv.value * factor;
2071 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2072 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2078 wxBitmap* ptoolBarBitmap;
2081 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2083 dwxdc.SelectObject(tbmp);
2085 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2087 ptoolBarBitmap =
new wxBitmap(img_dup);
2091 return ptoolBarBitmap;
2094wxArrayString PlugInManager::GetPlugInChartClassNameArray() {
2095 wxArrayString array;
2096 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2097 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2099 if (pic && pic->m_enabled && pic->m_init_state &&
2104 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2105 array.Add(carray[j]);
2113 while (j < array.GetCount()) {
2114 wxString test = array[j];
2115 unsigned int k = j + 1;
2116 while (k < array.GetCount()) {
2117 if (test == array[k]) {
2132 const wxString& ChartClassName) {
2134 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2135 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2137 if (pic && pic->m_enabled && pic->m_init_state &&
2142 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2143 if (carray[j].IsSameAs(ChartClassName)) {
2144 plugin = pic->m_pplugin;
2158#define DISABLED_SETTINGS_MSG \
2159 _("These settings might destabilize OpenCPN and are by default disabled." \
2160 " To despite the dangers enable them manually add a CatalogExpert=1" \
2161 " line in the [PlugIns] section in the configuration file.")
2166CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2167 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2169 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2172 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2174 wxStaticBox* itemStaticBoxSizer4Static =
2175 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2176 wxStaticBoxSizer* itemStaticBoxSizer4 =
2177 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2178 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2182 m_catalogText =
new wxStaticText(
this, wxID_STATIC,
"");
2183 itemStaticBoxSizer4->Add(m_catalogText,
2184 wxSizerFlags().Border().Proportion(1));
2185 m_catalogText->SetLabel(GetCatalogText(
false));
2188 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2189 itemStaticBoxSizer4->Add(rowSizer2,
2190 wxSizerFlags().Expand().Border().Proportion(1));
2192 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2193 wxDefaultPosition, wxDefaultSize, 0);
2194 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2195 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2196 &CatalogMgrPanel::OnUpdateButton,
this);
2197 rowSizer2->AddSpacer(4 * GetCharWidth());
2198 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2199 wxDefaultPosition, wxDefaultSize, 0);
2200 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2201 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2202 &CatalogMgrPanel::OnTarballButton,
this);
2204 rowSizer2->AddSpacer(4 * GetCharWidth());
2205 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2206 wxDefaultPosition, wxDefaultSize, 0);
2207 obs::ConfigVar<bool> expert(
"/PlugIns",
"CatalogExpert",
pConfig);
2208 if (expert.Get(
false)) {
2209 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2210 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2212 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2213 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2216 rowSizer2->AddSpacer(4 * GetCharWidth());
2217 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2219 SetUpdateButtonLabel();
2222 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2223 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2225 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2228 obs::GlobalVar<wxString> catalog(&g_catalog_channel);
2229 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2230 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2231 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2234 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2235 obs::ConfigVar<bool> expert(
"/PlugIns",
"CatalogExpert",
pConfig);
2236 if (!expert.Get(
false)) {
2238 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2239 wxDefaultPosition, wxDefaultSize, 0);
2240 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2241 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2242 &CatalogMgrPanel::OnUpdateButton,
this);
2243 SetUpdateButtonLabel();
2244 m_tarballButton = NULL;
2245 m_adv_button = NULL;
2248 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2249 itemStaticBoxSizer4->Add(m_catalogText,
2250 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2253 m_updateButton =
new wxButton(
2254 this, wxID_ANY,
"Update Plugin Catalog:master ",
2255 wxDefaultPosition, wxDefaultSize, 0);
2256 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2257 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2258 &CatalogMgrPanel::OnUpdateButton,
this);
2259 SetUpdateButtonLabel();
2262 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2263 wxDefaultPosition, wxDefaultSize, 0);
2264 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2266 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2267 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2270 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2271 wxDefaultPosition, wxDefaultSize, 0);
2272 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2273 2 * GetCharWidth());
2274 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2275 &CatalogMgrPanel::OnTarballButton,
this);
2281CatalogMgrPanel::~CatalogMgrPanel() {
2282 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2283 &CatalogMgrPanel::OnUpdateButton,
this);
2284 if (m_tarballButton)
2285 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2286 &CatalogMgrPanel::OnTarballButton,
this);
2289static const char*
const DOWNLOAD_REPO_PROTO =
2290 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2293void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2295 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2296 std::string url(g_catalog_custom_url);
2297 if (catalog !=
"custom") {
2298 url = std::string(DOWNLOAD_REPO_PROTO);
2302 std::string filePath =
2303 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2305 auto catalogHdlr = CatalogHandler::GetInstance();
2307 g_Platform->ShowBusySpinner();
2308 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2309 g_Platform->HideBusySpinner();
2311 std::string message;
2312 if (status != CatalogHandler::ServerStatus::OK) {
2313 message = _(
"Cannot download data from url");
2314 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2315 wxICON_ERROR | wxOK);
2321 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2323 wxFileName::GetPathSeparator() +
2324 "ocpn-plugins.xml")) {
2325 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2326 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2331 if (!wxCopyFile(wxString(filePath.c_str()),
2333 wxFileName::GetPathSeparator() +
"ocpn-plugins.xml")) {
2334 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2335 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2341 if (catalog ==
"master") {
2343 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2344 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2350 pConfig->SetPath(
"/PlugIns/");
2351 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2358 pluginHandler->setMetadata(
"");
2362 auto cataloghdlr = CatalogHandler::GetInstance();
2363 cataloghdlr->ClearCatalogData();
2366 LoadAllPlugIns(
false);
2370 m_catalogText->SetLabel(GetCatalogText(
true));
2373 OCPNMessageBox(
this, _(
"Catalog update successful"),
2374 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2377void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2381 androidDisableRotation();
2384 dialog->ShowModal();
2387 androidEnableRotation();
2391void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2394 int response = g_Platform->DoFileSelectorDialog(
2395 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2396 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2398 if (response != wxID_OK) {
2403 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2407 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2408 _(
"OpenCPN Plugin Import Error"));
2412 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2413 _(
"OpenCPN Plugin Import Error"));
2414 handler->Uninstall(metadata.name);
2417 UninstallPlugin(metadata.name);
2418 ok = handler->InstallPlugin(metadata, path.ToStdString());
2420 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2421 _(
"OpenCPN Plugin Import Error"));
2424 metadata.is_imported =
true;
2426 std::ofstream file(metadata_path);
2429 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2430 <<
" for imported plugin: " << metadata.name;
2432 LoadAllPlugIns(
false,
true);
2435 wxString ws(_(
"Plugin"));
2436 ws += metadata.name + _(
" successfully imported");
2437 OCPNMessageBox(wxTheApp->GetTopWindow(), ws, _(
"Installation complete"),
2438 wxICON_INFORMATION | wxOK | wxCENTRE);
2441wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2443 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2447 pConfig->SetPath(
"/PlugIns/");
2448 wxString latestCatalog =
pConfig->Read(
"LatestCatalogDownloaded",
"default");
2449 catalog += latestCatalog;
2455 std::string date = pluginHandler->GetCatalogData()->date;
2457 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2458 if (!updated) catalog +=
" : " + _(
"Please Update Plugin Catalog.");
2464void CatalogMgrPanel::SetUpdateButtonLabel() {
2465 wxString label = _(
"Update Plugin Catalog");
2467 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2468 m_updateButton->SetLabel(label);
2472wxString CatalogMgrPanel::GetImportInitDir() {
2474 pConfig->SetPath(
"/PlugIns/");
2475 wxString lastImportDir;
2477 pConfig->Read(
"LatestImportDir", g_Platform->GetWritableDocumentsDir());
2478 if (wxDirExists(lastImportDir)) {
2479 return lastImportDir;
2481 return (g_Platform->GetWritableDocumentsDir());
2490 const wxPoint& pos, const wxSize& size)
2491 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2492 m_PluginSelected(0) {
2493 m_is_loading.clear();
2494 SetSizer(
new wxBoxSizer(wxVERTICAL));
2495 ReloadPluginPanels();
2498void PluginListPanel::SelectByName(wxString& name) {
2499 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2500 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2502 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2503 pluginPanel->SetSelected(
true);
2504 pluginPanel->Layout();
2505 SelectPlugin(pluginPanel);
2514 std::vector<const PlugInData*> result;
2515 auto loader = PluginLoader::GetInstance();
2516 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2517 auto const item = loader->GetPlugInArray()->Item(i);
2518 if (item->m_managed_metadata.name.empty()) {
2519 const auto name = item->m_common_name.ToStdString();
2523 result.push_back(item);
2526 std::string slhs, srhs;
2527 for (
auto& cl : lhs->
Key()) slhs += toupper(cl);
2528 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2529 return slhs.compare(srhs) < 0;
2531 std::sort(result.begin(), result.end(), compare);
2536static bool IsPluginLoaded(
const std::string& name) {
2540 std::find(installed.begin(), installed.end(),
ocpn::tolower(name));
2541 return found != installed.end();
2544 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2545 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2552 if (m_is_loading.test_and_set()) {
2554 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2559 m_PluginItems.Clear();
2561 wxWindowList kids = GetChildren();
2562 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2563 wxWindowListNode* node = kids.Item(i);
2564 wxWindow* win = node->GetData();
2566 if (pp) win->Destroy();
2568 GetSizer()->Clear();
2571 m_PluginSelected = 0;
2576 for (
const auto& name : installed) AddPlugin(name);
2579 auto available = getCompatiblePlugins();
2583 return IsPluginLoaded(md.name);
2585 auto end = std::remove_if(available.begin(), available.end(), predicate);
2586 available.erase(end, available.end());
2592 std::string slhs, srhs;
2593 for (
auto& cl : lhs.name) slhs += toupper(cl);
2594 for (
auto& cr : rhs.name) srhs += toupper(cr);
2595 return slhs.compare(srhs) < 0;
2599 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2600 for (
const auto& p : available) unique_sorted_entries.insert(p);
2606 if (p->m_enabled) AddPlugin(*p);
2610 if (!p->m_enabled) AddPlugin(*p);
2613 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2621 m_is_loading.clear();
2624void PluginListPanel::AddPlugin(
const std::string& name) {
2627 panel->SetSelected(
false);
2628 GetSizer()->Add(panel, 0, wxEXPAND);
2629 m_PluginItems.Add(panel);
2630 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2631 GetSizer()->AddSpacer(m_pluginSpacer);
2634void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2636 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2637 pPluginPanel->SetSelected(
false);
2638 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2639 m_PluginItems.Add(pPluginPanel);
2641 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2642 GetSizer()->AddSpacer(m_pluginSpacer);
2655int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2656 wxBoxSizer* sizer) {
2658 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2659 auto panel = plugins.Item(i);
2660 bool was_selected = panel->GetSelected();
2661 panel->SetSelected(
false);
2663 wxSize unselected = panel->GetSize();
2665 panel->SetSelected(
true);
2667 wxSize selected = panel->GetSize();
2669 int dy = selected.GetHeight() - unselected.GetHeight();
2670 max_dy = wxMax(max_dy, dy);
2671 panel->SetSelected(was_selected);
2676PluginListPanel::~PluginListPanel() {}
2678void PluginListPanel::UpdateSelections() {
2679 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2682 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2687void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2689 GetViewStart(&xs, &ys);
2692 if (m_PluginSelected) {
2693 m_PluginSelected->SetSelected(
false);
2694 m_PluginSelected->Layout();
2697 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2699 m_PluginSelected = pi;
2701 GetSizer()->Layout();
2703 wxSize size = GetBestVirtualSize();
2704 SetVirtualSize(size);
2709 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2711 int yd = pPluginPanel->GetSize().y;
2713 htop += m_pluginSpacer;
2714 if (pPluginPanel == pi) {
2715 int piBottom = htop - (ys *
g_options->GetScrollRate());
2716 if (piBottom > GetClientSize().y) {
2717 ys += (piBottom - GetClientSize().y) /
g_options->GetScrollRate();
2727 int pos = m_PluginItems.Index(pi);
2730 m_PluginItems.RemoveAt(pos);
2733 m_PluginItems.Insert(pi, pos - 1);
2734 wxStaticLine* itemStaticLine =
new wxStaticLine(
2735 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2740 m_PluginSelected = pi;
2742 GetSizer()->Layout();
2748 int pos = m_PluginItems.Index(pi);
2749 if (pos == (
int)m_PluginItems.Count() -
2752 m_PluginItems.RemoveAt(pos);
2755 m_PluginItems.Insert(pi, pos + 1);
2756 wxStaticLine* itemStaticLine =
new wxStaticLine(
2757 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2762 m_PluginSelected = pi;
2764 GetSizer()->Layout();
2769static bool canUninstall(std::string name) {
2774 if (plugin.name == name) {
2778 return !plugin.readonly;
2785 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2787 m_is_safe_panel(true) {
2789 wxASSERT(m_PluginListPanel != 0);
2790 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2791 SetSizer(top_sizer);
2792 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2793 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2795 double iconSize = GetCharWidth() * 4;
2797 int icon_scale = iconSize * dpi_mult;
2799 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2800 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2801 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2803 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2804 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2805 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2806 top_horizontal->Add(m_pVersion);
2809 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2810 top_horizontal->Add(m_pButtons);
2811 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2812 top_horizontal->Add(m_info_btn);
2813 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2814 wxDefaultPosition, wxDefaultSize, 0);
2815 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2817 auto uninstall = [&](wxCommandEvent ev) {
2818 auto n = m_pName->GetLabel().ToStdString();
2819 int result = OCPNMessageBox(
2820 wxTheApp->GetTopWindow(), std::string(_(
"Uninstall plugin ")) + n +
"?",
2821 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2822 if (result != wxID_OK)
return;
2826 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2830EVT_PAINT(PluginPanel::OnPaint)
2835 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2837 m_is_safe_panel(false) {
2840 wxASSERT(m_PluginListPanel != 0);
2842 m_bSelected =
false;
2843 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2844 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2846 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2849 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2850 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2851 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2852 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2854 double iconSize = GetCharWidth() * 4;
2856 int icon_scale = iconSize * dpi_mult;
2858 wxImage plugin_icon;
2860 if (m_plugin.m_bitmap.IsOk()) {
2861 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2864 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2865 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2866 path.AppendDir(
"uidata");
2867 path.AppendDir(
"traditional");
2868 bitmap =
LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2869 }
else if (plugin_icon.IsOk()) {
2870 int nowSize = plugin_icon.GetWidth();
2871 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2872 bitmap = wxBitmap(plugin_icon);
2874 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2876 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2878 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2879 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2881 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2884 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2885 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2888 int nChars =
g_options->GetSize().x / GetCharWidth();
2889 bool bCompact =
false;
2895 wxString nameString = m_plugin.m_common_name;
2899 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2900 if (nameWidth > maxWidth) {
2901 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2902 wxELLIPSIZE_END, maxWidth);
2904 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2905 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2906 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2907 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2909 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2910 sl1->AddGrowableCol(1);
2911 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2913 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"X.YY.ZZ.AA");
2914 sl1->Add(m_pVersion, 0, wxALL, 5);
2915 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2918 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2919 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2921 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2922 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2923 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2926 wxString descriptionString = m_plugin.m_short_description;
2927 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2928 int descriptionWidth;
2929 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2930 if (descriptionWidth > maxDescriptionWidth)
2932 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2933 wxELLIPSIZE_END, maxDescriptionWidth);
2938 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2939 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2940 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2941 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2942 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2945 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2946 itemBoxSizer03->AddGrowableCol(2);
2947 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2949 wxString nameString = m_plugin.m_common_name;
2950 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2951 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2952 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2956 wxFont font = GetFont();
2957 font.SetWeight(wxFONTWEIGHT_BOLD);
2958 m_pName->SetFont(font);
2961 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2963 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"X.YY.ZZ.AA");
2964 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2965 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2968 !m_plugin.m_managed_metadata.is_orphan)) {
2971 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2972 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2974 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2975 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2976 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2978 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2980 m_pDescription =
new wxStaticText(
2981 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2983 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2984 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2985 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2989 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2991 itemBoxSizer02->Add(m_info_btn, 0);
2993 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2994 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2995 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2996 wxDefaultPosition, wxDefaultSize, 0);
2997 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
2999 m_pButtons->AddSpacer(3 * GetCharWidth());
3002 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3003 wxDefaultPosition, wxDefaultSize, 0);
3004 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3006 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3007 wxDefaultPosition, wxDefaultSize, 0);
3008 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3010 m_pButtons =
new wxBoxSizer(wxVERTICAL);
3011 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
3013 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
3014 m_pButtons->Add(tline, 0, wxALL, 2);
3016 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
3017 wxDefaultPosition, wxDefaultSize, 0);
3018 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
3020 tline->AddSpacer(3 * GetCharWidth());
3022 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
3024 tline->Add(m_info_btn, 0);
3027 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3028 wxDefaultPosition, wxDefaultSize);
3029 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3031 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3032 wxDefaultPosition, wxDefaultSize, 0);
3033 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3036 wxBitmap statusBitmap;
3037 const auto stat = m_plugin.m_status;
3038 auto icon_name = icon_by_status.at(stat);
3039 if (stat == PluginStatus::Imported &&
3040 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3042 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3045 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3046 path.AppendDir(
"uidata");
3047 path.AppendDir(
"traditional");
3049 int bmsize = GetCharWidth() * 3 * dpi_mult;
3050 if (path.IsFileReadable()) {
3051 statusBitmap =
LoadSVG(path.GetFullPath(), bmsize, bmsize);
3052 ok = statusBitmap.IsOk();
3055 auto style = g_StyleManager->GetCurrentStyle();
3056 statusBitmap = wxBitmap(style->GetIcon(
"default_pi", bmsize, bmsize));
3057 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3060 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3061 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3062 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3064 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3067 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3069 itemBoxSizer02->AddSpacer(GetCharWidth());
3071 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3072 &PluginPanel::OnPluginPreferences,
this);
3073 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3074 &PluginPanel::OnPluginUninstall,
this);
3075 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3076 &PluginPanel::OnPluginAction,
this);
3078 SetSelected(m_bSelected);
3079 SetAutoLayout(
true);
3087PluginPanel::~PluginPanel() {
3088 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3089 if (m_is_safe_panel)
return;
3090 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3092 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3093 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3094 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3095 if (m_pButtonAction) {
3096 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3097 &PluginPanel::OnPluginAction,
this);
3099 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3100 &PluginPanel::OnPluginPreferences,
this);
3101 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3102 &PluginPanel::OnPluginEnableToggle,
this);
3105void PluginPanel::SetActionLabel(wxString& label) {
3106 m_pButtonAction->SetLabel(label);
3110static wxStopWatch swclick;
3111static int downx, downy;
3113void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3116 event.GetPosition(&downx, &downy);
3122void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3124 qDebug() << swclick.Time();
3125 if (swclick.Time() < 200) {
3127 event.GetPosition(&upx, &upy);
3128 if ((fabs(upx - downx) < GetCharWidth()) &&
3129 (fabs(upy - downy) < GetCharWidth())) {
3137void PluginPanel::DoPluginSelect() {
3138 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3144 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3145 }
else if (m_bSelected) {
3147 m_PluginListPanel->SelectPlugin(NULL);
3150 m_PluginListPanel->SelectPlugin(
this);
3158static PluginMetadata GetMetadataByName(
const std::string& name) {
3160 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3161 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3162 if (found == plugins.end()) {
3163 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3168void PluginPanel::SetSelected(
bool selected) {
3169 m_bSelected = selected;
3171 m_pVersion->SetLabel(
3175 m_pButtons->Show(
true);
3176 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3179 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3182 unInstallPossible =
false;
3185 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3187 m_pButtonUninstall->Show(unInstallPossible);
3189 if (m_plugin.m_managed_metadata.info_url.size()) {
3190 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3194 m_cbEnable->Show(
true);
3199 switch (m_plugin.m_status) {
3200 case PluginStatus::LegacyUpdateAvailable:
3201 label = _(
"Upgrade to Version ");
3202 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3203 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3204 m_pButtonAction->Enable();
3207 case PluginStatus::ManagedInstallAvailable:
3208 label = _(
"Install...");
3209 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3210 m_pButtonAction->Enable();
3213 case PluginStatus::ManagedInstalledUpdateAvailable:
3214 label = _(
"Update to ");
3215 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3216 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3217 m_pButtonAction->Enable();
3220 case PluginStatus::ManagedInstalledCurrentVersion:
3221 label = _(
"Reinstall");
3222 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3223 m_pButtonAction->Enable();
3226 case PluginStatus::ManagedInstalledDowngradeAvailable:
3227 label = _(
"Downgrade");
3228 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3229 m_pButtonAction->Enable();
3232 case PluginStatus::Imported:
3233 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3234 label = _(
"Update");
3235 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3237 m_pButtonAction->Hide();
3238 m_action = ActionVerb::NOP;
3243 m_action = ActionVerb::NOP;
3244 m_pButtonAction->Hide();
3248 m_action = ActionVerb::NOP;
3249 m_pButtonAction->Hide();
3254 m_action = ActionVerb::NOP;
3257 SetActionLabel(label);
3269 m_pButtons->Show(
false);
3272 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3273 m_cbEnable->Show(
false);
3294 SetEnabled(m_plugin.m_enabled);
3309void PluginPanel::OnPaint(wxPaintEvent& event) {
3312 int penWidth = m_penWidthUnselected;
3317 penWidth = m_penWidthSelected;
3322 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3324 dc.SetPen(wxPen(border, penWidth));
3326 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3329void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3330 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3333 androidDisableRotation();
3344void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3345 g_Platform->ShowBusySpinner();
3346 SetEnabled(event.IsChecked());
3347 m_pVersion->SetLabel(
3354 g_Platform->HideBusySpinner();
3357void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3358 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
3361 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3362 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3363 actionEvent.SetClientData(
this);
3364 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3367void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3369 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3370 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3371 actionEvent.SetClientData(
this);
3372 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3377static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3378 auto font = window->GetFont();
3379 font.SetStyle(style);
3380 window->SetFont(font);
3383void PluginPanel::SetEnabled(
bool enabled) {
3384 if (m_is_safe_panel)
return;
3387 if (enabled) NotifySetupOptionsPlugin(&m_plugin);
3388 if (!enabled && !m_bSelected) {
3389 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3390 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3391 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3394 m_pVersion->Disable();
3395 m_pDescription->Disable();
3398 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3399 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3400 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3403 m_pVersion->Enable();
3404 m_pDescription->Enable();
3409 m_pName->Enable(enabled || m_bSelected);
3410 m_pVersion->Enable(enabled || m_bSelected);
3411 m_pDescription->Enable(enabled || m_bSelected);
3415 wxString description = m_plugin.m_long_description;
3416 if (description.IsEmpty())
3417 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3421 m_pDescription->SetLabel(wrapper.GetWrapped());
3422 if (m_plugin.m_managed_metadata.info_url.size()) {
3423 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3427 wxString description = m_plugin.m_short_description;
3428 if (description.IsEmpty())
3429 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3432 m_pDescription->SetLabel(wrapper.GetWrapped());
3435 m_pButtonPreferences->Enable(enabled &&
3437 m_cbEnable->SetValue(enabled);
3440void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3441 m_PluginListPanel->MoveUp(
this);
3444void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3445 m_PluginListPanel->MoveDown(
this);
3450 : wxPanel(parent), m_url(url) {
3451 auto vbox =
new wxBoxSizer(wxVERTICAL);
3452 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3453 button->Enable(strlen(url) > 0);
3456 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3457 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3465PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3467PlugInChartBase::~PlugInChartBase() {}
3476 bool b_allow_overzoom) {
3488 const wxRegion& Region) {
3489 return wxNullBitmap;
3498 wxRegion* pValidRegion) {}
3511 wxRect* pSourceRect) {}
3528 double* plat,
double* plon) {}
3535PlugInChartBaseGL::PlugInChartBaseGL() {}
3537PlugInChartBaseGL::~PlugInChartBaseGL() {}
3541 const wxRegion& Region,
3542 bool b_use_stencil) {
3568PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3570PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3574 const wxRegion& Region,
3575 bool b_use_stencil) {
3581 const wxRegion& Region,
bool b_use_stencil) {
3587 const wxRegion& Region,
bool b_use_stencil) {
3593 return wxNullBitmap;
3597 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3601ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3606wxString PlugInChartBaseExtended::CreateObjDescriptions(
3607 ListOfPI_S57Obj* obj_list) {
3611int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3613int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3615int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3617float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3626PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3628PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3631PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3641PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3643PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3655ChartPlugInWrapper::ChartPlugInWrapper() {}
3657ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3658 m_ppo = ::wxCreateDynamicObject(chart_class);
3662ChartPlugInWrapper::~ChartPlugInWrapper() {
3663 if (m_ppicb)
delete m_ppicb;
3666wxString ChartPlugInWrapper::GetFileSearchMask() {
3673InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3674 ChartInitFlag init_flags) {
3676 wxWindow* pa = wxWindow::FindFocus();
3678 InitReturn ret_val = (InitReturn)m_ppicb->
Init(name, (
int)init_flags);
3682 if (ret_val == INIT_OK) {
3689 m_ID = m_ppicb->
GetID();
3693 m_SE = m_ppicb->
GetSE();
3707 if ((fabs(m_Chart_Skew) < .01) &&
3708 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3710 if (GetChartExtent(&extent)) {
3711 double lon_range = extent.ELON - extent.WLON;
3712 if ((lon_range > 0) &&
3714 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3718 m_overlayENC =
false;
3720 wxCharBuffer buf = m_FullPath.ToUTF8();
3721 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3727 m_ChartType = CHART_TYPE_UNKNOWN;
3728 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3734 if (pc) pc->SetFocus();
3738 return INIT_FAIL_REMOVE;
3742int ChartPlugInWrapper::GetCOVREntries() {
3749int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3756int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3763float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3775int ChartPlugInWrapper::GetNoCOVREntries() {
3785int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3795int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3805float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3815bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3819 pext->NLAT = xpi.
NLAT;
3820 pext->SLAT = xpi.
SLAT;
3821 pext->ELON = xpi.
ELON;
3822 pext->WLON = xpi.
WLON;
3831ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3836 if (!pThumbData->pDIBThumb) {
3837 wxBitmap* pBMPOwnedByChart =
3838 m_ppicb->
GetThumbnail(tnx, tny, m_global_color_scheme);
3839 if (pBMPOwnedByChart) {
3840 wxImage img = pBMPOwnedByChart->ConvertToImage();
3841 pThumbData->pDIBThumb =
new wxBitmap(img);
3843 pThumbData->pDIBThumb = NULL;
3846 pThumbData->Thumb_Size_X = tnx;
3847 pThumbData->Thumb_Size_Y = tny;
3874 pThumbData->ShipX = 0;
3875 pThumbData->ShipY = 0;
3882ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3884bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3888double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3889 bool b_allow_overzoom) {
3896double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3918void RenderRotateToViewPort(
const ViewPort& VPoint) {
3919#ifndef USE_ANDROID_GLES2
3921 glTranslatef(xt, yt, 0);
3922 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3923 glTranslatef(-xt, -yt, 0);
3927void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3928#ifndef USE_ANDROID_GLES2
3930 glTranslatef(xt, yt, 0);
3931 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3932 glTranslatef(-xt, -yt, 0);
3936bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3939 const LLRegion& Region) {
3948 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3949 wxRegion* r = RectRegion.GetNew_wxRegion();
3952 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3953 chart_region.Intersect(Region);
3955 if (!chart_region.Empty()) {
3956 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3958 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3962#ifndef USE_ANDROID_GLES2
3965 RenderRotateToViewPort(VPoint);
3970 glChartCanvas::s_b_useStencil);
3973 glChartCanvas::s_b_useStencil);
3974 UndoRenderRotateToViewPort(VPoint);
3976#ifndef USE_ANDROID_GLES2
3979 glChartCanvas::DisableClipRegion();
3993bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
3994 const wxGLContext& glc,
const ViewPort& VPoint,
3995 const OCPNRegion& RectRegion,
const LLRegion& Region) {
4004 if (!Region.Empty() && ppicb_x) {
4006 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
4007 glChartCanvas::DisableClipRegion();
4010 RenderRotateToViewPort(VPoint);
4013 wxRegion* r = RectRegion.GetNew_wxRegion();
4016 glChartCanvas::s_b_useStencil);
4019 UndoRenderRotateToViewPort(VPoint);
4024 else if (!Region.Empty() &&
4028 wxRegion* r = RectRegion.GetNew_wxRegion();
4031 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4032 chart_region.Intersect(Region);
4034 if (!chart_region.Empty()) {
4035 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4037 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4039 RenderRotateToViewPort(VPoint);
4043 glChartCanvas::s_b_useStencil);
4046 UndoRenderRotateToViewPort(VPoint);
4048 glChartCanvas::DisableClipRegion();
4061bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4068 if (!Region.Empty() && ppicb_x) {
4069 wxRegion* r = Region.GetNew_wxRegion();
4071#ifndef USE_ANDROID_GLES2
4074 RenderRotateToViewPort(VPoint);
4078 glChartCanvas::s_b_useStencil);
4079 UndoRenderRotateToViewPort(VPoint);
4081#ifndef USE_ANDROID_GLES2
4094bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4100 if (Region.IsOk()) {
4101 wxRegion* r = Region.GetNew_wxRegion();
4108 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4109 wxColour nodat_sub = nodat;
4111#ifdef ocpnUSE_ocpnBitmap
4112 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4114 m_pMask =
new wxMask(obmp, nodat_sub);
4115 obmp.SetMask(m_pMask);
4117 dc.SelectObject(obmp);
4128bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4139 if (Region.IsOk() && (pCBx || ppicb)) {
4140 wxRegion* r = Region.GetNew_wxRegion();
4155bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4158 bool ret_val =
false;
4161 if (Region.IsOk()) {
4162 wxRegion* r = Region.GetNew_wxRegion();
4176void ChartPlugInWrapper::ClearPLIBTextList() {
4184bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4188 return m_ppicb->
AdjustVP(pivp_last, pivp_proposed);
4193void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4208void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4212 m_global_color_scheme = cs;
4214 if (pThumbData) pThumbData->pDIBThumb = NULL;
4218 double target_scale_ppm) {
4225void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4226 wxRect* pSourceRect) {
4233double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4235 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4240bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4242 wxCriticalSectionLocker locker(m_critSect);
4251int ChartPlugInWrapper::GetSize_X() {
4258int ChartPlugInWrapper::GetSize_Y() {
4265void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4266 double& pixx,
double& pixy) {
4270void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4271 double* plat,
double* plon) {
4286 return toSDMM(NEflag, a, hi_precision);
4290 return GetGlobalColor(colorName);
4294 const wxString& caption,
int style,
int x,
int y) {
4295 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4303 return g_Platform->GetWritableDocumentsDir();
4308 auto loader = PluginLoader::GetInstance();
4309 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4311 if (pic->m_pplugin == pplugin) {
4321ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4324 ListOfPI_S57Obj* list = NULL;
4338 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4348 ListOfPI_S57Obj* rule_list) {
4359 ret_str = picbx->CreateObjDescriptions(rule_list);
4373 return ps52plib->m_nDepthUnitDisplay;
4380 return ps52plib->m_nSymbolStyle;
4387 return ps52plib->m_nBoundaryStyle;
4397 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4399 ViewPort cvp = CreateCompatibleViewport(*vp);
4404 ObjRazRules rzRules;
4405 rzRules.obj = &cobj;
4406 rzRules.LUP = pContext->LUP;
4407 rzRules.sm_transform_parms = 0;
4408 rzRules.child = NULL;
4409 rzRules.next = NULL;
4411 if (pContext->LUP) {
4412 ps52plib->SetVPointCompat(
4416 ps52plib->PrepareForRender();
4418 return ps52plib->ObjectRenderCheck(&rzRules);
4427 return ps52plib->GetStateHash();
4432void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4433 chart_context* pctx) {
4436 cobj->att_array = pObj->att_array;
4437 cobj->attVal = pObj->attVal;
4438 cobj->n_attr = pObj->n_attr;
4443 cobj->npt = pObj->npt;
4445 cobj->iOBJL = pObj->iOBJL;
4446 cobj->Index = pObj->Index;
4448 cobj->geoPt = (pt*)pObj->geoPt;
4449 cobj->geoPtz = pObj->geoPtz;
4450 cobj->geoPtMulti = pObj->geoPtMulti;
4452 cobj->m_lat = pObj->m_lat;
4453 cobj->m_lon = pObj->m_lon;
4455 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4456 cobj->x_rate = pObj->x_rate;
4457 cobj->y_rate = pObj->y_rate;
4458 cobj->x_origin = pObj->x_origin;
4459 cobj->y_origin = pObj->y_origin;
4461 cobj->Scamin = pObj->Scamin;
4462 cobj->nRef = pObj->nRef;
4463 cobj->bIsAton = pObj->bIsAton;
4464 cobj->bIsAssociable = pObj->bIsAssociable;
4466 cobj->m_n_lsindex = pObj->m_n_lsindex;
4467 cobj->m_lsindex_array = pObj->m_lsindex_array;
4468 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4471 cobj->m_ls_list_legacy =
4475 cobj->m_ls_list_legacy = 0;
4476 cobj->m_ls_list = 0;
4479 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4481 cobj->m_bcategory_mutable =
true;
4485 if (pObj->m_DPRI == -1) {
4487 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4489 cobj->m_DPRI = pObj->m_DPRI;
4492 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4493 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4495 if (pObj->auxParm3 != 1234) {
4496 pObj->auxParm3 = 1234;
4497 pObj->auxParm0 = -99;
4500 cobj->auxParm0 = pObj->auxParm0;
4507 if (pContext->bBBObj_valid)
4509 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4510 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4512 cobj->CSrules = pContext->CSrules;
4513 cobj->bCS_Added = pContext->bCS_Added;
4515 cobj->FText = pContext->FText;
4516 cobj->bFText_Added = pContext->bFText_Added;
4517 cobj->rText = pContext->rText;
4519 cobj->bIsClone =
true;
4522 cobj->m_chart_context = pctx;
4523 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4526 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4527 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4528 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4529 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4530 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4531 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4532 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4533 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4535 cobj->m_chart_context->chart =
4537 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4551 CreateCompatibleS57Object(pObj, &cobj, NULL);
4553 LUPname LUP_Name = PAPER_CHART;
4556 ctx->CSrules = NULL;
4557 ctx->bCS_Added =
false;
4560 if (ctx->bFText_Added) {
4561 ctx->bFText_Added =
false;
4567 ctx->bBBObj_valid =
true;
4572 switch (cobj.Primitive_type) {
4577 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4578 LUP_Name = PAPER_CHART;
4580 LUP_Name = SIMPLIFIED;
4589 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4590 LUP_Name = PLAIN_BOUNDARIES;
4592 LUP_Name = SYMBOLIZED_BOUNDARIES;
4597 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4601 ps52plib->_LUP2rules(lup, &cobj);
4603 ctx->MPSRulesList = NULL;
4611 pContext->bBBObj_valid =
true;
4617void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4618 ObjRazRules* rzRules) {
4622 pContext->CSrules = cobj->CSrules;
4623 pContext->bCS_Added = cobj->bCS_Added;
4625 pContext->FText = cobj->FText;
4626 pContext->bFText_Added = cobj->bFText_Added;
4627 pContext->rText = cobj->rText;
4629 if (cobj->BBObj.GetValid()) {
4632 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4633 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4634 pContext->bBBObj_valid =
true;
4639 pObj->m_DisplayCat = (
PI_DisCat)cobj->m_DisplayCat;
4643 pContext->ChildRazRules = rzRules->child;
4644 pContext->MPSRulesList = rzRules->mps;
4646 pObj->auxParm0 = cobj->auxParm0;
4650 double* lon_min,
double* lon_max) {
4653 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4654 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4655 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4656 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4657 return pContext->bBBObj_valid;
4665 LUPrec* lup = pContext->LUP;
4674 LUPrec* lup = pContext->LUP;
4684 LUPrec* lup = pContext->LUP;
4690 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4697 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4702 ObjRazRules rzRules;
4703 rzRules.obj = &cobj;
4704 rzRules.LUP = pContext->LUP;
4705 rzRules.sm_transform_parms = 0;
4706 rzRules.child = NULL;
4707 rzRules.next = NULL;
4708 rzRules.mps = pContext->MPSRulesList;
4710 if (pContext->LUP) {
4711 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4714 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4720 ps52plib->PrepareForRender();
4721 ps52plib->ClearTextList();
4724 ps52plib->EnableGLLS(
true);
4726 ps52plib->EnableGLLS(
false);
4735 if (pctx->ChildRazRules) {
4736 ObjRazRules* ctop = pctx->ChildRazRules;
4740 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4742 ObjRazRules* cnxx = ctop->next;
4748 if (pctx->MPSRulesList) {
4749 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4750 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4752 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4753 ps52plib->DestroyRulesChain(top);
4755 delete pctx->MPSRulesList->cs_rules;
4757 free(pctx->MPSRulesList);
4769 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4776 &transform.easting_vp_center, &transform.northing_vp_center);
4779 ObjRazRules rzRules;
4780 rzRules.obj = &cobj;
4781 rzRules.LUP = pContext->LUP;
4782 rzRules.sm_transform_parms = &transform;
4783 rzRules.child = pContext->ChildRazRules;
4784 rzRules.next = NULL;
4785 rzRules.mps = pContext->MPSRulesList;
4787 if (pContext->LUP) {
4788 ViewPort cvp = CreateCompatibleViewport(*vp);
4794 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4796 ps52plib->PrepareForRender();
4798 ps52plib->RenderObjectToDC(pdc, &rzRules);
4801 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4808 wxRect rect,
unsigned char* pixbuf) {
4810 render_canvas_parms pb_spec;
4812 pb_spec.depth = BPP;
4813 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4814 pb_spec.lclip = rect.x;
4815 pb_spec.rclip = rect.x + rect.width - 1;
4816 pb_spec.pix_buff = pixbuf;
4817 pb_spec.width = rect.width;
4818 pb_spec.height = rect.height;
4821#ifdef ocpnUSE_ocpnBitmap
4822 pb_spec.b_revrgb =
true;
4824 pb_spec.b_revrgb =
false;
4827 pb_spec.b_revrgb =
false;
4832 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4839 &transform.easting_vp_center, &transform.northing_vp_center);
4842 ObjRazRules rzRules;
4843 rzRules.obj = &cobj;
4844 rzRules.LUP = pContext->LUP;
4845 rzRules.sm_transform_parms = &transform;
4846 rzRules.child = pContext->ChildRazRules;
4847 rzRules.next = NULL;
4848 rzRules.mps = pContext->MPSRulesList;
4850 ViewPort cvp = CreateCompatibleViewport(*vp);
4858 if (!tess)
return 1;
4860 PolyTriGroup* ptg =
new PolyTriGroup;
4861 ptg->tri_prim_head =
4862 tess->Get_PolyTriGroup_head()->tri_prim_head;
4863 ptg->bsingle_alloc =
false;
4864 ptg->data_type = DATA_TYPE_DOUBLE;
4865 tess->Set_PolyTriGroup_head(ptg);
4867 double* pd = (
double*)malloc(
sizeof(
double));
4872 if (pContext->LUP) {
4877 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4879 ps52plib->PrepareForRender();
4881 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4884 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4896 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4907 if (!tess)
return 1;
4911 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4912 ptg->bsingle_alloc =
false;
4913 ptg->data_type = DATA_TYPE_DOUBLE;
4914 tess->Set_PolyTriGroup_head(ptg);
4918 double* pd = (
double*)malloc(
sizeof(
double));
4935 &transform.easting_vp_center, &transform.northing_vp_center);
4938 ObjRazRules rzRules;
4939 rzRules.obj = &cobj;
4940 rzRules.LUP = pContext->LUP;
4941 rzRules.sm_transform_parms = &transform;
4942 rzRules.child = pContext->ChildRazRules;
4943 rzRules.next = NULL;
4944 rzRules.mps = pContext->MPSRulesList;
4946 if (pContext->LUP) {
4947 ViewPort cvp = CreateCompatibleViewport(*vp);
4953 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4955 ps52plib->PrepareForRender();
4957 ps52plib->RenderAreaToGL(glcc, &rzRules);
4960 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4972 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4979 &transform.easting_vp_center, &transform.northing_vp_center);
4982 ObjRazRules rzRules;
4983 rzRules.obj = &cobj;
4984 rzRules.LUP = pContext->LUP;
4985 rzRules.sm_transform_parms = &transform;
4986 rzRules.child = pContext->ChildRazRules;
4987 rzRules.next = NULL;
4988 rzRules.mps = pContext->MPSRulesList;
4990 if (pContext->LUP) {
4991 ViewPort cvp = CreateCompatibleViewport(*vp);
4997 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4999 ps52plib->PrepareForRender();
5001 ps52plib->RenderObjectToGL(glcc, &rzRules);
5004 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
5014OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
5015 : wxEvent(id, commandType) {
5018 m_b_complete =
false;
5022OCPN_downloadEvent::~OCPN_downloadEvent() {}
5024wxEvent* OCPN_downloadEvent::Clone()
const {
5026 newevent->m_stat = this->m_stat;
5027 newevent->m_condition = this->m_condition;
5029 newevent->m_totalBytes = this->m_totalBytes;
5030 newevent->m_sofarBytes = this->m_sofarBytes;
5031 newevent->m_b_complete = this->m_b_complete;
5037DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5042#define DL_EVENT_TIMER 4388
5050 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5051 void clearBackgroundMode();
5052 void onTimerEvent(wxTimerEvent& event);
5055 wxTimer m_eventTimer;
5056 wxEvtHandler* m_download_evHandler;
5062PI_DLEvtHandler::PI_DLEvtHandler() {
5066 m_download_evHandler = NULL;
5072PI_DLEvtHandler::~PI_DLEvtHandler() {
5073 m_eventTimer.Stop();
5076 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5083 g_download_status =
event.getDLEventStatus();
5084 g_download_condition =
event.getDLEventCondition();
5087 if (m_download_evHandler &&
5090 ev.setComplete(
true);
5091 ev.setTransferred(m_sofarBytes);
5092 ev.setTotal(m_totalBytes);
5094 ev.setDLEventStatus(event.getDLEventStatus());
5097 m_download_evHandler->AddPendingEvent(ev);
5098 m_eventTimer.Stop();
5100 finishAndroidFileDownload();
5107void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5109 m_download_evHandler = handler;
5111 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5115 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5116 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5119void PI_DLEvtHandler::clearBackgroundMode() {
5120 m_download_evHandler = NULL;
5121 m_eventTimer.Stop();
5124void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5130 int stat = queryAndroidFileDownload(m_id, &sstat);
5133 long sofarBytes = 0;
5134 long totalBytes = -1;
5138 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5139 ev.setComplete(
true);
5140 ev.setTransferred(sofarBytes);
5141 ev.setTotal(totalBytes);
5146 wxStringTokenizer tk(sstat,
";");
5147 if (tk.HasMoreTokens()) {
5148 wxString token = tk.GetNextToken();
5149 token.ToLong(&state);
5150 token = tk.GetNextToken();
5151 token.ToLong(&sofarBytes);
5152 token = tk.GetNextToken();
5153 token.ToLong(&totalBytes);
5156 qDebug() << state << sofarBytes << totalBytes;
5158 m_sofarBytes = sofarBytes;
5159 m_totalBytes = totalBytes;
5161 ev.setTransferred(sofarBytes);
5162 ev.setTotal(totalBytes);
5165 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5166 ev.setComplete(
true);
5169 }
else if (state == 8) {
5170 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5171 ev.setComplete(
true);
5175 ev.setComplete(
false);
5183 if (m_download_evHandler) {
5185 m_download_evHandler->AddPendingEvent(ev);
5190 m_eventTimer.Stop();
5191 finishAndroidFileDownload();
5201 const wxString& outputFile,
5202 const wxString& title,
const wxString& message,
5203 const wxBitmap& bitmap, wxWindow* parent,
5204 long style,
int timeout_secs) {
5207 wxString msg =
"Downloading file synchronously: ";
5214 int vres = validateAndroidWriteLocation(outputFile);
5226 g_piEventHandler->Connect(
5227 wxEVT_DOWNLOAD_EVENT,
5228 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5233 wxString fURI = outputFile;
5234 if (!fURI.StartsWith(
"file://")) {
5235 fURI.Prepend(
"file://");
5238 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5241 finishAndroidFileDownload();
5242 g_piEventHandler->Disconnect(
5243 wxEVT_DOWNLOAD_EVENT,
5244 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5249 wxDateTime dl_start_time = wxDateTime::Now();
5253 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5254 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5256 if (dt.GetSeconds() > timeout_secs) {
5257 qDebug() <<
"USER_TIMOUT";
5258 finishAndroidFileDownload();
5259 g_piEventHandler->Disconnect(
5260 wxEVT_DOWNLOAD_EVENT,
5261 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5269 finishAndroidFileDownload();
5270 g_piEventHandler->Disconnect(
5271 wxEVT_DOWNLOAD_EVENT,
5275 qDebug() <<
"RETURN DL_END" << (int)ss;
5281 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5283 qDebug() <<
"Error on queryAndroidFileDownload";
5284 finishAndroidFileDownload();
5285 g_piEventHandler->Disconnect(
5286 wxEVT_DOWNLOAD_EVENT,
5287 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5297#elif defined(OCPN_USE_CURL)
5298 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5299 wxFileOutputStream output(tfn.GetFullPath());
5301 wxCurlDownloadDialog ddlg(url, &output, title, message, bitmap, parent,
5303 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5309 case wxCDRF_SUCCESS: {
5310 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5316 case wxCDRF_FAILED: {
5320 case wxCDRF_USER_ABORTED: {
5328 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5338 return ocpn::toUsrDateTimeFormat(date_time,
options);
5343 const wxString& outputFile,
5344 wxEvtHandler* handler,
5347 wxString msg =
"Downloading file asynchronously: ";
5359 int res = startAndroidFileDownload(url, outputFile, NULL ,
5363 finishAndroidFileDownload();
5368 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5370 if (handle) *handle = dl_ID;
5374#elif defined(OCPN_USE_CURL)
5381 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5384 dynamic_cast<wxCurlHTTP*
>(
g_pi_manager->m_pCurl.get())) {
5391 bool failed =
false;
5400 new wxFileOutputStream(outputFile)),
5408 wxCurlThreadError err =
g_pi_manager->m_pCurlThread->Download();
5409 if (err != wxCTE_NO_ERROR) {
5423 delete (
g_pi_manager->m_pCurlThread->GetOutputStream());
5441 cancelAndroidFileDownload(handle);
5442 finishAndroidFileDownload();
5443 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5447 delete (
g_pi_manager->m_pCurlThread->GetOutputStream());
5458 const wxString& parameters, wxString& result,
5461 wxString lparms = parameters;
5462 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5465 result = postResult;
5468#elif defined(OCPN_USE_CURL)
5470 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5471 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5474 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5477 result = wxEmptyString;
5488 return androidCheckOnline();
5491#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5492 if (wxDateTime::GetTimeNow() >
5493 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5495 get.Head(
"http://yahoo.com/");
5496 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5498 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5506#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5507void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5509 if (ev.IsSuccessful()) {
5516 event.setComplete(
true);
5518 if (m_download_evHandler) {
5519 m_download_evHandler->AddPendingEvent(event);
5520 m_download_evHandler = NULL;
5521 m_downloadHandle = NULL;
5524 if (m_pCurlThread) {
5525 m_pCurlThread->Wait();
5526 if (!m_pCurlThread->IsAborting()) {
5527 delete (m_pCurlThread->GetOutputStream());
5528 wxDELETE(m_pCurlThread);
5533void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5537 event.setTotal(ev.GetTotalBytes());
5538 event.setTransferred(ev.GetDownloadedBytes());
5539 event.setComplete(
false);
5541 if (m_download_evHandler) {
5542 m_download_evHandler->AddPendingEvent(event);
5546bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5547 wxCurlBaseThread* p,
5548 const wxString& url) {
5550 case wxCTE_NO_ERROR:
5553 case wxCTE_NO_RESOURCE:
5555 wxS(
"Insufficient resources for correct execution of the program."));
5558 case wxCTE_ALREADY_RUNNING:
5562 case wxCTE_INVALID_PROTOCOL:
5563 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5567 case wxCTE_NO_VALID_STREAM:
5574 case wxCTE_CURL_ERROR: {
5575 wxString ws = wxS(
"unknown");
5576 if (p->GetCurlSession())
5578 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5579 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5584 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
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.
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.
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).
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.
Generic GUI downloads tool.
Handle downloading of files from remote urls.
OpenGL chart rendering canvas.
GSHHS Chart Object (Global Self-consistent, Hierarchical, High-resolution Shoreline) Derived from htt...
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
JSON event definition used in internal communications to/from plugins.
Enhanced logging interface on top of wx/log.h.
Multiplexer class and helpers.
bool replace(std::string &str, const std::string &from, const std::string &to)
Perform in place substitution in str, replacing "from" with "to".
std::string lookup_tarball(const char *uri)
Get path to tarball in cache for given filename.
std::string tolower(const std::string &input)
Return copy of s with all characters converted to lower case.
std::vector< std::string > split(const char *token_string, const std::string &delimiter)
Return vector of items in s separated by delimiter.
bool store_metadata(const char *path)
Store metadata in metadata cache, return success/fail.
bool store_tarball(const char *path, const char *basename)
Store a tarball in tarball cache, return success/fail.
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.