38#include <unordered_map>
46#if defined(__linux__) && !defined(__ANDROID__)
52#include <wx/filename.h>
53#include <wx/aui/aui.h>
54#include <wx/platinfo.h>
55#include <wx/popupwin.h>
56#include <wx/progdlg.h>
57#include <wx/statline.h>
58#include <wx/tokenzr.h>
59#include <wx/tooltip.h>
61#include <wx/hashset.h>
62#include <wx/hashmap.h>
63#include <wx/jsonval.h>
64#include <wx/jsonreader.h>
66#include <wx/zipstrm.h>
67#include <wx/zstream.h>
68#include <wx/tarstrm.h>
69#include <wx/textwrapper.h>
76#include <archive_entry.h>
77typedef __LA_INT64_T la_int64_t;
87#include "model/ais_target_data.h"
91#include "model/comm_drv_n2k.h"
94#include "model/comm_vars.h"
95#include "model/config_vars.h"
96#include "model/datetime.h"
97#include "model/downloader.h"
98#include "model/georef.h"
99#include "model/json_event.h"
102#include "model/nav_object_database.h"
103#include "model/navutil_base.h"
105#include "model/plugin_cache.h"
110#include "model/route.h"
111#include "model/routeman.h"
112#include "model/safe_mode.h"
113#include "model/select.h"
114#include "model/semantic_vers.h"
115#include "model/track.h"
118#include "canvasMenu.h"
119#include "cat_settings.h"
120#include "chartbase.h"
125#include "download_mgr.h"
135#include "OCPN_AUIManager.h"
137#include "ocpn_frame.h"
138#include "ocpn_pixel.h"
139#include "OCPNPlatform.h"
140#include "OCPNRegion.h"
144#include "routemanagerdialog.h"
145#include "routeman_gui.h"
148#include "SoundFactory.h"
151#include "SystemCmdSound.h"
153#include "update_mgr.h"
154#include "waypointman_gui.h"
158#include "androidUTIL.h"
162#include "glChartCanvas.h"
167#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
168extern wxLocale* plocale_def_lang;
177extern bool g_bShowChartBar;
181extern RouteList* pRouteList;
182extern std::vector<Track*> g_TrackList;
184extern s52plib* ps52plib;
185extern wxString ChartListFileName;
187extern ColorScheme global_color_scheme;
188extern wxArrayString g_locale_catalog_array;
189extern int g_GUIScaleFactor;
190extern int g_ChartScaleFactor;
194extern int g_chart_zoom_modifier_raster;
195extern int g_chart_zoom_modifier_vector;
197extern bool g_bopengl;
199extern ChartGroupArray* g_pGroupArray;
200extern unsigned int g_canvasConfig;
202extern wxString g_CmdSoundString;
204extern unsigned int gs_plib_flags;
207extern bool g_bquiting;
209WX_DEFINE_ARRAY_PTR(
ChartCanvas*, arrayofCanvasPtr);
210extern arrayofCanvasPtr g_canvasArray;
212void NotifySetupOptionsPlugin(
const PlugInData* pic);
214enum { CurlThreadId = wxID_HIGHEST + 1 };
216#include <wx/listimpl.cpp>
217WX_DEFINE_LIST(Plugin_WaypointList);
218WX_DEFINE_LIST(Plugin_HyperlinkList);
225 explicit RawKey(
const std::string& key) : m_key(key) {}
226 [[nodiscard]] std::string
GetKey()
const override {
return m_key; }
232static void SendAisJsonMessage(std::shared_ptr<const AisTargetData> pTarget) {
234 if (!GetJSONMessageTargetCount())
return;
239 wxLongLong t = ::wxGetLocalTimeMillis();
241 jMsg[wxS(
"Source")] = wxS(
"AisDecoder");
242 jMsg[wxT(
"Type")] = wxT(
"Information");
243 jMsg[wxT(
"Msg")] = wxS(
"AIS Target");
244 jMsg[wxT(
"MsgId")] = t.GetValue();
245 jMsg[wxS(
"lat")] = pTarget->Lat;
246 jMsg[wxS(
"lon")] = pTarget->Lon;
247 jMsg[wxS(
"sog")] = pTarget->SOG;
248 jMsg[wxS(
"cog")] = pTarget->COG;
249 jMsg[wxS(
"hdg")] = pTarget->HDG;
250 jMsg[wxS(
"mmsi")] = pTarget->MMSI;
251 jMsg[wxS(
"class")] = pTarget->Class;
252 jMsg[wxS(
"ownship")] = pTarget->b_OwnShip;
253 jMsg[wxS(
"active")] = pTarget->b_active;
254 jMsg[wxS(
"lost")] = pTarget->b_lost;
255 wxString l_ShipName = wxString::FromUTF8(pTarget->ShipName);
256 for (
size_t i = 0; i < l_ShipName.Len(); i++) {
257 if (l_ShipName.GetChar(i) ==
'@') l_ShipName.SetChar(i,
'\n');
259 jMsg[wxS(
"shipname")] = l_ShipName;
260 wxString l_CallSign = wxString::FromUTF8(pTarget->CallSign);
261 for (
size_t i = 0; i < l_CallSign.Len(); i++) {
262 if (l_CallSign.GetChar(i) ==
'@') l_CallSign.SetChar(i,
'\n');
264 jMsg[wxS(
"callsign")] = l_CallSign;
265 jMsg[wxS(
"removed")] = pTarget->b_removed;
266 SendJSONMessageToAllPlugins(wxT(
"AIS"), jMsg);
270 return (*p1)->Key().compare((*p2)->Key());
274 auto version = metadata.version;
276 if (version[0] ==
'v') version = version.substr(1);
281 auto imported_version = ParseVersion(metadata);
282 for (
auto& md :
PluginHandler::GetInstance()->GetAvailable()) {
283 if (md.name != metadata.name)
continue;
284 if (md.is_imported)
continue;
286 if (ParseVersion(md) >= imported_version)
return true;
297 void message(
const std::string& message) {
299 m_deferred_messages.push_back(message);
304 void show_deferred_messages() {
305 for (
auto m : m_deferred_messages) show_msg(m);
312 void show_msg(wxString msg) {
313 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
314 wxICON_INFORMATION | wxOK, 10);
318 std::vector<wxString> m_deferred_messages;
325 Wrap(win, text, widthMax);
327 wxString
const& GetWrapped()
const {
return m_wrapped; }
328 int const GetLineCount()
const {
return m_lineCount; }
329 wxArrayString GetLineArray() {
return m_array; }
332 virtual void OnOutputLine(
const wxString& line) {
336 virtual void OnNewLine() {
344 wxArrayString m_array;
348 template <
typename T>
349 std::size_t operator()(T t)
const {
350 return static_cast<std::size_t
>(t);
357 return _(
"Plugin is a standard system plugin");
359 return _(
"Plugin is managed by OpenCPN");
361 return _(
"Plugin is not managed by OpenCPN");
364 case PluginStatus::Unknown:
365 return _(
"Plugin status unknown");
366 case PluginStatus::LegacyUpdateAvailable:
367 return _(
"Update to managed Plugin is available");
368 case PluginStatus::ManagedInstallAvailable:
369 return _(
"New managed Plugin installation available");
370 case PluginStatus::ManagedInstalledUpdateAvailable:
371 return _(
"Update to installed Plugin is available");
372 case PluginStatus::ManagedInstalledCurrentVersion:
373 return _(
"Plugin is latest available");
374 case PluginStatus::Imported:
375 return _(
"Plugin is imported");
376 case PluginStatus::ManagedInstalledDowngradeAvailable:
378 case PluginStatus::PendingListRemoval:
385static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
391 {PluginStatus::Unknown,
"emblem-unmanaged.svg"},
392 {PluginStatus::LegacyUpdateAvailable,
"emblem-legacy-update.svg"},
393 {PluginStatus::ManagedInstallAvailable,
"emblem-download.svg"},
394 {PluginStatus::ManagedInstalledUpdateAvailable,
395 "emblem-legacy-update.svg"},
396 {PluginStatus::ManagedInstalledCurrentVersion,
"emblem-default.svg"},
397 {PluginStatus::ManagedInstalledDowngradeAvailable,
398 "emblem-default.svg"},
399 {PluginStatus::PendingListRemoval,
"emblem-default.svg"},
400 {PluginStatus::Imported,
"emblem-default.svg"}});
402static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
403 literalstatus_by_status(
408 {PluginStatus::Unknown,
"Unknown"},
409 {PluginStatus::LegacyUpdateAvailable,
"LegacyUpdateAvailable"},
410 {PluginStatus::ManagedInstallAvailable,
"ManagedInstallAvailable"},
411 {PluginStatus::ManagedInstalledUpdateAvailable,
412 "ManagedInstalledUpdateAvailable"},
413 {PluginStatus::ManagedInstalledCurrentVersion,
414 "ManagedInstalledCurrentVersion"},
415 {PluginStatus::ManagedInstalledDowngradeAvailable,
416 "ManagedInstalledDowngradeAvailable"},
417 {PluginStatus::PendingListRemoval,
"PendingListRemoval"},
418 {PluginStatus::Imported,
"Imported"}
426static std::vector<PluginMetadata> getCompatiblePlugins() {
428 struct metadata_compare {
431 return lhs.key() < rhs.key();
435 std::vector<PluginMetadata> returnArray;
437 std::set<PluginMetadata, metadata_compare> unique_plugins;
438 for (
auto plugin :
PluginHandler::GetInstance()->GetAvailable()) {
439 unique_plugins.insert(plugin);
441 for (
auto plugin : unique_plugins) {
443 returnArray.push_back(plugin);
460 std::string installed;
462 if (path ==
"" || !wxFileName::IsFileReadable(path)) {
465 std::ifstream stream;
466 stream.open(path, std::ifstream::in);
475static std::vector<PluginMetadata> getUpdates(
const char* name) {
476 auto updates = getCompatiblePlugins();
478 std::remove_if(updates.begin(), updates.end(),
482 auto inst_vers = getInstalledVersion(name);
483 if (inst_vers.major == -1) {
488 updates.erase(std::remove_if(updates.begin(), updates.end(),
490 return metadata_version(m) == inst_vers;
497static void gui_uninstall(
const PlugInData* pic,
const char* plugin) {
498 g_Platform->ShowBusySpinner();
503 wxLogMessage(
"Uninstalling %s", plugin);
506 g_Platform->HideBusySpinner();
509static bool LoadAllPlugIns(
bool load_enabled,
bool keep_orphans =
false) {
510 g_Platform->ShowBusySpinner();
512 PluginLoader::GetInstance()->
LoadAllPlugIns(load_enabled, keep_orphans);
513 g_Platform->HideBusySpinner();
518static void UninstallPlugin(
const std::string& name) {
520 auto loader = PluginLoader::GetInstance();
521 auto finder = [name](
const PluginMetadata pm) {
return pm.name == name; };
522 const auto& installed = handler->GetInstalled();
523 auto found = std::find_if(installed.begin(), installed.end(), finder);
524 if (found != installed.end()) {
525 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
526 auto const& item = loader->GetPlugInArray()->Item(i);
527 if (item->m_common_name.ToStdString() == name) {
528 DEBUG_LOG <<
"Unloading plugin: " << name;
529 loader->UnLoadPlugIn(i);
533 handler->Uninstall(found->name);
534 DEBUG_LOG <<
"Uninstalling: " << found->name;
539 bool uninstall,
const char* name = 0,
540 bool b_forceEnable =
false) {
542 const char* plugin = name == 0 ? pic->
m_common_name.mb_str().data() : name;
543 auto updates = getUpdates(plugin);
544 auto parent_dlg =
dynamic_cast<wxScrolledWindow*
>(parent);
545 wxASSERT(parent_dlg != 0);
547 auto status = dialog.ShowModal();
548 status = dialog.GetReturnCode();
549 if (status != wxID_OK) {
553 auto update = dialog.GetUpdate();
554 if (!g_pi_manager->CheckBlacklistedPlugin(update)) {
558 wxLogMessage(
"Installing %s", update.name.c_str());
562 if (uninstall && path !=
"") {
563 gui_uninstall(pic, update.name.c_str());
565 bool cacheResult = pluginHandler->InstallPluginFromCache(update);
568 g_Platform->ShowBusySpinner();
572 std::string tempTarballPath = downloader->run(parent_dlg, uninstall);
574 if (!tempTarballPath.size())
580 if (!isRegularFile(manifestPath.c_str())) {
581 wxLogMessage(
"Installation of %s failed", update.name.c_str());
582 PluginHandler::CleanupFiles(manifestPath, update.name);
588 wxLogMessage(
"Installation of %s successful", update.name.c_str());
589 wxURI uri(wxString(update.tarball_url.c_str()));
590 wxFileName fn(uri.GetPath());
591 std::string basename = fn.GetFullName().ToStdString();
594 wxLogDebug(
"Copied %s to local cache at %s", tempTarballPath.c_str(),
596 remove(tempTarballPath.c_str());
604 wxString pispec = _T(
"_pi.dll");
605#elif defined(__WXOSX__)
606 wxString pispec = _T(
"_pi.dylib");
608 wxString pispec = _T(
"_pi.so");
612 wxTextFile manifest_file(manifestPath);
614 if (manifest_file.Open()) {
616 for (wxString str = manifest_file.GetFirstLine(); !manifest_file.Eof();
617 str = manifest_file.GetNextLine()) {
618 if (str.Contains(pispec)) {
619 if (getenv(
"OCPN_KEEP_PLUGINS")) {
623 auto loader = PluginLoader::GetInstance();
624 if (!loader->CheckPluginCompatibility(str)) {
626 _(
"The plugin is not compatible with this version of OpenCPN, "
627 "and will be uninstalled.");
628 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
629 wxICON_INFORMATION | wxOK, 10);
631 PluginHandler::CleanupFiles(manifestPath, update.name);
640 if (b_forceEnable && pluginFile.Length()) {
641 wxString config_section = (_T (
"/PlugIns/" ));
642 wxFileName fn(pluginFile);
643 config_section += fn.GetFullName();
644 pConfig->SetPath(config_section);
645 pConfig->Write(_T (
"bEnabled" ),
true);
651 std::remove(handler->ImportedMetadataPath(update.name).c_str());
654 LoadAllPlugIns(
false);
676 pivp.
lat_min = tvp.GetBBox().GetMinLat();
677 pivp.
lat_max = tvp.GetBBox().GetMaxLat();
678 pivp.
lon_min = tvp.GetBBox().GetMinLon();
679 pivp.
lon_max = tvp.GetBBox().GetMaxLon();
681 pivp.
bValid = tvp.IsValid();
702 if (gFrame->GetPrimaryCanvas())
703 vp.
ref_scale = gFrame->GetPrimaryCanvas()->GetVP().ref_scale;
718 void OnPluginUtilAction(wxCommandEvent& event);
720 DECLARE_EVENT_TABLE()
724EVT_BUTTON(ID_CMD_BUTTON_PERFORM_ACTION, pluginUtilHandler::OnPluginUtilAction)
729void pluginUtilHandler::OnPluginUtilAction(wxCommandEvent& event) {
730 auto panel =
static_cast<PluginPanel*
>(
event.GetClientData());
733 wxASSERT(plugin_list_panel != 0);
735 auto actionPIC = panel->GetPlugin();
736 wxString name = actionPIC->m_common_name;
739 switch (panel->GetAction()) {
740 case ActionVerb::UPGRADE_TO_MANAGED_VERSION: {
741 auto loader = PluginLoader::GetInstance();
744 std::string pluginName = actionPIC->m_managed_metadata.name;
746 wxLogMessage(
"Installing managed plugin: %s", pluginName.c_str());
748 new GuiDownloader(plugin_list_panel, actionPIC->m_managed_metadata);
749 downloader->run(plugin_list_panel,
false);
753 if (isRegularFile(manifestPath.c_str())) {
755 for (
unsigned i = 0; i < loader->GetPlugInArray()->GetCount(); i += 1) {
756 if (actionPIC->m_managed_metadata.name ==
757 loader->GetPlugInArray()->Item(i)->m_common_name.ToStdString()) {
758 loader->UnLoadPlugIn(i);
764 LoadAllPlugIns(
false);
766 PluginHandler::CleanupFiles(manifestPath,
767 actionPIC->m_managed_metadata.name);
770 plugin_list_panel->SelectByName(name);
775 case ActionVerb::UPDATE_IMPORTED_VERSION:
776 case ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION:
777 case ActionVerb::REINSTALL_MANAGED_VERSION:
778 case ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION: {
780 auto metaSave = actionPIC->m_managed_metadata;
781 run_update_dialog(plugin_list_panel, actionPIC,
true,
782 metaSave.name.c_str());
786 case ActionVerb::INSTALL_MANAGED_VERSION: {
787 wxLogMessage(
"Installing new managed plugin.");
788 run_update_dialog(plugin_list_panel, actionPIC,
false);
792 case ActionVerb::UNINSTALL_MANAGED_VERSION: {
797 message.Printf(
"%s %s\n", actionPIC->m_managed_metadata.name.c_str(),
798 actionPIC->m_managed_metadata.version.c_str());
799 message += _(
"successfully un-installed");
801 wxLogMessage(
"Uninstalling %s",
802 actionPIC->m_managed_metadata.name.c_str());
805 actionPIC->m_managed_metadata.name);
808 auto loader = PluginLoader::GetInstance();
809 LoadAllPlugIns(
false);
812 OCPNMessageBox(gFrame, message, _(
"Un-Installation complete"),
813 wxICON_INFORMATION | wxOK);
818 case ActionVerb::NOP:
829const wxEventType wxEVT_OCPN_MSG = wxNewEventType();
831OCPN_MsgEvent::OCPN_MsgEvent(wxEventType commandType,
int id)
832 : wxEvent(id, commandType) {}
834OCPN_MsgEvent::~OCPN_MsgEvent() {}
836wxEvent* OCPN_MsgEvent::Clone()
const {
838 newevent->m_MessageID =
841 newevent->m_MessageText = this->m_MessageText.c_str();
850PlugInToolbarToolContainer::PlugInToolbarToolContainer() {
854 bitmap_Rollover_day = NULL;
855 bitmap_Rollover_dusk = NULL;
856 bitmap_Rollover_night = NULL;
859PlugInToolbarToolContainer::~PlugInToolbarToolContainer() {
863 delete bitmap_Rollover_day;
864 delete bitmap_Rollover_dusk;
865 delete bitmap_Rollover_night;
876#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
877EVT_CURL_END_PERFORM(CurlThreadId, PlugInManager::OnEndPerformCurlDownload)
878EVT_CURL_DOWNLOAD(CurlThreadId, PlugInManager::OnCurlDownload)
882static
void event_message_box(const wxString& msg) {
883 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
884 wxICON_INFORMATION | wxOK, 0);
890 if (!pic->m_toolbox_panel) NotifySetupOptionsPlugin(pic);
895PlugInManager::PlugInManager(
MyFrame* parent) {
896#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
897 m_pCurlThread = NULL;
903 MyFrame* pFrame = GetParentFrame();
905 m_plugin_menu_item_id_next = CanvasMenuHandler::GetNextContextMenuId();
906 m_plugin_tool_id_next = pFrame->GetNextToolbarToolId();
919 new wxRadioBox(pFrame, -1, _T(
""), wxPoint(0, 0), wxSize(-1, -1), as);
925#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
927 m_last_online =
false;
928 m_last_online_chk = -1;
933 m_blacklist = blacklist_factory();
934 m_blacklist_ui = std::unique_ptr<BlacklistUI>(
new BlacklistUI());
936 wxDEFINE_EVENT(EVT_JSON_TO_ALL_PLUGINS,
ObservedEvt);
937 evt_json_to_all_plugins_listener.
Listen(g_pRouteMan->
json_msg,
this,
938 EVT_JSON_TO_ALL_PLUGINS);
939 Bind(EVT_JSON_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
940 auto json = std::static_pointer_cast<const wxJSONValue>(ev.
GetSharedPtr());
941 SendJSONMessageToAllPlugins(ev.GetString(), *json);
944 wxDEFINE_EVENT(EVT_LEGINFO_TO_ALL_PLUGINS,
ObservedEvt);
946 EVT_LEGINFO_TO_ALL_PLUGINS);
947 Bind(EVT_LEGINFO_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
948 auto ptr = UnpackEvtPointer<ActiveLegDat>(ev);
949 SendActiveLegInfoToAllPlugIns(ptr.get());
952 HandlePluginLoaderEvents();
958 m_new_msgtype_lstnr.
Init(NavMsgBus::GetInstance().new_msg_event,
961PlugInManager::~PlugInManager() {
962#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
963 wxCurlBase::Shutdown();
965 delete m_utilHandler;
968void PlugInManager::InitCommListeners(
void) {
972 auto& msgbus = NavMsgBus::GetInstance();
975 m_listener_SignalK.
Listen(sk_msg,
this, EVT_SIGNALK);
982void PlugInManager::OnNewMessageType() {
983 for (
auto msg_key :
NavMsgBus::GetInstance().GetActiveMessages()) {
984 if (m_0183_listeners.find(msg_key) != m_0183_listeners.end())
continue;
985 if (msg_key.find(
"::") == std::string::npos)
continue;
987 if (key_parts.size() < 2)
continue;
992 m_0183_listeners[msg_key] = std::move(ol);
997 assert(n0183_msg->bus == NavAddr::Bus::N0183);
998 const std::string& payload = n0183_msg->payload;
1000 if (payload[0] ==
'$') {
1001 const auto& drivers = CommDriverRegistry::GetInstance().
GetDrivers();
1002 auto& target_driver =
FindDriver(drivers, n0183_msg->source->iface);
1006 bool passes_input_filter =
true;
1010 passes_input_filter =
1011 params.SentencePassesFilter(payload.c_str(), FILTER_INPUT);
1014 }
else if (payload[0] ==
'!') {
1015 SendAISSentenceToAllPlugIns(payload.c_str());
1020 g_ownshipMMSI_SK = sK_msg->context_self;
1025 std::string msgTerminated = sK_msg->raw_message;
1028 int errors = jsonReader.
Parse(msgTerminated, &root);
1029 if (errors == 0) SendJSONMessageToAllPlugins(wxT(
"OCPN_CORE_SIGNALK"), root);
1038wxDEFINE_EVENT(EVT_PLUGMGR_ROUTEMAN_MSG,
ObservedEvt);
1039wxDEFINE_EVENT(EVT_BLACKLISTED_PLUGIN, wxCommandEvent);
1040wxDEFINE_EVENT(EVT_LOAD_DIRECTORY, wxCommandEvent);
1041wxDEFINE_EVENT(EVT_LOAD_PLUGIN, wxCommandEvent);
1042wxDEFINE_EVENT(EVT_PLUGIN_UNLOAD, wxCommandEvent);
1043wxDEFINE_EVENT(EVT_PLUGLIST_CHANGE, wxCommandEvent);
1044wxDEFINE_EVENT(EVT_UPDATE_CHART_TYPES, wxCommandEvent);
1045wxDEFINE_EVENT(EVT_PLUGIN_LOADALL_FINALIZE, wxCommandEvent);
1047void PlugInManager::HandlePluginLoaderEvents() {
1048 auto loader = PluginLoader::GetInstance();
1050 loader->SetOnDeactivateCb(
1052 evt_pluglist_change_listener.
Listen(loader->evt_pluglist_change,
this,
1053 EVT_PLUGLIST_CHANGE);
1054 Bind(EVT_PLUGLIST_CHANGE, [&](wxCommandEvent&) {
1056 if (g_options) g_options->itemBoxSizerPanelPlugins->Layout();
1059 evt_load_directory_listener.
Listen(loader->evt_load_directory,
this,
1060 EVT_LOAD_DIRECTORY);
1061 Bind(EVT_LOAD_DIRECTORY, [&](wxCommandEvent&) {
1062 pConfig->SetPath(
"/PlugIns/");
1063 SetPluginOrder(pConfig->Read(
"PluginOrder", wxEmptyString));
1066 evt_load_plugin_listener.
Listen(loader->evt_load_plugin,
this,
1068 Bind(EVT_LOAD_PLUGIN, [&](wxCommandEvent& ev) {
1073 evt_update_chart_types_listener.
Listen(loader->evt_update_chart_types,
this,
1074 EVT_UPDATE_CHART_TYPES);
1075 Bind(EVT_UPDATE_CHART_TYPES,
1076 [&](wxCommandEvent& ev) { UpDateChartDataTypes(); });
1078 evt_plugin_loadall_finalize_listener.
Listen(
1079 loader->evt_plugin_loadall_finalize,
this, EVT_PLUGIN_LOADALL_FINALIZE);
1080 Bind(EVT_PLUGIN_LOADALL_FINALIZE,
1081 [&](wxCommandEvent& ev) { FinalizePluginLoadall(); });
1083 evt_ais_json_listener.
Listen(g_pAIS->
plugin_msg,
this, EVT_PLUGMGR_AIS_MSG);
1085 EVT_PLUGMGR_ROUTEMAN_MSG);
1087 auto pTarget = UnpackEvtPointer<AisTargetData>(ev);
1088 SendAisJsonMessage(pTarget);
1090 Bind(EVT_PLUGMGR_ROUTEMAN_MSG, [&](
ObservedEvt& ev) {
1091 auto msg = UnpackEvtPointer<wxJSONValue>(ev);
1092 SendJSONMessageToAllPlugins(ev.GetString(), *msg);
1100wxDEFINE_EVENT(EVT_DOWNLOAD_FAILED, wxCommandEvent);
1101wxDEFINE_EVENT(EVT_DOWNLOAD_OK, wxCommandEvent);
1103void PlugInManager::HandlePluginHandlerEvents() {
1104 auto loader = PluginLoader::GetInstance();
1106 evt_download_failed_listener.
Listen(loader->evt_update_chart_types,
this,
1107 EVT_DOWNLOAD_FAILED);
1108 Bind(EVT_DOWNLOAD_FAILED, [&](wxCommandEvent& ev) {
1109 wxString message = _(
"Please check system log for more info.");
1110 OCPNMessageBox(gFrame, message, _(
"Installation error"),
1111 wxICON_ERROR | wxOK | wxCENTRE);
1114 evt_download_ok_listener.
Listen(loader->evt_update_chart_types,
this,
1116 Bind(EVT_DOWNLOAD_OK, [&](wxCommandEvent& ev) {
1117 wxString message(ev.GetString());
1118 message += _(
" successfully installed from cache");
1119 OCPNMessageBox(gFrame, message, _(
"Installation complete"),
1120 wxICON_INFORMATION | wxOK | wxCENTRE);
1124bool PlugInManager::CallLateInit(
void) {
1127 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1128 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1131 switch (pic->m_api_version) {
1144 ProcessLateInit(pic);
1154 wxString msg(
"PlugInManager: Calling LateInit PlugIn: ");
1159 if (ppi) ppi->LateInit();
1167 ChartData->PurgeCachePlugins();
1168 gFrame->InvalidateAllQuilts();
1171 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1174 if (pttc->m_pplugin == pic->m_pplugin) {
1175 m_PlugInToolbarTools.Remove(pttc);
1181 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1183 if (pimis->m_pplugin == pic->m_pplugin) {
1184 m_PlugInMenuItems.Remove(pimis);
1190bool PlugInManager::IsAnyPlugInChartEnabled() {
1193 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1194 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1196 if (pic->m_enabled && pic->m_init_state) {
1205void PlugInManager::UpdateManagedPlugins() {
1207 PluginLoader::GetInstance()->
SortPlugins(ComparePlugins);
1210 g_options->itemBoxSizerPanelPlugins->Layout();
1213bool PlugInManager::UpDateChartDataTypes() {
1215 if (NULL == ChartData)
return bret;
1217 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1218 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1221 if (pic->m_init_state) {
1228 if (bret) ChartData->UpdateChartClassDescriptorArray();
1233void PlugInManager::FinalizePluginLoadall() {
1237 SetColorSchemeForAllPlugIns(global_color_scheme);
1240 SendBaseConfigToAllPlugIns();
1241 SendS52ConfigToAllPlugIns(
true);
1242 SendSKConfigToAllPlugIns();
1247 if (gFrame->GetPrimaryCanvas()->GetglCanvas())
1248 gFrame->GetPrimaryCanvas()->GetglCanvas()->SendJSONConfigMessage();
1256void PlugInManager::SetPluginOrder(wxString serialized_names) {
1257 m_plugin_order.Empty();
1258 wxStringTokenizer tokenizer(serialized_names,
";");
1259 while (tokenizer.HasMoreTokens()) {
1260 m_plugin_order.Add(tokenizer.GetNextToken());
1264wxString PlugInManager::GetPluginOrder() {
1265 wxString plugins = wxEmptyString;
1266 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1267 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1268 plugins.Append(plugin_array->Item(i)->m_common_name);
1269 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1274bool PlugInManager::UpdateConfig() {
1278 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1279 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1283 wxString config_section = (_T (
"/PlugIns/" ));
1285 pConfig->SetPath(config_section);
1286 pConfig->Write(_T (
"bEnabled" ), pic->m_enabled);
1293void PlugInManager::ShowDeferredBlacklistMessages() {
1294 m_blacklist_ui->show_deferred_messages();
1297bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1299 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1302bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin* plugin) {
1307 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1308 name.Replace(
"class ", wxEmptyString);
1310 const std::type_info& ti =
typeid(*plugin);
1312 char* realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1313 wxString name = wxString::FromAscii(realname);
1316 return CheckBlacklistedPlugin(name, major, minor);
1319bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
1321 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1322 if (block_status == plug_status::unblocked)
return true;
1323 plug_data data(name.ToStdString(), major, minor);
1324 auto msg = m_blacklist->get_message(block_status, data);
1325 m_blacklist_ui->message(msg);
1329bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC& dc,
1333 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1334 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1336 if (pic->m_enabled && pic->m_init_state) {
1340 wxDC* pdc = dc.GetDC();
1343 switch (pic->m_api_version) {
1345 if (priority > 0)
break;
1352 if (priority > 0)
break;
1355 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1366 if (priority > 0)
break;
1369 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1374 if (priority > 0)
break;
1378 ppi->RenderOverlay(*pdc, &pivp);
1390 if (priority <= 0) {
1394 ppi->RenderOverlay(*pdc, &pivp);
1410 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1412 if ((m_cached_overlay_bm.GetWidth() != vp.
pix_width) ||
1413 (m_cached_overlay_bm.GetHeight() != vp.
pix_height))
1417 mdc.SelectObject(m_cached_overlay_bm);
1418 mdc.SetBackground(*wxBLACK_BRUSH);
1421 bool b_rendered =
false;
1423 switch (pic->m_api_version) {
1425 if (priority > 0)
break;
1432 if (priority > 0)
break;
1435 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1446 if (priority > 0)
break;
1449 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1454 if (priority > 0)
break;
1458 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1471 if (priority <= 0) {
1475 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1482 mdc, &pivp, g_canvasConfig, priority);
1491 mdc.SelectObject(wxNullBitmap);
1494 wxMask* p_msk =
new wxMask(m_cached_overlay_bm, wxColour(0, 0, 0));
1495 m_cached_overlay_bm.SetMask(p_msk);
1497 dc.DrawBitmap(m_cached_overlay_bm, 0, 0,
true);
1500 }
else if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1508bool PlugInManager::RenderAllGLCanvasOverlayPlugIns(wxGLContext* pcontext,
1512 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1513 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1515 if (pic->m_enabled && pic->m_init_state) {
1516 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1519 switch (pic->m_api_version) {
1521 if (priority > 0)
break;
1524 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
1536 if (priority > 0)
break;
1544 if (priority > 0)
break;
1561 if (priority <= 0) {
1586void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort& vp) {
1587 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1588 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1590 if (pic->m_enabled && pic->m_init_state) {
1599void NotifySetupOptionsPlugin(
const PlugInData* pd) {
1600 PluginLoader::GetInstance()->NotifySetupOptionsPlugin(pd);
1603void PlugInManager::NotifySetupOptions() {
1604 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1605 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1607 NotifySetupOptionsPlugin(pic);
1612 int ok_apply_cancel) {
1613 if (pic->m_enabled && pic->m_init_state) {
1616 auto loader = PluginLoader::GetInstance();
1623void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
1624 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1625 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1628 ClosePlugInPanel(pic, ok_apply_cancel);
1633int PlugInManager::AddCanvasContextMenuItemPIM(wxMenuItem* pitem,
1638 pmic->pmenu_item = pitem;
1639 pmic->m_pplugin = pplugin;
1640 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
1641 : m_plugin_menu_item_id_next;
1643 pmic->b_grey =
false;
1644 pmic->m_in_menu = name;
1645 pmic->extended = is_extended;
1647 m_PlugInMenuItems.Add(pmic);
1649 m_plugin_menu_item_id_next++;
1654void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char* name) {
1655 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1658 if (pimis->id == item) {
1659 m_PlugInMenuItems.Remove(pimis);
1667void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
1669 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1672 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1680void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
1682 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1685 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1686 pimis->b_grey = grey;
1693void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
1694 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1695 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1697 if (pic->m_enabled && pic->m_init_state)
1702void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
1703 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1704 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1706 if (pic->m_enabled && pic->m_init_state)
1711void PlugInManager::PrepareAllPluginContextMenus() {
1712 int canvasIndex = gFrame->GetCanvasIndexUnderMouse();
1713 if (canvasIndex < 0)
return;
1715 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1716 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1718 if (pic->m_enabled && pic->m_init_state) {
1720 switch (pic->m_api_version) {
1740void PlugInManager::SendSKConfigToAllPlugIns() {
1743 v[_T(
"self")] = g_ownshipMMSI_SK;
1747 SendMessageToAllPlugins(wxString(_T(
"OCPN_CORE_SIGNALK")), out);
1750void PlugInManager::SendBaseConfigToAllPlugIns() {
1753 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1754 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1755 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1756 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1757 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1760 if (g_MainToolbar) {
1761 v[_T(
"OpenCPN Toolbar Width")] = g_MainToolbar->GetToolbarRect().width;
1762 v[_T(
"OpenCPN Toolbar Height")] = g_MainToolbar->GetToolbarRect().height;
1763 v[_T(
"OpenCPN Toolbar PosnX")] = g_MainToolbar->GetToolbarRect().x;
1764 v[_T(
"OpenCPN Toolbar PosnY")] = g_MainToolbar->GetToolbarRect().y;
1768 v[_T(
"OpenCPN Zoom Mod Vector")] = g_chart_zoom_modifier_vector;
1769 v[_T(
"OpenCPN Zoom Mod Other")] = g_chart_zoom_modifier_raster;
1770 v[_T(
"OpenCPN Scale Factor Exp")] =
1771 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1772 v[_T(
"OpenCPN Display Width")] = (int)g_display_size_mm;
1779 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1782void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1785 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1786 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1787 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1788 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1789 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1797 v[_T(
"OpenCPN S52PLIB ShowAnchorConditions")] = ps52plib->GetAnchorOn();
1798 v[_T(
"OpenCPN S52PLIB ShowQualityOfData")] = ps52plib->GetQualityOfData();
1803 v[_T(
"OpenCPN S52PLIB MetaDisplay")] = ps52plib->m_bShowMeta;
1804 v[_T(
"OpenCPN S52PLIB DeclutterText")] = ps52plib->m_bDeClutterText;
1805 v[_T(
"OpenCPN S52PLIB ShowNationalText")] = ps52plib->m_bShowNationalTexts;
1806 v[_T(
"OpenCPN S52PLIB ShowImportantTextOnly")] =
1807 ps52plib->m_bShowS57ImportantTextOnly;
1808 v[_T(
"OpenCPN S52PLIB UseSCAMIN")] = ps52plib->m_bUseSCAMIN;
1809 v[_T(
"OpenCPN S52PLIB UseSUPER_SCAMIN")] = ps52plib->m_bUseSUPER_SCAMIN;
1810 v[_T(
"OpenCPN S52PLIB SymbolStyle")] = ps52plib->m_nSymbolStyle;
1811 v[_T(
"OpenCPN S52PLIB BoundaryStyle")] = ps52plib->m_nBoundaryStyle;
1812 v[_T(
"OpenCPN S52PLIB ColorShades")] =
1813 S52_getMarinerParam(S52_MAR_TWO_SHADES);
1814 v[_T(
"OpenCPN S52PLIB Safety Depth")] =
1815 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1816 v[_T(
"OpenCPN S52PLIB Shallow Contour")] =
1817 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1818 v[_T(
"OpenCPN S52PLIB Deep Contour")] =
1819 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1823 v[_T(
"OpenCPN S52PLIB GlobalReconfig")] = bReconfig;
1828 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1831void PlugInManager::NotifyAuiPlugIns(
void) {
1832 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
1833 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1835 if (pic->m_enabled && pic->m_init_state &&
1841int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1842 wxBitmap* bmpRollover, wxItemKind kind,
1843 wxString shortHelp, wxString longHelp,
1844 wxObject* clientData,
int position,
1847 pttc->label = label;
1849 if (!bitmap->IsOk()) {
1851 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1854 pttc->bitmap_day =
new wxBitmap(*bitmap);
1855 pttc->bitmap_day->UnShare();
1858 if (!bmpRollover->IsOk()) {
1860 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1863 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1864 pttc->bitmap_Rollover_day->UnShare();
1867 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1868 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1869 pttc->bitmap_Rollover_dusk =
1870 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1871 pttc->bitmap_Rollover_night =
1872 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1875 pttc->shortHelp = shortHelp;
1876 pttc->longHelp = longHelp;
1877 pttc->clientData = clientData;
1878 pttc->position = position;
1879 pttc->m_pplugin = pplugin;
1880 pttc->tool_sel = tool_sel;
1882 pttc->b_toggle =
false;
1883 pttc->id = m_plugin_tool_id_next;
1885 m_PlugInToolbarTools.Add(pttc);
1887 m_plugin_tool_id_next++;
1892int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1893 wxString SVGRolloverfile,
1894 wxString SVGToggledfile, wxItemKind kind,
1895 wxString shortHelp, wxString longHelp,
1896 wxObject* clientData,
int position,
1899 pttc->label = label;
1901 pttc->pluginNormalIconSVG = SVGfile;
1902 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1903 pttc->pluginToggledIconSVG = SVGToggledfile;
1908 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1909 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1910 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1911 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1912 pttc->bitmap_Rollover_dusk =
1913 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1914 pttc->bitmap_Rollover_night =
1915 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1918 pttc->shortHelp = shortHelp;
1919 pttc->longHelp = longHelp;
1920 pttc->clientData = clientData;
1921 pttc->position = position;
1922 pttc->m_pplugin = pplugin;
1923 pttc->tool_sel = tool_sel;
1925 pttc->b_toggle =
false;
1926 pttc->id = m_plugin_tool_id_next;
1928 m_PlugInToolbarTools.Add(pttc);
1930 m_plugin_tool_id_next++;
1935void PlugInManager::RemoveToolbarTool(
int tool_id) {
1936 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1939 if (pttc->id == tool_id) {
1940 m_PlugInToolbarTools.Remove(pttc);
1946 pParent->RequestNewToolbars();
1949void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1950 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1953 if (pttc->id == item) {
1955 pParent->RequestNewToolbars();
1962void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1963 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1966 if (pttc->id == item) {
1967 pttc->b_toggle = toggle;
1968 pParent->SetMasterToolbarItemState(item, toggle);
1975void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1976 wxBitmap* bmpRollover) {
1977 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1980 if (pttc->id == item) {
1981 delete pttc->bitmap_day;
1982 delete pttc->bitmap_dusk;
1983 delete pttc->bitmap_night;
1984 delete pttc->bitmap_Rollover_day;
1986 if (!bitmap->IsOk()) {
1988 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1991 pttc->bitmap_day =
new wxBitmap(*bitmap);
1992 pttc->bitmap_day->UnShare();
1995 if (!bmpRollover->IsOk()) {
1997 pttc->bitmap_Rollover_day =
1998 new wxBitmap(style->GetIcon(_T(
"default_pi")));
2001 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
2002 pttc->bitmap_Rollover_day->UnShare();
2005 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
2006 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
2008 pParent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
2009 pttc->bitmap_Rollover_day);
2016void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2017 wxString SVGfileRollover,
2018 wxString SVGfileToggled) {
2019 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2022 if (pttc->id == item) {
2023 pttc->pluginNormalIconSVG = SVGfile;
2024 pttc->pluginRolloverIconSVG = SVGfileRollover;
2025 pttc->pluginToggledIconSVG = SVGfileToggled;
2026 pParent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2027 pttc->pluginRolloverIconSVG,
2028 pttc->pluginToggledIconSVG);
2036 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2038 if (
id == pc->id)
return pc->m_pplugin;
2044wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2047 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2048 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2050 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2054 return wxEmptyString;
2057wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2059wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2060 unsigned char dim_ratio) {
2061 wxImage img_dup = pbmp_normal->ConvertToImage();
2063 if (!img_dup.IsOk())
return NULL;
2065 if (dim_ratio < 200) {
2067 int gimg_width = img_dup.GetWidth();
2068 int gimg_height = img_dup.GetHeight();
2070 double factor = (double)(dim_ratio) / 256.0;
2072 for (
int iy = 0; iy < gimg_height; iy++) {
2073 for (
int ix = 0; ix < gimg_width; ix++) {
2074 if (!img_dup.IsTransparent(ix, iy)) {
2075 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2076 img_dup.GetGreen(ix, iy),
2077 img_dup.GetBlue(ix, iy));
2078 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2079 hsv.value = hsv.value * factor;
2080 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2081 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2087 wxBitmap* ptoolBarBitmap;
2090 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2092 dwxdc.SelectObject(tbmp);
2094 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2096 ptoolBarBitmap =
new wxBitmap(img_dup);
2100 return ptoolBarBitmap;
2103wxArrayString PlugInManager::GetPlugInChartClassNameArray(
void) {
2104 wxArrayString array;
2105 auto plugin_array = PluginLoader::GetInstance()->
GetPlugInArray();
2106 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2108 if (pic && pic->m_enabled && pic->m_init_state &&
2113 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2114 array.Add(carray[j]);
2122 while (j < array.GetCount()) {
2123 wxString test = array[j];
2124 unsigned int k = j + 1;
2125 while (k < array.GetCount()) {
2126 if (test == array[k]) {
2144#define DISABLED_SETTINGS_MSG \
2145 _("These settings might destabilize OpenCPN and are by default disabled." \
2146 " To despite the dangers enable them manually add a CatalogExpert=1" \
2147 " line in the [PlugIns] section in the configuration file.")
2152CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2153 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2155 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2158 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2160 wxStaticBox* itemStaticBoxSizer4Static =
2161 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2162 wxStaticBoxSizer* itemStaticBoxSizer4 =
2163 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2164 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2168 m_catalogText =
new wxStaticText(
this, wxID_STATIC, _T(
""));
2169 itemStaticBoxSizer4->Add(m_catalogText,
2170 wxSizerFlags().Border().Proportion(1));
2171 m_catalogText->SetLabel(GetCatalogText(
false));
2174 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2175 itemStaticBoxSizer4->Add(rowSizer2,
2176 wxSizerFlags().Expand().Border().Proportion(1));
2178 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2179 wxDefaultPosition, wxDefaultSize, 0);
2180 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2181 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2182 &CatalogMgrPanel::OnUpdateButton,
this);
2183 rowSizer2->AddSpacer(4 * GetCharWidth());
2184 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2185 wxDefaultPosition, wxDefaultSize, 0);
2186 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2187 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2188 &CatalogMgrPanel::OnTarballButton,
this);
2190 rowSizer2->AddSpacer(4 * GetCharWidth());
2191 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2192 wxDefaultPosition, wxDefaultSize, 0);
2194 if (expert.Get(
false)) {
2195 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2196 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2198 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2199 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2202 rowSizer2->AddSpacer(4 * GetCharWidth());
2203 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2205 SetUpdateButtonLabel();
2208 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2209 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2211 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2215 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2216 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2217 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2220 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2222 if (!expert.Get(
false)) {
2224 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2225 wxDefaultPosition, wxDefaultSize, 0);
2226 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2227 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2228 &CatalogMgrPanel::OnUpdateButton,
this);
2229 SetUpdateButtonLabel();
2230 m_tarballButton = NULL;
2231 m_adv_button = NULL;
2234 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2235 itemStaticBoxSizer4->Add(m_catalogText,
2236 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2239 m_updateButton =
new wxButton(
2240 this, wxID_ANY,
"Update Plugin Catalog:master ",
2241 wxDefaultPosition, wxDefaultSize, 0);
2242 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2243 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2244 &CatalogMgrPanel::OnUpdateButton,
this);
2245 SetUpdateButtonLabel();
2248 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2249 wxDefaultPosition, wxDefaultSize, 0);
2250 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2252 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2253 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2256 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2257 wxDefaultPosition, wxDefaultSize, 0);
2258 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2259 2 * GetCharWidth());
2260 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2261 &CatalogMgrPanel::OnTarballButton,
this);
2267CatalogMgrPanel::~CatalogMgrPanel() {
2268 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2269 &CatalogMgrPanel::OnUpdateButton,
this);
2270 if (m_tarballButton)
2271 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2272 &CatalogMgrPanel::OnTarballButton,
this);
2275static const char*
const DOWNLOAD_REPO_PROTO =
2276 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2279void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2281 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2282 std::string url(g_catalog_custom_url);
2283 if (catalog !=
"custom") {
2284 url = std::string(DOWNLOAD_REPO_PROTO);
2288 std::string filePath =
2289 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2291 auto catalogHdlr = CatalogHandler::GetInstance();
2293 g_Platform->ShowBusySpinner();
2294 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2295 g_Platform->HideBusySpinner();
2297 std::string message;
2298 if (status != CatalogHandler::ServerStatus::OK) {
2299 message = _(
"Cannot download data from url");
2300 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2301 wxICON_ERROR | wxOK);
2307 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2309 wxFileName::GetPathSeparator() +
2310 _T(
"ocpn-plugins.xml"))) {
2311 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2312 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2317 if (!wxCopyFile(wxString(filePath.c_str()),
2319 wxFileName::GetPathSeparator() +
2320 _T(
"ocpn-plugins.xml"))) {
2321 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2322 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2328 if (catalog ==
"master") {
2330 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2331 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2337 pConfig->SetPath(_T(
"/PlugIns/"));
2338 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2345 pluginHandler->setMetadata(
"");
2349 auto cataloghdlr = CatalogHandler::GetInstance();
2350 cataloghdlr->ClearCatalogData();
2353 LoadAllPlugIns(
false);
2357 m_catalogText->SetLabel(GetCatalogText(
true));
2360 OCPNMessageBox(
this, _(
"Catalog update successful"),
2361 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2364void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2368 androidDisableRotation();
2371 dialog->ShowModal();
2374 androidEnableRotation();
2378void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2381 int response = g_Platform->DoFileSelectorDialog(
2382 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2383 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2385 if (response != wxID_OK) {
2390 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2394 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2395 _(
"OpenCPN Plugin Import Error"));
2399 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2400 _(
"OpenCPN Plugin Import Error"));
2401 handler->Uninstall(metadata.name);
2404 UninstallPlugin(metadata.name);
2405 ok = handler->InstallPlugin(metadata, path.ToStdString());
2407 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2408 _(
"OpenCPN Plugin Import Error"));
2411 metadata.is_imported =
true;
2413 std::ofstream file(metadata_path);
2416 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2417 <<
" for imported plugin: " << metadata.name;
2419 LoadAllPlugIns(
false,
true);
2422 wxString ws(_(
"Plugin"));
2423 ws += metadata.name + _(
" successfully imported");
2424 OCPNMessageBox(gFrame, ws, _(
"Installation complete"),
2425 wxICON_INFORMATION | wxOK | wxCENTRE);
2428wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2430 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2431 catalog += _T(
": ");
2434 pConfig->SetPath(_T(
"/PlugIns/"));
2435 wxString latestCatalog =
2436 pConfig->Read(_T(
"LatestCatalogDownloaded"), _T(
"default"));
2437 catalog += latestCatalog;
2443 std::string date = pluginHandler->GetCatalogData()->date;
2445 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2446 if (!updated) catalog += _T(
" : ") + _(
"Please Update Plugin Catalog.");
2452void CatalogMgrPanel::SetUpdateButtonLabel() {
2453 wxString label = _(
"Update Plugin Catalog");
2455 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2456 m_updateButton->SetLabel(label);
2460wxString CatalogMgrPanel::GetImportInitDir() {
2462 pConfig->SetPath(_T(
"/PlugIns/"));
2463 wxString lastImportDir;
2464 lastImportDir = pConfig->Read(_T(
"LatestImportDir"),
2465 g_Platform->GetWritableDocumentsDir());
2466 if (wxDirExists(lastImportDir)) {
2467 return lastImportDir;
2469 return (g_Platform->GetWritableDocumentsDir());
2478 const wxPoint& pos, const wxSize& size)
2479 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2480 m_PluginSelected(0) {
2481 m_is_loading.clear();
2482 SetSizer(
new wxBoxSizer(wxVERTICAL));
2483 ReloadPluginPanels();
2486void PluginListPanel::SelectByName(wxString& name) {
2487 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2488 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2490 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2491 pluginPanel->SetSelected(
true);
2492 pluginPanel->Layout();
2493 SelectPlugin(pluginPanel);
2502 std::vector<const PlugInData*> result;
2503 auto loader = PluginLoader::GetInstance();
2504 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2505 auto const item = loader->GetPlugInArray()->Item(i);
2506 if (item->m_managed_metadata.name.empty()) {
2507 const auto name = item->m_common_name.ToStdString();
2511 result.push_back(item);
2514 std::string slhs, srhs;
2515 for (
auto& cl : lhs->
Key()) slhs += toupper(cl);
2516 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2517 return slhs.compare(srhs) < 0;
2519 std::sort(result.begin(), result.end(), compare);
2524static bool IsPluginLoaded(
const std::string& name) {
2525 if (safe_mode::get_mode()) {
2528 std::find(installed.begin(), installed.end(),
ocpn::tolower(name));
2529 return found != installed.end();
2532 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2533 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2540 if (m_is_loading.test_and_set()) {
2542 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2547 m_PluginItems.Clear();
2549 wxWindowList kids = GetChildren();
2550 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2551 wxWindowListNode* node = kids.Item(i);
2552 wxWindow* win = node->GetData();
2554 if (pp) win->Destroy();
2556 GetSizer()->Clear();
2559 m_PluginSelected = 0;
2561 if (safe_mode::get_mode()) {
2564 for (
const auto& name : installed) AddPlugin(name);
2567 auto available = getCompatiblePlugins();
2571 return IsPluginLoaded(md.name);
2573 auto end = std::remove_if(available.begin(), available.end(), predicate);
2574 available.erase(end, available.end());
2580 std::string slhs, srhs;
2581 for (
auto& cl : lhs.name) slhs += toupper(cl);
2582 for (
auto& cr : rhs.name) srhs += toupper(cr);
2583 return slhs.compare(srhs) < 0;
2587 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2588 for (
const auto& p : available) unique_sorted_entries.insert(p);
2594 if (p->m_enabled) AddPlugin(*p);
2598 if (!p->m_enabled) AddPlugin(*p);
2601 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2609 m_is_loading.clear();
2612void PluginListPanel::AddPlugin(
const std::string& name) {
2615 panel->SetSelected(
false);
2616 GetSizer()->Add(panel, 0, wxEXPAND);
2617 m_PluginItems.Add(panel);
2618 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2619 GetSizer()->AddSpacer(m_pluginSpacer);
2622void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2624 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2625 pPluginPanel->SetSelected(
false);
2626 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2627 m_PluginItems.Add(pPluginPanel);
2629 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2630 GetSizer()->AddSpacer(m_pluginSpacer);
2643int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2644 wxBoxSizer* sizer) {
2646 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2647 auto panel = plugins.Item(i);
2648 bool was_selected = panel->GetSelected();
2649 panel->SetSelected(
false);
2651 wxSize unselected = panel->GetSize();
2653 panel->SetSelected(
true);
2655 wxSize selected = panel->GetSize();
2657 int dy = selected.GetHeight() - unselected.GetHeight();
2658 max_dy = wxMax(max_dy, dy);
2659 panel->SetSelected(was_selected);
2664PluginListPanel::~PluginListPanel() {}
2666void PluginListPanel::UpdateSelections() {
2667 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2670 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2675void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2677 GetViewStart(&xs, &ys);
2680 if (m_PluginSelected) {
2681 m_PluginSelected->SetSelected(
false);
2682 m_PluginSelected->Layout();
2685 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2687 m_PluginSelected = pi;
2689 GetSizer()->Layout();
2691 wxSize size = GetBestVirtualSize();
2692 SetVirtualSize(size);
2697 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2699 int yd = pPluginPanel->GetSize().y;
2701 htop += m_pluginSpacer;
2702 if (pPluginPanel == pi) {
2703 int piBottom = htop - (ys * g_options->GetScrollRate());
2704 if (piBottom > GetClientSize().y) {
2705 ys += (piBottom - GetClientSize().y) / g_options->GetScrollRate();
2715 int pos = m_PluginItems.Index(pi);
2718 m_PluginItems.RemoveAt(pos);
2721 m_PluginItems.Insert(pi, pos - 1);
2722 wxStaticLine* itemStaticLine =
new wxStaticLine(
2723 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2728 m_PluginSelected = pi;
2730 GetSizer()->Layout();
2736 int pos = m_PluginItems.Index(pi);
2737 if (pos == (
int)m_PluginItems.Count() -
2740 m_PluginItems.RemoveAt(pos);
2743 m_PluginItems.Insert(pi, pos + 1);
2744 wxStaticLine* itemStaticLine =
new wxStaticLine(
2745 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2750 m_PluginSelected = pi;
2752 GetSizer()->Layout();
2757static bool canUninstall(std::string name) {
2762 if (plugin.name == name) {
2763 if (safe_mode::get_mode())
2766 return !plugin.readonly;
2773 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2775 m_is_safe_panel(true) {
2777 wxASSERT(m_PluginListPanel != 0);
2778 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2779 SetSizer(top_sizer);
2780 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2781 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2783 double iconSize = GetCharWidth() * 4;
2785 int icon_scale = iconSize * dpi_mult;
2787 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2788 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2789 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2791 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2792 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2793 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2794 top_horizontal->Add(m_pVersion);
2797 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2798 top_horizontal->Add(m_pButtons);
2799 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2800 top_horizontal->Add(m_info_btn);
2801 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2802 wxDefaultPosition, wxDefaultSize, 0);
2803 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2805 auto uninstall = [&](wxCommandEvent ev) {
2806 auto n = m_pName->GetLabel().ToStdString();
2808 OCPNMessageBox(gFrame, std::string(_(
"Uninstall plugin ")) + n +
"?",
2809 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2810 if (result != wxID_OK)
return;
2814 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2818EVT_PAINT(PluginPanel::OnPaint)
2823 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2825 m_is_safe_panel(false) {
2828 wxASSERT(m_PluginListPanel != 0);
2830 m_bSelected =
false;
2831 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2832 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2834 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2837 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2838 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2839 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2840 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2842 double iconSize = GetCharWidth() * 4;
2844 int icon_scale = iconSize * dpi_mult;
2846 wxImage plugin_icon;
2848 if (m_plugin.m_bitmap.IsOk()) {
2849 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2852 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2853 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2854 path.AppendDir(
"uidata");
2855 path.AppendDir(
"traditional");
2856 bitmap = LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2857 }
else if (plugin_icon.IsOk()) {
2858 int nowSize = plugin_icon.GetWidth();
2859 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2860 bitmap = wxBitmap(plugin_icon);
2862 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2864 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2866 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2867 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2869 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2872 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2873 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2876 int nChars = g_options->GetSize().x / GetCharWidth();
2877 bool bCompact =
false;
2883 wxString nameString = m_plugin.m_common_name;
2887 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2888 if (nameWidth > maxWidth) {
2889 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2890 wxELLIPSIZE_END, maxWidth);
2892 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2893 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2894 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2895 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2897 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2898 sl1->AddGrowableCol(1);
2899 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2901 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2902 sl1->Add(m_pVersion, 0, wxALL, 5);
2903 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2906 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2907 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2909 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2910 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2911 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2914 wxString descriptionString = m_plugin.m_short_description;
2915 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2916 int descriptionWidth;
2917 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2918 if (descriptionWidth > maxDescriptionWidth)
2920 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2921 wxELLIPSIZE_END, maxDescriptionWidth);
2926 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2927 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2928 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2929 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2930 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2933 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2934 itemBoxSizer03->AddGrowableCol(2);
2935 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2937 wxString nameString = m_plugin.m_common_name;
2938 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2939 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2940 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2944 wxFont font = GetFont();
2945 font.SetWeight(wxFONTWEIGHT_BOLD);
2946 m_pName->SetFont(font);
2949 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2951 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2952 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2953 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2956 !m_plugin.m_managed_metadata.is_orphan)) {
2959 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2960 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2962 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2963 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2964 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2966 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2968 m_pDescription =
new wxStaticText(
2969 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2971 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2972 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2973 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2977 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2979 itemBoxSizer02->Add(m_info_btn, 0);
2981 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2982 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2983 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2984 wxDefaultPosition, wxDefaultSize, 0);
2985 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
2987 m_pButtons->AddSpacer(3 * GetCharWidth());
2990 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
2991 wxDefaultPosition, wxDefaultSize, 0);
2992 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
2994 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2995 wxDefaultPosition, wxDefaultSize, 0);
2996 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
2998 m_pButtons =
new wxBoxSizer(wxVERTICAL);
2999 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
3001 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
3002 m_pButtons->Add(tline, 0, wxALL, 2);
3004 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
3005 wxDefaultPosition, wxDefaultSize, 0);
3006 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
3008 tline->AddSpacer(3 * GetCharWidth());
3010 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
3012 tline->Add(m_info_btn, 0);
3015 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3016 wxDefaultPosition, wxDefaultSize);
3017 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3019 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3020 wxDefaultPosition, wxDefaultSize, 0);
3021 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3024 wxBitmap statusBitmap;
3025 const auto stat = m_plugin.m_status;
3026 auto icon_name = icon_by_status.at(stat);
3027 if (stat == PluginStatus::Imported &&
3028 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3030 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3033 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3034 path.AppendDir(
"uidata");
3035 path.AppendDir(
"traditional");
3037 int bmsize = GetCharWidth() * 3 * dpi_mult;
3038 if (path.IsFileReadable()) {
3039 statusBitmap = LoadSVG(path.GetFullPath(), bmsize, bmsize);
3040 ok = statusBitmap.IsOk();
3043 auto style = g_StyleManager->GetCurrentStyle();
3044 statusBitmap = wxBitmap(style->GetIcon(_T(
"default_pi"), bmsize, bmsize));
3045 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3048 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3049 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3050 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3052 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3055 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3057 itemBoxSizer02->AddSpacer(GetCharWidth());
3059 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3060 &PluginPanel::OnPluginPreferences,
this);
3061 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3062 &PluginPanel::OnPluginUninstall,
this);
3063 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3064 &PluginPanel::OnPluginAction,
this);
3066 SetSelected(m_bSelected);
3067 SetAutoLayout(
true);
3075PluginPanel::~PluginPanel() {
3076 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3077 if (m_is_safe_panel)
return;
3078 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3080 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3081 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3082 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3083 if (m_pButtonAction) {
3084 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3085 &PluginPanel::OnPluginAction,
this);
3087 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3088 &PluginPanel::OnPluginPreferences,
this);
3089 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3090 &PluginPanel::OnPluginEnableToggle,
this);
3093void PluginPanel::SetActionLabel(wxString& label) {
3094 m_pButtonAction->SetLabel(label);
3098static wxStopWatch swclick;
3099static int downx, downy;
3101void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3104 event.GetPosition(&downx, &downy);
3110void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3112 qDebug() << swclick.Time();
3113 if (swclick.Time() < 200) {
3115 event.GetPosition(&upx, &upy);
3116 if ((fabs(upx - downx) < GetCharWidth()) &&
3117 (fabs(upy - downy) < GetCharWidth())) {
3125void PluginPanel::DoPluginSelect() {
3126 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3132 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3133 }
else if (m_bSelected) {
3135 m_PluginListPanel->SelectPlugin(NULL);
3138 m_PluginListPanel->SelectPlugin(
this);
3146static PluginMetadata GetMetadataByName(
const std::string& name) {
3148 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3149 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3150 if (found == plugins.end()) {
3151 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3156void PluginPanel::SetSelected(
bool selected) {
3157 m_bSelected = selected;
3159 m_pVersion->SetLabel(
3162 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3163 m_pButtons->Show(
true);
3164 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3167 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3170 unInstallPossible =
false;
3173 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3175 m_pButtonUninstall->Show(unInstallPossible);
3177 if (m_plugin.m_managed_metadata.info_url.size()) {
3178 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3182 m_cbEnable->Show(
true);
3187 switch (m_plugin.m_status) {
3188 case PluginStatus::LegacyUpdateAvailable:
3189 label = _(
"Upgrade to Version ");
3190 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3191 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3192 m_pButtonAction->Enable();
3195 case PluginStatus::ManagedInstallAvailable:
3196 label = _(
"Install...");
3197 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3198 m_pButtonAction->Enable();
3201 case PluginStatus::ManagedInstalledUpdateAvailable:
3202 label = _(
"Update to ");
3203 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3204 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3205 m_pButtonAction->Enable();
3208 case PluginStatus::ManagedInstalledCurrentVersion:
3209 label = _(
"Reinstall");
3210 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3211 m_pButtonAction->Enable();
3214 case PluginStatus::ManagedInstalledDowngradeAvailable:
3215 label = _(
"Downgrade");
3216 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3217 m_pButtonAction->Enable();
3220 case PluginStatus::Imported:
3221 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3222 label = _(
"Update");
3223 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3225 m_pButtonAction->Hide();
3226 m_action = ActionVerb::NOP;
3231 m_action = ActionVerb::NOP;
3232 m_pButtonAction->Hide();
3236 m_action = ActionVerb::NOP;
3237 m_pButtonAction->Hide();
3242 m_action = ActionVerb::NOP;
3245 SetActionLabel(label);
3248 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3257 m_pButtons->Show(
false);
3260 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3261 m_cbEnable->Show(
false);
3277 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3279 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3282 SetEnabled(m_plugin.m_enabled);
3297void PluginPanel::OnPaint(wxPaintEvent& event) {
3300 int penWidth = m_penWidthUnselected;
3301 wxColour color = GetDialogColor(DLG_UNSELECTED_BACKGROUND);
3302 wxColour border = GetDialogColor(DLG_UNSELECTED_ACCENT);
3305 penWidth = m_penWidthSelected;
3306 color = GetDialogColor(DLG_SELECTED_BACKGROUND);
3307 border = GetDialogColor(DLG_SELECTED_ACCENT);
3310 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3312 dc.SetPen(wxPen(border, penWidth));
3314 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3317void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3318 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3321 androidDisableRotation();
3332void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3333 SetEnabled(event.IsChecked());
3334 m_pVersion->SetLabel(
3343void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3344 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
3347 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3348 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3349 actionEvent.SetClientData(
this);
3350 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3353void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3355 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3356 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3357 actionEvent.SetClientData(
this);
3358 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3363static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3364 auto font = window->GetFont();
3365 font.SetStyle(style);
3366 window->SetFont(font);
3369void PluginPanel::SetEnabled(
bool enabled) {
3370 if (m_is_safe_panel)
return;
3373 if (enabled) NotifySetupOptionsPlugin(&m_plugin);
3374 if (!enabled && !m_bSelected) {
3375 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3376 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3377 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3380 m_pVersion->Disable();
3381 m_pDescription->Disable();
3384 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3385 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3386 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3389 m_pVersion->Enable();
3390 m_pDescription->Enable();
3395 m_pName->Enable(enabled || m_bSelected);
3396 m_pVersion->Enable(enabled || m_bSelected);
3397 m_pDescription->Enable(enabled || m_bSelected);
3401 wxString description = m_plugin.m_long_description;
3402 if (description.IsEmpty())
3403 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3406 g_options->GetSize().x * 7 / 10);
3407 m_pDescription->SetLabel(wrapper.GetWrapped());
3408 if (m_plugin.m_managed_metadata.info_url.size()) {
3409 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3413 wxString description = m_plugin.m_short_description;
3414 if (description.IsEmpty())
3415 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3417 g_options->GetSize().x * 7 / 10);
3418 m_pDescription->SetLabel(wrapper.GetWrapped());
3421 m_pButtonPreferences->Enable(enabled &&
3423 m_cbEnable->SetValue(enabled);
3426void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3427 m_PluginListPanel->MoveUp(
this);
3430void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3431 m_PluginListPanel->MoveDown(
this);
3436 : wxPanel(parent), m_url(url) {
3437 auto vbox =
new wxBoxSizer(wxVERTICAL);
3438 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3439 button->Enable(strlen(url) > 0);
3442 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3443 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3451PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3453PlugInChartBase::~PlugInChartBase() {}
3462 bool b_allow_overzoom) {
3474 const wxRegion& Region) {
3475 return wxNullBitmap;
3484 wxRegion* pValidRegion) {}
3497 wxRect* pSourceRect) {}
3514 double* plat,
double* plon) {}
3521PlugInChartBaseGL::PlugInChartBaseGL() {}
3523PlugInChartBaseGL::~PlugInChartBaseGL() {}
3527 const wxRegion& Region,
3528 bool b_use_stencil) {
3554PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3556PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3560 const wxRegion& Region,
3561 bool b_use_stencil) {
3567 const wxRegion& Region,
bool b_use_stencil) {
3573 const wxRegion& Region,
bool b_use_stencil) {
3579 return wxNullBitmap;
3583 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3587ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3592wxString PlugInChartBaseExtended::CreateObjDescriptions(
3593 ListOfPI_S57Obj* obj_list) {
3597int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3599int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3601int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3603float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3612PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3614PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3617PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3627PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3629PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3641ChartPlugInWrapper::ChartPlugInWrapper() {}
3643ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3644 m_ppo = ::wxCreateDynamicObject(chart_class);
3648ChartPlugInWrapper::~ChartPlugInWrapper() {
3649 if (m_ppicb)
delete m_ppicb;
3652wxString ChartPlugInWrapper::GetFileSearchMask(
void) {
3659InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3660 ChartInitFlag init_flags) {
3662 wxWindow* pa = wxWindow::FindFocus();
3664 InitReturn ret_val = (InitReturn)m_ppicb->
Init(name, (
int)init_flags);
3668 if (ret_val == INIT_OK) {
3675 m_ID = m_ppicb->
GetID();
3679 m_SE = m_ppicb->
GetSE();
3693 if ((fabs(m_Chart_Skew) < .01) &&
3694 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3696 if (GetChartExtent(&extent)) {
3697 double lon_range = extent.ELON - extent.WLON;
3698 if ((lon_range > 0) &&
3700 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3704 m_overlayENC =
false;
3706 wxCharBuffer buf = m_FullPath.ToUTF8();
3707 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3713 m_ChartType = CHART_TYPE_UNKNOWN;
3714 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3720 if (pc) pc->SetFocus();
3724 return INIT_FAIL_REMOVE;
3728int ChartPlugInWrapper::GetCOVREntries() {
3735int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3742int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3749float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3761int ChartPlugInWrapper::GetNoCOVREntries() {
3771int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3781int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3791float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3801bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3805 pext->NLAT = xpi.
NLAT;
3806 pext->SLAT = xpi.
SLAT;
3807 pext->ELON = xpi.
ELON;
3808 pext->WLON = xpi.
WLON;
3817ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3822 if (!pThumbData->pDIBThumb) {
3823 wxBitmap* pBMPOwnedByChart =
3824 m_ppicb->
GetThumbnail(tnx, tny, m_global_color_scheme);
3825 if (pBMPOwnedByChart) {
3826 wxImage img = pBMPOwnedByChart->ConvertToImage();
3827 pThumbData->pDIBThumb =
new wxBitmap(img);
3829 pThumbData->pDIBThumb = NULL;
3832 pThumbData->Thumb_Size_X = tnx;
3833 pThumbData->Thumb_Size_Y = tny;
3860 pThumbData->ShipX = 0;
3861 pThumbData->ShipY = 0;
3868ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3870bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3874double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3875 bool b_allow_overzoom) {
3882double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3904void RenderRotateToViewPort(
const ViewPort& VPoint) {
3905#ifndef USE_ANDROID_GLES2
3907 glTranslatef(xt, yt, 0);
3908 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3909 glTranslatef(-xt, -yt, 0);
3913void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3914#ifndef USE_ANDROID_GLES2
3916 glTranslatef(xt, yt, 0);
3917 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3918 glTranslatef(-xt, -yt, 0);
3922bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3925 const LLRegion& Region) {
3934 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3935 wxRegion* r = RectRegion.GetNew_wxRegion();
3938 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3939 chart_region.Intersect(Region);
3941 if (!chart_region.Empty()) {
3942 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3944 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3948#ifndef USE_ANDROID_GLES2
3951 RenderRotateToViewPort(VPoint);
3956 glChartCanvas::s_b_useStencil);
3959 glChartCanvas::s_b_useStencil);
3960 UndoRenderRotateToViewPort(VPoint);
3962#ifndef USE_ANDROID_GLES2
3965 glChartCanvas::DisableClipRegion();
3979bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
3980 const wxGLContext& glc,
const ViewPort& VPoint,
3981 const OCPNRegion& RectRegion,
const LLRegion& Region) {
3990 if (!Region.Empty() && ppicb_x) {
3992 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
3993 glChartCanvas::DisableClipRegion();
3996 RenderRotateToViewPort(VPoint);
3999 wxRegion* r = RectRegion.GetNew_wxRegion();
4002 glChartCanvas::s_b_useStencil);
4005 UndoRenderRotateToViewPort(VPoint);
4010 else if (!Region.Empty() &&
4014 wxRegion* r = RectRegion.GetNew_wxRegion();
4017 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4018 chart_region.Intersect(Region);
4020 if (!chart_region.Empty()) {
4021 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4023 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4025 RenderRotateToViewPort(VPoint);
4029 glChartCanvas::s_b_useStencil);
4032 UndoRenderRotateToViewPort(VPoint);
4034 glChartCanvas::DisableClipRegion();
4047bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4054 if (!Region.Empty() && ppicb_x) {
4055 wxRegion* r = Region.GetNew_wxRegion();
4057#ifndef USE_ANDROID_GLES2
4060 RenderRotateToViewPort(VPoint);
4064 glChartCanvas::s_b_useStencil);
4065 UndoRenderRotateToViewPort(VPoint);
4067#ifndef USE_ANDROID_GLES2
4080bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4086 if (Region.IsOk()) {
4087 wxRegion* r = Region.GetNew_wxRegion();
4094 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4095 wxColour nodat_sub = nodat;
4097#ifdef ocpnUSE_ocpnBitmap
4098 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4100 m_pMask =
new wxMask(obmp, nodat_sub);
4101 obmp.SetMask(m_pMask);
4103 dc.SelectObject(obmp);
4114bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4125 if (Region.IsOk() && (pCBx || ppicb)) {
4126 wxRegion* r = Region.GetNew_wxRegion();
4141bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4144 bool ret_val =
false;
4147 if (Region.IsOk()) {
4148 wxRegion* r = Region.GetNew_wxRegion();
4162void ChartPlugInWrapper::ClearPLIBTextList() {
4170bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4174 return m_ppicb->
AdjustVP(pivp_last, pivp_proposed);
4179void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4194void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4198 m_global_color_scheme = cs;
4200 if (pThumbData) pThumbData->pDIBThumb = NULL;
4204 double target_scale_ppm) {
4211void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4212 wxRect* pSourceRect) {
4219double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4221 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4226bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4228 wxCriticalSectionLocker locker(m_critSect);
4237int ChartPlugInWrapper::GetSize_X() {
4244int ChartPlugInWrapper::GetSize_Y() {
4251void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4252 double& pixx,
double& pixy) {
4256void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4257 double* plat,
double* plon) {
4272 return toSDMM(NEflag, a, hi_precision);
4276 return GetGlobalColor(colorName);
4280 const wxString& caption,
int style,
int x,
int y) {
4281 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4289 return g_Platform->GetWritableDocumentsDir();
4294 auto loader = PluginLoader::GetInstance();
4295 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4297 if (pic->m_pplugin == pplugin) {
4307ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4310 ListOfPI_S57Obj* list = NULL;
4324 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4334 ListOfPI_S57Obj* rule_list) {
4345 ret_str = picbx->CreateObjDescriptions(rule_list);
4359 return ps52plib->m_nDepthUnitDisplay;
4366 return ps52plib->m_nSymbolStyle;
4373 return ps52plib->m_nBoundaryStyle;
4383 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4385 ViewPort cvp = CreateCompatibleViewport(*vp);
4390 ObjRazRules rzRules;
4391 rzRules.obj = &cobj;
4392 rzRules.LUP = pContext->LUP;
4393 rzRules.sm_transform_parms = 0;
4394 rzRules.child = NULL;
4395 rzRules.next = NULL;
4397 if (pContext->LUP) {
4398 ps52plib->SetVPointCompat(
4402 ps52plib->PrepareForRender();
4404 return ps52plib->ObjectRenderCheck(&rzRules);
4413 return ps52plib->GetStateHash();
4418void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4419 chart_context* pctx) {
4422 cobj->att_array = pObj->att_array;
4423 cobj->attVal = pObj->attVal;
4424 cobj->n_attr = pObj->n_attr;
4429 cobj->npt = pObj->npt;
4431 cobj->iOBJL = pObj->iOBJL;
4432 cobj->Index = pObj->Index;
4434 cobj->geoPt = (pt*)pObj->geoPt;
4435 cobj->geoPtz = pObj->geoPtz;
4436 cobj->geoPtMulti = pObj->geoPtMulti;
4438 cobj->m_lat = pObj->m_lat;
4439 cobj->m_lon = pObj->m_lon;
4441 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4442 cobj->x_rate = pObj->x_rate;
4443 cobj->y_rate = pObj->y_rate;
4444 cobj->x_origin = pObj->x_origin;
4445 cobj->y_origin = pObj->y_origin;
4447 cobj->Scamin = pObj->Scamin;
4448 cobj->nRef = pObj->nRef;
4449 cobj->bIsAton = pObj->bIsAton;
4450 cobj->bIsAssociable = pObj->bIsAssociable;
4452 cobj->m_n_lsindex = pObj->m_n_lsindex;
4453 cobj->m_lsindex_array = pObj->m_lsindex_array;
4454 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4457 cobj->m_ls_list_legacy =
4461 cobj->m_ls_list_legacy = 0;
4462 cobj->m_ls_list = 0;
4465 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4467 cobj->m_bcategory_mutable =
true;
4471 if (pObj->m_DPRI == -1) {
4473 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4475 cobj->m_DPRI = pObj->m_DPRI;
4478 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4479 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4481 if (pObj->auxParm3 != 1234) {
4482 pObj->auxParm3 = 1234;
4483 pObj->auxParm0 = -99;
4486 cobj->auxParm0 = pObj->auxParm0;
4493 if (pContext->bBBObj_valid)
4495 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4496 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4498 cobj->CSrules = pContext->CSrules;
4499 cobj->bCS_Added = pContext->bCS_Added;
4501 cobj->FText = pContext->FText;
4502 cobj->bFText_Added = pContext->bFText_Added;
4503 cobj->rText = pContext->rText;
4505 cobj->bIsClone =
true;
4508 cobj->m_chart_context = pctx;
4509 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4512 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4513 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4514 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4515 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4516 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4517 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4518 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4519 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4521 cobj->m_chart_context->chart =
4523 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4537 CreateCompatibleS57Object(pObj, &cobj, NULL);
4539 LUPname LUP_Name = PAPER_CHART;
4542 ctx->CSrules = NULL;
4543 ctx->bCS_Added =
false;
4546 if (ctx->bFText_Added) {
4547 ctx->bFText_Added =
false;
4553 ctx->bBBObj_valid =
true;
4558 switch (cobj.Primitive_type) {
4563 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4564 LUP_Name = PAPER_CHART;
4566 LUP_Name = SIMPLIFIED;
4575 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4576 LUP_Name = PLAIN_BOUNDARIES;
4578 LUP_Name = SYMBOLIZED_BOUNDARIES;
4583 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4587 ps52plib->_LUP2rules(lup, &cobj);
4589 ctx->MPSRulesList = NULL;
4597 pContext->bBBObj_valid =
true;
4603void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4604 ObjRazRules* rzRules) {
4608 pContext->CSrules = cobj->CSrules;
4609 pContext->bCS_Added = cobj->bCS_Added;
4611 pContext->FText = cobj->FText;
4612 pContext->bFText_Added = cobj->bFText_Added;
4613 pContext->rText = cobj->rText;
4615 if (cobj->BBObj.GetValid()) {
4618 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4619 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4620 pContext->bBBObj_valid =
true;
4625 pObj->m_DisplayCat = (
PI_DisCat)cobj->m_DisplayCat;
4629 pContext->ChildRazRules = rzRules->child;
4630 pContext->MPSRulesList = rzRules->mps;
4632 pObj->auxParm0 = cobj->auxParm0;
4636 double* lon_min,
double* lon_max) {
4639 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4640 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4641 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4642 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4643 return pContext->bBBObj_valid;
4651 LUPrec* lup = pContext->LUP;
4660 LUPrec* lup = pContext->LUP;
4670 LUPrec* lup = pContext->LUP;
4676 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4683 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4688 ObjRazRules rzRules;
4689 rzRules.obj = &cobj;
4690 rzRules.LUP = pContext->LUP;
4691 rzRules.sm_transform_parms = 0;
4692 rzRules.child = NULL;
4693 rzRules.next = NULL;
4694 rzRules.mps = pContext->MPSRulesList;
4696 if (pContext->LUP) {
4697 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4700 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4706 ps52plib->PrepareForRender();
4707 ps52plib->ClearTextList();
4710 ps52plib->EnableGLLS(
true);
4712 ps52plib->EnableGLLS(
false);
4721 if (pctx->ChildRazRules) {
4722 ObjRazRules* ctop = pctx->ChildRazRules;
4726 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4728 ObjRazRules* cnxx = ctop->next;
4734 if (pctx->MPSRulesList) {
4735 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4736 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4738 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4739 ps52plib->DestroyRulesChain(top);
4741 delete pctx->MPSRulesList->cs_rules;
4743 free(pctx->MPSRulesList);
4755 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4762 &transform.easting_vp_center, &transform.northing_vp_center);
4765 ObjRazRules rzRules;
4766 rzRules.obj = &cobj;
4767 rzRules.LUP = pContext->LUP;
4768 rzRules.sm_transform_parms = &transform;
4769 rzRules.child = pContext->ChildRazRules;
4770 rzRules.next = NULL;
4771 rzRules.mps = pContext->MPSRulesList;
4773 if (pContext->LUP) {
4774 ViewPort cvp = CreateCompatibleViewport(*vp);
4780 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4782 ps52plib->PrepareForRender();
4784 ps52plib->RenderObjectToDC(pdc, &rzRules);
4787 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4794 wxRect rect,
unsigned char* pixbuf) {
4796 render_canvas_parms pb_spec;
4798 pb_spec.depth = BPP;
4799 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4800 pb_spec.lclip = rect.x;
4801 pb_spec.rclip = rect.x + rect.width - 1;
4802 pb_spec.pix_buff = pixbuf;
4803 pb_spec.width = rect.width;
4804 pb_spec.height = rect.height;
4807#ifdef ocpnUSE_ocpnBitmap
4808 pb_spec.b_revrgb =
true;
4810 pb_spec.b_revrgb =
false;
4813 pb_spec.b_revrgb =
false;
4818 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4825 &transform.easting_vp_center, &transform.northing_vp_center);
4828 ObjRazRules rzRules;
4829 rzRules.obj = &cobj;
4830 rzRules.LUP = pContext->LUP;
4831 rzRules.sm_transform_parms = &transform;
4832 rzRules.child = pContext->ChildRazRules;
4833 rzRules.next = NULL;
4834 rzRules.mps = pContext->MPSRulesList;
4836 ViewPort cvp = CreateCompatibleViewport(*vp);
4844 if (!tess)
return 1;
4846 PolyTriGroup* ptg =
new PolyTriGroup;
4847 ptg->tri_prim_head =
4848 tess->Get_PolyTriGroup_head()->tri_prim_head;
4849 ptg->bsingle_alloc =
false;
4850 ptg->data_type = DATA_TYPE_DOUBLE;
4851 tess->Set_PolyTriGroup_head(ptg);
4853 double* pd = (
double*)malloc(
sizeof(
double));
4858 if (pContext->LUP) {
4863 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4865 ps52plib->PrepareForRender();
4867 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4870 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4882 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4893 if (!tess)
return 1;
4897 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4898 ptg->bsingle_alloc =
false;
4899 ptg->data_type = DATA_TYPE_DOUBLE;
4900 tess->Set_PolyTriGroup_head(ptg);
4904 double* pd = (
double*)malloc(
sizeof(
double));
4921 &transform.easting_vp_center, &transform.northing_vp_center);
4924 ObjRazRules rzRules;
4925 rzRules.obj = &cobj;
4926 rzRules.LUP = pContext->LUP;
4927 rzRules.sm_transform_parms = &transform;
4928 rzRules.child = pContext->ChildRazRules;
4929 rzRules.next = NULL;
4930 rzRules.mps = pContext->MPSRulesList;
4932 if (pContext->LUP) {
4933 ViewPort cvp = CreateCompatibleViewport(*vp);
4939 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4941 ps52plib->PrepareForRender();
4943 ps52plib->RenderAreaToGL(glcc, &rzRules);
4946 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4958 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4965 &transform.easting_vp_center, &transform.northing_vp_center);
4968 ObjRazRules rzRules;
4969 rzRules.obj = &cobj;
4970 rzRules.LUP = pContext->LUP;
4971 rzRules.sm_transform_parms = &transform;
4972 rzRules.child = pContext->ChildRazRules;
4973 rzRules.next = NULL;
4974 rzRules.mps = pContext->MPSRulesList;
4976 if (pContext->LUP) {
4977 ViewPort cvp = CreateCompatibleViewport(*vp);
4983 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4985 ps52plib->PrepareForRender();
4987 ps52plib->RenderObjectToGL(glcc, &rzRules);
4990 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
5000OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
5001 : wxEvent(id, commandType) {
5004 m_b_complete =
false;
5008OCPN_downloadEvent::~OCPN_downloadEvent() {}
5010wxEvent* OCPN_downloadEvent::Clone()
const {
5012 newevent->m_stat = this->m_stat;
5013 newevent->m_condition = this->m_condition;
5015 newevent->m_totalBytes = this->m_totalBytes;
5016 newevent->m_sofarBytes = this->m_sofarBytes;
5017 newevent->m_b_complete = this->m_b_complete;
5023DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5028#define DL_EVENT_TIMER 4388
5036 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5037 void clearBackgroundMode();
5038 void onTimerEvent(wxTimerEvent& event);
5041 wxTimer m_eventTimer;
5042 wxEvtHandler* m_download_evHandler;
5048PI_DLEvtHandler::PI_DLEvtHandler() {
5052 m_download_evHandler = NULL;
5058PI_DLEvtHandler::~PI_DLEvtHandler() {
5059 m_eventTimer.Stop();
5062 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5069 g_download_status =
event.getDLEventStatus();
5070 g_download_condition =
event.getDLEventCondition();
5073 if (m_download_evHandler &&
5076 ev.setComplete(
true);
5077 ev.setTransferred(m_sofarBytes);
5078 ev.setTotal(m_totalBytes);
5080 ev.setDLEventStatus(event.getDLEventStatus());
5083 m_download_evHandler->AddPendingEvent(ev);
5084 m_eventTimer.Stop();
5086 finishAndroidFileDownload();
5093void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5095 m_download_evHandler = handler;
5097 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5101 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5102 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5105void PI_DLEvtHandler::clearBackgroundMode() {
5106 m_download_evHandler = NULL;
5107 m_eventTimer.Stop();
5110void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5116 int stat = queryAndroidFileDownload(m_id, &sstat);
5119 long sofarBytes = 0;
5120 long totalBytes = -1;
5124 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5125 ev.setComplete(
true);
5126 ev.setTransferred(sofarBytes);
5127 ev.setTotal(totalBytes);
5132 wxStringTokenizer tk(sstat, _T(
";"));
5133 if (tk.HasMoreTokens()) {
5134 wxString token = tk.GetNextToken();
5135 token.ToLong(&state);
5136 token = tk.GetNextToken();
5137 token.ToLong(&sofarBytes);
5138 token = tk.GetNextToken();
5139 token.ToLong(&totalBytes);
5142 qDebug() << state << sofarBytes << totalBytes;
5144 m_sofarBytes = sofarBytes;
5145 m_totalBytes = totalBytes;
5147 ev.setTransferred(sofarBytes);
5148 ev.setTotal(totalBytes);
5151 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5152 ev.setComplete(
true);
5155 }
else if (state == 8) {
5156 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5157 ev.setComplete(
true);
5161 ev.setComplete(
false);
5169 if (m_download_evHandler) {
5171 m_download_evHandler->AddPendingEvent(ev);
5176 m_eventTimer.Stop();
5177 finishAndroidFileDownload();
5187 const wxString& outputFile,
5188 const wxString& title,
const wxString& message,
5189 const wxBitmap& bitmap, wxWindow* parent,
5190 long style,
int timeout_secs) {
5193 wxString msg = _T(
"Downloading file synchronously: ");
5200 int vres = validateAndroidWriteLocation(outputFile);
5212 g_piEventHandler->Connect(
5213 wxEVT_DOWNLOAD_EVENT,
5214 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5219 wxString fURI = outputFile;
5220 if (!fURI.StartsWith(_T(
"file://"))) {
5221 fURI.Prepend(_T(
"file://"));
5224 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5227 finishAndroidFileDownload();
5228 g_piEventHandler->Disconnect(
5229 wxEVT_DOWNLOAD_EVENT,
5230 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5235 wxDateTime dl_start_time = wxDateTime::Now();
5239 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5240 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5242 if (dt.GetSeconds() > timeout_secs) {
5243 qDebug() <<
"USER_TIMOUT";
5244 finishAndroidFileDownload();
5245 g_piEventHandler->Disconnect(
5246 wxEVT_DOWNLOAD_EVENT,
5247 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5255 finishAndroidFileDownload();
5256 g_piEventHandler->Disconnect(
5257 wxEVT_DOWNLOAD_EVENT,
5261 qDebug() <<
"RETURN DL_END" << (int)ss;
5267 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5269 qDebug() <<
"Error on queryAndroidFileDownload";
5270 finishAndroidFileDownload();
5271 g_piEventHandler->Disconnect(
5272 wxEVT_DOWNLOAD_EVENT,
5273 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5283#elif defined(OCPN_USE_CURL)
5284 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5285 wxFileOutputStream output(tfn.GetFullPath());
5287 wxCurlDownloadDialog ddlg(url, &output, title, message + url, bitmap, parent,
5289 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5295 case wxCDRF_SUCCESS: {
5296 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5302 case wxCDRF_FAILED: {
5306 case wxCDRF_USER_ABORTED: {
5314 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5324 return ocpn::toUsrDateTimeFormat(date_time,
options);
5329 const wxString& outputFile,
5330 wxEvtHandler* handler,
5333 wxString msg = _T(
"Downloading file asynchronously: ");
5345 int res = startAndroidFileDownload(url, outputFile, NULL ,
5349 finishAndroidFileDownload();
5354 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5356 if (handle) *handle = dl_ID;
5360#elif defined(OCPN_USE_CURL)
5361 if (g_pi_manager->m_pCurlThread)
5365 g_pi_manager->m_pCurlThread =
5366 new wxCurlDownloadThread(g_pi_manager, CurlThreadId);
5367 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5369 if (http && g_pi_manager->m_pCurl &&
5370 dynamic_cast<wxCurlHTTP*
>(g_pi_manager->m_pCurl.get())) {
5374 g_pi_manager->m_pCurl = 0;
5377 bool failed =
false;
5378 if (!g_pi_manager->HandleCurlThreadError(
5379 g_pi_manager->m_pCurlThread->SetURL(url, g_pi_manager->m_pCurl),
5380 g_pi_manager->m_pCurlThread, url))
5383 g_pi_manager->m_pCurl = g_pi_manager->m_pCurlThread->GetCurlSharedPtr();
5384 if (!g_pi_manager->HandleCurlThreadError(
5385 g_pi_manager->m_pCurlThread->SetOutputStream(
5386 new wxFileOutputStream(outputFile)),
5387 g_pi_manager->m_pCurlThread))
5391 g_pi_manager->m_download_evHandler = handler;
5392 g_pi_manager->m_downloadHandle = handle;
5394 wxCurlThreadError err = g_pi_manager->m_pCurlThread->Download();
5395 if (err != wxCTE_NO_ERROR) {
5396 g_pi_manager->HandleCurlThreadError(
5397 err, g_pi_manager->m_pCurlThread);
5398 g_pi_manager->m_pCurlThread->Abort();
5405 if (g_pi_manager->m_pCurlThread) {
5406 if (g_pi_manager->m_pCurlThread->IsAlive())
5407 g_pi_manager->m_pCurlThread->Abort();
5408 if (g_pi_manager->m_pCurlThread->GetOutputStream())
5409 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5410 wxDELETE(g_pi_manager->m_pCurlThread);
5411 g_pi_manager->m_download_evHandler = NULL;
5412 g_pi_manager->m_downloadHandle = NULL;
5415 g_pi_manager->m_pCurl = 0;
5427 cancelAndroidFileDownload(handle);
5428 finishAndroidFileDownload();
5429 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5431 if (g_pi_manager->m_pCurlThread) {
5432 g_pi_manager->m_pCurlThread->Abort();
5433 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5434 wxDELETE(g_pi_manager->m_pCurlThread);
5435 g_pi_manager->m_download_evHandler = NULL;
5436 g_pi_manager->m_downloadHandle = NULL;
5438 g_pi_manager->m_pCurl = 0;
5444 const wxString& parameters, wxString& result,
5447 wxString lparms = parameters;
5448 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5451 result = postResult;
5454#elif defined(OCPN_USE_CURL)
5456 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5457 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5460 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5463 result = wxEmptyString;
5474 return androidCheckOnline();
5477#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5478 if (wxDateTime::GetTimeNow() >
5479 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5481 get.Head(_T(
"http://yahoo.com/"));
5482 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5484 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5486 return g_pi_manager->m_last_online;
5492#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5493void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5495 if (ev.IsSuccessful()) {
5498 g_pi_manager->m_pCurl = 0;
5502 event.setComplete(
true);
5504 if (m_download_evHandler) {
5505 m_download_evHandler->AddPendingEvent(event);
5506 m_download_evHandler = NULL;
5507 m_downloadHandle = NULL;
5510 if (m_pCurlThread) {
5511 m_pCurlThread->Wait();
5512 if (!m_pCurlThread->IsAborting()) {
5513 delete (m_pCurlThread->GetOutputStream());
5514 wxDELETE(m_pCurlThread);
5519void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5523 event.setTotal(ev.GetTotalBytes());
5524 event.setTransferred(ev.GetDownloadedBytes());
5525 event.setComplete(
false);
5527 if (m_download_evHandler) {
5528 m_download_evHandler->AddPendingEvent(event);
5532bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5533 wxCurlBaseThread* p,
5534 const wxString& url) {
5536 case wxCTE_NO_ERROR:
5539 case wxCTE_NO_RESOURCE:
5541 wxS(
"Insufficient resources for correct execution of the program."));
5544 case wxCTE_ALREADY_RUNNING:
5548 case wxCTE_INVALID_PROTOCOL:
5549 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5553 case wxCTE_NO_VALID_STREAM:
5560 case wxCTE_CURL_ERROR: {
5561 wxString ws = wxS(
"unknown");
5562 if (p->GetCurlSession())
5564 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5565 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5570 if (p->IsAlive()) p->Abort();
Class AisDecoder and helpers.
Plugin catalog management: Build the runtime catalog, handling downloads as required.
EventVar plugin_msg
A JSON message should be sent.
Handle messages for blacklisted plugins.
Modal dialog for plugin catalog settings.
ChartCanvas - Main chart display and interaction component.
Manages the chart database and provides access to chart data.
Wrapper class for plugin-based charts.
virtual double GetNearestPreferredScalePPM(double target_scale_ppm)
Find the nearest preferred viewport scale (in pixels/meter) for this chart.
NMEA0183 basic parsing common parts:
const std::vector< DriverPtr > & GetDrivers() const
Wrapper for configuration variables which lives in a wxBaseConfig object.
void Notify() override
Notify all listeners, no data supplied.
Wrapper for global variable, supports notification events when value changes.
Downloader with progress and final message dialogs.
Interface implemented by classes which listens.
Handle logging and forwarding of incoming n0183/n2k messages.
The raw message layer, a singleton.
static NavAddr::Bus GetBusByKey(const std::string &key)
Return bus corresponding to given key.
An iterator class for OCPNRegion.
A wrapper class for wxRegion with additional functionality.
Define an action to be performed when a KeyProvider is notified.
void Init(const KeyProvider &kp, const std::function< void(ObservedEvt &ev)> &action)
Initiate an object yet not listening.
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listener on changes in key.
Custom event class for OpenCPN's notification system.
std::shared_ptr< const void > GetSharedPtr() const
Gets the event's payload data.
Class representing an S-57 chart object.
double lon_max
Bounding box maximum longitude.
double lon_min
Bounding box minimum longitude.
double lat_max
Bounding box maximum latitude.
int auxParm0
Auxiliary parameter 0.
void * pPolyTessGeo
Tesselated polygon geometry.
double chart_ref_lon
Chart reference longitude.
double * geoPtMulti
Lat/lon pairs for decomposed points.
void * S52_Context
S52 presentation data.
double chart_ref_lat
Chart reference latitude.
char FeatureName[8]
S-57 feature type code (e.g., "DEPARE")
double lat_min
Bounding box minimum latitude.
int Primitive_type
Geometry type (point, line, area)
Represents a line segment element for efficient vector chart rendering.
Extended chart base class with separated text rendering.
virtual wxBitmap & RenderRegionViewOnDCNoText(const PlugIn_ViewPort &VPoint, const wxRegion &Region)
Standard DC rendering without text.
virtual bool RenderRegionViewOnDCTextOnly(wxMemoryDC &dc, const PlugIn_ViewPort &VPoint, const wxRegion &Region)
Standard DC text-only rendering.
virtual void ClearPLIBTextList()
Clears any cached text elements.
virtual int RenderRegionViewOnGLNoText(const wxGLContext &glc, const PlugIn_ViewPort &VPoint, const wxRegion &Region, bool b_use_stencil)
OpenGL rendering without text.
virtual int RenderRegionViewOnGLTextOnly(const wxGLContext &glc, const PlugIn_ViewPort &VPoint, const wxRegion &Region, bool b_use_stencil)
OpenGL text-only rendering.
virtual int RenderRegionViewOnGL(const wxGLContext &glc, const PlugIn_ViewPort &VPoint, const wxRegion &Region, bool b_use_stencil)
OpenGL rendering with combined text and graphics.
virtual ListOfPI_S57Obj * GetLightsObjRuleListVisibleAtLatLon(float lat, float lon, PlugIn_ViewPort *VPoint)
Gets list of visible light objects at specified position.
OpenGL-optimized chart base class for plugin chart types.
virtual int GetNoCOVRTablenPoints(int iTable)
Alternative to GetNoCOVRTablePoints().
virtual int GetNoCOVREntries()
Gets number of no-coverage areas in chart.
virtual int GetNoCOVRTablePoints(int iTable)
Gets number of points in no-coverage area boundary.
virtual wxString CreateObjDescriptions(ListOfPI_S57Obj *obj_list)
Creates description text for chart objects.
virtual float * GetNoCOVRTableHead(int iTable)
Gets coordinate data for no-coverage area boundary.
virtual int RenderRegionViewOnGL(const wxGLContext &glc, const PlugIn_ViewPort &VPoint, const wxRegion &Region, bool b_use_stencil)
Renders chart content using OpenGL.
virtual ListOfPI_S57Obj * GetObjRuleListAtLatLon(float lat, float lon, float select_radius, PlugIn_ViewPort *VPoint)
Gets chart objects near specified position.
Base class for implementing custom chart types in OpenCPN plugins.
virtual void SetColorScheme(int cs, bool bApplyImmediate)
Sets the color scheme for chart display.
virtual bool GetChartExtent(ExtentPI *pext)
Gets the geographic boundaries of the chart.
virtual void chartpix_to_latlong(double pixx, double pixy, double *plat, double *plon)
Converts chart pixel coordinates to geographic coordinates.
virtual double GetNearestPreferredScalePPM(double target_scale_ppm)
Returns the nearest preferred scale value for this chart.
virtual double GetNormalScaleMin(double canvas_scale_factor, bool b_allow_overzoom)
Returns the minimum recommended scale for this chart.
virtual wxBitmap & RenderRegionView(const PlugIn_ViewPort &VPoint, const wxRegion &Region)
Renders a region of the chart for display.
virtual ChartFamilyEnumPI GetChartFamily()
Returns the chart family classification.
virtual wxString GetID()
Returns a unique identifier for the chart.
virtual wxString GetDatumString()
Returns the horizontal geodetic datum of the chart.
virtual wxString GetName()
Returns the chart's name or title.
virtual double GetRasterScaleFactor()
Returns the scale factor for raster chart rendering.
virtual wxDateTime GetEditionDate(void)
Returns the edition date of the chart.
virtual int GetCOVRTablenPoints(int iTable)
Alternative method to get the number of points in a coverage table entry.
virtual bool GetChartBits(wxRect &source, unsigned char *pPix, int sub_samp)
Gets pixel data for a portion of a raster chart.
virtual int GetCOVREntries()
Returns the number of coverage table entries for this chart.
virtual double GetNormalScaleMax(double canvas_scale_factor, int canvas_width)
Returns the maximum recommended scale for this chart.
virtual wxString GetSoundingsDatum()
Returns the vertical datum used for soundings in the chart.
virtual wxString GetExtraInfo()
Returns additional information about the chart.
virtual int GetSize_X()
Gets the width of the chart in pixels.
virtual wxString GetFullPath() const
Returns the full file path of the chart.
virtual wxString GetSE()
Returns the chart's source edition identifier.
virtual bool IsReadyToRender()
Indicates whether the chart is ready for rendering.
virtual int GetNativeScale()
Returns the native scale of the chart.
virtual double GetChartSkew()
Returns the skew/rotation angle of the chart.
virtual wxString GetDepthUnits()
Returns the depth units used in the chart.
virtual int Init(const wxString &full_path, int init_flags)
Initializes a chart instance from a file.
virtual wxString GetFileSearchMask(void)
Returns file pattern(s) for chart files this plugin can handle.
virtual int GetSize_Y()
Gets the height of the chart in pixels.
virtual void latlong_to_chartpix(double lat, double lon, double &pixx, double &pixy)
Converts geographic coordinates to chart pixel coordinates.
virtual void ComputeSourceRectangle(const PlugIn_ViewPort &vp, wxRect *pSourceRect)
Computes the source rectangle for the chart based on a given viewport.
virtual float * GetCOVRTableHead(int iTable)
Returns a pointer to the coverage table data for a specific entry.
virtual double GetChartErrorFactor()
Returns the error factor for the chart.
virtual OcpnProjTypePI GetChartProjection()
Returns the projection type used by the chart.
virtual wxBitmap * GetThumbnail(int tnx, int tny, int cs)
Generates a thumbnail image of the chart.
virtual ChartTypeEnumPI GetChartType()
Returns the chart type identifier.
virtual void GetValidCanvasRegion(const PlugIn_ViewPort &VPoint, wxRegion *pValidRegion)
Determines the valid display area for this chart.
virtual bool AdjustVP(PlugIn_ViewPort &vp_last, PlugIn_ViewPort &vp_proposed)
Adjusts viewport parameters for chart-specific requirements.
virtual int GetCOVRTablePoints(int iTable)
Returns the number of points in a specific coverage table entry.
virtual ChartDepthUnitTypePI GetDepthUnitId()
Returns the depth unit type identifier.
Data for a loaded plugin, including dl-loaded library.
Basic data for a loaded plugin, trivially copyable.
wxString m_plugin_filename
The short file path.
wxString m_plugin_file
The full file path.
int m_cap_flag
PlugIn Capabilities descriptor.
wxString m_common_name
A common name string for the plugin.
std::string Key() const
sort key.
void HandleN0183(std::shared_ptr< const Nmea0183Msg > n0183_msg)
Process incoming NMEA 0183 messages from the message bus.
void HandleSignalK(std::shared_ptr< const SignalkMsg > sK_msg)
Process incoming SignalK messages from the message bus.
Contains view parameters and status information for a chart display viewport.
double view_scale_ppm
Display scale in pixels per meter.
wxRect rv_rect
Rectangle defining the rendered view area.
int pix_width
Viewport width in pixels.
double lon_max
Maximum longitude of the viewport.
double clon
Center longitude of the viewport in decimal degrees.
double lat_max
Maximum latitude of the viewport.
int pix_height
Viewport height in pixels.
double clat
Center latitude of the viewport in decimal degrees.
double skew
Display skew angle in radians.
double rotation
Display rotation angle in radians.
bool bValid
True if this viewport is valid and can be used for rendering.
double lon_min
Minimum longitude of the viewport.
double lat_min
Minimum latitude of the viewport.
int m_projection_type
Chart projection type (PROJECTION_MERCATOR, etc.)
bool b_quilt
True if the viewport is in quilt mode (showing multiple charts)
float chart_scale
Conventional chart displayed scale (e.g., 1:50000)
Handle plugin install from remote repositories and local operations to Uninstall and list plugins.
bool Uninstall(const std::string plugin)
Uninstall an installed and loaded plugin.
const std::vector< PluginMetadata > GetInstalled()
Return list of all installed and loaded plugins.
static std::string ImportedMetadataPath(std::string name)
Return path to imported metadata for given plugin.
static std::string VersionPath(std::string name)
Return path to file containing version for given plugin.
std::vector< std::string > GetInstalldataPlugins()
Return list of installed plugins lower case names, not necessarily loaded.
bool ClearInstallData(const std::string plugin_name)
Remove installation data for not loaded plugin.
static bool IsCompatible(const PluginMetadata &metadata, const char *os=PKG_TARGET, const char *os_version=PKG_TARGET_VERSION)
Return true if given plugin is loadable on given os/version.
static std::string FileListPath(std::string name)
Return path to installation manifest for given plugin.
void SetInstalledMetadata(const PluginMetadata &pm)
Set metadata for an installed plugin.
static PluginHandler * GetInstance()
Singleton factory.
void ReloadPluginPanels()
Complete reload from plugins array.
bool LoadAllPlugIns(bool enabled_plugins, bool keep_orphans=false)
Update catalog with imported metadata and load all plugin library files.
void UpdateManagedPlugins(bool keep_orphans)
Update all managed plugins i.
EventVar evt_pluglist_change
Notified without data when the GetPlugInArray() list is changed.
static std::string GetPluginVersion(const PlugInData pd, std::function< const PluginMetadata(const std::string &)> get_metadata)
Return version string for a plugin, possibly with an "Imported" suffix.
void SortPlugins(int(*cmp_func)(PlugInContainer **, PlugInContainer **))
Sort GetPluginArray().
static void UpdatePlugin(PlugInContainer *plugin, const PluginMetadata &md)
Update PlugInContainer status using data from PluginMetadata and manifest.
void SetEnabled(const wxString &common_name, bool enabled)
Update enabled/disabled state for plugin with given name.
static PluginMetadata MetadataByName(const std::string &name)
Find metadata for given plugin.
bool DeactivatePlugIn(PlugInContainer *pic)
Deactivate given plugin.
bool UpdatePlugIns()
Update the GetPlugInArray() list by reloading all plugins from disk.
void ShowPreferencesDialog(const PlugInData &pd, wxWindow *parent)
Display the preferences dialog for a plugin.
const ArrayOfPlugIns * GetPlugInArray()
Return list of currently loaded plugins.
PluginPanel(wxPanel *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, const PlugInData plugin)
An entry in the list of plugins presented by Options | Plugins.
KeyProvider wrapper for a plain key string.
std::string GetKey() const override
Get the Key object from the Key Provider.
EventVar json_msg
Notified with message targeting all plugins.
EventVar json_leg_info
Notified with a shared_ptr<ActiveLegDat>, leg info to all plugins.
EventVar on_message_sent
Notified when a message available as GetString() is sent to garmin.
A parsed SignalK message over ipv4.
Modal dialog, displays available updates (possibly just one) and lets user select and eventually conf...
ViewPort - Core geographic projection and coordinate transformation engine.
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
double ref_scale
The nominal scale of the "reference chart" for this view.
int pix_height
Height of the viewport in physical pixels.
void SetBoxes(void)
Computes the bounding box coordinates for the current viewport.
double rotation
Rotation angle of the viewport in radians.
int pix_width
Width of the viewport in physical pixels.
double skew
Angular distortion (shear transform) applied to the viewport in radians.
double clon
Center longitude of the viewport in degrees.
double clat
Center latitude of the viewport in degrees.
double chart_scale
Chart scale denominator (e.g., 50000 for a 1:50000 scale).
Device context class that can use either wxDC or OpenGL for drawing.
virtual void PrepareContextMenu(int canvasIndex)
Prepares plugin context menu items.
virtual bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvasIndex)
Renders plugin overlay graphics in standard DC mode for multi-canvas support.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex)
Renders plugin overlay graphics in OpenGL mode for multi-canvas support.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex, int priority)
Renders plugin overlay graphics in OpenGL mode with priority control.
virtual bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvas_ix, int priority)
Renders plugin overlay graphics in standard DC mode with priority control.
virtual bool RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in standard DC mode for single canvas.
virtual bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in OpenGL mode for single canvas.
Base class for OpenCPN plugins.
virtual void OnCloseToolboxPanel(int page_sel, int ok_apply_cancel)
Handles preference page closure.
virtual void SetCurrentViewPort(PlugIn_ViewPort &vp)
Notifies plugin of viewport changes.
virtual void UpdateAuiStatus(void)
Updates AUI manager status.
virtual void SetColorScheme(PI_ColorScheme cs)
Updates plugin color scheme.
virtual wxArrayString GetDynamicChartClassNameArray(void)
Returns array of dynamically loaded chart class names.
virtual int GetPlugInVersionMajor()
Returns the major version number of the plugin itself.
virtual bool RenderOverlay(wxMemoryDC *pmdc, PlugIn_ViewPort *vp)
Render plugin overlay graphics using standard device context.
virtual void ProcessParentResize(int x, int y)
Handles parent window resize events.
virtual int GetPlugInVersionMinor()
Returns the minor version number of the plugin itself.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
The JSON document writer.
void Write(const wxJSONValue &value, wxString &str)
Write the JSONvalue object to a JSON text.
DriverPtr & FindDriver(const std::vector< DriverPtr > &drivers, const std::string &iface, const NavAddr::Bus _bus)
Search list of drivers for a driver with given interface string.
Driver registration container, a singleton.
Raw messages layer, supports sending and recieving navmsg messages.
Enhanced logging interface on top of wx/log.h.
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.
Notify()/Listen() configuration variable wrapper.
Global variables Listen()/Notify() wrapper.
enum _PI_DisCat PI_DisCat
Display categories for S52 chart features.
#define INSTALLS_PLUGIN_CHART
Plugin provides new chart type for standard (non-GL) view.
enum _PI_DisPrio PI_DisPrio
Display priority levels for S52 chart objects.
#define PLIB_CAPS_OBJCATMUTATE
Support for object category mutation Allows dynamic changes to object display categories.
#define INSTALLS_CONTEXTMENU_ITEMS
Plugin will add items to chart context menu.
#define WANTS_LATE_INIT
Delay full plugin initialization until system is ready.
_OCPN_DLCondition
Event types for HTTP file download operations.
@ OCPN_DL_EVENT_TYPE_UNKNOWN
Unknown event type.
@ OCPN_DL_EVENT_TYPE_PROGRESS
Download progress update.
@ OCPN_DL_EVENT_TYPE_END
Download has completed.
PI_ColorScheme
Enumeration of color schemes.
#define PLIB_CAPS_SINGLEGEO_BUFFER
Support for single geometry buffers Allows combining multiple geometries into a single buffer.
#define PLIB_CAPS_LINE_BUFFER
Support for line vertex buffers Enables batched line rendering using vertex buffers.
_OCPN_DLStatus
Status codes for HTTP file download operations.
@ OCPN_DL_NO_ERROR
Download completed successfully.
@ OCPN_DL_USER_TIMEOUT
Download timed out waiting for user action.
@ OCPN_DL_STARTED
Download has begun but not yet complete.
@ OCPN_DL_FAILED
Download failed (general error)
@ OCPN_DL_UNKNOWN
Unknown or uninitialized status.
@ OCPN_DL_ABORTED
Download was cancelled by user.
@ PI_CHART_FAMILY_VECTOR
Vector chart formats (S-57, CM93, etc.)
#define INSTALLS_TOOLBOX_PAGE
Plugin will add pages to the toolbox/settings dialog.
enum _PI_LUPname PI_LUPname
Name identifiers for S57 lookup table sets.
#define USES_AUI_MANAGER
Plugin uses wxAuiManager for window management.
#define PLIB_CAPS_OBJSEGLIST
Support for object segment lists Enables breaking complex geometries into optimized segments.
#define INSTALLS_PLUGIN_CHART_GL
Plugin provides new chart type for OpenGL view.
#define WANTS_ONPAINT_VIEWPORT
Receive callbacks during chart viewport painting.
#define WANTS_PREFERENCES
Plugin will add page(s) to global preferences dialog.
#define WANTS_OVERLAY_CALLBACK
Receive callbacks to render custom overlay graphics on the chart.
wxWindow * GetOCPNCanvasWindow()
Gets OpenCPN's main canvas window.
double OCPN_GetDisplayContentScaleFactor()
Gets content scaling factor for current display.
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.
Miscellaneous utilities, many of which string related.
void SendNMEASentenceToAllPlugIns(const wxString &sentence)
Distribute a NMEA 0183 sentence to all plugins that have registered interest by setting the WANTS_NME...
Tools to send data to plugins.
PLugin remote repositories installation and Uninstall/list operations.
Low level code to load plugins from disk, notably the PluginLoader class.
@ Ghost
Managed, shadowing another (packaged?) plugin.
@ Unmanaged
Unmanaged, probably a package.
@ Managed
Managed by installer.
@ System
One of the four system plugins, unmanaged.
Plugin installation and data paths support.
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.
wxString GetWritableDocumentsDir(void)
Returns the platform-specific default documents directory.
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.
PI_DisCat PI_GetObjectDisplayCategory(PI_S57Obj *pObj)
Gets display category for object.
void PI_PLIBPrepareForNewRender(void)
Prepares PLIB for new rendering pass.
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.
_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.
wxString GetOCPN_ExePath(void)
Gets OpenCPN executable path.
bool OCPN_isOnline()
Checks internet connectivity.
void PI_PLIBSetRenderCaps(unsigned int flags)
Sets rendering capability flags.
wxString g_locale
Global locale setting for OpenCPN UI.
PI_DisPrio PI_GetObjectDisplayPriority(PI_S57Obj *pObj)
Gets display priority for object.
double g_display_size_mm
The width of the physical screen in millimeters.
PlugInManager and helper classes – Mostly gui parts (dialogs) and plugin API stuff.
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.