diff options
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/extras/layout/layout.cxx | 58 | ||||
-rw-r--r-- | sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx | 30 |
2 files changed, 88 insertions, 0 deletions
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 59e1e08939e0..2110eed1e31c 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -3096,6 +3096,64 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf127235) pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout(); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testShapeAllowOverlap) +{ +// Need to find out why this fails on macOS. +#ifndef MACOSX + // Create an empty document with two, intentionally overlapping shapes. + // Set their AllowOverlap property to false. + loadURL("private:factory/swriter", nullptr); + uno::Reference<lang::XMultiServiceFactory> xDocument(mxComponent, uno::UNO_QUERY); + awt::Point aPoint(1000, 1000); + awt::Size aSize(2000, 2000); + uno::Reference<drawing::XShape> xShape( + xDocument->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY); + xShape->setPosition(aPoint); + xShape->setSize(aSize); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xDocument, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShapeProperties(xShape, uno::UNO_QUERY); + xShapeProperties->setPropertyValue("AllowOverlap", uno::makeAny(false)); + xShapeProperties->setPropertyValue("AnchorType", + uno::makeAny(text::TextContentAnchorType_AT_CHARACTER)); + xDrawPageSupplier->getDrawPage()->add(xShape); + + aPoint = awt::Point(2000, 2000); + xShape.set(xDocument->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY); + xShape->setPosition(aPoint); + xShape->setSize(aSize); + xShapeProperties.set(xShape, uno::UNO_QUERY); + xShapeProperties->setPropertyValue("AllowOverlap", uno::makeAny(false)); + xShapeProperties->setPropertyValue("AnchorType", + uno::makeAny(text::TextContentAnchorType_AT_CHARACTER)); + xDrawPageSupplier->getDrawPage()->add(xShape); + + // Now verify that the rectangle of the anchored objects don't overlap. + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + SwFrame* pPageFrame = pLayout->GetLower(); + SwFrame* pBodyFrame = pPageFrame->GetLower(); + SwFrame* pTextFrame = pBodyFrame->GetLower(); + CPPUNIT_ASSERT(pTextFrame->GetDrawObjs()); + SwSortedObjs& rObjs = *pTextFrame->GetDrawObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rObjs.size()); + SwAnchoredObject* pFirst = rObjs[0]; + SwAnchoredObject* pSecond = rObjs[1]; + // Without the accompanying fix in place, this test would have failed: the layout dump was + // <bounds left="1984" top="1984" width="1137" height="1137"/> + // <bounds left="2551" top="2551" width="1137" height="1137"/> + // so there was a clear vertical overlap. (Allow for 1px tolerance.) + OString aMessage("Unexpected overlap: first shape's bottom is "); + aMessage += OString::number(pFirst->GetObjRect().Bottom()); + aMessage += ", second shape's top is "; + aMessage += OString::number(pSecond->GetObjRect().Top()); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), + std::abs(pFirst->GetObjRect().Bottom() - pSecond->GetObjRect().Top()) + < 15); +#endif +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx index 25424dfaa3f3..f26b48ac0a98 100644 --- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx +++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx @@ -42,6 +42,8 @@ #include <frmtool.hxx> #include <ndtxt.hxx> #include <dflyobj.hxx> +#include <fmtwrapinfluenceonobjpos.hxx> +#include <sortedobjs.hxx> using namespace objectpositioning; using namespace ::com::sun::star; @@ -971,6 +973,34 @@ void SwToContentAnchoredObjectPosition::CalcPosition() // keep layout frame vertical position is oriented at. mpVertPosOrientFrame = pUpperOfOrientFrame; + // If it was requested to not overlap with already formatted objects, take care of that + // here. + bool bAllowOverlap = rFrameFormat.GetWrapInfluenceOnObjPos().GetAllowOverlap(); + if (!bAllowOverlap) + { + // Get the list of objects. + const SwSortedObjs& rSortedObjs = *pAnchorFrameForVertPos->GetDrawObjs(); + for (const auto& pAnchoredObj : rSortedObjs) + { + if (pAnchoredObj == &GetAnchoredObj()) + { + // We found ourselves, stop iterating. + break; + } + + if (!GetAnchoredObj().GetObjRect().IsOver(pAnchoredObj->GetObjRect())) + { + // Found an already positioned object, but it doesn't overlap, ignore. + continue; + } + + // Already formatted, overlaps: resolve the conflict by shifting ourselves down. + SwTwips nYDiff + = pAnchoredObj->GetObjRect().Bottom() - GetAnchoredObj().GetObjRect().Top(); + aRelPos.setY(aRelPos.getY() + nYDiff + 1); + GetAnchoredObj().SetObjTop(nTopOfAnch + aRelPos.Y()); + } + } } // determine 'horizontal' position |