LCOV - code coverage report
Current view: top level - chart2/source/view/charttypes - VSeriesPlotter.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1036 1242 83.4 %
Date: 2014-11-03 Functions: 82 89 92.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10