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