diff options
author | Justin Luth <justin.luth@collabora.com> | 2023-04-12 08:57:36 -0400 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2023-04-12 21:33:00 +0200 |
commit | 1f53c056c4bdd403a709f72263168137d7bdb1c0 (patch) | |
tree | d5c174b5dc22bf8e18e83f1703b6d34c8b53a042 | |
parent | 9fd195881bd79c6b3ed09167e8d0af2769e72071 (diff) |
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 <jluth@mail.com>
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
-rw-r--r-- | sw/inc/textboxhelper.hxx | 17 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 18 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlimport/ooxmlimport2.cxx | 4 | ||||
-rw-r--r-- | sw/qa/extras/uiwriter/data/tdf147126.docx | bin | 39793 -> 0 bytes | |||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter3.cxx | 132 | ||||
-rw-r--r-- | sw/source/core/doc/textboxhelper.cxx | 281 | ||||
-rw-r--r-- | sw/source/core/frmedt/feshview.cxx | 8 | ||||
-rw-r--r-- | sw/source/core/text/porfly.cxx | 56 | ||||
-rw-r--r-- | xmloff/qa/unit/draw.cxx | 2 |
9 files changed, 235 insertions, 283 deletions
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 Binary files differdeleted file mode 100644 index 01ad39b345f4..000000000000 --- a/sw/qa/extras/uiwriter/data/tdf147126.docx +++ /dev/null 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; |