1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
// *****************************************************************************
// * 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 "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, wxNullBitmap, 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 = fastFromDIP(5), int border = fastFromDIP(5));
//set bitmap label flicker free:
void setImage(wxAnyButton& button, const wxImage& bmp);
void setImage(wxStaticBitmap& staticBmp, const wxImage& img);
wxBitmap renderSelectedButton(const wxSize& sz);
wxBitmap renderPressedButton(const wxSize& sz);
//################################### 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, gap) :
stackImages(imgTxt, img, ImageStackLayout::horizontal, ImageStackAlignment::center, gap);
//SetMinSize() instead of SetSize() is needed here for wxWindows layout determination to work correctly
const int defaultHeight = wxButton::GetDefaultSize().GetHeight();
btn.SetMinSize({imgTxt.GetWidth () + 2 * border,
std::max(imgTxt.GetHeight() + 2 * border, defaultHeight)});
setImage(btn, imgTxt);
}
inline
void setImage(wxAnyButton& button, const wxImage& img)
{
if (!img.IsOk())
{
button.SetBitmapLabel (wxNullBitmap);
button.SetBitmapDisabled(wxNullBitmap);
return;
}
button.SetBitmapLabel(toBitmapBundle(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(toBitmapBundle(img.ConvertToDisabled())); //inefficiency: wxBitmap::ConvertToDisabled() implicitly converts to wxImage!
}
inline
void setImage(wxStaticBitmap& staticBmp, const wxImage& img)
{
staticBmp.SetBitmap(toBitmapBundle(img));
}
inline
wxBitmap renderSelectedButton(const wxSize& sz)
{
wxBitmap bmp(sz); //seems we don't need to pass 24-bit depth here even for high-contrast color schemes
{
wxMemoryDC dc(bmp);
const wxColor borderCol(0x79, 0xbc, 0xed); //medium blue
const wxColor innerCol (0xcc, 0xe4, 0xf8); //light blue
drawInsetRectangle(dc, wxRect(bmp.GetSize()), fastFromDIP(1), borderCol, innerCol);
}
return bmp;
}
inline
wxBitmap renderPressedButton(const wxSize& sz)
{
wxBitmap bmp(sz); //seems we don't need to pass 24-bit depth here even for high-contrast color schemes
{
//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(bmp.GetSize());
const int borderSize = fastFromDIP(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(1);
}
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
dc.DrawRectangle(rect);
}
return bmp;
}
}
#endif //BITMAP_BUTTON_H_83415718945878341563415
|