1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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 // ================================================================================
66 class SchXMLDomain2Context
: public SvXMLImportContext
69 ::std::vector
< OUString
> & mrAddresses
;
72 SchXMLDomain2Context( SvXMLImport
& rImport
,
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(
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
);
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
);
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;
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;
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() )
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) ));
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(
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
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()) )
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
);
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
);
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
),
261 mrStyleList( rStyleList
),
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
)
291 sal_Int16 nAttrCount
= xAttrList
.is()? xAttrList
->getLength(): 0;
292 const SvXMLTokenMap
& rAttrTokenMap
= mrImportHelper
.GetSeriesAttrTokenMap();
295 bool bHasRange
= false;
296 bool bHasLabelRange
= false;
298 for( sal_Int16 i
= 0; i
< nAttrCount
; i
++ )
300 OUString sAttrName
= xAttrList
->getNameByIndex( i
);
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
;
311 case XML_TOK_SERIES_LABEL_ADDRESS
:
312 m_aSeriesLabelRange
= aValue
;
313 bHasLabelRange
= true;
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
] );
328 case XML_TOK_SERIES_STYLE_NAME
:
329 msAutoStyleName
= aValue
;
331 case XML_TOK_SERIES_CHART_CLASS
:
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
;
349 if( mpAttachedAxis
->nAxisIndex
> 0 )
351 // secondary axis => property has to be set (primary is default)
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";
371 && mnSeriesIndex
== 0 )
373 maSeriesChartTypeName
= OUString( "com.sun.star.chart2.ColumnChartType" );
374 bIsCandleStick
= false;
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
385 mrImportHelper
.GetNewDataSeries( mxNewDoc
, nCoordinateSystemIndex
, maSeriesChartTypeName
, ! mrGlobalChartTypeUsedBySeries
));
386 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq( SchXMLTools::GetNewLabeledDataSequence(), uno::UNO_QUERY_THROW
);
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 ));
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
);
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
));
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();
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
& )
477 DomainInfo( const OUString
& rRole
, const OUString
& rRange
, sal_Int32 nIndex
)
478 : aRole(rRole
), aRange(rRange
), nIndexForLocalData(nIndex
)
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
526 aDomainInfos
.push_back( aDomainInfo
);
528 else if( bIsBubbleChart
)
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
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
);
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
);
568 //delete created series
569 SchXMLImportHelper::DeleteDataSeries(
570 m_xSeries
, Reference
< chart2::XChartDocument
>( GetImport().GetModel(), uno::UNO_QUERY
) );
575 if( !msAutoStyleName
.isEmpty() || mnAttachedAxis
!= 1 )
577 DataRowPointStyle
aStyle(
578 DataRowPointStyle::DATA_SERIES
,
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
) ));
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(
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
:
630 m_bHasDomainContext
= true;
631 pContext
= new SchXMLDomain2Context(
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
);
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
);
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
);
663 case XML_TOK_SERIES_DATA_POINT
:
664 pContext
= new SchXMLDataPointContext( GetImport(), rLocalName
,
665 mrStyleList
, m_xSeries
, mnDataPointIndex
, mbSymbolSizeIsMissingInFile
);
669 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
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
)
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
)
701 iStyle
->m_xOldAPISeries
= aSeriesMap
[iStyle
->m_xSeries
];
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
)
719 uno::Reference
< beans::XPropertySet
> xSeries( iStyle
->m_xOldAPISeries
);
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
754 void SchXMLSeries2Context::setStylesToSeries( SeriesDefaultsAndStyles
& rSeriesDefaultsAndStyles
755 , const SvXMLStylesContext
* pStylesCtxt
756 , const SvXMLStyleContext
*& rpStyle
757 , OUString
& rCurrStyleName
758 , SchXMLImportHelper
& rImportHelper
759 , const SvXMLImport
& rImport
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() )
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
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;
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
);
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() )
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
;
898 case DataRowPointStyle::REGRESSION
:
899 xSeriesProp
->getPropertyValue(
900 OUString( "DataRegressionProperties" )) >>= xStatPropSet
;
902 case DataRowPointStyle::ERROR_INDICATOR
:
903 xSeriesProp
->getPropertyValue(
904 OUString( "DataErrorProperties" )) >>= xStatPropSet
;
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
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
));
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
);
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
)
949 if( iStyle
->m_nPointIndex
== -1 )
952 //ignore datapoint properties for stock charts
956 if( SchXMLSeriesHelper::isCandleStickSeries( iStyle
->m_xSeries
, uno::Reference
< frame::XModel
>( rImportHelper
.GetChartDocument(), uno::UNO_QUERY
) ) )
961 for( sal_Int32 i
= 0; i
< iStyle
->m_nPointRepeat
; i
++ )
965 uno::Reference
< beans::XPropertySet
> xSeriesProp( iStyle
->m_xOldAPISeries
);
966 if(!xSeriesProp
.is())
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() )
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
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
)
1043 uno::Reference
< beans::XPropertySet
> xSeries( iStyle
->m_xOldAPISeries
);
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: */