UI: Change custom wxCheckedList and wxCheckTree to use native checkboxes

This allows for OS and dark mode theming, and should unify all the looks for all of the checkboxes in Cemu.
This commit is contained in:
Crementif 2025-07-06 18:35:19 +02:00
parent 64c7489c08
commit ba9c19e802
16 changed files with 130 additions and 442 deletions

View file

@ -1,24 +0,0 @@
/* XPM */
static const char * checked_xpm[] = {
"16 16 5 1",
" c None",
". c #808080",
"X c Black",
"o c #c0c0c0",
"w c White",
" ",
" ",
" ............ ",
" .XXXXXXXXXXo ",
" .Xwwwwwwwwwo ",
" .XwwwwwwwXwo ",
" .XwwwwwwXXwo ",
" .XwXwwwXXXwo ",
" .XwXXwXXXwwo ",
" .XwXXXXXwwwo ",
" .XwwXXXwwwwo ",
" .XwwwXwwwwwo ",
" .Xwwwwwwwwwo ",
" .ooooooooooo ",
" ",
" "};

View file

@ -1,38 +0,0 @@
/* XPM */
static const char * checked2_xpm[] = {
"14 15 20 1",
" c None",
". c #1C5180",
"+ c #E2E2DD",
"@ c #E3E3DF",
"# c #E5E5E1",
"$ c #E7E7E3",
"% c #EAEAE6",
"& c #ECECE9",
"* c #EFEFEC",
"= c #F1F1EF",
"- c #F3F3F1",
"; c #F5F5F3",
"> c #21A121",
", c #F7F7F6",
"' c #F9F9F8",
") c #FAFAF9",
"! c #FCFCFB",
"~ c #FDFDFD",
"{ c #FEFEFE",
"] c #FFFFFF",
"............. ",
".+++@#$%&*=-. ",
".++@#$%&*=-;. ",
".+@#$%&*=>;,. ",
".@#$%&*=>>,'. ",
".#$>&*=>>>'). ",
".$%>>=>>>')!. ",
".%&>>>>>')!~. ",
".&*=>>>')!~{. ",
".*=-;>')!~{]. ",
".=-;,')!~{]]. ",
".-;,')!~{]]]. ",
"............. ",
" ",
" "};

View file

@ -1,21 +0,0 @@
/* XPM */
static const char * checked_d_xpm[] = {
"14 15 3 1",
" c None",
". c #CAC8BB",
"+ c #FFFFFF",
"............. ",
".+++++++++++. ",
".+++++++++++. ",
".++++++++.++. ",
".+++++++..++. ",
".++.+++...++. ",
".++..+...+++. ",
".++.....++++. ",
".+++...+++++. ",
".++++.++++++. ",
".+++++++++++. ",
".+++++++++++. ",
"............. ",
" ",
" "};

View file

@ -1,23 +0,0 @@
/* XPM */
static const char * checked_dis_xpm[] = {
"16 16 4 1",
" c None",
". c #808080",
"X c Black",
"o c #c0c0c0",
" ",
" ",
" ............ ",
" .XXXXXXXXXXo ",
" .Xoooooooooo ",
" .Xooooooo.oo ",
" .Xoooooo..oo ",
" .Xo.ooo...oo ",
" .Xo..o...ooo ",
" .Xo.....oooo ",
" .Xoo...ooooo ",
" .Xooo.oooooo ",
" .Xoooooooooo ",
" .ooooooooooo ",
" ",
" "};

View file

@ -1,44 +0,0 @@
/* XPM */
static const char * checked_ld_xpm[] = {
"14 15 26 1",
" c None",
". c #1C5180",
"+ c #B0B0A7",
"@ c #B3B3AA",
"# c #B7B7AD",
"$ c #BCBBB1",
"% c #C1C1B6",
"& c #C7C6BB",
"* c #CDCCC0",
"= c #D2D1C5",
"- c #D7D5C8",
"; c #DBDACC",
"> c #1C861A",
", c #DFDDCF",
"' c #1C8A1A",
") c #E3E1D3",
"! c #197A18",
"~ c #1D8C1B",
"{ c #E6E5D6",
"] c #1A7D18",
"^ c #1B8119",
"/ c #EAE8D9",
"( c #1B8419",
"_ c #EDEBDB",
": c #EFEDDD",
"< c #F1EFDF",
"............. ",
".+++@#$%&*=-. ",
".++@#$%&*=-;. ",
".+@#$%&*=>;,. ",
".@#$%&*=>',). ",
".#$!&*=>'~){. ",
".$%]^=>'~){/. ",
".%&^(>'~){/_. ",
".&*=>'~){/_:. ",
".*=-;~){/_:<. ",
".=-;,){/_:<<. ",
".-;,){/_:<<<. ",
"............. ",
" ",
" "};

View file

@ -1,70 +0,0 @@
/* XPM */
static const char * checked_mo_xpm[] = {
"14 15 52 1",
" c None",
". c #1C5180",
"+ c #FFF0CF",
"@ c #FFEDC6",
"# c #FFE9BA",
"$ c #FEE4AC",
"% c #FEDF9C",
"& c #FDD98C",
"* c #FDD889",
"= c #FDDB95",
"- c #FDDC97",
"; c #FCD687",
"> c #FBCA6A",
", c #FDE3AC",
"' c #FDE6B6",
") c #FDDEA2",
"! c #FBD07A",
"~ c #FFEABD",
"{ c #FEE9BC",
"] c #F7F7F5",
"^ c #F6F6F4",
"/ c #F4F4F3",
"( c #F8F8F7",
"_ c #FAFAF9",
": c #21A121",
"< c #FDE3AE",
"[ c #FBD280",
"} c #FEECC4",
"| c #FDE1AB",
"1 c #FBD07B",
"2 c #FEE7B5",
"3 c #FEECC7",
"4 c #FDE0A8",
"5 c #FBCE77",
"6 c #FEE3A9",
"7 c #FEEBC3",
"8 c #FBD892",
"9 c #FAC867",
"0 c #FEE0A3",
"a c #FEE9BF",
"b c #F9BC46",
"c c #F9B73A",
"d c #FCD27A",
"e c #F8B636",
"f c #FBCC6B",
"g c #FCDB99",
"h c #F8B433",
"i c #FBC863",
"j c #FAC55A",
"k c #FAC55B",
"l c #FBCC70",
"m c #F8B330",
"............. ",
".+@#$%&*=-;>. ",
".@#$%&*=,')!. ",
".~{]^/^(_:<[. ",
".{}_(^(_::|1. ",
".23:_(_:::45. ",
".67::_:::_89. ",
".0a:::::_(9b. ",
".=,_:::_(^bc. ",
".d;(_:_(^/ce. ",
".f>!g489bceh. ",
".ijkl59bcehm. ",
"............. ",
" ",
" "};

View file

@ -25,12 +25,7 @@
#if wxUSE_CHECKEDLISTCTRL
// resources
#include "wxgui/wxcomponents/checked.xpm"
#include "wxgui/wxcomponents/unchecked.xpm"
#include "wxgui/wxcomponents/checked_dis.xpm"
#include "wxgui/wxcomponents/unchecked_dis.xpm"
#include <wx/renderer.h>
IMPLEMENT_CLASS(wxCheckedListCtrl, wxListCtrl)
BEGIN_EVENT_TABLE(wxCheckedListCtrl, wxListCtrl)
@ -52,13 +47,52 @@ bool wxCheckedListCtrl::Create(wxWindow* parent, wxWindowID id, const wxPoint& p
if (!wxListCtrl::Create(parent, id, pt, sz, style, validator, name))
return FALSE;
SetImageList(&m_imageList, wxIMAGE_LIST_SMALL);
// Get the native size of the checkbox
int width = wxRendererNative::Get().GetCheckBoxSize(this).GetWidth();
int height = wxRendererNative::Get().GetCheckBoxSize(this).GetHeight();
// the add order must respect the wxCLC_XXX_IMGIDX defines in the headers !
m_imageList.Add(wxIcon(unchecked_xpm));
m_imageList.Add(wxIcon(checked_xpm));
m_imageList.Add(wxIcon(unchecked_dis_xpm));
m_imageList.Add(wxIcon(checked_dis_xpm));
m_imageList = new wxImageList(width, height, TRUE);
SetImageList(m_imageList, wxIMAGE_LIST_SMALL);
wxBitmap unchecked_bmp(width, height),
checked_bmp(width, height),
unchecked_disabled_bmp(width, height),
checked_disabled_bmp(width, height);
wxMemoryDC renderer_dc;
// Unchecked
renderer_dc.SelectObject(unchecked_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), 0);
// Checked
renderer_dc.SelectObject(checked_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_CHECKED);
// Unchecked and Disabled
renderer_dc.SelectObject(unchecked_disabled_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), 0 | wxCONTROL_DISABLED);
// Checked and Disabled
renderer_dc.SelectObject(checked_disabled_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_CHECKED | wxCONTROL_DISABLED);
// Deselect the renderers Object
renderer_dc.SelectObject(wxNullBitmap);
// the add order is important: the first added image will be
m_imageList->Add(unchecked_bmp);
m_imageList->Add(checked_bmp);
m_imageList->Add(unchecked_disabled_bmp);
m_imageList->Add(checked_disabled_bmp);
return TRUE;
}
@ -82,11 +116,10 @@ int wxCheckedListCtrl::GetItemImageFromAdditionalState(int addstate)
wxColour wxCheckedListCtrl::GetBgColourFromAdditionalState(int additionalstate)
{
if ((additionalstate & wxLIST_STATE_ENABLED) &&
this->IsEnabled())
return *wxWHITE;
if ((additionalstate & wxLIST_STATE_ENABLED) && this->IsEnabled())
return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
#ifdef __WXMSW__
return wxColour(212, 208, 200);
return wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK);
#else
return wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
#endif

View file

@ -81,11 +81,11 @@ protected:
wxArrayInt m_stateList;
// our set of checkbox images...
wxImageList m_imageList;
wxImageList* m_imageList;
public:
wxCheckedListCtrl()
: wxListView(), m_imageList(16, 16, TRUE) {}
: wxListView() {}
wxCheckedListCtrl(wxWindow *parent, wxWindowID id = wxID_ANY,
const wxPoint& pt = wxDefaultPosition,
@ -93,7 +93,7 @@ public:
long style = wxCLC_CHECK_WHEN_SELECTING,
const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxListCtrlNameStr)
: wxListView(), m_imageList(16, 16, TRUE)
: wxListView()
{ Create(parent, id, pt, sz, style, validator, name); }
bool Create(wxWindow *parent, wxWindowID id = wxID_ANY,

View file

@ -1,14 +1,9 @@
#include "wxgui/wxcomponents/checktree.h"
#include "wxgui/wxcomponents/checked2.xpm"
#include "wxgui/wxcomponents/checked_d.xpm"
#include "wxgui/wxcomponents/checked_ld.xpm"
#include "wxgui/wxcomponents/checked_mo.xpm"
#include "wxgui/wxcomponents/unchecked2.xpm"
#include "wxgui/wxcomponents/unchecked_d.xpm"
#include "wxgui/wxcomponents/unchecked_ld.xpm"
#include "wxgui/wxcomponents/unchecked_mo.xpm"
#include <wx/dcmemory.h>
#include <wx/icon.h>
#include <wx/imaglist.h>
#include <wx/renderer.h>
wxDEFINE_EVENT(wxEVT_CHECKTREE_FOCUS, wxTreeEvent);
wxDEFINE_EVENT(wxEVT_CHECKTREE_CHOICE, wxTreeEvent);
@ -108,17 +103,81 @@ wxCheckTree::wxCheckTree(wxWindow* parent, const wxWindowID id, const wxPoint& p
void wxCheckTree::Init()
{
wxIcon icons[8] =
{
wxIcon(unchecked2_xpm), wxIcon(unchecked_mo_xpm), wxIcon(unchecked_ld_xpm), wxIcon(unchecked_d_xpm), wxIcon(checked2_xpm), wxIcon(checked_mo_xpm), wxIcon(checked_ld_xpm), wxIcon(checked_d_xpm)
};
int width = wxRendererNative::Get().GetCheckBoxSize(this).GetWidth();
int height = wxRendererNative::Get().GetCheckBoxSize(this).GetHeight();
// Make an state image list containing small icons
auto states = new wxImageList(icons[0].GetWidth(), icons[0].GetHeight(), true);
auto states = new wxImageList(width, height, true);
for (const auto& icon : icons)
states->Add(icon);
wxBitmap unchecked_bmp(width, height);
wxBitmap unchecked_mouse_over_bmp(width, height);
wxBitmap unchecked_left_down_bmp(width, height);
wxBitmap unchecked_disabled_bmp(width, height);
wxBitmap checked_bmp(width, height);
wxBitmap checked_mouse_over_bmp(width, height);
wxBitmap checked_left_down_bmp(width, height);
wxBitmap checked_disabled_bmp(width, height);
wxMemoryDC renderer_dc;
// Unchecked
renderer_dc.SelectObject(unchecked_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_NONE);
// Unchecked Mouse Over
renderer_dc.SelectObject(unchecked_mouse_over_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_CURRENT);
// Unchecked and Disabled
renderer_dc.SelectObject(unchecked_disabled_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_DISABLED);
// Unchecked Left Down
renderer_dc.SelectObject(unchecked_left_down_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_CURRENT | wxCONTROL_PRESSED);
// Checked
renderer_dc.SelectObject(checked_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_CHECKED);
// Checked Mouse Over
renderer_dc.SelectObject(checked_mouse_over_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_CHECKED | wxCONTROL_CURRENT);
// Checked Left Down
renderer_dc.SelectObject(checked_left_down_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_CHECKED | wxCONTROL_CURRENT | wxCONTROL_PRESSED);
// Checked and Disabled
renderer_dc.SelectObject(checked_disabled_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, width, height), wxCONTROL_CHECKED | wxCONTROL_DISABLED);
renderer_dc.SelectObject(wxNullBitmap);
states->Add(unchecked_bmp);
states->Add(unchecked_mouse_over_bmp);
states->Add(unchecked_left_down_bmp);
states->Add(unchecked_disabled_bmp);
states->Add(checked_bmp);
states->Add(checked_mouse_over_bmp);
states->Add(checked_left_down_bmp);
states->Add(checked_disabled_bmp);
AssignStateImageList(states);
Connect(wxEVT_TREE_SEL_CHANGING, wxTreeEventHandler( wxCheckTree::On_Tree_Sel_Changed ), nullptr, this);
@ -173,7 +232,7 @@ void wxCheckTree::SetItemTextColour(const wxTreeItemId& item, const wxColour& co
{
const auto it = m_colors.find(item);
if (it == m_colors.end())
m_colors.emplace(std::pair<wxTreeItemId,wxColor>(item, col));
m_colors.emplace(std::pair<wxTreeItemId,wxColour>(item, col));
else
m_colors[item] = col;
@ -218,7 +277,7 @@ bool wxCheckTree::EnableCheckBox(const wxTreeItemId& item, bool enable)
else if (state == CHECKED || state == CHECKED_MOUSE_OVER || state == CHECKED_LEFT_DOWN)
SetItemState(item, CHECKED_DISABLED);
const wxColor col = GetItemTextColour(item);
const wxColour col = GetItemTextColour(item);
SetItemTextColour(item, wxColour(161, 161, 146));
m_colors[item] = col;
return true;

View file

@ -82,7 +82,7 @@ class WXDLLIMPEXP_CHECKTREE wxCheckTree : public wxTreeCtrl
void On_Tree_Focus_Lost( wxFocusEvent& event );
//private data:
std::map<wxTreeItemId,wxColor> m_colors;
std::map<wxTreeItemId,wxColour> m_colors;
bool mouse_entered_tree_with_left_down = false;

View file

@ -1,24 +0,0 @@
/* XPM */
static const char * unchecked_xpm[] = {
"16 16 5 1",
" c None",
". c #808080",
"X c Black",
"o c #c0c0c0",
"w c White",
" ",
" ",
" ............ ",
" .XXXXXXXXXXo ",
" .Xwwwwwwwwwo ",
" .Xwwwwwwwwwo ",
" .Xwwwwwwwwwo ",
" .Xwwwwwwwwwo ",
" .Xwwwwwwwwwo ",
" .Xwwwwwwwwwo ",
" .Xwwwwwwwwwo ",
" .Xwwwwwwwwwo ",
" .Xwwwwwwwwwo ",
" .ooooooooooo ",
" ",
" "};

View file

@ -1,37 +0,0 @@
/* XPM */
static const char * unchecked2_xpm[] = {
"14 15 19 1",
" c None",
". c #1C5180",
"+ c #DCDCD7",
"@ c #DEDED9",
"# c #E0E0DB",
"$ c #E2E2DE",
"% c #E5E5E2",
"& c #E8E8E5",
"* c #ECECE9",
"= c #EFEFEC",
"- c #F1F1EF",
"; c #F3F3F1",
"> c #F5F5F4",
", c #F7F7F6",
"' c #F9F9F8",
") c #FBFBFA",
"! c #FDFDFC",
"~ c #FEFEFE",
"{ c #FFFFFF",
"............. ",
".+++@#$%&*=-. ",
".++@#$%&*=-;. ",
".+@#$%&*=-;>. ",
".@#$%&*=-;>,. ",
".#$%&*=-;>,'. ",
".$%&*=-;>,'). ",
".%&*=-;>,')!. ",
".&*=-;>,')!~. ",
".*=-;>,')!~{. ",
".=-;>,')!~{{. ",
".-;>,')!~{{{. ",
"............. ",
" ",
" "};

View file

@ -1,21 +0,0 @@
/* XPM */
static const char * unchecked_d_xpm[] = {
"14 15 3 1",
" c None",
". c #CAC8BB",
"+ c #FFFFFF",
"............. ",
".+++++++++++. ",
".+++++++++++. ",
".+++++++++++. ",
".+++++++++++. ",
".+++++++++++. ",
".+++++++++++. ",
".+++++++++++. ",
".+++++++++++. ",
".+++++++++++. ",
".+++++++++++. ",
".+++++++++++. ",
"............. ",
" ",
" "};

View file

@ -1,23 +0,0 @@
/* XPM */
static const char * unchecked_dis_xpm[] = {
"16 16 4 1",
" c None",
". c #808080",
"X c Black",
"o c #c0c0c0",
" ",
" ",
" ............ ",
" .XXXXXXXXXXo ",
" .Xoooooooooo ",
" .Xoooooooooo ",
" .Xoooooooooo ",
" .Xoooooooooo ",
" .Xoooooooooo ",
" .Xoooooooooo ",
" .Xoooooooooo ",
" .Xoooooooooo ",
" .Xoooooooooo ",
" .ooooooooooo ",
" ",
" "};

View file

@ -1,37 +0,0 @@
/* XPM */
static const char * unchecked_ld_xpm[] = {
"14 15 19 1",
" c None",
". c #1C5180",
"+ c #B0B0A7",
"@ c #B3B3AA",
"# c #B7B7AD",
"$ c #BCBBB1",
"% c #C1C1B6",
"& c #C7C6BB",
"* c #CDCCC0",
"= c #D2D1C5",
"- c #D7D5C8",
"; c #DBDACC",
"> c #DFDDCF",
", c #E3E1D3",
"' c #E6E5D6",
") c #EAE8D9",
"! c #EDEBDB",
"~ c #EFEDDD",
"{ c #F1EFDF",
"............. ",
".+++@#$%&*=-. ",
".++@#$%&*=-;. ",
".+@#$%&*=-;>. ",
".@#$%&*=-;>,. ",
".#$%&*=-;>,'. ",
".$%&*=-;>,'). ",
".%&*=-;>,')!. ",
".&*=-;>,')!~. ",
".*=-;>,')!~{. ",
".=-;>,')!~{{. ",
".-;>,')!~{{{. ",
"............. ",
" ",
" "};

View file

@ -1,42 +0,0 @@
/* XPM */
static const char * unchecked_mo_xpm[] = {
"14 15 24 1",
" c None",
". c #1C5180",
"+ c #FFF0CF",
"@ c #FFEDC6",
"# c #FFE9BA",
"$ c #FEE4AC",
"% c #FEDF9C",
"& c #FDD98C",
"* c #FDD684",
"= c #FCD37C",
"- c #FCD074",
"; c #FBCC6B",
"> c #FBC863",
", c #FAC55A",
"' c #E7E7E3",
") c #FAC254",
"! c #FAC04E",
"~ c #F9BD48",
"{ c #F9BB43",
"] c #F9B93E",
"^ c #F9B73A",
"/ c #F8B636",
"( c #F8B433",
"_ c #F8B330",
"............. ",
".+@#$%&*=-;>. ",
".@#$%&*=-;>,. ",
".#$''''''',). ",
".$%''''''')!. ",
".%&'''''''!~. ",
".&*'''''''~{. ",
".*='''''''{]. ",
".=-''''''']^. ",
".-;'''''''^/. ",
".;>,)!~{]^/(. ",
".>,)!~{]^/(_. ",
"............. ",
" ",
" "};