From 7a993c0211adfde76cb5d8ebec908eafdf13e251 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 13 Sep 2021 23:30:22 +0100 Subject: [PATCH] Add support mode for dark mode to SCINTILLA_TRICKS. Also removes the return value from the BITMAP_STORE's themeChanged method as it will provide the wrong answer for the second frame it's called on. Also hooked up ACTION_TOOLBAR, the app launcher, and the project tree to the wx event for system color changes so they change on the fly. Fixes https://gitlab.com/kicad/code/kicad/issues/6026 --- common/bitmap_store.cpp | 10 ++- common/eda_base_frame.cpp | 10 ++- common/scintilla_tricks.cpp | 85 ++++++++++++++++++-------- common/tool/action_toolbar.cpp | 13 ++++ include/bitmap_store.h | 3 +- include/scintilla_tricks.h | 3 + include/tool/action_toolbar.h | 2 + kicad/dialogs/panel_kicad_launcher.cpp | 15 +++++ kicad/dialogs/panel_kicad_launcher.h | 3 +- kicad/project_tree.cpp | 23 ++++--- kicad/project_tree.h | 2 + kicad/project_tree_pane.cpp | 16 +++++ kicad/project_tree_pane.h | 2 + libs/kiplatform/osx/ui.mm | 16 ++++- 14 files changed, 153 insertions(+), 50 deletions(-) diff --git a/common/bitmap_store.cpp b/common/bitmap_store.cpp index 52b02f221c..65b48fc26d 100644 --- a/common/bitmap_store.cpp +++ b/common/bitmap_store.cpp @@ -164,11 +164,10 @@ wxImage BITMAP_STORE::getImage( BITMAPS aBitmapId, int aHeight ) } -bool BITMAP_STORE::ThemeChanged() +void BITMAP_STORE::ThemeChanged() { COMMON_SETTINGS* settings = Pgm().GetCommonSettings(); - - wxString oldTheme = m_theme; + wxString oldTheme = m_theme; if( settings ) { @@ -186,9 +185,8 @@ bool BITMAP_STORE::ThemeChanged() m_theme = wxT( "light" ); } - m_bitmapNameCache.clear(); - - return !oldTheme.IsSameAs( m_theme ); + if( !oldTheme.IsSameAs( m_theme ) ) + m_bitmapNameCache.clear(); } diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp index 9dc994e73d..5943f7271e 100644 --- a/common/eda_base_frame.cpp +++ b/common/eda_base_frame.cpp @@ -481,10 +481,8 @@ void EDA_BASE_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVars m_fileHistory->SetMaxFiles( (unsigned) std::max( 0, historySize ) ); } - if( GetBitmapStore()->ThemeChanged() ) - { - ThemeChanged(); - } + GetBitmapStore()->ThemeChanged(); + ThemeChanged(); if( GetMenuBar() ) { @@ -1236,8 +1234,8 @@ wxSize EDA_BASE_FRAME::GetWindowSize() void EDA_BASE_FRAME::HandleSystemColorChange() { // Update the icon theme when the system theme changes and update the toolbars - if( GetBitmapStore()->ThemeChanged() ) - ThemeChanged(); + GetBitmapStore()->ThemeChanged(); + ThemeChanged(); // This isn't handled by ThemeChanged() if( GetMenuBar() ) diff --git a/common/scintilla_tricks.cpp b/common/scintilla_tricks.cpp index 6c6228681f..de0ae89bee 100644 --- a/common/scintilla_tricks.cpp +++ b/common/scintilla_tricks.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2020-2021 KiCad Developers, see change_log.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 @@ -46,32 +46,7 @@ SCINTILLA_TRICKS::SCINTILLA_TRICKS( wxStyledTextCtrl* aScintilla, const wxString m_te->SetScrollWidth( 1 ); m_te->SetScrollWidthTracking( true ); - if( !m_singleLine ) - { - // Set a monospace font with a tab width of 4. This is the closest we can get to having - // Scintilla mimic the stroke font's tab positioning. - wxFont fixedFont = KIUI::GetMonospacedUIFont(); - - for( size_t i = 0; i < wxSTC_STYLE_MAX; ++i ) - m_te->StyleSetFont( i, fixedFont ); - - m_te->StyleClearAll(); // Addresses a bug in wx3.0 where styles are not correctly set - m_te->SetTabWidth( 4 ); - } - - // Set up the brace highlighting - wxColour highlight = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ); - wxColour highlightText = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); - - unsigned char r = highlight.Red(); - unsigned char g = highlight.Green(); - unsigned char b = highlight.Blue(); - wxColour::MakeGrey( &r, &g, &b ); - highlight.Set( r, g, b ); - - m_te->StyleSetForeground( wxSTC_STYLE_BRACELIGHT, highlightText ); - m_te->StyleSetBackground( wxSTC_STYLE_BRACELIGHT, highlight ); - m_te->StyleSetForeground( wxSTC_STYLE_BRACEBAD, *wxRED ); + setupStyles(); // Set up autocomplete m_te->AutoCompSetIgnoreCase( true ); @@ -83,6 +58,57 @@ SCINTILLA_TRICKS::SCINTILLA_TRICKS( wxStyledTextCtrl* aScintilla, const wxString // Dispatch command-keys in Scintilla control. m_te->Bind( wxEVT_CHAR_HOOK, &SCINTILLA_TRICKS::onCharHook, this ); + + m_te->Bind( wxEVT_SYS_COLOUR_CHANGED, + wxSysColourChangedEventHandler( SCINTILLA_TRICKS::onThemeChanged ), this ); +} + + +void SCINTILLA_TRICKS::onThemeChanged( wxSysColourChangedEvent &aEvent ) +{ + setupStyles(); + + aEvent.Skip(); +} + + +void SCINTILLA_TRICKS::setupStyles() +{ + wxTextCtrl dummy( m_te->GetParent(), wxID_ANY ); + wxColour foreground = dummy.GetForegroundColour(); + wxColour background = dummy.GetBackgroundColour(); + wxColour highlight = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ); + wxColour highlightText = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); + + m_te->StyleSetForeground( wxSTC_STYLE_DEFAULT, foreground ); + m_te->StyleSetBackground( wxSTC_STYLE_DEFAULT, background ); + m_te->StyleClearAll(); + + m_te->SetSelForeground( true, highlightText ); + m_te->SetSelBackground( true, highlight ); + + if( !m_singleLine ) + { + // Set a monospace font with a tab width of 4. This is the closest we can get to having + // Scintilla mimic the stroke font's tab positioning. + wxFont fixedFont = KIUI::GetMonospacedUIFont(); + + for( size_t i = 0; i < wxSTC_STYLE_MAX; ++i ) + m_te->StyleSetFont( i, fixedFont ); + + m_te->SetTabWidth( 4 ); + } + + // Set up the brace highlighting + unsigned char r = highlight.Red(); + unsigned char g = highlight.Green(); + unsigned char b = highlight.Blue(); + wxColour::MakeGrey( &r, &g, &b ); + highlight.Set( r, g, b ); + + m_te->StyleSetForeground( wxSTC_STYLE_BRACELIGHT, highlightText ); + m_te->StyleSetBackground( wxSTC_STYLE_BRACELIGHT, highlight ); + m_te->StyleSetForeground( wxSTC_STYLE_BRACEBAD, *wxRED ); } @@ -258,6 +284,11 @@ void SCINTILLA_TRICKS::onCharHook( wxKeyEvent& aEvent ) m_te->HomeWrap(); } #endif + else if( aEvent.GetKeyCode() == WXK_SPECIAL20 ) + { + // Proxy for a wxSysColourChangedEvent + setupStyles(); + } else { aEvent.Skip(); diff --git a/common/tool/action_toolbar.cpp b/common/tool/action_toolbar.cpp index 97b4bb775a..26c89eb162 100644 --- a/common/tool/action_toolbar.cpp +++ b/common/tool/action_toolbar.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -207,6 +208,9 @@ ACTION_TOOLBAR::ACTION_TOOLBAR( EDA_BASE_FRAME* parent, wxWindowID id, const wxP Connect( wxEVT_LEFT_UP, wxMouseEventHandler( ACTION_TOOLBAR::onMouseClick ), nullptr, this ); Connect( m_paletteTimer->GetId(), wxEVT_TIMER, wxTimerEventHandler( ACTION_TOOLBAR::onTimerDone ), nullptr, this ); + + Bind( wxEVT_SYS_COLOUR_CHANGED, + wxSysColourChangedEventHandler( ACTION_TOOLBAR::onThemeChanged ), this ); } @@ -822,6 +826,15 @@ bool ACTION_TOOLBAR::KiRealize() } +void ACTION_TOOLBAR::onThemeChanged( wxSysColourChangedEvent &aEvent ) +{ + GetBitmapStore()->ThemeChanged(); + RefreshBitmaps(); + + aEvent.Skip(); +} + + void ACTION_TOOLBAR::RefreshBitmaps() { for( const std::pair pair : m_toolActions ) diff --git a/include/bitmap_store.h b/include/bitmap_store.h index d1862a09fc..0d11546785 100644 --- a/include/bitmap_store.h +++ b/include/bitmap_store.h @@ -73,9 +73,8 @@ public: /** * Notifies the store that the icon theme has been changed by the user, so caches must be * invalidated. - * @return true if the new theme is different than what was previously in use */ - bool ThemeChanged(); + void ThemeChanged(); bool IsDarkTheme() const { return m_theme == wxT( "dark" ); } diff --git a/include/scintilla_tricks.h b/include/scintilla_tricks.h index edc2cacdae..d0de0ec9b6 100644 --- a/include/scintilla_tricks.h +++ b/include/scintilla_tricks.h @@ -41,10 +41,13 @@ public: void DoAutocomplete( const wxString& aPartial, const wxArrayString& aTokens ); protected: + void setupStyles(); + int firstNonWhitespace( int aLine, int* aWhitespaceCount = nullptr ); void onCharHook( wxKeyEvent& aEvent ); void onScintillaUpdateUI( wxStyledTextEvent& aEvent ); + void onThemeChanged( wxSysColourChangedEvent &aEvent ); protected: wxStyledTextCtrl* m_te; diff --git a/include/tool/action_toolbar.h b/include/tool/action_toolbar.h index 91c9830466..1dba363c72 100644 --- a/include/tool/action_toolbar.h +++ b/include/tool/action_toolbar.h @@ -330,6 +330,8 @@ protected: ///< Handle the palette timer triggering void onTimerDone( wxTimerEvent& aEvent ); + void onThemeChanged( wxSysColourChangedEvent &aEvent ); + ///< Render the triangle in the lower-right corner that represents that an action palette ///< is available for an item void OnCustomRender( wxDC& aDc, const wxAuiToolBarItem& aItem, const wxRect& aRect ) override; diff --git a/kicad/dialogs/panel_kicad_launcher.cpp b/kicad/dialogs/panel_kicad_launcher.cpp index d215d81c46..848b6e6e26 100644 --- a/kicad/dialogs/panel_kicad_launcher.cpp +++ b/kicad/dialogs/panel_kicad_launcher.cpp @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -32,6 +33,9 @@ PANEL_KICAD_LAUNCHER::PANEL_KICAD_LAUNCHER( wxWindow* aParent ) : { m_toolManager = static_cast( aParent )->GetToolManager(); CreateLaunchers(); + + Bind( wxEVT_SYS_COLOUR_CHANGED, + wxSysColourChangedEventHandler( PANEL_KICAD_LAUNCHER::onThemeChanged ), this ); } @@ -144,3 +148,14 @@ void PANEL_KICAD_LAUNCHER::CreateLaunchers() Layout(); } + + +void PANEL_KICAD_LAUNCHER::onThemeChanged( wxSysColourChangedEvent &aEvent ) +{ + GetBitmapStore()->ThemeChanged(); + CreateLaunchers(); + + aEvent.Skip(); +} + + diff --git a/kicad/dialogs/panel_kicad_launcher.h b/kicad/dialogs/panel_kicad_launcher.h index 71d74ef413..e72647072c 100644 --- a/kicad/dialogs/panel_kicad_launcher.h +++ b/kicad/dialogs/panel_kicad_launcher.h @@ -34,9 +34,10 @@ public: void CreateLaunchers(); private: + void onThemeChanged( wxSysColourChangedEvent &aEvent ); +private: TOOL_MANAGER* m_toolManager; - }; diff --git a/kicad/project_tree.cpp b/kicad/project_tree.cpp index 4348e7c866..e8f499039e 100644 --- a/kicad/project_tree.cpp +++ b/kicad/project_tree.cpp @@ -44,13 +44,28 @@ IMPLEMENT_ABSTRACT_CLASS( PROJECT_TREE, wxTreeCtrl ) PROJECT_TREE::PROJECT_TREE( PROJECT_TREE_PANE* parent ) : wxTreeCtrl( parent, ID_PROJECT_TREE, wxDefaultPosition, wxDefaultSize, PLATFORM_STYLE | wxTR_HAS_BUTTONS | wxTR_MULTIPLE, wxDefaultValidator, - wxT( "EDATreeCtrl" ) ) + wxT( "EDATreeCtrl" ) ), + m_imageList( nullptr ) { m_projectTreePane = parent; // Make sure the GUI font scales properly on GTK SetFont( KIUI::GetControlFont( this ) ); + LoadIcons(); +} + + +PROJECT_TREE::~PROJECT_TREE() +{ + delete m_imageList; +} + + +void PROJECT_TREE::LoadIcons() +{ + delete m_imageList; + // icons size is not know (depending on they are built) // so get it: wxSize iconsize; @@ -93,12 +108,6 @@ PROJECT_TREE::PROJECT_TREE( PROJECT_TREE_PANE* parent ) : } -PROJECT_TREE::~PROJECT_TREE() -{ - delete m_imageList; -} - - int PROJECT_TREE::OnCompareItems( const wxTreeItemId& item1, const wxTreeItemId& item2 ) { PROJECT_TREE_ITEM* myitem1 = (PROJECT_TREE_ITEM*) GetItemData( item1 ); diff --git a/kicad/project_tree.h b/kicad/project_tree.h index 39a5f0a6fc..67864a407f 100644 --- a/kicad/project_tree.h +++ b/kicad/project_tree.h @@ -49,6 +49,8 @@ public: PROJECT_TREE( PROJECT_TREE_PANE* parent ); ~PROJECT_TREE(); + void LoadIcons(); + private: /* overridden sort function */ int OnCompareItems( const wxTreeItemId& item1, const wxTreeItemId& item2 ) override; diff --git a/kicad/project_tree_pane.cpp b/kicad/project_tree_pane.cpp index 51caae3f77..1cce02d9f0 100644 --- a/kicad/project_tree_pane.cpp +++ b/kicad/project_tree_pane.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -146,6 +147,9 @@ PROJECT_TREE_PANE::PROJECT_TREE_PANE( KICAD_MANAGER_FRAME* parent ) : Connect( wxEVT_FSWATCHER, wxFileSystemWatcherEventHandler( PROJECT_TREE_PANE::onFileSystemEvent ) ); + Bind( wxEVT_SYS_COLOUR_CHANGED, + wxSysColourChangedEventHandler( PROJECT_TREE_PANE::onThemeChanged ), this ); + /* * Filtering is now inverted: the filters are actually used to _enable_ support * for a given file type. @@ -1297,7 +1301,19 @@ void PROJECT_TREE_PANE::EmptyTreePrj() } +void PROJECT_TREE_PANE::onThemeChanged( wxSysColourChangedEvent &aEvent ) +{ + GetBitmapStore()->ThemeChanged(); + m_TreeProject->LoadIcons(); + m_TreeProject->Refresh(); + + aEvent.Skip(); +} + + void KICAD_MANAGER_FRAME::OnChangeWatchedPaths( wxCommandEvent& aEvent ) { m_leftWin->FileWatcherReset(); } + + diff --git a/kicad/project_tree_pane.h b/kicad/project_tree_pane.h index 519b1aeb5e..4ecb51fe17 100644 --- a/kicad/project_tree_pane.h +++ b/kicad/project_tree_pane.h @@ -189,6 +189,8 @@ private: */ void onFileSystemEvent( wxFileSystemWatcherEvent& event ); + void onThemeChanged( wxSysColourChangedEvent &aEvent ); + public: KICAD_MANAGER_FRAME* m_Parent; PROJECT_TREE* m_TreeProject; diff --git a/libs/kiplatform/osx/ui.mm b/libs/kiplatform/osx/ui.mm index 22a66ac720..ff5f06884e 100644 --- a/libs/kiplatform/osx/ui.mm +++ b/libs/kiplatform/osx/ui.mm @@ -25,13 +25,27 @@ #include #include #include -#include +#include bool KIPLATFORM::UI::IsDarkTheme() { + // Disabled for now because it appears that the wxWidgets event goes out before the + // NSAppearance name has been updated +#ifdef NOTYET + // It appears the wxWidgets event goes out before the NSAppearance name has been updated NSString *appearanceName = [[NSAppearance currentAppearance] name]; return !![appearanceName containsString:@"Dark"]; +#else + wxColour bg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ); + + // Weighted W3C formula + double brightness = ( bg.Red() / 255.0 ) * 0.299 + + ( bg.Green() / 255.0 ) * 0.587 + + ( bg.Blue() / 255.0 ) * 0.117; + + return brightness < 0.5; +#endif }