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_chartcontroller.hxx" 26 #include "ChartDataWrapper.hxx" 27 #include "macros.hxx" 28 #include "DiagramHelper.hxx" 29 #include "DataSourceHelper.hxx" 30 #include "servicenames_charttypes.hxx" 31 #include "ContainerHelper.hxx" 32 #include "CommonFunctors.hxx" 33 #include "ChartModelHelper.hxx" 34 #include "DataSeriesHelper.hxx" 35 #include "ControllerLockGuard.hxx" 36 #include "Chart2ModelContact.hxx" 37 #include <com/sun/star/beans/PropertyAttribute.hpp> 38 #include <com/sun/star/chart2/XTitled.hpp> 39 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp> 40 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp> 41 #include <com/sun/star/chart2/data/XDataSource.hpp> 42 #include <com/sun/star/chart2/XDataSeries.hpp> 43 #include <com/sun/star/chart2/XDataSeriesContainer.hpp> 44 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> 45 #include <com/sun/star/chart2/XChartTypeContainer.hpp> 46 #include <com/sun/star/chart2/data/XDataReceiver.hpp> 47 #include <com/sun/star/chart/ChartDataRowSource.hpp> 48 #include <com/sun/star/chart/XChartDocument.hpp> 49 50 #include "CharacterProperties.hxx" 51 #include "LineProperties.hxx" 52 #include "FillProperties.hxx" 53 54 #include <map> 55 #include <algorithm> 56 #include <rtl/math.hxx> 57 58 using namespace ::com::sun::star; 59 using ::com::sun::star::uno::Reference; 60 using ::com::sun::star::uno::Sequence; 61 using ::rtl::OUString; 62 using ::osl::MutexGuard; 63 using ::com::sun::star::chart2::XAnyDescriptionAccess; 64 using ::com::sun::star::chart::XComplexDescriptionAccess; 65 using ::com::sun::star::chart::XChartData; 66 using ::com::sun::star::chart::XChartDataArray; 67 using ::com::sun::star::chart::XDateCategories; 68 69 namespace 70 { 71 static const ::rtl::OUString lcl_aServiceName( 72 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.ChartData" )); 73 74 uno::Sequence< uno::Sequence< double > > lcl_getNANInsteadDBL_MIN( const uno::Sequence< uno::Sequence< double > >& rData ) 75 { 76 uno::Sequence< uno::Sequence< double > > aRet; 77 const sal_Int32 nOuterSize = rData.getLength(); 78 aRet.realloc( nOuterSize ); 79 for( sal_Int32 nOuter=0; nOuter<nOuterSize; ++nOuter ) 80 { 81 sal_Int32 nInnerSize = rData[nOuter].getLength(); 82 aRet[nOuter].realloc( nInnerSize ); 83 for( sal_Int32 nInner=0; nInner<nInnerSize; ++nInner ) 84 { 85 aRet[nOuter][nInner] = rData[nOuter][nInner]; 86 double& rValue = aRet[nOuter][nInner]; 87 if( rValue == DBL_MIN ) 88 ::rtl::math::setNan( &rValue ); 89 } 90 } 91 return aRet; 92 } 93 94 uno::Sequence< uno::Sequence< double > > lcl_getDBL_MINInsteadNAN( const uno::Sequence< uno::Sequence< double > >& rData ) 95 { 96 uno::Sequence< uno::Sequence< double > > aRet; 97 const sal_Int32 nOuterSize = rData.getLength(); 98 aRet.realloc( nOuterSize ); 99 for( sal_Int32 nOuter=0; nOuter<nOuterSize; ++nOuter ) 100 { 101 sal_Int32 nInnerSize = rData[nOuter].getLength(); 102 aRet[nOuter].realloc( nInnerSize ); 103 for( sal_Int32 nInner=0; nInner<nInnerSize; ++nInner ) 104 { 105 aRet[nOuter][nInner] = rData[nOuter][nInner]; 106 double& rValue = aRet[nOuter][nInner]; 107 if( ::rtl::math::isNan( rValue ) ) 108 rValue = DBL_MIN; 109 } 110 } 111 return aRet; 112 } 113 114 } // anonymous namespace 115 116 // -------------------------------------------------------------------------------- 117 118 namespace chart 119 { 120 namespace wrapper 121 { 122 123 //-------------------------------------------------------------------------------------- 124 125 struct lcl_Operator 126 { 127 lcl_Operator() 128 { 129 } 130 virtual ~lcl_Operator() 131 { 132 } 133 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) = 0; 134 135 virtual bool setsCategories( bool /*bDataInColumns*/ ) 136 { 137 return false; 138 } 139 }; 140 141 //-------------------------------------------------------------------------- 142 143 struct lcl_AllOperator : public lcl_Operator 144 { 145 lcl_AllOperator( const Reference< XChartData >& xDataToApply ) 146 : lcl_Operator() 147 , m_xDataToApply( xDataToApply ) 148 { 149 } 150 151 virtual bool setsCategories( bool /*bDataInColumns*/ ) 152 { 153 return true; 154 } 155 156 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) 157 { 158 if( !xDataAccess.is() ) 159 return; 160 161 Reference< XAnyDescriptionAccess > xNewAny( m_xDataToApply, uno::UNO_QUERY ); 162 Reference< XComplexDescriptionAccess > xNewComplex( m_xDataToApply, uno::UNO_QUERY ); 163 if( xNewAny.is() ) 164 { 165 xDataAccess->setData( xNewAny->getData() ); 166 xDataAccess->setComplexRowDescriptions( xNewAny->getComplexRowDescriptions() ); 167 xDataAccess->setComplexColumnDescriptions( xNewAny->getComplexColumnDescriptions() ); 168 } 169 else if( xNewComplex.is() ) 170 { 171 xDataAccess->setData( xNewComplex->getData() ); 172 xDataAccess->setComplexRowDescriptions( xNewComplex->getComplexRowDescriptions() ); 173 xDataAccess->setComplexColumnDescriptions( xNewComplex->getComplexColumnDescriptions() ); 174 } 175 else 176 { 177 Reference< XChartDataArray > xNew( m_xDataToApply, uno::UNO_QUERY ); 178 if( xNew.is() ) 179 { 180 xDataAccess->setData( xNew->getData() ); 181 xDataAccess->setRowDescriptions( xNew->getRowDescriptions() ); 182 xDataAccess->setColumnDescriptions( xNew->getColumnDescriptions() ); 183 } 184 } 185 } 186 187 Reference< XChartData > m_xDataToApply; 188 }; 189 190 //-------------------------------------------------------------------------- 191 192 struct lcl_DataOperator : public lcl_Operator 193 { 194 lcl_DataOperator( const Sequence< Sequence< double > >& rData ) 195 : lcl_Operator() 196 , m_rData( rData ) 197 { 198 } 199 200 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) 201 { 202 if( xDataAccess.is() ) 203 xDataAccess->setData( lcl_getNANInsteadDBL_MIN( m_rData ) ); 204 } 205 206 const Sequence< Sequence< double > >& m_rData; 207 }; 208 209 //-------------------------------------------------------------------------- 210 211 struct lcl_RowDescriptionsOperator : public lcl_Operator 212 { 213 lcl_RowDescriptionsOperator( const Sequence< OUString >& rRowDescriptions 214 , const Reference< chart2::XChartDocument >& xChartDoc ) 215 : lcl_Operator() 216 , m_rRowDescriptions( rRowDescriptions ) 217 , m_xChartDoc(xChartDoc) 218 , m_bDataInColumns(true) 219 { 220 } 221 222 virtual bool setsCategories( bool bDataInColumns ) 223 { 224 m_bDataInColumns = bDataInColumns; 225 return bDataInColumns; 226 } 227 228 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) 229 { 230 if( xDataAccess.is() ) 231 { 232 xDataAccess->setRowDescriptions( m_rRowDescriptions ); 233 if( m_bDataInColumns ) 234 DiagramHelper::switchToTextCategories( m_xChartDoc ); 235 } 236 } 237 238 const Sequence< OUString >& m_rRowDescriptions; 239 Reference< chart2::XChartDocument > m_xChartDoc; 240 bool m_bDataInColumns; 241 }; 242 243 //-------------------------------------------------------------------------- 244 245 struct lcl_ComplexRowDescriptionsOperator : public lcl_Operator 246 { 247 lcl_ComplexRowDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexRowDescriptions 248 , const Reference< chart2::XChartDocument >& xChartDoc ) 249 : lcl_Operator() 250 , m_rComplexRowDescriptions( rComplexRowDescriptions ) 251 , m_xChartDoc(xChartDoc) 252 , m_bDataInColumns(true) 253 { 254 } 255 256 virtual bool setsCategories( bool bDataInColumns ) 257 { 258 m_bDataInColumns = bDataInColumns; 259 return bDataInColumns; 260 } 261 262 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) 263 { 264 if( xDataAccess.is() ) 265 { 266 xDataAccess->setComplexRowDescriptions( m_rComplexRowDescriptions ); 267 if( m_bDataInColumns ) 268 DiagramHelper::switchToTextCategories( m_xChartDoc ); 269 } 270 } 271 272 const Sequence< Sequence< OUString > >& m_rComplexRowDescriptions; 273 Reference< chart2::XChartDocument > m_xChartDoc; 274 bool m_bDataInColumns; 275 }; 276 //-------------------------------------------------------------------------- 277 278 struct lcl_AnyRowDescriptionsOperator : public lcl_Operator 279 { 280 lcl_AnyRowDescriptionsOperator( const Sequence< Sequence< uno::Any > >& rAnyRowDescriptions ) 281 : lcl_Operator() 282 , m_rAnyRowDescriptions( rAnyRowDescriptions ) 283 { 284 } 285 286 virtual bool setsCategories( bool bDataInColumns ) 287 { 288 return bDataInColumns; 289 } 290 291 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) 292 { 293 if( xDataAccess.is() ) 294 xDataAccess->setAnyRowDescriptions( m_rAnyRowDescriptions ); 295 } 296 297 const Sequence< Sequence< uno::Any > >& m_rAnyRowDescriptions; 298 }; 299 300 //-------------------------------------------------------------------------- 301 302 struct lcl_ColumnDescriptionsOperator : public lcl_Operator 303 { 304 lcl_ColumnDescriptionsOperator( const Sequence< OUString >& rColumnDescriptions 305 , const Reference< chart2::XChartDocument >& xChartDoc ) 306 : lcl_Operator() 307 , m_rColumnDescriptions( rColumnDescriptions ) 308 , m_xChartDoc(xChartDoc) 309 , m_bDataInColumns(true) 310 { 311 } 312 313 virtual bool setsCategories( bool bDataInColumns ) 314 { 315 m_bDataInColumns = bDataInColumns; 316 return !bDataInColumns; 317 } 318 319 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) 320 { 321 if( xDataAccess.is() ) 322 { 323 xDataAccess->setColumnDescriptions( m_rColumnDescriptions ); 324 if( !m_bDataInColumns ) 325 DiagramHelper::switchToTextCategories( m_xChartDoc ); 326 } 327 } 328 329 const Sequence< OUString >& m_rColumnDescriptions; 330 Reference< chart2::XChartDocument > m_xChartDoc; 331 bool m_bDataInColumns; 332 }; 333 334 //-------------------------------------------------------------------------- 335 336 struct lcl_ComplexColumnDescriptionsOperator : public lcl_Operator 337 { 338 lcl_ComplexColumnDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexColumnDescriptions 339 , const Reference< chart2::XChartDocument >& xChartDoc ) 340 : lcl_Operator() 341 , m_rComplexColumnDescriptions( rComplexColumnDescriptions ) 342 , m_xChartDoc(xChartDoc) 343 , m_bDataInColumns(true) 344 { 345 } 346 347 virtual bool setsCategories( bool bDataInColumns ) 348 { 349 m_bDataInColumns = bDataInColumns; 350 return !bDataInColumns; 351 } 352 353 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) 354 { 355 if( xDataAccess.is() ) 356 { 357 xDataAccess->setComplexColumnDescriptions( m_rComplexColumnDescriptions ); 358 if( !m_bDataInColumns ) 359 DiagramHelper::switchToTextCategories( m_xChartDoc ); 360 } 361 } 362 363 const Sequence< Sequence< OUString > >& m_rComplexColumnDescriptions; 364 Reference< chart2::XChartDocument > m_xChartDoc; 365 bool m_bDataInColumns; 366 }; 367 368 //-------------------------------------------------------------------------- 369 370 struct lcl_AnyColumnDescriptionsOperator : public lcl_Operator 371 { 372 lcl_AnyColumnDescriptionsOperator( const Sequence< Sequence< uno::Any > >& rAnyColumnDescriptions ) 373 : lcl_Operator() 374 , m_rAnyColumnDescriptions( rAnyColumnDescriptions ) 375 { 376 } 377 378 virtual bool setsCategories( bool bDataInColumns ) 379 { 380 return bDataInColumns; 381 } 382 383 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) 384 { 385 if( xDataAccess.is() ) 386 xDataAccess->setAnyColumnDescriptions( m_rAnyColumnDescriptions ); 387 } 388 389 const Sequence< Sequence< uno::Any > >& m_rAnyColumnDescriptions; 390 }; 391 392 //-------------------------------------------------------------------------- 393 394 struct lcl_DateCategoriesOperator : public lcl_Operator 395 { 396 lcl_DateCategoriesOperator( const Sequence< double >& rDates ) 397 : lcl_Operator() 398 , m_rDates( rDates ) 399 { 400 } 401 402 virtual bool setsCategories( bool /*bDataInColumns*/ ) 403 { 404 return true; 405 } 406 407 virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) 408 { 409 Reference< XDateCategories > xDateCategories( xDataAccess, uno::UNO_QUERY ); 410 if( xDateCategories.is() ) 411 xDateCategories->setDateCategories( m_rDates ); 412 } 413 414 const Sequence< double >& m_rDates; 415 }; 416 417 //-------------------------------------------------------------------------- 418 419 ChartDataWrapper::ChartDataWrapper( ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact ) : 420 m_spChart2ModelContact( spChart2ModelContact ), 421 m_aEventListenerContainer( m_aMutex ) 422 { 423 osl_incrementInterlockedCount( &m_refCount ); 424 initDataAccess(); 425 osl_decrementInterlockedCount( &m_refCount ); 426 } 427 428 ChartDataWrapper::ChartDataWrapper( ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact, 429 const Reference< XChartData >& xNewData ) : 430 m_spChart2ModelContact( spChart2ModelContact ), 431 m_aEventListenerContainer( m_aMutex ) 432 { 433 osl_incrementInterlockedCount( &m_refCount ); 434 lcl_AllOperator aOperator( xNewData ); 435 applyData( aOperator ); 436 osl_decrementInterlockedCount( &m_refCount ); 437 } 438 439 ChartDataWrapper::~ChartDataWrapper() 440 { 441 // @todo: implement XComponent and call this in dispose(). In the DTOR the 442 // ref-count is 0, thus creating a stack reference to this calls the DTOR at 443 // the end of the block recursively 444 // uno::Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) ); 445 // m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) ); 446 } 447 448 // ____ XChartDataArray (read)____ 449 Sequence< Sequence< double > > SAL_CALL ChartDataWrapper::getData() 450 { 451 initDataAccess(); 452 if( m_xDataAccess.is() ) 453 return lcl_getDBL_MINInsteadNAN( m_xDataAccess->getData() ); 454 return Sequence< Sequence< double > >(); 455 } 456 Sequence< OUString > SAL_CALL ChartDataWrapper::getRowDescriptions() 457 { 458 initDataAccess(); 459 if( m_xDataAccess.is() ) 460 return m_xDataAccess->getRowDescriptions(); 461 return Sequence< OUString >(); 462 } 463 Sequence< OUString > SAL_CALL ChartDataWrapper::getColumnDescriptions() 464 { 465 initDataAccess(); 466 if( m_xDataAccess.is() ) 467 return m_xDataAccess->getColumnDescriptions(); 468 return Sequence< OUString > (); 469 } 470 471 // ____ XComplexDescriptionAccess (read) ____ 472 Sequence< Sequence< OUString > > SAL_CALL ChartDataWrapper::getComplexRowDescriptions() 473 { 474 initDataAccess(); 475 if( m_xDataAccess.is() ) 476 return m_xDataAccess->getComplexRowDescriptions(); 477 return Sequence< Sequence< OUString > >(); 478 } 479 Sequence< Sequence< OUString > > SAL_CALL ChartDataWrapper::getComplexColumnDescriptions() 480 { 481 initDataAccess(); 482 if( m_xDataAccess.is() ) 483 return m_xDataAccess->getComplexColumnDescriptions(); 484 return Sequence< Sequence< OUString > >(); 485 } 486 487 // ____ XAnyDescriptionAccess (read) ____ 488 Sequence< Sequence< uno::Any > > SAL_CALL ChartDataWrapper::getAnyRowDescriptions() 489 { 490 initDataAccess(); 491 if( m_xDataAccess.is() ) 492 return m_xDataAccess->getAnyRowDescriptions(); 493 return Sequence< Sequence< uno::Any > >(); 494 } 495 Sequence< Sequence< uno::Any > > SAL_CALL ChartDataWrapper::getAnyColumnDescriptions() 496 { 497 initDataAccess(); 498 if( m_xDataAccess.is() ) 499 return m_xDataAccess->getAnyColumnDescriptions(); 500 return Sequence< Sequence< uno::Any > >(); 501 } 502 503 // ____ XDateCategories (read) ____ 504 Sequence< double > SAL_CALL ChartDataWrapper::getDateCategories() 505 { 506 initDataAccess(); 507 Reference< XDateCategories > xDateCategories( m_xDataAccess, uno::UNO_QUERY ); 508 if( xDateCategories.is() ) 509 return xDateCategories->getDateCategories(); 510 return Sequence< double >(); 511 } 512 513 // ____ XChartDataArray (write)____ 514 void SAL_CALL ChartDataWrapper::setData( const Sequence< Sequence< double > >& rData ) 515 { 516 lcl_DataOperator aOperator( rData ); 517 applyData( aOperator ); 518 } 519 void SAL_CALL ChartDataWrapper::setRowDescriptions( const Sequence< OUString >& rRowDescriptions ) 520 { 521 lcl_RowDescriptionsOperator aOperator( rRowDescriptions, m_spChart2ModelContact->getChart2Document() ); 522 applyData( aOperator ); 523 } 524 void SAL_CALL ChartDataWrapper::setColumnDescriptions( const Sequence< OUString >& rColumnDescriptions ) 525 { 526 lcl_ColumnDescriptionsOperator aOperator( rColumnDescriptions, m_spChart2ModelContact->getChart2Document() ); 527 applyData( aOperator ); 528 } 529 530 // ____ XComplexDescriptionAccess (write) ____ 531 void SAL_CALL ChartDataWrapper::setComplexRowDescriptions( const Sequence< Sequence< ::rtl::OUString > >& rRowDescriptions ) 532 { 533 lcl_ComplexRowDescriptionsOperator aOperator( rRowDescriptions, m_spChart2ModelContact->getChart2Document() ); 534 applyData( aOperator ); 535 } 536 void SAL_CALL ChartDataWrapper::setComplexColumnDescriptions( const Sequence< Sequence< ::rtl::OUString > >& rColumnDescriptions ) 537 { 538 lcl_ComplexColumnDescriptionsOperator aOperator( rColumnDescriptions, m_spChart2ModelContact->getChart2Document() ); 539 applyData( aOperator ); 540 } 541 542 // ____ XAnyDescriptionAccess (write) ____ 543 void SAL_CALL ChartDataWrapper::setAnyRowDescriptions( const Sequence< Sequence< uno::Any > >& rRowDescriptions ) 544 { 545 lcl_AnyRowDescriptionsOperator aOperator( rRowDescriptions ); 546 applyData( aOperator ); 547 } 548 void SAL_CALL ChartDataWrapper::setAnyColumnDescriptions( const Sequence< Sequence< uno::Any > >& rColumnDescriptions ) 549 { 550 lcl_AnyColumnDescriptionsOperator aOperator( rColumnDescriptions ); 551 applyData( aOperator ); 552 } 553 554 // ____ XDateCategories (write) ____ 555 void SAL_CALL ChartDataWrapper::setDateCategories( const Sequence< double >& rDates ) 556 { 557 Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); 558 ControllerLockGuard aCtrlLockGuard( uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY )); 559 lcl_DateCategoriesOperator aOperator( rDates ); 560 applyData( aOperator ); 561 DiagramHelper::switchToDateCategories( xChartDoc ); 562 } 563 564 //-------------------------------------------------------------------------------------- 565 566 // ____ XChartData (base of XChartDataArray) ____ 567 void SAL_CALL ChartDataWrapper::addChartDataChangeEventListener( 568 const uno::Reference< 569 ::com::sun::star::chart::XChartDataChangeEventListener >& aListener ) 570 { 571 m_aEventListenerContainer.addInterface( aListener ); 572 } 573 574 void SAL_CALL ChartDataWrapper::removeChartDataChangeEventListener( 575 const uno::Reference< 576 ::com::sun::star::chart::XChartDataChangeEventListener >& aListener ) 577 { 578 m_aEventListenerContainer.removeInterface( aListener ); 579 } 580 581 double SAL_CALL ChartDataWrapper::getNotANumber() 582 { 583 return DBL_MIN; 584 } 585 586 sal_Bool SAL_CALL ChartDataWrapper::isNotANumber( double nNumber ) 587 { 588 return DBL_MIN == nNumber 589 || ::rtl::math::isNan( nNumber ) 590 || ::rtl::math::isInf( nNumber ); 591 } 592 593 // ____ XComponent ____ 594 void SAL_CALL ChartDataWrapper::dispose() 595 { 596 m_aEventListenerContainer.disposeAndClear( lang::EventObject( static_cast< ::cppu::OWeakObject* >( this ))); 597 m_xDataAccess=0; 598 } 599 600 void SAL_CALL ChartDataWrapper::addEventListener( 601 const uno::Reference< lang::XEventListener > & xListener ) 602 { 603 m_aEventListenerContainer.addInterface( xListener ); 604 } 605 606 void SAL_CALL ChartDataWrapper::removeEventListener( 607 const uno::Reference< lang::XEventListener >& aListener ) 608 { 609 m_aEventListenerContainer.removeInterface( aListener ); 610 } 611 612 // ____ XEventListener ____ 613 void SAL_CALL ChartDataWrapper::disposing( const lang::EventObject& /* Source */ ) 614 { 615 } 616 617 // ::com::sun::star::chart::ChartDataChangeEvent aEvent; 618 // aEvent.Type = chart::ChartDataChangeType_ALL; 619 // aEvent.StartColumn = 0; 620 // aEvent.EndColumn = 0; 621 // aEvent.StartRow = 0; 622 // aEvent.EndRow = 0; 623 void ChartDataWrapper::fireChartDataChangeEvent( 624 ::com::sun::star::chart::ChartDataChangeEvent& aEvent ) 625 { 626 if( ! m_aEventListenerContainer.getLength() ) 627 return; 628 629 uno::Reference< uno::XInterface > xSrc( static_cast< cppu::OWeakObject* >( this )); 630 OSL_ASSERT( xSrc.is()); 631 if( xSrc.is() ) 632 aEvent.Source = xSrc; 633 634 ::cppu::OInterfaceIteratorHelper aIter( m_aEventListenerContainer ); 635 636 while( aIter.hasMoreElements() ) 637 { 638 uno::Reference< 639 ::com::sun::star::chart::XChartDataChangeEventListener > xListener( 640 aIter.next(), uno::UNO_QUERY ); 641 if( xListener.is() ) 642 xListener->chartDataChanged( aEvent ); 643 } 644 } 645 646 // -------------------------------------------------------------------------------- 647 648 void ChartDataWrapper::switchToInternalDataProvider() 649 { 650 //create an internal data provider that is connected to the model 651 Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); 652 if( xChartDoc.is() ) 653 xChartDoc->createInternalDataProvider( true /*bCloneExistingData*/ ); 654 initDataAccess(); 655 } 656 657 void ChartDataWrapper::initDataAccess() 658 { 659 Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); 660 if( !xChartDoc.is() ) 661 return; 662 if( xChartDoc->hasInternalDataProvider() ) 663 m_xDataAccess = Reference< XAnyDescriptionAccess >( xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW ); 664 else 665 { 666 //create a separate "internal data provider" that is not connected to the model 667 m_xDataAccess = Reference< XAnyDescriptionAccess >( ChartModelHelper::createInternalDataProvider( 668 xChartDoc, false /*bConnectToModel*/ ), uno::UNO_QUERY_THROW ); 669 } 670 } 671 672 void ChartDataWrapper::applyData( lcl_Operator& rDataOperator ) 673 { 674 //bool bSetValues, bool bSetRowDescriptions, bool bSetColumnDescriptions 675 Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() ); 676 if( !xChartDoc.is() ) 677 return; 678 679 // remember some diagram properties to reset later 680 sal_Bool bStacked = sal_False; 681 sal_Bool bPercent = sal_False; 682 sal_Bool bDeep = sal_False; 683 uno::Reference< ::com::sun::star::chart::XChartDocument > xOldDoc( xChartDoc, uno::UNO_QUERY ); 684 OSL_ASSERT( xOldDoc.is()); 685 uno::Reference< beans::XPropertySet > xDiaProp( xOldDoc->getDiagram(), uno::UNO_QUERY ); 686 if( xDiaProp.is()) 687 { 688 xDiaProp->getPropertyValue( C2U("Stacked")) >>= bStacked; 689 xDiaProp->getPropertyValue( C2U("Percent")) >>= bPercent; 690 xDiaProp->getPropertyValue( C2U("Deep")) >>= bDeep; 691 } 692 693 //detect arguments for the new data source 694 ::rtl::OUString aRangeString; 695 bool bUseColumns = true; 696 bool bFirstCellAsLabel = true; 697 bool bHasCategories = true; 698 uno::Sequence< sal_Int32 > aSequenceMapping; 699 700 DataSourceHelper::detectRangeSegmentation( 701 uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ), 702 aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ); 703 704 if( !bHasCategories && rDataOperator.setsCategories( bUseColumns ) ) 705 bHasCategories = true; 706 707 aRangeString = C2U("all"); 708 uno::Sequence< beans::PropertyValue > aArguments( DataSourceHelper::createArguments( 709 aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ) ); 710 711 712 // /-- locked controllers 713 ControllerLockGuard aCtrlLockGuard( uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY )); 714 715 // create and attach new data source 716 switchToInternalDataProvider(); 717 rDataOperator.apply(m_xDataAccess); 718 uno::Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() ); 719 OSL_ASSERT( xDataProvider.is() ); 720 if( !xDataProvider.is() ) 721 return; 722 uno::Reference< chart2::data::XDataSource > xSource( xDataProvider->createDataSource( aArguments ) ); 723 724 uno::Reference< chart2::XDiagram > xDia( xChartDoc->getFirstDiagram() ); 725 if( xDia.is() ) 726 xDia->setDiagramData( xSource, aArguments ); 727 728 //correct stacking mode 729 if( bStacked || bPercent || bDeep ) 730 { 731 StackMode eStackMode = StackMode_Y_STACKED; 732 if( bDeep ) 733 eStackMode = StackMode_Z_STACKED; 734 else if( bPercent ) 735 eStackMode = StackMode_Y_STACKED_PERCENT; 736 DiagramHelper::setStackMode( xDia, eStackMode ); 737 } 738 739 // notify listeners 740 ::com::sun::star::chart::ChartDataChangeEvent aEvent( 741 static_cast< ::cppu::OWeakObject* >( this ), 742 ::com::sun::star::chart::ChartDataChangeType_ALL, 0, 0, 0, 0 ); 743 fireChartDataChangeEvent( aEvent ); 744 // \-- locked controllers 745 } 746 747 // -------------------------------------------------------------------------------- 748 749 uno::Sequence< ::rtl::OUString > ChartDataWrapper::getSupportedServiceNames_Static() 750 { 751 uno::Sequence< ::rtl::OUString > aServices( 2 ); 752 aServices[ 0 ] = C2U( "com.sun.star.chart.ChartDataArray" ); 753 aServices[ 1 ] = C2U( "com.sun.star.chart.ChartData" ); 754 755 return aServices; 756 } 757 758 // ================================================================================ 759 760 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static 761 APPHELPER_XSERVICEINFO_IMPL( ChartDataWrapper, lcl_aServiceName ); 762 763 } // namespace wrapper 764 } // namespace chart 765