1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <swmodeltestbase.hxx>
12 #include <com/sun/star/text/VertOrientation.hpp>
13 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
15 #include <svx/svdpage.hxx>
18 #include <fmtanchr.hxx>
19 #include <IDocumentDrawModelAccess.hxx>
20 #include <drawdoc.hxx>
21 #include <dcontact.hxx>
22 #include <frameformats.hxx>
23 #include <unotxdoc.hxx>
25 #include <swdtflvr.hxx>
26 #include <caption.hxx>
28 #include <formatflysplit.hxx>
30 /// Covers sw/source/core/frmedt/ fixes.
31 class SwCoreFrmedtTest
: public SwModelTestBase
35 : SwModelTestBase("/sw/qa/core/frmedt/data/")
40 CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest
, testTextboxReanchor
)
42 // Load a document with a textframe and a textbox(shape+textframe).
43 createSwDoc("textbox-reanchor.odt");
44 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
45 SwDoc
* pDoc
= pTextDoc
->GetDocShell()->GetDoc();
46 SdrPage
* pDrawPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
47 SdrObject
* pDrawShape
= pDrawPage
->GetObj(1);
48 CPPUNIT_ASSERT_EQUAL(OUString("draw shape"), pDrawShape
->GetName());
50 // Select the shape of the textbox.
52 SwWrtShell
* pShell
= pDoc
->GetDocShell()->GetWrtShell();
53 pShell
->SelectObj(aPoint
, /*nFlag=*/0, pDrawShape
);
55 // Anchor the shape of the textbox into its own textframe.
56 SdrObject
* pTextFrameObj
= pDrawPage
->GetObj(2);
57 SwFrameFormat
* pTextFrameFormat
= FindFrameFormat(pTextFrameObj
);
58 CPPUNIT_ASSERT_EQUAL(OUString("Frame2"), pTextFrameFormat
->GetName());
59 SwFrameFormat
* pDrawShapeFormat
= FindFrameFormat(pDrawShape
);
60 SwNodeOffset nOldAnchor
= pDrawShapeFormat
->GetAnchor().GetAnchorNode()->GetIndex();
61 pShell
->FindAnchorPos(pTextFrameObj
->GetLastBoundRect().Center(), true);
62 SwNodeOffset nNewAnchor
= pDrawShapeFormat
->GetAnchor().GetAnchorNode()->GetIndex();
63 // Without the accompanying fix in place, this test would have failed with:
66 // i.e. SwFEShell allowed to anchor the textframe of a textbox into itself.
67 CPPUNIT_ASSERT_EQUAL(nOldAnchor
, nNewAnchor
);
70 CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest
, testVertPosFromBottomBoundingBox
)
72 // Insert a shape and anchor it vertically in a way, so its position is from the top of the page
73 // bottom margin area.
75 uno::Reference
<css::lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
76 uno::Reference
<drawing::XShape
> xShape(
77 xFactory
->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY
);
78 xShape
->setSize(awt::Size(10000, 10000));
79 uno::Reference
<beans::XPropertySet
> xShapeProps(xShape
, uno::UNO_QUERY
);
80 xShapeProps
->setPropertyValue("AnchorType", uno::Any(text::TextContentAnchorType_AT_CHARACTER
));
81 xShapeProps
->setPropertyValue("VertOrient", uno::Any(text::VertOrientation::NONE
));
82 xShapeProps
->setPropertyValue("VertOrientRelation",
83 uno::Any(text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
));
84 xShapeProps
->setPropertyValue("VertOrientPosition", uno::Any(static_cast<sal_Int32
>(-11000)));
85 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
86 xDrawPageSupplier
->getDrawPage()->add(xShape
);
88 // Get the absolute position of the top of the page bottom margin area.
89 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
90 SwTwips nPagePrintAreaBottom
= getXPath(pXmlDoc
, "//page/infos/prtBounds", "bottom").toInt32();
92 // Calculate the allowed bounding box of the shape, e.g. the shape's position & size dialog uses
93 // this to limit the vertical position to sensible values.
94 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
95 SwWrtShell
* pWrtShell
= pTextDoc
->GetDocShell()->GetWrtShell();
97 RndStdIds eAnchorType
= RndStdIds::FLY_AT_CHAR
;
98 SwDoc
* pDoc
= pTextDoc
->GetDocShell()->GetDoc();
99 const auto& rFrameFormats
= *pDoc
->GetFrameFormats();
100 const SwFormatAnchor
* pFormatAhchor
= &rFrameFormats
[0]->GetAnchor();
101 sal_Int16 eHoriRelOrient
= text::RelOrientation::PAGE_FRAME
;
102 sal_Int16 eVertRelOrient
= text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
;
103 bool bFollowTextFlow
= false;
104 bool bMirror
= false;
106 pWrtShell
->CalcBoundRect(aBoundRect
, eAnchorType
, eHoriRelOrient
, eVertRelOrient
, pFormatAhchor
,
107 bFollowTextFlow
, bMirror
, nullptr, &aPercentSize
);
109 // Without the accompanying fix in place, this test would have failed with:
110 // - Expected: -14705
112 // i.e. UI did not allow anchoring a shape 10cm above the bottom of the page due to wrong
114 CPPUNIT_ASSERT_EQUAL(-1 * nPagePrintAreaBottom
, aBoundRect
.Pos().getY());
117 CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest
, testPasteFlyInTextBox
)
119 // Given a document that contains a textbox, which contains an sw image (fly frame)
120 createSwDoc("paste-fly-in-textbox.docx");
121 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
122 SwDocShell
* pDocShell
= pTextDoc
->GetDocShell();
123 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
124 SwDoc
* pDoc
= pDocShell
->GetDoc();
125 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
126 SdrObject
* pObject
= pPage
->GetObj(0);
127 pWrtShell
->SelectObj(Point(), 0, pObject
);
128 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pDoc
->GetSpzFrameFormats()->GetFormatCount());
129 rtl::Reference
<SwTransferable
> pTransfer
= new SwTransferable(*pWrtShell
);
131 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pDoc
->GetSpzFrameFormats()->GetFormatCount());
132 TransferableDataHelper
aHelper(pTransfer
);
134 // When pasting that to an empty document.
135 SwTransferable::Paste(*pWrtShell
, aHelper
);
137 // Then we should have the image only once: 3 formats (draw+fly formats for the textbox and a
138 // fly format for the image).
139 // Without the accompanying fix in place, this test would have failed with:
142 // i.e. the image was pasted twice.
143 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pDoc
->GetSpzFrameFormats()->GetFormatCount());
146 CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest
, testTextBoxSelectCursorPos
)
148 // Given a document with a fly+draw format pair (textbox):
149 createSwDoc("paste-fly-in-textbox.docx");
151 // When selecting the fly format:
152 SwDoc
* pDoc
= getSwDoc();
153 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
154 SdrObject
* pFlyObject
= pPage
->GetObj(1);
155 SwContact
* pFlyContact
= static_cast<SwContact
*>(pFlyObject
->GetUserCall());
156 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(RES_FLYFRMFMT
), pFlyContact
->GetFormat()->Which());
157 SwWrtShell
* pWrtShell
= pDoc
->GetDocShell()->GetWrtShell();
158 pWrtShell
->SelectObj(Point(), 0, pFlyObject
);
160 // Then make sure the cursor is the anchor of the draw format:
161 SdrObject
* pDrawObject
= pPage
->GetObj(0);
162 SwDrawContact
* pDrawContact
= static_cast<SwDrawContact
*>(pDrawObject
->GetUserCall());
163 SwFrameFormat
* pDrawFormat
= pDrawContact
->GetFormat();
164 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(RES_DRAWFRMFMT
), pDrawFormat
->Which());
165 SwNodeOffset nAnchor
= pDrawFormat
->GetAnchor().GetContentAnchor()->GetNode().GetIndex();
166 SwNodeOffset nCursor
= pWrtShell
->GetCurrentShellCursor().GetPointNode().GetIndex();
167 // Without the accompanying fix in place, this test would have failed with:
168 // - Expected: 15 (anchor of draw format)
169 // - Actual : 6 (in-fly-format position)
170 // i.e. the cursor had a broken position after trying to select the fly format.
171 CPPUNIT_ASSERT_EQUAL(nAnchor
, nCursor
);
174 CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest
, testSplitFlyInsertCaption
)
176 // Given a document with a full-page floating table:
177 createSwDoc("floating-table-caption.docx");
179 // When trying to insert a caption below that table:
180 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
181 pWrtShell
->GotoTable("Table1");
183 SwView
& rView
= pWrtShell
->GetView();
184 aOpt
.SetCategory("Table");
185 aOpt
.SetCaption("Numbers English-German");
186 // After, not before.
188 // Without the accompanying fix in place, this call never finished, layout didn't handle content
189 // after the table in a floating table.
190 rView
.InsertCaption(&aOpt
);
192 // Then make sure the insertion finishes and now this is just a plain table-in-frame:
193 SwDoc
* pDoc
= getSwDoc();
194 sw::SpzFrameFormats
& rFlys
= *pDoc
->GetSpzFrameFormats();
195 sw::SpzFrameFormat
* pFly
= rFlys
[0];
196 CPPUNIT_ASSERT(!pFly
->GetAttrSet().GetFlySplit().GetValue());
199 CPPUNIT_PLUGIN_IMPLEMENT();
201 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */