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