#include "PluginDockPanel.hpp" #include "GUI_App.hpp" #include "Plater.hpp" #include #include namespace Slic3r { namespace GUI { std::string plugin_pane_name(const std::string& plugin_key, const std::string& title) { std::string name = "plugin:" + plugin_key + ":" + title; std::replace_if(name.begin(), name.end(), [](char c) { return c == '|' || c == ';' || c == '=' || c == '\\'; }, '_'); return name; } std::string plugin_pane_layout_entry(const std::string& layout, const std::string& pane_name) { // Panes are separated by '|'; SavePerspective() escapes a '|' inside a caption as "\|". const std::string prefix = "name=" + pane_name + ";"; size_t begin = 0; for (size_t i = 0; i <= layout.size(); ++i) { if (i < layout.size() && (layout[i] != '|' || (i > 0 && layout[i - 1] == '\\'))) continue; if (layout.compare(begin, prefix.size(), prefix) == 0) return layout.substr(begin, i - begin); begin = i + 1; } return {}; } PluginDockPanel::PluginDockPanel(wxWindow* parent, const std::string& html, MessageHandler on_message, CloseHandler on_close, CloseHandler on_destroyed) : PluginWebPanel(parent, orca_bridge_script()) , m_html(html) , m_on_message(std::move(on_message)) , m_on_close(std::move(on_close)) , m_on_destroyed(std::move(on_destroyed)) { // A link asking for a new window has nowhere to open from a docked panel. browser()->Bind(wxEVT_WEBVIEW_NEWWINDOW, [](wxWebViewEvent& event) { event.Veto(); }); } PluginDockPanel::~PluginDockPanel() { if (m_on_destroyed) m_on_destroyed(); } bool PluginDockPanel::on_page_message(const std::string& kind, const nlohmann::json& data) { if (kind == "message") { if (m_on_message) m_on_message(data); return true; } if (kind == "close") { request_close(); return true; } return false; } void PluginDockPanel::push_message(const nlohmann::json& data) { if (!m_closing) post_to_page(data.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace)); } void PluginDockPanel::fire_close() { if (m_closing) return; m_closing = true; if (m_on_close) { CloseHandler on_close = std::move(m_on_close); m_on_close = nullptr; on_close(); } } void PluginDockPanel::request_close() { if (m_closing) return; fire_close(); // A close requested by the page arrives inside the web view's own script-message callback, // which must return before the web view is destroyed. CallAfter([this]() { remove_pane(); }); } void PluginDockPanel::destroy_for_plugin() { m_closing = true; m_on_close = nullptr; remove_pane(); } void PluginDockPanel::remove_pane() { if (Plater* plater = wxGetApp().plater()) plater->remove_plugin_pane(this); else Destroy(); } }} // namespace Slic3r::GUI