#include "Button.hpp" #include "Label.hpp" #include 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.bmp().GetSize(); 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.bmp().GetSize(); szContent.x += szIcon.x; if (szIcon.y > szContent.y) szContent.y = szIcon.y; } wxWindow::SetMinSize(szContent + paddingSize * 2); } 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); }