xref: /trunk/main/sc/source/core/tool/charthelper.cxx (revision 17e36312)
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