Bump for 3.6-28
[LibreOffice.git] / xmloff / source / chart / SchXMLChartContext.cxx
blob801d4122508fb3a63309319e7fd5119ec2ffe47b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "SchXMLChartContext.hxx"
31 #include "SchXMLImport.hxx"
32 #include "SchXMLLegendContext.hxx"
33 #include "SchXMLPlotAreaContext.hxx"
34 #include "SchXMLParagraphContext.hxx"
35 #include "SchXMLTableContext.hxx"
36 #include "SchXMLSeriesHelper.hxx"
37 #include "SchXMLSeries2Context.hxx"
38 #include "SchXMLTools.hxx"
39 #include <comphelper/mediadescriptor.hxx>
40 #include <tools/debug.hxx>
41 #include "xmloff/xmlnmspe.hxx"
42 #include <xmloff/xmlement.hxx>
43 #include <xmloff/xmltoken.hxx>
44 #include <xmloff/nmspmap.hxx>
45 #include <xmloff/xmluconv.hxx>
46 #include <xmloff/xmlstyle.hxx>
47 #include <xmloff/prstylei.hxx>
49 #include "vector"
50 #include <com/sun/star/chart/XChartDocument.hpp>
51 #include <com/sun/star/chart/XDiagram.hpp>
52 #include <com/sun/star/xml/sax/XAttributeList.hpp>
53 #include <com/sun/star/util/XStringMapping.hpp>
54 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
55 #include <com/sun/star/drawing/XDrawPage.hpp>
56 #include <com/sun/star/chart/ChartDataRowSource.hpp>
57 #include <com/sun/star/awt/PosSize.hpp>
58 #include <com/sun/star/embed/Aspects.hpp>
59 #include <com/sun/star/embed/XVisualObject.hpp>
61 #include <com/sun/star/chart2/XChartDocument.hpp>
62 #include <com/sun/star/chart2/data/XDataSink.hpp>
63 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
64 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
65 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
66 #include <com/sun/star/chart2/XTitled.hpp>
68 using namespace com::sun::star;
69 using namespace ::xmloff::token;
70 using ::rtl::OUString;
71 using com::sun::star::uno::Reference;
72 using namespace ::SchXMLTools;
74 namespace
77 void lcl_setRoleAtLabeledSequence(
78 const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq,
79 const ::rtl::OUString &rRole )
81 // set role of sequence
82 uno::Reference< chart2::data::XDataSequence > xValues( xLSeq->getValues());
83 if( xValues.is())
85 uno::Reference< beans::XPropertySet > xProp( xValues, uno::UNO_QUERY );
86 if( xProp.is())
87 xProp->setPropertyValue(OUString( "Role" ), uno::makeAny( rRole ));
91 void lcl_MoveDataToCandleStickSeries(
92 const uno::Reference< chart2::data::XDataSource > & xDataSource,
93 const uno::Reference< chart2::XDataSeries > & xDestination,
94 const OUString & rRole )
96 try
98 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq(
99 xDataSource->getDataSequences());
100 if( aLabeledSeq.getLength())
102 lcl_setRoleAtLabeledSequence( aLabeledSeq[0], rRole );
104 // add to data series
105 uno::Reference< chart2::data::XDataSource > xSource( xDestination, uno::UNO_QUERY_THROW );
106 // @todo: realloc only once outside this function
107 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences());
108 aData.realloc( aData.getLength() + 1);
109 aData[ aData.getLength() - 1 ] = aLabeledSeq[0];
110 uno::Reference< chart2::data::XDataSink > xSink( xDestination, uno::UNO_QUERY_THROW );
111 xSink->setData( aData );
114 catch(const uno::Exception&)
116 OSL_FAIL( "Exception caught while moving data to candlestick series" );
120 void lcl_setRoleAtFirstSequence(
121 const uno::Reference< chart2::XDataSeries > & xSeries,
122 const ::rtl::OUString & rRole )
124 uno::Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
125 if( xSource.is())
127 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
128 if( aSeq.getLength())
129 lcl_setRoleAtLabeledSequence( aSeq[0], rRole );
133 void lcl_removeEmptyChartTypeGroups( const uno::Reference< chart2::XChartDocument > & xDoc )
135 if( ! xDoc.is())
136 return;
138 uno::Reference< chart2::XDiagram > xDia( xDoc->getFirstDiagram());
139 if( ! xDia.is())
140 return;
144 // count all charttype groups to be able to leave at least one
145 sal_Int32 nRemainingGroups = 0;
146 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDia, uno::UNO_QUERY_THROW );
147 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > >
148 aCooSysSeq( xCooSysCnt->getCoordinateSystems());
149 for( sal_Int32 nI = aCooSysSeq.getLength(); nI--; )
151 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nI], uno::UNO_QUERY_THROW );
152 nRemainingGroups += xCTCnt->getChartTypes().getLength();
155 // delete all empty groups, but leave at least group (empty or not)
156 for( sal_Int32 nI = aCooSysSeq.getLength(); nI-- && (nRemainingGroups > 1); )
158 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nI], uno::UNO_QUERY_THROW );
159 uno::Sequence< uno::Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
160 for( sal_Int32 nJ=aCTSeq.getLength(); nJ-- && (nRemainingGroups > 1); )
162 uno::Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nJ], uno::UNO_QUERY_THROW );
163 if( xDSCnt->getDataSeries().getLength() == 0 )
165 // note: iterator stays valid as we have a local sequence
166 xCTCnt->removeChartType( aCTSeq[nJ] );
167 --nRemainingGroups;
172 catch(const uno::Exception& ex)
174 rtl::OString aBStr(rtl::OUStringToOString(ex.Message, RTL_TEXTENCODING_ASCII_US));
175 OSL_TRACE( "Exception caught while removing empty chart types: %s", aBStr.getStr());
179 uno::Sequence< sal_Int32 > lcl_getNumberSequenceFromString( const ::rtl::OUString& rStr, bool bAddOneToEachOldIndex )
181 const sal_Unicode aSpace( ' ' );
183 // count number of entries
184 ::std::vector< sal_Int32 > aVec;
185 sal_Int32 nLastPos = 0;
186 sal_Int32 nPos = 0;
187 while( nPos != -1 )
189 nPos = rStr.indexOf( aSpace, nLastPos );
190 if( nPos > nLastPos )
192 aVec.push_back( rStr.copy( nLastPos, (nPos - nLastPos) ).toInt32() );
194 if( nPos != -1 )
195 nLastPos = nPos + 1;
197 // last entry
198 if( nLastPos != 0 &&
199 rStr.getLength() > nLastPos )
201 aVec.push_back( rStr.copy( nLastPos, (rStr.getLength() - nLastPos) ).toInt32() );
204 const sal_Int32 nVecSize = aVec.size();
205 uno::Sequence< sal_Int32 > aSeq( nVecSize );
207 if(!bAddOneToEachOldIndex)
209 sal_Int32* pSeqArr = aSeq.getArray();
210 for( nPos = 0; nPos < nVecSize; ++nPos )
212 pSeqArr[ nPos ] = aVec[ nPos ];
215 else if( bAddOneToEachOldIndex )
217 aSeq.realloc( nVecSize+1 );
218 aSeq[0]=0;
220 sal_Int32* pSeqArr = aSeq.getArray();
221 for( nPos = 0; nPos < nVecSize; ++nPos )
223 pSeqArr[ nPos+1 ] = aVec[ nPos ]+1;
227 return aSeq;
230 } // anonymous namespace
232 // ----------------------------------------
234 SchXMLChartContext::SchXMLChartContext( SchXMLImportHelper& rImpHelper,
235 SvXMLImport& rImport, const rtl::OUString& rLocalName ) :
236 SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
237 mrImportHelper( rImpHelper ),
238 m_bHasRangeAtPlotArea( false ),
239 m_bHasTableElement( false ),
240 mbAllRangeAddressesAvailable( sal_True ),
241 mbColHasLabels( sal_False ),
242 mbRowHasLabels( sal_False ),
243 meDataRowSource( chart::ChartDataRowSource_COLUMNS ),
244 mbIsStockChart( false )
248 SchXMLChartContext::~SchXMLChartContext()
251 void SchXMLChartContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
253 // parse attributes
254 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
255 const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetChartAttrTokenMap();
257 uno::Reference< embed::XVisualObject > xVisualObject( mrImportHelper.GetChartDocument(), uno::UNO_QUERY);
258 DBG_ASSERT(xVisualObject.is(),"need xVisualObject for page size");
259 if( xVisualObject.is() )
260 maChartSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); //#i103460# take the size given from the parent frame as default
262 // this flag is necessarry for pie charts in the core
263 sal_Bool bSetSwitchData = sal_False;
265 ::rtl::OUString sAutoStyleName;
266 ::rtl::OUString aOldChartTypeName;
267 bool bHasAddin = false;
269 for( sal_Int16 i = 0; i < nAttrCount; i++ )
271 rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
272 rtl::OUString aLocalName;
273 rtl::OUString aValue = xAttrList->getValueByIndex( i );
274 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
276 switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
278 case XML_TOK_CHART_HREF:
279 m_aXLinkHRefAttributeToIndicateDataProvider = aValue;
280 break;
282 case XML_TOK_CHART_CLASS:
284 rtl::OUString sClassName;
285 sal_uInt16 nClassPrefix =
286 GetImport().GetNamespaceMap().GetKeyByAttrName(
287 aValue, &sClassName );
288 if( XML_NAMESPACE_CHART == nClassPrefix )
290 SchXMLChartTypeEnum eChartTypeEnum = SchXMLTools::GetChartTypeEnum( sClassName );
291 if( eChartTypeEnum != XML_CHART_CLASS_UNKNOWN )
293 aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( sClassName, true /* bUseOldNames */ );
294 maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( sClassName, false /* bUseOldNames */ );
295 switch( eChartTypeEnum )
297 case XML_CHART_CLASS_CIRCLE:
298 bSetSwitchData = sal_True;
299 break;
300 case XML_CHART_CLASS_STOCK:
301 mbIsStockChart = true;
302 break;
303 default:
304 break;
308 else if( XML_NAMESPACE_OOO == nClassPrefix )
310 // service is taken from add-in-name attribute
311 bHasAddin = true;
313 aOldChartTypeName = sClassName;
314 maChartTypeServiceName = sClassName;
317 break;
319 case XML_TOK_CHART_WIDTH:
320 GetImport().GetMM100UnitConverter().convertMeasureToCore(
321 maChartSize.Width, aValue );
322 break;
324 case XML_TOK_CHART_HEIGHT:
325 GetImport().GetMM100UnitConverter().convertMeasureToCore(
326 maChartSize.Height, aValue );
327 break;
329 case XML_TOK_CHART_STYLE_NAME:
330 sAutoStyleName = aValue;
331 break;
333 case XML_TOK_CHART_COL_MAPPING:
334 msColTrans = aValue;
335 break;
336 case XML_TOK_CHART_ROW_MAPPING:
337 msRowTrans = aValue;
338 break;
342 if( aOldChartTypeName.isEmpty() )
344 OSL_FAIL( "need a charttype to create a diagram" );
345 //set a fallback value:
346 ::rtl::OUString aChartClass_Bar( GetXMLToken(XML_BAR ) );
347 aOldChartTypeName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, true /* bUseOldNames */ );
348 maChartTypeServiceName = SchXMLTools::GetChartTypeByClassName( aChartClass_Bar, false /* bUseOldNames */ );
351 // Set the size of the draw page.
352 if( xVisualObject.is() )
353 xVisualObject->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, maChartSize );
355 InitChart( aOldChartTypeName, bSetSwitchData);
357 if( bHasAddin )
359 //correct charttype serveice name when having an addin
360 //and don't refresh addin during load
361 uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
362 if( xDocProp.is() )
366 xDocProp->getPropertyValue( ::rtl::OUString( "BaseDiagram" )) >>= aOldChartTypeName;
367 maChartTypeServiceName = SchXMLTools::GetNewChartTypeName( aOldChartTypeName );
368 xDocProp->setPropertyValue( rtl::OUString( "RefreshAddInAllowed" ) , uno::makeAny( sal_False) );
370 catch(const uno::Exception&)
372 OSL_FAIL( "Exception during import SchXMLChartContext::StartElement" );
377 // set auto-styles for Area
378 uno::Reference< beans::XPropertySet > xProp( mrImportHelper.GetChartDocument()->getArea(), uno::UNO_QUERY );
379 if( xProp.is())
381 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
382 if( pStylesCtxt )
384 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
385 mrImportHelper.GetChartFamilyID(), sAutoStyleName );
387 if( pStyle && pStyle->ISA( XMLPropStyleContext ))
388 (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
393 namespace
396 struct NewDonutSeries
398 ::com::sun::star::uno::Reference<
399 ::com::sun::star::chart2::XDataSeries > m_xSeries;
400 ::rtl::OUString msStyleName;
401 sal_Int32 mnAttachedAxis;
403 ::std::vector< ::rtl::OUString > m_aSeriesStyles;
404 ::std::vector< ::rtl::OUString > m_aPointStyles;
406 NewDonutSeries( const ::com::sun::star::uno::Reference<
407 ::com::sun::star::chart2::XDataSeries >& xSeries, sal_Int32 nPointCount )
408 : m_xSeries( xSeries )
409 , mnAttachedAxis( 1 )
411 m_aPointStyles.resize(nPointCount);
412 m_aSeriesStyles.resize(nPointCount);
415 void setSeriesStyleNameToPoint( const ::rtl::OUString& rStyleName, sal_Int32 nPointIndex )
417 DBG_ASSERT(nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()),"donut point <-> series count mismatch");
418 if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
419 m_aSeriesStyles[nPointIndex]=rStyleName;
422 void setPointStyleNameToPoint( const ::rtl::OUString& rStyleName, sal_Int32 nPointIndex )
424 DBG_ASSERT(nPointIndex < static_cast<sal_Int32>(m_aPointStyles.size()),"donut point <-> series count mismatch");
425 if( nPointIndex < static_cast<sal_Int32>(m_aPointStyles.size()) )
426 m_aPointStyles[nPointIndex]=rStyleName;
429 ::std::list< DataRowPointStyle > creatStyleList()
431 ::std::list< DataRowPointStyle > aRet;
433 DataRowPointStyle aSeriesStyle( DataRowPointStyle::DATA_SERIES
434 , m_xSeries, -1, 1, msStyleName, mnAttachedAxis );
435 aRet.push_back( aSeriesStyle );
437 sal_Int32 nPointIndex=0;
438 ::std::vector< ::rtl::OUString >::iterator aPointIt( m_aPointStyles.begin() );
439 ::std::vector< ::rtl::OUString >::iterator aPointEnd( m_aPointStyles.end() );
440 while( aPointIt != aPointEnd )
442 DataRowPointStyle aPointStyle( DataRowPointStyle::DATA_POINT
443 , m_xSeries, nPointIndex, 1, *aPointIt, mnAttachedAxis );
444 if( nPointIndex < static_cast<sal_Int32>(m_aSeriesStyles.size()) )
446 aPointStyle.msSeriesStyleNameForDonuts = m_aSeriesStyles[nPointIndex];
448 if( !aPointStyle.msSeriesStyleNameForDonuts.isEmpty()
449 || !aPointStyle.msStyleName.isEmpty() )
450 aRet.push_back( aPointStyle );
451 ++aPointIt;
452 ++nPointIndex;
455 return aRet;
459 void lcl_swapPointAndSeriesStylesForDonutCharts( ::std::list< DataRowPointStyle >& rStyleList
460 , const ::std::map< ::com::sun::star::uno::Reference<
461 ::com::sun::star::chart2::XDataSeries> , sal_Int32 >& rSeriesMap )
463 ::std::list< DataRowPointStyle >::iterator aIt(rStyleList.begin());
464 ::std::list< DataRowPointStyle >::iterator aEnd(rStyleList.end());
466 //detect old series count
467 //and add old series to aSeriesMap
468 ::std::map< ::com::sun::star::uno::Reference<
469 ::com::sun::star::chart2::XDataSeries >, sal_Int32 > aSeriesMap(rSeriesMap);
470 sal_Int32 nOldSeriesCount = 0;
472 sal_Int32 nMaxOldSeriesIndex = 0;
473 sal_Int32 nOldSeriesIndex = 0;
474 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
476 DataRowPointStyle aStyle(*aIt);
477 if(aStyle.meType == DataRowPointStyle::DATA_SERIES &&
478 aStyle.m_xSeries.is() )
480 nMaxOldSeriesIndex = nOldSeriesIndex;
482 if( aSeriesMap.end() == aSeriesMap.find(aStyle.m_xSeries) )
483 aSeriesMap[aStyle.m_xSeries] = nOldSeriesIndex;
485 nOldSeriesIndex++;
488 nOldSeriesCount = nMaxOldSeriesIndex+1;
492 //initialize new series styles
493 ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapIt( aSeriesMap.begin() );
494 ::std::map< Reference< chart2::XDataSeries >, sal_Int32 >::const_iterator aSeriesMapEnd( aSeriesMap.end() );
496 //sort by index
497 ::std::vector< NewDonutSeries > aNewSeriesVector;
499 ::std::map< sal_Int32, Reference< chart2::XDataSeries > > aIndexSeriesMap;
500 for( ; aSeriesMapIt != aSeriesMapEnd; ++aSeriesMapIt )
501 aIndexSeriesMap[aSeriesMapIt->second] = aSeriesMapIt->first;
503 ::std::map< sal_Int32, Reference< chart2::XDataSeries > >::const_iterator aIndexIt( aIndexSeriesMap.begin() );
504 ::std::map< sal_Int32, Reference< chart2::XDataSeries > >::const_iterator aIndexEnd( aIndexSeriesMap.end() );
506 for( ; aIndexIt != aIndexEnd; ++aIndexIt )
507 aNewSeriesVector.push_back( NewDonutSeries(aIndexIt->second,nOldSeriesCount) );
510 //overwrite attached axis information according to old series styles
511 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
513 DataRowPointStyle aStyle(*aIt);
514 if(aStyle.meType == DataRowPointStyle::DATA_SERIES )
516 aSeriesMapIt = aSeriesMap.find( aStyle.m_xSeries );
517 if( aSeriesMapIt != aSeriesMapEnd && aSeriesMapIt->second < static_cast<sal_Int32>(aNewSeriesVector.size()) )
518 aNewSeriesVector[aSeriesMapIt->second].mnAttachedAxis = aStyle.mnAttachedAxis;
522 //overwrite new series style names with old series style name information
523 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
525 DataRowPointStyle aStyle(*aIt);
526 if( aStyle.meType == DataRowPointStyle::DATA_SERIES )
528 aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
529 if( aSeriesMapEnd != aSeriesMapIt )
531 sal_Int32 nNewPointIndex = aSeriesMapIt->second;
533 ::std::vector< NewDonutSeries >::iterator aNewSeriesIt( aNewSeriesVector.begin() );
534 ::std::vector< NewDonutSeries >::iterator aNewSeriesEnd( aNewSeriesVector.end() );
536 for( ;aNewSeriesIt!=aNewSeriesEnd; ++aNewSeriesIt)
537 aNewSeriesIt->setSeriesStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
542 //overwrite new series style names with point style name information
543 for( aIt = rStyleList.begin(); aIt != aEnd; ++aIt )
545 DataRowPointStyle aStyle(*aIt);
546 if( aStyle.meType == DataRowPointStyle::DATA_POINT )
548 aSeriesMapIt = aSeriesMap.find(aStyle.m_xSeries);
549 if( aSeriesMapEnd != aSeriesMapIt )
551 sal_Int32 nNewPointIndex = aSeriesMapIt->second;
552 sal_Int32 nNewSeriesIndex = aStyle.m_nPointIndex;
553 sal_Int32 nRepeatCount = aStyle.m_nPointRepeat;
555 while( nRepeatCount && (nNewSeriesIndex>=0) && (nNewSeriesIndex< static_cast<sal_Int32>(aNewSeriesVector.size()) ) )
557 NewDonutSeries& rNewSeries( aNewSeriesVector[nNewSeriesIndex] );
558 rNewSeries.setPointStyleNameToPoint( aStyle.msStyleName, nNewPointIndex );
560 nRepeatCount--;
561 nNewSeriesIndex++;
567 //put information from aNewSeriesVector to output parameter rStyleList
568 rStyleList.clear();
570 ::std::vector< NewDonutSeries >::iterator aNewSeriesIt( aNewSeriesVector.begin() );
571 ::std::vector< NewDonutSeries >::iterator aNewSeriesEnd( aNewSeriesVector.end() );
572 for( ;aNewSeriesIt!=aNewSeriesEnd; ++aNewSeriesIt)
574 ::std::list< DataRowPointStyle > aList( aNewSeriesIt->creatStyleList() );
575 rStyleList.insert(rStyleList.end(),aList.begin(),aList.end());
579 bool lcl_SpecialHandlingForDonutChartNeeded(
580 const ::rtl::OUString & rServiceName,
581 const SvXMLImport & rImport )
583 bool bResult = false;
584 if( rServiceName == "com.sun.star.chart2.DonutChartType" )
586 bResult = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( rImport.GetModel() );
588 return bResult;
591 } // anonymous namespace
594 void lcl_ApplyDataFromRectangularRangeToDiagram(
595 const uno::Reference< chart2::XChartDocument >& xNewDoc
596 , const rtl::OUString& rRectangularRange
597 , ::com::sun::star::chart::ChartDataRowSource eDataRowSource
598 , bool bRowHasLabels, bool bColHasLabels
599 , bool bSwitchOnLabelsAndCategoriesForOwnData
600 , const rtl::OUString& sColTrans
601 , const rtl::OUString& sRowTrans )
603 if( !xNewDoc.is() )
604 return;
606 uno::Reference< chart2::XDiagram > xNewDia( xNewDoc->getFirstDiagram());
607 uno::Reference< chart2::data::XDataProvider > xDataProvider( xNewDoc->getDataProvider() );
608 if( !xNewDia.is() || !xDataProvider.is() )
609 return;
611 sal_Bool bFirstCellAsLabel =
612 (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bRowHasLabels : bColHasLabels;
613 sal_Bool bHasCateories =
614 (eDataRowSource==chart::ChartDataRowSource_COLUMNS)? bColHasLabels : bRowHasLabels;
616 if( bSwitchOnLabelsAndCategoriesForOwnData )
618 bFirstCellAsLabel = true;
619 bHasCateories = true;
622 uno::Sequence< beans::PropertyValue > aArgs( 3 );
623 aArgs[0] = beans::PropertyValue(
624 ::rtl::OUString( "CellRangeRepresentation" ),
625 -1, uno::makeAny( rRectangularRange ),
626 beans::PropertyState_DIRECT_VALUE );
627 aArgs[1] = beans::PropertyValue(
628 ::rtl::OUString( "DataRowSource" ),
629 -1, uno::makeAny( eDataRowSource ),
630 beans::PropertyState_DIRECT_VALUE );
631 aArgs[2] = beans::PropertyValue(
632 ::rtl::OUString( "FirstCellAsLabel" ),
633 -1, uno::makeAny( bFirstCellAsLabel ),
634 beans::PropertyState_DIRECT_VALUE );
636 if( !sColTrans.isEmpty() || !sRowTrans.isEmpty() )
638 aArgs.realloc( aArgs.getLength() + 1 );
639 aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue(
640 ::rtl::OUString( "SequenceMapping" ),
641 -1, uno::makeAny( !sColTrans.isEmpty()
642 ? lcl_getNumberSequenceFromString( sColTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() )
643 : lcl_getNumberSequenceFromString( sRowTrans, bHasCateories && !xNewDoc->hasInternalDataProvider() ) ),
644 beans::PropertyState_DIRECT_VALUE );
647 //work around wrong writer ranges ( see Issue 58464 )
649 rtl::OUString aChartOleObjectName;
650 uno::Reference< frame::XModel > xModel(xNewDoc, uno::UNO_QUERY );
651 if( xModel.is() )
653 comphelper::MediaDescriptor aMediaDescriptor( xModel->getArgs() );
655 comphelper::MediaDescriptor::const_iterator aIt(
656 aMediaDescriptor.find( rtl::OUString( "HierarchicalDocumentName" )));
657 if( aIt != aMediaDescriptor.end() )
659 aChartOleObjectName = (*aIt).second.get< ::rtl::OUString >();
662 if( !aChartOleObjectName.isEmpty() )
664 aArgs.realloc( aArgs.getLength() + 1 );
665 aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue(
666 ::rtl::OUString( "ChartOleObjectName" ),
667 -1, uno::makeAny( aChartOleObjectName ),
668 beans::PropertyState_DIRECT_VALUE );
673 uno::Reference< chart2::data::XDataSource > xDataSource(
674 xDataProvider->createDataSource( aArgs ));
676 aArgs.realloc( aArgs.getLength() + 2 );
677 aArgs[ aArgs.getLength() - 2 ] = beans::PropertyValue(
678 ::rtl::OUString( "HasCategories" ),
679 -1, uno::makeAny( bHasCateories ),
680 beans::PropertyState_DIRECT_VALUE );
681 aArgs[ aArgs.getLength() - 1 ] = beans::PropertyValue(
682 ::rtl::OUString("UseCategoriesAsX"),
683 -1, uno::makeAny( sal_False ),//categories in ODF files are not to be used as x values (independent from what is offered in our ui)
684 beans::PropertyState_DIRECT_VALUE );
686 xNewDia->setDiagramData( xDataSource, aArgs );
689 void SchXMLChartContext::EndElement()
691 uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
692 uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
693 uno::Reference< chart2::XChartDocument > xNewDoc( xDoc, uno::UNO_QUERY );
695 if( xProp.is())
697 if( !maMainTitle.isEmpty())
699 uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getTitle(), uno::UNO_QUERY );
700 if( xTitleProp.is())
704 uno::Any aAny;
705 aAny <<= maMainTitle;
706 xTitleProp->setPropertyValue( rtl::OUString( "String" ), aAny );
708 catch(const beans::UnknownPropertyException&)
710 OSL_FAIL( "Property String for Title not available" );
714 if( !maSubTitle.isEmpty())
716 uno::Reference< beans::XPropertySet > xTitleProp( xDoc->getSubTitle(), uno::UNO_QUERY );
717 if( xTitleProp.is())
721 uno::Any aAny;
722 aAny <<= maSubTitle;
723 xTitleProp->setPropertyValue( rtl::OUString( "String" ), aAny );
725 catch(const beans::UnknownPropertyException&)
727 OSL_FAIL( "Property String for Title not available" );
733 // cleanup: remove empty chart type groups
734 lcl_removeEmptyChartTypeGroups( xNewDoc );
736 // set stack mode before a potential chart type detection (in case we have a rectangular range)
737 uno::Reference< chart::XDiagram > xDiagram( xDoc->getDiagram() );
738 uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
739 if( xDiaProp.is())
741 if( maSeriesDefaultsAndStyles.maStackedDefault.hasValue())
742 xDiaProp->setPropertyValue(::rtl::OUString("Stacked"),maSeriesDefaultsAndStyles.maStackedDefault);
743 if( maSeriesDefaultsAndStyles.maPercentDefault.hasValue())
744 xDiaProp->setPropertyValue(::rtl::OUString("Percent"),maSeriesDefaultsAndStyles.maPercentDefault);
745 if( maSeriesDefaultsAndStyles.maDeepDefault.hasValue())
746 xDiaProp->setPropertyValue(::rtl::OUString("Deep"),maSeriesDefaultsAndStyles.maDeepDefault);
747 if( maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault.hasValue())
748 xDiaProp->setPropertyValue(::rtl::OUString("StackedBarsConnected"),maSeriesDefaultsAndStyles.maStackedBarsConnectedDefault);
751 //the OOo 2.0 implementation and older has a bug with donuts
752 bool bSpecialHandlingForDonutChart = lcl_SpecialHandlingForDonutChartNeeded(
753 maChartTypeServiceName, GetImport());
755 // apply data
756 if(!xNewDoc.is())
757 return;
759 bool bHasOwnData = false;
760 if( m_aXLinkHRefAttributeToIndicateDataProvider == "." ) //data comes from the chart itself
761 bHasOwnData = true;
762 else if( m_aXLinkHRefAttributeToIndicateDataProvider == ".." ) //data comes from the parent application
763 bHasOwnData = false;
764 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
765 bHasOwnData = m_bHasTableElement;
766 else
767 bHasOwnData = !m_bHasRangeAtPlotArea;
769 if( xNewDoc->hasInternalDataProvider())
771 if( !m_bHasTableElement && m_aXLinkHRefAttributeToIndicateDataProvider != "." )
773 //#i103147# ODF, workaround broken files with a missing table:cell-range-address at the plot-area
774 bool bSwitchSuccessful = SchXMLTools::switchBackToDataProviderFromParent( xNewDoc, maLSequencesPerIndex );
775 bHasOwnData = !bSwitchSuccessful;
777 else
778 bHasOwnData = true;//e.g. in case of copy->paste from calc to impress
780 else if( bHasOwnData )
782 xNewDoc->createInternalDataProvider( sal_False /* bCloneExistingData */ );
784 if( bHasOwnData )
785 msChartAddress = ::rtl::OUString( "all" );
787 bool bSwitchRangesFromOuterToInternalIfNecessary = false;
788 if( !bHasOwnData && mbAllRangeAddressesAvailable )
790 // special handling for stock chart (merge series together)
791 if( mbIsStockChart )
792 MergeSeriesForStockChart();
794 else if( !msChartAddress.isEmpty() )
796 //own data or only rectangular range available
798 if( xNewDoc->hasInternalDataProvider() )
799 SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc );
801 bool bOlderThan2_3 = SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( Reference< frame::XModel >( xNewDoc, uno::UNO_QUERY ));
802 bool bOldFileWithOwnDataFromRows = (bOlderThan2_3 && bHasOwnData && (meDataRowSource==chart::ChartDataRowSource_ROWS)); // in this case there are range addresses that are simply wrong.
804 if( mbAllRangeAddressesAvailable && !bSpecialHandlingForDonutChart && !mbIsStockChart &&
805 !bOldFileWithOwnDataFromRows )
807 //bHasOwnData is true in this case!
808 //e.g. for normal files with own data or also in case of copy paste scenario (e.g. calc to impress)
809 bSwitchRangesFromOuterToInternalIfNecessary = true;
811 else
813 //apply data from rectangular range
815 // create datasource from data provider with rectangular range parameters and change the diagram setDiagramData
818 if( bOlderThan2_3 && xDiaProp.is() )//for older charts the hidden cells were removed by calc on the fly
819 xDiaProp->setPropertyValue(::rtl::OUString("IncludeHiddenCells"),uno::makeAny(false));
821 // note: mbRowHasLabels means the first row contains labels, that means we have "column-descriptions",
822 // (analogously mbColHasLabels means we have "row-descriptions")
823 lcl_ApplyDataFromRectangularRangeToDiagram( xNewDoc, msChartAddress, meDataRowSource, mbRowHasLabels, mbColHasLabels, bHasOwnData, msColTrans, msRowTrans );
825 catch(const uno::Exception&)
827 //try to fallback to internal data
828 OSL_FAIL( "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram try to fallback to internal data" );
829 if(!bHasOwnData)
831 bHasOwnData = true;
832 msChartAddress = ::rtl::OUString( "all" );
833 if( !xNewDoc->hasInternalDataProvider() )
835 xNewDoc->createInternalDataProvider( sal_False /* bCloneExistingData */ );
836 SchXMLTableHelper::applyTableToInternalDataProvider( maTable, xNewDoc );
839 lcl_ApplyDataFromRectangularRangeToDiagram( xNewDoc, msChartAddress, meDataRowSource, mbRowHasLabels, mbColHasLabels, bHasOwnData, msColTrans, msRowTrans );
841 catch(const uno::Exception&)
843 OSL_FAIL( "Exception during import SchXMLChartContext::lcl_ApplyDataFromRectangularRangeToDiagram fallback to internal data failed also" );
850 else
852 OSL_FAIL( " Must not get here" );
855 // now all series and data point properties are available and can be set
857 if( bSpecialHandlingForDonutChart )
859 uno::Reference< chart2::XDiagram > xNewDiagram( xNewDoc->getFirstDiagram() );
860 lcl_swapPointAndSeriesStylesForDonutCharts( maSeriesDefaultsAndStyles.maSeriesStyleList
861 , SchXMLSeriesHelper::getDataSeriesIndexMapFromDiagram(xNewDiagram) );
864 SchXMLSeries2Context::initSeriesPropertySets( maSeriesDefaultsAndStyles, uno::Reference< frame::XModel >(xDoc, uno::UNO_QUERY ) );
866 //set defaults from diagram to the new series:
867 //check whether we need to remove lines from symbol only charts
868 bool bSwitchOffLinesForScatter = false;
870 bool bLinesOn = true;
871 if( (maSeriesDefaultsAndStyles.maLinesOnProperty >>= bLinesOn) && !bLinesOn )
873 if( 0 == maChartTypeServiceName.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart2.ScatterChartType" ) ) )
875 bSwitchOffLinesForScatter = true;
876 SchXMLSeries2Context::switchSeriesLinesOff( maSeriesDefaultsAndStyles.maSeriesStyleList );
880 SchXMLSeries2Context::setDefaultsToSeries( maSeriesDefaultsAndStyles );
882 // set autostyles for series and data points
883 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
884 const SvXMLStyleContext* pStyle = NULL;
885 ::rtl::OUString sCurrStyleName;
887 if( pStylesCtxt )
889 //iterate over data-series first
890 //don't set series styles for donut charts
891 if( !bSpecialHandlingForDonutChart )
893 SchXMLSeries2Context::setStylesToSeries( maSeriesDefaultsAndStyles
894 , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, GetImport(), mbIsStockChart, maLSequencesPerIndex );
895 // ... then set attributes for statistics (after their existence was set in the series)
896 SchXMLSeries2Context::setStylesToStatisticsObjects( maSeriesDefaultsAndStyles
897 , pStylesCtxt, pStyle, sCurrStyleName );
901 //#i98319# call switchRangesFromOuterToInternalIfNecessary before the data point styles are applied, otherwise in copy->paste scenario the data point styles do get lost
902 if( bSwitchRangesFromOuterToInternalIfNecessary )
904 if( xNewDoc->hasInternalDataProvider() )
905 SchXMLTableHelper::switchRangesFromOuterToInternalIfNecessary( maTable, maLSequencesPerIndex, xNewDoc, meDataRowSource );
908 if( pStylesCtxt )
910 // ... then iterate over data-point attributes, so the latter are not overwritten
911 SchXMLSeries2Context::setStylesToDataPoints( maSeriesDefaultsAndStyles
912 , pStylesCtxt, pStyle, sCurrStyleName, mrImportHelper, GetImport(), mbIsStockChart, bSpecialHandlingForDonutChart, bSwitchOffLinesForScatter );
916 if( xProp.is())
917 xProp->setPropertyValue( rtl::OUString( "RefreshAddInAllowed" ) , uno::makeAny( sal_True) );
920 void SchXMLChartContext::MergeSeriesForStockChart()
922 OSL_ASSERT( mbIsStockChart );
925 uno::Reference< chart::XChartDocument > xOldDoc( mrImportHelper.GetChartDocument());
926 uno::Reference< chart2::XChartDocument > xDoc( xOldDoc, uno::UNO_QUERY_THROW );
927 uno::Reference< chart2::XDiagram > xDiagram( xDoc->getFirstDiagram());
928 if( ! xDiagram.is())
929 return;
931 bool bHasJapaneseCandlestick = true;
932 uno::Reference< chart2::XDataSeriesContainer > xDSContainer;
933 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
934 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
935 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
937 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
938 uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
939 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
941 if( aChartTypes[nCTIdx]->getChartType() == "com.sun.star.chart2.CandleStickChartType" )
943 xDSContainer.set( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
944 uno::Reference< beans::XPropertySet > xCTProp( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
945 xCTProp->getPropertyValue( ::rtl::OUString( "Japanese" )) >>= bHasJapaneseCandlestick;
946 break;
951 if( xDSContainer.is())
953 // with japanese candlesticks: open, low, high, close
954 // otherwise: low, high, close
955 uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDSContainer->getDataSeries());
956 const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
957 const sal_Int32 nSeriesPerCandleStick = bHasJapaneseCandlestick ? 4: 3;
958 sal_Int32 nCandleStickCount = nSeriesCount / nSeriesPerCandleStick;
959 OSL_ASSERT( nSeriesPerCandleStick * nCandleStickCount == nSeriesCount );
960 uno::Sequence< uno::Reference< chart2::XDataSeries > > aNewSeries( nCandleStickCount );
961 for( sal_Int32 i=0; i<nCandleStickCount; ++i )
963 sal_Int32 nSeriesIndex = i*nSeriesPerCandleStick;
964 if( bHasJapaneseCandlestick )
966 // open values
967 lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], OUString( "values-first" ));
968 aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
969 // low values
970 lcl_MoveDataToCandleStickSeries(
971 uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
972 aNewSeries[i], OUString( "values-min" ));
974 else
976 // low values
977 lcl_setRoleAtFirstSequence( aSeriesSeq[ nSeriesIndex ], OUString( "values-min" ));
978 aNewSeries[i] = aSeriesSeq[ nSeriesIndex ];
980 // high values
981 lcl_MoveDataToCandleStickSeries(
982 uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
983 aNewSeries[i], OUString( "values-max" ));
984 // close values
985 lcl_MoveDataToCandleStickSeries(
986 uno::Reference< chart2::data::XDataSource >( aSeriesSeq[ ++nSeriesIndex ], uno::UNO_QUERY_THROW ),
987 aNewSeries[i], OUString( "values-last" ));
989 xDSContainer->setDataSeries( aNewSeries );
992 catch(const uno::Exception&)
994 OSL_FAIL( "Exception while merging series for stock chart" );
998 SvXMLImportContext* SchXMLChartContext::CreateChildContext(
999 sal_uInt16 nPrefix,
1000 const rtl::OUString& rLocalName,
1001 const uno::Reference< xml::sax::XAttributeList >& xAttrList )
1003 static const sal_Bool bTrue = sal_True;
1004 static const uno::Any aTrueBool( &bTrue, ::getBooleanCppuType());
1006 SvXMLImportContext* pContext = 0;
1007 const SvXMLTokenMap& rTokenMap = mrImportHelper.GetChartElemTokenMap();
1008 uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1009 uno::Reference< beans::XPropertySet > xProp( xDoc, uno::UNO_QUERY );
1011 switch( rTokenMap.Get( nPrefix, rLocalName ))
1013 case XML_TOK_CHART_PLOT_AREA:
1014 pContext = new SchXMLPlotAreaContext( mrImportHelper, GetImport(), rLocalName,
1015 m_aXLinkHRefAttributeToIndicateDataProvider,
1016 maSeriesAddresses, msCategoriesAddress,
1017 msChartAddress, m_bHasRangeAtPlotArea, mbAllRangeAddressesAvailable,
1018 mbColHasLabels, mbRowHasLabels,
1019 meDataRowSource,
1020 maSeriesDefaultsAndStyles,
1021 maChartTypeServiceName,
1022 maLSequencesPerIndex, maChartSize );
1023 break;
1025 case XML_TOK_CHART_TITLE:
1026 if( xDoc.is())
1028 if( xProp.is())
1030 xProp->setPropertyValue( rtl::OUString( "HasMainTitle" ), aTrueBool );
1032 uno::Reference< drawing::XShape > xTitleShape( xDoc->getTitle(), uno::UNO_QUERY );
1033 pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1034 rLocalName, maMainTitle, xTitleShape );
1036 break;
1038 case XML_TOK_CHART_SUBTITLE:
1039 if( xDoc.is())
1041 if( xProp.is())
1043 xProp->setPropertyValue( rtl::OUString( "HasSubTitle" ), aTrueBool );
1045 uno::Reference< drawing::XShape > xTitleShape( xDoc->getSubTitle(), uno::UNO_QUERY );
1046 pContext = new SchXMLTitleContext( mrImportHelper, GetImport(),
1047 rLocalName, maSubTitle, xTitleShape );
1049 break;
1051 case XML_TOK_CHART_LEGEND:
1052 pContext = new SchXMLLegendContext( mrImportHelper, GetImport(), rLocalName );
1053 break;
1055 case XML_TOK_CHART_TABLE:
1057 SchXMLTableContext * pTableContext =
1058 new SchXMLTableContext( mrImportHelper, GetImport(), rLocalName, maTable );
1059 m_bHasTableElement = true;
1060 // #i85913# take into account column- and row- mapping for
1061 // charts with own data only for those which were not copied
1062 // from a place where they got data from the container. Note,
1063 // that this requires the plot-area been read before the table
1064 // (which is required in the ODF spec)
1065 // Note: For stock charts and donut charts with special handling
1066 // the mapping must not be applied!
1067 if( msChartAddress.isEmpty() && !mbIsStockChart &&
1068 !lcl_SpecialHandlingForDonutChartNeeded(
1069 maChartTypeServiceName, GetImport()))
1071 if( !msColTrans.isEmpty() )
1073 OSL_ASSERT( msRowTrans.isEmpty() );
1074 pTableContext->setColumnPermutation( lcl_getNumberSequenceFromString( msColTrans, true ));
1075 msColTrans = OUString();
1077 else if( !msRowTrans.isEmpty() )
1079 pTableContext->setRowPermutation( lcl_getNumberSequenceFromString( msRowTrans, true ));
1080 msRowTrans = OUString();
1083 pContext = pTableContext;
1085 break;
1087 default:
1088 // try importing as an additional shape
1089 if( ! mxDrawPage.is())
1091 uno::Reference< drawing::XDrawPageSupplier > xSupp( xDoc, uno::UNO_QUERY );
1092 if( xSupp.is())
1093 mxDrawPage = uno::Reference< drawing::XShapes >( xSupp->getDrawPage(), uno::UNO_QUERY );
1095 DBG_ASSERT( mxDrawPage.is(), "Invalid Chart Page" );
1097 if( mxDrawPage.is())
1098 pContext = GetImport().GetShapeImport()->CreateGroupChildContext(
1099 GetImport(), nPrefix, rLocalName, xAttrList, mxDrawPage );
1100 break;
1103 if( ! pContext )
1104 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1106 return pContext;
1111 With a locked controller the following is done here:
1112 1. Hide title, subtitle, and legend.
1113 2. Set the size of the draw page.
1114 3. Set a (logically) empty data set.
1115 4. Set the chart type.
1117 void SchXMLChartContext::InitChart(
1118 const OUString & rChartTypeServiceName, // currently the old service name
1119 sal_Bool /* bSetSwitchData */ )
1121 uno::Reference< chart::XChartDocument > xDoc = mrImportHelper.GetChartDocument();
1122 DBG_ASSERT( xDoc.is(), "No valid document!" );
1123 uno::Reference< frame::XModel > xModel (xDoc, uno::UNO_QUERY );
1125 // Remove Title and Diagram ("De-InitNew")
1126 uno::Reference< chart2::XChartDocument > xNewDoc( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
1127 if( xNewDoc.is())
1129 xNewDoc->setFirstDiagram( 0 );
1130 uno::Reference< chart2::XTitled > xTitled( xNewDoc, uno::UNO_QUERY );
1131 if( xTitled.is())
1132 xTitled->setTitleObject( 0 );
1135 // Set the chart type via setting the diagram.
1136 if( !rChartTypeServiceName.isEmpty() && xDoc.is())
1138 uno::Reference< lang::XMultiServiceFactory > xFact( xDoc, uno::UNO_QUERY );
1139 if( xFact.is())
1141 uno::Reference< chart::XDiagram > xDia( xFact->createInstance( rChartTypeServiceName ), uno::UNO_QUERY );
1142 if( xDia.is())
1143 xDoc->setDiagram( xDia );
1148 // ----------------------------------------
1150 SchXMLTitleContext::SchXMLTitleContext( SchXMLImportHelper& rImpHelper, SvXMLImport& rImport,
1151 const rtl::OUString& rLocalName,
1152 rtl::OUString& rTitle,
1153 uno::Reference< drawing::XShape >& xTitleShape ) :
1154 SvXMLImportContext( rImport, XML_NAMESPACE_CHART, rLocalName ),
1155 mrImportHelper( rImpHelper ),
1156 mrTitle( rTitle ),
1157 mxTitleShape( xTitleShape )
1161 SchXMLTitleContext::~SchXMLTitleContext()
1164 void SchXMLTitleContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
1166 sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
1168 com::sun::star::awt::Point maPosition;
1169 bool bHasXPosition=false;
1170 bool bHasYPosition=false;
1172 for( sal_Int16 i = 0; i < nAttrCount; i++ )
1174 rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
1175 rtl::OUString aLocalName;
1176 rtl::OUString aValue = xAttrList->getValueByIndex( i );
1177 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
1179 if( nPrefix == XML_NAMESPACE_SVG )
1181 if( IsXMLToken( aLocalName, XML_X ) )
1183 GetImport().GetMM100UnitConverter().convertMeasureToCore(
1184 maPosition.X, aValue );
1185 bHasXPosition = true;
1187 else if( IsXMLToken( aLocalName, XML_Y ) )
1189 GetImport().GetMM100UnitConverter().convertMeasureToCore(
1190 maPosition.Y, aValue );
1191 bHasYPosition = true;
1194 else if( nPrefix == XML_NAMESPACE_CHART )
1196 if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
1197 msAutoStyleName = aValue;
1202 if( mxTitleShape.is())
1204 if( bHasXPosition && bHasYPosition )
1205 mxTitleShape->setPosition( maPosition );
1207 uno::Reference< beans::XPropertySet > xProp( mxTitleShape, uno::UNO_QUERY );
1208 if( xProp.is())
1210 const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
1211 if( pStylesCtxt )
1213 const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
1214 mrImportHelper.GetChartFamilyID(), msAutoStyleName );
1216 if( pStyle && pStyle->ISA( XMLPropStyleContext ))
1217 (( XMLPropStyleContext* )pStyle )->FillPropertySet( xProp );
1223 SvXMLImportContext* SchXMLTitleContext::CreateChildContext(
1224 sal_uInt16 nPrefix,
1225 const rtl::OUString& rLocalName,
1226 const uno::Reference< xml::sax::XAttributeList >& )
1228 SvXMLImportContext* pContext = 0;
1230 if( nPrefix == XML_NAMESPACE_TEXT &&
1231 IsXMLToken( rLocalName, XML_P ) )
1233 pContext = new SchXMLParagraphContext( GetImport(), rLocalName, mrTitle );
1235 else
1236 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1238 return pContext;
1241 // ----------------------------------------
1244 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */