LCOV - code coverage report
Current view: top level - libreoffice/chart2/source/view/axes - VCartesianAxis.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 442 838 52.7 %
Date: 2012-12-27 Functions: 39 48 81.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10