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
27 #include "charthelper.hxx"
28 #include "document.hxx"
29 #include "drwlayer.hxx"
30 #include "rangelst.hxx"
31 #include "chartlis.hxx"
32 #include "docuno.hxx"
33
34 //#include <vcl/svapp.hxx>
35 #include <svx/svditer.hxx>
36 #include <svx/svdoole2.hxx>
37 #include <svx/svdpage.hxx>
38
39 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
40 #include <com/sun/star/util/XModifiable.hpp>
41
42 using namespace com::sun::star;
43 using ::com::sun::star::uno::Reference;
44
45
46 // ====================================================================
47
48 namespace
49 {
50
51
lcl_DoUpdateCharts(const ScAddress & rPos,ScDocument * pDoc,sal_Bool bAllCharts)52 sal_uInt16 lcl_DoUpdateCharts( const ScAddress& rPos, ScDocument* pDoc, sal_Bool bAllCharts )
53 {
54 ScDrawLayer* pModel = pDoc->GetDrawLayer();
55 if (!pModel)
56 return 0;
57
58 sal_uInt16 nFound = 0;
59
60 sal_uInt16 nPageCount = pModel->GetPageCount();
61 for (sal_uInt16 nPageNo=0; nPageNo<nPageCount; nPageNo++)
62 {
63 SdrPage* pPage = pModel->GetPage(nPageNo);
64 DBG_ASSERT(pPage,"Page ?");
65
66 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
67 SdrObject* pObject = aIter.Next();
68 while (pObject)
69 {
70 if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart( pObject ) )
71 {
72 String aName = ((SdrOle2Obj*)pObject)->GetPersistName();
73 sal_Bool bHit = sal_True;
74 if ( !bAllCharts )
75 {
76 ScRangeList aRanges;
77 sal_Bool bColHeaders = sal_False;
78 sal_Bool bRowHeaders = sal_False;
79 pDoc->GetOldChartParameters( aName, aRanges, bColHeaders, bRowHeaders );
80 bHit = aRanges.In( rPos );
81 }
82 if ( bHit )
83 {
84 pDoc->UpdateChart( aName );
85 ++nFound;
86 }
87 }
88 pObject = aIter.Next();
89 }
90 }
91 return nFound;
92 }
93
lcl_AdjustRanges(ScRangeList & rRanges,SCTAB nSourceTab,SCTAB nDestTab,SCTAB nTabCount)94 sal_Bool lcl_AdjustRanges( ScRangeList& rRanges, SCTAB nSourceTab, SCTAB nDestTab, SCTAB nTabCount )
95 {
96 //! if multiple sheets are copied, update references into the other copied sheets?
97
98 sal_Bool bChanged = sal_False;
99
100 sal_uLong nCount = rRanges.Count();
101 for (sal_uLong i=0; i<nCount; i++)
102 {
103 ScRange* pRange = rRanges.GetObject(i);
104 if ( pRange->aStart.Tab() == nSourceTab && pRange->aEnd.Tab() == nSourceTab )
105 {
106 pRange->aStart.SetTab( nDestTab );
107 pRange->aEnd.SetTab( nDestTab );
108 bChanged = sal_True;
109 }
110 if ( pRange->aStart.Tab() >= nTabCount )
111 {
112 pRange->aStart.SetTab( nTabCount > 0 ? ( nTabCount - 1 ) : 0 );
113 bChanged = sal_True;
114 }
115 if ( pRange->aEnd.Tab() >= nTabCount )
116 {
117 pRange->aEnd.SetTab( nTabCount > 0 ? ( nTabCount - 1 ) : 0 );
118 bChanged = sal_True;
119 }
120 }
121
122 return bChanged;
123 }
124
125 }//end anonymous namespace
126
127 // === ScChartHelper ======================================
128
129 //static
DoUpdateCharts(const ScAddress & rPos,ScDocument * pDoc)130 sal_uInt16 ScChartHelper::DoUpdateCharts( const ScAddress& rPos, ScDocument* pDoc )
131 {
132 return lcl_DoUpdateCharts( rPos, pDoc, sal_False );
133 }
134
135 //static
DoUpdateAllCharts(ScDocument * pDoc)136 sal_uInt16 ScChartHelper::DoUpdateAllCharts( ScDocument* pDoc )
137 {
138 return lcl_DoUpdateCharts( ScAddress(), pDoc, sal_True );
139 }
140
141 //static
AdjustRangesOfChartsOnDestinationPage(ScDocument * pSrcDoc,ScDocument * pDestDoc,const SCTAB nSrcTab,const SCTAB nDestTab)142 void ScChartHelper::AdjustRangesOfChartsOnDestinationPage( ScDocument* pSrcDoc, ScDocument* pDestDoc, const SCTAB nSrcTab, const SCTAB nDestTab )
143 {
144 if( !pSrcDoc || !pDestDoc )
145 return;
146 ScDrawLayer* pDrawLayer = pDestDoc->GetDrawLayer();
147 if( !pDrawLayer )
148 return;
149
150 SdrPage* pDestPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nDestTab));
151 if( pDestPage )
152 {
153 SdrObjListIter aIter( *pDestPage, IM_FLAT );
154 SdrObject* pObject = aIter.Next();
155 while( pObject )
156 {
157 if( pObject->GetObjIdentifier() == OBJ_OLE2 && ((SdrOle2Obj*)pObject)->IsChart() )
158 {
159 String aChartName = ((SdrOle2Obj*)pObject)->GetPersistName();
160
161 Reference< chart2::XChartDocument > xChartDoc( pDestDoc->GetChartByName( aChartName ) );
162 Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
163 if( xChartDoc.is() && xReceiver.is() && !xChartDoc->hasInternalDataProvider() )
164 {
165 ::std::vector< ScRangeList > aRangesVector;
166 pDestDoc->GetChartRanges( aChartName, aRangesVector, pSrcDoc );
167
168 ::std::vector< ScRangeList >::iterator aIt( aRangesVector.begin() );
169 for( ; aIt!=aRangesVector.end(); aIt++ )
170 {
171 ScRangeList& rScRangeList( *aIt );
172 lcl_AdjustRanges( rScRangeList, nSrcTab, nDestTab, pDestDoc->GetTableCount() );
173 }
174 pDestDoc->SetChartRanges( aChartName, aRangesVector );
175 }
176 }
177 pObject = aIter.Next();
178 }
179 }
180 }
181
182 //static
UpdateChartsOnDestinationPage(ScDocument * pDestDoc,const SCTAB nDestTab)183 void ScChartHelper::UpdateChartsOnDestinationPage( ScDocument* pDestDoc, const SCTAB nDestTab )
184 {
185 if( !pDestDoc )
186 return;
187 ScDrawLayer* pDrawLayer = pDestDoc->GetDrawLayer();
188 if( !pDrawLayer )
189 return;
190
191 SdrPage* pDestPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nDestTab));
192 if( pDestPage )
193 {
194 SdrObjListIter aIter( *pDestPage, IM_FLAT );
195 SdrObject* pObject = aIter.Next();
196 while( pObject )
197 {
198 if( pObject->GetObjIdentifier() == OBJ_OLE2 && ((SdrOle2Obj*)pObject)->IsChart() )
199 {
200 String aChartName = ((SdrOle2Obj*)pObject)->GetPersistName();
201 Reference< chart2::XChartDocument > xChartDoc( pDestDoc->GetChartByName( aChartName ) );
202 Reference< util::XModifiable > xModif(xChartDoc, uno::UNO_QUERY_THROW);
203 xModif->setModified( sal_True);
204 }
205 pObject = aIter.Next();
206 }
207 }
208 }
209
210 //static
GetChartFromSdrObject(SdrObject * pObject)211 uno::Reference< chart2::XChartDocument > ScChartHelper::GetChartFromSdrObject( SdrObject* pObject )
212 {
213 uno::Reference< chart2::XChartDocument > xReturn;
214 if( pObject )
215 {
216 if( pObject->GetObjIdentifier() == OBJ_OLE2 && ((SdrOle2Obj*)pObject)->IsChart() )
217 {
218 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
219 if( xIPObj.is() )
220 {
221 svt::EmbeddedObjectRef::TryRunningState( xIPObj );
222 uno::Reference< util::XCloseable > xComponent = xIPObj->getComponent();
223 xReturn.set( uno::Reference< chart2::XChartDocument >( xComponent, uno::UNO_QUERY ) );
224 }
225 }
226 }
227 return xReturn;
228 }
229
GetChartRanges(const uno::Reference<chart2::XChartDocument> & xChartDoc,uno::Sequence<rtl::OUString> & rRanges)230 void ScChartHelper::GetChartRanges( const uno::Reference< chart2::XChartDocument >& xChartDoc,
231 uno::Sequence< rtl::OUString >& rRanges )
232 {
233 rRanges.realloc(0);
234 uno::Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
235 if( !xDataSource.is() )
236 return;
237 //uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider();
238
239 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledDataSequences( xDataSource->getDataSequences() );
240 rRanges.realloc(2*aLabeledDataSequences.getLength());
241 sal_Int32 nRealCount=0;
242 for( sal_Int32 nN=0;nN<aLabeledDataSequences.getLength();nN++)
243 {
244 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSequence( aLabeledDataSequences[nN] );
245 if(!xLabeledSequence.is())
246 continue;
247 uno::Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel());
248 uno::Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues());
249
250 if( xLabel.is())
251 rRanges[nRealCount++] = xLabel->getSourceRangeRepresentation();
252 if( xValues.is())
253 rRanges[nRealCount++] = xValues->getSourceRangeRepresentation();
254 }
255 rRanges.realloc(nRealCount);
256 }
257
SetChartRanges(const uno::Reference<chart2::XChartDocument> & xChartDoc,const uno::Sequence<rtl::OUString> & rRanges)258 void ScChartHelper::SetChartRanges( const uno::Reference< chart2::XChartDocument >& xChartDoc,
259 const uno::Sequence< rtl::OUString >& rRanges )
260 {
261 uno::Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
262 if( !xDataSource.is() )
263 return;
264 uno::Reference< chart2::data::XDataProvider > xDataProvider = xChartDoc->getDataProvider();
265 if( !xDataProvider.is() )
266 return;
267
268 uno::Reference< frame::XModel > xModel( xChartDoc, uno::UNO_QUERY );
269 if( xModel.is() )
270 xModel->lockControllers();
271
272 try
273 {
274 rtl::OUString aPropertyNameRole( ::rtl::OUString::createFromAscii("Role") );
275
276 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledDataSequences( xDataSource->getDataSequences() );
277 sal_Int32 nRange=0;
278 for( sal_Int32 nN=0; (nN<aLabeledDataSequences.getLength()) && (nRange<rRanges.getLength()); nN++ )
279 {
280 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSequence( aLabeledDataSequences[nN] );
281 if(!xLabeledSequence.is())
282 continue;
283 uno::Reference< beans::XPropertySet > xLabel( xLabeledSequence->getLabel(), uno::UNO_QUERY );
284 uno::Reference< beans::XPropertySet > xValues( xLabeledSequence->getValues(), uno::UNO_QUERY );
285
286 if( xLabel.is())
287 {
288 // the range string must be in Calc A1 format.
289 uno::Reference< chart2::data::XDataSequence > xNewSeq(
290 xDataProvider->createDataSequenceByRangeRepresentation( rRanges[nRange++] ));
291
292 uno::Reference< beans::XPropertySet > xNewProps( xNewSeq, uno::UNO_QUERY );
293 if( xNewProps.is() )
294 xNewProps->setPropertyValue( aPropertyNameRole, xLabel->getPropertyValue( aPropertyNameRole ) );
295
296 xLabeledSequence->setLabel( xNewSeq );
297 }
298
299 if( !(nRange<rRanges.getLength()) )
300 break;
301
302 if( xValues.is())
303 {
304 // the range string must be in Calc A1 format.
305 uno::Reference< chart2::data::XDataSequence > xNewSeq(
306 xDataProvider->createDataSequenceByRangeRepresentation( rRanges[nRange++] ));
307
308 uno::Reference< beans::XPropertySet > xNewProps( xNewSeq, uno::UNO_QUERY );
309 if( xNewProps.is() )
310 xNewProps->setPropertyValue( aPropertyNameRole, xValues->getPropertyValue( aPropertyNameRole ) );
311
312 xLabeledSequence->setValues( xNewSeq );
313 }
314 }
315 }
316 catch ( uno::Exception& ex )
317 {
318 (void)ex;
319 DBG_ERROR("Exception in ScChartHelper::SetChartRanges - invalid range string?");
320 }
321
322 if( xModel.is() )
323 xModel->unlockControllers();
324 }
325
AddRangesIfProtectedChart(ScRangeListVector & rRangesVector,ScDocument * pDocument,SdrObject * pObject)326 void ScChartHelper::AddRangesIfProtectedChart( ScRangeListVector& rRangesVector, ScDocument* pDocument, SdrObject* pObject )
327 {
328 if ( pDocument && pObject && ( pObject->GetObjIdentifier() == OBJ_OLE2 ) )
329 {
330 SdrOle2Obj* pSdrOle2Obj = dynamic_cast< SdrOle2Obj* >( pObject );
331 if ( pSdrOle2Obj && pSdrOle2Obj->IsChart() )
332 {
333 uno::Reference< embed::XEmbeddedObject > xEmbeddedObj = pSdrOle2Obj->GetObjRef();
334 if ( xEmbeddedObj.is() )
335 {
336 bool bDisableDataTableDialog = false;
337 sal_Int32 nOldState = xEmbeddedObj->getCurrentState();
338 svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj );
339 uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
340 if ( xProps.is() &&
341 ( xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableDataTableDialog" ) ) ) >>= bDisableDataTableDialog ) &&
342 bDisableDataTableDialog )
343 {
344 ::rtl::OUString aChartName = pSdrOle2Obj->GetPersistName();
345 ScRange aEmptyRange;
346 ScChartListener aSearcher( aChartName, pDocument, aEmptyRange );
347 sal_uInt16 nIndex = 0;
348 ScChartListenerCollection* pCollection = pDocument->GetChartListenerCollection();
349 if ( pCollection && pCollection->Search( &aSearcher, nIndex ) )
350 {
351 ScChartListener* pListener = static_cast< ScChartListener* >( pCollection->At( nIndex ) );
352 if ( pListener )
353 {
354 const ScRangeListRef& rRangeList = pListener->GetRangeList();
355 if ( rRangeList.Is() )
356 {
357 rRangesVector.push_back( *rRangeList );
358 }
359 }
360 }
361 }
362 if ( xEmbeddedObj->getCurrentState() != nOldState )
363 {
364 xEmbeddedObj->changeState( nOldState );
365 }
366 }
367 }
368 }
369 }
370
FillProtectedChartRangesVector(ScRangeListVector & rRangesVector,ScDocument * pDocument,SdrPage * pPage)371 void ScChartHelper::FillProtectedChartRangesVector( ScRangeListVector& rRangesVector, ScDocument* pDocument, SdrPage* pPage )
372 {
373 if ( pDocument && pPage )
374 {
375 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
376 SdrObject* pObject = aIter.Next();
377 while ( pObject )
378 {
379 AddRangesIfProtectedChart( rRangesVector, pDocument, pObject );
380 pObject = aIter.Next();
381 }
382 }
383 }
384
GetChartNames(::std::vector<::rtl::OUString> & rChartNames,SdrPage * pPage)385 void ScChartHelper::GetChartNames( ::std::vector< ::rtl::OUString >& rChartNames, SdrPage* pPage )
386 {
387 if ( pPage )
388 {
389 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
390 SdrObject* pObject = aIter.Next();
391 while ( pObject )
392 {
393 if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
394 {
395 SdrOle2Obj* pSdrOle2Obj = dynamic_cast< SdrOle2Obj* >( pObject );
396 if ( pSdrOle2Obj && pSdrOle2Obj->IsChart() )
397 {
398 rChartNames.push_back( pSdrOle2Obj->GetPersistName() );
399 }
400 }
401 pObject = aIter.Next();
402 }
403 }
404 }
405
CreateProtectedChartListenersAndNotify(ScDocument * pDoc,SdrPage * pPage,ScModelObj * pModelObj,SCTAB nTab,const ScRangeListVector & rRangesVector,const::std::vector<::rtl::OUString> & rExcludedChartNames,bool bSameDoc)406 void ScChartHelper::CreateProtectedChartListenersAndNotify( ScDocument* pDoc, SdrPage* pPage, ScModelObj* pModelObj, SCTAB nTab,
407 const ScRangeListVector& rRangesVector, const ::std::vector< ::rtl::OUString >& rExcludedChartNames, bool bSameDoc )
408 {
409 if ( pDoc && pPage && pModelObj )
410 {
411 size_t nRangeListCount = rRangesVector.size();
412 size_t nRangeList = 0;
413 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
414 SdrObject* pObject = aIter.Next();
415 while ( pObject )
416 {
417 if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
418 {
419 SdrOle2Obj* pSdrOle2Obj = dynamic_cast< SdrOle2Obj* >( pObject );
420 if ( pSdrOle2Obj && pSdrOle2Obj->IsChart() )
421 {
422 ::rtl::OUString aChartName = pSdrOle2Obj->GetPersistName();
423 ::std::vector< ::rtl::OUString >::const_iterator aEnd = rExcludedChartNames.end();
424 ::std::vector< ::rtl::OUString >::const_iterator aFound = ::std::find( rExcludedChartNames.begin(), aEnd, aChartName );
425 if ( aFound == aEnd )
426 {
427 uno::Reference< embed::XEmbeddedObject > xEmbeddedObj = pSdrOle2Obj->GetObjRef();
428 if ( xEmbeddedObj.is() && ( nRangeList < nRangeListCount ) )
429 {
430 bool bDisableDataTableDialog = false;
431 svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj );
432 uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
433 if ( xProps.is() &&
434 ( xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableDataTableDialog" ) ) ) >>= bDisableDataTableDialog ) &&
435 bDisableDataTableDialog )
436 {
437 if ( bSameDoc )
438 {
439 ScRange aEmptyRange;
440 ScChartListener aSearcher( aChartName, pDoc, aEmptyRange );
441 sal_uInt16 nIndex = 0;
442 ScChartListenerCollection* pCollection = pDoc->GetChartListenerCollection();
443 if ( pCollection && !pCollection->Search( &aSearcher, nIndex ) )
444 {
445 ScRangeList aRangeList( rRangesVector[ nRangeList++ ] );
446 ScRangeListRef rRangeList( new ScRangeList( aRangeList ) );
447 ScChartListener* pChartListener = new ScChartListener( aChartName, pDoc, rRangeList );
448 pCollection->Insert( pChartListener );
449 pChartListener->StartListeningTo();
450 }
451 }
452 else
453 {
454 xProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableDataTableDialog" ) ),
455 uno::makeAny( sal_False ) );
456 xProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableComplexChartTypes" ) ),
457 uno::makeAny( sal_False ) );
458 }
459 }
460 }
461
462 if ( pModelObj && pModelObj->HasChangesListeners() )
463 {
464 Rectangle aRectangle = pSdrOle2Obj->GetSnapRect();
465 ScRange aRange( pDoc->GetRange( nTab, aRectangle ) );
466 ScRangeList aChangeRanges;
467 aChangeRanges.Append( aRange );
468
469 uno::Sequence< beans::PropertyValue > aProperties( 1 );
470 aProperties[ 0 ].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Name" ) );
471 aProperties[ 0 ].Value <<= aChartName;
472
473 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-chart" ) ), aChangeRanges, aProperties );
474 }
475 }
476 }
477 }
478 pObject = aIter.Next();
479 }
480 }
481 }
482