blob: 16c8071bd7070b4756cac8492ea9b500d82d0d0d [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
#include "SchXMLAxisContext.hxx"
#include "SchXMLChartContext.hxx"
#include "SchXMLTools.hxx"
#include <xmloff/xmlnmspe.hxx>
#include <xmloff/xmlement.hxx>
#include <xmloff/xmlstyle.hxx>
#include <xmloff/prstylei.hxx>
#include <xmloff/nmspmap.hxx>
#include <xmloff/xmluconv.hxx>
#include <tools/debug.hxx>
#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/ChartAxisType.hpp>
#include <com/sun/star/chart/TimeIncrement.hpp>
#include <com/sun/star/chart/TimeInterval.hpp>
#include <com/sun/star/chart/TimeUnit.hpp>
#include <com/sun/star/chart/XAxis.hpp>
#include <com/sun/star/chart/XAxisSupplier.hpp>
#include <com/sun/star/chart2/AxisType.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
using namespace ::xmloff::token;
using namespace com::sun::star;
using rtl::OUString;
using com::sun::star::uno::Reference;
//----------------------------------------
//----------------------------------------
static SvXMLEnumMapEntry aXMLAxisDimensionMap[] =
{
{ XML_X, SCH_XML_AXIS_X },
{ XML_Y, SCH_XML_AXIS_Y },
{ XML_Z, SCH_XML_AXIS_Z },
{ XML_TOKEN_INVALID, 0 }
};
static SvXMLEnumMapEntry aXMLAxisTypeMap[] =
{
{ XML_AUTO, ::com::sun::star::chart::ChartAxisType::AUTOMATIC },
{ XML_TEXT, ::com::sun::star::chart::ChartAxisType::CATEGORY },
{ XML_DATE, ::com::sun::star::chart::ChartAxisType::DATE },
{ XML_TOKEN_INVALID, 0 }
};
//----------------------------------------
//----------------------------------------
class SchXMLCategoriesContext : public SvXMLImportContext
{
private:
SchXMLImportHelper& m_rImportHelper;
OUString& mrAddress;
public:
SchXMLCategoriesContext( SchXMLImportHelper& rImpHelper,
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const OUString& rLocalName,
OUString& rAddress );
virtual ~SchXMLCategoriesContext();
virtual void StartElement( const Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
};
//----------------------------------------
//----------------------------------------
class DateScaleContext : public SvXMLImportContext
{
public:
DateScaleContext( SchXMLImportHelper& rImpHelper, SvXMLImport& rImport,
sal_uInt16 nPrefix, const OUString& rLocalName,
const Reference< beans::XPropertySet > xAxisProps );
virtual ~DateScaleContext();
virtual void StartElement( const Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
private:
SchXMLImportHelper& m_rImportHelper;
Reference< beans::XPropertySet > m_xAxisProps;
};
//----------------------------------------
//----------------------------------------
SchXMLAxisContext::SchXMLAxisContext( SchXMLImportHelper& rImpHelper,
SvXMLImport& rImport, const OUString& rLocalName,
Reference< chart::XDiagram > xDiagram,
std::vector< SchXMLAxis >& rAxes,
OUString & rCategoriesAddress,
bool bAddMissingXAxisForNetCharts,
bool bAdaptWrongPercentScaleValues,
bool bAdaptXAxisOrientationForOld2DBarCharts,
bool& rbAxisPositionAttributeImported ) :
SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
m_rImportHelper( rImpHelper ),
m_xDiagram( xDiagram ),
m_rAxes( rAxes ),
m_rCategoriesAddress( rCategoriesAddress ),
m_nAxisType(chart::ChartAxisType::AUTOMATIC),
m_bAxisTypeImported(false),
m_bDateScaleImported(false),
m_bAddMissingXAxisForNetCharts( bAddMissingXAxisForNetCharts ),
m_bAdaptWrongPercentScaleValues( bAdaptWrongPercentScaleValues ),
m_bAdaptXAxisOrientationForOld2DBarCharts( bAdaptXAxisOrientationForOld2DBarCharts ),
m_rbAxisPositionAttributeImported( rbAxisPositionAttributeImported )
{
}
SchXMLAxisContext::~SchXMLAxisContext()
{}
Reference< chart::XAxis > lcl_getChartAxis( SchXMLAxis aCurrentAxis, const Reference< chart::XDiagram > xDiagram )
{
Reference< chart::XAxis > xAxis;
Reference< chart::XAxisSupplier > xAxisSuppl( xDiagram, uno::UNO_QUERY );
if( !xAxisSuppl.is() )
return xAxis;
if( aCurrentAxis.nAxisIndex == 0 )
xAxis = xAxisSuppl->getAxis(aCurrentAxis.eDimension);
else
xAxis = xAxisSuppl->getSecondaryAxis(aCurrentAxis.eDimension);
return xAxis;
}
/* returns a shape for the current axis's title. The property
"Has...AxisTitle" is set to "True" to get the shape
*/
Reference< drawing::XShape > SchXMLAxisContext::getTitleShape()
{
Reference< drawing::XShape > xResult;
Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) );
if( !xDiaProp.is() || !xAxis.is() )
return xResult;
rtl::OUString aPropName;
switch( m_aCurrentAxis.eDimension )
{
case SCH_XML_AXIS_X:
if( m_aCurrentAxis.nAxisIndex == 0 )
aPropName = OUString::createFromAscii( "HasXAxisTitle" );
else
aPropName = OUString::createFromAscii( "HasSecondaryXAxisTitle" );
break;
case SCH_XML_AXIS_Y:
if( m_aCurrentAxis.nAxisIndex == 0 )
aPropName = OUString::createFromAscii( "HasYAxisTitle" );
else
aPropName = OUString::createFromAscii( "HasSecondaryYAxisTitle" );
break;
case SCH_XML_AXIS_Z:
aPropName = OUString::createFromAscii( "HasZAxisTitle" );
break;
case SCH_XML_AXIS_UNDEF:
DBG_ERROR( "Invalid axis" );
break;
}
xDiaProp->setPropertyValue( aPropName, uno::makeAny(sal_True) );
xResult = Reference< drawing::XShape >( xAxis->getAxisTitle(), uno::UNO_QUERY );
return xResult;
}
void SchXMLAxisContext::CreateGrid( OUString sAutoStyleName, bool bIsMajor )
{
Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) );
if( !xDiaProp.is() || !xAxis.is() )
return;
rtl::OUString aPropName;
switch( m_aCurrentAxis.eDimension )
{
case SCH_XML_AXIS_X:
if( bIsMajor )
aPropName = OUString::createFromAscii("HasXAxisGrid");
else
aPropName = OUString::createFromAscii("HasXAxisHelpGrid");
break;
case SCH_XML_AXIS_Y:
if( bIsMajor )
aPropName = OUString::createFromAscii("HasYAxisGrid");
else
aPropName = OUString::createFromAscii("HasYAxisHelpGrid");
break;
case SCH_XML_AXIS_Z:
if( bIsMajor )
aPropName = OUString::createFromAscii("HasZAxisGrid");
else
aPropName = OUString::createFromAscii("HasZAxisHelpGrid");
break;
case SCH_XML_AXIS_UNDEF:
DBG_ERROR( "Invalid axis" );
break;
}
xDiaProp->setPropertyValue( aPropName, uno::makeAny(sal_True) );
Reference< beans::XPropertySet > xGridProp;
if( bIsMajor )
xGridProp = xAxis->getMajorGrid();
else
xGridProp = xAxis->getMinorGrid();
// set properties
if( xGridProp.is())
{
// the line color is black as default, in the model it is a light gray
xGridProp->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "LineColor" )),
uno::makeAny( COL_BLACK ));
if( sAutoStyleName.getLength())
{
const SvXMLStylesContext* pStylesCtxt = m_rImportHelper.GetAutoStylesContext();
if( pStylesCtxt )
{
const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
m_rImportHelper.GetChartFamilyID(), sAutoStyleName );
if( pStyle && pStyle->ISA( XMLPropStyleContext ))
(( XMLPropStyleContext* )pStyle )->FillPropertySet( xGridProp );
}
}
}
}
namespace
{
enum AxisAttributeTokens
{
XML_TOK_AXIS_DIMENSION,
XML_TOK_AXIS_NAME,
XML_TOK_AXIS_STYLE_NAME,
XML_TOK_AXIS_TYPE,
XML_TOK_AXIS_TYPE_EXT
};
SvXMLTokenMapEntry aAxisAttributeTokenMap[] =
{
{ XML_NAMESPACE_CHART, XML_DIMENSION, XML_TOK_AXIS_DIMENSION },
{ XML_NAMESPACE_CHART, XML_NAME, XML_TOK_AXIS_NAME },
{ XML_NAMESPACE_CHART, XML_STYLE_NAME, XML_TOK_AXIS_STYLE_NAME },
{ XML_NAMESPACE_CHART, XML_AXIS_TYPE, XML_TOK_AXIS_TYPE },
{ XML_NAMESPACE_CHART_EXT, XML_AXIS_TYPE, XML_TOK_AXIS_TYPE_EXT },
XML_TOKEN_MAP_END
};
class AxisAttributeTokenMap : public SvXMLTokenMap
{
public:
AxisAttributeTokenMap(): SvXMLTokenMap( aAxisAttributeTokenMap ) {}
virtual ~AxisAttributeTokenMap() {}
};
//a AxisAttributeTokenMap Singleton
struct theAxisAttributeTokenMap : public rtl::Static< AxisAttributeTokenMap, theAxisAttributeTokenMap > {};
}
void SchXMLAxisContext::StartElement( const Reference< xml::sax::XAttributeList >& xAttrList )
{
// parse attributes
sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
SchXMLImport& rImport = ( SchXMLImport& )GetImport();
const SvXMLTokenMap& rAttrTokenMap = theAxisAttributeTokenMap::get();
for( sal_Int16 i = 0; i < nAttrCount; i++ )
{
OUString sAttrName = xAttrList->getNameByIndex( i );
OUString aLocalName;
OUString aValue = xAttrList->getValueByIndex( i );
sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
{
case XML_TOK_AXIS_DIMENSION:
{
sal_uInt16 nEnumVal;
if( rImport.GetMM100UnitConverter().convertEnum( nEnumVal, aValue, aXMLAxisDimensionMap ))
m_aCurrentAxis.eDimension = ( SchXMLAxisDimension )nEnumVal;
}
break;
case XML_TOK_AXIS_NAME:
m_aCurrentAxis.aName = aValue;
break;
case XML_TOK_AXIS_TYPE:
case XML_TOK_AXIS_TYPE_EXT:
sal_uInt16 nEnumVal;
if( rImport.GetMM100UnitConverter().convertEnum( nEnumVal, aValue, aXMLAxisTypeMap ))
{
m_nAxisType = nEnumVal;
m_bAxisTypeImported = true;
}
break;
case XML_TOK_AXIS_STYLE_NAME:
m_aAutoStyleName = aValue;
break;
}
}
// check for number of axes with same dimension
m_aCurrentAxis.nAxisIndex = 0;
sal_Int32 nNumOfAxes = m_rAxes.size();
for( sal_Int32 nCurrent = 0; nCurrent < nNumOfAxes; nCurrent++ )
{
if( m_rAxes[ nCurrent ].eDimension == m_aCurrentAxis.eDimension )
m_aCurrentAxis.nAxisIndex++;
}
CreateAxis();
}
namespace
{
Reference< chart2::XAxis > lcl_getAxis( const Reference< frame::XModel >& xChartModel,
sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
{
Reference< chart2::XAxis > xAxis;
try
{
Reference< chart2::XChartDocument > xChart2Document( xChartModel, uno::UNO_QUERY );
if( xChart2Document.is() )
{
Reference< chart2::XDiagram > xDiagram( xChart2Document->getFirstDiagram());
Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
uno::Sequence< Reference< chart2::XCoordinateSystem > >
aCooSysSeq( xCooSysCnt->getCoordinateSystems());
sal_Int32 nCooSysIndex = 0;
if( nCooSysIndex < aCooSysSeq.getLength() )
{
Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIndex] );
if( xCooSys.is() && nDimensionIndex < xCooSys->getDimension() )
{
const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
if( nAxisIndex <= nMaxAxisIndex )
xAxis = xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex );
}
}
}
}
catch( uno::Exception & )
{
DBG_ERROR( "Couldn't get axis" );
}
return xAxis;
}
bool lcl_divideBy100( uno::Any& rDoubleAny )
{
bool bChanged = false;
double fValue=0.0;
if( (rDoubleAny>>=fValue) && (fValue!=0.0) )
{
fValue/=100.0;
rDoubleAny = uno::makeAny(fValue);
bChanged = true;
}
return bChanged;
}
bool lcl_AdaptWrongPercentScaleValues(chart2::ScaleData& rScaleData)
{
bool bChanged = lcl_divideBy100( rScaleData.Minimum );
bChanged = lcl_divideBy100( rScaleData.Maximum ) || bChanged;
bChanged = lcl_divideBy100( rScaleData.Origin ) || bChanged;
bChanged = lcl_divideBy100( rScaleData.IncrementData.Distance ) || bChanged;
return bChanged;
}
}//end anonymous namespace
void SchXMLAxisContext::CreateAxis()
{
m_rAxes.push_back( m_aCurrentAxis );
Reference< beans::XPropertySet > xDiaProp( m_rImportHelper.GetChartDocument()->getDiagram(), uno::UNO_QUERY );
if( !xDiaProp.is() )
return;
rtl::OUString aPropName;
switch( m_aCurrentAxis.eDimension )
{
case SCH_XML_AXIS_X:
if( m_aCurrentAxis.nAxisIndex == 0 )
aPropName = OUString::createFromAscii("HasXAxis");
else
aPropName = OUString::createFromAscii("HasSecondaryXAxis");
break;
case SCH_XML_AXIS_Y:
if( m_aCurrentAxis.nAxisIndex == 0 )
aPropName = OUString::createFromAscii("HasYAxis");
else
aPropName = OUString::createFromAscii("HasSecondaryYAxis");
break;
case SCH_XML_AXIS_Z:
if( m_aCurrentAxis.nAxisIndex == 0 )
aPropName = OUString::createFromAscii("HasXAxis");
else
aPropName = OUString::createFromAscii("HasSecondaryXAxis");
break;
case SCH_XML_AXIS_UNDEF:
DBG_ERROR( "Invalid axis" );
break;
}
try
{
xDiaProp->setPropertyValue( aPropName, uno::makeAny(sal_True) );
}
catch( beans::UnknownPropertyException & )
{
DBG_ERROR( "Couldn't turn on axis" );
}
if( m_aCurrentAxis.eDimension==SCH_XML_AXIS_Z )
{
bool bSettingZAxisSuccedded = false;
try
{
xDiaProp->getPropertyValue( aPropName ) >>= bSettingZAxisSuccedded;
}
catch( beans::UnknownPropertyException & )
{
DBG_ERROR( "Couldn't turn on z axis" );
}
if( !bSettingZAxisSuccedded )
return;
}
m_xAxisProps = Reference<beans::XPropertySet>( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ), uno::UNO_QUERY );
if( m_bAddMissingXAxisForNetCharts && m_aCurrentAxis.eDimension==SCH_XML_AXIS_Y && m_aCurrentAxis.nAxisIndex==0 )
{
try
{
xDiaProp->setPropertyValue( OUString::createFromAscii( "HasXAxis" ), uno::makeAny(sal_True) );
}
catch( beans::UnknownPropertyException & )
{
DBG_ERROR( "Couldn't turn on x axis" );
}
}
// set properties
if( m_xAxisProps.is())
{
uno::Any aTrueBool( uno::makeAny( sal_True ));
uno::Any aFalseBool( uno::makeAny( sal_False ));
// #i109879# the line color is black as default, in the model it is a light gray
m_xAxisProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "LineColor" )),
uno::makeAny( COL_BLACK ));
m_xAxisProps->setPropertyValue( OUString::createFromAscii( "DisplayLabels" ), aFalseBool );
// #88077# AutoOrigin 'on' is default
m_xAxisProps->setPropertyValue( OUString::createFromAscii( "AutoOrigin" ), aTrueBool );
if( m_bAxisTypeImported )
m_xAxisProps->setPropertyValue( OUString::createFromAscii( "AxisType" ), uno::makeAny(m_nAxisType) );
if( m_aAutoStyleName.getLength())
{
const SvXMLStylesContext* pStylesCtxt = m_rImportHelper.GetAutoStylesContext();
if( pStylesCtxt )
{
const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
m_rImportHelper.GetChartFamilyID(), m_aAutoStyleName );
if( pStyle && pStyle->ISA( XMLPropStyleContext ))
{
// note: SvXMLStyleContext::FillPropertySet is not const
XMLPropStyleContext * pPropStyleContext = const_cast< XMLPropStyleContext * >( dynamic_cast< const XMLPropStyleContext * >( pStyle ));
if( pPropStyleContext )
pPropStyleContext->FillPropertySet( m_xAxisProps );
if( m_bAdaptWrongPercentScaleValues && m_aCurrentAxis.eDimension==SCH_XML_AXIS_Y )
{
//set scale data of added x axis back to default
Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(),
m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex ) );
if( xAxis.is() )
{
chart2::ScaleData aScaleData( xAxis->getScaleData());
if( lcl_AdaptWrongPercentScaleValues(aScaleData) )
xAxis->setScaleData( aScaleData );
}
}
if( m_bAddMissingXAxisForNetCharts )
{
//copy style from y axis to added x axis:
Reference< chart::XAxisSupplier > xAxisSuppl( xDiaProp, uno::UNO_QUERY );
if( xAxisSuppl.is() )
{
Reference< beans::XPropertySet > xXAxisProp( xAxisSuppl->getAxis(0), uno::UNO_QUERY );
(( XMLPropStyleContext* )pStyle )->FillPropertySet( xXAxisProp );
}
//set scale data of added x axis back to default
Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(),
0 /*nDimensionIndex*/, 0 /*nAxisIndex*/ ) );
if( xAxis.is() )
{
chart2::ScaleData aScaleData;
aScaleData.AxisType = chart2::AxisType::CATEGORY;
aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
xAxis->setScaleData( aScaleData );
}
//set line style of added x axis to invisible
Reference< beans::XPropertySet > xNewAxisProp( xAxis, uno::UNO_QUERY );
if( xNewAxisProp.is() )
{
xNewAxisProp->setPropertyValue( OUString::createFromAscii("LineStyle")
, uno::makeAny(drawing::LineStyle_NONE));
}
}
if( m_bAdaptXAxisOrientationForOld2DBarCharts && m_aCurrentAxis.eDimension == SCH_XML_AXIS_X )
{
bool bIs3DChart = false;
if( xDiaProp.is() && ( xDiaProp->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Dim3D"))) >>= bIs3DChart )
&& !bIs3DChart )
{
Reference< chart2::XChartDocument > xChart2Document( GetImport().GetModel(), uno::UNO_QUERY );
if( xChart2Document.is() )
{
Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xChart2Document->getFirstDiagram(), uno::UNO_QUERY );
if( xCooSysCnt.is() )
{
uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
if( aCooSysSeq.getLength() )
{
bool bSwapXandYAxis = false;
Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] );
Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
if( xCooSysProp.is() && ( xCooSysProp->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("SwapXAndYAxis"))) >>= bSwapXandYAxis )
&& bSwapXandYAxis )
{
Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( 0, m_aCurrentAxis.nAxisIndex );
if( xAxis.is() )
{
chart2::ScaleData aScaleData = xAxis->getScaleData();
aScaleData.Orientation = chart2::AxisOrientation_REVERSE;
xAxis->setScaleData( aScaleData );
}
}
}
}
}
}
}
m_rbAxisPositionAttributeImported = m_rbAxisPositionAttributeImported || SchXMLTools::getPropertyFromContext(
OUString(RTL_CONSTASCII_USTRINGPARAM("CrossoverPosition")), pPropStyleContext, pStylesCtxt ).hasValue();
}
}
}
}
}
void SchXMLAxisContext::SetAxisTitle()
{
if( !m_aCurrentAxis.aTitle.getLength() )
return;
Reference< chart::XAxis > xAxis( lcl_getChartAxis( m_aCurrentAxis, m_xDiagram ) );
if( !xAxis.is() )
return;
Reference< beans::XPropertySet > xTitleProp( xAxis->getAxisTitle() );
if( xTitleProp.is() )
{
try
{
xTitleProp->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )), uno::makeAny(m_aCurrentAxis.aTitle) );
}
catch( beans::UnknownPropertyException & )
{
DBG_ERROR( "Property String for Title not available" );
}
}
}
//-----------------------------------------------------------------------
namespace
{
enum AxisChildTokens
{
XML_TOK_AXIS_TITLE,
XML_TOK_AXIS_CATEGORIES,
XML_TOK_AXIS_GRID,
XML_TOK_AXIS_DATE_SCALE,
XML_TOK_AXIS_DATE_SCALE_EXT
};
SvXMLTokenMapEntry aAxisChildTokenMap[] =
{
{ XML_NAMESPACE_CHART, XML_TITLE, XML_TOK_AXIS_TITLE },
{ XML_NAMESPACE_CHART, XML_CATEGORIES, XML_TOK_AXIS_CATEGORIES },
{ XML_NAMESPACE_CHART, XML_GRID, XML_TOK_AXIS_GRID },
{ XML_NAMESPACE_CHART, XML_DATE_SCALE, XML_TOK_AXIS_DATE_SCALE },
{ XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, XML_TOK_AXIS_DATE_SCALE_EXT },
XML_TOKEN_MAP_END
};
class AxisChildTokenMap : public SvXMLTokenMap
{
public:
AxisChildTokenMap(): SvXMLTokenMap( aAxisChildTokenMap ) {}
virtual ~AxisChildTokenMap() {}
};
//a AxisChildTokenMap Singleton
struct theAxisChildTokenMap : public rtl::Static< AxisChildTokenMap, theAxisChildTokenMap > {};
}
SvXMLImportContext* SchXMLAxisContext::CreateChildContext(
sal_uInt16 p_nPrefix,
const OUString& rLocalName,
const Reference< xml::sax::XAttributeList >& xAttrList )
{
SvXMLImportContext* pContext = 0;
const SvXMLTokenMap& rTokenMap = theAxisChildTokenMap::get();
switch( rTokenMap.Get( p_nPrefix, rLocalName ))
{
case XML_TOK_AXIS_TITLE:
{
Reference< drawing::XShape > xTitleShape = getTitleShape();
pContext = new SchXMLTitleContext( m_rImportHelper, GetImport(), rLocalName,
m_aCurrentAxis.aTitle,
xTitleShape );
}
break;
case XML_TOK_AXIS_CATEGORIES:
pContext = new SchXMLCategoriesContext( m_rImportHelper, GetImport(),
p_nPrefix, rLocalName,
m_rCategoriesAddress );
m_aCurrentAxis.bHasCategories = true;
break;
case XML_TOK_AXIS_DATE_SCALE:
case XML_TOK_AXIS_DATE_SCALE_EXT:
pContext = new DateScaleContext( m_rImportHelper, GetImport(),
p_nPrefix, rLocalName, m_xAxisProps );
m_bDateScaleImported = true;
break;
case XML_TOK_AXIS_GRID:
{
sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
bool bIsMajor = true; // default value for class is "major"
OUString sAutoStyleName;
for( sal_Int16 i = 0; i < nAttrCount; i++ )
{
OUString sAttrName = xAttrList->getNameByIndex( i );
OUString aLocalName;
sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
if( nPrefix == XML_NAMESPACE_CHART )
{
if( IsXMLToken( aLocalName, XML_CLASS ) )
{
if( IsXMLToken( xAttrList->getValueByIndex( i ), XML_MINOR ) )
bIsMajor = false;
}
else if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
sAutoStyleName = xAttrList->getValueByIndex( i );
}
}
CreateGrid( sAutoStyleName, bIsMajor );
// don't create a context => use default context. grid elements are empty
pContext = new SvXMLImportContext( GetImport(), p_nPrefix, rLocalName );
}
break;
default:
pContext = new SvXMLImportContext( GetImport(), p_nPrefix, rLocalName );
break;
}
return pContext;
}
void SchXMLAxisContext::EndElement()
{
if( !m_bDateScaleImported && m_nAxisType==chart::ChartAxisType::AUTOMATIC )
{
Reference< chart2::XAxis > xAxis( lcl_getAxis( GetImport().GetModel(), m_aCurrentAxis.eDimension, m_aCurrentAxis.nAxisIndex ) );
if( xAxis.is() )
{
chart2::ScaleData aScaleData( xAxis->getScaleData());
aScaleData.AutoDateAxis = false;//different default for older documents
xAxis->setScaleData( aScaleData );
}
}
SetAxisTitle();
}
// ========================================
namespace
{
Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem > xCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
{
Reference< chart2::XAxis > xAxis;
try
{
xAxis = xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex );
}
catch( uno::Exception & )
{
}
return xAxis;
}
} // anonymous namespace
void SchXMLAxisContext::CorrectAxisPositions( const Reference< chart2::XChartDocument >& xNewDoc,
const OUString& rChartTypeServiceName,
const OUString& rODFVersionOfFile,
bool bAxisPositionAttributeImported )
{
if( ( !rODFVersionOfFile.getLength() || rODFVersionOfFile.equalsAscii("1.0")
|| rODFVersionOfFile.equalsAscii("1.1")
|| ( rODFVersionOfFile.equalsAscii("1.2") && !bAxisPositionAttributeImported ) ) )
{
try
{
Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
uno::Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
if( aCooSysSeq.getLength() )
{
Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[0] );
if( xCooSys.is() )
{
Reference< chart2::XAxis > xMainXAxis = lcl_getAxis( xCooSys, 0, 0 );
Reference< chart2::XAxis > xMainYAxis = lcl_getAxis( xCooSys, 1, 0 );
//Reference< chart2::XAxis > xMajorZAxis = lcl_getAxis( xCooSys, 2, 0 );
Reference< chart2::XAxis > xSecondaryXAxis = lcl_getAxis( xCooSys, 0, 1 );
Reference< chart2::XAxis > xSecondaryYAxis = lcl_getAxis( xCooSys, 1, 1 );
Reference< beans::XPropertySet > xMainXAxisProp( xMainXAxis, uno::UNO_QUERY );
Reference< beans::XPropertySet > xMainYAxisProp( xMainYAxis, uno::UNO_QUERY );
Reference< beans::XPropertySet > xSecondaryXAxisProp( xSecondaryXAxis, uno::UNO_QUERY );
Reference< beans::XPropertySet > xSecondaryYAxisProp( xSecondaryYAxis, uno::UNO_QUERY );
if( xMainXAxisProp.is() && xMainYAxisProp.is() )
{
chart2::ScaleData aMainXScale = xMainXAxis->getScaleData();
if( 0 == rChartTypeServiceName.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.ScatterChartType" ) ) )
{
xMainYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_VALUE) );
double fCrossoverValue = 0.0;
aMainXScale.Origin >>= fCrossoverValue;
xMainYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverValue")
, uno::makeAny( fCrossoverValue ) );
if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
{
xMainYAxisProp->setPropertyValue( OUString::createFromAscii("LabelPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END) );
xMainYAxisProp->setPropertyValue( OUString::createFromAscii("MarkPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS) );
if( xSecondaryYAxisProp.is() )
xSecondaryYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_START) );
}
else
{
xMainYAxisProp->setPropertyValue( OUString::createFromAscii("LabelPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START) );
xMainYAxisProp->setPropertyValue( OUString::createFromAscii("MarkPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS) );
if( xSecondaryYAxisProp.is() )
xSecondaryYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_END) );
}
}
else
{
if( aMainXScale.Orientation == chart2::AxisOrientation_REVERSE )
{
xMainYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_END) );
if( xSecondaryYAxisProp.is() )
xSecondaryYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_START) );
}
else
{
xMainYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_START) );
if( xSecondaryYAxisProp.is() )
xSecondaryYAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_END) );
}
}
chart2::ScaleData aMainYScale = xMainYAxis->getScaleData();
xMainXAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_VALUE) );
double fCrossoverValue = 0.0;
aMainYScale.Origin >>= fCrossoverValue;
xMainXAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverValue")
, uno::makeAny( fCrossoverValue ) );
if( aMainYScale.Orientation == chart2::AxisOrientation_REVERSE )
{
xMainXAxisProp->setPropertyValue( OUString::createFromAscii("LabelPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END) );
xMainXAxisProp->setPropertyValue( OUString::createFromAscii("MarkPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS) );
if( xSecondaryXAxisProp.is() )
xSecondaryXAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_START) );
}
else
{
xMainXAxisProp->setPropertyValue( OUString::createFromAscii("LabelPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START) );
xMainXAxisProp->setPropertyValue( OUString::createFromAscii("MarkPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS) );
if( xSecondaryXAxisProp.is() )
xSecondaryXAxisProp->setPropertyValue( OUString::createFromAscii("CrossoverPosition")
, uno::makeAny( ::com::sun::star::chart::ChartAxisPosition_END) );
}
}
}
}
}
catch( uno::Exception & )
{
}
}
}
// ========================================
SchXMLCategoriesContext::SchXMLCategoriesContext(
SchXMLImportHelper& rImpHelper,
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const OUString& rLocalName,
OUString& rAddress ) :
SvXMLImportContext( rImport, nPrefix, rLocalName ),
m_rImportHelper( rImpHelper ),
mrAddress( rAddress )
{
}
SchXMLCategoriesContext::~SchXMLCategoriesContext()
{
}
void SchXMLCategoriesContext::StartElement( const Reference< xml::sax::XAttributeList >& xAttrList )
{
sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
for( sal_Int16 i = 0; i < nAttrCount; i++ )
{
OUString sAttrName = xAttrList->getNameByIndex( i );
OUString aLocalName;
sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
if( nPrefix == XML_NAMESPACE_TABLE &&
IsXMLToken( aLocalName, XML_CELL_RANGE_ADDRESS ) )
{
Reference< chart2::XChartDocument > xNewDoc( GetImport().GetModel(), uno::UNO_QUERY );
mrAddress = xAttrList->getValueByIndex( i );
}
}
}
// ========================================
DateScaleContext::DateScaleContext(
SchXMLImportHelper& rImpHelper,
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const OUString& rLocalName,
const Reference< beans::XPropertySet > xAxisProps ) :
SvXMLImportContext( rImport, nPrefix, rLocalName ),
m_rImportHelper( rImpHelper ),
m_xAxisProps( xAxisProps )
{
}
DateScaleContext::~DateScaleContext()
{
}
namespace
{
enum DateScaleAttributeTokens
{
XML_TOK_DATESCALE_BASE_TIME_UNIT,
XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE,
XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT,
XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE,
XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT
};
SvXMLTokenMapEntry aDateScaleAttributeTokenMap[] =
{
{ XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, XML_TOK_DATESCALE_BASE_TIME_UNIT },
{ XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE },
{ XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT },
{ XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE },
{ XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT },
XML_TOKEN_MAP_END
};
class DateScaleAttributeTokenMap : public SvXMLTokenMap
{
public:
DateScaleAttributeTokenMap(): SvXMLTokenMap( aDateScaleAttributeTokenMap ) {}
virtual ~DateScaleAttributeTokenMap() {}
};
struct theDateScaleAttributeTokenMap : public rtl::Static< DateScaleAttributeTokenMap, theDateScaleAttributeTokenMap > {};
sal_Int32 lcl_getTimeUnit( const OUString& rValue )
{
sal_Int32 nTimeUnit = ::com::sun::star::chart::TimeUnit::DAY;
if( IsXMLToken( rValue, XML_DAYS ) )
nTimeUnit = ::com::sun::star::chart::TimeUnit::DAY;
else if( IsXMLToken( rValue, XML_MONTHS ) )
nTimeUnit = ::com::sun::star::chart::TimeUnit::MONTH;
else if( IsXMLToken( rValue, XML_YEARS ) )
nTimeUnit = ::com::sun::star::chart::TimeUnit::YEAR;
return nTimeUnit;
}
}
void DateScaleContext::StartElement( const Reference< xml::sax::XAttributeList >& xAttrList )
{
if( !m_xAxisProps.is() )
return;
// parse attributes
sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
const SvXMLTokenMap& rAttrTokenMap = theDateScaleAttributeTokenMap::get();
bool bSetNewIncrement=false;
chart::TimeIncrement aIncrement;
m_xAxisProps->getPropertyValue( OUString::createFromAscii( "TimeIncrement" )) >>= aIncrement;
for( sal_Int16 i = 0; i < nAttrCount; i++ )
{
OUString sAttrName = xAttrList->getNameByIndex( i );
OUString aLocalName;
OUString aValue = xAttrList->getValueByIndex( i );
sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
{
case XML_TOK_DATESCALE_BASE_TIME_UNIT:
{
aIncrement.TimeResolution = uno::makeAny( lcl_getTimeUnit(aValue) );
bSetNewIncrement = true;
}
break;
case XML_TOK_DATESCALE_MAJOR_INTERVAL_VALUE:
{
chart::TimeInterval aInterval(1,0);
aIncrement.MajorTimeInterval >>= aInterval;
SvXMLUnitConverter::convertNumber( aInterval.Number, aValue );
aIncrement.MajorTimeInterval = uno::makeAny(aInterval);
bSetNewIncrement = true;
}
break;
case XML_TOK_DATESCALE_MAJOR_INTERVAL_UNIT:
{
chart::TimeInterval aInterval(1,0);
aIncrement.MajorTimeInterval >>= aInterval;
aInterval.TimeUnit = lcl_getTimeUnit(aValue);
aIncrement.MajorTimeInterval = uno::makeAny(aInterval);
bSetNewIncrement = true;
}
break;
case XML_TOK_DATESCALE_MINOR_INTERVAL_VALUE:
{
chart::TimeInterval aInterval(1,0);
aIncrement.MinorTimeInterval >>= aInterval;
SvXMLUnitConverter::convertNumber( aInterval.Number, aValue );
aIncrement.MinorTimeInterval = uno::makeAny(aInterval);
bSetNewIncrement = true;
}
break;
case XML_TOK_DATESCALE_MINOR_INTERVAL_UNIT:
{
chart::TimeInterval aInterval(1,0);
aIncrement.MinorTimeInterval >>= aInterval;
aInterval.TimeUnit = lcl_getTimeUnit(aValue);
aIncrement.MinorTimeInterval = uno::makeAny(aInterval);
bSetNewIncrement = true;
}
break;
}
}
if( bSetNewIncrement )
m_xAxisProps->setPropertyValue( OUString::createFromAscii( "TimeIncrement" ), uno::makeAny( aIncrement ) );
}
// ========================================