Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / xmloff / source / chart / SchXMLChartContext.cxx
blob5cc699f61c3871a4e91f1b042737faf6f46049b1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "SchXMLChartContext.hxx"
21 #include "SchXMLImport.hxx"
22 #include "SchXMLLegendContext.hxx"
23 #include "SchXMLPlotAreaContext.hxx"
24 #include "SchXMLParagraphContext.hxx"
25 #include "SchXMLTableContext.hxx"
26 #include "SchXMLSeries2Context.hxx"
27 #include "SchXMLTools.hxx"
28 #include <osl/diagnose.h>
29 #include <unotools/mediadescriptor.hxx>
30 #include <xmloff/xmlnmspe.hxx>
31 #include <xmloff/xmlement.hxx>
32 #include <xmloff/xmltoken.hxx>
33 #include <xmloff/nmspmap.hxx>
34 #include <xmloff/xmluconv.hxx>
35 #include <xmloff/xmlstyle.hxx>
36 #include <xmloff/prstylei.hxx>
37 #include <xmloff/SchXMLSeriesHelper.hxx>
39 #include "vector"
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/chart/XChartDocument.hpp>
42 #include <com/sun/star/chart/XDiagram.hpp>
43 #include <com/sun/star/xml/sax/XAttributeList.hpp>
44 #include <com/sun/star/util/XStringMapping.hpp>
45 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
46 #include <com/sun/star/drawing/XDrawPage.hpp>
47 #include <com/sun/star/chart/ChartDataRowSource.hpp>
48 #include <com/sun/star/chart/ChartSeriesAddress.hpp>
49 #include <com/sun/star/awt/PosSize.hpp>
50 #include <com/sun/star/embed/Aspects.hpp>
51 #include <com/sun/star/embed/XVisualObject.hpp>
53 #include <com/sun/star/chart2/XChartDocument.hpp>
54 #include <com/sun/star/chart2/data/XDataSink.hpp>
55 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
56 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
57 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
58 #include <com/sun/star/chart2/XTitled.hpp>
60 using namespace com::sun::star;
61 using namespace ::xmloff::token;
62 using com::sun::star::uno::Reference;
63 using namespace ::SchXMLTools;
65 namespace
68 void lcl_setRoleAtLabeledSequence(
69 const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq,
70 const OUString &rRole )
72 // set role of sequence
73 uno::Reference< chart2::data::XDataSequence > xValues( xLSeq->getValues());
74 if( xValues.is())
76 uno::Reference< beans::XPropertySet > xProp( xValues, uno::UNO_QUERY );
77 if( xProp.is())
78 xProp->setPropertyValue("Role", uno::makeAny( rRole ));
82 void lcl_MoveDataToCandleStickSeries(
83 const uno::Reference< chart2::data::XDataSource > & xDataSource,
84 const uno::Reference< chart2::XDataSeries > & xDestination,
85 const OUString & rRole )
87 try
89 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq(
90 xDataSource->getDataSequences());
91 if( aLabeledSeq.getLength())
93 lcl_setRoleAtLabeledSequence( aLabeledSeq[0], rRole );
95 // add to data series
96 uno::Reference< chart2::data::XDataSource > xSource( xDestination, uno::UNO_QUERY_THROW );
97 // @todo: realloc only once outside this function
98 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences());
99 aData.realloc( aData.getLength() + 1);
100 aData[ aData.getLength() - 1 ] = aLabeledSeq[0];
101 uno::Reference< chart2::data::XDataSink > xSink( xDestination, uno::UNO_QUERY_THROW );
102 xSink->setData( aData );
105 catch(const uno::Exception&)
107 SAL_WARN("xmloff.chart", "Exception caught while moving data to candlestick series" );
111 void lcl_setRoleAtFirstSequence(
112 const uno::Reference< chart2::XDataSeries > & xSeries,
113 const OUString & rRole )
115 uno::Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
116 if( xSource.is())
118 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
119 if( aSeq.getLength())
120 lcl_setRoleAtLabeledSequence( aSeq[0], rRole );
124 void lcl_removeEmptyChartTypeGroups( const uno::Reference< chart2::XChartDocument > & xDoc )
126 if( ! xDoc.is())
127 return;
129 uno::Reference< chart2::XDiagram > xDia( xDoc->getFirstDiagram());
130 if( ! xDia.is())
131 return;
135 // count all charttype groups to be able to leave at least one
136 sal_Int32 nRemainingGroups = 0;
137 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY_THROW );
138 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > >
139 aCooSysSeq( xCooSysCnt->getCoordinateSystems());
140 for( sal_Int32 nI = aCooSysSeq.getLength(); nI--; )
142 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nI], uno::UNO_QUERY_THROW );
143 nRemainingGroups += xCTCnt->getChartTypes().getLength();
146 // delete all empty groups, but leave at least group (empty or not)
147 for( sal_Int32 nI = aCooSysSeq.getLength(); nI-- && (nRemainingGroups > 1); )
149 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nI], uno::UNO_QUERY_THROW );
150 uno::Sequence< uno::Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
151 for( sal_Int32 nJ=aCTSeq.getLength(); nJ-- && (nRemainingGroups > 1); )
153 uno::Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nJ], uno::UNO_QUERY_THROW );
154 if( xDSCnt->getDataSeries().getLength() == 0 )
156 // note: iterator stays valid as we have a local sequence
157 xCTCnt->removeChartType( aCTSeq[nJ] );
158 --nRemainingGroups;
163 catch(const uno::Exception& ex)
165 OString aBStr(OUStringToOString(ex.Message, RTL_TEXTENCODING_ASCII_US));
166 SAL_INFO("xmloff.chart", "Exception caught while removing empty chart types: " << aBStr);
170 uno::Sequence< sal_Int32 > lcl_getNumberSequenceFromString( const OUString& rStr, bool bAddOneToEachOldIndex )
172 const sal_Unicode aSpace( ' ' );
174 // count number of entries
175 ::std::vector< sal_Int32 > aVec;
176 sal_Int32 nLastPos = 0;
177 sal_Int32 nPos = 0;
178 while( nPos != -1 )
180 nPos = rStr.indexOf( aSpace, nLastPos );
181 if( nPos > nLastPos )
183 aVec.push_back( rStr.copy( nLastPos, (nPos - nLastPos) ).toInt32() );
185 if( nPos != -1 )
186 nLastPos = nPos + 1;
188 // last entry
189 if( nLastPos != 0 &&
190 rStr.getLength() > nLastPos )
192 aVec.push_back( rStr.copy( nLastPos, (rStr.getLength() - nLastPos) ).toInt32() );
195 const sal_Int32 nVecSize = aVec.size();
196 uno::Sequence< sal_Int32 > aSeq( nVecSize );
198 if(!bAddOneToEachOldIndex)
200 sal_Int32* pSeqArr = aSeq.getArray();
201 for( nPos = 0; nPos < nVecSize; ++nPos )
203 pSeqArr[ nPos ] = aVec[ nPos ];
206 else if( bAddOneToEachOldIndex )
208 aSeq.realloc( nVecSize+1 );
209 aSeq[0]=0;
211 sal_Int32* pSeqArr = aSeq.getArray();
212 for( nPos = 0; nPos < nVecSize; ++nPos )
214 pSeqArr[ nPos+1 ] = aVec[ nPos ]+1;
218 return aSeq;
221 } // anonymous namespace
223 SchXMLChartContext::SchXMLChartContext( SchXMLImportHelper& rImpHelper,
224 SvXMLImport& rImport, const OUString& rLocalName ) :
225 SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
226 mrImportHelper( rImpHelper ),
227 m_bHasRangeAtPlotArea( false ),
228 m_bHasTableElement( false ),
229 mbAllRangeAddressesAvailable( true ),
230 mbColHasLabels( false ),
231 mbRowHasLabels( false ),
232 meDataRowSource( chart::ChartDataRowSource_COLUMNS ),
233 mbIsStockChart( false )
237 SchXMLChartContext::~SchXMLChartContext()
240 void SchXMLChartContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
242 // parse attributes
243 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
244 const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetChartAttrTokenMap();
246 uno::Reference< embed::XVisualObject > xVisualObject( mrImportHelper.GetChartDocument(), uno::UNO_QUERY);
247 SAL_WARN_IF(!xVisualObject.is(), "xmloff.chart", "need xVisualObject for page size");
248 if( xVisualObject.is() )
249 maChartSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); //#i103460# take the size given from the parent frame as default
251 // this flag is necessary for pie charts in the core
252 bool bSetSwitchData = false;
254 OUString sAutoStyleName;
255 OUString aOldChartTypeName;
256 bool bHasAddin = false;
258 for( sal_Int16 i = 0; i < nAttrCount; i++ )
260 OUString sAttrName = xAttrList->getNameByIndex( i );
261 OUString aLocalName;
262 OUString aValue = xAttrList->getValueByIndex( i );
263 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
265 switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
267 case XML_TOK_CHART_HREF:
268 m_aXLinkHRefAttributeToIndicateDataProvider = aValue;
269 break;
271 case XML_TOK_CHART_CLASS:
273 OUString sClassName;
274 sal_uInt16 nClassPrefix =
275 GetImport().GetNamespaceMap().GetKeyByAttrName(
276 aValue, &sClassName );
277 if( XML_NAMESPACE_CHART == nClassPrefix )
279 SchXMLChartTypeEnum eChartTypeEnum = SchXMLTools::GetChartTypeEnum( sClassName );
280 if( eChartTypeEnum != XML_CHART_CLASS_UNKNOWN )
282 aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( sClassName, true /* bUseOldNames */ );
283 maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( sClassName, false /* bUseOldNames */ );
284 switch( eChartTypeEnum )
286 case XML_CHART_CLASS_CIRCLE:
287 bSetSwitchData = true;
288 break;
289 case XML_CHART_CLASS_STOCK:
290 mbIsStockChart = true;
291 break;
292 default:
293 break;
297 else if( XML_NAMESPACE_OOO == nClassPrefix )
299 // service is taken from add-in-name attribute
300 bHasAddin = true;
302 aOldChartTypeName = sClassName;
303 maChartTypeServiceName = sClassName;
306 break;
308 case XML_TOK_CHART_WIDTH:
309 GetImport().GetMM100UnitConverter().convertMeasureToCore(
310 maChartSize.Width, aValue );
311 break;
313 case XML_TOK_CHART_HEIGHT:
314 GetImport().GetMM100UnitConverter().convertMeasureToCore(
315 maChartSize.Height, aValue );
316 break;
318 case XML_TOK_CHART_STYLE_NAME:
319 sAutoStyleName = aValue;
320 break;
322 case XML_TOK_CHART_COL_MAPPING:
323 msColTrans = aValue;
324 break;
325 case XML_TOK_CHART_ROW_MAPPING:
326 msRowTrans = aValue;
327 break;
331 if( aOldChartTypeName.isEmpty() )
333 SAL_WARN("xmloff.chart", "need a charttype to create a diagram" );
334 //set a fallback value:
335 const OUString& aChartClass_Bar( GetXMLToken(XML_BAR ) );
336 aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, true /* bUseOldNames */ );
337 maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, false /* bUseOldNames */ );
340 // Set the size of the draw page.
341 if( xVisualObject.is() )
342 xVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, maChartSize );
344 InitChart( aOldChartTypeName, bSetSwitchData);
346 if( bHasAddin )
348 //correct charttype service name when having an addin
349 //and don't refresh addin during load
350 uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
351 if( xDocProp.is() )
355 xDocProp->getPropertyValue("BaseDiagram") >>= aOldChartTypeName;
356 maChartTypeServiceName = SchXMLTools::GetNewChartTypeName( aOldChartTypeName );
357 xDocProp->setPropertyValue("RefreshAddInAllowed", uno::makeAny( false) );
359 catch(const uno::Exception&)
361 SAL_WARN("xmloff.chart", "Exception during import SchXMLChartContext::StartElement" );
366 // set auto-styles for Area
367 uno::Reference< beans::XPropertySet > xProp( mrImportHelper.GetChartDocument()->getArea(), uno::UNO_QUERY );
368 if( xProp.is())
370 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
371 if( pStylesCtxt )
373 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
374 SchXMLImportHelper::GetChartFamilyID(), sAutoStyleName );
376 if( pStyle && dynamic_cast< const XMLPropStyleContext*>(pStyle) != nullptr)
377 const_cast<XMLPropStyleContext*>( static_cast< const XMLPropStyleContext* >( pStyle ) )->FillPropertySet( xProp );
382 namespace
385 struct NewDonutSeries
387 css::uno::Reference< css::chart2::XDataSeries > m_xSeries;
388 OUString msStyleName;
389 sal_Int32 mnAttachedAxis;
391 ::std::vector< OUString > m_aSeriesStyles;
392 ::std::vector< OUString > m_aPointStyles;
394 NewDonutSeries( const css::uno::Reference< css::chart2::XDataSeries >& xSeries, sal_Int32 nPointCount )
395 : m_xSeries( xSeries )
396 , mnAttachedAxis( 1 )
398 m_aPointStyles.resize(nPointCount);
399 m_aSeriesStyles.resize(nPointCount);
402 void setSeriesStyleNameToPoint( const OUString& rStyleName, sal_Int32 nPointIndex )
404 SAL_WARN_IF(nPointIndex >= static_cast<sal_Int32>(m_aSeriesStyles.size()), "xmloff.chart", "donut point <-> series count mismatch");
405 if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
406 m_aSeriesStyles[nPointIndex]=rStyleName;
409 void setPointStyleNameToPoint( const OUString& rStyleName, sal_Int32 nPointIndex )
411 SAL_WARN_IF(nPointIndex >= static_cast<sal_Int32>(m_aPointStyles.size()), "xmloff.chart", "donut point <-> series count mismatch");
412 if( nPointIndex < static_cast<sal_Int32>(m_aPointStyles.size()) )
413 m_aPointStyles[nPointIndex]=rStyleName;
416 ::std::list< DataRowPointStyle > creatStyleList()
418 ::std::list< DataRowPointStyle > aRet;
420 DataRowPointStyle aSeriesStyle( DataRowPointStyle::DATA_SERIES
421 , m_xSeries, -1, 1, msStyleName, mnAttachedAxis );
422 aRet.push_back( aSeriesStyle );
424 sal_Int32 nPointIndex=0;
425 ::std::vector< OUString >::iterator aPointIt( m_aPointStyles.begin() );
426 ::std::vector< OUString >::iterator aPointEnd( m_aPointStyles.end() );
427 while( aPointIt != aPointEnd )
429 DataRowPointStyle aPointStyle( DataRowPointStyle::DATA_POINT
430 , m_xSeries, nPointIndex, 1, *aPointIt, mnAttachedAxis );
431 if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
433 aPointStyle.msSeriesStyleNameForDonuts = m_aSeriesStyles[nPointIndex];
435 if( !aPointStyle.msSeriesStyleNameForDonuts.isEmpty()
436 || !aPointStyle.msStyleName.isEmpty() )
437 aRet.push_back( aPointStyle );
438 ++aPointIt;
439 ++nPointIndex;
442 return aRet;
446 void lcl_swapPointAndSeriesStylesForDonutCharts( ::std::list< DataRowPointStyle >& rStyleList
447 , const ::std::map< css::uno::Reference< css::chart2::XDataSeries> , sal_Int32 >& rSeriesMap )
449 ::std::list< DataRowPointStyle >::iterator aIt(rStyleList.begin());
450 ::std::list< DataRowPointStyle >::iterator aEnd(rStyleList.end());
452 //detect old series count
453 //and add old series to aSeriesMap
454 ::std::map< css::uno::Reference<
455 css::chart2::XDataSeries >, sal_Int32 > aSeriesMap(rSeriesMap);
456 sal_Int32 nOldSeriesCount = 0;
458 sal_Int32 nMaxOldSeriesIndex = 0;
459 sal_Int32 nOldSeriesIndex = 0;
460 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
462 DataRowPointStyle aStyle(*aIt);
463 if(aStyle.meType == DataRowPointStyle::DATA_SERIES &&
464 aStyle.m_xSeries.is() )
466 nMaxOldSeriesIndex = nOldSeriesIndex;
468 if( aSeriesMap.end() == aSeriesMap.find(aStyle.m_xSeries) )
469 aSeriesMap[aStyle.m_xSeries] = nOldSeriesIndex;
471 nOldSeriesIndex++;
474 nOldSeriesCount = nMaxOldSeriesIndex+1;
477 //initialize new series styles
478 ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapIt( aSeriesMap.begin() );
479 ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapEnd( aSeriesMap.end() );
481 //sort by index
482 ::std::vector< NewDonutSeries > aNewSeriesVector;
484 ::std::map< sal_Int32, Reference< chart2::XDataSeries > > aIndexSeriesMap;
485 for( ; aSeriesMapIt != aSeriesMapEnd; ++aSeriesMapIt )
486 aIndexSeriesMap[aSeriesMapIt->second] = aSeriesMapIt->first;
488 ::std::map< sal_Int32, Reference< chart2::XDataSeries > >::const_iterator aIndexIt( aIndexSeriesMap.begin() );
489 ::std::map< sal_Int32, Reference< chart2::XDataSeries > >::const_iterator aIndexEnd( aIndexSeriesMap.end() );
491 for( ; aIndexIt != aIndexEnd; ++aIndexIt )
492 aNewSeriesVector.push_back( NewDonutSeries(aIndexIt->second,nOldSeriesCount) );
495 //overwrite attached axis information according to old series styles
496 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
498 DataRowPointStyle aStyle(*aIt);
499 if(aStyle.meType == DataRowPointStyle::DATA_SERIES )
501 aSeriesMapIt = aSeriesMap.find( aStyle.m_xSeries );
502 if( aSeriesMapIt != aSeriesMapEnd && aSeriesMapIt->second < static_cast<sal_Int32>(aNewSeriesVector.size()) )
503 aNewSeriesVector[aSeriesMapIt->second].mnAttachedAxis = aStyle.mnAttachedAxis;
507 //overwrite new series style names with old series style name information
508 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
510 DataRowPointStyle aStyle(*aIt);
511 if( aStyle.meType == DataRowPointStyle::DATA_SERIES )
513 aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
514 if( aSeriesMapEnd != aSeriesMapIt )
516 sal_Int32 nNewPointIndex = aSeriesMapIt->second;
518 ::std::vector< NewDonutSeries >::iterator aNewSeriesIt( aNewSeriesVector.begin() );
519 ::std::vector< NewDonutSeries >::iterator aNewSeriesEnd( aNewSeriesVector.end() );
521 for( ;aNewSeriesIt!=aNewSeriesEnd; ++aNewSeriesIt)
522 aNewSeriesIt->setSeriesStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
527 //overwrite new series style names with point style name information
528 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
530 DataRowPointStyle aStyle(*aIt);
531 if( aStyle.meType == DataRowPointStyle::DATA_POINT )
533 aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
534 if( aSeriesMapEnd != aSeriesMapIt )
536 sal_Int32 nNewPointIndex = aSeriesMapIt->second;
537 sal_Int32 nNewSeriesIndex = aStyle.m_nPointIndex;
538 sal_Int32 nRepeatCount = aStyle.m_nPointRepeat;
540 while( nRepeatCount && (nNewSeriesIndex>=0) && (nNewSeriesIndex< static_cast<sal_Int32>(aNewSeriesVector.size()) ) )
542 NewDonutSeries& rNewSeries( aNewSeriesVector[nNewSeriesIndex] );
543 rNewSeries.setPointStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
545 nRepeatCount--;
546 nNewSeriesIndex++;
552 //put information from aNewSeriesVector to output parameter rStyleList
553 rStyleList.clear();
555 ::std::vector< NewDonutSeries >::iterator aNewSeriesIt( aNewSeriesVector.begin() );
556 ::std::vector< NewDonutSeries >::iterator aNewSeriesEnd( aNewSeriesVector.end() );
557 for( ;aNewSeriesIt!=aNewSeriesEnd; ++aNewSeriesIt)
559 ::std::list< DataRowPointStyle > aList( aNewSeriesIt->creatStyleList() );
560 rStyleList.insert(rStyleList.end(),aList.begin(),aList.end());
564 bool lcl_SpecialHandlingForDonutChartNeeded(
565 const OUString & rServiceName,
566 const SvXMLImport & rImport )
568 bool bResult = false;
569 if( rServiceName == "com.sun.star.chart2.DonutChartType" )
571 bResult = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( rImport.GetModel() );
573 return bResult;
576 } // anonymous namespace
578 static void lcl_ApplyDataFromRectangularRangeToDiagram(
579 const uno::Reference< chart2::XChartDocument >& xNewDoc
580 , const OUString& rRectangularRange
581 , css::chart::ChartDataRowSource eDataRowSource
582 , bool bRowHasLabels, bool bColHasLabels
583 , bool bSwitchOnLabelsAndCategoriesForOwnData
584 , const OUString& sColTrans
585 , const OUString& sRowTrans )
587 if( !xNewDoc.is() )
588 return;
590 uno::Reference< chart2::XDiagram > xNewDia( xNewDoc->getFirstDiagram());
591 uno::Reference< chart2::data::XDataProvider > xDataProvider( xNewDoc->getDataProvider() );
592 if( !xNewDia.is() || !xDataProvider.is() )
593 return;
595 bool bFirstCellAsLabel =
596 (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bRowHasLabels : bColHasLabels;
597 bool bHasCateories =
598 (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bColHasLabels : bRowHasLabels;
600 if( bSwitchOnLabelsAndCategoriesForOwnData )
602 bFirstCellAsLabel = true;
603 bHasCateories = true;
606 uno::Sequence< beans::PropertyValue > aArgs( 3 );
607 aArgs[0] = beans::PropertyValue(
608 OUString( "CellRangeRepresentation" ),
609 -1, uno::makeAny( rRectangularRange ),
610 beans::PropertyState_DIRECT_VALUE );
611 aArgs[1] = beans::PropertyValue(
612 OUString( "DataRowSource" ),
613 -1, uno::makeAny( eDataRowSource ),
614 beans::PropertyState_DIRECT_VALUE );
615 aArgs[2] = beans::PropertyValue(
616 OUString( "FirstCellAsLabel" ),
617 -1, uno::makeAny( bFirstCellAsLabel ),
618 beans::PropertyState_DIRECT_VALUE );
620 if( !sColTrans.isEmpty() || !sRowTrans.isEmpty() )
622 aArgs.realloc( aArgs.getLength() + 1 );
623 aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
624 OUString( "SequenceMapping" ),
625 -1, uno::makeAny( !sColTrans.isEmpty()
626 ? lcl_getNumberSequenceFromString( sColTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() )
627 : lcl_getNumberSequenceFromString( sRowTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() ) ),
628 beans::PropertyState_DIRECT_VALUE );
631 //work around wrong writer ranges ( see Issue 58464 )
633 OUString aChartOleObjectName;
634 uno::Reference< frame::XModel > xModel(xNewDoc, uno::UNO_QUERY );
635 if( xModel.is() )
637 utl::MediaDescriptor aMediaDescriptor( xModel->getArgs() );
639 utl::MediaDescriptor::const_iterator aIt(
640 aMediaDescriptor.find( OUString( "HierarchicalDocumentName" )));
641 if( aIt != aMediaDescriptor.end() )
643 aChartOleObjectName = (*aIt).second.get< OUString >();
646 if( !aChartOleObjectName.isEmpty() )
648 aArgs.realloc( aArgs.getLength() + 1 );
649 aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
650 OUString( "ChartOleObjectName" ),
651 -1, uno::makeAny( aChartOleObjectName ),
652 beans::PropertyState_DIRECT_VALUE );
656 uno::Reference< chart2::data::XDataSource > xDataSource(
657 xDataProvider->createDataSource( aArgs ));
659 aArgs.realloc( aArgs.getLength() + 2 );
660 aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 2 ] = beans::PropertyValue(
661 OUString( "HasCategories" ),
662 -1, uno::makeAny( bHasCateories ),
663 beans::PropertyState_DIRECT_VALUE );
664 aArgs[ sal::static_int_cast<sal_uInt32>(aArgs.getLength()) - 1 ] = beans::PropertyValue(
665 OUString("UseCategoriesAsX"),
666 -1, uno::makeAny( false ),//categories in ODF files are not to be used as x values (independent from what is offered in our ui)
667 beans::PropertyState_DIRECT_VALUE );
669 xNewDia->setDiagramData( xDataSource, aArgs );
672 void SchXMLChartContext::EndElement()
674 uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
675 uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
676 uno::Reference< chart2::XChartDocument > xNewDoc( xDoc, uno::UNO_QUERY );
678 if( xProp.is())
680 if( !maMainTitle.isEmpty())
682 uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getTitle(), uno::UNO_QUERY );
683 if( xTitleProp.is())
687 xTitleProp->setPropertyValue("String", uno::Any(maMainTitle) );
689 catch(const beans::UnknownPropertyException&)
691 SAL_WARN("xmloff.chart", "Property String for Title not available" );
695 if( !maSubTitle.isEmpty())
697 uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getSubTitle(), uno::UNO_QUERY );
698 if( xTitleProp.is())
702 xTitleProp->setPropertyValue("String", uno::Any(maSubTitle) );
704 catch(const beans::UnknownPropertyException&)
706 SAL_WARN("xmloff.chart", "Property String for Title not available" );
712 // cleanup: remove empty chart type groups
713 lcl_removeEmptyChartTypeGroups( xNewDoc );
715 // set stack mode before a potential chart type detection (in case we have a rectangular range)
716 uno::Reference< chart::XDiagram > xDiagram( xDoc->getDiagram() );
717 uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
718 if( xDiaProp.is())
720 if( maSeriesDefaultsAndStyles.maStackedDefault.hasValue())
721 xDiaProp->setPropertyValue("Stacked",maSeriesDefaultsAndStyles.maStackedDefault);
722 if( maSeriesDefaultsAndStyles.maPercentDefault.hasValue())
723 xDiaProp->setPropertyValue("Percent",maSeriesDefaultsAndStyles.maPercentDefault);
724 if( maSeriesDefaultsAndStyles.maDeepDefault.hasValue())
725 xDiaProp->setPropertyValue("Deep",maSeriesDefaultsAndStyles.maDeepDefault);
726 if( maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault.hasValue())
727 xDiaProp->setPropertyValue("StackedBarsConnected",maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault);
730 //the OOo 2.0 implementation and older has a bug with donuts
731 bool bSpecialHandlingForDonutChart = lcl_SpecialHandlingForDonutChartNeeded(
732 maChartTypeServiceName, GetImport());
734 // apply data
735 if(!xNewDoc.is())
736 return;
738 bool bHasOwnData = false;
739 if( m_aXLinkHRefAttributeToIndicateDataProvider == "." ) //data comes from the chart itself
740 bHasOwnData = true;
741 else if( m_aXLinkHRefAttributeToIndicateDataProvider == ".." ) //data comes from the parent application
742 bHasOwnData = false;
743 else if( !m_aXLinkHRefAttributeToIndicateDataProvider.isEmpty() ) //not supported so far to get the data by sibling objects -> fall back to chart itself if data are available
744 bHasOwnData = m_bHasTableElement;
745 else
746 bHasOwnData = !m_bHasRangeAtPlotArea;
748 if( xNewDoc->hasInternalDataProvider())
750 if( !m_bHasTableElement && m_aXLinkHRefAttributeToIndicateDataProvider != "." )
752 //#i103147# ODF, workaround broken files with a missing table:cell-range-address at the plot-area
753 bool bSwitchSuccessful = SchXMLTools::switchBackToDataProviderFromParent( xNewDoc, maLSequencesPerIndex );
754 bHasOwnData = !bSwitchSuccessful;
756 else
757 bHasOwnData = true;//e.g. in case of copy->paste from calc to impress
759 else if( bHasOwnData )
761 xNewDoc->createInternalDataProvider( false /* bCloneExistingData */ );
763 if( bHasOwnData )
764 msChartAddress = "all";
766 bool bSwitchRangesFromOuterToInternalIfNecessary = false;
767 if( !bHasOwnData && mbAllRangeAddressesAvailable )
769 // special handling for stock chart (merge series together)
770 if( mbIsStockChart )
771 MergeSeriesForStockChart();
773 else if( !msChartAddress.isEmpty() )
775 //own data or only rectangular range available
777 if( xNewDoc->hasInternalDataProvider() )
778 SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc );
780 bool bOlderThan2_3 = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( Reference< frame::XModel >( xNewDoc, uno::UNO_QUERY ));
781 bool bOldFileWithOwnDataFromRows = (bOlderThan2_3 && bHasOwnData && (meDataRowSource==chart::ChartDataRowSource_ROWS)); // in this case there are range addresses that are simply wrong.
783 if( mbAllRangeAddressesAvailable && !bSpecialHandlingForDonutChart && !mbIsStockChart &&
784 !bOldFileWithOwnDataFromRows )
786 //bHasOwnData is true in this case!
787 //e.g. for normal files with own data or also in case of copy paste scenario (e.g. calc to impress)
788 bSwitchRangesFromOuterToInternalIfNecessary = true;
790 else
792 //apply data from rectangular range
794 // create datasource from data provider with rectangular range parameters and change the diagram setDiagramData
797 if( bOlderThan2_3 && xDiaProp.is() )//for older charts the hidden cells were removed by calc on the fly
798 xDiaProp->setPropertyValue("IncludeHiddenCells",uno::makeAny(false));
800 // note: mbRowHasLabels means the first row contains labels, that means we have "column-descriptions",
801 // (analogously mbColHasLabels means we have "row-descriptions")
802 lcl_ApplyDataFromRectangularRangeToDiagram( xNewDoc, msChartAddress, meDataRowSource, mbRowHasLabels, mbColHasLabels, bHasOwnData, msColTrans, msRowTrans );
804 catch(const uno::Exception&)
806 //try to fallback to internal data
807 SAL_WARN("xmloff.chart", "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram try to fallback to internal data" );
808 if(!bHasOwnData)
810 bHasOwnData = true;
811 msChartAddress = "all";
812 if( !xNewDoc->hasInternalDataProvider() )
814 xNewDoc->createInternalDataProvider( false /* bCloneExistingData */ );
815 SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc );
818 lcl_ApplyDataFromRectangularRangeToDiagram( xNewDoc, msChartAddress, meDataRowSource, mbRowHasLabels, mbColHasLabels, bHasOwnData, msColTrans, msRowTrans );
820 catch(const uno::Exception&)
822 SAL_WARN("xmloff.chart", "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram fallback to internal data failed also" );
829 else
831 SAL_WARN("xmloff.chart", "Must not get here" );
834 // now all series and data point properties are available and can be set
836 if( bSpecialHandlingForDonutChart )
838 uno::Reference< chart2::XDiagram > xNewDiagram( xNewDoc->getFirstDiagram() );
839 lcl_swapPointAndSeriesStylesForDonutCharts( maSeriesDefaultsAndStyles.maSeriesStyleList
840 , SchXMLSeriesHelper::getDataSeriesIndexMapFromDiagram(xNewDiagram) );
843 SchXMLSeries2Context::initSeriesPropertySets( maSeriesDefaultsAndStyles, uno::Reference< frame::XModel >(xDoc, uno::UNO_QUERY ) );
845 //set defaults from diagram to the new series:
846 //check whether we need to remove lines from symbol only charts
847 bool bSwitchOffLinesForScatter = false;
849 bool bLinesOn = true;
850 if( (maSeriesDefaultsAndStyles.maLinesOnProperty >>= bLinesOn) && !bLinesOn )
852 if( maChartTypeServiceName == "com.sun.star.chart2.ScatterChartType" )
854 bSwitchOffLinesForScatter = true;
855 SchXMLSeries2Context::switchSeriesLinesOff( maSeriesDefaultsAndStyles.maSeriesStyleList );
859 SchXMLSeries2Context::setDefaultsToSeries( maSeriesDefaultsAndStyles );
861 // set autostyles for series and data points
862 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
863 const SvXMLStyleContext* pStyle = nullptr;
864 OUString sCurrStyleName;
866 if( pStylesCtxt )
868 //iterate over data-series first
869 //don't set series styles for donut charts
870 if( !bSpecialHandlingForDonutChart )
872 SchXMLSeries2Context::setStylesToSeries(
873 maSeriesDefaultsAndStyles, pStylesCtxt, pStyle,
874 sCurrStyleName, mrImportHelper, GetImport(),
875 mbIsStockChart, maLSequencesPerIndex );
876 // ... then set attributes for statistics (after their existence was set in the series)
877 SchXMLSeries2Context::setStylesToStatisticsObjects(
878 maSeriesDefaultsAndStyles, pStylesCtxt,
879 pStyle, sCurrStyleName );
881 SchXMLSeries2Context::setStylesToRegressionCurves(
882 maSeriesDefaultsAndStyles, pStylesCtxt,
883 pStyle, sCurrStyleName );
887 //#i98319# call switchRangesFromOuterToInternalIfNecessary before the data point styles are applied, otherwise in copy->paste scenario the data point styles do get lost
888 if( bSwitchRangesFromOuterToInternalIfNecessary )
890 if( xNewDoc->hasInternalDataProvider() )
891 SchXMLTableHelper::switchRangesFromOuterToInternalIfNecessary( maTable, maLSequencesPerIndex, xNewDoc, meDataRowSource );
894 if( pStylesCtxt )
896 // ... then iterate over data-point attributes, so the latter are not overwritten
897 SchXMLSeries2Context::setStylesToDataPoints( maSeriesDefaultsAndStyles
898 , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, GetImport(), mbIsStockChart, bSpecialHandlingForDonutChart, bSwitchOffLinesForScatter );
902 if( xProp.is())
903 xProp->setPropertyValue("RefreshAddInAllowed", uno::makeAny( true) );
906 void SchXMLChartContext::MergeSeriesForStockChart()
908 OSL_ASSERT( mbIsStockChart );
911 uno::Reference< chart::XChartDocument > xOldDoc( mrImportHelper.GetChartDocument());
912 uno::Reference< chart2::XChartDocument > xDoc( xOldDoc, uno::UNO_QUERY_THROW );
913 uno::Reference< chart2::XDiagram > xDiagram( xDoc->getFirstDiagram());
914 if( ! xDiagram.is())
915 return;
917 bool bHasJapaneseCandlestick = true;
918 uno::Reference< chart2::XDataSeriesContainer > xDSContainer;
919 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
920 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
921 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
923 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
924 uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
925 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
927 if( aChartTypes[nCTIdx]->getChartType() == "com.sun.star.chart2.CandleStickChartType" )
929 xDSContainer.set( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
930 uno::Reference< beans::XPropertySet > xCTProp( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
931 xCTProp->getPropertyValue("Japanese") >>= bHasJapaneseCandlestick;
932 break;
937 if( xDSContainer.is())
939 // with japanese candlesticks: open, low, high, close
940 // otherwise: low, high, close
941 uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDSContainer->getDataSeries());
942 const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
943 const sal_Int32 nSeriesPerCandleStick = bHasJapaneseCandlestick ? 4: 3;
944 sal_Int32 nCandleStickCount = nSeriesCount / nSeriesPerCandleStick;
945 OSL_ASSERT( nSeriesPerCandleStick * nCandleStickCount == nSeriesCount );
946 uno::Sequence< uno::Reference< chart2::XDataSeries > > aNewSeries( nCandleStickCount );
947 for( sal_Int32 i=0; i<nCandleStickCount; ++i )
949 sal_Int32 nSeriesIndex = i*nSeriesPerCandleStick;
950 if( bHasJapaneseCandlestick )
952 // open values
953 lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], "values-first");
954 aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
955 // low values
956 lcl_MoveDataToCandleStickSeries(
957 uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
958 aNewSeries[i], "values-min");
960 else
962 // low values
963 lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], "values-min");
964 aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
966 // high values
967 lcl_MoveDataToCandleStickSeries(
968 uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
969 aNewSeries[i], "values-max");
970 // close values
971 lcl_MoveDataToCandleStickSeries(
972 uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
973 aNewSeries[i], "values-last");
975 xDSContainer->setDataSeries( aNewSeries );
978 catch(const uno::Exception&)
980 SAL_WARN("xmloff.chart", "Exception while merging series for stock chart" );
984 SvXMLImportContext* SchXMLChartContext::CreateChildContext(
985 sal_uInt16 nPrefix,
986 const OUString& rLocalName,
987 const uno::Reference< xml::sax::XAttributeList >& xAttrList )
989 SvXMLImportContext* pContext = nullptr;
990 const SvXMLTokenMap& rTokenMap = mrImportHelper.GetChartElemTokenMap();
991 uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
992 uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
994 switch( rTokenMap.Get( nPrefix, rLocalName ))
996 case XML_TOK_CHART_PLOT_AREA:
997 pContext = new SchXMLPlotAreaContext( mrImportHelper, GetImport(), rLocalName,
998 m_aXLinkHRefAttributeToIndicateDataProvider,
999 msCategoriesAddress,
1000 msChartAddress, m_bHasRangeAtPlotArea, mbAllRangeAddressesAvailable,
1001 mbColHasLabels, mbRowHasLabels,
1002 meDataRowSource,
1003 maSeriesDefaultsAndStyles,
1004 maChartTypeServiceName,
1005 maLSequencesPerIndex, maChartSize );
1006 break;
1008 case XML_TOK_CHART_TITLE:
1009 if( xDoc.is())
1011 if( xProp.is())
1013 xProp->setPropertyValue("HasMainTitle", uno::makeAny(true) );
1015 uno::Reference< drawing::XShape > xTitleShape( xDoc->getTitle(), uno::UNO_QUERY );
1016 pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1017 rLocalName, maMainTitle, xTitleShape );
1019 break;
1021 case XML_TOK_CHART_SUBTITLE:
1022 if( xDoc.is())
1024 if( xProp.is())
1026 xProp->setPropertyValue("HasSubTitle", uno::makeAny(true) );
1028 uno::Reference< drawing::XShape > xTitleShape( xDoc->getSubTitle(), uno::UNO_QUERY );
1029 pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1030 rLocalName, maSubTitle, xTitleShape );
1032 break;
1034 case XML_TOK_CHART_LEGEND:
1035 pContext = new SchXMLLegendContext( mrImportHelper, GetImport(), rLocalName );
1036 break;
1038 case XML_TOK_CHART_TABLE:
1040 SchXMLTableContext * pTableContext =
1041 new SchXMLTableContext( mrImportHelper, GetImport(), rLocalName, maTable );
1042 m_bHasTableElement = true;
1043 // #i85913# take into account column- and row- mapping for
1044 // charts with own data only for those which were not copied
1045 // from a place where they got data from the container. Note,
1046 // that this requires the plot-area been read before the table
1047 // (which is required in the ODF spec)
1048 // Note: For stock charts and donut charts with special handling
1049 // the mapping must not be applied!
1050 if( msChartAddress.isEmpty() && !mbIsStockChart &&
1051 !lcl_SpecialHandlingForDonutChartNeeded(
1052 maChartTypeServiceName, GetImport()))
1054 if( !msColTrans.isEmpty() )
1056 OSL_ASSERT( msRowTrans.isEmpty() );
1057 pTableContext->setColumnPermutation( lcl_getNumberSequenceFromString( msColTrans, true ));
1058 msColTrans.clear();
1060 else if( !msRowTrans.isEmpty() )
1062 pTableContext->setRowPermutation( lcl_getNumberSequenceFromString( msRowTrans, true ));
1063 msRowTrans.clear();
1066 pContext = pTableContext;
1068 break;
1070 default:
1071 // try importing as an additional shape
1072 if( ! mxDrawPage.is())
1074 uno::Reference< drawing::XDrawPageSupplier > xSupp( xDoc, uno::UNO_QUERY );
1075 if( xSupp.is())
1076 mxDrawPage.set( xSupp->getDrawPage(), uno::UNO_QUERY );
1078 SAL_WARN_IF( !mxDrawPage.is(), "xmloff.chart", "Invalid Chart Page" );
1080 if( mxDrawPage.is())
1081 pContext = GetImport().GetShapeImport()->CreateGroupChildContext(
1082 GetImport(), nPrefix, rLocalName, xAttrList, mxDrawPage );
1083 break;
1086 if( ! pContext )
1087 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1089 return pContext;
1093 With a locked controller the following is done here:
1094 1. Hide title, subtitle, and legend.
1095 2. Set the size of the draw page.
1096 3. Set a (logically) empty data set.
1097 4. Set the chart type.
1099 void SchXMLChartContext::InitChart(
1100 const OUString & rChartTypeServiceName, // currently the old service name
1101 bool /* bSetSwitchData */ )
1103 uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1104 SAL_WARN_IF( !xDoc.is(), "xmloff.chart", "No valid document!" );
1105 uno::Reference< frame::XModel > xModel (xDoc, uno::UNO_QUERY );
1107 // Remove Title and Diagram ("De-InitNew")
1108 uno::Reference< chart2::XChartDocument > xNewDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
1109 if( xNewDoc.is())
1111 xNewDoc->setFirstDiagram( nullptr );
1112 uno::Reference< chart2::XTitled > xTitled( xNewDoc, uno::UNO_QUERY );
1113 if( xTitled.is())
1114 xTitled->setTitleObject( nullptr );
1117 // Set the chart type via setting the diagram.
1118 if( !rChartTypeServiceName.isEmpty() && xDoc.is())
1120 uno::Reference< lang::XMultiServiceFactory > xFact( xDoc, uno::UNO_QUERY );
1121 if( xFact.is())
1123 uno::Reference< chart::XDiagram > xDia( xFact->createInstance( rChartTypeServiceName ), uno::UNO_QUERY );
1124 if( xDia.is())
1125 xDoc->setDiagram( xDia );
1130 SchXMLTitleContext::SchXMLTitleContext( SchXMLImportHelper& rImpHelper, SvXMLImport& rImport,
1131 const OUString& rLocalName,
1132 OUString& rTitle,
1133 uno::Reference< drawing::XShape >& xTitleShape ) :
1134 SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
1135 mrImportHelper( rImpHelper ),
1136 mrTitle( rTitle ),
1137 mxTitleShape( xTitleShape )
1141 SchXMLTitleContext::~SchXMLTitleContext()
1144 void SchXMLTitleContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
1146 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
1148 css::awt::Point aPosition;
1149 bool bHasXPosition=false;
1150 bool bHasYPosition=false;
1152 for( sal_Int16 i = 0; i < nAttrCount; i++ )
1154 OUString sAttrName = xAttrList->getNameByIndex( i );
1155 OUString aLocalName;
1156 OUString aValue = xAttrList->getValueByIndex( i );
1157 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
1159 if( nPrefix == XML_NAMESPACE_SVG )
1161 if( IsXMLToken( aLocalName, XML_X ) )
1163 GetImport().GetMM100UnitConverter().convertMeasureToCore(
1164 aPosition.X, aValue );
1165 bHasXPosition = true;
1167 else if( IsXMLToken( aLocalName, XML_Y ) )
1169 GetImport().GetMM100UnitConverter().convertMeasureToCore(
1170 aPosition.Y, aValue );
1171 bHasYPosition = true;
1174 else if( nPrefix == XML_NAMESPACE_CHART )
1176 if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
1177 msAutoStyleName = aValue;
1181 if( mxTitleShape.is())
1183 if( bHasXPosition && bHasYPosition )
1184 mxTitleShape->setPosition( aPosition );
1186 uno::Reference< beans::XPropertySet > xProp( mxTitleShape, uno::UNO_QUERY );
1187 if( xProp.is())
1189 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
1190 if( pStylesCtxt )
1192 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
1193 SchXMLImportHelper::GetChartFamilyID(), msAutoStyleName );
1195 if( pStyle && dynamic_cast< const XMLPropStyleContext*>(pStyle) != nullptr)
1196 const_cast<XMLPropStyleContext*>( static_cast< const XMLPropStyleContext* >( pStyle ) )->FillPropertySet( xProp );
1202 SvXMLImportContext* SchXMLTitleContext::CreateChildContext(
1203 sal_uInt16 nPrefix,
1204 const OUString& rLocalName,
1205 const uno::Reference< xml::sax::XAttributeList >& )
1207 SvXMLImportContext* pContext = nullptr;
1209 if( (nPrefix == XML_NAMESPACE_TEXT ||
1210 nPrefix == XML_NAMESPACE_LO_EXT) &&
1211 IsXMLToken( rLocalName, XML_P ) )
1213 pContext = new SchXMLParagraphContext( GetImport(), rLocalName, mrTitle );
1215 else
1216 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1218 return pContext;
1221 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */