diff options
author | Ingrid Halama <iha@openoffice.org> | 2009-12-15 16:30:15 +0100 |
---|---|---|
committer | Ingrid Halama <iha@openoffice.org> | 2009-12-15 16:30:15 +0100 |
commit | 91f22fc22a92557dd823ac63456743736fd27ec0 (patch) | |
tree | d89d26ed8b9f009ad02902160fdc0af82815b939 | |
parent | 4d5f3c429b4391d63cab1af8b070b04f5787f5c4 (diff) |
chartmultiline: #i82971# complex categories (part2 - hierarchical axis label display)
22 files changed, 692 insertions, 326 deletions
diff --git a/chart2/source/inc/ExplicitCategoriesProvider.hxx b/chart2/source/inc/ExplicitCategoriesProvider.hxx index 965013b2bb6c..0ba0d92876f0 100644 --- a/chart2/source/inc/ExplicitCategoriesProvider.hxx +++ b/chart2/source/inc/ExplicitCategoriesProvider.hxx @@ -38,9 +38,20 @@ #include <com/sun/star/frame/XModel.hpp> #include "charttoolsdllapi.hxx" +#include <vector> + namespace chart { +struct OOO_DLLPUBLIC_CHARTTOOLS ComplexCategory +{ + rtl::OUString Text; + sal_Int32 Count; + + ComplexCategory( const rtl::OUString& rText, sal_Int32 nCount ) : Text( rText ), Count (nCount) + {} +}; + class OOO_DLLPUBLIC_CHARTTOOLS ExplicitCategoriesProvider { public: @@ -49,11 +60,12 @@ public: , const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xChartModel ); - SAL_DLLPRIVATE virtual ~ExplicitCategoriesProvider(); + virtual ~ExplicitCategoriesProvider(); + + void init(); - //XTextualDataSequence - SAL_DLLPRIVATE virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getTextualData() - throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Sequence< ::rtl::OUString > getSimpleCategories(); + ::std::vector< ComplexCategory > getCategoriesByLevel( sal_Int32 nLevel ); static ::rtl::OUString getCategoryByIndex( const ::com::sun::star::uno::Reference< @@ -66,7 +78,8 @@ public: sal_Int32 getCategoryLevelCount() const; private: //member - ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aExplicitCategories; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aExplicitCategories; + ::std::vector< ::std::vector< ComplexCategory > > m_aComplexCats; bool volatile m_bDirty; ::com::sun::star::uno::WeakReference< diff --git a/chart2/source/tools/DiagramHelper.cxx b/chart2/source/tools/DiagramHelper.cxx index 552c2b5304b5..60dcf1c00557 100644 --- a/chart2/source/tools/DiagramHelper.cxx +++ b/chart2/source/tools/DiagramHelper.cxx @@ -1024,7 +1024,7 @@ Sequence< rtl::OUString > DiagramHelper::getExplicitSimpleCategories( if( xCategories.is() ) { ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, xChartModel ); - aRet = aExplicitCategoriesProvider.getTextualData(); + aRet = aExplicitCategoriesProvider.getSimpleCategories(); } } } diff --git a/chart2/source/tools/ExplicitCategoriesProvider.cxx b/chart2/source/tools/ExplicitCategoriesProvider.cxx index 64137a20ebb2..f670b68d9ecb 100644 --- a/chart2/source/tools/ExplicitCategoriesProvider.cxx +++ b/chart2/source/tools/ExplicitCategoriesProvider.cxx @@ -89,7 +89,6 @@ ExplicitCategoriesProvider::ExplicitCategoriesProvider( const Reference< chart2: { Sequence< Reference< data::XLabeledDataSequence> > aColumns = xColumnCategoriesSource->getDataSequences(); Sequence< Reference< data::XLabeledDataSequence> > aRows = xRowCategoriesSource->getDataSequences(); - //m_aSplitCategoriesList; sal_Int32 nColumnCount = aColumns.getLength(); sal_Int32 nRowCount = aRows.getLength(); @@ -142,15 +141,6 @@ sal_Int32 ExplicitCategoriesProvider::getCategoryLevelCount() const return nCount; } -struct ComplexCategory -{ - OUString Text; - sal_Int32 Count; - - ComplexCategory( const OUString& rText, sal_Int32 nCount ) : Text( rText ), Count (nCount) - {} -}; - std::vector<sal_Int32> lcl_getLimitingBorders( const std::vector< ComplexCategory >& rComplexCategories ) { std::vector<sal_Int32> aLimitingBorders; @@ -168,7 +158,7 @@ std::vector<sal_Int32> lcl_getLimitingBorders( const std::vector< ComplexCategor std::vector< ComplexCategory > lcl_DataSequenceToComplexCategoryVector( const uno::Reference< data::XDataSequence >& xDataSequence - , const std::vector<sal_Int32>& rLimitingBorders ) + , const std::vector<sal_Int32>& rLimitingBorders, bool bCreateSingleCategories ) { std::vector< ComplexCategory > aResult; OSL_ASSERT( xDataSequence.is()); @@ -195,7 +185,7 @@ std::vector< ComplexCategory > lcl_DataSequenceToComplexCategoryVector( for( sal_Int32 nN=0; nN<nMaxCount; nN++ ) { OUString aCurrent = aStrings[nN]; - if( ::std::find( rLimitingBorders.begin(), rLimitingBorders.end(), nN ) != rLimitingBorders.end() ) + if( bCreateSingleCategories || ::std::find( rLimitingBorders.begin(), rLimitingBorders.end(), nN ) != rLimitingBorders.end() ) { aResult.push_back( ComplexCategory(aPrevious,nCurrentCount) ); nCurrentCount=1; @@ -234,20 +224,19 @@ sal_Int32 lcl_getCategoryCount( std::vector< ComplexCategory >& rComplexCategori return nCount; } -//XTextualDataSequence -Sequence< ::rtl::OUString > SAL_CALL ExplicitCategoriesProvider::getTextualData() throw( uno::RuntimeException) +void ExplicitCategoriesProvider::init() { if( m_bDirty ) { + m_aExplicitCategories.realloc(0); + m_aComplexCats.clear();//not one per index + if( m_xOriginalCategories.is() ) { if( !hasComplexCategories() ) m_aExplicitCategories = DataSequenceToStringSequence(m_xOriginalCategories->getValues()); else { - std::vector< std::vector< ComplexCategory > > aComplexCats;//not one per index - - //std::vector< std::vector< rtl::OUString > > aCats; sal_Int32 nLCount = m_aSplitCategoriesList.getLength(); for( sal_Int32 nL = 0; nL < nLCount; nL++ ) { @@ -256,24 +245,23 @@ Sequence< ::rtl::OUString > SAL_CALL ExplicitCategoriesProvider::getTextualData( { std::vector<sal_Int32> aLimitingBorders; if(nL>0) - aLimitingBorders = lcl_getLimitingBorders( aComplexCats.back() ); - aComplexCats.push_back( lcl_DataSequenceToComplexCategoryVector( xLabeledDataSequence->getValues(), aLimitingBorders ) ); - //aCats.push_back( ContainerHelper::SequenceToVector( DataSequenceToStringSequence(xLabeledDataSequence->getValues() ) ) ); + aLimitingBorders = lcl_getLimitingBorders( m_aComplexCats.back() ); + m_aComplexCats.push_back( lcl_DataSequenceToComplexCategoryVector( xLabeledDataSequence->getValues(), aLimitingBorders, nL==(nLCount-1) ) ); } } - std::vector< std::vector< ComplexCategory > >::iterator aOuterIt( aComplexCats.begin() ); - std::vector< std::vector< ComplexCategory > >::const_iterator aOuterEnd( aComplexCats.end() ); + std::vector< std::vector< ComplexCategory > >::iterator aOuterIt( m_aComplexCats.begin() ); + std::vector< std::vector< ComplexCategory > >::const_iterator aOuterEnd( m_aComplexCats.end() ); //ensure that the category count is the same on each level sal_Int32 nMaxCategoryCount = 0; { - for( aOuterIt=aComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt ) + for( aOuterIt=m_aComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt ) { sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt ); nMaxCategoryCount = std::max( nCurrentCount, nMaxCategoryCount ); } - for( aOuterIt=aComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt ) + for( aOuterIt=m_aComplexCats.begin(); aOuterIt != aOuterEnd; ++aOuterIt ) { sal_Int32 nCurrentCount = lcl_getCategoryCount( *aOuterIt ); if( nCurrentCount< nMaxCategoryCount ) @@ -286,7 +274,7 @@ Sequence< ::rtl::OUString > SAL_CALL ExplicitCategoriesProvider::getTextualData( //create a list with an element for every index std::vector< std::vector< ComplexCategory > > aComplexCatsPerIndex; - for( aOuterIt=aComplexCats.begin() ; aOuterIt != aOuterEnd; ++aOuterIt ) + for( aOuterIt=m_aComplexCats.begin() ; aOuterIt != aOuterEnd; ++aOuterIt ) { std::vector< ComplexCategory > aSingleLevel; std::vector< ComplexCategory >::iterator aIt( aOuterIt->begin() ); @@ -328,9 +316,25 @@ Sequence< ::rtl::OUString > SAL_CALL ExplicitCategoriesProvider::getTextualData( m_aExplicitCategories = DiagramHelper::generateAutomaticCategoriesFromCooSys( m_xCooSysModel ); m_bDirty = false; } +} + + +Sequence< ::rtl::OUString > ExplicitCategoriesProvider::getSimpleCategories() +{ + init(); return m_aExplicitCategories; } +std::vector< ComplexCategory > ExplicitCategoriesProvider::getCategoriesByLevel( sal_Int32 nLevel ) +{ + std::vector< ComplexCategory > aRet; + init(); + sal_Int32 nMaxIndex = m_aComplexCats.size()-1; + if( nLevel >= 0 && nLevel <= nMaxIndex ) + aRet = m_aComplexCats[nMaxIndex-nLevel]; + return aRet; +} + // static OUString ExplicitCategoriesProvider::getCategoryByIndex( const Reference< XCoordinateSystem >& xCooSysModel @@ -340,7 +344,7 @@ OUString ExplicitCategoriesProvider::getCategoryByIndex( if( xCooSysModel.is()) { ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSysModel, xChartModel ); - Sequence< OUString > aCategories( aExplicitCategoriesProvider.getTextualData()); + Sequence< OUString > aCategories( aExplicitCategoriesProvider.getSimpleCategories()); if( nIndex < aCategories.getLength()) return aCategories[ nIndex ]; } diff --git a/chart2/source/view/axes/TickmarkHelper.cxx b/chart2/source/view/axes/TickmarkHelper.cxx index 81dc5786653e..30697b1a31f2 100644 --- a/chart2/source/view/axes/TickmarkHelper.cxx +++ b/chart2/source/view/axes/TickmarkHelper.cxx @@ -51,6 +51,7 @@ TickInfo::TickInfo() , aTickScreenPosition(0.0,0.0) , bPaintIt( true ) , xTextShape( NULL ) +, nFactorForLimitedTextWidth(1) { } @@ -62,10 +63,45 @@ void TickInfo::updateUnscaledValue( const uno::Reference< XScaling >& xInverseSc this->fUnscaledTickValue = this->fScaledTickValue; } -TickIter::TickIter( const uno::Sequence< uno::Sequence< double > >& rTicks +sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const +{ + //return the positive distance between the two first tickmarks in screen values + + B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition; + sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength()); + if(nRet<0) + nRet *= -1; + return nRet; +} + +PureTickIter::PureTickIter( ::std::vector< TickInfo >& rTickInfoVector ) + : m_rTickVector(rTickInfoVector) + , m_aTickIter(m_rTickVector.begin()) +{ +} +PureTickIter::~PureTickIter() +{ +} +TickInfo* PureTickIter::firstInfo() +{ + m_aTickIter = m_rTickVector.begin(); + if(m_aTickIter!=m_rTickVector.end()) + return &*m_aTickIter; + return 0; +} +TickInfo* PureTickIter::nextInfo() +{ + m_aTickIter++; + if(m_aTickIter!=m_rTickVector.end()) + return &*m_aTickIter; + return 0; +} + +EquidistantTickIter::EquidistantTickIter( const uno::Sequence< uno::Sequence< double > >& rTicks , const ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) - : m_pSimpleTicks(&rTicks), m_pInfoTicks(NULL) + : m_pSimpleTicks(&rTicks) + , m_pInfoTicks(0) , m_rIncrement(rIncrement) , m_nMinDepth(0), m_nMaxDepth(0) , m_nTickCount(0), m_pnPositions(NULL) @@ -75,10 +111,11 @@ TickIter::TickIter( const uno::Sequence< uno::Sequence< double > >& rTicks initIter( nMinDepth, nMaxDepth ); } -TickIter::TickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks +EquidistantTickIter::EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks , const ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) - : m_pSimpleTicks(NULL), m_pInfoTicks(&rTicks) + : m_pSimpleTicks(NULL) + , m_pInfoTicks(&rTicks) , m_rIncrement(rIncrement) , m_nMinDepth(0), m_nMaxDepth(0) , m_nTickCount(0), m_pnPositions(NULL) @@ -88,7 +125,7 @@ TickIter::TickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks initIter( nMinDepth, nMaxDepth ); } -void TickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth ) +void EquidistantTickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth ) { m_nMaxDepth = nMaxDepth; if(nMaxDepth<0 || m_nMaxDepth>getMaxDepth()) @@ -131,14 +168,14 @@ void TickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth ) } } -TickIter::~TickIter() +EquidistantTickIter::~EquidistantTickIter() { delete[] m_pnPositions; delete[] m_pnPreParentCount; delete[] m_pbIntervalFinished; } -sal_Int32 TickIter::getStartDepth() const +sal_Int32 EquidistantTickIter::getStartDepth() const { //find the depth of the first visible tickmark: //it is the depth of the smallest value @@ -159,7 +196,7 @@ sal_Int32 TickIter::getStartDepth() const return nReturnDepth; } -double* TickIter::firstValue() +double* EquidistantTickIter::firstValue() { if( gotoFirst() ) { @@ -169,14 +206,14 @@ double* TickIter::firstValue() return NULL; } -TickInfo* TickIter::firstInfo() +TickInfo* EquidistantTickIter::firstInfo() { if( m_pInfoTicks && gotoFirst() ) return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]]; return NULL; } -sal_Int32 TickIter::getIntervalCount( sal_Int32 nDepth ) +sal_Int32 EquidistantTickIter::getIntervalCount( sal_Int32 nDepth ) { if(nDepth>m_rIncrement.SubIncrements.getLength() || nDepth<0) return 0; @@ -187,7 +224,7 @@ sal_Int32 TickIter::getIntervalCount( sal_Int32 nDepth ) return m_rIncrement.SubIncrements[nDepth-1].IntervalCount; } -bool TickIter::isAtLastPartTick() +bool EquidistantTickIter::isAtLastPartTick() { if(!m_nCurrentDepth) return false; @@ -206,7 +243,7 @@ bool TickIter::isAtLastPartTick() return bRet; } -bool TickIter::gotoFirst() +bool EquidistantTickIter::gotoFirst() { if( m_nMaxDepth<0 ) return false; @@ -222,7 +259,7 @@ bool TickIter::gotoFirst() return true; } -bool TickIter::gotoNext() +bool EquidistantTickIter::gotoNext() { if( m_nCurrentPos < 0 ) return false; @@ -253,7 +290,7 @@ bool TickIter::gotoNext() return true; } -bool TickIter::gotoIndex( sal_Int32 nTickIndex ) +bool EquidistantTickIter::gotoIndex( sal_Int32 nTickIndex ) { if( nTickIndex < 0 ) return false; @@ -271,16 +308,16 @@ bool TickIter::gotoIndex( sal_Int32 nTickIndex ) return true; } -sal_Int32 TickIter::getCurrentIndex() const +sal_Int32 EquidistantTickIter::getCurrentIndex() const { return m_nCurrentPos; } -sal_Int32 TickIter::getMaxIndex() const +sal_Int32 EquidistantTickIter::getMaxIndex() const { return m_nTickCount-1; } -double* TickIter::nextValue() +double* EquidistantTickIter::nextValue() { if( gotoNext() ) { @@ -290,7 +327,7 @@ double* TickIter::nextValue() return NULL; } -TickInfo* TickIter::nextInfo() +TickInfo* EquidistantTickIter::nextInfo() { if( m_pInfoTicks && gotoNext() && static_cast< sal_Int32 >( @@ -649,7 +686,7 @@ void TickmarkHelper::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo void TickmarkHelper::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno::Sequence< double > >& rParentTicks ) const { - TickIter aIter( rParentTicks, m_rIncrement, 0, nDepth-1 ); + EquidistantTickIter aIter( rParentTicks, m_rIncrement, 0, nDepth-1 ); double* pfNextParentTick = aIter.firstValue(); if(!pfNextParentTick) return; @@ -756,11 +793,7 @@ sal_Int32 TickmarkHelper_2D::getTickScreenDistance( TickIter& rIter ) if(!pSecondTickInfo || !pFirstTickInfo) return -1; - B2DVector aDistance = pSecondTickInfo->aTickScreenPosition-pFirstTickInfo->aTickScreenPosition; - sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength()); - if(nRet<0) - nRet *= -1; - return nRet; + return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo ); } B2DVector TickmarkHelper_2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const @@ -800,7 +833,7 @@ void TickmarkHelper_2D::addPointSequenceForTickLine( drawing::PointSequenceSeque rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY()); } -B2DVector TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties ) const +B2DVector TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const { bool bFarAwayLabels = false; if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos @@ -846,8 +879,9 @@ B2DVector TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties& rA if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign ) aOrthoLabelDirection*=-1.0; aOrthoLabelDirection.normalize(); - aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING; - if( bFarAwayLabels ) + if( bIncludeSpaceBetweenTickAndText ) + aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING; + if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo ) aLabelDirection += m_aAxisLineToLabelLineShift; return aLabelDirection; } @@ -879,27 +913,6 @@ void TickmarkHelper_2D::updateScreenValues( ::std::vector< ::std::vector< TickIn } } -//'hide' tickmarks with identical screen values in aAllTickInfos -void TickmarkHelper_2D::hideIdenticalScreenValues( - ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const -{ - TickIter aIter( rAllTickInfos, m_rIncrement ); - - TickInfo* pPreviousTickInfo = aIter.firstInfo(); - if(!pPreviousTickInfo) - return; - pPreviousTickInfo->bPaintIt = true; - for( TickInfo* pTickInfo = aIter.nextInfo(); pTickInfo; pTickInfo = aIter.nextInfo()) - { - pTickInfo->bPaintIt = - ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getX()) - != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getX()) ) - || - ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getY()) - != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getY()) ); - pPreviousTickInfo = pTickInfo; - } -} //----------------------------------------------------------------------------- // ___TickmarkHelper_3D___ //----------------------------------------------------------------------------- diff --git a/chart2/source/view/axes/TickmarkHelper.hxx b/chart2/source/view/axes/TickmarkHelper.hxx index a5749a074582..b28f98ce1b28 100644 --- a/chart2/source/view/axes/TickmarkHelper.hxx +++ b/chart2/source/view/axes/TickmarkHelper.hxx @@ -62,23 +62,48 @@ struct TickInfo ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xTextShape; + rtl::OUString aText;//used only for complex categories so far + sal_Int32 nFactorForLimitedTextWidth;//categories in higher levels of complex categories can have more place than a single simple category + //methods: TickInfo(); void updateUnscaledValue( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling >& xInverseScaling ); -}; + sal_Int32 getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const; +}; class TickIter { public: - TickIter( const ::com::sun::star::uno::Sequence< + virtual ~TickIter(){}; + virtual TickInfo* firstInfo()=0; + virtual TickInfo* nextInfo()=0; +}; + +class PureTickIter : public TickIter +{ +public: + PureTickIter( ::std::vector< TickInfo >& rTickInfoVector ); + virtual ~PureTickIter(); + virtual TickInfo* firstInfo(); + virtual TickInfo* nextInfo(); + +private: + ::std::vector< TickInfo >& m_rTickVector; + ::std::vector< TickInfo >::iterator m_aTickIter; +}; + +class EquidistantTickIter : public TickIter +{ +public: + EquidistantTickIter( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& rTicks , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 ); - TickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos + EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth=0, sal_Int32 nMaxDepth=-1 ); - virtual ~TickIter(); + virtual ~EquidistantTickIter(); virtual double* firstValue(); virtual double* nextValue(); @@ -174,7 +199,6 @@ protected: //methods bool isWithinOuterBorder( double fScaledValue ) const; //all within the outer major tick marks virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& /*rAllTickInfos*/ ) const {} - virtual void hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& /*rAllTickInfos*/ ) const {} protected: //member ::com::sun::star::chart2::ExplicitScaleData m_rScale; @@ -214,10 +238,11 @@ public: , sal_Int32 nSequenceIndex , double fScaledLogicTickValue, double fInnerDirectionSign , const TickmarkProperties& rTickmarkProperties, bool bPlaceAtLabels ) const; - ::basegfx::B2DVector getDistanceAxisTickToText( const AxisProperties& rAxisProperties ) const; + ::basegfx::B2DVector getDistanceAxisTickToText( const AxisProperties& rAxisProperties + , bool bIncludeFarAwayDistanceIfSo = false + , bool bIncludeSpaceBetweenTickAndText = true ) const; virtual void updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; - virtual void hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const; bool isHorizontalAxis() const; bool isVerticalAxis() const; diff --git a/chart2/source/view/axes/VAxisBase.cxx b/chart2/source/view/axes/VAxisBase.cxx index be24262e8801..530da86dab8f 100644 --- a/chart2/source/view/axes/VAxisBase.cxx +++ b/chart2/source/view/axes/VAxisBase.cxx @@ -98,13 +98,15 @@ void SAL_CALL VAxisBase::initAxisLabelProperties( const ::com::sun::star::awt::S else if( AxisType::CATEGORY==m_aAxisProperties.m_nAxisType ) { if( m_aAxisProperties.m_pExplicitCategoriesProvider ) - m_aTextLabels = m_aAxisProperties.m_pExplicitCategoriesProvider->getTextualData(); + m_aTextLabels = m_aAxisProperties.m_pExplicitCategoriesProvider->getSimpleCategories(); m_bUseTextLabels = true; } m_aAxisLabelProperties.nNumberFormatKey = m_aAxisProperties.m_nNumberFormatKey; m_aAxisLabelProperties.init(m_aAxisProperties.m_xAxisModel); + if( m_aAxisProperties.m_bComplexCategories && AxisType::CATEGORY == m_aAxisProperties.m_nAxisType ) + m_aAxisLabelProperties.eStaggering = SIDE_BY_SIDE; } void VAxisBase::recordMaximumTextSize( const Reference< drawing::XShape >& xShape, double fRotationAngleDegree ) @@ -161,6 +163,12 @@ void SAL_CALL VAxisBase::setExplicitScaleAndIncrement( m_aIncrement = rIncrement; } +void VAxisBase::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) +{ + std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() ); + apTickmarkHelper->getAllTicks( rAllTickInfos ); +} + bool VAxisBase::prepareShapeCreation() { //returns true if all is ready for further shape creation and any shapes need to be created @@ -171,14 +179,9 @@ bool VAxisBase::prepareShapeCreation() { //----------------------------------------- //create all scaled tickmark values - if( m_xTextTarget.is() ) - { - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeTextShapesFromTicks( aRemoveIter, m_xTextTarget ); - } + removeTextShapesFromTicks(); - std::auto_ptr< TickmarkHelper > apTickmarkHelper( this->createTickmarkHelper() ); - apTickmarkHelper->getAllTicks( m_aAllTickInfos ); + createAllTickInfos(m_aAllTickInfos); m_bReCreateAllTickInfos = false; } @@ -212,15 +215,25 @@ sal_Int32 VAxisBase::getIndexOfLongestLabel( const uno::Sequence< rtl::OUString return nRet; } -void VAxisBase::removeTextShapesFromTicks( TickIter& rIter, const Reference< drawing::XShapes >& xTarget ) +void VAxisBase::removeTextShapesFromTicks() { - for( TickInfo* pTickInfo = rIter.firstInfo() - ; pTickInfo; pTickInfo = rIter.nextInfo() ) + if( m_xTextTarget.is() ) { - if(pTickInfo->xTextShape.is()) + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = m_aAllTickInfos.begin(); + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = m_aAllTickInfos.end(); + for( ; aDepthIter != aDepthEnd; aDepthIter++ ) { - xTarget->remove(pTickInfo->xTextShape); - pTickInfo->xTextShape = NULL; + ::std::vector< TickInfo >::iterator aTickIter = (*aDepthIter).begin(); + const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end(); + for( ; aTickIter != aTickEnd; aTickIter++ ) + { + TickInfo& rTickInfo = (*aTickIter); + if(rTickInfo.xTextShape.is()) + { + m_xTextTarget->remove(rTickInfo.xTextShape); + rTickInfo.xTextShape = NULL; + } + } } } } diff --git a/chart2/source/view/axes/VAxisBase.hxx b/chart2/source/view/axes/VAxisBase.hxx index ab826caca2ff..6f8000af50de 100644 --- a/chart2/source/view/axes/VAxisBase.hxx +++ b/chart2/source/view/axes/VAxisBase.hxx @@ -70,6 +70,7 @@ public: throw (::com::sun::star::uno::RuntimeException); virtual sal_Int32 estimateMaximumAutoMainIncrementCount(); + virtual void createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ); void setExrtaLinePositionAtOtherAxis( const double& fCrossingAt ); @@ -77,7 +78,7 @@ public: //------------------------------------------------------------------------- protected: //methods sal_Int32 getIndexOfLongestLabel( const ::com::sun::star::uno::Sequence< rtl::OUString >& rLabels ); - void removeTextShapesFromTicks( TickIter& rIter, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget ); + void removeTextShapesFromTicks(); void updateUnscaledValuesAtTicks( TickIter& rIter ); virtual bool prepareShapeCreation(); diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx index eea2b2eb47f2..35fd0874399f 100644 --- a/chart2/source/view/axes/VAxisProperties.cxx +++ b/chart2/source/view/axes/VAxisProperties.cxx @@ -147,6 +147,18 @@ TickmarkProperties AxisProperties::makeTickmarkProperties( return aTickmarkProperties; } +TickmarkProperties AxisProperties::makeTickmarkPropertiesForComplexCategories( + sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis, sal_Int32 nTextLevel ) const +{ + sal_Int32 nTickmarkStyle = (m_fLabelDirectionSign==m_fInnerDirectionSign) ? 2/*outside*/ : 1/*inside*/; + + TickmarkProperties aTickmarkProperties; + aTickmarkProperties.Length = nTickLength;// + nTextLevel*( lcl_calcTickLengthForDepth(0,nTickmarkStyle) ); + aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length+nTickStartDistanceToAxis,nTickmarkStyle)); + aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( 0 ); + return aTickmarkProperties; +} + //static TickmarkProperties AxisProperties::getBiggestTickmarkProperties() { @@ -176,7 +188,6 @@ AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel , m_bAxisBetweenCategories(false) , m_fLabelDirectionSign(1.0) , m_fInnerDirectionSign(1.0) - , m_bLabelsOutside(true) , m_aLabelAlignment(LABEL_ALIGN_RIGHT_TOP) , m_bDisplayLabels( true ) , m_nNumberFormatKey(0) @@ -186,9 +197,9 @@ AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel , m_aLineProperties() //for category axes , m_nAxisType(AxisType::REALNUMBER) + , m_bComplexCategories(false) , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider) , m_xAxisTextProvider(0) - , m_bTickmarksAtIndicatedValue(false) { } @@ -207,7 +218,6 @@ AxisProperties::AxisProperties( const AxisProperties& rAxisProperties ) , m_bAxisBetweenCategories( rAxisProperties.m_bAxisBetweenCategories ) , m_fLabelDirectionSign( rAxisProperties.m_fLabelDirectionSign ) , m_fInnerDirectionSign( rAxisProperties.m_fInnerDirectionSign ) - , m_bLabelsOutside( rAxisProperties.m_bLabelsOutside ) , m_aLabelAlignment( rAxisProperties.m_aLabelAlignment ) , m_bDisplayLabels( rAxisProperties.m_bDisplayLabels ) , m_nNumberFormatKey( rAxisProperties.m_nNumberFormatKey ) @@ -217,9 +227,9 @@ AxisProperties::AxisProperties( const AxisProperties& rAxisProperties ) , m_aLineProperties( rAxisProperties.m_aLineProperties ) //for category axes , m_nAxisType( rAxisProperties.m_nAxisType ) + , m_bComplexCategories( rAxisProperties.m_bComplexCategories ) , m_pExplicitCategoriesProvider( rAxisProperties.m_pExplicitCategoriesProvider ) , m_xAxisTextProvider( rAxisProperties.m_xAxisTextProvider ) - , m_bTickmarksAtIndicatedValue( rAxisProperties.m_bTickmarksAtIndicatedValue ) { if( rAxisProperties.m_pfMainLinePositionAtOtherAxis ) m_pfMainLinePositionAtOtherAxis = new double(*rAxisProperties.m_pfMainLinePositionAtOtherAxis); diff --git a/chart2/source/view/axes/VAxisProperties.hxx b/chart2/source/view/axes/VAxisProperties.hxx index 56ef075bfdb2..c307bf5a3af7 100644 --- a/chart2/source/view/axes/VAxisProperties.hxx +++ b/chart2/source/view/axes/VAxisProperties.hxx @@ -88,7 +88,7 @@ struct AxisLabelProperties double fRotationAngleDegree; sal_Int32 nRhythm; //show only each nth label with n==nRhythm - bool bRhythmIsFix; //states wether the given rythm is fix or may be changed + bool bRhythmIsFix; //states wether the given rhythm is fix or may be changed //methods: void init( const ::com::sun::star::uno::Reference< @@ -120,7 +120,6 @@ struct AxisProperties double m_fLabelDirectionSign; //this direction is used to indicate in which direction inner tickmarks are to be drawn double m_fInnerDirectionSign; - bool m_bLabelsOutside; LabelAlignment m_aLabelAlignment; sal_Bool m_bDisplayLabels; @@ -137,13 +136,12 @@ struct AxisProperties VLineProperties m_aLineProperties; //for category axes -> - sal_Int32 m_nAxisType;//REALNUMBER, CATEGORY etc. type ::com::sun::star::chart2::AxisType + sal_Int32 m_nAxisType;//REALNUMBER, CATEGORY etc. type ::com::sun::star::chart2::AxisType + bool m_bComplexCategories; ExplicitCategoriesProvider* m_pExplicitCategoriesProvider;/*no ownership here*/ ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XTextualDataSequence > m_xAxisTextProvider; //for categries or series names - //position of main tickmarks in respect to the indicated value: at value or between neighboured indicated values - bool m_bTickmarksAtIndicatedValue; //<- category axes //methods: @@ -157,6 +155,7 @@ struct AxisProperties void initAxisPositioning( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xAxisProp ); static TickmarkProperties getBiggestTickmarkProperties(); + TickmarkProperties makeTickmarkPropertiesForComplexCategories( sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis, sal_Int32 nTextLevel ) const; private: AxisProperties(); diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx index 0f18029254ef..430945a0fd96 100644 --- a/chart2/source/view/axes/VCartesianAxis.cxx +++ b/chart2/source/view/axes/VCartesianAxis.cxx @@ -121,19 +121,19 @@ Reference< drawing::XShape > createSingleLabel( bool lcl_doesShapeOverlapWithTickmark( const Reference< drawing::XShape >& xShape , double fRotationAngleDegree , const basegfx::B2DVector& rTickScreenPosition - , TickmarkHelper_2D* pTickmarkHelper ) + , bool bIsHorizontalAxis, bool bIsVerticalAxis ) { if(!xShape.is()) return false; ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(xShape->getPosition(),ShapeFactory::getSizeAfterRotation( xShape, fRotationAngleDegree )); - if( pTickmarkHelper->isVerticalAxis() ) + if( bIsVerticalAxis ) { return ( (rTickScreenPosition.getY() >= aShapeRect.getMinY()) && (rTickScreenPosition.getY() <= aShapeRect.getMaxY()) ); } - if( pTickmarkHelper->isHorizontalAxis() ) + if( bIsHorizontalAxis ) { return ( (rTickScreenPosition.getX() >= aShapeRect.getMinX()) && (rTickScreenPosition.getX() <= aShapeRect.getMaxX()) ); @@ -157,7 +157,7 @@ bool doesOverlap( const Reference< drawing::XShape >& xShape1 return aRect1.overlaps(aRect2); } -void removeShapesAtWrongRythm( TickIter& rIter +void removeShapesAtWrongRhythm( TickIter& rIter , sal_Int32 nCorrectRhythm , sal_Int32 nMaxTickToCheck , const Reference< drawing::XShapes >& xTarget ) @@ -167,7 +167,7 @@ void removeShapesAtWrongRythm( TickIter& rIter ; pTickInfo && nTick <= nMaxTickToCheck ; pTickInfo = rIter.nextInfo(), nTick++ ) { - //remove labels which does not fit into the rythm + //remove labels which does not fit into the rhythm if( nTick%nCorrectRhythm != 0) { if(pTickInfo->xTextShape.is()) @@ -179,7 +179,7 @@ void removeShapesAtWrongRythm( TickIter& rIter } } -class LabelIterator : private TickIter +class EquidistantLabelIterator : public EquidistantTickIter { //this Iterator iterates over existing text labels @@ -193,7 +193,7 @@ class LabelIterator : private TickIter //we iterate through all labels public: - LabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos + EquidistantLabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , const AxisLabelStaggering eAxisLabelStaggering , bool bInnerLine @@ -203,29 +203,29 @@ public: virtual TickInfo* nextInfo(); private: //methods - LabelIterator(); + EquidistantLabelIterator(); private: //member const AxisLabelStaggering m_eAxisLabelStaggering; bool m_bInnerLine; }; -LabelIterator::LabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos +EquidistantLabelIterator::EquidistantLabelIterator( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , const AxisLabelStaggering eAxisLabelStaggering , bool bInnerLine , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) - : TickIter( rTickInfos, rIncrement, nMinDepth, nMaxDepth ) + : EquidistantTickIter( rTickInfos, rIncrement, nMinDepth, nMaxDepth ) , m_eAxisLabelStaggering(eAxisLabelStaggering) , m_bInnerLine(bInnerLine) { } -TickInfo* LabelIterator::firstInfo() +TickInfo* EquidistantLabelIterator::firstInfo() { - TickInfo* pTickInfo = TickIter::firstInfo(); + TickInfo* pTickInfo = EquidistantTickIter::firstInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ) - pTickInfo = TickIter::nextInfo(); + pTickInfo = EquidistantTickIter::nextInfo(); if(!pTickInfo) return NULL; if( (STAGGER_EVEN==m_eAxisLabelStaggering && m_bInnerLine) @@ -235,7 +235,7 @@ TickInfo* LabelIterator::firstInfo() { //skip first label do - pTickInfo = TickIter::nextInfo(); + pTickInfo = EquidistantTickIter::nextInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ); } if(!pTickInfo) @@ -243,12 +243,12 @@ TickInfo* LabelIterator::firstInfo() return pTickInfo; } -TickInfo* LabelIterator::nextInfo() +TickInfo* EquidistantLabelIterator::nextInfo() { TickInfo* pTickInfo = NULL; //get next label do - pTickInfo = TickIter::nextInfo(); + pTickInfo = EquidistantTickIter::nextInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ); if( STAGGER_EVEN==m_eAxisLabelStaggering @@ -256,16 +256,16 @@ TickInfo* LabelIterator::nextInfo() { //skip one label do - pTickInfo = TickIter::nextInfo(); + pTickInfo = EquidistantTickIter::nextInfo(); while( pTickInfo && !pTickInfo->xTextShape.is() ); } return pTickInfo; } -B2DVector lcl_getStaggerDistance( LabelIterator& rIter, const B2DVector& rDistanceTickToText ) +B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDistanceTickToText ) { - //calculates the height or width of the first line of labels - //thus the second line of labels needs to be shifted for that distance + //calculates the height or width of a line of labels + //thus a following line of labels can be shifted for that distance B2DVector aRet(0,0); @@ -283,13 +283,14 @@ B2DVector lcl_getStaggerDistance( LabelIterator& rIter, const B2DVector& rDistan ; pTickInfo = rIter.nextInfo() ) { xShape2DText = pTickInfo->xTextShape; - DBG_ASSERT(xShape2DText.is(),"LabelIterator does not work correctly"); - - awt::Size aSize = xShape2DText->getSize(); - if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY())) - nDistance = ::std::max(nDistance,aSize.Width); - else - nDistance = ::std::max(nDistance,aSize.Height); + if( xShape2DText.is() ) + { + awt::Size aSize = xShape2DText->getSize(); + if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY())) + nDistance = ::std::max(nDistance,aSize.Width); + else + nDistance = ::std::max(nDistance,aSize.Height); + } } aRet = aStaggerDirection*nDistance; @@ -301,7 +302,7 @@ B2DVector lcl_getStaggerDistance( LabelIterator& rIter, const B2DVector& rDistan return aRet; } -void lcl_correctPositionForStaggering( LabelIterator& rIter, const B2DVector& rStaggerDistance ) +void lcl_shiftLables( TickIter& rIter, const B2DVector& rStaggerDistance ) { if(rStaggerDistance.getLength()==0.0) return; @@ -311,23 +312,24 @@ void lcl_correctPositionForStaggering( LabelIterator& rIter, const B2DVector& rS ; pTickInfo = rIter.nextInfo() ) { xShape2DText = pTickInfo->xTextShape; - DBG_ASSERT(xShape2DText.is(),"LabelIterator does not work correctly"); - - awt::Point aPos = xShape2DText->getPosition(); - aPos.X += static_cast<sal_Int32>(rStaggerDistance.getX()); - aPos.Y += static_cast<sal_Int32>(rStaggerDistance.getY()); - xShape2DText->setPosition( aPos ); + if( xShape2DText.is() ) + { + awt::Point aPos = xShape2DText->getPosition(); + aPos.X += static_cast<sal_Int32>(rStaggerDistance.getX()); + aPos.Y += static_cast<sal_Int32>(rStaggerDistance.getY()); + xShape2DText->setPosition( aPos ); + } } } -class MaxLabelTickIter : public TickIter +class MaxLabelEquidistantTickIter : public EquidistantTickIter { //iterate over first two and last two labels and the longest label public: - MaxLabelTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos + MaxLabelEquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , sal_Int32 nLongestLabelIndex ); - virtual ~MaxLabelTickIter(); + virtual ~MaxLabelEquidistantTickIter(); virtual TickInfo* nextInfo(); @@ -335,10 +337,10 @@ private: sal_Int32 m_nLongestLabelIndex; }; -MaxLabelTickIter::MaxLabelTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos +MaxLabelEquidistantTickIter::MaxLabelEquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTickInfos , const ::com::sun::star::chart2::ExplicitIncrementData& rIncrement , sal_Int32 nLongestLabelIndex ) - : TickIter( rTickInfos, rIncrement, 0//nMinDepth + : EquidistantTickIter( rTickInfos, rIncrement, 0//nMinDepth , 0//nMaxDepth ) , m_nLongestLabelIndex( nLongestLabelIndex ) @@ -356,11 +358,11 @@ MaxLabelTickIter::MaxLabelTickIter( ::std::vector< ::std::vector< TickInfo > >& if( m_nLongestLabelIndex+1==nMaxIndex ) m_nLongestLabelIndex = 0; } -MaxLabelTickIter::~MaxLabelTickIter() +MaxLabelEquidistantTickIter::~MaxLabelEquidistantTickIter() { } -TickInfo* MaxLabelTickIter::nextInfo() +TickInfo* MaxLabelEquidistantTickIter::nextInfo() { sal_Int32 nCurrentPos = getCurrentIndex(); sal_Int32 nMaxIndex = getMaxIndex(); @@ -377,11 +379,11 @@ TickInfo* MaxLabelTickIter::nextInfo() } } - return TickIter::nextInfo(); + return EquidistantTickIter::nextInfo(); } bool VCartesianAxis::isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ) + , bool bIsHorizontalAxis ) { if( m_aTextLabels.getLength() > 100 ) return false; @@ -395,13 +397,11 @@ bool VCartesianAxis::isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLab if( !::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) ) return false; //break only for horizontal axis - if( pTickmarkHelper ) - return pTickmarkHelper->isHorizontalAxis(); - return false; + return bIsHorizontalAxis; } bool VCartesianAxis::isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ) + , bool bIsHorizontalAxis, bool bIsVerticalAxis ) { if( rAxisLabelProperties.eStaggering != STAGGER_AUTO ) return false; @@ -413,28 +413,163 @@ bool VCartesianAxis::isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& return false; //automatic staggering only for horizontal axis with horizontal text //or vertical axis with vertical text - if( pTickmarkHelper ) + if( bIsHorizontalAxis ) + return !rAxisLabelProperties.bStackCharacters; + if( bIsVerticalAxis ) + return rAxisLabelProperties.bStackCharacters; + return false; +} + +struct ComplexCategoryPlacement +{ + rtl::OUString Text; + sal_Int32 Count; + double TickValue; + + ComplexCategoryPlacement( const rtl::OUString& rText, sal_Int32 nCount, double fTickValue ) + : Text(rText), Count(nCount), TickValue(fTickValue) + {} +}; + +void VCartesianAxis::createAllTickInfosFromComplexCategories( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShiftedPosition ) +{ + //no minor tickmarks will be generated! + //order is: inner labels first , outer labels last (that is different to all other TickIter cases) + if(!bShiftedPosition) { - if( pTickmarkHelper->isHorizontalAxis() ) - return !rAxisLabelProperties.bStackCharacters; - if( pTickmarkHelper->isVerticalAxis() ) - return rAxisLabelProperties.bStackCharacters; + rAllTickInfos.clear(); + sal_Int32 nLevel=0; + sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount(); + for( ; nLevel<nLevelCount; nLevel++ ) + { + ::std::vector< TickInfo > aTickInfoVector; + std::vector< ComplexCategory > aComplexCategories( m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel( nLevel ) ); + sal_Int32 nCatIndex = 0; + std::vector< ComplexCategory >::const_iterator aIt(aComplexCategories.begin()); + std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end()); + for(;aIt!=aEnd;++aIt) + { + TickInfo aTickInfo; + ComplexCategory aCat(*aIt); + sal_Int32 nCount = aCat.Count; + if( nCatIndex + 0.5 + nCount >= m_aScale.Maximum ) + { + nCount = m_aScale.Maximum - 0.5 - nCatIndex; + if( nCount <= 0 ) + nCount = 1; + } + aTickInfo.fScaledTickValue = nCatIndex + 0.5 + nCount/2.0; + aTickInfo.nFactorForLimitedTextWidth = nCount; + aTickInfo.aText = aCat.Text; + aTickInfoVector.push_back(aTickInfo); + nCatIndex += nCount; + if( nCatIndex + 0.5 >= m_aScale.Maximum ) + break; + } + rAllTickInfos.push_back(aTickInfoVector); + } + } + else //bShiftedPosition==true + { + rAllTickInfos.clear(); + sal_Int32 nLevel=0; + sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount(); + for( ; nLevel<nLevelCount; nLevel++ ) + { + ::std::vector< TickInfo > aTickInfoVector; + std::vector< ComplexCategory > aComplexCategories( m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel( nLevel ) ); + sal_Int32 nCatIndex = 0; + std::vector< ComplexCategory >::const_iterator aIt(aComplexCategories.begin()); + std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end()); + for(;aIt!=aEnd;++aIt) + { + TickInfo aTickInfo; + ComplexCategory aCat(*aIt); + aTickInfo.fScaledTickValue = nCatIndex + 0.5; + aTickInfoVector.push_back(aTickInfo); + nCatIndex += aCat.Count; + if( nCatIndex + 0.5 > m_aScale.Maximum ) + break; + } + //fill up with single ticks until maximum scale + while( nCatIndex + 0.5 < m_aScale.Maximum ) + { + TickInfo aTickInfo; + aTickInfo.fScaledTickValue = nCatIndex + 0.5; + aTickInfoVector.push_back(aTickInfo); + nCatIndex ++; + if( nLevel>0 ) + break; + } + //add an additional tick at the end + { + TickInfo aTickInfo; + aTickInfo.fScaledTickValue = m_aScale.Maximum; + aTickInfoVector.push_back(aTickInfo); + } + rAllTickInfos.push_back(aTickInfoVector); + } } - return false; +} + +void VCartesianAxis::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) +{ + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + createAllTickInfosFromComplexCategories( rAllTickInfos, false ); + else + VAxisBase::createAllTickInfos(rAllTickInfos); +} + +::std::auto_ptr< TickIter > VCartesianAxis::createLabelTickIterator( sal_Int32 nTextLevel ) +{ + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + { + if( nTextLevel>=0 && nTextLevel < m_aAllTickInfos.size() ) + return ::std::auto_ptr< TickIter >( new PureTickIter( m_aAllTickInfos[nTextLevel] ) ); + } + else + { + if(nTextLevel==0) + return ::std::auto_ptr< TickIter >( new EquidistantTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ) ); + } + return ::std::auto_ptr< TickIter >(); +} +::std::auto_ptr< TickIter > VCartesianAxis::createMaximumLabelTickIterator( sal_Int32 nTextLevel ) +{ + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + { + return createLabelTickIterator( nTextLevel ); //mmmm maybe todo: create less than all texts here + } + else + { + if(nTextLevel==0) + { + sal_Int32 nLongestLabelIndex = m_bUseTextLabels ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0; + return ::std::auto_ptr< TickIter >( new MaxLabelEquidistantTickIter( m_aAllTickInfos, m_aIncrement, nLongestLabelIndex ) ); + } + } + return ::std::auto_ptr< TickIter >(); +} + +sal_Int32 VCartesianAxis::getTextLevelCount() const +{ + sal_Int32 nTextLevelCount = 1; + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + nTextLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount(); + return nTextLevelCount; } bool VCartesianAxis::createTextShapes( const Reference< drawing::XShapes >& xTarget , TickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ) + , TickmarkHelper_2D* pTickmarkHelper + , sal_Int32 nScreenDistanceBetweenTicks ) { //returns true if the text shapes have been created succesfully //otherwise false - in this case the AxisLabelProperties have changed //and contain new instructions for the next try for text shape creation - uno::Sequence< rtl::OUString >* pCategories = m_bUseTextLabels? &m_aTextLabels : 0; - Reference< XScaling > xInverseScaling( NULL ); if( m_aScale.Scaling.is() ) xInverseScaling = m_aScale.Scaling->getInverseScaling(); @@ -442,40 +577,44 @@ bool VCartesianAxis::createTextShapes( FixedNumberFormatter aFixedNumberFormatter( m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); - B2DVector aTextToTickDistance( pTickmarkHelper->getDistanceAxisTickToText( m_aAxisProperties ) ); - - TickInfo* pPreviousVisibleTickInfo = NULL; - TickInfo* pPREPreviousVisibleTickInfo = NULL; - TickInfo* pLastVisibleNeighbourTickInfo = NULL; + const bool bIsHorizontalAxis = pTickmarkHelper->isHorizontalAxis(); + const bool bIsVerticalAxis = pTickmarkHelper->isVerticalAxis(); bool bIsStaggered = rAxisLabelProperties.getIsStaggered(); - sal_Int32 nLimitedSpace = -1; - if( isBreakOfLabelsAllowed( rAxisLabelProperties, pTickmarkHelper ) ) + B2DVector aTextToTickDistance( pTickmarkHelper->getDistanceAxisTickToText( m_aAxisProperties, true ) ); + sal_Int32 nLimitedSpaceForText = -1; + if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis ) ) { - nLimitedSpace = TickmarkHelper_2D::getTickScreenDistance( rTickIter ); + nLimitedSpaceForText = nScreenDistanceBetweenTicks; if( bIsStaggered ) - nLimitedSpace *= 2; + nLimitedSpaceForText *= 2; - if( nLimitedSpace > 0 ) + if( nLimitedSpaceForText > 0 ) { //reduce space for a small amount to have a visible distance between the labels: - sal_Int32 nReduce = (nLimitedSpace*5)/100; + sal_Int32 nReduce = (nLimitedSpaceForText*5)/100; if(!nReduce) nReduce = 1; - nLimitedSpace -= nReduce; + nLimitedSpaceForText -= nReduce; } - //maybe @todo in future: - //if the labeled tickmarks are not equidistant [this is not considered to be a relevant case so far] - //the limited space maybe needs to be calculated for each tickmark seperatly - //or the staggering could be ignored in that case } + std::vector< ComplexCategoryPlacement > aComplexCategoryPlacements; + uno::Sequence< rtl::OUString >* pCategories = 0; + if( m_bUseTextLabels && !m_aAxisProperties.m_bComplexCategories ) + pCategories = &m_aTextLabels; + + TickInfo* pPreviousVisibleTickInfo = NULL; + TickInfo* pPREPreviousVisibleTickInfo = NULL; + TickInfo* pLastVisibleNeighbourTickInfo = NULL; + //------------------------------------------------ //prepare properties for multipropertyset-interface of shape tNameSequence aPropNames; tAnySequence aPropValues; + bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY()); Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY ); PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false - , nLimitedSpace, fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY()) ); + , nLimitedSpaceForText, bLimitedHeight ); LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps , m_aAxisLabelProperties.m_aFontReferenceSize ); LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, m_aAxisProperties.m_aLabelAlignment ); @@ -484,6 +623,8 @@ bool VCartesianAxis::createTextShapes( sal_Int32 nColor = Color( COL_AUTO ).GetColor(); if(pColorAny) *pColorAny >>= nColor; + + uno::Any* pLimitedSpaceAny = PropertyMapper::getValuePointerForLimitedSpace(aPropValues,aPropNames,bLimitedHeight); //------------------------------------------------ sal_Int32 nTick = 0; @@ -494,7 +635,7 @@ bool VCartesianAxis::createTextShapes( pLastVisibleNeighbourTickInfo = bIsStaggered ? pPREPreviousVisibleTickInfo : pPreviousVisibleTickInfo; - //don't create labels which does not fit into the rythm + //don't create labels which does not fit into the rhythm if( nTick%rAxisLabelProperties.nRhythm != 0) continue; @@ -508,10 +649,11 @@ bool VCartesianAxis::createTextShapes( { if( lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape , rAxisLabelProperties.fRotationAngleDegree - , pTickInfo->aTickScreenPosition, pTickmarkHelper ) ) + , pTickInfo->aTickScreenPosition + , bIsHorizontalAxis, bIsVerticalAxis ) ) { bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true; - if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, pTickmarkHelper ) ) + if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) ) { bIsStaggered = true; rAxisLabelProperties.eStaggering = STAGGER_EVEN; @@ -519,7 +661,8 @@ bool VCartesianAxis::createTextShapes( if( !pLastVisibleNeighbourTickInfo || !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape , rAxisLabelProperties.fRotationAngleDegree - , pTickInfo->aTickScreenPosition, pTickmarkHelper ) ) + , pTickInfo->aTickScreenPosition + , bIsHorizontalAxis, bIsVerticalAxis ) ) bOverlapAlsoAfterSwitchingOnAutoStaggering = false; } if( bOverlapAlsoAfterSwitchingOnAutoStaggering ) @@ -527,8 +670,7 @@ bool VCartesianAxis::createTextShapes( if( rAxisLabelProperties.bRhythmIsFix ) continue; rAxisLabelProperties.nRhythm++; - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeShapesAtWrongRythm( aRemoveIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); return false; } } @@ -546,11 +688,17 @@ bool VCartesianAxis::createTextShapes( if( nIndex>=0 && nIndex<pCategories->getLength() ) aLabel = (*pCategories)[nIndex]; } + else if( m_aAxisProperties.m_bComplexCategories ) + { + aLabel = pTickInfo->aText; + } else aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->fUnscaledTickValue, nExtraColor, bHasExtraColor ); if(pColorAny) *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor); + if(pLimitedSpaceAny) + *pLimitedSpaceAny = uno::makeAny(sal_Int32(nLimitedSpaceForText*pTickInfo->nFactorForLimitedTextWidth)); B2DVector aTickScreenPos2D( pTickInfo->aTickScreenPosition ); aTickScreenPos2D += aTextToTickDistance; @@ -575,7 +723,7 @@ bool VCartesianAxis::createTextShapes( if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, m_aAxisLabelProperties.fRotationAngleDegree ) ) { bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true; - if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, pTickmarkHelper ) ) + if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) ) { bIsStaggered = true; rAxisLabelProperties.eStaggering = STAGGER_EVEN; @@ -583,7 +731,8 @@ bool VCartesianAxis::createTextShapes( if( !pLastVisibleNeighbourTickInfo || !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape , rAxisLabelProperties.fRotationAngleDegree - , pTickInfo->aTickScreenPosition, pTickmarkHelper ) ) + , pTickInfo->aTickScreenPosition + , bIsHorizontalAxis, bIsVerticalAxis ) ) bOverlapAlsoAfterSwitchingOnAutoStaggering = false; } if( bOverlapAlsoAfterSwitchingOnAutoStaggering ) @@ -595,8 +744,7 @@ bool VCartesianAxis::createTextShapes( continue; } rAxisLabelProperties.nRhythm++; - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeShapesAtWrongRythm( aRemoveIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); return false; } } @@ -1060,6 +1208,37 @@ TickmarkHelper_2D* VCartesianAxis::createTickmarkHelper2D() return new TickmarkHelper_2D( m_aScale, m_aIncrement, aStart, aEnd, aLabelLineStart-aStart ); } +void lcl_hideIdenticalScreenValues( TickIter& rTickIter ) +{ + TickInfo* pPreviousTickInfo = rTickIter.firstInfo(); + if(!pPreviousTickInfo) + return; + pPreviousTickInfo->bPaintIt = true; + for( TickInfo* pTickInfo = rTickIter.nextInfo(); pTickInfo; pTickInfo = rTickIter.nextInfo()) + { + pTickInfo->bPaintIt = + ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getX()) + != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getX()) ) + || + ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getY()) + != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getY()) ); + pPreviousTickInfo = pTickInfo; + } +} + +//'hide' tickmarks with identical screen values in aAllTickInfos +void VCartesianAxis::hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const +{ + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + { + sal_Int32 nCount = rTickInfos.size(); + for( sal_Int32 nN=0; nN<nCount; nN++ ) + lcl_hideIdenticalScreenValues( PureTickIter( rTickInfos[nN] ) ); + } + else + lcl_hideIdenticalScreenValues( EquidistantTickIter( rTickInfos, m_aIncrement, 0, -1 ) ); +} + sal_Int32 VCartesianAxis::estimateMaximumAutoMainIncrementCount() { sal_Int32 nRet = 10; @@ -1095,15 +1274,31 @@ void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabel if( !pTickmarkHelper2D ) return; - if( rAxisLabelProperties.getIsStaggered() ) + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) + { + sal_Int32 nTextLevelCount = getTextLevelCount(); + B2DVector aCummulatedLabelsDistance(0,0); + for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) + { + ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel ); + if(apTickIter.get()) + { + if( nTextLevel>0 ) + lcl_shiftLables( *apTickIter.get(), aCummulatedLabelsDistance ); + aCummulatedLabelsDistance += lcl_getLabelsDistance( *apTickIter.get() + , pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ); + } + } + } + else if( rAxisLabelProperties.getIsStaggered() ) { - LabelIterator aInnerIter( m_aAllTickInfos, m_aIncrement + EquidistantLabelIterator aInnerIter( m_aAllTickInfos, m_aIncrement , rAxisLabelProperties.eStaggering, true, 0, 0 ); - LabelIterator aOuterIter( m_aAllTickInfos, m_aIncrement + EquidistantLabelIterator aOuterIter( m_aAllTickInfos, m_aIncrement , rAxisLabelProperties.eStaggering, false, 0, 0 ); - lcl_correctPositionForStaggering( aOuterIter - , lcl_getStaggerDistance( aInnerIter + lcl_shiftLables( aOuterIter + , lcl_getLabelsDistance( aInnerIter , pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ) ); } } @@ -1127,18 +1322,30 @@ void SAL_CALL VCartesianAxis::createLabels() pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos ); //----------------------------------------- //'hide' tickmarks with identical screen values in aAllTickInfos - pTickmarkHelper2D->hideIdenticalScreenValues( m_aAllTickInfos ); + hideIdenticalScreenValues( m_aAllTickInfos ); - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeTextShapesFromTicks( aRemoveIter, m_xTextTarget ); + removeTextShapesFromTicks(); //create tick mark text shapes - TickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - while( !createTextShapes( m_xTextTarget, aTickIter - , m_aAxisLabelProperties, pTickmarkHelper2D ) ) + sal_Int32 nTextLevelCount = getTextLevelCount(); + sal_Int32 nScreenDistanceBetweenTicks = -1; + for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) { - }; - + ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel ); + if(apTickIter.get()) + { + if(nTextLevel==0) + nScreenDistanceBetweenTicks = TickmarkHelper_2D::getTickScreenDistance( *apTickIter.get() ); + + AxisLabelProperties aCopy(m_aAxisLabelProperties); + aCopy.bRhythmIsFix = true; + aCopy.nRhythm = 1; + AxisLabelProperties& rAxisLabelProperties = nTextLevel==0 ? m_aAxisLabelProperties : aCopy; + while( !createTextShapes( m_xTextTarget, *apTickIter.get(), rAxisLabelProperties, pTickmarkHelper2D, nScreenDistanceBetweenTicks ) ) + { + }; + } + } doStaggeringOfLabels( m_aAxisLabelProperties, pTickmarkHelper2D ); } } @@ -1166,19 +1373,22 @@ void SAL_CALL VCartesianAxis::createMaximumLabels() //create tick mark text shapes //@todo: iterate through all tick depth wich should be labeled - sal_Int32 nLongestLabelIndex = m_bUseTextLabels - ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0; - MaxLabelTickIter aTickIter( m_aAllTickInfos, m_aIncrement, nLongestLabelIndex ); AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties ); - if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickmarkHelper2D ) ) + if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickmarkHelper2D->isHorizontalAxis(), pTickmarkHelper2D->isVerticalAxis() ) ) aAxisLabelProperties.eStaggering = STAGGER_EVEN; aAxisLabelProperties.bOverlapAllowed = true; aAxisLabelProperties.bLineBreakAllowed = false; - while( !createTextShapes( m_xTextTarget, aTickIter - , aAxisLabelProperties, pTickmarkHelper2D ) ) + sal_Int32 nTextLevelCount = getTextLevelCount(); + for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) { - }; - + ::std::auto_ptr< TickIter > apTickIter = createMaximumLabelTickIterator( nTextLevel ); + if(apTickIter.get()) + { + while( !createTextShapes( m_xTextTarget, *apTickIter.get(), aAxisLabelProperties, pTickmarkHelper2D, -1 ) ) + { + }; + } + } doStaggeringOfLabels( aAxisLabelProperties, pTickmarkHelper2D ); } } @@ -1198,46 +1408,47 @@ void SAL_CALL VCartesianAxis::updatePositions() //update positions of all existing text shapes pTickmarkHelper2D->updateScreenValues( m_aAllTickInfos ); - TickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - - Reference< drawing::XShape > xShape2DText; - for( TickInfo* pTickInfo = aTickIter.firstInfo() - ; pTickInfo; pTickInfo = aTickIter.nextInfo() ) + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = m_aAllTickInfos.begin(); + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = m_aAllTickInfos.end(); + for( ; aDepthIter != aDepthEnd; aDepthIter++ ) { - if( !pTickInfo ) - continue; - - xShape2DText = pTickInfo->xTextShape; - if( xShape2DText.is() ) + ::std::vector< TickInfo >::iterator aTickIter = aDepthIter->begin(); + const ::std::vector< TickInfo >::const_iterator aTickEnd = aDepthIter->end(); + for( ; aTickIter != aTickEnd; aTickIter++ ) { - B2DVector aTextToTickDistance( pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties ) ); - B2DVector aTickScreenPos2D( pTickInfo->aTickScreenPosition ); - aTickScreenPos2D += aTextToTickDistance; - awt::Point aAnchorScreenPosition2D( - static_cast<sal_Int32>(aTickScreenPos2D.getX()) - ,static_cast<sal_Int32>(aTickScreenPos2D.getY())); - - // #i78696# use mathematically correct rotation now - const double fRotationAnglePi(m_aAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0)); - uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi); - - //set new position - uno::Reference< beans::XPropertySet > xProp( xShape2DText, uno::UNO_QUERY ); - if( xProp.is() ) + TickInfo& rTickInfo = (*aTickIter); + Reference< drawing::XShape > xShape2DText( rTickInfo.xTextShape ); + if( xShape2DText.is() ) { - try + B2DVector aTextToTickDistance( pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, true ) ); + B2DVector aTickScreenPos2D( rTickInfo.aTickScreenPosition ); + aTickScreenPos2D += aTextToTickDistance; + awt::Point aAnchorScreenPosition2D( + static_cast<sal_Int32>(aTickScreenPos2D.getX()) + ,static_cast<sal_Int32>(aTickScreenPos2D.getY())); + + // #i78696# use mathematically correct rotation now + const double fRotationAnglePi(m_aAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0)); + uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi); + + //set new position + uno::Reference< beans::XPropertySet > xProp( xShape2DText, uno::UNO_QUERY ); + if( xProp.is() ) { - xProp->setPropertyValue( C2U( "Transformation" ), aATransformation ); + try + { + xProp->setPropertyValue( C2U( "Transformation" ), aATransformation ); + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } } - catch( uno::Exception& e ) - { - ASSERT_EXCEPTION( e ); - } - } - //correctPositionForRotation - LabelPositionHelper::correctPositionForRotation( xShape2DText - , m_aAxisProperties.m_aLabelAlignment, m_aAxisLabelProperties.fRotationAngleDegree, false ); + //correctPositionForRotation + LabelPositionHelper::correctPositionForRotation( xShape2DText + , m_aAxisProperties.m_aLabelAlignment, m_aAxisLabelProperties.fRotationAngleDegree, false ); + } } } @@ -1245,6 +1456,37 @@ void SAL_CALL VCartesianAxis::updatePositions() } } +void VCartesianAxis::createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickmarkHelper_2D& rTickmarkHelper2D, bool bOnlyAtLabels ) +{ + sal_Int32 nPointCount = rTickInfos.size(); + drawing::PointSequenceSequence aPoints(2*nPointCount); + + ::std::vector< TickInfo >::const_iterator aTickIter = rTickInfos.begin(); + const ::std::vector< TickInfo >::const_iterator aTickEnd = rTickInfos.end(); + sal_Int32 nN = 0; + for( ; aTickIter != aTickEnd; aTickIter++ ) + { + if( !(*aTickIter).bPaintIt ) + continue; + + bool bTicksAtLabels = ( m_aAxisProperties.m_eTickmarkPos != ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS ); + double fInnerDirectionSign = m_aAxisProperties.m_fInnerDirectionSign; + if( bTicksAtLabels && m_aAxisProperties.m_eLabelPos == ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END ) + fInnerDirectionSign *= -1.0; + bTicksAtLabels = bTicksAtLabels || bOnlyAtLabels; + //add ticks at labels: + rTickmarkHelper2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue + , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels ); + //add ticks at axis (without lables): + if( !bOnlyAtLabels && m_aAxisProperties.m_eTickmarkPos == ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ) + rTickmarkHelper2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue + , m_aAxisProperties.m_fInnerDirectionSign, rTickmarkProperties, !bTicksAtLabels ); + } + aPoints.realloc(nN); + m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints + , &rTickmarkProperties.aLineProperties ); +} + void SAL_CALL VCartesianAxis::createShapes() { if( !prepareShapeCreation() ) @@ -1256,55 +1498,64 @@ void SAL_CALL VCartesianAxis::createShapes() return; //----------------------------------------- - //create tick mark line shapes + //create line shapes if(2==m_nDimension) { - ::std::vector< ::std::vector< TickInfo > > aAllShiftedTickInfos; - if( m_aIncrement.ShiftedPosition ) - { - pTickmarkHelper2D->getAllTicksShifted( aAllShiftedTickInfos ); - pTickmarkHelper2D->updateScreenValues( aAllShiftedTickInfos ); - pTickmarkHelper2D->hideIdenticalScreenValues( aAllShiftedTickInfos ); - } - ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos = m_aIncrement.ShiftedPosition ? aAllShiftedTickInfos : m_aAllTickInfos; - - ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin(); - const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end(); - - if(aDepthIter == aDepthEnd)//no tickmarks at all - return; - - sal_Int32 nTickmarkPropertiesCount = m_aAxisProperties.m_aTickmarkPropertiesList.size(); - for( sal_Int32 nDepth=0 - ; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount - ; aDepthIter++, nDepth++ ) + //----------------------------------------- + //create extra long ticks to separate complex categories (create them only there where the labels are) + if( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) { - const TickmarkProperties& rTickmarkProperties = m_aAxisProperties.m_aTickmarkPropertiesList[nDepth]; - - sal_Int32 nPointCount = (*aDepthIter).size(); - drawing::PointSequenceSequence aPoints(2*nPointCount); + ::std::vector< ::std::vector< TickInfo > > aComplexTickInfos; + createAllTickInfosFromComplexCategories( aComplexTickInfos, true ); + pTickmarkHelper2D->updateScreenValues( aComplexTickInfos ); + hideIdenticalScreenValues( aComplexTickInfos ); + + ::std::vector<TickmarkProperties> aTickmarkPropertiesList; + static bool bIncludeSpaceBetweenTickAndText = false; + sal_Int32 nOffset = pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, false, bIncludeSpaceBetweenTickAndText ).getLength(); + sal_Int32 nTextLevelCount = getTextLevelCount(); + for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) + { + ::std::auto_ptr< TickIter > apTickIter = createLabelTickIterator( nTextLevel ); + if( apTickIter.get() ) + { + B2DVector aLabelsDistance( lcl_getLabelsDistance( *apTickIter.get(), pTickmarkHelper2D->getDistanceAxisTickToText( m_aAxisProperties, false ) ) ); + sal_Int32 nCurrentLength = aLabelsDistance.getLength(); + aTickmarkPropertiesList.push_back( m_aAxisProperties.makeTickmarkPropertiesForComplexCategories( nOffset + nCurrentLength, 0, nTextLevel ) ); + nOffset += nCurrentLength; + } + } - ::std::vector< TickInfo >::const_iterator aTickIter = (*aDepthIter).begin(); - const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end(); - sal_Int32 nN = 0; - for( ; aTickIter != aTickEnd; aTickIter++ ) + sal_Int32 nTickmarkPropertiesCount = aTickmarkPropertiesList.size(); + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = aComplexTickInfos.begin(); + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = aComplexTickInfos.end(); + for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; aDepthIter++, nDepth++ ) { - if( !(*aTickIter).bPaintIt ) + if(nDepth==0 && !m_aAxisProperties.m_nMajorTickmarks) continue; - - bool bTicksAtLabels = ( m_aAxisProperties.m_eTickmarkPos != ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS ); - double fInnerDirectionSign = m_aAxisProperties.m_fInnerDirectionSign; - if( bTicksAtLabels && m_aAxisProperties.m_eLabelPos == ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END ) - fInnerDirectionSign *= -1.0; - apTickmarkHelper2D->addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue - , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels ); - if( m_aAxisProperties.m_eTickmarkPos == ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ) - apTickmarkHelper2D->addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue - , m_aAxisProperties.m_fInnerDirectionSign, rTickmarkProperties, !bTicksAtLabels ); + createTickMarkLineShapes( *aDepthIter, aTickmarkPropertiesList[nDepth], *pTickmarkHelper2D, true /*bOnlyAtLabels*/ ); + } + } + //----------------------------------------- + //create normal ticks for major and minor intervals + { + ::std::vector< ::std::vector< TickInfo > > aAllShiftedTickInfos; + if( m_aIncrement.ShiftedPosition || ( m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels ) ) + { + pTickmarkHelper2D->getAllTicksShifted( aAllShiftedTickInfos ); + pTickmarkHelper2D->updateScreenValues( aAllShiftedTickInfos ); + hideIdenticalScreenValues( aAllShiftedTickInfos ); } - aPoints.realloc(nN); - m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints - , &rTickmarkProperties.aLineProperties ); + ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos = m_aIncrement.ShiftedPosition ? aAllShiftedTickInfos : m_aAllTickInfos; + + ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin(); + const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end(); + if(aDepthIter == aDepthEnd)//no tickmarks at all + return; + + sal_Int32 nTickmarkPropertiesCount = m_aAxisProperties.m_aTickmarkPropertiesList.size(); + for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; aDepthIter++, nDepth++ ) + createTickMarkLineShapes( *aDepthIter, m_aAxisProperties.m_aTickmarkPropertiesList[nDepth], *pTickmarkHelper2D, false /*bOnlyAtLabels*/ ); } //----------------------------------------- //create axis main lines diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx index ef5c8a0bf613..060d841065d7 100644 --- a/chart2/source/view/axes/VCartesianAxis.hxx +++ b/chart2/source/view/axes/VCartesianAxis.hxx @@ -72,6 +72,12 @@ public: virtual void SAL_CALL createShapes(); virtual sal_Int32 estimateMaximumAutoMainIncrementCount(); + virtual void createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ); + void createAllTickInfosFromComplexCategories( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShiftedPosition ); + + ::std::auto_ptr< TickIter > createLabelTickIterator( sal_Int32 nTextLevel ); + ::std::auto_ptr< TickIter > createMaximumLabelTickIterator( sal_Int32 nTextLevel ); + sal_Int32 getTextLevelCount() const; //------------------------------------------------------------------------- virtual TickmarkHelper* createTickmarkHelper(); @@ -117,16 +123,19 @@ protected: //methods ::com::sun::star::drawing::XShapes >& xTarget , TickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ); + , TickmarkHelper_2D* pTickmarkHelper + , sal_Int32 nScreenDistanceBetweenTicks ); + + void createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickmarkHelper_2D& rTickmarkHelper2D, bool bOnlyAtLabels ); TickmarkHelper_2D* createTickmarkHelper2D(); + void hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const; void doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties , TickmarkHelper_2D* pTickmarkHelper2D ); bool isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper); - bool isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties - , TickmarkHelper_2D* pTickmarkHelper ); + , bool bIsHorizontalAxis, bool bIsVerticalAxis ); + bool isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis ); ::basegfx::B2DVector getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const; ScreenPosAndLogicPos getScreenPosAndLogicPos( double fLogicX, double fLogicY, double fLogicZ ) const; diff --git a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx index e6e77ebea57a..489653aac03f 100644 --- a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx +++ b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx @@ -156,7 +156,8 @@ void VCartesianCoordinateSystem::createVAxisList( if( aCrossingScale.AxisType == AxisType::CATEGORY ) { aAxisProperties.m_bCrossingAxisIsCategoryAxes = true; - aAxisProperties.m_bAxisBetweenCategories = ChartTypeHelper::shiftTicksAtXAxisPerDefault( AxisHelper::getChartTypeByIndex( m_xCooSysModel, 0 ) ); + aAxisProperties.m_bAxisBetweenCategories = ChartTypeHelper::shiftTicksAtXAxisPerDefault( AxisHelper::getChartTypeByIndex( m_xCooSysModel, 0 ) ) + || ( aAxisProperties.m_pExplicitCategoriesProvider && aAxisProperties.m_pExplicitCategoriesProvider->hasComplexCategories() ); } } @@ -171,6 +172,13 @@ void VCartesianCoordinateSystem::createVAxisList( aAxisProperties.init(true); if(aAxisProperties.m_bDisplayLabels) aAxisProperties.m_nNumberFormatKey = this->getNumberFormatKeyForAxis( xAxis, xNumberFormatsSupplier ); + + if( nDimensionIndex == 0 && aAxisProperties.m_nAxisType == AxisType::CATEGORY + && aAxisProperties.m_pExplicitCategoriesProvider ) + { + if( aAxisProperties.m_pExplicitCategoriesProvider->hasComplexCategories() ) + aAxisProperties.m_bComplexCategories = true; + } //------------------- ::boost::shared_ptr< VAxisBase > apVAxis( new VCartesianAxis(aAxisProperties,xNumberFormatsSupplier,nDimensionIndex,nDimensionCount) ); tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex ); diff --git a/chart2/source/view/axes/VPolarAngleAxis.cxx b/chart2/source/view/axes/VPolarAngleAxis.cxx index 1aa56efbca78..6a177938d725 100644 --- a/chart2/source/view/axes/VPolarAngleAxis.cxx +++ b/chart2/source/view/axes/VPolarAngleAxis.cxx @@ -65,7 +65,7 @@ VPolarAngleAxis::~VPolarAngleAxis() bool VPolarAngleAxis::createTextShapes_ForAngleAxis( const uno::Reference< drawing::XShapes >& xTarget - , TickIter& rTickIter + , EquidistantTickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties , double fLogicRadius , double fLogicZ ) @@ -102,7 +102,7 @@ bool VPolarAngleAxis::createTextShapes_ForAngleAxis( ; pTickInfo ; pTickInfo = rTickIter.nextInfo(), nTick++ ) { - //don't create labels which does not fit into the rythm + //don't create labels which does not fit into the rhythm if( nTick%rAxisLabelProperties.nRhythm != 0) continue; @@ -192,11 +192,10 @@ void SAL_CALL VPolarAngleAxis::createLabels() //create tick mark text shapes //@todo: iterate through all tick depth wich should be labeled - TickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); + EquidistantTickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); this->updateUnscaledValuesAtTicks( aTickIter ); - TickIter aRemoveIter( m_aAllTickInfos, m_aIncrement, 0, 0 ); - removeTextShapesFromTicks( aRemoveIter, m_xTextTarget ); + removeTextShapesFromTicks(); AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties ); aAxisLabelProperties.bOverlapAllowed = true; diff --git a/chart2/source/view/axes/VPolarAngleAxis.hxx b/chart2/source/view/axes/VPolarAngleAxis.hxx index a04318b70ee1..0f20259b2572 100644 --- a/chart2/source/view/axes/VPolarAngleAxis.hxx +++ b/chart2/source/view/axes/VPolarAngleAxis.hxx @@ -58,7 +58,7 @@ public: private: //methods bool createTextShapes_ForAngleAxis( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget - , TickIter& rTickIter + , EquidistantTickIter& rTickIter , AxisLabelProperties& rAxisLabelProperties , double fLogicRadius, double fLogicZ ); }; diff --git a/chart2/source/view/axes/VPolarGrid.cxx b/chart2/source/view/axes/VPolarGrid.cxx index f9278b94b245..9ed18040f44f 100644 --- a/chart2/source/view/axes/VPolarGrid.cxx +++ b/chart2/source/view/axes/VPolarGrid.cxx @@ -93,7 +93,7 @@ void VPolarGrid::createLinePointSequence_ForAngleAxis( xInverseScaling = rScale.Scaling->getInverseScaling(); sal_Int32 nTick = 0; - TickIter aIter( rAllTickInfos, rIncrement, 0, 0 ); + EquidistantTickIter aIter( rAllTickInfos, rIncrement, 0, 0 ); for( TickInfo* pTickInfo = aIter.firstInfo() ; pTickInfo ; pTickInfo = aIter.nextInfo(), nTick++ ) diff --git a/chart2/source/view/axes/VPolarRadiusAxis.cxx b/chart2/source/view/axes/VPolarRadiusAxis.cxx index 2b3fdf5c327c..4fe7e87fce3e 100644 --- a/chart2/source/view/axes/VPolarRadiusAxis.cxx +++ b/chart2/source/view/axes/VPolarRadiusAxis.cxx @@ -52,7 +52,6 @@ VPolarRadiusAxis::VPolarRadiusAxis( const AxisProperties& rAxisProperties { m_aAxisProperties.m_fLabelDirectionSign=0.0; m_aAxisProperties.m_fInnerDirectionSign=0.0; - m_aAxisProperties.m_bLabelsOutside=true; m_aAxisProperties.m_bIsMainAxis=false; m_aAxisProperties.m_aLabelAlignment=LABEL_ALIGN_RIGHT; m_aAxisProperties.init(); @@ -159,7 +158,7 @@ void SAL_CALL VPolarRadiusAxis::createShapes() AxisProperties aAxisProperties(m_aAxisProperties); sal_Int32 nTick = 0; - TickIter aIter( aAngleTickInfos, rAngleIncrement, 0, 0 ); + EquidistantTickIter aIter( aAngleTickInfos, rAngleIncrement, 0, 0 ); for( TickInfo* pTickInfo = aIter.firstInfo() ; pTickInfo; pTickInfo = aIter.nextInfo(), nTick++ ) { diff --git a/chart2/source/view/charttypes/AreaChart.cxx b/chart2/source/view/charttypes/AreaChart.cxx index 406e5d119cd6..20a5f174f10f 100644 --- a/chart2/source/view/charttypes/AreaChart.cxx +++ b/chart2/source/view/charttypes/AreaChart.cxx @@ -75,7 +75,6 @@ AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel , bool bNoArea , PlottingPositionHelper* pPlottingPositionHelper , bool bConnectLastToFirstPoint - , bool bAddOneToXMax , bool bExpandIfValuesCloseToBorder , sal_Int32 nKeepAspectRatio , const drawing::Direction3D& rAspectRatio @@ -87,7 +86,6 @@ AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel , m_bSymbol( ChartTypeHelper::isSupportingSymbolProperties(xChartTypeModel,nDimensionCount) ) , m_bIsPolarCooSys( bConnectLastToFirstPoint ) , m_bConnectLastToFirstPoint( bConnectLastToFirstPoint ) - , m_bAddOneToXMax(bAddOneToXMax) , m_bExpandIfValuesCloseToBorder( bExpandIfValuesCloseToBorder ) , m_nKeepAspectRatio(nKeepAspectRatio) , m_aGivenAspectRatio(rAspectRatio) @@ -126,14 +124,17 @@ AreaChart::~AreaChart() delete m_pMainPosHelper; } +double AreaChart::getMinimumX() +{ + if( m_bCategoryXAxis && m_bIsPolarCooSys )//the angle axis in net charts needs a different autoscaling + return 1.0;//first category (index 0) matches with real number 1.0 + return VSeriesPlotter::getMinimumX(); +} + double AreaChart::getMaximumX() { - if( m_bAddOneToXMax ) - { - //return category count - sal_Int32 nPointCount = getPointCount(); - return nPointCount+1; - } + if( m_bCategoryXAxis && m_bIsPolarCooSys )//the angle axis in net charts needs a different autoscaling + return getPointCount()+1; return VSeriesPlotter::getMaximumX(); } diff --git a/chart2/source/view/charttypes/AreaChart.hxx b/chart2/source/view/charttypes/AreaChart.hxx index ec90e92ba1a4..e941c7094e27 100644 --- a/chart2/source/view/charttypes/AreaChart.hxx +++ b/chart2/source/view/charttypes/AreaChart.hxx @@ -52,7 +52,6 @@ public: , bool bCategoryXAxis, bool bNoArea=false , PlottingPositionHelper* pPlottingPositionHelper=NULL //takes owner ship , bool bConnectLastToFirstPoint=false - , bool bAddOneToXMax=false , bool bExpandIfValuesCloseToBorder=true , sal_Int32 nKeepAspectRatio=-1 //0->no 1->yes other value->automatic , const ::com::sun::star::drawing::Direction3D& rAspectRatio=::com::sun::star::drawing::Direction3D(1,1,1)//only taken into account if nKeepAspectRatio==1 @@ -79,6 +78,7 @@ public: //------------------------------------------------------------------------- // MinimumAndMaximumSupplier //------------------------------------------------------------------------- + virtual double getMinimumX(); virtual double getMaximumX(); virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ); virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex ); @@ -112,7 +112,6 @@ private: //member bool m_bSymbol; bool m_bIsPolarCooSys;//used e.g. for net chart (the data labels need to be placed different) bool m_bConnectLastToFirstPoint;//used e.g. for net chart - bool m_bAddOneToXMax;//used e.g. for net chart (the angle axis needs a different autoscaling) bool m_bExpandIfValuesCloseToBorder; // e.g. false for net charts sal_Int32 m_nKeepAspectRatio; //0->no 1->yes other value->automatic diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index f1f9d0ce8ce6..e83596a02b61 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -482,7 +482,7 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re { if( m_pExplicitCategoriesProvider ) { - Sequence< OUString > aCategories( m_pExplicitCategoriesProvider->getTextualData() ); + Sequence< OUString > aCategories( m_pExplicitCategoriesProvider->getSimpleCategories() ); if( nPointIndex >= 0 && nPointIndex < aCategories.getLength() ) { aText.append( aCategories[nPointIndex] ); @@ -1127,7 +1127,12 @@ void VSeriesPlotter::setMappedProperties( double VSeriesPlotter::getMinimumX() { if( m_bCategoryXAxis ) - return 1.0;//first category (index 0) matches with real number 1.0 + { + double fRet = 1.0;//first category (index 0) matches with real number 1.0 + if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() ) + fRet -= 0.5; + return fRet; + } double fMinimum, fMaximum; this->getMinimumAndMaximiumX( fMinimum, fMaximum ); @@ -1138,8 +1143,10 @@ double VSeriesPlotter::getMaximumX() if( m_bCategoryXAxis ) { //return category count - sal_Int32 nPointCount = getPointCount(); - return nPointCount;//first category (index 0) matches with real number 1.0 + double fRet = getPointCount();//first category (index 0) matches with real number 1.0 + if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() ) + fRet += 0.5; + return fRet; } double fMinimum, fMaximum; @@ -1930,7 +1937,7 @@ std::vector< ViewLegendEntry > SAL_CALL VSeriesPlotter::createLegendEntriesForSe { Sequence< OUString > aCategoryNames; if( m_pExplicitCategoriesProvider ) - aCategoryNames = m_pExplicitCategoriesProvider->getTextualData(); + aCategoryNames = m_pExplicitCategoriesProvider->getSimpleCategories(); for( sal_Int32 nIdx=0; nIdx<aCategoryNames.getLength(); ++nIdx ) { @@ -2074,9 +2081,9 @@ VSeriesPlotter* VSeriesPlotter::createSeriesPlotter( else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) pRet = new PieChart(xChartTypeModel,nDimensionCount); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) - pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true,new PolarPlottingPositionHelper(),true,true,false,1,drawing::Direction3D(1,1,1) ); + pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true,new PolarPlottingPositionHelper(),true,false,1,drawing::Direction3D(1,1,1) ); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) ) - pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,false,new PolarPlottingPositionHelper(),true,true,false,1,drawing::Direction3D(1,1,1) ); + pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,false,new PolarPlottingPositionHelper(),true,false,1,drawing::Direction3D(1,1,1) ); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) pRet = new CandleStickChart(xChartTypeModel,nDimensionCount); else diff --git a/chart2/source/view/inc/PropertyMapper.hxx b/chart2/source/view/inc/PropertyMapper.hxx index 57227e7f6292..0e21cc617b04 100644 --- a/chart2/source/view/inc/PropertyMapper.hxx +++ b/chart2/source/view/inc/PropertyMapper.hxx @@ -91,6 +91,11 @@ public: , const tNameSequence& rPropNames , const rtl::OUString& rPropName ); + static ::com::sun::star::uno::Any* + getValuePointerForLimitedSpace( tAnySequence& rPropValues + , const tNameSequence& rPropNames + , bool bLimitedHeight ); + static void setMultiProperties( const tNameSequence& rNames , const tAnySequence& rValues diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx index 8da5c2772493..b7a54a154fbf 100644 --- a/chart2/source/view/main/ChartView.cxx +++ b/chart2/source/view/main/ChartView.cxx @@ -577,13 +577,13 @@ private: std::vector< VCoordinateSystem* >& m_rVCooSysList; ::std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList; sal_Int32 m_nMaxAxisIndex; - bool m_bShiftXAxisTicks; + bool m_bChartTypeUsesShiftedXAxisTicksPerDefault; }; SeriesPlotterContainer::SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList ) : m_rVCooSysList( rVCooSysList ) , m_nMaxAxisIndex(0) - , m_bShiftXAxisTicks(false) + , m_bChartTypeUsesShiftedXAxisTicksPerDefault(false) { } @@ -678,7 +678,7 @@ void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter( uno::Reference< XChartType > xChartType( aChartTypeList[nT] ); if(nT==0) - m_bShiftXAxisTicks = ChartTypeHelper::shiftTicksAtXAxisPerDefault( xChartType ); + m_bChartTypeUsesShiftedXAxisTicksPerDefault = ChartTypeHelper::shiftTicksAtXAxisPerDefault( xChartType ); VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount ); if( !pPlotter ) @@ -932,7 +932,9 @@ void SeriesPlotterContainer::doAutoScaling( const uno::Reference< frame::XModel for( nC=0; nC < aVCooSysList_X.size(); nC++) { - if( m_bShiftXAxisTicks ) + ExplicitCategoriesProvider* pExplicitCategoriesProvider = aVCooSysList_X[nC]->getExplicitCategoriesProvider(); + + if( m_bChartTypeUsesShiftedXAxisTicksPerDefault || (aExplicitScale.AxisType==AxisType::CATEGORY && pExplicitCategoriesProvider && pExplicitCategoriesProvider->hasComplexCategories() ) ) aExplicitIncrement.ShiftedPosition = true; aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement ); } diff --git a/chart2/source/view/main/PropertyMapper.cxx b/chart2/source/view/main/PropertyMapper.cxx index 04d95ce249a6..efbadab9a4c8 100644 --- a/chart2/source/view/main/PropertyMapper.cxx +++ b/chart2/source/view/main/PropertyMapper.cxx @@ -168,6 +168,14 @@ uno::Any* PropertyMapper::getValuePointer( tAnySequence& rPropValues return NULL; } +uno::Any* PropertyMapper::getValuePointerForLimitedSpace( tAnySequence& rPropValues + , const tNameSequence& rPropNames + , bool bLimitedHeight) +{ + return PropertyMapper::getValuePointer( rPropValues, rPropNames + , bLimitedHeight ? C2U("TextMaximumFrameHeight") : C2U("TextMaximumFrameWidth") ); +} + /* //set some properties from service style::CharacterProperties: //-------- tabpage: Zeichen ----------- |