summaryrefslogtreecommitdiff
path: root/xmloff/source/chart/SchXMLChartContext.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xmloff/source/chart/SchXMLChartContext.cxx')
-rw-r--r--xmloff/source/chart/SchXMLChartContext.cxx1248
1 files changed, 1248 insertions, 0 deletions
diff --git a/xmloff/source/chart/SchXMLChartContext.cxx b/xmloff/source/chart/SchXMLChartContext.cxx
new file mode 100644
index 000000000000..131b7a97e73e
--- /dev/null
+++ b/xmloff/source/chart/SchXMLChartContext.cxx
@@ -0,0 +1,1248 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_xmloff.hxx"
+
+#include "SchXMLChartContext.hxx"
+#include "SchXMLImport.hxx"
+#include "SchXMLLegendContext.hxx"
+#include "SchXMLPlotAreaContext.hxx"
+#include "SchXMLParagraphContext.hxx"
+#include "SchXMLTableContext.hxx"
+#include "SchXMLSeriesHelper.hxx"
+#include "SchXMLSeries2Context.hxx"
+#include "SchXMLTools.hxx"
+#include <comphelper/mediadescriptor.hxx>
+#include <tools/debug.hxx>
+// header for class ByteString
+#include <tools/string.hxx>
+#include "xmloff/xmlnmspe.hxx"
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlstyle.hxx>
+#include <xmloff/prstylei.hxx>
+
+#include "vector"
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/chart/XDiagram.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/util/XStringMapping.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XVisualObject.hpp>
+
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart2/data/XDataSink.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
+#include <com/sun/star/chart2/XChartTypeContainer.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+
+using namespace com::sun::star;
+using namespace ::xmloff::token;
+using ::rtl::OUString;
+using com::sun::star::uno::Reference;
+using namespace ::SchXMLTools;
+
+namespace
+{
+
+void lcl_setRoleAtLabeledSequence(
+ const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq,
+ const ::rtl::OUString &rRole )
+{
+ // set role of sequence
+ uno::Reference< chart2::data::XDataSequence > xValues( xLSeq->getValues());
+ if( xValues.is())
+ {
+ uno::Reference< beans::XPropertySet > xProp( xValues, uno::UNO_QUERY );
+ if( xProp.is())
+ xProp->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM( "Role" )), uno::makeAny( rRole ));
+ }
+}
+
+void lcl_MoveDataToCandleStickSeries(
+ const uno::Reference< chart2::data::XDataSource > & xDataSource,
+ const uno::Reference< chart2::XDataSeries > & xDestination,
+ const OUString & rRole )
+{
+ try
+ {
+ uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq(
+ xDataSource->getDataSequences());
+ if( aLabeledSeq.getLength())
+ {
+ lcl_setRoleAtLabeledSequence( aLabeledSeq[0], rRole );
+
+ // add to data series
+ uno::Reference< chart2::data::XDataSource > xSource( xDestination, uno::UNO_QUERY_THROW );
+ // @todo: realloc only once outside this function
+ uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences());
+ aData.realloc( aData.getLength() + 1);
+ aData[ aData.getLength() - 1 ] = aLabeledSeq[0];
+ uno::Reference< chart2::data::XDataSink > xSink( xDestination, uno::UNO_QUERY_THROW );
+ xSink->setData( aData );
+ }
+ }
+ catch( uno::Exception & )
+ {
+ OSL_FAIL( "Exception caught while moving data to candlestick series" );
+ }
+}
+
+void lcl_setRoleAtFirstSequence(
+ const uno::Reference< chart2::XDataSeries > & xSeries,
+ const ::rtl::OUString & rRole )
+{
+ uno::Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
+ if( xSource.is())
+ {
+ uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
+ if( aSeq.getLength())
+ lcl_setRoleAtLabeledSequence( aSeq[0], rRole );
+ }
+}
+
+void lcl_removeEmptyChartTypeGroups( const uno::Reference< chart2::XChartDocument > & xDoc )
+{
+ if( ! xDoc.is())
+ return;
+
+ uno::Reference< chart2::XDiagram > xDia( xDoc->getFirstDiagram());
+ if( ! xDia.is())
+ return;
+
+ try
+ {
+ // count all charttype groups to be able to leave at least one
+ sal_Int32 nRemainingGroups = 0;
+ uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY_THROW );
+ uno::Sequence< uno::Reference< chart2::XCoordinateSystem > >
+ aCooSysSeq( xCooSysCnt->getCoordinateSystems());
+ for( sal_Int32 nI = aCooSysSeq.getLength(); nI--; )
+ {
+ uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nI], uno::UNO_QUERY_THROW );
+ nRemainingGroups += xCTCnt->getChartTypes().getLength();
+ }
+
+ // delete all empty groups, but leave at least group (empty or not)
+ for( sal_Int32 nI = aCooSysSeq.getLength(); nI-- && (nRemainingGroups > 1); )
+ {
+ uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nI], uno::UNO_QUERY_THROW );
+ uno::Sequence< uno::Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
+ for( sal_Int32 nJ=aCTSeq.getLength(); nJ-- && (nRemainingGroups > 1); )
+ {
+ uno::Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nJ], uno::UNO_QUERY_THROW );
+ if( xDSCnt->getDataSeries().getLength() == 0 )
+ {
+ // note: iterator stays valid as we have a local sequence
+ xCTCnt->removeChartType( aCTSeq[nJ] );
+ --nRemainingGroups;
+ }
+ }
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ String aStr( ex.Message );
+ ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
+ OSL_TRACE( "Exception caught while removing empty chart types: %s", aBStr.GetBuffer());
+ }
+}
+
+uno::Sequence< sal_Int32 > lcl_getNumberSequenceFromString( const ::rtl::OUString& rStr, bool bAddOneToEachOldIndex )
+{
+ const sal_Unicode aSpace( ' ' );
+
+ // count number of entries
+ ::std::vector< sal_Int32 > aVec;
+ sal_Int32 nLastPos = 0;
+ sal_Int32 nPos = 0;
+ while( nPos != -1 )
+ {
+ nPos = rStr.indexOf( aSpace, nLastPos );
+ if( nPos > nLastPos )
+ {
+ aVec.push_back( rStr.copy( nLastPos, (nPos - nLastPos) ).toInt32() );
+ }
+ if( nPos != -1 )
+ nLastPos = nPos + 1;
+ }
+ // last entry
+ if( nLastPos != 0 &&
+ rStr.getLength() > nLastPos )
+ {
+ aVec.push_back( rStr.copy( nLastPos, (rStr.getLength() - nLastPos) ).toInt32() );
+ }
+
+ const sal_Int32 nVecSize = aVec.size();
+ uno::Sequence< sal_Int32 > aSeq( nVecSize );
+
+ if(!bAddOneToEachOldIndex)
+ {
+ sal_Int32* pSeqArr = aSeq.getArray();
+ for( nPos = 0; nPos < nVecSize; ++nPos )
+ {
+ pSeqArr[ nPos ] = aVec[ nPos ];
+ }
+ }
+ else if( bAddOneToEachOldIndex )
+ {
+ aSeq.realloc( nVecSize+1 );
+ aSeq[0]=0;
+
+ sal_Int32* pSeqArr = aSeq.getArray();
+ for( nPos = 0; nPos < nVecSize; ++nPos )
+ {
+ pSeqArr[ nPos+1 ] = aVec[ nPos ]+1;
+ }
+ }
+
+ return aSeq;
+}
+
+} // anonymous namespace
+
+// ----------------------------------------
+
+SchXMLChartContext::SchXMLChartContext( SchXMLImportHelper& rImpHelper,
+ SvXMLImport& rImport, const rtl::OUString& rLocalName ) :
+ SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
+ mrImportHelper( rImpHelper ),
+ m_bHasRangeAtPlotArea( false ),
+ m_bHasTableElement( false ),
+ mbAllRangeAddressesAvailable( sal_True ),
+ mbColHasLabels( sal_False ),
+ mbRowHasLabels( sal_False ),
+ meDataRowSource( chart::ChartDataRowSource_COLUMNS ),
+ mbIsStockChart( false )
+{
+}
+
+SchXMLChartContext::~SchXMLChartContext()
+{}
+
+void SchXMLChartContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
+{
+ // parse attributes
+ sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
+ const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetChartAttrTokenMap();
+
+ uno::Reference< embed::XVisualObject > xVisualObject( mrImportHelper.GetChartDocument(), uno::UNO_QUERY);
+ DBG_ASSERT(xVisualObject.is(),"need xVisualObject for page size");
+ if( xVisualObject.is() )
+ maChartSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); //#i103460# take the size given from the parent frame as default
+
+ // this flag is necessarry for pie charts in the core
+ sal_Bool bSetSwitchData = sal_False;
+
+ ::rtl::OUString sAutoStyleName;
+ ::rtl::OUString aOldChartTypeName;
+ bool bHasAddin = false;
+
+ for( sal_Int16 i = 0; i < nAttrCount; i++ )
+ {
+ rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
+ rtl::OUString aLocalName;
+ rtl::OUString aValue = xAttrList->getValueByIndex( i );
+ sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
+
+ switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
+ {
+ case XML_TOK_CHART_HREF:
+ m_aXLinkHRefAttributeToIndicateDataProvider = aValue;
+ break;
+
+ case XML_TOK_CHART_CLASS:
+ {
+ rtl::OUString sClassName;
+ sal_uInt16 nClassPrefix =
+ GetImport().GetNamespaceMap().GetKeyByAttrName(
+ aValue, &sClassName );
+ if( XML_NAMESPACE_CHART == nClassPrefix )
+ {
+ SchXMLChartTypeEnum eChartTypeEnum = SchXMLTools::GetChartTypeEnum( sClassName );
+ if( eChartTypeEnum != XML_CHART_CLASS_UNKNOWN )
+ {
+ aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( sClassName, true /* bUseOldNames */ );
+ maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( sClassName, false /* bUseOldNames */ );
+ switch( eChartTypeEnum )
+ {
+ case XML_CHART_CLASS_CIRCLE:
+ bSetSwitchData = sal_True;
+ break;
+ case XML_CHART_CLASS_STOCK:
+ mbIsStockChart = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else if( XML_NAMESPACE_OOO == nClassPrefix )
+ {
+ // service is taken from add-in-name attribute
+ bHasAddin = true;
+
+ aOldChartTypeName = sClassName;
+ maChartTypeServiceName = sClassName;
+ }
+ }
+ break;
+
+ case XML_TOK_CHART_WIDTH:
+ GetImport().GetMM100UnitConverter().convertMeasure( maChartSize.Width, aValue );
+ break;
+
+ case XML_TOK_CHART_HEIGHT:
+ GetImport().GetMM100UnitConverter().convertMeasure( maChartSize.Height, aValue );
+ break;
+
+ case XML_TOK_CHART_STYLE_NAME:
+ sAutoStyleName = aValue;
+ break;
+
+ case XML_TOK_CHART_COL_MAPPING:
+ msColTrans = aValue;
+ break;
+ case XML_TOK_CHART_ROW_MAPPING:
+ msRowTrans = aValue;
+ break;
+ }
+ }
+
+ if( aOldChartTypeName.getLength()<= 0 )
+ {
+ OSL_FAIL( "need a charttype to create a diagram" );
+ //set a fallback value:
+ ::rtl::OUString aChartClass_Bar( GetXMLToken(XML_BAR ) );
+ aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, true /* bUseOldNames */ );
+ maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, false /* bUseOldNames */ );
+ }
+
+ // Set the size of the draw page.
+ if( xVisualObject.is() )
+ xVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, maChartSize );
+
+ InitChart( aOldChartTypeName, bSetSwitchData);
+
+ if( bHasAddin )
+ {
+ //correct charttype serveice name when having an addin
+ //and don't refresh addin during load
+ uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
+ if( xDocProp.is() )
+ {
+ try
+ {
+ xDocProp->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "BaseDiagram" ))) >>= aOldChartTypeName;
+ maChartTypeServiceName = SchXMLTools::GetNewChartTypeName( aOldChartTypeName );
+ xDocProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "RefreshAddInAllowed" )) , uno::makeAny( sal_False) );
+ }
+ catch( uno::Exception & )
+ {
+ OSL_FAIL( "Exception during import SchXMLChartContext::StartElement" );
+ }
+ }
+ }
+
+ // set auto-styles for Area
+ uno::Reference< beans::XPropertySet > xProp( mrImportHelper.GetChartDocument()->getArea(), uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
+ if( pStylesCtxt )
+ {
+ const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
+ mrImportHelper.GetChartFamilyID(), sAutoStyleName );
+
+ if( pStyle && pStyle->ISA( XMLPropStyleContext ))
+ (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
+ }
+ }
+}
+
+namespace
+{
+
+struct NewDonutSeries
+{
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XDataSeries > m_xSeries;
+ ::rtl::OUString msStyleName;
+ sal_Int32 mnAttachedAxis;
+
+ ::std::vector< ::rtl::OUString > m_aSeriesStyles;
+ ::std::vector< ::rtl::OUString > m_aPointStyles;
+
+ NewDonutSeries( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XDataSeries >& xSeries, sal_Int32 nPointCount )
+ : m_xSeries( xSeries )
+ , mnAttachedAxis( 1 )
+ {
+ m_aPointStyles.resize(nPointCount);
+ m_aSeriesStyles.resize(nPointCount);
+ }
+
+ void setSeriesStyleNameToPoint( const ::rtl::OUString& rStyleName, sal_Int32 nPointIndex )
+ {
+ DBG_ASSERT(nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()),"donut point <-> series count mismatch");
+ if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
+ m_aSeriesStyles[nPointIndex]=rStyleName;
+ }
+
+ void setPointStyleNameToPoint( const ::rtl::OUString& rStyleName, sal_Int32 nPointIndex )
+ {
+ DBG_ASSERT(nPointIndex < static_cast<sal_Int32>(m_aPointStyles.size()),"donut point <-> series count mismatch");
+ if( nPointIndex < static_cast<sal_Int32>(m_aPointStyles.size()) )
+ m_aPointStyles[nPointIndex]=rStyleName;
+ }
+
+ ::std::list< DataRowPointStyle > creatStyleList()
+ {
+ ::std::list< DataRowPointStyle > aRet;
+
+ DataRowPointStyle aSeriesStyle( DataRowPointStyle::DATA_SERIES
+ , m_xSeries, -1, 1, msStyleName, mnAttachedAxis );
+ aRet.push_back( aSeriesStyle );
+
+ sal_Int32 nPointIndex=0;
+ ::std::vector< ::rtl::OUString >::iterator aPointIt( m_aPointStyles.begin() );
+ ::std::vector< ::rtl::OUString >::iterator aPointEnd( m_aPointStyles.end() );
+ while( aPointIt != aPointEnd )
+ {
+ DataRowPointStyle aPointStyle( DataRowPointStyle::DATA_POINT
+ , m_xSeries, nPointIndex, 1, *aPointIt, mnAttachedAxis );
+ if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
+ {
+ aPointStyle.msSeriesStyleNameForDonuts = m_aSeriesStyles[nPointIndex];
+ }
+ if( aPointStyle.msSeriesStyleNameForDonuts.getLength()
+ || aPointStyle.msStyleName.getLength() )
+ aRet.push_back( aPointStyle );
+ ++aPointIt;
+ ++nPointIndex;
+ }
+
+ return aRet;
+ }
+};
+
+void lcl_swapPointAndSeriesStylesForDonutCharts( ::std::list< DataRowPointStyle >& rStyleList
+ , const ::std::map< ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XDataSeries> , sal_Int32 >& rSeriesMap )
+{
+ ::std::list< DataRowPointStyle >::iterator aIt(rStyleList.begin());
+ ::std::list< DataRowPointStyle >::iterator aEnd(rStyleList.end());
+
+ //detect old series count
+ //and add old series to aSeriesMap
+ ::std::map< ::com::sun::star::uno::Reference<
+ ::com::sun::star::chart2::XDataSeries >, sal_Int32 > aSeriesMap(rSeriesMap);
+ sal_Int32 nOldSeriesCount = 0;
+ {
+ sal_Int32 nMaxOldSeriesIndex = 0;
+ sal_Int32 nOldSeriesIndex = 0;
+ for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
+ {
+ DataRowPointStyle aStyle(*aIt);
+ if(aStyle.meType == DataRowPointStyle::DATA_SERIES &&
+ aStyle.m_xSeries.is() )
+ {
+ nMaxOldSeriesIndex = nOldSeriesIndex;
+
+ if( aSeriesMap.end() == aSeriesMap.find(aStyle.m_xSeries) )
+ aSeriesMap[aStyle.m_xSeries] = nOldSeriesIndex;
+
+ nOldSeriesIndex++;
+ }
+ }
+ nOldSeriesCount = nMaxOldSeriesIndex+1;
+ }
+
+
+ //initialize new series styles
+ ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapIt( aSeriesMap.begin() );
+ ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapEnd( aSeriesMap.end() );
+
+ //sort by index
+ ::std::vector< NewDonutSeries > aNewSeriesVector;
+ {
+ ::std::map< sal_Int32, Reference< chart2::XDataSeries > > aIndexSeriesMap;
+ for( ; aSeriesMapIt != aSeriesMapEnd; ++aSeriesMapIt )
+ aIndexSeriesMap[aSeriesMapIt->second] = aSeriesMapIt->first;
+
+ ::std::map< sal_Int32, Reference< chart2::XDataSeries > >::const_iterator aIndexIt( aIndexSeriesMap.begin() );
+ ::std::map< sal_Int32, Reference< chart2::XDataSeries > >::const_iterator aIndexEnd( aIndexSeriesMap.end() );
+
+ for( ; aIndexIt != aIndexEnd; ++aIndexIt )
+ aNewSeriesVector.push_back( NewDonutSeries(aIndexIt->second,nOldSeriesCount) );
+ }
+
+ //overwrite attached axis information according to old series styles
+ for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
+ {
+ DataRowPointStyle aStyle(*aIt);
+ if(aStyle.meType == DataRowPointStyle::DATA_SERIES )
+ {
+ aSeriesMapIt = aSeriesMap.find( aStyle.m_xSeries );
+ if( aSeriesMapIt != aSeriesMapEnd && aSeriesMapIt->second < static_cast<sal_Int32>(aNewSeriesVector.size()) )
+ aNewSeriesVector[aSeriesMapIt->second].mnAttachedAxis = aStyle.mnAttachedAxis;
+ }
+ }
+
+ //overwrite new series style names with old series style name information
+ for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
+ {
+ DataRowPointStyle aStyle(*aIt);
+ if( aStyle.meType == DataRowPointStyle::DATA_SERIES )
+ {
+ aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
+ if( aSeriesMapEnd != aSeriesMapIt )
+ {
+ sal_Int32 nNewPointIndex = aSeriesMapIt->second;
+
+ ::std::vector< NewDonutSeries >::iterator aNewSeriesIt( aNewSeriesVector.begin() );
+ ::std::vector< NewDonutSeries >::iterator aNewSeriesEnd( aNewSeriesVector.end() );
+
+ for( ;aNewSeriesIt!=aNewSeriesEnd; ++aNewSeriesIt)
+ aNewSeriesIt->setSeriesStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
+ }
+ }
+ }
+
+ //overwrite new series style names with point style name information
+ for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
+ {
+ DataRowPointStyle aStyle(*aIt);
+ if( aStyle.meType == DataRowPointStyle::DATA_POINT )
+ {
+ aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
+ if( aSeriesMapEnd != aSeriesMapIt )
+ {
+ sal_Int32 nNewPointIndex = aSeriesMapIt->second;
+ sal_Int32 nNewSeriesIndex = aStyle.m_nPointIndex;
+ sal_Int32 nRepeatCount = aStyle.m_nPointRepeat;
+
+ while( nRepeatCount && (nNewSeriesIndex>=0) && (nNewSeriesIndex< static_cast<sal_Int32>(aNewSeriesVector.size()) ) )
+ {
+ NewDonutSeries& rNewSeries( aNewSeriesVector[nNewSeriesIndex] );
+ rNewSeries.setPointStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
+
+ nRepeatCount--;
+ nNewSeriesIndex++;
+ }
+ }
+ }
+ }
+
+ //put information from aNewSeriesVector to output parameter rStyleList
+ rStyleList.clear();
+
+ ::std::vector< NewDonutSeries >::iterator aNewSeriesIt( aNewSeriesVector.begin() );
+ ::std::vector< NewDonutSeries >::iterator aNewSeriesEnd( aNewSeriesVector.end() );
+ for( ;aNewSeriesIt!=aNewSeriesEnd; ++aNewSeriesIt)
+ {
+ ::std::list< DataRowPointStyle > aList( aNewSeriesIt->creatStyleList() );
+ rStyleList.insert(rStyleList.end(),aList.begin(),aList.end());
+ }
+}
+
+bool lcl_SpecialHandlingForDonutChartNeeded(
+ const ::rtl::OUString & rServiceName,
+ const SvXMLImport & rImport )
+{
+ bool bResult = false;
+ if( rServiceName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.DonutChartType" )))
+ {
+ bResult = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( rImport.GetModel() );
+ }
+ return bResult;
+}
+
+} // anonymous namespace
+
+
+void lcl_ApplyDataFromRectangularRangeToDiagram(
+ const uno::Reference< chart2::XChartDocument >& xNewDoc
+ , const rtl::OUString& rRectangularRange
+ , ::com::sun::star::chart::ChartDataRowSource eDataRowSource
+ , bool bRowHasLabels, bool bColHasLabels
+ , bool bSwitchOnLabelsAndCategoriesForOwnData
+ , const rtl::OUString& sColTrans
+ , const rtl::OUString& sRowTrans )
+{
+ if( !xNewDoc.is() )
+ return;
+
+ uno::Reference< chart2::XDiagram > xNewDia( xNewDoc->getFirstDiagram());
+ uno::Reference< chart2::data::XDataProvider > xDataProvider( xNewDoc->getDataProvider() );
+ if( !xNewDia.is() || !xDataProvider.is() )
+ return;
+
+ sal_Bool bFirstCellAsLabel =
+ (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bRowHasLabels : bColHasLabels;
+ sal_Bool bHasCateories =
+ (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bColHasLabels : bRowHasLabels;
+
+ if( bSwitchOnLabelsAndCategoriesForOwnData )
+ {
+ bFirstCellAsLabel = true;
+ bHasCateories = true;
+ }
+
+ uno::Sequence< beans::PropertyValue > aArgs( 3 );
+ aArgs[0] = beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "CellRangeRepresentation" )),
+ -1, uno::makeAny( rRectangularRange ),
+ beans::PropertyState_DIRECT_VALUE );
+ aArgs[1] = beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "DataRowSource" )),
+ -1, uno::makeAny( eDataRowSource ),
+ beans::PropertyState_DIRECT_VALUE );
+ aArgs[2] = beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FirstCellAsLabel" )),
+ -1, uno::makeAny( bFirstCellAsLabel ),
+ beans::PropertyState_DIRECT_VALUE );
+
+ if( sColTrans.getLength() || sRowTrans.getLength() )
+ {
+ aArgs.realloc( aArgs.getLength() + 1 );
+ aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "SequenceMapping" )),
+ -1, uno::makeAny( sColTrans.getLength()
+ ? lcl_getNumberSequenceFromString( sColTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() )
+ : lcl_getNumberSequenceFromString( sRowTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() ) ),
+ beans::PropertyState_DIRECT_VALUE );
+ }
+
+ //work around wrong writer ranges ( see Issue 58464 )
+ {
+ rtl::OUString aChartOleObjectName;
+ uno::Reference< frame::XModel > xModel(xNewDoc, uno::UNO_QUERY );
+ if( xModel.is() )
+ {
+ comphelper::MediaDescriptor aMediaDescriptor( xModel->getArgs() );
+
+ comphelper::MediaDescriptor::const_iterator aIt(
+ aMediaDescriptor.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HierarchicalDocumentName" ))));
+ if( aIt != aMediaDescriptor.end() )
+ {
+ aChartOleObjectName = (*aIt).second.get< ::rtl::OUString >();
+ }
+ }
+ if( aChartOleObjectName.getLength() )
+ {
+ aArgs.realloc( aArgs.getLength() + 1 );
+ aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ChartOleObjectName" )),
+ -1, uno::makeAny( aChartOleObjectName ),
+ beans::PropertyState_DIRECT_VALUE );
+ }
+ }
+
+
+ uno::Reference< chart2::data::XDataSource > xDataSource(
+ xDataProvider->createDataSource( aArgs ));
+
+ aArgs.realloc( aArgs.getLength() + 2 );
+ aArgs[ aArgs.getLength() - 2 ] = beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "HasCategories" )),
+ -1, uno::makeAny( bHasCateories ),
+ beans::PropertyState_DIRECT_VALUE );
+ aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue(
+ ::rtl::OUString::createFromAscii("UseCategoriesAsX"),
+ -1, uno::makeAny( sal_False ),//categories in ODF files are not to be used as x values (independent from what is offered in our ui)
+ beans::PropertyState_DIRECT_VALUE );
+
+ xNewDia->setDiagramData( xDataSource, aArgs );
+}
+
+void SchXMLChartContext::EndElement()
+{
+ uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
+ uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
+ uno::Reference< chart2::XChartDocument > xNewDoc( xDoc, uno::UNO_QUERY );
+
+ if( xProp.is())
+ {
+ if( maMainTitle.getLength())
+ {
+ uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getTitle(), uno::UNO_QUERY );
+ if( xTitleProp.is())
+ {
+ try
+ {
+ uno::Any aAny;
+ aAny <<= maMainTitle;
+ xTitleProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )), aAny );
+ }
+ catch( beans::UnknownPropertyException )
+ {
+ OSL_FAIL( "Property String for Title not available" );
+ }
+ }
+ }
+ if( maSubTitle.getLength())
+ {
+ uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getSubTitle(), uno::UNO_QUERY );
+ if( xTitleProp.is())
+ {
+ try
+ {
+ uno::Any aAny;
+ aAny <<= maSubTitle;
+ xTitleProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "String" )), aAny );
+ }
+ catch( beans::UnknownPropertyException )
+ {
+ OSL_FAIL( "Property String for Title not available" );
+ }
+ }
+ }
+ }
+
+ // cleanup: remove empty chart type groups
+ lcl_removeEmptyChartTypeGroups( xNewDoc );
+
+ // set stack mode before a potential chart type detection (in case we have a rectangular range)
+ uno::Reference< chart::XDiagram > xDiagram( xDoc->getDiagram() );
+ uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
+ if( xDiaProp.is())
+ {
+ if( maSeriesDefaultsAndStyles.maStackedDefault.hasValue())
+ xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Stacked")),maSeriesDefaultsAndStyles.maStackedDefault);
+ if( maSeriesDefaultsAndStyles.maPercentDefault.hasValue())
+ xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Percent")),maSeriesDefaultsAndStyles.maPercentDefault);
+ if( maSeriesDefaultsAndStyles.maDeepDefault.hasValue())
+ xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Deep")),maSeriesDefaultsAndStyles.maDeepDefault);
+ if( maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault.hasValue())
+ xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StackedBarsConnected")),maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault);
+ }
+
+ //the OOo 2.0 implementation and older has a bug with donuts
+ bool bSpecialHandlingForDonutChart = lcl_SpecialHandlingForDonutChartNeeded(
+ maChartTypeServiceName, GetImport());
+
+ // apply data
+ if(!xNewDoc.is())
+ return;
+
+ bool bHasOwnData = false;
+ if( m_aXLinkHRefAttributeToIndicateDataProvider.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "." ) ) ) //data comes from the chart itself
+ bHasOwnData = true;
+ else if( m_aXLinkHRefAttributeToIndicateDataProvider.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ".." ) ) ) //data comes from the parent application
+ bHasOwnData = false;
+ else if( m_aXLinkHRefAttributeToIndicateDataProvider.getLength() ) //not supported so far to get the data by sibling objects -> fall back to chart itself if data are available
+ bHasOwnData = m_bHasTableElement;
+ else
+ bHasOwnData = !m_bHasRangeAtPlotArea;
+
+ if( xNewDoc->hasInternalDataProvider())
+ {
+ if( !m_bHasTableElement && !m_aXLinkHRefAttributeToIndicateDataProvider.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "." ) ) )
+ {
+ //#i103147# ODF, workaround broken files with a missing table:cell-range-address at the plot-area
+ bool bSwitchSuccessful = SchXMLTools::switchBackToDataProviderFromParent( xNewDoc, maLSequencesPerIndex );
+ bHasOwnData = !bSwitchSuccessful;
+ }
+ else
+ bHasOwnData = true;//e.g. in case of copy->paste from calc to impress
+ }
+ else if( bHasOwnData )
+ {
+ xNewDoc->createInternalDataProvider( sal_False /* bCloneExistingData */ );
+ }
+ if( bHasOwnData )
+ msChartAddress = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "all" ));
+
+ bool bSwitchRangesFromOuterToInternalIfNecessary = false;
+ if( !bHasOwnData && mbAllRangeAddressesAvailable )
+ {
+ // special handling for stock chart (merge series together)
+ if( mbIsStockChart )
+ MergeSeriesForStockChart();
+ }
+ else if( msChartAddress.getLength() )
+ {
+ //own data or only rectangular range available
+
+ if( xNewDoc->hasInternalDataProvider() )
+ SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc );
+
+ bool bOlderThan2_3 = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( Reference< frame::XModel >( xNewDoc, uno::UNO_QUERY ));
+ bool bOldFileWithOwnDataFromRows = (bOlderThan2_3 && bHasOwnData && (meDataRowSource==chart::ChartDataRowSource_ROWS)); // in this case there are range addresses that are simply wrong.
+
+ if( mbAllRangeAddressesAvailable && !bSpecialHandlingForDonutChart && !mbIsStockChart &&
+ !bOldFileWithOwnDataFromRows )
+ {
+ //bHasOwnData is true in this case!
+ //e.g. for normal files with own data or also in case of copy paste scenario (e.g. calc to impress)
+ bSwitchRangesFromOuterToInternalIfNecessary = true;
+ }
+ else
+ {
+ //apply data from rectangular range
+
+ // create datasource from data provider with rectangular range parameters and change the diagram setDiagramData
+ try
+ {
+ if( bOlderThan2_3 && xDiaProp.is() )//for older charts the hidden cells were removed by calc on the fly
+ xDiaProp->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IncludeHiddenCells")),uno::makeAny(false));
+
+ // note: mbRowHasLabels means the first row contains labels, that means we have "column-descriptions",
+ // (analogously mbColHasLabels means we have "row-descriptions")
+ lcl_ApplyDataFromRectangularRangeToDiagram( xNewDoc, msChartAddress, meDataRowSource, mbRowHasLabels, mbColHasLabels, bHasOwnData, msColTrans, msRowTrans );
+ }
+ catch( uno::Exception & )
+ {
+ //try to fallback to internal data
+ OSL_FAIL( "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram try to fallback to internal data" );
+ if(!bHasOwnData)
+ {
+ bHasOwnData = true;
+ msChartAddress = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "all" ));
+ if( !xNewDoc->hasInternalDataProvider() )
+ {
+ xNewDoc->createInternalDataProvider( sal_False /* bCloneExistingData */ );
+ SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc );
+ try
+ {
+ lcl_ApplyDataFromRectangularRangeToDiagram( xNewDoc, msChartAddress, meDataRowSource, mbRowHasLabels, mbColHasLabels, bHasOwnData, msColTrans, msRowTrans );
+ }
+ catch( uno::Exception & )
+ {
+ OSL_FAIL( "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram fallback to internal data failed also" );
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ OSL_FAIL( " Must not get here" );
+ }
+
+ // now all series and data point properties are available and can be set
+ {
+ if( bSpecialHandlingForDonutChart )
+ {
+ uno::Reference< chart2::XDiagram > xNewDiagram( xNewDoc->getFirstDiagram() );
+ lcl_swapPointAndSeriesStylesForDonutCharts( maSeriesDefaultsAndStyles.maSeriesStyleList
+ , SchXMLSeriesHelper::getDataSeriesIndexMapFromDiagram(xNewDiagram) );
+ }
+
+ SchXMLSeries2Context::initSeriesPropertySets( maSeriesDefaultsAndStyles, uno::Reference< frame::XModel >(xDoc, uno::UNO_QUERY ) );
+
+ //set defaults from diagram to the new series:
+ //check whether we need to remove lines from symbol only charts
+ bool bSwitchOffLinesForScatter = false;
+ {
+ bool bLinesOn = true;
+ if( (maSeriesDefaultsAndStyles.maLinesOnProperty >>= bLinesOn) && !bLinesOn )
+ {
+ if( 0 == maChartTypeServiceName.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.ScatterChartType" ) ) )
+ {
+ bSwitchOffLinesForScatter = true;
+ SchXMLSeries2Context::switchSeriesLinesOff( maSeriesDefaultsAndStyles.maSeriesStyleList );
+ }
+ }
+ }
+ SchXMLSeries2Context::setDefaultsToSeries( maSeriesDefaultsAndStyles );
+
+ // set autostyles for series and data points
+ const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
+ const SvXMLStyleContext* pStyle = NULL;
+ ::rtl::OUString sCurrStyleName;
+
+ if( pStylesCtxt )
+ {
+ //iterate over data-series first
+ //don't set series styles for donut charts
+ if( !bSpecialHandlingForDonutChart )
+ {
+ SchXMLSeries2Context::setStylesToSeries( maSeriesDefaultsAndStyles
+ , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, GetImport(), mbIsStockChart, maLSequencesPerIndex );
+ // ... then set attributes for statistics (after their existence was set in the series)
+ SchXMLSeries2Context::setStylesToStatisticsObjects( maSeriesDefaultsAndStyles
+ , pStylesCtxt, pStyle, sCurrStyleName );
+ }
+ }
+
+ //#i98319# call switchRangesFromOuterToInternalIfNecessary before the data point styles are applied, otherwise in copy->paste scenario the data point styles do get lost
+ if( bSwitchRangesFromOuterToInternalIfNecessary )
+ {
+ if( xNewDoc->hasInternalDataProvider() )
+ SchXMLTableHelper::switchRangesFromOuterToInternalIfNecessary( maTable, maLSequencesPerIndex, xNewDoc, meDataRowSource );
+ }
+
+ if( pStylesCtxt )
+ {
+ // ... then iterate over data-point attributes, so the latter are not overwritten
+ SchXMLSeries2Context::setStylesToDataPoints( maSeriesDefaultsAndStyles
+ , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, GetImport(), mbIsStockChart, bSpecialHandlingForDonutChart, bSwitchOffLinesForScatter );
+ }
+ }
+
+ if( xProp.is())
+ xProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "RefreshAddInAllowed" )) , uno::makeAny( sal_True) );
+}
+
+void SchXMLChartContext::MergeSeriesForStockChart()
+{
+ OSL_ASSERT( mbIsStockChart );
+ try
+ {
+ uno::Reference< chart::XChartDocument > xOldDoc( mrImportHelper.GetChartDocument());
+ uno::Reference< chart2::XChartDocument > xDoc( xOldDoc, uno::UNO_QUERY_THROW );
+ uno::Reference< chart2::XDiagram > xDiagram( xDoc->getFirstDiagram());
+ if( ! xDiagram.is())
+ return;
+
+ bool bHasJapaneseCandlestick = true;
+ uno::Reference< chart2::XDataSeriesContainer > xDSContainer;
+ uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
+ uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
+ for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
+ {
+ uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
+ uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
+ for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
+ {
+ if( aChartTypes[nCTIdx]->getChartType().equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.CandleStickChartType")))
+ {
+ xDSContainer.set( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySet > xCTProp( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
+ xCTProp->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Japanese" ))) >>= bHasJapaneseCandlestick;
+ break;
+ }
+ }
+ }
+
+ if( xDSContainer.is())
+ {
+ // with japanese candlesticks: open, low, high, close
+ // otherwise: low, high, close
+ uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDSContainer->getDataSeries());
+ const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
+ const sal_Int32 nSeriesPerCandleStick = bHasJapaneseCandlestick ? 4: 3;
+ sal_Int32 nCandleStickCount = nSeriesCount / nSeriesPerCandleStick;
+ OSL_ASSERT( nSeriesPerCandleStick * nCandleStickCount == nSeriesCount );
+ uno::Sequence< uno::Reference< chart2::XDataSeries > > aNewSeries( nCandleStickCount );
+ for( sal_Int32 i=0; i<nCandleStickCount; ++i )
+ {
+ sal_Int32 nSeriesIndex = i*nSeriesPerCandleStick;
+ if( bHasJapaneseCandlestick )
+ {
+ // open values
+ lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], OUString(RTL_CONSTASCII_USTRINGPARAM( "values-first" )));
+ aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
+ // low values
+ lcl_MoveDataToCandleStickSeries(
+ uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
+ aNewSeries[i], OUString(RTL_CONSTASCII_USTRINGPARAM( "values-min" )));
+ }
+ else
+ {
+ // low values
+ lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], OUString(RTL_CONSTASCII_USTRINGPARAM( "values-min" )));
+ aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
+ }
+ // high values
+ lcl_MoveDataToCandleStickSeries(
+ uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
+ aNewSeries[i], OUString(RTL_CONSTASCII_USTRINGPARAM( "values-max" )));
+ // close values
+ lcl_MoveDataToCandleStickSeries(
+ uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
+ aNewSeries[i], OUString(RTL_CONSTASCII_USTRINGPARAM( "values-last" )));
+ }
+ xDSContainer->setDataSeries( aNewSeries );
+ }
+ }
+ catch( uno::Exception & )
+ {
+ OSL_FAIL( "Exception while merging series for stock chart" );
+ }
+}
+
+SvXMLImportContext* SchXMLChartContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList >& xAttrList )
+{
+ static const sal_Bool bTrue = sal_True;
+ static const uno::Any aTrueBool( &bTrue, ::getBooleanCppuType());
+
+ SvXMLImportContext* pContext = 0;
+ const SvXMLTokenMap& rTokenMap = mrImportHelper.GetChartElemTokenMap();
+ uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
+ uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
+
+ switch( rTokenMap.Get( nPrefix, rLocalName ))
+ {
+ case XML_TOK_CHART_PLOT_AREA:
+ pContext = new SchXMLPlotAreaContext( mrImportHelper, GetImport(), rLocalName,
+ m_aXLinkHRefAttributeToIndicateDataProvider,
+ maSeriesAddresses, msCategoriesAddress,
+ msChartAddress, m_bHasRangeAtPlotArea, mbAllRangeAddressesAvailable,
+ mbColHasLabels, mbRowHasLabels,
+ meDataRowSource,
+ maSeriesDefaultsAndStyles,
+ maChartTypeServiceName,
+ maLSequencesPerIndex, maChartSize );
+ break;
+
+ case XML_TOK_CHART_TITLE:
+ if( xDoc.is())
+ {
+ if( xProp.is())
+ {
+ xProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "HasMainTitle" )), aTrueBool );
+ }
+ uno::Reference< drawing::XShape > xTitleShape( xDoc->getTitle(), uno::UNO_QUERY );
+ pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
+ rLocalName, maMainTitle, xTitleShape );
+ }
+ break;
+
+ case XML_TOK_CHART_SUBTITLE:
+ if( xDoc.is())
+ {
+ if( xProp.is())
+ {
+ xProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "HasSubTitle" )), aTrueBool );
+ }
+ uno::Reference< drawing::XShape > xTitleShape( xDoc->getSubTitle(), uno::UNO_QUERY );
+ pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
+ rLocalName, maSubTitle, xTitleShape );
+ }
+ break;
+
+ case XML_TOK_CHART_LEGEND:
+ pContext = new SchXMLLegendContext( mrImportHelper, GetImport(), rLocalName );
+ break;
+
+ case XML_TOK_CHART_TABLE:
+ {
+ SchXMLTableContext * pTableContext =
+ new SchXMLTableContext( mrImportHelper, GetImport(), rLocalName, maTable );
+ m_bHasTableElement = true;
+ // #i85913# take into account column- and row- mapping for
+ // charts with own data only for those which were not copied
+ // from a place where they got data from the container. Note,
+ // that this requires the plot-area been read before the table
+ // (which is required in the ODF spec)
+ // Note: For stock charts and donut charts with special handling
+ // the mapping must not be applied!
+ if( !msChartAddress.getLength() && !mbIsStockChart &&
+ !lcl_SpecialHandlingForDonutChartNeeded(
+ maChartTypeServiceName, GetImport()))
+ {
+ if( msColTrans.getLength() > 0 )
+ {
+ OSL_ASSERT( msRowTrans.getLength() == 0 );
+ pTableContext->setColumnPermutation( lcl_getNumberSequenceFromString( msColTrans, true ));
+ msColTrans = OUString();
+ }
+ else if( msRowTrans.getLength() > 0 )
+ {
+ pTableContext->setRowPermutation( lcl_getNumberSequenceFromString( msRowTrans, true ));
+ msRowTrans = OUString();
+ }
+ }
+ pContext = pTableContext;
+ }
+ break;
+
+ default:
+ // try importing as an additional shape
+ if( ! mxDrawPage.is())
+ {
+ uno::Reference< drawing::XDrawPageSupplier > xSupp( xDoc, uno::UNO_QUERY );
+ if( xSupp.is())
+ mxDrawPage = uno::Reference< drawing::XShapes >( xSupp->getDrawPage(), uno::UNO_QUERY );
+
+ DBG_ASSERT( mxDrawPage.is(), "Invalid Chart Page" );
+ }
+ if( mxDrawPage.is())
+ pContext = GetImport().GetShapeImport()->CreateGroupChildContext(
+ GetImport(), nPrefix, rLocalName, xAttrList, mxDrawPage );
+ break;
+ }
+
+ if( ! pContext )
+ pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
+
+ return pContext;
+}
+
+
+/*
+ With a locked controller the following is done here:
+ 1. Hide title, subtitle, and legend.
+ 2. Set the size of the draw page.
+ 3. Set a (logically) empty data set.
+ 4. Set the chart type.
+*/
+void SchXMLChartContext::InitChart(
+ const OUString & rChartTypeServiceName, // currently the old service name
+ sal_Bool /* bSetSwitchData */ )
+{
+ uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
+ DBG_ASSERT( xDoc.is(), "No valid document!" );
+ uno::Reference< frame::XModel > xModel (xDoc, uno::UNO_QUERY );
+
+ // Remove Title and Diagram ("De-InitNew")
+ uno::Reference< chart2::XChartDocument > xNewDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
+ if( xNewDoc.is())
+ {
+ xNewDoc->setFirstDiagram( 0 );
+ uno::Reference< chart2::XTitled > xTitled( xNewDoc, uno::UNO_QUERY );
+ if( xTitled.is())
+ xTitled->setTitleObject( 0 );
+ }
+
+ // Set the chart type via setting the diagram.
+ if( rChartTypeServiceName.getLength() &&
+ xDoc.is())
+ {
+ uno::Reference< lang::XMultiServiceFactory > xFact( xDoc, uno::UNO_QUERY );
+ if( xFact.is())
+ {
+ uno::Reference< chart::XDiagram > xDia( xFact->createInstance( rChartTypeServiceName ), uno::UNO_QUERY );
+ if( xDia.is())
+ xDoc->setDiagram( xDia );
+ }
+ }
+}
+
+// ----------------------------------------
+
+SchXMLTitleContext::SchXMLTitleContext( SchXMLImportHelper& rImpHelper, SvXMLImport& rImport,
+ const rtl::OUString& rLocalName,
+ rtl::OUString& rTitle,
+ uno::Reference< drawing::XShape >& xTitleShape ) :
+ SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
+ mrImportHelper( rImpHelper ),
+ mrTitle( rTitle ),
+ mxTitleShape( xTitleShape )
+{
+}
+
+SchXMLTitleContext::~SchXMLTitleContext()
+{}
+
+void SchXMLTitleContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
+{
+ sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
+
+ com::sun::star::awt::Point maPosition;
+ bool bHasXPosition=false;
+ bool bHasYPosition=false;
+
+ for( sal_Int16 i = 0; i < nAttrCount; i++ )
+ {
+ rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
+ rtl::OUString aLocalName;
+ rtl::OUString aValue = xAttrList->getValueByIndex( i );
+ sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
+
+ if( nPrefix == XML_NAMESPACE_SVG )
+ {
+ if( IsXMLToken( aLocalName, XML_X ) )
+ {
+ GetImport().GetMM100UnitConverter().convertMeasure( maPosition.X, aValue );
+ bHasXPosition = true;
+ }
+ else if( IsXMLToken( aLocalName, XML_Y ) )
+ {
+ GetImport().GetMM100UnitConverter().convertMeasure( maPosition.Y, aValue );
+ bHasYPosition = true;
+ }
+ }
+ else if( nPrefix == XML_NAMESPACE_CHART )
+ {
+ if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
+ msAutoStyleName = aValue;
+ }
+ }
+
+
+ if( mxTitleShape.is())
+ {
+ if( bHasXPosition && bHasYPosition )
+ mxTitleShape->setPosition( maPosition );
+
+ uno::Reference< beans::XPropertySet > xProp( mxTitleShape, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
+ if( pStylesCtxt )
+ {
+ const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
+ mrImportHelper.GetChartFamilyID(), msAutoStyleName );
+
+ if( pStyle && pStyle->ISA( XMLPropStyleContext ))
+ (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
+ }
+ }
+ }
+}
+
+SvXMLImportContext* SchXMLTitleContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList >& )
+{
+ SvXMLImportContext* pContext = 0;
+
+ if( nPrefix == XML_NAMESPACE_TEXT &&
+ IsXMLToken( rLocalName, XML_P ) )
+ {
+ pContext = new SchXMLParagraphContext( GetImport(), rLocalName, mrTitle );
+ }
+ else
+ pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
+
+ return pContext;
+}
+
+// ----------------------------------------
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */