LibreOffice Module xmloff (master) 1
SchXMLSeries2Context.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
24#include "SchXMLTools.hxx"
25
26#include <com/sun/star/chart2/XChartDocument.hpp>
27#include <com/sun/star/chart2/XRegressionCurve.hpp>
28#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
29#include <com/sun/star/chart2/data/XDataSink.hpp>
30#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
31#include <com/sun/star/chart2/RelativePosition.hpp>
32
33#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
34#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
35#include <com/sun/star/chart2/DataPointCustomLabelField.hpp>
36
37#include <com/sun/star/chart/ChartAxisAssign.hpp>
38#include <com/sun/star/chart/ChartSymbolType.hpp>
39#include <com/sun/star/chart/ChartDataCaption.hpp>
40#include <com/sun/star/chart/ErrorBarStyle.hpp>
41#include <com/sun/star/chart/XChartDocument.hpp>
42#include <com/sun/star/lang/XMultiServiceFactory.hpp>
43#include <com/sun/star/chart/ChartLegendPosition.hpp>
44#include <com/sun/star/embed/Aspects.hpp>
45#include <com/sun/star/embed/XVisualObject.hpp>
46
48
49#include <sal/log.hxx>
50#include <utility>
52#include <xmloff/xmlimp.hxx>
55#include <SchXMLImport.hxx>
56#include <xmloff/prstylei.hxx>
58
59#include <algorithm> // std::find_if
60
61using namespace ::com::sun::star;
62using namespace ::xmloff::token;
63
64using ::com::sun::star::uno::Reference;
65using ::com::sun::star::uno::Sequence;
66
67namespace
68{
69
70class SchXMLDomain2Context : public SvXMLImportContext
71{
72private:
73 ::std::vector< OUString > & mrAddresses;
74
75public:
76 SchXMLDomain2Context( SvXMLImport& rImport,
77 ::std::vector< OUString > & rAddresses );
78 virtual void SAL_CALL startFastElement(
79 sal_Int32 nElement,
80 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
81};
82
83SchXMLDomain2Context::SchXMLDomain2Context(
84 SvXMLImport& rImport,
85 ::std::vector< OUString > & rAddresses ) :
86 SvXMLImportContext( rImport ),
87 mrAddresses( rAddresses )
88{
89}
90
91void SchXMLDomain2Context::startFastElement(
92 sal_Int32 /*nElement*/,
93 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
94{
95 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
96 {
97 if (aIter.getToken() == XML_ELEMENT(TABLE, XML_CELL_RANGE_ADDRESS) )
98 mrAddresses.push_back( aIter.toString() );
99 else
100 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
101 }
102}
103
104void lcl_setAutomaticSymbolSize( const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp, const SvXMLImport& rImport )
105{
106 awt::Size aSymbolSize(140,140);//old default for standard sized charts 7cm height
107
108 uno::Reference< chart::XChartDocument > xChartDoc( rImport.GetModel(), uno::UNO_QUERY );
109 if( xChartDoc.is() )
110 {
111 double fScale = 1;
112 uno::Reference< beans::XPropertySet > xLegendProp( xChartDoc->getLegend(), uno::UNO_QUERY );
113 chart::ChartLegendPosition aLegendPosition = chart::ChartLegendPosition_NONE;
114 if( xLegendProp.is() && (xLegendProp->getPropertyValue("Alignment") >>= aLegendPosition)
115 && chart::ChartLegendPosition_NONE != aLegendPosition )
116 {
117
118 double fFontHeight = 6.0;
119 if( xLegendProp->getPropertyValue("CharHeight") >>= fFontHeight )
120 fScale = 0.75*fFontHeight/6.0;
121 }
122 else
123 {
124 uno::Reference< embed::XVisualObject > xVisualObject( rImport.GetModel(), uno::UNO_QUERY );
125 if( xVisualObject.is() )
126 {
127 awt::Size aPageSize( xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ) );
128 fScale = aPageSize.Height/7000.0;
129 }
130 }
131 if( fScale>0 )
132 {
133 aSymbolSize.Height = static_cast<sal_Int32>( fScale * aSymbolSize.Height );
134 aSymbolSize.Width = aSymbolSize.Height;
135 }
136 }
137 xSeriesOrPointProp->setPropertyValue("SymbolSize",uno::Any( aSymbolSize ));
138}
139
140void lcl_setSymbolSizeIfNeeded( const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp, const SvXMLImport& rImport )
141{
142 if( !xSeriesOrPointProp.is() )
143 return;
144
145 sal_Int32 nSymbolType = chart::ChartSymbolType::NONE;
146 if( !(xSeriesOrPointProp.is() && ( xSeriesOrPointProp->getPropertyValue("SymbolType") >>= nSymbolType)) )
147 return;
148
149 if(chart::ChartSymbolType::NONE!=nSymbolType)
150 {
151 if( chart::ChartSymbolType::BITMAPURL==nSymbolType )
152 {
153 //set special size for graphics to indicate to use the bitmap size itself
154 xSeriesOrPointProp->setPropertyValue("SymbolSize",uno::Any( awt::Size(-1,-1) ));
155 }
156 else
157 {
158 lcl_setAutomaticSymbolSize( xSeriesOrPointProp, rImport );
159 }
160 }
161}
162
163void lcl_resetSymbolSizeForPointsIfNecessary( const uno::Reference< beans::XPropertySet >& xPointProp, const SvXMLImport& rImport
164 , const XMLPropStyleContext * pPropStyleContext, const SvXMLStylesContext* pStylesCtxt )
165{
166 uno::Any aASymbolSize( SchXMLTools::getPropertyFromContext( u"SymbolSize", pPropStyleContext, pStylesCtxt ) );
167 if( !aASymbolSize.hasValue() )
168 lcl_setSymbolSizeIfNeeded( xPointProp, rImport );
169}
170
171void lcl_setLinkNumberFormatToSourceIfNeeded( const uno::Reference< beans::XPropertySet >& xPointProp
172 , const XMLPropStyleContext* pPropStyleContext, const SvXMLStylesContext* pStylesCtxt )
173{
174 uno::Any aAny( SchXMLTools::getPropertyFromContext(u"LinkNumberFormatToSource", pPropStyleContext, pStylesCtxt) );
175 if( aAny.hasValue() )
176 return;
177
178 if( !xPointProp.is() )
179 return;
180
181 bool bLinkToSource = false;
182 if( xPointProp.is() && (xPointProp->getPropertyValue("LinkNumberFormatToSource") >>= bLinkToSource) )
183 {
184 if( bLinkToSource )
185 {
186 xPointProp->setPropertyValue("LinkNumberFormatToSource", uno::Any(false));
187 }
188 }
189}
190
191void lcl_insertErrorBarLSequencesToMap(
192 tSchXMLLSequencesPerIndex & rInOutMap,
193 const uno::Reference< beans::XPropertySet > & xSeriesProp )
194{
195 Reference< chart2::data::XDataSource > xErrorBarSource;
196 if( ( xSeriesProp->getPropertyValue( "ErrorBarY" ) >>= xErrorBarSource ) &&
197 xErrorBarSource.is() )
198 {
199 const Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSequences(
200 xErrorBarSource->getDataSequences());
201 for( const auto& rLSequence : aLSequences )
202 {
203 // use "0" as data index. This is ok, as it is not used for error bars
204 rInOutMap.emplace(
206 }
207 }
208}
209
210Reference< chart2::data::XLabeledDataSequence2 > lcl_createAndAddSequenceToSeries( const OUString& rRole
211 , const OUString& rRange
212 , const Reference< chart2::XChartDocument >& xChartDoc
213 , const Reference< chart2::XDataSeries >& xSeries )
214{
215 Reference< chart2::data::XLabeledDataSequence2 > xLabeledSeq;
216
217 Reference< chart2::data::XDataSource > xSeriesSource( xSeries,uno::UNO_QUERY );
218 Reference< chart2::data::XDataSink > xSeriesSink( xSeries, uno::UNO_QUERY );
219
220 if( !(!rRange.isEmpty() && xChartDoc.is() && xSeriesSource.is() && xSeriesSink.is()) )
221 return xLabeledSeq;
222
223 // create a new sequence
225
226 // set values at the new sequence
227 Reference< chart2::data::XDataSequence > xSeq = SchXMLTools::CreateDataSequence( rRange, xChartDoc );
228 Reference< beans::XPropertySet > xSeqProp( xSeq, uno::UNO_QUERY );
229 if( xSeqProp.is())
230 xSeqProp->setPropertyValue("Role", uno::Any( rRole));
231 xLabeledSeq->setValues( xSeq );
232
233 // add new sequence to data series / push to front to have the correct sequence order if charttype is changed afterwards
234 const Sequence< Reference< chart2::data::XLabeledDataSequence > > aOldSeq( xSeriesSource->getDataSequences());
235 sal_Int32 nOldCount = aOldSeq.getLength();
236 Sequence< Reference< chart2::data::XLabeledDataSequence > > aNewSeq( nOldCount + 1 );
237 auto pNewSeq = aNewSeq.getArray();
238 pNewSeq[0].set(xLabeledSeq, uno::UNO_QUERY_THROW);
239 std::copy(aOldSeq.begin(), aOldSeq.end(), std::next(pNewSeq));
240 xSeriesSink->setData( aNewSeq );
241
242 return xLabeledSeq;
243}
244
245XMLPropStyleContext* lcl_GetStylePropContext(
246 const SvXMLStylesContext* pStylesCtxt,
247 const SvXMLStyleContext*& rpStyle,
248 OUString const & rStyleName )
249{
250 rpStyle = pStylesCtxt->FindStyleChildContext( SchXMLImportHelper::GetChartFamilyID(), rStyleName );
251 XMLPropStyleContext* pPropStyleContext =
252 const_cast< XMLPropStyleContext* >(dynamic_cast< const XMLPropStyleContext* >( rpStyle ));
253 return pPropStyleContext;
254}
255
256} // anonymous namespace
257
259 SchXMLImportHelper& rImpHelper,
260 SvXMLImport& rImport,
261 const Reference< chart2::XChartDocument > & xNewDoc,
262 std::vector< SchXMLAxis >& rAxes,
263 ::std::vector< DataRowPointStyle >& rStyleVector,
264 ::std::vector< RegressionStyle >& rRegressionStyleVector,
265 sal_Int32 nSeriesIndex,
266 bool bStockHasVolume,
267 GlobalSeriesImportInfo& rGlobalSeriesImportInfo,
268 const OUString & aGlobalChartTypeName,
269 tSchXMLLSequencesPerIndex & rLSequencesPerIndex,
270 bool& rGlobalChartTypeUsedBySeries,
271 const awt::Size & rChartSize ) :
272 SvXMLImportContext( rImport ),
273 mrImportHelper( rImpHelper ),
274 mxNewDoc( xNewDoc ),
275 mrAxes( rAxes ),
276 mrStyleVector( rStyleVector ),
277 mrRegressionStyleVector( rRegressionStyleVector ),
278 mnSeriesIndex( nSeriesIndex ),
279 mnDataPointIndex( 0 ),
280 m_bStockHasVolume( bStockHasVolume ),
281 m_rGlobalSeriesImportInfo(rGlobalSeriesImportInfo),
282 mpAttachedAxis( nullptr ),
283 mnAttachedAxis( 0 ),
284 maGlobalChartTypeName( aGlobalChartTypeName ),
285 maSeriesChartTypeName( aGlobalChartTypeName ),
286 m_bHasDomainContext(false),
287 mrLSequencesPerIndex( rLSequencesPerIndex ),
288 mrGlobalChartTypeUsedBySeries( rGlobalChartTypeUsedBySeries ),
289 mbSymbolSizeIsMissingInFile(false),
290 maChartSize( rChartSize ),
291 // A series manages the DataRowPointStyle-struct of a data-label child element.
292 mDataLabel(DataRowPointStyle::DATA_LABEL_SERIES, OUString{})
293{
294 if( aGlobalChartTypeName == "com.sun.star.chart2.DonutChartType" )
295 {
296 maSeriesChartTypeName = "com.sun.star.chart2.PieChartType";
298 }
299}
300
302{
303 SAL_WARN_IF( !maPostponedSequences.empty(), "xmloff.chart", "maPostponedSequences is NULL");
304}
305
306void SchXMLSeries2Context::startFastElement (sal_Int32 /*Element*/,
307 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
308{
309 // parse attributes
310 mnAttachedAxis = 1;
311
312 bool bHasRange = false;
313 OUString aSeriesLabelRange;
314 OUString aSeriesLabelString;
315 bool bHideLegend = false;
316
317 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
318 {
319 OUString aValue = aIter.toString();
320 switch(aIter.getToken())
321 {
323 m_aSeriesRange = aValue;
324 bHasRange = true;
325 break;
327 aSeriesLabelRange = aValue;
328 break;
329 case XML_ELEMENT(LO_EXT, XML_LABEL_STRING):
330 aSeriesLabelString = aValue;
331 break;
333 {
334 sal_Int32 nNumOfAxes = mrAxes.size();
335 for( sal_Int32 nCurrent = 0; nCurrent < nNumOfAxes; nCurrent++ )
336 {
337 if( aValue == mrAxes[ nCurrent ].aName &&
338 mrAxes[ nCurrent ].eDimension == SCH_XML_AXIS_Y )
339 {
340 mpAttachedAxis = &( mrAxes[ nCurrent ] );
341 }
342 }
343 }
344 break;
346 msAutoStyleName = aValue;
347 break;
349 {
350 OUString aClassName;
351 sal_uInt16 nClassPrefix =
352 GetImport().GetNamespaceMap().GetKeyByAttrValueQName(
353 aValue, &aClassName );
354 if( XML_NAMESPACE_CHART == nClassPrefix )
355 maSeriesChartTypeName = SchXMLTools::GetChartTypeByClassName( aClassName, false /* bUseOldNames */ );
356
357 if( maSeriesChartTypeName.isEmpty())
358 maSeriesChartTypeName = aClassName;
359 }
360 break;
361 case XML_ELEMENT(LO_EXT, XML_HIDE_LEGEND):
362 bHideLegend = aValue.toBoolean();
363 break;
364 default:
365 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
366 }
367 }
368
369 if( mpAttachedAxis )
370 {
371 if( mpAttachedAxis->nAxisIndex > 0 )
372 {
373 // secondary axis => property has to be set (primary is default)
374 mnAttachedAxis = 2;
375 }
376 }
377
378 try
379 {
380 SAL_WARN_IF( !mxNewDoc.is(), "xmloff.chart", "mxNewDoc is NULL");
383
384 bool bIsCandleStick = maGlobalChartTypeName == "com.sun.star.chart2.CandleStickChartType";
385 if( !maSeriesChartTypeName.isEmpty() )
386 {
387 bIsCandleStick = maSeriesChartTypeName == "com.sun.star.chart2.CandleStickChartType";
388 }
389 else
390 {
391 if( bIsCandleStick
393 && mnSeriesIndex == 0 )
394 {
395 maSeriesChartTypeName = "com.sun.star.chart2.ColumnChartType";
396 bIsCandleStick = false;
397 }
398 else
399 {
401 }
402 }
405 sal_Int32 const nCoordinateSystemIndex = 0;//so far we can only import one coordinate system
406 m_xSeries.set(
408 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( SchXMLTools::GetNewLabeledDataSequence(), uno::UNO_QUERY_THROW );
409
410 Reference< beans::XPropertySet > xSeriesProp( m_xSeries, uno::UNO_QUERY );
411 if (xSeriesProp.is())
412 {
413 if (bHideLegend)
414 xSeriesProp->setPropertyValue("ShowLegendEntry", uno::Any(false));
415
416 if( bIsCandleStick )
417 {
418 // set default color for range-line to black (before applying styles)
419 xSeriesProp->setPropertyValue("Color",
420 uno::Any( sal_Int32( 0x000000 ))); // black
421 }
422 else if ( maSeriesChartTypeName == "com.sun.star.chart2.PieChartType" )
423 {
424 //@todo: this property should be saved
425 xSeriesProp->setPropertyValue("VaryColorsByPoint",
426 uno::Any( true ));
427 }
428
429 }
430
431 Reference<chart2::data::XDataProvider> xDataProvider(mxNewDoc->getDataProvider());
432 Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(xDataProvider, uno::UNO_QUERY);
433
434 Reference<chart2::data::XDataSequence> xSequenceValues;
435
436 // values
437 if (xPivotTableDataProvider.is()) // is pivot chart
438 {
439 xSequenceValues.set(xPivotTableDataProvider->createDataSequenceOfValuesByIndex(mnSeriesIndex));
440 }
441 else
442 {
443 if (bHasRange && !m_aSeriesRange.isEmpty())
445 }
446
447 Reference<beans::XPropertySet> xSeqProp(xSequenceValues, uno::UNO_QUERY);
448 if (xSeqProp.is())
449 {
450 OUString aMainRole("values-y");
451 if (maSeriesChartTypeName == "com.sun.star.chart2.BubbleChartType")
452 aMainRole = "values-size";
453 xSeqProp->setPropertyValue("Role", uno::Any(aMainRole));
454 }
455 xLabeledSeq->setValues(xSequenceValues);
456
457 // register for setting local data if external data provider is not present
458 maPostponedSequences.emplace(
460
461 // label
462 Reference<chart2::data::XDataSequence> xSequenceLabel;
463
464 if (xPivotTableDataProvider.is())
465 {
466 xSequenceLabel.set(xPivotTableDataProvider->createDataSequenceOfLabelsByIndex(mnSeriesIndex));
467 }
468 else
469 {
470 if (!aSeriesLabelRange.isEmpty())
471 {
472 xSequenceLabel.set(SchXMLTools::CreateDataSequence(aSeriesLabelRange, mxNewDoc));
473 }
474 else if (!aSeriesLabelString.isEmpty())
475 {
476 xSequenceLabel.set(SchXMLTools::CreateDataSequenceWithoutConvert(aSeriesLabelString, mxNewDoc));
477 }
478 }
479
480 //Labels should always include hidden cells
481 Reference<beans::XPropertySet> xSeqLabelProp(xSequenceLabel, uno::UNO_QUERY);
482 if (xSeqLabelProp.is() && xSeqLabelProp->getPropertySetInfo()->hasPropertyByName("IncludeHiddenCells"))
483 {
484 xSeqLabelProp->setPropertyValue( "IncludeHiddenCells", uno::Any(true));
485 }
486
487 xLabeledSeq->setLabel(xSequenceLabel);
488
489 // Note: Even if we have no label, we have to register the label
490 // for creation, because internal data always has labels. If
491 // they don't exist in the original, auto-generated labels are
492 // used for the internal data.
493 maPostponedSequences.emplace(
495
496 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( &xLabeledSeq, 1 );
497 Reference< chart2::data::XDataSink > xSink( m_xSeries, uno::UNO_QUERY_THROW );
498 xSink->setData( aSeq );
499 }
500 catch( const uno::Exception &)
501 {
502 DBG_UNHANDLED_EXCEPTION("xmloff.chart");
503 }
504
505 //init mbSymbolSizeIsMissingInFile:
506 try
507 {
508 if( !msAutoStyleName.isEmpty() )
509 {
511 if( pStylesCtxt )
512 {
513 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
515
516 const XMLPropStyleContext* pPropStyleContext = dynamic_cast< const XMLPropStyleContext * >( pStyle );
517
518 uno::Any aASymbolSize( SchXMLTools::getPropertyFromContext( u"SymbolSize"
519 , pPropStyleContext, pStylesCtxt ) );
520 mbSymbolSizeIsMissingInFile = !aASymbolSize.hasValue();
521 }
522 }
523 }
524 catch( const uno::Exception & )
525 {
526 }
527}
528
529namespace {
530
531struct DomainInfo
532{
533 DomainInfo( OUString _aRole, OUString _aRange, sal_Int32 nIndex )
534 : aRole(std::move(_aRole)), aRange(std::move(_aRange)), nIndexForLocalData(nIndex)
535 {}
536
537 OUString aRole;
538 OUString aRange;
539 sal_Int32 nIndexForLocalData;
540};
541
542}
543
545{
546 // special handling for different chart types. This is necessary as the
547 // roles are not yet saved in the file format
548 sal_Int32 nDomainCount = maDomainAddresses.size();
549 bool bIsScatterChart = maSeriesChartTypeName == "com.sun.star.chart2.ScatterChartType";
550 bool bIsBubbleChart = maSeriesChartTypeName == "com.sun.star.chart2.BubbleChartType";
551 bool bDeleteSeries = false;
552 std::vector< DomainInfo > aDomainInfos;
553
554 //different handling for different chart types necessary
555 if( bIsScatterChart || ( nDomainCount==1 && !bIsBubbleChart ) )
556 {
558 bool bCreateXValues = true;
559 if( !maDomainAddresses.empty() )
560 {
562 {
565 }
566 aDomainInfo.aRange = maDomainAddresses.front();
567 aDomainInfo.nIndexForLocalData = m_rGlobalSeriesImportInfo.nCurrentDataIndex;
569 }
571 {
572 if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( GetImport().GetModel() ) ) //wrong old chart files:
573 {
574 //for xy charts the first series needs to have a domain
575 //if this by error iss not the case the first series is taken s x values
576 //needed for wrong files created while having an addin (e.g. BoxPlot)
579 bDeleteSeries = true;
580 bCreateXValues = false;//they will be created for the next series
581 }
582 }
583 if( bCreateXValues )
584 aDomainInfos.push_back( aDomainInfo );
585 }
586 else if( bIsBubbleChart )
587 {
588 if( nDomainCount>1 )
589 {
590 DomainInfo aDomainInfo( "values-x", maDomainAddresses[1], m_rGlobalSeriesImportInfo.nCurrentDataIndex ) ;
592 {
593 //for bubble chart the second domain contains the x values which should become an index smaller than y values for own data table
594 //->so second first
597 }
598 aDomainInfos.push_back( aDomainInfo );
600 }
602 {
604 aDomainInfos.push_back( aDomainInfo );
605 }
606 if( nDomainCount>0)
607 {
608 DomainInfo aDomainInfo( "values-y", maDomainAddresses.front(), m_rGlobalSeriesImportInfo.nCurrentDataIndex ) ;
610 {
613 }
614 aDomainInfos.push_back( aDomainInfo );
616 }
618 {
620 aDomainInfos.push_back( aDomainInfo );
621 }
622 }
623
624 if( bDeleteSeries )
625 {
626 //delete created series
628 m_xSeries, Reference< chart2::XChartDocument >( GetImport().GetModel(), uno::UNO_QUERY ) );
629 }
630 else
631 {
632 //add style
633 if( !msAutoStyleName.isEmpty() || mnAttachedAxis != 1 )
634 {
635 DataRowPointStyle aStyle(
637 m_xSeries,
638 -1, 1,
641 mrStyleVector.push_back( aStyle );
642 }
643 // And styles for a data-label child element too. In contrast to data-labels as child of data points,
644 // an information about absolute position is useless here. We need only style information.
645 if (!mDataLabel.msStyleName.isEmpty())
646 {
649 mDataLabel.mnAttachedAxis = mnAttachedAxis; // not needed, but be consistent with its parent
650 mrStyleVector.push_back(mDataLabel);
651 }
652 }
653
654 for( std::vector< DomainInfo >::reverse_iterator aIt( aDomainInfos.rbegin() ); aIt!= aDomainInfos.rend(); ++aIt )
655 {
656 DomainInfo aDomainInfo( *aIt );
657 Reference< chart2::data::XLabeledDataSequence2 > xLabeledSeq =
658 lcl_createAndAddSequenceToSeries( aDomainInfo.aRole, aDomainInfo.aRange, mxNewDoc, m_xSeries );
659 if( xLabeledSeq.is() )
660 {
661 // register for setting local data if external data provider is not present
662 mrLSequencesPerIndex.emplace(
663 tSchXMLIndexWithPart( aDomainInfo.nIndexForLocalData, SCH_XML_PART_VALUES ),
664 Reference< chart2::data::XLabeledDataSequence >(xLabeledSeq, uno::UNO_QUERY_THROW) );
665 }
666 }
667
668 if( !bDeleteSeries )
669 {
670 for (auto const& postponedSequence : maPostponedSequences)
671 {
672 sal_Int32 nNewIndex = postponedSequence.first.first + nDomainCount;
673 mrLSequencesPerIndex.emplace( tSchXMLIndexWithPart( nNewIndex, postponedSequence.first.second ), postponedSequence.second );
674 }
676 }
677 maPostponedSequences.clear();
678}
679
680css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLSeries2Context::createFastChildContext(
681 sal_Int32 nElement,
682 const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
683{
684 SvXMLImportContext* pContext = nullptr;
685
686 switch(nElement)
687 {
689 if( m_xSeries.is())
690 {
691 m_bHasDomainContext = true;
692 pContext = new SchXMLDomain2Context(
694 }
695 break;
696
698 pContext = new SchXMLStatisticsObjectContext(
704 break;
710 break;
712 pContext = new SchXMLStatisticsObjectContext(
718 break;
719
721 pContext = new SchXMLDataPointContext( GetImport(),
723 break;
725 // CustomLabels are useless for a data label element as child of a series, because it serves as default
726 // for all data labels. But the ctor expects it, so use that of the mDataLabel struct as ersatz.
728 mDataLabel);
729 break;
730
731 case XML_ELEMENT(LO_EXT, XML_PROPERTY_MAPPING):
732 pContext = new SchXMLPropertyMappingContext(
733 GetImport(),
735 break;
736 default:
737 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
738 }
739
740 return pContext;
741}
742
743//static
745 , const uno::Reference< frame::XModel >& xChartModel )
746{
747 // iterate over series first and remind propertysets in map
748 // new api <-> old api wrapper
749 ::std::map< Reference< chart2::XDataSeries >, Reference< beans::XPropertySet > > aSeriesMap;
750 for (auto & seriesStyle : rSeriesDefaultsAndStyles.maSeriesStyleVector)
751 {
752 if( seriesStyle.meType != DataRowPointStyle::DATA_SERIES )
753 continue;
754
755 if( !seriesStyle.m_xOldAPISeries.is() )
756 seriesStyle.m_xOldAPISeries = SchXMLSeriesHelper::createOldAPISeriesPropertySet( seriesStyle.m_xSeries, xChartModel );
757
758 aSeriesMap[seriesStyle.m_xSeries] = seriesStyle.m_xOldAPISeries;
759
760 }
761
762 //initialize m_xOldAPISeries for all other styles also
763 for (auto & seriesStyle : rSeriesDefaultsAndStyles.maSeriesStyleVector)
764 {
765 if( seriesStyle.meType == DataRowPointStyle::DATA_SERIES )
766 continue;
767 seriesStyle.m_xOldAPISeries = aSeriesMap[seriesStyle.m_xSeries];
768 }
769}
770
771//static
773{
774 // iterate over series
775 // call initSeriesPropertySets first
776
777 for (const auto & seriesStyle : rSeriesDefaultsAndStyles.maSeriesStyleVector)
778 {
779 if( seriesStyle.meType != DataRowPointStyle::DATA_SERIES )
780 continue;
781
782 try
783 {
784 uno::Reference< beans::XPropertySet > xSeries( seriesStyle.m_xOldAPISeries );
785 if( !xSeries.is() )
786 continue;
787
788 if( rSeriesDefaultsAndStyles.maSymbolTypeDefault.hasValue() )
789 xSeries->setPropertyValue("SymbolType",rSeriesDefaultsAndStyles.maSymbolTypeDefault);
790 if( rSeriesDefaultsAndStyles.maDataCaptionDefault.hasValue() )
791 xSeries->setPropertyValue("DataCaption",rSeriesDefaultsAndStyles.maDataCaptionDefault);
792
793 if( rSeriesDefaultsAndStyles.maErrorIndicatorDefault.hasValue() )
794 xSeries->setPropertyValue("ErrorIndicator",rSeriesDefaultsAndStyles.maErrorIndicatorDefault);
795 if( rSeriesDefaultsAndStyles.maErrorCategoryDefault.hasValue() )
796 xSeries->setPropertyValue("ErrorCategory",rSeriesDefaultsAndStyles.maErrorCategoryDefault);
797 if( rSeriesDefaultsAndStyles.maConstantErrorLowDefault.hasValue() )
798 xSeries->setPropertyValue("ConstantErrorLow",rSeriesDefaultsAndStyles.maConstantErrorLowDefault);
799 if( rSeriesDefaultsAndStyles.maConstantErrorHighDefault.hasValue() )
800 xSeries->setPropertyValue("ConstantErrorHigh",rSeriesDefaultsAndStyles.maConstantErrorHighDefault);
801 if( rSeriesDefaultsAndStyles.maPercentageErrorDefault.hasValue() )
802 xSeries->setPropertyValue("PercentageError",rSeriesDefaultsAndStyles.maPercentageErrorDefault);
803 if( rSeriesDefaultsAndStyles.maErrorMarginDefault.hasValue() )
804 xSeries->setPropertyValue("ErrorMargin",rSeriesDefaultsAndStyles.maErrorMarginDefault);
805
806 if( rSeriesDefaultsAndStyles.maMeanValueDefault.hasValue() )
807 xSeries->setPropertyValue("MeanValue",rSeriesDefaultsAndStyles.maMeanValueDefault);
808 if( rSeriesDefaultsAndStyles.maRegressionCurvesDefault.hasValue() )
809 xSeries->setPropertyValue("RegressionCurves",rSeriesDefaultsAndStyles.maRegressionCurvesDefault);
810 }
811 catch( uno::Exception & )
812 {
813 //end of series reached
814 }
815 }
816}
817
818// ODF has the line and fill properties in a <style:style> element, which is referenced by the
819// <chart:data-label> element. But LibreOffice has them as special label properties of the series
820// or point respectively. The following array maps the API name of the ODF property to the name of
821// the internal property. Those are of kind "LabelFoo".
822// The array is used in methods setStylesToSeries and setStylesToDataPoints.
823const std::pair<OUString, OUString> aApiToLabelFooPairs[]
824 = { { "LineStyle", "LabelBorderStyle" },
825 { "LineWidth", "LabelBorderWidth" },
826 { "LineColor", "LabelBorderColor" },
827 // The name "LabelBorderDash" is defined, but the associated API name "LineDash" belongs to
828 // the <draw:stroke-dash> element and is not used directly as line property.
829 //{"LineDash", "LabelBorderDash"},
830 { "LineDashName", "LabelBorderDashName" },
831 { "LineTransparence", "LabelBorderTransparency" },
832 { "FillStyle", "LabelFillStyle" },
833 { "FillBackground", "LabelFillBackground" },
834 { "FillHatchName", "LabelFillHatchName" },
835 { "FillColor", "LabelFillColor" } };
836
837
838//static
840 , const SvXMLStylesContext* pStylesCtxt
841 , const SvXMLStyleContext*& rpStyle
842 , OUString& rCurrStyleName
843 , const SchXMLImportHelper& rImportHelper
844 , const SvXMLImport& rImport
845 , bool bIsStockChart
846 , tSchXMLLSequencesPerIndex & rInOutLSequencesPerIndex )
847{
848 // iterate over series
849 for (const auto & seriesStyle : rSeriesDefaultsAndStyles.maSeriesStyleVector)
850 {
851 if (seriesStyle.meType != DataRowPointStyle::DATA_SERIES)
852 continue;
853 try
854 {
855 uno::Reference< beans::XPropertySet > xSeriesProp( seriesStyle.m_xOldAPISeries );
856 if( !xSeriesProp.is() )
857 continue;
858
859 if( seriesStyle.mnAttachedAxis != 1 )
860 {
861 xSeriesProp->setPropertyValue("Axis"
862 , uno::Any(chart::ChartAxisAssign::SECONDARY_Y) );
863 }
864
865 if( seriesStyle.msStyleName.isEmpty())
866 continue;
867
868 if( rCurrStyleName != seriesStyle.msStyleName )
869 {
870 rCurrStyleName = seriesStyle.msStyleName;
871 rpStyle = pStylesCtxt->FindStyleChildContext(
872 SchXMLImportHelper::GetChartFamilyID(), rCurrStyleName );
873 }
874
875 //set style to series
876 // note: SvXMLStyleContext::FillPropertySet is not const
877 XMLPropStyleContext * pPropStyleContext =
878 const_cast< XMLPropStyleContext * >(
879 dynamic_cast< const XMLPropStyleContext * >( rpStyle ));
880
881 if (!pPropStyleContext)
882 continue;
883
884 // error bar style must be set before the other error
885 // bar properties (which may be alphabetically before
886 // this property)
887 bool bHasErrorBarRangesFromData = false;
888 {
889 static const OUStringLiteral aErrorBarStylePropName( u"ErrorBarStyle");
890 uno::Any aErrorBarStyle(
891 SchXMLTools::getPropertyFromContext( aErrorBarStylePropName, pPropStyleContext, pStylesCtxt ));
892 if( aErrorBarStyle.hasValue())
893 {
894 xSeriesProp->setPropertyValue( aErrorBarStylePropName, aErrorBarStyle );
895 sal_Int32 eEBStyle = chart::ErrorBarStyle::NONE;
896 bHasErrorBarRangesFromData =
897 ( ( aErrorBarStyle >>= eEBStyle ) &&
898 eEBStyle == chart::ErrorBarStyle::FROM_DATA );
899 }
900 }
901
902 //don't set the style to the min max line series of a stock chart
903 //otherwise the min max line properties gets overwritten and the series becomes invisible typically
904 if (bIsStockChart)
905 {
907 seriesStyle.m_xSeries,
908 rImportHelper.GetChartDocument()))
909 continue;
910 }
911
912 // Has the series a data-label child element?
913 auto pItLabel
914 = std::find_if(rSeriesDefaultsAndStyles.maSeriesStyleVector.begin(),
915 rSeriesDefaultsAndStyles.maSeriesStyleVector.end(),
916 [&seriesStyle](const DataRowPointStyle& rStyle) {
917 return rStyle.meType == DataRowPointStyle::DATA_LABEL_SERIES
918 && rStyle.msStyleNameOfParent == seriesStyle.msStyleName;
919 });
920 if (pItLabel != rSeriesDefaultsAndStyles.maSeriesStyleVector.end())
921 {
922 // Bring the information from the data-label to the series
923 const SvXMLStyleContext* pLabelStyleContext(pStylesCtxt->FindStyleChildContext(
924 SchXMLImportHelper::GetChartFamilyID(), (*pItLabel).msStyleName));
925 // note: SvXMLStyleContext::FillPropertySet is not const
926 XMLPropStyleContext* pLabelPropStyleContext = const_cast<XMLPropStyleContext*>(
927 dynamic_cast<const XMLPropStyleContext*>(pLabelStyleContext));
928 if (pLabelPropStyleContext)
929 {
930 // Test each to be mapped property whether the data-label has a value for it.
931 // If found, set it at series.
932 uno::Reference<beans::XPropertySetInfo> xSeriesPropInfo(
933 xSeriesProp->getPropertySetInfo());
934 for (const auto& rPropPair : aApiToLabelFooPairs)
935 {
937 rPropPair.first, pLabelPropStyleContext, pStylesCtxt));
938 if (aPropValue.hasValue()
939 && xSeriesPropInfo->hasPropertyByName(rPropPair.second))
940 xSeriesProp->setPropertyValue(rPropPair.second, aPropValue);
941 }
942 }
943 }
944
945 pPropStyleContext->FillPropertySet( xSeriesProp );
946 if( seriesStyle.mbSymbolSizeForSeriesIsMissingInFile )
947 lcl_setSymbolSizeIfNeeded( xSeriesProp, rImport );
948 if( bHasErrorBarRangesFromData )
949 lcl_insertErrorBarLSequencesToMap( rInOutLSequencesPerIndex, xSeriesProp );
950
951 }
952 catch( const uno::Exception & )
953 {
954 TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during setting styles to series" );
955 }
956 }
957}
958
959// static
961 SeriesDefaultsAndStyles& rSeriesDefaultsAndStyles,
962 const SvXMLStylesContext* pStylesCtxt,
963 const SvXMLStyleContext*& rpStyle,
964 OUString const & rCurrentStyleName )
965{
966 // iterate over regression etc
967 for (auto const& regressionStyle : rSeriesDefaultsAndStyles.maRegressionStyleVector)
968 {
969 try
970 {
971 OUString aServiceName;
972 XMLPropStyleContext* pPropStyleContext = nullptr;
973
974 if (!rCurrentStyleName.isEmpty())
975 {
976 XMLPropStyleContext* pCurrent = lcl_GetStylePropContext(pStylesCtxt, rpStyle, rCurrentStyleName);
977 if( pCurrent )
978 {
979 pPropStyleContext = pCurrent;
980 uno::Any aAny = SchXMLTools::getPropertyFromContext(u"RegressionType", pPropStyleContext, pStylesCtxt);
981 if ( aAny.hasValue() )
982 {
983 aAny >>= aServiceName;
984 }
985 }
986 }
987
988 if (!regressionStyle.msStyleName.isEmpty())
989 {
990 XMLPropStyleContext* pCurrent = lcl_GetStylePropContext(pStylesCtxt, rpStyle, regressionStyle.msStyleName);
991 if( pCurrent )
992 {
993 pPropStyleContext = pCurrent;
994 uno::Any aAny = SchXMLTools::getPropertyFromContext(u"RegressionType", pPropStyleContext, pStylesCtxt);
995 if ( aAny.hasValue() )
996 {
997 aAny >>= aServiceName;
998 }
999 }
1000 }
1001
1002 if( !aServiceName.isEmpty() )
1003 {
1004 Reference< lang::XMultiServiceFactory > xMSF = comphelper::getProcessServiceFactory();
1005 Reference< chart2::XRegressionCurve > xRegCurve( xMSF->createInstance( aServiceName ), uno::UNO_QUERY_THROW );
1006 Reference< chart2::XRegressionCurveContainer > xRegCurveCont( regressionStyle.m_xSeries, uno::UNO_QUERY_THROW );
1007
1008 Reference< beans::XPropertySet > xCurveProperties( xRegCurve, uno::UNO_QUERY );
1009 if( pPropStyleContext != nullptr)
1010 pPropStyleContext->FillPropertySet( xCurveProperties );
1011
1012 xRegCurve->setEquationProperties( regressionStyle.m_xEquationProperties );
1013
1014 xRegCurveCont->addRegressionCurve( xRegCurve );
1015 }
1016 }
1017 catch( const uno::Exception& )
1018 {
1019 TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during setting styles to series" );
1020 }
1021
1022 }
1023}
1024
1025// static
1027 , const SvXMLStylesContext* pStylesCtxt
1028 , const SvXMLStyleContext*& rpStyle
1029 , OUString& rCurrStyleName )
1030{
1031 // iterate over regression etc
1032 for (auto const& seriesStyle : rSeriesDefaultsAndStyles.maSeriesStyleVector)
1033 {
1034 if( seriesStyle.meType == DataRowPointStyle::ERROR_INDICATOR ||
1035 seriesStyle.meType == DataRowPointStyle::MEAN_VALUE )
1036 {
1037 if ( seriesStyle.meType == DataRowPointStyle::ERROR_INDICATOR )
1038 {
1039 uno::Reference< beans::XPropertySet > xNewSeriesProp(seriesStyle.m_xSeries,uno::UNO_QUERY);
1040
1041 if (seriesStyle.m_xErrorXProperties.is())
1042 xNewSeriesProp->setPropertyValue("ErrorBarX",uno::Any(seriesStyle.m_xErrorXProperties));
1043
1044 if (seriesStyle.m_xErrorYProperties.is())
1045 xNewSeriesProp->setPropertyValue("ErrorBarY",uno::Any(seriesStyle.m_xErrorYProperties));
1046 }
1047
1048 try
1049 {
1050 uno::Reference< beans::XPropertySet > xSeriesProp( seriesStyle.m_xOldAPISeries );
1051 if( !xSeriesProp.is() )
1052 continue;
1053
1054 if( !seriesStyle.msStyleName.isEmpty())
1055 {
1056 if( rCurrStyleName != seriesStyle.msStyleName )
1057 {
1058 rCurrStyleName = seriesStyle.msStyleName;
1059 rpStyle = pStylesCtxt->FindStyleChildContext(
1060 SchXMLImportHelper::GetChartFamilyID(), rCurrStyleName );
1061 }
1062
1063 // note: SvXMLStyleContext::FillPropertySet is not const
1064 XMLPropStyleContext * pPropStyleContext =
1065 const_cast< XMLPropStyleContext * >(
1066 dynamic_cast< const XMLPropStyleContext * >( rpStyle ));
1067 if( pPropStyleContext )
1068 {
1069 Reference< beans::XPropertySet > xStatPropSet;
1070 switch( seriesStyle.meType )
1071 {
1073 xSeriesProp->getPropertyValue("DataMeanValueProperties") >>= xStatPropSet;
1074 break;
1076 xSeriesProp->getPropertyValue("DataErrorProperties") >>= xStatPropSet;
1077 break;
1078 default:
1079 break;
1080 }
1081 if( xStatPropSet.is())
1082 pPropStyleContext->FillPropertySet( xStatPropSet );
1083 }
1084 }
1085 }
1086 catch( const uno::Exception & )
1087 {
1088 TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during setting styles to series" );
1089 }
1090 }
1091 }
1092}
1093
1094//static
1096 , const SvXMLStylesContext* pStylesCtxt
1097 , const SvXMLStyleContext*& rpStyle
1098 , OUString& rCurrStyleName
1099 , const SchXMLImportHelper& rImportHelper
1100 , const SvXMLImport& rImport
1101 , bool bIsStockChart, bool bIsDonutChart, bool bSwitchOffLinesForScatter )
1102{
1103 for (auto const& seriesStyle : rSeriesDefaultsAndStyles.maSeriesStyleVector)
1104 {
1105 if( seriesStyle.meType != DataRowPointStyle::DATA_POINT )
1106 continue;
1107
1108 if( seriesStyle.m_nPointIndex == -1 )
1109 continue;
1110
1111 uno::Reference< beans::XPropertySet > xSeriesProp( seriesStyle.m_xOldAPISeries );
1112 if(!xSeriesProp.is())
1113 continue;
1114
1115 //ignore datapoint properties for stock charts
1116 //... todo ...
1117 if( bIsStockChart )
1118 {
1119 if( SchXMLSeriesHelper::isCandleStickSeries( seriesStyle.m_xSeries, rImportHelper.GetChartDocument() ) )
1120 continue;
1121 }
1122
1123 // data point style
1124 for( sal_Int32 i = 0; i < seriesStyle.m_nPointRepeat; i++ )
1125 {
1126 try
1127 {
1128 uno::Reference< beans::XPropertySet > xPointProp(
1129 SchXMLSeriesHelper::createOldAPIDataPointPropertySet( seriesStyle.m_xSeries, seriesStyle.m_nPointIndex + i
1130 , rImportHelper.GetChartDocument() ) );
1131
1132 if( !xPointProp.is() )
1133 continue;
1134
1135 if( bIsDonutChart )
1136 {
1137 //set special series styles for donut charts first
1138 if( rCurrStyleName != seriesStyle.msSeriesStyleNameForDonuts )
1139 {
1140 rCurrStyleName = seriesStyle.msSeriesStyleNameForDonuts;
1141 rpStyle = pStylesCtxt->FindStyleChildContext(
1142 SchXMLImportHelper::GetChartFamilyID(), rCurrStyleName );
1143 }
1144
1145 // note: SvXMLStyleContext::FillPropertySet is not const
1146 XMLPropStyleContext * pPropStyleContext =
1147 const_cast< XMLPropStyleContext * >(
1148 dynamic_cast< const XMLPropStyleContext * >( rpStyle ));
1149 if( pPropStyleContext )
1150 pPropStyleContext->FillPropertySet( xPointProp );
1151 }
1152
1153 try
1154 {
1155 //need to set this explicitly here for old files as the new api does not support this property fully anymore
1156 if( bSwitchOffLinesForScatter )
1157 xPointProp->setPropertyValue("Lines",uno::Any(false));
1158 }
1159 catch( const uno::Exception & )
1160 {
1161 }
1162
1163 if( rCurrStyleName != seriesStyle.msStyleName )
1164 {
1165 rCurrStyleName = seriesStyle.msStyleName;
1166 rpStyle = pStylesCtxt->FindStyleChildContext(
1167 SchXMLImportHelper::GetChartFamilyID(), rCurrStyleName );
1168 }
1169
1170 // note: SvXMLStyleContext::FillPropertySet is not const
1171 XMLPropStyleContext * pPropStyleContext =
1172 const_cast< XMLPropStyleContext * >(
1173 dynamic_cast< const XMLPropStyleContext * >( rpStyle ));
1174 if (pPropStyleContext)
1175 {
1176 // Has the point a data-label child element?
1177 auto pItLabel = std::find_if(
1178 rSeriesDefaultsAndStyles.maSeriesStyleVector.begin(),
1179 rSeriesDefaultsAndStyles.maSeriesStyleVector.end(),
1180 [&seriesStyle](const DataRowPointStyle& rStyle) {
1181 return rStyle.meType == DataRowPointStyle::DATA_LABEL_POINT
1182 && rStyle.msStyleNameOfParent == seriesStyle.msStyleName;
1183 });
1184 if (pItLabel != rSeriesDefaultsAndStyles.maSeriesStyleVector.end())
1185 {
1186 // Bring the information from the data-label to the point
1187 const SvXMLStyleContext* pLabelStyleContext(
1188 pStylesCtxt->FindStyleChildContext(
1189 SchXMLImportHelper::GetChartFamilyID(), (*pItLabel).msStyleName));
1190 // note: SvXMLStyleContext::FillPropertySet is not const
1191 XMLPropStyleContext* pLabelPropStyleContext
1192 = const_cast<XMLPropStyleContext*>(
1193 dynamic_cast<const XMLPropStyleContext*>(pLabelStyleContext));
1194 if (pLabelPropStyleContext)
1195 {
1196 // Test each to be mapped property whether the data-label has a value for it.
1197 // If found, set it at the point.
1198 uno::Reference<beans::XPropertySetInfo> xPointPropInfo(
1199 xPointProp->getPropertySetInfo());
1200 for (const auto& rPropPair : aApiToLabelFooPairs)
1201 {
1203 rPropPair.first, pLabelPropStyleContext, pStylesCtxt));
1204 if (aPropValue.hasValue()
1205 && xPointPropInfo->hasPropertyByName(rPropPair.second))
1206 xPointProp->setPropertyValue(rPropPair.second, aPropValue);
1207 }
1208 }
1209 }
1210
1211 pPropStyleContext->FillPropertySet( xPointProp );
1212 if( seriesStyle.mbSymbolSizeForSeriesIsMissingInFile )
1213 lcl_resetSymbolSizeForPointsIfNecessary( xPointProp, rImport, pPropStyleContext, pStylesCtxt );
1214 if( !pPropStyleContext->isEmptyDataStyleName() )
1215 lcl_setLinkNumberFormatToSourceIfNeeded( xPointProp, pPropStyleContext, pStylesCtxt );
1216 }
1217
1218 // Custom labels might be passed as property
1219 if(const size_t nLabelCount = seriesStyle.mCustomLabels.mLabels.size(); nLabelCount > 0)
1220 {
1221 auto& rCustomLabels = seriesStyle.mCustomLabels;
1222
1223 Sequence< Reference<chart2::XDataPointCustomLabelField>> xLabels(nLabelCount);
1224 auto pxLabels = xLabels.getArray();
1225 Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
1226 for( size_t j = 0; j < nLabelCount; ++j )
1227 {
1228 Reference< chart2::XDataPointCustomLabelField > xCustomLabel = chart2::DataPointCustomLabelField::create(xContext);
1229 pxLabels[j] = xCustomLabel;
1230 xCustomLabel->setString(rCustomLabels.mLabels[j]);
1231 if ( j == 0 && rCustomLabels.mbDataLabelsRange)
1232 {
1233 xCustomLabel->setFieldType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLRANGE);
1234 xCustomLabel->setGuid(rCustomLabels.msLabelGuid);
1235 xCustomLabel->setCellRange(rCustomLabels.msLabelsCellRange);
1236 xCustomLabel->setDataLabelsRange(true);
1237 }
1238 else
1239 {
1240 xCustomLabel->setFieldType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT);
1241 }
1242
1243 // Restore character properties on the text span manually, till
1244 // SchXMLExportHelper_Impl::exportCustomLabel() does not write the style.
1245 uno::Reference<beans::XPropertySetInfo> xPointPropInfo
1246 = xPointProp->getPropertySetInfo();
1247 if (xPointPropInfo.is())
1248 {
1249 uno::Sequence<beans::Property> aProperties = xPointPropInfo->getProperties();
1250 for (const auto& rProperty : std::as_const(aProperties))
1251 {
1252 if (!rProperty.Name.startsWith("Char")
1253 || rProperty.Name.startsWith("Chart"))
1254 {
1255 continue;
1256 }
1257
1258 xCustomLabel->setPropertyValue(
1259 rProperty.Name, xPointProp->getPropertyValue(rProperty.Name));
1260 }
1261 }
1262 }
1263
1264 xPointProp->setPropertyValue("CustomLabelFields", uno::Any(xLabels));
1265 xPointProp->setPropertyValue("DataCaption", uno::Any(chart::ChartDataCaption::CUSTOM));
1266 }
1267
1268 if( seriesStyle.mCustomLabelPos[0] != 0.0 || seriesStyle.mCustomLabelPos[1] != 0.0 )
1269 {
1270 chart2::RelativePosition aCustomlabelPosition;
1271 aCustomlabelPosition.Primary = seriesStyle.mCustomLabelPos[0];
1272 aCustomlabelPosition.Secondary = seriesStyle.mCustomLabelPos[1];
1273 xPointProp->setPropertyValue("CustomLabelPosition", uno::Any(aCustomlabelPosition));
1274 }
1275 }
1276 catch( const uno::Exception & )
1277 {
1278 TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during setting styles to data points" );
1279 }
1280 }
1281 } // styles iterator
1282}
1283
1284//static
1285void SchXMLSeries2Context::switchSeriesLinesOff( ::std::vector< DataRowPointStyle >& rSeriesStyleVector )
1286{
1287 // iterate over series
1288 for (auto const& seriesStyle : rSeriesStyleVector)
1289 {
1290 if( seriesStyle.meType != DataRowPointStyle::DATA_SERIES )
1291 continue;
1292
1293 try
1294 {
1295 uno::Reference< beans::XPropertySet > xSeries( seriesStyle.m_xOldAPISeries );
1296 if( !xSeries.is() )
1297 continue;
1298
1299 xSeries->setPropertyValue("Lines",uno::Any(false));
1300 }
1301 catch( uno::Exception & )
1302 {
1303 //end of series reached
1304 }
1305 }
1306}
1307
1308/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const std::pair< OUString, OUString > aApiToLabelFooPairs[]
PropertiesInfo aProperties
With this class you can import a <chart:chart> element containing its data as <table:table> element o...
const css::uno::Reference< css::chart::XChartDocument > & GetChartDocument() const
static void DeleteDataSeries(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, const css::uno::Reference< css::chart2::XChartDocument > &xDoc)
SvXMLStylesContext * GetAutoStylesContext() const
static css::uno::Reference< css::chart2::XDataSeries > GetNewDataSeries(const css::uno::Reference< css::chart2::XChartDocument > &xDoc, sal_Int32 nCoordinateSystemIndex, const OUString &rChartTypeName, bool bPushLastChartType)
static XmlStyleFamily GetChartFamilyID()
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
::std::vector< DataRowPointStyle > & mrStyleVector
css::uno::Reference< css::chart2::XDataSeries > m_xSeries
static void initSeriesPropertySets(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const css::uno::Reference< css::frame::XModel > &xChartModel)
SchXMLImportHelper & mrImportHelper
tSchXMLLSequencesPerIndex & mrLSequencesPerIndex
static void setDefaultsToSeries(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles)
css::uno::Reference< css::chart2::XChartDocument > mxNewDoc
static void switchSeriesLinesOff(::std::vector< DataRowPointStyle > &rSeriesStyleVector)
::std::vector< RegressionStyle > & mrRegressionStyleVector
::std::vector< SchXMLAxis > & mrAxes
::std::vector< OUString > maDomainAddresses
static void setStylesToSeries(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const SvXMLStylesContext *pStylesCtxt, const SvXMLStyleContext *&rpStyle, OUString &rCurrStyleName, const SchXMLImportHelper &rImportHelper, const SvXMLImport &rImport, bool bIsStockChart, tSchXMLLSequencesPerIndex &rInOutLSequencesPerIndex)
tSchXMLLSequencesPerIndex maPostponedSequences
SchXMLSeries2Context(SchXMLImportHelper &rImpHelper, SvXMLImport &rImport, const css::uno::Reference< css::chart2::XChartDocument > &xNewDoc, std::vector< SchXMLAxis > &rAxes, ::std::vector< DataRowPointStyle > &rStyleVector, ::std::vector< RegressionStyle > &rRegressionStyleVector, sal_Int32 nSeriesIndex, bool bStockHasVolume, GlobalSeriesImportInfo &rGlobalSeriesImportInfo, const OUString &aGlobalChartTypeName, tSchXMLLSequencesPerIndex &rLSequencesPerIndex, bool &rGlobalChartTypeUsedBySeries, const css::awt::Size &rChartSize)
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
virtual ~SchXMLSeries2Context() override
static void setStylesToRegressionCurves(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const SvXMLStylesContext *pStylesCtxt, const SvXMLStyleContext *&rpStyle, OUString const &rCurrStyleName)
static void setStylesToStatisticsObjects(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const SvXMLStylesContext *pStylesCtxt, const SvXMLStyleContext *&rpStyle, OUString &rCurrStyleName)
DataRowPointStyle mDataLabel
static void setStylesToDataPoints(SeriesDefaultsAndStyles &rSeriesDefaultsAndStyles, const SvXMLStylesContext *pStylesCtxt, const SvXMLStyleContext *&rpStyle, OUString &rCurrStyleName, const SchXMLImportHelper &rImportHelper, const SvXMLImport &rImport, bool bIsStockChart, bool bIsDonutChart, bool bSwitchOffLinesForScatter)
GlobalSeriesImportInfo & m_rGlobalSeriesImportInfo
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
static bool isCandleStickSeries(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, const css::uno::Reference< css::frame::XModel > &xChartModel)
static css::uno::Reference< css::beans::XPropertySet > createOldAPIDataPointPropertySet(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, sal_Int32 nPointIndex, const css::uno::Reference< css::frame::XModel > &xChartModel)
static css::uno::Reference< css::beans::XPropertySet > createOldAPISeriesPropertySet(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, const css::uno::Reference< css::frame::XModel > &xChartModel)
This class deliberately does not support XWeak, to improve performance when loading large documents.
Definition: xmlictxt.hxx:48
virtual void SAL_CALL startFastElement(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
Definition: xmlictxt.cxx:45
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:60
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
Definition: xmlstyle.cxx:799
virtual bool isEmptyDataStyleName()
Definition: prstylei.hxx:100
virtual void FillPropertySet(const css::uno::Reference< css::beans::XPropertySet > &rPropSet)
Definition: prstylei.cxx:222
#define TOOLS_INFO_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
float u
sal_Int32 nIndex
OUString aName
tools::SvRef< SvBaseLink > xSink
Sequence< sal_Int8 > aSeq
#define SAL_WARN_IF(condition, area, stream)
Reference< chart2::data::XLabeledDataSequence2 > GetNewLabeledDataSequence()
Reference< chart2::data::XDataSequence > CreateDataSequenceWithoutConvert(const OUString &rRange, const Reference< chart2::XChartDocument > &xChartDoc)
bool isDocumentGeneratedWithOpenOfficeOlderThan2_3(const uno::Reference< frame::XModel > &xChartModel)
uno::Any getPropertyFromContext(std::u16string_view rPropertyName, const XMLPropStyleContext *pPropStyleContext, const SvXMLStylesContext *pStylesCtxt)
OUString GetChartTypeByClassName(std::u16string_view rClassName, bool bUseOldNames)
Reference< chart2::data::XDataSequence > CreateDataSequence(const OUString &rRange, const Reference< chart2::XChartDocument > &xChartDoc)
Reference< XMultiServiceFactory > getProcessServiceFactory()
Reference< XComponentContext > getProcessComponentContext()
int i
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
Handling of tokens in XML:
@ XML_CELL_RANGE_ADDRESS
Definition: xmltoken.hxx:410
@ XML_LABEL_CELL_ADDRESS
Definition: xmltoken.hxx:1144
@ XML_VALUES_CELL_RANGE_ADDRESS
Definition: xmltoken.hxx:2097
bool mbSymbolSizeForSeriesIsMissingInFile
CustomLabelsInfo mCustomLabels
css::uno::Reference< css::chart2::XDataSeries > m_xSeries
OUString msStyleNameOfParent
sal_Int8 nAxisIndex
css::uno::Any maConstantErrorLowDefault
css::uno::Any maConstantErrorHighDefault
css::uno::Any maErrorIndicatorDefault
css::uno::Any maErrorCategoryDefault
::std::vector< RegressionStyle > maRegressionStyleVector
css::uno::Any maRegressionCurvesDefault
css::uno::Any maPercentageErrorDefault
::std::vector< DataRowPointStyle > maSeriesStyleVector
bool hasValue()
@ SCH_XML_PART_VALUES
@ SCH_XML_PART_ERROR_BARS
@ SCH_XML_PART_LABEL
::std::multimap< tSchXMLIndexWithPart, css::uno::Reference< css::chart2::data::XLabeledDataSequence > > tSchXMLLSequencesPerIndex
::std::pair< tSchXMLIndex, SchXMLLabeledSequencePart > tSchXMLIndexWithPart
@ SCH_XML_AXIS_Y
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:120
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:114
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:98
constexpr sal_uInt16 XML_NAMESPACE_CHART