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