sw/inc/viscrs.hxx | 5 ++ sw/source/core/crsr/crsrsh.cxx | 2 + sw/source/core/crsr/viscrs.cxx | 78 +++++++++++++++++++++++++++++++++++++++ sw/source/core/txtnode/ndtxt.cxx | 1 4 files changed, 86 insertions(+)
New commits: commit c2999f9f3e0efa04f89055399f2d176c9c95e92d Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Apr 6 08:40:31 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Apr 6 09:49:36 2022 +0200 sw content controls: add overlay to render a border around the text portions - introduce SwSelPaintRects::HighlightContentControl() to create the overlay - use GetTextAttrAt() to enable this when we're inside a content control (not only when the cursor is exactly at the dummy char of the content control, which is at the start) - tested that this works correctly even if the portions inside the content control don't have the same height (similar to the selection overlay) Change-Id: I1db51cdb1ddc87c45740cd8677de645dc8906697 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132618 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/inc/viscrs.hxx b/sw/inc/viscrs.hxx index 6755b548e8a0..2eb2f787fbc7 100644 --- a/sw/inc/viscrs.hxx +++ b/sw/inc/viscrs.hxx @@ -84,8 +84,11 @@ class SwSelPaintRects : public SwRects bool m_bShowTextInputFieldOverlay; std::unique_ptr<sw::overlay::OverlayRangesOutline> m_pTextInputFieldOverlay; + bool m_bShowContentControlOverlay; + std::unique_ptr<sw::overlay::OverlayRangesOutline> m_pContentControlOverlay; void HighlightInputField(); + void HighlightContentControl(); public: SwSelPaintRects( const SwCursorShell& rCSh ); @@ -108,6 +111,8 @@ public: m_bShowTextInputFieldOverlay = bShow; } + void SetShowContentControlOverlay(const bool bShow) { m_bShowContentControlOverlay = bShow; } + const SwCursorShell* GetShell() const { return m_pCursorShell; } // check current MapMode of the shell and set possibly the static members. // Optional set the parameters pX, pY diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index eb5caf60a0ab..ebb15bec6107 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -2402,6 +2402,7 @@ void SwCursorShell::ShowCursor() m_bSVCursorVis = true; m_pCurrentCursor->SetShowTextInputFieldOverlay( true ); + m_pCurrentCursor->SetShowContentControlOverlay(true); if (comphelper::LibreOfficeKit::isActive()) { @@ -2422,6 +2423,7 @@ void SwCursorShell::HideCursor() // possibly reverse selected areas!! CurrShell aCurr( this ); m_pCurrentCursor->SetShowTextInputFieldOverlay( false ); + m_pCurrentCursor->SetShowContentControlOverlay(false); m_pVisibleCursor->Hide(); if (comphelper::LibreOfficeKit::isActive()) diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx index 0501162a2a16..d72289bdbb36 100644 --- a/sw/source/core/crsr/viscrs.cxx +++ b/sw/source/core/crsr/viscrs.cxx @@ -59,6 +59,7 @@ #include <svtools/optionsdrawinglayer.hxx> #include <cellfrm.hxx> #include <wrtsh.hxx> +#include <textcontentcontrol.hxx> // Here static members are defined. They will get changed on alteration of the // MapMode. This is done so that on ShowCursor the same size does not have to be @@ -350,6 +351,7 @@ SwSelPaintRects::SwSelPaintRects( const SwCursorShell& rCSh ) : m_pCursorShell( &rCSh ) #if HAVE_FEATURE_DESKTOP , m_bShowTextInputFieldOverlay(true) + , m_bShowContentControlOverlay(true) #endif { } @@ -368,6 +370,8 @@ void SwSelPaintRects::swapContent(SwSelPaintRects& rSwap) std::swap(m_pCursorOverlay, rSwap.m_pCursorOverlay); std::swap(m_bShowTextInputFieldOverlay, rSwap.m_bShowTextInputFieldOverlay); std::swap(m_pTextInputFieldOverlay, rSwap.m_pTextInputFieldOverlay); + std::swap(m_bShowContentControlOverlay, rSwap.m_bShowContentControlOverlay); + std::swap(m_pContentControlOverlay, rSwap.m_pContentControlOverlay); #endif } @@ -376,6 +380,7 @@ void SwSelPaintRects::Hide() #if HAVE_FEATURE_DESKTOP m_pCursorOverlay.reset(); m_pTextInputFieldOverlay.reset(); + m_pContentControlOverlay.reset(); #endif SwRects::clear(); @@ -466,6 +471,7 @@ void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles) } HighlightInputField(); + HighlightContentControl(); #endif // Tiled editing does not expose the draw and writer cursor, it just @@ -625,6 +631,78 @@ void SwSelPaintRects::HighlightInputField() } } +void SwSelPaintRects::HighlightContentControl() +{ + std::vector<basegfx::B2DRange> aContentControlRanges; + + if (m_bShowContentControlOverlay) + { + const SwPosition* pStart = GetShell()->GetCursor()->Start(); + SwTextNode* pTextNode = pStart->nNode.GetNode().GetTextNode(); + SwTextContentControl* pCurContentControlAtCursor = nullptr; + if (pTextNode) + { + // SwTextNode::PARENT because this way we highlight when the cursor is on the right side + // of the dummy character: ideally the end of the range would have the same behavior. + SwTextAttr* pAttr = pTextNode->GetTextAttrAt( + pStart->nContent.GetIndex(), RES_TXTATR_CONTENTCONTROL, SwTextNode::PARENT); + if (pAttr) + { + pCurContentControlAtCursor = static_txtattr_cast<SwTextContentControl*>(pAttr); + } + } + if (pCurContentControlAtCursor) + { + auto pCursorForContentControl = std::make_unique<SwShellCursor>( + *GetShell(), SwPosition(*pTextNode, pCurContentControlAtCursor->GetStart())); + pCursorForContentControl->SetMark(); + pCursorForContentControl->GetMark()->nNode = *pTextNode; + pCursorForContentControl->GetMark()->nContent.Assign( + pTextNode, *(pCurContentControlAtCursor->End())); + + pCursorForContentControl->FillRects(); + SwRects* pRects = pCursorForContentControl.get(); + for (const auto& rRect : *pRects) + { + tools::Rectangle aRect(rRect.SVRect()); + + aContentControlRanges.emplace_back(aRect.Left(), aRect.Top(), aRect.Right() + 1, + aRect.Bottom() + 1); + } + } + } + + if (!aContentControlRanges.empty()) + { + if (m_pContentControlOverlay) + { + m_pContentControlOverlay->setRanges(std::move(aContentControlRanges)); + } + else + { + SdrView* pView = const_cast<SdrView*>(GetShell()->GetDrawView()); + SdrPaintWindow* pCandidate = pView->GetPaintWindow(0); + const rtl::Reference<sdr::overlay::OverlayManager>& xTargetOverlay + = pCandidate->GetOverlayManager(); + + if (xTargetOverlay.is()) + { + // Use the system's highlight color with decreased luminance as highlight color. + Color aHighlight(SvtOptionsDrawinglayer::getHilightColor()); + aHighlight.DecreaseLuminance(128); + + m_pContentControlOverlay.reset(new sw::overlay::OverlayRangesOutline( + aHighlight, std::move(aContentControlRanges))); + xTargetOverlay->add(*m_pContentControlOverlay); + } + } + } + else + { + m_pContentControlOverlay.reset(); + } +} + void SwSelPaintRects::Invalidate( const SwRect& rRect ) { size_type nSz = size(); diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx index 71513b183599..088792546980 100644 --- a/sw/source/core/txtnode/ndtxt.cxx +++ b/sw/source/core/txtnode/ndtxt.cxx @@ -1716,6 +1716,7 @@ SwTextNode::GetTextAttrAt(sal_Int32 const nIndex, sal_uInt16 const nWhich, || (nWhich == RES_TXTATR_INETFMT) || (nWhich == RES_TXTATR_CJK_RUBY) || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER) + || (nWhich == RES_TXTATR_CONTENTCONTROL) || (nWhich == RES_TXTATR_INPUTFIELD ) ); // "GetTextAttrAt() will give wrong result for this hint!")