LibreOffice Module sc (master)  1
XMLTableShapeImportHelper.cxx
Go to the documentation of this file.
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 
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 
42  XMLShapeImportHelper(rImp, rImp.GetModel(), nullptr ),
43  pAnnotationContext(nullptr),
44  bOnTable(false)
45 {
46 }
47 
49 {
50 }
51 
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
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 
76  uno::Reference< drawing::XShape >& rShape,
77  const uno::Reference< xml::sax::XAttributeList >& 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  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
97  std::optional<OUString> xRangeList;
98  SdrLayerID nLayerID = SDRLAYER_NOTFOUND;
99  for( sal_Int16 i=0; i < nAttrCount; ++i )
100  {
101  const OUString& rAttrName(xAttrList->getNameByIndex( i ));
102  const OUString& rValue(xAttrList->getValueByIndex( i ));
103 
104  OUString aLocalName;
105  sal_uInt16 nPrefix(
106  static_cast<ScXMLImport&>(mrImporter).GetNamespaceMap().GetKeyByAttrName( rAttrName,
107  &aLocalName ));
108  if(nPrefix == XML_NAMESPACE_TABLE)
109  {
110  if (IsXMLToken(aLocalName, XML_END_CELL_ADDRESS))
111  {
112  sal_Int32 nOffset(0);
113  ScDocument* pDoc = static_cast<ScXMLImport&>(mrImporter).GetDocument();
114  assert(pDoc);
116  // When the cell end address is set, we let the shape resize with the cell
117  aAnchor.mbResizeWithCell = true;
118  }
119  else if (IsXMLToken(aLocalName, XML_END_X))
120  {
121  static_cast<ScXMLImport&>(mrImporter).
122  GetMM100UnitConverter().convertMeasureToCore(
123  nEndX, rValue);
124  aAnchor.maEndOffset.setX( nEndX );
125  }
126  else if (IsXMLToken(aLocalName, XML_END_Y))
127  {
128  static_cast<ScXMLImport&>(mrImporter).
129  GetMM100UnitConverter().convertMeasureToCore(
130  nEndY, rValue);
131  aAnchor.maEndOffset.setY( nEndY );
132  }
133  else if (IsXMLToken(aLocalName, XML_TABLE_BACKGROUND))
134  if (IsXMLToken(rValue, XML_TRUE))
135  nLayerID = SC_LAYER_BACK;
136  }
137  else if(nPrefix == XML_NAMESPACE_DRAW)
138  {
140  xRangeList = rValue;
141  }
142  }
143  SetLayer(rShape, nLayerID, rShape->getShapeType());
144 
145  if (SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>(rShape))
146  {
147  if (SdrObject *pSdrObj = pShapeImp->GetSdrObject())
148  {
149  if (!bOnTable)
150  ScDrawLayer::SetCellAnchored(*pSdrObj, aAnchor);
151  else
153  }
154  }
155 
156  if (xRangeList)
157  {
158  // #i78086# If there are notification ranges, the ChartListener must be created
159  // also when anchored to the sheet
160  // -> call AddOLE with invalid cell position (checked in ScMyShapeResizer::ResizeShapes)
161 
162  if (ScMyTables::IsOLE(rShape))
163  rTables.AddOLE(rShape, *xRangeList);
164  }
165  }
166  else // shape is annotation
167  {
168  // get the style names for stream copying
169  OUString aStyleName;
170  OUString aTextStyle;
171  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
172  for( sal_Int16 i=0; i < nAttrCount; ++i )
173  {
174  const OUString& rAttrName(xAttrList->getNameByIndex( i ));
175  OUString aLocalName;
176  sal_uInt16 nPrefix(static_cast<ScXMLImport&>(mrImporter).GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName ));
177  if(nPrefix == XML_NAMESPACE_DRAW)
178  {
179  if (IsXMLToken(aLocalName, XML_STYLE_NAME))
180  aStyleName = xAttrList->getValueByIndex( i );
181  else if (IsXMLToken(aLocalName, XML_TEXT_STYLE_NAME))
182  aTextStyle = xAttrList->getValueByIndex( i );
183  }
184  }
185 
186  pAnnotationContext->SetShape(rShape, rShapes, aStyleName, aTextStyle);
187  bNote = true;
188  }
189  }
190  else //this are grouped shapes which should also get the layerid
191  {
192  uno::Reference< drawing::XShapes > xGroup( rShape, uno::UNO_QUERY );
193  // ignore the group ( within group ) object if it exists
194  if ( !bOnTable && !xGroup.is() )
195  {
196  // For cell anchored grouped shape we need to set the start
197  // position from the most top and left positioned shape(s) within
198  // the group
199  Point aStartPoint( rShape->getPosition().X,rShape->getPosition().Y );
200  uno::Reference< drawing::XShape > xChild( rShapes, uno::UNO_QUERY );
201  if (SvxShape* pGroupShapeImp = xChild.is() ? comphelper::getUnoTunnelImplementation<SvxShape>(lcl_getTopLevelParent(xChild)) : nullptr)
202  {
203  if (SdrObject *pSdrObj = pGroupShapeImp->GetSdrObject())
204  {
205  if ( ScDrawObjData* pAnchor = ScDrawLayer::GetObjData( pSdrObj ) )
206  {
207  if ( pAnchor->maStartOffset.getX() == 0 && pAnchor->maStartOffset.getY() == 0 )
208  pAnchor->maStartOffset = aStartPoint;
209  if ( aStartPoint.getX() < pAnchor->maStartOffset.getX() )
210  pAnchor->maStartOffset.setX( aStartPoint.getX() );
211  if ( aStartPoint.getY() < pAnchor->maStartOffset.getY() )
212  pAnchor->maStartOffset.setY( aStartPoint.getY() );
213  }
214  }
215  }
216  }
217  sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
218  SdrLayerID nLayerID = SDRLAYER_NOTFOUND;
219  for( sal_Int16 i=0; i < nAttrCount; ++i )
220  {
221  const OUString& rAttrName(xAttrList->getNameByIndex( i ));
222  const OUString& rValue(xAttrList->getValueByIndex( i ));
223 
224  OUString aLocalName;
225  sal_uInt16 nPrefix(static_cast<ScXMLImport&>(mrImporter).GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName ));
226  if(nPrefix == XML_NAMESPACE_TABLE)
227  {
228  if (IsXMLToken(aLocalName, XML_TABLE_BACKGROUND))
229  if (IsXMLToken(rValue, XML_TRUE))
230  nLayerID = SC_LAYER_BACK;
231  }
232  }
233  SetLayer(rShape, nLayerID, rShape->getShapeType());
234  }
235 
236  if (!bNote)
237  {
238  // any shape other than a note prevents copying the sheet
239  ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(mrImporter.GetModel())->GetSheetSaveData();
240  pSheetData->BlockSheet( rTables.GetCurrentSheet() );
241  }
242 
243  static_cast<ScXMLImport&>(mrImporter).UnlockSolarMutex();
244 }
245 
246 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
XML_STYLE_NAME
XML_END_CELL_ADDRESS
static bool GetAddressFromString(ScAddress &rAddress, const OUString &rAddressStr, const ScDocument &rDocument, formula::FormulaGrammar::AddressConvention eConv, sal_Int32 &nOffset, sal_Unicode cSeparator= ' ', sal_Unicode cQuote= '\'')
String to Range core.
Definition: rangeutl.cxx:435
SCTAB GetCurrentSheet() const
Definition: xmlsubti.hxx:85
static void SetPageAnchored(SdrObject &)
Definition: drwlayer.cxx:2313
static ScDrawObjData * GetObjData(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2475
ScXMLAnnotationContext * pAnnotationContext
constexpr SdrLayerID SC_LAYER_BACK(1)
ScAddress maStart
Definition: userdat.hxx:37
void BlockSheet(SCTAB nTab)
Definition: sheetdata.cxx:92
XML_END_X
css::uno::Any const & rValue
#define SC_LAYERID
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
XML_TEXT_STYLE_NAME
static bool IsOLE(const css::uno::Reference< css::drawing::XShape > &rShape)
Definition: xmlsubti.hxx:78
constexpr SdrLayerID SDRLAYER_NOTFOUND(0xff)
Point maEndOffset
Definition: userdat.hxx:40
constexpr sal_uInt16 XML_NAMESPACE_DRAW
static uno::Reference< drawing::XShape > lcl_getTopLevelParent(const uno::Reference< drawing::XShape > &rShape)
bool mbResizeWithCell
Definition: userdat.hxx:42
XMLTableShapeImportHelper(ScXMLImport &rImp)
static void SetCellAnchored(SdrObject &, const ScDrawObjData &rAnchor)
Definition: drwlayer.cxx:2181
void SetShape(const css::uno::Reference< css::drawing::XShape > &rxShape, const css::uno::Reference< css::drawing::XShapes > &rxShapes, const OUString &rStyleName, const OUString &rTextStyle)
Definition: xmlannoi.cxx:167
virtual void finishShape(css::uno::Reference< css::drawing::XShape > &rShape, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList, css::uno::Reference< css::drawing::XShapes > &rShapes)
int i
SvXMLImport & mrImporter
float u
Point maStartOffset
Definition: userdat.hxx:39
virtual ~XMLTableShapeImportHelper() override
virtual void finishShape(css::uno::Reference< css::drawing::XShape > &rShape, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList, css::uno::Reference< css::drawing::XShapes > &rShapes) override
XML_TABLE_BACKGROUND
constexpr sal_uInt16 XML_NAMESPACE_TABLE
unsigned char sal_uInt8
css::uno::Reference< css::drawing::XShapes > const & GetCurrentXShapes()
Definition: xmlsubti.cxx:231
const css::uno::Reference< css::frame::XModel > & GetModel() const
XML_TRUE
XML_NOTIFY_ON_UPDATE_OF_RANGES
if(!pCandidateA->getEnd().equal(pCandidateB->getStart()))
ScAddress maEnd
Definition: userdat.hxx:38
void AddOLE(const css::uno::Reference< css::drawing::XShape > &rShape, const OUString &rRangeList)
Definition: xmlsubti.cxx:253
constexpr SdrLayerID SC_LAYER_CONTROLS(3)
static void SetLayer(const css::uno::Reference< css::drawing::XShape > &rShape, SdrLayerID nLayerID, std::u16string_view sType)
XML_END_Y