Files
OrcaSlicer/src/slic3r/GUI/TabButton.cpp
T
HanifKoh 84657ff11e Add Missing Includes Across the Remaining Sources and Tests (#16071)
* Ignore Clipper, libpng, mcut and Boost.Polygon Internals in clang-tidy

Each only works through a wrapper or umbrella header: libslic3r/clipper.hpp or clipper_z.hpp configure Clipper before including it, png.h pulls in libpng's config headers, and Boost.Polygon's headers only compile through polygon.hpp or voronoi.hpp.

* Ignore minilzo's Config Headers in clang-tidy

lzoconf.h and lzodefs.h are internal to minilzo.h, which is what the code includes.

* Add Missing Includes Across the Remaining Sources and Tests

Covers src/slic3r/Utils, src/slic3r/plugin, src/slic3r/Config, src/libvgcode, src/dev-utils, src/OrcaSlicer.cpp and tests/, the directories left after src/slic3r/GUI and src/libslic3r. Generated with clang-tidy misc-include-cleaner. libvgcode's own headers are included by relative path as in the rest of that library, and Catch2 and pybind11 with angle brackets as elsewhere in the repo.

* Make the GUI and Test Headers Compile on Their Own

Each now includes, or forward-declares, what it uses instead of relying on what its includers happened to include first. Headers that only compile on one platform, or that nothing built includes, are left alone.

* Keep Windows and nanosvg Setup Ahead of the Added Includes

OrcaSlicer.cpp and several tests set _WIN32_WINNT, WIN32_LEAN_AND_MEAN or NOMINMAX before including Windows.h, and the profile validator defines NANOSVG_IMPLEMENTATION before any libslic3r header. The added includes had landed above those blocks, which broke the Windows build.

* Add the GUI Includes the First Pass Missed

Covers headers that only became editable once they compiled on their own, and wx symbols whose suggested header changed as the clang-tidy ignore list grew after the src/slic3r/GUI pass.

* Keep the Added Test Includes Below the NOMINMAX Guard

test_marchingsquares.cpp and test_texture_displacement.cpp had includes inside #ifndef NOMINMAX, which the tests inherit as defined on Windows from libslic3r, so those were skipped there. .clang-tidy also ignores the MSVC STL and UCRT internals, Boost.Multiprecision's fwd.hpp and CPython's Windows include directory, as in #16068.
2026-10-03 13:45:21 +08:00

245 lines
6.2 KiB
C++

#include "TabButton.hpp"
#include "Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/StaticBox.hpp"
#include <wx/anybutton.h>
#include <wx/colour.h>
#include <utility>
#include "slic3r/GUI/wxExtensions.hpp"
#include <wx/checklst.h>
#include "slic3r/GUI/Widgets/StateHandler.hpp"
#include <wx/dc.h>
#include <wx/dcclient.h>
#include <wx/dcgraph.h>
#include <wx/string.h>
#include <wx/gdicmn.h>
#include <wx/event.h>
BEGIN_EVENT_TABLE(TabButton, StaticBox)
EVT_LEFT_DOWN(TabButton::mouseDown)
EVT_LEFT_UP(TabButton::mouseReleased)
// catch paint events
EVT_PAINT(TabButton::paintEvent)
END_EVENT_TABLE()
static wxColour BORDER_HOVER_COL = wxColour(0, 150, 136);
const static wxColour TAB_BUTTON_BG = wxColour("#FEFFFF");
const static wxColour TAB_BUTTON_SEL = wxColour("#BFE1DE"); // ORCA
TabButton::TabButton()
: paddingSize(18, 16) // ORCA reduce / match left margin buttons on sidebars
, text_color(*wxBLACK)
{
background_color = StateColor(
std::make_pair(TAB_BUTTON_SEL, (int) StateColor::Checked),
std::make_pair(wxColour("#FEFFFF"), (int) StateColor::Hovered),
std::make_pair(wxColour("#FEFFFF"), (int) StateColor::Normal));
border_color = StateColor(
std::make_pair(TAB_BUTTON_SEL, (int) StateColor::Checked), // ORCA use same color for border to prevent 1px blank border
std::make_pair(BORDER_HOVER_COL, (int) StateColor::Hovered),
std::make_pair(wxColour("#FEFFFF"), (int)StateColor::Normal));
}
TabButton::TabButton(wxWindow *parent, wxString text, ScalableBitmap &bmp, long style, int iconSize)
: TabButton()
{
Create(parent, text, bmp, style, iconSize);
}
bool TabButton::Create(wxWindow *parent, wxString text, ScalableBitmap &bmp, long style, int iconSize)
{
StaticBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style);
newtag_img = ScalableBitmap(this, "monitor_hms_new",7);
state_handler.attach({&text_color, &border_color});
state_handler.update_binds();
//BBS set default font
SetFont(Label::Body_14);
wxWindow::SetLabel(text);
this->icon = bmp;
messureSize();
return true;
}
void TabButton::SetLabel(const wxString &label)
{
wxWindow::SetLabel(label);
messureSize();
Refresh();
}
void TabButton::SetMinSize(const wxSize &size)
{
minSize = size;
messureSize();
}
void TabButton::SetPaddingSize(const wxSize &size)
{
paddingSize = size;
messureSize();
}
const wxSize& TabButton::GetPaddingSize()
{
return paddingSize;
}
void TabButton::SetTextColor(StateColor const &color)
{
text_color = color;
state_handler.update_binds();
Refresh();
}
void TabButton::SetBorderColor(StateColor const &color)
{
border_color = color;
state_handler.update_binds();
Refresh();
}
void TabButton::SetBGColor(StateColor const &color)
{
background_color = color;
state_handler.update_binds();
Refresh();
}
void TabButton::SetBitmap(ScalableBitmap &bitmap)
{
this->icon = bitmap;
}
bool TabButton::Enable(bool enable)
{
bool result = wxWindow::Enable(enable);
if (result) {
wxCommandEvent e(EVT_ENABLE_CHANGED);
e.SetEventObject(this);
GetEventHandler()->ProcessEvent(e);
}
return result;
}
void TabButton::Rescale()
{
messureSize();
}
void TabButton::paintEvent(wxPaintEvent &evt)
{
// depending on your system you may need to look at double-buffered dcs
wxPaintDC dc(this);
render(dc);
}
/*
* Here we do the actual rendering. I put it in a separate
* method so that it can work no matter what type of DC
* (e.g. wxPaintDC or wxClientDC) is used.
*/
void TabButton::render(wxDC &dc)
{
StaticBox::render(dc);
int states = state_handler.states();
wxSize size = GetSize();
dc.SetPen(wxPen(border_color.colorForStates(states)));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRectangle(0, 0, size.x, size.y);
// calc content size
wxSize szIcon;
wxSize szContent = textSize;
if (icon.bmp().IsOk()) {
if (szContent.y > 0) {
// BBS norrow size between text and icon
szContent.x += 5;
}
szIcon = icon.GetBmpSize();
szContent.x += szIcon.x;
if (szIcon.y > szContent.y) szContent.y = szIcon.y;
}
// move to center
wxRect rcContent = {{0, 0}, size};
wxSize offset = (size - szContent) / 2;
rcContent.Deflate(offset.x, offset.y);
// start draw
wxPoint pt = rcContent.GetLeftTop();
auto text = GetLabel();
if (!text.IsEmpty()) {
pt.x = FromDIP(paddingSize.x); // ORCA match padding on scaling
pt.y = rcContent.y + (rcContent.height - textSize.y) / 2;
dc.SetFont(GetFont());
dc.SetTextForeground(text_color.colorForStates(states));
dc.DrawText(text, pt);
}
wxBitmap showimg = icon.bmp();
int offset_left = 0;
if (show_new_tag) {
showimg = newtag_img.bmp();
offset_left = FromDIP(4);
}
if (showimg.IsOk()) {
pt.x = size.x - showimg.GetWidth() - paddingSize.y - offset_left;
pt.y = (size.y - showimg.GetHeight()) / 2;
dc.DrawBitmap(showimg, pt);
}
}
void TabButton::messureSize()
{
wxClientDC dc(this);
textSize = dc.GetTextExtent(GetLabel());
if (minSize.GetWidth() > 0) {
wxWindow::SetMinSize(minSize);
return;
}
wxSize szContent = textSize;
if (this->icon.bmp().IsOk()) {
if (szContent.y > 0) {
// BBS norrow size between text and icon
szContent.x += 5;
}
wxSize szIcon = this->icon.GetBmpSize();
szContent.x += szIcon.x;
if (szIcon.y > szContent.y) szContent.y = szIcon.y;
}
wxWindow::SetMinSize(szContent + paddingSize);
}
void TabButton::mouseDown(wxMouseEvent &event)
{
event.Skip();
pressedDown = true;
SetFocus();
CaptureMouse();
}
void TabButton::mouseReleased(wxMouseEvent &event)
{
event.Skip();
if (pressedDown) {
pressedDown = false;
ReleaseMouse();
if (wxRect({0, 0}, GetSize()).Contains(event.GetPosition()))
sendButtonEvent();
}
}
void TabButton::sendButtonEvent()
{
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
event.SetEventObject(this);
GetEventHandler()->ProcessEvent(event);
}