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

Generated by: LCOV version 1.10