dev/null |binary sw/inc/frmfmt.hxx | 6 sw/inc/textboxhelper.hxx | 26 + sw/qa/extras/ooxmlexport/ooxmlexport14.cxx | 6 sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 18 - sw/qa/extras/ooxmlimport/ooxmlimport2.cxx | 4 sw/qa/extras/uiwriter/uiwriter3.cxx | 132 --------- sw/source/core/doc/DocumentLayoutManager.cxx | 8 sw/source/core/doc/docdraw.cxx | 29 -- sw/source/core/doc/textboxhelper.cxx | 373 +++++++++++++------------- sw/source/core/draw/dcontact.cxx | 2 sw/source/core/frmedt/feshview.cxx | 8 sw/source/core/layout/atrfrm.cxx | 31 +- sw/source/core/text/porfly.cxx | 56 +++ sw/source/core/undo/undobj1.cxx | 22 - sw/source/core/undo/undraw.cxx | 32 +- xmloff/qa/unit/draw.cxx | 2 17 files changed, 338 insertions(+), 417 deletions(-)
New commits: commit 1f53c056c4bdd403a709f72263168137d7bdb1c0 Author: Justin Luth <[email protected]> AuthorDate: Wed Apr 12 08:57:36 2023 -0400 Commit: Andras Timar <[email protected]> CommitDate: Wed Apr 12 21:33:00 2023 +0200 Revert "tdf#147126 sw: fix missing as_char anchoring of group textboxes" This reverts commit 341e397d970d10281fbc9691874b4441a841837d. It was added for T38690 and removed for T41585 Change-Id: I39cd0711047a131a3d60106b8682097411318781 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150293 Reviewed-by: Justin Luth <[email protected]> Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx index fd194a639bcc..1a0cadabc0e9 100644 --- a/sw/inc/textboxhelper.hxx +++ b/sw/inc/textboxhelper.hxx @@ -92,6 +92,10 @@ public: /// Copy shape attributes to the text frame static void updateTextBoxMargin(SdrObject* pObj); + /// Sets the surround to through for the textframe of the given shape, + /// not to interfere with the layout. Returns true on success. + static bool setWrapThrough(SwFrameFormat* pShape); + /// Sets the anchor of the associated textframe of the given shape, and /// returns true on success. static bool changeAnchor(SwFrameFormat* pShape, SdrObject* pObj); @@ -100,9 +104,19 @@ public: /// returns true on success. static bool doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pObj); + /// Returns true if the anchor different for the given shape, and the + /// associated textframe of the given shape. + /// Note: In case of AS_CHAR anchor the anchor type must be different, + /// because if not, layout breaks, but this situation also handled by + /// this function, and returns true in that case too. + static std::optional<bool> isAnchorTypeDifferent(const SwFrameFormat* pShape); + /// Sets the correct size of textframe depending on the given SdrObject. static bool syncTextBoxSize(SwFrameFormat* pShape, SdrObject* pObj); + /// Returns true if the given shape has a valid textframe. + static bool isTextBoxShapeHasValidTextFrame(const SwFrameFormat* pShape); + // Returns true on success. Synchronize z-order of the text frame of the given textbox // by setting it one level higher than the z-order of the shape of the textbox. static bool DoTextBoxZOrderCorrection(SwFrameFormat* pShape, const SdrObject* pObj); @@ -174,8 +188,7 @@ public: /// Calls the method given by pFunc with every textboxes of the group given by pFormat. static void synchronizeGroupTextBoxProperty(bool pFunc(SwFrameFormat*, SdrObject*), SwFrameFormat* pFormat, SdrObject* pObj); - - /// Collect all textboxes of the group given by the pGroupObj Parameter. Returns with a + /// Collect all textboxes of the group given by the pGoupObj Parameter. Returns with a /// vector filled with the textboxes. static std::vector<SwFrameFormat*> CollectTextBoxes(SdrObject* pGroupObject, SwFrameFormat* pFormat); diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index b84b9ef1f9d6..3747aa399a27 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -400,16 +400,14 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testFdo78910, "fdo78910.docx") assertXPath ( pXmlDoc, "//w:hyperlink[2]/w:r[5]/w:fldChar", "fldCharType", "end" ); } -// FIXME: During this test a pure VML shape get converted to DML and crash at verifying. -// CPPUNIT_TEST_FIXTURE(Test, testFDO78590) -// DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testFDO78590, "FDO78590.docx") -// { -// xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); -// -// // This is to ensure that the fld starts and ends inside a hyperlink... -// assertXPath ( pXmlDoc, "/w:document/w:body/w:p[1]/w:pPr/w:framePr", "w", "9851" ); -// assertXPath ( pXmlDoc, "/w:document/w:body/w:p[1]/w:pPr/w:framePr", "h", "1669" ); -// } +DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testFDO78590, "FDO78590.docx") +{ + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + + // This is to ensure that the fld starts and ends inside a hyperlink... + assertXPath ( pXmlDoc, "/w:document/w:body/w:p[1]/w:pPr/w:framePr", "w", "9851" ); + assertXPath ( pXmlDoc, "/w:document/w:body/w:p[1]/w:pPr/w:framePr", "h", "1669" ); +} DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testSdtCitationRun, "sdt-citation-run.docx") { diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx index 2736775b2c81..232b67ab4056 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx @@ -246,10 +246,10 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf114212) { load(mpTestDocumentPath, "tdf114212.docx"); // Without the accompanying fix in place, this test would have failed with: - // - Expected: 1428 + // - Expected: 1427 // - Actual : 387 OUString aTop = parseDump("//anchored/fly[1]/infos/bounds", "top"); - CPPUNIT_ASSERT_EQUAL(OUString("1428"), aTop); + CPPUNIT_ASSERT_EQUAL(OUString("1427"), aTop); } CPPUNIT_TEST_FIXTURE(Test, testTdf109524) diff --git a/sw/qa/extras/uiwriter/data/tdf147126.docx b/sw/qa/extras/uiwriter/data/tdf147126.docx deleted file mode 100644 index 01ad39b345f4..000000000000 Binary files a/sw/qa/extras/uiwriter/data/tdf147126.docx and /dev/null differ diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx index 563b631727a0..a1a1272ae23d 100644 --- a/sw/qa/extras/uiwriter/uiwriter3.cxx +++ b/sw/qa/extras/uiwriter/uiwriter3.cxx @@ -158,138 +158,6 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testVariableFieldTableRowSplitHeader) assertXPath(pXmlDoc, "/root/page[5]/footer/txt[1]/Special[1]", "rText", "4"); } -CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf147126) -{ - createSwDoc(DATA_DIRECTORY, "tdf147126.docx"); - CPPUNIT_ASSERT(mxComponent); - SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); - CPPUNIT_ASSERT(pTextDoc); - - const auto pLayoutXML1 = parseLayoutDump(); - - for (auto nFly = 1; nFly < 8; ++nFly) - { - const auto nFlyLeft = getXPath(pLayoutXML1, - OString::Concat("/root/page/body/txt[2]/anchored/fly[") - + OString::Concat(OString::number(nFly)) - + OString::Concat("]/infos/bounds"), - "left") - .toInt64(); - const auto nFlyRight = getXPath(pLayoutXML1, - OString::Concat("/root/page/body/txt[2]/anchored/fly[") - + OString::Concat(OString::number(nFly)) - + OString::Concat("]/infos/bounds"), - "width") - .toInt64(); - const auto nFlyTop = getXPath(pLayoutXML1, - OString::Concat("/root/page/body/txt[2]/anchored/fly[") - + OString::Concat(OString::number(nFly)) - + OString::Concat("]/infos/bounds"), - "top") - .toInt64(); - const auto nFlyBottom = getXPath(pLayoutXML1, - OString::Concat("/root/page/body/txt[2]/anchored/fly[") - + OString::Concat(OString::number(nFly)) - + OString::Concat("]/infos/bounds"), - "height") - .toInt64(); - - const auto sDrawRect = getXPath( - pLayoutXML1, - OString::Concat("/root/page/body/txt[2]/anchored/SwAnchoredDrawObject/SdrObjGroup/" - "SdrObjList/SdrObject[") - + OString::Concat(OString::number(nFly)) + OString::Concat("]"), - "aOutRect"); - - const auto nComaPos1 = sDrawRect.indexOf(',', 0); - const auto nComaPos2 = sDrawRect.indexOf(',', nComaPos1 + 1); - const auto nComaPos3 = sDrawRect.indexOf(',', nComaPos2 + 1); - - const auto nDraw1 = OUString(sDrawRect.subView(0, nComaPos1).data()).toInt64(); - const auto nDraw2 - = OUString(sDrawRect.subView(nComaPos1 + 1, nComaPos2 - nComaPos1).data()).toInt64(); - const auto nDraw3 - = OUString(sDrawRect.subView(nComaPos2 + 1, nComaPos3 - nComaPos2).data()).toInt64(); - const auto nDraw4 - = OUString( - sDrawRect.subView(nComaPos3 + 1, sDrawRect.getLength() - nComaPos3 - 1).data()) - .toInt64(); - - CPPUNIT_ASSERT_GREATER(nDraw1, nFlyLeft); - CPPUNIT_ASSERT_GREATER(nDraw2, nFlyTop); - CPPUNIT_ASSERT_LESS(nDraw3, nFlyRight); - CPPUNIT_ASSERT_LESS(nDraw4, nFlyBottom); - } - - for (auto nLineBreakCount = 0; nLineBreakCount < 4; ++nLineBreakCount) - { - pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN); - Scheduler::ProcessEventsToIdle(); - } - for (auto nSpaceCount = 0; nSpaceCount < 10; ++nSpaceCount) - { - pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_SPACE); - Scheduler::ProcessEventsToIdle(); - } - - dumpLayout(mxComponent); - const auto pLayoutXML2 = parseLayoutDump(); - - for (auto nFly = 1; nFly < 8; ++nFly) - { - const auto nFlyLeft = getXPath(pLayoutXML2, - OString::Concat("/root/page/body/txt[6]/anchored/fly[") - + OString::Concat(OString::number(nFly)) - + OString::Concat("]/infos/bounds"), - "left") - .toInt64(); - const auto nFlyRight = getXPath(pLayoutXML2, - OString::Concat("/root/page/body/txt[6]/anchored/fly[") - + OString::Concat(OString::number(nFly)) - + OString::Concat("]/infos/bounds"), - "width") - .toInt64(); - const auto nFlyTop = getXPath(pLayoutXML2, - OString::Concat("/root/page/body/txt[6]/anchored/fly[") - + OString::Concat(OString::number(nFly)) - + OString::Concat("]/infos/bounds"), - "top") - .toInt64(); - const auto nFlyBottom = getXPath(pLayoutXML2, - OString::Concat("/root/page/body/txt[6]/anchored/fly[") - + OString::Concat(OString::number(nFly)) - + OString::Concat("]/infos/bounds"), - "height") - .toInt64(); - - const auto sDrawRect = getXPath( - pLayoutXML2, - OString::Concat("/root/page/body/txt[6]/anchored/SwAnchoredDrawObject/SdrObjGroup/" - "SdrObjList/SdrObject[") - + OString::Concat(OString::number(nFly)) + OString::Concat("]"), - "aOutRect"); - - const auto nComaPos1 = sDrawRect.indexOf(',', 0); - const auto nComaPos2 = sDrawRect.indexOf(',', nComaPos1 + 1); - const auto nComaPos3 = sDrawRect.indexOf(',', nComaPos2 + 1); - - const auto nDraw1 = OUString(sDrawRect.subView(0, nComaPos1).data()).toInt64(); - const auto nDraw2 - = OUString(sDrawRect.subView(nComaPos1 + 1, nComaPos2 - nComaPos1).data()).toInt64(); - const auto nDraw3 - = OUString(sDrawRect.subView(nComaPos2 + 1, nComaPos3 - nComaPos2).data()).toInt64(); - const auto nDraw4 - = OUString( - sDrawRect.subView(nComaPos3 + 1, sDrawRect.getLength() - nComaPos3 - 1).data()) - .toInt64(); - - CPPUNIT_ASSERT_GREATER(nDraw1, nFlyLeft); - CPPUNIT_ASSERT_GREATER(nDraw2, nFlyTop); - CPPUNIT_ASSERT_LESS(nDraw3, nFlyRight); - CPPUNIT_ASSERT_LESS(nDraw4, nFlyBottom); - } -} - CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf129382) { SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf129382.docx"); diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index b09e98f343a7..1b9155f9b6e8 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -318,9 +318,6 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj, } // Do sync for the new textframe. synchronizeGroupTextBoxProperty(&changeAnchor, pShapeFormat, pObj); - synchronizeGroupTextBoxProperty(&syncTextBoxSize, pShapeFormat, pObj); - - updateTextBoxMargin(pObj); } void SwTextBoxHelper::destroy(const SwFrameFormat* pShape, const SdrObject* pObject) @@ -869,7 +866,10 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u { case MID_ANCHOR_ANCHORTYPE: { + setWrapThrough(pShape); changeAnchor(pShape, pObj); + doTextBoxPositioning(pShape, pObj); + return; } break; @@ -1183,6 +1183,7 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& if (aTextBoxSet.Count()) pFormat->SetFormatAttr(aTextBoxSet); + //pFormat->GetDoc()->SetFlyFrameAttr(*pFormat, aTextBoxSet); DoTextBoxZOrderCorrection(&rShape, pObj); } @@ -1202,35 +1203,67 @@ void SwTextBoxHelper::updateTextBoxMargin(SdrObject* pObj) // Sync the padding syncProperty(pParentFormat, UNO_NAME_TEXT_LEFTDIST, - xPropertySet->getPropertyValue(UNO_NAME_TEXT_LEFTDIST), pObj); + xPropertySet->getPropertyValue(UNO_NAME_TEXT_LEFTDIST)); syncProperty(pParentFormat, UNO_NAME_TEXT_RIGHTDIST, - xPropertySet->getPropertyValue(UNO_NAME_TEXT_RIGHTDIST), pObj); + xPropertySet->getPropertyValue(UNO_NAME_TEXT_RIGHTDIST)); syncProperty(pParentFormat, UNO_NAME_TEXT_UPPERDIST, - xPropertySet->getPropertyValue(UNO_NAME_TEXT_UPPERDIST), pObj); + xPropertySet->getPropertyValue(UNO_NAME_TEXT_UPPERDIST)); syncProperty(pParentFormat, UNO_NAME_TEXT_LOWERDIST, - xPropertySet->getPropertyValue(UNO_NAME_TEXT_LOWERDIST), pObj); + xPropertySet->getPropertyValue(UNO_NAME_TEXT_LOWERDIST)); // Sync the text aligning syncProperty(pParentFormat, UNO_NAME_TEXT_VERTADJUST, - xPropertySet->getPropertyValue(UNO_NAME_TEXT_VERTADJUST), pObj); + xPropertySet->getPropertyValue(UNO_NAME_TEXT_VERTADJUST)); syncProperty(pParentFormat, UNO_NAME_TEXT_HORZADJUST, - xPropertySet->getPropertyValue(UNO_NAME_TEXT_HORZADJUST), pObj); + xPropertySet->getPropertyValue(UNO_NAME_TEXT_HORZADJUST)); // tdf137803: Sync autogrow: const bool bIsAutoGrow = xPropertySet->getPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT).get<bool>(); const bool bIsAutoWrap = xPropertySet->getPropertyValue(UNO_NAME_TEXT_WORDWRAP).get<bool>(); - syncProperty(pParentFormat, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, uno::Any(bIsAutoGrow), - pObj); + syncProperty(pParentFormat, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, uno::Any(bIsAutoGrow)); syncProperty(pParentFormat, RES_FRM_SIZE, MID_FRMSIZE_WIDTH_TYPE, - uno::Any(bIsAutoWrap ? text::SizeType::FIX : text::SizeType::MIN), pObj); + uno::Any(bIsAutoWrap ? text::SizeType::FIX : text::SizeType::MIN)); changeAnchor(pParentFormat, pObj); DoTextBoxZOrderCorrection(pParentFormat, pObj); } +bool SwTextBoxHelper::setWrapThrough(SwFrameFormat* pShape) +{ + OUString sErrMsg; + if (isTextBoxShapeHasValidTextFrame(pShape)) + { + if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) + { + ::sw::UndoGuard const UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo()); + if (auto xFrame = SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat)) + try + { + uno::Reference<beans::XPropertySet> const xPropertySet(xFrame, uno::UNO_QUERY); + xPropertySet->setPropertyValue(UNO_NAME_SURROUND, + uno::makeAny(text::WrapTextMode_THROUGH)); + return true; + } + catch (uno::Exception& e) + { + sErrMsg = "Exception caught: " + e.Message; + } + else + sErrMsg = "No XTextFrame!"; + } + else + sErrMsg = "No Other TextBox Format!"; + } + else + sErrMsg = "Not a Valid TextBox object!"; + + SAL_WARN("sw.core", "SwTextBoxHelper::setWrapThrough: " << sErrMsg); + return false; +} + bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) { if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj)) @@ -1244,68 +1277,72 @@ bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj) const uno::Any aShapeHorRelOrient = uno::makeAny(pShape->GetHoriOrient().GetRelationOrient()); - try + if (isAnchorTypeDifferent(pShape) || (pObj && pObj != pShape->FindRealSdrObject())) { - ::sw::UndoGuard const UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo()); - uno::Reference<beans::XPropertySet> const xPropertySet( - SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY); - if (pOldCnt && rNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE - && rNewAnch.GetPageNum()) - { - uno::Any aValue(text::TextContentAnchorType_AT_PAGE); - xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, aShapeHorRelOrient); - xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); - xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_PAGE_NO, - uno::Any(rNewAnch.GetPageNum())); - } - else if (rOldAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE && pNewCnt) + try { - if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR) - { - uno::Any aValue(text::TextContentAnchorType_AT_CHARACTER); - xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); - xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, - uno::Any(text::RelOrientation::CHAR)); - xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, - uno::Any(text::RelOrientation::PRINT_AREA)); - SwFormatAnchor aPos(pFormat->GetAnchor()); - aPos.SetAnchor(pNewCnt); - pFormat->SetFormatAttr(aPos); - } - else + ::sw::UndoGuard const UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo()); + uno::Reference<beans::XPropertySet> const xPropertySet( + SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat), uno::UNO_QUERY); + if (pOldCnt && rNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE + && rNewAnch.GetPageNum()) { - uno::Any aValue(mapAnchorType(rNewAnch.GetAnchorId())); + uno::Any aValue(text::TextContentAnchorType_AT_PAGE); xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, aShapeHorRelOrient); xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); - pFormat->SetFormatAttr(rNewAnch); + xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_PAGE_NO, + uno::Any(rNewAnch.GetPageNum())); } - } - else - { - if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR) + else if (rOldAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE && pNewCnt) { - uno::Any aValue(text::TextContentAnchorType_AT_CHARACTER); - xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); - xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, - uno::Any(text::RelOrientation::CHAR)); - xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, - uno::Any(text::RelOrientation::PRINT_AREA)); - SwFormatAnchor aPos(pFormat->GetAnchor()); - aPos.SetAnchor(pNewCnt); - pFormat->SetFormatAttr(aPos); + if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR) + { + uno::Any aValue(text::TextContentAnchorType_AT_CHARACTER); + xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); + xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, + uno::Any(text::RelOrientation::CHAR)); + xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, + uno::Any(text::RelOrientation::PRINT_AREA)); + SwFormatAnchor aPos(pFormat->GetAnchor()); + aPos.SetAnchor(pNewCnt); + pFormat->SetFormatAttr(aPos); + } + else + { + uno::Any aValue(mapAnchorType(rNewAnch.GetAnchorId())); + xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, + aShapeHorRelOrient); + xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); + pFormat->SetFormatAttr(rNewAnch); + } } else { - xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, - aShapeHorRelOrient); - pFormat->SetFormatAttr(pShape->GetAnchor()); + if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR) + { + uno::Any aValue(text::TextContentAnchorType_AT_CHARACTER); + xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue); + xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, + uno::Any(text::RelOrientation::CHAR)); + xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, + uno::Any(text::RelOrientation::PRINT_AREA)); + SwFormatAnchor aPos(pFormat->GetAnchor()); + aPos.SetAnchor(pNewCnt); + pFormat->SetFormatAttr(aPos); + } + else + { + xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, + aShapeHorRelOrient); + pFormat->SetFormatAttr(pShape->GetAnchor()); + } } } - } - catch (uno::Exception& e) - { - SAL_WARN("sw.core", "SwTextBoxHelper::changeAnchor(): " << e.Message); + catch (uno::Exception& e) + { + SAL_WARN("sw.core", "SwTextBoxHelper::changeAnchor(): " << e.Message); + } } return doTextBoxPositioning(pShape, pObj) && DoTextBoxZOrderCorrection(pShape, pObj); @@ -1328,80 +1365,42 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb auto nLeftSpace = pShape->GetLRSpace().GetLeft(); SwFormatHoriOrient aNewHOri(pFormat->GetHoriOrient()); - aNewHOri.SetPos(aRect.Left() + nLeftSpace - + (bIsGroupObj ? pObj->GetRelativePos().getX() : 0)); + aNewHOri.SetPos(aRect.Left() + nLeftSpace); + SwFormatVertOrient aNewVOri(pFormat->GetVertOrient()); + aNewVOri.SetPos(aRect.Top() + pShape->GetVertOrient().GetPos()); - if (bIsGroupObj) + // tdf#140598: Do not apply wrong rectangle position. + if (aRect.TopLeft() != Point(0, 0)) { - aNewVOri.SetPos( - ((pObj->GetRelativePos().getY()) > 0 - ? (pShape->GetVertOrient().GetPos() > 0 - ? pObj->GetRelativePos().getY() - : pObj->GetRelativePos().getY() - pShape->GetVertOrient().GetPos()) - : (pShape->GetVertOrient().GetPos() > 0 - ? 0 // Is this can be a variation? - : pObj->GetRelativePos().getY() - pShape->GetVertOrient().GetPos())) - + aRect.Top()); + pFormat->SetFormatAttr(aNewHOri); + pFormat->SetFormatAttr(aNewVOri); } else - { - aNewVOri.SetPos( - ((pShape->GetVertOrient().GetPos()) > 0 ? pShape->GetVertOrient().GetPos() : 0) - + aRect.Top()); - } - - if (pShape->GetVertOrient().GetVertOrient() != text::VertOrientation::NONE) - { - aNewVOri.SetVertOrient(text::VertOrientation::NONE); - switch (pShape->GetVertOrient().GetVertOrient()) - { - case text::VertOrientation::TOP: - case text::VertOrientation::CHAR_TOP: - case text::VertOrientation::LINE_TOP: - { - aNewVOri.SetPos(aNewVOri.GetPos() - pShape->GetFrameSize().GetHeight()); - break; - } - case text::VertOrientation::BOTTOM: - case text::VertOrientation::CHAR_BOTTOM: - case text::VertOrientation::LINE_BOTTOM: - { - aNewVOri.SetPos(aNewVOri.GetPos() + pShape->GetFrameSize().GetHeight()); - break; - } - case text::VertOrientation::CENTER: - case text::VertOrientation::CHAR_CENTER: - case text::VertOrientation::LINE_CENTER: - { - aNewVOri.SetPos(aNewVOri.GetPos() - + std::lroundf(pShape->GetFrameSize().GetHeight() / 2)); - break; - } - default: - break; - } - } - - pFormat->SetFormatAttr(aNewHOri); - pFormat->SetFormatAttr(aNewVOri); + SAL_WARN("sw.core", "SwTextBoxHelper::syncProperty: Repositioning failed!"); } else { tools::Rectangle aRect( getTextRectangle(pObj ? pObj : pShape->FindRealSdrObject(), false)); - SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient()); - aNewHOri.SetPos( - (bIsGroupObj && pObj ? pObj->GetRelativePos().getX() : aNewHOri.GetPos()) - + aRect.Left()); - SwFormatVertOrient aNewVOri(pShape->GetVertOrient()); - aNewVOri.SetPos( - (bIsGroupObj && pObj ? pObj->GetRelativePos().getY() : aNewVOri.GetPos()) - + aRect.Top()); - - pFormat->SetFormatAttr(aNewHOri); - pFormat->SetFormatAttr(aNewVOri); + // tdf#140598: Do not apply wrong rectangle position. + if (aRect.TopLeft() != Point(0, 0) || bIsGroupObj) + { + SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient()); + aNewHOri.SetPos( + (bIsGroupObj && pObj ? pObj->GetRelativePos().getX() : aNewHOri.GetPos()) + + aRect.Left()); + SwFormatVertOrient aNewVOri(pShape->GetVertOrient()); + aNewVOri.SetPos( + (bIsGroupObj && pObj ? pObj->GetRelativePos().getY() : aNewVOri.GetPos()) + + aRect.Top()); + + pFormat->SetFormatAttr(aNewHOri); + pFormat->SetFormatAttr(aNewVOri); + } + else + SAL_WARN("sw.core", "SwTextBoxHelper::syncProperty: Repositioning failed!"); } return true; } @@ -1409,6 +1408,23 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb return false; } +std::optional<bool> SwTextBoxHelper::isAnchorTypeDifferent(const SwFrameFormat* pShape) +{ + std::optional<bool> bRet; + if (isTextBoxShapeHasValidTextFrame(pShape)) + { + if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) + { + if (pShape->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR) + bRet = (pFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AT_CHAR + && pFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR); + else + bRet = pFormat->GetAnchor().GetAnchorId() != pShape->GetAnchor().GetAnchorId(); + } + } + return bRet; +} + bool SwTextBoxHelper::syncTextBoxSize(SwFrameFormat* pShape, SdrObject* pObj) { if (!pShape || !pObj) @@ -1428,6 +1444,23 @@ bool SwTextBoxHelper::syncTextBoxSize(SwFrameFormat* pShape, SdrObject* pObj) return false; } +bool SwTextBoxHelper::isTextBoxShapeHasValidTextFrame(const SwFrameFormat* pShape) +{ + if (pShape && pShape->Which() == RES_DRAWFRMFMT) + if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT)) + if (pFormat && pFormat->Which() == RES_FLYFRMFMT) + return true; + else + SAL_WARN("sw.core", "SwTextBoxHelper::isTextBoxShapeHasValidTextFrame: " + "Shape does not have valid textframe!"); + else + SAL_WARN("sw.core", "SwTextBoxHelper::isTextBoxShapeHasValidTextFrame: " + "Shape does not have associated frame!"); + else + SAL_WARN("sw.core", "SwTextBoxHelper::isTextBoxShapeHasValidTextFrame: Not valid shape!"); + return false; +} + bool SwTextBoxHelper::DoTextBoxZOrderCorrection(SwFrameFormat* pShape, const SdrObject* pObj) { // TODO: do this with group shape textboxes. diff --git a/sw/source/core/frmedt/feshview.cxx b/sw/source/core/frmedt/feshview.cxx index d74bc7e1c2cf..eab41d781c7a 100644 --- a/sw/source/core/frmedt/feshview.cxx +++ b/sw/source/core/frmedt/feshview.cxx @@ -1070,7 +1070,7 @@ void SwFEShell::SelectionToTop( bool bTop ) if (auto pFormat = FindFrameFormat(pObj)) { // If it has not textframe skip... - if (!SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT, pObj)) + if (!SwTextBoxHelper::isTextBoxShapeHasValidTextFrame(pFormat)) continue; // If it has a textframe so it is a textbox, get its page if (auto pDrwModel @@ -1100,7 +1100,7 @@ void SwFEShell::SelectionToTop( bool bTop ) // If this object is a textbox, two level increasing needed // (one for the shape and one for the frame) if (auto pNextFormat = FindFrameFormat(pNextObj)) - if (SwTextBoxHelper::isTextBox(pNextFormat, RES_DRAWFRMFMT, pNextObj) + if (SwTextBoxHelper::isTextBox(pNextFormat, RES_DRAWFRMFMT) || SwTextBoxHelper::isTextBox(pNextFormat, RES_FLYFRMFMT)) nShift++; } @@ -1139,7 +1139,7 @@ void SwFEShell::SelectionToBottom( bool bBottom ) if (auto pFormat = FindFrameFormat(pObj)) { // If the shape has not textframes skip. - if (!SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT, pObj)) + if (!SwTextBoxHelper::isTextBoxShapeHasValidTextFrame(pFormat)) continue; // If has, move the shape to correct level with... if (auto pDrwModel @@ -1152,7 +1152,7 @@ void SwFEShell::SelectionToBottom( bool bBottom ) { // If the lower has no textframe, just do nothing, else move by one lower if (auto pNextFormat = FindFrameFormat(pNextObj)) - if (SwTextBoxHelper::isTextBox(pNextFormat, RES_DRAWFRMFMT, pNextObj) + if (SwTextBoxHelper::isTextBox(pNextFormat, RES_DRAWFRMFMT) || SwTextBoxHelper::isTextBox(pNextFormat, RES_FLYFRMFMT)) pPage->SetObjectOrdNum(pObj->GetOrdNum(), pObj->GetOrdNum() - 1); } diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx index fc1b28f990d4..fc540731a975 100644 --- a/sw/source/core/text/porfly.cxx +++ b/sw/source/core/text/porfly.cxx @@ -26,7 +26,6 @@ #include <frmfmt.hxx> #include <viewsh.hxx> #include <textboxhelper.hxx> -#include <IDocumentState.hxx> #include <frmatr.hxx> #include <sal/log.hxx> @@ -364,15 +363,56 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase, aObjPositioning.CalcPosition(); } - if (auto pFormat = FindFrameFormat(pSdrObj)) + SwFrameFormat* pShape = FindFrameFormat(pSdrObj); + const SwFormatAnchor& rAnchor(pShape->GetAnchor()); + if (rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) { - if (pFormat->GetOtherTextBoxFormat()) + // This is an inline draw shape, see if it has a textbox. + SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT); + if (pTextBox) { - const bool bModified = pFormat->GetDoc()->getIDocumentState().IsEnableSetModified(); - pFormat->GetDoc()->getIDocumentState().SetEnableSetModified(false); - SwTextBoxHelper::synchronizeGroupTextBoxProperty(SwTextBoxHelper::changeAnchor, pFormat, - pFormat->FindRealSdrObject()); - pFormat->GetDoc()->getIDocumentState().SetEnableSetModified(bModified); + // It has, so look up its text rectangle, and adjust the position + // of the textbox accordingly. + // Both rectangles are absolute, SwFormatHori/VertOrient's position + // is relative to the print area of the anchor text frame. + tools::Rectangle aTextRectangle = SwTextBoxHelper::getTextRectangle(pSdrObj); + + const auto aPos(pShape->GetAnchor().GetContentAnchor()); + SwFormatVertOrient aVert(pTextBox->GetVertOrient()); + SwFormatHoriOrient aHori(pTextBox->GetHoriOrient()); + + // tdf#138598 Replace vertical alignment of As_char textboxes in footer + // tdf#140158 Remove horizontal positioning of As_char textboxes, because + // the anchor moving does the same for it. + const bool bIsInHeaderFooter = aPos->nNode.GetNode().FindFooterStartNode(); + // TODO: Find solution for Group Shapes in Header/Footer. + tools::Long nXoffs + = SwTextBoxHelper::getTextRectangle( + bIsInHeaderFooter ? pShape->FindRealSdrObject() : pSdrObj, false) + .Left(); + if (!bIsInHeaderFooter) + { + aVert.SetVertOrient(css::text::VertOrientation::NONE); + aVert.SetRelationOrient(css::text::RelOrientation::FRAME); + auto const nTop = aTextRectangle.Top() - rFrame.getFrameArea().Top() + - rFrame.getFramePrintArea().Top(); + aVert.SetPos(nTop); + } + else + { + aVert.SetVertOrient(css::text::VertOrientation::NONE); + aVert.SetPos(SwTextBoxHelper::getTextRectangle(pShape->FindRealSdrObject(), false).Top()); + } + + SwFormatAnchor aNewTxBxAnchor(pTextBox->GetAnchor()); + aNewTxBxAnchor.SetAnchor(aPos); + aHori.SetPos(nXoffs + pShape->GetLRSpace().GetLeft()); + + pTextBox->LockModify(); + pTextBox->SetFormatAttr(aNewTxBxAnchor); + pTextBox->SetFormatAttr(aVert); + pTextBox->SetFormatAttr(aHori); + pTextBox->UnlockModify(); } } diff --git a/xmloff/qa/unit/draw.cxx b/xmloff/qa/unit/draw.cxx index 114d1cb204f2..3f80c1770900 100644 --- a/xmloff/qa/unit/draw.cxx +++ b/xmloff/qa/unit/draw.cxx @@ -138,7 +138,7 @@ CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testTextBoxLoss) // Make sure that the shape is still a textbox. uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(getComponent(), uno::UNO_QUERY); uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); - uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(1), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); bool bTextBox = false; xShape->getPropertyValue("TextBox") >>= bTextBox; commit 9fd195881bd79c6b3ed09167e8d0af2769e72071 Author: Justin Luth <[email protected]> AuthorDate: Wed Apr 12 08:39:02 2023 -0400 Commit: Andras Timar <[email protected]> CommitDate: Wed Apr 12 21:32:52 2023 +0200 Revert "tdf#147485 sw: fix group shape crash using std::shared_ptr" This reverts commit 044c63c631f0af832aa8452bc4a8b0b38dc91c23. It was added for T38690 and removed for T41585 Change-Id: I0010c40e486843e942fb958982e60ea92fddbb3c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150292 Reviewed-by: Justin Luth <[email protected]> Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> diff --git a/sw/inc/frmfmt.hxx b/sw/inc/frmfmt.hxx index 808bbb482e5d..59aee54a2f4a 100644 --- a/sw/inc/frmfmt.hxx +++ b/sw/inc/frmfmt.hxx @@ -74,7 +74,7 @@ class SW_DLLPUBLIC SwFrameFormat // The assigned SwFrmFmt list. SwFrameFormats *m_ffList; - std::shared_ptr< SwTextBoxNode > m_pOtherTextBoxFormats; + SwTextBoxNode* m_pOtherTextBoxFormat; struct change_name { @@ -102,8 +102,8 @@ protected: public: - const std::shared_ptr< SwTextBoxNode >& GetOtherTextBoxFormats() const { return m_pOtherTextBoxFormats; }; - void SetOtherTextBoxFormats(const std::shared_ptr<SwTextBoxNode>& rNew) { m_pOtherTextBoxFormats = rNew; }; + SwTextBoxNode* GetOtherTextBoxFormat() const { return m_pOtherTextBoxFormat; }; + void SetOtherTextBoxFormat(SwTextBoxNode* pNew) { m_pOtherTextBoxFormat = pNew; }; virtual ~SwFrameFormat() override; diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx index a389634c60eb..fd194a639bcc 100644 --- a/sw/inc/textboxhelper.hxx +++ b/sw/inc/textboxhelper.hxx @@ -214,7 +214,7 @@ public: ~SwTextBoxNode(); // default copy ctor is enough - SwTextBoxNode(const SwTextBoxNode&) = default; + SwTextBoxNode(SwTextBoxNode&) = default; // This method adds a textbox entry to the shape // Parameters: @@ -225,12 +225,7 @@ public: // This will remove the textbox entry. // Parameters: // pDrawObject: The shape which have the textbox to be deleted. - void DelTextBox(const SdrObject* pDrawObject, bool bDelFromDoc = false); - - // This will remove the textbox entry. - // Parameters: - // pTextBox: The textbox what have to be deleted. - void DelTextBox(const SwFrameFormat* pTextBox, bool bDelFromDoc = false); + void DelTextBox(const SdrObject* pDrawObject); // This will return with the frame format of the textbox what belongs // to the given shape (pDrawObject) diff --git a/sw/qa/extras/ooxmlexport/data/Tdf147485.docx b/sw/qa/extras/ooxmlexport/data/Tdf147485.docx deleted file mode 100644 index cb630efb8717..000000000000 Binary files a/sw/qa/extras/ooxmlexport/data/Tdf147485.docx and /dev/null differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx index d3feaf95f720..ffa1968648ef 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx @@ -843,12 +843,6 @@ CPPUNIT_TEST_FIXTURE(SwModelTestBase, testSemiTransparentText) CPPUNIT_ASSERT_EQUAL(nTransparence, nActual); } -CPPUNIT_TEST_FIXTURE(SwModelTestBase, testTdf147485) -{ - // Before the fix this was impossible. - load(DATA_DIRECTORY, "Tdf147485.docx"); -} - CPPUNIT_TEST_FIXTURE(SwModelTestBase, testUserField) { // Create an in-memory empty document with a user field. diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx b/sw/source/core/doc/DocumentLayoutManager.cxx index 006501b3aa36..c67e9e05e9a6 100644 --- a/sw/source/core/doc/DocumentLayoutManager.cxx +++ b/sw/source/core/doc/DocumentLayoutManager.cxx @@ -464,11 +464,11 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( pDest->MakeFrames(); // If the draw format has a TextBox, then copy its fly format as well. - if (rSource.Which() == RES_DRAWFRMFMT && rSource.GetOtherTextBoxFormats()) + if (rSource.Which() == RES_DRAWFRMFMT && rSource.GetOtherTextBoxFormat()) { auto pObj = rSource.FindRealSdrObject(); - auto pTextBoxNd = std::make_shared<SwTextBoxNode>(SwTextBoxNode(pDest)); - pDest->SetOtherTextBoxFormats(pTextBoxNd); + auto pTextBoxNd = new SwTextBoxNode(pDest); + pDest->SetOtherTextBoxFormat(pTextBoxNd); if (pObj) { @@ -515,7 +515,7 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( && pNewObj->getChildrenOfSdrObject()->GetObj(it)) pNewObj = pNewObj->getChildrenOfSdrObject()->GetObj(it); pTextBoxNd->AddTextBox(pNewObj, pDestTextBox); - pDestTextBox->SetOtherTextBoxFormats(pTextBoxNd); + pDestTextBox->SetOtherTextBoxFormat(pTextBoxNd); } if (!bIsGroupObj) diff --git a/sw/source/core/doc/docdraw.cxx b/sw/source/core/doc/docdraw.cxx index cd1883ee346b..6445ab757a0e 100644 --- a/sw/source/core/doc/docdraw.cxx +++ b/sw/source/core/doc/docdraw.cxx @@ -225,7 +225,7 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView ) #endif // Before the format will be killed, save its textbox for later use. if (auto pShapeFormat = pContact->GetFormat()) - if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormats()) + if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormat()) for (const auto& rTextBoxElement : pTextBoxNode->GetAllTextBoxes()) vSavedTextBoxes.emplace(rTextBoxElement); @@ -255,15 +255,14 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView ) text::PositionLayoutDir::PositionInLayoutDirOfAnchor ); // Add the saved textboxes to the new format. - auto pTextBoxNode = std::make_shared<SwTextBoxNode>( - SwTextBoxNode(static_cast<SwFrameFormat*>(pFormat))); + auto pTextBoxNode = new SwTextBoxNode(pFormat); for (const auto& pTextBoxEntry : vSavedTextBoxes) { pTextBoxNode->AddTextBox(const_cast<SdrObject*>(pTextBoxEntry.first), pTextBoxEntry.second); - pTextBoxEntry.second->SetOtherTextBoxFormats(pTextBoxNode); + pTextBoxEntry.second->SetOtherTextBoxFormat(pTextBoxNode); } - pFormat->SetOtherTextBoxFormats(pTextBoxNode); + pFormat->SetOtherTextBoxFormat(pTextBoxNode); vSavedTextBoxes.clear(); rDrawView.GroupMarked(); @@ -303,7 +302,7 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView ) return pNewContact; } -static void lcl_CollectTextBoxesForSubGroupObj(SwFrameFormat* pTargetFormat, std::shared_ptr<SwTextBoxNode> pTextBoxNode, +static void lcl_CollectTextBoxesForSubGroupObj(SwFrameFormat* pTargetFormat, SwTextBoxNode* pTextBoxNode, SdrObject* pSourceObjs) { if (auto pChildrenObjs = pSourceObjs->getChildrenOfSdrObject()) @@ -313,12 +312,12 @@ static void lcl_CollectTextBoxesForSubGroupObj(SwFrameFormat* pTargetFormat, std { if (auto pTextBox = pTextBoxNode->GetTextBox(pSourceObjs)) { - if (!pTargetFormat->GetOtherTextBoxFormats()) + if (!pTargetFormat->GetOtherTextBoxFormat()) { - pTargetFormat->SetOtherTextBoxFormats(std::make_shared<SwTextBoxNode>(SwTextBoxNode(pTargetFormat))); + pTargetFormat->SetOtherTextBoxFormat(new SwTextBoxNode(pTargetFormat)); } - pTargetFormat->GetOtherTextBoxFormats()->AddTextBox(pSourceObjs, pTextBox); - pTextBox->SetOtherTextBoxFormats(pTargetFormat->GetOtherTextBoxFormats()); + pTargetFormat->GetOtherTextBoxFormat()->AddTextBox(pSourceObjs, pTextBox); + pTextBox->SetOtherTextBoxFormat(pTargetFormat->GetOtherTextBoxFormat()); } } } @@ -352,9 +351,9 @@ void SwDoc::UnGroupSelection( SdrView& rDrawView ) { SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall(pObj)); - std::shared_ptr<SwTextBoxNode> pTextBoxNode; + SwTextBoxNode* pTextBoxNode = nullptr; if (auto pGroupFormat = pContact->GetFormat()) - pTextBoxNode = pGroupFormat->GetOtherTextBoxFormats(); + pTextBoxNode = pGroupFormat->GetOtherTextBoxFormat(); SwFormatAnchor aAnch( pContact->GetFormat()->GetAnchor() ); SdrObjList *pLst = pObjGroup->GetSubList(); @@ -379,10 +378,10 @@ void SwDoc::UnGroupSelection( SdrView& rDrawView ) { if (auto pTextBoxFormat = pTextBoxNode->GetTextBox(pSubObj)) { - auto pNewTextBoxNode =std::make_shared<SwTextBoxNode>(SwTextBoxNode(pFormat)); + auto pNewTextBoxNode = new SwTextBoxNode(pFormat); pNewTextBoxNode->AddTextBox(pSubObj, pTextBoxFormat); - pFormat->SetOtherTextBoxFormats(pNewTextBoxNode); - pTextBoxFormat->SetOtherTextBoxFormats(pNewTextBoxNode); + pFormat->SetOtherTextBoxFormat(pNewTextBoxNode); + pTextBoxFormat->SetOtherTextBoxFormat(pNewTextBoxNode); } } else diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index 41ca905f5d19..b09e98f343a7 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -67,7 +67,7 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo const bool bIsGroupObj = dynamic_cast<SdrObjGroup*>(pObject->getParentSdrObjectFromSdrObject()); // If TextBox wasn't enabled previously - if (pShape->GetOtherTextBoxFormats() && pShape->GetOtherTextBoxFormats()->GetTextBox(pObject)) + if (pShape->GetOtherTextBoxFormat() && pShape->GetOtherTextBoxFormat()->GetTextBox(pObject)) return; // Store the current text content of the shape @@ -104,19 +104,19 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo assert(nullptr != dynamic_cast<SwDrawFrameFormat*>(pShape)); assert(nullptr != dynamic_cast<SwFlyFrameFormat*>(pFormat)); - if (!pShape->GetOtherTextBoxFormats()) + if (!pShape->GetOtherTextBoxFormat()) { - auto pTextBox = std::make_shared<SwTextBoxNode>(SwTextBoxNode(pShape)); + auto* pTextBox = new SwTextBoxNode(pShape); pTextBox->AddTextBox(pObject, pFormat); - pShape->SetOtherTextBoxFormats(pTextBox); - pFormat->SetOtherTextBoxFormats(pTextBox); + pShape->SetOtherTextBoxFormat(pTextBox); + pFormat->SetOtherTextBoxFormat(pTextBox); } else { - auto pTextBox = pShape->GetOtherTextBoxFormats(); + auto* pTextBox = pShape->GetOtherTextBoxFormat(); pTextBox->AddTextBox(pObject, pFormat); - pShape->SetOtherTextBoxFormats(pTextBox); - pFormat->SetOtherTextBoxFormats(pTextBox); + pShape->SetOtherTextBoxFormat(pTextBox); + pFormat->SetOtherTextBoxFormat(pTextBox); } // Initialize properties. uno::Reference<beans::XPropertySet> xPropertySet(xTextFrame, uno::UNO_QUERY); @@ -212,7 +212,7 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj, return; std::vector<std::pair<beans::Property, uno::Any>> aOldProps; // If there is a format, check if the shape already has a textbox assigned to. - if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormats()) + if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormat()) { // If it has a texbox, destroy it. if (pTextBoxNode->GetTextBox(pObj)) @@ -241,16 +241,16 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj, } // And set the new one. pTextBoxNode->AddTextBox(pObj, pFormat); - pFormat->SetOtherTextBoxFormats(pTextBoxNode); + pFormat->SetOtherTextBoxFormat(pTextBoxNode); } else { // If the shape do not have a texbox node and textbox, // create that for the shape. - auto pTextBox = std::shared_ptr<SwTextBoxNode>(new SwTextBoxNode(pShapeFormat)); + auto* pTextBox = new SwTextBoxNode(pShapeFormat); pTextBox->AddTextBox(pObj, pFormat); - pShapeFormat->SetOtherTextBoxFormats(pTextBox); - pFormat->SetOtherTextBoxFormats(pTextBox); + pShapeFormat->SetOtherTextBoxFormat(pTextBox); + pFormat->SetOtherTextBoxFormat(pTextBox); } // Initialize its properties uno::Reference<beans::XPropertySet> xPropertySet(xNew, uno::UNO_QUERY); @@ -326,14 +326,14 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj, void SwTextBoxHelper::destroy(const SwFrameFormat* pShape, const SdrObject* pObject) { // If a TextBox was enabled previously - auto pTextBox = pShape->GetOtherTextBoxFormats(); + auto pTextBox = pShape->GetOtherTextBoxFormat(); if (pTextBox && pTextBox->IsTextBoxActive(pObject)) { // Unlink the TextBox's text range from the original shape. pTextBox->SetTextBoxInactive(pObject); // Delete the associated TextFrame. - pTextBox->DelTextBox(pObject, true); + pTextBox->DelTextBox(pObject); } } @@ -345,7 +345,7 @@ bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pFormat, sal_uInt16 nType, if (!pFormat || pFormat->Which() != nType) return false; - auto pTextBox = pFormat->GetOtherTextBoxFormats(); + auto pTextBox = pFormat->GetOtherTextBoxFormat(); if (!pTextBox) return false; @@ -464,14 +464,14 @@ SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(const SwFrameFormat* pForm if (nType == RES_DRAWFRMFMT) { if (pObject) - return pFormat->GetOtherTextBoxFormats()->GetTextBox(pObject); + return pFormat->GetOtherTextBoxFormat()->GetTextBox(pObject); if (pFormat->FindRealSdrObject()) - return pFormat->GetOtherTextBoxFormats()->GetTextBox(pFormat->FindRealSdrObject()); + return pFormat->GetOtherTextBoxFormat()->GetTextBox(pFormat->FindRealSdrObject()); return nullptr; } if (nType == RES_FLYFRMFMT) { - return pFormat->GetOtherTextBoxFormats()->GetOwnerShape(); + return pFormat->GetOtherTextBoxFormat()->GetOwnerShape(); } return nullptr; } @@ -1530,7 +1530,13 @@ SwTextBoxNode::SwTextBoxNode(SwFrameFormat* pOwnerShape) m_pTextBoxes.clear(); } -SwTextBoxNode::~SwTextBoxNode() { m_pTextBoxes.clear(); } +SwTextBoxNode::~SwTextBoxNode() +{ + m_pTextBoxes.clear(); + + if (m_pOwnerShapeFormat && m_pOwnerShapeFormat->GetOtherTextBoxFormat()) + m_pOwnerShapeFormat->SetOtherTextBoxFormat(nullptr); +} void SwTextBoxNode::AddTextBox(SdrObject* pDrawObject, SwFrameFormat* pNewTextBox) { @@ -1551,7 +1557,7 @@ void SwTextBoxNode::AddTextBox(SdrObject* pDrawObject, SwFrameFormat* pNewTextBo m_pTextBoxes.push_back(aElem); } -void SwTextBoxNode::DelTextBox(const SdrObject* pDrawObject, bool bDelFromDoc) +void SwTextBoxNode::DelTextBox(const SdrObject* pDrawObject) { assert(pDrawObject); if (m_pTextBoxes.empty()) @@ -1561,46 +1567,10 @@ void SwTextBoxNode::DelTextBox(const SdrObject* pDrawObject, bool bDelFromDoc) { if (it->m_pDrawObject == pDrawObject) { - if (bDelFromDoc) - { - m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( - it->m_pTextBoxFormat); - // What about m_pTextBoxes? So, when the DelLayoutFormat() removes the format - // then the ~SwFrameFormat() will call this method again to remove the entry. - break; - } - else - { - it = m_pTextBoxes.erase(it); - break; - } - } - ++it; - } -} - -void SwTextBoxNode::DelTextBox(const SwFrameFormat* pTextBox, bool bDelFromDoc) -{ - if (m_pTextBoxes.empty()) - return; - - for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end();) - { - if (it->m_pTextBoxFormat == pTextBox) - { - if (bDelFromDoc) - { - m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( - it->m_pTextBoxFormat); - // What about m_pTextBoxes? So, when the DelLayoutFormat() removes the format - // then the ~SwFrameFormat() will call this method again to remove the entry. - break; - } - else - { - it = m_pTextBoxes.erase(it); - break; - } + m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( + it->m_pTextBoxFormat); + it = m_pTextBoxes.erase(it); + break; } ++it; } diff --git a/sw/source/core/draw/dcontact.cxx b/sw/source/core/draw/dcontact.cxx index d9a8bf6d2c70..e397964ba4ec 100644 --- a/sw/source/core/draw/dcontact.cxx +++ b/sw/source/core/draw/dcontact.cxx @@ -1341,7 +1341,7 @@ void SwDrawContact::Changed_( const SdrObject& rObj, // tdf#135198: keep text box together with its shape const SwPageFrame* rPageFrame = pAnchoredDrawObj->GetPageFrame(); if (rPageFrame && rPageFrame->isFrameAreaPositionValid() && GetFormat() - && GetFormat()->GetOtherTextBoxFormats()) + && GetFormat()->GetOtherTextBoxFormat()) { SwDoc* const pDoc = GetFormat()->GetDoc(); diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx index 3734963ead87..1fcf14c9f063 100644 --- a/sw/source/core/layout/atrfrm.cxx +++ b/sw/source/core/layout/atrfrm.cxx @@ -2521,7 +2521,8 @@ SwFrameFormat::SwFrameFormat( sal_uInt16 nFormatWhich, const WhichRangesContainer& pWhichRange) : SwFormat(rPool, pFormatNm, pWhichRange, pDrvdFrame, nFormatWhich), - m_ffList(nullptr) + m_ffList(nullptr), + m_pOtherTextBoxFormat(nullptr) { } @@ -2532,7 +2533,8 @@ SwFrameFormat::SwFrameFormat( sal_uInt16 nFormatWhich, const WhichRangesContainer& pWhichRange) : SwFormat(rPool, rFormatNm, pWhichRange, pDrvdFrame, nFormatWhich), - m_ffList(nullptr) + m_ffList(nullptr), + m_pOtherTextBoxFormat(nullptr) { } @@ -2547,15 +2549,24 @@ SwFrameFormat::~SwFrameFormat() } } - if( nullptr == m_pOtherTextBoxFormats ) + if( nullptr == m_pOtherTextBoxFormat ) return; - // This is a fly-frame-format just delete this - // textbox entry from the textbox collection. - if (Which() == RES_FLYFRMFMT) - m_pOtherTextBoxFormats->DelTextBox(this); + auto pObj = FindRealSdrObject(); + if (Which() == RES_FLYFRMFMT && pObj) + { + // This is a fly-frame-format just delete this + // textbox entry from the draw-frame-format. + m_pOtherTextBoxFormat->DelTextBox(pObj); + } - m_pOtherTextBoxFormats.reset(); + if (Which() == RES_DRAWFRMFMT) + { + // This format is the owner shape, so its time + // to del the textbox node. + delete m_pOtherTextBoxFormat; + m_pOtherTextBoxFormat = nullptr; + } } void SwFrameFormat::SetName( const OUString& rNewName, bool bBroadcast ) @@ -2874,9 +2885,9 @@ void SwFrameFormat::dumpAsXml(xmlTextWriterPtr pWriter) const if (pWhich) (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("which"), BAD_CAST(pWhich)); - if (m_pOtherTextBoxFormats) + if (m_pOtherTextBoxFormat) { - (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("OtherTextBoxFormat"), "%p", m_pOtherTextBoxFormats.get()); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("OtherTextBoxFormat"), "%p", m_pOtherTextBoxFormat); } GetAttrSet().dumpAsXml(pWriter); diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx index 8944abe1994d..fc1b28f990d4 100644 --- a/sw/source/core/text/porfly.cxx +++ b/sw/source/core/text/porfly.cxx @@ -366,7 +366,7 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase, if (auto pFormat = FindFrameFormat(pSdrObj)) { - if (pFormat->GetOtherTextBoxFormats()) + if (pFormat->GetOtherTextBoxFormat()) { const bool bModified = pFormat->GetDoc()->getIDocumentState().IsEnableSetModified(); pFormat->GetDoc()->getIDocumentState().SetEnableSetModified(false); diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx index fb624d68d6b0..22eefa8a55a4 100644 --- a/sw/source/core/undo/undobj1.cxx +++ b/sw/source/core/undo/undobj1.cxx @@ -56,9 +56,9 @@ SwUndoFlyBase::~SwUndoFlyBase() { if( m_bDelFormat ) // delete during an Undo? { - if (m_pFrameFormat->GetOtherTextBoxFormats()) + if (m_pFrameFormat->GetOtherTextBoxFormat()) { // clear that before delete - m_pFrameFormat->SetOtherTextBoxFormats(nullptr); + m_pFrameFormat->SetOtherTextBoxFormat(nullptr); } delete m_pFrameFormat; } @@ -139,19 +139,19 @@ void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrame) pCNd->GetTextNode()->InsertItem(aFormat, m_nContentPos, m_nContentPos, SetAttrMode::NOHINTEXPAND); } - if (m_pFrameFormat->GetOtherTextBoxFormats()) + if (m_pFrameFormat->GetOtherTextBoxFormat()) { // recklessly assume that this thing will live longer than the // SwUndoFlyBase - not sure what could be done if that isn't the case... - m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape()->SetOtherTextBoxFormats( - m_pFrameFormat->GetOtherTextBoxFormats()); + m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape()->SetOtherTextBoxFormat( + m_pFrameFormat->GetOtherTextBoxFormat()); SdrObject* pSdrObject - = m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape()->FindSdrObject(); + = m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape()->FindSdrObject(); if (pSdrObject && m_pFrameFormat->Which() == RES_FLYFRMFMT) - m_pFrameFormat->GetOtherTextBoxFormats()->AddTextBox(pSdrObject, m_pFrameFormat); + m_pFrameFormat->GetOtherTextBoxFormat()->AddTextBox(pSdrObject, m_pFrameFormat); - if (m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape()->Which() == RES_DRAWFRMFMT) + if (m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape()->Which() == RES_DRAWFRMFMT) { if (pSdrObject) @@ -164,7 +164,7 @@ void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrame) } if (m_pFrameFormat->Which() == RES_FLYFRMFMT) { - SwFrameFormat* pShapeFormat = m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape(); + SwFrameFormat* pShapeFormat = m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape(); pShapeFormat->SetFormatAttr(m_pFrameFormat->GetContent()); } } @@ -208,9 +208,9 @@ void SwUndoFlyBase::DelFly( SwDoc* pDoc ) m_bDelFormat = true; // delete Format in DTOR m_pFrameFormat->DelFrames(); // destroy Frames - if (m_pFrameFormat->GetOtherTextBoxFormats()) + if (m_pFrameFormat->GetOtherTextBoxFormat()) { // tdf#108867 clear that pointer - m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape()->SetOtherTextBoxFormats(nullptr); + m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape()->SetOtherTextBoxFormat(nullptr); } // all Uno objects should now log themselves off diff --git a/sw/source/core/undo/undraw.cxx b/sw/source/core/undo/undraw.cxx index f316858c2bfd..94146fef2a22 100644 --- a/sw/source/core/undo/undraw.cxx +++ b/sw/source/core/undo/undraw.cxx @@ -199,7 +199,7 @@ void SwUndoDrawGroup::UndoImpl(::sw::UndoRedoContext &) // This will store the textboxes what were owned by this group std::vector<std::pair<SdrObject*, SwFrameFormat*>> vTextBoxes; - if (auto pOldTextBoxNode = pFormat->GetOtherTextBoxFormats()) + if (auto pOldTextBoxNode = pFormat->GetOtherTextBoxFormat()) { if (auto pChildren = pObj->getChildrenOfSdrObject()) { @@ -240,10 +240,10 @@ void SwUndoDrawGroup::UndoImpl(::sw::UndoRedoContext &) { if (rElem.first == pObj) { - auto pNewTextBoxNode = std::make_shared<SwTextBoxNode>(SwTextBoxNode(rSave.pFormat)); - rSave.pFormat->SetOtherTextBoxFormats(pNewTextBoxNode); + auto pNewTextBoxNode = new SwTextBoxNode(rSave.pFormat); + rSave.pFormat->SetOtherTextBoxFormat(pNewTextBoxNode); pNewTextBoxNode->AddTextBox(rElem.first, rElem.second); - rElem.second->SetOtherTextBoxFormats(pNewTextBoxNode); + rElem.second->SetOtherTextBoxFormat(pNewTextBoxNode); break; } } @@ -278,7 +278,7 @@ void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &) SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall(pObj)); // Save the textboxes - if (auto pOldTextBoxNode = rSave.pFormat->GetOtherTextBoxFormats()) + if (auto pOldTextBoxNode = rSave.pFormat->GetOtherTextBoxFormat()) { if (auto pTextBox = pOldTextBoxNode->GetTextBox(pObj)) vTextBoxes.push_back(std::pair(pObj, pTextBox)); @@ -310,13 +310,13 @@ void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &) // Restore the textboxes if (vTextBoxes.size()) { - auto pNewTextBoxNode = std::make_shared<SwTextBoxNode>(SwTextBoxNode(m_pObjArray[0].pFormat)); + auto pNewTextBoxNode = new SwTextBoxNode(m_pObjArray[0].pFormat); for (auto& rElem : vTextBoxes) { pNewTextBoxNode->AddTextBox(rElem.first, rElem.second); - rElem.second->SetOtherTextBoxFormats(pNewTextBoxNode); + rElem.second->SetOtherTextBoxFormat(pNewTextBoxNode); } - m_pObjArray[0].pFormat->SetOtherTextBoxFormats(pNewTextBoxNode); + m_pObjArray[0].pFormat->SetOtherTextBoxFormat(pNewTextBoxNode); } // #i45952# - notify that position attributes are already set @@ -401,7 +401,7 @@ void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & rContext) ::lcl_SaveAnchor( rSave.pFormat, rSave.nNodeIdx ); // copy the textboxes for later use to this vector - if (auto pTxBxNd = rSave.pFormat->GetOtherTextBoxFormats()) + if (auto pTxBxNd = rSave.pFormat->GetOtherTextBoxFormat()) { if (auto pGroupObj = m_pObjArray[0].pObj) { @@ -436,13 +436,13 @@ void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & rContext) // Restore the vector content for the new formats if (vTextBoxes.size()) { - auto pNewTxBxNd = std::make_shared<SwTextBoxNode>( SwTextBoxNode(m_pObjArray[0].pFormat)); + auto pNewTxBxNd = new SwTextBoxNode(m_pObjArray[0].pFormat); for (auto& rElem : vTextBoxes) { pNewTxBxNd->AddTextBox(rElem.first, rElem.second); - rElem.second->SetOtherTextBoxFormats(pNewTxBxNd); + rElem.second->SetOtherTextBoxFormat(pNewTxBxNd); } - m_pObjArray[0].pFormat->SetOtherTextBoxFormats(pNewTxBxNd); + m_pObjArray[0].pFormat->SetOtherTextBoxFormat(pNewTxBxNd); } @@ -466,7 +466,7 @@ void SwUndoDrawUnGroup::RedoImpl(::sw::UndoRedoContext &) // Store the textboxes in this vector for later use. std::vector<std::pair<SdrObject*, SwFrameFormat*>> vTextBoxes; - if (auto pTextBoxNode = pFormat->GetOtherTextBoxFormats()) + if (auto pTextBoxNode = pFormat->GetOtherTextBoxFormat()) { auto pMasterObj = m_pObjArray[0].pObj; @@ -498,10 +498,10 @@ void SwUndoDrawUnGroup::RedoImpl(::sw::UndoRedoContext &) { if (pElem.first == rSave.pObj) { - auto pTmpTxBxNd = std::make_shared<SwTextBoxNode>(SwTextBoxNode(rSave.pFormat)); + auto pTmpTxBxNd = new SwTextBoxNode(rSave.pFormat); pTmpTxBxNd->AddTextBox(rSave.pObj, pElem.second); - pFormat->SetOtherTextBoxFormats(pTmpTxBxNd); - pElem.second->SetOtherTextBoxFormats(pTmpTxBxNd); + pFormat->SetOtherTextBoxFormat(pTmpTxBxNd); + pElem.second->SetOtherTextBoxFormat(pTmpTxBxNd); break; } }
