From 3e255a2d48d3af2792f0e843151abf13d16e0ad5 Mon Sep 17 00:00:00 2001 From: Alex Shvartzkop Date: Wed, 7 Jan 2026 15:31:23 +0500 Subject: [PATCH] More improvements in toolbar icon handling. Also makes WX_AUI_TOOLBAR_ART more in-line with wx implementation. --- common/bitmap.cpp | 10 ++++- common/bitmap_store.cpp | 47 ++++++++++++++++++- common/tool/action_toolbar.cpp | 60 ++++++++++++++++--------- common/widgets/wx_aui_art_providers.cpp | 27 +++-------- include/bitmap_store.h | 13 +++++- include/bitmaps/bitmap_types.h | 4 +- 6 files changed, 116 insertions(+), 45 deletions(-) diff --git a/common/bitmap.cpp b/common/bitmap.cpp index 39836d808d..d2dcd48333 100644 --- a/common/bitmap.cpp +++ b/common/bitmap.cpp @@ -119,9 +119,15 @@ wxBitmapBundle KiBitmapBundleDef( BITMAPS aBitmap, int aDefHeight ) } -wxBitmapBundle KiDisabledBitmapBundle( BITMAPS aBitmap ) +wxBitmapBundle KiDisabledBitmapBundle( BITMAPS aBitmap, int aMinHeight ) { - return GetBitmapStore()->GetDisabledBitmapBundle( aBitmap ); + return GetBitmapStore()->GetDisabledBitmapBundle( aBitmap, aMinHeight ); +} + + +KICOMMON_API wxBitmapBundle KiDisabledBitmapBundleDef( BITMAPS aBitmap, int aDefHeight ) +{ + return GetBitmapStore()->GetDisabledBitmapBundleDef( aBitmap, aDefHeight ); } diff --git a/common/bitmap_store.cpp b/common/bitmap_store.cpp index a9e35f800e..ab4c52d061 100644 --- a/common/bitmap_store.cpp +++ b/common/bitmap_store.cpp @@ -212,7 +212,7 @@ wxBitmapBundle BITMAP_STORE::GetBitmapBundleDef( BITMAPS aBitmapId, int aDefHeig } -wxBitmapBundle BITMAP_STORE::GetDisabledBitmapBundle( BITMAPS aBitmapId ) +wxBitmapBundle BITMAP_STORE::GetDisabledBitmapBundle( BITMAPS aBitmapId, int aMinHeight ) { wxVector bmps; @@ -221,6 +221,9 @@ wxBitmapBundle BITMAP_STORE::GetDisabledBitmapBundle( BITMAPS aBitmapId ) if( info.theme != m_theme ) continue; + if( aMinHeight > 0 && info.height < aMinHeight ) + continue; + wxBitmap bmp( getImage( info.id, info.height ) .ConvertToDisabled( KIPLATFORM::UI::IsDarkTheme() ? 70 : 255 ) ); bmps.push_back( bmp ); @@ -230,6 +233,48 @@ wxBitmapBundle BITMAP_STORE::GetDisabledBitmapBundle( BITMAPS aBitmapId ) } +wxBitmapBundle BITMAP_STORE::GetDisabledBitmapBundleDef( BITMAPS aBitmapId, int aDefHeight ) +{ + wxVector bmps; + std::set sizes; + int largestHeight = 0; + wxImage largestImage; + + for( const BITMAP_INFO& info : m_bitmapInfoCache[aBitmapId] ) + { + if( info.theme != m_theme ) + continue; + + wxImage img = getImage( info.id, info.height ).ConvertToDisabled( KIPLATFORM::UI::IsDarkTheme() ? 70 : 255 ); + + if( info.height > largestHeight ) + { + largestHeight = info.height; + largestImage = img; + } + + if( info.height >= aDefHeight ) + { + sizes.emplace( info.height ); + bmps.push_back( wxBitmap( img ) ); + } + } + + if( !sizes.contains( aDefHeight ) ) + bmps.push_back( wxBitmap( resampleImage( largestImage, aDefHeight, aDefHeight ) ) ); + +#ifdef __WXOSX__ + // OSX doesn't align text in trees properly when 2x bitmaps are not provided, apparently + int size2x = aDefHeight * 2; + + if( !sizes.contains( size2x ) ) + bmps.push_back( wxBitmap( resampleImage( largestImage, size2x, size2x ) ) ); +#endif + + return wxBitmapBundle::FromBitmaps( bmps ); +} + + wxBitmap BITMAP_STORE::GetBitmapScaled( BITMAPS aBitmapId, int aScaleFactor, int aHeight ) { wxImage image = getImage( aBitmapId, aHeight ); diff --git a/common/tool/action_toolbar.cpp b/common/tool/action_toolbar.cpp index 6607274ecc..2e75ac9ac0 100644 --- a/common/tool/action_toolbar.cpp +++ b/common/tool/action_toolbar.cpp @@ -136,19 +136,17 @@ ACTION_TOOLBAR_PALETTE::ACTION_TOOLBAR_PALETTE( wxWindow* aParent, bool aVertica void ACTION_TOOLBAR_PALETTE::AddAction( const TOOL_ACTION& aAction ) { - int size = Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size; - wxBitmapBundle normalBmp = KiBitmapBundle( aAction.GetIcon(), size ); + int iconSize = Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size; + wxBitmapBundle normalBmp = KiBitmapBundleDef( aAction.GetIcon(), iconSize ); int bmpWidth = normalBmp.GetPreferredBitmapSizeFor( this ).GetWidth(); int padding = ( m_buttonSize.GetWidth() - bmpWidth ) / 2; - wxSize bmSize( size, size ); - bmSize *= KIPLATFORM::UI::GetContentScaleFactor( m_parent ); BITMAP_BUTTON* button = new BITMAP_BUTTON( m_panel, aAction.GetUIId() ); button->SetIsToolbarButton(); button->SetBitmap( normalBmp ); - button->SetDisabledBitmap( KiDisabledBitmapBundle( aAction.GetIcon() ) ); + button->SetDisabledBitmap( KiDisabledBitmapBundleDef( aAction.GetIcon(), iconSize ) ); button->SetPadding( padding ); button->SetToolTip( aAction.GetButtonTooltip() ); button->AcceptDragInAsClick(); @@ -223,6 +221,23 @@ ACTION_TOOLBAR::ACTION_TOOLBAR( EDA_BASE_FRAME* parent, wxWindowID id, const wxP Connect( m_paletteTimer->GetId(), wxEVT_TIMER, wxTimerEventHandler( ACTION_TOOLBAR::onTimerDone ), nullptr, this ); Bind( wxEVT_SYS_COLOUR_CHANGED, wxSysColourChangedEventHandler( ACTION_TOOLBAR::onThemeChanged ), this ); + + Bind( wxEVT_DPI_CHANGED, + [&]( wxDPIChangedEvent& aEvent ) + { +#ifdef __WXMSW__ + // Update values which are normally only initialized in wxAuiToolBar::Create + // FromDIP is no-op on backends other than wxMSW + m_toolPacking = FromDIP( 2 ); + m_toolBorderPadding = FromDIP( 3 ); + + wxSize margin_lt = FromDIP( wxSize( 5, 5 ) ); + wxSize margin_rb = FromDIP( wxSize( 2, 2 ) ); + SetMargins( margin_lt.x, margin_lt.y, margin_rb.x, margin_rb.y ); +#endif + + aEvent.Skip(); + } ); } @@ -411,10 +426,11 @@ void ACTION_TOOLBAR::Add( const TOOL_ACTION& aAction, bool aIsToggleEntry, bool wxS( "aIsCancellable requires aIsToggleEntry" ) ); int toolId = aAction.GetUIId(); + int iconSize = Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size; AddTool( toolId, wxEmptyString, - KiBitmapBundle( aAction.GetIcon(), Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size ), - KiDisabledBitmapBundle( aAction.GetIcon() ), + KiBitmapBundleDef( aAction.GetIcon(), iconSize ), + KiDisabledBitmapBundleDef( aAction.GetIcon(), iconSize ), aIsToggleEntry ? wxITEM_CHECK : wxITEM_NORMAL, aAction.GetButtonTooltip(), wxEmptyString, nullptr ); @@ -427,11 +443,12 @@ void ACTION_TOOLBAR::Add( const TOOL_ACTION& aAction, bool aIsToggleEntry, bool void ACTION_TOOLBAR::AddButton( const TOOL_ACTION& aAction ) { int toolId = aAction.GetUIId(); + int iconSize = Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size; AddTool( toolId, wxEmptyString, - KiBitmapBundle( aAction.GetIcon(), Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size ), - KiDisabledBitmapBundle( aAction.GetIcon() ), wxITEM_NORMAL, - aAction.GetButtonTooltip(), wxEmptyString, nullptr ); + KiBitmapBundleDef( aAction.GetIcon(), iconSize ), + KiDisabledBitmapBundleDef( aAction.GetIcon(), iconSize ), + wxITEM_NORMAL, aAction.GetButtonTooltip(), wxEmptyString, nullptr ); m_toolKinds[ toolId ] = false; m_toolActions[ toolId ] = &aAction; @@ -470,8 +487,9 @@ void ACTION_TOOLBAR::AddToolContextMenu( const TOOL_ACTION& aAction, std::unique void ACTION_TOOLBAR::AddGroup( std::unique_ptr aGroup ) { - int groupId = aGroup->GetUIId(); + int groupId = aGroup->GetUIId(); const TOOL_ACTION* defaultAction = aGroup->GetDefaultAction(); + int iconSize = Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size; wxASSERT( GetParent() ); wxASSERT( defaultAction ); @@ -489,10 +507,9 @@ void ACTION_TOOLBAR::AddGroup( std::unique_ptr aGroup ) // Add the main toolbar item representing the group AddTool( groupId, wxEmptyString, - KiBitmapBundle( defaultAction->GetIcon(), Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size ), - KiDisabledBitmapBundle( defaultAction->GetIcon() ), - isToggleEntry ? wxITEM_CHECK : wxITEM_NORMAL, - wxEmptyString, wxEmptyString, nullptr ); + KiBitmapBundleDef( defaultAction->GetIcon(), iconSize ), + KiDisabledBitmapBundleDef( defaultAction->GetIcon(), iconSize ), + isToggleEntry ? wxITEM_CHECK : wxITEM_NORMAL, wxEmptyString, wxEmptyString, nullptr ); // Select the default action doSelectAction( m_actionGroups[ groupId ].get(), *defaultAction ); @@ -546,10 +563,12 @@ void ACTION_TOOLBAR::doSelectAction( ACTION_GROUP* aGroup, const TOOL_ACTION& aA if( !item ) return; + int iconSize = Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size; + // Update the item information item->SetShortHelp( aAction.GetButtonTooltip() ); - item->SetBitmap( KiBitmapBundle( aAction.GetIcon(), Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size ) ); - item->SetDisabledBitmap( KiDisabledBitmapBundle( aAction.GetIcon() ) ); + item->SetBitmap( KiBitmapBundleDef( aAction.GetIcon(), iconSize ) ); + item->SetDisabledBitmap( KiDisabledBitmapBundleDef( aAction.GetIcon(), iconSize ) ); // Register a new handler with the new UI conditions if( m_toolManager ) @@ -1071,13 +1090,14 @@ void ACTION_TOOLBAR::onThemeChanged( wxSysColourChangedEvent &aEvent ) void ACTION_TOOLBAR::RefreshBitmaps() { + int iconSize = Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size; + for( const std::pair pair : m_toolActions ) { wxAuiToolBarItem* tool = FindTool( pair.first ); - tool->SetBitmap( KiBitmapBundle( pair.second->GetIcon(), - Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size ) ); - tool->SetDisabledBitmap( KiDisabledBitmapBundle( pair.second->GetIcon() ) ); + tool->SetBitmap( KiBitmapBundleDef( pair.second->GetIcon(), iconSize ) ); + tool->SetDisabledBitmap( KiDisabledBitmapBundleDef( pair.second->GetIcon(), iconSize ) ); } Refresh(); diff --git a/common/widgets/wx_aui_art_providers.cpp b/common/widgets/wx_aui_art_providers.cpp index b0dc11fcb2..618ec7ac9a 100644 --- a/common/widgets/wx_aui_art_providers.cpp +++ b/common/widgets/wx_aui_art_providers.cpp @@ -40,16 +40,12 @@ wxSize WX_AUI_TOOLBAR_ART::GetToolSize( wxDC& aDc, wxWindow* aWindow, #endif { // Based on the upstream wxWidgets implementation, but simplified for our application - int size = Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size; - -#ifdef __WXMSW__ - size *= KIPLATFORM::UI::GetContentScaleFactor( aWindow ); -#endif + int size = aWindow->FromDIP( Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size ); int width = size; int height = size; - if( m_flags & wxAUI_TB_TEXT ) + if( ( m_flags & wxAUI_TB_TEXT ) && !aItem.GetLabel().empty() ) { aDc.SetFont( m_font ); int tx, ty; @@ -65,7 +61,7 @@ wxSize WX_AUI_TOOLBAR_ART::GetToolSize( wxDC& aDc, wxWindow* aWindow, width = wxMax( width, tx + aWindow->FromDIP( 6 ) ); } } - else if( m_textOrientation == wxAUI_TBTOOL_TEXT_RIGHT && !aItem.GetLabel().empty() ) + else if( m_textOrientation == wxAUI_TBTOOL_TEXT_RIGHT ) { width += aWindow->FromDIP( 3 ); // space between left border and bitmap width += aWindow->FromDIP( 3 ); // space between bitmap and text @@ -92,12 +88,10 @@ wxSize WX_AUI_TOOLBAR_ART::GetToolSize( wxDC& aDc, wxWindow* aWindow, void WX_AUI_TOOLBAR_ART::DrawButton( wxDC& aDc, wxWindow* aWindow, const wxAuiToolBarItem& aItem, const wxRect& aRect ) { - // Taken from upstream implementation; modified to respect tool size - wxSize bmpSize = GetToolSize( aDc, aWindow, aItem ); - + // Taken from upstream implementation int textWidth = 0, textHeight = 0; - if( m_flags & wxAUI_TB_TEXT ) + if( ( m_flags & wxAUI_TB_TEXT ) && !aItem.GetLabel().empty() ) { aDc.SetFont( m_font ); @@ -111,15 +105,8 @@ void WX_AUI_TOOLBAR_ART::DrawButton( wxDC& aDc, wxWindow* aWindow, const wxAuiTo int bmpX = 0, bmpY = 0; int textX = 0, textY = 0; - double scale = KIPLATFORM::UI::GetPixelScaleFactor( aWindow ); - const wxBitmapBundle& bundle = ( aItem.GetState() & wxAUI_BUTTON_STATE_DISABLED ) - ? aItem.GetDisabledBitmapBundle() - : aItem.GetBitmapBundle(); - wxBitmap bmp = bundle.GetBitmap( bmpSize * scale ); - - // wxBitmapBundle::GetBitmap thinks we need this rescaled to match the base size, which we don't - if( bmp.IsOk() ) - bmp.SetScaleFactor( scale ); + const wxBitmap& bmp = aItem.GetCurrentBitmapFor( aWindow ); + const wxSize bmpSize = bmp.IsOk() ? bmp.GetLogicalSize() : wxSize( 0, 0 ); if( m_textOrientation == wxAUI_TBTOOL_TEXT_BOTTOM ) { diff --git a/include/bitmap_store.h b/include/bitmap_store.h index cbb50964ac..5a4c10b3dc 100644 --- a/include/bitmap_store.h +++ b/include/bitmap_store.h @@ -80,8 +80,19 @@ public: * Constructs and returns a bitmap bundle for the given icon ID, with the bitmaps * converted to disabled state according to the current UI theme. * @param aBitmapId is from the BITMAPS enum in bitmaps_list.h + * @param aMinHeight is the minimum height of the bitmaps to include in the bundle. */ - wxBitmapBundle GetDisabledBitmapBundle( BITMAPS aBitmapId ); + wxBitmapBundle GetDisabledBitmapBundle( BITMAPS aBitmapId, int aMinHeight = -1 ); + + /** + * Constructs and returns a bitmap bundle for the given icon ID, with the bitmaps + * converted to disabled state according to the current UI theme and the default + * bitmap size being aDefHeight. Rescaling is applied if no bitmap of that size + * is available. + * @param aBitmapId is from the BITMAPS enum in bitmaps_list.h + * @param aDefHeight is the desired height of the default bitmap in the bundle. + */ + wxBitmapBundle GetDisabledBitmapBundleDef( BITMAPS aBitmapId, int aDefHeight ); /** * Retrieves a bitmap from the given bitmap id, scaled to a given factor. diff --git a/include/bitmaps/bitmap_types.h b/include/bitmaps/bitmap_types.h index b19e559fa8..f3c3b070a5 100644 --- a/include/bitmaps/bitmap_types.h +++ b/include/bitmaps/bitmap_types.h @@ -67,7 +67,9 @@ KICOMMON_API wxBitmapBundle KiBitmapBundle( BITMAPS aBitmap, int aMinHeight = -1 */ KICOMMON_API wxBitmapBundle KiBitmapBundleDef( BITMAPS aBitmap, int aDefHeight ); -KICOMMON_API wxBitmapBundle KiDisabledBitmapBundle( BITMAPS aBitmap ); +KICOMMON_API wxBitmapBundle KiDisabledBitmapBundle( BITMAPS aBitmap, int aMinHeight = -1 ); + +KICOMMON_API wxBitmapBundle KiDisabledBitmapBundleDef( BITMAPS aBitmap, int aDefHeight ); /** * Wipes out the scaled bitmap cache so that the icon theme can be changed.