diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2021-04-26 21:01:45 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2021-04-29 10:29:19 +0200 |
commit | e8bba2f28851c8826f003f893dcad75115017940 (patch) | |
tree | c04023288ff2b8a87eb3e8b0fac1ae73b3ca5d23 | |
parent | 46b7d1d707b47e03163c5bcbbaa54ca49980f64a (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.docx | bin | 0 -> 25642 bytes | |||
-rw-r--r-- | sw/qa/core/doc/doc.cxx | 36 | ||||
-rw-r--r-- | sw/source/core/doc/DocumentLayoutManager.cxx | 8 | ||||
-rw-r--r-- | sw/source/core/txtnode/atrflyin.cxx | 9 |
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 Binary files differnew file mode 100644 index 000000000000..9e26cda3c6a6 --- /dev/null +++ b/sw/qa/core/doc/data/textbox-makeflyframe.docx 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(); + } } } |