sw/qa/core/unocore/unocore.cxx    |    7 ++++-
 sw/qa/uibase/wrtsh/wrtsh.cxx      |   46 ++++++++++++++++++++++++++++++++++++++
 sw/source/uibase/docvw/edtwin.cxx |   26 +++++++++++++++++++++
 sw/source/uibase/uiview/view2.cxx |    2 -
 sw/source/uibase/wrtsh/wrtsh3.cxx |   18 ++++++++++++++
 5 files changed, 96 insertions(+), 3 deletions(-)

New commits:
commit b213abcb77e19fa5d22af45c7ecd17c8a63af554
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed May 18 10:51:18 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu May 19 14:38:03 2022 +0200

    sw content controls, picture: replace placeholder image on click
    
    Previous content control types (rich text, checkbox, dropdown) had the
    cursor somewhere in the content control and click selected the content
    control in the placeholder case.
    
    The picture case is somewhat different: the content control has a single
    as-char image, and by the time SwWrtShell::GotoContentControl() is
    invoked, the picture frame is already selected.
    
    All we have to do here is to trigger the file picker to select a
    replacement and then insert that image to replace the already selected
    frame's bitmap.
    
    Change-Id: Id3ad94ed8f7e13b0ebc2f57327bb8c0b1e374a86
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134511
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx
index c9ea6f833c12..3739362fb403 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -553,7 +553,12 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlPicture)
     uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
     uno::Reference<text::XText> xText = xTextDocument->getText();
     uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
-    xText->insertString(xCursor, "test", /*bAbsorb=*/false);
+    uno::Reference<beans::XPropertySet> xTextGraphic(
+        xMSF->createInstance("com.sun.star.text.TextGraphicObject"), 
uno::UNO_QUERY);
+    xTextGraphic->setPropertyValue("AnchorType",
+                                   
uno::Any(text::TextContentAnchorType_AS_CHARACTER));
+    uno::Reference<text::XTextContent> xTextContent(xTextGraphic, 
uno::UNO_QUERY);
+    xText->insertTextContent(xCursor, xTextContent, false);
     xCursor->gotoStart(/*bExpand=*/false);
     xCursor->gotoEnd(/*bExpand=*/true);
     uno::Reference<text::XTextContent> xContentControl(
diff --git a/sw/qa/uibase/wrtsh/wrtsh.cxx b/sw/qa/uibase/wrtsh/wrtsh.cxx
index 6faf642e10e4..297e7a2d1ebd 100644
--- a/sw/qa/uibase/wrtsh/wrtsh.cxx
+++ b/sw/qa/uibase/wrtsh/wrtsh.cxx
@@ -25,6 +25,7 @@
 #include <wrtsh.hxx>
 #include <ndtxt.hxx>
 #include <textcontentcontrol.hxx>
+#include <fmtanchr.hxx>
 
 namespace
 {
@@ -239,6 +240,51 @@ CPPUNIT_TEST_FIXTURE(Test, 
testInsertDropdownContentControl)
     // i.e. the inserted content control was a default (rich text) one, not a 
dropdown.
     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), 
pContentControl->GetListItems().size());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testReplacePictureContentControl)
+{
+    // Given a document with a picture content control:
+    SwDoc* pDoc = createSwDoc();
+    uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xText = xTextDocument->getText();
+    uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+    uno::Reference<beans::XPropertySet> xTextGraphic(
+        xMSF->createInstance("com.sun.star.text.TextGraphicObject"), 
uno::UNO_QUERY);
+    xTextGraphic->setPropertyValue("AnchorType",
+                                   
uno::Any(text::TextContentAnchorType_AS_CHARACTER));
+    uno::Reference<text::XTextContent> xTextContent(xTextGraphic, 
uno::UNO_QUERY);
+    xText->insertTextContent(xCursor, xTextContent, false);
+    xCursor->gotoStart(/*bExpand=*/false);
+    xCursor->gotoEnd(/*bExpand=*/true);
+    uno::Reference<text::XTextContent> xContentControl(
+        xMSF->createInstance("com.sun.star.text.ContentControl"), 
uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, 
uno::UNO_QUERY);
+    xContentControlProps->setPropertyValue("ShowingPlaceHolder", 
uno::Any(true));
+    xContentControlProps->setPropertyValue("Picture", uno::Any(true));
+    xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
+
+    // When clicking on that content control:
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    pWrtShell->GotoObj(/*bNext=*/true, GotoObjFlags::Any);
+    pWrtShell->EnterSelFrameMode();
+    const SwFrameFormat* pFlyFormat = pWrtShell->GetFlyFrameFormat();
+    const SwFormatAnchor& rFormatAnchor = pFlyFormat->GetAnchor();
+    const SwPosition* pAnchorPos = rFormatAnchor.GetContentAnchor();
+    SwTextNode* pTextNode = pAnchorPos->nNode.GetNode().GetTextNode();
+    SwTextAttr* pAttr = pTextNode->GetTextAttrForCharAt(0, 
RES_TXTATR_CONTENTCONTROL);
+    auto pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
+    auto& rFormatContentControl
+        = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
+    pWrtShell->GotoContentControl(rFormatContentControl);
+
+    // Then make sure that the picture is replaced:
+    
CPPUNIT_ASSERT(!rFormatContentControl.GetContentControl()->GetShowingPlaceHolder());
+    // Without the accompanying fix in place, this test would have failed, 
there was no special
+    // handling for picture content control (how to interact with them), and 
the default handler
+    // killed the image selection.
+    CPPUNIT_ASSERT(pWrtShell->IsFrameSelected());
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/uibase/docvw/edtwin.cxx 
b/sw/source/uibase/docvw/edtwin.cxx
index 12ade08df6d6..69dc6f7aa509 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -4684,6 +4684,32 @@ void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt)
 
                             CaptureMouse();
                         }
+
+                        if (pFlyFormat)
+                        {
+                            // See if the fly frame's anchor is in a content 
control. If so,
+                            // interact with it.
+                            const SwFormatAnchor& rFormatAnchor = 
pFlyFormat->GetAnchor();
+                            const SwPosition* pAnchorPos = 
rFormatAnchor.GetContentAnchor();
+                            if (pAnchorPos)
+                            {
+                                SwTextNode* pTextNode = 
pAnchorPos->nNode.GetNode().GetTextNode();
+                                if (pTextNode)
+                                {
+                                    SwTextAttr* pAttr = 
pTextNode->GetTextAttrAt(
+                                        pAnchorPos->nContent.GetIndex(), 
RES_TXTATR_CONTENTCONTROL,
+                                        SwTextNode::PARENT);
+                                    if (pAttr)
+                                    {
+                                        SwTextContentControl* 
pTextContentControl
+                                            = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
+                                        const SwFormatContentControl& 
rFormatContentControl
+                                            = 
pTextContentControl->GetContentControl();
+                                        
rSh.GotoContentControl(rFormatContentControl);
+                                    }
+                                }
+                            }
+                        }
                     }
                     rSh.EndDrag( &aDocPt, false );
                 }
diff --git a/sw/source/uibase/uiview/view2.cxx 
b/sw/source/uibase/uiview/view2.cxx
index 970064c6c164..75219fcbab07 100644
--- a/sw/source/uibase/uiview/view2.cxx
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -380,7 +380,7 @@ bool SwView::InsertGraphicDlg( SfxRequest& rReq )
     bool bShowError = !pName;
     if( pName
 #if HAVE_FEATURE_DESKTOP
-        || ERRCODE_NONE == pFileDlg->Execute()
+        || (!Application::IsHeadlessModeEnabled() && ERRCODE_NONE == 
pFileDlg->Execute())
 #endif
         )
     {
diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx 
b/sw/source/uibase/wrtsh/wrtsh3.cxx
index c0567d03427b..978f95397b52 100644
--- a/sw/source/uibase/wrtsh/wrtsh3.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh3.cxx
@@ -28,6 +28,8 @@
 #include <com/sun/star/form/FormButtonType.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <osl/diagnose.h>
+#include <sfx2/dispatch.hxx>
+
 #include <swmodule.hxx>
 #include <wrtsh.hxx>
 #include <view.hxx>
@@ -90,11 +92,25 @@ bool SwWrtShell::GotoField( const SwFormatField& rField )
 
 bool SwWrtShell::GotoContentControl(const SwFormatContentControl& 
rContentControl)
 {
+    std::shared_ptr<SwContentControl> pContentControl = 
rContentControl.GetContentControl();
+    if (IsFrameSelected() && pContentControl && pContentControl->GetPicture())
+    {
+        // A frame is already selected, and its anchor is inside a picture 
content control.
+        if (pContentControl->GetShowingPlaceHolder())
+        {
+            // Replace the placeholder image with a real one.
+            GetView().StopShellTimer();
+            
GetView().GetViewFrame()->GetDispatcher()->Execute(SID_CHANGE_PICTURE,
+                                                               
SfxCallMode::SYNCHRON);
+            pContentControl->SetShowingPlaceHolder(false);
+        }
+        return true;
+    }
+
     (this->*m_fnKillSel)(nullptr, false);
 
     bool bRet = SwCursorShell::GotoFormatContentControl(rContentControl);
 
-    std::shared_ptr<SwContentControl> pContentControl = 
rContentControl.GetContentControl();
     if (bRet && pContentControl && pContentControl->GetCheckbox())
     {
         // Checkbox: GotoFormatContentControl() selected the old state.

Reply via email to