LCOV - code coverage report
Current view: top level - chart2/source/view/charttypes - VSeriesPlotter.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 840 1178 71.3 %
Date: 2012-08-25 Functions: 71 89 79.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 858 2099 40.9 %

           Branch data     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 "VSeriesPlotter.hxx"
      21                 :            : #include "ShapeFactory.hxx"
      22                 :            : #include "chartview/ExplicitValueProvider.hxx"
      23                 :            : 
      24                 :            : #include "CommonConverters.hxx"
      25                 :            : #include "macros.hxx"
      26                 :            : #include "ViewDefines.hxx"
      27                 :            : #include "ObjectIdentifier.hxx"
      28                 :            : #include "StatisticsHelper.hxx"
      29                 :            : #include "PlottingPositionHelper.hxx"
      30                 :            : #include "LabelPositionHelper.hxx"
      31                 :            : #include "ChartTypeHelper.hxx"
      32                 :            : #include "Clipping.hxx"
      33                 :            : #include "servicenames_charttypes.hxx"
      34                 :            : #include "NumberFormatterWrapper.hxx"
      35                 :            : #include "ContainerHelper.hxx"
      36                 :            : #include "DataSeriesHelper.hxx"
      37                 :            : #include "RegressionCurveHelper.hxx"
      38                 :            : #include "VLegendSymbolFactory.hxx"
      39                 :            : #include "FormattedStringHelper.hxx"
      40                 :            : #include "ResId.hxx"
      41                 :            : #include "Strings.hrc"
      42                 :            : #include "RelativePositionHelper.hxx"
      43                 :            : #include "DateHelper.hxx"
      44                 :            : #include "DiagramHelper.hxx"
      45                 :            : 
      46                 :            : //only for creation: @todo remove if all plotter are uno components and instanciated via servicefactory
      47                 :            : #include "BarChart.hxx"
      48                 :            : #include "PieChart.hxx"
      49                 :            : #include "AreaChart.hxx"
      50                 :            : #include "CandleStickChart.hxx"
      51                 :            : #include "BubbleChart.hxx"
      52                 :            : //
      53                 :            : 
      54                 :            : #include <com/sun/star/chart/ErrorBarStyle.hpp>
      55                 :            : #include <com/sun/star/chart/TimeUnit.hpp>
      56                 :            : #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
      57                 :            : #include <com/sun/star/container/XChild.hpp>
      58                 :            : #include <com/sun/star/chart2/RelativePosition.hpp>
      59                 :            : #include <editeng/unoprnms.hxx>
      60                 :            : #include <tools/color.hxx>
      61                 :            : // header for class OUStringBuffer
      62                 :            : #include <rtl/ustrbuf.hxx>
      63                 :            : #include <rtl/math.hxx>
      64                 :            : #include <basegfx/vector/b2dvector.hxx>
      65                 :            : #include <com/sun/star/drawing/LineStyle.hpp>
      66                 :            : #include <com/sun/star/util/XCloneable.hpp>
      67                 :            : 
      68                 :            : #include <svx/unoshape.hxx>
      69                 :            : 
      70                 :            : #include <functional>
      71                 :            : #include <map>
      72                 :            : 
      73                 :            : #include <boost/ptr_container/ptr_map.hpp>
      74                 :            : 
      75                 :            : namespace chart {
      76                 :            : 
      77                 :            : using namespace ::com::sun::star;
      78                 :            : using namespace ::com::sun::star::chart2;
      79                 :            : using ::com::sun::star::uno::Reference;
      80                 :            : using ::com::sun::star::uno::Sequence;
      81                 :            : using rtl::OUString;
      82                 :            : 
      83                 :            : //-----------------------------------------------------------------------------
      84                 :            : 
      85                 :      13820 : VDataSeriesGroup::CachedYValues::CachedYValues()
      86                 :            :         : m_bValuesDirty(true)
      87                 :            :         , m_fMinimumY(0.0)
      88                 :      13820 :         , m_fMaximumY(0.0)
      89                 :            : {
      90                 :      13820 : }
      91                 :            : 
      92                 :          0 : VDataSeriesGroup::VDataSeriesGroup()
      93                 :            :         : m_aSeriesVector()
      94                 :            :         , m_bMaxPointCountDirty(true)
      95                 :            :         , m_nMaxPointCount(0)
      96         [ #  # ]:          0 :         , m_aListOfCachedYValues()
      97                 :            : {
      98                 :          0 : }
      99                 :            : 
     100                 :       3194 : VDataSeriesGroup::VDataSeriesGroup( VDataSeries* pSeries )
     101                 :            :         : m_aSeriesVector(1,pSeries)
     102                 :            :         , m_bMaxPointCountDirty(true)
     103                 :            :         , m_nMaxPointCount(0)
     104 [ +  - ][ +  - ]:       3194 :         , m_aListOfCachedYValues()
     105                 :            : {
     106                 :       3194 : }
     107                 :            : 
     108                 :      17077 : VDataSeriesGroup::~VDataSeriesGroup()
     109                 :            : {
     110         [ -  + ]:      17077 : }
     111                 :            : 
     112                 :       3194 : void VDataSeriesGroup::deleteSeries()
     113                 :            : {
     114                 :            :     //delete all data series help objects:
     115         [ +  - ]:       3194 :     ::std::vector< VDataSeries* >::const_iterator       aIter = m_aSeriesVector.begin();
     116         [ +  - ]:       3194 :     const ::std::vector< VDataSeries* >::const_iterator aEnd  = m_aSeriesVector.end();
     117 [ +  - ][ +  + ]:       6400 :     for( ; aIter != aEnd; ++aIter )
     118                 :            :     {
     119 [ +  - ][ +  - ]:       3206 :         delete *aIter;
     120                 :            :     }
     121                 :       3194 :     m_aSeriesVector.clear();
     122                 :       3194 : }
     123                 :            : 
     124                 :         12 : void VDataSeriesGroup::addSeries( VDataSeries* pSeries )
     125                 :            : {
     126                 :         12 :     m_aSeriesVector.push_back(pSeries);
     127                 :         12 :     m_bMaxPointCountDirty=true;
     128                 :         12 : }
     129                 :            : 
     130                 :         12 : sal_Int32 VDataSeriesGroup::getSeriesCount() const
     131                 :            : {
     132                 :         12 :     return m_aSeriesVector.size();
     133                 :            : }
     134                 :            : 
     135                 :            : //-----------------------------------------------------------------------------
     136                 :            : 
     137                 :        981 : VSeriesPlotter::VSeriesPlotter( const uno::Reference<XChartType>& xChartTypeModel
     138                 :            :                                , sal_Int32 nDimensionCount, bool bCategoryXAxis )
     139                 :            :         : PlotterBase( nDimensionCount )
     140                 :            :         , m_pMainPosHelper( 0 )
     141                 :            :         , m_xChartTypeModel(xChartTypeModel)
     142                 :            :         , m_xChartTypeModelProps( uno::Reference< beans::XPropertySet >::query( xChartTypeModel ))
     143                 :            :         , m_aZSlots()
     144                 :            :         , m_bCategoryXAxis(bCategoryXAxis)
     145                 :            :         , m_nTimeResolution(::com::sun::star::chart::TimeUnit::DAY)
     146                 :            :         , m_aNullDate(30,12,1899)
     147                 :            :         , m_xColorScheme()
     148                 :            :         , m_pExplicitCategoriesProvider(0)
     149 [ +  - ][ +  - ]:        981 :         , m_bPointsWereSkipped(false)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     150                 :            : {
     151                 :            :     OSL_POSTCOND(m_xChartTypeModel.is(),"no XChartType available in view, fallback to default values may be wrong");
     152                 :        981 : }
     153                 :            : 
     154 [ +  - ][ +  - ]:        981 : VSeriesPlotter::~VSeriesPlotter()
     155                 :            : {
     156                 :            :     //delete all data series help objects:
     157                 :        981 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator             aZSlotIter = m_aZSlots.begin();
     158         [ +  - ]:        981 :     const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator  aZSlotEnd = m_aZSlots.end();
     159 [ +  - ][ +  + ]:       1980 :     for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
     160                 :            :     {
     161                 :        999 :         ::std::vector< VDataSeriesGroup >::iterator             aXSlotIter = aZSlotIter->begin();
     162         [ +  - ]:        999 :         const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
     163 [ +  - ][ +  + ]:       4193 :         for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
     164                 :            :         {
     165         [ +  - ]:       3194 :             aXSlotIter->deleteSeries();
     166                 :            :         }
     167                 :        999 :         aZSlotIter->clear();
     168                 :            :     }
     169                 :        981 :     m_aZSlots.clear();
     170                 :            : 
     171                 :        981 :     tSecondaryPosHelperMap::iterator aPosIt = m_aSecondaryPosHelperMap.begin();
     172         [ -  + ]:        981 :     while( aPosIt != m_aSecondaryPosHelperMap.end() )
     173                 :            :     {
     174                 :          0 :         PlottingPositionHelper* pPosHelper = aPosIt->second;
     175         [ #  # ]:          0 :         if( pPosHelper )
     176 [ #  # ][ #  # ]:          0 :             delete pPosHelper;
     177                 :          0 :         ++aPosIt;
     178                 :            :     }
     179                 :        981 :     m_aSecondaryPosHelperMap.clear();
     180                 :            : 
     181                 :        981 :     m_aSecondaryValueScales.clear();
     182         [ -  + ]:        981 : }
     183                 :            : 
     184                 :       3206 : void VSeriesPlotter::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
     185                 :            : {
     186                 :            :     //take ownership of pSeries
     187                 :            : 
     188                 :            :     OSL_PRECOND( pSeries, "series to add is NULL" );
     189         [ -  + ]:       3206 :     if(!pSeries)
     190                 :       3206 :         return;
     191                 :            : 
     192         [ +  - ]:       3206 :     if(m_bCategoryXAxis)
     193                 :            :     {
     194 [ +  - ][ -  + ]:       3206 :         if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() )
                 [ -  + ]
     195         [ #  # ]:          0 :             pSeries->setXValues( m_pExplicitCategoriesProvider->getOriginalCategories() );
     196                 :            :         else
     197                 :       3206 :             pSeries->setCategoryXAxis();
     198                 :            :     }
     199                 :            :     else
     200                 :            :     {
     201         [ #  # ]:          0 :         if( m_pExplicitCategoriesProvider )
     202         [ #  # ]:          0 :             pSeries->setXValuesIfNone( m_pExplicitCategoriesProvider->getOriginalCategories() );
     203                 :            :     }
     204                 :            : 
     205 [ +  - ][ +  + ]:       3206 :     if(zSlot<0 || zSlot>=static_cast<sal_Int32>(m_aZSlots.size()))
                 [ +  + ]
     206                 :            :     {
     207                 :            :         //new z slot
     208         [ +  - ]:        116 :         ::std::vector< VDataSeriesGroup > aZSlot;
     209 [ +  - ][ +  - ]:        116 :         aZSlot.push_back( VDataSeriesGroup(pSeries) );
     210         [ +  - ]:        116 :         m_aZSlots.push_back( aZSlot );
     211                 :            :     }
     212                 :            :     else
     213                 :            :     {
     214                 :            :         //existing zslot
     215                 :       3090 :         ::std::vector< VDataSeriesGroup >& rXSlots = m_aZSlots[zSlot];
     216                 :            : 
     217 [ +  + ][ +  + ]:       3090 :         if(xSlot<0 || xSlot>=static_cast<sal_Int32>(rXSlots.size()))
                 [ +  + ]
     218                 :            :         {
     219                 :            :             //append the series to already existing x series
     220         [ +  - ]:       3078 :             rXSlots.push_back( VDataSeriesGroup(pSeries) );
     221                 :            :         }
     222                 :            :         else
     223                 :            :         {
     224                 :            :             //x slot is already occupied
     225                 :            :             //y slot decides what to do:
     226                 :            : 
     227                 :         12 :             VDataSeriesGroup& rYSlots = rXSlots[xSlot];
     228                 :         12 :             sal_Int32 nYSlotCount = rYSlots.getSeriesCount();
     229                 :            : 
     230         [ +  - ]:         12 :             if( ySlot < -1 )
     231                 :            :             {
     232                 :            :                 //move all existing series in the xSlot to next slot
     233                 :            :                 //@todo
     234                 :            :                 OSL_FAIL( "Not implemented yet");
     235                 :            :             }
     236 [ +  - ][ +  - ]:         12 :             else if( ySlot == -1 || ySlot >= nYSlotCount)
     237                 :            :             {
     238                 :            :                 //append the series to already existing y series
     239                 :         12 :                 rYSlots.addSeries(pSeries);
     240                 :            :             }
     241                 :            :             else
     242                 :            :             {
     243                 :            :                 //y slot is already occupied
     244                 :            :                 //insert at given y and x position
     245                 :            : 
     246                 :            :                 //@todo
     247                 :            :                 OSL_FAIL( "Not implemented yet");
     248                 :            :             }
     249                 :            :         }
     250                 :            :     }
     251                 :            : }
     252                 :            : 
     253                 :          0 : drawing::Direction3D VSeriesPlotter::getPreferredDiagramAspectRatio() const
     254                 :            : {
     255                 :          0 :     drawing::Direction3D aRet(1.0,1.0,1.0);
     256         [ #  # ]:          0 :     drawing::Direction3D aScale( m_pPosHelper->getScaledLogicWidth() );
     257                 :          0 :     aRet.DirectionZ = aScale.DirectionZ*0.2;
     258         [ #  # ]:          0 :     if(aRet.DirectionZ>1.0)
     259                 :          0 :         aRet.DirectionZ=1.0;
     260         [ #  # ]:          0 :     if(aRet.DirectionZ>10)
     261                 :          0 :         aRet.DirectionZ=10;
     262                 :          0 :     return aRet;
     263                 :            : }
     264                 :            : 
     265                 :          0 : bool VSeriesPlotter::keepAspectRatio() const
     266                 :            : {
     267                 :          0 :     return true;
     268                 :            : }
     269                 :            : 
     270                 :         19 : void VSeriesPlotter::releaseShapes()
     271                 :            : {
     272                 :         19 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator             aZSlotIter = m_aZSlots.begin();
     273         [ +  - ]:         19 :     const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
     274 [ +  - ][ +  + ]:         38 :     for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
     275                 :            :     {
     276                 :         19 :         ::std::vector< VDataSeriesGroup >::iterator             aXSlotIter = aZSlotIter->begin();
     277         [ +  - ]:         19 :         const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
     278 [ +  - ][ +  + ]:         76 :         for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
     279                 :            :         {
     280                 :         57 :             ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
     281                 :            : 
     282                 :         57 :             ::std::vector< VDataSeries* >::iterator             aSeriesIter = pSeriesList->begin();
     283         [ +  - ]:         57 :             const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd  = pSeriesList->end();
     284                 :            : 
     285                 :            :             //iterate through all series in this x slot
     286 [ +  - ][ +  + ]:        114 :             for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
     287                 :            :             {
     288                 :         57 :                 VDataSeries* pSeries( *aSeriesIter );
     289         [ +  - ]:         57 :                 pSeries->releaseShapes();
     290                 :            :             }
     291                 :            :         }
     292                 :            :     }
     293                 :         19 : }
     294                 :            : 
     295                 :      11909 : uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShape( VDataSeries* pDataSeries
     296                 :            :                                         , const uno::Reference< drawing::XShapes >& xTarget )
     297                 :            : {
     298                 :      11909 :     uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xGroupShape );
     299         [ +  + ]:      11909 :     if( !xShapes.is() )
     300                 :            :     {
     301                 :            :         //create a group shape for this series and add to logic target:
     302 [ +  - ][ +  - ]:       3187 :         xShapes = createGroupShape( xTarget,pDataSeries->getCID() );
                 [ +  - ]
     303         [ +  - ]:       3187 :         pDataSeries->m_xGroupShape = xShapes;
     304                 :            :     }
     305                 :      11909 :     return xShapes;
     306                 :            : }
     307                 :            : 
     308                 :       2538 : uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries
     309                 :            :                                         , const uno::Reference< drawing::XShapes >& xTarget )
     310                 :            : {
     311                 :       2538 :     uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xFrontSubGroupShape );
     312         [ +  + ]:       2538 :     if(!xShapes.is())
     313                 :            :     {
     314                 :            :         //ensure that the series group shape is already created
     315         [ +  - ]:        296 :         uno::Reference< drawing::XShapes > xSeriesShapes( this->getSeriesGroupShape( pDataSeries, xTarget ) );
     316                 :            :         //ensure that the back child is created first
     317         [ +  - ]:        296 :         this->getSeriesGroupShapeBackChild( pDataSeries, xTarget );
     318                 :            :         //use series group shape as parent for the new created front group shape
     319 [ +  - ][ +  - ]:        296 :         xShapes = createGroupShape( xSeriesShapes );
     320         [ +  - ]:        296 :         pDataSeries->m_xFrontSubGroupShape = xShapes;
     321                 :            :     }
     322                 :       2538 :     return xShapes;
     323                 :            : }
     324                 :            : 
     325                 :        592 : uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShapeBackChild( VDataSeries* pDataSeries
     326                 :            :                                         , const uno::Reference< drawing::XShapes >& xTarget )
     327                 :            : {
     328                 :        592 :     uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xBackSubGroupShape );
     329         [ +  + ]:        592 :     if(!xShapes.is())
     330                 :            :     {
     331                 :            :         //ensure that the series group shape is already created
     332         [ +  - ]:        296 :         uno::Reference< drawing::XShapes > xSeriesShapes( this->getSeriesGroupShape( pDataSeries, xTarget ) );
     333                 :            :         //use series group shape as parent for the new created back group shape
     334 [ +  - ][ +  - ]:        296 :         xShapes = createGroupShape( xSeriesShapes );
     335         [ +  - ]:        296 :         pDataSeries->m_xBackSubGroupShape = xShapes;
     336                 :            :     }
     337                 :        592 :     return xShapes;
     338                 :            : }
     339                 :            : 
     340                 :       2272 : uno::Reference< drawing::XShapes > VSeriesPlotter::getLabelsGroupShape( VDataSeries& rDataSeries
     341                 :            :                                         , const uno::Reference< drawing::XShapes >& xTextTarget )
     342                 :            : {
     343                 :            :     //xTextTarget needs to be a 2D shape container always!
     344                 :            : 
     345                 :       2272 :     uno::Reference< drawing::XShapes > xShapes( rDataSeries.m_xLabelsGroupShape );
     346         [ +  + ]:       2272 :     if(!xShapes.is())
     347                 :            :     {
     348                 :            :         //create a 2D group shape for texts of this series and add to text target:
     349 [ +  - ][ +  - ]:        400 :         xShapes = m_pShapeFactory->createGroup2D( xTextTarget, rDataSeries.getLabelsCID() );
                 [ +  - ]
     350         [ +  - ]:        400 :         rDataSeries.m_xLabelsGroupShape = xShapes;
     351                 :            :     }
     352                 :       2272 :     return xShapes;
     353                 :            : }
     354                 :            : 
     355                 :       4671 : uno::Reference< drawing::XShapes > VSeriesPlotter::getErrorBarsGroupShape( VDataSeries& rDataSeries
     356                 :            :                                         , const uno::Reference< drawing::XShapes >& xTarget
     357                 :            :                                         , bool bYError )
     358                 :            : {
     359                 :            :     uno::Reference< ::com::sun::star::drawing::XShapes > &rShapeGroup =
     360         [ +  - ]:       4671 :             bYError ? rDataSeries.m_xErrorYBarsGroupShape : rDataSeries.m_xErrorXBarsGroupShape;
     361                 :            : 
     362                 :       4671 :     uno::Reference< drawing::XShapes > xShapes( rShapeGroup );
     363         [ +  + ]:       4671 :     if(!xShapes.is())
     364                 :            :     {
     365                 :            :         //create a group shape for this series and add to logic target:
     366 [ +  - ][ +  - ]:       1080 :         xShapes = this->createGroupShape( xTarget,rDataSeries.getErrorBarsCID(bYError) );
                 [ +  - ]
     367         [ +  - ]:       1080 :         rShapeGroup = xShapes;
     368                 :            :     }
     369                 :       4671 :     return xShapes;
     370                 :            : 
     371                 :            : }
     372                 :            : 
     373                 :       2282 : OUString VSeriesPlotter::getLabelTextForValue( VDataSeries& rDataSeries
     374                 :            :                 , sal_Int32 nPointIndex
     375                 :            :                 , double fValue
     376                 :            :                 , bool bAsPercentage )
     377                 :            : {
     378                 :       2282 :     OUString aNumber;
     379                 :            : 
     380         [ +  - ]:       2282 :     if( m_apNumberFormatterWrapper.get())
     381                 :            :     {
     382                 :       2282 :         sal_Int32 nNumberFormatKey = 0;
     383 [ +  - ][ -  + ]:       2282 :         if( rDataSeries.hasExplicitNumberFormat(nPointIndex,bAsPercentage) )
     384         [ #  # ]:          0 :             nNumberFormatKey = rDataSeries.getExplicitNumberFormat(nPointIndex,bAsPercentage);
     385         [ +  + ]:       2282 :         else if( bAsPercentage )
     386                 :            :         {
     387 [ +  - ][ +  - ]:         91 :             sal_Int32 nPercentFormat = DiagramHelper::getPercentNumberFormat( m_apNumberFormatterWrapper->getNumberFormatsSupplier() );
     388         [ +  - ]:         91 :             if( nPercentFormat != -1 )
     389                 :         91 :                 nNumberFormatKey = nPercentFormat;
     390                 :            :         }
     391                 :            :         else
     392                 :            :         {
     393 [ +  - ][ +  - ]:       2191 :             if( rDataSeries.shouldLabelNumberFormatKeyBeDetectedFromYAxis() && m_aAxesNumberFormats.hasFormat(1,rDataSeries.getAttachedAxisIndex()) ) //y-axis
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
     394 [ #  # ][ #  # ]:          0 :                 nNumberFormatKey = m_aAxesNumberFormats.getFormat(1,rDataSeries.getAttachedAxisIndex());
     395                 :            :             else
     396         [ +  - ]:       2191 :                 nNumberFormatKey = rDataSeries.detectNumberFormatKey( nPointIndex );
     397                 :            :         }
     398         [ -  + ]:       2282 :         if(nNumberFormatKey<0)
     399                 :          0 :             nNumberFormatKey=0;
     400                 :            : 
     401                 :       2282 :         sal_Int32 nLabelCol = 0;
     402                 :            :         bool bColChanged;
     403                 :            :         aNumber = m_apNumberFormatterWrapper->getFormattedString(
     404         [ +  - ]:       2282 :                 nNumberFormatKey, fValue, nLabelCol, bColChanged );
     405                 :            :         //@todo: change color of label if bColChanged is true
     406                 :            :     }
     407                 :            :     else
     408                 :            :     {
     409                 :          0 :         sal_Unicode cDecSeparator = '.';//@todo get this locale dependent
     410                 :            :         aNumber = ::rtl::math::doubleToUString( fValue, rtl_math_StringFormat_G /*rtl_math_StringFormat*/
     411                 :          0 :             , 3/*DecPlaces*/ , cDecSeparator, false /*bEraseTrailingDecZeros*/ );
     412                 :            :     }
     413                 :       2282 :     return aNumber;
     414                 :            : }
     415                 :            : 
     416                 :       2272 : uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Reference< drawing::XShapes >& xTarget
     417                 :            :                     , VDataSeries& rDataSeries
     418                 :            :                     , sal_Int32 nPointIndex
     419                 :            :                     , double fValue
     420                 :            :                     , double fSumValue
     421                 :            :                     , const awt::Point& rScreenPosition2D
     422                 :            :                     , LabelAlignment eAlignment
     423                 :            :                     , sal_Int32 nOffset )
     424                 :            : {
     425                 :       2272 :     uno::Reference< drawing::XShape > xTextShape;
     426                 :            : 
     427                 :            :     try
     428                 :            :     {
     429                 :       2272 :         awt::Point aScreenPosition2D(rScreenPosition2D);
     430         [ -  + ]:       2272 :         if(LABEL_ALIGN_LEFT==eAlignment)
     431                 :          0 :             aScreenPosition2D.X -= nOffset;
     432         [ -  + ]:       2272 :         else if(LABEL_ALIGN_RIGHT==eAlignment)
     433                 :          0 :             aScreenPosition2D.X += nOffset;
     434         [ +  - ]:       2272 :         else if(LABEL_ALIGN_TOP==eAlignment)
     435                 :       2272 :             aScreenPosition2D.Y -= nOffset;
     436         [ #  # ]:          0 :         else if(LABEL_ALIGN_BOTTOM==eAlignment)
     437                 :          0 :             aScreenPosition2D.Y += nOffset;
     438                 :            : 
     439                 :            :         uno::Reference< drawing::XShapes > xTarget_(
     440                 :            :                 m_pShapeFactory->createGroup2D( this->getLabelsGroupShape(rDataSeries, xTarget)
     441 [ +  - ][ +  - ]:       2272 :                     , ObjectIdentifier::createPointCID( rDataSeries.getLabelCID_Stub(),nPointIndex ) ) );
         [ +  - ][ +  - ]
     442                 :            : 
     443                 :            :         //check whether the label needs to be created and how:
     444         [ +  - ]:       2272 :         DataPointLabel* pLabel = rDataSeries.getDataPointLabelIfLabel( nPointIndex );
     445                 :            : 
     446         [ -  + ]:       2272 :         if( !pLabel )
     447                 :            :             return xTextShape;
     448                 :            : 
     449                 :            :         //------------------------------------------------
     450                 :            :         //prepare legend symbol
     451                 :            : 
     452                 :       2272 :         float fViewFontSize( 10.0 );
     453                 :            :         {
     454         [ +  - ]:       2272 :             uno::Reference< beans::XPropertySet > xProps( rDataSeries.getPropertiesOfPoint( nPointIndex ) );
     455         [ +  - ]:       2272 :             if( xProps.is() )
     456 [ +  - ][ +  - ]:       2272 :                 xProps->getPropertyValue( C2U( "CharHeight" )) >>= fViewFontSize;
                 [ +  - ]
     457                 :            :             // pt -> 1/100th mm
     458                 :       2272 :             fViewFontSize *= (2540.0f / 72.0f);
     459                 :            :         }
     460                 :       2272 :         Reference< drawing::XShape > xSymbol;
     461         [ -  + ]:       2272 :         if(pLabel->ShowLegendSymbol)
     462                 :            :         {
     463                 :          0 :             sal_Int32 nSymbolHeigth = static_cast< sal_Int32 >( fViewFontSize * 0.6  );
     464         [ #  # ]:          0 :             awt::Size aCurrentRatio = this->getPreferredLegendKeyAspectRatio();
     465                 :          0 :             sal_Int32 nSymbolWidth = aCurrentRatio.Width;
     466         [ #  # ]:          0 :             if( aCurrentRatio.Height > 0 )
     467                 :            :             {
     468                 :          0 :                 nSymbolWidth = nSymbolHeigth* aCurrentRatio.Width/aCurrentRatio.Height;
     469                 :            :             }
     470                 :          0 :             awt::Size aMaxSymbolExtent( nSymbolWidth, nSymbolHeigth );
     471                 :            : 
     472 [ #  # ][ #  # ]:          0 :             if( rDataSeries.isVaryColorsByPoint() )
     473 [ #  # ][ #  # ]:          0 :                 xSymbol.set( VSeriesPlotter::createLegendSymbolForPoint( aMaxSymbolExtent, rDataSeries, nPointIndex, xTarget_, m_xShapeFactory ) );
     474                 :            :             else
     475 [ #  # ][ #  # ]:          0 :                 xSymbol.set( VSeriesPlotter::createLegendSymbolForSeries( aMaxSymbolExtent, rDataSeries, xTarget_, m_xShapeFactory ) );
     476                 :            : 
     477                 :            :         }
     478                 :            :         //prepare text
     479                 :       2272 :         ::rtl::OUStringBuffer aText;
     480                 :       2272 :         ::rtl::OUString aSeparator(sal_Unicode(' '));
     481                 :       2272 :         double fRotationDegrees = 0.0;
     482                 :            :         try
     483                 :            :         {
     484         [ +  - ]:       2272 :             uno::Reference< beans::XPropertySet > xPointProps( rDataSeries.getPropertiesOfPoint( nPointIndex ) );
     485         [ +  - ]:       2272 :             if(xPointProps.is())
     486                 :            :             {
     487 [ +  - ][ +  - ]:       2272 :                 xPointProps->getPropertyValue( C2U( "LabelSeparator" ) ) >>= aSeparator;
                 [ +  - ]
     488 [ +  - ][ +  - ]:       2272 :                 xPointProps->getPropertyValue( C2U( "TextRotation" ) ) >>= fRotationDegrees;
                 [ +  - ]
     489         [ #  # ]:       2272 :             }
     490                 :            :         }
     491         [ #  # ]:          0 :         catch( const uno::Exception& e )
     492                 :            :         {
     493                 :            :             ASSERT_EXCEPTION( e );
     494                 :            :         }
     495         [ +  - ]:       2272 :         bool bMultiLineLabel = aSeparator.equals(C2U("\n"));;
     496                 :       2272 :         sal_Int32 nLineCountForSymbolsize = 0;
     497                 :            :         {
     498         [ +  + ]:       2272 :             if(pLabel->ShowCategoryName)
     499                 :            :             {
     500         [ +  - ]:       2218 :                 if( m_pExplicitCategoriesProvider )
     501                 :            :                 {
     502         [ +  - ]:       2218 :                     Sequence< OUString > aCategories( m_pExplicitCategoriesProvider->getSimpleCategories() );
     503 [ +  - ][ +  - ]:       2218 :                     if( nPointIndex >= 0 && nPointIndex < aCategories.getLength() )
                 [ +  - ]
     504                 :            :                     {
     505 [ +  - ][ +  - ]:       2218 :                         aText.append( aCategories[nPointIndex] );
     506                 :       2218 :                         ++nLineCountForSymbolsize;
     507         [ +  - ]:       2218 :                     }
     508                 :            :                 }
     509                 :            :             }
     510                 :            : 
     511         [ +  + ]:       2272 :             if(pLabel->ShowNumber)
     512                 :            :             {
     513                 :            :                 OUString aNumber( this->getLabelTextForValue( rDataSeries
     514         [ +  - ]:       2191 :                     , nPointIndex, fValue, false /*bAsPercentage*/ ) );
     515         [ +  - ]:       2191 :                 if( !aNumber.isEmpty() )
     516                 :            :                 {
     517         [ +  + ]:       2191 :                     if(aText.getLength())
     518         [ +  - ]:       2177 :                         aText.append(aSeparator);
     519         [ +  - ]:       2191 :                     aText.append(aNumber);
     520                 :       2191 :                     ++nLineCountForSymbolsize;
     521                 :       2191 :                 }
     522                 :            :             }
     523                 :            : 
     524         [ +  + ]:       2272 :             if(pLabel->ShowNumberInPercent)
     525                 :            :             {
     526         [ -  + ]:         91 :                 if(fSumValue==0.0)
     527                 :          0 :                     fSumValue=1.0;
     528                 :         91 :                 fValue /= fSumValue;
     529         [ -  + ]:         91 :                 if( fValue < 0 )
     530                 :          0 :                     fValue*=-1.0;
     531                 :            : 
     532                 :            :                 OUString aPercentage( this->getLabelTextForValue( rDataSeries
     533         [ +  - ]:         91 :                     , nPointIndex, fValue, true /*bAsPercentage*/ ) );
     534         [ +  - ]:         91 :                 if( !aPercentage.isEmpty() )
     535                 :            :                 {
     536         [ +  + ]:         91 :                     if(aText.getLength())
     537         [ +  - ]:         51 :                         aText.append(aSeparator);
     538         [ +  - ]:         91 :                     aText.append(aPercentage);
     539                 :         91 :                     ++nLineCountForSymbolsize;
     540                 :         91 :                 }
     541                 :            :             }
     542                 :            :         }
     543                 :            :         //------------------------------------------------
     544                 :            :         //prepare properties for multipropertyset-interface of shape
     545                 :            :         tNameSequence* pPropNames;
     546                 :            :         tAnySequence* pPropValues;
     547 [ +  - ][ -  + ]:       2272 :         if( !rDataSeries.getTextLabelMultiPropertyLists( nPointIndex, pPropNames, pPropValues ) )
     548                 :            :             return xTextShape;
     549         [ +  - ]:       2272 :         LabelPositionHelper::changeTextAdjustment( *pPropValues, *pPropNames, eAlignment );
     550                 :            : 
     551                 :            :         //------------------------------------------------
     552                 :            :         //create text shape
     553                 :            :         xTextShape = ShapeFactory(m_xShapeFactory).
     554                 :            :             createText( xTarget_, aText.makeStringAndClear()
     555 [ +  - ][ +  - ]:       2272 :                         , *pPropNames, *pPropValues, ShapeFactory::makeTransformation( aScreenPosition2D ) );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     556                 :            : 
     557         [ -  + ]:       2272 :         if( !xTextShape.is() )
     558                 :            :             return xTextShape;
     559                 :            : 
     560 [ +  - ][ +  - ]:       2272 :         const awt::Point aUnrotatedTextPos( xTextShape->getPosition() );
     561         [ +  + ]:       2272 :         if( fRotationDegrees != 0.0 )
     562                 :            :         {
     563                 :        138 :             const double fDegreesPi( fRotationDegrees * ( F_PI / -180.0 ) );
     564         [ +  - ]:        138 :             uno::Reference< beans::XPropertySet > xProp( xTextShape, uno::UNO_QUERY );
     565         [ +  - ]:        138 :             if( xProp.is() )
     566 [ +  - ][ +  - ]:        138 :                 xProp->setPropertyValue( C2U( "Transformation" ), ShapeFactory::makeTransformation( aScreenPosition2D, fDegreesPi ) );
         [ +  - ][ +  - ]
     567         [ +  - ]:        138 :             LabelPositionHelper::correctPositionForRotation( xTextShape, eAlignment, fRotationDegrees, true /*bRotateAroundCenter*/ );
     568                 :            :         }
     569                 :            : 
     570         [ -  + ]:       2272 :         if( xSymbol.is() )
     571                 :            :         {
     572 [ #  # ][ #  # ]:          0 :             const awt::Point aOldTextPos( xTextShape->getPosition() );
     573                 :          0 :             awt::Point aNewTextPos( aOldTextPos );
     574                 :            : 
     575                 :          0 :             awt::Point aSymbolPosition( aUnrotatedTextPos );
     576 [ #  # ][ #  # ]:          0 :             awt::Size aSymbolSize( xSymbol->getSize() );
     577 [ #  # ][ #  # ]:          0 :             awt::Size aTextSize( xTextShape->getSize() );
     578                 :            : 
     579         [ #  # ]:          0 :             sal_Int32 nXDiff = aSymbolSize.Width + static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.22 ) );//minimum 1mm
     580 [ #  # ][ #  # ]:          0 :             if( !bMultiLineLabel || nLineCountForSymbolsize <= 0 )
     581                 :          0 :                 nLineCountForSymbolsize = 1;
     582                 :          0 :             aSymbolPosition.Y += ((aTextSize.Height/nLineCountForSymbolsize)/4);
     583                 :            : 
     584 [ #  # ][ #  # ]:          0 :             if(LABEL_ALIGN_LEFT==eAlignment
                 [ #  # ]
     585                 :            :                 || LABEL_ALIGN_LEFT_TOP==eAlignment
     586                 :            :                 || LABEL_ALIGN_LEFT_BOTTOM==eAlignment)
     587                 :            :             {
     588                 :          0 :                 aSymbolPosition.X -= nXDiff;
     589                 :            :             }
     590 [ #  # ][ #  # ]:          0 :             else if(LABEL_ALIGN_RIGHT==eAlignment
                 [ #  # ]
     591                 :            :                 || LABEL_ALIGN_RIGHT_TOP==eAlignment
     592                 :            :                 || LABEL_ALIGN_RIGHT_BOTTOM==eAlignment )
     593                 :            :             {
     594                 :          0 :                 aNewTextPos.X += nXDiff;
     595                 :            :             }
     596 [ #  # ][ #  # ]:          0 :             else if(LABEL_ALIGN_TOP==eAlignment
                 [ #  # ]
     597                 :            :                 || LABEL_ALIGN_BOTTOM==eAlignment
     598                 :            :                 || LABEL_ALIGN_CENTER==eAlignment )
     599                 :            :             {
     600                 :          0 :                 aSymbolPosition.X -= nXDiff/2;
     601                 :          0 :                 aNewTextPos.X += nXDiff/2;
     602                 :            :             }
     603                 :            : 
     604 [ #  # ][ #  # ]:          0 :             xSymbol->setPosition( aSymbolPosition );
     605 [ #  # ][ #  # ]:       2272 :             xTextShape->setPosition( aNewTextPos );
     606 [ -  + ][ -  + ]:       2272 :         }
         [ -  + ][ +  - ]
                 [ #  # ]
     607                 :            :     }
     608         [ #  # ]:          0 :     catch( const uno::Exception& e )
     609                 :            :     {
     610                 :            :         ASSERT_EXCEPTION( e );
     611                 :            :     }
     612                 :            : 
     613                 :       2272 :     return xTextShape;
     614                 :            : }
     615                 :            : 
     616                 :            : namespace
     617                 :            : {
     618                 :        975 : double lcl_getErrorBarLogicLength(
     619                 :            :     const uno::Sequence< double > & rData,
     620                 :            :     uno::Reference< beans::XPropertySet > xProp,
     621                 :            :     sal_Int32 nErrorBarStyle,
     622                 :            :     sal_Int32 nIndex,
     623                 :            :     bool bPositive,
     624                 :            :     bool bYError )
     625                 :            : {
     626                 :            :     double fResult;
     627                 :        975 :     ::rtl::math::setNan( & fResult );
     628                 :            :     try
     629                 :            :     {
     630   [ -  -  -  +  :        975 :         switch( nErrorBarStyle )
             -  -  -  -  
                      - ]
     631                 :            :         {
     632                 :            :             case ::com::sun::star::chart::ErrorBarStyle::NONE:
     633                 :          0 :                 break;
     634                 :            :             case ::com::sun::star::chart::ErrorBarStyle::VARIANCE:
     635         [ #  # ]:          0 :                 fResult = StatisticsHelper::getVariance( rData );
     636                 :          0 :                 break;
     637                 :            :             case ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION:
     638         [ #  # ]:          0 :                 fResult = StatisticsHelper::getStandardDeviation( rData );
     639                 :          0 :                 break;
     640                 :            :             case ::com::sun::star::chart::ErrorBarStyle::RELATIVE:
     641                 :            :             {
     642                 :        975 :                 double fPercent = 0;
     643   [ +  -  +  - ]:       1950 :                 if( xProp->getPropertyValue( bPositive
     644                 :            :                                              ? C2U("PositiveError")
     645 [ +  + ][ +  - ]:        975 :                                              : C2U("NegativeError")) >>= fPercent )
         [ +  - ][ +  - ]
     646                 :            :                 {
     647 [ +  - ][ +  -  :       2925 :                     if( nIndex >=0 && nIndex < rData.getLength() &&
             +  -  +  - ]
                 [ +  - ]
     648                 :        975 :                         ! ::rtl::math::isNan( rData[nIndex] ) &&
     649                 :        975 :                         ! ::rtl::math::isNan( fPercent ))
     650                 :            :                     {
     651                 :        975 :                         fResult = rData[nIndex] * fPercent / 100.0;
     652                 :            :                     }
     653                 :            :                 }
     654                 :            :             }
     655                 :        975 :             break;
     656                 :            :             case ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE:
     657         [ #  # ]:          0 :                 xProp->getPropertyValue( bPositive
     658                 :            :                                          ? C2U("PositiveError")
     659 [ #  # ][ #  # ]:          0 :                                          : C2U("NegativeError")) >>= fResult;
         [ #  # ][ #  # ]
     660                 :          0 :                 break;
     661                 :            :             case ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN:
     662                 :            :             {
     663                 :            :                 // todo: check if this is really what's called error-margin
     664                 :          0 :                 double fPercent = 0;
     665   [ #  #  #  # ]:          0 :                 if( xProp->getPropertyValue( bPositive
     666                 :            :                                              ? C2U("PositiveError")
     667 [ #  # ][ #  # ]:          0 :                                              : C2U("NegativeError")) >>= fPercent )
         [ #  # ][ #  # ]
     668                 :            :                 {
     669                 :            :                     double fMaxValue;
     670                 :          0 :                     ::rtl::math::setInf(&fMaxValue, true);
     671                 :          0 :                     const double* pValues = rData.getConstArray();
     672         [ #  # ]:          0 :                     for(sal_Int32 i=0; i<rData.getLength(); ++i, ++pValues)
     673                 :            :                     {
     674         [ #  # ]:          0 :                         if(fMaxValue<*pValues)
     675                 :          0 :                             fMaxValue=*pValues;
     676                 :            :                     }
     677   [ #  #  #  # ]:          0 :                     if( ::rtl::math::isFinite( fMaxValue ) &&
                 [ #  # ]
     678                 :          0 :                         ::rtl::math::isFinite( fPercent ))
     679                 :            :                     {
     680                 :          0 :                         fResult = fMaxValue * fPercent / 100.0;
     681                 :            :                     }
     682                 :            :                 }
     683                 :            :             }
     684                 :          0 :             break;
     685                 :            :             case ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR:
     686         [ #  # ]:          0 :                 fResult = StatisticsHelper::getStandardError( rData );
     687                 :          0 :                 break;
     688                 :            :             case ::com::sun::star::chart::ErrorBarStyle::FROM_DATA:
     689                 :            :             {
     690         [ #  # ]:          0 :                 uno::Reference< chart2::data::XDataSource > xErrorBarData( xProp, uno::UNO_QUERY );
     691         [ #  # ]:          0 :                 if( xErrorBarData.is())
     692                 :            :                     fResult = StatisticsHelper::getErrorFromDataSource(
     693 [ #  # ][ #  # ]:          0 :                         xErrorBarData, nIndex, bPositive, bYError);
     694                 :            :             }
     695                 :          0 :             break;
     696                 :            :         }
     697                 :            :     }
     698         [ #  # ]:          0 :     catch( const uno::Exception & e )
     699                 :            :     {
     700                 :            :         ASSERT_EXCEPTION( e );
     701                 :            :     }
     702                 :            : 
     703                 :        975 :     return fResult;
     704                 :            : }
     705                 :            : 
     706                 :        659 : void lcl_AddErrorBottomLine( const drawing::Position3D& rPosition, ::basegfx::B2DVector aMainDirection
     707                 :            :                 , drawing::PolyPolygonShape3D& rPoly, sal_Int32 nSequenceIndex )
     708                 :            : {
     709                 :        659 :     double fFixedWidth = 200.0;
     710                 :            : 
     711         [ +  - ]:        659 :     aMainDirection.normalize();
     712                 :        659 :     ::basegfx::B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
     713         [ +  - ]:        659 :     aOrthoDirection.normalize();
     714                 :            : 
     715                 :        659 :     ::basegfx::B2DVector aAnchor( rPosition.PositionX, rPosition.PositionY );
     716                 :        659 :     ::basegfx::B2DVector aStart = aAnchor + aOrthoDirection*fFixedWidth/2.0;
     717                 :        659 :     ::basegfx::B2DVector aEnd = aAnchor - aOrthoDirection*fFixedWidth/2.0;
     718                 :            : 
     719         [ +  - ]:        659 :     AddPointToPoly( rPoly, drawing::Position3D( aStart.getX(), aStart.getY(), rPosition.PositionZ), nSequenceIndex );
     720         [ +  - ]:        659 :     AddPointToPoly( rPoly, drawing::Position3D( aEnd.getX(), aEnd.getY(), rPosition.PositionZ), nSequenceIndex );
     721                 :        659 : }
     722                 :            : 
     723                 :        659 : ::basegfx::B2DVector lcl_getErrorBarMainDirection(
     724                 :            :               const drawing::Position3D& rStart
     725                 :            :             , const drawing::Position3D& rBottomEnd
     726                 :            :             , PlottingPositionHelper* pPosHelper
     727                 :            :             , const drawing::Position3D& rUnscaledLogicPosition
     728                 :            :             , bool bYError )
     729                 :            : {
     730                 :            :     ::basegfx::B2DVector aMainDirection = ::basegfx::B2DVector( rStart.PositionX - rBottomEnd.PositionX
     731                 :        659 :                                               , rStart.PositionY - rBottomEnd.PositionY );
     732 [ -  + ][ +  - ]:        659 :     if( !aMainDirection.getLength() )
     733                 :            :     {
     734                 :            :         //get logic clip values:
     735         [ #  # ]:          0 :         double MinX = pPosHelper->getLogicMinX();
     736         [ #  # ]:          0 :         double MinY = pPosHelper->getLogicMinY();
     737         [ #  # ]:          0 :         double MaxX = pPosHelper->getLogicMaxX();
     738         [ #  # ]:          0 :         double MaxY = pPosHelper->getLogicMaxY();
     739         [ #  # ]:          0 :         double fZ = pPosHelper->getLogicMinZ();
     740                 :            : 
     741                 :            : 
     742         [ #  # ]:          0 :         if( bYError )
     743                 :            :         {
     744                 :            :             //main direction has constant x value
     745                 :          0 :             MinX = rUnscaledLogicPosition.PositionX;
     746                 :          0 :             MaxX = rUnscaledLogicPosition.PositionX;
     747                 :            :         }
     748                 :            :         else
     749                 :            :         {
     750                 :            :             //main direction has constant y value
     751                 :          0 :             MinY = rUnscaledLogicPosition.PositionY;
     752                 :          0 :             MaxY = rUnscaledLogicPosition.PositionY;
     753                 :            :         }
     754                 :            : 
     755         [ #  # ]:          0 :         drawing::Position3D aStart = pPosHelper->transformLogicToScene( MinX, MinY, fZ, false );
     756         [ #  # ]:          0 :         drawing::Position3D aEnd = pPosHelper->transformLogicToScene( MaxX, MaxY, fZ, false );
     757                 :            : 
     758                 :            :         aMainDirection = ::basegfx::B2DVector( aStart.PositionX - aEnd.PositionX
     759         [ #  # ]:          0 :                                               , aStart.PositionY - aEnd.PositionY );
     760                 :            :     }
     761         [ +  - ]:        659 :     if( !aMainDirection.getLength() )
     762                 :            :     {
     763                 :            :         //@todo
     764                 :            :     }
     765                 :        659 :     return aMainDirection;
     766                 :            : }
     767                 :            : 
     768                 :       1482 : drawing::Position3D lcl_transformMixedToScene( PlottingPositionHelper* pPosHelper
     769                 :            :     , double fX /*scaled*/, double fY /*unscaled*/, double fZ /*unscaled*/, bool bClip )
     770                 :            : {
     771         [ -  + ]:       1482 :     if(!pPosHelper)
     772                 :          0 :         return drawing::Position3D(0,0,0);
     773                 :       1482 :     pPosHelper->doLogicScaling( 0,&fY,&fZ );
     774         [ +  - ]:       1482 :     if(bClip)
     775                 :       1482 :         pPosHelper->clipScaledLogicValues( &fX,&fY,&fZ );
     776                 :       1482 :     return pPosHelper->transformScaledLogicToScene( fX, fY, fZ, false );
     777                 :            : }
     778                 :            : 
     779                 :            : } // anonymous namespace
     780                 :            : 
     781                 :       4671 : void VSeriesPlotter::createErrorBar(
     782                 :            :       const uno::Reference< drawing::XShapes >& xTarget
     783                 :            :     , const drawing::Position3D& rUnscaledLogicPosition
     784                 :            :     , const uno::Reference< beans::XPropertySet > & xErrorBarProperties
     785                 :            :     , const VDataSeries& rVDataSeries
     786                 :            :     , sal_Int32 nIndex
     787                 :            :     , bool bYError /* = true */
     788                 :            :     , double* pfScaledLogicX
     789                 :            :     )
     790                 :            : {
     791         [ -  + ]:       4671 :     if( !ChartTypeHelper::isSupportingStatisticProperties( m_xChartTypeModel, m_nDimension ) )
     792                 :          0 :         return;
     793                 :            : 
     794         [ -  + ]:       4671 :     if( ! xErrorBarProperties.is())
     795                 :          0 :         return;
     796                 :            : 
     797                 :            :     try
     798                 :            :     {
     799                 :       4671 :         sal_Bool bShowPositive = sal_False;
     800                 :       4671 :         sal_Bool bShowNegative = sal_False;
     801                 :       4671 :         sal_Int32 nErrorBarStyle = ::com::sun::star::chart::ErrorBarStyle::VARIANCE;
     802                 :            : 
     803 [ +  - ][ +  - ]:       4671 :         xErrorBarProperties->getPropertyValue( C2U( "ShowPositiveError" )) >>= bShowPositive;
                 [ +  - ]
     804 [ +  - ][ +  - ]:       4671 :         xErrorBarProperties->getPropertyValue( C2U( "ShowNegativeError" )) >>= bShowNegative;
                 [ +  - ]
     805 [ +  - ][ +  - ]:       4671 :         xErrorBarProperties->getPropertyValue( C2U( "ErrorBarStyle" )) >>= nErrorBarStyle;
                 [ +  - ]
     806                 :            : 
     807 [ -  + ][ +  + ]:       4671 :         if(!bShowPositive && !bShowNegative)
     808                 :            :             return;
     809                 :            : 
     810         [ +  - ]:        507 :         if(nErrorBarStyle==::com::sun::star::chart::ErrorBarStyle::NONE)
     811                 :            :             return;
     812                 :            : 
     813                 :        507 :         drawing::Position3D aUnscaledLogicPosition(rUnscaledLogicPosition);
     814         [ -  + ]:        507 :         if(nErrorBarStyle==::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION)
     815                 :            :         {
     816         [ #  # ]:          0 :             if (bYError)
     817         [ #  # ]:          0 :                 aUnscaledLogicPosition.PositionY = rVDataSeries.getYMeanValue();
     818                 :            :             else
     819         [ #  # ]:          0 :                 aUnscaledLogicPosition.PositionX = rVDataSeries.getXMeanValue();
     820                 :            :         }
     821                 :            : 
     822                 :        507 :         bool bCreateNegativeBorder = false;//make a vertical line at the negative end of the error bar
     823                 :        507 :         bool bCreatePositiveBorder = false;//make a vertical line at the positive end of the error bar
     824                 :        507 :         drawing::Position3D aMiddle(aUnscaledLogicPosition);
     825                 :        507 :         const double fX = aUnscaledLogicPosition.PositionX;
     826                 :        507 :         const double fY = aUnscaledLogicPosition.PositionY;
     827                 :        507 :         const double fZ = aUnscaledLogicPosition.PositionZ;
     828                 :        507 :         double fScaledX = fX;
     829         [ -  + ]:        507 :         if( pfScaledLogicX )
     830                 :          0 :             fScaledX = *pfScaledLogicX;
     831                 :            :         else
     832         [ +  - ]:        507 :             m_pPosHelper->doLogicScaling( &fScaledX, 0, 0 );
     833                 :            : 
     834         [ +  - ]:        507 :         aMiddle = lcl_transformMixedToScene( m_pPosHelper, fScaledX, fY, fZ, true );
     835                 :            : 
     836                 :        507 :         drawing::Position3D aNegative(aMiddle);
     837                 :        507 :         drawing::Position3D aPositive(aMiddle);
     838                 :            : 
     839 [ +  - ][ +  - ]:        507 :         uno::Sequence< double > aData( bYError ? rVDataSeries.getAllY() : rVDataSeries.getAllX() );
                 [ #  # ]
     840                 :            : 
     841         [ +  - ]:        507 :         if( bShowPositive )
     842                 :            :         {
     843         [ +  - ]:        507 :             double fLength = lcl_getErrorBarLogicLength( aData, xErrorBarProperties, nErrorBarStyle, nIndex, true, bYError );
     844         [ +  - ]:        507 :             if( ::rtl::math::isFinite( fLength ) )
     845                 :            :             {
     846                 :        507 :                 double fLocalX = fX;
     847                 :        507 :                 double fLocalY = fY;
     848         [ +  - ]:        507 :                 if( bYError )
     849                 :            :                 {
     850                 :        507 :                     fLocalY+=fLength;
     851         [ +  - ]:        507 :                     aPositive = lcl_transformMixedToScene( m_pPosHelper, fScaledX, fLocalY, fZ, true );
     852                 :            :                 }
     853                 :            :                 else
     854                 :            :                 {
     855                 :          0 :                     fLocalX+=fLength;
     856         [ #  # ]:          0 :                     aPositive = m_pPosHelper->transformLogicToScene( fLocalX, fLocalY, fZ, true );
     857                 :            :                 }
     858         [ +  - ]:        507 :                 bCreatePositiveBorder = m_pPosHelper->isLogicVisible(fLocalX, fLocalY, fZ);
     859                 :            :             }
     860                 :            :             else
     861                 :          0 :                 bShowPositive = false;
     862                 :            :         }
     863                 :            : 
     864         [ +  + ]:        507 :         if( bShowNegative )
     865                 :            :         {
     866         [ +  - ]:        468 :             double fLength = lcl_getErrorBarLogicLength( aData, xErrorBarProperties, nErrorBarStyle, nIndex, false, bYError );
     867         [ +  - ]:        468 :             if( ::rtl::math::isFinite( fLength ) )
     868                 :            :             {
     869                 :        468 :                 double fLocalX = fX;
     870                 :        468 :                 double fLocalY = fY;
     871         [ +  - ]:        468 :                 if( bYError )
     872                 :            :                 {
     873                 :        468 :                     fLocalY-=fLength;
     874         [ +  - ]:        468 :                     aNegative = lcl_transformMixedToScene( m_pPosHelper, fScaledX, fLocalY, fZ, true );
     875                 :            :                 }
     876                 :            :                 else
     877                 :            :                 {
     878                 :          0 :                     fLocalX-=fLength;
     879         [ #  # ]:          0 :                     aNegative = m_pPosHelper->transformLogicToScene( fLocalX, fLocalY, fZ, true );
     880                 :            :                 }
     881         [ +  - ]:        468 :                 bCreateNegativeBorder = m_pPosHelper->isLogicVisible( fLocalX, fLocalY, fZ);
     882                 :            :             }
     883                 :            :             else
     884                 :          0 :                 bShowNegative = false;
     885                 :            :         }
     886                 :            : 
     887 [ -  + ][ #  # ]:        507 :         if(!bShowPositive && !bShowNegative)
     888                 :            :             return;
     889                 :            : 
     890         [ +  - ]:        507 :         drawing::PolyPolygonShape3D aPoly;
     891                 :            : 
     892                 :        507 :         sal_Int32 nSequenceIndex=0;
     893         [ +  + ]:        507 :         if( bShowNegative )
     894         [ +  - ]:        468 :             AddPointToPoly( aPoly, aNegative, nSequenceIndex );
     895         [ +  - ]:        507 :         AddPointToPoly( aPoly, aMiddle, nSequenceIndex );
     896         [ +  - ]:        507 :         if( bShowPositive )
     897         [ +  - ]:        507 :             AddPointToPoly( aPoly, aPositive, nSequenceIndex );
     898                 :            : 
     899 [ +  + ][ +  + ]:        507 :         if( bShowNegative && bCreateNegativeBorder )
     900                 :            :         {
     901         [ +  - ]:        312 :             ::basegfx::B2DVector aMainDirection = lcl_getErrorBarMainDirection( aMiddle, aNegative, m_pPosHelper, aUnscaledLogicPosition, bYError );
     902                 :        312 :             nSequenceIndex++;
     903         [ +  - ]:        312 :             lcl_AddErrorBottomLine( aNegative, aMainDirection, aPoly, nSequenceIndex );
     904                 :            :         }
     905 [ +  - ][ +  + ]:        507 :         if( bShowPositive && bCreatePositiveBorder )
     906                 :            :         {
     907         [ +  - ]:        347 :             ::basegfx::B2DVector aMainDirection = lcl_getErrorBarMainDirection( aMiddle, aPositive, m_pPosHelper, aUnscaledLogicPosition, bYError );
     908                 :        347 :             nSequenceIndex++;
     909         [ +  - ]:        347 :             lcl_AddErrorBottomLine( aPositive, aMainDirection, aPoly, nSequenceIndex );
     910                 :            :         }
     911                 :            : 
     912 [ +  - ][ +  - ]:        507 :         uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( xTarget, PolyToPointSequence( aPoly) );
                 [ +  - ]
     913 [ +  - ][ +  - ]:       4671 :         this->setMappedProperties( xShape, xErrorBarProperties, PropertyMapper::getPropertyNameMapForLineProperties() );
         [ +  - ][ +  - ]
         [ +  - ][ #  # ]
     914                 :            :     }
     915                 :          0 :     catch( const uno::Exception & e )
     916                 :            :     {
     917                 :            :         ASSERT_EXCEPTION( e );
     918                 :            :     }
     919                 :            : 
     920                 :            : }
     921                 :            : 
     922                 :          0 : void VSeriesPlotter::createErrorBar_X( const drawing::Position3D& rUnscaledLogicPosition
     923                 :            :                             , VDataSeries& rVDataSeries, sal_Int32 nPointIndex
     924                 :            :                             , const uno::Reference< drawing::XShapes >& xTarget
     925                 :            :                             , double* pfScaledLogicX )
     926                 :            : {
     927         [ #  # ]:          0 :     if(m_nDimension!=2)
     928                 :          0 :         return;
     929                 :            :     // error bars
     930         [ #  # ]:          0 :     uno::Reference< beans::XPropertySet > xErrorBarProp(rVDataSeries.getXErrorBarProperties(nPointIndex));
     931         [ #  # ]:          0 :     if( xErrorBarProp.is())
     932                 :            :     {
     933                 :            :         uno::Reference< drawing::XShapes > xErrorBarsGroup_Shapes(
     934         [ #  # ]:          0 :             this->getErrorBarsGroupShape(rVDataSeries, xTarget, false) );
     935                 :            : 
     936                 :            :         createErrorBar( xErrorBarsGroup_Shapes
     937                 :            :             , rUnscaledLogicPosition, xErrorBarProp
     938                 :            :             , rVDataSeries, nPointIndex
     939                 :            :             , false /* bYError */
     940         [ #  # ]:          0 :             , pfScaledLogicX );
     941                 :          0 :     }
     942                 :            : }
     943                 :            : 
     944                 :      11476 : void VSeriesPlotter::createErrorBar_Y( const drawing::Position3D& rUnscaledLogicPosition
     945                 :            :                             , VDataSeries& rVDataSeries, sal_Int32 nPointIndex
     946                 :            :                             , const uno::Reference< drawing::XShapes >& xTarget
     947                 :            :                             , double* pfScaledLogicX )
     948                 :            : {
     949         [ +  + ]:      11476 :     if(m_nDimension!=2)
     950                 :      11476 :         return;
     951                 :            :     // error bars
     952         [ +  - ]:      11440 :     uno::Reference< beans::XPropertySet > xErrorBarProp(rVDataSeries.getYErrorBarProperties(nPointIndex));
     953         [ +  + ]:      11440 :     if( xErrorBarProp.is())
     954                 :            :     {
     955                 :            :         uno::Reference< drawing::XShapes > xErrorBarsGroup_Shapes(
     956         [ +  - ]:       4671 :             this->getErrorBarsGroupShape(rVDataSeries, xTarget, true) );
     957                 :            : 
     958                 :            :         createErrorBar( xErrorBarsGroup_Shapes
     959                 :            :             , rUnscaledLogicPosition, xErrorBarProp
     960                 :            :             , rVDataSeries, nPointIndex
     961                 :            :             , true /* bYError */
     962         [ +  - ]:       4671 :             , pfScaledLogicX );
     963                 :      11476 :     }
     964                 :            : }
     965                 :            : 
     966                 :       3129 : void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries& rVDataSeries
     967                 :            :                             , const uno::Reference< drawing::XShapes >& xTarget
     968                 :            :                             , const uno::Reference< drawing::XShapes >& xEquationTarget
     969                 :            :                             , bool bMaySkipPointsInRegressionCalculation )
     970                 :            : {
     971         [ +  + ]:       3129 :     if(m_nDimension!=2)
     972                 :            :         return;
     973                 :            :     uno::Reference< XRegressionCurveContainer > xRegressionContainer(
     974 [ +  - ][ +  - ]:       3087 :                 rVDataSeries.getModel(), uno::UNO_QUERY );
     975         [ -  + ]:       3087 :     if(!xRegressionContainer.is())
     976                 :            :         return;
     977         [ +  - ]:       3087 :     double fMinX = m_pPosHelper->getLogicMinX();
     978         [ +  - ]:       3087 :     double fMaxX = m_pPosHelper->getLogicMaxX();
     979                 :            : 
     980                 :            :     uno::Sequence< uno::Reference< XRegressionCurve > > aCurveList =
     981 [ +  - ][ +  - ]:       3087 :         xRegressionContainer->getRegressionCurves();
     982         [ +  + ]:       3195 :     for(sal_Int32 nN=0; nN<aCurveList.getLength(); nN++)
     983                 :            :     {
     984                 :            :         uno::Reference< XRegressionCurveCalculator > xRegressionCurveCalculator(
     985 [ +  - ][ +  - ]:        108 :             aCurveList[nN]->getCalculator() );
                 [ +  - ]
     986         [ -  + ]:        108 :         if( ! xRegressionCurveCalculator.is())
     987                 :          0 :             continue;
     988 [ +  - ][ +  - ]:        108 :         xRegressionCurveCalculator->recalculateRegression( rVDataSeries.getAllX(), rVDataSeries.getAllY() );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     989                 :            : 
     990                 :        108 :         sal_Int32 nRegressionPointCount = 50;//@todo find a more optimal solution if more complicated curve types are introduced
     991         [ +  - ]:        108 :         drawing::PolyPolygonShape3D aRegressionPoly;
     992         [ +  - ]:        108 :         aRegressionPoly.SequenceX.realloc(1);
     993         [ +  - ]:        108 :         aRegressionPoly.SequenceY.realloc(1);
     994         [ +  - ]:        108 :         aRegressionPoly.SequenceZ.realloc(1);
     995 [ +  - ][ +  - ]:        108 :         aRegressionPoly.SequenceX[0].realloc(nRegressionPointCount);
     996 [ +  - ][ +  - ]:        108 :         aRegressionPoly.SequenceY[0].realloc(nRegressionPointCount);
     997 [ +  - ][ +  - ]:        108 :         aRegressionPoly.SequenceZ[0].realloc(nRegressionPointCount);
     998                 :        108 :         sal_Int32 nRealPointCount=0;
     999                 :            : 
    1000 [ +  - ][ +  - ]:        108 :         std::vector< ExplicitScaleData > aScales( m_pPosHelper->getScales());
    1001                 :        108 :         uno::Reference< chart2::XScaling > xScalingX;
    1002                 :        108 :         uno::Reference< chart2::XScaling > xScalingY;
    1003         [ +  - ]:        108 :         if( aScales.size() >= 2 )
    1004                 :            :         {
    1005 [ +  - ][ +  - ]:        108 :             xScalingX.set( aScales[0].Scaling );
    1006 [ +  - ][ +  - ]:        108 :             xScalingY.set( aScales[1].Scaling );
    1007                 :            :         }
    1008                 :            : 
    1009                 :            :         uno::Sequence< geometry::RealPoint2D > aCalculatedPoints(
    1010         [ +  - ]:        108 :             xRegressionCurveCalculator->getCurveValues(
    1011         [ +  - ]:        108 :                 fMinX, fMaxX, nRegressionPointCount, xScalingX, xScalingY, bMaySkipPointsInRegressionCalculation ));
    1012                 :        108 :         nRegressionPointCount = aCalculatedPoints.getLength();
    1013         [ +  + ]:       1860 :         for(sal_Int32 nP=0; nP<nRegressionPointCount; nP++)
    1014                 :            :         {
    1015         [ +  - ]:       1752 :             double fLogicX = aCalculatedPoints[nP].X;
    1016         [ +  - ]:       1752 :             double fLogicY = aCalculatedPoints[nP].Y;
    1017                 :       1752 :             double fLogicZ = 0.0;//dummy
    1018                 :            : 
    1019         [ +  - ]:       1752 :             m_pPosHelper->doLogicScaling( &fLogicX, &fLogicY, &fLogicZ );
    1020                 :            : 
    1021 [ +  - ][ +  -  :       8760 :             if(    !::rtl::math::isNan(fLogicX) && !::rtl::math::isInf(fLogicX)
          +  -  +  -  +  
                -  +  - ]
                 [ +  - ]
    1022                 :       3504 :                     && !::rtl::math::isNan(fLogicY) && !::rtl::math::isInf(fLogicY)
    1023                 :       3504 :                     && !::rtl::math::isNan(fLogicZ) && !::rtl::math::isInf(fLogicZ) )
    1024                 :            :             {
    1025 [ +  - ][ +  - ]:       1752 :                 aRegressionPoly.SequenceX[0][nRealPointCount] = fLogicX;
    1026 [ +  - ][ +  - ]:       1752 :                 aRegressionPoly.SequenceY[0][nRealPointCount] = fLogicY;
    1027                 :       1752 :                 nRealPointCount++;
    1028                 :            :             }
    1029                 :            :         }
    1030 [ +  - ][ +  - ]:        108 :         aRegressionPoly.SequenceX[0].realloc(nRealPointCount);
    1031 [ +  - ][ +  - ]:        108 :         aRegressionPoly.SequenceY[0].realloc(nRealPointCount);
    1032 [ +  - ][ +  - ]:        108 :         aRegressionPoly.SequenceZ[0].realloc(nRealPointCount);
    1033                 :            : 
    1034         [ +  - ]:        108 :         drawing::PolyPolygonShape3D aClippedPoly;
    1035 [ +  - ][ +  - ]:        108 :         Clipping::clipPolygonAtRectangle( aRegressionPoly, m_pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly );
    1036         [ +  - ]:        108 :         aRegressionPoly = aClippedPoly;
    1037         [ +  - ]:        108 :         m_pPosHelper->transformScaledLogicToScene( aRegressionPoly );
    1038                 :            : 
    1039                 :        108 :         awt::Point aDefaultPos;
    1040 [ +  - ][ +  - ]:        108 :         if( aRegressionPoly.SequenceX.getLength() && aRegressionPoly.SequenceX[0].getLength() )
         [ +  + ][ +  + ]
    1041                 :            :         {
    1042 [ +  - ][ +  - ]:         84 :             uno::Reference< beans::XPropertySet > xCurveModelProp( aCurveList[nN], uno::UNO_QUERY );
    1043         [ +  - ]:         84 :             VLineProperties aVLineProperties;
    1044         [ +  - ]:         84 :             aVLineProperties.initFromPropertySet( xCurveModelProp );
    1045                 :            : 
    1046                 :            :             //create an extra group shape for each curve for selection handling
    1047 [ +  - ][ +  - ]:         84 :             bool bAverageLine = RegressionCurveHelper::isMeanValueLine( aCurveList[nN] );
    1048                 :            :             uno::Reference< drawing::XShapes > xRegressionGroupShapes =
    1049 [ +  - ][ +  - ]:         84 :                 createGroupShape( xTarget, rVDataSeries.getDataCurveCID( nN, bAverageLine ) );
    1050                 :            :             uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
    1051 [ +  - ][ +  - ]:         84 :                 xRegressionGroupShapes, PolyToPointSequence( aRegressionPoly ), &aVLineProperties );
                 [ +  - ]
    1052 [ +  - ][ +  - ]:         84 :             m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
    1053 [ +  - ][ +  - ]:         84 :             aDefaultPos = xShape->getPosition();
    1054                 :            :         }
    1055                 :            : 
    1056                 :            :         // curve equation and correlation coefficient
    1057 [ +  - ][ +  - ]:        108 :         uno::Reference< beans::XPropertySet > xEqProp( aCurveList[nN]->getEquationProperties());
                 [ +  - ]
    1058         [ +  - ]:        108 :         if( xEqProp.is())
    1059                 :            :         {
    1060                 :            :             createRegressionCurveEquationShapes(
    1061                 :            :                 rVDataSeries.getDataCurveEquationCID( nN ),
    1062                 :            :                 xEqProp, xEquationTarget, xRegressionCurveCalculator,
    1063 [ +  - ][ +  - ]:        108 :                 aDefaultPos );
    1064                 :            :         }
    1065 [ +  - ][ +  - ]:       3237 :     }
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1066                 :            : }
    1067                 :            : 
    1068                 :        108 : void VSeriesPlotter::createRegressionCurveEquationShapes(
    1069                 :            :     const OUString & rEquationCID,
    1070                 :            :     const uno::Reference< beans::XPropertySet > & xEquationProperties,
    1071                 :            :     const uno::Reference< drawing::XShapes >& xEquationTarget,
    1072                 :            :     const uno::Reference< chart2::XRegressionCurveCalculator > & xRegressionCurveCalculator,
    1073                 :            :     awt::Point aDefaultPos )
    1074                 :            : {
    1075                 :            :     OSL_ASSERT( xEquationProperties.is());
    1076         [ +  - ]:        108 :     if( !xEquationProperties.is())
    1077                 :            :         return;
    1078                 :            : 
    1079                 :        108 :     bool bShowEquation = false;
    1080                 :        108 :     bool bShowCorrCoeff = false;
    1081                 :        108 :     OUString aSep( sal_Unicode('\n'));
    1082 [ +  - ][ +  - ]:        324 :     if(( xEquationProperties->getPropertyValue( C2U("ShowEquation")) >>= bShowEquation ) &&
           [ +  -  +  - ]
         [ +  - ][ +  - ]
           [ +  -  #  #  
           #  # ][ +  - ]
    1083 [ +  - ][ +  - ]:        216 :        ( xEquationProperties->getPropertyValue( C2U("ShowCorrelationCoefficient")) >>= bShowCorrCoeff ))
         [ +  - ][ +  - ]
                 [ +  - ]
           [ #  #  #  # ]
    1084                 :            :     {
    1085 [ +  - ][ -  + ]:        108 :         if( ! (bShowEquation || bShowCorrCoeff))
    1086                 :            :             return;
    1087                 :            : 
    1088                 :          0 :         ::rtl::OUStringBuffer aFormula;
    1089                 :          0 :         sal_Int32 nNumberFormatKey = 0;
    1090 [ #  # ][ #  # ]:          0 :         xEquationProperties->getPropertyValue( C2U("NumberFormat")) >>= nNumberFormatKey;
                 [ #  # ]
    1091                 :            : 
    1092         [ #  # ]:          0 :         if( bShowEquation )
    1093                 :            :         {
    1094         [ #  # ]:          0 :             if( m_apNumberFormatterWrapper.get())
    1095                 :            :             {
    1096         [ #  # ]:          0 :                 aFormula = xRegressionCurveCalculator->getFormattedRepresentation(
    1097                 :            :                     m_apNumberFormatterWrapper->getNumberFormatsSupplier(),
    1098 [ #  # ][ #  # ]:          0 :                     nNumberFormatKey );
         [ #  # ][ #  # ]
    1099                 :            :             }
    1100                 :            :             else
    1101                 :            :             {
    1102 [ #  # ][ #  # ]:          0 :                 aFormula = xRegressionCurveCalculator->getRepresentation();
         [ #  # ][ #  # ]
    1103                 :            :             }
    1104                 :            : 
    1105         [ #  # ]:          0 :             if( bShowCorrCoeff )
    1106                 :            :             {
    1107         [ #  # ]:          0 :                 aFormula.append( aSep );
    1108                 :            :             }
    1109                 :            :         }
    1110         [ #  # ]:          0 :         if( bShowCorrCoeff )
    1111                 :            :         {
    1112         [ #  # ]:          0 :             aFormula.append( sal_Unicode( 'R' ));
    1113         [ #  # ]:          0 :             aFormula.append( sal_Unicode( 0x00b2 ));
    1114 [ #  # ][ #  # ]:          0 :             aFormula.append( C2U( " = " ));
    1115 [ #  # ][ #  # ]:          0 :             double fR( xRegressionCurveCalculator->getCorrelationCoefficient());
    1116         [ #  # ]:          0 :             if( m_apNumberFormatterWrapper.get())
    1117                 :            :             {
    1118                 :          0 :                 sal_Int32 nLabelCol = 0;
    1119                 :            :                 bool bColChanged;
    1120                 :            :                 aFormula.append(
    1121                 :            :                     m_apNumberFormatterWrapper->getFormattedString(
    1122 [ #  # ][ #  # ]:          0 :                         nNumberFormatKey, fR*fR, nLabelCol, bColChanged ));
    1123                 :            :                 //@todo: change color of label if bColChanged is true
    1124                 :            :             }
    1125                 :            :             else
    1126                 :            :             {
    1127                 :          0 :                 sal_Unicode aDecimalSep( '.' );//@todo get this locale dependent
    1128                 :            :                 aFormula.append( ::rtl::math::doubleToUString(
    1129         [ #  # ]:          0 :                                      fR*fR, rtl_math_StringFormat_G, 4, aDecimalSep, true ));
    1130                 :            :             }
    1131                 :            :         }
    1132                 :            : 
    1133                 :          0 :         awt::Point aScreenPosition2D;
    1134                 :          0 :         chart2::RelativePosition aRelativePosition;
    1135 [ #  # ][ #  # ]:          0 :         if( xEquationProperties->getPropertyValue( C2U("RelativePosition")) >>= aRelativePosition )
         [ #  # ][ #  # ]
                 [ #  # ]
    1136                 :            :         {
    1137                 :            :             //@todo decide whether x is primary or secondary
    1138                 :          0 :             double fX = aRelativePosition.Primary*m_aPageReferenceSize.Width;
    1139                 :          0 :             double fY = aRelativePosition.Secondary*m_aPageReferenceSize.Height;
    1140                 :          0 :             aScreenPosition2D.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
    1141                 :          0 :             aScreenPosition2D.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
    1142                 :            :         }
    1143                 :            :         else
    1144                 :          0 :             aScreenPosition2D = aDefaultPos;
    1145                 :            : 
    1146         [ #  # ]:          0 :         if( aFormula.getLength())
    1147                 :            :         {
    1148                 :            :             // set fill and line properties on creation
    1149         [ #  # ]:          0 :             tNameSequence aNames;
    1150         [ #  # ]:          0 :             tAnySequence  aValues;
    1151         [ #  # ]:          0 :             PropertyMapper::getPreparedTextShapePropertyLists( xEquationProperties, aNames, aValues );
    1152                 :            : 
    1153                 :            :             uno::Reference< drawing::XShape > xTextShape = m_pShapeFactory->createText(
    1154                 :            :                 xEquationTarget, aFormula.makeStringAndClear(),
    1155 [ #  # ][ #  # ]:          0 :                 aNames, aValues, ShapeFactory::makeTransformation( aScreenPosition2D ));
                 [ #  # ]
    1156                 :            : 
    1157                 :            :             OSL_ASSERT( xTextShape.is());
    1158         [ #  # ]:          0 :             if( xTextShape.is())
    1159                 :            :             {
    1160         [ #  # ]:          0 :                 ShapeFactory::setShapeName( xTextShape, rEquationCID );
    1161 [ #  # ][ #  # ]:          0 :                 awt::Size aSize( xTextShape->getSize() );
    1162                 :            :                 awt::Point aPos( RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
    1163         [ #  # ]:          0 :                     aScreenPosition2D, aSize, aRelativePosition.Anchor ) );
    1164                 :            :                 //ensure that the equation is fully placed within the page (if possible)
    1165         [ #  # ]:          0 :                 if( (aPos.X + aSize.Width) > m_aPageReferenceSize.Width )
    1166                 :          0 :                     aPos.X = m_aPageReferenceSize.Width - aSize.Width;
    1167         [ #  # ]:          0 :                 if( aPos.X < 0 )
    1168                 :          0 :                     aPos.X = 0;
    1169         [ #  # ]:          0 :                 if( (aPos.Y + aSize.Height) > m_aPageReferenceSize.Height )
    1170                 :          0 :                     aPos.Y = m_aPageReferenceSize.Height - aSize.Height;
    1171         [ #  # ]:          0 :                 if( aPos.Y < 0 )
    1172                 :          0 :                     aPos.Y = 0;
    1173 [ #  # ][ #  # ]:          0 :                 xTextShape->setPosition(aPos);
    1174 [ #  # ][ #  # ]:          0 :             }
    1175                 :        108 :         }
    1176         [ -  + ]:        108 :     }
    1177                 :            : }
    1178                 :            : 
    1179                 :            : 
    1180                 :      11933 : void VSeriesPlotter::setMappedProperties(
    1181                 :            :           const uno::Reference< drawing::XShape >& xTargetShape
    1182                 :            :         , const uno::Reference< beans::XPropertySet >& xSource
    1183                 :            :         , const tPropertyNameMap& rMap
    1184                 :            :         , tPropertyNameValueMap* pOverwriteMap )
    1185                 :            : {
    1186         [ +  - ]:      11933 :     uno::Reference< beans::XPropertySet > xTargetProp( xTargetShape, uno::UNO_QUERY );
    1187         [ +  - ]:      11933 :     PropertyMapper::setMappedProperties(xTargetProp,xSource,rMap,pOverwriteMap);
    1188                 :      11933 : }
    1189                 :            : 
    1190                 :          0 : void VSeriesPlotter::setTimeResolutionOnXAxis( long TimeResolution, const Date& rNullDate )
    1191                 :            : {
    1192                 :          0 :     m_nTimeResolution = TimeResolution;
    1193                 :          0 :     m_aNullDate = rNullDate;
    1194                 :          0 : }
    1195                 :            : 
    1196                 :            : //-------------------------------------------------------------------------
    1197                 :            : // MinimumAndMaximumSupplier
    1198                 :            : //-------------------------------------------------------------------------
    1199                 :          0 : long VSeriesPlotter::calculateTimeResolutionOnXAxis()
    1200                 :            : {
    1201                 :          0 :     long nRet = ::com::sun::star::chart::TimeUnit::YEAR;
    1202         [ #  # ]:          0 :     if( m_pExplicitCategoriesProvider )
    1203                 :            :     {
    1204         [ #  # ]:          0 :         const std::vector< DatePlusIndex >&  rDateCategories = m_pExplicitCategoriesProvider->getDateCategories();
    1205                 :          0 :         std::vector< DatePlusIndex >::const_iterator aIt = rDateCategories.begin(), aEnd = rDateCategories.end();
    1206                 :          0 :         Date aNullDate(30,12,1899);
    1207         [ #  # ]:          0 :         if( m_apNumberFormatterWrapper.get() )
    1208         [ #  # ]:          0 :             aNullDate = m_apNumberFormatterWrapper->getNullDate();
    1209 [ #  # ][ #  # ]:          0 :         if( aIt!=aEnd )
    1210                 :            :         {
    1211         [ #  # ]:          0 :             Date aPrevious(aNullDate); aPrevious+=static_cast<long>(rtl::math::approxFloor(aIt->fValue));
    1212                 :          0 :             ++aIt;
    1213 [ #  # ][ #  # ]:          0 :             for(;aIt!=aEnd;++aIt)
    1214                 :            :             {
    1215         [ #  # ]:          0 :                 Date aCurrent(aNullDate); aCurrent+=static_cast<long>(rtl::math::approxFloor(aIt->fValue));
    1216         [ #  # ]:          0 :                 if( ::com::sun::star::chart::TimeUnit::YEAR == nRet )
    1217                 :            :                 {
    1218 [ #  # ][ #  # ]:          0 :                     if( DateHelper::IsInSameYear( aPrevious, aCurrent ) )
    1219                 :          0 :                         nRet = ::com::sun::star::chart::TimeUnit::MONTH;
    1220                 :            :                 }
    1221         [ #  # ]:          0 :                 if( ::com::sun::star::chart::TimeUnit::MONTH == nRet )
    1222                 :            :                 {
    1223 [ #  # ][ #  # ]:          0 :                     if( DateHelper::IsInSameMonth( aPrevious, aCurrent ) )
    1224                 :          0 :                         nRet = ::com::sun::star::chart::TimeUnit::DAY;
    1225                 :            :                 }
    1226         [ #  # ]:          0 :                 if( ::com::sun::star::chart::TimeUnit::DAY == nRet )
    1227                 :            :                     break;
    1228                 :          0 :                 aPrevious=aCurrent;
    1229                 :            :             }
    1230                 :            :         }
    1231                 :            :     }
    1232                 :          0 :     return nRet;
    1233                 :            : }
    1234                 :       1938 : double VSeriesPlotter::getMinimumX()
    1235                 :            : {
    1236                 :            :     double fMinimum, fMaximum;
    1237         [ +  - ]:       1938 :     this->getMinimumAndMaximiumX( fMinimum, fMaximum );
    1238                 :       1938 :     return fMinimum;
    1239                 :            : }
    1240                 :       1938 : double VSeriesPlotter::getMaximumX()
    1241                 :            : {
    1242                 :            :     double fMinimum, fMaximum;
    1243         [ +  - ]:       1938 :     this->getMinimumAndMaximiumX( fMinimum, fMaximum );
    1244                 :       1938 :     return fMaximum;
    1245                 :            : }
    1246                 :            : 
    1247                 :       1952 : double VSeriesPlotter::getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
    1248                 :            : {
    1249 [ +  - ][ +  - ]:       1952 :     if( !m_bCategoryXAxis || ( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() ) )
         [ +  - ][ -  + ]
                 [ -  + ]
    1250                 :            :     {
    1251                 :            :         double fMinY, fMaxY;
    1252         [ #  # ]:          0 :         this->getMinimumAndMaximiumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex );
    1253                 :          0 :         return fMinY;
    1254                 :            :     }
    1255                 :            : 
    1256                 :            :     double fMinimum, fMaximum;
    1257                 :       1952 :     ::rtl::math::setInf(&fMinimum, false);
    1258                 :       1952 :     ::rtl::math::setInf(&fMaximum, true);
    1259         [ +  + ]:       3996 :     for(size_t nZ =0; nZ<m_aZSlots.size();nZ++ )
    1260                 :            :     {
    1261                 :       2044 :         ::std::vector< VDataSeriesGroup >& rXSlots = m_aZSlots[nZ];
    1262         [ +  + ]:       8402 :         for(size_t nN =0; nN<rXSlots.size();nN++ )
    1263                 :            :         {
    1264                 :            :             double fLocalMinimum, fLocalMaximum;
    1265                 :       6358 :             rXSlots[nN].calculateYMinAndMaxForCategoryRange(
    1266                 :            :                                 static_cast<sal_Int32>(fMinimumX-1.0) //first category (index 0) matches with real number 1.0
    1267                 :            :                                 , static_cast<sal_Int32>(fMaximumX-1.0) //first category (index 0) matches with real number 1.0
    1268         [ +  - ]:       6358 :                                 , isSeperateStackingForDifferentSigns( 1 )
    1269         [ +  - ]:       6358 :                                 , fLocalMinimum, fLocalMaximum, nAxisIndex );
    1270         [ +  + ]:       6358 :             if(fMaximum<fLocalMaximum)
    1271                 :       3974 :                 fMaximum=fLocalMaximum;
    1272         [ +  + ]:       6358 :             if(fMinimum>fLocalMinimum)
    1273                 :       3956 :                 fMinimum=fLocalMinimum;
    1274                 :            :         }
    1275                 :            :     }
    1276         [ +  + ]:       1952 :     if(::rtl::math::isInf(fMinimum))
    1277                 :         14 :         ::rtl::math::setNan(&fMinimum);
    1278                 :       1952 :     return fMinimum;
    1279                 :            : }
    1280                 :            : 
    1281                 :       1952 : double VSeriesPlotter::getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
    1282                 :            : {
    1283 [ +  - ][ +  - ]:       1952 :     if( !m_bCategoryXAxis || ( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() ) )
         [ +  - ][ -  + ]
                 [ -  + ]
    1284                 :            :     {
    1285                 :            :         double fMinY, fMaxY;
    1286         [ #  # ]:          0 :         this->getMinimumAndMaximiumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex );
    1287                 :          0 :         return fMaxY;
    1288                 :            :     }
    1289                 :            : 
    1290                 :            :     double fMinimum, fMaximum;
    1291                 :       1952 :     ::rtl::math::setInf(&fMinimum, false);
    1292                 :       1952 :     ::rtl::math::setInf(&fMaximum, true);
    1293         [ +  + ]:       3996 :     for(size_t nZ =0; nZ<m_aZSlots.size();nZ++ )
    1294                 :            :     {
    1295                 :       2044 :         ::std::vector< VDataSeriesGroup >& rXSlots = m_aZSlots[nZ];
    1296         [ +  + ]:       8402 :         for(size_t nN =0; nN<rXSlots.size();nN++ )
    1297                 :            :         {
    1298                 :            :             double fLocalMinimum, fLocalMaximum;
    1299                 :       6358 :             rXSlots[nN].calculateYMinAndMaxForCategoryRange(
    1300                 :            :                                 static_cast<sal_Int32>(fMinimumX-1.0) //first category (index 0) matches with real number 1.0
    1301                 :            :                                 , static_cast<sal_Int32>(fMaximumX-1.0) //first category (index 0) matches with real number 1.0
    1302         [ +  - ]:       6358 :                                 , isSeperateStackingForDifferentSigns( 1 )
    1303         [ +  - ]:       6358 :                                 , fLocalMinimum, fLocalMaximum, nAxisIndex );
    1304         [ +  + ]:       6358 :             if(fMaximum<fLocalMaximum)
    1305                 :       3974 :                 fMaximum=fLocalMaximum;
    1306         [ +  + ]:       6358 :             if(fMinimum>fLocalMinimum)
    1307                 :       3956 :                 fMinimum=fLocalMinimum;
    1308                 :            :         }
    1309                 :            :     }
    1310         [ +  + ]:       1952 :     if(::rtl::math::isInf(fMaximum))
    1311                 :         14 :         ::rtl::math::setNan(&fMaximum);
    1312                 :       1952 :     return fMaximum;
    1313                 :            : }
    1314                 :            : 
    1315                 :         28 : double VSeriesPlotter::getMinimumZ()
    1316                 :            : {
    1317                 :            :     //this is the default for all charts without a meaningfull z axis
    1318                 :         28 :     return 1.0;
    1319                 :            : }
    1320                 :         28 : double VSeriesPlotter::getMaximumZ()
    1321                 :            : {
    1322 [ +  - ][ -  + ]:         28 :     if( 3!=m_nDimension || !m_aZSlots.size() )
                 [ -  + ]
    1323                 :          0 :         return getMinimumZ()+1;
    1324                 :         28 :     return m_aZSlots.size();
    1325                 :            : }
    1326                 :            : 
    1327                 :            : namespace
    1328                 :            : {
    1329                 :       7710 :     bool lcl_isValueAxis( sal_Int32 nDimensionIndex, bool bCategoryXAxis )
    1330                 :            :     {
    1331                 :            :         // default implementation: true for Y axes, and for value X axis
    1332         [ +  + ]:       7710 :         if( nDimensionIndex == 0 )
    1333                 :       3834 :             return !bCategoryXAxis;
    1334         [ +  + ]:       3876 :         if( nDimensionIndex == 1 )
    1335                 :       3848 :             return true;
    1336                 :       7710 :         return false;
    1337                 :            :     }
    1338                 :            : }
    1339                 :            : 
    1340                 :       3918 : bool VSeriesPlotter::isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex )
    1341                 :            : {
    1342                 :       3918 :     return lcl_isValueAxis( nDimensionIndex, m_bCategoryXAxis );
    1343                 :            : }
    1344                 :            : 
    1345                 :       3918 : bool VSeriesPlotter::isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex )
    1346                 :            : {
    1347                 :            :     // do not expand axes in 3D charts
    1348 [ +  + ][ +  + ]:       3918 :     return (m_nDimension < 3) && lcl_isValueAxis( nDimensionIndex, m_bCategoryXAxis );
    1349                 :            : }
    1350                 :            : 
    1351                 :       3918 : bool VSeriesPlotter::isExpandWideValuesToZero( sal_Int32 nDimensionIndex )
    1352                 :            : {
    1353                 :            :     // default implementation: only for Y axis
    1354                 :       3918 :     return nDimensionIndex == 1;
    1355                 :            : }
    1356                 :            : 
    1357                 :       3918 : bool VSeriesPlotter::isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex )
    1358                 :            : {
    1359                 :            :     // default implementation: only for Y axis
    1360                 :       3918 :     return nDimensionIndex == 1;
    1361                 :            : }
    1362                 :            : 
    1363                 :      33542 : bool VSeriesPlotter::isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex )
    1364                 :            : {
    1365                 :            :     // default implementation: only for Y axis
    1366                 :      33542 :     return nDimensionIndex == 1;
    1367                 :            : }
    1368                 :            : 
    1369                 :       3876 : void VSeriesPlotter::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const
    1370                 :            : {
    1371                 :       3876 :     ::rtl::math::setInf(&rfMinimum, false);
    1372                 :       3876 :     ::rtl::math::setInf(&rfMaximum, true);
    1373                 :            : 
    1374                 :       3876 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator       aZSlotIter = m_aZSlots.begin();
    1375                 :       3876 :     const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator  aZSlotEnd = m_aZSlots.end();
    1376 [ +  - ][ +  + ]:       7880 :     for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
    1377                 :            :     {
    1378                 :       4004 :         ::std::vector< VDataSeriesGroup >::const_iterator      aXSlotIter = aZSlotIter->begin();
    1379                 :       4004 :         const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
    1380 [ +  - ][ +  + ]:      16636 :         for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
    1381                 :            :         {
    1382                 :            :             double fLocalMinimum, fLocalMaximum;
    1383         [ +  - ]:      12632 :             aXSlotIter->getMinimumAndMaximiumX( fLocalMinimum, fLocalMaximum );
    1384 [ +  - ][ +  + ]:      12632 :             if( !::rtl::math::isNan(fLocalMinimum) && fLocalMinimum< rfMinimum )
                 [ +  + ]
    1385                 :       3876 :                 rfMinimum = fLocalMinimum;
    1386 [ +  - ][ +  + ]:      12632 :             if( !::rtl::math::isNan(fLocalMaximum) && fLocalMaximum> rfMaximum )
                 [ +  + ]
    1387                 :       3876 :                 rfMaximum = fLocalMaximum;
    1388                 :            :         }
    1389                 :            :     }
    1390         [ -  + ]:       3876 :     if(::rtl::math::isInf(rfMinimum))
    1391                 :          0 :         ::rtl::math::setNan(&rfMinimum);
    1392         [ -  + ]:       3876 :     if(::rtl::math::isInf(rfMaximum))
    1393                 :          0 :         ::rtl::math::setNan(&rfMaximum);
    1394                 :       3876 : }
    1395                 :            : 
    1396                 :          0 : void VSeriesPlotter::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const
    1397                 :            : {
    1398                 :          0 :     ::rtl::math::setInf(&rfMinY, false);
    1399                 :          0 :     ::rtl::math::setInf(&rfMaxY, true);
    1400                 :            : 
    1401                 :          0 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator       aZSlotIter = m_aZSlots.begin();
    1402                 :          0 :     const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator  aZSlotEnd = m_aZSlots.end();
    1403 [ #  # ][ #  # ]:          0 :     for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
    1404                 :            :     {
    1405                 :          0 :         ::std::vector< VDataSeriesGroup >::const_iterator      aXSlotIter = aZSlotIter->begin();
    1406                 :          0 :         const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
    1407 [ #  # ][ #  # ]:          0 :         for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
    1408                 :            :         {
    1409                 :            :             double fLocalMinimum, fLocalMaximum;
    1410         [ #  # ]:          0 :             aXSlotIter->getMinimumAndMaximiumYInContinuousXRange( fLocalMinimum, fLocalMaximum, fMinX, fMaxX, nAxisIndex );
    1411 [ #  # ][ #  # ]:          0 :             if( !::rtl::math::isNan(fLocalMinimum) && fLocalMinimum< rfMinY )
                 [ #  # ]
    1412                 :          0 :                 rfMinY = fLocalMinimum;
    1413 [ #  # ][ #  # ]:          0 :             if( !::rtl::math::isNan(fLocalMaximum) && fLocalMaximum> rfMaxY )
                 [ #  # ]
    1414                 :          0 :                 rfMaxY = fLocalMaximum;
    1415                 :            :         }
    1416                 :            :     }
    1417         [ #  # ]:          0 :     if(::rtl::math::isInf(rfMinY))
    1418                 :          0 :         ::rtl::math::setNan(&rfMinY);
    1419         [ #  # ]:          0 :     if(::rtl::math::isInf(rfMaxY))
    1420                 :          0 :         ::rtl::math::setNan(&rfMaxY);
    1421                 :          0 : }
    1422                 :            : 
    1423                 :        962 : sal_Int32 VSeriesPlotter::getPointCount() const
    1424                 :            : {
    1425                 :        962 :     sal_Int32 nRet = 0;
    1426                 :            : 
    1427                 :        962 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator       aZSlotIter = m_aZSlots.begin();
    1428                 :        962 :     const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
    1429                 :            : 
    1430 [ +  - ][ +  + ]:       1942 :     for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
    1431                 :            :     {
    1432                 :        980 :         ::std::vector< VDataSeriesGroup >::const_iterator       aXSlotIter = aZSlotIter->begin();
    1433                 :        980 :         const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
    1434                 :            : 
    1435 [ +  - ][ +  + ]:       4117 :         for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
    1436                 :            :         {
    1437         [ +  - ]:       3137 :             sal_Int32 nPointCount = aXSlotIter->getPointCount();
    1438         [ +  + ]:       3137 :             if( nPointCount>nRet )
    1439                 :        962 :                 nRet = nPointCount;
    1440                 :            :         }
    1441                 :            :     }
    1442                 :        962 :     return nRet;
    1443                 :            : }
    1444                 :            : 
    1445                 :        981 : void VSeriesPlotter::setNumberFormatsSupplier(
    1446                 :            :     const uno::Reference< util::XNumberFormatsSupplier > & xNumFmtSupplier )
    1447                 :            : {
    1448         [ +  - ]:        981 :     m_apNumberFormatterWrapper.reset( new NumberFormatterWrapper( xNumFmtSupplier ));
    1449                 :        981 : }
    1450                 :            : 
    1451                 :        981 : void VSeriesPlotter::setColorScheme( const uno::Reference< XColorScheme >& xColorScheme )
    1452                 :            : {
    1453                 :        981 :     m_xColorScheme = xColorScheme;
    1454                 :        981 : }
    1455                 :            : 
    1456                 :        981 : void VSeriesPlotter::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider )
    1457                 :            : {
    1458                 :        981 :     m_pExplicitCategoriesProvider = pExplicitCategoriesProvider;
    1459                 :        981 : }
    1460                 :            : 
    1461                 :      93131 : sal_Int32 VDataSeriesGroup::getPointCount() const
    1462                 :            : {
    1463         [ +  + ]:      93131 :     if(!m_bMaxPointCountDirty)
    1464                 :      89994 :         return m_nMaxPointCount;
    1465                 :            : 
    1466                 :       3137 :     sal_Int32 nRet = 0;
    1467                 :       3137 :     ::std::vector< VDataSeries* >::const_iterator       aSeriesIter = m_aSeriesVector.begin();
    1468                 :       3137 :     const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = m_aSeriesVector.end();
    1469                 :            : 
    1470 [ +  - ][ +  + ]:       6286 :     for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter)
    1471                 :            :     {
    1472         [ +  - ]:       3149 :         sal_Int32 nPointCount = (*aSeriesIter)->getTotalPointCount();
    1473         [ +  + ]:       3149 :         if( nPointCount>nRet )
    1474                 :       3137 :             nRet = nPointCount;
    1475                 :            :     }
    1476                 :       3137 :     m_nMaxPointCount=nRet;
    1477                 :       3137 :     m_aListOfCachedYValues.clear();
    1478         [ +  - ]:       3137 :     m_aListOfCachedYValues.resize(m_nMaxPointCount);
    1479                 :       3137 :     m_bMaxPointCountDirty=false;
    1480                 :      93131 :     return nRet;
    1481                 :            : }
    1482                 :            : 
    1483                 :      22222 : sal_Int32 VDataSeriesGroup::getAttachedAxisIndexForFirstSeries() const
    1484                 :            : {
    1485                 :      22222 :     sal_Int32 nRet = 0;
    1486                 :      22222 :     ::std::vector< VDataSeries* >::const_iterator       aSeriesIter = m_aSeriesVector.begin();
    1487                 :      22222 :     const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = m_aSeriesVector.end();
    1488                 :            : 
    1489 [ +  - ][ +  - ]:      22222 :     if( aSeriesIter != aSeriesEnd )
    1490         [ +  - ]:      22222 :         nRet = (*aSeriesIter)->getAttachedAxisIndex();
    1491                 :            : 
    1492                 :      22222 :     return nRet;
    1493                 :            : }
    1494                 :            : 
    1495                 :      12632 : void VDataSeriesGroup::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const
    1496                 :            : {
    1497                 :      12632 :     const ::std::vector< VDataSeries* >* pSeriesList = &this->m_aSeriesVector;
    1498                 :            : 
    1499                 :      12632 :     ::std::vector< VDataSeries* >::const_iterator       aSeriesIter = pSeriesList->begin();
    1500                 :      12632 :     const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd  = pSeriesList->end();
    1501                 :            : 
    1502                 :      12632 :     ::rtl::math::setInf(&rfMinimum, false);
    1503                 :      12632 :     ::rtl::math::setInf(&rfMaximum, true);
    1504                 :            : 
    1505 [ +  - ][ +  + ]:      25312 :     for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
    1506                 :            :     {
    1507         [ +  - ]:      12680 :         sal_Int32 nPointCount = (*aSeriesIter)->getTotalPointCount();
    1508         [ +  + ]:      68584 :         for(sal_Int32 nN=0;nN<nPointCount;nN++)
    1509                 :            :         {
    1510         [ +  - ]:      55904 :             double fX = (*aSeriesIter)->getXValue( nN );
    1511         [ -  + ]:      55904 :             if( ::rtl::math::isNan(fX) )
    1512                 :          0 :                 continue;
    1513         [ +  + ]:      55904 :             if(rfMaximum<fX)
    1514                 :      55280 :                 rfMaximum=fX;
    1515         [ +  + ]:      55904 :             if(rfMinimum>fX)
    1516                 :      12632 :                 rfMinimum=fX;
    1517                 :            :         }
    1518                 :            :     }
    1519         [ -  + ]:      12632 :     if(::rtl::math::isInf(rfMinimum))
    1520                 :          0 :         ::rtl::math::setNan(&rfMinimum);
    1521         [ -  + ]:      12632 :     if(::rtl::math::isInf(rfMaximum))
    1522                 :          0 :         ::rtl::math::setNan(&rfMaximum);
    1523                 :      12632 : }
    1524                 :            : 
    1525                 :            : namespace {
    1526                 :            : 
    1527                 :            : /**
    1528                 :            :  * Keep track of minimum and maximum Y values for one or more data series.
    1529                 :            :  * When multiple data series exist, that indicates that the data series are
    1530                 :            :  * stacked.
    1531                 :            :  *
    1532                 :            :  * <p>For each X value, we calculate separate Y value ranges for each data
    1533                 :            :  * series in the first pass.  In the second pass, we calculate the minimum Y
    1534                 :            :  * value by taking the absolute minimum value of all data series, whereas
    1535                 :            :  * the maxium Y value is the sum of all the series maximum Y values.</p>
    1536                 :            :  *
    1537                 :            :  * <p>Once that's done for all X values, the final min / max Y values get
    1538                 :            :  * calculated by taking the absolute min / max Y values across all the X
    1539                 :            :  * values.</p>
    1540                 :            :  */
    1541                 :          0 : class PerXMinMaxCalculator
    1542                 :            : {
    1543                 :            :     typedef std::pair<double, double> MinMaxType;
    1544                 :            :     typedef std::map<size_t, MinMaxType> SeriesMinMaxType;
    1545                 :            :     typedef boost::ptr_map<double, SeriesMinMaxType> GroupMinMaxType;
    1546                 :            :     typedef boost::unordered_map<double, MinMaxType> TotalStoreType;
    1547                 :            :     GroupMinMaxType maSeriesGroup;
    1548                 :            :     size_t mnCurSeries;
    1549                 :            : 
    1550                 :            : public:
    1551                 :          0 :     PerXMinMaxCalculator() : mnCurSeries(0) {}
    1552                 :            : 
    1553                 :          0 :     void nextSeries() { ++mnCurSeries; }
    1554                 :            : 
    1555                 :          0 :     void setValue(double fX, double fY)
    1556                 :            :     {
    1557         [ #  # ]:          0 :         SeriesMinMaxType* pStore = getByXValue(fX); // get storage for given X value.
    1558         [ #  # ]:          0 :         if (!pStore)
    1559                 :            :             // This shouldn't happen!
    1560                 :          0 :             return;
    1561                 :            : 
    1562         [ #  # ]:          0 :         SeriesMinMaxType::iterator it = pStore->lower_bound(mnCurSeries);
    1563 [ #  # ][ #  # ]:          0 :         if (it != pStore->end() && !pStore->key_comp()(mnCurSeries, it->first))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  #  
                   #  # ]
    1564                 :            :         {
    1565         [ #  # ]:          0 :             MinMaxType& r = it->second;
    1566                 :            :             // A min-max pair already exists for this series.  Update it.
    1567         [ #  # ]:          0 :             if (fY < r.first)
    1568                 :          0 :                 r.first = fY;
    1569         [ #  # ]:          0 :             if (r.second < fY)
    1570                 :          0 :                 r.second = fY;
    1571                 :            :         }
    1572                 :            :         else
    1573                 :            :         {
    1574                 :            :             // No existing pair. Insert a new one.
    1575                 :            :             pStore->insert(
    1576                 :            :                 it, SeriesMinMaxType::value_type(
    1577 [ #  # ][ #  # ]:          0 :                     mnCurSeries, MinMaxType(fY,fY)));
         [ #  # ][ #  # ]
    1578                 :            :         }
    1579                 :            :     }
    1580                 :            : 
    1581                 :          0 :     void getTotalRange(double& rfMin, double& rfMax) const
    1582                 :            :     {
    1583                 :          0 :         rtl::math::setNan(&rfMin);
    1584                 :          0 :         rtl::math::setNan(&rfMax);
    1585                 :            : 
    1586         [ #  # ]:          0 :         TotalStoreType aStore;
    1587         [ #  # ]:          0 :         getTotalStore(aStore);
    1588                 :            : 
    1589         [ #  # ]:          0 :         if (aStore.empty())
    1590                 :          0 :             return;
    1591                 :            : 
    1592 [ #  # ][ #  # ]:          0 :         TotalStoreType::const_iterator it = aStore.begin(), itEnd = aStore.end();
    1593         [ #  # ]:          0 :         rfMin = it->second.first;
    1594         [ #  # ]:          0 :         rfMax = it->second.second;
    1595         [ #  # ]:          0 :         for (++it; it != itEnd; ++it)
    1596                 :            :         {
    1597 [ #  # ][ #  # ]:          0 :             if (rfMin > it->second.first)
    1598         [ #  # ]:          0 :                 rfMin = it->second.first;
    1599 [ #  # ][ #  # ]:          0 :             if (rfMax < it->second.second)
    1600         [ #  # ]:          0 :                 rfMax = it->second.second;
    1601 [ #  # ][ #  # ]:          0 :         }
    1602                 :            :     }
    1603                 :            : 
    1604                 :            : private:
    1605                 :            :     /**
    1606                 :            :      * Parse all data and reduce them into a set of global Y value ranges per
    1607                 :            :      * X value.
    1608                 :            :      */
    1609                 :          0 :     void getTotalStore(TotalStoreType& rStore) const
    1610                 :            :     {
    1611         [ #  # ]:          0 :         TotalStoreType aStore;
    1612 [ #  # ][ #  # ]:          0 :         GroupMinMaxType::const_iterator it = maSeriesGroup.begin(), itEnd = maSeriesGroup.end();
    1613 [ #  # ][ #  # ]:          0 :         for (; it != itEnd; ++it)
                 [ #  # ]
    1614                 :            :         {
    1615         [ #  # ]:          0 :             double fX = it->first;
    1616                 :            : 
    1617         [ #  # ]:          0 :             const SeriesMinMaxType& rSeries = *it->second;
    1618                 :          0 :             SeriesMinMaxType::const_iterator itSeries = rSeries.begin(), itSeriesEnd = rSeries.end();
    1619 [ #  # ][ #  # ]:          0 :             for (; itSeries != itSeriesEnd; ++itSeries)
                 [ #  # ]
    1620                 :            :             {
    1621 [ #  # ][ #  # ]:          0 :                 double fYMin = itSeries->second.first, fYMax = itSeries->second.second;
    1622         [ #  # ]:          0 :                 TotalStoreType::iterator itr = aStore.find(fX);
    1623 [ #  # ][ #  # ]:          0 :                 if (itr == aStore.end())
    1624                 :            :                     // New min-max pair for give X value.
    1625                 :            :                     aStore.insert(
    1626 [ #  # ][ #  # ]:          0 :                         TotalStoreType::value_type(fX, std::pair<double,double>(fYMin,fYMax)));
                 [ #  # ]
    1627                 :            :                 else
    1628                 :            :                 {
    1629         [ #  # ]:          0 :                     MinMaxType& r = itr->second;
    1630         [ #  # ]:          0 :                     if (fYMin < r.first)
    1631                 :          0 :                         r.first = fYMin; // min y-value
    1632                 :            : 
    1633                 :          0 :                     r.second += fYMax; // accumulative max y-value.
    1634                 :            :                 }
    1635                 :            :             }
    1636                 :            :         }
    1637 [ #  # ][ #  # ]:          0 :         rStore.swap(aStore);
    1638                 :          0 :     }
    1639                 :            : 
    1640                 :          0 :     SeriesMinMaxType* getByXValue(double fX)
    1641                 :            :     {
    1642         [ #  # ]:          0 :         GroupMinMaxType::iterator it = maSeriesGroup.find(fX);
    1643 [ #  # ][ #  # ]:          0 :         if (it == maSeriesGroup.end())
                 [ #  # ]
    1644                 :            :         {
    1645                 :            :             std::pair<GroupMinMaxType::iterator,bool> r =
    1646 [ #  # ][ #  # ]:          0 :                 maSeriesGroup.insert(fX, new SeriesMinMaxType);
                 [ #  # ]
    1647                 :            : 
    1648         [ #  # ]:          0 :             if (!r.second)
    1649                 :            :                 // insertion failed.
    1650                 :          0 :                 return NULL;
    1651                 :            : 
    1652                 :          0 :             it = r.first;
    1653                 :            :         }
    1654                 :            : 
    1655         [ #  # ]:          0 :         return it->second;
    1656                 :            :     }
    1657                 :            : };
    1658                 :            : 
    1659                 :            : }
    1660                 :            : 
    1661                 :          0 : void VDataSeriesGroup::getMinimumAndMaximiumYInContinuousXRange(
    1662                 :            :     double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const
    1663                 :            : {
    1664                 :          0 :     ::rtl::math::setNan(&rfMinY);
    1665                 :          0 :     ::rtl::math::setNan(&rfMaxY);
    1666                 :            : 
    1667         [ #  # ]:          0 :     if (m_aSeriesVector.empty())
    1668                 :            :         // No data series.  Bail out.
    1669                 :          0 :         return;
    1670                 :            : 
    1671         [ #  # ]:          0 :     PerXMinMaxCalculator aRangeCalc;
    1672                 :          0 :     std::vector<VDataSeries*>::const_iterator it = m_aSeriesVector.begin(), itEnd = m_aSeriesVector.end();
    1673 [ #  # ][ #  # ]:          0 :     for (; it != itEnd; ++it)
    1674                 :            :     {
    1675                 :          0 :         const VDataSeries* pSeries = *it;
    1676         [ #  # ]:          0 :         if (!pSeries)
    1677                 :          0 :             continue;
    1678                 :            : 
    1679 [ #  # ][ #  # ]:          0 :         for (sal_Int32 i = 0, n = pSeries->getTotalPointCount(); i < n; ++i)
    1680                 :            :         {
    1681 [ #  # ][ #  # ]:          0 :             if (nAxisIndex != pSeries->getAttachedAxisIndex())
    1682                 :          0 :                 continue;
    1683                 :            : 
    1684         [ #  # ]:          0 :             double fX = pSeries->getXValue(i);
    1685         [ #  # ]:          0 :             if (rtl::math::isNan(fX))
    1686                 :          0 :                 continue;
    1687                 :            : 
    1688 [ #  # ][ #  # ]:          0 :             if (fX < fMinX || fX > fMaxX)
    1689                 :            :                 // Outside specified X range.  Skip it.
    1690                 :          0 :                 continue;
    1691                 :            : 
    1692         [ #  # ]:          0 :             double fY = pSeries->getYValue(i);
    1693         [ #  # ]:          0 :             if (::rtl::math::isNan(fY))
    1694                 :          0 :                 continue;
    1695                 :            : 
    1696         [ #  # ]:          0 :             aRangeCalc.setValue(fX, fY);
    1697                 :            :         }
    1698                 :          0 :         aRangeCalc.nextSeries();
    1699                 :            :     }
    1700                 :            : 
    1701 [ #  # ][ #  # ]:          0 :     aRangeCalc.getTotalRange(rfMinY, rfMaxY);
    1702                 :            : }
    1703                 :            : 
    1704                 :      89994 : void VDataSeriesGroup::calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex
    1705                 :            :         , bool bSeperateStackingForDifferentSigns
    1706                 :            :         , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex )
    1707                 :            : {
    1708                 :      89994 :     ::rtl::math::setInf(&rfMinimumY, false);
    1709                 :      89994 :     ::rtl::math::setInf(&rfMaximumY, true);
    1710                 :            : 
    1711         [ +  - ]:      89994 :     sal_Int32 nPointCount = getPointCount();//necessary to create m_aListOfCachedYValues
    1712 [ +  - ][ +  + ]:      89994 :     if(nCategoryIndex<0 || nCategoryIndex>=nPointCount || m_aSeriesVector.empty())
         [ -  + ][ +  + ]
    1713                 :            :         return;
    1714                 :            : 
    1715         [ +  - ]:      78582 :     CachedYValues aCachedYValues = m_aListOfCachedYValues[nCategoryIndex][nAxisIndex];
    1716         [ +  + ]:      78582 :     if( !aCachedYValues.m_bValuesDirty )
    1717                 :            :     {
    1718                 :            :         //return cached values
    1719                 :      64762 :         rfMinimumY = aCachedYValues.m_fMinimumY;
    1720                 :      64762 :         rfMaximumY = aCachedYValues.m_fMaximumY;
    1721                 :            :         return;
    1722                 :            :     }
    1723                 :            : 
    1724                 :            :     double fTotalSum, fPositiveSum, fNegativeSum, fFirstPositiveY, fFirstNegativeY;
    1725                 :      13820 :     ::rtl::math::setNan( &fTotalSum );
    1726                 :      13820 :     ::rtl::math::setNan( &fPositiveSum );
    1727                 :      13820 :     ::rtl::math::setNan( &fNegativeSum );
    1728                 :      13820 :     ::rtl::math::setNan( &fFirstPositiveY );
    1729                 :      13820 :     ::rtl::math::setNan( &fFirstNegativeY );
    1730                 :            : 
    1731         [ +  - ]:      13820 :     ::std::vector< VDataSeries* >::const_iterator aSeriesIter = m_aSeriesVector.begin();
    1732         [ +  - ]:      13820 :     ::std::vector< VDataSeries* >::const_iterator aSeriesEnd  = m_aSeriesVector.end();
    1733                 :            : 
    1734         [ +  + ]:      13820 :     if( bSeperateStackingForDifferentSigns )
    1735                 :            :     {
    1736 [ +  - ][ +  + ]:      22210 :         for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
    1737                 :            :         {
    1738 [ +  - ][ -  + ]:      11105 :             if( nAxisIndex != (*aSeriesIter)->getAttachedAxisIndex() )
    1739                 :          0 :                 continue;
    1740                 :            : 
    1741         [ +  - ]:      11105 :             double fValueMinY = (*aSeriesIter)->getMinimumofAllDifferentYValues( nCategoryIndex );
    1742         [ +  - ]:      11105 :             double fValueMaxY = (*aSeriesIter)->getMaximumofAllDifferentYValues( nCategoryIndex );
    1743                 :            : 
    1744         [ +  + ]:      11105 :             if( fValueMaxY >= 0 )
    1745                 :            :             {
    1746         [ +  - ]:      10899 :                 if( ::rtl::math::isNan( fPositiveSum ) )
    1747                 :      10899 :                     fPositiveSum = fFirstPositiveY = fValueMaxY;
    1748                 :            :                 else
    1749                 :          0 :                     fPositiveSum += fValueMaxY;
    1750                 :            :             }
    1751         [ +  + ]:      11105 :             if( fValueMinY < 0 )
    1752                 :            :             {
    1753         [ +  - ]:        190 :                 if(::rtl::math::isNan( fNegativeSum ))
    1754                 :        190 :                     fNegativeSum = fFirstNegativeY = fValueMinY;
    1755                 :            :                 else
    1756                 :          0 :                     fNegativeSum += fValueMinY;
    1757                 :            :             }
    1758                 :            :         }
    1759         [ +  + ]:      11105 :         rfMinimumY = ::rtl::math::isNan( fNegativeSum ) ? fFirstPositiveY : fNegativeSum;
    1760         [ +  + ]:      11105 :         rfMaximumY = ::rtl::math::isNan( fPositiveSum ) ? fFirstNegativeY : fPositiveSum;
    1761                 :            :     }
    1762                 :            :     else
    1763                 :            :     {
    1764 [ +  - ][ +  + ]:       5586 :         for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
    1765                 :            :         {
    1766 [ +  - ][ +  + ]:       2871 :             if( nAxisIndex != (*aSeriesIter)->getAttachedAxisIndex() )
    1767                 :        273 :                 continue;
    1768                 :            : 
    1769         [ +  - ]:       2598 :             double fValueMinY = (*aSeriesIter)->getMinimumofAllDifferentYValues( nCategoryIndex );
    1770         [ +  - ]:       2598 :             double fValueMaxY = (*aSeriesIter)->getMaximumofAllDifferentYValues( nCategoryIndex );
    1771                 :            : 
    1772         [ +  + ]:       2598 :             if( ::rtl::math::isNan( fTotalSum ) )
    1773                 :            :             {
    1774                 :       2442 :                 rfMinimumY = fValueMinY;
    1775                 :       2442 :                 rfMaximumY = fTotalSum = fValueMaxY;
    1776                 :            :             }
    1777                 :            :             else
    1778                 :            :             {
    1779                 :        156 :                 fTotalSum += fValueMaxY;
    1780         [ +  + ]:        156 :                 if( rfMinimumY > fTotalSum )
    1781                 :         36 :                     rfMinimumY = fTotalSum;
    1782         [ +  + ]:        156 :                 if( rfMaximumY < fTotalSum )
    1783                 :        102 :                     rfMaximumY = fTotalSum;
    1784                 :            :             }
    1785                 :            :         }
    1786                 :            :     }
    1787                 :            : 
    1788                 :      13820 :     aCachedYValues.m_fMinimumY = rfMinimumY;
    1789                 :      13820 :     aCachedYValues.m_fMaximumY = rfMaximumY;
    1790                 :      13820 :     aCachedYValues.m_bValuesDirty = false;
    1791         [ +  - ]:      89994 :     m_aListOfCachedYValues[nCategoryIndex][nAxisIndex]=aCachedYValues;
    1792                 :            : }
    1793                 :            : 
    1794                 :      12716 : void VDataSeriesGroup::calculateYMinAndMaxForCategoryRange(
    1795                 :            :         sal_Int32 nStartCategoryIndex, sal_Int32 nEndCategoryIndex
    1796                 :            :         , bool bSeperateStackingForDifferentSigns
    1797                 :            :         , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex )
    1798                 :            : {
    1799                 :            :     //@todo maybe cache these values
    1800                 :      12716 :     ::rtl::math::setInf(&rfMinimumY, false);
    1801                 :      12716 :     ::rtl::math::setInf(&rfMaximumY, true);
    1802                 :            : 
    1803                 :            :     //iterate through the given categories
    1804         [ -  + ]:      12716 :     if(nStartCategoryIndex<0)
    1805                 :          0 :         nStartCategoryIndex=0;
    1806         [ -  + ]:      12716 :     if(nEndCategoryIndex<0)
    1807                 :          0 :         nEndCategoryIndex=0;
    1808         [ +  + ]:      80500 :     for( sal_Int32 nCatIndex = nStartCategoryIndex; nCatIndex <= nEndCategoryIndex; nCatIndex++ )
    1809                 :            :     {
    1810                 :      67784 :         double fMinimumY; ::rtl::math::setNan(&fMinimumY);
    1811                 :      67784 :         double fMaximumY; ::rtl::math::setNan(&fMaximumY);
    1812                 :            : 
    1813                 :            :         this->calculateYMinAndMaxForCategory( nCatIndex
    1814         [ +  - ]:      67784 :             , bSeperateStackingForDifferentSigns, fMinimumY, fMaximumY, nAxisIndex );
    1815                 :            : 
    1816         [ +  + ]:      67784 :         if(rfMinimumY > fMinimumY)
    1817                 :      25760 :             rfMinimumY = fMinimumY;
    1818         [ +  + ]:      67784 :         if(rfMaximumY < fMaximumY)
    1819                 :      25904 :             rfMaximumY = fMaximumY;
    1820                 :            :     }
    1821                 :      12716 : }
    1822                 :            : 
    1823                 :       2213 : double VSeriesPlotter::getTransformedDepth() const
    1824                 :            : {
    1825         [ +  - ]:       2213 :     double MinZ = m_pMainPosHelper->getLogicMinZ();
    1826         [ +  - ]:       2213 :     double MaxZ = m_pMainPosHelper->getLogicMaxZ();
    1827         [ +  - ]:       2213 :     m_pMainPosHelper->doLogicScaling( 0, 0, &MinZ );
    1828         [ +  - ]:       2213 :     m_pMainPosHelper->doLogicScaling( 0, 0, &MaxZ );
    1829                 :       2213 :     return FIXED_SIZE_FOR_3D_CHART_VOLUME/(MaxZ-MinZ);
    1830                 :            : }
    1831                 :            : 
    1832                 :         14 : void VSeriesPlotter::addSecondaryValueScale( const ExplicitScaleData& rScale, sal_Int32 nAxisIndex )
    1833                 :            :                 throw (uno::RuntimeException)
    1834                 :            : {
    1835         [ -  + ]:         14 :     if( nAxisIndex<1 )
    1836                 :         14 :         return;
    1837                 :            : 
    1838                 :         14 :     m_aSecondaryValueScales[nAxisIndex]=rScale;
    1839                 :            : }
    1840                 :            : 
    1841                 :      16492 : PlottingPositionHelper& VSeriesPlotter::getPlottingPositionHelper( sal_Int32 nAxisIndex ) const
    1842                 :            : {
    1843                 :      16492 :     PlottingPositionHelper* pRet = 0;
    1844         [ -  + ]:      16492 :     if(nAxisIndex>0)
    1845                 :            :     {
    1846         [ #  # ]:          0 :         tSecondaryPosHelperMap::const_iterator aPosIt = m_aSecondaryPosHelperMap.find( nAxisIndex );
    1847         [ #  # ]:          0 :         if( aPosIt != m_aSecondaryPosHelperMap.end() )
    1848                 :            :         {
    1849                 :          0 :             pRet = aPosIt->second;
    1850                 :            :         }
    1851                 :            :         else
    1852                 :            :         {
    1853         [ #  # ]:          0 :             tSecondaryValueScales::const_iterator aScaleIt = m_aSecondaryValueScales.find( nAxisIndex );
    1854 [ #  # ][ #  # ]:          0 :             if( aScaleIt != m_aSecondaryValueScales.end() )
    1855                 :            :             {
    1856 [ #  # ][ #  # ]:          0 :                 pRet = m_pPosHelper->createSecondaryPosHelper( aScaleIt->second );
    1857         [ #  # ]:          0 :                 m_aSecondaryPosHelperMap[nAxisIndex] = pRet;
    1858                 :            :             }
    1859                 :            :         }
    1860                 :            :     }
    1861         [ +  - ]:      16492 :     if( !pRet )
    1862                 :      16492 :         pRet = m_pMainPosHelper;
    1863         [ +  - ]:      16492 :     if(pRet)
    1864                 :      16492 :         pRet->setTimeResolution( m_nTimeResolution, m_aNullDate );
    1865                 :      16492 :     return *pRet;
    1866                 :            : }
    1867                 :            : 
    1868                 :          0 : void VSeriesPlotter::rearrangeLabelToAvoidOverlapIfRequested( const awt::Size& /*rPageSize*/ )
    1869                 :            : {
    1870                 :          0 : }
    1871                 :            : 
    1872                 :        886 : VDataSeries* VSeriesPlotter::getFirstSeries() const
    1873                 :            : {
    1874                 :        886 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotIter( m_aZSlots.begin() );
    1875                 :        886 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd( m_aZSlots.end() );
    1876 [ +  - ][ +  - ]:        886 :     for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
    1877                 :            :     {
    1878                 :        886 :         ::std::vector< VDataSeriesGroup >::const_iterator       aXSlotIter = aZSlotIter->begin();
    1879                 :        886 :         const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd  = aZSlotIter->end();
    1880                 :            : 
    1881 [ +  - ][ +  - ]:        886 :         if( aXSlotIter != aXSlotEnd )
    1882                 :            :         {
    1883         [ +  - ]:        886 :             VDataSeriesGroup aSeriesGroup( *aXSlotIter );
    1884         [ +  - ]:        886 :             if( aSeriesGroup.m_aSeriesVector.size() )
    1885                 :            :             {
    1886                 :        886 :                 VDataSeries* pSeries = aSeriesGroup.m_aSeriesVector[0];
    1887         [ +  - ]:        886 :                 if(pSeries)
    1888                 :        886 :                     return pSeries;
    1889         [ -  + ]:        886 :             }
    1890                 :            :         }
    1891                 :            :     }
    1892                 :        886 :     return 0;
    1893                 :            : }
    1894                 :            : 
    1895                 :         14 : uno::Sequence< rtl::OUString > VSeriesPlotter::getSeriesNames() const
    1896                 :            : {
    1897         [ +  - ]:         14 :     ::std::vector< rtl::OUString > aRetVector;
    1898                 :            : 
    1899                 :         14 :     rtl::OUString aRole;
    1900         [ +  - ]:         14 :     if( m_xChartTypeModel.is() )
    1901 [ +  - ][ +  - ]:         14 :         aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel();
    1902                 :            : 
    1903                 :         14 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotIter( m_aZSlots.begin() );
    1904                 :         14 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd( m_aZSlots.end() );
    1905 [ +  - ][ +  + ]:         46 :     for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
    1906                 :            :     {
    1907                 :         32 :         ::std::vector< VDataSeriesGroup >::const_iterator       aXSlotIter = aZSlotIter->begin();
    1908                 :         32 :         const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd  = aZSlotIter->end();
    1909                 :            : 
    1910 [ +  - ][ +  - ]:         32 :         if( aXSlotIter != aXSlotEnd )
    1911                 :            :         {
    1912         [ +  - ]:         32 :             VDataSeriesGroup aSeriesGroup( *aXSlotIter );
    1913         [ +  - ]:         32 :             if( aSeriesGroup.m_aSeriesVector.size() )
    1914                 :            :             {
    1915                 :         32 :                 VDataSeries* pSeries = aSeriesGroup.m_aSeriesVector[0];
    1916 [ +  - ][ #  # ]:         32 :                 uno::Reference< XDataSeries > xSeries( pSeries ? pSeries->getModel() : 0 );
                 [ +  - ]
    1917         [ +  - ]:         32 :                 if( xSeries.is() )
    1918                 :            :                 {
    1919         [ +  - ]:         32 :                     rtl::OUString aSeriesName( DataSeriesHelper::getDataSeriesLabel( xSeries, aRole ) );
    1920         [ +  - ]:         32 :                     aRetVector.push_back( aSeriesName );
    1921                 :         32 :                 }
    1922                 :         32 :             }
    1923                 :            :         }
    1924                 :            :     }
    1925         [ +  - ]:         14 :     return ContainerHelper::ContainerToSequence( aRetVector );
    1926                 :            : }
    1927                 :            : 
    1928                 :            : namespace
    1929                 :            : {
    1930                 :            : struct lcl_setRefSizeAtSeriesGroup : public ::std::unary_function< VDataSeriesGroup, void >
    1931                 :            : {
    1932                 :        981 :     lcl_setRefSizeAtSeriesGroup( awt::Size aRefSize ) : m_aRefSize( aRefSize ) {}
    1933                 :       3194 :     void operator()( VDataSeriesGroup & rGroup )
    1934                 :            :     {
    1935                 :       3194 :         ::std::vector< VDataSeries* >::iterator aIt( rGroup.m_aSeriesVector.begin());
    1936                 :       3194 :         const ::std::vector< VDataSeries* >::iterator aEndIt( rGroup.m_aSeriesVector.end());
    1937 [ +  - ][ +  + ]:       6400 :         for( ; aIt != aEndIt; ++aIt )
    1938         [ +  - ]:       3206 :             (*aIt)->setPageReferenceSize( m_aRefSize );
    1939                 :       3194 :     }
    1940                 :            : 
    1941                 :            : private:
    1942                 :            :     awt::Size m_aRefSize;
    1943                 :            : };
    1944                 :            : } // anonymous namespace
    1945                 :            : 
    1946                 :        981 : void VSeriesPlotter::setPageReferenceSize( const ::com::sun::star::awt::Size & rPageRefSize )
    1947                 :            : {
    1948                 :        981 :     m_aPageReferenceSize = rPageRefSize;
    1949                 :            : 
    1950                 :            :     // set reference size also at all data series
    1951                 :            : 
    1952         [ +  - ]:        981 :     ::std::vector< VDataSeriesGroup > aSeriesGroups( FlattenVector( m_aZSlots ));
    1953                 :            :     ::std::for_each( aSeriesGroups.begin(), aSeriesGroups.end(),
    1954         [ +  - ]:        981 :                      lcl_setRefSizeAtSeriesGroup( m_aPageReferenceSize ));
    1955                 :        981 : }
    1956                 :            : 
    1957                 :            : //better performance for big data
    1958                 :        981 : void VSeriesPlotter::setCoordinateSystemResolution( const Sequence< sal_Int32 >& rCoordinateSystemResolution )
    1959                 :            : {
    1960                 :        981 :     m_aCoordinateSystemResolution = rCoordinateSystemResolution;
    1961                 :        981 : }
    1962                 :            : 
    1963                 :       1000 : bool VSeriesPlotter::PointsWereSkipped() const
    1964                 :            : {
    1965                 :       1000 :     return m_bPointsWereSkipped;
    1966                 :            : }
    1967                 :            : 
    1968                 :        981 : bool VSeriesPlotter::WantToPlotInFrontOfAxisLine()
    1969                 :            : {
    1970                 :        981 :     return ChartTypeHelper::isSeriesInFrontOfAxisLine( m_xChartTypeModel );
    1971                 :            : }
    1972                 :            : 
    1973                 :        962 : bool VSeriesPlotter::shouldSnapRectToUsedArea()
    1974                 :            : {
    1975         [ +  + ]:        962 :     if( m_nDimension == 3 )
    1976                 :         14 :         return false;
    1977                 :        962 :     return true;
    1978                 :            : }
    1979                 :            : 
    1980                 :        944 : std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntries(
    1981                 :            :               const awt::Size& rEntryKeyAspectRatio
    1982                 :            :             , ::com::sun::star::chart::ChartLegendExpansion eLegendExpansion
    1983                 :            :             , const Reference< beans::XPropertySet >& xTextProperties
    1984                 :            :             , const Reference< drawing::XShapes >& xTarget
    1985                 :            :             , const Reference< lang::XMultiServiceFactory >& xShapeFactory
    1986                 :            :             , const Reference< uno::XComponentContext >& xContext
    1987                 :            :             )
    1988                 :            : {
    1989                 :        944 :     std::vector< ViewLegendEntry > aResult;
    1990                 :            : 
    1991         [ +  - ]:        944 :     if( xTarget.is() )
    1992                 :            :     {
    1993                 :            :         //iterate through all series
    1994                 :        944 :         bool bBreak = false;
    1995                 :        944 :         bool bFirstSeries = true;
    1996                 :        944 :         ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator             aZSlotIter = m_aZSlots.begin();
    1997         [ +  - ]:        944 :         const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator  aZSlotEnd = m_aZSlots.end();
    1998 [ +  - ][ +  + ]:       1906 :         for( ; aZSlotIter!=aZSlotEnd && !bBreak; ++aZSlotIter )
         [ +  - ][ +  + ]
    1999                 :            :         {
    2000                 :        962 :             ::std::vector< VDataSeriesGroup >::iterator             aXSlotIter = aZSlotIter->begin();
    2001         [ +  - ]:        962 :             const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
    2002 [ +  - ][ +  + ]:       4023 :             for( ; aXSlotIter!=aXSlotEnd && !bBreak; ++aXSlotIter )
         [ +  + ][ +  + ]
    2003                 :            :             {
    2004                 :       3061 :                 ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
    2005         [ +  - ]:       3061 :                 ::std::vector< VDataSeries* >::const_iterator       aSeriesIter = pSeriesList->begin();
    2006         [ +  - ]:       3061 :                 const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd  = pSeriesList->end();
    2007                 :            :                 //iterate through all series in this x slot
    2008 [ +  - ][ +  + ]:       6134 :                 for( ; aSeriesIter!=aSeriesEnd && !bBreak; ++aSeriesIter )
         [ +  - ][ +  + ]
    2009                 :            :                 {
    2010                 :       3073 :                     VDataSeries* pSeries( *aSeriesIter );
    2011         [ -  + ]:       3073 :                     if(!pSeries)
    2012                 :          0 :                         continue;
    2013                 :            : 
    2014                 :            :                     std::vector< ViewLegendEntry > aSeriesEntries( this->createLegendEntriesForSeries( rEntryKeyAspectRatio,
    2015         [ +  - ]:       3073 :                             *pSeries, xTextProperties, xTarget, xShapeFactory, xContext ) );
    2016                 :            : 
    2017                 :            :                     //add series entries to the result now
    2018                 :            : 
    2019                 :            :                     // use only the first series if VaryColorsByPoint is set for the first series
    2020 [ +  + ][ +  - ]:       3073 :                     if( bFirstSeries && pSeries->isVaryColorsByPoint() )
         [ +  + ][ +  + ]
    2021                 :         11 :                         bBreak = true;
    2022                 :       3073 :                     bFirstSeries = false;
    2023                 :            : 
    2024                 :            :                     // add entries reverse if chart is stacked in y-direction and the legend is not wide.
    2025                 :            :                     // If the legend is wide and we have a stacked bar-chart the normal order
    2026                 :            :                     // is the correct one
    2027                 :       3073 :                     bool bReverse = false;
    2028         [ +  - ]:       3073 :                     if( eLegendExpansion != ::com::sun::star::chart::ChartLegendExpansion_WIDE )
    2029                 :            :                     {
    2030         [ +  - ]:       3073 :                         StackingDirection eStackingDirection( pSeries->getStackingDirection() );
    2031                 :       3073 :                         bReverse = ( eStackingDirection == StackingDirection_Y_STACKING );
    2032                 :            : 
    2033                 :            :                         //todo: respect direction of axis in future
    2034                 :            :                     }
    2035                 :            : 
    2036         [ +  + ]:       3073 :                     if(bReverse)
    2037         [ +  - ]:         18 :                         aResult.insert( aResult.begin(), aSeriesEntries.begin(), aSeriesEntries.end() );
    2038                 :            :                     else
    2039         [ +  - ]:       3055 :                         aResult.insert( aResult.end(), aSeriesEntries.begin(), aSeriesEntries.end() );
    2040                 :       3073 :                 }
    2041                 :            :             }
    2042                 :            :         }
    2043                 :            :     }
    2044                 :            : 
    2045                 :        944 :     return aResult;
    2046                 :            : }
    2047                 :            : 
    2048                 :        930 : ::std::vector< VDataSeries* > VSeriesPlotter::getAllSeries()
    2049                 :            : {
    2050         [ +  - ]:        930 :     ::std::vector< VDataSeries* > aAllSeries;
    2051                 :        930 :     ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator            aZSlotIter = m_aZSlots.begin();
    2052         [ +  - ]:        930 :     const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
    2053 [ +  - ][ +  + ]:       1860 :     for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
    2054                 :            :     {
    2055                 :        930 :         ::std::vector< VDataSeriesGroup >::iterator             aXSlotIter = aZSlotIter->begin();
    2056         [ +  - ]:        930 :         const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
    2057 [ +  - ][ +  + ]:       3971 :         for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
    2058                 :            :         {
    2059         [ +  - ]:       3041 :             ::std::vector< VDataSeries* > aSeriesList = aXSlotIter->m_aSeriesVector;
    2060         [ +  - ]:       3041 :             aAllSeries.insert( aAllSeries.end(), aSeriesList.begin(), aSeriesList.end() );
    2061                 :       3041 :         }
    2062                 :            :     }
    2063                 :        930 :     return aAllSeries;
    2064                 :            : }
    2065                 :            : 
    2066                 :            : namespace
    2067                 :            : {
    2068                 :        391 : bool lcl_HasVisibleLine( const uno::Reference< beans::XPropertySet >& xProps, bool& rbHasDashedLine )
    2069                 :            : {
    2070                 :        391 :     bool bHasVisibleLine = false;
    2071                 :        391 :     rbHasDashedLine = false;
    2072                 :        391 :     drawing::LineStyle aLineStyle = drawing::LineStyle_NONE;
    2073 [ +  - ][ +  - ]:        391 :     if( xProps.is() && ( xProps->getPropertyValue( C2U("LineStyle")) >>= aLineStyle ) )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
           [ +  -  #  #  
                   #  # ]
    2074                 :            :     {
    2075         [ +  + ]:        391 :         if( aLineStyle != drawing::LineStyle_NONE )
    2076                 :        381 :             bHasVisibleLine = true;
    2077         [ -  + ]:        391 :         if( aLineStyle == drawing::LineStyle_DASH )
    2078                 :          0 :             rbHasDashedLine = true;
    2079                 :            :     }
    2080                 :        391 :     return bHasVisibleLine;
    2081                 :            : }
    2082                 :            : 
    2083                 :       3053 : bool lcl_HasRegressionCurves( const VDataSeries& rSeries, bool& rbHasDashedLine )
    2084                 :            : {
    2085                 :       3053 :     bool bHasRegressionCurves = false;
    2086 [ +  - ][ +  - ]:       3053 :     Reference< XRegressionCurveContainer > xRegrCont( rSeries.getModel(), uno::UNO_QUERY );
    2087         [ +  - ]:       3053 :     if( xRegrCont.is())
    2088                 :            :     {
    2089 [ +  - ][ +  - ]:       3053 :         Sequence< Reference< XRegressionCurve > > aCurves( xRegrCont->getRegressionCurves() );
    2090                 :       3053 :         sal_Int32 i = 0, nCount = aCurves.getLength();
    2091         [ +  + ]:       3161 :         for( i=0; i<nCount; ++i )
    2092                 :            :         {
    2093 [ +  - ][ +  - ]:        108 :             if( aCurves[i].is() )
    2094                 :            :             {
    2095                 :        108 :                 bHasRegressionCurves = true;
    2096 [ +  - ][ +  - ]:        108 :                 lcl_HasVisibleLine( uno::Reference< beans::XPropertySet >( aCurves[i], uno::UNO_QUERY ), rbHasDashedLine );
                 [ +  - ]
    2097                 :            :             }
    2098         [ +  - ]:       3053 :         }
    2099                 :            :     }
    2100                 :       3053 :     return bHasRegressionCurves;
    2101                 :            : }
    2102                 :            : }
    2103                 :       3646 : LegendSymbolStyle VSeriesPlotter::getLegendSymbolStyle()
    2104                 :            : {
    2105                 :       3646 :     return LegendSymbolStyle_BOX;
    2106                 :            : }
    2107                 :            : 
    2108                 :        944 : awt::Size VSeriesPlotter::getPreferredLegendKeyAspectRatio()
    2109                 :            : {
    2110                 :        944 :     awt::Size aRet(1000,1000);
    2111         [ +  + ]:        944 :     if( m_nDimension==3 )
    2112                 :            :         return aRet;
    2113                 :            : 
    2114         [ +  - ]:        930 :     bool bSeriesAllowsLines = (getLegendSymbolStyle() == LegendSymbolStyle_LINE);
    2115                 :        930 :     bool bHasLines = false;
    2116                 :        930 :     bool bHasDashedLines = false;
    2117         [ +  - ]:        930 :     ::std::vector< VDataSeries* > aAllSeries( getAllSeries() );
    2118         [ +  - ]:        930 :     ::std::vector< VDataSeries* >::const_iterator       aSeriesIter = aAllSeries.begin();
    2119         [ +  - ]:        930 :     const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd  = aAllSeries.end();
    2120                 :            :     //iterate through all series
    2121 [ +  - ][ +  + ]:       3983 :     for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
    2122                 :            :     {
    2123         [ +  + ]:       3053 :         if( bSeriesAllowsLines )
    2124                 :            :         {
    2125                 :        283 :             bool bCurrentDashed = false;
    2126 [ +  - ][ +  - ]:        283 :             if( lcl_HasVisibleLine( (*aSeriesIter)->getPropertiesOfSeries(), bCurrentDashed ) )
                 [ +  - ]
    2127                 :            :             {
    2128                 :        283 :                 bHasLines = true;
    2129         [ -  + ]:        283 :                 if( bCurrentDashed )
    2130                 :            :                 {
    2131                 :        283 :                     bHasDashedLines = true;
    2132                 :            :                     break;
    2133                 :            :                 }
    2134                 :            :             }
    2135                 :            :         }
    2136                 :       3053 :         bool bRegressionHasDashedLines=false;
    2137 [ +  - ][ +  + ]:       3053 :         if( lcl_HasRegressionCurves( **aSeriesIter, bRegressionHasDashedLines ) )
    2138                 :            :         {
    2139                 :         76 :             bHasLines = true;
    2140         [ -  + ]:         76 :             if( bRegressionHasDashedLines )
    2141                 :            :             {
    2142                 :          0 :                 bHasDashedLines = true;
    2143                 :            :                 break;
    2144                 :            :             }
    2145                 :            :         }
    2146                 :            :     }
    2147         [ +  + ]:        930 :     if( bHasLines )
    2148                 :            :     {
    2149         [ -  + ]:         65 :         if( bHasDashedLines )
    2150                 :          0 :             aRet = awt::Size(1600,-1);
    2151                 :            :         else
    2152                 :         65 :             aRet = awt::Size(800,-1);
    2153                 :            :     }
    2154                 :        944 :     return aRet;
    2155                 :            : }
    2156                 :            : 
    2157                 :       2801 : uno::Any VSeriesPlotter::getExplicitSymbol( const VDataSeries& /*rSeries*/, sal_Int32 /*nPointIndex*/ )
    2158                 :            : {
    2159                 :       2801 :     return uno::Any();
    2160                 :            : }
    2161                 :            : 
    2162                 :       3062 : Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForSeries(
    2163                 :            :                   const awt::Size& rEntryKeyAspectRatio
    2164                 :            :                 , const VDataSeries& rSeries
    2165                 :            :                 , const Reference< drawing::XShapes >& xTarget
    2166                 :            :                 , const Reference< lang::XMultiServiceFactory >& xShapeFactory )
    2167                 :            : {
    2168                 :            : 
    2169         [ +  - ]:       3062 :     LegendSymbolStyle eLegendSymbolStyle = this->getLegendSymbolStyle();
    2170         [ +  - ]:       3062 :     uno::Any aExplicitSymbol( this->getExplicitSymbol( rSeries ) );
    2171                 :            : 
    2172                 :            :     VLegendSymbolFactory::tPropertyType ePropType =
    2173                 :       3062 :         VLegendSymbolFactory::PROP_TYPE_FILLED_SERIES;
    2174                 :            : 
    2175                 :            :     // todo: maybe the property-style does not solely depend on the
    2176                 :            :     // legend-symbol type
    2177         [ +  + ]:       3062 :     switch( eLegendSymbolStyle )
    2178                 :            :     {
    2179                 :            :         case LegendSymbolStyle_LINE:
    2180                 :        283 :             ePropType = VLegendSymbolFactory::PROP_TYPE_LINE_SERIES;
    2181                 :        283 :             break;
    2182                 :            :         default:
    2183                 :       2779 :             break;
    2184                 :            :     };
    2185                 :            :     Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio,
    2186                 :            :         xTarget, eLegendSymbolStyle, xShapeFactory
    2187 [ +  - ][ +  - ]:       3062 :             , rSeries.getPropertiesOfSeries(), ePropType, aExplicitSymbol ));
    2188                 :            : 
    2189                 :       3062 :     return xShape;
    2190                 :            : }
    2191                 :            : 
    2192                 :         35 : Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForPoint(
    2193                 :            :                   const awt::Size& rEntryKeyAspectRatio
    2194                 :            :                 , const VDataSeries& rSeries
    2195                 :            :                 , sal_Int32 nPointIndex
    2196                 :            :                 , const Reference< drawing::XShapes >& xTarget
    2197                 :            :                 , const Reference< lang::XMultiServiceFactory >& xShapeFactory )
    2198                 :            : {
    2199                 :            : 
    2200         [ +  - ]:         35 :     LegendSymbolStyle eLegendSymbolStyle = this->getLegendSymbolStyle();
    2201         [ +  - ]:         35 :     uno::Any aExplicitSymbol( this->getExplicitSymbol(rSeries,nPointIndex) );
    2202                 :            : 
    2203                 :            :     VLegendSymbolFactory::tPropertyType ePropType =
    2204                 :         35 :         VLegendSymbolFactory::PROP_TYPE_FILLED_SERIES;
    2205                 :            : 
    2206                 :            :     // todo: maybe the property-style does not solely depend on the
    2207                 :            :     // legend-symbol type
    2208         [ -  + ]:         35 :     switch( eLegendSymbolStyle )
    2209                 :            :     {
    2210                 :            :         case LegendSymbolStyle_LINE:
    2211                 :          0 :             ePropType = VLegendSymbolFactory::PROP_TYPE_LINE_SERIES;
    2212                 :          0 :             break;
    2213                 :            :         default:
    2214                 :         35 :             break;
    2215                 :            :     };
    2216                 :            : 
    2217                 :            :     // the default properties for the data point are the data series properties.
    2218                 :            :     // If a data point has own attributes overwrite them
    2219         [ +  - ]:         35 :     Reference< beans::XPropertySet > xSeriesProps( rSeries.getPropertiesOfSeries() );
    2220                 :         35 :     Reference< beans::XPropertySet > xPointSet( xSeriesProps );
    2221 [ -  + ][ +  - ]:         35 :     if( rSeries.isAttributedDataPoint( nPointIndex ) )
    2222 [ #  # ][ #  # ]:          0 :         xPointSet.set( rSeries.getPropertiesOfPoint( nPointIndex ));
    2223                 :            : 
    2224                 :            :     // if a data point has no own color use a color fom the diagram's color scheme
    2225 [ +  - ][ +  - ]:         35 :     if( ! rSeries.hasPointOwnColor( nPointIndex ))
    2226                 :            :     {
    2227         [ +  - ]:         35 :         Reference< util::XCloneable > xCloneable( xPointSet,uno::UNO_QUERY );
    2228 [ +  - ][ +  - ]:         35 :         if( xCloneable.is() && m_xColorScheme.is() )
                 [ +  - ]
    2229                 :            :         {
    2230 [ +  - ][ +  - ]:         35 :             xPointSet.set( xCloneable->createClone(), uno::UNO_QUERY );
                 [ +  - ]
    2231         [ +  - ]:         35 :             Reference< container::XChild > xChild( xPointSet, uno::UNO_QUERY );
    2232         [ -  + ]:         35 :             if( xChild.is())
    2233 [ #  # ][ #  # ]:          0 :                 xChild->setParent( xSeriesProps );
    2234                 :            : 
    2235                 :            :             OSL_ASSERT( xPointSet.is());
    2236         [ +  - ]:         35 :             xPointSet->setPropertyValue(
    2237 [ +  - ][ +  - ]:         35 :                 C2U("Color"), uno::makeAny( m_xColorScheme->getColorByIndex( nPointIndex )));
         [ +  - ][ +  - ]
                 [ +  - ]
    2238                 :         35 :         }
    2239                 :            :     }
    2240                 :            : 
    2241                 :            :     Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio,
    2242         [ +  - ]:         35 :         xTarget, eLegendSymbolStyle, xShapeFactory, xPointSet, ePropType, aExplicitSymbol ));
    2243                 :            : 
    2244                 :         35 :     return xShape;
    2245                 :            : }
    2246                 :            : 
    2247                 :       3073 : std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries(
    2248                 :            :               const awt::Size& rEntryKeyAspectRatio
    2249                 :            :             , const VDataSeries& rSeries
    2250                 :            :             , const Reference< beans::XPropertySet >& xTextProperties
    2251                 :            :             , const Reference< drawing::XShapes >& xTarget
    2252                 :            :             , const Reference< lang::XMultiServiceFactory >& xShapeFactory
    2253                 :            :             , const Reference< uno::XComponentContext >& xContext
    2254                 :            :             )
    2255                 :            : {
    2256                 :       3073 :     std::vector< ViewLegendEntry > aResult;
    2257                 :            : 
    2258 [ +  - ][ -  + ]:       3073 :     if( ! ( xShapeFactory.is() && xTarget.is() && xContext.is() ) )
         [ -  + ][ +  - ]
    2259                 :          0 :         return aResult;
    2260                 :            : 
    2261                 :            :     try
    2262                 :            :     {
    2263         [ +  - ]:       3073 :         ViewLegendEntry aEntry;
    2264                 :       3073 :         OUString aLabelText;
    2265         [ +  - ]:       3073 :         bool bVaryColorsByPoint = rSeries.isVaryColorsByPoint();
    2266         [ +  + ]:       3073 :         if( bVaryColorsByPoint )
    2267                 :            :         {
    2268         [ +  - ]:         11 :             Sequence< OUString > aCategoryNames;
    2269         [ +  - ]:         11 :             if( m_pExplicitCategoriesProvider )
    2270 [ +  - ][ +  - ]:         11 :                 aCategoryNames = m_pExplicitCategoriesProvider->getSimpleCategories();
                 [ +  - ]
    2271                 :            : 
    2272         [ +  + ]:         46 :             for( sal_Int32 nIdx=0; nIdx<aCategoryNames.getLength(); ++nIdx )
    2273                 :            :             {
    2274                 :            :                 // symbol
    2275 [ +  - ][ +  - ]:         35 :                 uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory(xShapeFactory).createGroup2D( xTarget ));
                 [ +  - ]
    2276                 :            : 
    2277                 :            :                 // create the symbol
    2278                 :            :                 Reference< drawing::XShape > xShape( this->createLegendSymbolForPoint( rEntryKeyAspectRatio,
    2279         [ +  - ]:         35 :                     rSeries, nIdx, xSymbolGroup, xShapeFactory ) );
    2280                 :            : 
    2281                 :            :                 // set CID to symbol for selection
    2282         [ +  - ]:         35 :                 if( xShape.is() )
    2283                 :            :                 {
    2284 [ +  - ][ +  - ]:         35 :                     aEntry.aSymbol = uno::Reference< drawing::XShape >( xSymbolGroup, uno::UNO_QUERY );
    2285                 :            : 
    2286         [ +  - ]:         35 :                     OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_DATA_POINT, nIdx ) );
    2287 [ +  - ][ +  - ]:         35 :                     aChildParticle = ObjectIdentifier::addChildParticle( aChildParticle, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) );
    2288 [ +  - ][ +  - ]:         35 :                     OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle );
    2289         [ +  - ]:         35 :                     ShapeFactory::setShapeName( xShape, aCID );
    2290                 :            :                 }
    2291                 :            : 
    2292                 :            :                 // label
    2293         [ +  - ]:         35 :                 aLabelText = aCategoryNames[nIdx];
    2294 [ #  # ][ +  - ]:         35 :                 if( xShape.is() || !aLabelText.isEmpty() )
                 [ -  + ]
    2295                 :            :                 {
    2296 [ +  - ][ +  - ]:         35 :                     aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aLabelText, xTextProperties );
    2297         [ +  - ]:         35 :                     aResult.push_back(aEntry);
    2298                 :            :                 }
    2299         [ +  - ]:         46 :             }
    2300                 :            :         }
    2301                 :            :         else
    2302                 :            :         {
    2303                 :            :             // symbol
    2304 [ +  - ][ +  - ]:       3062 :             uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory(xShapeFactory).createGroup2D( xTarget ));
                 [ +  - ]
    2305                 :            : 
    2306                 :            :             // create the symbol
    2307                 :            :             Reference< drawing::XShape > xShape( this->createLegendSymbolForSeries(
    2308         [ +  - ]:       3062 :                 rEntryKeyAspectRatio, rSeries, xSymbolGroup, xShapeFactory ) );
    2309                 :            : 
    2310                 :            :             // set CID to symbol for selection
    2311         [ +  - ]:       3062 :             if( xShape.is())
    2312                 :            :             {
    2313 [ +  - ][ +  - ]:       3062 :                 aEntry.aSymbol = uno::Reference< drawing::XShape >( xSymbolGroup, uno::UNO_QUERY );
    2314                 :            : 
    2315         [ +  - ]:       3062 :                 OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) );
    2316 [ +  - ][ +  - ]:       3062 :                 OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle );
    2317         [ +  - ]:       3062 :                 ShapeFactory::setShapeName( xShape, aCID );
    2318                 :            :             }
    2319                 :            : 
    2320                 :            :             // label
    2321 [ +  - ][ +  - ]:       3062 :             aLabelText = ( DataSeriesHelper::getDataSeriesLabel( rSeries.getModel(), m_xChartTypeModel.is() ? m_xChartTypeModel->getRoleOfSequenceForSeriesLabel() : C2U("values-y")) );
         [ +  - ][ #  # ]
         [ +  - ][ +  - ]
    2322 [ +  - ][ +  - ]:       3062 :             aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aLabelText, xTextProperties );
    2323                 :            : 
    2324         [ +  - ]:       3062 :             aResult.push_back(aEntry);
    2325                 :            :         }
    2326                 :            : 
    2327                 :            :         // don't show legend entry of regression curve & friends if this type of chart
    2328                 :            :         // doesn't support statistics #i63016#, fdo#37197
    2329 [ +  - ][ +  + ]:       3073 :         if (!ChartTypeHelper::isSupportingStatisticProperties( m_xChartTypeModel, m_nDimension ))
    2330                 :            :             return aResult;
    2331                 :            : 
    2332 [ +  - ][ +  - ]:       3000 :         Reference< XRegressionCurveContainer > xRegrCont( rSeries.getModel(), uno::UNO_QUERY );
    2333         [ +  - ]:       3000 :         if( xRegrCont.is())
    2334                 :            :         {
    2335 [ +  - ][ +  - ]:       3000 :             Sequence< Reference< XRegressionCurve > > aCurves( xRegrCont->getRegressionCurves());
    2336                 :       3000 :             sal_Int32 i = 0, nCount = aCurves.getLength();
    2337         [ +  + ]:       3108 :             for( i=0; i<nCount; ++i )
    2338                 :            :             {
    2339 [ +  - ][ +  - ]:        108 :                 if( aCurves[i].is() )
    2340                 :            :                 {
    2341                 :            :                     //label
    2342 [ +  - ][ +  - ]:        108 :                     OUString aResStr( RegressionCurveHelper::getUINameForRegressionCurve( aCurves[i] ) );
    2343 [ +  - ][ +  - ]:        108 :                     replaceParamterInString( aResStr, C2U("%SERIESNAME"), aLabelText );
    2344 [ +  - ][ +  - ]:        108 :                     aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aResStr, xTextProperties );
    2345                 :            : 
    2346                 :            :                     // symbol
    2347 [ +  - ][ +  - ]:        108 :                     uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory(xShapeFactory).createGroup2D( xTarget ));
                 [ +  - ]
    2348                 :            : 
    2349                 :            :                     // create the symbol
    2350                 :            :                     Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio,
    2351                 :            :                         xSymbolGroup, LegendSymbolStyle_LINE, xShapeFactory,
    2352         [ +  - ]:        108 :                         Reference< beans::XPropertySet >( aCurves[i], uno::UNO_QUERY ),
    2353 [ +  - ][ +  - ]:        216 :                         VLegendSymbolFactory::PROP_TYPE_LINE, uno::Any() ));
    2354                 :            : 
    2355                 :            :                     // set CID to symbol for selection
    2356         [ +  - ]:        108 :                     if( xShape.is())
    2357                 :            :                     {
    2358 [ +  - ][ +  - ]:        108 :                         aEntry.aSymbol = uno::Reference< drawing::XShape >( xSymbolGroup, uno::UNO_QUERY );
    2359                 :            : 
    2360 [ +  - ][ +  - ]:        108 :                         bool bAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[i] );
    2361         [ +  + ]:        108 :                         ObjectType eObjectType = bAverageLine ? OBJECTTYPE_DATA_AVERAGE_LINE : OBJECTTYPE_DATA_CURVE;
    2362         [ +  - ]:        108 :                         OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( eObjectType, i ) );
    2363 [ +  - ][ +  - ]:        108 :                         aChildParticle = ObjectIdentifier::addChildParticle( aChildParticle, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) );
    2364 [ +  - ][ +  - ]:        108 :                         OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle );
    2365         [ +  - ]:        108 :                         ShapeFactory::setShapeName( xShape, aCID );
    2366                 :            :                     }
    2367                 :            : 
    2368         [ +  - ]:        108 :                     aResult.push_back(aEntry);
    2369                 :            :                 }
    2370         [ +  - ]:       3000 :             }
    2371 [ +  + ][ +  - ]:       3073 :         }
         [ +  + ][ #  # ]
    2372                 :            :     }
    2373         [ #  # ]:          0 :     catch( const uno::Exception & ex )
    2374                 :            :     {
    2375                 :            :         ASSERT_EXCEPTION( ex );
    2376                 :            :     }
    2377                 :       3073 :     return aResult;
    2378                 :            : }
    2379                 :            : 
    2380                 :        981 : VSeriesPlotter* VSeriesPlotter::createSeriesPlotter(
    2381                 :            :     const uno::Reference<XChartType>& xChartTypeModel
    2382                 :            :     , sal_Int32 nDimensionCount
    2383                 :            :     , bool bExcludingPositioning )
    2384                 :            : {
    2385 [ +  - ][ +  - ]:        981 :     rtl::OUString aChartType = xChartTypeModel->getChartType();
    2386                 :            : 
    2387                 :            :     //@todo: in future the plotter should be instanciated via service factory
    2388                 :        981 :     VSeriesPlotter* pRet=NULL;
    2389 [ +  - ][ +  + ]:        981 :     if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ) )
    2390 [ +  - ][ +  - ]:        886 :         pRet = new BarChart(xChartTypeModel,nDimensionCount);
    2391 [ +  - ][ -  + ]:         95 :     else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_BAR ) )
    2392 [ #  # ][ #  # ]:          0 :         pRet = new BarChart(xChartTypeModel,nDimensionCount);
    2393 [ +  - ][ -  + ]:         95 :     else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_AREA ) )
    2394 [ #  # ][ #  # ]:          0 :         pRet = new AreaChart(xChartTypeModel,nDimensionCount,true);
    2395 [ +  - ][ +  + ]:         95 :     else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_LINE ) )
    2396 [ +  - ][ +  - ]:         72 :         pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true);
    2397 [ +  - ][ -  + ]:         23 :     else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) )
    2398 [ #  # ][ #  # ]:          0 :         pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true);
    2399 [ +  - ][ -  + ]:         23 :     else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) )
    2400 [ #  # ][ #  # ]:          0 :         pRet = new BubbleChart(xChartTypeModel,nDimensionCount);
    2401 [ +  - ][ +  + ]:         23 :     else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
    2402 [ +  - ][ +  - ]:         19 :         pRet = new PieChart(xChartTypeModel,nDimensionCount, bExcludingPositioning );
    2403 [ +  - ][ -  + ]:          4 :     else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
    2404 [ #  # ][ #  # ]:          0 :         pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true,new PolarPlottingPositionHelper(),true,false,1,drawing::Direction3D(1,1,1) );
         [ #  # ][ #  # ]
    2405 [ +  - ][ -  + ]:          4 :     else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
    2406 [ #  # ][ #  # ]:          0 :         pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,false,new PolarPlottingPositionHelper(),true,false,1,drawing::Direction3D(1,1,1) );
         [ #  # ][ #  # ]
    2407 [ +  - ][ +  - ]:          4 :     else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
    2408 [ +  - ][ +  - ]:          4 :         pRet = new CandleStickChart(xChartTypeModel,nDimensionCount);
    2409                 :            :     else
    2410 [ #  # ][ #  # ]:          0 :         pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true);
    2411                 :        981 :     return pRet;
    2412                 :            : }
    2413                 :            : 
    2414                 :            : //.............................................................................
    2415                 :            : } //namespace chart
    2416                 :            : //.............................................................................
    2417                 :            : 
    2418                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10