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