LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/oox/source/drawingml/chart - seriesconverter.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 97 309 31.4 %
Date: 2013-07-09 Functions: 13 37 35.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "oox/drawingml/chart/seriesconverter.hxx"
      21             : 
      22             : #include <com/sun/star/chart/DataLabelPlacement.hpp>
      23             : #include <com/sun/star/chart/ErrorBarStyle.hpp>
      24             : #include <com/sun/star/chart2/DataPointLabel.hpp>
      25             : #include <com/sun/star/chart2/XDataSeries.hpp>
      26             : #include <com/sun/star/chart2/XRegressionCurve.hpp>
      27             : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
      28             : #include <com/sun/star/chart2/data/XDataSink.hpp>
      29             : #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
      30             : #include <basegfx/numeric/ftools.hxx>
      31             : #include "oox/drawingml/chart/datasourceconverter.hxx"
      32             : #include "oox/drawingml/chart/seriesmodel.hxx"
      33             : #include "oox/drawingml/chart/titleconverter.hxx"
      34             : #include "oox/drawingml/chart/typegroupconverter.hxx"
      35             : #include "oox/drawingml/chart/typegroupmodel.hxx"
      36             : #include "oox/helper/containerhelper.hxx"
      37             : 
      38             : namespace oox {
      39             : namespace drawingml {
      40             : namespace chart {
      41             : 
      42             : // ============================================================================
      43             : 
      44             : using namespace ::com::sun::star::beans;
      45             : using namespace ::com::sun::star::chart2;
      46             : using namespace ::com::sun::star::chart2::data;
      47             : using namespace ::com::sun::star::uno;
      48             : 
      49             : // ============================================================================
      50             : 
      51             : namespace {
      52             : 
      53             : /** nastied-up sgn function - employs some gratuity around 0 - values
      54             :    smaller than 0.33 are clamped to 0
      55             :  */
      56           0 : int lclSgn( double nVal )
      57             : {
      58           0 :     const int intVal=nVal*3;
      59           0 :     return intVal == 0 ? 0 : (intVal < 0 ? -1 : 1);
      60             : }
      61             : 
      62           4 : Reference< XLabeledDataSequence > lclCreateLabeledDataSequence(
      63             :         const ConverterRoot& rParent,
      64             :         DataSourceModel* pValues, const OUString& rRole,
      65             :         TextModel* pTitle = 0 )
      66             : {
      67             :     // create data sequence for values
      68           4 :     Reference< XDataSequence > xValueSeq;
      69           4 :     if( pValues )
      70             :     {
      71           4 :         DataSourceConverter aSourceConv( rParent, *pValues );
      72           4 :         xValueSeq = aSourceConv.createDataSequence( rRole );
      73             :     }
      74             : 
      75             :     // create data sequence for title
      76           8 :     Reference< XDataSequence > xTitleSeq;
      77           4 :     if( pTitle )
      78             :     {
      79           2 :         TextConverter aTextConv( rParent, *pTitle );
      80           2 :         xTitleSeq = aTextConv.createDataSequence( "label" );
      81             :     }
      82             : 
      83             :     // create the labeled data sequence, if values or title are present
      84           4 :     Reference< XLabeledDataSequence > xLabeledSeq;
      85           4 :     if( xValueSeq.is() || xTitleSeq.is() )
      86             :     {
      87           4 :         xLabeledSeq.set( LabeledDataSequence::create(rParent.getComponentContext()), UNO_QUERY );
      88           4 :         if( xLabeledSeq.is() )
      89             :         {
      90           4 :             xLabeledSeq->setValues( xValueSeq );
      91           4 :             xLabeledSeq->setLabel( xTitleSeq );
      92             :         }
      93             :     }
      94           8 :     return xLabeledSeq;
      95             : }
      96             : 
      97           0 : void lclConvertLabelFormatting( PropertySet& rPropSet, ObjectFormatter& rFormatter,
      98             :         const DataLabelModelBase& rDataLabel, const TypeGroupConverter& rTypeGroup, bool bDataSeriesLabel )
      99             : {
     100           0 :     const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo();
     101             : 
     102             :     /*  Excel 2007 does not change the series setting for a single data point,
     103             :         if none of some specific elements occur. But only one existing element
     104             :         in a data point will reset most other of these elements from the series
     105             :         (e.g.: series has <c:showVal>, data point has <c:showCatName>, this
     106             :         will reset <c:showVal> for this point, unless <c:showVal> is repeated
     107             :         in the data point). The elements <c:layout>, <c:numberFormat>,
     108             :         <c:spPr>, <c:tx>, and <c:txPr> are not affected at all. */
     109             :     bool bHasAnyElement =
     110           0 :         rDataLabel.moaSeparator.has() || rDataLabel.monLabelPos.has() ||
     111           0 :         rDataLabel.mobShowCatName.has() || rDataLabel.mobShowLegendKey.has() ||
     112           0 :         rDataLabel.mobShowPercent.has() || rDataLabel.mobShowSerName.has() ||
     113           0 :         rDataLabel.mobShowVal.has();
     114             : 
     115           0 :     bool bShowValue   = !rDataLabel.mbDeleted && rDataLabel.mobShowVal.get( false );
     116           0 :     bool bShowPercent = !rDataLabel.mbDeleted && rDataLabel.mobShowPercent.get( false ) && (rTypeInfo.meTypeCategory == TYPECATEGORY_PIE);
     117           0 :     if( bShowValue &&
     118           0 :         !bShowPercent && rTypeInfo.meTypeCategory == TYPECATEGORY_PIE &&
     119           0 :         rDataLabel.maNumberFormat.maFormatCode.indexOf('%') >= 0 )
     120             :     {
     121           0 :         bShowValue = false;
     122           0 :         bShowPercent = true;
     123             :     }
     124           0 :     bool bShowCateg   = !rDataLabel.mbDeleted && rDataLabel.mobShowCatName.get( false );
     125           0 :     bool bShowSymbol  = !rDataLabel.mbDeleted && rDataLabel.mobShowLegendKey.get( false );
     126             : 
     127             :     // type of attached label
     128           0 :     if( bHasAnyElement || rDataLabel.mbDeleted )
     129             :     {
     130           0 :         DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol );
     131           0 :         rPropSet.setProperty( PROP_Label, aPointLabel );
     132             :     }
     133             : 
     134           0 :     if( !rDataLabel.mbDeleted )
     135             :     {
     136             :         // data label number format (percentage format wins over value format)
     137           0 :         rFormatter.convertNumberFormat( rPropSet, rDataLabel.maNumberFormat, bShowPercent );
     138             : 
     139             :         // data label text formatting (frame formatting not supported by Chart2)
     140           0 :         rFormatter.convertTextFormatting( rPropSet, rDataLabel.mxTextProp, OBJECTTYPE_DATALABEL );
     141           0 :         rFormatter.convertTextRotation( rPropSet, rDataLabel.mxTextProp, false );
     142             : 
     143             :         // data label separator (do not overwrite series separator, if no explicit point separator is present)
     144           0 :         if( bDataSeriesLabel || rDataLabel.moaSeparator.has() )
     145           0 :             rPropSet.setProperty( PROP_LabelSeparator, rDataLabel.moaSeparator.get( "; " ) );
     146             : 
     147             :         // data label placement (do not overwrite series placement, if no explicit point placement is present)
     148           0 :         if( bDataSeriesLabel || rDataLabel.monLabelPos.has() )
     149             :         {
     150             :             namespace csscd = ::com::sun::star::chart::DataLabelPlacement;
     151           0 :             sal_Int32 nPlacement = rTypeInfo.mnDefLabelPos;
     152           0 :             switch( rDataLabel.monLabelPos.get( XML_TOKEN_INVALID ) )
     153             :             {
     154           0 :                 case XML_outEnd:    nPlacement = csscd::OUTSIDE;        break;
     155           0 :                 case XML_inEnd:     nPlacement = csscd::INSIDE;         break;
     156           0 :                 case XML_ctr:       nPlacement = csscd::CENTER;         break;
     157           0 :                 case XML_inBase:    nPlacement = csscd::NEAR_ORIGIN;    break;
     158           0 :                 case XML_t:         nPlacement = csscd::TOP;            break;
     159           0 :                 case XML_b:         nPlacement = csscd::BOTTOM;         break;
     160           0 :                 case XML_l:         nPlacement = csscd::LEFT;           break;
     161           0 :                 case XML_r:         nPlacement = csscd::RIGHT;          break;
     162           0 :                 case XML_bestFit:   nPlacement = csscd::AVOID_OVERLAP;  break;
     163             :             }
     164           0 :             rPropSet.setProperty( PROP_LabelPlacement, nPlacement );
     165             :         }
     166             :     }
     167           0 : }
     168             : 
     169             : } // namespace
     170             : 
     171             : // ============================================================================
     172             : 
     173           0 : DataLabelConverter::DataLabelConverter( const ConverterRoot& rParent, DataLabelModel& rModel ) :
     174           0 :     ConverterBase< DataLabelModel >( rParent, rModel )
     175             : {
     176           0 : }
     177             : 
     178           0 : DataLabelConverter::~DataLabelConverter()
     179             : {
     180           0 : }
     181             : 
     182           0 : void DataLabelConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup )
     183             : {
     184           0 :     if( rxDataSeries.is() ) try
     185             :     {
     186           0 :         PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) );
     187           0 :         lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, false );
     188             : 
     189           0 :         if( mrModel.mxLayout && !mrModel.mxLayout->mbAutoLayout )
     190             :         {
     191             :             // bnc#694340 - nasty hack - chart2 cannot individually
     192             :             // place data labels, let's try to find a useful
     193             :             // compromise instead
     194             :             namespace csscd = ::com::sun::star::chart::DataLabelPlacement;
     195             :             const sal_Int32 aPositionsLookupTable[] =
     196             :                 {
     197             :                     csscd::TOP_LEFT,    csscd::TOP,    csscd::TOP_RIGHT,
     198             :                     csscd::LEFT,        csscd::CENTER, csscd::RIGHT,
     199             :                     csscd::BOTTOM_LEFT, csscd::BOTTOM, csscd::BOTTOM_RIGHT
     200           0 :                 };
     201             :             const double nMax=std::max(
     202           0 :                 fabs(mrModel.mxLayout->mfX),
     203           0 :                 fabs(mrModel.mxLayout->mfY));
     204           0 :             const int simplifiedX=lclSgn(mrModel.mxLayout->mfX/nMax);
     205           0 :             const int simplifiedY=lclSgn(mrModel.mxLayout->mfY/nMax);
     206             :             aPropSet.setProperty( PROP_LabelPlacement,
     207           0 :                                   aPositionsLookupTable[ simplifiedX+1 + 3*(simplifiedY+1) ] );
     208           0 :         }
     209             :     }
     210           0 :     catch( Exception& )
     211             :     {
     212             :     }
     213           0 : }
     214             : 
     215             : // ============================================================================
     216             : 
     217           0 : DataLabelsConverter::DataLabelsConverter( const ConverterRoot& rParent, DataLabelsModel& rModel ) :
     218           0 :     ConverterBase< DataLabelsModel >( rParent, rModel )
     219             : {
     220           0 : }
     221             : 
     222           0 : DataLabelsConverter::~DataLabelsConverter()
     223             : {
     224           0 : }
     225             : 
     226           0 : void DataLabelsConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup )
     227             : {
     228           0 :     if( !mrModel.mbDeleted )
     229             :     {
     230           0 :         PropertySet aPropSet( rxDataSeries );
     231           0 :         lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, true );
     232             :     }
     233             : 
     234             :     // data point label settings
     235           0 :     for( DataLabelsModel::DataLabelVector::iterator aIt = mrModel.maPointLabels.begin(), aEnd = mrModel.maPointLabels.end(); aIt != aEnd; ++aIt )
     236             :     {
     237           0 :         (*aIt)->maNumberFormat.maFormatCode = mrModel.maNumberFormat.maFormatCode;
     238           0 :         if( !mrModel.maNumberFormat.maFormatCode.isEmpty() )
     239           0 :             (*aIt)->maNumberFormat.mbSourceLinked = false;
     240             : 
     241           0 :         DataLabelConverter aLabelConv( *this, **aIt );
     242           0 :         aLabelConv.convertFromModel( rxDataSeries, rTypeGroup );
     243           0 :     }
     244           0 : }
     245             : 
     246             : // ============================================================================
     247             : 
     248           1 : ErrorBarConverter::ErrorBarConverter( const ConverterRoot& rParent, ErrorBarModel& rModel ) :
     249           1 :     ConverterBase< ErrorBarModel >( rParent, rModel )
     250             : {
     251           1 : }
     252             : 
     253           1 : ErrorBarConverter::~ErrorBarConverter()
     254             : {
     255           1 : }
     256             : 
     257           1 : void ErrorBarConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries )
     258             : {
     259           1 :     bool bShowPos = (mrModel.mnTypeId == XML_plus) || (mrModel.mnTypeId == XML_both);
     260           1 :     bool bShowNeg = (mrModel.mnTypeId == XML_minus) || (mrModel.mnTypeId == XML_both);
     261           1 :     if( bShowPos || bShowNeg ) try
     262             :     {
     263           1 :         Reference< XPropertySet > xErrorBar( createInstance( "com.sun.star.chart2.ErrorBar" ), UNO_QUERY_THROW );
     264           2 :         PropertySet aBarProp( xErrorBar );
     265             : 
     266             :         // plus/minus bars
     267           1 :         aBarProp.setProperty( PROP_ShowPositiveError, bShowPos );
     268           1 :         aBarProp.setProperty( PROP_ShowNegativeError, bShowNeg );
     269             : 
     270             :         // type of displayed error
     271             :         namespace cssc = ::com::sun::star::chart;
     272           1 :         switch( mrModel.mnValueType )
     273             :         {
     274             :             case XML_cust:
     275             :             {
     276             :                 // #i87806# manual error bars
     277           0 :                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::FROM_DATA );
     278             :                 // attach data sequences to erorr bar
     279           0 :                 Reference< XDataSink > xDataSink( xErrorBar, UNO_QUERY );
     280           0 :                 if( xDataSink.is() )
     281             :                 {
     282             :                     // create vector of all value sequences
     283           0 :                     ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
     284             :                     // add positive values
     285           0 :                     if( bShowPos )
     286             :                     {
     287           0 :                         Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::PLUS );
     288           0 :                         if( xValueSeq.is() )
     289           0 :                             aLabeledSeqVec.push_back( xValueSeq );
     290             :                     }
     291             :                     // add negative values
     292           0 :                     if( bShowNeg )
     293             :                     {
     294           0 :                         Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::MINUS );
     295           0 :                         if( xValueSeq.is() )
     296           0 :                             aLabeledSeqVec.push_back( xValueSeq );
     297             :                     }
     298             :                     // attach labeled data sequences to series
     299           0 :                     if( aLabeledSeqVec.empty() )
     300           0 :                         xErrorBar.clear();
     301             :                     else
     302           0 :                         xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) );
     303           0 :                 }
     304             :             }
     305           0 :             break;
     306             :             case XML_fixedVal:
     307           0 :                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::ABSOLUTE );
     308           0 :                 aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue );
     309           0 :                 aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue );
     310           0 :             break;
     311             :             case XML_percentage:
     312           1 :                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::RELATIVE );
     313           1 :                 aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue );
     314           1 :                 aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue );
     315           1 :             break;
     316             :             case XML_stdDev:
     317           0 :                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_DEVIATION );
     318           0 :                 aBarProp.setProperty( PROP_Weight, mrModel.mfValue );
     319           0 :             break;
     320             :             case XML_stdErr:
     321           0 :                 aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_ERROR );
     322           0 :             break;
     323             :             default:
     324             :                 OSL_FAIL( "ErrorBarConverter::convertFromModel - unknown error bar type" );
     325           0 :                 xErrorBar.clear();
     326             :         }
     327             : 
     328             :         // error bar formatting
     329           1 :         getFormatter().convertFrameFormatting( aBarProp, mrModel.mxShapeProp, OBJECTTYPE_ERRORBAR );
     330             : 
     331           1 :         if( xErrorBar.is() )
     332             :         {
     333           1 :             PropertySet aSeriesProp( rxDataSeries );
     334           1 :             switch( mrModel.mnDirection )
     335             :             {
     336           0 :                 case XML_x: aSeriesProp.setProperty( PROP_ErrorBarX, xErrorBar );   break;
     337           1 :                 case XML_y: aSeriesProp.setProperty( PROP_ErrorBarY, xErrorBar );   break;
     338             :                 default:    OSL_FAIL( "ErrorBarConverter::convertFromModel - invalid error bar direction" );
     339           1 :             }
     340           1 :         }
     341             :     }
     342           0 :     catch( Exception& )
     343             :     {
     344             :         OSL_FAIL( "ErrorBarConverter::convertFromModel - error while creating error bars" );
     345             :     }
     346           1 : }
     347             : 
     348             : // private --------------------------------------------------------------------
     349             : 
     350           0 : Reference< XLabeledDataSequence > ErrorBarConverter::createLabeledDataSequence( ErrorBarModel::SourceType eSourceType )
     351             : {
     352           0 :     OUString aRole;
     353           0 :     switch( eSourceType )
     354             :     {
     355             :         case ErrorBarModel::PLUS:
     356           0 :             switch( mrModel.mnDirection )
     357             :             {
     358           0 :                 case XML_x: aRole = "error-bars-x-positive"; break;
     359           0 :                 case XML_y: aRole = "error-bars-y-positive"; break;
     360             :             }
     361           0 :         break;
     362             :         case ErrorBarModel::MINUS:
     363           0 :             switch( mrModel.mnDirection )
     364             :             {
     365           0 :                 case XML_x: aRole = "error-bars-x-negative"; break;
     366           0 :                 case XML_y: aRole = "error-bars-y-negative"; break;
     367             :             }
     368           0 :         break;
     369             :     }
     370             :     OSL_ENSURE( !aRole.isEmpty(), "ErrorBarConverter::createLabeledDataSequence - invalid error bar direction" );
     371           0 :     return lclCreateLabeledDataSequence( *this, mrModel.maSources.get( eSourceType ).get(), aRole );
     372             : }
     373             : 
     374             : // ============================================================================
     375             : 
     376           0 : TrendlineLabelConverter::TrendlineLabelConverter( const ConverterRoot& rParent, TrendlineLabelModel& rModel ) :
     377           0 :     ConverterBase< TrendlineLabelModel >( rParent, rModel )
     378             : {
     379           0 : }
     380             : 
     381           0 : TrendlineLabelConverter::~TrendlineLabelConverter()
     382             : {
     383           0 : }
     384             : 
     385           0 : void TrendlineLabelConverter::convertFromModel( PropertySet& rPropSet )
     386             : {
     387             :     // formatting
     388           0 :     getFormatter().convertFormatting( rPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_TRENDLINELABEL );
     389           0 : }
     390             : 
     391             : // ============================================================================
     392             : 
     393           0 : TrendlineConverter::TrendlineConverter( const ConverterRoot& rParent, TrendlineModel& rModel ) :
     394           0 :     ConverterBase< TrendlineModel >( rParent, rModel )
     395             : {
     396           0 : }
     397             : 
     398           0 : TrendlineConverter::~TrendlineConverter()
     399             : {
     400           0 : }
     401             : 
     402           0 : void TrendlineConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries )
     403             : {
     404             :     try
     405             :     {
     406             :         // trend line type
     407           0 :         OUString aServiceName;
     408           0 :         switch( mrModel.mnTypeId )
     409             :         {
     410             :             case XML_exp:
     411           0 :                 aServiceName = "com.sun.star.chart2.ExponentialRegressionCurve";
     412           0 :             break;
     413             :             case XML_linear:
     414           0 :                 aServiceName = "com.sun.star.chart2.LinearRegressionCurve";
     415           0 :             break;
     416             :             case XML_log:
     417           0 :                 aServiceName = "com.sun.star.chart2.LogarithmicRegressionCurve";
     418           0 :             break;
     419             :             case XML_movingAvg:
     420           0 :                 aServiceName = "com.sun.star.chart2.MovingAverageRegressionCurve";
     421           0 :             break;
     422             :             case XML_poly:
     423           0 :                 aServiceName = "com.sun.star.chart2.PolynomialRegressionCurve";
     424           0 :             break;
     425             :             case XML_power:
     426           0 :                 aServiceName = "com.sun.star.chart2.PotentialRegressionCurve";
     427           0 :             break;
     428             :             default:
     429             :                 OSL_FAIL( "TrendlineConverter::convertFromModel - unknown trendline type" );
     430             :         }
     431           0 :         if( !aServiceName.isEmpty() )
     432             :         {
     433           0 :             Reference< XRegressionCurve > xRegCurve( createInstance( aServiceName ), UNO_QUERY_THROW );
     434           0 :             PropertySet aPropSet( xRegCurve );
     435             : 
     436           0 :             aPropSet.setProperty( PROP_PolynomialDegree, mrModel.mnOrder );
     437           0 :             aPropSet.setProperty( PROP_MovingAveragePeriod, mrModel.mnPeriod );
     438             : 
     439             :             // Intercept
     440           0 :             sal_Bool hasIntercept = mrModel.mfIntercept.has();
     441           0 :             aPropSet.setProperty( PROP_ForceIntercept, hasIntercept);
     442           0 :             if (hasIntercept)
     443           0 :                 aPropSet.setProperty( PROP_InterceptValue,  mrModel.mfIntercept.get());
     444             : 
     445             :             // Extrapolation
     446           0 :             if (mrModel.mfForward.has())
     447           0 :                 aPropSet.setProperty( PROP_ExtrapolateForward, mrModel.mfForward.get() );
     448           0 :             if (mrModel.mfBackward.has())
     449           0 :                 aPropSet.setProperty( PROP_ExtrapolateBackward, mrModel.mfBackward.get() );
     450             : 
     451             :             // trendline formatting
     452           0 :             getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, OBJECTTYPE_TRENDLINE );
     453             : 
     454             :             // #i83100# show equation and correlation coefficient
     455           0 :             PropertySet aLabelProp( xRegCurve->getEquationProperties() );
     456           0 :             aLabelProp.setProperty( PROP_ShowEquation, mrModel.mbDispEquation );
     457           0 :             aLabelProp.setProperty( PROP_ShowCorrelationCoefficient, mrModel.mbDispRSquared );
     458             : 
     459             :             // #i83100# formatting of the equation text box
     460           0 :             if( mrModel.mbDispEquation || mrModel.mbDispRSquared )
     461             :             {
     462           0 :                 TrendlineLabelConverter aLabelConv( *this, mrModel.mxLabel.getOrCreate() );
     463           0 :                 aLabelConv.convertFromModel( aLabelProp );
     464             :             }
     465             : 
     466             :             // unsupported: #i5085# manual trendline size
     467             :             // unsupported: #i34093# manual crossing point
     468             : 
     469           0 :             Reference< XRegressionCurveContainer > xRegCurveCont( rxDataSeries, UNO_QUERY_THROW );
     470           0 :             xRegCurveCont->addRegressionCurve( xRegCurve );
     471           0 :         }
     472             :     }
     473           0 :     catch( Exception& )
     474             :     {
     475             :         OSL_FAIL( "TrendlineConverter::convertFromModel - error while creating trendline" );
     476             :     }
     477           0 : }
     478             : 
     479             : // ============================================================================
     480             : 
     481           0 : DataPointConverter::DataPointConverter( const ConverterRoot& rParent, DataPointModel& rModel ) :
     482           0 :     ConverterBase< DataPointModel >( rParent, rModel )
     483             : {
     484           0 : }
     485             : 
     486           0 : DataPointConverter::~DataPointConverter()
     487             : {
     488           0 : }
     489             : 
     490           0 : void DataPointConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries,
     491             :         const TypeGroupConverter& rTypeGroup, const SeriesModel& rSeries )
     492             : {
     493             :     try
     494             :     {
     495           0 :         PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) );
     496             : 
     497             :         // data point marker
     498           0 :         if( mrModel.monMarkerSymbol.differsFrom( rSeries.mnMarkerSymbol ) || mrModel.monMarkerSize.differsFrom( rSeries.mnMarkerSize ) )
     499           0 :             rTypeGroup.convertMarker( aPropSet, mrModel.monMarkerSymbol.get( rSeries.mnMarkerSymbol ), mrModel.monMarkerSize.get( rSeries.mnMarkerSize ) );
     500             : 
     501             :         // data point pie explosion
     502           0 :         if( mrModel.monExplosion.differsFrom( rSeries.mnExplosion ) )
     503           0 :             rTypeGroup.convertPieExplosion( aPropSet, mrModel.monExplosion.get() );
     504             : 
     505             :         // point formatting
     506           0 :         if( mrModel.mxShapeProp.is() )
     507             :         {
     508           0 :             if( rTypeGroup.getTypeInfo().mbPictureOptions )
     509           0 :                 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), rTypeGroup.getSeriesObjectType(), rSeries.mnIndex );
     510             :             else
     511           0 :                 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, rTypeGroup.getSeriesObjectType(), rSeries.mnIndex );
     512           0 :         }
     513             :     }
     514           0 :     catch( Exception& )
     515             :     {
     516             :     }
     517           0 : }
     518             : 
     519             : // ============================================================================
     520             : 
     521           2 : SeriesConverter::SeriesConverter( const ConverterRoot& rParent, SeriesModel& rModel ) :
     522           2 :     ConverterBase< SeriesModel >( rParent, rModel )
     523             : {
     524           2 : }
     525             : 
     526           4 : SeriesConverter::~SeriesConverter()
     527             : {
     528           4 : }
     529             : 
     530           2 : Reference< XLabeledDataSequence > SeriesConverter::createCategorySequence( const OUString& rRole )
     531             : {
     532           2 :     return createLabeledDataSequence( SeriesModel::CATEGORIES, rRole, false );
     533             : }
     534             : 
     535           2 : Reference< XLabeledDataSequence > SeriesConverter::createValueSequence( const OUString& rRole )
     536             : {
     537           2 :     return createLabeledDataSequence( SeriesModel::VALUES, rRole, true );
     538             : }
     539             : 
     540           2 : Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConverter& rTypeGroup, bool bVaryColorsByPoint )
     541             : {
     542           2 :     const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo();
     543             : 
     544             :     // create the data series object
     545           2 :     Reference< XDataSeries > xDataSeries( createInstance( "com.sun.star.chart2.DataSeries" ), UNO_QUERY );
     546           4 :     PropertySet aSeriesProp( xDataSeries );
     547             : 
     548             :     // attach data and title sequences to series
     549           2 :     sal_Int32 nDataPointCount = 0;
     550           4 :     Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY );
     551           2 :     if( xDataSink.is() )
     552             :     {
     553             :         // create vector of all value sequences
     554           2 :         ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec;
     555             :         // add Y values
     556           4 :         Reference< XLabeledDataSequence > xYValueSeq = createValueSequence( "values-y" );
     557           2 :         if( xYValueSeq.is() )
     558             :         {
     559           2 :             aLabeledSeqVec.push_back( xYValueSeq );
     560           2 :             Reference< XDataSequence > xValues = xYValueSeq->getValues();
     561           2 :             if( xValues.is() )
     562           2 :                 nDataPointCount = xValues->getData().getLength();
     563             :         }
     564             :         // add X values of scatter and bubble charts
     565           2 :         if( !rTypeInfo.mbCategoryAxis )
     566             :         {
     567           2 :             Reference< XLabeledDataSequence > xXValueSeq = createCategorySequence( "values-x" );
     568           2 :             if( xXValueSeq.is() )
     569           2 :                 aLabeledSeqVec.push_back( xXValueSeq );
     570             :             // add size values of bubble charts
     571           2 :             if( rTypeInfo.meTypeId == TYPEID_BUBBLE )
     572             :             {
     573           0 :                 Reference< XLabeledDataSequence > xSizeValueSeq = createLabeledDataSequence( SeriesModel::POINTS, "values-size", true );
     574           0 :                 if( xSizeValueSeq.is() )
     575           0 :                     aLabeledSeqVec.push_back( xSizeValueSeq );
     576           2 :             }
     577             :         }
     578             :         // attach labeled data sequences to series
     579           2 :         if( !aLabeledSeqVec.empty() )
     580           4 :             xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) );
     581             :     }
     582             : 
     583             :     // error bars
     584           3 :     for( SeriesModel::ErrorBarVector::iterator aIt = mrModel.maErrorBars.begin(), aEnd = mrModel.maErrorBars.end(); aIt != aEnd; ++aIt )
     585             :     {
     586           1 :         ErrorBarConverter aErrorBarConv( *this, **aIt );
     587           1 :         aErrorBarConv.convertFromModel( xDataSeries );
     588           1 :     }
     589             : 
     590             :     // trendlines
     591           2 :     for( SeriesModel::TrendlineVector::iterator aIt = mrModel.maTrendlines.begin(), aEnd = mrModel.maTrendlines.end(); aIt != aEnd; ++aIt )
     592             :     {
     593           0 :         TrendlineConverter aTrendlineConv( *this, **aIt );
     594           0 :         aTrendlineConv.convertFromModel( xDataSeries );
     595           0 :     }
     596             : 
     597             :     // data point markers
     598           2 :     rTypeGroup.convertMarker( aSeriesProp, mrModel.mnMarkerSymbol, mrModel.mnMarkerSize );
     599             : #if OOX_CHART_SMOOTHED_PER_SERIES
     600             :     // #i66858# smoothed series lines
     601             :     rTypeGroup.convertLineSmooth( aSeriesProp, mrModel.mbSmooth );
     602             : #endif
     603             :     // 3D bar style (not possible to set at chart type -> set at all series)
     604           2 :     rTypeGroup.convertBarGeometry( aSeriesProp, mrModel.monShape.get( rTypeGroup.getModel().mnShape ) );
     605             :     // pie explosion (restricted to [0%,100%] in Chart2)
     606           2 :     rTypeGroup.convertPieExplosion( aSeriesProp, mrModel.mnExplosion );
     607             : 
     608             :     // series formatting
     609           2 :     ObjectFormatter& rFormatter = getFormatter();
     610           2 :     ObjectType eObjType = rTypeGroup.getSeriesObjectType();
     611           2 :     if( rTypeInfo.mbPictureOptions )
     612           0 :         rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), eObjType, mrModel.mnIndex );
     613             :     else
     614           2 :         rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, eObjType, mrModel.mnIndex );
     615             : 
     616             :     // set the (unused) property default value used by the Chart2 templates (true for pie/doughnut charts)
     617           2 :     bool bIsPie = rTypeInfo.meTypeCategory == TYPECATEGORY_PIE;
     618           2 :     aSeriesProp.setProperty( PROP_VaryColorsByPoint, bIsPie );
     619             : 
     620             :     // own area formatting for every data point (TODO: varying line color not supported)
     621             :     // #i91271# always set area formatting for every point in pie/doughnut charts to override their automatic point formatting
     622           2 :     if( bIsPie || (bVaryColorsByPoint && rTypeGroup.isSeriesFrameFormat() && ObjectFormatter::isAutomaticFill( mrModel.mxShapeProp )) )
     623             :     {
     624             :         /*  Set the series point number as color cycle size at the object
     625             :             formatter to get correct start-shade/end-tint. TODO: in doughnut
     626             :             charts, the sizes of the series may vary, need to use the maximum
     627             :             point count of all series. */
     628           0 :         sal_Int32 nOldMax = rFormatter.getMaxSeriesIndex();
     629           0 :         if( bVaryColorsByPoint )
     630           0 :             rFormatter.setMaxSeriesIndex( nDataPointCount - 1 );
     631           0 :         for( sal_Int32 nIndex = 0; nIndex < nDataPointCount; ++nIndex )
     632             :         {
     633             :             try
     634             :             {
     635           0 :                 PropertySet aPointProp( xDataSeries->getDataPointByIndex( nIndex ) );
     636           0 :                 rFormatter.convertAutomaticFill( aPointProp, eObjType, bVaryColorsByPoint ? nIndex : mrModel.mnIndex );
     637             :             }
     638           0 :             catch( Exception& )
     639             :             {
     640             :             }
     641             :         }
     642           0 :         rFormatter.setMaxSeriesIndex( nOldMax );
     643             :     }
     644             : 
     645             :     // data point settings
     646           2 :     for( SeriesModel::DataPointVector::iterator aIt = mrModel.maPoints.begin(), aEnd = mrModel.maPoints.end(); aIt != aEnd; ++aIt )
     647             :     {
     648           0 :         DataPointConverter aPointConv( *this, **aIt );
     649           0 :         aPointConv.convertFromModel( xDataSeries, rTypeGroup, mrModel );
     650           0 :     }
     651             : 
     652             :     /*  Series data label settings. If and only if the series does not contain
     653             :         a c:dLbls element, then the c:dLbls element of the parent chart type is
     654             :         used (data label settings of the parent chart type are *not* merged
     655             :         into own existing data label settings). */
     656           4 :     ModelRef< DataLabelsModel > xLabels = mrModel.mxLabels.is() ? mrModel.mxLabels : rTypeGroup.getModel().mxLabels;
     657           2 :     if( xLabels.is() )
     658             :     {
     659           0 :         if( xLabels->maNumberFormat.maFormatCode.isEmpty() )
     660             :         {
     661             :             // Use number format code from Value series
     662           0 :             DataSourceModel* pValues = mrModel.maSources.get( SeriesModel::VALUES ).get();
     663           0 :             xLabels->maNumberFormat.maFormatCode = pValues->mxDataSeq->maFormatCode;
     664             :         }
     665           0 :         DataLabelsConverter aLabelsConv( *this, *xLabels );
     666           0 :         aLabelsConv.convertFromModel( xDataSeries, rTypeGroup );
     667             :     }
     668             : 
     669           4 :     return xDataSeries;
     670             : }
     671             : 
     672             : // private --------------------------------------------------------------------
     673             : 
     674           4 : Reference< XLabeledDataSequence > SeriesConverter::createLabeledDataSequence(
     675             :         SeriesModel::SourceType eSourceType, const OUString& rRole, bool bUseTextLabel )
     676             : {
     677           4 :     DataSourceModel* pValues = mrModel.maSources.get( eSourceType ).get();
     678           4 :     TextModel* pTitle = bUseTextLabel ? mrModel.mxText.get() : 0;
     679           4 :     return lclCreateLabeledDataSequence( *this, pValues, rRole, pTitle );
     680             : }
     681             : 
     682             : // ============================================================================
     683             : 
     684             : } // namespace chart
     685             : } // namespace drawingml
     686         141 : } // namespace oox
     687             : 
     688             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10