summaryrefslogtreecommitdiff
path: root/oox/source/drawingml/chart/axisconverter.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/drawingml/chart/axisconverter.cxx')
-rw-r--r--oox/source/drawingml/chart/axisconverter.cxx99
1 files changed, 70 insertions, 29 deletions
diff --git a/oox/source/drawingml/chart/axisconverter.cxx b/oox/source/drawingml/chart/axisconverter.cxx
index da4fc3e5b83f..d2c3b4901258 100644
--- a/oox/source/drawingml/chart/axisconverter.cxx
+++ b/oox/source/drawingml/chart/axisconverter.cxx
@@ -30,6 +30,8 @@
#include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
#include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart/TimeInterval.hpp>
+#include <com/sun/star/chart/TimeUnit.hpp>
#include <com/sun/star/chart2/TickmarkStyle.hpp>
#include <com/sun/star/chart2/AxisType.hpp>
#include <com/sun/star/chart2/XAxis.hpp>
@@ -65,23 +67,35 @@ namespace chart {
namespace {
-template< typename Type >
-inline void lclSetValueOrClearAny( Any& orAny, const OptValue< Type >& roValue )
+inline void lclSetValueOrClearAny( Any& orAny, const OptValue< double >& rofValue )
{
- if( roValue.has() ) orAny <<= roValue.get(); else orAny.clear();
+ if( rofValue.has() ) orAny <<= rofValue.get(); else orAny.clear();
}
-void lclSetScaledValueOrClearAny( Any& orAny, const OptValue< double >& rofValue, const Reference< XScaling >& rxScaling )
+bool lclIsLogarithmicScale( const AxisModel& rAxisModel )
{
- if( rofValue.has() && rxScaling.is() )
- orAny <<= rxScaling->doScaling( rofValue.get() );
- else
- lclSetValueOrClearAny( orAny, rofValue );
+ return rAxisModel.mofLogBase.has() && (2.0 <= rAxisModel.mofLogBase.get()) && (rAxisModel.mofLogBase.get() <= 1000.0);
}
-bool lclIsLogarithmicScale( const AxisModel& rAxisModel )
+sal_Int32 lclGetApiTimeUnit( sal_Int32 nTimeUnit )
{
- return rAxisModel.mofLogBase.has() && (2.0 <= rAxisModel.mofLogBase.get()) && (rAxisModel.mofLogBase.get() <= 1000.0);
+ using namespace ::com::sun::star::chart;
+ switch( nTimeUnit )
+ {
+ case XML_days: return TimeUnit::DAY;
+ case XML_months: return TimeUnit::MONTH;
+ case XML_years: return TimeUnit::YEAR;
+ default: OSL_ENSURE( false, "lclGetApiTimeUnit - unexpected time unit" );
+ }
+ return TimeUnit::DAY;
+}
+
+void lclConvertTimeInterval( Any& orInterval, const OptValue< double >& rofUnit, sal_Int32 nTimeUnit )
+{
+ if( rofUnit.has() && (1.0 <= rofUnit.get()) && (rofUnit.get() <= SAL_MAX_INT32) )
+ orInterval <<= ::com::sun::star::chart::TimeInterval( static_cast< sal_Int32 >( rofUnit.get() ), lclGetApiTimeUnit( nTimeUnit ) );
+ else
+ orInterval.clear();
}
::com::sun::star::chart::ChartAxisLabelPosition lclGetLabelPosition( sal_Int32 nToken )
@@ -183,8 +197,13 @@ void AxisConverter::convertFromModel( const Reference< XCoordinateSystem >& rxCo
if( rTypeInfo.mbCategoryAxis )
{
OSL_ENSURE( (mrModel.mnTypeId == C_TOKEN( catAx )) || (mrModel.mnTypeId == C_TOKEN( dateAx )),
- "AxisConverter::convertFromModel - unexpected axis model type (must: c:catAx or c:dateEx)" );
- aScaleData.AxisType = cssc2::AxisType::CATEGORY;
+ "AxisConverter::convertFromModel - unexpected axis model type (must: c:catAx or c:dateAx)" );
+ bool bDateAxis = mrModel.mnTypeId == C_TOKEN( dateAx );
+ /* Chart2 requires axis type CATEGORY for automatic
+ category/date axis (even if it is a date axis
+ currently). */
+ aScaleData.AxisType = (bDateAxis && !mrModel.mbAuto) ? cssc2::AxisType::DATE : cssc2::AxisType::CATEGORY;
+ aScaleData.AutoDateAxis = mrModel.mbAuto;
aScaleData.Categories = rTypeGroup.createCategorySequence();
}
else
@@ -210,14 +229,37 @@ void AxisConverter::convertFromModel( const Reference< XCoordinateSystem >& rxCo
{
case cssc2::AxisType::CATEGORY:
case cssc2::AxisType::SERIES:
+ case cssc2::AxisType::DATE:
{
- // do not overlap text unless all labels are visible
- aAxisProp.setProperty( PROP_TextOverlap, mrModel.mnTickLabelSkip == 1 );
- // do not break text into several lines
- aAxisProp.setProperty( PROP_TextBreak, false );
- // do not stagger labels in two lines
- aAxisProp.setProperty( PROP_ArrangeOrder, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE );
- //! TODO #i58731# show n-th category
+ /* Determine date axis type from XML type identifier, and not
+ via aScaleData.AxisType, as this value sticks to CATEGORY
+ for automatic category/date axes). */
+ if( mrModel.mnTypeId == C_TOKEN( dateAx ) )
+ {
+ // scaling algorithm
+ aScaleData.Scaling.set( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.LinearScaling" ) ), UNO_QUERY );
+ // min/max
+ lclSetValueOrClearAny( aScaleData.Minimum, mrModel.mofMin );
+ lclSetValueOrClearAny( aScaleData.Maximum, mrModel.mofMax );
+ // major/minor increment
+ lclConvertTimeInterval( aScaleData.TimeIncrement.MajorTimeInterval, mrModel.mofMajorUnit, mrModel.mnMajorTimeUnit );
+ lclConvertTimeInterval( aScaleData.TimeIncrement.MinorTimeInterval, mrModel.mofMinorUnit, mrModel.mnMinorTimeUnit );
+ // base time unit
+ if( mrModel.monBaseTimeUnit.has() )
+ aScaleData.TimeIncrement.TimeResolution <<= lclGetApiTimeUnit( mrModel.monBaseTimeUnit.get() );
+ else
+ aScaleData.TimeIncrement.TimeResolution.clear();
+ }
+ else
+ {
+ // do not overlap text unless all labels are visible
+ aAxisProp.setProperty( PROP_TextOverlap, mrModel.mnTickLabelSkip == 1 );
+ // do not break text into several lines
+ aAxisProp.setProperty( PROP_TextBreak, false );
+ // do not stagger labels in two lines
+ aAxisProp.setProperty( PROP_ArrangeOrder, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE );
+ //! TODO #i58731# show n-th category
+ }
}
break;
case cssc2::AxisType::REALNUMBER:
@@ -234,26 +276,25 @@ void AxisConverter::convertFromModel( const Reference< XCoordinateSystem >& rxCo
lclSetValueOrClearAny( aScaleData.Maximum, mrModel.mofMax );
// major increment
IncrementData& rIncrementData = aScaleData.IncrementData;
- lclSetScaledValueOrClearAny( rIncrementData.Distance, mrModel.mofMajorUnit, aScaleData.Scaling );
+ if( mrModel.mofMajorUnit.has() && aScaleData.Scaling.is() )
+ rIncrementData.Distance <<= aScaleData.Scaling->doScaling( mrModel.mofMajorUnit.get() );
+ else
+ lclSetValueOrClearAny( rIncrementData.Distance, mrModel.mofMajorUnit );
// minor increment
Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements;
rSubIncrementSeq.realloc( 1 );
Any& rIntervalCount = rSubIncrementSeq[ 0 ].IntervalCount;
+ rIntervalCount.clear();
if( bLogScale )
{
if( mrModel.mofMinorUnit.has() )
rIntervalCount <<= sal_Int32( 9 );
}
- else
+ else if( mrModel.mofMajorUnit.has() && mrModel.mofMinorUnit.has() && (0.0 < mrModel.mofMinorUnit.get()) && (mrModel.mofMinorUnit.get() <= mrModel.mofMajorUnit.get()) )
{
- OptValue< sal_Int32 > onCount;
- if( mrModel.mofMajorUnit.has() && mrModel.mofMinorUnit.has() && (0.0 < mrModel.mofMinorUnit.get()) && (mrModel.mofMinorUnit.get() <= mrModel.mofMajorUnit.get()) )
- {
- double fCount = mrModel.mofMajorUnit.get() / mrModel.mofMinorUnit.get() + 0.5;
- if( (1.0 <= fCount) && (fCount < 1001.0) )
- onCount = static_cast< sal_Int32 >( fCount );
- }
- lclSetValueOrClearAny( rIntervalCount, onCount );
+ double fCount = mrModel.mofMajorUnit.get() / mrModel.mofMinorUnit.get() + 0.5;
+ if( (1.0 <= fCount) && (fCount < 1001.0) )
+ rIntervalCount <<= static_cast< sal_Int32 >( fCount );
}
}
break;