diff options
author | Attila Bakos (NISZ) <bakos.attilakaroly@nisz.hu> | 2021-02-22 14:28:59 +0100 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2021-03-02 12:14:28 +0100 |
commit | 6edeb6a8209a990e83f07c02753d606226f59be7 (patch) | |
tree | 7fe435fb78a6db03782b3ab75280433bc65e7f57 | |
parent | e941720d5c3e6a555c2405d5f8d9de6c37150e27 (diff) |
Textboxes anchored "As Character" fell apart, when
typing before some characters or inserting a page break.
By fixing that, the tdf#138598 bug also have fixed which
was a regression from commit b6850bbe95418ecfde404be1696548f18d200c9b
(tdf#106153 sw compatibility: fix textboxes exceeding the page).
In addition, tdf140598 is also fixed, which was
a regression from commit c96c386c5db45dc4d5e358915caad7474e373068
(tdf#136516 add positioning to SwTextBoxHelper::syncProperty()).
Change-Id: Ifeadd8b2055ce52a019d651369ca41185de7bbe3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111338
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111796
Tested-by: Jenkins
-rw-r--r-- | sw/inc/textboxhelper.hxx | 5 | ||||
-rwxr-xr-x | sw/qa/extras/uiwriter/data3/AsCharTxBxTest.docx | bin | 0 -> 19888 bytes | |||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter3.cxx | 52 | ||||
-rw-r--r-- | sw/source/core/doc/textboxhelper.cxx | 137 | ||||
-rw-r--r-- | sw/source/core/text/porfly.cxx | 32 |
5 files changed, 204 insertions, 22 deletions
diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx index 45d8a6c56f5d..2043b1ffcfb3 100644 --- a/sw/inc/textboxhelper.hxx +++ b/sw/inc/textboxhelper.hxx @@ -16,6 +16,8 @@ #include <com/sun/star/uno/Any.h> #include <com/sun/star/uno/Type.h> +#include <com/sun/star/text/TextContentAnchorType.hpp> +#include <svx/swframetypes.hxx> #include "swdllapi.h" @@ -71,6 +73,9 @@ public: static void getProperty(SwFrameFormat const* pShape, sal_uInt16 nWID, sal_uInt8 nMemberID, css::uno::Any& rValue); + /// There are two types of enum of anchor type, so this function maps this. + static css::text::TextContentAnchorType mapAnchorType(const RndStdIds& rAnchorID); + /// Similar to syncProperty(), but used by the internal API (e.g. for UI purposes). static void syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& rSet); diff --git a/sw/qa/extras/uiwriter/data3/AsCharTxBxTest.docx b/sw/qa/extras/uiwriter/data3/AsCharTxBxTest.docx Binary files differnew file mode 100755 index 000000000000..7603b80d2c2d --- /dev/null +++ b/sw/qa/extras/uiwriter/data3/AsCharTxBxTest.docx diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx index e568e695000a..018a96a78ee6 100644 --- a/sw/qa/extras/uiwriter/uiwriter3.cxx +++ b/sw/qa/extras/uiwriter/uiwriter3.cxx @@ -725,6 +725,58 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf134253) CPPUNIT_ASSERT_EQUAL(6, getPages()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, TestAsCharTextBox) +{ + // Releated tickets: + // 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. + + load(DATA_DIRECTORY, "AsCharTxBxTest.docx"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + + // Add 3x tab to the doc + pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); + pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); + pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); + Scheduler::ProcessEventsToIdle(); + + auto pExportDump = parseLayoutDump(); + CPPUNIT_ASSERT(pExportDump); + + // Check if the texbox fallen apart due to the tabs + const double nLeftSideOfShape1 + = getXPath(pExportDump, "/root/page/body/txt/anchored/SwAnchoredDrawObject/bounds", "left") + .toDouble(); + const double nLeftSideOfTxBx1 + = getXPath(pExportDump, "/root/page/body/txt/anchored/fly/infos/bounds", "left").toDouble(); + + CPPUNIT_ASSERT(nLeftSideOfShape1 < nLeftSideOfTxBx1); + + // Another test is for the tdf#138598: Check footer textbox + const double nLeftSideOfShape2 + = getXPath(pExportDump, "/root/page[2]/footer/txt/anchored/SwAnchoredDrawObject/bounds", + "left") + .toDouble(); + const double nLeftSideOfTxBx2 + = getXPath(pExportDump, "/root/page[2]/footer/txt/anchored/fly/infos/bounds", "left") + .toDouble(); + + CPPUNIT_ASSERT(nLeftSideOfShape2 < nLeftSideOfTxBx2); + + const double nTopSideOfShape2 + = getXPath(pExportDump, "/root/page[2]/footer/txt/anchored/SwAnchoredDrawObject/bounds", + "top") + .toDouble(); + const double nTopSideOfTxBx2 + = getXPath(pExportDump, "/root/page[2]/footer/txt/anchored/fly/infos/bounds", "top") + .toDouble(); + + CPPUNIT_ASSERT(nTopSideOfShape2 < nTopSideOfTxBx2); + // Without the fix in place the two texboxes has been fallen apart, and asserts will broken. +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf76636) { load(DATA_DIRECTORY, "tdf76636.doc"); diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index 4d44d1c35ff8..5257d448bd55 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -33,6 +33,7 @@ #include <editeng/memberids.h> #include <svx/svdoashp.hxx> #include <svx/svdpage.hxx> +#include <svx/swframetypes.hxx> #include <svl/itemiter.hxx> #include <comphelper/sequenceashashmap.hxx> #include <sal/log.hxx> @@ -686,10 +687,39 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u if (aValue.get<text::TextContentAnchorType>() == text::TextContentAnchorType::TextContentAnchorType_AS_CHARACTER) { - xPropertySet->setPropertyValue( - UNO_NAME_ANCHOR_TYPE, - uno::makeAny( - text::TextContentAnchorType::TextContentAnchorType_AT_CHARACTER)); + if (const auto aPos = pShape->GetAnchor().GetContentAnchor()) + { + xPropertySet->setPropertyValue( + UNO_NAME_ANCHOR_TYPE, + uno::makeAny(text::TextContentAnchorType:: + TextContentAnchorType_AT_CHARACTER)); + xPropertySet->setPropertyValue( + UNO_NAME_HORI_ORIENT_RELATION, + uno::makeAny(text::RelOrientation::CHAR)); + + auto pAnch = pFormat->GetAnchor(); + pAnch.SetAnchor(pShape->GetAnchor().GetContentAnchor()); + tools::Rectangle aRect(getTextRectangle(pShape, false)); + + SwFormatHoriOrient aNewHOri(pFormat->GetHoriOrient()); + aNewHOri.SetPos(aRect.getX()); + + SwFormatVertOrient aNewVOri(pFormat->GetVertOrient()); + aNewVOri.SetPos(aRect.getY()); + + pFormat->SetFormatAttr(pAnch); + // tdf#140598: Do not apply wrong rectangle position. + if (aRect.TopLeft() != Point(0, 0)) + { + pFormat->SetFormatAttr(aNewHOri); + pFormat->SetFormatAttr(aNewVOri); + } + else + SAL_WARN("sw.core", + "SwTextBoxHelper::syncProperty: Repositioning failed!"); + } + + return; } else // Otherwise copy the anchor type of the shape { @@ -699,11 +729,55 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u if (aValue.get<text::TextContentAnchorType>() == text::TextContentAnchorType::TextContentAnchorType_AT_PAGE) { - xPropertySet->setPropertyValue( - UNO_NAME_ANCHOR_PAGE_NO, - uno::makeAny(pShape->GetAnchor().GetPageNum())); + if (pShape->GetAnchor().GetPageNum()) + xPropertySet->setPropertyValue( + UNO_NAME_ANCHOR_PAGE_NO, + uno::makeAny(pShape->GetAnchor().GetPageNum())); + else + { + SAL_WARN("sw.core", "SwTextBoxHelper::syncProperty: Invalid Page Num!"); + return; + } } + // At-Content Anchors have to be synced: + if (aValue.get<text::TextContentAnchorType>() + == text::TextContentAnchorType::TextContentAnchorType_AT_PARAGRAPH + || aValue.get<text::TextContentAnchorType>() + == text::TextContentAnchorType::TextContentAnchorType_AT_CHARACTER) + { + // If the shape has content... + if (auto aPos = pShape->GetAnchor().GetContentAnchor()) + { + SwFormatAnchor aAnch(pFormat->GetAnchor()); + // ...set it for the textframe too. + aAnch.SetAnchor(aPos); + pFormat->SetFormatAttr(aAnch); + } + else + SAL_WARN("sw.core", + "SwTextBoxHelper::syncProperty: Anchor without content!"); + } + // And the repositioning: + if (pShape->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR) + { + tools::Rectangle aRect(getTextRectangle(pShape, false)); + + // tdf#140598: Do not apply wrong rectangle position. + if (aRect.TopLeft() != Point(0, 0)) + { + SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient()); + aNewHOri.SetPos(aNewHOri.GetPos() + aRect.getX()); + SwFormatVertOrient aNewVOri(pShape->GetVertOrient()); + aNewVOri.SetPos(aNewVOri.GetPos() + aRect.getY()); + + pFormat->SetFormatAttr(aNewHOri); + pFormat->SetFormatAttr(aNewVOri); + } + else + SAL_WARN("sw.core", + "SwTextBoxHelper::syncProperty: Repositioning failed!"); + } return; } break; @@ -834,12 +908,41 @@ void SwTextBoxHelper::restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrame } } +text::TextContentAnchorType SwTextBoxHelper::mapAnchorType(const RndStdIds& rAnchorID) +{ + text::TextContentAnchorType aAnchorType; + switch (rAnchorID) + { + case RndStdIds::FLY_AS_CHAR: + aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AS_CHARACTER; + break; + case RndStdIds::FLY_AT_CHAR: + aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_CHARACTER; + break; + case RndStdIds::FLY_AT_PARA: + aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_PARAGRAPH; + break; + case RndStdIds::FLY_AT_PAGE: + aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_PAGE; + break; + case RndStdIds::FLY_AT_FLY: + aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_FRAME; + break; + default: + aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_PARAGRAPH; + SAL_WARN("sw.core", "SwTextBoxHelper::mapAnchorType: Unknown AnchorType!"); + break; + } + return aAnchorType; +} + void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& rSet) { SwFrameFormat* pFormat = getOtherTextBoxFormat(&rShape, RES_DRAWFRMFMT); if (!pFormat) return; + const bool bInlineAnchored = rShape.GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR; SfxItemSet aTextBoxSet(pFormat->GetDoc()->GetAttrPool(), aFrameFormatSetRange); SfxItemIter aIter(rSet); @@ -861,6 +964,13 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& { case RES_VERT_ORIENT: { + // The new position can be with anchor changing so sync it! + const text::TextContentAnchorType aNewAnchorType + = mapAnchorType(rShape.GetAnchor().GetAnchorId()); + syncProperty(&rShape, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE, uno::Any(aNewAnchorType)); + if (bInlineAnchored) + return; + auto& rOrient = static_cast<const SwFormatVertOrient&>(*pItem); SwFormatVertOrient aOrient(rOrient); @@ -885,6 +995,8 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& case RES_HORI_ORIENT: { auto& rOrient = static_cast<const SwFormatHoriOrient&>(*pItem); + if (bInlineAnchored) + return; SwFormatHoriOrient aOrient(rOrient); tools::Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false); @@ -910,11 +1022,14 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& tools::Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false); if (!aRect.IsEmpty()) { - aVertOrient.SetPos(aVertOrient.GetPos() + aRect.getY()); - aTextBoxSet.Put(aVertOrient); + if (!bInlineAnchored) + { + aVertOrient.SetPos(aVertOrient.GetPos() + aRect.getY()); + aHoriOrient.SetPos(aHoriOrient.GetPos() + aRect.getX()); - aHoriOrient.SetPos(aHoriOrient.GetPos() + aRect.getX()); - aTextBoxSet.Put(aHoriOrient); + aTextBoxSet.Put(aVertOrient); + aTextBoxSet.Put(aHoriOrient); + } aSize.SetWidth(aRect.getWidth()); aSize.SetHeight(aRect.getHeight()); diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx index 24961c08b68d..cafa70c48227 100644 --- a/sw/source/core/text/porfly.cxx +++ b/sw/source/core/text/porfly.cxx @@ -352,20 +352,30 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase, // is relative to the print area of the anchor text frame. tools::Rectangle aTextRectangle = SwTextBoxHelper::getTextRectangle(pShape); - SwFormatHoriOrient aHori(pTextBox->GetHoriOrient()); - aHori.SetHoriOrient(css::text::HoriOrientation::NONE); - sal_Int32 nLeft = aTextRectangle.getX() - rFrame.getFrameArea().Left() - - rFrame.getFramePrintArea().Left(); - aHori.SetPos(nLeft); - + const auto aPos(pShape->GetAnchor().GetContentAnchor()); SwFormatVertOrient aVert(pTextBox->GetVertOrient()); - aVert.SetVertOrient(css::text::VertOrientation::NONE); - sal_Int32 const nTop = aTextRectangle.getY() - rFrame.getFrameArea().Top() - - rFrame.getFramePrintArea().Top(); - aVert.SetPos(nTop); + + // 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. + if (!aPos->nNode.GetNode().FindFooterStartNode()) + { + aVert.SetVertOrient(css::text::VertOrientation::NONE); + sal_Int32 const nTop = aTextRectangle.getY() - rFrame.getFrameArea().Top() + - rFrame.getFramePrintArea().Top(); + aVert.SetPos(nTop); + } + else + { + aVert.SetVertOrient(css::text::VertOrientation::NONE); + aVert.SetPos(SwTextBoxHelper::getTextRectangle(pShape, false).getY()); + } + + SwFormatAnchor aNewTxBxAnchor(pTextBox->GetAnchor()); + aNewTxBxAnchor.SetAnchor(aPos); pTextBox->LockModify(); - pTextBox->SetFormatAttr(aHori); + pTextBox->SetFormatAttr(aNewTxBxAnchor); pTextBox->SetFormatAttr(aVert); pTextBox->UnlockModify(); } |