tdf#137185 sw: move shape text on adding textbox
The original text of the shape is moved to the new
(text frame of the) text box instead of overlapping
the text content added later.
Change-Id: I2ad8865cdbe3c424c70985737ecda3ac9315cabc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104942
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index 1c4a723..fd408c1 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -49,8 +49,9 @@ public:
using SavedLink = std::map<const SwFrameFormat*, const SwFrameFormat*>;
/// Maps a draw format to content.
using SavedContent = std::map<const SwFrameFormat*, SwFormatContent>;
/// Create a TextBox for a shape.
static void create(SwFrameFormat* pShape);
/// Create a TextBox for a shape. If the second parameter is true,
/// the original text in the shape will be copied to the frame
static void create(SwFrameFormat* pShape, bool bCopyText = false);
/// Destroy a TextBox for a shape.
static void destroy(SwFrameFormat* pShape);
/// Get interface of a shape's TextBox, if there is any.
diff --git a/sw/qa/extras/layout/data/tdf137185.odt b/sw/qa/extras/layout/data/tdf137185.odt
new file mode 100755
index 0000000..65d1f5d
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf137185.odt
Binary files differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index e303cb2..7fd1ec9 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -42,6 +42,12 @@
#include <rootfrm.hxx>
#include <docsh.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <textboxhelper.hxx>
#include <unoframe.hxx>
#include <drawdoc.hxx>
#include <svx/svdpage.hxx>
#include <dcontact.hxx>
char const DATA_DIRECTORY[] = "/sw/qa/extras/layout/data/";
@@ -2505,6 +2511,43 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf124423)
CPPUNIT_ASSERT_LESS(nPageWidth / 2, nFly1Width);
}
CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf137185)
{
// First load the sample bugdoc
load(DATA_DIRECTORY, "tdf137185.odt");
SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pTextDoc);
// Get the doc shell
SwDoc* pDoc(pTextDoc->GetDocShell()->GetDoc());
// Get the DrawObject from page
auto pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel();
CPPUNIT_ASSERT(pModel);
auto pPage = pModel->GetPage(0);
CPPUNIT_ASSERT(pModel);
auto pObj = pPage->GetObj(0);
CPPUNIT_ASSERT(pObj);
// Get the format of the draw object
auto pShape = FindFrameFormat(pObj);
CPPUNIT_ASSERT(pShape);
// Check the text of the shape
uno::Reference<text::XText> xTxt(getShape(1), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(OUString("Align me!"), xTxt->getText()->getString());
// Add a textbox to the shape
SwTextBoxHelper::create(pShape, true);
// Check if the text moved from the shape to the frame
auto pFormat = SwTextBoxHelper::getOtherTextBoxFormat(getShape(1));
auto xTextFrame = SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat);
CPPUNIT_ASSERT_EQUAL(OUString("Align me!"), xTextFrame->getText()->getString());
CPPUNIT_ASSERT_EQUAL(OUString(), xTxt->getText()->getString());
// Before the patch it failled, because the text appeared 2 times on each other.
}
CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf135035)
{
createDoc("tdf135035.docx");
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index b62269f..14fa593 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -15,6 +15,7 @@
#include <fmtfsize.hxx>
#include <doc.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <IDocumentState.hxx>
#include <docsh.hxx>
#include <unocoll.hxx>
#include <unoframe.hxx>
@@ -51,12 +52,27 @@
using namespace com::sun::star;
void SwTextBoxHelper::create(SwFrameFormat* pShape)
void SwTextBoxHelper::create(SwFrameFormat* pShape, bool bCopyText)
{
// If TextBox wasn't enabled previously
if (pShape->GetAttrSet().HasItem(RES_CNTNT) && pShape->GetOtherTextBoxFormat())
return;
// Store the current text conent of the shape
OUString sCopyableText;
if (bCopyText)
{
if (auto pSdrShape = pShape->FindRealSdrObject())
{
uno::Reference<text::XText> xSrcCnt(pSdrShape->getWeakUnoShape(), uno::UNO_QUERY);
auto xCur = xSrcCnt->createTextCursor();
xCur->gotoStart(false);
xCur->gotoEnd(true);
sCopyableText = xCur->getText()->getString();
}
}
// Create the associated TextFrame and insert it into the document.
uno::Reference<text::XTextContent> xTextFrame(
SwXServiceProvider::MakeInstance(SwServiceType::TypeTextFrame, *pShape->GetDoc()),
@@ -178,6 +194,24 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape)
if (aTxFrmSet.Count())
pFormat->SetFormatAttr(aTxFrmSet);
// Check if the shape had text before and move it to the new textframe
if (bCopyText && !sCopyableText.isEmpty())
{
auto pSdrShape = pShape->FindRealSdrObject();
if (pSdrShape)
{
auto pSourceText = dynamic_cast<SdrTextObj*>(pSdrShape);
uno::Reference<text::XTextRange> xDestText(xRealTextFrame, uno::UNO_QUERY);
xDestText->setString(sCopyableText);
if (pSourceText)
pSourceText->SetText(OUString());
pShape->GetDoc()->getIDocumentState().SetModified();
}
}
}
void SwTextBoxHelper::destroy(SwFrameFormat* pShape)
diff --git a/sw/source/uibase/shells/drawsh.cxx b/sw/source/uibase/shells/drawsh.cxx
index 0f2c454..080f322 100644
--- a/sw/source/uibase/shells/drawsh.cxx
+++ b/sw/source/uibase/shells/drawsh.cxx
@@ -351,7 +351,7 @@ void SwDrawShell::Execute(SfxRequest &rReq)
{
SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj);
if (pFrameFormat)
SwTextBoxHelper::create(pFrameFormat);
SwTextBoxHelper::create(pFrameFormat, pObj->HasText());
}
break;
}