Add icon theme selection behind advanced config flag

This commit is contained in:
Jon Evans 2021-03-09 17:47:24 -05:00
parent 18037e2f65
commit 405fa183b2
15 changed files with 444 additions and 26 deletions

View File

@ -151,6 +151,8 @@ static const wxChar HotkeysDumper[] = wxT( "HotkeysDumper" );
static const wxChar DrawBoundingBoxes[] = wxT( "DrawBoundingBoxes" ); static const wxChar DrawBoundingBoxes[] = wxT( "DrawBoundingBoxes" );
static const wxChar AllowDarkMode[] = wxT( "AllowDarkMode" );
} // namespace KEYS } // namespace KEYS
@ -252,6 +254,7 @@ ADVANCED_CFG::ADVANCED_CFG()
m_SmallDrillMarkSize = 0.35; m_SmallDrillMarkSize = 0.35;
m_HotkeysDumper = false; m_HotkeysDumper = false;
m_DrawBoundingBoxes = false; m_DrawBoundingBoxes = false;
m_AllowDarkMode = false;
loadFromConfigFile(); loadFromConfigFile();
} }
@ -342,6 +345,9 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DrawBoundingBoxes, configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DrawBoundingBoxes,
&m_DrawBoundingBoxes, false ) ); &m_DrawBoundingBoxes, false ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::AllowDarkMode,
&m_AllowDarkMode, false ) );
wxConfigLoadSetups( &aCfg, configParams ); wxConfigLoadSetups( &aCfg, configParams );
for( PARAM_CFG* param : configParams ) for( PARAM_CFG* param : configParams )

View File

@ -85,7 +85,12 @@ namespace std {
} }
BITMAP_STORE* GetStore() static std::unordered_map<SCALED_BITMAP_ID, wxBitmap> s_ScaledBitmapCache;
static std::mutex s_BitmapCacheMutex;
BITMAP_STORE* GetBitmapStore()
{ {
if( !s_BitmapStore ) if( !s_BitmapStore )
{ {
@ -99,7 +104,7 @@ BITMAP_STORE* GetStore()
wxBitmap KiBitmap( BITMAPS aBitmap ) wxBitmap KiBitmap( BITMAPS aBitmap )
{ {
return GetStore()->GetBitmap( aBitmap ); return GetBitmapStore()->GetBitmap( aBitmap );
} }
@ -143,32 +148,37 @@ static int get_scale_factor( wxWindow* aWindow )
wxBitmap KiScaledBitmap( BITMAPS aBitmap, wxWindow* aWindow, int aHeight ) wxBitmap KiScaledBitmap( BITMAPS aBitmap, wxWindow* aWindow, int aHeight )
{ {
// Bitmap conversions are cached because they can be slow. // Bitmap conversions are cached because they can be slow.
static std::unordered_map<SCALED_BITMAP_ID, wxBitmap> bitmap_cache;
static std::mutex bitmap_cache_mutex;
const int scale = get_scale_factor( aWindow ); const int scale = get_scale_factor( aWindow );
SCALED_BITMAP_ID id = { static_cast<BITMAPS>( aBitmap ), scale }; SCALED_BITMAP_ID id = { static_cast<BITMAPS>( aBitmap ), scale };
std::lock_guard<std::mutex> guard( bitmap_cache_mutex ); std::lock_guard<std::mutex> guard( s_BitmapCacheMutex );
auto it = bitmap_cache.find( id ); auto it = s_ScaledBitmapCache.find( id );
if( it != bitmap_cache.end() ) if( it != s_ScaledBitmapCache.end() )
{ {
return it->second; return it->second;
} }
else else
{ {
wxBitmap bitmap = GetStore()->GetBitmapScaled( aBitmap, scale, aHeight ); wxBitmap bitmap = GetBitmapStore()->GetBitmapScaled( aBitmap, scale, aHeight );
return bitmap_cache.emplace( id, bitmap ).first->second; return s_ScaledBitmapCache.emplace( id, bitmap ).first->second;
} }
} }
void ClearScaledBitmapCache()
{
std::lock_guard<std::mutex> guard( s_BitmapCacheMutex );
s_ScaledBitmapCache.clear();
}
wxBitmap KiScaledBitmap( const wxBitmap& aBitmap, wxWindow* aWindow ) wxBitmap KiScaledBitmap( const wxBitmap& aBitmap, wxWindow* aWindow )
{ {
const int scale = get_scale_factor( aWindow ); const int scale = get_scale_factor( aWindow );
if( scale == 4) if( scale == 4 )
{ {
return wxBitmap( aBitmap ); return wxBitmap( aBitmap );
} }
@ -185,7 +195,7 @@ wxBitmap KiScaledBitmap( const wxBitmap& aBitmap, wxWindow* aWindow )
wxBitmap* KiBitmapNew( BITMAPS aBitmap ) wxBitmap* KiBitmapNew( BITMAPS aBitmap )
{ {
wxBitmap* bitmap = new wxBitmap( GetStore()->GetBitmap( aBitmap ) ); wxBitmap* bitmap = new wxBitmap( GetBitmapStore()->GetBitmap( aBitmap ) );
return bitmap; return bitmap;
} }

View File

@ -23,12 +23,15 @@
#include <wx/mstream.h> #include <wx/mstream.h>
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
#include <advanced_config.h>
#include <asset_archive.h> #include <asset_archive.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <bitmap_store.h> #include <bitmap_store.h>
#include <bitmaps/bitmap_info.h> #include <bitmaps/bitmap_info.h>
#include <kiplatform/ui.h> #include <kiplatform/ui.h>
#include <paths.h> #include <paths.h>
#include <pgm_base.h>
#include <settings/common_settings.h>
/// A question-mark icon shown when we can't find a given bitmap in the archive /// A question-mark icon shown when we can't find a given bitmap in the archive
@ -102,9 +105,9 @@ BITMAP_STORE::BITMAP_STORE()
m_archive = std::make_unique<ASSET_ARCHIVE>( path.GetFullPath() ); m_archive = std::make_unique<ASSET_ARCHIVE>( path.GetFullPath() );
m_theme = KIPLATFORM::UI::IsDarkTheme() ? wxT( "dark" ) : wxT( "light" );
buildBitmapInfoCache(); buildBitmapInfoCache();
ThemeChanged();
} }
@ -158,9 +161,31 @@ wxImage BITMAP_STORE::getImage( BITMAPS aBitmapId, int aHeight )
} }
void BITMAP_STORE::ThemeChanged() bool BITMAP_STORE::ThemeChanged()
{ {
COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
wxString oldTheme = m_theme;
if( ADVANCED_CFG::GetCfg().m_AllowDarkMode )
{
switch( settings->m_Appearance.icon_theme )
{
case ICON_THEME::LIGHT: m_theme = wxT( "light" ); break;
case ICON_THEME::DARK: m_theme = wxT( "dark" ); break;
case ICON_THEME::AUTO:
m_theme = KIPLATFORM::UI::IsDarkTheme() ? wxT( "dark" ) : wxT( "light" );
break;
}
}
else
{
m_theme = wxT( "light" );
}
m_bitmapNameCache.clear(); m_bitmapNameCache.clear();
return !oldTheme.IsSameAs( m_theme );
} }

View File

@ -23,6 +23,7 @@
#include <dialogs/panel_common_settings.h> #include <dialogs/panel_common_settings.h>
#include <advanced_config.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <dialog_shim.h> #include <dialog_shim.h>
#include <gal/dpi_scaling.h> #include <gal/dpi_scaling.h>
@ -71,6 +72,14 @@ PANEL_COMMON_SETTINGS::PANEL_COMMON_SETTINGS( DIALOG_SHIM* aDialog, wxWindow* aP
m_antialiasingFallbackLabel->Show( false ); m_antialiasingFallbackLabel->Show( false );
#endif #endif
if( !ADVANCED_CFG::GetCfg().m_AllowDarkMode )
{
m_rbIconThemeLight->Hide();
m_rbIconThemeDark->Hide();
m_rbIconThemeAuto->Hide();
m_stIconTheme->Hide();
}
m_textEditorBtn->SetBitmap( KiBitmap( BITMAPS::small_folder ) ); m_textEditorBtn->SetBitmap( KiBitmap( BITMAPS::small_folder ) );
m_pdfViewerBtn->SetBitmap( KiBitmap( BITMAPS::small_folder ) ); m_pdfViewerBtn->SetBitmap( KiBitmap( BITMAPS::small_folder ) );
@ -123,6 +132,13 @@ bool PANEL_COMMON_SETTINGS::TransferDataFromWindow()
dpi.SetDpiConfig( m_canvasScaleAuto->GetValue(), m_canvasScaleCtrl->GetValue() ); dpi.SetDpiConfig( m_canvasScaleAuto->GetValue(), m_canvasScaleCtrl->GetValue() );
} }
if( m_rbIconThemeLight->GetValue() )
commonSettings->m_Appearance.icon_theme = ICON_THEME::LIGHT;
else if( m_rbIconThemeDark->GetValue() )
commonSettings->m_Appearance.icon_theme = ICON_THEME::DARK;
else if( m_rbIconThemeAuto->GetValue() )
commonSettings->m_Appearance.icon_theme = ICON_THEME::AUTO;
commonSettings->m_Appearance.use_icons_in_menus = m_checkBoxIconsInMenus->GetValue(); commonSettings->m_Appearance.use_icons_in_menus = m_checkBoxIconsInMenus->GetValue();
commonSettings->m_Input.immediate_actions = !m_NonImmediateActions->GetValue(); commonSettings->m_Input.immediate_actions = !m_NonImmediateActions->GetValue();
@ -199,6 +215,13 @@ void PANEL_COMMON_SETTINGS::applySettingsToPanel( COMMON_SETTINGS& aSettings )
m_canvasScaleAuto->SetValue( dpi.GetCanvasIsAutoScaled() ); m_canvasScaleAuto->SetValue( dpi.GetCanvasIsAutoScaled() );
} }
switch( aSettings.m_Appearance.icon_theme )
{
case ICON_THEME::LIGHT: m_rbIconThemeLight->SetValue( true ); break;
case ICON_THEME::DARK: m_rbIconThemeDark->SetValue( true ); break;
case ICON_THEME::AUTO: m_rbIconThemeAuto->SetValue( true ); break;
}
m_checkBoxIconsInMenus->SetValue( aSettings.m_Appearance.use_icons_in_menus ); m_checkBoxIconsInMenus->SetValue( aSettings.m_Appearance.use_icons_in_menus );
m_warpMouseOnMove->SetValue( aSettings.m_Input.warp_mouse_on_move ); m_warpMouseOnMove->SetValue( aSettings.m_Input.warp_mouse_on_move );

View File

@ -181,7 +181,27 @@ PANEL_COMMON_SETTINGS_BASE::PANEL_COMMON_SETTINGS_BASE( wxWindow* parent, wxWind
gbSizer4->Add( m_canvasScaleAuto, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 15 ); gbSizer4->Add( m_canvasScaleAuto, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 15 );
m_checkBoxIconsInMenus = new wxCheckBox( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Show icons in menus"), wxDefaultPosition, wxDefaultSize, 0 ); m_checkBoxIconsInMenus = new wxCheckBox( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Show icons in menus"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer4->Add( m_checkBoxIconsInMenus, wxGBPosition( 2, 0 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT, 5 ); gbSizer4->Add( m_checkBoxIconsInMenus, wxGBPosition( 2, 0 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT, 5 );
m_stIconTheme = new wxStaticText( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Icon theme:"), wxDefaultPosition, wxDefaultSize, 0 );
m_stIconTheme->Wrap( -1 );
gbSizer4->Add( m_stIconTheme, wxGBPosition( 3, 0 ), wxGBSpan( 1, 3 ), wxLEFT|wxRIGHT, 5 );
m_rbIconThemeLight = new wxRadioButton( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Light"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
m_rbIconThemeLight->SetToolTip( _("Use icons designed for light window backgrounds") );
gbSizer4->Add( m_rbIconThemeLight, wxGBPosition( 4, 0 ), wxGBSpan( 1, 1 ), wxLEFT|wxRIGHT, 5 );
m_rbIconThemeDark = new wxRadioButton( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Dark"), wxDefaultPosition, wxDefaultSize, 0 );
m_rbIconThemeDark->SetToolTip( _("Use icons designed for dark window backgrounds") );
gbSizer4->Add( m_rbIconThemeDark, wxGBPosition( 4, 1 ), wxGBSpan( 1, 1 ), wxLEFT|wxRIGHT, 5 );
m_rbIconThemeAuto = new wxRadioButton( sbSizerIconsOpts->GetStaticBox(), wxID_ANY, _("Automatic"), wxDefaultPosition, wxDefaultSize, 0 );
m_rbIconThemeAuto->SetValue( true );
m_rbIconThemeAuto->SetToolTip( _("Automatically choose light or dark icons based on the system color theme") );
gbSizer4->Add( m_rbIconThemeAuto, wxGBPosition( 4, 2 ), wxGBSpan( 1, 1 ), wxLEFT|wxRIGHT, 5 );
gbSizer4->AddGrowableCol( 1 ); gbSizer4->AddGrowableCol( 1 );

View File

@ -1824,7 +1824,7 @@
</object> </object>
<object class="gbsizeritem" expanded="1"> <object class="gbsizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="colspan">3</property> <property name="colspan">2</property>
<property name="column">0</property> <property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT</property>
<property name="row">2</property> <property name="row">2</property>
@ -1889,6 +1889,271 @@
<property name="window_style"></property> <property name="window_style"></property>
</object> </object>
</object> </object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">3</property>
<property name="column">0</property>
<property name="flag">wxLEFT|wxRIGHT</property>
<property name="row">3</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Icon theme:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_stIconTheme</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxLEFT|wxRIGHT</property>
<property name="row">4</property>
<property name="rowspan">1</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Light</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_rbIconThemeLight</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxRB_GROUP</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Use icons designed for light window backgrounds</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxLEFT|wxRIGHT</property>
<property name="row">4</property>
<property name="rowspan">1</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Dark</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_rbIconThemeDark</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Use icons designed for dark window backgrounds</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">2</property>
<property name="flag">wxLEFT|wxRIGHT</property>
<property name="row">4</property>
<property name="rowspan">1</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Automatic</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_rbIconThemeAuto</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Automatically choose light or dark icons based on the system color theme</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">1</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
</object> </object>
</object> </object>
</object> </object>

View File

@ -67,6 +67,10 @@ class PANEL_COMMON_SETTINGS_BASE : public RESETTABLE_PANEL
wxSpinCtrlDouble* m_canvasScaleCtrl; wxSpinCtrlDouble* m_canvasScaleCtrl;
wxCheckBox* m_canvasScaleAuto; wxCheckBox* m_canvasScaleAuto;
wxCheckBox* m_checkBoxIconsInMenus; wxCheckBox* m_checkBoxIconsInMenus;
wxStaticText* m_stIconTheme;
wxRadioButton* m_rbIconThemeLight;
wxRadioButton* m_rbIconThemeDark;
wxRadioButton* m_rbIconThemeAuto;
wxCheckBox* m_warpMouseOnMove; wxCheckBox* m_warpMouseOnMove;
wxCheckBox* m_NonImmediateActions; wxCheckBox* m_NonImmediateActions;
wxCheckBox* m_cbBackupEnabled; wxCheckBox* m_cbBackupEnabled;

View File

@ -24,6 +24,7 @@
*/ */
#include <bitmaps.h> #include <bitmaps.h>
#include <bitmap_store.h>
#include <dialog_shim.h> #include <dialog_shim.h>
#include <dialogs/panel_common_settings.h> #include <dialogs/panel_common_settings.h>
#include <dialogs/panel_mouse_settings.h> #include <dialogs/panel_mouse_settings.h>
@ -41,6 +42,7 @@
#include <project/project_local_settings.h> #include <project/project_local_settings.h>
#include <tool/action_manager.h> #include <tool/action_manager.h>
#include <tool/action_menu.h> #include <tool/action_menu.h>
#include <tool/action_toolbar.h>
#include <tool/actions.h> #include <tool/actions.h>
#include <tool/common_control.h> #include <tool/common_control.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
@ -53,6 +55,7 @@
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
#include <wx/string.h> #include <wx/string.h>
#include <kiplatform/app.h> #include <kiplatform/app.h>
#include <kiplatform/ui.h>
#include <functional> #include <functional>
@ -446,6 +449,19 @@ void EDA_BASE_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVars
m_fileHistory->SetMaxFiles( (unsigned) std::max( 0, historySize ) ); m_fileHistory->SetMaxFiles( (unsigned) std::max( 0, historySize ) );
} }
if( GetBitmapStore()->ThemeChanged() )
{
ClearScaledBitmapCache();
wxAuiPaneInfoArray panes = m_auimgr.GetAllPanes();
for( size_t i = 0; i < panes.GetCount(); ++i )
{
if( ACTION_TOOLBAR* toolbar = dynamic_cast<ACTION_TOOLBAR*>( panes[i].window ) )
toolbar->RefreshBitmaps();
}
}
if( GetMenuBar() ) if( GetMenuBar() )
{ {
// For icons in menus, icon scaling & hotkeys // For icons in menus, icon scaling & hotkeys

View File

@ -68,6 +68,9 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
m_params.emplace_back( new PARAM<int>( "appearance.icon_scale", m_params.emplace_back( new PARAM<int>( "appearance.icon_scale",
&m_Appearance.icon_scale, 0 ) ); &m_Appearance.icon_scale, 0 ) );
m_params.emplace_back( new PARAM_ENUM<ICON_THEME>( "appearance.icon_theme",
&m_Appearance.icon_theme, ICON_THEME::AUTO, ICON_THEME::LIGHT, ICON_THEME::AUTO ) );
m_params.emplace_back( new PARAM<bool>( "appearance.use_icons_in_menus", m_params.emplace_back( new PARAM<bool>( "appearance.use_icons_in_menus",
&m_Appearance.use_icons_in_menus, defaultUseIconsInMenus ) ); &m_Appearance.use_icons_in_menus, defaultUseIconsInMenus ) );

View File

@ -23,6 +23,7 @@
*/ */
#include <algorithm> #include <algorithm>
#include <advanced_config.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <eda_draw_frame.h> #include <eda_draw_frame.h>
#include <functional> #include <functional>
@ -170,14 +171,13 @@ ACTION_TOOLBAR::ACTION_TOOLBAR( EDA_BASE_FRAME* parent, wxWindowID id, const wxP
{ {
m_paletteTimer = new wxTimer( this ); m_paletteTimer = new wxTimer( this );
// Enable this once dark icon switching is available. Without dark theme icons, this just
// makes things (even) harder to see
#ifdef NOTYET
#if !wxCHECK_VERSION( 3, 1, 0 ) #if !wxCHECK_VERSION( 3, 1, 0 )
// Custom art provider makes dark mode work on wx < 3.1 // Custom art provider makes dark mode work on wx < 3.1
WX_AUI_TOOLBAR_ART* newArt = new WX_AUI_TOOLBAR_ART(); if( ADVANCED_CFG::GetCfg().m_AllowDarkMode )
SetArtProvider( newArt ); {
#endif WX_AUI_TOOLBAR_ART* newArt = new WX_AUI_TOOLBAR_ART();
SetArtProvider( newArt );
}
#endif #endif
Connect( wxEVT_COMMAND_TOOL_CLICKED, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onToolEvent ), Connect( wxEVT_COMMAND_TOOL_CLICKED, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onToolEvent ),
@ -759,3 +759,19 @@ bool ACTION_TOOLBAR::KiRealize()
Refresh( false ); Refresh( false );
return retval; return retval;
} }
void ACTION_TOOLBAR::RefreshBitmaps()
{
for( const std::pair<int, const TOOL_ACTION*> pair : m_toolActions )
{
wxAuiToolBarItem* tool = FindTool( pair.first );
wxBitmap bmp = KiScaledBitmap( pair.second->GetIcon(), GetParent() );
tool->SetBitmap( bmp );
tool->SetDisabledBitmap( bmp.ConvertToDisabled() );
}
Refresh();
}

View File

@ -160,6 +160,11 @@ public:
*/ */
bool m_DrawBoundingBoxes; bool m_DrawBoundingBoxes;
/**
* Enable detection of dark mode and automatic switch to dark-mode icon theme
*/
bool m_AllowDarkMode;
private: private:
ADVANCED_CFG(); ADVANCED_CFG();

View File

@ -26,6 +26,7 @@
#include <bitmaps/bitmap_info.h> #include <bitmaps/bitmap_info.h>
class ASSET_ARCHIVE; class ASSET_ARCHIVE;
class wxImage;
namespace std namespace std
@ -72,8 +73,11 @@ public:
/** /**
* Notifies the store that the icon theme has been changed by the user, so caches must be * Notifies the store that the icon theme has been changed by the user, so caches must be
* invalidated. * invalidated.
* @return true if the new theme is different than what was previously in use
*/ */
void ThemeChanged(); bool ThemeChanged();
bool IsDarkTheme() const { return m_theme == wxT( "dark" ); }
private: private:

View File

@ -33,11 +33,14 @@ class wxBitmap; // only to define wxBitmap
class EDA_DRAW_FRAME; class EDA_DRAW_FRAME;
class wxWindow; class wxWindow;
struct BITMAP_OPAQUE; struct BITMAP_OPAQUE;
class BITMAP_STORE;
enum class BITMAPS : unsigned int; enum class BITMAPS : unsigned int;
#include <wx/gdicmn.h> // wxBitmapType #include <wx/gdicmn.h> // wxBitmapType
BITMAP_STORE* GetBitmapStore();
/** /**
* Construct a wxBitmap from an image identifier * Construct a wxBitmap from an image identifier
* Returns the image from the active theme if the image has multiple theme variants. * Returns the image from the active theme if the image has multiple theme variants.
@ -50,6 +53,11 @@ wxBitmap KiBitmap( BITMAPS aBitmap );
*/ */
wxBitmap KiBitmap( const BITMAP_OPAQUE* aBitmap ); wxBitmap KiBitmap( const BITMAP_OPAQUE* aBitmap );
/**
* Wipes out the scaled bitmap cache so that the icon theme can be changed.
* TODO: move scaling system into BITMAP_STORE so this global doesn't need to exist
*/
void ClearScaledBitmapCache();
/** /**
* Construct a wxBitmap from a memory record, scaling it if device DPI demands it. * Construct a wxBitmap from a memory record, scaling it if device DPI demands it.

View File

@ -35,15 +35,23 @@ enum class MOUSE_DRAG_ACTION
NONE NONE
}; };
enum class ICON_THEME
{
LIGHT,
DARK,
AUTO
};
class COMMON_SETTINGS : public JSON_SETTINGS class COMMON_SETTINGS : public JSON_SETTINGS
{ {
public: public:
struct APPEARANCE struct APPEARANCE
{ {
double canvas_scale; double canvas_scale;
int icon_scale; int icon_scale;
bool use_icons_in_menus; ICON_THEME icon_theme;
bool use_icons_in_menus;
}; };
struct AUTO_BACKUP struct AUTO_BACKUP

View File

@ -284,6 +284,11 @@ public:
*/ */
bool KiRealize(); bool KiRealize();
/**
* Reload all the bitmaps for the tools (e.g. when switching icon themes)
*/
void RefreshBitmaps();
static constexpr bool TOGGLE = true; static constexpr bool TOGGLE = true;
static constexpr bool CANCEL = true; static constexpr bool CANCEL = true;