LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/chart2/source/view/axes - VCartesianAxis.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 584 896 65.2 %
Date: 2013-07-09 Functions: 43 51 84.3 %
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 <basegfx/numeric/ftools.hxx>
      21             : 
      22             : #include "VCartesianAxis.hxx"
      23             : #include "PlottingPositionHelper.hxx"
      24             : #include "ShapeFactory.hxx"
      25             : #include "CommonConverters.hxx"
      26             : #include "macros.hxx"
      27             : #include "ViewDefines.hxx"
      28             : #include "PropertyMapper.hxx"
      29             : #include "NumberFormatterWrapper.hxx"
      30             : #include "LabelPositionHelper.hxx"
      31             : #include "TrueGuard.hxx"
      32             : #include "BaseGFXHelper.hxx"
      33             : #include "AxisHelper.hxx"
      34             : #include "Tickmarks_Equidistant.hxx"
      35             : 
      36             : #include <rtl/math.hxx>
      37             : #include <tools/color.hxx>
      38             : #include <com/sun/star/text/XText.hpp>
      39             : #include <com/sun/star/text/WritingMode2.hpp>
      40             : #include <editeng/unoprnms.hxx>
      41             : #include <svx/unoshape.hxx>
      42             : #include <svx/unoshtxt.hxx>
      43             : 
      44             : #include <algorithm>
      45             : #include <boost/scoped_ptr.hpp>
      46             : #include <basegfx/polygon/b2dpolygon.hxx>
      47             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      48             : #include <basegfx/polygon/b2dpolygontools.hxx>
      49             : #include <basegfx/polygon/b2dpolygonclipper.hxx>
      50             : #include <basegfx/matrix/b2dhommatrix.hxx>
      51             : 
      52             : //.............................................................................
      53             : namespace chart
      54             : {
      55             : //.............................................................................
      56             : using namespace ::com::sun::star;
      57             : using namespace ::com::sun::star::chart2;
      58             : using namespace ::rtl::math;
      59             : using ::basegfx::B2DVector;
      60             : using ::com::sun::star::uno::Reference;
      61             : using ::basegfx::B2DPolygon;
      62             : using ::basegfx::B2DPolyPolygon;
      63             : 
      64             : //-----------------------------------------------------------------------------
      65             : //-----------------------------------------------------------------------------
      66             : //-----------------------------------------------------------------------------
      67             : 
      68        1044 : VCartesianAxis::VCartesianAxis( const AxisProperties& rAxisProperties
      69             :             , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
      70             :             , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
      71             :             , PlottingPositionHelper* pPosHelper )//takes ownership
      72        1044 :             : VAxisBase( nDimensionIndex, nDimensionCount, rAxisProperties, xNumberFormatsSupplier )
      73             : {
      74        1044 :     if( pPosHelper )
      75           0 :         m_pPosHelper = pPosHelper;
      76             :     else
      77        1044 :         m_pPosHelper = new PlottingPositionHelper();
      78        1044 : }
      79             : 
      80        3132 : VCartesianAxis::~VCartesianAxis()
      81             : {
      82        1044 :     delete m_pPosHelper;
      83        1044 :     m_pPosHelper = NULL;
      84        2088 : }
      85             : 
      86        8797 : Reference< drawing::XShape > createSingleLabel(
      87             :             const Reference< lang::XMultiServiceFactory>& xShapeFactory
      88             :           , const Reference< drawing::XShapes >& xTarget
      89             :           , const awt::Point& rAnchorScreenPosition2D
      90             :           , const OUString& rLabel
      91             :           , const AxisLabelProperties& rAxisLabelProperties
      92             :           , const AxisProperties& rAxisProperties
      93             :           , const tNameSequence& rPropNames
      94             :           , const tAnySequence& rPropValues
      95             :           )
      96             : {
      97        8797 :     if(rLabel.isEmpty())
      98          17 :         return 0;
      99             : 
     100             :     // #i78696# use mathematically correct rotation now
     101        8780 :     const double fRotationAnglePi(rAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0));
     102        8780 :     uno::Any aATransformation = ShapeFactory::makeTransformation( rAnchorScreenPosition2D, fRotationAnglePi );
     103       17560 :     OUString aLabel = ShapeFactory::getStackedString( rLabel, rAxisLabelProperties.bStackCharacters );
     104             : 
     105             :     Reference< drawing::XShape > xShape2DText = ShapeFactory(xShapeFactory)
     106       17560 :                     .createText( xTarget, aLabel, rPropNames, rPropValues, aATransformation );
     107             : 
     108             :     LabelPositionHelper::correctPositionForRotation( xShape2DText
     109        8780 :         , rAxisProperties.m_aLabelAlignment, rAxisLabelProperties.fRotationAngleDegree, rAxisProperties.m_bComplexCategories );
     110             : 
     111       17560 :     return xShape2DText;
     112             : }
     113             : 
     114        4188 : bool lcl_doesShapeOverlapWithTickmark( const Reference< drawing::XShape >& xShape
     115             :                        , double fRotationAngleDegree
     116             :                        , const basegfx::B2DVector& rTickScreenPosition
     117             :                        , bool bIsHorizontalAxis, bool bIsVerticalAxis )
     118             : {
     119        4188 :     if(!xShape.is())
     120           0 :         return false;
     121             : 
     122        4188 :     ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(xShape->getPosition(),ShapeFactory::getSizeAfterRotation( xShape, fRotationAngleDegree ));
     123             : 
     124        4188 :     if( bIsVerticalAxis )
     125             :     {
     126        2402 :         return ( (rTickScreenPosition.getY() >= aShapeRect.getMinY())
     127        2402 :             && (rTickScreenPosition.getY() <= aShapeRect.getMaxY()) );
     128             :     }
     129        1786 :     if( bIsHorizontalAxis )
     130             :     {
     131        1750 :         return ( (rTickScreenPosition.getX() >= aShapeRect.getMinX())
     132        1750 :             && (rTickScreenPosition.getX() <= aShapeRect.getMaxX()) );
     133             :     }
     134             : 
     135             :     basegfx::B2IVector aPosition(
     136          36 :         static_cast<sal_Int32>( rTickScreenPosition.getX() )
     137          72 :         , static_cast<sal_Int32>( rTickScreenPosition.getY() ) );
     138          36 :     return aShapeRect.isInside(aPosition);
     139             : }
     140             : 
     141        8336 : void lcl_getRotatedPolygon( B2DPolygon &aPoly, const ::basegfx::B2DRectangle &aRect, const awt::Point &aPos, const double fRotationAngleDegree )
     142             : {
     143        8336 :     ::basegfx::B2DHomMatrix aMatrix;
     144             : 
     145        8336 :     aPoly = basegfx::tools::createPolygonFromRect( aRect );
     146        8336 :     aMatrix.translate( -aRect.getWidth()/2, -aRect.getHeight()/2);
     147        8336 :     aMatrix.rotate( fRotationAngleDegree*M_PI/180.0 );
     148        8336 :     aPoly.transform( aMatrix );
     149        8336 :     aMatrix = ::basegfx::B2DHomMatrix();
     150        8336 :     aMatrix.translate( aRect.getWidth()/2+aPos.X, aRect.getHeight()/2+aPos.Y);
     151        8336 :     aPoly.transform( aMatrix );
     152        8336 : }
     153             : 
     154        4168 : bool doesOverlap( const Reference< drawing::XShape >& xShape1
     155             :                 , const Reference< drawing::XShape >& xShape2
     156             :                 , double fRotationAngleDegree )
     157             : {
     158        4168 :     if( !xShape1.is() || !xShape2.is() )
     159           0 :         return false;
     160             : 
     161        4168 :     ::basegfx::B2DRectangle aRect1( BaseGFXHelper::makeRectangle( awt::Point(0,0), xShape1->getSize()));
     162        4168 :     ::basegfx::B2DRectangle aRect2( BaseGFXHelper::makeRectangle( awt::Point(0,0), xShape2->getSize()));
     163             : 
     164        4168 :     B2DPolygon aPoly1;
     165        8336 :     B2DPolygon aPoly2;
     166        4168 :     lcl_getRotatedPolygon( aPoly1, aRect1, xShape1->getPosition(), fRotationAngleDegree );
     167        4168 :     lcl_getRotatedPolygon( aPoly2, aRect2, xShape2->getPosition(), fRotationAngleDegree );
     168             : 
     169        8336 :     B2DPolyPolygon aPolyPoly1, aPolyPoly2;
     170        4168 :     aPolyPoly1.append( aPoly1 );
     171        4168 :     aPolyPoly2.append( aPoly2 );
     172        8336 :     B2DPolyPolygon overlapPoly = ::basegfx::tools::clipPolyPolygonOnPolyPolygon( aPolyPoly1, aPolyPoly2, true, false );
     173             : 
     174        8336 :     return (overlapPoly.count() > 0);
     175             : }
     176             : 
     177          30 : void removeShapesAtWrongRhythm( TickIter& rIter
     178             :                               , sal_Int32 nCorrectRhythm
     179             :                               , sal_Int32 nMaxTickToCheck
     180             :                               , const Reference< drawing::XShapes >& xTarget )
     181             : {
     182          30 :     sal_Int32 nTick = 0;
     183          99 :     for( TickInfo* pTickInfo = rIter.firstInfo()
     184          88 :         ; pTickInfo && nTick <= nMaxTickToCheck
     185          69 :         ; pTickInfo = rIter.nextInfo(), nTick++ )
     186             :     {
     187             :         //remove labels which does not fit into the rhythm
     188          69 :         if( nTick%nCorrectRhythm != 0)
     189             :         {
     190          39 :             if(pTickInfo->xTextShape.is())
     191             :             {
     192          10 :                 xTarget->remove(pTickInfo->xTextShape);
     193          10 :                 pTickInfo->xTextShape = NULL;
     194             :             }
     195             :         }
     196             :     }
     197          30 : }
     198             : 
     199         958 : class LabelIterator : public TickIter
     200             : {
     201             :     //this Iterator iterates over existing text labels
     202             : 
     203             :     //if the labels are staggered and bInnerLine is true
     204             :     //we iterate only through the labels which are lying more inside the diagram
     205             : 
     206             :     //if the labels are staggered and bInnerLine is false
     207             :     //we iterate only through the labels which are lying more outside the diagram
     208             : 
     209             :     //if the labels are not staggered
     210             :     //we iterate through all labels
     211             : 
     212             : public:
     213             :     LabelIterator( ::std::vector< TickInfo >& rTickInfoVector
     214             :             , const AxisLabelStaggering eAxisLabelStaggering
     215             :             , bool bInnerLine );
     216             : 
     217             :     virtual TickInfo*   firstInfo();
     218             :     virtual TickInfo*   nextInfo();
     219             : 
     220             : private: //methods
     221             :     LabelIterator();
     222             : 
     223             : private: //member
     224             :     PureTickIter m_aPureTickIter;
     225             :     const AxisLabelStaggering   m_eAxisLabelStaggering;
     226             :     bool m_bInnerLine;
     227             : };
     228             : 
     229         958 : LabelIterator::LabelIterator( ::std::vector< TickInfo >& rTickInfoVector
     230             :             , const AxisLabelStaggering eAxisLabelStaggering
     231             :             , bool bInnerLine )
     232             :             : m_aPureTickIter( rTickInfoVector )
     233             :             , m_eAxisLabelStaggering(eAxisLabelStaggering)
     234         958 :             , m_bInnerLine(bInnerLine)
     235             : {
     236         958 : }
     237             : 
     238         956 : TickInfo* LabelIterator::firstInfo()
     239             : {
     240         956 :     TickInfo* pTickInfo = m_aPureTickIter.firstInfo();
     241        1925 :     while( pTickInfo && !pTickInfo->xTextShape.is() )
     242          13 :         pTickInfo = m_aPureTickIter.nextInfo();
     243         956 :     if(!pTickInfo)
     244           1 :         return NULL;
     245         955 :     if( (STAGGER_EVEN==m_eAxisLabelStaggering && m_bInnerLine)
     246         477 :         ||
     247         477 :         (STAGGER_ODD==m_eAxisLabelStaggering && !m_bInnerLine)
     248             :         )
     249             :     {
     250             :         //skip first label
     251         478 :         do
     252         478 :             pTickInfo = m_aPureTickIter.nextInfo();
     253         478 :         while( pTickInfo && !pTickInfo->xTextShape.is() );
     254             :     }
     255         955 :     if(!pTickInfo)
     256           1 :         return NULL;
     257         954 :     return pTickInfo;
     258             : }
     259             : 
     260        1908 : TickInfo* LabelIterator::nextInfo()
     261             : {
     262        1908 :     TickInfo* pTickInfo = NULL;
     263             :     //get next label
     264        2141 :     do
     265        2141 :         pTickInfo = m_aPureTickIter.nextInfo();
     266        2141 :     while( pTickInfo && !pTickInfo->xTextShape.is() );
     267             : 
     268        1908 :     if(  STAGGER_EVEN==m_eAxisLabelStaggering
     269           0 :       || STAGGER_ODD==m_eAxisLabelStaggering )
     270             :     {
     271             :         //skip one label
     272        2141 :         do
     273        2141 :             pTickInfo = m_aPureTickIter.nextInfo();
     274        2141 :         while( pTickInfo && !pTickInfo->xTextShape.is() );
     275             :     }
     276        1908 :     return pTickInfo;
     277             : }
     278             : 
     279         479 : B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDistanceTickToText, double fRotationAngleDegree )
     280             : {
     281             :     //calculates the height or width of a line of labels
     282             :     //thus a following line of labels can be shifted for that distance
     283             : 
     284         479 :     B2DVector aRet(0,0);
     285             : 
     286         479 :     sal_Int32 nDistanceTickToText = static_cast<sal_Int32>( rDistanceTickToText.getLength() );
     287         479 :     if( nDistanceTickToText==0.0)
     288           0 :         return aRet;
     289             : 
     290         958 :     B2DVector aStaggerDirection(rDistanceTickToText);
     291         479 :     aStaggerDirection.normalize();
     292             : 
     293         479 :     sal_Int32 nDistance=0;
     294         958 :     Reference< drawing::XShape >  xShape2DText(NULL);
     295        1424 :     for( TickInfo* pTickInfo = rIter.firstInfo()
     296             :         ; pTickInfo
     297         945 :         ; pTickInfo = rIter.nextInfo() )
     298             :     {
     299         945 :         xShape2DText = pTickInfo->xTextShape;
     300         945 :         if( xShape2DText.is() )
     301             :         {
     302         945 :             awt::Size aSize = ShapeFactory::getSizeAfterRotation( xShape2DText, fRotationAngleDegree );
     303         945 :             if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY()))
     304          27 :                 nDistance = ::std::max(nDistance,aSize.Width);
     305             :             else
     306         918 :                 nDistance = ::std::max(nDistance,aSize.Height);
     307             :         }
     308             :     }
     309             : 
     310         479 :     aRet = aStaggerDirection*nDistance;
     311             : 
     312             :     //add extra distance for vertical distance
     313         479 :     if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY()))
     314           9 :         aRet += rDistanceTickToText;
     315             : 
     316         479 :     return aRet;
     317             : }
     318             : 
     319         479 : void lcl_shiftLables( TickIter& rIter, const B2DVector& rStaggerDistance )
     320             : {
     321         479 :     if(rStaggerDistance.getLength()==0.0)
     322         481 :         return;
     323         477 :     Reference< drawing::XShape >  xShape2DText(NULL);
     324        1440 :     for( TickInfo* pTickInfo = rIter.firstInfo()
     325             :         ; pTickInfo
     326         963 :         ; pTickInfo = rIter.nextInfo() )
     327             :     {
     328         963 :         xShape2DText = pTickInfo->xTextShape;
     329         963 :         if( xShape2DText.is() )
     330             :         {
     331         963 :             awt::Point aPos  = xShape2DText->getPosition();
     332         963 :             aPos.X += static_cast<sal_Int32>(rStaggerDistance.getX());
     333         963 :             aPos.Y += static_cast<sal_Int32>(rStaggerDistance.getY());
     334         963 :             xShape2DText->setPosition( aPos );
     335             :         }
     336         477 :     }
     337             : }
     338             : 
     339           0 : bool lcl_hasWordBreak( const Reference< drawing::XShape >& rxShape )
     340             : {
     341           0 :     if ( rxShape.is() )
     342             :     {
     343           0 :         SvxShape* pShape = SvxShape::getImplementation( rxShape );
     344           0 :         SvxShapeText* pShapeText = dynamic_cast< SvxShapeText* >( pShape );
     345           0 :         if ( pShapeText )
     346             :         {
     347           0 :             SvxTextEditSource* pTextEditSource = dynamic_cast< SvxTextEditSource* >( pShapeText->GetEditSource() );
     348           0 :             if ( pTextEditSource )
     349             :             {
     350           0 :                 pTextEditSource->UpdateOutliner();
     351           0 :                 SvxTextForwarder* pTextForwarder = pTextEditSource->GetTextForwarder();
     352           0 :                 if ( pTextForwarder )
     353             :                 {
     354           0 :                     sal_Int32 nParaCount = pTextForwarder->GetParagraphCount();
     355           0 :                     for ( sal_Int32 nPara = 0; nPara < nParaCount; ++nPara )
     356             :                     {
     357           0 :                         sal_uInt16 nLineCount = pTextForwarder->GetLineCount( nPara );
     358           0 :                         for ( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
     359             :                         {
     360           0 :                             sal_uInt16 nLineStart = 0;
     361           0 :                             sal_uInt16 nLineEnd = 0;
     362           0 :                             pTextForwarder->GetLineBoundaries( nLineStart, nLineEnd, nPara, nLine );
     363           0 :                             sal_uInt16 nWordStart = 0;
     364           0 :                             sal_uInt16 nWordEnd = 0;
     365           0 :                             if ( pTextForwarder->GetWordIndices( nPara, nLineStart, nWordStart, nWordEnd ) &&
     366           0 :                                  ( nWordStart != nLineStart ) )
     367             :                             {
     368           0 :                                 return true;
     369             :                             }
     370             :                         }
     371             :                     }
     372             :                 }
     373             :             }
     374             :         }
     375             :     }
     376             : 
     377           0 :     return false;
     378             : }
     379             : 
     380             : class MaxLabelTickIter : public TickIter
     381             : {
     382             :     //iterate over first two and last two labels and the longest label
     383             : public:
     384             :     MaxLabelTickIter( ::std::vector< TickInfo >& rTickInfoVector
     385             :             , sal_Int32 nLongestLabelIndex );
     386             :     virtual ~MaxLabelTickIter();
     387             : 
     388             :     virtual TickInfo* firstInfo();
     389             :     virtual TickInfo* nextInfo();
     390             : 
     391             : private:
     392             :     ::std::vector< TickInfo >& m_rTickInfoVector;
     393             :     ::std::vector< sal_Int32 > m_aValidIndices;
     394             :     sal_Int32 m_nCurrentIndex;
     395             : };
     396             : 
     397         925 : MaxLabelTickIter::MaxLabelTickIter( ::std::vector< TickInfo >& rTickInfoVector
     398             :             , sal_Int32 nLongestLabelIndex )
     399             :             : m_rTickInfoVector(rTickInfoVector)
     400         925 :             , m_nCurrentIndex(0)
     401             : {
     402         925 :     sal_Int32 nMaxIndex = m_rTickInfoVector.size()-1;
     403         925 :     if( nLongestLabelIndex<0 || nLongestLabelIndex>=nMaxIndex-1 )
     404           8 :         nLongestLabelIndex = 0;
     405             : 
     406         925 :     if( nMaxIndex>=0 )
     407         925 :         m_aValidIndices.push_back(0);
     408         925 :     if( nMaxIndex>=1 )
     409         924 :         m_aValidIndices.push_back(1);
     410         925 :     if( nLongestLabelIndex>1 )
     411           0 :         m_aValidIndices.push_back(nLongestLabelIndex);
     412         925 :     if( nMaxIndex > 2 )
     413         895 :         m_aValidIndices.push_back(nMaxIndex-1);
     414         925 :     if( nMaxIndex > 1 )
     415         917 :         m_aValidIndices.push_back(nMaxIndex);
     416         925 : }
     417        1850 : MaxLabelTickIter::~MaxLabelTickIter()
     418             : {
     419        1850 : }
     420             : 
     421         925 : TickInfo* MaxLabelTickIter::firstInfo()
     422             : {
     423         925 :     m_nCurrentIndex = 0;
     424         925 :     if( m_nCurrentIndex < static_cast<sal_Int32>(m_aValidIndices.size()) )
     425         925 :         return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]];
     426           0 :     return 0;
     427             : }
     428             : 
     429        3661 : TickInfo* MaxLabelTickIter::nextInfo()
     430             : {
     431        3661 :     m_nCurrentIndex++;
     432        3661 :     if( m_nCurrentIndex>=0 && m_nCurrentIndex<static_cast<sal_Int32>(m_aValidIndices.size()) )
     433        2736 :         return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]];
     434         925 :     return 0;
     435             : }
     436             : 
     437        1890 : bool VCartesianAxis::isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
     438             :                                                      , bool bIsHorizontalAxis )
     439             : {
     440        1890 :     if( m_aTextLabels.getLength() > 100 )
     441           0 :         return false;
     442        1890 :     if( !rAxisLabelProperties.bLineBreakAllowed )
     443        1838 :         return false;
     444          52 :     if( rAxisLabelProperties.bStackCharacters )
     445           1 :         return false;
     446             :     //no break for value axis
     447          51 :     if( !m_bUseTextLabels )
     448           6 :         return false;
     449          45 :     if( !::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) )
     450           0 :         return false;
     451             :     //break only for horizontal axis
     452          45 :     return bIsHorizontalAxis;
     453             : }
     454             : 
     455         965 : bool VCartesianAxis::isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
     456             :                                                      , bool bIsHorizontalAxis, bool bIsVerticalAxis )
     457             : {
     458         965 :     if( rAxisLabelProperties.eStaggering != STAGGER_AUTO )
     459         105 :         return false;
     460         860 :     if( rAxisLabelProperties.bOverlapAllowed )
     461           3 :         return false;
     462         857 :     if( rAxisLabelProperties.bLineBreakAllowed ) //auto line break or auto staggering, doing both automatisms they may conflict...
     463           0 :         return false;
     464         857 :     if( !::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) )
     465           4 :         return false;
     466             :     //automatic staggering only for horizontal axis with horizontal text
     467             :     //or vertical axis with vertical text
     468         853 :     if( bIsHorizontalAxis )
     469         470 :         return !rAxisLabelProperties.bStackCharacters;
     470         383 :     if( bIsVerticalAxis )
     471         374 :         return rAxisLabelProperties.bStackCharacters;
     472           9 :     return false;
     473             : }
     474             : 
     475             : struct ComplexCategoryPlacement
     476             : {
     477             :     OUString Text;
     478             :     sal_Int32 Count;
     479             :     double TickValue;
     480             : 
     481             :     ComplexCategoryPlacement( const OUString& rText, sal_Int32 nCount, double fTickValue )
     482             :         : Text(rText), Count(nCount), TickValue(fTickValue)
     483             :     {}
     484             : };
     485             : 
     486           0 : void VCartesianAxis::createAllTickInfosFromComplexCategories( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShiftedPosition )
     487             : {
     488             :     //no minor tickmarks will be generated!
     489             :     //order is: inner labels first , outer labels last (that is different to all other TickIter cases)
     490           0 :     if(!bShiftedPosition)
     491             :     {
     492           0 :         rAllTickInfos.clear();
     493           0 :         sal_Int32 nLevel=0;
     494           0 :         sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
     495           0 :         for( ; nLevel<nLevelCount; nLevel++ )
     496             :         {
     497           0 :             ::std::vector< TickInfo > aTickInfoVector;
     498             :             const std::vector<ComplexCategory>* pComplexCategories =
     499           0 :                 m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel(nLevel);
     500             : 
     501           0 :             if (!pComplexCategories)
     502           0 :                 continue;
     503             : 
     504           0 :             sal_Int32 nCatIndex = 0;
     505           0 :             std::vector<ComplexCategory>::const_iterator aIt = pComplexCategories->begin();
     506           0 :             std::vector<ComplexCategory>::const_iterator aEnd = pComplexCategories->end();
     507             : 
     508           0 :             for(;aIt!=aEnd;++aIt)
     509             :             {
     510           0 :                 TickInfo aTickInfo(0);
     511           0 :                 ComplexCategory aCat(*aIt);
     512           0 :                 sal_Int32 nCount = aCat.Count;
     513           0 :                 if( nCatIndex + 1.0 + nCount >= m_aScale.Maximum )
     514             :                 {
     515           0 :                     nCount = static_cast<sal_Int32>(m_aScale.Maximum - 1.0 - nCatIndex);
     516           0 :                     if( nCount <= 0 )
     517           0 :                         nCount = 1;
     518             :                 }
     519           0 :                 aTickInfo.fScaledTickValue = nCatIndex + 1.0 + nCount/2.0;
     520           0 :                 aTickInfo.nFactorForLimitedTextWidth = nCount;
     521           0 :                 aTickInfo.aText = aCat.Text;
     522           0 :                 aTickInfoVector.push_back(aTickInfo);
     523           0 :                 nCatIndex += nCount;
     524           0 :                 if( nCatIndex + 1.0 >= m_aScale.Maximum )
     525           0 :                     break;
     526           0 :             }
     527           0 :             rAllTickInfos.push_back(aTickInfoVector);
     528           0 :         }
     529             :     }
     530             :     else //bShiftedPosition==false
     531             :     {
     532           0 :         rAllTickInfos.clear();
     533           0 :         sal_Int32 nLevel=0;
     534           0 :         sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
     535           0 :         for( ; nLevel<nLevelCount; nLevel++ )
     536             :         {
     537           0 :             ::std::vector< TickInfo > aTickInfoVector;
     538             :             const std::vector<ComplexCategory>* pComplexCategories =
     539           0 :                 m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel(nLevel);
     540           0 :             sal_Int32 nCatIndex = 0;
     541           0 :             if (pComplexCategories)
     542             :             {
     543           0 :                 std::vector<ComplexCategory>::const_iterator aIt = pComplexCategories->begin();
     544           0 :                 std::vector<ComplexCategory>::const_iterator aEnd = pComplexCategories->end();
     545           0 :                 for(;aIt!=aEnd;++aIt)
     546             :                 {
     547           0 :                     TickInfo aTickInfo(0);
     548           0 :                     ComplexCategory aCat(*aIt);
     549           0 :                     aTickInfo.fScaledTickValue = nCatIndex + 1.0;
     550           0 :                     aTickInfoVector.push_back(aTickInfo);
     551           0 :                     nCatIndex += aCat.Count;
     552           0 :                     if( nCatIndex + 1.0 > m_aScale.Maximum )
     553           0 :                         break;
     554           0 :                 }
     555             :             }
     556             : 
     557             :             //fill up with single ticks until maximum scale
     558           0 :             while( nCatIndex + 1.0 < m_aScale.Maximum )
     559             :             {
     560           0 :                 TickInfo aTickInfo(0);
     561           0 :                 aTickInfo.fScaledTickValue = nCatIndex + 1.0;
     562           0 :                 aTickInfoVector.push_back(aTickInfo);
     563           0 :                 nCatIndex ++;
     564           0 :                 if( nLevel>0 )
     565           0 :                     break;
     566           0 :             }
     567             :             //add an additional tick at the end
     568             :             {
     569           0 :                 TickInfo aTickInfo(0);
     570           0 :                 aTickInfo.fScaledTickValue = m_aScale.Maximum;
     571           0 :                 aTickInfoVector.push_back(aTickInfo);
     572             :             }
     573           0 :             rAllTickInfos.push_back(aTickInfoVector);
     574           0 :         }
     575             :     }
     576           0 : }
     577             : 
     578        1996 : void VCartesianAxis::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos )
     579             : {
     580        1996 :     if( isComplexCategoryAxis() )
     581           0 :         createAllTickInfosFromComplexCategories( rAllTickInfos, false );
     582             :     else
     583        1996 :         VAxisBase::createAllTickInfos(rAllTickInfos);
     584        1996 : }
     585             : 
     586         925 : TickIter* VCartesianAxis::createLabelTickIterator( sal_Int32 nTextLevel )
     587             : {
     588         925 :     if( nTextLevel>=0 && nTextLevel < static_cast< sal_Int32 >(m_aAllTickInfos.size()) )
     589         925 :         return new PureTickIter( m_aAllTickInfos[nTextLevel] );
     590           0 :     return NULL;
     591             : }
     592             : 
     593         925 : TickIter* VCartesianAxis::createMaximumLabelTickIterator( sal_Int32 nTextLevel )
     594             : {
     595         925 :     if( isComplexCategoryAxis() || isDateAxis() )
     596             :     {
     597           0 :         return createLabelTickIterator( nTextLevel ); //mmmm maybe todo: create less than all texts here
     598             :     }
     599             :     else
     600             :     {
     601         925 :         if(nTextLevel==0)
     602             :         {
     603         925 :             if( !m_aAllTickInfos.empty() )
     604             :             {
     605         925 :                 sal_Int32 nLongestLabelIndex = m_bUseTextLabels ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0;
     606         925 :                 return new MaxLabelTickIter( m_aAllTickInfos[0], nLongestLabelIndex );
     607             :             }
     608             :         }
     609             :     }
     610           0 :     return NULL;
     611             : }
     612             : 
     613        1850 : sal_Int32 VCartesianAxis::getTextLevelCount() const
     614             : {
     615        1850 :     sal_Int32 nTextLevelCount = 1;
     616        1850 :     if( isComplexCategoryAxis() )
     617           0 :         nTextLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
     618        1850 :     return nTextLevelCount;
     619             : }
     620             : 
     621        1890 : bool VCartesianAxis::createTextShapes(
     622             :                        const Reference< drawing::XShapes >& xTarget
     623             :                      , TickIter& rTickIter
     624             :                      , AxisLabelProperties& rAxisLabelProperties
     625             :                      , TickFactory_2D* pTickFactory
     626             :                      , sal_Int32 nScreenDistanceBetweenTicks )
     627             : {
     628             :     //returns true if the text shapes have been created successfully
     629             :     //otherwise false - in this case the AxisLabelProperties have changed
     630             :     //and contain new instructions for the next try for text shape creation
     631             : 
     632        1890 :     Reference< XScaling > xInverseScaling( NULL );
     633        1890 :     if( m_aScale.Scaling.is() )
     634         862 :         xInverseScaling = m_aScale.Scaling->getInverseScaling();
     635             : 
     636             :     FixedNumberFormatter aFixedNumberFormatter(
     637        3780 :                 m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey );
     638             : 
     639        1890 :     const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis();
     640        1890 :     const bool bIsVerticalAxis = pTickFactory->isVerticalAxis();
     641        1890 :     bool bIsStaggered = rAxisLabelProperties.getIsStaggered();
     642        3780 :     B2DVector aTextToTickDistance( pTickFactory->getDistanceAxisTickToText( m_aAxisProperties, true ) );
     643        1890 :     sal_Int32 nLimitedSpaceForText = -1;
     644        1890 :     if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis ) )
     645             :     {
     646          45 :         nLimitedSpaceForText = nScreenDistanceBetweenTicks;
     647          45 :         if( bIsStaggered )
     648           0 :             nLimitedSpaceForText *= 2;
     649             : 
     650          45 :         if( nLimitedSpaceForText > 0 )
     651             :         { //reduce space for a small amount to have a visible distance between the labels:
     652          45 :             sal_Int32 nReduce = (nLimitedSpaceForText*5)/100;
     653          45 :             if(!nReduce)
     654           0 :                 nReduce = 1;
     655          45 :             nLimitedSpaceForText -= nReduce;
     656             :         }
     657             :     }
     658             : 
     659        1890 :     uno::Sequence< OUString >* pCategories = 0;
     660        1890 :     if( m_bUseTextLabels && !m_aAxisProperties.m_bComplexCategories )
     661        1024 :         pCategories = &m_aTextLabels;
     662             : 
     663        1890 :     TickInfo* pPreviousVisibleTickInfo = NULL;
     664        1890 :     TickInfo* pPREPreviousVisibleTickInfo = NULL;
     665        1890 :     TickInfo* pLastVisibleNeighbourTickInfo = NULL;
     666             : 
     667             :     //------------------------------------------------
     668             :     //prepare properties for multipropertyset-interface of shape
     669        3780 :     tNameSequence aPropNames;
     670        3780 :     tAnySequence aPropValues;
     671             : 
     672        1890 :     bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
     673        3780 :     Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
     674             :     PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false
     675        1890 :         , nLimitedSpaceForText, bLimitedHeight );
     676             :     LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps
     677        1890 :         , m_aAxisLabelProperties.m_aFontReferenceSize );
     678        1890 :     LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, m_aAxisProperties.m_aLabelAlignment );
     679             : 
     680        1890 :     uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,"CharColor");
     681        1890 :     sal_Int32 nColor = Color( COL_AUTO ).GetColor();
     682        1890 :     if(pColorAny)
     683        1890 :         *pColorAny >>= nColor;
     684             : 
     685        1890 :     uno::Any* pLimitedSpaceAny = PropertyMapper::getValuePointerForLimitedSpace(aPropValues,aPropNames,bLimitedHeight);
     686             :     //------------------------------------------------
     687             : 
     688        1890 :     sal_Int32 nTick = 0;
     689       10736 :     for( TickInfo* pTickInfo = rTickIter.firstInfo()
     690             :         ; pTickInfo
     691        8846 :         ; pTickInfo = rTickIter.nextInfo(), nTick++ )
     692             :     {
     693             :         pLastVisibleNeighbourTickInfo = bIsStaggered ?
     694        8886 :                     pPREPreviousVisibleTickInfo : pPreviousVisibleTickInfo;
     695             : 
     696             :         //don't create labels which does not fit into the rhythm
     697        8886 :         if( nTick%rAxisLabelProperties.nRhythm != 0 )
     698          95 :             continue;
     699             : 
     700             :         //don't create labels for invisible ticks
     701        8847 :         if( !pTickInfo->bPaintIt )
     702           0 :             continue;
     703             : 
     704             :         //if NO OVERLAP -> don't create labels where the tick overlaps
     705             :         //with the text of the last neighbour tickmark
     706        8847 :         if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed )
     707             :         {
     708        4188 :             if( lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
     709             :                        , rAxisLabelProperties.fRotationAngleDegree
     710             :                        , pTickInfo->aTickScreenPosition
     711        4188 :                        , bIsHorizontalAxis, bIsVerticalAxis ) )
     712             :             {
     713          20 :                 bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true;
     714          20 :                 if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) )
     715             :                 {
     716           0 :                     bIsStaggered = true;
     717           0 :                     rAxisLabelProperties.eStaggering = STAGGER_EVEN;
     718           0 :                     pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
     719           0 :                     if( !pLastVisibleNeighbourTickInfo ||
     720             :                         !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
     721             :                                 , rAxisLabelProperties.fRotationAngleDegree
     722             :                                 , pTickInfo->aTickScreenPosition
     723           0 :                                 , bIsHorizontalAxis, bIsVerticalAxis ) )
     724           0 :                         bOverlapAlsoAfterSwitchingOnAutoStaggering = false;
     725             :                 }
     726          20 :                 if( bOverlapAlsoAfterSwitchingOnAutoStaggering )
     727             :                 {
     728          20 :                     if( rAxisLabelProperties.bRhythmIsFix )
     729           0 :                         continue;
     730          20 :                     rAxisLabelProperties.nRhythm++;
     731          20 :                     removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget );
     732          60 :                     return false;
     733             :                 }
     734             :             }
     735             :         }
     736             : 
     737             :         //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling );
     738             : 
     739        8827 :         bool bHasExtraColor=false;
     740        8827 :         sal_Int32 nExtraColor=0;
     741             : 
     742        8827 :         OUString aLabel;
     743        8827 :         if(pCategories)
     744             :         {
     745        4242 :             sal_Int32 nIndex = static_cast< sal_Int32 >(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0
     746        4242 :             if( nIndex>=0 && nIndex<pCategories->getLength() )
     747        4227 :                 aLabel = (*pCategories)[nIndex];
     748             :         }
     749        4585 :         else if( m_aAxisProperties.m_bComplexCategories )
     750             :         {
     751           0 :             aLabel = pTickInfo->aText;
     752             :         }
     753             :         else
     754        4585 :             aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor );
     755             : 
     756        8827 :         if(pColorAny)
     757        8827 :             *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor);
     758        8827 :         if(pLimitedSpaceAny)
     759         180 :             *pLimitedSpaceAny = uno::makeAny(sal_Int32(nLimitedSpaceForText*pTickInfo->nFactorForLimitedTextWidth));
     760             : 
     761       17617 :         B2DVector aTickScreenPos2D( pTickInfo->aTickScreenPosition );
     762        8827 :         aTickScreenPos2D += aTextToTickDistance;
     763             :         awt::Point aAnchorScreenPosition2D(
     764        8827 :             static_cast<sal_Int32>(aTickScreenPos2D.getX())
     765       17654 :             ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
     766             : 
     767             :         //create single label
     768        8827 :         if(!pTickInfo->xTextShape.is())
     769       17594 :             pTickInfo->xTextShape = createSingleLabel( m_xShapeFactory, xTarget
     770             :                                     , aAnchorScreenPosition2D, aLabel
     771             :                                     , rAxisLabelProperties, m_aAxisProperties
     772        8797 :                                     , aPropNames, aPropValues );
     773        8827 :         if(!pTickInfo->xTextShape.is())
     774          17 :             continue;
     775             : 
     776        8810 :         recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree );
     777             : 
     778             :          //better rotate if single words are broken apart
     779        8990 :         if( nLimitedSpaceForText>0 && !rAxisLabelProperties.bOverlapAllowed
     780         180 :                 && ::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 )
     781         180 :                 && m_aAxisProperties.m_bComplexCategories
     782        8810 :                 && lcl_hasWordBreak( pTickInfo->xTextShape ) )
     783             :         {
     784           0 :             rAxisLabelProperties.fRotationAngleDegree = 90;
     785           0 :             rAxisLabelProperties.bLineBreakAllowed = false;
     786           0 :             m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree;
     787           0 :             removeTextShapesFromTicks();
     788           0 :             return false;
     789             :         }
     790             : 
     791             :         //if NO OVERLAP -> remove overlapping shapes
     792        8810 :         if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed )
     793             :         {
     794        4168 :             if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ) )
     795             :             {
     796          20 :                 bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true;
     797          20 :                 if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) )
     798             :                 {
     799           0 :                     bIsStaggered = true;
     800           0 :                     rAxisLabelProperties.eStaggering = STAGGER_EVEN;
     801           0 :                     pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
     802           0 :                     if( !pLastVisibleNeighbourTickInfo ||
     803             :                         !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
     804             :                             , rAxisLabelProperties.fRotationAngleDegree
     805             :                             , pTickInfo->aTickScreenPosition
     806           0 :                             , bIsHorizontalAxis, bIsVerticalAxis ) )
     807           0 :                         bOverlapAlsoAfterSwitchingOnAutoStaggering = false;
     808             :                 }
     809          20 :                 if( bOverlapAlsoAfterSwitchingOnAutoStaggering )
     810             :                 {
     811             :                     /* Try auto-rotating to 45 degrees */
     812          20 :                     if( !rAxisLabelProperties.bOverlapAllowed && ::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) )
     813             :                     {
     814          10 :                         rAxisLabelProperties.fRotationAngleDegree = 45;
     815          10 :                         rAxisLabelProperties.bLineBreakAllowed = false;
     816          10 :                         rAxisLabelProperties.eStaggering = SIDE_BY_SIDE;
     817          10 :                         m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree;
     818          10 :                         removeTextShapesFromTicks();
     819          10 :                         return false;
     820             :                     }
     821          10 :                     if( rAxisLabelProperties.bRhythmIsFix )
     822             :                     {
     823           0 :                         xTarget->remove(pTickInfo->xTextShape);
     824           0 :                         pTickInfo->xTextShape = NULL;
     825           0 :                         continue;
     826             :                     }
     827          10 :                     rAxisLabelProperties.nRhythm++;
     828          10 :                     removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget );
     829          10 :                     return false;
     830             :                 }
     831             :             }
     832             :         }
     833             : 
     834        8790 :         pPREPreviousVisibleTickInfo = pPreviousVisibleTickInfo;
     835        8790 :         pPreviousVisibleTickInfo = pTickInfo;
     836        8790 :     }
     837        3740 :     return true;
     838             : }
     839             : 
     840           0 : drawing::PointSequenceSequence lcl_makePointSequence( B2DVector& rStart, B2DVector& rEnd )
     841             : {
     842           0 :     drawing::PointSequenceSequence aPoints(1);
     843           0 :     aPoints[0].realloc(2);
     844           0 :     aPoints[0][0].X = static_cast<sal_Int32>(rStart.getX());
     845           0 :     aPoints[0][0].Y = static_cast<sal_Int32>(rStart.getY());
     846           0 :     aPoints[0][1].X = static_cast<sal_Int32>(rEnd.getX());
     847           0 :     aPoints[0][1].Y = static_cast<sal_Int32>(rEnd.getY());
     848           0 :     return aPoints;
     849             : }
     850             : 
     851       12253 : double VCartesianAxis::getLogicValueWhereMainLineCrossesOtherAxis() const
     852             : {
     853       12253 :     double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
     854       12253 :     double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
     855             : 
     856             :     double fCrossesOtherAxis;
     857       12253 :     if(m_aAxisProperties.m_pfMainLinePositionAtOtherAxis)
     858       11582 :         fCrossesOtherAxis = *m_aAxisProperties.m_pfMainLinePositionAtOtherAxis;
     859             :     else
     860             :     {
     861         671 :         if( ::com::sun::star::chart::ChartAxisPosition_END == m_aAxisProperties.m_eCrossoverType )
     862           0 :             fCrossesOtherAxis = fMax;
     863             :         else
     864         671 :             fCrossesOtherAxis = fMin;
     865             :     }
     866       12253 :     return fCrossesOtherAxis;
     867             : }
     868             : 
     869        5802 : double VCartesianAxis::getLogicValueWhereLabelLineCrossesOtherAxis() const
     870             : {
     871        5802 :     double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
     872        5802 :     double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
     873             : 
     874             :     double fCrossesOtherAxis;
     875        5802 :     if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == m_aAxisProperties.m_eLabelPos )
     876         276 :         fCrossesOtherAxis = fMin;
     877        5526 :     else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == m_aAxisProperties.m_eLabelPos )
     878           0 :         fCrossesOtherAxis = fMax;
     879             :     else
     880        5526 :         fCrossesOtherAxis = getLogicValueWhereMainLineCrossesOtherAxis();
     881        5802 :     return fCrossesOtherAxis;
     882             : }
     883             : 
     884           0 : bool VCartesianAxis::getLogicValueWhereExtraLineCrossesOtherAxis( double& fCrossesOtherAxis ) const
     885             : {
     886           0 :     if( !m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis )
     887           0 :         return false;
     888           0 :     double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
     889           0 :     double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
     890           0 :     if( *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis <= fMin
     891           0 :         || *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis >= fMax )
     892           0 :         return false;
     893           0 :     fCrossesOtherAxis = *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis;
     894           0 :     return true;
     895             : }
     896             : 
     897       25058 : B2DVector VCartesianAxis::getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const
     898             : {
     899       25058 :     B2DVector aRet(0,0);
     900             : 
     901       25058 :     if( m_pPosHelper )
     902             :     {
     903       25058 :         drawing::Position3D aScenePos = m_pPosHelper->transformLogicToScene( fLogicX, fLogicY, fLogicZ, true );
     904       25058 :         if(3==m_nDimension)
     905             :         {
     906         584 :             if( m_xLogicTarget.is() && m_pPosHelper && m_pShapeFactory )
     907             :             {
     908         584 :                 tPropertyNameMap aDummyPropertyNameMap;
     909             :                 Reference< drawing::XShape > xShape3DAnchor = m_pShapeFactory->createCube( m_xLogicTarget
     910        1168 :                         , aScenePos,drawing::Direction3D(1,1,1), 0, 0, aDummyPropertyNameMap);
     911         584 :                 awt::Point a2DPos = xShape3DAnchor->getPosition(); //get 2D position from xShape3DAnchor
     912         584 :                 m_xLogicTarget->remove(xShape3DAnchor);
     913         584 :                 aRet.setX( a2DPos.X );
     914        1168 :                 aRet.setY( a2DPos.Y );
     915             :             }
     916             :             else
     917             :             {
     918             :                 OSL_FAIL("cannot calculate scrren position in VCartesianAxis::getScreenPosition");
     919             :             }
     920             :         }
     921             :         else
     922             :         {
     923       24474 :             aRet.setX( aScenePos.PositionX );
     924       24474 :             aRet.setY( aScenePos.PositionY );
     925             :         }
     926             :     }
     927             : 
     928       25058 :     return aRet;
     929             : }
     930             : 
     931           0 : VCartesianAxis::ScreenPosAndLogicPos VCartesianAxis::getScreenPosAndLogicPos( double fLogicX_, double fLogicY_, double fLogicZ_ ) const
     932             : {
     933           0 :     ScreenPosAndLogicPos aRet;
     934           0 :     aRet.fLogicX = fLogicX_;
     935           0 :     aRet.fLogicY = fLogicY_;
     936           0 :     aRet.fLogicZ = fLogicZ_;
     937           0 :     aRet.aScreenPos = getScreenPosition( fLogicX_, fLogicY_, fLogicZ_ );
     938           0 :     return aRet;
     939             : }
     940             : 
     941             : typedef ::std::vector< VCartesianAxis::ScreenPosAndLogicPos > tScreenPosAndLogicPosList;
     942             : struct lcl_LessXPos : ::std::binary_function< VCartesianAxis::ScreenPosAndLogicPos, VCartesianAxis::ScreenPosAndLogicPos, bool >
     943             : {
     944           0 :     inline bool operator() ( const VCartesianAxis::ScreenPosAndLogicPos& rPos1, const VCartesianAxis::ScreenPosAndLogicPos& rPos2 )
     945             :     {
     946           0 :         return ( rPos1.aScreenPos.getX() < rPos2.aScreenPos.getX() );
     947             :     }
     948             : };
     949             : 
     950             : struct lcl_GreaterYPos : ::std::binary_function< VCartesianAxis::ScreenPosAndLogicPos, VCartesianAxis::ScreenPosAndLogicPos, bool >
     951             : {
     952           0 :     inline bool operator() ( const VCartesianAxis::ScreenPosAndLogicPos& rPos1, const VCartesianAxis::ScreenPosAndLogicPos& rPos2 )
     953             :     {
     954           0 :         return ( rPos1.aScreenPos.getY() > rPos2.aScreenPos.getY() );
     955             :     }
     956             : };
     957             : 
     958       12529 : void VCartesianAxis::get2DAxisMainLine( B2DVector& rStart, B2DVector& rEnd, double fCrossesOtherAxis )
     959             : {
     960             :     //m_aAxisProperties might get updated and changed here because
     961             :     //    the label alignmant and inner direction sign depends exactly of the choice of the axis line position which is made here in this method
     962             : 
     963       12529 :     double fMinX = m_pPosHelper->getLogicMinX();
     964       12529 :     double fMinY = m_pPosHelper->getLogicMinY();
     965       12529 :     double fMinZ = m_pPosHelper->getLogicMinZ();
     966       12529 :     double fMaxX = m_pPosHelper->getLogicMaxX();
     967       12529 :     double fMaxY = m_pPosHelper->getLogicMaxY();
     968       12529 :     double fMaxZ = m_pPosHelper->getLogicMaxZ();
     969             : 
     970       12529 :     double fXStart = fMinX;
     971       12529 :     double fYStart = fMinY;
     972       12529 :     double fZStart = fMinZ;
     973       12529 :     double fXEnd = fXStart;
     974       12529 :     double fYEnd = fYStart;
     975       12529 :     double fZEnd = fZStart;
     976             : 
     977       12529 :     double fXOnXPlane = fMinX;
     978       12529 :     double fXOther = fMaxX;
     979       12529 :     int nDifferentValue = !m_pPosHelper->isMathematicalOrientationX() ? -1 : 1;
     980       12529 :     if( !m_pPosHelper->isSwapXAndY() )
     981       12380 :         nDifferentValue *= (CuboidPlanePosition_Left != m_eLeftWallPos) ? -1 : 1;
     982             :     else
     983         149 :         nDifferentValue *= (CuboidPlanePosition_Bottom != m_eBottomPos) ? -1 : 1;
     984       12529 :     if( nDifferentValue<0 )
     985             :     {
     986           0 :         fXOnXPlane = fMaxX;
     987           0 :         fXOther = fMinX;
     988             :     }
     989             : 
     990       12529 :     double fYOnYPlane = fMinY;
     991       12529 :     double fYOther = fMaxY;
     992       12529 :     nDifferentValue = !m_pPosHelper->isMathematicalOrientationY() ? -1 : 1;
     993       12529 :     if( !m_pPosHelper->isSwapXAndY() )
     994       12380 :         nDifferentValue *= (CuboidPlanePosition_Bottom != m_eBottomPos) ? -1 : 1;
     995             :     else
     996         149 :         nDifferentValue *= (CuboidPlanePosition_Left != m_eLeftWallPos) ? -1 : 1;
     997       12529 :     if( nDifferentValue<0 )
     998             :     {
     999         333 :         fYOnYPlane = fMaxY;
    1000         333 :         fYOther = fMinY;
    1001             :     }
    1002             : 
    1003       12529 :     double fZOnZPlane = fMaxZ;
    1004       12529 :     double fZOther = fMinZ;
    1005       12529 :     nDifferentValue = !m_pPosHelper->isMathematicalOrientationZ() ? -1 : 1;
    1006       12529 :     nDifferentValue *= (CuboidPlanePosition_Back != m_eBackWallPos) ? -1 : 1;
    1007       12529 :     if( nDifferentValue<0 )
    1008             :     {
    1009           0 :         fZOnZPlane = fMinZ;
    1010           0 :         fZOther = fMaxZ;
    1011             :     }
    1012             : 
    1013       12529 :     if( 0==m_nDimensionIndex ) //x-axis
    1014             :     {
    1015        6733 :         if( fCrossesOtherAxis < fMinY )
    1016        1456 :             fCrossesOtherAxis = fMinY;
    1017        5277 :         else if( fCrossesOtherAxis > fMaxY )
    1018           0 :             fCrossesOtherAxis = fMaxY;
    1019             : 
    1020        6733 :         fYStart = fYEnd = fCrossesOtherAxis;
    1021        6733 :         fXEnd=m_pPosHelper->getLogicMaxX();
    1022             : 
    1023        6733 :         if(3==m_nDimension)
    1024             :         {
    1025         104 :             if( AxisHelper::isAxisPositioningEnabled() )
    1026             :             {
    1027         104 :                 if( ::rtl::math::approxEqual( fYOther, fYStart) )
    1028           0 :                     fZStart = fZEnd = fZOnZPlane;
    1029             :                 else
    1030         104 :                     fZStart = fZEnd = fZOther;
    1031             :             }
    1032             :             else
    1033             :             {
    1034           0 :                 rStart = getScreenPosition( fXStart, fYStart, fZStart );
    1035           0 :                 rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
    1036             : 
    1037           0 :                 double fDeltaX = rEnd.getX() - rStart.getX();
    1038           0 :                 double fDeltaY = rEnd.getY() - rStart.getY();
    1039             : 
    1040             :                 //only those points are candidates which are lying on exactly one wall as these are outer edges
    1041           0 :                 tScreenPosAndLogicPosList aPosList;
    1042           0 :                 aPosList.push_back( getScreenPosAndLogicPos( fMinX, fYOnYPlane, fZOther ) );
    1043           0 :                 aPosList.push_back( getScreenPosAndLogicPos( fMinX, fYOther, fZOnZPlane ) );
    1044             : 
    1045           0 :                 if( fabs(fDeltaY) > fabs(fDeltaX)  )
    1046             :                 {
    1047           0 :                     m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_LEFT;
    1048             :                     //choose most left positions
    1049           0 :                     ::std::sort( aPosList.begin(), aPosList.end(), lcl_LessXPos() );
    1050           0 :                     m_aAxisProperties.m_fLabelDirectionSign = fDeltaY<0 ? -1 : 1;
    1051             :                 }
    1052             :                 else
    1053             :                 {
    1054           0 :                     m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_BOTTOM;
    1055             :                     //choose most bottom positions
    1056           0 :                     ::std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
    1057           0 :                     m_aAxisProperties.m_fLabelDirectionSign = fDeltaX<0 ? -1 : 1;
    1058             :                 }
    1059           0 :                 ScreenPosAndLogicPos aBestPos( aPosList[0] );
    1060           0 :                 fYStart = fYEnd = aBestPos.fLogicY;
    1061           0 :                 fZStart = fZEnd = aBestPos.fLogicZ;
    1062           0 :                 if( !m_pPosHelper->isMathematicalOrientationX() )
    1063           0 :                     m_aAxisProperties.m_fLabelDirectionSign *= -1;
    1064             :             }
    1065             :         }//end 3D x axis
    1066             :     }
    1067        5796 :     else if( 1==m_nDimensionIndex ) //y-axis
    1068             :     {
    1069        5713 :         if( fCrossesOtherAxis < fMinX )
    1070        5016 :             fCrossesOtherAxis = fMinX;
    1071         697 :         else if( fCrossesOtherAxis > fMaxX )
    1072           0 :             fCrossesOtherAxis = fMaxX;
    1073             : 
    1074        5713 :         fXStart = fXEnd = fCrossesOtherAxis;
    1075        5713 :         fYEnd=m_pPosHelper->getLogicMaxY();
    1076             : 
    1077        5713 :         if(3==m_nDimension)
    1078             :         {
    1079         105 :             if( AxisHelper::isAxisPositioningEnabled() )
    1080             :             {
    1081         105 :                 if( ::rtl::math::approxEqual( fXOther, fXStart) )
    1082           0 :                     fZStart = fZEnd = fZOnZPlane;
    1083             :                 else
    1084         105 :                     fZStart = fZEnd = fZOther;
    1085             :             }
    1086             :             else
    1087             :             {
    1088           0 :                 rStart = getScreenPosition( fXStart, fYStart, fZStart );
    1089           0 :                 rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
    1090             : 
    1091           0 :                 double fDeltaX = rEnd.getX() - rStart.getX();
    1092           0 :                 double fDeltaY = rEnd.getY() - rStart.getY();
    1093             : 
    1094             :                 //only those points are candidates which are lying on exactly one wall as these are outer edges
    1095           0 :                 tScreenPosAndLogicPosList aPosList;
    1096           0 :                 aPosList.push_back( getScreenPosAndLogicPos( fXOnXPlane, fMinY, fZOther ) );
    1097           0 :                 aPosList.push_back( getScreenPosAndLogicPos( fXOther, fMinY, fZOnZPlane ) );
    1098             : 
    1099           0 :                 if( fabs(fDeltaY) > fabs(fDeltaX)  )
    1100             :                 {
    1101           0 :                     m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_LEFT;
    1102             :                     //choose most left positions
    1103           0 :                     ::std::sort( aPosList.begin(), aPosList.end(), lcl_LessXPos() );
    1104           0 :                     m_aAxisProperties.m_fLabelDirectionSign = fDeltaY<0 ? -1 : 1;
    1105             :                 }
    1106             :                 else
    1107             :                 {
    1108           0 :                     m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_BOTTOM;
    1109             :                     //choose most bottom positions
    1110           0 :                     ::std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
    1111           0 :                     m_aAxisProperties.m_fLabelDirectionSign = fDeltaX<0 ? -1 : 1;
    1112             :                 }
    1113           0 :                 ScreenPosAndLogicPos aBestPos( aPosList[0] );
    1114           0 :                 fXStart = fXEnd = aBestPos.fLogicX;
    1115           0 :                 fZStart = fZEnd = aBestPos.fLogicZ;
    1116           0 :                 if( !m_pPosHelper->isMathematicalOrientationY() )
    1117           0 :                     m_aAxisProperties.m_fLabelDirectionSign *= -1;
    1118             :             }
    1119             :         }//end 3D y axis
    1120             :     }
    1121             :     else //z-axis
    1122             :     {
    1123          83 :         fZEnd = m_pPosHelper->getLogicMaxZ();
    1124          83 :         if( AxisHelper::isAxisPositioningEnabled() )
    1125             :         {
    1126          83 :             if( !m_aAxisProperties.m_bSwapXAndY )
    1127             :             {
    1128          38 :                 if( fCrossesOtherAxis < fMinY )
    1129           0 :                     fCrossesOtherAxis = fMinY;
    1130          38 :                 else if( fCrossesOtherAxis > fMaxY )
    1131           0 :                     fCrossesOtherAxis = fMaxY;
    1132          38 :                 fYStart = fYEnd = fCrossesOtherAxis;
    1133             : 
    1134          38 :                 if( ::rtl::math::approxEqual( fYOther, fYStart) )
    1135           0 :                     fXStart = fXEnd = fXOnXPlane;
    1136             :                 else
    1137          38 :                     fXStart = fXEnd = fXOther;
    1138             :             }
    1139             :             else
    1140             :             {
    1141          45 :                 if( fCrossesOtherAxis < fMinX )
    1142          45 :                     fCrossesOtherAxis = fMinX;
    1143           0 :                 else if( fCrossesOtherAxis > fMaxX )
    1144           0 :                     fCrossesOtherAxis = fMaxX;
    1145          45 :                 fXStart = fXEnd = fCrossesOtherAxis;
    1146             : 
    1147          45 :                 if( ::rtl::math::approxEqual( fXOther, fXStart) )
    1148           0 :                     fYStart = fYEnd = fYOnYPlane;
    1149             :                 else
    1150          45 :                     fYStart = fYEnd = fYOther;
    1151             :             }
    1152             :         }
    1153             :         else
    1154             :         {
    1155           0 :             if( !m_pPosHelper->isSwapXAndY() )
    1156             :             {
    1157           0 :                 fXStart = fXEnd = m_pPosHelper->isMathematicalOrientationX() ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMinX();
    1158           0 :                 fYStart = fYEnd = m_pPosHelper->isMathematicalOrientationY() ? m_pPosHelper->getLogicMinY() : m_pPosHelper->getLogicMaxY();
    1159             :             }
    1160             :             else
    1161             :             {
    1162           0 :                 fXStart = fXEnd = m_pPosHelper->isMathematicalOrientationX() ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMaxX();
    1163           0 :                 fYStart = fYEnd = m_pPosHelper->isMathematicalOrientationY() ? m_pPosHelper->getLogicMaxY() : m_pPosHelper->getLogicMinY();
    1164             :             }
    1165             : 
    1166           0 :             if(3==m_nDimension)
    1167             :             {
    1168           0 :                 rStart = getScreenPosition( fXStart, fYStart, fZStart );
    1169           0 :                 rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
    1170             : 
    1171           0 :                 double fDeltaX = rEnd.getX() - rStart.getX();
    1172             : 
    1173             :                 //only those points are candidates which are lying on exactly one wall as these are outer edges
    1174           0 :                 tScreenPosAndLogicPosList aPosList;
    1175           0 :                 aPosList.push_back( getScreenPosAndLogicPos( fXOther, fYOnYPlane, fMinZ ) );
    1176           0 :                 aPosList.push_back( getScreenPosAndLogicPos( fXOnXPlane, fYOther, fMinZ ) );
    1177             : 
    1178           0 :                 ::std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
    1179           0 :                 ScreenPosAndLogicPos aBestPos( aPosList[0] );
    1180           0 :                 ScreenPosAndLogicPos aNotSoGoodPos( aPosList[1] );
    1181             : 
    1182             :                 //choose most bottom positions
    1183           0 :                 if( !::rtl::math::approxEqual( fDeltaX, 0.0 ) ) // prefere left-right algnments
    1184             :                 {
    1185           0 :                     if( aBestPos.aScreenPos.getX() > aNotSoGoodPos.aScreenPos.getX() )
    1186           0 :                         m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_RIGHT;
    1187             :                     else
    1188           0 :                          m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_LEFT;
    1189             :                 }
    1190             :                 else
    1191             :                 {
    1192           0 :                     if( aBestPos.aScreenPos.getY() > aNotSoGoodPos.aScreenPos.getY() )
    1193           0 :                         m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_BOTTOM;
    1194             :                     else
    1195           0 :                          m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_TOP;
    1196             :                 }
    1197             : 
    1198           0 :                 m_aAxisProperties.m_fLabelDirectionSign = fDeltaX<0 ? -1 : 1;
    1199           0 :                 if( !m_pPosHelper->isMathematicalOrientationZ() )
    1200           0 :                     m_aAxisProperties.m_fLabelDirectionSign *= -1;
    1201             : 
    1202           0 :                 fXStart = fXEnd = aBestPos.fLogicX;
    1203           0 :                 fYStart = fYEnd = aBestPos.fLogicY;
    1204             :             }
    1205             :         }//end 3D z axis
    1206             :     }
    1207             : 
    1208       12529 :     rStart = getScreenPosition( fXStart, fYStart, fZStart );
    1209       12529 :     rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
    1210             : 
    1211       12529 :     if(3==m_nDimension && !AxisHelper::isAxisPositioningEnabled() )
    1212           0 :         m_aAxisProperties.m_fInnerDirectionSign = m_aAxisProperties.m_fLabelDirectionSign;//to behave like before
    1213             : 
    1214       12529 :     if(3==m_nDimension && AxisHelper::isAxisPositioningEnabled() )
    1215             :     {
    1216         292 :         double fDeltaX = rEnd.getX() - rStart.getX();
    1217         292 :         double fDeltaY = rEnd.getY() - rStart.getY();
    1218             : 
    1219         292 :         if( 2==m_nDimensionIndex )
    1220             :         {
    1221          83 :             if( m_eLeftWallPos != CuboidPlanePosition_Left )
    1222             :             {
    1223           0 :                 m_aAxisProperties.m_fLabelDirectionSign *= -1.0;
    1224           0 :                 m_aAxisProperties.m_fInnerDirectionSign *= -1.0;
    1225             :             }
    1226             : 
    1227             :             m_aAxisProperties.m_aLabelAlignment =
    1228          83 :                 ( m_aAxisProperties.m_fLabelDirectionSign<0 ) ?
    1229          83 :                     LABEL_ALIGN_LEFT :  LABEL_ALIGN_RIGHT;
    1230             : 
    1231          83 :             if( ( fDeltaY<0 && m_aScale.Orientation == AxisOrientation_REVERSE ) ||
    1232           0 :                 ( fDeltaY>0 && m_aScale.Orientation == AxisOrientation_MATHEMATICAL ) )
    1233             :                 m_aAxisProperties.m_aLabelAlignment =
    1234           0 :                     ( m_aAxisProperties.m_aLabelAlignment==LABEL_ALIGN_RIGHT ) ?
    1235           0 :                         LABEL_ALIGN_LEFT :  LABEL_ALIGN_RIGHT;
    1236             :         }
    1237         209 :         else if( fabs(fDeltaY) > fabs(fDeltaX) )
    1238             :         {
    1239         105 :             if( m_eBackWallPos != CuboidPlanePosition_Back )
    1240             :             {
    1241           0 :                 m_aAxisProperties.m_fLabelDirectionSign *= -1.0;
    1242           0 :                 m_aAxisProperties.m_fInnerDirectionSign *= -1.0;
    1243             :             }
    1244             : 
    1245             :             m_aAxisProperties.m_aLabelAlignment =
    1246         105 :                 ( m_aAxisProperties.m_fLabelDirectionSign<0 ) ?
    1247         105 :                     LABEL_ALIGN_LEFT :  LABEL_ALIGN_RIGHT;
    1248             : 
    1249         105 :             if( ( fDeltaY<0 && m_aScale.Orientation == AxisOrientation_REVERSE ) ||
    1250           0 :                 ( fDeltaY>0 && m_aScale.Orientation == AxisOrientation_MATHEMATICAL ) )
    1251             :                 m_aAxisProperties.m_aLabelAlignment =
    1252           0 :                     ( m_aAxisProperties.m_aLabelAlignment==LABEL_ALIGN_RIGHT ) ?
    1253           0 :                         LABEL_ALIGN_LEFT :  LABEL_ALIGN_RIGHT;
    1254             :         }
    1255             :         else
    1256             :         {
    1257         104 :             if( m_eBackWallPos != CuboidPlanePosition_Back )
    1258             :             {
    1259           0 :                 m_aAxisProperties.m_fLabelDirectionSign *= -1.0;
    1260           0 :                 m_aAxisProperties.m_fInnerDirectionSign *= -1.0;
    1261             :             }
    1262             : 
    1263             :             m_aAxisProperties.m_aLabelAlignment =
    1264         104 :                 ( m_aAxisProperties.m_fLabelDirectionSign<0 ) ?
    1265         104 :                     LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
    1266             : 
    1267         104 :             if( ( fDeltaX>0 && m_aScale.Orientation == AxisOrientation_REVERSE ) ||
    1268           0 :                 ( fDeltaX<0 && m_aScale.Orientation == AxisOrientation_MATHEMATICAL ) )
    1269             :                 m_aAxisProperties.m_aLabelAlignment =
    1270           0 :                     ( m_aAxisProperties.m_aLabelAlignment==LABEL_ALIGN_TOP ) ?
    1271           0 :                         LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
    1272             :         }
    1273             :     }
    1274       12529 : }
    1275             : 
    1276        1996 : TickFactory* VCartesianAxis::createTickFactory()
    1277             : {
    1278        1996 :     return createTickFactory2D();
    1279             : }
    1280             : 
    1281        5802 : TickFactory_2D* VCartesianAxis::createTickFactory2D()
    1282             : {
    1283       11604 :     B2DVector aStart, aEnd;
    1284        5802 :     this->get2DAxisMainLine( aStart, aEnd, this->getLogicValueWhereMainLineCrossesOtherAxis() );
    1285             : 
    1286       11604 :     B2DVector aLabelLineStart, aLabelLineEnd;
    1287        5802 :     this->get2DAxisMainLine( aLabelLineStart, aLabelLineEnd, this->getLogicValueWhereLabelLineCrossesOtherAxis() );
    1288             : 
    1289       11604 :     return new TickFactory_2D( m_aScale, m_aIncrement, aStart, aEnd, aLabelLineStart-aStart );
    1290             : }
    1291             : 
    1292        1401 : void lcl_hideIdenticalScreenValues( TickIter& rTickIter )
    1293             : {
    1294        1401 :     TickInfo* pPreviousTickInfo = rTickIter.firstInfo();
    1295        1401 :     if(!pPreviousTickInfo)
    1296        1401 :         return;
    1297        1401 :     pPreviousTickInfo->bPaintIt = true;
    1298       14736 :     for( TickInfo* pTickInfo = rTickIter.nextInfo(); pTickInfo; pTickInfo = rTickIter.nextInfo())
    1299             :     {
    1300             :         pTickInfo->bPaintIt =
    1301       13335 :             ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getX())
    1302       13335 :             != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getX()) )
    1303       18322 :             ||
    1304        4987 :             ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getY())
    1305       18322 :             != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getY()) );
    1306       13335 :         pPreviousTickInfo = pTickInfo;
    1307             :     }
    1308             : }
    1309             : 
    1310             : //'hide' tickmarks with identical screen values in aAllTickInfos
    1311        1401 : void VCartesianAxis::hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const
    1312             : {
    1313        1401 :     if( isComplexCategoryAxis() || isDateAxis() )
    1314             :     {
    1315           0 :         sal_Int32 nCount = rTickInfos.size();
    1316           0 :         for( sal_Int32 nN=0; nN<nCount; nN++ )
    1317             :         {
    1318           0 :             PureTickIter aTickIter( rTickInfos[nN] );
    1319           0 :             lcl_hideIdenticalScreenValues( aTickIter );
    1320           0 :         }
    1321             :     }
    1322             :     else
    1323             :     {
    1324        1401 :         EquidistantTickIter aTickIter( rTickInfos, m_aIncrement, 0, -1 );
    1325        1401 :         lcl_hideIdenticalScreenValues( aTickIter );
    1326             :     }
    1327        1401 : }
    1328             : 
    1329        2090 : sal_Int32 VCartesianAxis::estimateMaximumAutoMainIncrementCount()
    1330             : {
    1331        2090 :     sal_Int32 nRet = 10;
    1332             : 
    1333        2090 :     if( m_nMaximumTextWidthSoFar==0 && m_nMaximumTextHeightSoFar==0 )
    1334        1165 :         return nRet;
    1335             : 
    1336        1850 :     B2DVector aStart, aEnd;
    1337         925 :     this->get2DAxisMainLine( aStart, aEnd, this->getLogicValueWhereMainLineCrossesOtherAxis() );
    1338             : 
    1339         925 :     sal_Int32 nMaxHeight = static_cast<sal_Int32>(fabs(aEnd.getY()-aStart.getY()));
    1340         925 :     sal_Int32 nMaxWidth = static_cast<sal_Int32>(fabs(aEnd.getX()-aStart.getX()));
    1341             : 
    1342         925 :     sal_Int32 nTotalAvailable = nMaxHeight;
    1343         925 :     sal_Int32 nSingleNeeded = m_nMaximumTextHeightSoFar;
    1344             : 
    1345             :     //for horizontal axis:
    1346         925 :     if( (m_nDimensionIndex == 0 && !m_aAxisProperties.m_bSwapXAndY)
    1347         412 :         || (m_nDimensionIndex == 1 && m_aAxisProperties.m_bSwapXAndY) )
    1348             :     {
    1349         517 :         nTotalAvailable = nMaxWidth;
    1350         517 :         nSingleNeeded = m_nMaximumTextWidthSoFar;
    1351             :     }
    1352             : 
    1353         925 :     if( nSingleNeeded>0 )
    1354         925 :         nRet = nTotalAvailable/nSingleNeeded;
    1355             : 
    1356        1850 :     return nRet;
    1357             : }
    1358             : 
    1359        2808 : void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties, TickFactory_2D* pTickFactory2D )
    1360             : {
    1361        2808 :     if( !pTickFactory2D )
    1362        2808 :         return;
    1363             : 
    1364        2808 :     if( isComplexCategoryAxis() )
    1365             :     {
    1366           0 :         sal_Int32 nTextLevelCount = getTextLevelCount();
    1367           0 :         B2DVector aCummulatedLabelsDistance(0,0);
    1368           0 :         for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
    1369             :         {
    1370           0 :             boost::scoped_ptr<TickIter> apTickIter(createLabelTickIterator(nTextLevel));
    1371           0 :             if (apTickIter)
    1372             :             {
    1373           0 :                 double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree;
    1374           0 :                 if( nTextLevel>0 )
    1375             :                 {
    1376           0 :                     lcl_shiftLables( *apTickIter.get(), aCummulatedLabelsDistance );
    1377           0 :                     fRotationAngleDegree = 0.0;
    1378             :                 }
    1379           0 :                 aCummulatedLabelsDistance += lcl_getLabelsDistance( *apTickIter.get()
    1380             :                     , pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties )
    1381           0 :                     , fRotationAngleDegree );
    1382             :             }
    1383           0 :         }
    1384             :     }
    1385        2808 :     else if( rAxisLabelProperties.getIsStaggered() )
    1386             :     {
    1387         496 :         if( !m_aAllTickInfos.empty() )
    1388             :         {
    1389         479 :             LabelIterator aInnerIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, true );
    1390         958 :             LabelIterator aOuterIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, false );
    1391             : 
    1392             :             lcl_shiftLables( aOuterIter
    1393             :                 , lcl_getLabelsDistance( aInnerIter
    1394         958 :                     , pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties ), 0.0 ) );
    1395             :         }
    1396             :     }
    1397             : }
    1398             : 
    1399        1044 : void VCartesianAxis::createLabels()
    1400             : {
    1401        1044 :     if( !prepareShapeCreation() )
    1402          46 :         return;
    1403             : 
    1404             :     //-----------------------------------------
    1405             :     //create labels
    1406         998 :     if( m_aAxisProperties.m_bDisplayLabels )
    1407             :     {
    1408         925 :         boost::scoped_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() );
    1409         925 :         TickFactory_2D* pTickFactory2D = apTickFactory2D.get();
    1410         925 :         if( !pTickFactory2D )
    1411           0 :             return;
    1412             : 
    1413             :         //-----------------------------------------
    1414             :         //get the transformed screen values for all tickmarks in aAllTickInfos
    1415         925 :         pTickFactory2D->updateScreenValues( m_aAllTickInfos );
    1416             :         //-----------------------------------------
    1417             :         //'hide' tickmarks with identical screen values in aAllTickInfos
    1418         925 :         hideIdenticalScreenValues( m_aAllTickInfos );
    1419             : 
    1420         925 :         removeTextShapesFromTicks();
    1421             : 
    1422             :         //create tick mark text shapes
    1423         925 :         sal_Int32 nTextLevelCount = getTextLevelCount();
    1424         925 :         sal_Int32 nScreenDistanceBetweenTicks = -1;
    1425        1850 :         for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
    1426             :         {
    1427         925 :             boost::scoped_ptr< TickIter > apTickIter(createLabelTickIterator( nTextLevel ));
    1428         925 :             if(apTickIter)
    1429             :             {
    1430         925 :                 if(nTextLevel==0)
    1431             :                 {
    1432         925 :                     nScreenDistanceBetweenTicks = TickFactory_2D::getTickScreenDistance( *apTickIter.get() );
    1433         925 :                     if( nTextLevelCount>1 )
    1434           0 :                         nScreenDistanceBetweenTicks*=2; //the above used tick iter does contain also the sub ticks -> thus the given distance is only the half
    1435             :                 }
    1436             : 
    1437         925 :                 AxisLabelProperties aComplexProps(m_aAxisLabelProperties);
    1438         925 :                 if( m_aAxisProperties.m_bComplexCategories )
    1439             :                 {
    1440           0 :                     aComplexProps.bLineBreakAllowed = true;
    1441           0 :                     aComplexProps.bOverlapAllowed = !::rtl::math::approxEqual( aComplexProps.fRotationAngleDegree, 0.0 );
    1442             : 
    1443             :                 }
    1444         925 :                 AxisLabelProperties& rAxisLabelProperties =  m_aAxisProperties.m_bComplexCategories ? aComplexProps : m_aAxisLabelProperties;
    1445         925 :                 while( !createTextShapes( m_xTextTarget, *apTickIter.get(), rAxisLabelProperties, pTickFactory2D, nScreenDistanceBetweenTicks ) )
    1446             :                 {
    1447             :                 };
    1448             :             }
    1449         925 :         }
    1450         925 :         doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D );
    1451             :     }
    1452             : }
    1453             : 
    1454        1044 : void VCartesianAxis::createMaximumLabels()
    1455             : {
    1456        1044 :     TrueGuard aRecordMaximumTextSize(m_bRecordMaximumTextSize);
    1457             : 
    1458        1044 :     if( !prepareShapeCreation() )
    1459          46 :         return;
    1460             : 
    1461             :     //-----------------------------------------
    1462             :     //create labels
    1463         998 :     if( m_aAxisProperties.m_bDisplayLabels )
    1464             :     {
    1465         925 :         boost::scoped_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() );
    1466         925 :         TickFactory_2D* pTickFactory2D = apTickFactory2D.get();
    1467         925 :         if( !pTickFactory2D )
    1468           0 :             return;
    1469             : 
    1470             :         //-----------------------------------------
    1471             :         //get the transformed screen values for all tickmarks in aAllTickInfos
    1472         925 :         pTickFactory2D->updateScreenValues( m_aAllTickInfos );
    1473             : 
    1474             :         //create tick mark text shapes
    1475             :         //@todo: iterate through all tick depth which should be labeled
    1476             : 
    1477         925 :         AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties );
    1478         925 :         if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickFactory2D->isHorizontalAxis(), pTickFactory2D->isVerticalAxis() ) )
    1479         470 :             aAxisLabelProperties.eStaggering = STAGGER_EVEN;
    1480         925 :         aAxisLabelProperties.bOverlapAllowed = true;
    1481         925 :         aAxisLabelProperties.bLineBreakAllowed = false;
    1482         925 :         sal_Int32 nTextLevelCount = getTextLevelCount();
    1483        1850 :         for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
    1484             :         {
    1485         925 :             boost::scoped_ptr< TickIter > apTickIter(createMaximumLabelTickIterator( nTextLevel ));
    1486         925 :             if(apTickIter)
    1487             :             {
    1488         925 :                 while( !createTextShapes( m_xTextTarget, *apTickIter.get(), aAxisLabelProperties, pTickFactory2D, -1 ) )
    1489             :                 {
    1490             :                 };
    1491             :             }
    1492         925 :         }
    1493         925 :         doStaggeringOfLabels( aAxisLabelProperties, pTickFactory2D );
    1494         998 :     }
    1495             : }
    1496             : 
    1497        1044 : void VCartesianAxis::updatePositions()
    1498             : {
    1499             :     //-----------------------------------------
    1500             :     //update positions of labels
    1501        1044 :     if( m_aAxisProperties.m_bDisplayLabels )
    1502             :     {
    1503         958 :         boost::scoped_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() );
    1504         958 :         TickFactory_2D* pTickFactory2D = apTickFactory2D.get();
    1505         958 :         if( !pTickFactory2D )
    1506        1044 :             return;
    1507             : 
    1508             :         //-----------------------------------------
    1509             :         //update positions of all existing text shapes
    1510         958 :         pTickFactory2D->updateScreenValues( m_aAllTickInfos );
    1511             : 
    1512         958 :         ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = m_aAllTickInfos.begin();
    1513         958 :         const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd  = m_aAllTickInfos.end();
    1514        2808 :         for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd; ++aDepthIter, nDepth++ )
    1515             :         {
    1516        1850 :             ::std::vector< TickInfo >::iterator aTickIter = aDepthIter->begin();
    1517        1850 :             const ::std::vector< TickInfo >::const_iterator aTickEnd  = aDepthIter->end();
    1518       12330 :             for( ; aTickIter != aTickEnd; ++aTickIter )
    1519             :             {
    1520       10480 :                 TickInfo& rTickInfo = (*aTickIter);
    1521       10480 :                 Reference< drawing::XShape > xShape2DText( rTickInfo.xTextShape );
    1522       10480 :                 if( xShape2DText.is() )
    1523             :                 {
    1524        5094 :                     B2DVector aTextToTickDistance( pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, true ) );
    1525       10188 :                     B2DVector aTickScreenPos2D( rTickInfo.aTickScreenPosition );
    1526        5094 :                     aTickScreenPos2D += aTextToTickDistance;
    1527             :                     awt::Point aAnchorScreenPosition2D(
    1528        5094 :                         static_cast<sal_Int32>(aTickScreenPos2D.getX())
    1529       10188 :                         ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
    1530             : 
    1531        5094 :                     double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree;
    1532        5094 :                     if( nDepth > 0 )
    1533             :                     {
    1534             :                         /* Multi-level Labels: default to 0 or 90 */
    1535           0 :                         if( pTickFactory2D->isHorizontalAxis() )
    1536           0 :                             fRotationAngleDegree = 0.0;
    1537             :                         else
    1538           0 :                             fRotationAngleDegree = 90;
    1539             :                     }
    1540             : 
    1541             :                     // #i78696# use mathematically correct rotation now
    1542        5094 :                     const double fRotationAnglePi(fRotationAngleDegree * (F_PI / -180.0));
    1543       10188 :                     uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi);
    1544             : 
    1545             :                     //set new position
    1546       10188 :                     uno::Reference< beans::XPropertySet > xProp( xShape2DText, uno::UNO_QUERY );
    1547        5094 :                     if( xProp.is() )
    1548             :                     {
    1549             :                         try
    1550             :                         {
    1551        5094 :                             xProp->setPropertyValue( "Transformation", aATransformation );
    1552             :                         }
    1553           0 :                         catch( const uno::Exception& e )
    1554             :                         {
    1555             :                             ASSERT_EXCEPTION( e );
    1556             :                         }
    1557             :                     }
    1558             : 
    1559             :                     //correctPositionForRotation
    1560             :                     LabelPositionHelper::correctPositionForRotation( xShape2DText
    1561       10188 :                         , m_aAxisProperties.m_aLabelAlignment, fRotationAngleDegree, m_aAxisProperties.m_bComplexCategories );
    1562             :                 }
    1563       10480 :             }
    1564             :         }
    1565             : 
    1566         958 :         doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D );
    1567             :     }
    1568             : }
    1569             : 
    1570        1050 : void VCartesianAxis::createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickFactory_2D& rTickFactory2D, bool bOnlyAtLabels )
    1571             : {
    1572        1050 :     sal_Int32 nPointCount = rTickInfos.size();
    1573        1050 :     drawing::PointSequenceSequence aPoints(2*nPointCount);
    1574             : 
    1575        1050 :     ::std::vector< TickInfo >::const_iterator       aTickIter = rTickInfos.begin();
    1576        1050 :     const ::std::vector< TickInfo >::const_iterator aTickEnd  = rTickInfos.end();
    1577        1050 :     sal_Int32 nN = 0;
    1578        7355 :     for( ; aTickIter != aTickEnd; ++aTickIter )
    1579             :     {
    1580        6305 :         if( !(*aTickIter).bPaintIt )
    1581           0 :             continue;
    1582             : 
    1583        6305 :         bool bTicksAtLabels = ( m_aAxisProperties.m_eTickmarkPos != ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS );
    1584        6305 :         double fInnerDirectionSign = m_aAxisProperties.m_fInnerDirectionSign;
    1585        6305 :         if( bTicksAtLabels && m_aAxisProperties.m_eLabelPos == ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END )
    1586           0 :             fInnerDirectionSign *= -1.0;
    1587        6305 :         bTicksAtLabels = bTicksAtLabels || bOnlyAtLabels;
    1588             :         //add ticks at labels:
    1589        6305 :         rTickFactory2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue
    1590       12610 :             , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels );
    1591             :         //add ticks at axis (without lables):
    1592        6305 :         if( !bOnlyAtLabels && m_aAxisProperties.m_eTickmarkPos == ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
    1593        5696 :             rTickFactory2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue
    1594       11392 :                 , m_aAxisProperties.m_fInnerDirectionSign, rTickmarkProperties, !bTicksAtLabels );
    1595             :     }
    1596        1050 :     aPoints.realloc(nN);
    1597             :     m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints
    1598        1050 :                                 , &rTickmarkProperties.aLineProperties );
    1599        1050 : }
    1600             : 
    1601        1044 : void VCartesianAxis::createShapes()
    1602             : {
    1603        1044 :     if( !prepareShapeCreation() )
    1604          92 :         return;
    1605             : 
    1606         998 :     boost::scoped_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() );
    1607         998 :     TickFactory_2D* pTickFactory2D = apTickFactory2D.get();
    1608         998 :     if( !pTickFactory2D )
    1609           0 :         return;
    1610             : 
    1611             :     //-----------------------------------------
    1612             :     //create line shapes
    1613         998 :     if(2==m_nDimension)
    1614             :     {
    1615             :         //-----------------------------------------
    1616             :         //create extra long ticks to separate complex categories (create them only there where the labels are)
    1617         974 :         if( isComplexCategoryAxis() )
    1618             :         {
    1619           0 :             ::std::vector< ::std::vector< TickInfo > > aComplexTickInfos;
    1620           0 :             createAllTickInfosFromComplexCategories( aComplexTickInfos, true );
    1621           0 :             pTickFactory2D->updateScreenValues( aComplexTickInfos );
    1622           0 :             hideIdenticalScreenValues( aComplexTickInfos );
    1623             : 
    1624           0 :             ::std::vector<TickmarkProperties> aTickmarkPropertiesList;
    1625             :             static bool bIncludeSpaceBetweenTickAndText = false;
    1626           0 :             sal_Int32 nOffset = static_cast<sal_Int32>(pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, false, bIncludeSpaceBetweenTickAndText ).getLength());
    1627           0 :             sal_Int32 nTextLevelCount = getTextLevelCount();
    1628           0 :             for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
    1629             :             {
    1630           0 :                 boost::scoped_ptr< TickIter > apTickIter(createLabelTickIterator( nTextLevel ));
    1631           0 :                 if( apTickIter )
    1632             :                 {
    1633           0 :                     double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree;
    1634           0 :                     B2DVector aLabelsDistance( lcl_getLabelsDistance( *apTickIter.get(), pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, false ), fRotationAngleDegree ) );
    1635           0 :                     sal_Int32 nCurrentLength = static_cast<sal_Int32>(aLabelsDistance.getLength());
    1636           0 :                     aTickmarkPropertiesList.push_back( m_aAxisProperties.makeTickmarkPropertiesForComplexCategories( nOffset + nCurrentLength, 0, nTextLevel ) );
    1637           0 :                     nOffset += nCurrentLength;
    1638             :                 }
    1639           0 :             }
    1640             : 
    1641           0 :             sal_Int32 nTickmarkPropertiesCount = aTickmarkPropertiesList.size();
    1642           0 :             ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter             = aComplexTickInfos.begin();
    1643           0 :             const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd  = aComplexTickInfos.end();
    1644           0 :             for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; ++aDepthIter, nDepth++ )
    1645             :             {
    1646           0 :                 if(nDepth==0 && !m_aAxisProperties.m_nMajorTickmarks)
    1647           0 :                     continue;
    1648           0 :                 createTickMarkLineShapes( *aDepthIter, aTickmarkPropertiesList[nDepth], *pTickFactory2D, true /*bOnlyAtLabels*/ );
    1649           0 :             }
    1650             :         }
    1651             :         //-----------------------------------------
    1652             :         //create normal ticks for major and minor intervals
    1653             :         {
    1654         974 :             ::std::vector< ::std::vector< TickInfo > > aUnshiftedTickInfos;
    1655         974 :             if( m_aScale.ShiftedCategoryPosition )// if ShiftedCategoryPosition==true the tickmarks in m_aAllTickInfos are shifted
    1656             :             {
    1657         476 :                 pTickFactory2D->getAllTicks( aUnshiftedTickInfos );
    1658         476 :                 pTickFactory2D->updateScreenValues( aUnshiftedTickInfos );
    1659         476 :                 hideIdenticalScreenValues( aUnshiftedTickInfos );
    1660             :             }
    1661         974 :             ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos = m_aScale.ShiftedCategoryPosition ? aUnshiftedTickInfos : m_aAllTickInfos;
    1662             : 
    1663         974 :             ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter             = rAllTickInfos.begin();
    1664         974 :             const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd  = rAllTickInfos.end();
    1665         974 :             if(aDepthIter == aDepthEnd)//no tickmarks at all
    1666           0 :                 return;
    1667             : 
    1668         974 :             sal_Int32 nTickmarkPropertiesCount = m_aAxisProperties.m_aTickmarkPropertiesList.size();
    1669        2024 :             for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; ++aDepthIter, nDepth++ )
    1670        2024 :                 createTickMarkLineShapes( *aDepthIter, m_aAxisProperties.m_aTickmarkPropertiesList[nDepth], *pTickFactory2D, false /*bOnlyAtLabels*/ );
    1671             :         }
    1672             :         //-----------------------------------------
    1673             :         //create axis main lines
    1674             :         //it serves also as the handle shape for the axis selection
    1675             :         {
    1676         974 :             drawing::PointSequenceSequence aPoints(1);
    1677         974 :             apTickFactory2D->createPointSequenceForAxisMainLine( aPoints );
    1678             :             Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
    1679             :                     m_xGroupShape_Shapes, aPoints
    1680        1948 :                     , &m_aAxisProperties.m_aLineProperties );
    1681             :             //because of this name this line will be used for marking the axis
    1682        1948 :             m_pShapeFactory->setShapeName( xShape, "MarkHandles" );
    1683             :         }
    1684             :         //-----------------------------------------
    1685             :         //create an additional line at NULL
    1686         974 :         if( !AxisHelper::isAxisPositioningEnabled() )
    1687             :         {
    1688             :             double fExtraLineCrossesOtherAxis;
    1689           0 :             if( getLogicValueWhereExtraLineCrossesOtherAxis(fExtraLineCrossesOtherAxis) )
    1690             :             {
    1691           0 :                 B2DVector aStart, aEnd;
    1692           0 :                 this->get2DAxisMainLine( aStart, aEnd, fExtraLineCrossesOtherAxis );
    1693           0 :                 drawing::PointSequenceSequence aPoints( lcl_makePointSequence(aStart,aEnd) );
    1694             :                 Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
    1695           0 :                         m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties );
    1696             :             }
    1697             :         }
    1698         998 :     }
    1699             : 
    1700             :     //createLabels();
    1701             : }
    1702             : 
    1703             : //.............................................................................
    1704          33 : } //namespace chart
    1705             : //.............................................................................
    1706             : 
    1707             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10