diff options
author | Vladimir Glazounov <vg@openoffice.org> | 2007-05-22 15:05:37 +0000 |
---|---|---|
committer | Vladimir Glazounov <vg@openoffice.org> | 2007-05-22 15:05:37 +0000 |
commit | 67ff20be544c9f3d803314458ec72a146d13ce02 (patch) | |
tree | dd56877abfc415820d3b8c0c0ea234cd2e2dcfd9 /xmloff/source | |
parent | d8d96656408fbdeb612b2f7354c8c59721c0c332 (diff) |
INTEGRATION: CWS chart2mst3 (1.29.28); FILE MERGED
2007/02/15 15:41:52 bm 1.29.28.64: assertion removed in EndElement: at that place we do not always have internal data
2007/01/29 14:20:30 bm 1.29.28.63: do not need table-number-list on import
2006/12/12 19:16:49 bm 1.29.28.62: use applyTableSimple instead of applyTable for stock charts with own data
2006/12/12 18:08:35 iha 1.29.28.61: correct loading of old donuts after clipboard impl
2006/12/07 16:32:06 bm 1.29.28.60: #i64497# some more fixes for clipboard
2006/12/06 18:50:45 bm 1.29.28.59: #i64497# allow import and export to deal with flexible source ranges also with own data. This is needed for the clipboard between Calc and Impress
2006/11/17 14:08:29 iha 1.29.28.58: fallback to internal data table for wrong files with wrong range strings see issue i59297, example document e.g. issue 16280
2006/11/14 19:25:37 iha 1.29.28.57: #i71330# xy 'symbols only' get lines when loading older versions
2006/10/27 11:10:33 iha 1.29.28.56: removed warning error
2006/10/26 19:36:49 iha 1.29.28.55: correct order of series when importing old style donuts
2006/10/20 09:50:39 bm 1.29.28.54: warnings removed
2006/10/19 16:21:35 bm 1.29.28.53: warnings removed
2006/10/19 09:59:00 bm 1.29.28.52: RESYNC: (1.32-1.34); FILE MERGED
2006/08/25 18:29:00 iha 1.29.28.51: #i58457# cope with wrong files for donuts from older versions and also with corrected ones
2006/08/08 15:03:39 iha 1.29.28.50: don't refresh addin when loading is not finished
2006/08/01 09:27:52 iha 1.29.28.49: use correct charttype for series creation when having addin
2006/08/01 09:25:37 iha 1.29.28.48: helping methods for chart im- and export
2006/06/22 14:49:38 bm 1.29.28.47: correct loading of data table for charts with own data and empty msChartAddress
2006/06/17 16:11:05 bm 1.29.28.46: const removed on error
2006/06/07 14:59:12 bm 1.29.28.45: #124497# set styles of series before the styles of statistics properties, because the existence of statistics objects is determined by proeprties of the series
2006/05/15 11:56:08 bm 1.29.28.44: legend has fill-style NONE per default, although in the model the default is SOLID
2006/05/15 09:46:02 bm 1.29.28.43: #i64497# allow loading charts with external data references in containers that do not support those (like Impress) for clipboard from Calc to Impress to work.
2006/04/22 10:54:51 iha 1.29.28.42: park unused categories in scale with AxisType not being CATEGORY( own data has always categories)
2006/02/03 19:52:10 iha 1.29.28.41: remove series index dependency
2005/12/21 21:34:21 iha 1.29.28.40: remove identifiers from model objects and create an index based CID protocol instead for selection purposes
2005/11/29 18:05:59 iha 1.29.28.39: #i58464# work around wrong writer ranges in file
2005/11/28 15:20:30 bm 1.29.28.38: implemented StackedBarsConnected property at Diagram
2005/11/05 11:34:00 iha 1.29.28.37: fixed loading of donut styles also if old series count is less than old point count
2005/11/05 01:26:15 iha 1.29.28.36: fix loading of donut series and point styles - work around of OOo 2.0 and older
2005/11/04 17:01:23 iha 1.29.28.35: cleanup moced code to new method ChangeDiagramAccordingToTemplate
2005/11/03 18:22:39 iha 1.29.28.34: fix sequence mapping for internal data
2005/11/02 22:54:09 iha 1.29.28.33: don't clone data if creating internal dataprovider
2005/11/02 22:52:37 iha 1.29.28.32: correct sequence mapping
2005/10/29 09:42:20 iha 1.29.28.31: support SequenceMapping also for chart local data
2005/10/28 12:18:03 iha 1.29.28.30: enhanced exception message
2005/10/25 16:38:11 iha 1.29.28.29: support SequenceMapping
2005/10/24 10:45:02 iha 1.29.28.28: coordinate system restructure
2005/10/13 17:37:22 iha 1.29.28.27: renamed BoundedCoordinateSystem to CoordinateSystem
2005/10/09 08:05:36 bm 1.29.28.26: RESYNC: (1.31-1.32); FILE MERGED
2005/09/08 15:46:08 iha 1.29.28.25: lock controller for binary loading already before the dataprovider gets attached
2005/08/30 16:54:29 iha 1.29.28.24: lock controllers only once starting the import and unlock after all was imported -> necessary to get no update notifications during import of binary files
2005/08/29 16:24:11 bm 1.29.28.23: clean chart properly before loading (binfilter uses flat XML which calls InitNew. The default data must be removed)
2005/08/19 16:10:22 bm 1.29.28.22: chart2::XChartDocument: getDiagram -> getFirstDiagram
2005/08/15 13:09:11 bm 1.29.28.21: applyTableSimple: gets the data directly. This eases filling the internal data provider
2005/08/03 13:34:46 bm 1.29.28.20: bug on import of stock charts (wrong series reused)
2005/07/22 11:00:18 bm 1.29.28.19: set stack mode before a potential template detection (in case we have a rectangular range)
2005/07/22 08:35:47 bm 1.29.28.18: remove empty chart type groups before a potential template detection for changing the diagram data
2005/07/19 17:02:26 bm 1.29.28.17: StockChart issues (range-line defaults, series at which to set properties)
2005/07/18 16:11:14 bm 1.29.28.16: Stock Issues fixed: remove empty chart types in Chart Context instead of PlotArea, stock with volume: create new series with correct chart type
2005/07/15 21:00:15 iha 1.29.28.15: change from series index to series identifier
2005/07/01 16:18:50 bm 1.29.28.14: remove empty chart type groups
2005/06/30 14:24:08 bm 1.29.28.13: import of stacking mode fixed (old deprecated method removed)
2005/06/24 13:07:12 bm 1.29.28.12: stock chart
2005/06/24 09:07:27 bm 1.29.28.11: stock chart
2005/06/23 14:44:26 iha 1.29.28.10: correct support for statistic properties
2005/06/22 08:17:59 iha 1.29.28.9: load property DataCaption at diagram, series and data point correctly
2005/06/21 15:18:38 iha 1.29.28.8: set series and point properties after data is available
2005/06/17 17:03:40 bm 1.29.28.7: using new API for im-/export of data
2005/06/01 16:06:05 iha 1.29.28.6: use visarea for page size
2005/04/19 17:54:39 iha 1.29.28.5: remove unused property ExportData
2005/03/17 11:21:00 bm 1.29.28.4: RESYNC: (1.29-1.30); FILE MERGED
2004/08/26 15:39:29 iha 1.29.28.3: View independent loading - different setting of page size
2004/08/25 16:47:51 iha 1.29.28.2: removed unused code
2004/08/25 16:00:43 iha 1.29.28.1: View independent loading - smarter setting of legend & title and diagram position
Diffstat (limited to 'xmloff/source')
-rw-r--r-- | xmloff/source/chart/SchXMLChartContext.cxx | 1199 |
1 files changed, 796 insertions, 403 deletions
diff --git a/xmloff/source/chart/SchXMLChartContext.cxx b/xmloff/source/chart/SchXMLChartContext.cxx index 54ac5191fcf0..6f9dfd9ce21a 100644 --- a/xmloff/source/chart/SchXMLChartContext.cxx +++ b/xmloff/source/chart/SchXMLChartContext.cxx @@ -4,9 +4,9 @@ * * $RCSfile: SchXMLChartContext.cxx,v $ * - * $Revision: 1.34 $ + * $Revision: 1.35 $ * - * last change: $Author: obo $ $Date: 2006-09-17 10:14:57 $ + * last change: $Author: vg $ $Date: 2007-05-22 16:05:37 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -41,10 +41,21 @@ #include "SchXMLPlotAreaContext.hxx" #include "SchXMLParagraphContext.hxx" #include "SchXMLTableContext.hxx" +#include "SchXMLSeriesHelper.hxx" +#include "SchXMLSeries2Context.hxx" +#include "SchXMLTools.hxx" +#include "SchXMLErrorBuildIds.hxx" +#ifndef _COMPHELPER_MEDIADESCRIPTOR_HXX_ +#include <comphelper/mediadescriptor.hxx> +#endif #ifndef _TOOLS_DEBUG_HXX #include <tools/debug.hxx> #endif +// header for class ByteString +#ifndef _STRING_HXX +#include <tools/string.hxx> +#endif #ifndef _XMLOFF_XMLNMSPE_HXX #include "xmlnmspe.hxx" @@ -97,44 +108,182 @@ #ifndef _COM_SUN_STAR_CHART_XCHARTDATAARRAY_HPP_ #include <com/sun/star/chart/XChartDataArray.hpp> #endif +#ifndef _COM_SUN_STAR_AWT_POSSIZE_HPP_ +#include <com/sun/star/awt/PosSize.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBED_ASPECTS_HPP_ +#include <com/sun/star/embed/Aspects.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBED_XVISUALOBJECT_HPP_ +#include <com/sun/star/embed/XVisualObject.hpp> +#endif +#ifndef _COM_SUN_STAR_DRAWING_FILLSTYLE_HPP_ +#include <com/sun/star/drawing/FillStyle.hpp> +#endif + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XChartTypeTemplate.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; -#define SCH_BUILDCHART(xDoc) if( xDoc->hasControllersLocked() ) {\ - xDoc->unlockControllers();\ - xDoc->lockControllers(); } +namespace +{ +uno::Reference< chart2::XChartTypeTemplate > lcl_getTemplate( const uno::Reference< chart2::XChartDocument > & xDoc ) +{ + uno::Reference< chart2::XChartTypeTemplate > xResult; + try + { + if( !xDoc.is()) + return xResult; + uno::Reference< lang::XMultiServiceFactory > xChartTypeManager( xDoc->getChartTypeManager(), uno::UNO_QUERY ); + if( !xChartTypeManager.is()) + return xResult; + uno::Reference< chart2::XDiagram > xDiagram( xDoc->getFirstDiagram()); + if( !xDiagram.is()) + return xResult; + + uno::Sequence< ::rtl::OUString > aServiceNames( xChartTypeManager->getAvailableServiceNames()); + const sal_Int32 nLength = aServiceNames.getLength(); + + for( sal_Int32 i = 0; i < nLength; ++i ) + { + try + { + uno::Reference< chart2::XChartTypeTemplate > xTempl( + xChartTypeManager->createInstance( aServiceNames[ i ] ), uno::UNO_QUERY_THROW ); -enum SchXMLChartType + if( xTempl->matchesTemplate( xDiagram, sal_True )) + { + xResult.set( xTempl ); + break; + } + } + catch( uno::Exception & ) + { + DBG_ERROR( "Exception during determination of chart type template" ); + } + } + } + catch( uno::Exception & ) + { + DBG_ERROR( "Exception during import lcl_getTemplate" ); + } + return xResult; +} + +void lcl_setRoleAtLabeledSequence( + const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq, + const ::rtl::OUString &rRole ) { - XML_CHART_CLASS_LINE, - XML_CHART_CLASS_AREA, - XML_CHART_CLASS_CIRCLE, - XML_CHART_CLASS_RING, - XML_CHART_CLASS_SCATTER, - XML_CHART_CLASS_RADAR, - XML_CHART_CLASS_BAR, - XML_CHART_CLASS_STOCK, - XML_CHART_CLASS_BUBBLE, // not yet implemented - XML_CHART_CLASS_ADDIN -}; + // 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::createFromAscii("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_ENSURE( false, "Exception caught while moving data to candlestick series" ); + } +} -static __FAR_DATA SvXMLEnumMapEntry aXMLChartClassMap[] = +void lcl_setRoleAtFirstSequence( + const uno::Reference< chart2::XDataSeries > & xSeries, + const ::rtl::OUString & rRole ) { - { XML_LINE, XML_CHART_CLASS_LINE }, - { XML_AREA, XML_CHART_CLASS_AREA }, - { XML_CIRCLE, XML_CHART_CLASS_CIRCLE }, - { XML_RING, XML_CHART_CLASS_RING }, - { XML_SCATTER, XML_CHART_CLASS_SCATTER }, - { XML_RADAR, XML_CHART_CLASS_RADAR }, - { XML_BAR, XML_CHART_CLASS_BAR }, - { XML_STOCK, XML_CHART_CLASS_STOCK }, - { XML_BUBBLE, XML_CHART_CLASS_BUBBLE }, - { XML_ADD_IN, XML_CHART_CLASS_ADDIN }, - { XML_TOKEN_INVALID, 0 } -}; + 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 ); + DBG_ERROR1( "Exception caught while removing empty chart types: %s", aBStr.GetBuffer()); + } +} + +} // anonymous namespace static __FAR_DATA SvXMLEnumMapEntry aXMLLegendAlignmentMap[] = { @@ -155,11 +304,12 @@ SchXMLChartContext::SchXMLChartContext( SchXMLImportHelper& rImpHelper, SvXMLImport& rImport, const rtl::OUString& rLocalName ) : SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ), mrImportHelper( rImpHelper ), - mbSetMainTitlePos( false ), - mbSetSubTitlePos( false ), - mbSetLegendPos( false ), - mbHasOwnTable( sal_False ), - mbHasLegend( sal_False ) + mbHasOwnTable( sal_True ), + mbAllRangeAddressesAvailable( sal_True ), + mbColHasLabels( sal_False ), + mbRowHasLabels( sal_False ), + meDataRowSource( chart::ChartDataRowSource_COLUMNS ), + mbIsStockChart( false ) { } @@ -176,8 +326,9 @@ void SchXMLChartContext::StartElement( const uno::Reference< xml::sax::XAttribut sal_Bool bSetSwitchData = sal_False; sal_Bool bDomainForDefaultDataNeeded = sal_False; - rtl::OUString aServiceName; - rtl::OUString sAutoStyleName; + ::rtl::OUString sAutoStyleName; + ::rtl::OUString aOldChartTypeName; + bool bHasAddin = false; for( sal_Int16 i = 0; i < nAttrCount; i++ ) { @@ -196,69 +347,41 @@ void SchXMLChartContext::StartElement( const uno::Reference< xml::sax::XAttribut aValue, &sClassName ); if( XML_NAMESPACE_CHART == nClassPrefix ) { - USHORT nEnumVal; - if( GetImport().GetMM100UnitConverter().convertEnum( - nEnumVal, sClassName, aXMLChartClassMap )) + SchXMLChartTypeEnum eChartTypeEnum = SchXMLTools::GetChartTypeEnum( sClassName ); + if( eChartTypeEnum != XML_CHART_CLASS_UNKNOWN ) { - switch( nEnumVal ) + aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( sClassName, true /* bUseOldNames */ ); + maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( sClassName, false /* bUseOldNames */ ); + switch( eChartTypeEnum ) { - case XML_CHART_CLASS_LINE: - aServiceName = - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.chart.LineDiagram" )); - break; - case XML_CHART_CLASS_AREA: - aServiceName = - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.chart.AreaDiagram" )); - break; case XML_CHART_CLASS_CIRCLE: - aServiceName = - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.chart.PieDiagram" )); bSetSwitchData = sal_True; break; - case XML_CHART_CLASS_RING: - aServiceName = - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.chart.DonutDiagram" )); - break; case XML_CHART_CLASS_SCATTER: - aServiceName = - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.chart.XYDiagram" )); bDomainForDefaultDataNeeded = sal_True; break; - case XML_CHART_CLASS_RADAR: - aServiceName = - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.chart.NetDiagram" )); - break; - case XML_CHART_CLASS_BAR: - aServiceName = - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.chart.BarDiagram" )); - break; case XML_CHART_CLASS_STOCK: - aServiceName = - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.chart.StockDiagram" )); + mbIsStockChart = true; break; case XML_CHART_CLASS_BUBBLE: DBG_ERROR( "Bubble chart not supported yet" ); break; + default: + break; } } } else if( XML_NAMESPACE_OOO == nClassPrefix ) { // service is taken from add-in-name attribute + bHasAddin = true; // for service charts assume domain in base type // if base type doesn't use a domain this is ok, // the data just grows bigger bDomainForDefaultDataNeeded = sal_True; - aServiceName = sClassName; + aOldChartTypeName = sClassName; + maChartTypeServiceName = sClassName; } } break; @@ -284,7 +407,27 @@ void SchXMLChartContext::StartElement( const uno::Reference< xml::sax::XAttribut } } - InitChart (aChartSize, bDomainForDefaultDataNeeded, aServiceName, bSetSwitchData); + InitChart (aChartSize, bDomainForDefaultDataNeeded, 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::createFromAscii("BaseDiagram")) >>= aOldChartTypeName; + maChartTypeServiceName = SchXMLTools::GetNewChartTypeName( aOldChartTypeName ); + xDocProp->setPropertyValue( rtl::OUString::createFromAscii( "RefreshAddInAllowed" ) , uno::makeAny( sal_False) ); + } + catch( uno::Exception & ) + { + DBG_ERROR( "Exception during import SchXMLChartContext::StartElement" ); + } + } + } // set auto-styles for Area uno::Reference< beans::XPropertySet > xProp( mrImportHelper.GetChartDocument()->getArea(), uno::UNO_QUERY ); @@ -300,17 +443,307 @@ void SchXMLChartContext::StartElement( const uno::Reference< xml::sax::XAttribut (( 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; + } +}; - // prevent BuildChart from now on - uno::Reference< frame::XModel > xModel( mrImportHelper.GetChartDocument(), uno::UNO_QUERY ); - if( xModel.is()) - xModel->lockControllers(); +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; + } + /* + 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 ) + { + nMaxOldSeriesIndex = 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()); + } +} + +} // anonymous namespace + +void SchXMLChartContext::ChangeDiagramAccordingToTemplate( + const uno::Reference< chart2::XChartDocument >& xNewDoc ) +{ + if( !xNewDoc.is() ) + return; + + uno::Reference< chart2::XDiagram > xNewDia( xNewDoc->getFirstDiagram()); + uno::Reference< chart2::data::XDataProvider > xDataProvider( mrImportHelper.GetDataProvider( xNewDoc ) ); + if( !xNewDia.is() || !xDataProvider.is() ) + return; + + uno::Reference< chart2::XChartTypeTemplate > xTemplate( lcl_getTemplate( xNewDoc )); + if(!xTemplate.is()) + return; + + sal_Bool bFirstCellAsLabel = + (meDataRowSource==chart::ChartDataRowSource_COLUMNS)? mbRowHasLabels : mbColHasLabels; + sal_Bool bHasCateories = + (meDataRowSource==chart::ChartDataRowSource_COLUMNS)? mbColHasLabels : mbRowHasLabels; + + if( mbHasOwnTable ) + { + bFirstCellAsLabel = true; + bHasCateories = true; + } + + uno::Sequence< beans::PropertyValue > aArgs( 3 ); + aArgs[0] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("CellRangeRepresentation"), + -1, uno::makeAny( msChartAddress ), + beans::PropertyState_DIRECT_VALUE ); + aArgs[1] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("DataRowSource"), + -1, uno::makeAny( meDataRowSource ), + beans::PropertyState_DIRECT_VALUE ); + aArgs[2] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("FirstCellAsLabel"), + -1, uno::makeAny( bFirstCellAsLabel ), + beans::PropertyState_DIRECT_VALUE ); + + if( msColTrans.getLength() || msRowTrans.getLength() ) + { + aArgs.realloc( aArgs.getLength() + 1 ); + aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("SequenceMapping"), + -1, uno::makeAny( msColTrans.getLength() + ? GetNumberSequenceFromString( msColTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() ) + : GetNumberSequenceFromString( msRowTrans, 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::createFromAscii("ChartOleObjectName"), + -1, uno::makeAny( aChartOleObjectName ), + beans::PropertyState_DIRECT_VALUE ); + } + } + + + uno::Reference< chart2::data::XDataSource > xDataSource( + xDataProvider->createDataSource( aArgs )); + + aArgs.realloc( aArgs.getLength() + 1 ); + aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("HasCategories"), + -1, uno::makeAny( bHasCateories ), + beans::PropertyState_DIRECT_VALUE ); + + xTemplate->changeDiagramData( xNewDia, 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()) { @@ -329,19 +762,7 @@ void SchXMLChartContext::EndElement() { DBG_ERROR( "Property String for Title not available" ); } -/* uno::Reference< drawing::XShape > xShape( xTitleProp, uno::UNO_QUERY ); - if( xShape.is()) - { - // perform build chart with new title string - // so that setting the position works correctly - if( xDoc.is()) - { - xDoc->unlockControllers(); - xDoc->lockControllers(); - } - xShape->setPosition( maMainTitlePos ); - } -*/ } + } } if( maSubTitle.getLength()) { @@ -358,186 +779,247 @@ void SchXMLChartContext::EndElement() { DBG_ERROR( "Property String for Title not available" ); } -/* uno::Reference< drawing::XShape > xShape( xTitleProp, uno::UNO_QUERY ); - if( xShape.is()) - { - // perform build chart with new title string - // so that setting the position works correctly - if( xDoc.is()) - { - xDoc->unlockControllers(); - xDoc->lockControllers(); - } - xShape->setPosition( maSubTitlePos ); - } -*/ } + } } } + // cleanup: remove empty chart type groups + lcl_removeEmptyChartTypeGroups( xNewDoc ); + // set stack mode before a potential template 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 = false; + if( 0 == maChartTypeServiceName.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.DonutChartType" ) ) ) + { + sal_Int32 nBuildId = 0; + sal_Int32 nUPD; + if( (!GetImport().getBuildIds( nUPD, nBuildId ) ) ) + bSpecialHandlingForDonutChart = true; + } + + // apply data + if(!xNewDoc.is()) + return; + + // if we already have an internal data provider, we know that we cannot have + // external data here. If we can have external data but know that we have + // internal data due to missing ranges, we must create an internal data + // provider + if( xNewDoc->hasInternalDataProvider()) + mbHasOwnTable = true; + else if( mbHasOwnTable ) + { + xNewDoc->createInternalDataProvider( sal_False /* bCloneExistingData */ ); + } if( mbHasOwnTable ) + msChartAddress = ::rtl::OUString::createFromAscii("all"); + + if( !mbHasOwnTable && mbAllRangeAddressesAvailable ) { - // apply data read in table sub-element to chart -// SchXMLTableHelper::applyTable( maTable, maSeriesAddresses, msCategoriesAddress, xDoc ); - SchXMLTableHelper::applyTableSimple( maTable, xDoc ); + // special handling for stock chart (merge series together) + if( mbIsStockChart ) + MergeSeriesForStockChart(); } - else + else if( msChartAddress.getLength() ) { - // deprecated method - // translate cell-address strings - if( maSeriesAddresses.getLength() || - msCategoriesAddress.getLength()) + if( mbAllRangeAddressesAvailable && !bSpecialHandlingForDonutChart && !mbIsStockChart ) + { + // note: mbRowHasLabels means the first row contains labels, that + // means we have "column-descriptions", (analogously mbColHasLabels + // means we have "row-descriptions") + SchXMLTableHelper::applyTable( maTable, maLSequencesPerIndex, xNewDoc ); //, meDataRowSource ); + } + else { - uno::Reference< util::XStringMapping > xTableAddressMapper = mrImportHelper.GetTableAddressMapper(); - if( xTableAddressMapper.is()) + // apply data read from the table sub-element to the chart + // if the data provider supports the XChartDataArray interface like + // the internal data provider + uno::Reference< chart::XChartDataArray > xChartData( mrImportHelper.GetDataProvider( xNewDoc ), uno::UNO_QUERY ); + if( xChartData.is()) + SchXMLTableHelper::applyTableSimple( maTable, xChartData ); + + // create datasource from data provider with rectangular range + // parameters and change the diagram via template mechanism + try { - // series - sal_Int32 nLength = maSeriesAddresses.getLength(); - sal_Int32 nIdx; - uno::Sequence< rtl::OUString > aStrSeq( nLength * 2 + 1 ); - sal_Bool bHasDomain = sal_False; - - for( nIdx = 0; nIdx < nLength; nIdx++ ) + ChangeDiagramAccordingToTemplate( xNewDoc ); + } + catch( uno::Exception & ) + { + //try to fallback to internal data + DBG_ERROR( "Exception during import SchXMLChartContext::ChangeDiagramAccordingToTemplate try to fallback to internal data" ); + if(!mbHasOwnTable) { - aStrSeq[ nIdx * 2 ] = maSeriesAddresses[ nIdx ].DataRangeAddress; - aStrSeq[ nIdx * 2 + 1 ] = maSeriesAddresses[ nIdx ].LabelAddress; - - // domains - if( maSeriesAddresses[ nIdx ].DomainRangeAddresses.getLength()) + mbHasOwnTable = true; + msChartAddress = ::rtl::OUString::createFromAscii("all"); + if( !xNewDoc->hasInternalDataProvider() ) { - xTableAddressMapper->mapStrings( maSeriesAddresses[ nIdx ].DomainRangeAddresses ); - bHasDomain = sal_True; + xNewDoc->createInternalDataProvider( sal_False /* bCloneExistingData */ ); + xChartData = uno::Reference< chart::XChartDataArray >( mrImportHelper.GetDataProvider( xNewDoc ), uno::UNO_QUERY ); + if( xChartData.is()) + SchXMLTableHelper::applyTableSimple( maTable, xChartData ); + try + { + ChangeDiagramAccordingToTemplate( xNewDoc ); + } + catch( uno::Exception & ) + { + DBG_ERROR( "Exception during import SchXMLChartContext::ChangeDiagramAccordingToTemplate fallback to internal data failed also" ); + } } } - // categories - aStrSeq[ nLength * 2 ] = msCategoriesAddress; + } + } + } + else + { + DBG_ERROR( " Must not get here" ); + } - // translate - xTableAddressMapper->mapStrings( aStrSeq ); + // 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) ); + } - // write back - sal_Int32 nOffset = 0; - for( nIdx = 0; nIdx < nLength; nIdx++ ) - { - // #81525# convert addresses for xy charts - // this should be done by calc in the future - if( nIdx == 0 && - bHasDomain ) - { - // enlarge the sequence - maSeriesAddresses.realloc( maSeriesAddresses.getLength() + 1 ); - - // copy the domain as first series - if( maSeriesAddresses[ nIdx + nOffset ].DomainRangeAddresses.getLength() > 0 ) - maSeriesAddresses[ nIdx + nOffset ].DataRangeAddress = - maSeriesAddresses[ nIdx + nOffset ].DomainRangeAddresses[ 0 ]; - // the current data range becomes the second series - nOffset++; - } + SchXMLSeries2Context::initSeriesPropertySets( maSeriesDefaultsAndStyles, uno::Reference< frame::XModel >(xDoc, uno::UNO_QUERY ) ); + + //set defaults from diagram to the new series: + SchXMLSeries2Context::setDefaultsToSeries( maSeriesDefaultsAndStyles ); + + // set autostyles for series and data points + const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext(); + const SvXMLStyleContext* pStyle = NULL; + ::rtl::OUString sCurrStyleName; - maSeriesAddresses[ nIdx + nOffset ].DataRangeAddress = aStrSeq[ nIdx * 2 ]; - maSeriesAddresses[ nIdx + nOffset ].LabelAddress = aStrSeq[ nIdx * 2 + 1 ]; + if( pStylesCtxt ) + { + //iterate over data-series first + //don't set series styles for donut charts + if( !bSpecialHandlingForDonutChart ) + { + SchXMLSeries2Context::setStylesToSeries( maSeriesDefaultsAndStyles + , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, mbIsStockChart ); + // ... then set attributes for statistics (after their existence was set in the series) + SchXMLSeries2Context::setStylesToStatisticsObjects( maSeriesDefaultsAndStyles + , pStylesCtxt, pStyle, sCurrStyleName ); + } + + // ... then iterate over data-point attributes, so the latter are not overwritten + SchXMLSeries2Context::setStylesToDataPoints( maSeriesDefaultsAndStyles + , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, mbIsStockChart, bSpecialHandlingForDonutChart ); + + //check whether we need to remove lines from symbol only charts + bool bLinesOn = true; + if( (maSeriesDefaultsAndStyles.maLinesOnProperty >>= bLinesOn) && !bLinesOn ) + { + if( 0 == maChartTypeServiceName.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.ScatterChartType" ) ) ) + { + SchXMLSeries2Context::switchSeriesLinesOff( maSeriesDefaultsAndStyles.maSeriesStyleList ); } - msCategoriesAddress = aStrSeq[ nLength * 2 ]; } } } - // set table references at document - // even when having own table (Writer) if( xProp.is()) + xProp->setPropertyValue( rtl::OUString::createFromAscii( "RefreshAddInAllowed" ) , uno::makeAny( sal_True) ); +} + +void SchXMLChartContext::MergeSeriesForStockChart() +{ + OSL_ASSERT( mbIsStockChart ); + try { - 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::Any aAny; - if( msChartAddress.getLength()) + 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 ) { - aAny <<= msChartAddress; - xProp->setPropertyValue( ::rtl::OUString::createFromAscii( "ChartRangeAddress" ), aAny ); - - if( msTableNumberList.getLength()) + if( aChartTypes[nCTIdx]->getChartType().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.CandleStickChartType"))) { - aAny <<= msTableNumberList; - xProp->setPropertyValue( ::rtl::OUString::createFromAscii( "TableNumberList" ), aAny ); + xDSContainer.set( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xCTProp( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW ); + xCTProp->getPropertyValue( ::rtl::OUString::createFromAscii("Japanese")) >>= bHasJapaneseCandlestick; + break; } } - else + } + + 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 ) { - // deprecated - if( msCategoriesAddress.getLength()) + sal_Int32 nSeriesIndex = i*nSeriesPerCandleStick; + if( bHasJapaneseCandlestick ) { - aAny <<= msCategoriesAddress; - xProp->setPropertyValue( rtl::OUString::createFromAscii( "CategoriesRangeAddress" ), aAny ); + // open values + lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], OUString::createFromAscii("values-first")); + aNewSeries[i] = aSeriesSeq[ nSeriesIndex ]; + // low values + lcl_MoveDataToCandleStickSeries( + uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ), + aNewSeries[i], OUString::createFromAscii("values-min")); } - - // deprecated - if( maSeriesAddresses.getLength()) + else { - aAny <<= maSeriesAddresses; - xProp->setPropertyValue( rtl::OUString::createFromAscii( "SeriesAddresses" ), aAny ); + // low values + lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], OUString::createFromAscii("values-min")); + aNewSeries[i] = aSeriesSeq[ nSeriesIndex ]; } + // high values + lcl_MoveDataToCandleStickSeries( + uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ), + aNewSeries[i], OUString::createFromAscii("values-max")); + // close values + lcl_MoveDataToCandleStickSeries( + uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ), + aNewSeries[i], OUString::createFromAscii("values-last")); } - - // row / col translations - bool bHasColTrans = (msColTrans.getLength() > 0); - bool bHasRowTrans = (msRowTrans.getLength() > 0); - if( bHasColTrans ) - { - uno::Sequence< sal_Int32 > aSeq = GetNumberSequenceFromString( msColTrans ); - aAny <<= aSeq; - xProp->setPropertyValue( ::rtl::OUString::createFromAscii( "TranslatedColumns" ), aAny ); - } - else if( bHasRowTrans ) - { - uno::Sequence< sal_Int32 > aSeq = GetNumberSequenceFromString( msRowTrans ); - aAny <<= aSeq; - xProp->setPropertyValue( ::rtl::OUString::createFromAscii( "TranslatedRows" ), aAny ); - } - } - catch( beans::UnknownPropertyException ) - { - DBG_WARNING( "Required property not found in ChartDocument" ); + xDSContainer->setDataSeries( aNewSeries ); } } - - // allow BuildChart again -/* uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY ); - if( xModel.is()) - xModel->unlockControllers(); -*/ - // Set the main title's and subtitle's positions. - if( mbSetMainTitlePos && maMainTitle.getLength() > 0) + catch( uno::Exception & ) { - uno::Reference<drawing::XShape> xMainTitleShape(xDoc->getTitle(), uno::UNO_QUERY); - if( xMainTitleShape.is()) - xMainTitleShape->setPosition( maMainTitlePos ); + DBG_ERROR( "Exception while merging series for stock chart" ); } - if( mbSetSubTitlePos && maSubTitle.getLength() > 0) - { - uno::Reference<drawing::XShape> xSubTitleShape(xDoc->getSubTitle(), uno::UNO_QUERY); - if( xSubTitleShape.is()) - xSubTitleShape->setPosition( maSubTitlePos ); - } - - // set absolute legend position after (BuildChart!) - if( mbSetLegendPos && mbHasLegend ) - { - uno::Reference< drawing::XShape > xLegendShape( xDoc->getLegend(), uno::UNO_QUERY ); - if( xLegendShape.is()) - xLegendShape->setPosition( maLegendPos ); - } - - // #102413# BuildChart to manifest legend position - if( xDoc->hasControllersLocked()) - xDoc->unlockControllers(); - - // AF: No more BuildCharts until Initialize is called (by Draw or SaveAs). - - // BM: There should be no further BuildCharts, and it is very dangerous to - // leave the lock status on hoping that it is changed in Draw or SaveAs - // (OLE-Clone?). At least it isn't for the writer flat XML filter. So, - // leave Controllers unlocked from now on, as this is the last line of code - // that the Chart XML import routine will call } SvXMLImportContext* SchXMLChartContext::CreateChildContext( @@ -558,7 +1040,12 @@ SvXMLImportContext* SchXMLChartContext::CreateChildContext( case XML_TOK_CHART_PLOT_AREA: pContext = new SchXMLPlotAreaContext( mrImportHelper, GetImport(), rLocalName, maSeriesAddresses, msCategoriesAddress, - msChartAddress, msTableNumberList ); + msChartAddress, mbHasOwnTable, mbAllRangeAddressesAvailable, + mbColHasLabels, mbRowHasLabels, + meDataRowSource, + maSeriesDefaultsAndStyles, + maChartTypeServiceName, + maLSequencesPerIndex ); break; case XML_TOK_CHART_TITLE: @@ -567,12 +1054,10 @@ SvXMLImportContext* SchXMLChartContext::CreateChildContext( if( xProp.is()) { xProp->setPropertyValue( rtl::OUString::createFromAscii( "HasMainTitle" ), aTrueBool ); - - SCH_BUILDCHART( xDoc ); } uno::Reference< drawing::XShape > xTitleShape( xDoc->getTitle(), uno::UNO_QUERY ); pContext = new SchXMLTitleContext( mrImportHelper, GetImport(), - rLocalName, maMainTitle, xTitleShape, maMainTitlePos, mbSetMainTitlePos ); + rLocalName, maMainTitle, xTitleShape ); } break; @@ -582,34 +1067,19 @@ SvXMLImportContext* SchXMLChartContext::CreateChildContext( if( xProp.is()) { xProp->setPropertyValue( rtl::OUString::createFromAscii( "HasSubTitle" ), aTrueBool ); - SCH_BUILDCHART( xDoc ); } uno::Reference< drawing::XShape > xTitleShape( xDoc->getSubTitle(), uno::UNO_QUERY ); pContext = new SchXMLTitleContext( mrImportHelper, GetImport(), - rLocalName, maSubTitle, xTitleShape, maSubTitlePos, mbSetSubTitlePos ); + rLocalName, maSubTitle, xTitleShape ); } break; case XML_TOK_CHART_LEGEND: - pContext = new SchXMLLegendContext( mrImportHelper, GetImport(), rLocalName, maLegendPos, mbSetLegendPos ); - mbHasLegend =sal_True; + pContext = new SchXMLLegendContext( mrImportHelper, GetImport(), rLocalName ); break; case XML_TOK_CHART_TABLE: pContext = new SchXMLTableContext( mrImportHelper, GetImport(), rLocalName, maTable ); - if( pContext ) - { - mbHasOwnTable = sal_True; - if( xProp.is()) - try - { - xProp->setPropertyValue( ::rtl::OUString::createFromAscii( "ExportData" ), aTrueBool ); - } - catch( uno::Exception ) - { - DBG_ERRORFILE( "Property missing" ); - } - } break; default: @@ -642,137 +1112,47 @@ SvXMLImportContext* SchXMLChartContext::CreateChildContext( 3. Set a (logically) empty data set. 4. Set the chart type. */ -void SchXMLChartContext::InitChart (awt::Size aChartSize, - sal_Bool bDomainForDefaultDataNeeded, - rtl::OUString aServiceName, - sal_Bool bSetSwitchData) +void SchXMLChartContext::InitChart( + awt::Size aChartSize, + sal_Bool /* bDomainForDefaultDataNeeded */, + 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 ); - if( xModel.is()) - xModel->lockControllers(); - // Hide title, subtitle, and legend - uno::Reference< beans::XPropertySet > xProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY ); - if( xProp.is()) + // Remove Title and Diagram ("De-InitNew") + uno::Reference< chart2::XChartDocument > xNewDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY ); + if( xNewDoc.is()) { - uno::Any aFalseBool; - aFalseBool <<= (sal_Bool)(sal_False); - try - { - xProp->setPropertyValue( rtl::OUString::createFromAscii( "HasMainTitle" ), aFalseBool ); - xProp->setPropertyValue( rtl::OUString::createFromAscii( "HasSubTitle" ), aFalseBool ); - xProp->setPropertyValue( rtl::OUString::createFromAscii( "HasLegend" ), aFalseBool ); - } - catch( beans::UnknownPropertyException ) - { - DBG_ERROR( "XML-Chart Import: Property not found" ); - } + xNewDoc->setFirstDiagram( 0 ); + uno::Reference< chart2::XTitled > xTitled( xNewDoc, uno::UNO_QUERY ); + if( xTitled.is()) + xTitled->setTitle( 0 ); } // Set the size of the draw page. - uno::Reference< drawing::XDrawPageSupplier > xPageSupp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY ); - if( xPageSupp.is()) - { - uno::Reference< beans::XPropertySet > xPageProp( xPageSupp->getDrawPage(), uno::UNO_QUERY ); - if( xPageProp.is()) - { - try - { - uno::Any aAny; - aAny <<= (sal_Int32)( aChartSize.Width ); - xPageProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Width" )), aAny ); - - aAny <<= (sal_Int32)( aChartSize.Height ); - xPageProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Height" )), aAny ); - } - catch( beans::UnknownPropertyException ) - { - DBG_ERROR( "Cannot set page size" ); - } - } - } - - // We have to unlock the controllers and execute an implicit BuildChart because - // the following call to setData needs data structures created in a BuildChart. - if( xModel.is()) - xModel->unlockControllers(); - - // Set a (logically) empty data set. It will later be filled with the - // actual data. - // Because the chart does not work with a really empty data set a dummy data point - // and, if necessary, a dummy domain value (Not a number) are set. - uno::Reference< chart::XChartDataArray > xArray( xDoc->getData(), uno::UNO_QUERY ); - if( xArray.is()) - { - double fNan = 0.0; - - uno::Reference< chart::XChartData > xData( xDoc->getData(), uno::UNO_QUERY ); - if( xData.is()) - fNan = xData->getNotANumber(); - - // attention: the data must at least be 1 x 1, - // (or 2 x 2 for scatter charts) - // otherwise BuildChart doesn't perform much. - if( bDomainForDefaultDataNeeded ) - { - uno::Sequence< uno::Sequence< double > > aAlmostEmptySeq( 2 ); - aAlmostEmptySeq[ 0 ].realloc( 2 ); - aAlmostEmptySeq[ 0 ][ 0 ] = 0.0; - aAlmostEmptySeq[ 0 ][ 1 ] = fNan; - - aAlmostEmptySeq[ 1 ].realloc( 2 ); - aAlmostEmptySeq[ 1 ][ 0 ] = 0.0; - aAlmostEmptySeq[ 1 ][ 1 ] = fNan; - - xArray->setData( aAlmostEmptySeq ); - } - else - { - uno::Sequence< uno::Sequence< double > > aAlmostEmptySeq( 1 ); - aAlmostEmptySeq[ 0 ].realloc( 1 ); - aAlmostEmptySeq[ 0 ][ 0 ] = 0.0; - - xArray->setData( aAlmostEmptySeq ); - } - } - - if( xModel.is()) - xModel->lockControllers(); + uno::Reference< embed::XVisualObject > xVisualObject(xModel,uno::UNO_QUERY); + DBG_ASSERT(xVisualObject.is(),"need xVisualObject for page size"); + if( xVisualObject.is() ) + xVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, aChartSize ); // Set the chart type via setting the diagram. - if( aServiceName.getLength() && + if( rChartTypeServiceName.getLength() && xDoc.is()) { uno::Reference< lang::XMultiServiceFactory > xFact( xDoc, uno::UNO_QUERY ); if( xFact.is()) { - uno::Reference< chart::XDiagram > xDia( xFact->createInstance( aServiceName ), uno::UNO_QUERY ); + uno::Reference< chart::XDiagram > xDia( xFact->createInstance( rChartTypeServiceName ), uno::UNO_QUERY ); if( xDia.is()) - { xDoc->setDiagram( xDia ); - - // set data row source for pie charts to ROWS - if( bSetSwitchData ) - { - uno::Reference< beans::XPropertySet > xDiaProp( xDia, uno::UNO_QUERY ); - if( xDiaProp.is()) - { - uno::Any aAny; - aAny <<= chart::ChartDataRowSource( chart::ChartDataRowSource_ROWS ); - xDiaProp->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataRowSource" )), aAny ); - } - } - } } } - - if( xModel.is()) - xModel->unlockControllers(); } -uno::Sequence< sal_Int32 > SchXMLChartContext::GetNumberSequenceFromString( const ::rtl::OUString& rStr ) +uno::Sequence< sal_Int32 > SchXMLChartContext::GetNumberSequenceFromString( const ::rtl::OUString& rStr, bool bAddOneToEachOldIndex ) { const sal_Unicode aSpace( ' ' ); @@ -799,11 +1179,27 @@ uno::Sequence< sal_Int32 > SchXMLChartContext::GetNumberSequenceFromString( cons const sal_Int32 nVecSize = aVec.size(); uno::Sequence< sal_Int32 > aSeq( nVecSize ); - sal_Int32* pSeqArr = aSeq.getArray(); - for( nPos = 0; nPos < nVecSize; ++nPos ) + + if(!bAddOneToEachOldIndex) { - pSeqArr[ nPos ] = aVec[ nPos ]; + 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; } @@ -812,15 +1208,11 @@ uno::Sequence< sal_Int32 > SchXMLChartContext::GetNumberSequenceFromString( cons SchXMLTitleContext::SchXMLTitleContext( SchXMLImportHelper& rImpHelper, SvXMLImport& rImport, const rtl::OUString& rLocalName, rtl::OUString& rTitle, - uno::Reference< drawing::XShape >& xTitleShape, - awt::Point& rPosition, - bool & rSetPosition ) : + uno::Reference< drawing::XShape >& xTitleShape ) : SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ), mrImportHelper( rImpHelper ), mrTitle( rTitle ), - mxTitleShape( xTitleShape ), - mrPosition( rPosition ), - mrSetPosition( rSetPosition ) + mxTitleShape( xTitleShape ) { } @@ -831,8 +1223,9 @@ void SchXMLTitleContext::StartElement( const uno::Reference< xml::sax::XAttribut { sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0; - if( mxTitleShape.is()) - mrPosition = mxTitleShape->getPosition(); + com::sun::star::awt::Point maPosition; + bool bHasXPosition=false; + bool bHasYPosition=false; for( sal_Int16 i = 0; i < nAttrCount; i++ ) { @@ -845,13 +1238,13 @@ void SchXMLTitleContext::StartElement( const uno::Reference< xml::sax::XAttribut { if( IsXMLToken( aLocalName, XML_X ) ) { - GetImport().GetMM100UnitConverter().convertMeasure( mrPosition.X, aValue ); - mrSetPosition = true; + GetImport().GetMM100UnitConverter().convertMeasure( maPosition.X, aValue ); + bHasXPosition = true; } else if( IsXMLToken( aLocalName, XML_Y ) ) { - GetImport().GetMM100UnitConverter().convertMeasure( mrPosition.Y, aValue ); - mrSetPosition = true; + GetImport().GetMM100UnitConverter().convertMeasure( maPosition.Y, aValue ); + bHasYPosition = true; } } else if( nPrefix == XML_NAMESPACE_CHART ) @@ -861,8 +1254,12 @@ void SchXMLTitleContext::StartElement( const uno::Reference< xml::sax::XAttribut } } + if( mxTitleShape.is()) { + if( bHasXPosition && bHasYPosition ) + mxTitleShape->setPosition( maPosition ); + uno::Reference< beans::XPropertySet > xProp( mxTitleShape, uno::UNO_QUERY ); if( xProp.is()) { @@ -900,13 +1297,9 @@ SvXMLImportContext* SchXMLTitleContext::CreateChildContext( // ---------------------------------------- SchXMLLegendContext::SchXMLLegendContext( SchXMLImportHelper& rImpHelper, - SvXMLImport& rImport, const rtl::OUString& rLocalName, - com::sun::star::awt::Point& rPosition, - bool & rSetPosition ) : + SvXMLImport& rImport, const rtl::OUString& rLocalName ) : SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ), - mrImportHelper( rImpHelper ), - mrPosition( rPosition ), - mrSetPosition( rSetPosition ) + mrImportHelper( rImpHelper ) { } @@ -925,12 +1318,6 @@ void SchXMLLegendContext::StartElement( const uno::Reference< xml::sax::XAttribu try { xDocProp->setPropertyValue( rtl::OUString::createFromAscii( "HasLegend" ), aTrueBool ); - SCH_BUILDCHART( xDoc ); - - // initialize position - uno::Reference< drawing::XShape > xLegendShape( xDoc->getLegend(), uno::UNO_QUERY ); - if( xLegendShape.is()) - mrPosition = xLegendShape->getPosition(); } catch( beans::UnknownPropertyException ) { @@ -942,10 +1329,9 @@ void SchXMLLegendContext::StartElement( const uno::Reference< xml::sax::XAttribu sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0; const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetLegendAttrTokenMap(); - awt::Point aPosition; - uno::Reference< drawing::XShape > xLegendShape( xDoc->getLegend(), uno::UNO_QUERY ); - if( xLegendShape.is()) - aPosition = xLegendShape->getPosition(); + awt::Point aLegendPos; + bool bHasXPosition=false; + bool bHasYPosition=false; rtl::OUString sAutoStyleName; @@ -983,22 +1369,29 @@ void SchXMLLegendContext::StartElement( const uno::Reference< xml::sax::XAttribu break; case XML_TOK_LEGEND_X: - GetImport().GetMM100UnitConverter().convertMeasure( mrPosition.X, aValue ); - mrSetPosition = true; + GetImport().GetMM100UnitConverter().convertMeasure( aLegendPos.X, aValue ); + bHasXPosition = true; break; case XML_TOK_LEGEND_Y: - GetImport().GetMM100UnitConverter().convertMeasure( mrPosition.Y, aValue ); - mrSetPosition = true; + GetImport().GetMM100UnitConverter().convertMeasure( aLegendPos.Y, aValue ); + bHasYPosition = true; break; case XML_TOK_LEGEND_STYLE_NAME: sAutoStyleName = aValue; } } - // set auto-styles for Area - uno::Reference< beans::XPropertySet > xProp( xDoc->getLegend(), uno::UNO_QUERY ); + uno::Reference< drawing::XShape > xLegendShape( xDoc->getLegend(), uno::UNO_QUERY ); + if( xLegendShape.is() && bHasXPosition && bHasYPosition ) + xLegendShape->setPosition( aLegendPos ); + + // set auto-styles for Legend + uno::Reference< beans::XPropertySet > xProp( xLegendShape, uno::UNO_QUERY ); if( xProp.is()) { + // the fill style has the default "none" in XML, but "solid" in the model. + xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FillStyle" )), + uno::makeAny( drawing::FillStyle_NONE )); const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext(); if( pStylesCtxt ) { |