From 064e7f0f2c41db63462b5c34d35a173bd4c1a00d Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 23 Oct 2022 17:56:07 +0100 Subject: [PATCH] Dark mode hacks for SPLIT_BUTTON on OSX. --- common/widgets/split_button.cpp | 62 +++++++++++++++++++++++++++++---- include/widgets/split_button.h | 3 +- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/common/widgets/split_button.cpp b/common/widgets/split_button.cpp index 399865a158..d6e6a3bc38 100644 --- a/common/widgets/split_button.cpp +++ b/common/widgets/split_button.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2016 Anil8735(https://stackoverflow.com/users/3659387/anil8753) * from https://stackoverflow.com/a/37274011 - * Copyright (C) 2020-2021 Kicad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2020-2022 Kicad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,16 +29,14 @@ #include #include #include - +#include +#include SPLIT_BUTTON::SPLIT_BUTTON( wxWindow* aParent, wxWindowID aId, const wxString& aLabel, const wxPoint& aPos, const wxSize& aSize ) : wxPanel( aParent, aId, aPos, aSize, wxBORDER_NONE | wxTAB_TRAVERSAL, "DropDownButton" ), m_label( aLabel ) { - m_colorNormal = GetForegroundColour(); - m_colorDisabled = GetForegroundColour().MakeDisabled(); - if( aSize == wxDefaultSize ) { wxSize defaultSize = wxButton::GetDefaultSize(); @@ -54,6 +52,9 @@ SPLIT_BUTTON::SPLIT_BUTTON( wxWindow* aParent, wxWindowID aId, const wxString& a Bind( wxEVT_LEAVE_WINDOW, &SPLIT_BUTTON::OnMouseLeave, this ); Bind( wxEVT_ENTER_WINDOW, &SPLIT_BUTTON::OnMouseEnter, this ); + Bind( wxEVT_SYS_COLOUR_CHANGED, wxSysColourChangedEventHandler( SPLIT_BUTTON::onThemeChanged ), + this ); + m_pMenu = new wxMenu(); } @@ -65,6 +66,12 @@ SPLIT_BUTTON::~SPLIT_BUTTON() } +void SPLIT_BUTTON::onThemeChanged( wxSysColourChangedEvent &aEvent ) +{ + Refresh(); +} + + void SPLIT_BUTTON::SetMinSize( const wxSize& aSize ) { m_unadjustedMinSize = aSize; @@ -202,6 +209,37 @@ void SPLIT_BUTTON::OnPaint( wxPaintEvent& WXUNUSED( aEvent ) ) wxSize size = GetSize(); const int width = size.GetWidth() - m_arrowButtonWidth; +#ifdef __WXMAC__ + auto drawBackground = + [&]( wxRect aRect ) + { + // wxWidgets doesn't have much support for dark mode on OSX; none of the + // system colours return the right values, nor does wxRendererNative draw + // the borders correctly. So we add some empirically chosen hacks here. + + wxColor bg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ); + + if( KIPLATFORM::UI::IsDarkTheme() ) + { + aRect.width += 1; + aRect.height += 1; + bg = bg.ChangeLightness( m_bIsEnable ? 130 : 120 ); + } + else + { + aRect.x += 1; + aRect.y += 1; + aRect.width -= 1; + aRect.height -= 1; + bg = bg.ChangeLightness( m_bIsEnable ? 200 : 160 ); + } + + dc.SetBrush( bg ); + dc.SetPen( bg ); + dc.DrawRectangle( aRect ); + }; +#endif + // Draw first part of button wxRect r1; r1.x = 0; @@ -211,7 +249,13 @@ void SPLIT_BUTTON::OnPaint( wxPaintEvent& WXUNUSED( aEvent ) ) wxRendererNative::Get().DrawPushButton( this, dc, r1, m_stateButton ); - SetForegroundColour( m_bIsEnable ? m_colorNormal : m_colorDisabled ); +#ifdef __WXMAC__ + // wxRendereNative doesn't handle dark mode on OSX. Repaint the background. + drawBackground( r1 ); +#endif + + SetForegroundColour( m_bIsEnable ? wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT ) + : wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); if( m_bitmap.IsOk() ) { @@ -240,6 +284,12 @@ void SPLIT_BUTTON::OnPaint( wxPaintEvent& WXUNUSED( aEvent ) ) r2.height = size.GetHeight(); wxRendererNative::Get().DrawPushButton( this, dc, r2, m_stateMenu ); + +#ifdef __WXMAC__ + // wxRendereNative doesn't handle dark mode on OSX. Repaint the background. + drawBackground( r2 ); +#endif + wxRendererNative::Get().DrawDropArrow( this, dc, r2, m_stateMenu ); } diff --git a/include/widgets/split_button.h b/include/widgets/split_button.h index be8d98f565..564e1f0a5f 100644 --- a/include/widgets/split_button.h +++ b/include/widgets/split_button.h @@ -52,6 +52,7 @@ protected: void OnLeftButtonUp( wxMouseEvent& aEvent ); void OnLeftButtonDown( wxMouseEvent& aEvent ); void OnPaint( wxPaintEvent& WXUNUSED( aEvent ) ); + void onThemeChanged( wxSysColourChangedEvent &aEvent ); bool Enable( bool aEnable = true ) override; @@ -59,8 +60,6 @@ private: int m_stateButton = 0; int m_stateMenu = 0; bool m_bIsEnable = true; - wxColor m_colorNormal; - wxColor m_colorDisabled; const int m_arrowButtonWidth = 20; int m_widthPadding = 20; bool m_bLButtonDown = false;