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_chart2.hxx" 30 31 #include "DialogModel.hxx" 32 #include "RangeSelectionHelper.hxx" 33 #include "PropertyHelper.hxx" 34 #include "DataSeriesHelper.hxx" 35 #include "DataSourceHelper.hxx" 36 #include "DiagramHelper.hxx" 37 #include "macros.hxx" 38 #include "Strings.hrc" 39 #include "ResId.hxx" 40 #include "ContainerHelper.hxx" 41 #include "CommonFunctors.hxx" 42 #include "ControllerLockGuard.hxx" 43 #include "ChartTypeHelper.hxx" 44 #include "ThreeDHelper.hxx" 45 46 #include <com/sun/star/util/XCloneable.hpp> 47 #include <com/sun/star/chart2/AxisType.hpp> 48 #include <com/sun/star/chart2/XTitled.hpp> 49 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> 50 #include <com/sun/star/chart2/XChartTypeContainer.hpp> 51 #include <com/sun/star/chart2/XDataSeriesContainer.hpp> 52 #include <com/sun/star/chart2/data/XDataSink.hpp> 53 54 #include <tools/string.hxx> 55 56 #include <utility> 57 #include <algorithm> 58 #include <iterator> 59 #include <functional> 60 #include <numeric> 61 62 using namespace ::com::sun::star; 63 using namespace ::com::sun::star::chart2; 64 using namespace ::chart::ContainerHelper; 65 66 using ::com::sun::star::uno::Reference; 67 using ::com::sun::star::uno::Sequence; 68 using ::rtl::OUString; 69 70 // ---------------------------------------- 71 72 namespace 73 { 74 const OUString lcl_aLabelRole( RTL_CONSTASCII_USTRINGPARAM( "label" )); 75 76 struct lcl_ChartTypeToSeriesCnt : ::std::unary_function< 77 Reference< XChartType >, Reference< XDataSeriesContainer > > 78 { 79 Reference< XDataSeriesContainer > operator() ( 80 const Reference< XChartType > & xChartType ) 81 { 82 return Reference< XDataSeriesContainer >::query( xChartType ); 83 } 84 }; 85 86 OUString lcl_ConvertRole( const OUString & rRoleString, bool bFromInternalToUI ) 87 { 88 OUString aResult( rRoleString ); 89 90 typedef ::std::map< OUString, OUString > tTranslationMap; 91 static tTranslationMap aTranslationMap; 92 93 if( aTranslationMap.size() == 0 ) 94 { 95 aTranslationMap[ C2U( "categories" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_CATEGORIES ))); 96 aTranslationMap[ C2U( "error-bars-x" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X_ERROR ))); 97 aTranslationMap[ C2U( "error-bars-x-positive" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X_ERROR_POSITIVE ))); 98 aTranslationMap[ C2U( "error-bars-x-negative" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X_ERROR_NEGATIVE ))); 99 aTranslationMap[ C2U( "error-bars-y" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y_ERROR ))); 100 aTranslationMap[ C2U( "error-bars-y-positive" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_POSITIVE ))); 101 aTranslationMap[ C2U( "error-bars-y-negative" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_NEGATIVE ))); 102 aTranslationMap[ C2U( "label" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_LABEL ))); 103 aTranslationMap[ C2U( "values-first" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_FIRST ))); 104 aTranslationMap[ C2U( "values-last" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_LAST ))); 105 aTranslationMap[ C2U( "values-max" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_MAX ))); 106 aTranslationMap[ C2U( "values-min" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_MIN ))); 107 aTranslationMap[ C2U( "values-x" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X ))); 108 aTranslationMap[ C2U( "values-y" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y ))); 109 aTranslationMap[ C2U( "values-size" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_SIZE ))); 110 } 111 112 if( bFromInternalToUI ) 113 { 114 tTranslationMap::const_iterator aIt( aTranslationMap.find( rRoleString )); 115 if( aIt != aTranslationMap.end()) 116 { 117 aResult = (*aIt).second; 118 } 119 } 120 else 121 { 122 tTranslationMap::const_iterator aIt( 123 ::std::find_if( aTranslationMap.begin(), aTranslationMap.end(), 124 ::std::compose1( ::std::bind2nd( 125 ::std::equal_to< tTranslationMap::mapped_type >(), 126 rRoleString ), 127 ::std::select2nd< tTranslationMap::value_type >()))); 128 129 if( aIt != aTranslationMap.end()) 130 aResult = (*aIt).first; 131 } 132 133 return aResult; 134 } 135 136 typedef ::std::map< ::rtl::OUString, sal_Int32 > lcl_tRoleIndexMap; 137 138 void lcl_createRoleIndexMap( lcl_tRoleIndexMap & rOutMap ) 139 { 140 rOutMap.clear(); 141 sal_Int32 nIndex = 0; 142 143 rOutMap[ C2U( "label" ) ] = ++nIndex; 144 rOutMap[ C2U( "categories" ) ] = ++nIndex; 145 rOutMap[ C2U( "values-x" ) ] = ++nIndex; 146 rOutMap[ C2U( "values-y" ) ] = ++nIndex; 147 rOutMap[ C2U( "error-bars-x" ) ] = ++nIndex; 148 rOutMap[ C2U( "error-bars-x-positive" ) ] = ++nIndex; 149 rOutMap[ C2U( "error-bars-x-negative" ) ] = ++nIndex; 150 rOutMap[ C2U( "error-bars-y" ) ] = ++nIndex; 151 rOutMap[ C2U( "error-bars-y-positive" ) ] = ++nIndex; 152 rOutMap[ C2U( "error-bars-y-negative" ) ] = ++nIndex; 153 rOutMap[ C2U( "values-first" ) ] = ++nIndex; 154 rOutMap[ C2U( "values-min" ) ] = ++nIndex; 155 rOutMap[ C2U( "values-max" ) ] = ++nIndex; 156 rOutMap[ C2U( "values-last" ) ] = ++nIndex; 157 rOutMap[ C2U( "values-size" ) ] = ++nIndex; 158 } 159 160 struct lcl_DataSeriesContainerAppend : public 161 ::std::iterator< ::std::output_iterator_tag, Reference< XDataSeriesContainer > > 162 { 163 typedef ::std::vector< ::chart::DialogModel::tSeriesWithChartTypeByName > tContainerType; 164 165 explicit lcl_DataSeriesContainerAppend( tContainerType & rCnt ) 166 : m_rDestCnt( rCnt ) 167 {} 168 169 lcl_DataSeriesContainerAppend & operator= ( const value_type & xVal ) 170 { 171 try 172 { 173 if( xVal.is()) 174 { 175 Sequence< Reference< XDataSeries > > aSeq( xVal->getDataSeries()); 176 OUString aRole( RTL_CONSTASCII_USTRINGPARAM("values-y")); 177 Reference< XChartType > xCT( xVal, uno::UNO_QUERY ); 178 if( xCT.is()) 179 aRole = xCT->getRoleOfSequenceForSeriesLabel(); 180 for( sal_Int32 nI = 0; nI < aSeq.getLength(); ++ nI ) 181 { 182 m_rDestCnt.push_back( 183 ::chart::DialogModel::tSeriesWithChartTypeByName( 184 ::chart::DataSeriesHelper::getDataSeriesLabel( aSeq[nI], aRole ), 185 ::std::make_pair( aSeq[nI], xCT ))); 186 } 187 } 188 } 189 catch( uno::Exception & ex ) 190 { 191 ASSERT_EXCEPTION( ex ); 192 } 193 return *this; 194 } 195 196 lcl_DataSeriesContainerAppend & operator* () { return *this; } 197 lcl_DataSeriesContainerAppend & operator++ () { return *this; } 198 lcl_DataSeriesContainerAppend & operator++ (int) { return *this; } 199 200 private: 201 tContainerType & m_rDestCnt; 202 }; 203 204 struct lcl_RolesWithRangeAppend : public 205 ::std::iterator< ::std::output_iterator_tag, Reference< data::XLabeledDataSequence > > 206 { 207 typedef ::chart::DialogModel::tRolesWithRanges tContainerType; 208 209 explicit lcl_RolesWithRangeAppend( tContainerType & rCnt, 210 const ::rtl::OUString & aLabelRole ) 211 : m_rDestCnt( rCnt ), 212 m_aRoleForLabelSeq( aLabelRole ) 213 {} 214 215 lcl_RolesWithRangeAppend & operator= ( const value_type & xVal ) 216 { 217 try 218 { 219 if( xVal.is()) 220 { 221 // data sequence 222 Reference< data::XDataSequence > xSeq( xVal->getValues()); 223 if( xSeq.is()) 224 { 225 OUString aRole; 226 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW ); 227 if( xProp->getPropertyValue( C2U("Role")) >>= aRole ) 228 { 229 m_rDestCnt.insert( 230 tContainerType::value_type( 231 aRole, xSeq->getSourceRangeRepresentation())); 232 // label 233 if( aRole.equals( m_aRoleForLabelSeq )) 234 { 235 Reference< data::XDataSequence > xLabelSeq( xVal->getLabel()); 236 if( xLabelSeq.is()) 237 { 238 m_rDestCnt.insert( 239 tContainerType::value_type( 240 lcl_aLabelRole, xLabelSeq->getSourceRangeRepresentation())); 241 } 242 } 243 } 244 } 245 } 246 } 247 catch( uno::Exception & ex ) 248 { 249 ASSERT_EXCEPTION( ex ); 250 } 251 return *this; 252 } 253 254 lcl_RolesWithRangeAppend & operator* () { return *this; } 255 lcl_RolesWithRangeAppend & operator++ () { return *this; } 256 lcl_RolesWithRangeAppend & operator++ (int) { return *this; } 257 258 private: 259 tContainerType & m_rDestCnt; 260 OUString m_aRoleForLabelSeq; 261 }; 262 263 void lcl_SetSequenceRole( 264 const Reference< data::XDataSequence > & xSeq, 265 const OUString & rRole ) 266 { 267 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY ); 268 if( xProp.is()) 269 xProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole )); 270 } 271 272 Reference< XDataSeries > lcl_CreateNewSeries( 273 const Reference< uno::XComponentContext > & xContext, 274 const Reference< XChartType > & xChartType, 275 sal_Int32 nNewSeriesIndex, 276 sal_Int32 nTotalNumberOfSeriesInCTGroup, 277 const Reference< XDiagram > & xDiagram, 278 const Reference< XChartTypeTemplate > & xTemplate, 279 bool bCreateDataCachedSequences ) 280 { 281 // create plain series 282 Reference< XDataSeries > xResult( 283 xContext->getServiceManager()->createInstanceWithContext( 284 C2U( "com.sun.star.chart2.DataSeries" ), 285 xContext ), uno::UNO_QUERY ); 286 if( xTemplate.is()) 287 { 288 Reference< beans::XPropertySet > xResultProp( xResult, uno::UNO_QUERY ); 289 if( xResultProp.is()) 290 { 291 // @deprecated: correct default color should be found by view 292 // without setting it as hard attribute 293 Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); 294 if( xColorScheme.is()) 295 xResultProp->setPropertyValue( 296 C2U("Color"), uno::makeAny( xColorScheme->getColorByIndex( nNewSeriesIndex ))); 297 } 298 sal_Int32 nGroupIndex=0; 299 if( xChartType.is()) 300 { 301 Sequence< Reference< XChartType > > aCTs( 302 ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram )); 303 for( ; nGroupIndex<aCTs.getLength(); ++nGroupIndex) 304 if( aCTs[nGroupIndex] == xChartType ) 305 break; 306 if( nGroupIndex == aCTs.getLength()) 307 nGroupIndex = 0; 308 } 309 xTemplate->applyStyle( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup ); 310 } 311 312 if( bCreateDataCachedSequences ) 313 { 314 // set chart type specific roles 315 Reference< data::XDataSink > xSink( xResult, uno::UNO_QUERY ); 316 if( xChartType.is() && xSink.is()) 317 { 318 ::std::vector< Reference< data::XLabeledDataSequence > > aNewSequences; 319 const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel(); 320 const OUString aLabel( String( ::chart::SchResId( STR_DATA_UNNAMED_SERIES ))); 321 const Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles()); 322 const Sequence< OUString > aOptRoles( xChartType->getSupportedOptionalRoles()); 323 sal_Int32 nI = 0; 324 325 for(nI=0; nI<aRoles.getLength(); ++nI) 326 { 327 if( aRoles[nI].equals( lcl_aLabelRole )) 328 continue; 329 Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence() ); 330 lcl_SetSequenceRole( xSeq, aRoles[nI] ); 331 // assert that aRoleOfSeqForSeriesLabel is part of the mandatory roles 332 if( aRoles[nI].equals( aRoleOfSeqForSeriesLabel )) 333 { 334 Reference< data::XDataSequence > xLabel( ::chart::DataSourceHelper::createCachedDataSequence( aLabel )); 335 lcl_SetSequenceRole( xLabel, lcl_aLabelRole ); 336 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq, xLabel )); 337 } 338 else 339 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq )); 340 } 341 342 for(nI=0; nI<aOptRoles.getLength(); ++nI) 343 { 344 if( aOptRoles[nI].equals( lcl_aLabelRole )) 345 continue; 346 Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence()); 347 lcl_SetSequenceRole( xSeq, aOptRoles[nI] ); 348 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq )); 349 } 350 351 xSink->setData( ContainerToSequence( aNewSequences )); 352 } 353 } 354 355 return xResult; 356 } 357 358 struct lcl_addSeriesNumber : public ::std::binary_function< 359 sal_Int32, Reference< XDataSeriesContainer >, sal_Int32 > 360 { 361 sal_Int32 operator() ( sal_Int32 nCurrentNumber, const Reference< XDataSeriesContainer > & xCnt ) const 362 { 363 if( xCnt.is()) 364 return nCurrentNumber + (xCnt->getDataSeries().getLength()); 365 return nCurrentNumber; 366 } 367 }; 368 369 } // anonymous namespace 370 371 // ---------------------------------------- 372 373 374 namespace chart 375 { 376 377 DialogModel::DialogModel( 378 const Reference< XChartDocument > & xChartDocument, 379 const Reference< uno::XComponentContext > & xContext ) : 380 m_xChartDocument( xChartDocument ), 381 m_xContext( xContext ), 382 m_aTimerTriggeredControllerLock( uno::Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) ) 383 { 384 } 385 386 DialogModel::~DialogModel() 387 {} 388 389 void DialogModel::setTemplate( 390 const Reference< XChartTypeTemplate > & xTemplate ) 391 { 392 m_xTemplate = xTemplate; 393 } 394 395 ::boost::shared_ptr< RangeSelectionHelper > 396 DialogModel::getRangeSelectionHelper() const 397 { 398 if( ! m_spRangeSelectionHelper.get()) 399 m_spRangeSelectionHelper.reset( 400 new RangeSelectionHelper( m_xChartDocument )); 401 402 return m_spRangeSelectionHelper; 403 } 404 405 Reference< frame::XModel > DialogModel::getChartModel() const 406 { 407 Reference< frame::XModel > xResult( m_xChartDocument, uno::UNO_QUERY ); 408 return xResult; 409 } 410 411 Reference< data::XDataProvider > DialogModel::getDataProvider() const 412 { 413 Reference< data::XDataProvider > xResult; 414 if( m_xChartDocument.is()) 415 xResult.set( m_xChartDocument->getDataProvider()); 416 return xResult; 417 } 418 419 ::std::vector< Reference< XDataSeriesContainer > > 420 DialogModel::getAllDataSeriesContainers() const 421 { 422 ::std::vector< Reference< XDataSeriesContainer > > aResult; 423 424 try 425 { 426 Reference< XDiagram > xDiagram; 427 if( m_xChartDocument.is()) 428 xDiagram.set( m_xChartDocument->getFirstDiagram()); 429 if( xDiagram.is()) 430 { 431 Reference< XCoordinateSystemContainer > xCooSysCnt( 432 xDiagram, uno::UNO_QUERY_THROW ); 433 Sequence< Reference< XCoordinateSystem > > aCooSysSeq( 434 xCooSysCnt->getCoordinateSystems()); 435 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i ) 436 { 437 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW ); 438 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); 439 ::std::transform( 440 aChartTypeSeq.getConstArray(), aChartTypeSeq.getConstArray() + aChartTypeSeq.getLength(), 441 ::std::back_inserter( aResult ), 442 lcl_ChartTypeToSeriesCnt() ); 443 } 444 } 445 } 446 catch( uno::Exception & ex ) 447 { 448 ASSERT_EXCEPTION( ex ); 449 } 450 451 return aResult; 452 } 453 454 ::std::vector< DialogModel::tSeriesWithChartTypeByName > 455 DialogModel::getAllDataSeriesWithLabel() const 456 { 457 ::std::vector< tSeriesWithChartTypeByName > aResult; 458 ::std::vector< Reference< XDataSeriesContainer > > aContainers( 459 getAllDataSeriesContainers()); 460 461 ::std::copy( aContainers.begin(), aContainers.end(), 462 lcl_DataSeriesContainerAppend( aResult )); 463 return aResult; 464 } 465 466 DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges( 467 const Reference< XDataSeries > & xSeries, 468 const ::rtl::OUString & aRoleOfSequenceForLabel, 469 const Reference< chart2::XChartType > & xChartType ) const 470 { 471 DialogModel::tRolesWithRanges aResult; 472 try 473 { 474 Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW ); 475 const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences()); 476 ::std::copy( aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength(), 477 lcl_RolesWithRangeAppend( aResult, aRoleOfSequenceForLabel )); 478 if( xChartType.is()) 479 { 480 // add missing mandatory roles 481 Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles()); 482 OUString aEmptyString; 483 sal_Int32 nI = 0; 484 for( nI=0; nI < aRoles.getLength(); ++nI ) 485 { 486 if( aResult.find( aRoles[nI] ) == aResult.end() ) 487 aResult.insert( DialogModel::tRolesWithRanges::value_type( aRoles[nI], aEmptyString )); 488 } 489 490 // add missing optional roles 491 aRoles = xChartType->getSupportedOptionalRoles(); 492 for( nI=0; nI < aRoles.getLength(); ++nI ) 493 { 494 if( aResult.find( aRoles[nI] ) == aResult.end() ) 495 aResult.insert( DialogModel::tRolesWithRanges::value_type( aRoles[nI], aEmptyString )); 496 } 497 } 498 } 499 catch( uno::Exception & ex ) 500 { 501 ASSERT_EXCEPTION( ex ); 502 } 503 return aResult; 504 } 505 506 void DialogModel::moveSeries( 507 const Reference< XDataSeries > & xSeries, 508 eMoveDirection eDirection ) 509 { 510 m_aTimerTriggeredControllerLock.startTimer(); 511 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) ); 512 513 Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); 514 DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MOVE_UP ); 515 } 516 517 Reference< chart2::XDataSeries > DialogModel::insertSeriesAfter( 518 const Reference< XDataSeries > & xSeries, 519 const Reference< XChartType > & xChartType, 520 bool bCreateDataCachedSequences /* = false */ ) 521 { 522 m_aTimerTriggeredControllerLock.startTimer(); 523 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) ); 524 Reference< XDataSeries > xNewSeries; 525 526 try 527 { 528 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); 529 ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); 530 531 sal_Int32 nSeriesInChartType = 0; 532 const sal_Int32 nTotalSeries = countSeries(); 533 if( xChartType.is()) 534 { 535 Reference< XDataSeriesContainer > xCnt( xChartType, uno::UNO_QUERY_THROW ); 536 nSeriesInChartType = xCnt->getDataSeries().getLength(); 537 } 538 539 // create new series 540 xNewSeries.set( 541 lcl_CreateNewSeries( 542 m_xContext, 543 xChartType, 544 nTotalSeries, // new series' index 545 nSeriesInChartType, 546 xDiagram, 547 m_xTemplate, 548 bCreateDataCachedSequences )); 549 550 // add new series to container 551 if( xNewSeries.is()) 552 { 553 Reference< XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW ); 554 ::std::vector< Reference< XDataSeries > > aSeries( 555 SequenceToVector( xSeriesCnt->getDataSeries())); 556 ::std::vector< Reference< XDataSeries > >::iterator aIt = 557 ::std::find( aSeries.begin(), aSeries.end(), xSeries ); 558 if( aIt == aSeries.end()) 559 // if we have no series we insert at the first position. 560 aIt = aSeries.begin(); 561 else 562 // vector::insert inserts before, so we have to advance 563 ++aIt; 564 aSeries.insert( aIt, xNewSeries ); 565 xSeriesCnt->setDataSeries( ContainerToSequence( aSeries )); 566 } 567 568 ThreeDHelper::setScheme( xDiagram, e3DScheme ); 569 } 570 catch( uno::Exception & ex ) 571 { 572 ASSERT_EXCEPTION( ex ); 573 } 574 return xNewSeries; 575 } 576 577 void DialogModel::deleteSeries( 578 const Reference< XDataSeries > & xSeries, 579 const Reference< XChartType > & xChartType ) 580 { 581 m_aTimerTriggeredControllerLock.startTimer(); 582 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) ); 583 584 DataSeriesHelper::deleteSeries( xSeries, xChartType ); 585 } 586 587 Reference< data::XLabeledDataSequence > DialogModel::getCategories() const 588 { 589 Reference< data::XLabeledDataSequence > xResult; 590 try 591 { 592 if( m_xChartDocument.is()) 593 { 594 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); 595 xResult.set( DiagramHelper::getCategoriesFromDiagram( xDiagram )); 596 } 597 } 598 catch( uno::Exception & ex ) 599 { 600 ASSERT_EXCEPTION( ex ); 601 } 602 return xResult; 603 } 604 605 void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories ) 606 { 607 if( m_xChartDocument.is()) 608 { 609 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); 610 if( xDiagram.is()) 611 { 612 // categories 613 bool bSupportsCategories = true; 614 615 Reference< XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); 616 if( xFirstChartType.is() ) 617 { 618 sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis 619 bSupportsCategories = (nAxisType == AxisType::CATEGORY); 620 } 621 DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram, true, bSupportsCategories ); 622 } 623 } 624 } 625 626 OUString DialogModel::getCategoriesRange() const 627 { 628 Reference< data::XLabeledDataSequence > xLSeq( getCategories()); 629 OUString aRange; 630 if( xLSeq.is()) 631 { 632 Reference< data::XDataSequence > xSeq( xLSeq->getValues()); 633 if( xSeq.is()) 634 aRange = xSeq->getSourceRangeRepresentation(); 635 } 636 return aRange; 637 } 638 639 bool DialogModel::isCategoryDiagram() const 640 { 641 bool bRet = false; 642 if( m_xChartDocument.is()) 643 bRet = DiagramHelper::isCategoryDiagram( m_xChartDocument->getFirstDiagram() ); 644 return bRet; 645 } 646 647 void DialogModel::detectArguments( 648 OUString & rOutRangeString, 649 bool & rOutUseColumns, 650 bool & rOutFirstCellAsLabel, 651 bool & rOutHasCategories ) const 652 { 653 try 654 { 655 uno::Sequence< sal_Int32 > aSequenceMapping;//todo YYYX 656 657 // Note: unused data is currently not supported in being passed to detectRangeSegmentation 658 if( m_xChartDocument.is()) 659 DataSourceHelper::detectRangeSegmentation( 660 Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY_THROW ), 661 rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories ); 662 } 663 catch( uno::Exception & ex ) 664 { 665 ASSERT_EXCEPTION( ex ); 666 } 667 } 668 669 bool DialogModel::allArgumentsForRectRangeDetected() const 670 { 671 return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument ); 672 } 673 674 void DialogModel::startControllerLockTimer() 675 { 676 m_aTimerTriggeredControllerLock.startTimer(); 677 } 678 679 bool DialogModel::setData( 680 const Sequence< beans::PropertyValue > & rArguments ) 681 { 682 m_aTimerTriggeredControllerLock.startTimer(); 683 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) ); 684 685 Reference< data::XDataProvider > xDataProvider( getDataProvider()); 686 if( ! xDataProvider.is() || 687 ! m_xTemplate.is() ) 688 { 689 OSL_ENSURE( false, "Model objects missing" ); 690 return false; 691 } 692 693 try 694 { 695 Reference< chart2::data::XDataSource > xDataSource( 696 xDataProvider->createDataSource( rArguments ) ); 697 698 Reference< chart2::XDataInterpreter > xInterpreter( 699 m_xTemplate->getDataInterpreter()); 700 if( xInterpreter.is()) 701 { 702 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); 703 ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); 704 705 ::std::vector< Reference< XDataSeries > > aSeriesToReUse( 706 DiagramHelper::getDataSeriesFromDiagram( xDiagram )); 707 applyInterpretedData( 708 xInterpreter->interpretDataSource( 709 xDataSource, rArguments, 710 ContainerToSequence( aSeriesToReUse )), 711 aSeriesToReUse, 712 true /* bSetStyles */); 713 714 ThreeDHelper::setScheme( xDiagram, e3DScheme ); 715 } 716 } 717 catch( uno::Exception & ex ) 718 { 719 ASSERT_EXCEPTION( ex ); 720 return false; 721 } 722 723 return true; 724 } 725 726 OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString ) 727 { 728 return lcl_ConvertRole( rRoleString, true ); 729 } 730 731 OUString DialogModel::GetRoleDataLabel() 732 { 733 return OUString( String( ::chart::SchResId( STR_OBJECT_DATALABELS ))); 734 } 735 736 sal_Int32 DialogModel::GetRoleIndexForSorting( const ::rtl::OUString & rInternalRoleString ) 737 { 738 static lcl_tRoleIndexMap aRoleIndexMap; 739 740 if( aRoleIndexMap.empty()) 741 lcl_createRoleIndexMap( aRoleIndexMap ); 742 743 lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString )); 744 if( aIt != aRoleIndexMap.end()) 745 return aIt->second; 746 747 return 0; 748 } 749 750 // private methods 751 752 void DialogModel::applyInterpretedData( 753 const InterpretedData & rNewData, 754 const ::std::vector< Reference< XDataSeries > > & rSeriesToReUse, 755 bool bSetStyles ) 756 { 757 if( ! m_xChartDocument.is()) 758 return; 759 760 m_aTimerTriggeredControllerLock.startTimer(); 761 Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); 762 if( xDiagram.is()) 763 { 764 // styles 765 if( bSetStyles && m_xTemplate.is() ) 766 { 767 sal_Int32 nGroup = 0; 768 sal_Int32 nSeriesCounter = 0; 769 sal_Int32 nNewSeriesIndex = static_cast< sal_Int32 >( rSeriesToReUse.size()); 770 const sal_Int32 nOuterSize=rNewData.Series.getLength(); 771 772 for(; nGroup < nOuterSize; ++nGroup) 773 { 774 Sequence< Reference< XDataSeries > > aSeries( rNewData.Series[ nGroup ] ); 775 const sal_Int32 nSeriesInGroup = aSeries.getLength(); 776 for( sal_Int32 nSeries=0; nSeries<nSeriesInGroup; ++nSeries, ++nSeriesCounter ) 777 { 778 if( ::std::find( rSeriesToReUse.begin(), rSeriesToReUse.end(), aSeries[nSeries] ) 779 == rSeriesToReUse.end()) 780 { 781 Reference< beans::XPropertySet > xSeriesProp( aSeries[nSeries], uno::UNO_QUERY ); 782 if( xSeriesProp.is()) 783 { 784 // @deprecated: correct default color should be found by view 785 // without setting it as hard attribute 786 Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); 787 if( xColorScheme.is()) 788 xSeriesProp->setPropertyValue( 789 C2U("Color"), uno::makeAny( xColorScheme->getColorByIndex( nSeriesCounter ))); 790 } 791 m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup ); 792 } 793 } 794 } 795 } 796 797 // data series 798 ::std::vector< Reference< XDataSeriesContainer > > aSeriesCnt( getAllDataSeriesContainers()); 799 ::std::vector< Sequence< Reference< XDataSeries > > > aNewSeries( 800 SequenceToVector( rNewData.Series )); 801 802 OSL_ASSERT( aSeriesCnt.size() == aNewSeries.size()); 803 804 ::std::vector< Sequence< Reference< XDataSeries > > >::const_iterator aSrcIt( aNewSeries.begin()); 805 ::std::vector< Reference< XDataSeriesContainer > >::iterator aDestIt( aSeriesCnt.begin()); 806 for(; aSrcIt != aNewSeries.end() && aDestIt != aSeriesCnt.end(); 807 ++aSrcIt, ++aDestIt ) 808 { 809 try 810 { 811 OSL_ASSERT( (*aDestIt).is()); 812 (*aDestIt)->setDataSeries( *aSrcIt ); 813 } 814 catch( uno::Exception & ex ) 815 { 816 ASSERT_EXCEPTION( ex ); 817 } 818 } 819 820 DialogModel::setCategories(rNewData.Categories); 821 } 822 } 823 824 sal_Int32 DialogModel::countSeries() const 825 { 826 ::std::vector< Reference< XDataSeriesContainer > > aCnt( getAllDataSeriesContainers()); 827 return ::std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber()); 828 } 829 830 } // namespace chart 831