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

Generated by: LCOV version 1.11