summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2021-04-26 21:01:45 +0200
committerMiklos Vajna <vmiklos@collabora.com>2021-04-29 10:29:19 +0200
commite8bba2f28851c8826f003f893dcad75115017940 (patch)
treec04023288ff2b8a87eb3e8b0fac1ae73b3ca5d23
parent46b7d1d707b47e03163c5bcbbaa54ca49980f64a (diff)
tdf#138604 sw textbox copy: fix missing fly frames of as-char draw frame
Regression from commit 682e0488df819c191c13a03758fad0690706e508 (tdf#134099 sw: fix textbox anchors on copy-paste and undo, 2020-06-29), now that we don't copy draw+fly format pairs more than once, the fly frame of a fly format was missing. This was broken because sw::DocumentContentOperationsManager::CopyFlyInFlyImpl() calls CopyLayoutFormat() with bMakeFrames=true, but the frame format list doesn't contain as-char frames. For as-char frames CopyLayoutFormat() is called by SwTextFlyCnt::CopyFlyFormat() instead, but with bMakeFrames=false, so the fly frame's layout frame were never made. Fix the problem by explicitly making frames in DocumentLayoutManager::CopyLayoutFormat(), which also requires delete+make in SwTextFlyCnt::SetAnchor(). [ This is now consistent with the start of SwTextFlyCnt::SetAnchor(), which also deletes frames for fly frame formats. Otherwise CppunitTest_sw_core_txtnode would crash in testTextBoxCopyAnchor. ] (cherry picked from commit feeaa5d3ca0c784344549816fbaab2c8716b4105) Change-Id: I87003ee09ca75b9fecd70a1aa5c42f762f715be8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114832 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--sw/qa/core/doc/data/textbox-makeflyframe.docxbin0 -> 25642 bytes
-rw-r--r--sw/qa/core/doc/doc.cxx36
-rw-r--r--sw/source/core/doc/DocumentLayoutManager.cxx8
-rw-r--r--sw/source/core/txtnode/atrflyin.cxx9
4 files changed, 53 insertions, 0 deletions
diff --git a/sw/qa/core/doc/data/textbox-makeflyframe.docx b/sw/qa/core/doc/data/textbox-makeflyframe.docx
new file mode 100644
index 000000000000..9e26cda3c6a6
--- /dev/null
+++ b/sw/qa/core/doc/data/textbox-makeflyframe.docx
Binary files differ
diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index 1bd9b4207444..14f724328fe0 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -16,6 +16,8 @@
#include <vcl/errinf.hxx>
#include <vcl/event.hxx>
#include <editeng/langitem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
#include <wrtsh.hxx>
#include <fmtanchr.hxx>
@@ -24,6 +26,9 @@
#include <edtwin.hxx>
#include <view.hxx>
#include <ndtxt.hxx>
+#include <swdtflvr.hxx>
+#include <cmdid.h>
+#include <unotxdoc.hxx>
char const DATA_DIRECTORY[] = "/sw/qa/core/doc/data/";
@@ -129,6 +134,37 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testTextBoxZOrder)
CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(2), pEllipseShape->GetOrdNum());
}
+CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testTextBoxMakeFlyFrame)
+{
+ // Given a document with an as-char textbox (as-char draw format + at-char fly format):
+ SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "textbox-makeflyframe.docx");
+
+ // When cutting the textbox and pasting it to a new document:
+ SwView* pView = pDoc->GetDocShell()->GetView();
+ pView->GetViewFrame()->GetDispatcher()->Execute(FN_CNTNT_TO_NEXT_FRAME, SfxCallMode::SYNCHRON);
+ pView->StopShellTimer();
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable(*pWrtShell);
+ pTransfer->Cut();
+ TransferableDataHelper aHelper(pTransfer.get());
+ uno::Reference<lang::XComponent> xDoc2
+ = loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument", {});
+ SwXTextDocument* pTextDoc2 = dynamic_cast<SwXTextDocument*>(xDoc2.get());
+ SwDocShell* pDocShell2 = pTextDoc2->GetDocShell();
+ SwWrtShell* pWrtShell2 = pDocShell2->GetWrtShell();
+ SwTransferable::Paste(*pWrtShell2, aHelper);
+
+ // Then make sure its fly frame is created.
+ mxComponent->dispose();
+ mxComponent = xDoc2;
+ xmlDocUniquePtr pLayout = parseLayoutDump();
+ // Without the accompanying fix in place, this test would have failed, because the first text
+ // frame in the body frame had an SwAnchoredDrawObject anchored to it, but not a fly frame, so
+ // a blank square was painted, not the image.
+ assertXPath(pLayout, "/root/page/body/txt/anchored/fly", 1);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx b/sw/source/core/doc/DocumentLayoutManager.cxx
index 7df5d2871f91..08dcdc80b540 100644
--- a/sw/source/core/doc/DocumentLayoutManager.cxx
+++ b/sw/source/core/doc/DocumentLayoutManager.cxx
@@ -474,6 +474,14 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat(
// presumably these anchors are supported though not sure
assert(RndStdIds::FLY_AT_CHAR == boxAnchor.GetAnchorId() || RndStdIds::FLY_AT_PARA == boxAnchor.GetAnchorId()
|| boxAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE);
+
+ if (!bMakeFrames && rNewAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
+ {
+ // If the draw format is as-char, then it will be copied with bMakeFrames=false, but
+ // doing the same for the fly format would result in not making fly frames at all.
+ bMakeFrames = true;
+ }
+
SwFrameFormat* pDestTextBox = CopyLayoutFormat(*pSourceTextBox,
boxAnchor, bSetTextFlyAtt, bMakeFrames);
SwAttrSet aSet(pDest->GetAttrSet());
diff --git a/sw/source/core/txtnode/atrflyin.cxx b/sw/source/core/txtnode/atrflyin.cxx
index d04da840d8e4..2207d1337b18 100644
--- a/sw/source/core/txtnode/atrflyin.cxx
+++ b/sw/source/core/txtnode/atrflyin.cxx
@@ -217,6 +217,11 @@ void SwTextFlyCnt::SetAnchor( const SwTextNode *pNode )
{
pTextBox->LockModify();
}
+ else
+ {
+ // Otherwise delete fly frames on anchor change.
+ pTextBox->DelFrames();
+ }
pTextBox->SetFormatAttr(aTextBoxAnchor);
@@ -226,6 +231,10 @@ void SwTextFlyCnt::SetAnchor( const SwTextNode *pNode )
aPos.nNode.GetNode().AddAnchoredFly(pTextBox);
pTextBox->UnlockModify();
}
+ else
+ {
+ pTextBox->MakeFrames();
+ }
}
}