xref: /trunk/main/xmloff/source/chart/SchXMLExport.cxx (revision d666495c4f609ab94ddded8b0141831070b22d11)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26 
27 #include <xmloff/xmlprmap.hxx>
28 
29 #include "SchXMLExport.hxx"
30 #include "XMLChartPropertySetMapper.hxx"
31 #include "SchXMLSeriesHelper.hxx"
32 #include "ColorPropertySet.hxx"
33 #include "SchXMLTools.hxx"
34 #include "SchXMLEnumConverter.hxx"
35 
36 #include <tools/debug.hxx>
37 #include <rtl/logfile.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <tools/globname.hxx>
40 #include <sot/clsids.hxx>
41 
42 #include <xmloff/nmspmap.hxx>
43 #include "xmloff/xmlnmspe.hxx"
44 #include <xmloff/xmltoken.hxx>
45 #include <xmloff/families.hxx>
46 #include <xmloff/xmlaustp.hxx>
47 #include <xmloff/xmluconv.hxx>
48 #include <xmloff/xmlmetae.hxx>
49 #include "xexptran.hxx"
50 #include <rtl/math.hxx>
51 // header for any2enum
52 #include <comphelper/extract.hxx>
53 
54 #include <list>
55 #include <typeinfo>
56 #include <algorithm>
57 #include <iterator>
58 
59 #include <com/sun/star/task/XStatusIndicatorSupplier.hpp>
60 #include <com/sun/star/lang/XServiceInfo.hpp>
61 #include <com/sun/star/lang/XServiceName.hpp>
62 #include <com/sun/star/beans/XPropertySet.hpp>
63 #include <com/sun/star/uno/XComponentContext.hpp>
64 #include <com/sun/star/util/XRefreshable.hpp>
65 
66 #include <com/sun/star/chart/XAxis.hpp>
67 #include <com/sun/star/chart/XAxisSupplier.hpp>
68 #include <com/sun/star/chart/XChartDocument.hpp>
69 #include <com/sun/star/chart/ChartLegendPosition.hpp>
70 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
71 #include <com/sun/star/chart/ChartDataRowSource.hpp>
72 #include <com/sun/star/chart/ChartAxisAssign.hpp>
73 #include <com/sun/star/chart/ChartAxisType.hpp>
74 #include <com/sun/star/chart/TimeIncrement.hpp>
75 #include <com/sun/star/chart/TimeInterval.hpp>
76 #include <com/sun/star/chart/TimeUnit.hpp>
77 #include <com/sun/star/chart/ChartSeriesAddress.hpp>
78 #include <com/sun/star/chart/X3DDisplay.hpp>
79 #include <com/sun/star/chart/XStatisticDisplay.hpp>
80 #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
81 #include <com/sun/star/chart/XDiagramPositioning.hpp>
82 
83 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
84 #include <com/sun/star/chart2/AxisType.hpp>
85 #include <com/sun/star/chart2/XChartDocument.hpp>
86 #include <com/sun/star/chart2/XDiagram.hpp>
87 #include <com/sun/star/chart2/RelativePosition.hpp>
88 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
89 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
90 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
91 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
92 #include <com/sun/star/chart2/data/XDataSource.hpp>
93 #include <com/sun/star/chart2/data/XDataSink.hpp>
94 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
95 #include <com/sun/star/chart2/data/XDataProvider.hpp>
96 #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
97 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
98 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
99 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
100 
101 #include <com/sun/star/util/XStringMapping.hpp>
102 #include <com/sun/star/drawing/HomogenMatrix.hpp>
103 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
104 #include <com/sun/star/drawing/XShapes.hpp>
105 #include <com/sun/star/embed/Aspects.hpp>
106 #include <com/sun/star/embed/XVisualObject.hpp>
107 #include <com/sun/star/container/XChild.hpp>
108 
109 
110 #include "MultiPropertySetHandler.hxx"
111 #include "PropertyMap.hxx"
112 
113 using namespace com::sun::star;
114 using namespace ::xmloff::token;
115 
116 using ::rtl::OUString;
117 using ::rtl::OUStringBuffer;
118 using ::rtl::OUStringToOString;
119 using ::com::sun::star::uno::Sequence;
120 using ::com::sun::star::uno::Reference;
121 using ::com::sun::star::uno::Any;
122 using ::std::vector;
123 
124 // ========================================
125 // class SchXMLExportHelper_Impl
126 // ========================================
127 
128 class SchXMLExportHelper_Impl
129 {
130 public:
131     // first: data sequence for label, second: data sequence for values.
132     typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence >,
133             ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > > tLabelValuesDataPair;
134     typedef ::std::vector< tLabelValuesDataPair > tDataSequenceCont;
135 
136 public:
137     SchXMLExportHelper_Impl( SvXMLExport& rExport,
138                         SvXMLAutoStylePoolP& rASPool );
139 
140     virtual ~SchXMLExportHelper_Impl();
141 
142     // auto-styles
143     /// parse chart and collect all auto-styles used in current pool
144     void collectAutoStyles( com::sun::star::uno::Reference<
145                             com::sun::star::chart::XChartDocument > rChartDoc );
146 
147     /// write the styles collected into the current pool as <style:style> elements
148     void exportAutoStyles();
149 
150     /** export the <chart:chart> element corresponding to rChartDoc
151         if bIncludeTable is true, the chart data is exported as <table:table>
152         element (inside the chart element).
153 
154         Otherwise the external references stored in the chart document are used
155         for writing the corresponding attributes at series
156 
157         All attributes contained in xAttrList are written at the chart element,
158         which ist the outer element of a chart. So these attributes can easily
159         be parsed again by the container
160      */
161     void exportChart( com::sun::star::uno::Reference<
162                         com::sun::star::chart::XChartDocument > rChartDoc,
163                       sal_Bool bIncludeTable );
164 
165     UniReference< XMLPropertySetMapper > GetPropertySetMapper() const;
166 
SetChartRangeAddress(const::rtl::OUString & rAddress)167     void SetChartRangeAddress( const ::rtl::OUString& rAddress )
168         { msChartAddress = rAddress; }
SetTableNumberList(const::rtl::OUString & rList)169     void SetTableNumberList( const ::rtl::OUString& rList )
170         { msTableNumberList = rList; }
171 
172     void InitRangeSegmentationProperties(
173         const ::com::sun::star::uno::Reference<
174             ::com::sun::star::chart2::XChartDocument > & xChartDoc );
175 
176     ::com::sun::star::awt::Size getPageSize(
177         const ::com::sun::star::uno::Reference<
178             ::com::sun::star::chart2::XChartDocument > & xChartDoc ) const;
179 
180     /** first parseDocument: collect autostyles and store names in this queue
181         second parseDocument: export content and use names from this queue
182      */
183     ::std::queue< ::rtl::OUString > maAutoStyleNameQueue;
184     void CollectAutoStyle(
185         const std::vector< XMLPropertyState >& aStates );
186     void AddAutoStyleAttribute(
187         const std::vector< XMLPropertyState >& aStates );
188 
GetAutoStylePoolP()189     SvXMLAutoStylePoolP& GetAutoStylePoolP()
190     { return mrAutoStylePool; }
191 
192     /// if bExportContent is false the auto-styles are collected
193     void parseDocument( com::sun::star::uno::Reference<
194                             com::sun::star::chart::XChartDocument >& rChartDoc,
195                         sal_Bool bExportContent,
196                         sal_Bool bIncludeTable = sal_False );
197     void exportTable();
198     void exportPlotArea(
199         com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > xDiagram,
200         com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > xNewDiagram,
201         const ::com::sun::star::awt::Size & rPageSize,
202         sal_Bool bExportContent,
203         sal_Bool bIncludeTable );
204     void exportCoordinateRegion( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram >& xDiagram );
205     void exportAxes( const com::sun::star::uno::Reference< com::sun::star::chart::XDiagram > & xDiagram,
206                                     const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
207                                     sal_Bool bExportContent );
208     void exportAxis( enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName,
209                     const Reference< beans::XPropertySet > xAxisProps, const Reference< chart2::XAxis >& xChart2Axis,
210                     const OUString& rCategoriesRanges,
211                     bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent );
212     void exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent );
213     void exportDateScale( const Reference< beans::XPropertySet > xAxisProps );
214     void exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent );
215 
216     void exportSeries(
217         const com::sun::star::uno::Reference< com::sun::star::chart2::XDiagram > & xNewDiagram,
218         const ::com::sun::star::awt::Size & rPageSize,
219         sal_Bool bExportContent,
220         sal_Bool bHasTwoYAxes );
221     void exportCandleStickSeries(
222         const ::com::sun::star::uno::Sequence<
223             ::com::sun::star::uno::Reference<
224                 ::com::sun::star::chart2::XDataSeries > > & aSeriesSeq,
225         const ::com::sun::star::uno::Reference<
226             ::com::sun::star::chart2::XDiagram > & xDiagram,
227         sal_Bool bJapaneseCandleSticks,
228         sal_Bool bExportContent );
229     void exportDataPoints(
230         const ::com::sun::star::uno::Reference<
231             ::com::sun::star::beans::XPropertySet > & xSeriesProperties,
232         sal_Int32 nSeriesLength,
233         const ::com::sun::star::uno::Reference<
234             ::com::sun::star::chart2::XDiagram > & xDiagram,
235         sal_Bool bExportContent );
236     void exportRegressionCurve(
237         const ::com::sun::star::uno::Reference<
238             ::com::sun::star::chart2::XDataSeries > & xSeries,
239         const ::com::sun::star::uno::Reference<
240             ::com::sun::star::beans::XPropertySet > & xSeriesProp,
241         const ::com::sun::star::awt::Size & rPageSize,
242         sal_Bool bExportContent );
243 
244     /// add svg position as attribute for current element
245     void addPosition( const ::com::sun::star::awt::Point & rPosition );
246     void addPosition( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape );
247     /// add svg size as attribute for current element
248     void addSize( const ::com::sun::star::awt::Size & rSize, bool bIsOOoNamespace = false );
249     void addSize( com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape, bool bIsOOoNamespace = false  );
250     /// fills the member msString with the appropriate String (i.e. "A3")
251     void getCellAddress( sal_Int32 nCol, sal_Int32 nRow );
252     /// exports a string as a paragraph element
253     void exportText( const ::rtl::OUString& rText, bool bConvertTabsLFs = false );
254     void exportErrorBarRanges();
255 
256     SchXMLExportHelper_Impl(SchXMLExportHelper_Impl &); // not defined
257     void operator =(SchXMLExportHelper_Impl &); // not defined
258 
259 public:
260     SvXMLExport& mrExport;
261     SvXMLAutoStylePoolP& mrAutoStylePool;
262     UniReference< XMLPropertyHandlerFactory > mxPropertyHandlerFactory;
263     UniReference< XMLPropertySetMapper > mxPropertySetMapper;
264     UniReference< XMLChartExportPropertyMapper > mxExpPropMapper;
265 
266     rtl::OUString msTableName;
267     rtl::OUStringBuffer msStringBuffer;
268     rtl::OUString msString;
269 
270     // members filled by InitRangeSegmentationProperties (retrieved from DataProvider)
271     sal_Bool mbHasSeriesLabels;
272     sal_Bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false
273     sal_Bool mbRowSourceColumns;
274     rtl::OUString msChartAddress;
275     rtl::OUString msTableNumberList;
276     ::com::sun::star::uno::Sequence< sal_Int32 > maSequenceMapping;
277 
278     rtl::OUString msCLSID;
279 
280     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > mxAdditionalShapes;
281 
282     tDataSequenceCont m_aDataSequencesToExport;
283     rtl::OUString maCategoriesRange;
284 };
285 
286 namespace
287 {
lcl_getComponentContext()288 Reference< uno::XComponentContext > lcl_getComponentContext()
289 {
290     Reference< uno::XComponentContext > xContext;
291     try
292     {
293         Reference< beans::XPropertySet > xFactProp( comphelper::getProcessServiceFactory(), uno::UNO_QUERY );
294         if( xFactProp.is())
295             xFactProp->getPropertyValue(OUString::createFromAscii("DefaultContext")) >>= xContext;
296     }
297     catch( uno::Exception& )
298     {}
299 
300     return xContext;
301 }
302 
303 class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
304 {
305 public:
lcl_MatchesRole(const OUString & aRole)306     explicit lcl_MatchesRole( const OUString & aRole ) :
307             m_aRole( aRole )
308     {}
309 
operator ()(const Reference<chart2::data::XLabeledDataSequence> & xSeq) const310     bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
311     {
312         if( !xSeq.is() )
313             return  false;
314         Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
315         OUString aRole;
316 
317         return ( xProp.is() &&
318                  (xProp->getPropertyValue(
319                      OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) &&
320                  m_aRole.equals( aRole ));
321     }
322 
323 private:
324     OUString m_aRole;
325 };
326 
327 template< typename T >
lcl_SequenceToVectorAppend(const Sequence<T> & rSource,::std::vector<T> & rDestination)328     void lcl_SequenceToVectorAppend( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
329 {
330     rDestination.reserve( rDestination.size() + rSource.getLength());
331     ::std::copy( rSource.getConstArray(), rSource.getConstArray() + rSource.getLength(),
332                  ::std::back_inserter( rDestination ));
333 }
334 
335 template< typename T >
lcl_SequenceToVector(const Sequence<T> & rSource,::std::vector<T> & rDestination)336     void lcl_SequenceToVector( const Sequence< T > & rSource, ::std::vector< T > & rDestination )
337 {
338     rDestination.clear();
339     lcl_SequenceToVectorAppend( rSource, rDestination );
340 }
341 
lcl_getCategories(const Reference<chart2::XDiagram> & xDiagram)342 Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram )
343 {
344     Reference< chart2::data::XLabeledDataSequence >  xResult;
345     try
346     {
347         Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
348             xDiagram, uno::UNO_QUERY_THROW );
349         Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
350             xCooSysCnt->getCoordinateSystems());
351         for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
352         {
353             Reference< chart2::XCoordinateSystem > xCooSys( aCooSysSeq[i] );
354             OSL_ASSERT( xCooSys.is());
355             for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
356             {
357                 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
358                 for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
359                 {
360                     Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI );
361                     OSL_ASSERT( xAxis.is());
362                     if( xAxis.is())
363                     {
364                         chart2::ScaleData aScaleData = xAxis->getScaleData();
365                         if( aScaleData.Categories.is())
366                         {
367                             xResult.set( aScaleData.Categories );
368                             break;
369                         }
370                     }
371                 }
372             }
373         }
374     }
375     catch( uno::Exception & ex )
376     {
377         (void)ex; // avoid warning for pro build
378         OSL_ENSURE( false, OUStringToOString(
379                         OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) +
380                         OUString::createFromAscii( typeid( ex ).name()) +
381                         OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) +
382                         ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
383     }
384 
385     return xResult;
386 }
387 
lcl_createDataSource(const Sequence<Reference<chart2::data::XLabeledDataSequence>> & aData)388 Reference< chart2::data::XDataSource > lcl_createDataSource(
389     const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData )
390 {
391     Reference< chart2::data::XDataSink > xSink;
392     Reference< uno::XComponentContext > xContext( lcl_getComponentContext());
393     if( xContext.is() )
394         xSink.set(
395             xContext->getServiceManager()->createInstanceWithContext(
396                 OUString::createFromAscii("com.sun.star.chart2.data.DataSource"),
397                 xContext ), uno::UNO_QUERY_THROW );
398     if( xSink.is())
399         xSink->setData( aData );
400 
401     return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY );
402 }
403 
lcl_getAllSeriesSequences(const Reference<chart2::XChartDocument> & xChartDoc)404 Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc )
405 {
406     ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer;
407     if( xChartDoc.is() )
408     {
409         Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
410         ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram ));
411         for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aSeriesIt( aSeriesVector.begin() )
412             ; aSeriesIt != aSeriesVector.end(); ++aSeriesIt )
413         {
414             Reference< chart2::data::XDataSource > xDataSource( *aSeriesIt, uno::UNO_QUERY );
415             if( !xDataSource.is() )
416                 continue;
417             uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
418             lcl_SequenceToVectorAppend( aDataSequences, aContainer );
419         }
420     }
421 
422     Sequence< Reference< chart2::data::XLabeledDataSequence > > aRet( aContainer.size());
423     ::std::copy( aContainer.begin(), aContainer.end(), aRet.getArray());
424 
425     return aRet;
426 }
427 
428 Reference< chart2::data::XLabeledDataSequence >
lcl_getDataSequenceByRole(const Sequence<Reference<chart2::data::XLabeledDataSequence>> & aLabeledSeq,const OUString & rRole)429     lcl_getDataSequenceByRole(
430         const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq,
431         const OUString & rRole )
432 {
433     Reference< chart2::data::XLabeledDataSequence > aNoResult;
434 
435     const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
436     const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
437     const Reference< chart2::data::XLabeledDataSequence > * pMatch =
438         ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole ));
439 
440     if( pMatch != pEnd )
441         return *pMatch;
442 
443     return aNoResult;
444 }
445 
lcl_pressUsedDataIntoRectangularFormat(const Reference<chart2::XChartDocument> & xChartDoc,sal_Bool & rOutSourceHasCategoryLabels)446 Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, sal_Bool& rOutSourceHasCategoryLabels )
447 {
448     ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector;
449 
450     //categories are always the first sequence
451     Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
452     Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) );
453     if( xCategories.is() )
454         aLabeledSeqVector.push_back( xCategories );
455     rOutSourceHasCategoryLabels = sal_Bool(xCategories.is());
456 
457     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector(
458             lcl_getAllSeriesSequences( xChartDoc ) );
459 
460     //the first x-values is always the next sequence //todo ... other x-values get lost for old format
461     Reference< chart2::data::XLabeledDataSequence > xXValues(
462         lcl_getDataSequenceByRole( aSeriesSeqVector, OUString::createFromAscii("values-x" ) ) );
463     if( xXValues.is() )
464         aLabeledSeqVector.push_back( xXValues );
465 
466     //add all other sequences now without x-values
467     lcl_MatchesRole aHasXValues( OUString::createFromAscii("values-x" ) );
468     for( sal_Int32 nN=0; nN<aSeriesSeqVector.getLength(); nN++ )
469     {
470         if( !aHasXValues( aSeriesSeqVector[nN] ) )
471             aLabeledSeqVector.push_back( aSeriesSeqVector[nN] );
472     }
473 
474     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( aLabeledSeqVector.size() );
475     ::std::copy( aLabeledSeqVector.begin(), aLabeledSeqVector.end(), aSeq.getArray() );
476 
477     return lcl_createDataSource( aSeq );
478 }
479 
lcl_isSeriesAttachedToFirstAxis(const Reference<chart2::XDataSeries> & xDataSeries)480 bool lcl_isSeriesAttachedToFirstAxis(
481     const Reference< chart2::XDataSeries > & xDataSeries )
482 {
483     bool bResult=true;
484 
485     try
486     {
487         sal_Int32 nAxisIndex = 0;
488         Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
489         if( xProp.is() )
490             xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("AttachedAxisIndex") ) ) >>= nAxisIndex;
491         bResult = (0==nAxisIndex);
492     }
493     catch( uno::Exception & ex )
494     {
495         (void)ex; // avoid warning for pro build
496         OSL_ENSURE( false, OUStringToOString(
497                         OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) +
498                         OUString::createFromAscii( typeid( ex ).name()) +
499                         OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) +
500                         ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
501     }
502 
503     return bResult;
504 }
505 
lcl_ConvertRange(const::rtl::OUString & rRange,const Reference<chart2::XChartDocument> & xDoc)506 OUString lcl_ConvertRange( const ::rtl::OUString & rRange, const Reference< chart2::XChartDocument > & xDoc )
507 {
508     OUString aResult = rRange;
509     if( !xDoc.is() )
510         return aResult;
511     Reference< chart2::data::XRangeXMLConversion > xConversion(
512         xDoc->getDataProvider(), uno::UNO_QUERY );
513     if( xConversion.is())
514         aResult = xConversion->convertRangeToXML( rRange );
515     return aResult;
516 }
517 
518 typedef ::std::pair< OUString, OUString > tLabelAndValueRange;
519 
lcl_getLabelAndValueRangeByRole(const Sequence<Reference<chart2::data::XLabeledDataSequence>> & aSeqCnt,const OUString & rRole,const Reference<chart2::XChartDocument> & xDoc,SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport)520 tLabelAndValueRange lcl_getLabelAndValueRangeByRole(
521     const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
522     const OUString & rRole,
523     const Reference< chart2::XChartDocument > & xDoc,
524     SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport )
525 {
526     tLabelAndValueRange aResult;
527 
528     Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
529         lcl_getDataSequenceByRole( aSeqCnt, rRole ));
530     if( xLabeledSeq.is())
531     {
532         Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel());
533         if( xLabelSeq.is())
534             aResult.first = lcl_ConvertRange( xLabelSeq->getSourceRangeRepresentation(), xDoc );
535 
536         Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues());
537         if( xValueSeq.is())
538             aResult.second = lcl_ConvertRange( xValueSeq->getSourceRangeRepresentation(), xDoc );
539 
540         if( xLabelSeq.is() || xValueSeq.is())
541             rOutSequencesToExport.push_back( SchXMLExportHelper_Impl::tLabelValuesDataPair( xLabelSeq, xValueSeq ));
542     }
543 
544     return aResult;
545 }
546 
lcl_getSequenceLengthByRole(const Sequence<Reference<chart2::data::XLabeledDataSequence>> & aSeqCnt,const OUString & rRole)547 sal_Int32 lcl_getSequenceLengthByRole(
548     const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
549     const OUString & rRole )
550 {
551     Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
552         lcl_getDataSequenceByRole( aSeqCnt, rRole ));
553     if( xLabeledSeq.is())
554     {
555         Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getValues());
556         return xSeq->getData().getLength();
557     }
558     return 0;
559 }
560 
lcl_hasChartType(const Reference<chart2::XDiagram> & xDiagram,const OUString & rChartType)561 bool lcl_hasChartType( const Reference< chart2::XDiagram > & xDiagram, const OUString & rChartType )
562 {
563     try
564     {
565         Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
566         Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
567         for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
568         {
569             Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
570             Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
571             for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
572             {
573                 if( aChartTypes[nCTIdx]->getChartType().equals( rChartType ))
574                     return true;
575             }
576         }
577     }
578     catch( uno::Exception & )
579     {
580         DBG_ERROR( "Exception while searching for chart type in diagram" );
581     }
582     return false;
583 }
584 
lcl_flattenStringSequence(const Sequence<OUString> & rSequence)585 OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence )
586 {
587     OUStringBuffer aResult;
588     bool bPrecedeWithSpace = false;
589     for( sal_Int32 nIndex=0; nIndex<rSequence.getLength(); ++nIndex )
590     {
591         if( rSequence[nIndex].getLength())
592         {
593             if( bPrecedeWithSpace )
594                 aResult.append( static_cast< sal_Unicode >( ' ' ));
595             aResult.append( rSequence[nIndex] );
596             bPrecedeWithSpace = true;
597         }
598     }
599     return aResult.makeStringAndClear();
600 }
601 
lcl_getLabelStringSequence(Sequence<OUString> & rOutLabels,const Reference<chart2::data::XDataSequence> & xLabelSeq)602 void lcl_getLabelStringSequence( Sequence< OUString >& rOutLabels, const Reference< chart2::data::XDataSequence > & xLabelSeq )
603 {
604     uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY );
605     if( xTextualDataSequence.is())
606     {
607         rOutLabels = xTextualDataSequence->getTextualData();
608     }
609     else if( xLabelSeq.is())
610     {
611         Sequence< uno::Any > aAnies( xLabelSeq->getData());
612         rOutLabels.realloc( aAnies.getLength());
613         for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
614             aAnies[i] >>= rOutLabels[i];
615     }
616 }
617 
lcl_getMaxSequenceLength(const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer)618 sal_Int32 lcl_getMaxSequenceLength(
619     const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer )
620 {
621     sal_Int32 nResult = 0;
622     for( SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( rContainer.begin());
623          aIt != rContainer.end(); ++aIt )
624     {
625         if( aIt->second.is())
626         {
627             sal_Int32 nSeqLength = aIt->second->getData().getLength();
628             if( nSeqLength > nResult )
629                 nResult = nSeqLength;
630         }
631     }
632     return nResult;
633 }
634 
lcl_DataSequenceToStringSequence(const uno::Reference<chart2::data::XDataSequence> & xDataSequence)635 uno::Sequence< rtl::OUString > lcl_DataSequenceToStringSequence(
636     const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
637 {
638     uno::Sequence< rtl::OUString > aResult;
639     if(!xDataSequence.is())
640         return aResult;
641 
642     uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
643     if( xTextualDataSequence.is() )
644     {
645         aResult = xTextualDataSequence->getTextualData();
646     }
647     else
648     {
649         uno::Sequence< uno::Any > aValues = xDataSequence->getData();
650         aResult.realloc(aValues.getLength());
651 
652         for(sal_Int32 nN=aValues.getLength();nN--;)
653             aValues[nN] >>= aResult[nN];
654     }
655 
656     return aResult;
657 }
lcl_getAllValuesFromSequence(const Reference<chart2::data::XDataSequence> & xSeq)658 ::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq )
659 {
660     double fNan = 0.0;
661     ::rtl::math::setNan( &fNan );
662     ::std::vector< double > aResult;
663     if(!xSeq.is())
664         return aResult;
665 
666     uno::Sequence< double > aValuesSequence;
667     Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
668     if( xNumSeq.is() )
669     {
670         aValuesSequence = xNumSeq->getNumericalData();
671     }
672     else
673     {
674         Sequence< uno::Any > aAnies( xSeq->getData() );
675         aValuesSequence.realloc( aAnies.getLength() );
676         for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
677             aAnies[i] >>= aValuesSequence[i];
678     }
679 
680     //special handling for x-values (if x-values do point to categories, indices are used instead )
681     Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
682     if( xProp.is() )
683     {
684         OUString aRole;
685         xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Role") ) ) >>= aRole;
686         if( aRole.match( OUString( RTL_CONSTASCII_USTRINGPARAM( "values-x") ) ) )
687         {
688             //lcl_clearIfNoValuesButTextIsContained - replace by indices if the values are not appropriate
689             bool bHasValue=false;
690             bool bHasText=false;
691             sal_Int32 nCount = aValuesSequence.getLength();
692             for( sal_Int32 j = 0; j < nCount; ++j )
693             {
694                 if( !::rtl::math::isNan( aValuesSequence[j] ) )
695                 {
696                     bHasValue=true;
697                     break;
698                 }
699             }
700             if(!bHasValue)
701             {
702                 //no double value is countained
703                 //is there any text?
704                 uno::Sequence< rtl::OUString > aStrings( lcl_DataSequenceToStringSequence( xSeq ) );
705                 sal_Int32 nTextCount = aStrings.getLength();
706                 for( sal_Int32 j = 0; j < nTextCount; ++j )
707                 {
708                     if( aStrings[j].getLength() )
709                     {
710                         bHasText=true;
711                         break;
712                     }
713                 }
714             }
715             if( !bHasValue && bHasText )
716             {
717                 for( sal_Int32 j = 0; j < nCount; ++j )
718                     aValuesSequence[j] = j+1;
719             }
720         }
721     }
722 
723     ::std::copy( aValuesSequence.getConstArray(), aValuesSequence.getConstArray() + aValuesSequence.getLength(),
724                      ::std::back_inserter( aResult ));
725     return aResult;
726 }
727 
lcl_SequenceHasUnhiddenData(const uno::Reference<chart2::data::XDataSequence> & xDataSequence)728 bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
729 {
730     if( !xDataSequence.is() )
731         return false;
732     uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
733     if( xProp.is() )
734     {
735         uno::Sequence< sal_Int32 > aHiddenValues;
736         try
737         {
738             xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "HiddenValues" ) ) ) >>= aHiddenValues;
739             if( !aHiddenValues.getLength() )
740                 return true;
741         }
742         catch( uno::Exception& e )
743         {
744             (void)e; // avoid warning
745             return true;
746         }
747     }
748     if( xDataSequence->getData().getLength() )
749         return true;
750     return false;
751 }
752 
753 typedef vector< OUString > tStringVector;
754 typedef vector< double > tDoubleVector;
755 typedef vector< vector< OUString > > t2DStringVector;
756 typedef vector< vector< double > > t2DNumberContainer;
757 
758 struct lcl_TableData
759 {
760     t2DNumberContainer  aDataInRows;
761     tStringVector       aDataRangeRepresentations;
762 
763     tStringVector       aColumnDescriptions;
764     tStringVector       aColumnDescriptions_Ranges;
765 
766     tStringVector       aRowDescriptions;
767     tStringVector       aRowDescriptions_Ranges;
768 
769     Sequence< Sequence< uno::Any > >    aComplexColumnDescriptions;//outer index is columns - inner index is level
770     Sequence< Sequence< uno::Any > >    aComplexRowDescriptions;//outer index is rows - inner index is level
771 
772     ::std::vector< sal_Int32 > aHiddenColumns;
773 };
774 
775 // ::std::bind2nd( ::std::mem_fun_ref( &T::resize ), nSize ) does not work
776 template< class T >
777     struct lcl_resize
778     {
lcl_resize__anon2a707c240111::lcl_resize779         lcl_resize( typename T::size_type nSize, typename T::value_type fDefaultValue ) : m_nSize( nSize ), m_fDefaultValue( fDefaultValue ) {}
operator ()__anon2a707c240111::lcl_resize780         void operator()( T & t )
781         { t.resize( m_nSize, m_fDefaultValue ); }
782     private:
783         typename T::size_type m_nSize;
784         typename T::value_type m_fDefaultValue;
785     };
786 
787 
788 typedef ::std::map< sal_Int32, SchXMLExportHelper_Impl::tLabelValuesDataPair >
789     lcl_DataSequenceMap;
790 
791 struct lcl_SequenceToMapElement :
792     public ::std::unary_function< lcl_DataSequenceMap::mapped_type, lcl_DataSequenceMap::value_type >
793 {
lcl_SequenceToMapElement__anon2a707c240111::lcl_SequenceToMapElement794     lcl_SequenceToMapElement()
795     {}
operator ()__anon2a707c240111::lcl_SequenceToMapElement796     result_type operator() ( const argument_type & rContent )
797     {
798         sal_Int32 nIndex = -1;
799         if( rContent.second.is()) //has values
800         {
801             OUString aRangeRep( rContent.second->getSourceRangeRepresentation());
802             nIndex = aRangeRep.toInt32();
803         }
804         else if( rContent.first.is()) //has labels
805             nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32();
806         return result_type( nIndex, rContent );
807     }
808 };
809 
lcl_ReorderInternalSequencesAccordingToTheirRangeName(SchXMLExportHelper_Impl::tDataSequenceCont & rInOutSequences)810 void lcl_ReorderInternalSequencesAccordingToTheirRangeName(
811     SchXMLExportHelper_Impl::tDataSequenceCont & rInOutSequences )
812 {
813     lcl_DataSequenceMap aIndexSequenceMap;
814     ::std::transform( rInOutSequences.begin(), rInOutSequences.end(),
815                       ::std::inserter( aIndexSequenceMap, aIndexSequenceMap.begin()),
816                       lcl_SequenceToMapElement());
817 
818     rInOutSequences.clear();
819     sal_Int32 nIndex = 0;
820     for( lcl_DataSequenceMap::const_iterator aIt = aIndexSequenceMap.begin();
821          aIt != aIndexSequenceMap.end(); ++aIt, ++nIndex )
822     {
823         if( aIt->first < 0 )
824             continue;
825         // fill empty columns
826         for( ; nIndex < aIt->first; ++nIndex )
827             rInOutSequences.push_back(
828                 SchXMLExportHelper_Impl::tDataSequenceCont::value_type( 0, 0 ));
829         OSL_ASSERT( nIndex == aIt->first );
830         rInOutSequences.push_back( aIt->second );
831     }
832 }
833 
834 
lcl_getDataForLocalTable(const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport,const Reference<chart2::XAnyDescriptionAccess> & xAnyDescriptionAccess,const OUString & rCategoriesRange,bool bSeriesFromColumns,const Reference<chart2::data::XRangeXMLConversion> & xRangeConversion)835 lcl_TableData lcl_getDataForLocalTable(
836     const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport,
837     const Reference< chart2::XAnyDescriptionAccess >& xAnyDescriptionAccess,
838     const OUString& rCategoriesRange,
839     bool bSeriesFromColumns,
840     const Reference< chart2::data::XRangeXMLConversion > & xRangeConversion )
841 {
842     lcl_TableData aResult;
843 
844     try
845     {
846         Sequence< OUString > aSimpleCategories;
847         if( xAnyDescriptionAccess.is() )
848         {
849             //categories
850             if( bSeriesFromColumns )
851             {
852                 aSimpleCategories = xAnyDescriptionAccess->getRowDescriptions();
853                 aResult.aComplexRowDescriptions = xAnyDescriptionAccess->getAnyRowDescriptions();
854             }
855             else
856             {
857                 aSimpleCategories = xAnyDescriptionAccess->getColumnDescriptions();
858                 aResult.aComplexColumnDescriptions = xAnyDescriptionAccess->getAnyColumnDescriptions();
859             }
860         }
861 
862         //series values and series labels
863         SchXMLExportHelper_Impl::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size();
864         SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aBegin( aSequencesToExport.begin());
865         SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aEnd( aSequencesToExport.end());
866         SchXMLExportHelper_Impl::tDataSequenceCont::const_iterator aIt( aBegin );
867 
868         size_t nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport ));
869         size_t nCategoriesLength( aSimpleCategories.getLength() );
870         if( nCategoriesLength > nMaxSequenceLength )
871         {
872             aSimpleCategories.realloc(nMaxSequenceLength);//#i110617#
873             nCategoriesLength = nMaxSequenceLength;
874         }
875         size_t nNumColumns( bSeriesFromColumns ? nNumSequences : nMaxSequenceLength );
876         size_t nNumRows( bSeriesFromColumns ? nMaxSequenceLength : nNumSequences );
877 
878         // resize data
879         aResult.aDataInRows.resize( nNumRows );
880         double fNan = 0.0;
881         ::rtl::math::setNan( &fNan );
882         ::std::for_each( aResult.aDataInRows.begin(), aResult.aDataInRows.end(),
883                          lcl_resize< t2DNumberContainer::value_type >( nNumColumns, fNan ));
884         aResult.aColumnDescriptions.resize( nNumColumns );
885         aResult.aComplexColumnDescriptions.realloc( nNumColumns );
886         aResult.aRowDescriptions.resize( nNumRows );
887         aResult.aComplexRowDescriptions.realloc( nNumRows );
888 
889         tStringVector& rCategories = bSeriesFromColumns ? aResult.aRowDescriptions    : aResult.aColumnDescriptions;
890         tStringVector& rLabels     = bSeriesFromColumns ? aResult.aColumnDescriptions : aResult.aRowDescriptions;
891 
892         //categories
893         lcl_SequenceToVector( aSimpleCategories, rCategories );
894         if( rCategoriesRange.getLength() )
895         {
896             OUString aRange(rCategoriesRange);
897             if( xRangeConversion.is())
898                 aRange = xRangeConversion->convertRangeToXML( aRange );
899             if( bSeriesFromColumns )
900                 aResult.aRowDescriptions_Ranges.push_back( aRange );
901             else
902                 aResult.aColumnDescriptions_Ranges.push_back( aRange );
903         }
904 
905         // iterate over all sequences
906         size_t nSeqIdx = 0;
907         Sequence< Sequence< OUString > > aComplexLabels(nNumSequences);
908         for( ; aIt != aEnd; ++aIt, ++nSeqIdx )
909         {
910             OUString aRange;
911             Sequence< OUString >& rCurrentComplexLabel = aComplexLabels[nSeqIdx];
912             if( aIt->first.is())
913             {
914                 lcl_getLabelStringSequence( rCurrentComplexLabel, aIt->first );
915                 rLabels[nSeqIdx] = lcl_flattenStringSequence( rCurrentComplexLabel );
916                 aRange = aIt->first->getSourceRangeRepresentation();
917                 if( xRangeConversion.is())
918                     aRange = xRangeConversion->convertRangeToXML( aRange );
919             }
920             else if( aIt->second.is())
921             {
922                 rCurrentComplexLabel.realloc(1);
923                 rLabels[nSeqIdx] = rCurrentComplexLabel[0] = lcl_flattenStringSequence(
924                     aIt->second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE ));
925             }
926             if( bSeriesFromColumns )
927                 aResult.aColumnDescriptions_Ranges.push_back( aRange );
928             else
929                 aResult.aRowDescriptions_Ranges.push_back( aRange );
930 
931             ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( aIt->second ));
932             if( bSeriesFromColumns )
933             {
934                 const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size()));
935                 for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx )
936                     aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx];
937             }
938             else
939                 aResult.aDataInRows[nSeqIdx] = aNumbers;
940 
941             if( aIt->second.is())
942             {
943                 aRange =  aIt->second->getSourceRangeRepresentation();
944                 if( xRangeConversion.is())
945                     aRange = xRangeConversion->convertRangeToXML( aRange );
946             }
947             aResult.aDataRangeRepresentations.push_back( aRange );
948 
949             //is column hidden?
950             if( !lcl_SequenceHasUnhiddenData(aIt->first) && !lcl_SequenceHasUnhiddenData(aIt->second) )
951                 aResult.aHiddenColumns.push_back(nSeqIdx);
952         }
953         Sequence< Sequence< Any > >& rComplexAnyLabels = bSeriesFromColumns ? aResult.aComplexColumnDescriptions : aResult.aComplexRowDescriptions;//#i116544#
954         rComplexAnyLabels.realloc(aComplexLabels.getLength());
955         for( sal_Int32 nN=0; nN<aComplexLabels.getLength();nN++ )
956         {
957             Sequence< OUString >& rSource = aComplexLabels[nN];
958             Sequence< Any >& rTarget = rComplexAnyLabels[nN];
959             rTarget.realloc( rSource.getLength() );
960             for( sal_Int32 i=0; i<rSource.getLength(); i++ )
961                 rTarget[i] = uno::makeAny( rSource[i] );
962         }
963     }
964     catch( uno::Exception & rEx )
965     {
966         (void)rEx; // avoid warning for pro build
967         OSL_TRACE( OUStringToOString( OUString( RTL_CONSTASCII_USTRINGPARAM(
968                     "something went wrong during table data collection: " )) + rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
969     }
970 
971     return aResult;
972 }
973 
lcl_exportNumberFormat(const OUString & rPropertyName,const Reference<beans::XPropertySet> & xPropSet,SvXMLExport & rExport)974 void lcl_exportNumberFormat( const OUString& rPropertyName, const Reference< beans::XPropertySet >& xPropSet,
975                                         SvXMLExport& rExport )
976 {
977     if( xPropSet.is())
978     {
979         sal_Int32 nNumberFormat = 0;
980         Any aNumAny = xPropSet->getPropertyValue( rPropertyName );
981         if( (aNumAny >>= nNumberFormat) && (nNumberFormat != -1) )
982             rExport.addDataStyle( nNumberFormat );
983     }
984 }
985 
986 ::std::vector< Reference< chart2::data::XDataSequence > >
lcl_getErrorBarSequences(const Reference<beans::XPropertySet> & xErrorBarProp)987     lcl_getErrorBarSequences( const Reference< beans::XPropertySet > & xErrorBarProp )
988 {
989     ::std::vector< Reference< chart2::data::XDataSequence > > aResult;
990     Reference< chart2::data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
991     if( !xErrorBarDataSource.is())
992         return aResult;
993 
994     const OUString aRolePrefix( RTL_CONSTASCII_USTRINGPARAM( "error-bars-" ));
995 //     const OUString aXRolePrefix( aRolePrefix + OUString( RTL_CONSTASCII_USTRINGPARAM( "x-" )));
996 //     const OUString aYRolePrefix( aRolePrefix + OUString( RTL_CONSTASCII_USTRINGPARAM( "y-" )));
997 //     const OUString aPositivePostfix( RTL_CONSTASCII_USTRINGPARAM( "positive" ));
998 //     const OUString aNegativePostfix( RTL_CONSTASCII_USTRINGPARAM( "negative" ));
999 
1000     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
1001         xErrorBarDataSource->getDataSequences());
1002     for( sal_Int32 nI=0; nI< aSequences.getLength(); ++nI )
1003     {
1004         try
1005         {
1006             if( aSequences[nI].is())
1007             {
1008                 Reference< chart2::data::XDataSequence > xSequence( aSequences[nI]->getValues());
1009                 Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
1010                 OUString aRole;
1011                 if( ( xSeqProp->getPropertyValue(
1012                           OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" ))) >>= aRole ) &&
1013                     aRole.match( aRolePrefix ))
1014                 {
1015                     aResult.push_back( xSequence );
1016                 }
1017             }
1018         }
1019         catch( uno::Exception & rEx )
1020         {
1021 #ifdef DBG_UTIL
1022             String aStr( rEx.Message );
1023             ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
1024             DBG_ERROR1( "chart:exporting error bar ranges: %s", aBStr.GetBuffer());
1025 #else
1026             (void)rEx; // avoid warning
1027 #endif
1028         }
1029     }
1030 
1031     return aResult;
1032 }
1033 
lcl_exportDomainForThisSequence(const Reference<chart2::data::XDataSequence> xValues,rtl::OUString & rFirstRangeForThisDomainIndex,SvXMLExport & rExport)1034 bool lcl_exportDomainForThisSequence( const Reference< chart2::data::XDataSequence > xValues, rtl::OUString& rFirstRangeForThisDomainIndex, SvXMLExport& rExport )
1035 {
1036     bool bDomainExported = false;
1037     if( xValues.is())
1038     {
1039         Reference< chart2::XChartDocument > xNewDoc( rExport.GetModel(), uno::UNO_QUERY );
1040         OUString aRange( lcl_ConvertRange( xValues->getSourceRangeRepresentation(), xNewDoc ) );
1041 
1042         //work around error in OOo 2.0 (problems with multiple series having a domain element)
1043         if( !rFirstRangeForThisDomainIndex.getLength() || !aRange.equals(rFirstRangeForThisDomainIndex) )
1044         {
1045             rExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, aRange);
1046             SvXMLElementExport aDomain( rExport, XML_NAMESPACE_CHART, XML_DOMAIN, sal_True, sal_True );
1047             bDomainExported = true;
1048         }
1049 
1050         if( !rFirstRangeForThisDomainIndex.getLength() )
1051             rFirstRangeForThisDomainIndex = aRange;
1052     }
1053     return bDomainExported;
1054 }
1055 
1056 } // anonymous namespace
1057 
1058 struct SchXMLDataPointStruct
1059 {
1060     OUString   maStyleName;
1061     sal_Int32  mnRepeat;
1062 
SchXMLDataPointStructSchXMLDataPointStruct1063     SchXMLDataPointStruct() : mnRepeat( 1 ) {}
1064 };
1065 
1066 // ========================================
1067 // class SchXMLExportHelper
1068 // ========================================
1069 
SchXMLExportHelper(SvXMLExport & rExport,SvXMLAutoStylePoolP & rASPool)1070 SchXMLExportHelper::SchXMLExportHelper( SvXMLExport& rExport, SvXMLAutoStylePoolP& rASPool )
1071     : m_pImpl( new SchXMLExportHelper_Impl( rExport, rASPool ) )
1072 {
1073 }
1074 
~SchXMLExportHelper()1075 SchXMLExportHelper::~SchXMLExportHelper()
1076 {
1077     delete m_pImpl;
1078 }
1079 
getChartCLSID()1080 const OUString& SchXMLExportHelper::getChartCLSID()
1081 {
1082     return m_pImpl->msCLSID;
1083 }
1084 
GetPropertySetMapper() const1085 UniReference< XMLPropertySetMapper > SchXMLExportHelper_Impl::GetPropertySetMapper() const
1086 {
1087     return mxPropertySetMapper;
1088 }
1089 
exportAutoStyles()1090 void SchXMLExportHelper_Impl::exportAutoStyles()
1091 {
1092     if( mxExpPropMapper.is())
1093     {
1094         //ToDo: when embedded in calc/writer this is not necessary because the
1095         // numberformatter is shared between both documents
1096         mrExport.exportAutoDataStyles();
1097 
1098         // export chart auto styles
1099         mrAutoStylePool.exportXML(
1100             XML_STYLE_FAMILY_SCH_CHART_ID
1101             , mrExport.GetDocHandler(),
1102             mrExport.GetMM100UnitConverter(),
1103             mrExport.GetNamespaceMap()
1104             );
1105 
1106         // export auto styles for additional shapes
1107         mrExport.GetShapeExport()->exportAutoStyles();
1108         // and for text in additional shapes
1109         mrExport.GetTextParagraphExport()->exportTextAutoStyles();
1110     }
1111 }
1112 
1113 // private methods
1114 // ---------------
1115 
SchXMLExportHelper_Impl(SvXMLExport & rExport,SvXMLAutoStylePoolP & rASPool)1116 SchXMLExportHelper_Impl::SchXMLExportHelper_Impl(
1117     SvXMLExport& rExport,
1118     SvXMLAutoStylePoolP& rASPool ) :
1119         mrExport( rExport ),
1120         mrAutoStylePool( rASPool ),
1121         mbHasSeriesLabels( sal_False ),
1122         mbHasCategoryLabels( sal_False ),
1123         mbRowSourceColumns( sal_True )
1124         // #110680#
1125         // this id depends on the ServiceManager used due to the binary filter stripping.
1126         // ,msCLSID( rtl::OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName()))
1127 {
1128     // #110680#
1129     // changed initialisation for msCLSID. Compare the ServiceInfo name with
1130     // the known name of the LegacyServiceManager.
1131     Reference<lang::XServiceInfo> xServiceInfo( mrExport.getServiceFactory(), uno::UNO_QUERY );
1132     DBG_ASSERT( xServiceInfo.is(), "XMultiServiceFactory without xServiceInfo (!)" );
1133     OUString rdbURL = xServiceInfo->getImplementationName();
1134     OUString implLegacyServiceManagerName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.office.LegacyServiceManager" ) );
1135 
1136     if( rdbURL.equals( implLegacyServiceManagerName ))
1137     {
1138         msCLSID = OUString( SvGlobalName( BF_SO3_SCH_CLASSID ).GetHexName());
1139     }
1140     else
1141     {
1142         msCLSID = OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName());
1143     }
1144 
1145     msTableName = OUString::createFromAscii( "local-table" );
1146 
1147     // create factory
1148     mxPropertyHandlerFactory = new XMLChartPropHdlFactory;
1149 
1150     if( mxPropertyHandlerFactory.is() )
1151     {
1152         // create property set mapper
1153         mxPropertySetMapper = new XMLChartPropertySetMapper;
1154     }
1155 
1156     mxExpPropMapper = new XMLChartExportPropertyMapper( mxPropertySetMapper, rExport );
1157 
1158     // register chart auto-style family
1159     mrAutoStylePool.AddFamily(
1160         XML_STYLE_FAMILY_SCH_CHART_ID,
1161         OUString::createFromAscii( XML_STYLE_FAMILY_SCH_CHART_NAME ),
1162         mxExpPropMapper.get(),
1163         OUString::createFromAscii( XML_STYLE_FAMILY_SCH_CHART_PREFIX ));
1164 
1165     // register shape family
1166     mrAutoStylePool.AddFamily(
1167         XML_STYLE_FAMILY_SD_GRAPHICS_ID,
1168         OUString::createFromAscii( XML_STYLE_FAMILY_SD_GRAPHICS_NAME ),
1169         mxExpPropMapper.get(),
1170         OUString::createFromAscii( XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX ));
1171     // register paragraph family also for shapes
1172     mrAutoStylePool.AddFamily(
1173         XML_STYLE_FAMILY_TEXT_PARAGRAPH,
1174         GetXMLToken( XML_PARAGRAPH ),
1175         mxExpPropMapper.get(),
1176         String( 'P' ));
1177     // register text family also for shapes
1178     mrAutoStylePool.AddFamily(
1179         XML_STYLE_FAMILY_TEXT_TEXT,
1180         GetXMLToken( XML_TEXT ),
1181         mxExpPropMapper.get(),
1182         String( 'T' ));
1183 }
1184 
~SchXMLExportHelper_Impl()1185 SchXMLExportHelper_Impl::~SchXMLExportHelper_Impl()
1186 {
1187 }
1188 
collectAutoStyles(Reference<chart::XChartDocument> rChartDoc)1189 void SchXMLExportHelper_Impl::collectAutoStyles( Reference< chart::XChartDocument > rChartDoc )
1190 {
1191     parseDocument( rChartDoc, sal_False );
1192 }
1193 
exportChart(Reference<chart::XChartDocument> rChartDoc,sal_Bool bIncludeTable)1194 void SchXMLExportHelper_Impl::exportChart( Reference< chart::XChartDocument > rChartDoc,
1195                                       sal_Bool bIncludeTable )
1196 {
1197     parseDocument( rChartDoc, sal_True, bIncludeTable );
1198     DBG_ASSERT( maAutoStyleNameQueue.empty(), "There are still remaining autostyle names in the queue" );
1199 }
1200 
lcl_GetStringFromNumberSequence(const::com::sun::star::uno::Sequence<sal_Int32> & rSequenceMapping,bool bRemoveOneFromEachIndex)1201 ::rtl::OUString lcl_GetStringFromNumberSequence( const ::com::sun::star::uno::Sequence< sal_Int32 >& rSequenceMapping, bool bRemoveOneFromEachIndex /*should be true if having categories*/ )
1202 {
1203     const sal_Int32* pArray = rSequenceMapping.getConstArray();
1204     const sal_Int32 nSize = rSequenceMapping.getLength();
1205     sal_Int32 i = 0;
1206     OUStringBuffer aBuf;
1207     bool bHasPredecessor = false;
1208     for( i = 0; i < nSize; ++i )
1209     {
1210         sal_Int32 nIndex = pArray[ i ];
1211         if( bRemoveOneFromEachIndex )
1212             --nIndex;
1213         if(nIndex>=0)
1214         {
1215             if(bHasPredecessor)
1216                 aBuf.append( static_cast< sal_Unicode >( ' ' ));
1217             aBuf.append( nIndex, 10 );
1218             bHasPredecessor = true;
1219         }
1220     }
1221     return aBuf.makeStringAndClear();
1222 }
1223 
1224 /// if bExportContent is false the auto-styles are collected
parseDocument(Reference<chart::XChartDocument> & rChartDoc,sal_Bool bExportContent,sal_Bool bIncludeTable)1225 void SchXMLExportHelper_Impl::parseDocument( Reference< chart::XChartDocument >& rChartDoc,
1226                                         sal_Bool bExportContent,
1227                                         sal_Bool bIncludeTable )
1228 {
1229     Reference< chart2::XChartDocument > xNewDoc( rChartDoc, uno::UNO_QUERY );
1230     if( !rChartDoc.is() || !xNewDoc.is() )
1231     {
1232         DBG_ERROR( "No XChartDocument was given for export." );
1233         return;
1234     }
1235 
1236     awt::Size aPageSize( getPageSize( xNewDoc ));
1237     if( bExportContent )
1238         addSize( aPageSize );
1239     Reference< chart::XDiagram > xDiagram = rChartDoc->getDiagram();
1240     Reference< chart2::XDiagram > xNewDiagram;
1241     if( xNewDoc.is())
1242         xNewDiagram.set( xNewDoc->getFirstDiagram());
1243 
1244     //todo remove if model changes are notified and view is updated automatically
1245     if( bExportContent )
1246     {
1247         Reference< util::XRefreshable > xRefreshable( xNewDoc, uno::UNO_QUERY );
1248         if( xRefreshable.is() )
1249             xRefreshable->refresh();
1250     }
1251 
1252     // get Properties of ChartDocument
1253     sal_Bool bHasMainTitle = sal_False;
1254     sal_Bool bHasSubTitle = sal_False;
1255     sal_Bool bHasLegend = sal_False;
1256     util::DateTime aNullDate(0,0,0,0,30,12,1899);
1257 
1258     std::vector< XMLPropertyState > aPropertyStates;
1259 
1260     Reference< beans::XPropertySet > xDocPropSet( rChartDoc, uno::UNO_QUERY );
1261     if( xDocPropSet.is())
1262     {
1263         try
1264         {
1265             Any aAny( xDocPropSet->getPropertyValue(
1266                 OUString( RTL_CONSTASCII_USTRINGPARAM( "HasMainTitle" ))));
1267             aAny >>= bHasMainTitle;
1268             aAny = xDocPropSet->getPropertyValue(
1269                 OUString( RTL_CONSTASCII_USTRINGPARAM( "HasSubTitle" )));
1270             aAny >>= bHasSubTitle;
1271             aAny = xDocPropSet->getPropertyValue(
1272                 OUString( RTL_CONSTASCII_USTRINGPARAM( "HasLegend" )));
1273             aAny >>= bHasLegend;
1274             if ( bIncludeTable )
1275             {
1276                 OUString sNullDate( RTL_CONSTASCII_USTRINGPARAM( "NullDate" ));
1277                 aAny = xDocPropSet->getPropertyValue(sNullDate);
1278                 if ( !aAny.hasValue() )
1279                 {
1280                     Reference<container::XChild> xChild(rChartDoc, uno::UNO_QUERY );
1281                     if ( xChild.is() )
1282                     {
1283                         Reference< beans::XPropertySet > xParentDoc( xChild->getParent(),uno::UNO_QUERY);
1284                         if ( xParentDoc.is() && xParentDoc->getPropertySetInfo()->hasPropertyByName(sNullDate) )
1285                             aAny = xParentDoc->getPropertyValue(sNullDate);
1286                     }
1287                 }
1288 
1289                 aAny >>= aNullDate;
1290             }
1291         }
1292         catch( beans::UnknownPropertyException & )
1293         {
1294             DBG_WARNING( "Required property not found in ChartDocument" );
1295         }
1296     } // if( xDocPropSet.is())
1297 
1298     if ( bIncludeTable && (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 ) )
1299     {
1300         SvXMLElementExport aSet( mrExport, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, sal_True, sal_True );
1301         {
1302             ::rtl::OUStringBuffer sBuffer;
1303             SvXMLUnitConverter::convertDateTime(sBuffer,aNullDate);
1304             mrExport.AddAttribute( XML_NAMESPACE_TABLE,XML_DATE_VALUE,sBuffer.makeStringAndClear());
1305             SvXMLElementExport aNull( mrExport, XML_NAMESPACE_TABLE, XML_NULL_DATE, sal_True, sal_True );
1306         }
1307     }
1308 
1309     // chart element
1310     // -------------
1311 
1312     SvXMLElementExport* pElChart = 0;
1313     // get property states for autostyles
1314     if( mxExpPropMapper.is())
1315     {
1316         Reference< beans::XPropertySet > xPropSet( rChartDoc->getArea(), uno::UNO_QUERY );
1317         if( xPropSet.is())
1318             aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1319     }
1320 
1321     if( bExportContent )
1322     {
1323         //export data provider in xlink:href attribute
1324         const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1325         if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
1326         {
1327             OUString aDataProviderURL( RTL_CONSTASCII_USTRINGPARAM( ".." ) );
1328             if( xNewDoc->hasInternalDataProvider() )
1329                 aDataProviderURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) );
1330             else //special handling for data base data provider necessary
1331             {
1332                 Reference< chart2::data::XDatabaseDataProvider > xDBDataProvider( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1333                 if( xDBDataProvider.is() )
1334                     aDataProviderURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) );
1335             }
1336             mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aDataProviderURL );
1337             mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
1338         }
1339 
1340         OUString sChartType( xDiagram->getDiagramType() );
1341 
1342         // attributes
1343         // determine class
1344         if( sChartType.getLength())
1345         {
1346             enum XMLTokenEnum eXMLChartType = SchXMLTools::getTokenByChartType( sChartType, true /* bUseOldNames */ );
1347 
1348             DBG_ASSERT( eXMLChartType != XML_TOKEN_INVALID, "invalid chart class" );
1349             if( eXMLChartType == XML_TOKEN_INVALID )
1350                 eXMLChartType = XML_BAR;
1351 
1352             if( eXMLChartType == XML_ADD_IN )
1353             {
1354                 // sChartType is the servie-name of the add-in
1355                 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1356                                        mrExport.GetNamespaceMap().GetQNameByKey(
1357                                            XML_NAMESPACE_OOO, sChartType) );
1358             }
1359             else if( eXMLChartType != XML_TOKEN_INVALID )
1360             {
1361                 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
1362                         mrExport.GetNamespaceMap().GetQNameByKey(
1363                             XML_NAMESPACE_CHART, GetXMLToken(eXMLChartType )) );
1364             }
1365 
1366             //column-mapping or row-mapping
1367             if( maSequenceMapping.getLength() )
1368             {
1369                 enum XMLTokenEnum eTransToken = ::xmloff::token::XML_ROW_MAPPING;
1370                 if( mbRowSourceColumns )
1371                     eTransToken = ::xmloff::token::XML_COLUMN_MAPPING;
1372                 ::rtl::OUString aSequenceMappingStr( lcl_GetStringFromNumberSequence(
1373                     maSequenceMapping, mbHasCategoryLabels && !xNewDoc->hasInternalDataProvider() ) );
1374 
1375                 mrExport.AddAttribute( XML_NAMESPACE_CHART,
1376                                         ::xmloff::token::GetXMLToken( eTransToken ),
1377                                         aSequenceMappingStr );
1378             }
1379         }
1380         // write style name
1381         AddAutoStyleAttribute( aPropertyStates );
1382 
1383         //element
1384         pElChart = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_CHART, sal_True, sal_True );
1385     }
1386     else    // autostyles
1387     {
1388         CollectAutoStyle( aPropertyStates );
1389     }
1390     // remove property states for autostyles
1391     aPropertyStates.clear();
1392 
1393     // title element
1394     // -------------
1395 
1396     if( bHasMainTitle )
1397     {
1398         // get property states for autostyles
1399         if( mxExpPropMapper.is())
1400         {
1401             Reference< beans::XPropertySet > xPropSet( rChartDoc->getTitle(), uno::UNO_QUERY );
1402             if( xPropSet.is())
1403                 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1404         }
1405         if( bExportContent )
1406         {
1407             Reference< drawing::XShape > xShape = rChartDoc->getTitle();
1408             if( xShape.is())    // && "hasTitleBeenMoved"
1409                 addPosition( xShape );
1410 
1411             // write style name
1412             AddAutoStyleAttribute( aPropertyStates );
1413 
1414             // element
1415             SvXMLElementExport aElTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, sal_True, sal_True );
1416 
1417             // content (text:p)
1418             Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1419             if( xPropSet.is())
1420             {
1421                 Any aAny( xPropSet->getPropertyValue(
1422                     OUString( RTL_CONSTASCII_USTRINGPARAM( "String" ))));
1423                 OUString aText;
1424                 aAny >>= aText;
1425                 exportText( aText );
1426             }
1427         }
1428         else    // autostyles
1429         {
1430             CollectAutoStyle( aPropertyStates );
1431         }
1432         // remove property states for autostyles
1433         aPropertyStates.clear();
1434     }
1435 
1436     // subtitle element
1437     // ----------------
1438 
1439     if( bHasSubTitle )
1440     {
1441         // get property states for autostyles
1442         if( mxExpPropMapper.is())
1443         {
1444             Reference< beans::XPropertySet > xPropSet( rChartDoc->getSubTitle(), uno::UNO_QUERY );
1445             if( xPropSet.is())
1446                 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1447         }
1448 
1449         if( bExportContent )
1450         {
1451             Reference< drawing::XShape > xShape = rChartDoc->getSubTitle();
1452             if( xShape.is())
1453                 addPosition( xShape );
1454 
1455             // write style name
1456             AddAutoStyleAttribute( aPropertyStates );
1457 
1458             // element (has no subelements)
1459             SvXMLElementExport aElSubTitle( mrExport, XML_NAMESPACE_CHART, XML_SUBTITLE, sal_True, sal_True );
1460 
1461             // content (text:p)
1462             Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1463             if( xPropSet.is())
1464             {
1465                 Any aAny( xPropSet->getPropertyValue(
1466                     OUString( RTL_CONSTASCII_USTRINGPARAM( "String" ))));
1467                 OUString aText;
1468                 aAny >>= aText;
1469                 exportText( aText );
1470             }
1471         }
1472         else    // autostyles
1473         {
1474             CollectAutoStyle( aPropertyStates );
1475         }
1476         // remove property states for autostyles
1477         aPropertyStates.clear();
1478     }
1479 
1480     // legend element
1481     // --------------
1482     if( bHasLegend )
1483     {
1484         // get property states for autostyles
1485         if( mxExpPropMapper.is())
1486         {
1487             Reference< beans::XPropertySet > xPropSet( rChartDoc->getLegend(), uno::UNO_QUERY );
1488             if( xPropSet.is())
1489                 aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1490         }
1491 
1492         if( bExportContent )
1493         {
1494             Reference< beans::XPropertySet > xProp( rChartDoc->getLegend(), uno::UNO_QUERY );
1495             if( xProp.is())
1496             {
1497                 // export legend anchor position
1498                 try
1499                 {
1500                     Any aAny( xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Alignment" ))));
1501                     if( SchXMLEnumConverter::getLegendPositionConverter().exportXML( msString, aAny, mrExport.GetMM100UnitConverter() ) )
1502                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LEGEND_POSITION, msString );
1503                 }
1504                 catch( beans::UnknownPropertyException & )
1505                 {
1506                     DBG_WARNING( "Property Align not found in ChartLegend" );
1507                 }
1508 
1509                 // export absolute legend position
1510                 Reference< drawing::XShape > xLegendShape( xProp, uno::UNO_QUERY );
1511                 addPosition( xLegendShape );
1512 
1513                 // export legend size
1514                 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1515                 if( xLegendShape.is() && nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && ( SvtSaveOptions::IsODFExtended( nCurrentODFVersion ) || nCurrentODFVersion >= SvtSaveOptions::ODFVER_013 ) )//do not export legend-expansion to ODF 1.0 and export size only if extensions are enabled or in ODF 1.3 //#i28670# todo: change this dependent on fileformat evolution
1516                 {
1517                     try
1518                     {
1519                         chart::ChartLegendExpansion nLegendExpansion = chart::ChartLegendExpansion_HIGH;
1520                         OUString aExpansionString;
1521                         Any aAny( xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Expansion" ))));
1522                         bool bHasExpansion = (aAny >>= nLegendExpansion);
1523                         if( bHasExpansion && SchXMLEnumConverter::getLegendExpansionConverter().exportXML( aExpansionString, aAny, mrExport.GetMM100UnitConverter() ) )
1524                         {
1525                             mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION, aExpansionString );
1526                             if( nLegendExpansion == chart::ChartLegendExpansion_CUSTOM)
1527                             {
1528                                 awt::Size aSize( xLegendShape->getSize() );
1529                                 addSize( aSize, nCurrentODFVersion < SvtSaveOptions::ODFVER_013 );
1530                                 rtl::OUStringBuffer aAspectRatioString;
1531                                 SvXMLUnitConverter::convertDouble(aAspectRatioString, double(aSize.Width)/double(aSize.Height));
1532                                 mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION_ASPECT_RATIO, aAspectRatioString.makeStringAndClear() );
1533                             }
1534                         }
1535                     }
1536                     catch( beans::UnknownPropertyException & )
1537                     {
1538                         DBG_WARNING( "Property Expansion not found in ChartLegend" );
1539                     }
1540                 }
1541             }
1542 
1543             // write style name
1544             AddAutoStyleAttribute( aPropertyStates );
1545 
1546             // element
1547             SvXMLElementExport aLegend( mrExport, XML_NAMESPACE_CHART, XML_LEGEND, sal_True, sal_True );
1548         }
1549         else    // autostyles
1550         {
1551             CollectAutoStyle( aPropertyStates );
1552         }
1553         // remove property states for autostyles
1554         aPropertyStates.clear();
1555     }
1556 
1557     // plot-area element
1558     // -----------------
1559     if( xDiagram.is())
1560         exportPlotArea( xDiagram, xNewDiagram, aPageSize, bExportContent, bIncludeTable );
1561 
1562     // export additional shapes
1563     // ------------------------
1564     if( xDocPropSet.is() )
1565     {
1566         if( bExportContent )
1567         {
1568             if( mxAdditionalShapes.is())
1569             {
1570                 // can't call exportShapes with all shapes because the
1571                 // initialisation happened with the complete draw page and not
1572                 // the XShapes object used here. Thus the shapes have to be
1573                 // exported one by one
1574                 UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1575                 Reference< drawing::XShape > xShape;
1576                 const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1577                 for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1578                 {
1579                     mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1580                     DBG_ASSERT( xShape.is(), "Shape without an XShape?" );
1581                     if( ! xShape.is())
1582                         continue;
1583 
1584                     rShapeExport->exportShape( xShape );
1585                 }
1586                 // this would be the easier way if it worked:
1587                 //mrExport.GetShapeExport()->exportShapes( mxAdditionalShapes );
1588             }
1589         }
1590         else
1591         {
1592             // get a sequence of non-chart shapes (inserted via clipboard)
1593             try
1594             {
1595                 Any aShapesAny = xDocPropSet->getPropertyValue( OUString::createFromAscii( "AdditionalShapes" ));
1596                 aShapesAny >>= mxAdditionalShapes;
1597                 if( mrExport.getDefaultVersion() >= SvtSaveOptions::ODFVER_010 && mrExport.getDefaultVersion() < SvtSaveOptions::ODFVER_013 && !SvtSaveOptions::IsODFExtended( mrExport.getDefaultVersion() ) )
1598                     mxAdditionalShapes.clear();
1599             }
1600             catch( uno::Exception & rEx )
1601             {
1602                 (void)rEx; // avoid warning for pro build
1603                 OSL_TRACE(
1604                     OUStringToOString(
1605                         OUString( RTL_CONSTASCII_USTRINGPARAM(
1606                             "AdditionalShapes not found: " )) +
1607                         rEx.Message,
1608                         RTL_TEXTENCODING_ASCII_US ).getStr());
1609             }
1610 
1611             if( mxAdditionalShapes.is())
1612             {
1613                 // seek shapes has to be called for the whole page because in
1614                 // the shape export the vector of shapes is accessed via the
1615                 // ZOrder which might be (actually is) larger than the number of
1616                 // shapes in mxAdditionalShapes
1617                 Reference< drawing::XDrawPageSupplier > xSupplier( rChartDoc, uno::UNO_QUERY );
1618                 DBG_ASSERT( xSupplier.is(), "Cannot retrieve draw page to initialize shape export" );
1619                 if( xSupplier.is() )
1620                 {
1621                     Reference< drawing::XShapes > xDrawPage( xSupplier->getDrawPage(), uno::UNO_QUERY );
1622                     DBG_ASSERT( xDrawPage.is(), "Invalid draw page for initializing shape export" );
1623                     if( xDrawPage.is())
1624                         mrExport.GetShapeExport()->seekShapes( xDrawPage );
1625                 }
1626 
1627                 // can't call collectShapesAutoStyles with all shapes because
1628                 // the initialisation happened with the complete draw page and
1629                 // not the XShapes object used here. Thus the shapes have to be
1630                 // exported one by one
1631                 UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1632                 Reference< drawing::XShape > xShape;
1633                 const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1634                 for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1635                 {
1636                     mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1637                     DBG_ASSERT( xShape.is(), "Shape without an XShape?" );
1638                     if( ! xShape.is())
1639                         continue;
1640 
1641                     rShapeExport->collectShapeAutoStyles( xShape );
1642                 }
1643                 // this would be the easier way if it worked:
1644                 // mrExport.GetShapeExport()->collectShapesAutoStyles( mxAdditionalShapes );
1645             }
1646         }
1647     }
1648 
1649     // table element
1650     // (is included as subelement of chart)
1651     // ------------------------------------
1652     if( bExportContent )
1653     {
1654         // #85929# always export table, otherwise clipboard may loose data
1655         exportTable();
1656     }
1657 
1658     // close <chart:chart> element
1659     if( pElChart )
1660         delete pElChart;
1661 }
1662 
lcl_exportComplexLabel(const Sequence<uno::Any> & rComplexLabel,SvXMLExport & rExport)1663 void lcl_exportComplexLabel( const Sequence< uno::Any >& rComplexLabel, SvXMLExport& rExport )
1664 {
1665     sal_Int32 nLength = rComplexLabel.getLength();
1666     if( nLength<=1 )
1667         return;
1668     SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, sal_True, sal_True );
1669     for(sal_Int32 nN=0; nN<nLength; nN++)
1670     {
1671         SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, sal_True, sal_True );
1672         OUString aString;
1673         if( !(rComplexLabel[nN]>>=aString) )
1674         {
1675             //todo?
1676         }
1677         SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ );
1678     }
1679 }
1680 
exportTable()1681 void SchXMLExportHelper_Impl::exportTable()
1682 {
1683     // table element
1684     // -------------
1685     mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, msTableName );
1686 
1687     try
1688     {
1689         bool bProtected = false;
1690         Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW );
1691         if ( ( xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableDataTableDialog" ) ) ) >>= bProtected ) &&
1692              bProtected )
1693         {
1694             mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE );
1695         }
1696     }
1697     catch ( uno::Exception& )
1698     {
1699     }
1700 
1701     SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, sal_True, sal_True );
1702 
1703     bool bHasOwnData = false;
1704     Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
1705     Reference< chart2::data::XRangeXMLConversion > xRangeConversion;
1706     if( xNewDoc.is())
1707     {
1708         bHasOwnData = xNewDoc->hasInternalDataProvider();
1709         xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1710     }
1711 
1712     Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess;
1713     {
1714         Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY );
1715         if( xChartDoc.is() )
1716             xAnyDescriptionAccess = Reference< chart2::XAnyDescriptionAccess >( xChartDoc->getData(), uno::UNO_QUERY );
1717     }
1718 
1719     if( bHasOwnData )
1720         lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport );
1721     lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport
1722                                 , xAnyDescriptionAccess, maCategoriesRange
1723                                 , mbRowSourceColumns, xRangeConversion ));
1724 
1725     tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin());
1726     const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end());
1727 
1728     tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin());
1729     const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end());
1730 
1731     // declare columns
1732     {
1733         SvXMLElementExport aHeaderColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, sal_True, sal_True );
1734         SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1735     }
1736     if( !aData.aHiddenColumns.empty() || !aData.aColumnDescriptions.empty() )
1737     {
1738         SvXMLElementExport aColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, sal_True, sal_True );
1739 
1740         sal_Int32 nNextIndex = 0;
1741         for( size_t nN=0; nN< aData.aHiddenColumns.size(); nN++ )
1742         {
1743             //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste )
1744             sal_Int32 nHiddenIndex = aData.aHiddenColumns[nN];
1745             if( nHiddenIndex > nNextIndex )
1746             {
1747                 sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex );
1748                 if(nRepeat>1)
1749                     mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1750                                    OUString::valueOf( nRepeat ));
1751                 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1752             }
1753             mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_VISIBILITY, GetXMLToken( XML_COLLAPSE ) );
1754             SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1755             nNextIndex = nHiddenIndex+1;
1756         }
1757 
1758         sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1;
1759         if( nEndIndex >= nNextIndex )
1760         {
1761             sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 );
1762             if(nRepeat>1)
1763                 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1764                                OUString::valueOf( nRepeat ));
1765             SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1766         }
1767     }
1768 
1769     // export rows with content
1770     //export header row
1771     {
1772         SvXMLElementExport aHeaderRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, sal_True, sal_True );
1773         SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True );
1774 
1775         //first one empty cell for the row descriptions
1776         {
1777             SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1778             SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_True );
1779         }
1780 
1781         //export column descriptions
1782         tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin());
1783         const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end());
1784         const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions;
1785         sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength();
1786         sal_Int32 nC = 0;
1787         for( tStringVector::const_iterator aIt( aData.aColumnDescriptions.begin())
1788              ; (aIt != aData.aColumnDescriptions.end())
1789              ; aIt++, nC++ )
1790         {
1791             bool bExportString = true;
1792             if( nC < nComplexCount )
1793             {
1794                 const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC];
1795                 if( rComplexLabel.getLength()>0 )
1796                 {
1797                     double fValue=0.0;
1798                     if( rComplexLabel[0] >>=fValue )
1799                     {
1800                         bExportString = false;
1801 
1802                         SvXMLUnitConverter::convertDouble( msStringBuffer, fValue );
1803                         msString = msStringBuffer.makeStringAndClear();
1804                         mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1805                         mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1806                     }
1807                 }
1808             }
1809             if( bExportString )
1810             {
1811                 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1812             }
1813 
1814             SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1815             exportText( *aIt );
1816             if( nC < nComplexCount )
1817                 lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport );
1818             if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd )
1819             {
1820                 // remind the original range to allow a correct re-association when copying via clipboard
1821                 if ((*aColumnDescriptions_RangeIter).getLength())
1822                     SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter );
1823                 ++aColumnDescriptions_RangeIter;
1824             }
1825         }
1826         OSL_ASSERT( bHasOwnData || aColumnDescriptions_RangeIter == aColumnDescriptions_RangeEnd );
1827     } // closing row and header-rows elements
1828 
1829     // export value rows
1830     if( !aData.aDataInRows.empty() )
1831     {
1832         SvXMLElementExport aRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROWS, sal_True, sal_True );
1833         tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin());
1834         const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions;
1835         sal_Int32 nComplexCount = rComplexRowDescriptions.getLength();
1836         sal_Int32 nC = 0;
1837 
1838         for( t2DNumberContainer::const_iterator aRowIt( aData.aDataInRows.begin())
1839             ; aRowIt != aData.aDataInRows.end()
1840             ; ++aRowIt, ++nC )
1841         {
1842             SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True );
1843 
1844             //export row descriptions
1845             {
1846                 bool bExportString = true;
1847                 if( nC < nComplexCount )
1848                 {
1849                     const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC];
1850                     if( rComplexLabel.getLength()>0 )
1851                     {
1852                         double fValue=0.0;
1853                         if( rComplexLabel[0] >>=fValue )
1854                         {
1855                             bExportString = false;
1856 
1857                             SvXMLUnitConverter::convertDouble( msStringBuffer, fValue );
1858                             msString = msStringBuffer.makeStringAndClear();
1859                             mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1860                             mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1861                         }
1862                     }
1863                 }
1864                 if( bExportString )
1865                 {
1866                     mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1867                 }
1868 
1869                 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1870                 if( aRowDescriptionsIter != aData.aRowDescriptions.end())
1871                 {
1872                     exportText( *aRowDescriptionsIter );
1873                     if( nC < nComplexCount )
1874                         lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport );
1875                     if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd )
1876                     {
1877                         // remind the original range to allow a correct re-association when copying via clipboard
1878                         SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter );
1879                         ++aRowDescriptions_RangeIter;
1880                     }
1881                     ++aRowDescriptionsIter;
1882                 }
1883             }
1884 
1885             //export row values
1886             for( t2DNumberContainer::value_type::const_iterator aColIt( aRowIt->begin());
1887                  aColIt != aRowIt->end(); ++aColIt )
1888             {
1889                 SvXMLUnitConverter::convertDouble( msStringBuffer, *aColIt );
1890                 msString = msStringBuffer.makeStringAndClear();
1891                 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1892                 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1893                 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1894                 exportText( msString, false ); // do not convert tabs and lfs
1895                 if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) &&
1896                     ( mbRowSourceColumns || (aColIt == aRowIt->begin()) ) )
1897                 {
1898                     // remind the original range to allow a correct re-association when copying via clipboard
1899                     if ((*aDataRangeIter).getLength())
1900                         SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter );
1901                     ++aDataRangeIter;
1902                 }
1903             }
1904         }
1905     }
1906 
1907     // if range iterator was used it should have reached its end
1908     OSL_ASSERT( bHasOwnData || (aDataRangeIter == aDataRangeEndIter) );
1909     OSL_ASSERT( bHasOwnData || (aRowDescriptions_RangeIter == aRowDescriptions_RangeEnd) );
1910 }
1911 
1912 namespace
1913 {
1914 
lcl_getCooSys(const Reference<chart2::XDiagram> & xNewDiagram)1915 Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram )
1916 {
1917     Reference< chart2::XCoordinateSystem > xCooSys;
1918     Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY );
1919     if(xCooSysCnt.is())
1920     {
1921         Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1922         if(aCooSysSeq.getLength()>0)
1923             xCooSys = aCooSysSeq[0];
1924     }
1925     return xCooSys;
1926 }
1927 
lcl_getAxis(const Reference<chart2::XCoordinateSystem> & xCooSys,enum XMLTokenEnum eDimension,bool bPrimary=true)1928 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys,
1929         enum XMLTokenEnum eDimension, bool bPrimary=true )
1930 {
1931     Reference< chart2::XAxis > xNewAxis;
1932     try
1933     {
1934         if( xCooSys.is() )
1935         {
1936             sal_Int32 nDimensionIndex=0;
1937             switch( eDimension )
1938             {
1939             case XML_X:
1940                 nDimensionIndex=0;
1941                 break;
1942             case XML_Y:
1943                 nDimensionIndex=1;
1944                 break;
1945             case XML_Z:
1946                 nDimensionIndex=2;
1947                 break;
1948             default:
1949                 break;
1950             }
1951 
1952             xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 );
1953         }
1954     }
1955     catch( const uno::Exception & )
1956     {
1957     }
1958     return xNewAxis;
1959 }
1960 
1961 }
1962 
exportPlotArea(Reference<chart::XDiagram> xDiagram,Reference<chart2::XDiagram> xNewDiagram,const awt::Size & rPageSize,sal_Bool bExportContent,sal_Bool bIncludeTable)1963 void SchXMLExportHelper_Impl::exportPlotArea(
1964     Reference< chart::XDiagram > xDiagram,
1965     Reference< chart2::XDiagram > xNewDiagram,
1966     const awt::Size & rPageSize,
1967     sal_Bool bExportContent,
1968     sal_Bool bIncludeTable )
1969 {
1970     DBG_ASSERT( xDiagram.is(), "Invalid XDiagram as parameter" );
1971     if( ! xDiagram.is())
1972         return;
1973 
1974     // variables for autostyles
1975     Reference< beans::XPropertySet > xPropSet;
1976     std::vector< XMLPropertyState > aPropertyStates;
1977 
1978     sal_Bool bIs3DChart = sal_False;
1979     drawing::HomogenMatrix aTransMatrix;
1980 
1981     msStringBuffer.setLength( 0 );
1982 
1983     // plot-area element
1984     // -----------------
1985 
1986     SvXMLElementExport* pElPlotArea = 0;
1987     // get property states for autostyles
1988     xPropSet = Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY );
1989     if( xPropSet.is())
1990     {
1991         if( mxExpPropMapper.is())
1992             aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1993     }
1994     if( bExportContent )
1995     {
1996         UniReference< XMLShapeExport > rShapeExport;
1997 
1998         // write style name
1999         AddAutoStyleAttribute( aPropertyStates );
2000 
2001         if( msChartAddress.getLength() )
2002         {
2003             if( !bIncludeTable )
2004                 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, msChartAddress );
2005 
2006             Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY );
2007             if( xDoc.is() )
2008             {
2009                 Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY );
2010                 if( xDocProp.is())
2011                 {
2012                     Any aAny;
2013                     sal_Bool bFirstCol = false, bFirstRow = false;
2014 
2015                     try
2016                     {
2017                         aAny = xDocProp->getPropertyValue(
2018                             OUString( RTL_CONSTASCII_USTRINGPARAM( "DataSourceLabelsInFirstColumn" )));
2019                         aAny >>= bFirstCol;
2020                         aAny = xDocProp->getPropertyValue(
2021                             OUString( RTL_CONSTASCII_USTRINGPARAM( "DataSourceLabelsInFirstRow" )));
2022                         aAny >>= bFirstRow;
2023 
2024                         if( bFirstCol || bFirstRow )
2025                         {
2026                             mrExport.AddAttribute( XML_NAMESPACE_CHART,
2027                                                    ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DATA_SOURCE_HAS_LABELS ),
2028                                                    ( bFirstCol
2029                                                      ? ( bFirstRow
2030                                                          ?  ::xmloff::token::GetXMLToken( ::xmloff::token::XML_BOTH )
2031                                                          :  ::xmloff::token::GetXMLToken( ::xmloff::token::XML_COLUMN ))
2032                                                      : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_ROW )));
2033                         }
2034                     }
2035                     catch( beans::UnknownPropertyException & )
2036                     {
2037                         DBG_ERRORFILE( "Properties missing" );
2038                     }
2039                 }
2040             }
2041         }
2042 
2043         // #i72973#, #144135# only export table-number-list in OOo format (also for binary)
2044         Reference< beans::XPropertySet > xExportInfo( mrExport.getExportInfo());
2045         if( msTableNumberList.getLength() &&
2046             xExportInfo.is())
2047         {
2048             try
2049             {
2050                 OUString sExportTableNumListPropName( RTL_CONSTASCII_USTRINGPARAM("ExportTableNumberList"));
2051                 Reference< beans::XPropertySetInfo > xInfo( xExportInfo->getPropertySetInfo());
2052                 bool bExportTableNumberList = false;
2053                 if( xInfo.is() && xInfo->hasPropertyByName( sExportTableNumListPropName ) &&
2054                     (xExportInfo->getPropertyValue( sExportTableNumListPropName ) >>= bExportTableNumberList) &&
2055                     bExportTableNumberList )
2056                 {
2057                     // this attribute is for charts embedded in calc documents only.
2058                     // With this you are able to store a file again in 5.0 binary format
2059                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_TABLE_NUMBER_LIST, msTableNumberList );
2060                 }
2061             }
2062             catch( uno::Exception & rEx )
2063             {
2064 #ifdef DBG_UTIL
2065                 String aStr( rEx.Message );
2066                 ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
2067                 DBG_ERROR1( "chart:TableNumberList property caught: %s", aBStr.GetBuffer());
2068 #else
2069                 (void)rEx; // avoid warning
2070 #endif
2071             }
2072         }
2073 
2074         // attributes
2075         Reference< drawing::XShape > xShape ( xDiagram, uno::UNO_QUERY );
2076         if( xShape.is())
2077         {
2078             addPosition( xShape );
2079             addSize( xShape );
2080         }
2081 
2082         if( xPropSet.is())
2083         {
2084             Any aAny;
2085 
2086             // 3d attributes
2087             try
2088             {
2089                 aAny = xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Dim3D" )));
2090                 aAny >>= bIs3DChart;
2091 
2092                 if( bIs3DChart )
2093                 {
2094                     rShapeExport = mrExport.GetShapeExport();
2095                     if( rShapeExport.is())
2096                         rShapeExport->export3DSceneAttributes( xPropSet );
2097                 }
2098             }
2099             catch( uno::Exception & rEx )
2100             {
2101 #ifdef DBG_UTIL
2102                 String aStr( rEx.Message );
2103                 ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
2104                 DBG_ERROR1( "chart:exportPlotAreaException caught: %s", aBStr.GetBuffer());
2105 #else
2106                 (void)rEx; // avoid warning
2107 #endif
2108             }
2109         }
2110 
2111         // plot-area element
2112         pElPlotArea = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, sal_True, sal_True );
2113 
2114         //inner position rectangle element
2115         exportCoordinateRegion( xDiagram );
2116 
2117         // light sources (inside plot area element)
2118         if( bIs3DChart &&
2119             rShapeExport.is())
2120             rShapeExport->export3DLamps( xPropSet );
2121     }
2122     else    // autostyles
2123     {
2124         CollectAutoStyle( aPropertyStates );
2125     }
2126     // remove property states for autostyles
2127     aPropertyStates.clear();
2128 
2129     // axis elements
2130     // -------------
2131     exportAxes( xDiagram, xNewDiagram, bExportContent );
2132 
2133     // series elements
2134     // ---------------
2135     Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false );
2136     exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() );
2137 
2138     // stock-chart elements
2139     OUString sChartType ( xDiagram->getDiagramType());
2140     if( 0 == sChartType.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart.StockDiagram" )))
2141     {
2142         Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY );
2143         if( xStockPropProvider.is())
2144         {
2145             // stock-gain-marker
2146             Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar();
2147             if( xStockPropSet.is())
2148             {
2149                 aPropertyStates.clear();
2150                 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2151 
2152                 if( !aPropertyStates.empty() )
2153                 {
2154                     if( bExportContent )
2155                     {
2156                         AddAutoStyleAttribute( aPropertyStates );
2157 
2158                         SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_GAIN_MARKER, sal_True, sal_True );
2159                     }
2160                     else
2161                     {
2162                         CollectAutoStyle( aPropertyStates );
2163                     }
2164                 }
2165             }
2166 
2167             // stock-loss-marker
2168             xStockPropSet = xStockPropProvider->getDownBar();
2169             if( xStockPropSet.is())
2170             {
2171                 aPropertyStates.clear();
2172                 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2173 
2174                 if( !aPropertyStates.empty() )
2175                 {
2176                     if( bExportContent )
2177                     {
2178                         AddAutoStyleAttribute( aPropertyStates );
2179 
2180                         SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_LOSS_MARKER, sal_True, sal_True );
2181                     }
2182                     else
2183                     {
2184                         CollectAutoStyle( aPropertyStates );
2185                     }
2186                 }
2187             }
2188 
2189             // stock-range-line
2190             xStockPropSet = xStockPropProvider->getMinMaxLine();
2191             if( xStockPropSet.is())
2192             {
2193                 aPropertyStates.clear();
2194                 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2195 
2196                 if( !aPropertyStates.empty() )
2197                 {
2198                     if( bExportContent )
2199                     {
2200                         AddAutoStyleAttribute( aPropertyStates );
2201 
2202                         SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_RANGE_LINE, sal_True, sal_True );
2203                     }
2204                     else
2205                     {
2206                         CollectAutoStyle( aPropertyStates );
2207                     }
2208                 }
2209             }
2210         }
2211     }
2212 
2213     // wall and floor element
2214     // ----------------------
2215 
2216     Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY );
2217     if( mxExpPropMapper.is() &&
2218         xWallFloorSupplier.is())
2219     {
2220         // remove property states for autostyles
2221         aPropertyStates.clear();
2222 
2223         Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY );
2224         if( xWallPropSet.is())
2225         {
2226             aPropertyStates = mxExpPropMapper->Filter( xWallPropSet );
2227 
2228             if( !aPropertyStates.empty() )
2229             {
2230                 // write element
2231                 if( bExportContent )
2232                 {
2233                     // add style name attribute
2234                     AddAutoStyleAttribute( aPropertyStates );
2235 
2236                     SvXMLElementExport aWall( mrExport, XML_NAMESPACE_CHART, XML_WALL, sal_True, sal_True );
2237                 }
2238                 else    // autostyles
2239                 {
2240                     CollectAutoStyle( aPropertyStates );
2241                 }
2242             }
2243         }
2244 
2245         // floor element
2246         // -------------
2247 
2248         // remove property states for autostyles
2249         aPropertyStates.clear();
2250 
2251         Reference< beans::XPropertySet > xFloorPropSet( xWallFloorSupplier->getFloor(), uno::UNO_QUERY );
2252         if( xFloorPropSet.is())
2253         {
2254             aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet );
2255 
2256             if( !aPropertyStates.empty() )
2257             {
2258                 // write element
2259                 if( bExportContent )
2260                 {
2261                     // add style name attribute
2262                     AddAutoStyleAttribute( aPropertyStates );
2263 
2264                     SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, sal_True, sal_True );
2265                 }
2266                 else    // autostyles
2267                 {
2268                     CollectAutoStyle( aPropertyStates );
2269                 }
2270             }
2271         }
2272     }
2273 
2274     if( pElPlotArea )
2275         delete pElPlotArea;
2276 }
2277 
exportCoordinateRegion(const uno::Reference<chart::XDiagram> & xDiagram)2278 void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram )
2279 {
2280     const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2281     const sal_Bool bODF13( nCurrentODFVersion >= SvtSaveOptions::ODFVER_013 );
2282     if( !bODF13 && !SvtSaveOptions::IsODFExtended( nCurrentODFVersion ) )//ODF 1.2 and older have no coordinate region, extended mode writes it as an extension
2283         return;
2284 
2285     Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY );
2286     DBG_ASSERT( xDiaPos.is(), "Invalid xDiaPos as parameter" );
2287     if( !xDiaPos.is() )
2288         return;
2289 
2290     awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() );
2291     addPosition( awt::Point(aRect.X,aRect.Y) );
2292     addSize( awt::Size(aRect.Width,aRect.Height) );
2293 
2294     SvXMLElementExport aCoordinateRegion( mrExport, bODF13 ? XML_NAMESPACE_CHART : XML_NAMESPACE_CHART_EXT, XML_COORDINATE_REGION, sal_True, sal_True );
2295 }
2296 
2297 namespace
2298 {
lcl_getTimeUnitToken(sal_Int32 nTimeUnit)2299     XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit )
2300     {
2301         XMLTokenEnum eToken = XML_DAYS;
2302         switch( nTimeUnit )
2303         {
2304         case ::com::sun::star::chart::TimeUnit::YEAR:
2305             eToken = XML_YEARS;
2306             break;
2307         case ::com::sun::star::chart::TimeUnit::MONTH:
2308             eToken = XML_MONTHS;
2309             break;
2310         default://days
2311             break;
2312         }
2313         return eToken;
2314     }
2315 }
2316 
exportDateScale(const Reference<beans::XPropertySet> xAxisProps)2317 void SchXMLExportHelper_Impl::exportDateScale( const Reference< beans::XPropertySet > xAxisProps )
2318 {
2319     if( !xAxisProps.is() )
2320         return;
2321 
2322     chart::TimeIncrement aIncrement;
2323     if( (xAxisProps->getPropertyValue( OUString::createFromAscii( "TimeIncrement" )) >>= aIncrement) )
2324     {
2325         sal_Int32 nTimeResolution = ::com::sun::star::chart::TimeUnit::DAY;
2326         if( aIncrement.TimeResolution >>= nTimeResolution )
2327             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) );
2328 
2329         OUStringBuffer aValue;
2330         chart::TimeInterval aInterval;
2331         if( aIncrement.MajorTimeInterval >>= aInterval )
2332         {
2333             SvXMLUnitConverter::convertNumber( aValue, aInterval.Number );
2334             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2335             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2336         }
2337         if( aIncrement.MinorTimeInterval >>= aInterval )
2338         {
2339             SvXMLUnitConverter::convertNumber( aValue, aInterval.Number );
2340             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2341             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2342         }
2343 
2344         SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, sal_True, sal_True );//#i25706#todo: change namespace for next ODF version
2345     }
2346 }
2347 
exportAxisTitle(const Reference<beans::XPropertySet> xTitleProps,bool bExportContent)2348 void SchXMLExportHelper_Impl::exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent )
2349 {
2350     if( !xTitleProps.is() )
2351         return;
2352     std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xTitleProps );
2353     if( bExportContent )
2354     {
2355         OUString aText;
2356         Any aAny( xTitleProps->getPropertyValue(
2357             OUString( RTL_CONSTASCII_USTRINGPARAM( "String" ))));
2358         aAny >>= aText;
2359 
2360         Reference< drawing::XShape > xShape( xTitleProps, uno::UNO_QUERY );
2361         if( xShape.is())
2362             addPosition( xShape );
2363 
2364         AddAutoStyleAttribute( aPropertyStates );
2365         SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, sal_True, sal_True );
2366 
2367         // paragraph containing title
2368         exportText( aText );
2369     }
2370     else
2371     {
2372         CollectAutoStyle( aPropertyStates );
2373     }
2374     aPropertyStates.clear();
2375 }
2376 
exportGrid(const Reference<beans::XPropertySet> xGridProperties,bool bMajor,bool bExportContent)2377 void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent )
2378 {
2379     if( !xGridProperties.is() )
2380         return;
2381     std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xGridProperties );
2382     if( bExportContent )
2383     {
2384         AddAutoStyleAttribute( aPropertyStates );
2385         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, bMajor ? XML_MAJOR : XML_MINOR );
2386         SvXMLElementExport aGrid( mrExport, XML_NAMESPACE_CHART, XML_GRID, sal_True, sal_True );
2387     }
2388     else
2389     {
2390         CollectAutoStyle( aPropertyStates );
2391     }
2392     aPropertyStates.clear();
2393 }
2394 
2395 namespace
2396 {
2397 
2398 //returns true if a date scale needs to be exported
lcl_exportAxisType(const Reference<chart2::XAxis> xChart2Axis,SvXMLExport & rExport)2399 bool lcl_exportAxisType( const Reference< chart2::XAxis > xChart2Axis, SvXMLExport& rExport)
2400 {
2401     bool bExportDateScale = false;
2402     if( !xChart2Axis.is() )
2403         return bExportDateScale;
2404 
2405     const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2406     if( !SvtSaveOptions::IsODFExtended( nCurrentODFVersion ) ) //#i25706#todo: change version for next ODF version
2407         return bExportDateScale;
2408 
2409     chart2::ScaleData aScale( xChart2Axis->getScaleData() );
2410     //#i25706#todo: change namespace for next ODF version
2411     sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT;
2412 
2413     switch(aScale.AxisType)
2414     {
2415     case chart2::AxisType::CATEGORY:
2416         if( aScale.AutoDateAxis )
2417         {
2418             rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2419             bExportDateScale = true;
2420         }
2421         else
2422             rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT );
2423         break;
2424     case chart2::AxisType::DATE:
2425         rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE );
2426         bExportDateScale = true;
2427         break;
2428     default: //AUTOMATIC
2429         rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2430         break;
2431     }
2432 
2433     return bExportDateScale;
2434 }
2435 
2436 }
2437 
exportAxis(enum XMLTokenEnum eDimension,enum XMLTokenEnum eAxisName,const Reference<beans::XPropertySet> xAxisProps,const Reference<chart2::XAxis> & xChart2Axis,const OUString & rCategoriesRange,bool bHasTitle,bool bHasMajorGrid,bool bHasMinorGrid,bool bExportContent)2438 void SchXMLExportHelper_Impl::exportAxis(
2439     enum XMLTokenEnum eDimension,
2440     enum XMLTokenEnum eAxisName,
2441     const Reference< beans::XPropertySet > xAxisProps,
2442     const Reference< chart2::XAxis >& xChart2Axis,
2443     const OUString& rCategoriesRange,
2444     bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
2445     bool bExportContent )
2446 {
2447     static const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" ));
2448     std::vector< XMLPropertyState > aPropertyStates;
2449     SvXMLElementExport* pAxis = NULL;
2450 
2451     // get property states for autostyles
2452     if( xAxisProps.is() && mxExpPropMapper.is() )
2453     {
2454         lcl_exportNumberFormat( sNumFormat, xAxisProps, mrExport );
2455         aPropertyStates = mxExpPropMapper->Filter( xAxisProps );
2456     }
2457 
2458     bool bExportDateScale = false;
2459     if( bExportContent )
2460     {
2461         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, eDimension );
2462         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_NAME, eAxisName );
2463         AddAutoStyleAttribute( aPropertyStates ); // write style name
2464         if( rCategoriesRange.getLength() )
2465             bExportDateScale = lcl_exportAxisType( xChart2Axis, mrExport );
2466 
2467         // open axis element
2468         pAxis = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, sal_True, sal_True );
2469     }
2470     else
2471     {
2472         CollectAutoStyle( aPropertyStates );
2473     }
2474     aPropertyStates.clear();
2475 
2476     //date scale
2477     if( bExportDateScale )
2478         exportDateScale( xAxisProps );
2479 
2480     Reference< beans::XPropertySet > xTitleProps;
2481     Reference< beans::XPropertySet > xMajorGridProps;
2482     Reference< beans::XPropertySet > xMinorGridProps;
2483     Reference< chart::XAxis > xAxis( xAxisProps, uno::UNO_QUERY );
2484     if( xAxis.is() )
2485     {
2486         xTitleProps = bHasTitle ? xAxis->getAxisTitle() : 0;
2487         xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : 0;
2488         xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : 0;
2489     }
2490 
2491     // axis-title
2492     exportAxisTitle( xTitleProps , bExportContent );
2493 
2494     // categories if we have a categories chart
2495     if( bExportContent && rCategoriesRange.getLength() )
2496     {
2497         mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, rCategoriesRange );
2498         SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, sal_True, sal_True );
2499     }
2500 
2501     // grid
2502     exportGrid( xMajorGridProps, true, bExportContent );
2503     exportGrid( xMinorGridProps, false, bExportContent );
2504 
2505     if( pAxis )
2506     {
2507         //close axis element
2508         delete pAxis;
2509         pAxis = NULL;
2510     }
2511 }
2512 
exportAxes(const Reference<chart::XDiagram> & xDiagram,const Reference<chart2::XDiagram> & xNewDiagram,sal_Bool bExportContent)2513 void SchXMLExportHelper_Impl::exportAxes(
2514     const Reference< chart::XDiagram > & xDiagram,
2515     const Reference< chart2::XDiagram > & xNewDiagram,
2516     sal_Bool bExportContent )
2517 {
2518     DBG_ASSERT( xDiagram.is(), "Invalid XDiagram as parameter" );
2519     if( ! xDiagram.is())
2520         return;
2521 
2522     // get some properties from document first
2523     sal_Bool bHasXAxis = sal_False,
2524         bHasYAxis = sal_False,
2525         bHasZAxis = sal_False,
2526         bHasSecondaryXAxis = sal_False,
2527         bHasSecondaryYAxis = sal_False;
2528     sal_Bool bHasXAxisTitle = sal_False,
2529         bHasYAxisTitle = sal_False,
2530         bHasZAxisTitle = sal_False,
2531         bHasSecondaryXAxisTitle = sal_False,
2532         bHasSecondaryYAxisTitle = sal_False;
2533     sal_Bool bHasXAxisMajorGrid = sal_False,
2534         bHasXAxisMinorGrid = sal_False,
2535         bHasYAxisMajorGrid = sal_False,
2536         bHasYAxisMinorGrid = sal_False,
2537         bHasZAxisMajorGrid = sal_False,
2538         bHasZAxisMinorGrid = sal_False;
2539 
2540     // get multiple properties using XMultiPropertySet
2541     MultiPropertySetHandler aDiagramProperties (xDiagram);
2542 
2543     aDiagramProperties.Add (
2544         OUString(RTL_CONSTASCII_USTRINGPARAM("HasXAxis")), bHasXAxis);
2545     aDiagramProperties.Add (
2546         OUString(RTL_CONSTASCII_USTRINGPARAM("HasYAxis")), bHasYAxis);
2547     aDiagramProperties.Add (
2548         OUString(RTL_CONSTASCII_USTRINGPARAM("HasZAxis")), bHasZAxis);
2549     aDiagramProperties.Add (
2550         OUString(RTL_CONSTASCII_USTRINGPARAM("HasSecondaryXAxis")), bHasSecondaryXAxis);
2551     aDiagramProperties.Add (
2552         OUString(RTL_CONSTASCII_USTRINGPARAM("HasSecondaryYAxis")), bHasSecondaryYAxis);
2553 
2554     aDiagramProperties.Add (
2555         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisTitle")), bHasXAxisTitle);
2556     aDiagramProperties.Add (
2557         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisTitle")), bHasYAxisTitle);
2558     aDiagramProperties.Add (
2559         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisTitle")), bHasZAxisTitle);
2560     aDiagramProperties.Add (
2561         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasSecondaryXAxisTitle")), bHasSecondaryXAxisTitle);
2562     aDiagramProperties.Add (
2563         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasSecondaryYAxisTitle")), bHasSecondaryYAxisTitle);
2564 
2565     aDiagramProperties.Add (
2566         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisGrid")), bHasXAxisMajorGrid);
2567     aDiagramProperties.Add (
2568         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisGrid")), bHasYAxisMajorGrid);
2569     aDiagramProperties.Add (
2570         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisGrid")), bHasZAxisMajorGrid);
2571 
2572     aDiagramProperties.Add (
2573         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisHelpGrid")), bHasXAxisMinorGrid);
2574     aDiagramProperties.Add (
2575         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisHelpGrid")), bHasYAxisMinorGrid);
2576     aDiagramProperties.Add (
2577         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisHelpGrid")), bHasZAxisMinorGrid);
2578 
2579     if ( ! aDiagramProperties.GetProperties ())
2580     {
2581         DBG_WARNING ("Required properties not found in Chart diagram");
2582     }
2583 
2584     Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) );
2585 
2586     // write an axis element also if the axis itself is not visible, but a grid or a title
2587 
2588     OUString aCategoriesRange;
2589     Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );
2590 
2591     // x axis
2592     // -------
2593     Reference< ::com::sun::star::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X );
2594     if( xNewAxis.is() )
2595     {
2596         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : 0, uno::UNO_QUERY );
2597         if( mbHasCategoryLabels && bExportContent )
2598         {
2599             Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2600             if( xCategories.is() )
2601             {
2602                 Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2603                 if( xValues.is() )
2604                 {
2605                     Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2606                     maCategoriesRange = xValues->getSourceRangeRepresentation();
2607                     aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc );
2608                 }
2609             }
2610         }
2611         exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent );
2612         aCategoriesRange = OUString();
2613     }
2614 
2615     // secondary x axis
2616     // -------
2617     Reference< chart::XSecondAxisTitleSupplier > xSecondTitleSupp( xDiagram, uno::UNO_QUERY );
2618     xNewAxis = lcl_getAxis( xCooSys, XML_X, false );
2619     if( xNewAxis.is() )
2620     {
2621         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : 0, uno::UNO_QUERY );
2622         exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent );
2623     }
2624 
2625     // y axis
2626     // -------
2627     xNewAxis = lcl_getAxis( xCooSys, XML_Y );
2628     if( xNewAxis.is() )
2629     {
2630         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : 0, uno::UNO_QUERY );
2631         exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent );
2632     }
2633 
2634     // secondary y axis
2635     // -------
2636     xNewAxis = lcl_getAxis( xCooSys, XML_Y, false );
2637     if( xNewAxis.is() )
2638     {
2639         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : 0, uno::UNO_QUERY );
2640         exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent );
2641     }
2642 
2643     // z axis
2644     // -------
2645     xNewAxis = lcl_getAxis( xCooSys, XML_Z );
2646     if( xNewAxis.is() )
2647     {
2648         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : 0, uno::UNO_QUERY );
2649         exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent );
2650     }
2651 }
2652 
2653 namespace
2654 {
lcl_hasNoValuesButText(const uno::Reference<chart2::data::XDataSequence> & xDataSequence)2655     bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
2656     {
2657         if( !xDataSequence.is() )
2658             return false;//have no data
2659 
2660         Sequence< uno::Any > aData;
2661         Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
2662         if( xNumericalDataSequence.is() )
2663         {
2664             Sequence< double >  aDoubles( xNumericalDataSequence->getNumericalData() );
2665             sal_Int32 nCount = aDoubles.getLength();
2666             for( sal_Int32 i = 0; i < nCount; ++i )
2667             {
2668                 if( !::rtl::math::isNan( aDoubles[i] ) )
2669                     return false;//have double value
2670             }
2671         }
2672         else
2673         {
2674             aData = xDataSequence->getData();
2675             double fDouble = 0.0;
2676             sal_Int32 nCount = aData.getLength();
2677             for( sal_Int32 i = 0; i < nCount; ++i )
2678             {
2679                 if( (aData[i] >>= fDouble) && !::rtl::math::isNan( fDouble ) )
2680                     return false;//have double value
2681             }
2682 
2683         }
2684         //no values found
2685 
2686         Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
2687         if( xTextualDataSequence.is() )
2688         {
2689             uno::Sequence< rtl::OUString > aStrings( xTextualDataSequence->getTextualData() );
2690             sal_Int32 nCount = aStrings.getLength();
2691             for( sal_Int32 i = 0; i < nCount; ++i )
2692             {
2693                 if( aStrings[i].getLength() )
2694                     return true;//have text
2695             }
2696         }
2697         else
2698         {
2699             if( !aData.getLength() )
2700                 aData = xDataSequence->getData();
2701             uno::Any aAny;
2702             OUString aString;
2703             sal_Int32 nCount = aData.getLength();
2704             for( sal_Int32 i = 0; i < nCount; ++i )
2705             {
2706                 if( (aData[i]>>=aString) && aString.getLength() )
2707                     return true;//have text
2708             }
2709         }
2710         //no doubles and no texts
2711         return false;
2712     }
2713 }
2714 
exportSeries(const Reference<chart2::XDiagram> & xNewDiagram,const awt::Size & rPageSize,sal_Bool bExportContent,sal_Bool bHasTwoYAxes)2715 void SchXMLExportHelper_Impl::exportSeries(
2716     const Reference< chart2::XDiagram > & xNewDiagram,
2717     const awt::Size & rPageSize,
2718     sal_Bool bExportContent,
2719     sal_Bool bHasTwoYAxes )
2720 {
2721     Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY );
2722     if( ! xBCooSysCnt.is())
2723         return;
2724     Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2725 
2726     OUString aFirstXDomainRange;
2727     OUString aFirstYDomainRange;
2728 
2729     std::vector< XMLPropertyState > aPropertyStates;
2730 
2731     const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" ));
2732     const OUString sPercentageNumFormat( OUString::createFromAscii( "PercentageNumberFormat" ));
2733 
2734     Sequence< Reference< chart2::XCoordinateSystem > >
2735         aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
2736     for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx )
2737     {
2738         Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY );
2739         if( ! xCTCnt.is())
2740             continue;
2741         Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
2742         for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx )
2743         {
2744             Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY );
2745             if( ! xDSCnt.is())
2746                 continue;
2747             // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
2748             OUString aChartType( aCTSeq[nCTIdx]->getChartType());
2749             OUString aLabelRole = aCTSeq[nCTIdx]->getRoleOfSequenceForSeriesLabel();
2750 
2751             // special export for stock charts
2752             if( aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.CandleStickChartType")))
2753             {
2754                 sal_Bool bJapaneseCandleSticks = sal_False;
2755                 Reference< beans::XPropertySet > xCTProp( aCTSeq[nCTIdx], uno::UNO_QUERY );
2756                 if( xCTProp.is())
2757                     xCTProp->getPropertyValue( OUString::createFromAscii("Japanese")) >>= bJapaneseCandleSticks;
2758                 exportCandleStickSeries(
2759                     xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent );
2760                 continue;
2761             }
2762 
2763             // export dataseries for current chart-type
2764             Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
2765             for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
2766             {
2767                 // export series
2768                 Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
2769                 if( xSource.is())
2770                 {
2771                     SvXMLElementExport* pSeries = NULL;
2772                     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2773                         xSource->getDataSequences());
2774                     sal_Int32 nMainSequenceIndex = -1;
2775                     sal_Int32 nSeriesLength = 0;
2776                     sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y;
2777                     sal_Bool bHasMeanValueLine = false;
2778                     chart::ChartRegressionCurveType eRegressionType( chart::ChartRegressionCurveType_NONE );
2779                     chart::ChartErrorIndicatorType eErrorType( chart::ChartErrorIndicatorType_NONE );
2780                     sal_Int32 nErrorBarStyle( chart::ErrorBarStyle::NONE );
2781                     Reference< beans::XPropertySet > xPropSet;
2782                     tLabelValuesDataPair aSeriesLabelValuesPair;
2783 
2784                     // search for main sequence and create a series element
2785                     {
2786                         Reference< chart2::data::XDataSequence > xValuesSeq;
2787                         Reference< chart2::data::XDataSequence > xLabelSeq;
2788                         sal_Int32 nSeqIdx=0;
2789                         for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
2790                         {
2791                             OUString aRole;
2792                             Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
2793                             if( nMainSequenceIndex==-1 )
2794                             {
2795                                 Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
2796                                 if( xSeqProp.is())
2797                                     xSeqProp->getPropertyValue(OUString::createFromAscii("Role")) >>= aRole;
2798                                 // "main" sequence
2799                                 if( aRole.equals( aLabelRole ))
2800                                 {
2801                                     xValuesSeq.set( xTempValueSeq );
2802                                     xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
2803                                     nMainSequenceIndex = nSeqIdx;
2804                                 }
2805                             }
2806                             sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
2807                             if( nSeriesLength < nSequenceLength )
2808                                 nSeriesLength = nSequenceLength;
2809                         }
2810 
2811                         // have found the main sequence, then xValuesSeq and
2812                         // xLabelSeq contain those.  Otherwise both are empty
2813                         {
2814                             // get property states for autostyles
2815                             try
2816                             {
2817                                 xPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
2818                                     aSeriesSeq[nSeriesIdx], mrExport.GetModel() );
2819                             }
2820                             catch( uno::Exception & rEx )
2821                             {
2822                                 (void)rEx; // avoid warning for pro build
2823                                 OSL_TRACE(
2824                                     OUStringToOString(
2825                                         OUString( RTL_CONSTASCII_USTRINGPARAM(
2826                                                       "Series not found or no XPropertySet: " )) +
2827                                         rEx.Message,
2828                                         RTL_TEXTENCODING_ASCII_US ).getStr());
2829                                 continue;
2830                             }
2831                             if( xPropSet.is())
2832                             {
2833                                 // determine attached axis
2834                                 try
2835                                 {
2836                                     Any aAny( xPropSet->getPropertyValue(
2837                                                   OUString( RTL_CONSTASCII_USTRINGPARAM( "Axis" ))));
2838                                     aAny >>= nAttachedAxis;
2839 
2840                                     aAny = xPropSet->getPropertyValue(
2841                                         OUString( RTL_CONSTASCII_USTRINGPARAM ( "MeanValue" )));
2842                                     aAny >>= bHasMeanValueLine;
2843 
2844                                     aAny = xPropSet->getPropertyValue(
2845                                         OUString( RTL_CONSTASCII_USTRINGPARAM( "RegressionCurves" )));
2846                                     aAny >>= eRegressionType;
2847 
2848                                     aAny = xPropSet->getPropertyValue(
2849                                         OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorIndicator" )));
2850                                     aAny >>= eErrorType;
2851 
2852                                     aAny = xPropSet->getPropertyValue(
2853                                         OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorBarStyle" )));
2854                                     aAny >>= nErrorBarStyle;
2855                                 }
2856                                 catch( beans::UnknownPropertyException & rEx )
2857                                 {
2858                                     (void)rEx; // avoid warning for pro build
2859                                     OSL_TRACE(
2860                                         OUStringToOString(
2861                                             OUString( RTL_CONSTASCII_USTRINGPARAM(
2862                                                           "Required property not found in DataRowProperties: " )) +
2863                                             rEx.Message,
2864                                             RTL_TEXTENCODING_ASCII_US ).getStr());
2865                                 }
2866 
2867                                 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2868                                 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
2869                                 {
2870                                     lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
2871                                     lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
2872                                 }
2873 
2874                                 if( mxExpPropMapper.is())
2875                                     aPropertyStates = mxExpPropMapper->Filter( xPropSet );
2876                             }
2877 
2878                             if( bExportContent )
2879                             {
2880                                 if( bHasTwoYAxes )
2881                                 {
2882                                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
2883                                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
2884                                     else
2885                                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
2886                                 }
2887 
2888                                 // write style name
2889                                 AddAutoStyleAttribute( aPropertyStates );
2890 
2891                                 if( xValuesSeq.is())
2892                                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS,
2893                                                            lcl_ConvertRange(
2894                                                                xValuesSeq->getSourceRangeRepresentation(),
2895                                                                xNewDoc ));
2896                                 else
2897                                     // #i75297# allow empty series, export empty range to have all ranges on import
2898                                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, OUString());
2899 
2900                                 if( xLabelSeq.is())
2901                                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS,
2902                                                            lcl_ConvertRange(
2903                                                                xLabelSeq->getSourceRangeRepresentation(),
2904                                                                xNewDoc ));
2905                                 if( xLabelSeq.is() || xValuesSeq.is() )
2906                                     aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq );
2907 
2908                                 // chart-type for mixed types
2909                                 enum XMLTokenEnum eCTToken(
2910                                     SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ ));
2911                                 //@todo: get token for current charttype
2912                                 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
2913                                                        mrExport.GetNamespaceMap().GetQNameByKey(
2914                                                            XML_NAMESPACE_CHART, GetXMLToken( eCTToken )));
2915 
2916                                 // open series element until end of for loop
2917                                 pSeries = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
2918                             }
2919                             else    // autostyles
2920                             {
2921                                 CollectAutoStyle( aPropertyStates );
2922                             }
2923                             // remove property states for autostyles
2924                             aPropertyStates.clear();
2925                         }
2926                     }
2927 
2928                     // export domain elements if we have a series parent element
2929                     if( pSeries )
2930                     {
2931                         // domain elements
2932                         if( bExportContent )
2933                         {
2934                             bool bIsScatterChart = aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.ScatterChartType"));
2935                             bool bIsBubbleChart = aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.BubbleChartType"));
2936                             Reference< chart2::data::XDataSequence > xYValuesForBubbleChart;
2937                             if( bIsBubbleChart )
2938                             {
2939                                 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii("values-y" ) ) );
2940                                 if( xSequence.is() )
2941                                 {
2942                                     xYValuesForBubbleChart = xSequence->getValues();
2943                                     if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) )
2944                                         xYValuesForBubbleChart = 0;
2945                                 }
2946                             }
2947                             if( bIsScatterChart || bIsBubbleChart )
2948                             {
2949                                 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii("values-x" ) ) );
2950                                 if( xSequence.is() )
2951                                 {
2952                                     Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2953                                     if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) )
2954                                         m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, xValues ));
2955                                 }
2956                                 else if( nSeriesIdx==0 )
2957                                 {
2958                                     //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly
2959                                     Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2960                                     if( xCategories.is() )
2961                                     {
2962                                         Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2963                                         if( !lcl_hasNoValuesButText( xValues ) )
2964                                             lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport );
2965                                     }
2966                                 }
2967                             }
2968                             if( xYValuesForBubbleChart.is() )
2969                                 m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, xYValuesForBubbleChart ));
2970                         }
2971                     }
2972 
2973                     // add sequences for main sequence after domain sequences,
2974                     // so that the export of the local table has the correct order
2975                     if( bExportContent &&
2976                         (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is()))
2977                         m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair );
2978 
2979                     // statistical objects:
2980                     // regression curves and mean value lines
2981                     if( bHasMeanValueLine &&
2982                         xPropSet.is() &&
2983                         mxExpPropMapper.is() )
2984                     {
2985                         Reference< beans::XPropertySet > xStatProp;
2986                         try
2987                         {
2988                             Any aPropAny( xPropSet->getPropertyValue(
2989                                             OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMeanValueProperties" ))));
2990                             aPropAny >>= xStatProp;
2991                         }
2992                         catch( uno::Exception & rEx )
2993                         {
2994                             (void)rEx; // avoid warning for pro build
2995                             DBG_ERROR1( "Exception caught during Export of series - optional DataMeanValueProperties not available: %s",
2996                                         OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
2997                         }
2998 
2999                         if( xStatProp.is() )
3000                         {
3001                             aPropertyStates = mxExpPropMapper->Filter( xStatProp );
3002 
3003                             if( !aPropertyStates.empty() )
3004                             {
3005                                 // write element
3006                                 if( bExportContent )
3007                                 {
3008                                     // add style name attribute
3009                                     AddAutoStyleAttribute( aPropertyStates );
3010 
3011                                     SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_MEAN_VALUE, sal_True, sal_True );
3012                                 }
3013                                 else    // autostyles
3014                                 {
3015                                     CollectAutoStyle( aPropertyStates );
3016                                 }
3017                             }
3018                         }
3019                     }
3020 
3021                     if( eRegressionType != chart::ChartRegressionCurveType_NONE &&
3022                         xPropSet.is() &&
3023                         mxExpPropMapper.is() )
3024                     {
3025                         exportRegressionCurve( aSeriesSeq[nSeriesIdx], xPropSet, rPageSize, bExportContent );
3026                     }
3027 
3028                     if( nErrorBarStyle != chart::ErrorBarStyle::NONE &&
3029                         eErrorType != chart::ChartErrorIndicatorType_NONE &&
3030                         xPropSet.is() &&
3031                         mxExpPropMapper.is() )
3032                     {
3033                         Reference< beans::XPropertySet > xStatProp;
3034                         try
3035                         {
3036                             Any aPropAny( xPropSet->getPropertyValue(
3037                                             OUString( RTL_CONSTASCII_USTRINGPARAM( "DataErrorProperties" ))));
3038                             aPropAny >>= xStatProp;
3039                         }
3040                         catch( uno::Exception & rEx )
3041                         {
3042                             (void)rEx; // avoid warning for pro build
3043                             DBG_ERROR1( "Exception caught during Export of series - optional DataErrorProperties not available: %s",
3044                                         OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
3045                         }
3046 
3047                         if( xStatProp.is() )
3048                         {
3049                             if( bExportContent &&
3050                                 nErrorBarStyle == chart::ErrorBarStyle::FROM_DATA )
3051                             {
3052                                 // register data ranges for error bars for export in local table
3053                                 ::std::vector< Reference< chart2::data::XDataSequence > > aErrorBarSequences(
3054                                     lcl_getErrorBarSequences( xStatProp ));
3055                                 for( ::std::vector< Reference< chart2::data::XDataSequence > >::const_iterator aIt(
3056                                          aErrorBarSequences.begin()); aIt != aErrorBarSequences.end(); ++aIt )
3057                                 {
3058                                     m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, *aIt ));
3059                                 }
3060                             }
3061 
3062                             aPropertyStates = mxExpPropMapper->Filter( xStatProp );
3063 
3064                             if( !aPropertyStates.empty() )
3065                             {
3066                                 // write element
3067                                 if( bExportContent )
3068                                 {
3069                                     // add style name attribute
3070                                     AddAutoStyleAttribute( aPropertyStates );
3071 
3072                                     const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
3073                                     if( nCurrentVersion >= SvtSaveOptions::ODFVER_012 )
3074                                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, XML_Y );//#i114149#
3075                                     SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_ERROR_INDICATOR, sal_True, sal_True );
3076                                 }
3077                                 else    // autostyles
3078                                 {
3079                                     CollectAutoStyle( aPropertyStates );
3080                                 }
3081                             }
3082                         }
3083                     }
3084 
3085                     exportDataPoints(
3086                         uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ),
3087                         nSeriesLength, xNewDiagram, bExportContent );
3088 
3089                     // close series element
3090                     if( pSeries )
3091                         delete pSeries;
3092                 }
3093             }
3094             aPropertyStates.clear();
3095         }
3096     }
3097 }
3098 
exportRegressionCurve(const Reference<chart2::XDataSeries> & xSeries,const Reference<beans::XPropertySet> & xSeriesProp,const awt::Size & rPageSize,sal_Bool bExportContent)3099 void SchXMLExportHelper_Impl::exportRegressionCurve(
3100     const Reference< chart2::XDataSeries > & xSeries,
3101     const Reference< beans::XPropertySet > & xSeriesProp,
3102     const awt::Size & rPageSize,
3103     sal_Bool bExportContent )
3104 {
3105     OSL_ASSERT( mxExpPropMapper.is());
3106 
3107     std::vector< XMLPropertyState > aPropertyStates;
3108     std::vector< XMLPropertyState > aEquationPropertyStates;
3109     Reference< beans::XPropertySet > xStatProp;
3110     try
3111     {
3112         Any aPropAny( xSeriesProp->getPropertyValue(
3113                           OUString( RTL_CONSTASCII_USTRINGPARAM( "DataRegressionProperties" ))));
3114         aPropAny >>= xStatProp;
3115     }
3116     catch( uno::Exception & rEx )
3117     {
3118         (void)rEx; // avoid warning for pro build
3119         DBG_ERROR1( "Exception caught during Export of series - optional DataRegressionProperties not available: %s",
3120                     OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
3121     }
3122 
3123     if( xStatProp.is() )
3124     {
3125         Reference< chart2::XRegressionCurve > xRegCurve( SchXMLTools::getRegressionCurve( xSeries ));
3126         Reference< beans::XPropertySet > xEquationProperties;
3127         if( xRegCurve.is())
3128             xEquationProperties.set( xRegCurve->getEquationProperties());
3129 
3130         bool bShowEquation = false;
3131         bool bShowRSquared = false;
3132         bool bExportEquation = false;
3133         aPropertyStates = mxExpPropMapper->Filter( xStatProp );
3134         if( xEquationProperties.is())
3135         {
3136             xEquationProperties->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ShowEquation" )))
3137                 >>= bShowEquation;
3138             xEquationProperties->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ShowCorrelationCoefficient" )))
3139                 >>= bShowRSquared;
3140             bExportEquation = ( bShowEquation || bShowRSquared );
3141             const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
3142             if( nCurrentVersion < SvtSaveOptions::ODFVER_012 )
3143                 bExportEquation=false;
3144             if( bExportEquation )
3145             {
3146                 // number format
3147                 sal_Int32 nNumberFormat = 0;
3148                 if( ( xEquationProperties->getPropertyValue(
3149                           OUString( RTL_CONSTASCII_USTRINGPARAM( "NumberFormat" ))) >>= nNumberFormat ) &&
3150                     nNumberFormat != -1 )
3151                 {
3152                     mrExport.addDataStyle( nNumberFormat );
3153                 }
3154                 aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties );
3155             }
3156         }
3157 
3158         if( !aPropertyStates.empty() || bExportEquation )
3159         {
3160             // write element
3161             if( bExportContent )
3162             {
3163                 // add style name attribute
3164                 if( !aPropertyStates.empty())
3165                     AddAutoStyleAttribute( aPropertyStates );
3166                 SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, sal_True, sal_True );
3167                 if( bExportEquation )
3168                 {
3169                     // default is true
3170                     if( !bShowEquation )
3171                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_EQUATION, XML_FALSE );
3172                     // default is false
3173                     if( bShowRSquared )
3174                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, XML_TRUE );
3175 
3176                     // export position
3177                     chart2::RelativePosition aRelativePosition;
3178                     if( xEquationProperties->getPropertyValue(
3179                             OUString( RTL_CONSTASCII_USTRINGPARAM("RelativePosition"))) >>= aRelativePosition )
3180                     {
3181                         double fX = aRelativePosition.Primary * rPageSize.Width;
3182                         double fY = aRelativePosition.Secondary * rPageSize.Height;
3183                         awt::Point aPos;
3184                         aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
3185                         aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
3186                         addPosition( aPos );
3187                     }
3188 
3189                     if( !aEquationPropertyStates.empty())
3190                         AddAutoStyleAttribute( aEquationPropertyStates );
3191 
3192                     SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_EQUATION, sal_True, sal_True );
3193                 }
3194             }
3195             else    // autostyles
3196             {
3197                 if( !aPropertyStates.empty())
3198                     CollectAutoStyle( aPropertyStates );
3199                 if( bExportEquation && !aEquationPropertyStates.empty())
3200                     CollectAutoStyle( aEquationPropertyStates );
3201             }
3202         }
3203     }
3204 }
3205 
exportCandleStickSeries(const Sequence<Reference<chart2::XDataSeries>> & aSeriesSeq,const Reference<chart2::XDiagram> & xDiagram,sal_Bool bJapaneseCandleSticks,sal_Bool bExportContent)3206 void SchXMLExportHelper_Impl::exportCandleStickSeries(
3207     const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
3208     const Reference< chart2::XDiagram > & xDiagram,
3209     sal_Bool bJapaneseCandleSticks,
3210     sal_Bool bExportContent )
3211 {
3212 //  std::vector< XMLPropertyState > aPropertyStates;
3213 
3214     for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
3215     {
3216         Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx] );
3217         sal_Int32 nAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries )
3218             ? chart::ChartAxisAssign::PRIMARY_Y
3219             : chart::ChartAxisAssign::SECONDARY_Y;
3220 
3221         Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
3222         if( xSource.is())
3223         {
3224             // export series in correct order (as we don't store roles)
3225             // with japanese candlesticks: open, low, high, close
3226             // otherwise: low, high, close
3227             Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
3228                 xSource->getDataSequences());
3229 
3230             sal_Int32 nSeriesLength =
3231                 lcl_getSequenceLengthByRole( aSeqCnt, OUString::createFromAscii("values-last"));
3232 
3233             if( bExportContent )
3234             {
3235                 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
3236                 //@todo: export data points
3237 
3238                 // open
3239                 if( bJapaneseCandleSticks )
3240                 {
3241                     tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3242                         aSeqCnt, OUString::createFromAscii("values-first"),  xNewDoc, m_aDataSequencesToExport ));
3243                     if( aRanges.second.getLength())
3244                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3245                     if( aRanges.first.getLength())
3246                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3247                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3248                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3249                     else
3250                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3251                     SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3252                     // export empty data points
3253                     exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3254                 }
3255 
3256                 // low
3257                 {
3258                     tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3259                         aSeqCnt, OUString::createFromAscii("values-min"),  xNewDoc, m_aDataSequencesToExport ));
3260                     if( aRanges.second.getLength())
3261                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3262                     if( aRanges.first.getLength())
3263                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3264                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3265                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3266                     else
3267                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3268                     SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3269                     // export empty data points
3270                     exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3271                 }
3272 
3273                 // high
3274                 {
3275                     tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3276                         aSeqCnt, OUString::createFromAscii("values-max"),  xNewDoc, m_aDataSequencesToExport ));
3277                     if( aRanges.second.getLength())
3278                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3279                     if( aRanges.first.getLength())
3280                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3281                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3282                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3283                     else
3284                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3285                     SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3286                     // export empty data points
3287                     exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3288                 }
3289 
3290                 // close
3291                 {
3292                     tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3293                         aSeqCnt, OUString::createFromAscii("values-last"),  xNewDoc, m_aDataSequencesToExport ));
3294                     if( aRanges.second.getLength())
3295                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3296                     if( aRanges.first.getLength())
3297                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3298                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3299                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3300                     else
3301                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3302                     // write style name
3303 //                     AddAutoStyleAttribute( aPropertyStates );
3304                     // chart type
3305 //                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
3306 //                                            mrExport.GetNamespaceMap().GetQNameByKey(
3307 //                                                XML_NAMESPACE_CHART, GetXMLToken( XML_STOCK )));
3308                     SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3309                     // export empty data points
3310                     exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3311                 }
3312             }
3313             else    // autostyles
3314             {
3315                 // for close series
3316 //                 CollectAutoStyle( aPropertyStates );
3317             }
3318             // remove property states for autostyles
3319 //             aPropertyStates.clear();
3320         }
3321     }
3322 }
3323 
exportDataPoints(const uno::Reference<beans::XPropertySet> & xSeriesProperties,sal_Int32 nSeriesLength,const uno::Reference<chart2::XDiagram> & xDiagram,sal_Bool bExportContent)3324 void SchXMLExportHelper_Impl::exportDataPoints(
3325     const uno::Reference< beans::XPropertySet > & xSeriesProperties,
3326     sal_Int32 nSeriesLength,
3327     const uno::Reference< chart2::XDiagram > & xDiagram,
3328     sal_Bool bExportContent )
3329 {
3330     // data-points
3331     // -----------
3332     // write data-points only if they contain autostyles
3333     // objects with equal autostyles are grouped using the attribute
3334     // repeat="number"
3335 
3336     // Note: if only the nth data-point has autostyles there is an element
3337     // without style and repeat="n-1" attribute written in advance.
3338 
3339     // the sequence aDataPointSeq contains indices of data-points that
3340     // do have own attributes.  This increases the performance substantially.
3341 
3342     // more performant version for #93600#
3343     if( mxExpPropMapper.is())
3344     {
3345         uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
3346 
3347         std::vector< XMLPropertyState > aPropertyStates;
3348 
3349         const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" ));
3350         const OUString sPercentageNumFormat( OUString::createFromAscii( "PercentageNumberFormat" ));
3351 
3352         bool bVaryColorsByPoint = false;
3353         Sequence< sal_Int32 > aDataPointSeq;
3354         if( xSeriesProperties.is())
3355         {
3356             Any aAny = xSeriesProperties->getPropertyValue(
3357                 OUString( RTL_CONSTASCII_USTRINGPARAM( "AttributedDataPoints" )));
3358             aAny >>= aDataPointSeq;
3359             xSeriesProperties->getPropertyValue(
3360                 OUString( RTL_CONSTASCII_USTRINGPARAM( "VaryColorsByPoint" ))) >>= bVaryColorsByPoint;
3361         }
3362 
3363 
3364         sal_Int32 nSize = aDataPointSeq.getLength();
3365         DBG_ASSERT( nSize <= nSeriesLength, "Too many point attributes" );
3366 
3367         const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
3368         sal_Int32 nElement;
3369         sal_Int32 nRepeat;
3370         Reference< chart2::XColorScheme > xColorScheme;
3371         if( xDiagram.is())
3372             xColorScheme.set( xDiagram->getDefaultColorScheme());
3373 
3374         ::std::list< SchXMLDataPointStruct > aDataPointList;
3375 
3376         sal_Int32 nLastIndex = -1;
3377         sal_Int32 nCurrIndex = 0;
3378 
3379         // collect elements
3380         if( bVaryColorsByPoint && xColorScheme.is() )
3381         {
3382             ::std::set< sal_Int32 > aAttrPointSet;
3383             ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(),
3384                             ::std::inserter( aAttrPointSet, aAttrPointSet.begin()));
3385             const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end());
3386             for( nElement = 0; nElement < nSeriesLength; ++nElement )
3387             {
3388                 aPropertyStates.clear();
3389                 uno::Reference< beans::XPropertySet > xPropSet;
3390                 bool bExportNumFmt = false;
3391                 if( aAttrPointSet.find( nElement ) != aEndIt )
3392                 {
3393                     try
3394                     {
3395                         xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3396                                     xSeries, nElement, mrExport.GetModel() );
3397                         bExportNumFmt = true;
3398                     }
3399                     catch( uno::Exception & rEx )
3400                     {
3401                         (void)rEx; // avoid warning for pro build
3402                         DBG_ERROR1( "Exception caught during Export of data point: %s",
3403                                     OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
3404                     }
3405                 }
3406                 else
3407                 {
3408                     // property set only containing the color
3409                     xPropSet.set( new ::xmloff::chart::ColorPropertySet(
3410                                         xColorScheme->getColorByIndex( nElement )));
3411                 }
3412                 DBG_ASSERT( xPropSet.is(), "Pie Segments should have properties" );
3413                 if( xPropSet.is())
3414                 {
3415                     const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3416                     if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && bExportNumFmt )
3417                     {
3418                         lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
3419                         lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
3420                     }
3421 
3422                     aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3423                     if( !aPropertyStates.empty() )
3424                     {
3425                         if( bExportContent )
3426                         {
3427                             // write data-point with style
3428                             DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" );
3429 
3430                             SchXMLDataPointStruct aPoint;
3431                             aPoint.maStyleName = maAutoStyleNameQueue.front();
3432                             maAutoStyleNameQueue.pop();
3433                             aDataPointList.push_back( aPoint );
3434                         }
3435                         else
3436                         {
3437                             CollectAutoStyle( aPropertyStates );
3438                         }
3439                     }
3440                 }
3441             }
3442             DBG_ASSERT( !bExportContent || (static_cast<sal_Int32>(aDataPointList.size()) == nSeriesLength),
3443                         "not enough data points on content export" );
3444         }
3445         else
3446         {
3447             for( nElement = 0; nElement < nSize; ++nElement )
3448             {
3449                 aPropertyStates.clear();
3450                 nCurrIndex = pPoints[ nElement ];
3451                 //assuming sorted indices in pPoints
3452 
3453                 if( nCurrIndex<0 || nCurrIndex>=nSeriesLength )
3454                     break;
3455 
3456                 // write leading empty data points
3457                 if( nCurrIndex - nLastIndex > 1 )
3458                 {
3459                     SchXMLDataPointStruct aPoint;
3460                     aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
3461                     aDataPointList.push_back( aPoint );
3462                 }
3463 
3464                 uno::Reference< beans::XPropertySet > xPropSet;
3465                 // get property states
3466                 try
3467                 {
3468                     xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3469                                     xSeries, nCurrIndex, mrExport.GetModel() );
3470                 }
3471                 catch( uno::Exception & rEx )
3472                 {
3473                     (void)rEx; // avoid warning for pro build
3474                     DBG_ERROR1( "Exception caught during Export of data point: %s",
3475                                 OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
3476                 }
3477                 if( xPropSet.is())
3478                 {
3479                     const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3480                     if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
3481                     {
3482                         lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
3483                         lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
3484                     }
3485 
3486                     aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3487                     if( !aPropertyStates.empty() )
3488                     {
3489                         if( bExportContent )
3490                         {
3491                             // write data-point with style
3492                             DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" );
3493                             SchXMLDataPointStruct aPoint;
3494                             aPoint.maStyleName = maAutoStyleNameQueue.front();
3495                             maAutoStyleNameQueue.pop();
3496 
3497                             aDataPointList.push_back( aPoint );
3498                             nLastIndex = nCurrIndex;
3499                         }
3500                         else
3501                         {
3502                             CollectAutoStyle( aPropertyStates );
3503                         }
3504                         continue;
3505                     }
3506                 }
3507 
3508                 // if we get here the property states are empty
3509                 SchXMLDataPointStruct aPoint;
3510                 aDataPointList.push_back( aPoint );
3511 
3512                 nLastIndex = nCurrIndex;
3513             }
3514             // final empty elements
3515             nRepeat = nSeriesLength - nLastIndex - 1;
3516             if( nRepeat > 0 )
3517             {
3518                 SchXMLDataPointStruct aPoint;
3519                 aPoint.mnRepeat = nRepeat;
3520                 aDataPointList.push_back( aPoint );
3521             }
3522         }
3523 
3524         if( bExportContent )
3525         {
3526             // write elements (merge equal ones)
3527             ::std::list< SchXMLDataPointStruct >::iterator aIter = aDataPointList.begin();
3528             SchXMLDataPointStruct aPoint;
3529             SchXMLDataPointStruct aLastPoint;
3530 
3531             // initialize so that it doesn't matter if
3532             // the element is counted in the first iteration
3533             aLastPoint.mnRepeat = 0;
3534 
3535             for( ; aIter != aDataPointList.end(); ++aIter )
3536             {
3537                 aPoint = (*aIter);
3538 
3539                 if( aPoint.maStyleName == aLastPoint.maStyleName )
3540                     aPoint.mnRepeat += aLastPoint.mnRepeat;
3541                 else if( aLastPoint.mnRepeat > 0 )
3542                 {
3543                     // write last element
3544                     if( aLastPoint.maStyleName.getLength() )
3545                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3546 
3547                     if( aLastPoint.mnRepeat > 1 )
3548                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3549                                             OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) ));
3550 
3551                     SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True );
3552                 }
3553                 aLastPoint = aPoint;
3554             }
3555             // write last element if it hasn't been written in last iteration
3556             if( aPoint.maStyleName == aLastPoint.maStyleName )
3557             {
3558                 if( aLastPoint.maStyleName.getLength() )
3559                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3560 
3561                 if( aLastPoint.mnRepeat > 1 )
3562                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3563                                         OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) ));
3564 
3565                 SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True );
3566             }
3567         }
3568     }
3569 }
3570 
3571 
getCellAddress(sal_Int32 nCol,sal_Int32 nRow)3572 void SchXMLExportHelper_Impl::getCellAddress( sal_Int32 nCol, sal_Int32 nRow )
3573 {
3574     msStringBuffer.append( (sal_Unicode)'.' );
3575     if( nCol < 26 )
3576         msStringBuffer.append( (sal_Unicode)('A' + nCol) );
3577     else if( nCol < 702 )
3578     {
3579         msStringBuffer.append( (sal_Unicode)('A' + nCol / 26 - 1 ));
3580         msStringBuffer.append( (sal_Unicode)('A' + nCol % 26) );
3581     }
3582     else
3583     {
3584         msStringBuffer.append( (sal_Unicode)('A' + nCol / 702 - 1 ));
3585         msStringBuffer.append( (sal_Unicode)('A' + (nCol % 702) / 26 ));
3586         msStringBuffer.append( (sal_Unicode)('A' + nCol % 26) );
3587     }
3588 
3589     msStringBuffer.append( nRow + (sal_Int32)1 );
3590 }
3591 
addPosition(const awt::Point & rPosition)3592 void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition )
3593 {
3594     mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rPosition.X );
3595     msString = msStringBuffer.makeStringAndClear();
3596     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, msString );
3597 
3598     mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rPosition.Y );
3599     msString = msStringBuffer.makeStringAndClear();
3600     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, msString );
3601 }
3602 
addPosition(Reference<drawing::XShape> xShape)3603 void SchXMLExportHelper_Impl::addPosition( Reference< drawing::XShape > xShape )
3604 {
3605     if( xShape.is())
3606         addPosition( xShape->getPosition());
3607 }
3608 
addSize(const awt::Size & rSize,bool bIsOOoNamespace)3609 void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace)
3610 {
3611     mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rSize.Width );
3612     msString = msStringBuffer.makeStringAndClear();
3613     mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG , XML_WIDTH,  msString );
3614 
3615 
3616     mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rSize.Height);
3617     msString = msStringBuffer.makeStringAndClear();
3618     mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString );
3619 }
3620 
addSize(Reference<drawing::XShape> xShape,bool bIsOOoNamespace)3621 void SchXMLExportHelper_Impl::addSize( Reference< drawing::XShape > xShape, bool bIsOOoNamespace )
3622 {
3623     if( xShape.is())
3624         addSize( xShape->getSize(), bIsOOoNamespace );
3625 }
3626 
getPageSize(const Reference<chart2::XChartDocument> & xChartDoc) const3627 awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc ) const
3628 {
3629     awt::Size aSize( 8000, 7000 );
3630     uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
3631     DBG_ASSERT( xVisualObject.is(),"need XVisualObject for page size" );
3632     if( xVisualObject.is() )
3633         aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
3634 
3635     return aSize;
3636 }
3637 
CollectAutoStyle(const std::vector<XMLPropertyState> & aStates)3638 void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates )
3639 {
3640     if( !aStates.empty() )
3641         maAutoStyleNameQueue.push( GetAutoStylePoolP().Add( XML_STYLE_FAMILY_SCH_CHART_ID, aStates ));
3642 }
3643 
AddAutoStyleAttribute(const std::vector<XMLPropertyState> & aStates)3644 void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates )
3645 {
3646     if( !aStates.empty() )
3647     {
3648         DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" );
3649 
3650         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME,  maAutoStyleNameQueue.front() );
3651         maAutoStyleNameQueue.pop();
3652     }
3653 }
3654 
exportText(const OUString & rText,bool bConvertTabsLFs)3655 void SchXMLExportHelper_Impl::exportText( const OUString& rText, bool bConvertTabsLFs )
3656 {
3657     SchXMLTools::exportText( mrExport, rText, bConvertTabsLFs );
3658 }
3659 
3660 // ========================================
3661 // class SchXMLExport
3662 // ========================================
3663 
3664 // #110680#
SchXMLExport(const Reference<lang::XMultiServiceFactory> & xServiceFactory,sal_uInt16 nExportFlags)3665 SchXMLExport::SchXMLExport(
3666     const Reference< lang::XMultiServiceFactory >& xServiceFactory,
3667     sal_uInt16 nExportFlags )
3668 :   SvXMLExport( xServiceFactory, MAP_CM, ::xmloff::token::XML_CHART, nExportFlags ),
3669     maAutoStylePool( *this ),
3670     maExportHelper( *this, maAutoStylePool )
3671 {
3672     if( SvtSaveOptions::IsODFExtended( getDefaultVersion() ) )
3673         _GetNamespaceMap().Add( GetXMLToken(XML_NP_CHART_EXT), GetXMLToken(XML_N_CHART_EXT), XML_NAMESPACE_CHART_EXT);
3674 }
3675 
3676 
~SchXMLExport()3677 SchXMLExport::~SchXMLExport()
3678 {
3679     // stop progress view
3680     if( mxStatusIndicator.is())
3681     {
3682         mxStatusIndicator->end();
3683         mxStatusIndicator->reset();
3684     }
3685 }
3686 
exportDoc(enum::xmloff::token::XMLTokenEnum eClass)3687 sal_uInt32 SchXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )
3688 {
3689     Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3690     maExportHelper.m_pImpl->InitRangeSegmentationProperties( xChartDoc );
3691     return SvXMLExport::exportDoc( eClass );
3692 }
3693 
_ExportStyles(sal_Bool bUsed)3694 void SchXMLExport::_ExportStyles( sal_Bool bUsed )
3695 {
3696     SvXMLExport::_ExportStyles( bUsed );
3697 }
3698 
_ExportMasterStyles()3699 void SchXMLExport::_ExportMasterStyles()
3700 {
3701     // not available in chart
3702     DBG_WARNING( "Master Style Export requested. Not available for Chart" );
3703 }
3704 
_ExportAutoStyles()3705 void SchXMLExport::_ExportAutoStyles()
3706 {
3707     // there are no styles that require their own autostyles
3708     if( getExportFlags() & EXPORT_CONTENT )
3709     {
3710         Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3711         if( xChartDoc.is())
3712         {
3713             maExportHelper.m_pImpl->collectAutoStyles( xChartDoc );
3714             maExportHelper.m_pImpl->exportAutoStyles();
3715         }
3716         else
3717         {
3718             DBG_ERROR( "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3719         }
3720     }
3721 }
3722 
_ExportContent()3723 void SchXMLExport::_ExportContent()
3724 {
3725     Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3726     if( xChartDoc.is())
3727     {
3728         // determine if data comes from the outside
3729         sal_Bool bIncludeTable = sal_True;
3730 
3731         Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
3732         if( xNewDoc.is())
3733         {
3734             // check if we have own data.  If so we must not export the complete
3735             // range string, as this is our only indicator for having own or
3736             // external data. @todo: fix this in the file format!
3737             Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
3738             if( ! (xDPServiceInfo.is() &&
3739                    xDPServiceInfo->getImplementationName().equalsAsciiL(
3740                        RTL_CONSTASCII_STRINGPARAM( "com.sun.star.comp.chart.InternalDataProvider" ))))
3741             {
3742                 bIncludeTable = sal_False;
3743             }
3744         }
3745         else
3746         {
3747             Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
3748             if( xServ.is())
3749             {
3750                 if( xServ->supportsService(
3751                         OUString::createFromAscii( "com.sun.star.chart.ChartTableAddressSupplier" )))
3752                 {
3753                     Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
3754                     if( xProp.is())
3755                     {
3756                         Any aAny;
3757                         try
3758                         {
3759                             OUString sChartAddress;
3760                             aAny = xProp->getPropertyValue(
3761                                 OUString::createFromAscii( "ChartRangeAddress" ));
3762                             aAny >>= sChartAddress;
3763                             maExportHelper.m_pImpl->SetChartRangeAddress( sChartAddress );
3764 
3765                             OUString sTableNumberList;
3766                             aAny = xProp->getPropertyValue(
3767                                 OUString::createFromAscii( "TableNumberList" ));
3768                             aAny >>= sTableNumberList;
3769                             maExportHelper.m_pImpl->SetTableNumberList( sTableNumberList );
3770 
3771                             // do not include own table if there are external addresses
3772                             bIncludeTable = (sChartAddress.getLength() == 0);
3773                         }
3774                         catch( beans::UnknownPropertyException & )
3775                         {
3776                             DBG_ERROR( "Property ChartRangeAddress not supported by ChartDocument" );
3777                         }
3778                     }
3779                 }
3780             }
3781         }
3782         maExportHelper.m_pImpl->exportChart( xChartDoc, bIncludeTable );
3783     }
3784     else
3785     {
3786         DBG_ERROR( "Couldn't export chart due to wrong XModel" );
3787     }
3788 }
3789 
SetProgress(sal_Int32 nPercentage)3790 void SchXMLExport::SetProgress( sal_Int32 nPercentage )
3791 {
3792     // set progress view
3793     if( mxStatusIndicator.is())
3794         mxStatusIndicator->setValue( nPercentage );
3795 }
3796 
GetPropertySetMapper() const3797 UniReference< XMLPropertySetMapper > SchXMLExport::GetPropertySetMapper() const
3798 {
3799     return maExportHelper.m_pImpl->GetPropertySetMapper();
3800 }
3801 
InitRangeSegmentationProperties(const Reference<chart2::XChartDocument> & xChartDoc)3802 void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
3803 {
3804     if( xChartDoc.is())
3805         try
3806         {
3807             Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
3808             OSL_ENSURE( xDataProvider.is(), "No DataProvider" );
3809             if( xDataProvider.is())
3810             {
3811                 Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
3812                 Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
3813                 ::rtl::OUString sCellRange, sBrokenRange;
3814                 bool bBrokenRangeAvailable = false;
3815                 for( sal_Int32 i=0; i<aArgs.getLength(); ++i )
3816                 {
3817                     if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
3818                         aArgs[i].Value >>= sCellRange;
3819                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("BrokenCellRangeForExport")))
3820                     {
3821                         if( aArgs[i].Value >>= sBrokenRange )
3822                             bBrokenRangeAvailable = true;
3823                     }
3824                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DataRowSource")))
3825                     {
3826                         chart::ChartDataRowSource eRowSource;
3827                         aArgs[i].Value >>= eRowSource;
3828                         mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS );
3829                     }
3830                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("FirstCellAsLabel")))
3831                         aArgs[i].Value >>= mbHasSeriesLabels;
3832                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
3833                         aArgs[i].Value >>= maSequenceMapping;
3834                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("TableNumberList")))
3835                         aArgs[i].Value >>= msTableNumberList;
3836                 }
3837 
3838                 // #i79009# For Writer we have to export a broken version of the
3839                 // range, where every row number is noe too large, so that older
3840                 // version can correctly read those files.
3841                 msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
3842                 if( msChartAddress.getLength() > 0 )
3843                 {
3844                     // convert format to XML-conform one
3845                     Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
3846                     if( xConversion.is())
3847                         msChartAddress = xConversion->convertRangeToXML( msChartAddress );
3848                 }
3849             }
3850         }
3851         catch( uno::Exception & ex )
3852         {
3853             (void)ex; // avoid warning for pro build
3854             OSL_ENSURE( false, OUStringToOString(
3855                             OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) +
3856                             OUString::createFromAscii( typeid( ex ).name()) +
3857                             OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) +
3858                             ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
3859         }
3860 }
3861 
3862 // export components ========================================
3863 
3864 // first version: everything goes in one storage
3865 
SchXMLExport_getSupportedServiceNames()3866 Sequence< OUString > SAL_CALL SchXMLExport_getSupportedServiceNames() throw()
3867 {
3868     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLExporter" ) );
3869     const Sequence< OUString > aSeq( &aServiceName, 1 );
3870     return aSeq;
3871 }
3872 
SchXMLExport_getImplementationName()3873 OUString SAL_CALL SchXMLExport_getImplementationName() throw()
3874 {
3875     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Compact" ) );
3876 }
3877 
SchXMLExport_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3878 Reference< uno::XInterface > SAL_CALL SchXMLExport_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3879 {
3880     // #110680#
3881     // #103997# removed some flags from EXPORT_ALL
3882     // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS ));
3883     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS ));
3884 }
3885 
3886 // Oasis format
SchXMLExport_Oasis_getSupportedServiceNames()3887 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_getSupportedServiceNames() throw()
3888 {
3889     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisExporter" ) );
3890     const Sequence< OUString > aSeq( &aServiceName, 1 );
3891     return aSeq;
3892 }
3893 
SchXMLExport_Oasis_getImplementationName()3894 OUString SAL_CALL SchXMLExport_Oasis_getImplementationName() throw()
3895 {
3896     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Compact" ) );
3897 }
3898 
SchXMLExport_Oasis_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3899 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3900 {
3901     // #103997# removed some flags from EXPORT_ALL
3902     return (cppu::OWeakObject*)new SchXMLExport( rSMgr,
3903         (EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS )) | EXPORT_OASIS );
3904 }
3905 
3906 // ============================================================
3907 
3908 // multiple storage version: one for content / styles / meta
3909 
SchXMLExport_Styles_getSupportedServiceNames()3910 Sequence< OUString > SAL_CALL SchXMLExport_Styles_getSupportedServiceNames() throw()
3911 {
3912     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLStylesExporter" ));
3913     const Sequence< OUString > aSeq( &aServiceName, 1 );
3914     return aSeq;
3915 }
3916 
SchXMLExport_Styles_getImplementationName()3917 OUString SAL_CALL SchXMLExport_Styles_getImplementationName() throw()
3918 {
3919     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Styles" ));
3920 }
3921 
SchXMLExport_Styles_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3922 Reference< uno::XInterface > SAL_CALL SchXMLExport_Styles_createInstance(const Reference< lang::XMultiServiceFactory >& rSMgr)
3923 {
3924     // #110680#
3925     // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_STYLES );
3926     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_STYLES );
3927 }
3928 
3929 // Oasis format
SchXMLExport_Oasis_Styles_getSupportedServiceNames()3930 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Styles_getSupportedServiceNames() throw()
3931 {
3932     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisStylesExporter" ));
3933     const Sequence< OUString > aSeq( &aServiceName, 1 );
3934     return aSeq;
3935 }
3936 
SchXMLExport_Oasis_Styles_getImplementationName()3937 OUString SAL_CALL SchXMLExport_Oasis_Styles_getImplementationName() throw()
3938 {
3939     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Styles" ));
3940 }
3941 
SchXMLExport_Oasis_Styles_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3942 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Styles_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3943 {
3944     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_STYLES | EXPORT_OASIS );
3945 }
3946 
3947 // ------------------------------------------------------------
3948 
SchXMLExport_Content_getSupportedServiceNames()3949 Sequence< OUString > SAL_CALL SchXMLExport_Content_getSupportedServiceNames() throw()
3950 {
3951     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLContentExporter" ));
3952     const Sequence< OUString > aSeq( &aServiceName, 1 );
3953     return aSeq;
3954 }
3955 
SchXMLExport_Content_getImplementationName()3956 OUString SAL_CALL SchXMLExport_Content_getImplementationName() throw()
3957 {
3958     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Content" ));
3959 }
3960 
SchXMLExport_Content_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3961 Reference< uno::XInterface > SAL_CALL SchXMLExport_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3962 {
3963     // #110680#
3964     // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS );
3965     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS );
3966 }
3967 
3968 // Oasis format
SchXMLExport_Oasis_Content_getSupportedServiceNames()3969 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Content_getSupportedServiceNames() throw()
3970 {
3971     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisContentExporter" ));
3972     const Sequence< OUString > aSeq( &aServiceName, 1 );
3973     return aSeq;
3974 }
3975 
SchXMLExport_Oasis_Content_getImplementationName()3976 OUString SAL_CALL SchXMLExport_Oasis_Content_getImplementationName() throw()
3977 {
3978     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Content" ));
3979 }
3980 
SchXMLExport_Oasis_Content_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3981 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3982 {
3983     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS );
3984 }
3985 
3986 // ------------------------------------------------------------
3987 
3988 // Sequence< OUString > SAL_CALL SchXMLExport_Meta_getSupportedServiceNames() throw()
3989 // {
3990 //  const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLMetaExporter" ));
3991 //  const Sequence< OUString > aSeq( &aServiceName, 1 );
3992 //  return aSeq;
3993 // }
3994 
3995 // OUString SAL_CALL SchXMLExport_Meta_getImplementationName() throw()
3996 // {
3997 //  return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Meta" ));
3998 // }
3999 
4000 // Reference< uno::XInterface > SAL_CALL SchXMLExport_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
4001 // {
4002 //  return (cppu::OWeakObject*)new SchXMLExport( EXPORT_META );
4003 // }
4004 
4005 // Oasis format
SchXMLExport_Oasis_Meta_getSupportedServiceNames()4006 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Meta_getSupportedServiceNames() throw()
4007 {
4008     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisMetaExporter" ));
4009     const Sequence< OUString > aSeq( &aServiceName, 1 );
4010     return aSeq;
4011 }
4012 
SchXMLExport_Oasis_Meta_getImplementationName()4013 OUString SAL_CALL SchXMLExport_Oasis_Meta_getImplementationName() throw()
4014 {
4015     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Meta" ));
4016 }
4017 
SchXMLExport_Oasis_Meta_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)4018 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
4019 {
4020     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_META | EXPORT_OASIS  );
4021 }
4022 
4023 
4024 // XServiceInfo
getImplementationName()4025 OUString SAL_CALL SchXMLExport::getImplementationName()
4026 {
4027     switch( getExportFlags())
4028     {
4029         case EXPORT_ALL:
4030             return SchXMLExport_getImplementationName();
4031         case EXPORT_STYLES:
4032             return SchXMLExport_Styles_getImplementationName();
4033         case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS ):
4034             return SchXMLExport_Content_getImplementationName();
4035 //         case EXPORT_META:
4036 //             return SchXMLExport_Meta_getImplementationName();
4037 
4038         // Oasis format
4039         case ( EXPORT_ALL | EXPORT_OASIS ):
4040             return SchXMLExport_Oasis_getImplementationName();
4041         case ( EXPORT_STYLES | EXPORT_OASIS ):
4042             return SchXMLExport_Oasis_Styles_getImplementationName();
4043         case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS  ):
4044             return SchXMLExport_Oasis_Content_getImplementationName();
4045         case ( EXPORT_META | EXPORT_OASIS ):
4046             return SchXMLExport_Oasis_Meta_getImplementationName();
4047 
4048         case EXPORT_SETTINGS:
4049         // there is no settings component in chart
4050         default:
4051             return OUString::createFromAscii( "SchXMLExport" );
4052     }
4053 }
4054