OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::PluginPages Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/plugin/host/PluginPages.hpp>

Collaboration diagram for Slic3r::PluginPages:

Classes

struct  Page

Public Member Functions

 PluginPages ()=default
 ~PluginPages ()
 PluginPages (const PluginPages &)=delete
PluginPages & operator= (const PluginPages &)=delete
void initialize (Notebook *parent)
void shutdown ()
void on_cap_register (const PluginCapabilityId &id)
void on_cap_deregister (const PluginCapabilityId &id)
void on_plugin_register (const std::string &plugin_key)
void on_plugin_deregister (const std::string &plugin_key)
void set_visible_page_count (int count)
void relayout ()
void select_page (const PluginCapabilityId &id)

Private Member Functions

std::shared_ptr< PagesPluginCapability > get_pages_cap (const PluginCapabilityId &id, bool is_enabled) const
bool create_page (const PluginCapabilityId &id)
void remove_page (const PluginCapabilityId &id)
void show_overflow_menu ()

Static Private Member Functions

static wxString page_tab_id (const PluginCapabilityId &id)

Private Attributes

std::map< PluginCapabilityId, Page > m_pages
std::vector< PluginCapabilityId > m_order
Notebook * m_parent {nullptr}
int m_visible_page_count {0}
std::optional< PluginCapabilityId > m_swapped_in_id
wxWindow * m_overflow_button {nullptr}

Detailed Description


Class Documentation

◆ Slic3r::PluginPages::Page

struct Slic3r::PluginPages::Page
Collaboration diagram for Slic3r::PluginPages::Page:
Class Members
wxBitmap icon
LazyPage< PluginPage > * page {nullptr}

Constructor & Destructor Documentation

◆ PluginPages() [1/2]

Slic3r::PluginPages::PluginPages ( )
default

Referenced by PluginPages(), and operator=().

Here is the caller graph for this function:

◆ ~PluginPages()

Slic3r::PluginPages::~PluginPages ( )
167{
168 shutdown();
169}
void shutdown()
Definition PluginPages.cpp:187

References shutdown().

Here is the call graph for this function:

◆ PluginPages() [2/2]

Slic3r::PluginPages::PluginPages ( const PluginPages & )
delete

References PluginPages().

Here is the call graph for this function:

Member Function Documentation

◆ create_page()

bool Slic3r::PluginPages::create_page ( const PluginCapabilityId & id)
private
216{
217 if (m_pages.find(id) != m_pages.end())
218 return false;
219
220 auto capability = get_pages_cap(id, true);
221 if (!capability)
222 return false;
223
224 std::string icon;
225 try {
226 icon = capability->get_icon();
227 } catch (const std::exception& error) {
228 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " Failed to get icon for plugin " << id.plugin_key << ": " << error.what();
229 } catch (...) {
230 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " Failed to get icon for plugin " << id.plugin_key;
231 }
232
233 wxBitmap bitmap;
234 if (!icon.empty()) {
235 try {
236 boost::filesystem::path icon_path(icon);
237 const std::string extension = icon_path.extension().string();
238 if (extension == ".svg" || extension == ".png")
239 icon_path.replace_extension();
240
241 bitmap = create_scaled_bitmap(icon_path.string(), m_parent, 20);
242 } catch (const std::exception& error) {
243 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " Failed to load icon for plugin " << id.plugin_key << ": " << error.what();
244 } catch (...) {
245 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " Failed to load icon for plugin " << id.plugin_key;
246 }
247 }
248
249 // Built the first time its tab is shown, so a language switch never creates the page's browser
250 // while the main window is being rebuilt. Never prebuilt: the idle queue cannot drop a page
251 // that remove_page() destroys.
252 auto* page = new GUI::LazyPage<PluginPage>(m_parent, GUI::into_u8(page_tab_id(id)), -1,
253 [capability = std::move(capability)](wxWindow* parent) {
254 return new PluginPage(parent, capability);
255 });
256
257 m_pages.emplace(id, Page{page, bitmap});
258 m_order.push_back(id);
259 return true;
260}
std::vector< PluginCapabilityId > m_order
Definition PluginPages.hpp:86
std::shared_ptr< PagesPluginCapability > get_pages_cap(const PluginCapabilityId &id, bool is_enabled) const
Definition PluginPages.cpp:206
Notebook * m_parent
Definition PluginPages.hpp:87
std::map< PluginCapabilityId, Page > m_pages
Definition PluginPages.hpp:85
static wxString page_tab_id(const PluginCapabilityId &id)
Definition PluginPages.cpp:314
Definition PluginPages.hpp:80
std::string into_u8(const wxString &str)
Definition GUI.cpp:549
wxBitmap create_scaled_bitmap(const std::string &bmp_name_in, wxWindow *win, const int px_cnt, const bool grayscale, const std::string &new_color, const bool menu_bitmap, const bool resize, const bool bitmap2, const std::vector< std::string > &array_new_color)
Definition wxExtensions.cpp:448

References create_scaled_bitmap(), get_pages_cap(), Slic3r::GUI::into_u8(), m_order, m_pages, m_parent, and page_tab_id().

Referenced by initialize(), and on_cap_register().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_pages_cap()

std::shared_ptr< PagesPluginCapability > Slic3r::PluginPages::get_pages_cap ( const PluginCapabilityId & id,
bool is_enabled ) const
private
207{
208 auto capability = PluginManager::instance().get_plugin_capability(id, /*only_enabled=*/false);
209 if (!capability || capability->is_enabled() != is_enabled || capability->type() != PluginCapabilityType::Pages)
210 return nullptr;
211
212 return std::dynamic_pointer_cast<PagesPluginCapability>(capability);
213}
static PluginManager & instance()
Definition PluginManager.cpp:74
std::shared_ptr< PluginCapabilityInterface > get_plugin_capability(const PluginCapabilityId &id, bool only_enabled=true) const
Definition PluginManager.cpp:616
@ Pages
Definition PythonPluginInterface.hpp:17

References Slic3r::PluginManager::get_plugin_capability(), Slic3r::PluginManager::instance(), and Slic3r::Pages.

Referenced by create_page().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initialize()

void Slic3r::PluginPages::initialize ( Notebook * parent)
172{
173 shutdown();
174 m_parent = parent;
175 if (m_parent == nullptr)
176 return;
177
178 m_visible_page_count = GUI::wxGetApp().app_config->get_plugin_pages_visible_count();
179
180 for (const auto& capability : PluginManager::instance().get_plugin_capabilities("", PluginCapabilityType::Pages)) {
181 if (capability)
182 create_page(capability->identity());
183 }
184 relayout();
185}
bool create_page(const PluginCapabilityId &id)
Definition PluginPages.cpp:215
void relayout()
Definition PluginPages.cpp:319
int m_visible_page_count
Definition PluginPages.hpp:89

References create_page(), Slic3r::PluginManager::instance(), m_parent, m_visible_page_count, Slic3r::Pages, relayout(), and shutdown().

Here is the call graph for this function:

◆ on_cap_deregister()

void Slic3r::PluginPages::on_cap_deregister ( const PluginCapabilityId & id)
272{
273 remove_page(id);
274}
void remove_page(const PluginCapabilityId &id)
Definition PluginPages.cpp:292

References remove_page().

Here is the call graph for this function:

◆ on_cap_register()

void Slic3r::PluginPages::on_cap_register ( const PluginCapabilityId & id)
263{
264 if (m_parent == nullptr)
265 return;
266
267 if (create_page(id))
268 relayout();
269}

References create_page(), m_parent, and relayout().

Referenced by on_plugin_register().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ on_plugin_deregister()

void Slic3r::PluginPages::on_plugin_deregister ( const std::string & plugin_key)
285{
286 // In tab order, as in shutdown().
287 for (const PluginCapabilityId& id : std::vector<PluginCapabilityId>(m_order))
288 if (id.plugin_key == plugin_key)
289 remove_page(id);
290}

References m_order, and remove_page().

Here is the call graph for this function:

◆ on_plugin_register()

void Slic3r::PluginPages::on_plugin_register ( const std::string & plugin_key)
277{
278 for (const auto& capability : PluginManager::instance().get_plugin_capabilities(plugin_key, PluginCapabilityType::Pages)) {
279 if (capability)
280 on_cap_register(capability->identity());
281 }
282}
void on_cap_register(const PluginCapabilityId &id)
Definition PluginPages.cpp:262

References Slic3r::PluginManager::instance(), on_cap_register(), and Slic3r::Pages.

Here is the call graph for this function:

◆ operator=()

PluginPages & Slic3r::PluginPages::operator= ( const PluginPages & )
delete

References PluginPages(), and count.

Here is the call graph for this function:

◆ page_tab_id()

wxString Slic3r::PluginPages::page_tab_id ( const PluginCapabilityId & id)
staticprivate
315{
316 return wxString::FromUTF8("plugin." + id.plugin_key + "." + id.name);
317}

Referenced by create_page(), relayout(), select_page(), and show_overflow_menu().

Here is the caller graph for this function:

◆ relayout()

void Slic3r::PluginPages::relayout ( )
320{
321 if (m_parent == nullptr)
322 return;
323
324 m_order.erase(std::remove_if(m_order.begin(), m_order.end(),
325 [this](const PluginCapabilityId& id) {
326 const bool orphaned = m_pages.find(id) == m_pages.end();
327 if (orphaned)
328 BOOST_LOG_TRIVIAL(error) << "PluginPages::relayout: '" << id.name << "' was in m_order but not m_pages, dropping";
329 return orphaned;
330 }),
331 m_order.end());
332
333 const int visible_slots = std::max(1, m_visible_page_count);
334 const bool need_overflow = static_cast<int>(m_order.size()) > visible_slots;
335
336 // Every visible slot is a normal, individual tab hosting its own page. When there's
337 // overflow, the last slot's page is swappable via m_overflow_button/show_overflow_menu()
338 // rather than being a fixed page — m_swapped_in_id tracks which one currently sits there.
339 std::vector<PluginCapabilityId> tab_ids;
340 if (!need_overflow) {
341 tab_ids = m_order;
342 m_swapped_in_id.reset();
343 } else {
344 const auto overflow_begin = m_order.begin() + (visible_slots - 1);
345 tab_ids.assign(m_order.begin(), overflow_begin);
346
347 if (!m_swapped_in_id || std::find(overflow_begin, m_order.end(), *m_swapped_in_id) == m_order.end())
348 m_swapped_in_id = *overflow_begin;
349 tab_ids.push_back(*m_swapped_in_id);
350 }
351
352 // MainFrame::show_device() relayouts on every printer change and most of those change
353 // nothing, so only touch the notebook when the trailing slots don't already spell out
354 // tab_ids — a rebuild destroys and recreates every tab button and rasterizes every icon.
355 const size_t page_count = m_parent->GetPageCount();
356 bool up_to_date = page_count >= tab_ids.size();
357 for (size_t i = 0; up_to_date && i < tab_ids.size(); ++i)
358 up_to_date = m_parent->GetPageName(page_count - tab_ids.size() + i) == page_tab_id(tab_ids[i]);
359 for (const auto& [id, entry] : m_pages) {
360 if (!up_to_date)
361 break;
362 const bool wanted = std::find(tab_ids.begin(), tab_ids.end(), id) != tab_ids.end();
363 up_to_date = entry.page->in_book() == wanted;
364 }
365
366 if (!up_to_date) {
367 const wxString id_to_reselect = m_parent->GetSelectedPageName();
368
369 // In tab order, as in shutdown().
370 for (const auto& id : m_order) {
371 const int idx = m_parent->FindPage(m_pages.at(id).page);
372 if (idx != wxNOT_FOUND)
373 m_parent->RemovePage(idx);
374 }
375
376 for (const auto& id : tab_ids) {
377 const Page& entry = m_pages.at(id);
378 m_parent->InsertPage(m_parent->GetPageCount(), page_tab_id(id), entry.page, wxString::FromUTF8(id.name), "",
379 false, entry.icon);
380 }
381
382 if (!id_to_reselect.empty())
383 m_parent->SelectPageByName(id_to_reselect);
384 }
385
386 const bool overflow_changed = need_overflow != (m_overflow_button != nullptr);
387 if (need_overflow) {
388 if (m_overflow_button == nullptr) {
389 auto* btn = new Button(m_parent->GetBtnsListCtrl(), wxString(L"\u25BE"), wxString(), wxNO_BORDER);
390 btn->SetCornerRadius(0);
391 const int em = em_unit(m_parent);
392 btn->SetMinSize({40 * em / 10, 36 * em / 10});
393 btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { show_overflow_menu(); });
394 GUI::wxGetApp().UpdateDarkUI(btn);
395 m_overflow_button = btn;
396 }
397 m_parent->SetOverflowButton(m_overflow_button);
398 } else if (m_overflow_button != nullptr) {
399 m_parent->SetOverflowButton(nullptr);
400 m_overflow_button->Destroy();
401 m_overflow_button = nullptr;
402 }
403
404 // The tab strip changed width; compact the labels again so the side tools stay visible.
405 if ((!up_to_date || overflow_changed) && !GUI::wxGetApp().is_closing())
406 if (GUI::MainFrame* mainframe = GUI::wxGetApp().mainframe)
407 mainframe->fit_tab_labels();
408}
#define L(s)
Definition ExtrusionEntity.cpp:25
void show_overflow_menu()
Definition PluginPages.cpp:421
std::optional< PluginCapabilityId > m_swapped_in_id
Definition PluginPages.hpp:91
wxWindow * m_overflow_button
Definition PluginPages.hpp:92
int em_unit(wxWindow *win)
Definition wxExtensions.cpp:424

References em_unit(), Slic3r::PluginPages::Page::icon, L, m_order, m_overflow_button, m_pages, m_parent, m_swapped_in_id, m_visible_page_count, Slic3r::PluginPages::Page::page, page_tab_id(), and show_overflow_menu().

Referenced by initialize(), on_cap_register(), remove_page(), select_page(), set_visible_page_count(), and show_overflow_menu().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_page()

void Slic3r::PluginPages::remove_page ( const PluginCapabilityId & id)
private
293{
294 auto it = m_pages.find(id);
295 if (it == m_pages.end())
296 return;
297
298 GUI::LazyPage<PluginPage>* page = it->second.page;
299 // Only a built page has installed a message sender on the capability.
300 if (PluginPage* built = page->get())
301 built->detach_capability();
302
303 m_pages.erase(it);
304 m_order.erase(std::remove(m_order.begin(), m_order.end(), id), m_order.end());
305
306 const int idx = m_parent != nullptr ? m_parent->FindPage(page) : wxNOT_FOUND;
307 if (idx != wxNOT_FOUND)
308 m_parent->RemovePage(idx);
309
310 relayout();
311 page->Destroy();
312}

References Slic3r::GUI::Lazy< T >::get(), m_order, m_pages, m_parent, and relayout().

Referenced by on_cap_deregister(), on_plugin_deregister(), and shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_page()

void Slic3r::PluginPages::select_page ( const PluginCapabilityId & id)
411{
412 if (m_parent == nullptr || m_pages.find(id) == m_pages.end())
413 return;
414
415 // Swap the page into the visible slot first when it lives behind the overflow menu.
416 m_swapped_in_id = id;
417 relayout();
418 m_parent->SelectPageByName(page_tab_id(id));
419}

References m_pages, m_parent, m_swapped_in_id, page_tab_id(), and relayout().

Referenced by Slic3r::GUI::anonymous_namespace{ActionRegistry.cpp}::PluginPageAction::run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_visible_page_count()

void Slic3r::PluginPages::set_visible_page_count ( int count)
197{
199 if (clamped == m_visible_page_count)
200 return;
201
202 m_visible_page_count = clamped;
203 relayout();
204}
#define PLUGIN_PAGES_VISIBLE_COUNT_MAX
Definition AppConfig.hpp:55
#define PLUGIN_PAGES_VISIBLE_COUNT_MIN
Definition AppConfig.hpp:53
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246

References count, m_visible_page_count, PLUGIN_PAGES_VISIBLE_COUNT_MAX, PLUGIN_PAGES_VISIBLE_COUNT_MIN, and relayout().

Here is the call graph for this function:

◆ show_overflow_menu()

void Slic3r::PluginPages::show_overflow_menu ( )
private
422{
423 const int visible_slots = std::max(1, m_visible_page_count);
424 if (m_overflow_button == nullptr || static_cast<int>(m_order.size()) <= visible_slots)
425 return;
426
427 const std::vector<PluginCapabilityId> overflow_ids(m_order.begin() + (visible_slots - 1), m_order.end());
428
429 wxMenu menu;
430 for (size_t i = 0; i < overflow_ids.size(); ++i)
431 menu.AppendRadioItem(static_cast<int>(wxID_HIGHEST + 1 + i), wxString::FromUTF8(overflow_ids[i].name));
432 if (m_swapped_in_id) {
433 const auto it = std::find(overflow_ids.begin(), overflow_ids.end(), *m_swapped_in_id);
434 if (it != overflow_ids.end())
435 menu.Check(static_cast<int>(wxID_HIGHEST + 1 + (it - overflow_ids.begin())), true);
436 }
437
438 menu.Bind(wxEVT_MENU, [this, overflow_ids](wxCommandEvent& evt) {
439 const size_t index = static_cast<size_t>(evt.GetId() - (wxID_HIGHEST + 1));
440 if (index >= overflow_ids.size())
441 return;
442 m_swapped_in_id = overflow_ids[index];
443 relayout();
444 m_parent->SelectPageByName(page_tab_id(*m_swapped_in_id));
445 });
446 m_overflow_button->PopupMenu(&menu);
447}

References m_order, m_overflow_button, m_parent, m_swapped_in_id, m_visible_page_count, page_tab_id(), and relayout().

Referenced by relayout().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdown()

void Slic3r::PluginPages::shutdown ( )
188{
189 // Removing the selected tab selects the tab to its left. In tab order that is a built-in tab,
190 // never an unbuilt plugin page that is removed next and would be built only to be destroyed.
191 for (const PluginCapabilityId& id : std::vector<PluginCapabilityId>(m_order))
192 remove_page(id);
193 m_parent = nullptr;
194}

References m_order, m_parent, and remove_page().

Referenced by ~PluginPages(), and initialize().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_order

std::vector<PluginCapabilityId> Slic3r::PluginPages::m_order
private

◆ m_overflow_button

wxWindow* Slic3r::PluginPages::m_overflow_button {nullptr}
private
92{nullptr};

Referenced by relayout(), and show_overflow_menu().

◆ m_pages

std::map<PluginCapabilityId, Page> Slic3r::PluginPages::m_pages
private

◆ m_parent

Notebook* Slic3r::PluginPages::m_parent {nullptr}
private

◆ m_swapped_in_id

std::optional<PluginCapabilityId> Slic3r::PluginPages::m_swapped_in_id
private

◆ m_visible_page_count

int Slic3r::PluginPages::m_visible_page_count {0}
private

The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/plugin/host/PluginPages.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/plugin/host/PluginPages.cpp