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!")
 

Reply via email to