1278 lines
48 KiB
C++
1278 lines
48 KiB
C++
/* -*- 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 .
|
|
*/
|
|
|
|
#include "SchXMLPlotAreaContext.hxx"
|
|
#include <SchXMLImport.hxx>
|
|
#include "SchXMLAxisContext.hxx"
|
|
#include "SchXMLSeries2Context.hxx"
|
|
#include "SchXMLTools.hxx"
|
|
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <comphelper/sequence.hxx>
|
|
#include <sal/log.hxx>
|
|
#include <comphelper/diagnose_ex.hxx>
|
|
#include <utility>
|
|
#include <xmloff/xmlnamespace.hxx>
|
|
#include <xmloff/xmluconv.hxx>
|
|
#include <xmloff/prstylei.hxx>
|
|
#include <xmloff/xmlstyle.hxx>
|
|
|
|
#include <com/sun/star/awt/Point.hpp>
|
|
#include <com/sun/star/awt/Size.hpp>
|
|
#include <com/sun/star/chart/ErrorBarStyle.hpp>
|
|
#include <com/sun/star/chart/X3DDisplay.hpp>
|
|
#include <com/sun/star/chart/XStatisticDisplay.hpp>
|
|
#include <com/sun/star/chart/XDiagramPositioning.hpp>
|
|
#include <com/sun/star/chart/XChartDocument.hpp>
|
|
#include <com/sun/star/chart2/XChartDocument.hpp>
|
|
#include <com/sun/star/chart2/data/XDataSink.hpp>
|
|
#include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
|
|
#include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
|
|
#include <com/sun/star/drawing/CameraGeometry.hpp>
|
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
|
#include <com/sun/star/lang/XServiceInfo.hpp>
|
|
|
|
using namespace com::sun::star;
|
|
using namespace ::xmloff::token;
|
|
|
|
using com::sun::star::uno::Reference;
|
|
|
|
namespace
|
|
{
|
|
|
|
struct lcl_AxisHasCategories
|
|
{
|
|
bool operator() ( const SchXMLAxis & rAxis )
|
|
{
|
|
return rAxis.bHasCategories;
|
|
}
|
|
};
|
|
|
|
OUString lcl_ConvertRange( const OUString & rRange, const uno::Reference< chart2::XChartDocument > & xDoc )
|
|
{
|
|
OUString aResult = rRange;
|
|
if(!xDoc.is())
|
|
return aResult;
|
|
uno::Reference< chart2::data::XRangeXMLConversion > xConversion(
|
|
xDoc->getDataProvider(), uno::UNO_QUERY );
|
|
if( xConversion.is())
|
|
aResult = xConversion->convertRangeFromXML( rRange );
|
|
return aResult;
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
SchXML3DSceneAttributesHelper::SchXML3DSceneAttributesHelper( SvXMLImport& rImporter )
|
|
: SdXML3DSceneAttributesHelper( rImporter )
|
|
{
|
|
}
|
|
|
|
void SchXML3DSceneAttributesHelper::getCameraDefaultFromDiagram( const uno::Reference< chart::XDiagram >& xDiagram )
|
|
{
|
|
//different defaults for camera geometry necessary to workaround wrong behaviour in old chart
|
|
//in future make this version dependent if we have versioning (metastream) for ole objects
|
|
|
|
try
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY );
|
|
if( xProp.is() )
|
|
{
|
|
drawing::CameraGeometry aCamGeo;
|
|
xProp->getPropertyValue(u"D3DCameraGeometry"_ustr) >>= aCamGeo;
|
|
maVRP.setX( aCamGeo.vrp.PositionX );
|
|
maVRP.setY( aCamGeo.vrp.PositionY );
|
|
maVRP.setZ( aCamGeo.vrp.PositionZ );
|
|
maVPN.setX( aCamGeo.vpn.DirectionX );
|
|
maVPN.setY( aCamGeo.vpn.DirectionY );
|
|
maVPN.setZ( aCamGeo.vpn.DirectionZ );
|
|
maVUP.setX( aCamGeo.vup.DirectionX );
|
|
maVUP.setY( aCamGeo.vup.DirectionY );
|
|
maVUP.setZ( aCamGeo.vup.DirectionZ );
|
|
}
|
|
}
|
|
catch( const uno::Exception & )
|
|
{
|
|
TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught for property NumberOfLines");
|
|
}
|
|
}
|
|
|
|
SchXML3DSceneAttributesHelper::~SchXML3DSceneAttributesHelper()
|
|
{
|
|
}
|
|
|
|
SchXMLPlotAreaContext::SchXMLPlotAreaContext(
|
|
SchXMLImportHelper& rImpHelper,
|
|
SvXMLImport& rImport,
|
|
const OUString& rXLinkHRefAttributeToIndicateDataProvider,
|
|
OUString& rCategoriesAddress,
|
|
OUString& rChartAddress,
|
|
bool & rbHasRangeAtPlotArea,
|
|
bool & rAllRangeAddressesAvailable,
|
|
bool & rColHasLabels,
|
|
bool & rRowHasLabels,
|
|
chart::ChartDataRowSource & rDataRowSource,
|
|
SeriesDefaultsAndStyles& rSeriesDefaultsAndStyles,
|
|
OUString aChartTypeServiceName,
|
|
tSchXMLLSequencesPerIndex & rLSequencesPerIndex,
|
|
const awt::Size & rChartSize ) :
|
|
SvXMLImportContext( rImport ),
|
|
mrImportHelper( rImpHelper ),
|
|
mrCategoriesAddress( rCategoriesAddress ),
|
|
mrSeriesDefaultsAndStyles( rSeriesDefaultsAndStyles ),
|
|
mnNumOfLinesProp( 0 ),
|
|
mbStockHasVolume( false ),
|
|
mnSeries( 0 ),
|
|
m_aGlobalSeriesImportInfo( rAllRangeAddressesAvailable ),
|
|
maSceneImportHelper( rImport ),
|
|
m_aOuterPositioning( rImport ),
|
|
m_aInnerPositioning( rImport ),
|
|
mbPercentStacked(false),
|
|
m_bAxisPositionAttributeImported(false),
|
|
m_rXLinkHRefAttributeToIndicateDataProvider(rXLinkHRefAttributeToIndicateDataProvider),
|
|
mrChartAddress( rChartAddress ),
|
|
m_rbHasRangeAtPlotArea( rbHasRangeAtPlotArea ),
|
|
mrColHasLabels( rColHasLabels ),
|
|
mrRowHasLabels( rRowHasLabels ),
|
|
mrDataRowSource( rDataRowSource ),
|
|
maChartTypeServiceName(std::move( aChartTypeServiceName )),
|
|
mrLSequencesPerIndex( rLSequencesPerIndex ),
|
|
mbGlobalChartTypeUsedBySeries( false ),
|
|
maChartSize( rChartSize )
|
|
{
|
|
m_rbHasRangeAtPlotArea = false;
|
|
|
|
// get Diagram
|
|
const uno::Reference< chart::XChartDocument >& xDoc = rImpHelper.GetChartDocument();
|
|
if( xDoc.is())
|
|
{
|
|
mxDiagram = xDoc->getDiagram();
|
|
mxNewDoc.set( xDoc, uno::UNO_QUERY );
|
|
|
|
maSceneImportHelper.getCameraDefaultFromDiagram( mxDiagram );
|
|
}
|
|
SAL_WARN_IF( !mxDiagram.is(),"xmloff.chart", "Couldn't get XDiagram" );
|
|
|
|
// turn off all axes initially
|
|
uno::Any aFalseBool;
|
|
aFalseBool <<= false;
|
|
|
|
uno::Reference< lang::XServiceInfo > xInfo( mxDiagram, uno::UNO_QUERY );
|
|
uno::Reference< beans::XPropertySet > xProp( mxDiagram, uno::UNO_QUERY );
|
|
if( !xInfo.is() || !xProp.is() )
|
|
return;
|
|
|
|
try
|
|
{
|
|
xProp->setPropertyValue(u"HasXAxis"_ustr, aFalseBool );
|
|
xProp->setPropertyValue(u"HasXAxisGrid"_ustr, aFalseBool );
|
|
xProp->setPropertyValue(u"HasXAxisDescription"_ustr, aFalseBool );
|
|
xProp->setPropertyValue(u"HasSecondaryXAxis"_ustr, aFalseBool );
|
|
xProp->setPropertyValue(u"HasSecondaryXAxisDescription"_ustr, aFalseBool );
|
|
|
|
xProp->setPropertyValue(u"HasYAxis"_ustr, aFalseBool );
|
|
xProp->setPropertyValue(u"HasYAxisGrid"_ustr, aFalseBool );
|
|
xProp->setPropertyValue(u"HasYAxisDescription"_ustr, aFalseBool );
|
|
xProp->setPropertyValue(u"HasSecondaryYAxis"_ustr, aFalseBool );
|
|
xProp->setPropertyValue(u"HasSecondaryYAxisDescription"_ustr, aFalseBool );
|
|
|
|
xProp->setPropertyValue(u"HasZAxis"_ustr, aFalseBool );
|
|
xProp->setPropertyValue(u"HasZAxisDescription"_ustr, aFalseBool );
|
|
|
|
xProp->setPropertyValue(u"DataRowSource"_ustr, uno::Any(chart::ChartDataRowSource_COLUMNS) );
|
|
}
|
|
catch( const beans::UnknownPropertyException & )
|
|
{
|
|
SAL_WARN("xmloff.chart", "Property required by service not supported" );
|
|
}
|
|
}
|
|
|
|
SchXMLPlotAreaContext::~SchXMLPlotAreaContext()
|
|
{}
|
|
|
|
void SchXMLPlotAreaContext::startFastElement (sal_Int32 /*nElement*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// parse attributes
|
|
uno::Reference< chart2::XChartDocument > xNewDoc( GetImport().GetModel(), uno::UNO_QUERY );
|
|
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
switch( aIter.getToken() )
|
|
{
|
|
case XML_ELEMENT(SVG, XML_X):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X):
|
|
case XML_ELEMENT(SVG, XML_Y):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y):
|
|
case XML_ELEMENT(SVG, XML_WIDTH):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
|
|
case XML_ELEMENT(SVG, XML_HEIGHT):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
|
|
m_aOuterPositioning.readPositioningAttribute( aIter.getToken(), aIter.toView() );
|
|
break;
|
|
case XML_ELEMENT(CHART, XML_STYLE_NAME):
|
|
msAutoStyleName = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(TABLE, XML_CELL_RANGE_ADDRESS):
|
|
mrChartAddress = lcl_ConvertRange( aIter.toString(), xNewDoc );
|
|
// indicator for getting data from the outside
|
|
m_rbHasRangeAtPlotArea = true;
|
|
break;
|
|
case XML_ELEMENT(CHART, XML_DATA_SOURCE_HAS_LABELS):
|
|
{
|
|
if( IsXMLToken(aIter, XML_BOTH) )
|
|
mrColHasLabels = mrRowHasLabels = true;
|
|
else if( IsXMLToken(aIter, XML_ROW) )
|
|
mrRowHasLabels = true;
|
|
else if( IsXMLToken(aIter, XML_COLUMN) )
|
|
mrColHasLabels = true;
|
|
}
|
|
break;
|
|
case XML_ELEMENT(DR3D, XML_TRANSFORM):
|
|
case XML_ELEMENT(DR3D, XML_VRP):
|
|
case XML_ELEMENT(DR3D, XML_VPN):
|
|
case XML_ELEMENT(DR3D, XML_VUP):
|
|
case XML_ELEMENT(DR3D, XML_PROJECTION):
|
|
case XML_ELEMENT(DR3D, XML_DISTANCE):
|
|
case XML_ELEMENT(DR3D, XML_FOCAL_LENGTH):
|
|
case XML_ELEMENT(DR3D, XML_SHADOW_SLANT):
|
|
case XML_ELEMENT(DR3D, XML_SHADE_MODE):
|
|
case XML_ELEMENT(DR3D, XML_AMBIENT_COLOR):
|
|
case XML_ELEMENT(DR3D, XML_LIGHTING_MODE):
|
|
maSceneImportHelper.processSceneAttribute( aIter );
|
|
break;
|
|
default:
|
|
XMLOFF_WARN_UNKNOWN("xmloff", aIter);
|
|
}
|
|
}
|
|
|
|
if( ! mxNewDoc.is())
|
|
{
|
|
uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
|
|
if( xDocProp.is())
|
|
{
|
|
try
|
|
{
|
|
xDocProp->setPropertyValue(u"DataSourceLabelsInFirstColumn"_ustr, uno::Any(mrColHasLabels) );
|
|
xDocProp->setPropertyValue(u"DataSourceLabelsInFirstRow"_ustr, uno::Any(mrRowHasLabels) );
|
|
}
|
|
catch( const beans::UnknownPropertyException & )
|
|
{
|
|
SAL_WARN("xmloff.chart", "Properties missing" );
|
|
}
|
|
}
|
|
}
|
|
|
|
// set properties
|
|
uno::Reference< beans::XPropertySet > xProp( mxDiagram, uno::UNO_QUERY );
|
|
if( !msAutoStyleName.isEmpty())
|
|
{
|
|
if( xProp.is())
|
|
{
|
|
const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
|
|
if( pStylesCtxt )
|
|
{
|
|
const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
|
|
SchXMLImportHelper::GetChartFamilyID(), msAutoStyleName );
|
|
|
|
XMLPropStyleContext* pPropStyleContext =
|
|
const_cast< XMLPropStyleContext * >(
|
|
dynamic_cast< const XMLPropStyleContext * >( pStyle ) );
|
|
if( pPropStyleContext )
|
|
{
|
|
pPropStyleContext->FillPropertySet( xProp );
|
|
|
|
// get the data row source that was set without having data
|
|
xProp->getPropertyValue(u"DataRowSource"_ustr)
|
|
>>= mrDataRowSource;
|
|
|
|
//lines on/off
|
|
//this old property is not supported fully anymore with the new chart, so we need to get the information a little bit different from similar properties
|
|
mrSeriesDefaultsAndStyles.maLinesOnProperty = SchXMLTools::getPropertyFromContext(
|
|
u"Lines", pPropStyleContext, pStylesCtxt );
|
|
|
|
//handle automatic position and size
|
|
m_aOuterPositioning.readAutomaticPositioningProperties( pPropStyleContext, pStylesCtxt );
|
|
|
|
//correct default starting angle for old 3D pies
|
|
if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan3_0( GetImport().GetModel() ) )
|
|
{
|
|
bool bIs3d = false;
|
|
if( xProp.is() && ( xProp->getPropertyValue(u"Dim3D"_ustr) >>= bIs3d ) &&
|
|
bIs3d )
|
|
{
|
|
if( maChartTypeServiceName == "com.sun.star.chart2.PieChartType" || maChartTypeServiceName == "com.sun.star.chart2.DonutChartType" )
|
|
{
|
|
OUString aPropName( u"StartingAngle"_ustr );
|
|
uno::Any aAStartingAngle( SchXMLTools::getPropertyFromContext( aPropName, pPropStyleContext, pStylesCtxt ) );
|
|
if( !aAStartingAngle.hasValue() )
|
|
xProp->setPropertyValue( aPropName, uno::Any(sal_Int32(0)) ) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//remember default values for dataseries
|
|
if(xProp.is())
|
|
{
|
|
try
|
|
{
|
|
mrSeriesDefaultsAndStyles.maSymbolTypeDefault = xProp->getPropertyValue(u"SymbolType"_ustr);
|
|
mrSeriesDefaultsAndStyles.maDataCaptionDefault = xProp->getPropertyValue(u"DataCaption"_ustr);
|
|
|
|
mrSeriesDefaultsAndStyles.maMeanValueDefault = xProp->getPropertyValue(u"MeanValue"_ustr);
|
|
mrSeriesDefaultsAndStyles.maRegressionCurvesDefault = xProp->getPropertyValue(u"RegressionCurves"_ustr);
|
|
|
|
bool bStacked = false;
|
|
mrSeriesDefaultsAndStyles.maStackedDefault = xProp->getPropertyValue(u"Stacked"_ustr);
|
|
mrSeriesDefaultsAndStyles.maStackedDefault >>= bStacked;
|
|
mrSeriesDefaultsAndStyles.maPercentDefault = xProp->getPropertyValue(u"Percent"_ustr);
|
|
mrSeriesDefaultsAndStyles.maPercentDefault >>= mbPercentStacked;
|
|
mrSeriesDefaultsAndStyles.maStackedBarsConnectedDefault = xProp->getPropertyValue(u"StackedBarsConnected"_ustr);
|
|
|
|
// deep
|
|
uno::Any aDeepProperty( xProp->getPropertyValue(u"Deep"_ustr));
|
|
// #124488# old versions store a 3d area and 3D line deep chart with Deep==false => workaround for this
|
|
if( ! (bStacked || mbPercentStacked ))
|
|
{
|
|
if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( GetImport().GetModel() ) )
|
|
{
|
|
bool bIs3d = false;
|
|
if( ( xProp->getPropertyValue(u"Dim3D"_ustr) >>= bIs3d ) &&
|
|
bIs3d )
|
|
{
|
|
if( maChartTypeServiceName == "com.sun.star.chart2.AreaChartType" || maChartTypeServiceName == "com.sun.star.chart2.LineChartType" )
|
|
{
|
|
aDeepProperty <<= true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
mrSeriesDefaultsAndStyles.maDeepDefault = std::move(aDeepProperty);
|
|
|
|
xProp->getPropertyValue(u"NumberOfLines"_ustr) >>= mnNumOfLinesProp;
|
|
xProp->getPropertyValue(u"Volume"_ustr) >>= mbStockHasVolume;
|
|
}
|
|
catch( const uno::Exception & )
|
|
{
|
|
TOOLS_INFO_EXCEPTION("xmloff.chart", "PlotAreaContext:EndElement(): Exception caught");
|
|
}
|
|
} // if
|
|
|
|
bool bCreateInternalDataProvider = false;
|
|
if( m_rXLinkHRefAttributeToIndicateDataProvider == "." ) //data comes from the chart itself
|
|
bCreateInternalDataProvider = true;
|
|
else if( m_rXLinkHRefAttributeToIndicateDataProvider == ".." ) //data comes from the parent application
|
|
bCreateInternalDataProvider = false;
|
|
else if( !m_rXLinkHRefAttributeToIndicateDataProvider.isEmpty() ) //not supported so far to get the data by sibling objects -> fall back to chart itself
|
|
bCreateInternalDataProvider = true;
|
|
else if( !m_rbHasRangeAtPlotArea )
|
|
bCreateInternalDataProvider = true;
|
|
|
|
if( bCreateInternalDataProvider && mxNewDoc.is() )
|
|
{
|
|
// we have no complete range => we have own data, so switch the data
|
|
// provider to internal. Clone is not necessary, as we don't have any
|
|
// data yet.
|
|
mxNewDoc->createInternalDataProvider( false /* bCloneExistingData */ );
|
|
if( xProp.is() && mrDataRowSource!=chart::ChartDataRowSource_COLUMNS )
|
|
xProp->setPropertyValue(u"DataRowSource"_ustr, uno::Any(mrDataRowSource) );
|
|
}
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLPlotAreaContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
SvXMLImportContext* pContext = nullptr;
|
|
|
|
switch(nElement)
|
|
{
|
|
case XML_ELEMENT(CHART_EXT, XML_COORDINATE_REGION):
|
|
case XML_ELEMENT(CHART, XML_COORDINATE_REGION):
|
|
{
|
|
pContext = new SchXMLCoordinateRegionContext( GetImport(), m_aInnerPositioning );
|
|
}
|
|
break;
|
|
|
|
case XML_ELEMENT(CHART, XML_AXIS):
|
|
{
|
|
bool bAddMissingXAxisForNetCharts = false;
|
|
bool bAdaptWrongPercentScaleValues = false;
|
|
if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( GetImport().GetModel() ) )
|
|
{
|
|
//correct errors from older versions
|
|
|
|
// for NetCharts there were no xAxis exported to older files
|
|
// so we need to add the x axis here for those old NetChart files
|
|
if ( maChartTypeServiceName == "com.sun.star.chart2.NetChartType" )
|
|
bAddMissingXAxisForNetCharts = true;
|
|
|
|
//Issue 59288
|
|
if( mbPercentStacked )
|
|
bAdaptWrongPercentScaleValues = true;
|
|
}
|
|
|
|
bool bAdaptXAxisOrientationForOld2DBarCharts = false;
|
|
if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_4( GetImport().GetModel() ) )
|
|
{
|
|
//issue74660
|
|
if ( maChartTypeServiceName == "com.sun.star.chart2.ColumnChartType" )
|
|
bAdaptXAxisOrientationForOld2DBarCharts = true;
|
|
}
|
|
|
|
pContext = new SchXMLAxisContext( mrImportHelper, GetImport(), mxDiagram, maAxes, mrCategoriesAddress,
|
|
bAddMissingXAxisForNetCharts, bAdaptWrongPercentScaleValues, bAdaptXAxisOrientationForOld2DBarCharts, m_bAxisPositionAttributeImported );
|
|
}
|
|
break;
|
|
|
|
case XML_ELEMENT(CHART, XML_SERIES):
|
|
{
|
|
if( mxNewDoc.is())
|
|
{
|
|
pContext = new SchXMLSeries2Context(
|
|
mrImportHelper, GetImport(),
|
|
mxNewDoc, maAxes,
|
|
mrSeriesDefaultsAndStyles.maSeriesStyleVector,
|
|
mrSeriesDefaultsAndStyles.maRegressionStyleVector,
|
|
mnSeries,
|
|
mbStockHasVolume,
|
|
m_aGlobalSeriesImportInfo,
|
|
maChartTypeServiceName,
|
|
mrLSequencesPerIndex,
|
|
mbGlobalChartTypeUsedBySeries, maChartSize );
|
|
}
|
|
mnSeries++;
|
|
}
|
|
break;
|
|
|
|
case XML_ELEMENT(CHART, XML_WALL):
|
|
pContext = new SchXMLWallFloorContext( mrImportHelper, GetImport(), mxDiagram,
|
|
SchXMLWallFloorContext::CONTEXT_TYPE_WALL );
|
|
break;
|
|
case XML_ELEMENT(CHART, XML_FLOOR):
|
|
pContext = new SchXMLWallFloorContext( mrImportHelper, GetImport(), mxDiagram,
|
|
SchXMLWallFloorContext::CONTEXT_TYPE_FLOOR );
|
|
break;
|
|
|
|
case XML_ELEMENT(DR3D, XML_LIGHT):
|
|
pContext = maSceneImportHelper.create3DLightContext( xAttrList );
|
|
break;
|
|
|
|
// elements for stock charts
|
|
case XML_ELEMENT(CHART, XML_STOCK_GAIN_MARKER):
|
|
pContext = new SchXMLStockContext( mrImportHelper, GetImport(), mxDiagram,
|
|
SchXMLStockContext::CONTEXT_TYPE_GAIN );
|
|
break;
|
|
case XML_ELEMENT(CHART, XML_STOCK_LOSS_MARKER):
|
|
pContext = new SchXMLStockContext( mrImportHelper, GetImport(), mxDiagram,
|
|
SchXMLStockContext::CONTEXT_TYPE_LOSS );
|
|
break;
|
|
case XML_ELEMENT(CHART, XML_STOCK_RANGE_LINE):
|
|
pContext = new SchXMLStockContext( mrImportHelper, GetImport(), mxDiagram,
|
|
SchXMLStockContext::CONTEXT_TYPE_RANGE );
|
|
break;
|
|
default:
|
|
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
|
|
}
|
|
|
|
return pContext;
|
|
}
|
|
|
|
void SchXMLPlotAreaContext::endFastElement(sal_Int32 )
|
|
{
|
|
// set categories
|
|
if( !mrCategoriesAddress.isEmpty() && mxNewDoc.is())
|
|
{
|
|
uno::Reference< chart2::data::XDataProvider > xDataProvider(
|
|
mxNewDoc->getDataProvider() );
|
|
// @todo: correct coordinate system index
|
|
sal_Int32 nDimension( 0 );
|
|
::std::vector< SchXMLAxis >::const_iterator aIt(
|
|
::std::find_if( maAxes.begin(), maAxes.end(), lcl_AxisHasCategories()));
|
|
if( aIt != maAxes.end())
|
|
nDimension = static_cast< sal_Int32 >( (*aIt).eDimension );
|
|
SchXMLTools::CreateCategories(
|
|
xDataProvider, mxNewDoc, mrCategoriesAddress,
|
|
0 /* nCooSysIndex */,
|
|
nDimension, &mrLSequencesPerIndex );
|
|
}
|
|
|
|
uno::Reference< beans::XPropertySet > xDiaProp( mxDiagram, uno::UNO_QUERY );
|
|
if( xDiaProp.is())
|
|
{
|
|
bool bIsThreeDim = false;
|
|
uno::Any aAny = xDiaProp->getPropertyValue(u"Dim3D"_ustr);
|
|
aAny >>= bIsThreeDim;
|
|
|
|
// set 3d scene attributes
|
|
if( bIsThreeDim )
|
|
{
|
|
// set scene attributes at diagram
|
|
maSceneImportHelper.setSceneAttributes( xDiaProp );
|
|
}
|
|
|
|
// set correct number of lines at series
|
|
if( ! m_aGlobalSeriesImportInfo.rbAllRangeAddressesAvailable && mnNumOfLinesProp > 0 && maChartTypeServiceName == "com.sun.star.chart2.ColumnChartType" )
|
|
{
|
|
try
|
|
{
|
|
xDiaProp->setPropertyValue(u"NumberOfLines"_ustr,
|
|
uno::Any( mnNumOfLinesProp ));
|
|
}
|
|
catch( const uno::Exception & )
|
|
{
|
|
TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught for property NumberOfLines");
|
|
}
|
|
}
|
|
|
|
// #i32366# stock has volume
|
|
if( mxDiagram->getDiagramType() == "com.sun.star.chart.StockDiagram" &&
|
|
mbStockHasVolume )
|
|
{
|
|
try
|
|
{
|
|
xDiaProp->setPropertyValue(u"Volume"_ustr,
|
|
uno::Any( true ));
|
|
}
|
|
catch( const uno::Exception & )
|
|
{
|
|
TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught for property Volume");
|
|
}
|
|
}
|
|
}
|
|
|
|
// set changed size and position after properties (esp. 3d)
|
|
|
|
uno::Reference< chart::XDiagramPositioning > xDiaPos( mxDiagram, uno::UNO_QUERY );
|
|
if( xDiaPos.is())
|
|
{
|
|
if( !m_aOuterPositioning.isAutomatic() )
|
|
{
|
|
if( m_aInnerPositioning.hasPosSize() )
|
|
xDiaPos->setDiagramPositionExcludingAxes( m_aInnerPositioning.getRectangle() );
|
|
else if( m_aOuterPositioning.hasPosSize() )
|
|
{
|
|
if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan3_3( GetImport().GetModel() ) ) //old version of OOo did write a wrong rectangle for the diagram size
|
|
xDiaPos->setDiagramPositionIncludingAxesAndAxisTitles( m_aOuterPositioning.getRectangle() );
|
|
else
|
|
xDiaPos->setDiagramPositionIncludingAxes( m_aOuterPositioning.getRectangle() );
|
|
}
|
|
}
|
|
}
|
|
|
|
SchXMLAxisContext::CorrectAxisPositions( uno::Reference< chart2::XChartDocument >( mrImportHelper.GetChartDocument(), uno::UNO_QUERY ), maChartTypeServiceName, GetImport().GetODFVersion(), m_bAxisPositionAttributeImported );
|
|
}
|
|
|
|
SchXMLDataLabelSpanContext::SchXMLDataLabelSpanContext( SvXMLImport& rImport, ::std::vector<OUString>& rLabels):
|
|
SvXMLImportContext( rImport ),
|
|
mrLabels(rLabels)
|
|
{
|
|
}
|
|
|
|
void SchXMLDataLabelSpanContext::characters(const OUString& rChars)
|
|
{
|
|
maCharBuffer.append(rChars);
|
|
}
|
|
|
|
void SchXMLDataLabelSpanContext::endFastElement(sal_Int32 )
|
|
{
|
|
mrLabels.push_back(maCharBuffer.makeStringAndClear());
|
|
}
|
|
|
|
SchXMLDataLabelParaContext::SchXMLDataLabelParaContext( SvXMLImport& rImport, ::std::vector<OUString>& rLabels):
|
|
SvXMLImportContext( rImport ),
|
|
mrLabels(rLabels)
|
|
{
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataLabelParaContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
|
|
{
|
|
if ( nElement == XML_ELEMENT(TEXT, XML_SPAN) )
|
|
return new SchXMLDataLabelSpanContext(GetImport(), mrLabels);
|
|
else
|
|
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
|
|
return nullptr;
|
|
}
|
|
|
|
SchXMLDataLabelContext::SchXMLDataLabelContext(SvXMLImport& rImport,
|
|
CustomLabelsInfo& rLabels,
|
|
DataRowPointStyle& rDataLabelStyle)
|
|
: SvXMLImportContext(rImport)
|
|
, mrLabels(rLabels)
|
|
, mrDataLabelStyle(rDataLabelStyle)
|
|
{
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataLabelContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
|
|
{
|
|
if ( nElement == XML_ELEMENT(TEXT, XML_P) )
|
|
return new SchXMLDataLabelParaContext(GetImport(), mrLabels.mLabels);
|
|
else
|
|
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
|
|
return nullptr;
|
|
}
|
|
|
|
void SchXMLDataLabelContext::startFastElement(
|
|
sal_Int32 /*nElement*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
switch(aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(SVG, XML_X):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X):
|
|
{
|
|
sal_Int32 nResultValue;
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(nResultValue, aIter.toView());
|
|
mrDataLabelStyle.mo_nLabelAbsolutePosX = nResultValue;
|
|
break;
|
|
}
|
|
case XML_ELEMENT(SVG, XML_Y):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y):
|
|
{
|
|
sal_Int32 nResultValue;
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(nResultValue, aIter.toView());
|
|
mrDataLabelStyle.mo_nLabelAbsolutePosY = nResultValue;
|
|
break;
|
|
}
|
|
case XML_ELEMENT(CHART, XML_STYLE_NAME):
|
|
mrDataLabelStyle.msStyleName = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(LO_EXT, XML_DATA_LABEL_GUID):
|
|
mrLabels.msLabelGuid = aIter.toString();
|
|
mrLabels.mbDataLabelsRange = true;
|
|
break;
|
|
case XML_ELEMENT(LO_EXT, XML_DATA_LABELS_CELL_RANGE):
|
|
mrLabels.msLabelsCellRange = aIter.toString();
|
|
mrLabels.mbDataLabelsRange = true;
|
|
break;
|
|
default:
|
|
XMLOFF_WARN_UNKNOWN("xmloff", aIter);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
SchXMLDataPointContext::SchXMLDataPointContext( SvXMLImport& rImport,
|
|
::std::vector< DataRowPointStyle >& rStyleVector,
|
|
const css::uno::Reference< css::chart2::XDataSeries >& xSeries,
|
|
sal_Int32& rIndex,
|
|
bool bSymbolSizeForSeriesIsMissingInFile ) :
|
|
SvXMLImportContext( rImport ),
|
|
mrStyleVector( rStyleVector ),
|
|
mrIndex( rIndex ),
|
|
mDataPoint(DataRowPointStyle::DATA_POINT, xSeries, rIndex, 1, OUString{}),
|
|
mDataLabel(DataRowPointStyle::DATA_LABEL_POINT, xSeries, rIndex, 1, OUString{})
|
|
{
|
|
mDataPoint.mbSymbolSizeForSeriesIsMissingInFile = bSymbolSizeForSeriesIsMissingInFile;
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataPointContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
|
|
{
|
|
SvXMLImportContext* pContext = nullptr;
|
|
switch(nElement)
|
|
{
|
|
case XML_ELEMENT(CHART, XML_DATA_LABEL):
|
|
mbHasLabelParagraph = true;
|
|
pContext = new SchXMLDataLabelContext(GetImport(), mDataPoint.mCustomLabels,
|
|
mDataLabel);
|
|
break;
|
|
default:
|
|
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
|
|
}
|
|
return pContext;
|
|
}
|
|
|
|
SchXMLDataPointContext::~SchXMLDataPointContext()
|
|
{
|
|
}
|
|
|
|
void SchXMLDataPointContext::startFastElement (sal_Int32 /*Element*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
OUString sAutoStyleName;
|
|
sal_Int32 nRepeat = 1;
|
|
OUString sCustomLabelField;
|
|
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(CHART, XML_STYLE_NAME):
|
|
{
|
|
sAutoStyleName = aIter.toString();
|
|
mDataPoint.msStyleName = sAutoStyleName;
|
|
mDataLabel.msStyleNameOfParent = sAutoStyleName;
|
|
break;
|
|
}
|
|
case XML_ELEMENT(CHART, XML_REPEATED):
|
|
{
|
|
nRepeat = aIter.toInt32();
|
|
mDataPoint.m_nPointRepeat = nRepeat;
|
|
mDataLabel.m_nPointRepeat = nRepeat;
|
|
break;
|
|
}
|
|
// Deprecated. New documents use the chart:data-label element
|
|
// instead in order to store custom label text.
|
|
case XML_ELEMENT(LO_EXT, XML_CUSTOM_LABEL_FIELD):
|
|
if (!mbHasLabelParagraph)
|
|
{
|
|
sCustomLabelField = aIter.toString();
|
|
mDataPoint.mCustomLabels.mLabels.push_back(sCustomLabelField);
|
|
}
|
|
break;
|
|
case XML_ELEMENT(LO_EXT, XML_HIDE_LEGEND):
|
|
{
|
|
bool bHideLegend = aIter.toBoolean();
|
|
if (bHideLegend)
|
|
{
|
|
uno::Sequence<sal_Int32> deletedLegendEntriesSeq;
|
|
Reference<beans::XPropertySet> xSeriesProp(mDataPoint.m_xSeries, uno::UNO_QUERY);
|
|
xSeriesProp->getPropertyValue(u"DeletedLegendEntries"_ustr) >>= deletedLegendEntriesSeq;
|
|
std::vector<sal_Int32> deletedLegendEntries;
|
|
for (const auto& deletedLegendEntry : deletedLegendEntriesSeq)
|
|
{
|
|
deletedLegendEntries.push_back(deletedLegendEntry);
|
|
}
|
|
deletedLegendEntries.push_back(mDataPoint.m_nPointIndex);
|
|
xSeriesProp->setPropertyValue(u"DeletedLegendEntries"_ustr, uno::Any(comphelper::containerToSequence(deletedLegendEntries)));
|
|
}
|
|
break;
|
|
}
|
|
case XML_ELEMENT(LO_EXT, XML_CUSTOM_LABEL_POS_X):
|
|
{
|
|
mDataPoint.mCustomLabelPos[0] = aIter.toDouble();
|
|
break;
|
|
}
|
|
case XML_ELEMENT(LO_EXT, XML_CUSTOM_LABEL_POS_Y):
|
|
{
|
|
mDataPoint.mCustomLabelPos[1] = aIter.toDouble();
|
|
break;
|
|
}
|
|
default:
|
|
XMLOFF_WARN_UNKNOWN("xmloff", aIter);
|
|
}
|
|
}
|
|
|
|
mrIndex += nRepeat;
|
|
}
|
|
|
|
void SchXMLDataPointContext::endFastElement(sal_Int32 )
|
|
{
|
|
if(!mDataPoint.msStyleName.isEmpty() || mDataPoint.mCustomLabels.mLabels.size() > 0)
|
|
{
|
|
mrStyleVector.push_back(mDataPoint);
|
|
}
|
|
if (!mDataLabel.msStyleName.isEmpty() || mDataLabel.mo_nLabelAbsolutePosX.has_value()
|
|
|| mDataLabel.mo_nLabelAbsolutePosY.has_value())
|
|
{
|
|
mrStyleVector.push_back(mDataLabel);
|
|
}
|
|
}
|
|
|
|
SchXMLPositionAttributesHelper::SchXMLPositionAttributesHelper( SvXMLImport& rImporter )
|
|
: m_rImport( rImporter )
|
|
, m_aPosition(0,0)
|
|
, m_aSize(0,0)
|
|
, m_bHasSizeWidth( false )
|
|
, m_bHasSizeHeight( false )
|
|
, m_bHasPositionX( false )
|
|
, m_bHasPositionY( false )
|
|
, m_bAutoSize( false )
|
|
, m_bAutoPosition( false )
|
|
{
|
|
}
|
|
|
|
bool SchXMLPositionAttributesHelper::hasPosSize() const
|
|
{
|
|
return (m_bHasPositionX && m_bHasPositionY) && (m_bHasSizeWidth && m_bHasSizeHeight);
|
|
}
|
|
|
|
bool SchXMLPositionAttributesHelper::isAutomatic() const
|
|
{
|
|
return m_bAutoSize || m_bAutoPosition;
|
|
}
|
|
|
|
void SchXMLPositionAttributesHelper::readPositioningAttribute( sal_Int32 nAttributeToken, std::string_view rValue )
|
|
{
|
|
if( !IsTokenInNamespace(nAttributeToken, XML_NAMESPACE_SVG) && !IsTokenInNamespace(nAttributeToken, XML_NAMESPACE_SVG_COMPAT) )
|
|
return;
|
|
|
|
switch (nAttributeToken & TOKEN_MASK)
|
|
{
|
|
case XML_X:
|
|
{
|
|
m_rImport.GetMM100UnitConverter().convertMeasureToCore(
|
|
m_aPosition.X, rValue );
|
|
m_bHasPositionX = true;
|
|
break;
|
|
}
|
|
case XML_Y:
|
|
{
|
|
m_rImport.GetMM100UnitConverter().convertMeasureToCore(
|
|
m_aPosition.Y, rValue );
|
|
m_bHasPositionY = true;
|
|
break;
|
|
}
|
|
case XML_WIDTH:
|
|
{
|
|
m_rImport.GetMM100UnitConverter().convertMeasureToCore(
|
|
m_aSize.Width, rValue );
|
|
m_bHasSizeWidth = true;
|
|
break;
|
|
}
|
|
case XML_HEIGHT:
|
|
{
|
|
m_rImport.GetMM100UnitConverter().convertMeasureToCore(
|
|
m_aSize.Height, rValue );
|
|
m_bHasSizeHeight = true;
|
|
break;
|
|
}
|
|
default:
|
|
XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttributeToken, OUString::fromUtf8(rValue));
|
|
}
|
|
}
|
|
|
|
void SchXMLPositionAttributesHelper::readAutomaticPositioningProperties( XMLPropStyleContext const * pPropStyleContext, const SvXMLStylesContext* pStylesCtxt )
|
|
{
|
|
if( pPropStyleContext && pStylesCtxt )
|
|
{
|
|
//handle automatic position and size
|
|
SchXMLTools::getPropertyFromContext(
|
|
u"AutomaticSize", pPropStyleContext, pStylesCtxt ) >>= m_bAutoSize;
|
|
SchXMLTools::getPropertyFromContext(
|
|
u"AutomaticPosition", pPropStyleContext, pStylesCtxt ) >>= m_bAutoPosition;
|
|
}
|
|
}
|
|
|
|
SchXMLCoordinateRegionContext::SchXMLCoordinateRegionContext(
|
|
SvXMLImport& rImport
|
|
, SchXMLPositionAttributesHelper& rPositioning )
|
|
: SvXMLImportContext( rImport )
|
|
, m_rPositioning( rPositioning )
|
|
{
|
|
}
|
|
|
|
SchXMLCoordinateRegionContext::~SchXMLCoordinateRegionContext()
|
|
{
|
|
}
|
|
|
|
void SchXMLCoordinateRegionContext::startFastElement (sal_Int32 /*Element*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// parse attributes
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
m_rPositioning.readPositioningAttribute( aIter.getToken(), aIter.toView() );
|
|
}
|
|
|
|
SchXMLWallFloorContext::SchXMLWallFloorContext(
|
|
SchXMLImportHelper& rImpHelper,
|
|
SvXMLImport& rImport,
|
|
uno::Reference< chart::XDiagram > const & xDiagram,
|
|
ContextType eContextType ) :
|
|
SvXMLImportContext( rImport ),
|
|
mrImportHelper( rImpHelper ),
|
|
mxWallFloorSupplier( xDiagram, uno::UNO_QUERY ),
|
|
meContextType( eContextType )
|
|
{
|
|
}
|
|
|
|
SchXMLWallFloorContext::~SchXMLWallFloorContext()
|
|
{
|
|
}
|
|
|
|
void SchXMLWallFloorContext::startFastElement (sal_Int32 /*Element*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
if( !mxWallFloorSupplier.is())
|
|
return;
|
|
|
|
OUString sAutoStyleName;
|
|
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
if( aIter.getToken() == XML_ELEMENT(CHART, XML_STYLE_NAME) )
|
|
sAutoStyleName = aIter.toString();
|
|
else
|
|
XMLOFF_WARN_UNKNOWN("xmloff", aIter);
|
|
}
|
|
|
|
// set properties
|
|
uno::Reference< beans::XPropertySet > xProp = ( meContextType == CONTEXT_TYPE_WALL )
|
|
? mxWallFloorSupplier->getWall()
|
|
: mxWallFloorSupplier->getFloor();
|
|
|
|
if (!sAutoStyleName.isEmpty())
|
|
mrImportHelper.FillAutoStyle(sAutoStyleName, xProp);
|
|
}
|
|
|
|
SchXMLStockContext::SchXMLStockContext(
|
|
SchXMLImportHelper& rImpHelper,
|
|
SvXMLImport& rImport,
|
|
uno::Reference< chart::XDiagram > const & xDiagram,
|
|
ContextType eContextType ) :
|
|
SvXMLImportContext( rImport ),
|
|
mrImportHelper( rImpHelper ),
|
|
mxStockPropProvider( xDiagram, uno::UNO_QUERY ),
|
|
meContextType( eContextType )
|
|
{
|
|
}
|
|
|
|
SchXMLStockContext::~SchXMLStockContext()
|
|
{
|
|
}
|
|
|
|
void SchXMLStockContext::startFastElement (sal_Int32 /*Element*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
if( !mxStockPropProvider.is())
|
|
return;
|
|
|
|
OUString sAutoStyleName;
|
|
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
if( aIter.getToken() == XML_ELEMENT(CHART, XML_STYLE_NAME) )
|
|
sAutoStyleName = aIter.toString();
|
|
else
|
|
XMLOFF_WARN_UNKNOWN("xmloff", aIter);
|
|
}
|
|
|
|
if( sAutoStyleName.isEmpty())
|
|
return;
|
|
|
|
// set properties
|
|
uno::Reference< beans::XPropertySet > xProp;
|
|
switch( meContextType )
|
|
{
|
|
case CONTEXT_TYPE_GAIN:
|
|
xProp = mxStockPropProvider->getUpBar();
|
|
break;
|
|
case CONTEXT_TYPE_LOSS:
|
|
xProp = mxStockPropProvider->getDownBar();
|
|
break;
|
|
case CONTEXT_TYPE_RANGE:
|
|
xProp = mxStockPropProvider->getMinMaxLine();
|
|
break;
|
|
}
|
|
|
|
mrImportHelper.FillAutoStyle(sAutoStyleName, xProp);
|
|
}
|
|
|
|
static void lcl_setErrorBarSequence ( const uno::Reference< chart2::XChartDocument > &xDoc,
|
|
const uno::Reference< beans::XPropertySet > &xBarProp,
|
|
const OUString &aXMLRange,
|
|
bool bPositiveValue, bool bYError,
|
|
tSchXMLLSequencesPerIndex& rSequences)
|
|
{
|
|
uno::Reference< css::chart2::data::XDataProvider > xDataProvider(xDoc->getDataProvider());
|
|
uno::Reference< css::chart2::data::XDataSource > xDataSource( xBarProp, uno::UNO_QUERY );
|
|
uno::Reference< css::chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
|
|
|
|
assert( xDataSink.is() && xDataSource.is() && xDataProvider.is() );
|
|
|
|
OUString aRange(lcl_ConvertRange(aXMLRange,xDoc));
|
|
|
|
uno::Reference< chart2::data::XDataSequence > xNewSequence(
|
|
xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
|
|
|
|
if( !xNewSequence.is())
|
|
return;
|
|
|
|
SchXMLTools::setXMLRangePropertyAtDataSequence(xNewSequence,aXMLRange);
|
|
|
|
OUStringBuffer aRoleBuffer("error-bars-");
|
|
if( bYError )
|
|
aRoleBuffer.append( 'y' );
|
|
else
|
|
aRoleBuffer.append( 'x');
|
|
|
|
aRoleBuffer.append( '-' );
|
|
|
|
if( bPositiveValue )
|
|
aRoleBuffer = aRoleBuffer.append( "positive" );
|
|
else
|
|
aRoleBuffer = aRoleBuffer.append( "negative" );
|
|
|
|
OUString aRole = aRoleBuffer.makeStringAndClear();
|
|
|
|
Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
|
|
|
|
xSeqProp->setPropertyValue(u"Role"_ustr, uno::Any( aRole ));
|
|
|
|
const Reference< uno::XComponentContext >& xContext = comphelper::getProcessComponentContext();
|
|
|
|
Reference< chart2::data::XLabeledDataSequence > xLabelSeq( chart2::data::LabeledDataSequence::create(xContext),
|
|
uno::UNO_QUERY_THROW );
|
|
|
|
rSequences.emplace( tSchXMLIndexWithPart( -2, SCH_XML_PART_ERROR_BARS ), xLabelSeq );
|
|
|
|
xLabelSeq->setValues( xNewSequence );
|
|
|
|
uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
|
|
xDataSource->getDataSequences());
|
|
|
|
aSequences.realloc( aSequences.getLength() + 1 );
|
|
aSequences.getArray()[ aSequences.getLength() - 1 ] = std::move(xLabelSeq);
|
|
xDataSink->setData( aSequences );
|
|
|
|
}
|
|
|
|
SchXMLStatisticsObjectContext::SchXMLStatisticsObjectContext(
|
|
SchXMLImportHelper& rImpHelper,
|
|
SvXMLImport& rImport,
|
|
OUString sSeriesStyleName,
|
|
::std::vector< DataRowPointStyle >& rStyleVector,
|
|
css::uno::Reference< css::chart2::XDataSeries > xSeries,
|
|
ContextType eContextType,
|
|
tSchXMLLSequencesPerIndex & rLSequencesPerIndex) :
|
|
|
|
SvXMLImportContext( rImport ),
|
|
mrImportHelper( rImpHelper ),
|
|
mrStyleVector( rStyleVector ),
|
|
m_xSeries(std::move( xSeries )),
|
|
meContextType( eContextType ),
|
|
maSeriesStyleName(std::move( sSeriesStyleName)),
|
|
mrLSequencesPerIndex(rLSequencesPerIndex)
|
|
{}
|
|
|
|
SchXMLStatisticsObjectContext::~SchXMLStatisticsObjectContext()
|
|
{
|
|
}
|
|
|
|
namespace {
|
|
|
|
void SetErrorBarStyleProperties( const OUString& rStyleName, const uno::Reference< beans::XPropertySet >& xBarProp,
|
|
SchXMLImportHelper const & rImportHelper )
|
|
{
|
|
const SvXMLStylesContext* pStylesCtxt = rImportHelper.GetAutoStylesContext();
|
|
const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(SchXMLImportHelper::GetChartFamilyID(),
|
|
rStyleName);
|
|
|
|
XMLPropStyleContext &rSeriesStyleContext =
|
|
const_cast< XMLPropStyleContext& >( dynamic_cast< const XMLPropStyleContext& >( *pStyle ));
|
|
|
|
rSeriesStyleContext.FillPropertySet( xBarProp );
|
|
}
|
|
|
|
void SetErrorBarPropertiesFromStyleName( const OUString& aStyleName, const uno::Reference< beans::XPropertySet>& xBarProp,
|
|
SchXMLImportHelper const & rImportHelper, OUString& aPosRange, OUString& aNegRange)
|
|
{
|
|
const SvXMLStylesContext* pStylesCtxt = rImportHelper.GetAutoStylesContext();
|
|
const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(SchXMLImportHelper::GetChartFamilyID(),
|
|
aStyleName);
|
|
|
|
XMLPropStyleContext * pSeriesStyleContext =
|
|
const_cast< XMLPropStyleContext * >( dynamic_cast< const XMLPropStyleContext * >( pStyle ));
|
|
|
|
uno::Any aAny = SchXMLTools::getPropertyFromContext(u"ErrorBarStyle",
|
|
pSeriesStyleContext,pStylesCtxt);
|
|
|
|
if ( !aAny.hasValue() )
|
|
return;
|
|
|
|
sal_Int32 aBarStyle = css::chart::ErrorBarStyle::NONE;
|
|
aAny >>= aBarStyle;
|
|
xBarProp->setPropertyValue(u"ErrorBarStyle"_ustr, aAny);
|
|
|
|
aAny = SchXMLTools::getPropertyFromContext(u"ShowPositiveError",
|
|
pSeriesStyleContext,pStylesCtxt);
|
|
|
|
if(aAny.hasValue())
|
|
xBarProp->setPropertyValue(u"ShowPositiveError"_ustr,aAny);
|
|
|
|
aAny = SchXMLTools::getPropertyFromContext(u"ShowNegativeError",
|
|
pSeriesStyleContext,pStylesCtxt);
|
|
|
|
if(aAny.hasValue())
|
|
xBarProp->setPropertyValue(u"ShowNegativeError"_ustr,aAny);
|
|
|
|
aAny = SchXMLTools::getPropertyFromContext(u"PositiveError",
|
|
pSeriesStyleContext, pStylesCtxt);
|
|
|
|
if(aAny.hasValue())
|
|
xBarProp->setPropertyValue(u"PositiveError"_ustr, aAny);
|
|
else
|
|
{
|
|
aAny = SchXMLTools::getPropertyFromContext(u"ConstantErrorHigh",
|
|
pSeriesStyleContext, pStylesCtxt);
|
|
|
|
if(aAny.hasValue())
|
|
xBarProp->setPropertyValue(u"PositiveError"_ustr, aAny);
|
|
}
|
|
|
|
aAny = SchXMLTools::getPropertyFromContext(u"NegativeError",
|
|
pSeriesStyleContext, pStylesCtxt);
|
|
|
|
if(aAny.hasValue())
|
|
xBarProp->setPropertyValue(u"NegativeError"_ustr, aAny);
|
|
else
|
|
{
|
|
aAny = SchXMLTools::getPropertyFromContext(u"ConstantErrorLow",
|
|
pSeriesStyleContext, pStylesCtxt);
|
|
|
|
if(aAny.hasValue())
|
|
xBarProp->setPropertyValue(u"NegativeError"_ustr, aAny);
|
|
}
|
|
|
|
aAny = SchXMLTools::getPropertyFromContext(u"ErrorBarRangePositive",
|
|
pSeriesStyleContext, pStylesCtxt);
|
|
if( aAny.hasValue() )
|
|
{
|
|
aAny >>= aPosRange;
|
|
}
|
|
|
|
aAny = SchXMLTools::getPropertyFromContext(u"ErrorBarRangeNegative",
|
|
pSeriesStyleContext, pStylesCtxt);
|
|
if( aAny.hasValue() )
|
|
{
|
|
aAny >>= aNegRange;
|
|
}
|
|
|
|
aAny = SchXMLTools::getPropertyFromContext(u"Weight",
|
|
pSeriesStyleContext, pStylesCtxt);
|
|
if( aAny.hasValue() )
|
|
{
|
|
xBarProp->setPropertyValue(u"Weight"_ustr, aAny);
|
|
}
|
|
|
|
aAny = SchXMLTools::getPropertyFromContext(u"PercentageError",
|
|
pSeriesStyleContext, pStylesCtxt);
|
|
if( aAny.hasValue() && aBarStyle == css::chart::ErrorBarStyle::RELATIVE )
|
|
{
|
|
xBarProp->setPropertyValue(u"PositiveError"_ustr, aAny);
|
|
xBarProp->setPropertyValue(u"NegativeError"_ustr, aAny);
|
|
}
|
|
|
|
switch(aBarStyle)
|
|
{
|
|
case css::chart::ErrorBarStyle::ERROR_MARGIN:
|
|
{
|
|
aAny = SchXMLTools::getPropertyFromContext(u"NegativeError",
|
|
pSeriesStyleContext,pStylesCtxt);
|
|
|
|
xBarProp->setPropertyValue(u"NegativeError"_ustr,aAny);
|
|
|
|
aAny = SchXMLTools::getPropertyFromContext(u"PositiveError",
|
|
pSeriesStyleContext,pStylesCtxt);
|
|
|
|
xBarProp->setPropertyValue(u"PositiveError"_ustr,aAny);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void SchXMLStatisticsObjectContext::startFastElement (sal_Int32 /*Element*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
OUString sAutoStyleName;
|
|
OUString aPosRange;
|
|
OUString aNegRange;
|
|
bool bYError = true; /// Default errorbar, to be backward compatible with older files!
|
|
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(CHART, XML_STYLE_NAME):
|
|
sAutoStyleName = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(CHART, XML_DIMENSION):
|
|
bYError = aIter.toView() == "y";
|
|
break;
|
|
case XML_ELEMENT(CHART, XML_ERROR_UPPER_RANGE):
|
|
aPosRange = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(CHART, XML_ERROR_LOWER_RANGE):
|
|
aNegRange = aIter.toString();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( sAutoStyleName.isEmpty() )
|
|
return;
|
|
|
|
DataRowPointStyle aStyle( DataRowPointStyle::MEAN_VALUE, m_xSeries, -1, 1, sAutoStyleName );
|
|
|
|
switch( meContextType )
|
|
{
|
|
case CONTEXT_TYPE_MEAN_VALUE_LINE:
|
|
aStyle.meType = DataRowPointStyle::MEAN_VALUE;
|
|
break;
|
|
case CONTEXT_TYPE_ERROR_INDICATOR:
|
|
{
|
|
aStyle.meType = DataRowPointStyle::ERROR_INDICATOR;
|
|
|
|
uno::Reference< lang::XMultiServiceFactory > xFact = comphelper::getProcessServiceFactory();
|
|
|
|
uno::Reference< beans::XPropertySet > xBarProp( xFact->createInstance(u"com.sun.star.chart2.ErrorBar"_ustr ),
|
|
uno::UNO_QUERY );
|
|
|
|
xBarProp->setPropertyValue(u"ErrorBarStyle"_ustr,uno::Any(css::chart::ErrorBarStyle::NONE));
|
|
xBarProp->setPropertyValue(u"PositiveError"_ustr,uno::Any(0.0));
|
|
xBarProp->setPropertyValue(u"NegativeError"_ustr,uno::Any(0.0));
|
|
xBarProp->setPropertyValue(u"Weight"_ustr,uno::Any(1.0));
|
|
xBarProp->setPropertyValue(u"ShowPositiveError"_ustr,uno::Any(true));
|
|
xBarProp->setPropertyValue(u"ShowNegativeError"_ustr,uno::Any(true));
|
|
|
|
// first import defaults from parent style
|
|
SetErrorBarStyleProperties( maSeriesStyleName, xBarProp, mrImportHelper );
|
|
SetErrorBarStyleProperties( sAutoStyleName, xBarProp, mrImportHelper );
|
|
SetErrorBarPropertiesFromStyleName( maSeriesStyleName, xBarProp, mrImportHelper, aPosRange, aNegRange );
|
|
SetErrorBarPropertiesFromStyleName( sAutoStyleName, xBarProp, mrImportHelper, aPosRange, aNegRange );
|
|
|
|
uno::Reference< chart2::XChartDocument > xDoc(GetImport().GetModel(),uno::UNO_QUERY);
|
|
|
|
if (!aPosRange.isEmpty())
|
|
lcl_setErrorBarSequence(xDoc,xBarProp,aPosRange,true,bYError, mrLSequencesPerIndex);
|
|
|
|
if (!aNegRange.isEmpty())
|
|
lcl_setErrorBarSequence(xDoc,xBarProp,aNegRange,false,bYError, mrLSequencesPerIndex);
|
|
|
|
if ( !bYError )
|
|
{
|
|
aStyle.m_xErrorXProperties.set( xBarProp );
|
|
}
|
|
else
|
|
{
|
|
aStyle.m_xErrorYProperties.set( xBarProp );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
mrStyleVector.push_back( aStyle );
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|