bump product version to 4.1.6.2
[LibreOffice.git] / xmloff / source / chart / SchXMLSeries2Context.cxx
blob148b7352c68f7e3d50b1ca91f60059a05dfce19a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "SchXMLSeries2Context.hxx"
22 #include "SchXMLPlotAreaContext.hxx"
23 #include "SchXMLTools.hxx"
24 #include "PropertyMap.hxx"
26 #include <com/sun/star/chart2/XChartDocument.hpp>
27 #include <com/sun/star/chart2/XDataSeries.hpp>
28 #include <com/sun/star/chart2/XRegressionCurve.hpp>
29 #include <com/sun/star/chart2/data/XDataSink.hpp>
30 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
32 #include <com/sun/star/chart/ChartAxisAssign.hpp>
33 #include <com/sun/star/chart/ChartSymbolType.hpp>
34 #include <com/sun/star/container/XChild.hpp>
35 #include <com/sun/star/chart/ChartLegendPosition.hpp>
36 #include <com/sun/star/drawing/LineStyle.hpp>
37 #include <com/sun/star/embed/Aspects.hpp>
38 #include <com/sun/star/embed/XVisualObject.hpp>
39 #include <com/sun/star/uno/XComponentContext.hpp>
41 // header for define DBG_ERROR1
42 #include <tools/debug.hxx>
43 #include <rtl/ustrbuf.hxx>
44 #include "xmloff/xmlnmspe.hxx"
45 #include <xmloff/xmlimp.hxx>
46 #include <xmloff/nmspmap.hxx>
47 #include <xmloff/SchXMLSeriesHelper.hxx>
48 #include "SchXMLImport.hxx"
49 // header for class XMLPropStyleContext
50 #include <xmloff/prstylei.hxx>
51 #include <xmloff/xmlprmap.hxx>
53 #include <typeinfo>
55 using namespace ::com::sun::star;
56 using namespace ::xmloff::token;
58 using ::com::sun::star::uno::Reference;
59 using ::com::sun::star::uno::Sequence;
61 // ================================================================================
63 namespace
66 class SchXMLDomain2Context : public SvXMLImportContext
68 private:
69 ::std::vector< OUString > & mrAddresses;
71 public:
72 SchXMLDomain2Context( SvXMLImport& rImport,
73 sal_uInt16 nPrefix,
74 const OUString& rLocalName,
75 ::std::vector< OUString > & rAddresses );
76 virtual ~SchXMLDomain2Context();
77 virtual void StartElement( const Reference< xml::sax::XAttributeList >& xAttrList );
80 SchXMLDomain2Context::SchXMLDomain2Context(
81 SvXMLImport& rImport,
82 sal_uInt16 nPrefix,
83 const OUString& rLocalName,
84 ::std::vector< OUString > & rAddresses ) :
85 SvXMLImportContext( rImport, nPrefix, rLocalName ),
86 mrAddresses( rAddresses )
90 SchXMLDomain2Context::~SchXMLDomain2Context()
94 void SchXMLDomain2Context::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
96 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
98 for( sal_Int16 i = 0; i < nAttrCount; i++ )
100 OUString sAttrName = xAttrList->getNameByIndex( i );
101 OUString aLocalName;
102 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
104 if( nPrefix == XML_NAMESPACE_TABLE &&
105 IsXMLToken( aLocalName, XML_CELL_RANGE_ADDRESS ) )
107 Reference< chart2::XChartDocument > xNewDoc( GetImport().GetModel(), uno::UNO_QUERY );
108 mrAddresses.push_back( xAttrList->getValueByIndex( i ));
113 void lcl_setAutomaticSymbolSize( const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp, const SvXMLImport& rImport )
115 awt::Size aSymbolSize(140,140);//old default for standard sized charts 7cm height
117 uno::Reference< chart::XChartDocument > xChartDoc( rImport.GetModel(), uno::UNO_QUERY );
118 if( xChartDoc.is() )
120 double fScale = 1;
121 uno::Reference< beans::XPropertySet > xLegendProp( xChartDoc->getLegend(), uno::UNO_QUERY );
122 chart::ChartLegendPosition aLegendPosition = chart::ChartLegendPosition_NONE;
123 if( xLegendProp.is() && (xLegendProp->getPropertyValue( OUString( "Alignment" )) >>= aLegendPosition)
124 && chart::ChartLegendPosition_NONE != aLegendPosition )
127 double fFontHeight = 6.0;
128 if( xLegendProp->getPropertyValue( OUString( "CharHeight" )) >>= fFontHeight )
129 fScale = 0.75*fFontHeight/6.0;
131 else
133 uno::Reference< embed::XVisualObject > xVisualObject( rImport.GetModel(), uno::UNO_QUERY );
134 if( xVisualObject.is() )
136 awt::Size aPageSize( xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ) );
137 fScale = aPageSize.Height/7000.0;
140 if( fScale>0 )
142 aSymbolSize.Height = static_cast<sal_Int32>( fScale * aSymbolSize.Height );
143 aSymbolSize.Width = aSymbolSize.Height;
146 xSeriesOrPointProp->setPropertyValue(OUString("SymbolSize"),uno::makeAny( aSymbolSize ));
149 void lcl_setSymbolSizeIfNeeded( const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp, const SvXMLImport& rImport )
151 if( !xSeriesOrPointProp.is() )
152 return;
154 sal_Int32 nSymbolType = chart::ChartSymbolType::NONE;
155 if( xSeriesOrPointProp.is() && ( xSeriesOrPointProp->getPropertyValue(OUString("SymbolType")) >>= nSymbolType) )
157 if(chart::ChartSymbolType::NONE!=nSymbolType)
159 if( chart::ChartSymbolType::BITMAPURL==nSymbolType )
161 //set special size for graphics to indicate to use the bitmap size itself
162 xSeriesOrPointProp->setPropertyValue(OUString("SymbolSize"),uno::makeAny( awt::Size(-1,-1) ));
164 else
166 lcl_setAutomaticSymbolSize( xSeriesOrPointProp, rImport );
172 void lcl_resetSymbolSizeForPointsIfNecessary( const uno::Reference< beans::XPropertySet >& xPointProp, const SvXMLImport& rImport
173 , const XMLPropStyleContext * pPropStyleContext, const SvXMLStylesContext* pStylesCtxt )
175 uno::Any aASymbolSize( SchXMLTools::getPropertyFromContext( OUString("SymbolSize"), pPropStyleContext, pStylesCtxt ) );
176 if( !aASymbolSize.hasValue() )
177 lcl_setSymbolSizeIfNeeded( xPointProp, rImport );
180 void lcl_insertErrorBarLSequencesToMap(
181 tSchXMLLSequencesPerIndex & rInOutMap,
182 const uno::Reference< beans::XPropertySet > & xSeriesProp,
183 bool bYError = true )
185 Reference< chart2::data::XDataSource > xErrorBarSource;
186 const OUString aPropName(
187 bYError
188 ? OUString( "ErrorBarY" )
189 : OUString( "ErrorBarX" ));
190 if( ( xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBarSource ) &&
191 xErrorBarSource.is() )
193 Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSequences(
194 xErrorBarSource->getDataSequences());
195 for( sal_Int32 nIndex = 0; nIndex < aLSequences.getLength(); ++nIndex )
197 // use "0" as data index. This is ok, as it is not used for error bars
198 rInOutMap.insert(
199 tSchXMLLSequencesPerIndex::value_type(
200 tSchXMLIndexWithPart( 0, SCH_XML_PART_ERROR_BARS ), aLSequences[ nIndex ] ));
205 Reference< chart2::data::XLabeledDataSequence2 > lcl_createAndAddSequenceToSeries( const OUString& rRole
206 , const OUString& rRange
207 , const Reference< chart2::XChartDocument >& xChartDoc
208 , const Reference< chart2::XDataSeries >& xSeries )
210 Reference< chart2::data::XLabeledDataSequence2 > xLabeledSeq;
212 Reference< chart2::data::XDataSource > xSeriesSource( xSeries,uno::UNO_QUERY );
213 Reference< chart2::data::XDataSink > xSeriesSink( xSeries, uno::UNO_QUERY );
215 if( !(!rRange.isEmpty() && xChartDoc.is() && xSeriesSource.is() && xSeriesSink.is()) )
216 return xLabeledSeq;
218 // create a new sequence
219 xLabeledSeq = SchXMLTools::GetNewLabeledDataSequence();
221 // set values at the new sequence
222 Reference< chart2::data::XDataSequence > xSeq = SchXMLTools::CreateDataSequence( rRange, xChartDoc );
223 Reference< beans::XPropertySet > xSeqProp( xSeq, uno::UNO_QUERY );
224 if( xSeqProp.is())
225 xSeqProp->setPropertyValue(OUString( "Role" ), uno::makeAny( rRole));
226 xLabeledSeq->setValues( xSeq );
228 // add new sequence to data series / push to front to have the correct sequence order if charttype is changed afterwards
229 Sequence< Reference< chart2::data::XLabeledDataSequence > > aOldSeq( xSeriesSource->getDataSequences());
230 sal_Int32 nOldCount = aOldSeq.getLength();
231 Sequence< Reference< chart2::data::XLabeledDataSequence > > aNewSeq( nOldCount + 1 );
232 aNewSeq[0] = Reference< chart2::data::XLabeledDataSequence >(xLabeledSeq, uno::UNO_QUERY_THROW);
233 for( sal_Int32 nN=0; nN<nOldCount; nN++ )
234 aNewSeq[nN+1] = aOldSeq[nN];
235 xSeriesSink->setData( aNewSeq );
237 return xLabeledSeq;
240 } // anonymous namespace
242 // ================================================================================
244 SchXMLSeries2Context::SchXMLSeries2Context(
245 SchXMLImportHelper& rImpHelper,
246 SvXMLImport& rImport, const OUString& rLocalName,
247 const Reference< chart2::XChartDocument > & xNewDoc,
248 std::vector< SchXMLAxis >& rAxes,
249 ::std::list< DataRowPointStyle >& rStyleList,
250 sal_Int32 nSeriesIndex,
251 sal_Bool bStockHasVolume,
252 GlobalSeriesImportInfo& rGlobalSeriesImportInfo,
253 const OUString & aGlobalChartTypeName,
254 tSchXMLLSequencesPerIndex & rLSequencesPerIndex,
255 bool& rGlobalChartTypeUsedBySeries,
256 const awt::Size & rChartSize ) :
257 SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
258 mrImportHelper( rImpHelper ),
259 mxNewDoc( xNewDoc ),
260 mrAxes( rAxes ),
261 mrStyleList( rStyleList ),
262 m_xSeries(0),
263 mnSeriesIndex( nSeriesIndex ),
264 mnDataPointIndex( 0 ),
265 m_bStockHasVolume( bStockHasVolume ),
266 m_rGlobalSeriesImportInfo(rGlobalSeriesImportInfo),
267 mpAttachedAxis( NULL ),
268 maGlobalChartTypeName( aGlobalChartTypeName ),
269 maSeriesChartTypeName( aGlobalChartTypeName ),
270 m_bHasDomainContext(false),
271 mrLSequencesPerIndex( rLSequencesPerIndex ),
272 mrGlobalChartTypeUsedBySeries( rGlobalChartTypeUsedBySeries ),
273 mbSymbolSizeIsMissingInFile(false),
274 maChartSize( rChartSize )
276 if( 0 == aGlobalChartTypeName.reverseCompareTo( "com.sun.star.chart2.DonutChartType" ) )
278 maSeriesChartTypeName = "com.sun.star.chart2.PieChartType";
279 maGlobalChartTypeName = maSeriesChartTypeName;
283 SchXMLSeries2Context::~SchXMLSeries2Context()
285 SAL_WARN_IF( !maPostponedSequences.empty(), "xmloff.chart", "maPostponedSequences is NULL");
288 void SchXMLSeries2Context::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
290 // parse attributes
291 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
292 const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetSeriesAttrTokenMap();
293 mnAttachedAxis = 1;
295 bool bHasRange = false;
296 bool bHasLabelRange = false;
298 for( sal_Int16 i = 0; i < nAttrCount; i++ )
300 OUString sAttrName = xAttrList->getNameByIndex( i );
301 OUString aLocalName;
302 OUString aValue = xAttrList->getValueByIndex( i );
303 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
305 switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
307 case XML_TOK_SERIES_CELL_RANGE:
308 m_aSeriesRange = aValue;
309 bHasRange = true;
310 break;
311 case XML_TOK_SERIES_LABEL_ADDRESS:
312 m_aSeriesLabelRange = aValue;
313 bHasLabelRange = true;
314 break;
315 case XML_TOK_SERIES_ATTACHED_AXIS:
317 sal_Int32 nNumOfAxes = mrAxes.size();
318 for( sal_Int32 nCurrent = 0; nCurrent < nNumOfAxes; nCurrent++ )
320 if( aValue.equals( mrAxes[ nCurrent ].aName ) &&
321 mrAxes[ nCurrent ].eDimension == SCH_XML_AXIS_Y )
323 mpAttachedAxis = &( mrAxes[ nCurrent ] );
327 break;
328 case XML_TOK_SERIES_STYLE_NAME:
329 msAutoStyleName = aValue;
330 break;
331 case XML_TOK_SERIES_CHART_CLASS:
333 OUString aClassName;
334 sal_uInt16 nClassPrefix =
335 GetImport().GetNamespaceMap().GetKeyByAttrName(
336 aValue, &aClassName );
337 if( XML_NAMESPACE_CHART == nClassPrefix )
338 maSeriesChartTypeName = SchXMLTools::GetChartTypeByClassName( aClassName, false /* bUseOldNames */ );
340 if( maSeriesChartTypeName.isEmpty())
341 maSeriesChartTypeName = aClassName;
343 break;
347 if( mpAttachedAxis )
349 if( mpAttachedAxis->nAxisIndex > 0 )
351 // secondary axis => property has to be set (primary is default)
352 mnAttachedAxis = 2;
358 SAL_WARN_IF( !mxNewDoc.is(), "xmloff.chart", "mxNewDoc is NULL");
359 if( m_rGlobalSeriesImportInfo.rbAllRangeAddressesAvailable && ! bHasRange )
360 m_rGlobalSeriesImportInfo.rbAllRangeAddressesAvailable = sal_False;
362 bool bIsCandleStick = maGlobalChartTypeName == "com.sun.star.chart2.CandleStickChartType";
363 if( !maSeriesChartTypeName.isEmpty() )
365 bIsCandleStick = maSeriesChartTypeName == "com.sun.star.chart2.CandleStickChartType";
367 else
369 if( bIsCandleStick
370 && m_bStockHasVolume
371 && mnSeriesIndex == 0 )
373 maSeriesChartTypeName = OUString( "com.sun.star.chart2.ColumnChartType" );
374 bIsCandleStick = false;
376 else
378 maSeriesChartTypeName = maGlobalChartTypeName;
381 if( ! mrGlobalChartTypeUsedBySeries )
382 mrGlobalChartTypeUsedBySeries = (maSeriesChartTypeName.equals( maGlobalChartTypeName ));
383 sal_Int32 nCoordinateSystemIndex = 0;//so far we can only import one coordinate system
384 m_xSeries.set(
385 mrImportHelper.GetNewDataSeries( mxNewDoc, nCoordinateSystemIndex, maSeriesChartTypeName, ! mrGlobalChartTypeUsedBySeries ));
386 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( SchXMLTools::GetNewLabeledDataSequence(), uno::UNO_QUERY_THROW );
388 if( bIsCandleStick )
390 // set default color for range-line to black (before applying styles)
391 Reference< beans::XPropertySet > xSeriesProp( m_xSeries, uno::UNO_QUERY );
392 if( xSeriesProp.is())
393 xSeriesProp->setPropertyValue( OUString("Color"),
394 uno::makeAny( sal_Int32( 0x000000 ))); // black
396 else if ( maSeriesChartTypeName == "com.sun.star.chart2.PieChartType" )
398 //@todo: this property should be saved
399 Reference< beans::XPropertySet > xSeriesProp( m_xSeries, uno::UNO_QUERY );
400 if( xSeriesProp.is())
401 xSeriesProp->setPropertyValue( OUString("VaryColorsByPoint"),
402 uno::makeAny( true ));
405 // values
406 Reference< chart2::data::XDataSequence > xSeq;
407 if( bHasRange && !m_aSeriesRange.isEmpty() )
408 xSeq = SchXMLTools::CreateDataSequence( m_aSeriesRange, mxNewDoc );
410 Reference< beans::XPropertySet > xSeqProp( xSeq, uno::UNO_QUERY );
411 if( xSeqProp.is())
413 OUString aMainRole("values-y");
414 if ( maSeriesChartTypeName == "com.sun.star.chart2.BubbleChartType" )
415 aMainRole = OUString( "values-size" );
416 xSeqProp->setPropertyValue(OUString( "Role" ), uno::makeAny( aMainRole ));
418 xLabeledSeq->setValues( xSeq );
420 // register for setting local data if external data provider is not present
421 maPostponedSequences.insert(
422 tSchXMLLSequencesPerIndex::value_type(
423 tSchXMLIndexWithPart( m_rGlobalSeriesImportInfo.nCurrentDataIndex, SCH_XML_PART_VALUES ), xLabeledSeq ));
425 // label
426 if( bHasLabelRange && !m_aSeriesLabelRange.isEmpty() )
428 Reference< chart2::data::XDataSequence > xLabelSequence =
429 SchXMLTools::CreateDataSequence( m_aSeriesLabelRange, mxNewDoc );
430 xLabeledSeq->setLabel( xLabelSequence );
433 // Note: Even if we have no label, we have to register the label
434 // for creation, because internal data always has labels. If
435 // they don't exist in the original, auto-generated labels are
436 // used for the internal data.
437 maPostponedSequences.insert(
438 tSchXMLLSequencesPerIndex::value_type(
439 tSchXMLIndexWithPart( m_rGlobalSeriesImportInfo.nCurrentDataIndex, SCH_XML_PART_LABEL ), xLabeledSeq ));
442 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( &xLabeledSeq, 1 );
443 Reference< chart2::data::XDataSink > xSink( m_xSeries, uno::UNO_QUERY_THROW );
444 xSink->setData( aSeq );
446 catch( const uno::Exception & ex )
448 SAL_WARN("xmloff.chart", "Exception caught. Type: " << OUString::createFromAscii( typeid( ex ).name()) << ", Message: " << ex.Message);
451 //init mbSymbolSizeIsMissingInFile:
454 if( !msAutoStyleName.isEmpty() )
456 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
457 if( pStylesCtxt )
459 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
460 mrImportHelper.GetChartFamilyID(), msAutoStyleName );
462 const XMLPropStyleContext* pPropStyleContext = dynamic_cast< const XMLPropStyleContext * >( pStyle );
464 uno::Any aASymbolSize( SchXMLTools::getPropertyFromContext( OUString("SymbolSize")
465 , pPropStyleContext, pStylesCtxt ) );
466 mbSymbolSizeIsMissingInFile = !aASymbolSize.hasValue();
470 catch( const uno::Exception & )
475 struct DomainInfo
477 DomainInfo( const OUString& rRole, const OUString& rRange, sal_Int32 nIndex )
478 : aRole(rRole), aRange(rRange), nIndexForLocalData(nIndex)
481 OUString aRole;
482 OUString aRange;
483 sal_Int32 nIndexForLocalData;
486 void SchXMLSeries2Context::EndElement()
488 // special handling for different chart types. This is necessary as the
489 // roles are not yet saved in the file format
490 sal_Int32 nDomainCount = maDomainAddresses.size();
491 bool bIsScatterChart = maSeriesChartTypeName == "com.sun.star.chart2.ScatterChartType";
492 bool bIsBubbleChart = maSeriesChartTypeName == "com.sun.star.chart2.BubbleChartType";
493 bool bDeleteSeries = false;
494 std::vector< DomainInfo > aDomainInfos;
496 //different handling for different chart types necessary
497 if( bIsScatterChart || ( nDomainCount==1 && !bIsBubbleChart ) )
499 DomainInfo aDomainInfo( OUString( "values-x" ), m_rGlobalSeriesImportInfo.aFirstFirstDomainAddress, m_rGlobalSeriesImportInfo.nFirstFirstDomainIndex ) ;
500 bool bCreateXValues = true;
501 if( !maDomainAddresses.empty() )
503 if( m_rGlobalSeriesImportInfo.aFirstFirstDomainAddress.isEmpty() )
505 m_rGlobalSeriesImportInfo.aFirstFirstDomainAddress = maDomainAddresses.front();
506 m_rGlobalSeriesImportInfo.nFirstFirstDomainIndex = m_rGlobalSeriesImportInfo.nCurrentDataIndex;
508 aDomainInfo.aRange = maDomainAddresses.front();
509 aDomainInfo.nIndexForLocalData = m_rGlobalSeriesImportInfo.nCurrentDataIndex;
510 m_rGlobalSeriesImportInfo.nCurrentDataIndex++;
512 else if( m_rGlobalSeriesImportInfo.aFirstFirstDomainAddress.isEmpty() && !m_bHasDomainContext && mnSeriesIndex==0 )
514 if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( GetImport().GetModel() ) ) //wrong old chart files:
516 //for xy charts the first series needs to have a domain
517 //if this by error iss not the case the first series is taken s x values
518 //needed for wrong files created while having an addin (e.g. BoxPlot)
519 m_rGlobalSeriesImportInfo.aFirstFirstDomainAddress = m_aSeriesRange;
520 m_rGlobalSeriesImportInfo.nFirstFirstDomainIndex = m_rGlobalSeriesImportInfo.nCurrentDataIndex++;
521 bDeleteSeries = true;
522 bCreateXValues = false;//they will be created for the next series
525 if( bCreateXValues )
526 aDomainInfos.push_back( aDomainInfo );
528 else if( bIsBubbleChart )
530 if( nDomainCount>1 )
532 DomainInfo aDomainInfo( OUString( "values-x" ), maDomainAddresses[1], m_rGlobalSeriesImportInfo.nCurrentDataIndex ) ;
533 if( m_rGlobalSeriesImportInfo.aFirstSecondDomainAddress.isEmpty() )
535 //for bubble chart the second domain contains the x values which should become an index smaller than y values for own data table
536 //->so second first
537 m_rGlobalSeriesImportInfo.aFirstSecondDomainAddress = maDomainAddresses[1];
538 m_rGlobalSeriesImportInfo.nFirstSecondDomainIndex = m_rGlobalSeriesImportInfo.nCurrentDataIndex;
540 aDomainInfos.push_back( aDomainInfo );
541 m_rGlobalSeriesImportInfo.nCurrentDataIndex++;
543 else if( !m_rGlobalSeriesImportInfo.aFirstSecondDomainAddress.isEmpty() )
545 DomainInfo aDomainInfo( OUString( "values-x" ), m_rGlobalSeriesImportInfo.aFirstSecondDomainAddress, m_rGlobalSeriesImportInfo.nFirstSecondDomainIndex ) ;
546 aDomainInfos.push_back( aDomainInfo );
548 if( nDomainCount>0)
550 DomainInfo aDomainInfo( OUString( "values-y" ), maDomainAddresses.front(), m_rGlobalSeriesImportInfo.nCurrentDataIndex ) ;
551 if( m_rGlobalSeriesImportInfo.aFirstFirstDomainAddress.isEmpty() )
553 m_rGlobalSeriesImportInfo.aFirstFirstDomainAddress = maDomainAddresses.front();
554 m_rGlobalSeriesImportInfo.nFirstFirstDomainIndex = m_rGlobalSeriesImportInfo.nCurrentDataIndex;
556 aDomainInfos.push_back( aDomainInfo );
557 m_rGlobalSeriesImportInfo.nCurrentDataIndex++;
559 else if( !m_rGlobalSeriesImportInfo.aFirstFirstDomainAddress.isEmpty() )
561 DomainInfo aDomainInfo( OUString("values-y"), m_rGlobalSeriesImportInfo.aFirstFirstDomainAddress, m_rGlobalSeriesImportInfo.nFirstFirstDomainIndex ) ;
562 aDomainInfos.push_back( aDomainInfo );
566 if( bDeleteSeries )
568 //delete created series
569 SchXMLImportHelper::DeleteDataSeries(
570 m_xSeries, Reference< chart2::XChartDocument >( GetImport().GetModel(), uno::UNO_QUERY ) );
572 else
574 //add style
575 if( !msAutoStyleName.isEmpty() || mnAttachedAxis != 1 )
577 DataRowPointStyle aStyle(
578 DataRowPointStyle::DATA_SERIES,
579 m_xSeries,
580 -1, 1,
581 msAutoStyleName, mnAttachedAxis );
582 aStyle.mbSymbolSizeForSeriesIsMissingInFile=mbSymbolSizeIsMissingInFile;
583 mrStyleList.push_back( aStyle );
587 for( std::vector< DomainInfo >::reverse_iterator aIt( aDomainInfos.rbegin() ); aIt!= aDomainInfos.rend(); ++aIt )
589 DomainInfo aDomainInfo( *aIt );
590 Reference< chart2::data::XLabeledDataSequence2 > xLabeledSeq =
591 lcl_createAndAddSequenceToSeries( aDomainInfo.aRole, aDomainInfo.aRange, mxNewDoc, m_xSeries );
592 if( xLabeledSeq.is() )
594 // register for setting local data if external data provider is not present
595 mrLSequencesPerIndex.insert(
596 tSchXMLLSequencesPerIndex::value_type(
597 tSchXMLIndexWithPart( aDomainInfo.nIndexForLocalData, SCH_XML_PART_VALUES ),
598 Reference< chart2::data::XLabeledDataSequence >(xLabeledSeq, uno::UNO_QUERY_THROW) ));
602 if( !bDeleteSeries )
604 for( tSchXMLLSequencesPerIndex::const_iterator aIt( maPostponedSequences.begin());
605 aIt != maPostponedSequences.end(); ++aIt )
607 sal_Int32 nNewIndex = aIt->first.first + nDomainCount;
608 mrLSequencesPerIndex.insert(
609 tSchXMLLSequencesPerIndex::value_type(
610 tSchXMLIndexWithPart( nNewIndex, aIt->first.second ), aIt->second ));
612 m_rGlobalSeriesImportInfo.nCurrentDataIndex++;
614 maPostponedSequences.clear();
617 SvXMLImportContext* SchXMLSeries2Context::CreateChildContext(
618 sal_uInt16 nPrefix,
619 const OUString& rLocalName,
620 const uno::Reference< xml::sax::XAttributeList >& )
622 SvXMLImportContext* pContext = 0;
623 const SvXMLTokenMap& rTokenMap = mrImportHelper.GetSeriesElemTokenMap();
625 switch( rTokenMap.Get( nPrefix, rLocalName ))
627 case XML_TOK_SERIES_DOMAIN:
628 if( m_xSeries.is())
630 m_bHasDomainContext = true;
631 pContext = new SchXMLDomain2Context(
632 GetImport(),
633 nPrefix, rLocalName,
634 maDomainAddresses );
636 break;
638 case XML_TOK_SERIES_MEAN_VALUE_LINE:
639 pContext = new SchXMLStatisticsObjectContext(
640 mrImportHelper, GetImport(),
641 nPrefix, rLocalName, msAutoStyleName,
642 mrStyleList, m_xSeries,
643 SchXMLStatisticsObjectContext::CONTEXT_TYPE_MEAN_VALUE_LINE,
644 maChartSize, mrLSequencesPerIndex );
645 break;
646 case XML_TOK_SERIES_REGRESSION_CURVE:
647 pContext = new SchXMLStatisticsObjectContext(
648 mrImportHelper, GetImport(),
649 nPrefix, rLocalName, msAutoStyleName,
650 mrStyleList, m_xSeries,
651 SchXMLStatisticsObjectContext::CONTEXT_TYPE_REGRESSION_CURVE,
652 maChartSize, mrLSequencesPerIndex );
653 break;
654 case XML_TOK_SERIES_ERROR_INDICATOR:
655 pContext = new SchXMLStatisticsObjectContext(
656 mrImportHelper, GetImport(),
657 nPrefix, rLocalName, msAutoStyleName,
658 mrStyleList, m_xSeries,
659 SchXMLStatisticsObjectContext::CONTEXT_TYPE_ERROR_INDICATOR,
660 maChartSize, mrLSequencesPerIndex );
661 break;
663 case XML_TOK_SERIES_DATA_POINT:
664 pContext = new SchXMLDataPointContext( GetImport(), rLocalName,
665 mrStyleList, m_xSeries, mnDataPointIndex, mbSymbolSizeIsMissingInFile );
666 break;
668 default:
669 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
672 return pContext;
675 //static
676 void SchXMLSeries2Context::initSeriesPropertySets( SeriesDefaultsAndStyles& rSeriesDefaultsAndStyles
677 , const uno::Reference< frame::XModel >& xChartModel )
679 ::std::list< DataRowPointStyle >::iterator iStyle;
681 // iterate over series first and remind propertysets in map
682 // new api <-> old api wrapper
683 ::std::map< Reference< chart2::XDataSeries >, Reference< beans::XPropertySet > > aSeriesMap;
684 for( iStyle = rSeriesDefaultsAndStyles.maSeriesStyleList.begin(); iStyle != rSeriesDefaultsAndStyles.maSeriesStyleList.end(); ++iStyle )
686 if( iStyle->meType != DataRowPointStyle::DATA_SERIES )
687 continue;
689 if( !iStyle->m_xOldAPISeries.is() )
690 iStyle->m_xOldAPISeries = SchXMLSeriesHelper::createOldAPISeriesPropertySet( iStyle->m_xSeries, xChartModel );
692 aSeriesMap[iStyle->m_xSeries] = iStyle->m_xOldAPISeries;
696 //initialize m_xOldAPISeries for all other styles also
697 for( iStyle = rSeriesDefaultsAndStyles.maSeriesStyleList.begin(); iStyle != rSeriesDefaultsAndStyles.maSeriesStyleList.end(); ++iStyle )
699 if( iStyle->meType == DataRowPointStyle::DATA_SERIES )
700 continue;
701 iStyle->m_xOldAPISeries = aSeriesMap[iStyle->m_xSeries];
705 //static
706 void SchXMLSeries2Context::setDefaultsToSeries( SeriesDefaultsAndStyles& rSeriesDefaultsAndStyles )
708 ::std::list< DataRowPointStyle >::iterator iStyle;
709 // iterate over series
710 // call initSeriesPropertySets first
712 for( iStyle = rSeriesDefaultsAndStyles.maSeriesStyleList.begin(); iStyle != rSeriesDefaultsAndStyles.maSeriesStyleList.end(); ++iStyle )
714 if( iStyle->meType != DataRowPointStyle::DATA_SERIES )
715 continue;
719 uno::Reference< beans::XPropertySet > xSeries( iStyle->m_xOldAPISeries );
720 if( !xSeries.is() )
721 continue;
723 if( rSeriesDefaultsAndStyles.maSymbolTypeDefault.hasValue() )
724 xSeries->setPropertyValue(OUString("SymbolType"),rSeriesDefaultsAndStyles.maSymbolTypeDefault);
725 if( rSeriesDefaultsAndStyles.maDataCaptionDefault.hasValue() )
726 xSeries->setPropertyValue(OUString("DataCaption"),rSeriesDefaultsAndStyles.maDataCaptionDefault);
728 if( rSeriesDefaultsAndStyles.maErrorIndicatorDefault.hasValue() )
729 xSeries->setPropertyValue(OUString("ErrorIndicator"),rSeriesDefaultsAndStyles.maErrorIndicatorDefault);
730 if( rSeriesDefaultsAndStyles.maErrorCategoryDefault.hasValue() )
731 xSeries->setPropertyValue(OUString("ErrorCategory"),rSeriesDefaultsAndStyles.maErrorCategoryDefault);
732 if( rSeriesDefaultsAndStyles.maConstantErrorLowDefault.hasValue() )
733 xSeries->setPropertyValue(OUString("ConstantErrorLow"),rSeriesDefaultsAndStyles.maConstantErrorLowDefault);
734 if( rSeriesDefaultsAndStyles.maConstantErrorHighDefault.hasValue() )
735 xSeries->setPropertyValue(OUString("ConstantErrorHigh"),rSeriesDefaultsAndStyles.maConstantErrorHighDefault);
736 if( rSeriesDefaultsAndStyles.maPercentageErrorDefault.hasValue() )
737 xSeries->setPropertyValue(OUString("PercentageError"),rSeriesDefaultsAndStyles.maPercentageErrorDefault);
738 if( rSeriesDefaultsAndStyles.maErrorMarginDefault.hasValue() )
739 xSeries->setPropertyValue(OUString("ErrorMargin"),rSeriesDefaultsAndStyles.maErrorMarginDefault);
741 if( rSeriesDefaultsAndStyles.maMeanValueDefault.hasValue() )
742 xSeries->setPropertyValue(OUString("MeanValue"),rSeriesDefaultsAndStyles.maMeanValueDefault);
743 if( rSeriesDefaultsAndStyles.maRegressionCurvesDefault.hasValue() )
744 xSeries->setPropertyValue(OUString("RegressionCurves"),rSeriesDefaultsAndStyles.maRegressionCurvesDefault);
746 catch( uno::Exception & )
748 //end of series reached
753 //static
754 void SchXMLSeries2Context::setStylesToSeries( SeriesDefaultsAndStyles& rSeriesDefaultsAndStyles
755 , const SvXMLStylesContext* pStylesCtxt
756 , const SvXMLStyleContext*& rpStyle
757 , OUString& rCurrStyleName
758 , SchXMLImportHelper& rImportHelper
759 , const SvXMLImport& rImport
760 , bool bIsStockChart
761 , tSchXMLLSequencesPerIndex & rInOutLSequencesPerIndex )
763 ::std::list< DataRowPointStyle >::iterator iStyle;
765 // iterate over series
766 for( iStyle = rSeriesDefaultsAndStyles.maSeriesStyleList.begin(); iStyle != rSeriesDefaultsAndStyles.maSeriesStyleList.end(); ++iStyle )
768 if( iStyle->meType == DataRowPointStyle::DATA_SERIES )
772 uno::Reference< beans::XPropertySet > xSeriesProp( iStyle->m_xOldAPISeries );
773 if( !xSeriesProp.is() )
774 continue;
776 if( iStyle->mnAttachedAxis != 1 )
778 xSeriesProp->setPropertyValue( OUString( "Axis" )
779 , uno::makeAny(chart::ChartAxisAssign::SECONDARY_Y) );
782 if( !(iStyle->msStyleName).isEmpty())
784 if( ! rCurrStyleName.equals( iStyle->msStyleName ))
786 rCurrStyleName = iStyle->msStyleName;
787 rpStyle = pStylesCtxt->FindStyleChildContext(
788 rImportHelper.GetChartFamilyID(), rCurrStyleName );
791 //set style to series
792 // note: SvXMLStyleContext::FillPropertySet is not const
793 XMLPropStyleContext * pPropStyleContext =
794 const_cast< XMLPropStyleContext * >(
795 dynamic_cast< const XMLPropStyleContext * >( rpStyle ));
796 if( pPropStyleContext )
798 // error bar style must be set before the other error
799 // bar properties (which may be alphabetically before
800 // this property)
801 bool bHasErrorBarRangesFromData = false;
803 const OUString aErrorBarStylePropName( "ErrorBarStyle");
804 uno::Any aErrorBarStyle(
805 SchXMLTools::getPropertyFromContext( aErrorBarStylePropName, pPropStyleContext, pStylesCtxt ));
806 if( aErrorBarStyle.hasValue())
808 xSeriesProp->setPropertyValue( aErrorBarStylePropName, aErrorBarStyle );
809 sal_Int32 eEBStyle = chart::ErrorBarStyle::NONE;
810 bHasErrorBarRangesFromData =
811 ( ( aErrorBarStyle >>= eEBStyle ) &&
812 eEBStyle == chart::ErrorBarStyle::FROM_DATA );
816 //don't set the style to the min max line series of a stock chart
817 //otherwise the min max line properties gets overwritten and the series becomes invisible typically
818 bool bIsMinMaxSeries = false;
819 if( bIsStockChart )
821 if( SchXMLSeriesHelper::isCandleStickSeries( iStyle->m_xSeries
822 , uno::Reference< frame::XModel >( rImportHelper.GetChartDocument(), uno::UNO_QUERY ) ) )
823 bIsMinMaxSeries = true;
825 if( !bIsMinMaxSeries )
827 pPropStyleContext->FillPropertySet( xSeriesProp );
828 if( iStyle->mbSymbolSizeForSeriesIsMissingInFile )
829 lcl_setSymbolSizeIfNeeded( xSeriesProp, rImport );
830 if( bHasErrorBarRangesFromData )
831 lcl_insertErrorBarLSequencesToMap( rInOutLSequencesPerIndex, xSeriesProp );
836 catch( const uno::Exception & rEx )
838 SAL_INFO("xmloff.chart", "Exception caught during setting styles to series: " << rEx.Message );
844 // static
845 void SchXMLSeries2Context::setStylesToStatisticsObjects( SeriesDefaultsAndStyles& rSeriesDefaultsAndStyles
846 , const SvXMLStylesContext* pStylesCtxt
847 , const SvXMLStyleContext*& rpStyle
848 , OUString& rCurrStyleName )
850 ::std::list< DataRowPointStyle >::iterator iStyle;
852 // iterate over regession etc
853 for( iStyle = rSeriesDefaultsAndStyles.maSeriesStyleList.begin(); iStyle != rSeriesDefaultsAndStyles.maSeriesStyleList.end(); ++iStyle )
855 if( iStyle->meType == DataRowPointStyle::REGRESSION ||
856 iStyle->meType == DataRowPointStyle::ERROR_INDICATOR ||
857 iStyle->meType == DataRowPointStyle::MEAN_VALUE )
859 if ( iStyle->meType == DataRowPointStyle::ERROR_INDICATOR )
861 uno::Reference< beans::XPropertySet > xNewSeriesProp(iStyle->m_xSeries,uno::UNO_QUERY);
863 if (iStyle->m_xErrorXProperties.is())
864 xNewSeriesProp->setPropertyValue("ErrorBarX",uno::makeAny(iStyle->m_xErrorXProperties));
866 if (iStyle->m_xErrorYProperties.is())
867 xNewSeriesProp->setPropertyValue("ErrorBarY",uno::makeAny(iStyle->m_xErrorYProperties));
872 uno::Reference< beans::XPropertySet > xSeriesProp( iStyle->m_xOldAPISeries );
873 if( !xSeriesProp.is() )
874 continue;
876 if( !(iStyle->msStyleName).isEmpty())
878 if( ! rCurrStyleName.equals( iStyle->msStyleName ))
880 rCurrStyleName = iStyle->msStyleName;
881 rpStyle = pStylesCtxt->FindStyleChildContext(
882 SchXMLImportHelper::GetChartFamilyID(), rCurrStyleName );
885 // note: SvXMLStyleContext::FillPropertySet is not const
886 XMLPropStyleContext * pPropStyleContext =
887 const_cast< XMLPropStyleContext * >(
888 dynamic_cast< const XMLPropStyleContext * >( rpStyle ));
889 if( pPropStyleContext )
891 Reference< beans::XPropertySet > xStatPropSet;
892 switch( iStyle->meType )
894 case DataRowPointStyle::MEAN_VALUE:
895 xSeriesProp->getPropertyValue(
896 OUString( "DataMeanValueProperties" )) >>= xStatPropSet;
897 break;
898 case DataRowPointStyle::REGRESSION:
899 xSeriesProp->getPropertyValue(
900 OUString( "DataRegressionProperties" )) >>= xStatPropSet;
901 break;
902 case DataRowPointStyle::ERROR_INDICATOR:
903 xSeriesProp->getPropertyValue(
904 OUString( "DataErrorProperties" )) >>= xStatPropSet;
905 break;
906 default:
907 break;
909 if( xStatPropSet.is())
910 pPropStyleContext->FillPropertySet( xStatPropSet );
914 // set equation properties at a regression curve
915 // note: this must be done after setting the regression
916 // properties at the old API, otherwise the curve itself does
917 // not exist here
918 if( iStyle->meType == DataRowPointStyle::REGRESSION && iStyle->m_xEquationProperties.is())
920 SAL_WARN_IF( !iStyle->m_xSeries.is(), "xmloff.chart", "iStyle->m_xSeries is NULL");
921 Reference< chart2::XRegressionCurve > xRegCurve( SchXMLTools::getRegressionCurve( iStyle->m_xSeries ));
922 if( xRegCurve.is())
923 xRegCurve->setEquationProperties( iStyle->m_xEquationProperties );
926 catch( const uno::Exception & rEx )
928 SAL_INFO("xmloff.chart", "Exception caught during setting styles to series: " << rEx.Message );
934 //static
935 void SchXMLSeries2Context::setStylesToDataPoints( SeriesDefaultsAndStyles& rSeriesDefaultsAndStyles
936 , const SvXMLStylesContext* pStylesCtxt
937 , const SvXMLStyleContext*& rpStyle
938 , OUString& rCurrStyleName
939 , SchXMLImportHelper& rImportHelper
940 , const SvXMLImport& rImport
941 , bool bIsStockChart, bool bIsDonutChart, bool bSwitchOffLinesForScatter )
943 ::std::list< DataRowPointStyle >::iterator iStyle;
944 for( iStyle = rSeriesDefaultsAndStyles.maSeriesStyleList.begin(); iStyle != rSeriesDefaultsAndStyles.maSeriesStyleList.end(); ++iStyle )
946 if( iStyle->meType != DataRowPointStyle::DATA_POINT )
947 continue;
949 if( iStyle->m_nPointIndex == -1 )
950 continue;
952 //ignore datapoint properties for stock charts
953 //... todo ...
954 if( bIsStockChart )
956 if( SchXMLSeriesHelper::isCandleStickSeries( iStyle->m_xSeries, uno::Reference< frame::XModel >( rImportHelper.GetChartDocument(), uno::UNO_QUERY ) ) )
957 continue;
960 // data point style
961 for( sal_Int32 i = 0; i < iStyle->m_nPointRepeat; i++ )
965 uno::Reference< beans::XPropertySet > xSeriesProp( iStyle->m_xOldAPISeries );
966 if(!xSeriesProp.is())
967 continue;
969 uno::Reference< beans::XPropertySet > xPointProp(
970 SchXMLSeriesHelper::createOldAPIDataPointPropertySet( iStyle->m_xSeries, iStyle->m_nPointIndex + i
971 , uno::Reference< frame::XModel >( rImportHelper.GetChartDocument(), uno::UNO_QUERY ) ) );
973 if( !xPointProp.is() )
974 continue;
976 if( bIsDonutChart )
978 //set special series styles for donut charts first
979 if( !rCurrStyleName.equals( iStyle->msSeriesStyleNameForDonuts ) )
981 rCurrStyleName = iStyle->msSeriesStyleNameForDonuts;
982 rpStyle = pStylesCtxt->FindStyleChildContext(
983 rImportHelper.GetChartFamilyID(), rCurrStyleName );
986 // note: SvXMLStyleContext::FillPropertySet is not const
987 XMLPropStyleContext * pPropStyleContext =
988 const_cast< XMLPropStyleContext * >(
989 dynamic_cast< const XMLPropStyleContext * >( rpStyle ));
990 if( pPropStyleContext )
991 pPropStyleContext->FillPropertySet( xPointProp );
996 //need to set this explicitly here for old files as the new api does not support this property fully anymore
997 if( bSwitchOffLinesForScatter )
998 xPointProp->setPropertyValue(OUString("Lines"),uno::makeAny(sal_False));
1000 catch( const uno::Exception & )
1004 if( !rCurrStyleName.equals( iStyle->msStyleName ) )
1006 rCurrStyleName = iStyle->msStyleName;
1007 rpStyle = pStylesCtxt->FindStyleChildContext(
1008 rImportHelper.GetChartFamilyID(), rCurrStyleName );
1011 // note: SvXMLStyleContext::FillPropertySet is not const
1012 XMLPropStyleContext * pPropStyleContext =
1013 const_cast< XMLPropStyleContext * >(
1014 dynamic_cast< const XMLPropStyleContext * >( rpStyle ));
1015 if( pPropStyleContext )
1017 pPropStyleContext->FillPropertySet( xPointProp );
1018 if( iStyle->mbSymbolSizeForSeriesIsMissingInFile )
1019 lcl_resetSymbolSizeForPointsIfNecessary( xPointProp, rImport, pPropStyleContext, pStylesCtxt );
1022 catch( const uno::Exception & rEx )
1024 SAL_INFO("xmloff.chart", "Exception caught during setting styles to data points: " << rEx.Message );
1027 } // styles iterator
1030 //static
1031 void SchXMLSeries2Context::switchSeriesLinesOff( ::std::list< DataRowPointStyle >& rSeriesStyleList )
1033 ::std::list< DataRowPointStyle >::iterator iStyle;
1034 // iterate over series
1036 for( iStyle = rSeriesStyleList.begin(); iStyle != rSeriesStyleList.end(); ++iStyle )
1038 if( iStyle->meType != DataRowPointStyle::DATA_SERIES )
1039 continue;
1043 uno::Reference< beans::XPropertySet > xSeries( iStyle->m_xOldAPISeries );
1044 if( !xSeries.is() )
1045 continue;
1047 xSeries->setPropertyValue(OUString("Lines"),uno::makeAny(sal_False));
1049 catch( uno::Exception & )
1051 //end of series reached
1056 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */