diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-10-22 10:51:44 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-11-04 12:30:36 -0500 |
commit | 519634b357a63bc1ff5c559244d9c7313f1b4c04 (patch) | |
tree | e2bb87f8640d020602621852c5f56189b591ad1e /chart2/source/view | |
parent | c95a355b0571329747095b23747405252c232c8b (diff) |
Create a variant of createTextShapes for simpler use cases.
So that we can do more aggressive optimization without breaking the other
cases.
Change-Id: I5d4ceb2a3b7f041f752a570827815236e9de58db
Diffstat (limited to 'chart2/source/view')
-rw-r--r-- | chart2/source/view/axes/VAxisProperties.cxx | 2 | ||||
-rw-r--r-- | chart2/source/view/axes/VAxisProperties.hxx | 2 | ||||
-rw-r--r-- | chart2/source/view/axes/VCartesianAxis.cxx | 186 | ||||
-rw-r--r-- | chart2/source/view/axes/VCartesianAxis.hxx | 20 |
4 files changed, 193 insertions, 17 deletions
diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx index 9b449d5a96d4..3b5502f464e8 100644 --- a/chart2/source/view/axes/VAxisProperties.cxx +++ b/chart2/source/view/axes/VAxisProperties.cxx @@ -407,7 +407,7 @@ void AxisLabelProperties::init( const uno::Reference< XAxis >& xAxisModel ) } } -bool AxisLabelProperties::getIsStaggered() const +bool AxisLabelProperties::isStaggered() const { return ( STAGGER_ODD == eStaggering || STAGGER_EVEN == eStaggering ); } diff --git a/chart2/source/view/axes/VAxisProperties.hxx b/chart2/source/view/axes/VAxisProperties.hxx index 7495c21a03b4..b65892507a02 100644 --- a/chart2/source/view/axes/VAxisProperties.hxx +++ b/chart2/source/view/axes/VAxisProperties.hxx @@ -81,7 +81,7 @@ struct AxisLabelProperties SAL_FINAL void init( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XAxis >& xAxisModel ); - bool getIsStaggered() const; + bool isStaggered() const; }; struct AxisLabelAlignment diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx index d095af5df24e..d43e32f69fee 100644 --- a/chart2/source/view/axes/VCartesianAxis.cxx +++ b/chart2/source/view/axes/VCartesianAxis.cxx @@ -600,20 +600,25 @@ sal_Int32 VCartesianAxis::getTextLevelCount() const } bool VCartesianAxis::createTextShapes( - const Reference< drawing::XShapes >& xTarget - , TickIter& rTickIter - , AxisLabelProperties& rAxisLabelProperties - , TickFactory2D* pTickFactory - , sal_Int32 nScreenDistanceBetweenTicks ) + const Reference<drawing::XShapes>& xTarget, TickIter& rTickIter, + AxisLabelProperties& rAxisLabelProperties, TickFactory2D* pTickFactory, + sal_Int32 nScreenDistanceBetweenTicks ) { + const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis(); + const bool bIsVerticalAxis = pTickFactory->isVerticalAxis(); + + if (!isBreakOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis) && + !isAutoStaggeringOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) && + !rAxisLabelProperties.isStaggered()) + return createTextShapesSimple(xTarget, rTickIter, rAxisLabelProperties, pTickFactory); + FixedNumberFormatter aFixedNumberFormatter( m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); - const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis(); - const bool bIsVerticalAxis = pTickFactory->isVerticalAxis(); - bool bIsStaggered = rAxisLabelProperties.getIsStaggered(); + bool bIsStaggered = rAxisLabelProperties.isStaggered(); B2DVector aTextToTickDistance = pTickFactory->getDistanceAxisTickToText(m_aAxisProperties, true); sal_Int32 nLimitedSpaceForText = -1; + if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis ) ) { nLimitedSpaceForText = nScreenDistanceBetweenTicks; @@ -837,6 +842,169 @@ bool VCartesianAxis::createTextShapes( return true; } +bool VCartesianAxis::createTextShapesSimple( + const Reference<drawing::XShapes>& xTarget, TickIter& rTickIter, + AxisLabelProperties& rAxisLabelProperties, TickFactory2D* pTickFactory ) +{ + FixedNumberFormatter aFixedNumberFormatter( + m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); + + const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis(); + const bool bIsVerticalAxis = pTickFactory->isVerticalAxis(); + B2DVector aTextToTickDistance = pTickFactory->getDistanceAxisTickToText(m_aAxisProperties, true); + + // Stores an array of text label strings in case of a normal + // (non-complex) category axis. + const uno::Sequence<OUString>* pCategories = NULL; + if( m_bUseTextLabels && !m_aAxisProperties.m_bComplexCategories ) + pCategories = &m_aTextLabels; + + const TickInfo* pPreviousVisibleTickInfo = NULL; + const 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 + , -1, bLimitedHeight ); + LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps + , m_aAxisLabelProperties.m_aFontReferenceSize ); + LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, m_aAxisProperties.maLabelAlignment.meAlignment ); + + uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,"CharColor"); + sal_Int32 nColor = Color( COL_AUTO ).GetColor(); + if(pColorAny) + *pColorAny >>= nColor; + + uno::Any* pLimitedSpaceAny = PropertyMapper::getValuePointerForLimitedSpace(aPropValues,aPropNames,bLimitedHeight); + + sal_Int32 nTick = 0; + for( TickInfo* pTickInfo = rTickIter.firstInfo() + ; pTickInfo + ; pTickInfo = rTickIter.nextInfo(), nTick++ ) + { + pLastVisibleNeighbourTickInfo = pPreviousVisibleTickInfo; + + //don't create labels which does not fit into the rhythm + if( nTick%rAxisLabelProperties.nRhythm != 0 ) + continue; + + //don't create labels for invisible ticks + if( !pTickInfo->bPaintIt ) + continue; + + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed ) + { + // Overlapping is not allowed. If the label overlaps with its + // neighbering label, try increasing the tick interval (or rhythm + // as it's called) and start over. + + if( lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape + , rAxisLabelProperties.fRotationAngleDegree + , pTickInfo->aTickScreenPosition + , bIsHorizontalAxis, bIsVerticalAxis ) ) + { + // This tick overlaps with its neighbor. Increment the visible + // tick intervals (if that's allowed) and start over. + + if( rAxisLabelProperties.bRhythmIsFix ) + continue; + rAxisLabelProperties.nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + return false; + } + } + + bool bHasExtraColor=false; + sal_Int32 nExtraColor=0; + + OUString aLabel; + if(pCategories) + { + // This is a normal category axis. Get the label string from the + // label string array. + sal_Int32 nIndex = static_cast<sal_Int32>(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0 + if( nIndex>=0 && nIndex<pCategories->getLength() ) + aLabel = (*pCategories)[nIndex]; + } + else if( m_aAxisProperties.m_bComplexCategories ) + { + // This is a complex category axis. The label is stored in the tick. + aLabel = pTickInfo->aText; + } + else + { + // This is a numeric axis. Format the original tick value per number format. + aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor ); + } + + if(pColorAny) + *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor); + if(pLimitedSpaceAny) + *pLimitedSpaceAny = uno::makeAny(sal_Int32(-1*pTickInfo->nFactorForLimitedTextWidth)); + + B2DVector aTickScreenPos2D = pTickInfo->aTickScreenPosition; + aTickScreenPos2D += aTextToTickDistance; + awt::Point aAnchorScreenPosition2D( + static_cast<sal_Int32>(aTickScreenPos2D.getX()) + ,static_cast<sal_Int32>(aTickScreenPos2D.getY())); + + //create single label + if(!pTickInfo->xTextShape.is()) + pTickInfo->xTextShape = createSingleLabel( m_xShapeFactory, xTarget + , aAnchorScreenPosition2D, aLabel + , rAxisLabelProperties, m_aAxisProperties + , aPropNames, aPropValues ); + if(!pTickInfo->xTextShape.is()) + continue; + + recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ); + + //if NO OVERLAP -> remove overlapping shapes + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed ) + { + // Check if the label still overlaps with its neighber. + if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ) ) + { + // It overlaps. + if( !rAxisLabelProperties.bOverlapAllowed && ::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) ) + { + // Try auto-rotating the labels at 45 degrees and + // start over. This rotation angle will be stored for + // all future text shape creation runs. + + rAxisLabelProperties.fRotationAngleDegree = 45; + rAxisLabelProperties.bLineBreakAllowed = false; + rAxisLabelProperties.eStaggering = SIDE_BY_SIDE; + m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; // Store it for future runs. + removeTextShapesFromTicks(); + return false; + } + + if( rAxisLabelProperties.bRhythmIsFix ) + { + // Tick interval is fixed. We have no choice but to + // remove this label. + xTarget->remove(pTickInfo->xTextShape); + pTickInfo->xTextShape = NULL; + continue; + } + + // Try incrementing the tick interval and start over. + rAxisLabelProperties.nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + return false; + } + } + + pPreviousVisibleTickInfo = pTickInfo; + } + return true; +} + drawing::PointSequenceSequence lcl_makePointSequence( B2DVector& rStart, B2DVector& rEnd ) { drawing::PointSequenceSequence aPoints(1); @@ -1377,7 +1545,7 @@ void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabel } } } - else if( rAxisLabelProperties.getIsStaggered() ) + else if (rAxisLabelProperties.isStaggered()) { if( !m_aAllTickInfos.empty() ) { diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx index 3b9886daab65..839d5e817d5e 100644 --- a/chart2/source/view/axes/VCartesianAxis.hxx +++ b/chart2/source/view/axes/VCartesianAxis.hxx @@ -117,12 +117,20 @@ private: //methods * have changed during the call, and the caller needs to call this * method once again to get the text shapes created. */ - bool createTextShapes( const ::com::sun::star::uno::Reference< - ::com::sun::star::drawing::XShapes >& xTarget - , TickIter& rTickIter - , AxisLabelProperties& rAxisLabelProperties - , TickFactory2D* pTickFactory - , sal_Int32 nScreenDistanceBetweenTicks ); + bool createTextShapes( + const css::uno::Reference<css::drawing::XShapes >& xTarget, + TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties, + TickFactory2D* pTickFactory, sal_Int32 nScreenDistanceBetweenTicks ); + + /** + * Variant of createTextShapes where none of auto-staggering and + * link-breaking are allowed in case of overlaps. Overlaps of text shapes + * are to be resolved only by adjusting the label tick interval. + */ + bool createTextShapesSimple( + const css::uno::Reference<css::drawing::XShapes >& xTarget, + TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties, + TickFactory2D* pTickFactory ); void createTickMarkLineShapes( TickInfoArrayType& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickFactory2D& rTickFactory2D, bool bOnlyAtLabels ); |