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