Files
OrcaSlicer/src/slic3r/GUI/Notebook.hpp
T
HanifKoh 4895bc03b4 Remove Unused Project Includes and Forward-Declare Where a Type Is Only Referenced (#16099)
* Remove Unused Project Includes and Forward-Declare Where a Type Is Only Referenced

Generated with include-what-you-use and applied conservatively. Only OrcaSlicer's own headers, the ones under src/ and tests/, are removed or forward-declared; standard-library and third-party includes are left alone. An include is removed only when both the Release and the Debug configuration leave it unused, never from inside a conditional block, and never from a file with platform-specific blocks, which only gain includes. Files whose only use of a header sits behind a feature or debug macro (libvgcode's OpenGL ES and marker code, the ARACHNE/TESTS_EXPORT_SVGS debug output) keep their includes.

clonable_ptr.hpp gains #pragma once; it had no include guard and was only safe while Config.hpp was its sole includer.

* Remove Unused Project Includes From Files With Platform-Specific Code

A Linux include-what-you-use run cannot see the code inside _WIN32, __APPLE__ or __linux__ blocks, so its verdict is only taken where nothing the removed header declares, directly or through what it includes, is named inside those blocks. Removals also have to hold in both the Release and Debug configuration and never touch a line inside a conditional block.

* Restore the libslic3r Precompiled Header and Direct Includes Lost in the Platform Pass

The platform-file pass treated pchheader.hpp as an ordinary header and
emptied it, and left GUI_Preview.hpp and 14 other files relying on
headers they no longer reached directly.

* Restore MainFrame.hpp in ParamsDialog.cpp for the Windows-Only Reparent Call

* Include Headers That Files Reached Through Ones the Cleanup Removed

* Drop Includes Duplicated by the Cleanup or by Main's Own Additions

* Leave PreciseSeam.cpp as Main Has It After the Precise Seam Rework
2026-10-05 16:47:17 +08:00

513 lines
17 KiB
C++

#ifndef slic3r_Notebook_hpp_
#define slic3r_Notebook_hpp_
//#ifdef _WIN32
#include <cstddef>
#include <initializer_list>
#include <string>
#include <vector>
#include <wx/bookctrl.h>
#include <wx/bitmap.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/debug.h>
#include <wx/chartype.h>
#include <wx/object.h>
#include <wx/sizer.h>
#include <wx/string.h>
#include <wx/withimages.h>
#include <wx/window.h>
#include <wx/defs.h>
#include <wx/notebook.h>
class wxObject;
class Button;
// custom message the ButtonsListCtrl sends to its parent (Notebook) to notify a selection change:
wxDECLARE_EVENT(wxCUSTOMEVT_NOTEBOOK_SEL_CHANGED, wxCommandEvent);
class ButtonsListCtrl : public wxControl
{
public:
// BBS
ButtonsListCtrl(wxWindow* parent, wxBoxSizer* side_tools = NULL);
~ButtonsListCtrl() {}
void OnPaint(wxPaintEvent&);
void SetSelection(int sel);
void UpdateMode();
void Rescale();
bool InsertPage(size_t n, const wxString &text, bool bSelect = false, const std::string &bmp_name = "", const wxBitmap &bmp = wxNullBitmap);
void RemovePage(size_t n);
bool SetPageImage(size_t n, const std::string& bmp_name) const;
void SetPageText(size_t n, const wxString& strText);
void SetCompact(size_t n, bool compact); // ORCA
wxString GetPageText(size_t n) const;
// ORCA: the full page label, unaffected by SetCompact() blanking the button text.
wxString GetPageLabel(size_t n) const;
// Resource name the page was inserted with (empty for plugin pages, which pass a wxBitmap).
const std::string& GetPageIcon(size_t n) const
{
static const std::string empty;
return n < m_pageIcons.size() ? m_pageIcons[n] : empty;
}
wxFlexGridSizer* GetBtnsSizer(){return m_buttons_sizer;}; // ORCA
// ORCA: a companion widget shown right after the tab buttons (before any side_tools), e.g.
// an overflow indicator. Pass nullptr to remove it; ownership stays with the caller.
void SetOverflowButton(wxWindow* button);
private:
wxFlexGridSizer* m_buttons_sizer;
wxBoxSizer* m_sizer;
// BBS: use Button
std::vector<Button*> m_pageButtons;
int m_selection {-1};
int m_btn_margin;
int m_line_margin;
std::vector<wxString> m_pageLabels; // ORCA
std::vector<std::string> m_pageIcons; // ORCA: resource icon name per page, plugin pages empty
wxWindow* m_overflow_button{nullptr}; // ORCA
};
class Notebook : public wxBookCtrlBase
{
public:
Notebook(wxWindow * parent,
wxWindowID winid = wxID_ANY,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
// BBS
wxBoxSizer* side_tools = NULL,
long style = 0)
{
Init();
Create(parent, winid, pos, size, side_tools, style);
}
bool Create(wxWindow * parent,
wxWindowID winid = wxID_ANY,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
// BBS
wxBoxSizer* side_tools = NULL,
long style = 0)
{
if (!wxBookCtrlBase::Create(parent, winid, pos, size, style | wxBK_TOP))
return false;
m_bookctrl = new ButtonsListCtrl(this, side_tools);
wxSizer* mainSizer = new wxBoxSizer(IsVertical() ? wxVERTICAL : wxHORIZONTAL);
if (style & wxBK_RIGHT || style & wxBK_BOTTOM)
mainSizer->Add(0, 0, 1, wxEXPAND, 0);
m_controlSizer = new wxBoxSizer(IsVertical() ? wxHORIZONTAL : wxVERTICAL);
m_controlSizer->Add(m_bookctrl, wxSizerFlags(1).Expand());
wxSizerFlags flags;
if (IsVertical())
flags.Expand();
else
flags.CentreVertical();
mainSizer->Add(m_controlSizer, flags.Border(wxALL, m_controlMargin));
SetSizer(mainSizer);
this->Bind(wxCUSTOMEVT_NOTEBOOK_SEL_CHANGED, [this](wxCommandEvent& evt)
{
if (int page_idx = evt.GetId(); page_idx >= 0)
SetSelection(page_idx);
});
this->Bind(wxEVT_NAVIGATION_KEY, &Notebook::OnNavigationKey, this);
return true;
}
// Methods specific to this class.
// A method allowing to add a new page without any label (which is unused
// by this control) and show it immediately.
bool ShowNewPage(wxWindow * page)
{
return AddPage(page, wxString(), false, NO_IMAGE);
}
// Set effect to use for showing/hiding pages.
void SetEffects(wxShowEffect showEffect, wxShowEffect hideEffect)
{
m_showEffect = showEffect;
m_hideEffect = hideEffect;
}
// Or the same effect for both of them.
void SetEffect(wxShowEffect effect)
{
SetEffects(effect, effect);
}
// And the same for time outs.
void SetEffectsTimeouts(unsigned showTimeout, unsigned hideTimeout)
{
m_showTimeout = showTimeout;
m_hideTimeout = hideTimeout;
}
void SetEffectTimeout(unsigned timeout)
{
SetEffectsTimeouts(timeout, timeout);
}
// Implement base class pure virtual methods.
// Page management. Every insertion funnels through the InsertPage() below; `id` is the
// stable page name FindPageByName() resolves. Built-in tabs name a resource bitmap,
// plugin pages hand over a ready wxBitmap; wx's own imageId overloads carry neither.
bool AddPage(const wxString& id,
wxWindow* page,
const wxString& text,
const std::string& bmp_name = "",
bool bSelect = false)
{
DoInvalidateBestSize();
return InsertPage(GetPageCount(), id, page, text, bmp_name, bSelect);
}
bool AddPage(wxWindow* page, const wxString& text, bool bSelect = false, int imageId = NO_IMAGE) override
{
DoInvalidateBestSize();
return InsertPage(GetPageCount(), page, text, bSelect, imageId);
}
bool InsertPage(size_t n,
const wxString& id,
wxWindow * page,
const wxString & text,
const std::string& bmp_name = "",
bool bSelect = false,
const wxBitmap& bmp = wxNullBitmap)
{
if (!wxBookCtrlBase::InsertPage(n, page, text, bSelect))
return false;
m_pageNames.insert(m_pageNames.begin() + n, id);
GetBtnsListCtrl()->InsertPage(n, text, bSelect, bmp_name, bmp);
// wxBookCtrlBase::InsertPage() only inserts into the page list and sizes the new
// page to the current page's rect — it never touches visibility, and a freshly
// constructed page defaults to shown. Without this it renders on top of whatever
// page is currently selected until the next SetSelection() call hides it.
if (!DoSetSelectionAfterInsertion(n, bSelect))
page->Hide();
return true;
}
virtual bool InsertPage(size_t n,
wxWindow * page,
const wxString & text,
bool bSelect = false,
int WXUNUSED(imageId) = NO_IMAGE) override
{
return InsertPage(n, wxString(), page, text, "", bSelect);
}
virtual int SetSelection(size_t n) override
{
int ret = DoSetSelection(n, SetSelection_SendEvent);
int new_sel = GetSelection();
//check the new_sel firstly
if (new_sel != n) {
//not allowed, skip it
return ret;
}
GetBtnsListCtrl()->SetSelection(n);
// check that only the selected page is visible and others are hidden:
for (size_t page = 0; page < m_pages.size(); page++) {
wxWindow* win_a = GetPage(page);
wxWindow* win_b = GetPage(n);
if (page != n && GetPage(page) != GetPage(n)) {
m_pages[page]->Hide();
}
}
return ret;
}
virtual int ChangeSelection(size_t n) override
{
GetBtnsListCtrl()->SetSelection(n);
return DoSetSelection(n);
}
// Labels are stored by the custom button list; wx's image-list API is unused — tab icons
// are set directly on the buttons, either from a resource name or a ready wxBitmap.
virtual bool SetPageText(size_t n, const wxString & strText) override
{
wxCHECK_MSG(n < GetPageCount(), false, wxS("Invalid page"));
GetBtnsListCtrl()->SetPageText(n, strText);
return true;
}
virtual wxString GetPageText(size_t n) const override
{
wxCHECK_MSG(n < GetPageCount(), wxString(), wxS("Invalid page"));
return GetBtnsListCtrl()->GetPageText(n);
}
// ORCA: the real page label. GetPageText() returns the button label, which SetCompact() blanks.
wxString GetPageLabel(size_t n) const
{
wxCHECK_MSG(n < GetPageCount(), wxString(), wxS("Invalid page"));
return GetBtnsListCtrl()->GetPageLabel(n);
}
// Resource icon name the page was inserted with; empty for pages added with a wxBitmap.
std::string GetPageIcon(size_t n) const
{
wxCHECK_MSG(n < GetPageCount(), std::string(), wxS("Invalid page"));
return GetBtnsListCtrl()->GetPageIcon(n);
}
virtual bool SetPageImage(size_t WXUNUSED(n), int WXUNUSED(imageId)) override
{
return false;
}
virtual int GetPageImage(size_t WXUNUSED(n)) const override
{
return NO_IMAGE;
}
bool SetPageImage(size_t n, const std::string& bmp_name)
{
return GetBtnsListCtrl()->SetPageImage(n, bmp_name);
}
// Override some wxWindow methods too.
virtual void SetFocus() override
{
wxWindow* const page = GetCurrentPage();
if (page)
page->SetFocus();
}
// The base clears its page list directly instead of calling DoRemovePage() per page,
// which would leave m_pageNames behind. No caller today; kept in sync regardless.
virtual bool DeleteAllPages() override
{
m_pageNames.clear();
return wxBookCtrlBase::DeleteAllPages();
}
ButtonsListCtrl* GetBtnsListCtrl() const { return static_cast<ButtonsListCtrl*>(m_bookctrl); }
void SetOverflowButton(wxWindow* button) { GetBtnsListCtrl()->SetOverflowButton(button); }
// Insertion index just past the first of `ids` that is present, or the end of the bar
// if none is — lets call sites state tab order as "after X" instead of re-deriving it.
size_t PositionAfter(std::initializer_list<const char*> ids) const
{
for (const char* id : ids)
if (const int idx = FindPageByName(id); idx != wxNOT_FOUND)
return static_cast<size_t>(idx) + 1;
return GetPageCount();
}
int FindPageByName(const wxString& id) const
{
if (id.empty())
return wxNOT_FOUND;
for (size_t i = 0; i < m_pageNames.size(); ++i)
if (m_pageNames[i] == id)
return static_cast<int>(i);
return wxNOT_FOUND;
}
wxWindow* GetPageByName(const wxString& id) const
{
const int idx = FindPageByName(id);
return idx == wxNOT_FOUND ? nullptr : GetPage(static_cast<size_t>(idx));
}
bool SelectPageByName(const wxString& id)
{
const int idx = FindPageByName(id);
if (idx == wxNOT_FOUND)
return false;
SetSelection(static_cast<size_t>(idx));
return true;
}
// Inverse of FindPageByName: index -> id. Empty string for an out-of-range
// index or a page that was never given an id (e.g. settings Tab pages).
wxString GetPageName(size_t n) const
{
return n < m_pageNames.size() ? m_pageNames[n] : wxString();
}
wxString GetSelectedPageName() const
{
const int sel = GetSelection();
return sel < 0 ? wxString() : GetPageName(static_cast<size_t>(sel));
}
void UpdateMode()
{
GetBtnsListCtrl()->UpdateMode();
}
void Rescale()
{
GetBtnsListCtrl()->Rescale();
}
void OnNavigationKey(wxNavigationKeyEvent& event)
{
if (event.IsWindowChange()) {
// change pages
AdvanceSelection(event.GetDirection());
}
else {
// we get this event in 3 cases
//
// a) one of our pages might have generated it because the user TABbed
// out from it in which case we should propagate the event upwards and
// our parent will take care of setting the focus to prev/next sibling
//
// or
//
// b) the parent panel wants to give the focus to us so that we
// forward it to our selected page. We can't deal with this in
// OnSetFocus() because we don't know which direction the focus came
// from in this case and so can't choose between setting the focus to
// first or last panel child
//
// or
//
// c) we ourselves (see MSWTranslateMessage) generated the event
//
wxWindow* const parent = GetParent();
// the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
const bool isFromParent = event.GetEventObject() == (wxObject*)parent;
const bool isFromSelf = event.GetEventObject() == (wxObject*)this;
const bool isForward = event.GetDirection();
if (isFromSelf && !isForward)
{
// focus is currently on notebook tab and should leave
// it backwards (Shift-TAB)
event.SetCurrentFocus(this);
parent->HandleWindowEvent(event);
}
else if (isFromParent || isFromSelf)
{
// no, it doesn't come from child, case (b) or (c): forward to a
// page but only if entering notebook page (i.e. direction is
// backwards (Shift-TAB) comething from out-of-notebook, or
// direction is forward (TAB) from ourselves),
if (m_selection != wxNOT_FOUND &&
(!event.GetDirection() || isFromSelf))
{
// so that the page knows that the event comes from it's parent
// and is being propagated downwards
event.SetEventObject(this);
wxWindow* page = m_pages[m_selection];
if (!page->HandleWindowEvent(event))
{
page->SetFocus();
}
//else: page manages focus inside it itself
}
else // otherwise set the focus to the notebook itself
{
SetFocus();
}
}
else
{
// it comes from our child, case (a), pass to the parent, but only
// if the direction is forwards. Otherwise set the focus to the
// notebook itself. The notebook is always the 'first' control of a
// page.
if (!isForward)
{
SetFocus();
}
else if (parent)
{
event.SetCurrentFocus(this);
parent->HandleWindowEvent(event);
}
}
}
}
protected:
virtual void UpdateSelectedPage(size_t WXUNUSED(newsel)) override
{
// Nothing to do here, but must be overridden to avoid the assert in
// the base class version.
}
virtual wxBookCtrlEvent * CreatePageChangingEvent() const override
{
return new wxBookCtrlEvent(wxEVT_BOOKCTRL_PAGE_CHANGING,
GetId());
}
virtual void MakeChangedEvent(wxBookCtrlEvent & event) override
{
event.SetEventType(wxEVT_BOOKCTRL_PAGE_CHANGED);
}
virtual wxWindow * DoRemovePage(size_t page) override
{
wxWindow* const win = wxBookCtrlBase::DoRemovePage(page);
if (win)
{
m_pageNames.erase(m_pageNames.begin() + page);
GetBtnsListCtrl()->RemovePage(page);
DoSetSelectionAfterRemoval(page);
}
return win;
}
virtual void DoSize() override
{
wxWindow* const page = GetCurrentPage();
if (page)
page->SetSize(GetPageRect());
}
virtual void DoShowPage(wxWindow * page, bool show) override
{
if (show)
page->ShowWithEffect(m_showEffect, m_showTimeout);
else
page->HideWithEffect(m_hideEffect, m_hideTimeout);
}
private:
void Init();
std::vector<wxString> m_pageNames; // index-parallel to wxBookCtrlBase::m_pages
wxShowEffect m_showEffect,
m_hideEffect;
unsigned m_showTimeout,
m_hideTimeout;
};
//#endif // _WIN32
#endif // slic3r_Notebook_hpp_