BambuStudio/src/slic3r/GUI/Widgets/Button.cpp

250 lines
6.3 KiB
C++

#include "Button.hpp"
#include "Label.hpp"
#include <wx/dcgraph.h>
BEGIN_EVENT_TABLE(Button, StaticBox)
EVT_LEFT_DOWN(Button::mouseDown)
EVT_LEFT_UP(Button::mouseReleased)
// catch paint events
EVT_PAINT(Button::paintEvent)
END_EVENT_TABLE()
/*
* Called by the system of by wxWidgets when the panel needs
* to be redrawn. You can also trigger this call by
* calling Refresh()/Update().
*/
Button::Button()
: paddingSize(10, 8)
, text_color(*wxBLACK)
{
background_color = StateColor(
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Checked),
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Hovered),
std::make_pair(*wxWHITE, (int) StateColor::Normal));
}
Button::Button(wxWindow* parent, wxString text, wxString icon, long style, int iconSize)
: Button()
{
Create(parent, text, icon, style, iconSize);
}
bool Button::Create(wxWindow* parent, wxString text, wxString icon, long style, int iconSize)
{
StaticBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style);
state_handler.attach({&text_color});
state_handler.update_binds();
//BBS set default font
SetFont(Label::Body_14);
wxWindow::SetLabel(text);
if (!icon.IsEmpty()) {
//BBS set button icon default size to 20
this->active_icon = ScalableBitmap(this, icon.ToStdString(), iconSize > 0 ? iconSize : 20);
}
messureSize();
return true;
}
void Button::SetLabel(const wxString& label)
{
wxWindow::SetLabel(label);
messureSize();
Refresh();
}
void Button::SetIcon(const wxString& icon)
{
if (!icon.IsEmpty()) {
//BBS set button icon default size to 20
this->active_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt());
}
else
{
this->active_icon = ScalableBitmap();
}
Refresh();
}
void Button::SetInactiveIcon(const wxString &icon)
{
if (!icon.IsEmpty()) {
// BBS set button icon default size to 20
this->inactive_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt());
} else {
this->inactive_icon = ScalableBitmap();
}
Refresh();
}
void Button::SetMinSize(const wxSize& size)
{
minSize = size;
messureSize();
}
void Button::SetPaddingSize(const wxSize& size)
{
paddingSize = size;
messureSize();
}
void Button::SetTextColor(StateColor const& color)
{
text_color = color;
state_handler.update_binds();
Refresh();
}
void Button::SetTextColorNormal(wxColor const &color)
{
text_color.setColorForStates(color, 0);
Refresh();
}
bool Button::Enable(bool enable)
{
bool result = wxWindow::Enable(enable);
if (result) {
wxCommandEvent e(EVT_ENABLE_CHANGED);
e.SetEventObject(this);
GetEventHandler()->ProcessEvent(e);
}
return result;
}
void Button::Rescale()
{
if (this->active_icon.bmp().IsOk())
this->active_icon.msw_rescale();
if (this->inactive_icon.bmp().IsOk())
this->inactive_icon.msw_rescale();
messureSize();
}
void Button::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 Button::render(wxDC& dc)
{
StaticBox::render(dc);
int states = state_handler.states();
wxSize size = GetSize();
dc.SetBrush(*wxTRANSPARENT_BRUSH);
// calc content size
wxSize szIcon;
wxSize szContent = textSize;
ScalableBitmap icon;
if (m_selected || ((states & (int)StateColor::State::Hovered) != 0))
icon = active_icon;
else
icon = inactive_icon;
int padding = 5;
if (icon.bmp().IsOk()) {
if (szContent.y > 0) {
//BBS norrow size between text and icon
szContent.x += padding;
}
szIcon = icon.GetBmpSize();
szContent.x += szIcon.x;
if (szIcon.y > szContent.y)
szContent.y = szIcon.y;
if (szContent.x > size.x) {
int d = std::min(padding, szContent.x - size.x);
padding -= d;
szContent.x -= d;
}
}
// move to center
wxRect rcContent = { {0, 0}, size };
wxSize offset = (size - szContent) / 2;
if (offset.x < 0) offset.x = 0;
rcContent.Deflate(offset.x, offset.y);
// start draw
wxPoint pt = rcContent.GetLeftTop();
if (icon.bmp().IsOk()) {
pt.y += (rcContent.height - szIcon.y) / 2;
dc.DrawBitmap(icon.bmp(), pt);
//BBS norrow size between text and icon
pt.x += szIcon.x + padding;
pt.y = rcContent.y;
}
auto text = GetLabel();
if (!text.IsEmpty()) {
if (pt.x + textSize.x > size.x)
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, size.x - pt.x);
pt.y += (rcContent.height - textSize.y) / 2;
dc.SetFont(GetFont());
dc.SetTextForeground(text_color.colorForStates(states));
dc.DrawText(text, pt);
}
}
void Button::messureSize()
{
wxClientDC dc(this);
textSize = dc.GetTextExtent(GetLabel());
if (minSize.GetWidth() > 0) {
wxWindow::SetMinSize(minSize);
return;
}
wxSize szContent = textSize;
if (this->active_icon.bmp().IsOk()) {
if (szContent.y > 0) {
//BBS norrow size between text and icon
szContent.x += 5;
}
wxSize szIcon = this->active_icon.GetBmpSize();
szContent.x += szIcon.x;
if (szIcon.y > szContent.y)
szContent.y = szIcon.y;
}
wxSize size = szContent + paddingSize * 2;
if (minSize.GetHeight() > 0)
size.SetHeight(minSize.GetHeight());
wxWindow::SetMinSize(size);
}
void Button::mouseDown(wxMouseEvent& event)
{
event.Skip();
pressedDown = true;
SetFocus();
CaptureMouse();
}
void Button::mouseReleased(wxMouseEvent& event)
{
event.Skip();
if (pressedDown) {
pressedDown = false;
ReleaseMouse();
if (wxRect({0, 0}, GetSize()).Contains(event.GetPosition()))
sendButtonEvent();
}
}
void Button::sendButtonEvent()
{
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
event.SetEventObject(this);
GetEventHandler()->ProcessEvent(event);
}