1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include "XMLTableShapeImportHelper.hxx"
21 #include "xmlimprt.hxx"
22 #include <drwlayer.hxx>
23 #include "xmlannoi.hxx"
24 #include <rangeutl.hxx>
25 #include <userdat.hxx>
26 #include <docuno.hxx>
27 #include <sheetdata.hxx>
28 #include <xmloff/namespacemap.hxx>
29 #include <xmloff/xmlnamespace.hxx>
30 #include <xmloff/xmluconv.hxx>
31 #include <xmloff/xmltoken.hxx>
32 #include <svx/unoshape.hxx>
33 #include <com/sun/star/drawing/XShape.hpp>
34 #include <com/sun/star/drawing/XShapes.hpp>
35
36 #define SC_LAYERID "LayerID"
37
38 using namespace ::com::sun::star;
39 using namespace xmloff::token;
40
XMLTableShapeImportHelper(ScXMLImport & rImp)41 XMLTableShapeImportHelper::XMLTableShapeImportHelper( ScXMLImport& rImp ) :
42 XMLShapeImportHelper(rImp, rImp.GetModel(), nullptr ),
43 pAnnotationContext(nullptr),
44 bOnTable(false)
45 {
46 }
47
~XMLTableShapeImportHelper()48 XMLTableShapeImportHelper::~XMLTableShapeImportHelper()
49 {
50 }
51
SetLayer(const uno::Reference<drawing::XShape> & rShape,SdrLayerID nLayerID,std::u16string_view sType)52 void XMLTableShapeImportHelper::SetLayer(const uno::Reference<drawing::XShape>& rShape, SdrLayerID nLayerID, std::u16string_view sType)
53 {
54 if ( sType == u"com.sun.star.drawing.ControlShape" )
55 nLayerID = SC_LAYER_CONTROLS;
56 if (nLayerID != SDRLAYER_NOTFOUND)
57 {
58 uno::Reference< beans::XPropertySet > xShapeProp( rShape, uno::UNO_QUERY );
59 if( xShapeProp.is() )
60 xShapeProp->setPropertyValue( SC_LAYERID, uno::makeAny<sal_uInt16>(sal_uInt8(nLayerID)) );
61 }
62 }
63
64 // Attempt to find the topmost parent of the group, this is the one we apply
65 // offsets to
lcl_getTopLevelParent(const uno::Reference<drawing::XShape> & rShape)66 static uno::Reference< drawing::XShape > lcl_getTopLevelParent( const uno::Reference< drawing::XShape >& rShape )
67 {
68 uno::Reference< container::XChild > xChild( rShape, uno::UNO_QUERY );
69 uno::Reference< drawing::XShape > xParent( xChild->getParent(), uno::UNO_QUERY );
70 if ( xParent.is() )
71 return lcl_getTopLevelParent( xParent );
72 return rShape;
73 }
74
finishShape(uno::Reference<drawing::XShape> & rShape,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> & rShapes)75 void XMLTableShapeImportHelper::finishShape(
76 uno::Reference< drawing::XShape >& rShape,
77 const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
78 uno::Reference< drawing::XShapes >& rShapes )
79 {
80 bool bNote = false;
81 XMLShapeImportHelper::finishShape( rShape, xAttrList, rShapes );
82 static_cast<ScXMLImport&>(mrImporter).LockSolarMutex();
83 ScMyTables& rTables = static_cast<ScXMLImport&>(mrImporter).GetTables();
84 if (rShapes == rTables.GetCurrentXShapes())
85 {
86 if (!pAnnotationContext)
87 {
88 ScDrawObjData aAnchor;
89 aAnchor.maStart = aStartCell;
90 awt::Point aStartPoint(rShape->getPosition());
91 aAnchor.maStartOffset = Point(aStartPoint.X, aStartPoint.Y);
92 aAnchor.mbResizeWithCell = false;
93
94 sal_Int32 nEndX(-1);
95 sal_Int32 nEndY(-1);
96 std::optional<OUString> xRangeList;
97 SdrLayerID nLayerID = SDRLAYER_NOTFOUND;
98 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
99 {
100 switch(aIter.getToken())
101 {
102 case XML_ELEMENT(TABLE, XML_END_CELL_ADDRESS):
103 {
104 sal_Int32 nOffset(0);
105 ScDocument* pDoc = static_cast<ScXMLImport&>(mrImporter).GetDocument();
106 assert(pDoc);
107 ScRangeStringConverter::GetAddressFromString(aAnchor.maEnd, aIter.toString(), *pDoc, ::formula::FormulaGrammar::CONV_OOO, nOffset);
108 // When the cell end address is set, we let the shape resize with the cell
109 aAnchor.mbResizeWithCell = true;
110 break;
111 }
112 case XML_ELEMENT(TABLE, XML_END_X):
113 {
114 static_cast<ScXMLImport&>(mrImporter).
115 GetMM100UnitConverter().convertMeasureToCore(
116 nEndX, aIter.toView());
117 aAnchor.maEndOffset.setX( nEndX );
118 break;
119 }
120 case XML_ELEMENT(TABLE, XML_END_Y):
121 {
122 static_cast<ScXMLImport&>(mrImporter).
123 GetMM100UnitConverter().convertMeasureToCore(
124 nEndY, aIter.toView());
125 aAnchor.maEndOffset.setY( nEndY );
126 break;
127 }
128 case XML_ELEMENT(TABLE, XML_TABLE_BACKGROUND):
129 if (IsXMLToken(aIter, XML_TRUE))
130 nLayerID = SC_LAYER_BACK;
131 break;
132 case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES):
133 xRangeList = aIter.toString();
134 break;
135 default: ;
136 }
137 }
138 SetLayer(rShape, nLayerID, rShape->getShapeType());
139
140 if (SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape(rShape))
141 {
142 if (!bOnTable)
143 ScDrawLayer::SetCellAnchored(*pSdrObj, aAnchor);
144 else
145 ScDrawLayer::SetPageAnchored(*pSdrObj);
146 }
147
148 if (xRangeList)
149 {
150 // #i78086# If there are notification ranges, the ChartListener must be created
151 // also when anchored to the sheet
152 // -> call AddOLE with invalid cell position (checked in ScMyShapeResizer::ResizeShapes)
153
154 if (ScMyTables::IsOLE(rShape))
155 rTables.AddOLE(rShape, *xRangeList);
156 }
157 }
158 else // shape is annotation
159 {
160 // get the style names for stream copying
161 OUString aStyleName;
162 OUString aTextStyle;
163 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
164 {
165 const OUString sValue = aIter.toString();
166 switch (aIter.getToken())
167 {
168 case XML_ELEMENT(DRAW, XML_STYLE_NAME):
169 aStyleName = sValue;
170 break;
171 case XML_ELEMENT(DRAW, XML_TEXT_STYLE_NAME):
172 aTextStyle = sValue;
173 break;
174 default:;
175 }
176 }
177
178 pAnnotationContext->SetShape(rShape, rShapes, aStyleName, aTextStyle);
179 bNote = true;
180 }
181 }
182 else //this are grouped shapes which should also get the layerid
183 {
184 uno::Reference< drawing::XShapes > xGroup( rShape, uno::UNO_QUERY );
185 // ignore the group ( within group ) object if it exists
186 if ( !bOnTable && !xGroup.is() )
187 {
188 // For cell anchored grouped shape we need to set the start
189 // position from the most top and left positioned shape(s) within
190 // the group
191 Point aStartPoint( rShape->getPosition().X,rShape->getPosition().Y );
192 uno::Reference< drawing::XShape > xChild( rShapes, uno::UNO_QUERY );
193 if (xChild)
194 {
195 if (SdrObject *pSdrObj = SdrObject::getSdrObjectFromXShape(lcl_getTopLevelParent(xChild)))
196 {
197 if ( ScDrawObjData* pAnchor = ScDrawLayer::GetObjData( pSdrObj ) )
198 {
199 if ( pAnchor->maStartOffset.getX() == 0 && pAnchor->maStartOffset.getY() == 0 )
200 pAnchor->maStartOffset = aStartPoint;
201 if ( aStartPoint.getX() < pAnchor->maStartOffset.getX() )
202 pAnchor->maStartOffset.setX( aStartPoint.getX() );
203 if ( aStartPoint.getY() < pAnchor->maStartOffset.getY() )
204 pAnchor->maStartOffset.setY( aStartPoint.getY() );
205 }
206 }
207 }
208 }
209 SdrLayerID nLayerID = SDRLAYER_NOTFOUND;
210 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
211 {
212 if (aIter.getToken() == XML_ELEMENT(TABLE, XML_TABLE_BACKGROUND))
213 {
214 if (IsXMLToken(aIter, XML_TRUE))
215 nLayerID = SC_LAYER_BACK;
216 break;
217 }
218 }
219 SetLayer(rShape, nLayerID, rShape->getShapeType());
220 }
221
222 if (!bNote)
223 {
224 // any shape other than a note prevents copying the sheet
225 ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(mrImporter.GetModel())->GetSheetSaveData();
226 pSheetData->BlockSheet( rTables.GetCurrentSheet() );
227 }
228
229 static_cast<ScXMLImport&>(mrImporter).UnlockSolarMutex();
230 }
231
232 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
233