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

Generated by: LCOV version 1.10