151 lines
5.5 KiB
C++
151 lines
5.5 KiB
C++
// *****************************************************************************
|
|
// * This file is part of the FreeFileSync project. It is distributed under *
|
|
// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 *
|
|
// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
|
|
// *****************************************************************************
|
|
|
|
#ifndef BITMAP_BUTTON_H_83415718945878341563415
|
|
#define BITMAP_BUTTON_H_83415718945878341563415
|
|
|
|
#include <wx/bmpbuttn.h>
|
|
#include <wx/settings.h>
|
|
#include <wx/statbmp.h>
|
|
#include "image_tools.h"
|
|
#include "std_button_layout.h"
|
|
#include "dc.h"
|
|
|
|
|
|
namespace zen
|
|
{
|
|
//zen::BitmapTextButton is identical to wxBitmapButton, but preserves the label via SetLabel(), which wxFormbuilder would ditch!
|
|
class BitmapTextButton : public wxBitmapButton
|
|
{
|
|
public:
|
|
BitmapTextButton(wxWindow* parent,
|
|
wxWindowID id,
|
|
const wxString& label,
|
|
const wxPoint& pos = wxDefaultPosition,
|
|
const wxSize& size = wxDefaultSize,
|
|
long style = 0,
|
|
const wxValidator& validator = wxDefaultValidator,
|
|
const wxString& name = wxASCII_STR(wxButtonNameStr)) :
|
|
wxBitmapButton(parent, id,
|
|
//(FreeFileSync_x86_64:77379): Gtk-CRITICAL **: 11:04:31.752: IA__gtk_widget_modify_style: assertion 'GTK_IS_WIDGET (widget)' failed
|
|
rectangleImage({1, 1}, *wxRED),
|
|
pos, size, style, validator, name)
|
|
{
|
|
SetLabel(label);
|
|
}
|
|
};
|
|
|
|
//wxButton::SetBitmap() also supports "image + text", but screws up proper gap and border handling
|
|
void setBitmapTextLabel(wxBitmapButton& btn, const wxImage& img, const wxString& text, int gap = dipToWxsize(5), int border = dipToWxsize(5));
|
|
|
|
//set bitmap label flicker free:
|
|
void setImage(wxAnyButton& button, const wxImage& bmp);
|
|
void setImage(wxStaticBitmap& staticBmp, const wxImage& img);
|
|
|
|
wxImage renderPressedButton(const wxSize& sz);
|
|
|
|
inline wxColor getColorToggleButtonBorder() { return {0x79, 0xbc, 0xed}; } //medium blue
|
|
inline wxColor getColorToggleButtonFill () { return {0xcc, 0xe4, 0xf8}; } //light blue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//################################### implementation ###################################
|
|
inline
|
|
void setBitmapTextLabel(wxBitmapButton& btn, const wxImage& img, const wxString& text, int gap, int border)
|
|
{
|
|
assert(gap >= 0 && border >= 0);
|
|
gap = std::max(0, gap);
|
|
border = std::max(0, border);
|
|
|
|
wxImage imgTxt = createImageFromText(text, btn.GetFont(), btn.GetForegroundColour());
|
|
if (img.IsOk())
|
|
imgTxt = btn.GetLayoutDirection() != wxLayout_RightToLeft ?
|
|
stackImages(img, imgTxt, ImageStackLayout::horizontal, ImageStackAlignment::center, wxsizeToScreen(gap)) :
|
|
stackImages(imgTxt, img, ImageStackLayout::horizontal, ImageStackAlignment::center, wxsizeToScreen(gap));
|
|
|
|
//SetMinSize() instead of SetSize() is needed here for wxWidgets layout determination to work correctly
|
|
btn.SetMinSize({screenToWxsize(imgTxt.GetWidth()) + 2 * border,
|
|
std::max(screenToWxsize(imgTxt.GetHeight()) + 2 * border, getDefaultButtonHeight())});
|
|
|
|
setImage(btn, imgTxt);
|
|
}
|
|
|
|
|
|
inline
|
|
void setImage(wxAnyButton& button, const wxImage& img)
|
|
{
|
|
if (!img.IsOk())
|
|
{
|
|
button.SetBitmapLabel (wxNullBitmap);
|
|
button.SetBitmapDisabled(wxNullBitmap);
|
|
return;
|
|
}
|
|
|
|
|
|
button.SetBitmapLabel(toScaledBitmap(img));
|
|
|
|
//wxWidgets excels at screwing up consistently once again:
|
|
//the first call to SetBitmapLabel() *implicitly* sets the disabled bitmap, too, subsequent calls, DON'T!
|
|
button.SetBitmapDisabled(toScaledBitmap(img.ConvertToDisabled())); //inefficiency: wxBitmap::ConvertToDisabled() implicitly converts to wxImage!
|
|
}
|
|
|
|
|
|
inline
|
|
void setImage(wxStaticBitmap& staticBmp, const wxImage& img)
|
|
{
|
|
staticBmp.SetBitmap(toScaledBitmap(img));
|
|
}
|
|
|
|
|
|
|
|
inline
|
|
wxImage generatePressedButtonBack(const wxSize& sz)
|
|
{
|
|
#if 1
|
|
return rectangleImage(sz, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW), {0x11, 0x79, 0xfe} /*light blue*/, dipToScreen(2));
|
|
|
|
#else //rectangle border with gradient as background
|
|
wxBitmap bmp(wxsizeToScreen(sz.x),
|
|
wxsizeToScreen(sz.y)); //seems we don't need to pass 24-bit depth here even for high-contrast color schemes
|
|
bmp.SetScaleFactor(getScreenDpiScale());
|
|
{
|
|
//draw rectangle border with gradient
|
|
const wxColor colFrom = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
|
|
const wxColor colTo(0x11, 0x79, 0xfe); //light blue
|
|
|
|
wxMemoryDC dc(bmp);
|
|
dc.SetPen(*wxTRANSPARENT_PEN); //wxTRANSPARENT_PEN is about 2x faster than redundantly drawing with col!
|
|
|
|
wxRect rect(sz);
|
|
|
|
const int borderSize = dipToWxsize(3);
|
|
for (int i = 1 ; i <= borderSize; ++i)
|
|
{
|
|
const wxColor colGradient((colFrom.Red () * (borderSize - i) + colTo.Red () * i) / borderSize,
|
|
(colFrom.Green() * (borderSize - i) + colTo.Green() * i) / borderSize,
|
|
(colFrom.Blue () * (borderSize - i) + colTo.Blue () * i) / borderSize);
|
|
dc.SetBrush(colGradient);
|
|
dc.DrawRectangle(rect);
|
|
rect.Deflate(dipToWxsize(1));
|
|
}
|
|
|
|
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
|
dc.DrawRectangle(rect);
|
|
}
|
|
wxImage img = bmp.ConvertToImage();
|
|
convertToVanillaImage(img);
|
|
return img;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#endif //BITMAP_BUTTON_H_83415718945878341563415
|