/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
css::chart::ChartAxisLabelPosition lclGetLabelPosition( sal_Int32 nToken )
{ usingnamespace ::com::sun::star::chart; switch( nToken )
{ case XML_high: return ChartAxisLabelPosition_OUTSIDE_END; case XML_low: return ChartAxisLabelPosition_OUTSIDE_START; case XML_nextTo: return ChartAxisLabelPosition_NEAR_AXIS;
} return ChartAxisLabelPosition_NEAR_AXIS;
}
sal_Int32 lclGetTickMark( sal_Int32 nToken )
{ usingnamespace ::com::sun::star::chart2::TickmarkStyle; switch( nToken )
{ case XML_in: return INNER; case XML_out: return OUTER; case XML_cross: return INNER | OUTER;
} return css::chart2::TickmarkStyle::NONE;
}
/** * The groups is of percent type only when all of its members are of percent * type.
*/ bool isPercent( const RefVector<TypeGroupConverter>& rTypeGroups )
{ if (rTypeGroups.empty()) returnfalse;
for (autoconst& typeGroup : rTypeGroups)
{
TypeGroupConverter& rConv = *typeGroup; if (!rConv.isPercent()) returnfalse;
}
// axis type and X axis categories ------------------------------------
ScaleData aScaleData = xAxis->getScaleData(); // set axis type switch( nAxisIdx )
{ case API_X_AXIS: 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:dateAx)" ); bool bDateAxis = mrModel.mnTypeId == C_TOKEN( dateAx ); // tdf#132076: set axis type to date, if it is a date axis!
aScaleData.AxisType = bDateAxis ? cssc2::AxisType::DATE : cssc2::AxisType::CATEGORY;
aScaleData.AutoDateAxis = mrModel.mbAuto; /* TODO: create main category axis labels once, while InternalDataProvider
can not handle different category names on the primary and secondary category axis. */ if( nAxesSetIdx == 0 )
aScaleData.Categories = rTypeGroups.front()->createCategorySequence(); /* set default ShiftedCategoryPosition values for some charttype,
because the XML can contain wrong CrossBetween value, if came from MSO */ if( rTypeGroups.front()->is3dChart() && (rTypeInfo.meTypeId == TYPEID_BAR || rTypeInfo.meTypeId == TYPEID_HORBAR || rTypeInfo.meTypeId == TYPEID_STOCK) )
aScaleData.ShiftedCategoryPosition = true; elseif( rTypeInfo.meTypeId == TYPEID_RADARLINE || rTypeInfo.meTypeId == TYPEID_RADARAREA )
aScaleData.ShiftedCategoryPosition = false; elseif( pCrossingAxis->mnCrossBetween != -1 ) /*because of backwards compatibility*/
aScaleData.ShiftedCategoryPosition = pCrossingAxis->mnCrossBetween == XML_between; elseif( rTypeInfo.meTypeCategory == TYPECATEGORY_BAR || rTypeInfo.meTypeId == TYPEID_LINE || rTypeInfo.meTypeId == TYPEID_STOCK )
aScaleData.ShiftedCategoryPosition = true;
} else
{
OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( valAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:valAx)" );
aScaleData.AxisType = cssc2::AxisType::REALNUMBER;
} break; case API_Y_AXIS:
OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( valAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:valAx)" );
aScaleData.AxisType = isPercent(rTypeGroups) ? cssc2::AxisType::PERCENT : cssc2::AxisType::REALNUMBER; break; case API_Z_AXIS:
OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( serAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:serAx)" );
OSL_ENSURE( rTypeGroups.front()->isDeep3dChart(), "AxisConverter::convertFromModel - series axis not supported by this chart type" );
aScaleData.AxisType = cssc2::AxisType::SERIES; break;
}
// axis scaling and increment -----------------------------------------
switch( aScaleData.AxisType )
{ case cssc2::AxisType::CATEGORY: case cssc2::AxisType::SERIES: case cssc2::AxisType::DATE:
{ /* 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 = LinearScaling::create( comphelper::getProcessComponentContext() ); // 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_value() )
aScaleData.TimeIncrement.TimeResolution <<= lclGetApiTimeUnit( mrModel.monBaseTimeUnit.value() ); else
aScaleData.TimeIncrement.TimeResolution.clear();
} else
{ // do not overlap text unless the rotation is 0 in xml bool bTextOverlap = false; if (mrModel.mxTextProp.is()
&& mrModel.mxTextProp->getTextProperties().moTextAreaRotation.has_value())
bTextOverlap
= mrModel.mxTextProp->getTextProperties().moTextAreaRotation.value() == 0;
aAxisProp.setProperty(PROP_TextOverlap, bTextOverlap); /* do not break text into several lines unless the rotation is 0 degree, or the rotation is 90 degree and the inner size of the chart is not fixed,
or the rotation is 270 degree and the inner size of the chart is not fixed */ bool bTextBreak = true; double fRotationAngle = 0.0; if (aAxisProp.getProperty(fRotationAngle, PROP_TextRotation)
&& fRotationAngle != 0.0)
bTextBreak = !bUseFixedInnerSize
&& (fRotationAngle == 90.0 || fRotationAngle == 270.0);
aAxisProp.setProperty(PROP_TextBreak, bTextBreak); // 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: case cssc2::AxisType::PERCENT:
{ // scaling algorithm constbool bLogScale = lclIsLogarithmicScale( mrModel ); if( bLogScale )
aScaleData.Scaling = LogarithmicScaling::create( comphelper::getProcessComponentContext() ); else
aScaleData.Scaling = LinearScaling::create( comphelper::getProcessComponentContext() ); // min/max
lclSetValueOrClearAny( aScaleData.Minimum, mrModel.mofMin );
lclSetValueOrClearAny( aScaleData.Maximum, mrModel.mofMax ); // major increment
IncrementData& rIncrementData = aScaleData.IncrementData; if( mrModel.mofMajorUnit.has_value() && aScaleData.Scaling.is() )
rIncrementData.Distance <<= aScaleData.Scaling->doScaling( mrModel.mofMajorUnit.value() ); else
lclSetValueOrClearAny( rIncrementData.Distance, mrModel.mofMajorUnit ); // minor increment
Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements;
rSubIncrementSeq.realloc( 1 );
Any& rIntervalCount = rSubIncrementSeq.getArray()[ 0 ].IntervalCount;
rIntervalCount.clear(); if( bLogScale )
{ if( mrModel.mofMinorUnit.has_value() )
rIntervalCount <<= sal_Int32( 9 );
} elseif( mrModel.mofMajorUnit.has_value() && mrModel.mofMinorUnit.has_value() && (0.0 < mrModel.mofMinorUnit.value()) && (mrModel.mofMinorUnit.value() <= mrModel.mofMajorUnit.value()) )
{ double fCount = mrModel.mofMajorUnit.value() / mrModel.mofMinorUnit.value() + 0.5; if( (1.0 <= fCount) && (fCount < 1001.0) )
rIntervalCount <<= static_cast< sal_Int32 >( fCount );
} elseif( !mrModel.mofMinorUnit.has_value() )
{ // tdf#114168 If minor unit is not set then set interval to 5, as MS Excel do.
rIntervalCount <<= static_cast< sal_Int32 >( 5 );
}
} break; default:
OSL_FAIL( "AxisConverter::convertFromModel - unknown axis type" );
}
/* Do not set a value to the Origin member anymore (already done via
new axis properties 'CrossoverPosition' and 'CrossoverValue'). */
aScaleData.Origin.clear();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.