sw/qa/extras/uiwriter/data/tdf135581.odt |binary
 sw/qa/extras/uiwriter/uiwriter3.cxx      |   11 ++++++++
 sw/source/core/doc/docfly.cxx            |   38 +++++++++++++------------------
 3 files changed, 28 insertions(+), 21 deletions(-)

New commits:
commit d68e428a2ab9f0027ff82d67ae2492d143364586
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Thu Mar 16 18:49:12 2023 -0400
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Mar 22 10:39:53 2023 +0000

    tdf#135581 sw UI: keep image in place when changing anchor
    
    Changing the anchor type should not move an image around.
    
    The only time we have a prosition to fix AFAICS is when
    the anchor changes and the RelationOrient is no longer appropriate.
    In that case we always get a new p*OrientItem.
    If GetPos changed, then that means the user (or earlier algorithm)
    already adjusted for the change. If there is no difference in GetPos
    even though the relation changed, then that is the only time we (likely)
    need to recalculate.
    
    So the typical example requiring an adjustment would be a change
    from "to paragraph" at text position 0 to a "to page" anchor.
    In this case "page" has no relationship to "text margins"
    and thus needs to base the absolute position 0 on page instead of text,
    meaning that the margins would need to be added to the absolute position.
    
    This code is basically unchanged since initial import.
    I have no idea why it could possibly be good to change
    the position when there is no new information given
    (no pHoriOrientItem/pVertOrientItem).
    
    [I checked and "from top" and "from bottom"
     are both == NONE, as well of course as "from left".]
    
    make CppunitTest_sw_uiwriter3 CPPUNIT_TEST_NAME=testTdf135581
    
    Change-Id: Ib89ad9ba26c8826ed43f6d4505a82502b9ad8af9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149012
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/uiwriter/data/tdf135581.odt 
b/sw/qa/extras/uiwriter/data/tdf135581.odt
new file mode 100644
index 000000000000..cbd678ba0f73
Binary files /dev/null and b/sw/qa/extras/uiwriter/data/tdf135581.odt differ
diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx 
b/sw/qa/extras/uiwriter/uiwriter3.cxx
index dfcde8d7eaa7..40f02901de09 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -1759,6 +1759,17 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, TestAsCharTextBox)
     // Without the fix in place the two texboxes has been fallen apart, and  
asserts will broken.
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf135581)
+{
+    createSwDoc("tdf135581.odt");
+
+    selectShape(1);
+    dispatchCommand(mxComponent, ".uno:SetAnchorAtChar", {}); // this is "to 
char"
+
+    // Without the fix, the image was moving when the anchor changed, letting 
text flow back.
+    CPPUNIT_ASSERT_EQUAL(2, getPages());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf140975)
 {
     // Load the bugdoc
diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
index 5ddc713ff4af..998f123ee6c0 100644
--- a/sw/source/core/doc/docfly.cxx
+++ b/sw/source/core/doc/docfly.cxx
@@ -363,26 +363,25 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& 
rFormat, SfxItemSet& rSet, boo
     case RndStdIds::FLY_AT_FLY:    // LAYER_IMPL
     case RndStdIds::FLY_AT_PAGE:
         {
-            // If no position attributes are coming in, we correct the 
position in a way
-            // such that the fly's document coordinates are preserved.
-            // If only the alignment changes in the position attributes 
(text::RelOrientation::FRAME
-            // vs. text::RelOrientation::PRTAREA), we also correct the 
position.
+            // If only the anchor type has changed (char -> para -> page) and 
the absolute position
+            // is unchanged even though there is a new relative orientation
+            // (likely because the old orientation was not valid for the new 
anchor type),
+            // then adjust the position to account for the moved anchor 
position.
             const SwFormatHoriOrient* pHoriOrientItem = rSet.GetItemIfSet( 
RES_HORI_ORIENT, false );
 
             SwFormatHoriOrient aOldH( rFormat.GetHoriOrient() );
             bool bPutOldH(false);
 
-            if( text::HoriOrientation::NONE == aOldH.GetHoriOrient() && ( 
!pHoriOrientItem ||
-                aOldH.GetPos() == pHoriOrientItem->GetPos() ))
+            if (text::HoriOrientation::NONE == aOldH.GetHoriOrient() && 
pHoriOrientItem
+                && text::HoriOrientation::NONE == 
pHoriOrientItem->GetHoriOrient()
+                && aOldH.GetPos() == pHoriOrientItem->GetPos())
             {
                 SwTwips nPos = (RndStdIds::FLY_AS_CHAR == nOld) ? 0 : 
aOldH.GetPos();
                 nPos += aOldAnchorPos.getX() - aNewAnchorPos.getX();
 
-                if( pHoriOrientItem )
-                {
-                    aOldH.SetHoriOrient( pHoriOrientItem->GetHoriOrient() );
-                    aOldH.SetRelationOrient( 
pHoriOrientItem->GetRelationOrient() );
-                }
+                assert(aOldH.GetRelationOrient() != 
pHoriOrientItem->GetRelationOrient());
+                aOldH.SetRelationOrient(pHoriOrientItem->GetRelationOrient());
+
                 aOldH.SetPos( nPos );
                 bPutOldH = true;
             }
@@ -406,19 +405,16 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& 
rFormat, SfxItemSet& rSet, boo
             const SwFormatVertOrient* pVertOrientItem = rSet.GetItemIfSet( 
RES_VERT_ORIENT, false );
             SwFormatVertOrient aOldV( rFormat.GetVertOrient() );
 
-            // #i28922# - correction: compare <aOldV.GetVertOrient() with
-            // <text::VertOrientation::NONE>
-            if( text::VertOrientation::NONE == aOldV.GetVertOrient() && 
(!pVertOrientItem ||
-                aOldV.GetPos() == pVertOrientItem->GetPos() ) )
+            if (text::VertOrientation::NONE == aOldV.GetVertOrient() && 
pVertOrientItem
+                && text::VertOrientation::NONE == 
pVertOrientItem->GetVertOrient()
+                && aOldV.GetPos() == pVertOrientItem->GetPos())
             {
                 SwTwips nPos = (RndStdIds::FLY_AS_CHAR == nOld) ? 0 : 
aOldV.GetPos();
                 nPos += aOldAnchorPos.getY() - aNewAnchorPos.getY();
-                if( pVertOrientItem )
-                {
-                    SwFormatVertOrient& rV = 
const_cast<SwFormatVertOrient&>(*pVertOrientItem);
-                    aOldV.SetVertOrient( rV.GetVertOrient() );
-                    aOldV.SetRelationOrient( rV.GetRelationOrient() );
-                }
+
+                assert(aOldV.GetRelationOrient() != 
pVertOrientItem->GetRelationOrient());
+                aOldV.SetRelationOrient(pVertOrientItem->GetRelationOrient());
+
                 aOldV.SetPos( nPos );
                 rSet.Put( aOldV );
             }

Reply via email to