vcl/source/treelist/treelistbox.cxx | 116 ++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 45 deletions(-)
New commits: commit a750d23591aaf1bb7883e949769a9b31d6a95983 Author: Mike Kaganski <[email protected]> AuthorDate: Thu May 29 01:40:11 2025 +0500 Commit: Mike Kaganski <[email protected]> CommitDate: Sun Jun 1 08:17:39 2025 +0200 tdf#166773: avoid using HighlightTextColor on treeview standard image ... when the image is not on a highlight background. The problem was, that the non-native-drawn symbol of a highlighted element was drawn using "highlighted text" color (usually white), but that only makes sense when the background of such an element (text, symbol) is itself "highlighted" (dark). In tree view, the usual rendering only gighlights the text of active element, not the area of the "expand" symbol. That resulted in white-on-white rendering. This change tracks, if the background painted for the element's items intersects with the area of the symbol, and only uses the "highlighted text" color, if it does. Change-Id: I781b3341466419c1e654d7b46c8cc8db9ead7120 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186089 Tested-by: Jenkins Reviewed-by: Caolán McNamara <[email protected]> diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx index 44815e8aa6c9..576f5b9b4a8f 100644 --- a/vcl/source/treelist/treelistbox.cxx +++ b/vcl/source/treelist/treelistbox.cxx @@ -2620,10 +2620,68 @@ void SvTreeListBox::PaintEntry1(SvTreeListEntry& rEntry, tools::Long nLine, vcl: const bool bHasButtonsAtRoot = nWindowStyle & WB_HASBUTTONSATROOT; const size_t nTabCount = aTabs.size(); + + // Get image information + + sal_uInt16 nFirstDynTabPos(0); + SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab(nFirstDynTabPos); + + const Image* pImg = nullptr; + Point aImagePos; + Size aImageSize; + bool bDefaultImage = false; + bool bExpanded = false; + + const bool bNeedsImage = (!(rEntry.GetFlags() & SvTLEntryFlags::NO_NODEBMP)) + && (nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab + && (rEntry.HasChildren() || rEntry.HasChildrenOnDemand()); + if (bNeedsImage) + { + tools::Long nDynTabPos = GetTabPos(&rEntry, pFirstDynamicTab); + nDynTabPos += pImpl->m_nNodeBmpTabDistance; + nDynTabPos += pImpl->m_nNodeBmpWidth / 2; + nDynTabPos += 4; // 4 pixels of buffer, so the node bitmap is not too close to the next tab + + // find first tab and check if the node bitmap extends into it + sal_uInt16 nNextTab = nFirstDynTabPos; + SvLBoxTab* pNextTab; + do + { + nNextTab++; + pNextTab = nNextTab < nTabCount ? aTabs[nNextTab].get() : nullptr; + } while (pNextTab && pNextTab->IsDynamic()); + + if (pNextTab && (GetTabPos(&rEntry, pNextTab) <= nDynTabPos)) + return; + + if (!((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(&rEntry) > 0)) + return; + + aImagePos = Point(GetTabPos(&rEntry, pFirstDynamicTab), nLine); + aImagePos.AdjustX(pImpl->m_nNodeBmpTabDistance); + + bExpanded = IsExpanded(&rEntry); + if (bExpanded) + pImg = &pImpl->GetExpandedNodeBmp(); + else + pImg = &pImpl->GetCollapsedNodeBmp(); + bDefaultImage = bExpanded ? *pImg == GetDefaultExpandedNodeImage() + : *pImg == GetDefaultCollapsedNodeImage(); + aImageSize = pImg->GetSizePixel(); + aImagePos.AdjustY((nTempEntryHeight - aImageSize.Height()) / 2); + } + + // Draw items + const size_t nItemCount = rEntry.ItemCount(); size_t nCurTab = 0; size_t nCurItem = 0; + const bool bEntryHighlighted = pViewDataEntry->IsHighlighted(); + // We need to track, if the area for the image area has selection background; otherwise, + // the symbol may be drawn using aHighlightTextColor (usually white) on white background + bool bImageHighlighted = false; + while (nCurTab < nTabCount && nCurItem < nItemCount) { SvLBoxTab* pTab = aTabs[nCurTab].get(); @@ -2669,7 +2727,7 @@ void SvTreeListBox::PaintEntry1(SvTreeListEntry& rEntry, tools::Long nLine, vcl: bool bSelTab = bool(nFlags & SvLBoxTabFlags::SHOW_SELECTION); - if (pViewDataEntry->IsHighlighted() && bSelTab) + if (bEntryHighlighted && bSelTab) { Color aNewWallColor = rSettings.GetHighlightColor(); // if the face color is bright then the deactivate color is also bright @@ -2744,7 +2802,14 @@ void SvTreeListBox::PaintEntry1(SvTreeListEntry& rEntry, tools::Long nLine, vcl: rRenderContext.SetFillColor(aBackgroundColor); // this case may occur for smaller horizontal resizes if (aRect.Left() < aRect.Right()) + { rRenderContext.DrawRect(aRect); + if (!bImageHighlighted && bNeedsImage && bDefaultImage && bEntryHighlighted) + { + if (!aRect.GetIntersection({ aImagePos, aImageSize }).IsEmpty()) + bImageHighlighted = true; + } + } } } // draw item @@ -2794,55 +2859,16 @@ void SvTreeListBox::PaintEntry1(SvTreeListEntry& rEntry, tools::Long nLine, vcl: rRenderContext.SetFont(aBackupFont); } - sal_uInt16 nFirstDynTabPos(0); - SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab(nFirstDynTabPos); - tools::Long nDynTabPos = GetTabPos(&rEntry, pFirstDynamicTab); - nDynTabPos += pImpl->m_nNodeBmpTabDistance; - nDynTabPos += pImpl->m_nNodeBmpWidth / 2; - nDynTabPos += 4; // 4 pixels of buffer, so the node bitmap is not too close - // to the next tab - - if( !((!(rEntry.GetFlags() & SvTLEntryFlags::NO_NODEBMP)) && - (nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab && - (rEntry.HasChildren() || rEntry.HasChildrenOnDemand()))) + if (!bNeedsImage) return; - // find first tab and check if the node bitmap extends into it - sal_uInt16 nNextTab = nFirstDynTabPos; - SvLBoxTab* pNextTab; - do - { - nNextTab++; - pNextTab = nNextTab < nTabCount ? aTabs[nNextTab].get() : nullptr; - } while (pNextTab && pNextTab->IsDynamic()); - - if (pNextTab && (GetTabPos( &rEntry, pNextTab ) <= nDynTabPos)) - return; - - if (!((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(&rEntry) > 0)) - return; - - Point aPos(GetTabPos(&rEntry, pFirstDynamicTab), nLine); - aPos.AdjustX(pImpl->m_nNodeBmpTabDistance ); - - const Image* pImg = nullptr; - - const bool bExpanded = IsExpanded(&rEntry); - if (bExpanded) - pImg = &pImpl->GetExpandedNodeBmp(); - else - pImg = &pImpl->GetCollapsedNodeBmp(); - const bool bDefaultImage = bExpanded ? *pImg == GetDefaultExpandedNodeImage() - : *pImg == GetDefaultCollapsedNodeImage(); - aPos.AdjustY((nTempEntryHeight - pImg->GetSizePixel().Height()) / 2 ); - if (!bDefaultImage) { // If it's a custom image then draw what was explicitly set to use DrawImageFlags nStyle = DrawImageFlags::NONE; if (!IsEnabled()) nStyle |= DrawImageFlags::Disable; - rRenderContext.DrawImage(aPos, *pImg, nStyle); + rRenderContext.DrawImage(aImagePos, *pImg, nStyle); } else { @@ -2851,7 +2877,7 @@ void SvTreeListBox::PaintEntry1(SvTreeListEntry& rEntry, tools::Long nLine, vcl: if (rRenderContext.IsNativeControlSupported(ControlType::ListNode, ControlPart::Entire)) { ImplControlValue aControlValue; - tools::Rectangle aCtrlRegion(aPos, pImg->GetSizePixel()); + tools::Rectangle aCtrlRegion(aImagePos, pImg->GetSizePixel()); ControlState nState = ControlState::NONE; if (IsEnabled()) @@ -2882,11 +2908,11 @@ void SvTreeListBox::PaintEntry1(SvTreeListEntry& rEntry, tools::Long nLine, vcl: nSymbolStyle |= DrawSymbolFlags::Disable; Color aCol = aBackupTextColor; - if (pViewDataEntry->IsHighlighted()) + if (bImageHighlighted) aCol = aHighlightTextColor; SymbolType eSymbol = bExpanded ? SymbolType::SPIN_DOWN : SymbolType::SPIN_RIGHT; - aDecoView.DrawSymbol(tools::Rectangle(aPos, pImg->GetSizePixel()), eSymbol, aCol, nSymbolStyle); + aDecoView.DrawSymbol(tools::Rectangle(aImagePos, pImg->GetSizePixel()), eSymbol, aCol, nSymbolStyle); } } }
