xref: /AOO42X/main/sc/source/filter/xml/XMLTableShapeResizer.cxx (revision b1c5455db1639c48e26c568e4fa7ee78ca5d60ee)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 #include "XMLTableShapeResizer.hxx"
27 #include "unonames.hxx"
28 #include "document.hxx"
29 #include "xmlimprt.hxx"
30 #include "chartlis.hxx"
31 #include "XMLConverter.hxx"
32 #include "rangeutl.hxx"
33 #include "reftokenhelper.hxx"
34 #include <tools/debug.hxx>
35 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
36 #include <com/sun/star/table/XColumnRowRange.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 
39 #include <memory>
40 #include <vector>
41 
42 using namespace ::com::sun::star;
43 using ::std::auto_ptr;
44 using ::std::vector;
45 using ::rtl::OUString;
46 
ScMyShapeResizer(ScXMLImport & rTempImport)47 ScMyShapeResizer::ScMyShapeResizer(ScXMLImport& rTempImport)
48     : rImport(rTempImport),
49     aShapes(),
50     pCollection(NULL)
51 {
52 }
53 
~ScMyShapeResizer()54 ScMyShapeResizer::~ScMyShapeResizer()
55 {
56 }
57 
IsOLE(uno::Reference<drawing::XShape> & rShape) const58 sal_Bool ScMyShapeResizer::IsOLE(uno::Reference< drawing::XShape >& rShape) const
59 {
60     return rShape->getShapeType().equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.OLE2Shape")));
61 }
62 
CreateChartListener(ScDocument * pDoc,const rtl::OUString & rName,const rtl::OUString * pRangeList)63 void ScMyShapeResizer::CreateChartListener(ScDocument* pDoc,
64     const rtl::OUString& rName,
65     const rtl::OUString* pRangeList)
66 {
67     if (!pDoc || !pRangeList)
68         // These are minimum required.
69         return;
70 
71     if (!pRangeList->getLength())
72     {
73         pDoc->AddOLEObjectToCollection(rName);
74         return;
75     }
76 
77     OUString aRangeStr;
78     ScRangeStringConverter::GetStringFromXMLRangeString(aRangeStr, *pRangeList, pDoc);
79     if (!aRangeStr.getLength())
80     {
81         pDoc->AddOLEObjectToCollection(rName);
82         return;
83     }
84 
85     if (!pCollection)
86         pCollection = pDoc->GetChartListenerCollection();
87 
88     if (!pCollection)
89         return;
90 
91     auto_ptr< vector<ScSharedTokenRef> > pRefTokens(new vector<ScSharedTokenRef>);
92     ScRefTokenHelper::compileRangeRepresentation(*pRefTokens, aRangeStr, pDoc);
93     if (!pRefTokens->empty())
94     {
95         ScChartListener* pCL(new ScChartListener(rName, pDoc, pRefTokens.release()));
96 
97         //for loading binary files e.g.
98         //if we have the flat filter we need to set the dirty flag thus the visible charts get repainted
99         //otherwise the charts keep their first visual representation which was created at a moment where the calc itself was not loaded completely and is incorrect therefor
100         if( (rImport.getImportFlags() & IMPORT_ALL) == IMPORT_ALL )
101             pCL->SetDirty( sal_True );
102         else
103         {
104             // #i104899# If a formula cell is already dirty, further changes aren't propagated.
105             // This can happen easily now that row heights aren't updated for all sheets.
106             pDoc->InterpretDirtyCells( *pCL->GetRangeList() );
107         }
108 
109         pCollection->Insert( pCL );
110         pCL->StartListeningTo();
111     }
112 }
113 
AddShape(uno::Reference<drawing::XShape> & rShape,rtl::OUString * pRangeList,table::CellAddress & rStartAddress,table::CellAddress & rEndAddress,sal_Int32 nEndX,sal_Int32 nEndY)114 void ScMyShapeResizer::AddShape(uno::Reference <drawing::XShape>& rShape,
115     rtl::OUString* pRangeList,
116     table::CellAddress& rStartAddress, table::CellAddress& rEndAddress,
117     sal_Int32 nEndX, sal_Int32 nEndY)
118 {
119     ScMyToResizeShape aShape;
120     aShape.xShape.set(rShape);
121     aShape.pRangeList = pRangeList;
122     aShape.aEndCell = rEndAddress;
123     aShape.aStartCell = rStartAddress;
124     aShape.nEndY = nEndY;
125     aShape.nEndX = nEndX;
126     aShapes.push_back(aShape);
127 }
128 
GetNewShapeSizePos(ScDocument * pDoc,const Rectangle & rStartRect,const table::CellAddress & rEndCell,awt::Point & rPoint,awt::Size & rSize,sal_Int32 & rEndX,sal_Int32 & rEndY) const129 void ScMyShapeResizer::GetNewShapeSizePos(ScDocument* pDoc, const Rectangle& rStartRect,
130                                           const table::CellAddress& rEndCell,
131                                           awt::Point& rPoint, awt::Size& rSize,
132                                           sal_Int32& rEndX, sal_Int32& rEndY) const
133 {
134     awt::Point aRefPoint;
135     sal_Bool bNegativePage(pDoc->IsNegativePage(rEndCell.Sheet));
136     if (bNegativePage)
137         aRefPoint.X = rStartRect.Right();
138     else
139         aRefPoint.X = rStartRect.Left();
140     aRefPoint.Y = rStartRect.Top();
141     Rectangle aRect(pDoc->GetMMRect(
142         static_cast<SCCOL>(rEndCell.Column), static_cast<SCROW>(rEndCell.Row),
143         static_cast<SCCOL>(rEndCell.Column), static_cast<SCROW>(rEndCell.Row), rEndCell.Sheet ));
144     if (bNegativePage)
145         rEndX = -rEndX + aRect.Right();
146     else
147         rEndX += aRect.Left();
148     rEndY += aRect.Top();
149     rPoint.X += aRefPoint.X;
150     if (bNegativePage)
151     {
152         if (rPoint.X < rStartRect.Left())
153             rPoint.X = rStartRect.Left() + 2; // increment by 2 100th_mm because the cellwidth is internal in twips
154     }
155     else
156     {
157         if (rPoint.X > rStartRect.Right())
158             rPoint.X = rStartRect.Right() - 2; // decrement by 2 100th_mm because the cellwidth is internal in twips
159     }
160     rPoint.Y += aRefPoint.Y;
161     if (rPoint.Y > rStartRect.Bottom())
162         rPoint.Y = rStartRect.Bottom() - 2; // decrement by 2 100th_mm because the cellheight is internal in twips
163     if (bNegativePage)
164     {
165         rSize.Width = -(rEndX - rPoint.X);
166     }
167     else
168         rSize.Width = rEndX - rPoint.X;
169     rSize.Height = rEndY - rPoint.Y;
170 }
171 
ResizeShapes()172 void ScMyShapeResizer::ResizeShapes()
173 {
174     if (!aShapes.empty() && rImport.GetModel().is())
175     {
176         rtl::OUString sRowHeight(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CELLHGT));
177         rtl::OUString sPersistName (RTL_CONSTASCII_USTRINGPARAM("PersistName"));
178         rtl::OUString sCaptionPoint( RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" ));
179         rtl::OUString sConnectorShape( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.ConnectorShape") );
180         rtl::OUString sCaptionShape( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CaptionShape") );
181         rtl::OUString sStartShape(RTL_CONSTASCII_USTRINGPARAM("StartShape"));
182         rtl::OUString sEndShape(RTL_CONSTASCII_USTRINGPARAM("EndShape"));
183         rtl::OUString sStartPosition(RTL_CONSTASCII_USTRINGPARAM("StartPosition"));
184         rtl::OUString sEndPosition(RTL_CONSTASCII_USTRINGPARAM("EndPosition"));
185         uno::Reference<table::XCellRange> xTableRow;
186         uno::Reference<sheet::XSpreadsheet> xSheet;
187         uno::Reference<table::XTableRows> xTableRows;
188         sal_Int32 nOldRow(-1);
189         sal_Int32 nOldSheet(-1);
190         ScMyToResizeShapes::iterator aItr(aShapes.begin());
191         ScMyToResizeShapes::iterator aEndItr(aShapes.end());
192         uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( rImport.GetModel(), uno::UNO_QUERY );
193         if ( xSpreadDoc.is() )
194         {
195             uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
196             ScDocument* pDoc(rImport.GetDocument());
197             if ( pDoc && xIndex.is() )
198             {
199                 rImport.LockSolarMutex();
200                 while (aItr != aEndItr)
201                 {
202                     // #i78086# invalid cell position is used to call CreateChartListener only
203                     if ( aItr->aEndCell.Sheet >= 0 )
204                     {
205                         if ((nOldSheet != aItr->aEndCell.Sheet) || !xSheet.is())
206                         {
207                             nOldSheet = aItr->aEndCell.Sheet;
208                             xSheet.set(xIndex->getByIndex(nOldSheet), uno::UNO_QUERY);
209                             if (xSheet.is())
210                             {
211                                 uno::Reference<table::XColumnRowRange> xColumnRowRange (xSheet, uno::UNO_QUERY);
212                                 if (xColumnRowRange.is())
213                                     xTableRows = xColumnRowRange->getRows();
214                             }
215                         }
216                         if (xTableRows.is())
217                         {
218                             if (nOldRow != aItr->aEndCell.Row || !xTableRow.is())
219                             {
220                                 nOldRow = aItr->aEndCell.Row;
221                                 xTableRows->getByIndex(nOldRow) >>= xTableRow;
222                             }
223                             if (xTableRow.is())
224                             {
225                                 uno::Reference <beans::XPropertySet> xRowProperties(xTableRow, uno::UNO_QUERY);
226                                 if (xRowProperties.is())
227                                 {
228                                     sal_Int32 nHeight;
229                                     if (xRowProperties->getPropertyValue(sRowHeight) >>= nHeight)
230                                     {
231                                         Rectangle aRec = pDoc->GetMMRect(static_cast<SCCOL>(aItr->aStartCell.Column), static_cast<SCROW>(aItr->aStartCell.Row),
232                                             static_cast<SCCOL>(aItr->aStartCell.Column), static_cast<SCROW>(aItr->aStartCell.Row), aItr->aStartCell.Sheet);
233                                         awt::Point aPoint(aItr->xShape->getPosition());
234                                         awt::Size aSize(aItr->xShape->getSize());
235                                         if (pDoc->IsNegativePage(static_cast<SCTAB>(nOldSheet)))
236                                             aPoint.X += aSize.Width;
237                                         if (aItr->nEndY >= 0 && aItr->nEndX >= 0)
238                                         {
239                                             if (aItr->xShape->getShapeType().equals(sConnectorShape))
240                                             {
241                                                 //#103122#; handle connected Connectorshapes
242                                                 uno::Reference<beans::XPropertySet> xShapeProps (aItr->xShape, uno::UNO_QUERY);
243                                                 if(xShapeProps.is())
244                                                 {
245                                                     uno::Reference<drawing::XShape> xStartShape(xShapeProps->getPropertyValue(  sStartShape ), uno::UNO_QUERY);
246                                                     uno::Reference<drawing::XShape> xEndShape(xShapeProps->getPropertyValue( sEndShape ), uno::UNO_QUERY);
247                                                     if (!xStartShape.is() && !xEndShape.is())
248                                                     {
249                                                         awt::Size aOldSize(aSize);
250                                                         GetNewShapeSizePos(pDoc, aRec, aItr->aEndCell, aPoint, aSize, aItr->nEndX, aItr->nEndY);
251                                                         aItr->xShape->setPosition(aPoint);
252                                                         if( (aSize.Width != aOldSize.Width) ||
253                                                             (aSize.Height != aOldSize.Height) )
254                                                             aItr->xShape->setSize(aSize);
255                                                     }
256                                                     else if (xStartShape.is() && xEndShape.is())
257                                                     {
258                                                         // do nothing, because they are connected
259                                                     }
260                                                     else
261                                                     {
262                                                         // only one point is connected, the other should be moved
263 
264                                                         rtl::OUString sProperty;
265                                                         if (xStartShape.is())
266                                                         {
267                                                             awt::Point aEndPoint;
268                                                             xShapeProps->getPropertyValue(sEndPosition) >>= aEndPoint;
269                                                             aPoint.X = aRec.Left() + aEndPoint.X;
270                                                             aPoint.Y = aRec.Top() + aEndPoint.Y;
271                                                             sProperty = sEndPosition;
272                                                         }
273                                                         else
274                                                         {
275                                                             awt::Point aStartPoint;
276                                                             xShapeProps->getPropertyValue(sStartPosition) >>= aStartPoint;
277                                                             aPoint.X = aRec.Left() + aStartPoint.X;
278                                                             aPoint.Y = aRec.Top() + aStartPoint.Y;
279                                                             sProperty = sStartPosition;
280                                                         }
281                                                         xShapeProps->setPropertyValue(sProperty, uno::makeAny(aPoint));
282                                                     }
283                                                 }
284                                             }
285                                             else
286                                             {
287                                                 awt::Size aOldSize(aSize);
288                                                 GetNewShapeSizePos(pDoc, aRec, aItr->aEndCell, aPoint, aSize, aItr->nEndX, aItr->nEndY);
289                                                 if (pDoc->IsNegativePage(static_cast<SCTAB>(nOldSheet)))
290                                                     aPoint.X -= aSize.Width;
291                                                 aItr->xShape->setPosition(aPoint);
292                                                 if( (aSize.Width != aOldSize.Width) ||
293                                                     (aSize.Height != aOldSize.Height) )
294                                                     aItr->xShape->setSize(aSize);
295                                             }
296                                         }
297                                         else
298                                         {
299                                             if (aItr->xShape->getShapeType().equals(sCaptionShape))
300                                             {
301                                                 Rectangle aRectangle(aPoint.X, aPoint.Y, aPoint.X + aSize.Width, aPoint.Y + aSize.Height);
302 
303                                                 awt::Point aCaptionPoint;
304                                                 uno::Reference< beans::XPropertySet > xShapeProps(aItr->xShape, uno::UNO_QUERY);
305                                                 if (xShapeProps.is())
306                                                 {
307                                                     try
308                                                     {
309                                                         xShapeProps->getPropertyValue( sCaptionPoint ) >>= aCaptionPoint;
310                                                     }
311                                                     catch ( uno::Exception& )
312                                                     {
313                                                         DBG_ERROR("This Captionshape has no CaptionPoint property.");
314                                                     }
315                                                 }
316                                                 Point aCorePoint(aPoint.X, aPoint.Y);
317                                                 Point aCoreCaptionPoint(aCaptionPoint.X, aCaptionPoint.Y);
318                                                 aCoreCaptionPoint += aCorePoint;
319                                                 aRectangle.Union(Rectangle(aCoreCaptionPoint, aCoreCaptionPoint));
320 
321                                                 Point aBeforeRightBottomPoint(aRectangle.BottomRight());
322 
323                                                 aRectangle += aRec.TopLeft();
324                                                 if (aRectangle.Left() > aRec.Right())
325                                                     aRectangle -= (Point(aRectangle.Left() - aRec.Right() + 2, 0));
326                                                 if (aRectangle.Top() > aRec.Bottom())
327                                                     aRectangle -= (Point(0, aRectangle.Top() - aRec.Bottom() + 2));
328 
329                                                 Point aDifferencePoint(aRectangle.BottomRight() - aBeforeRightBottomPoint);
330                                                 aPoint.X += aDifferencePoint.X();
331                                                 aPoint.Y += aDifferencePoint.Y();
332 
333                                                 aItr->xShape->setPosition(aPoint);
334                                             }
335                                             else
336                                             {
337                                                 // #96159# it is possible, that shapes have a negative position
338                                                 // this is now handled here
339                                                 DBG_ERROR("no or negative end address of this shape");
340                                                 awt::Point aRefPoint;
341                                                 aRefPoint.X = aRec.Left();
342                                                 aRefPoint.Y = aRec.Top();
343                                                 aPoint.X += aRefPoint.X;
344                                                 if (aPoint.X > aRec.Right())
345                                                     aPoint.X = aRec.Right() - 2; // decrement by 2 100th_mm because the cellheight is internal in twips
346                                                 aPoint.Y += aRefPoint.Y;
347                                                 if (aPoint.Y > aRec.Bottom())
348                                                     aPoint.Y = aRec.Bottom() - 2; // decrement by 2 100th_mm because the cellheight is internal in twips
349                                                 aItr->xShape->setPosition(aPoint);
350                                             }
351                                         }
352                                     }
353                                 }
354                             }
355                         }
356                         else
357                     {
358                             DBG_ERROR("something wents wrong");
359                     }
360                     }
361                     // #i78086# call CreateChartListener also for invalid position (anchored to sheet)
362                     if (IsOLE(aItr->xShape))
363                     {
364                         uno::Reference < beans::XPropertySet > xShapeProps ( aItr->xShape, uno::UNO_QUERY );
365                         uno::Reference < beans::XPropertySetInfo > xShapeInfo(xShapeProps->getPropertySetInfo());
366                         rtl::OUString sName;
367                         if (xShapeProps.is() && xShapeInfo.is() && xShapeInfo->hasPropertyByName(sPersistName) &&
368                             (xShapeProps->getPropertyValue(sPersistName) >>= sName))
369                             CreateChartListener(pDoc, sName, aItr->pRangeList);
370                     }
371                     if (aItr->pRangeList)
372                         delete aItr->pRangeList;
373                     aItr = aShapes.erase(aItr);
374                 }
375                 rImport.UnlockSolarMutex();
376 //              if (pCollection)
377 //                  pDoc->SetChartListenerCollection(pCollection);
378             }
379         }
380     }
381 }
382