xref: /trunk/main/xmloff/source/chart/SchXMLExport.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 && nCurrentODFVersion == SvtSaveOptions::ODFVER_LATEST )//do not export legend-expansion to ODF 1.0 and export size only if extensions are enabled //#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, true );
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             }
1598             catch( uno::Exception & rEx )
1599             {
1600                 (void)rEx; // avoid warning for pro build
1601                 OSL_TRACE(
1602                     OUStringToOString(
1603                         OUString( RTL_CONSTASCII_USTRINGPARAM(
1604                             "AdditionalShapes not found: " )) +
1605                         rEx.Message,
1606                         RTL_TEXTENCODING_ASCII_US ).getStr());
1607             }
1608 
1609             if( mxAdditionalShapes.is())
1610             {
1611                 // seek shapes has to be called for the whole page because in
1612                 // the shape export the vector of shapes is accessed via the
1613                 // ZOrder which might be (actually is) larger than the number of
1614                 // shapes in mxAdditionalShapes
1615                 Reference< drawing::XDrawPageSupplier > xSupplier( rChartDoc, uno::UNO_QUERY );
1616                 DBG_ASSERT( xSupplier.is(), "Cannot retrieve draw page to initialize shape export" );
1617                 if( xSupplier.is() )
1618                 {
1619                     Reference< drawing::XShapes > xDrawPage( xSupplier->getDrawPage(), uno::UNO_QUERY );
1620                     DBG_ASSERT( xDrawPage.is(), "Invalid draw page for initializing shape export" );
1621                     if( xDrawPage.is())
1622                         mrExport.GetShapeExport()->seekShapes( xDrawPage );
1623                 }
1624 
1625                 // can't call collectShapesAutoStyles with all shapes because
1626                 // the initialisation happened with the complete draw page and
1627                 // not the XShapes object used here. Thus the shapes have to be
1628                 // exported one by one
1629                 UniReference< XMLShapeExport > rShapeExport = mrExport.GetShapeExport();
1630                 Reference< drawing::XShape > xShape;
1631                 const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1632                 for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1633                 {
1634                     mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1635                     DBG_ASSERT( xShape.is(), "Shape without an XShape?" );
1636                     if( ! xShape.is())
1637                         continue;
1638 
1639                     rShapeExport->collectShapeAutoStyles( xShape );
1640                 }
1641                 // this would be the easier way if it worked:
1642                 // mrExport.GetShapeExport()->collectShapesAutoStyles( mxAdditionalShapes );
1643             }
1644         }
1645     }
1646 
1647     // table element
1648     // (is included as subelement of chart)
1649     // ------------------------------------
1650     if( bExportContent )
1651     {
1652         // #85929# always export table, otherwise clipboard may loose data
1653         exportTable();
1654     }
1655 
1656     // close <chart:chart> element
1657     if( pElChart )
1658         delete pElChart;
1659 }
1660 
lcl_exportComplexLabel(const Sequence<uno::Any> & rComplexLabel,SvXMLExport & rExport)1661 void lcl_exportComplexLabel( const Sequence< uno::Any >& rComplexLabel, SvXMLExport& rExport )
1662 {
1663     sal_Int32 nLength = rComplexLabel.getLength();
1664     if( nLength<=1 )
1665         return;
1666     SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, sal_True, sal_True );
1667     for(sal_Int32 nN=0; nN<nLength; nN++)
1668     {
1669         SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, sal_True, sal_True );
1670         OUString aString;
1671         if( !(rComplexLabel[nN]>>=aString) )
1672         {
1673             //todo?
1674         }
1675         SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ );
1676     }
1677 }
1678 
exportTable()1679 void SchXMLExportHelper_Impl::exportTable()
1680 {
1681     // table element
1682     // -------------
1683     mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, msTableName );
1684 
1685     try
1686     {
1687         bool bProtected = false;
1688         Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW );
1689         if ( ( xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableDataTableDialog" ) ) ) >>= bProtected ) &&
1690              bProtected )
1691         {
1692             mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE );
1693         }
1694     }
1695     catch ( uno::Exception& )
1696     {
1697     }
1698 
1699     SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, sal_True, sal_True );
1700 
1701     bool bHasOwnData = false;
1702     Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
1703     Reference< chart2::data::XRangeXMLConversion > xRangeConversion;
1704     if( xNewDoc.is())
1705     {
1706         bHasOwnData = xNewDoc->hasInternalDataProvider();
1707         xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1708     }
1709 
1710     Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess;
1711     {
1712         Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY );
1713         if( xChartDoc.is() )
1714             xAnyDescriptionAccess = Reference< chart2::XAnyDescriptionAccess >( xChartDoc->getData(), uno::UNO_QUERY );
1715     }
1716 
1717     if( bHasOwnData )
1718         lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport );
1719     lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport
1720                                 , xAnyDescriptionAccess, maCategoriesRange
1721                                 , mbRowSourceColumns, xRangeConversion ));
1722 
1723     tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin());
1724     const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end());
1725 
1726     tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin());
1727     const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end());
1728 
1729     // declare columns
1730     {
1731         SvXMLElementExport aHeaderColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, sal_True, sal_True );
1732         SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1733     }
1734     {
1735         SvXMLElementExport aColumns( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, sal_True, sal_True );
1736 
1737         sal_Int32 nNextIndex = 0;
1738         for( size_t nN=0; nN< aData.aHiddenColumns.size(); nN++ )
1739         {
1740             //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste )
1741             sal_Int32 nHiddenIndex = aData.aHiddenColumns[nN];
1742             if( nHiddenIndex > nNextIndex )
1743             {
1744                 sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex );
1745                 if(nRepeat>1)
1746                     mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1747                                    OUString::valueOf( nRepeat ));
1748                 SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1749             }
1750             mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_VISIBILITY, GetXMLToken( XML_COLLAPSE ) );
1751             SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1752             nNextIndex = nHiddenIndex+1;
1753         }
1754 
1755         sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1;
1756         if( nEndIndex >= nNextIndex )
1757         {
1758             sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 );
1759             if(nRepeat>1)
1760                 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1761                                OUString::valueOf( nRepeat ));
1762             SvXMLElementExport aColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True );
1763         }
1764     }
1765 
1766     // export rows with content
1767     //export header row
1768     {
1769         SvXMLElementExport aHeaderRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, sal_True, sal_True );
1770         SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True );
1771 
1772         //first one empty cell for the row descriptions
1773         {
1774             SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1775             SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_True );
1776         }
1777 
1778         //export column descriptions
1779         tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin());
1780         const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end());
1781         const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions;
1782         sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength();
1783         sal_Int32 nC = 0;
1784         for( tStringVector::const_iterator aIt( aData.aColumnDescriptions.begin())
1785              ; (aIt != aData.aColumnDescriptions.end())
1786              ; aIt++, nC++ )
1787         {
1788             bool bExportString = true;
1789             if( nC < nComplexCount )
1790             {
1791                 const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC];
1792                 if( rComplexLabel.getLength()>0 )
1793                 {
1794                     double fValue=0.0;
1795                     if( rComplexLabel[0] >>=fValue )
1796                     {
1797                         bExportString = false;
1798 
1799                         SvXMLUnitConverter::convertDouble( msStringBuffer, fValue );
1800                         msString = msStringBuffer.makeStringAndClear();
1801                         mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1802                         mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1803                     }
1804                 }
1805             }
1806             if( bExportString )
1807             {
1808                 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1809             }
1810 
1811             SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1812             exportText( *aIt );
1813             if( nC < nComplexCount )
1814                 lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport );
1815             if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd )
1816             {
1817                 // remind the original range to allow a correct re-association when copying via clipboard
1818                 if ((*aColumnDescriptions_RangeIter).getLength())
1819                     SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter );
1820                 ++aColumnDescriptions_RangeIter;
1821             }
1822         }
1823         OSL_ASSERT( bHasOwnData || aColumnDescriptions_RangeIter == aColumnDescriptions_RangeEnd );
1824     } // closing row and header-rows elements
1825 
1826     // export value rows
1827     {
1828         SvXMLElementExport aRows( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROWS, sal_True, sal_True );
1829         tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin());
1830         const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions;
1831         sal_Int32 nComplexCount = rComplexRowDescriptions.getLength();
1832         sal_Int32 nC = 0;
1833 
1834         for( t2DNumberContainer::const_iterator aRowIt( aData.aDataInRows.begin())
1835             ; aRowIt != aData.aDataInRows.end()
1836             ; ++aRowIt, ++nC )
1837         {
1838             SvXMLElementExport aRow( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True );
1839 
1840             //export row descriptions
1841             {
1842                 bool bExportString = true;
1843                 if( nC < nComplexCount )
1844                 {
1845                     const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC];
1846                     if( rComplexLabel.getLength()>0 )
1847                     {
1848                         double fValue=0.0;
1849                         if( rComplexLabel[0] >>=fValue )
1850                         {
1851                             bExportString = false;
1852 
1853                             SvXMLUnitConverter::convertDouble( msStringBuffer, fValue );
1854                             msString = msStringBuffer.makeStringAndClear();
1855                             mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1856                             mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1857                         }
1858                     }
1859                 }
1860                 if( bExportString )
1861                 {
1862                     mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING );
1863                 }
1864 
1865                 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1866                 if( aRowDescriptionsIter != aData.aRowDescriptions.end())
1867                 {
1868                     exportText( *aRowDescriptionsIter );
1869                     if( nC < nComplexCount )
1870                         lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport );
1871                     if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd )
1872                     {
1873                         // remind the original range to allow a correct re-association when copying via clipboard
1874                         SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter );
1875                         ++aRowDescriptions_RangeIter;
1876                     }
1877                     ++aRowDescriptionsIter;
1878                 }
1879             }
1880 
1881             //export row values
1882             for( t2DNumberContainer::value_type::const_iterator aColIt( aRowIt->begin());
1883                  aColIt != aRowIt->end(); ++aColIt )
1884             {
1885                 SvXMLUnitConverter::convertDouble( msStringBuffer, *aColIt );
1886                 msString = msStringBuffer.makeStringAndClear();
1887                 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT );
1888                 mrExport.AddAttribute( XML_NAMESPACE_OFFICE, XML_VALUE, msString );
1889                 SvXMLElementExport aCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True );
1890                 exportText( msString, false ); // do not convert tabs and lfs
1891                 if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) &&
1892                     ( mbRowSourceColumns || (aColIt == aRowIt->begin()) ) )
1893                 {
1894                     // remind the original range to allow a correct re-association when copying via clipboard
1895                     if ((*aDataRangeIter).getLength())
1896                         SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter );
1897                     ++aDataRangeIter;
1898                 }
1899             }
1900         }
1901     }
1902 
1903     // if range iterator was used it should have reached its end
1904     OSL_ASSERT( bHasOwnData || (aDataRangeIter == aDataRangeEndIter) );
1905     OSL_ASSERT( bHasOwnData || (aRowDescriptions_RangeIter == aRowDescriptions_RangeEnd) );
1906 }
1907 
1908 namespace
1909 {
1910 
lcl_getCooSys(const Reference<chart2::XDiagram> & xNewDiagram)1911 Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram )
1912 {
1913     Reference< chart2::XCoordinateSystem > xCooSys;
1914     Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY );
1915     if(xCooSysCnt.is())
1916     {
1917         Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1918         if(aCooSysSeq.getLength()>0)
1919             xCooSys = aCooSysSeq[0];
1920     }
1921     return xCooSys;
1922 }
1923 
lcl_getAxis(const Reference<chart2::XCoordinateSystem> & xCooSys,enum XMLTokenEnum eDimension,bool bPrimary=true)1924 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys,
1925         enum XMLTokenEnum eDimension, bool bPrimary=true )
1926 {
1927     Reference< chart2::XAxis > xNewAxis;
1928     try
1929     {
1930         if( xCooSys.is() )
1931         {
1932             sal_Int32 nDimensionIndex=0;
1933             switch( eDimension )
1934             {
1935             case XML_X:
1936                 nDimensionIndex=0;
1937                 break;
1938             case XML_Y:
1939                 nDimensionIndex=1;
1940                 break;
1941             case XML_Z:
1942                 nDimensionIndex=2;
1943                 break;
1944             default:
1945                 break;
1946             }
1947 
1948             xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 );
1949         }
1950     }
1951     catch( const uno::Exception & )
1952     {
1953     }
1954     return xNewAxis;
1955 }
1956 
1957 }
1958 
exportPlotArea(Reference<chart::XDiagram> xDiagram,Reference<chart2::XDiagram> xNewDiagram,const awt::Size & rPageSize,sal_Bool bExportContent,sal_Bool bIncludeTable)1959 void SchXMLExportHelper_Impl::exportPlotArea(
1960     Reference< chart::XDiagram > xDiagram,
1961     Reference< chart2::XDiagram > xNewDiagram,
1962     const awt::Size & rPageSize,
1963     sal_Bool bExportContent,
1964     sal_Bool bIncludeTable )
1965 {
1966     DBG_ASSERT( xDiagram.is(), "Invalid XDiagram as parameter" );
1967     if( ! xDiagram.is())
1968         return;
1969 
1970     // variables for autostyles
1971     Reference< beans::XPropertySet > xPropSet;
1972     std::vector< XMLPropertyState > aPropertyStates;
1973 
1974     sal_Bool bIs3DChart = sal_False;
1975     drawing::HomogenMatrix aTransMatrix;
1976 
1977     msStringBuffer.setLength( 0 );
1978 
1979     // plot-area element
1980     // -----------------
1981 
1982     SvXMLElementExport* pElPlotArea = 0;
1983     // get property states for autostyles
1984     xPropSet = Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY );
1985     if( xPropSet.is())
1986     {
1987         if( mxExpPropMapper.is())
1988             aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1989     }
1990     if( bExportContent )
1991     {
1992         UniReference< XMLShapeExport > rShapeExport;
1993 
1994         // write style name
1995         AddAutoStyleAttribute( aPropertyStates );
1996 
1997         if( msChartAddress.getLength() )
1998         {
1999             if( !bIncludeTable )
2000                 mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, msChartAddress );
2001 
2002             Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY );
2003             if( xDoc.is() )
2004             {
2005                 Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY );
2006                 if( xDocProp.is())
2007                 {
2008                     Any aAny;
2009                     sal_Bool bFirstCol = false, bFirstRow = false;
2010 
2011                     try
2012                     {
2013                         aAny = xDocProp->getPropertyValue(
2014                             OUString( RTL_CONSTASCII_USTRINGPARAM( "DataSourceLabelsInFirstColumn" )));
2015                         aAny >>= bFirstCol;
2016                         aAny = xDocProp->getPropertyValue(
2017                             OUString( RTL_CONSTASCII_USTRINGPARAM( "DataSourceLabelsInFirstRow" )));
2018                         aAny >>= bFirstRow;
2019 
2020                         if( bFirstCol || bFirstRow )
2021                         {
2022                             mrExport.AddAttribute( XML_NAMESPACE_CHART,
2023                                                    ::xmloff::token::GetXMLToken( ::xmloff::token::XML_DATA_SOURCE_HAS_LABELS ),
2024                                                    ( bFirstCol
2025                                                      ? ( bFirstRow
2026                                                          ?  ::xmloff::token::GetXMLToken( ::xmloff::token::XML_BOTH )
2027                                                          :  ::xmloff::token::GetXMLToken( ::xmloff::token::XML_COLUMN ))
2028                                                      : ::xmloff::token::GetXMLToken( ::xmloff::token::XML_ROW )));
2029                         }
2030                     }
2031                     catch( beans::UnknownPropertyException & )
2032                     {
2033                         DBG_ERRORFILE( "Properties missing" );
2034                     }
2035                 }
2036             }
2037         }
2038 
2039         // #i72973#, #144135# only export table-number-list in OOo format (also for binary)
2040         Reference< beans::XPropertySet > xExportInfo( mrExport.getExportInfo());
2041         if( msTableNumberList.getLength() &&
2042             xExportInfo.is())
2043         {
2044             try
2045             {
2046                 OUString sExportTableNumListPropName( RTL_CONSTASCII_USTRINGPARAM("ExportTableNumberList"));
2047                 Reference< beans::XPropertySetInfo > xInfo( xExportInfo->getPropertySetInfo());
2048                 bool bExportTableNumberList = false;
2049                 if( xInfo.is() && xInfo->hasPropertyByName( sExportTableNumListPropName ) &&
2050                     (xExportInfo->getPropertyValue( sExportTableNumListPropName ) >>= bExportTableNumberList) &&
2051                     bExportTableNumberList )
2052                 {
2053                     // this attribute is for charts embedded in calc documents only.
2054                     // With this you are able to store a file again in 5.0 binary format
2055                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_TABLE_NUMBER_LIST, msTableNumberList );
2056                 }
2057             }
2058             catch( uno::Exception & rEx )
2059             {
2060 #ifdef DBG_UTIL
2061                 String aStr( rEx.Message );
2062                 ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
2063                 DBG_ERROR1( "chart:TableNumberList property caught: %s", aBStr.GetBuffer());
2064 #else
2065                 (void)rEx; // avoid warning
2066 #endif
2067             }
2068         }
2069 
2070         // attributes
2071         Reference< drawing::XShape > xShape ( xDiagram, uno::UNO_QUERY );
2072         if( xShape.is())
2073         {
2074             addPosition( xShape );
2075             addSize( xShape );
2076         }
2077 
2078         if( xPropSet.is())
2079         {
2080             Any aAny;
2081 
2082             // 3d attributes
2083             try
2084             {
2085                 aAny = xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Dim3D" )));
2086                 aAny >>= bIs3DChart;
2087 
2088                 if( bIs3DChart )
2089                 {
2090                     rShapeExport = mrExport.GetShapeExport();
2091                     if( rShapeExport.is())
2092                         rShapeExport->export3DSceneAttributes( xPropSet );
2093                 }
2094             }
2095             catch( uno::Exception & rEx )
2096             {
2097 #ifdef DBG_UTIL
2098                 String aStr( rEx.Message );
2099                 ByteString aBStr( aStr, RTL_TEXTENCODING_ASCII_US );
2100                 DBG_ERROR1( "chart:exportPlotAreaException caught: %s", aBStr.GetBuffer());
2101 #else
2102                 (void)rEx; // avoid warning
2103 #endif
2104             }
2105         }
2106 
2107         // plot-area element
2108         pElPlotArea = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, sal_True, sal_True );
2109 
2110         //inner position rectangle element
2111         exportCoordinateRegion( xDiagram );
2112 
2113         // light sources (inside plot area element)
2114         if( bIs3DChart &&
2115             rShapeExport.is())
2116             rShapeExport->export3DLamps( xPropSet );
2117     }
2118     else    // autostyles
2119     {
2120         CollectAutoStyle( aPropertyStates );
2121     }
2122     // remove property states for autostyles
2123     aPropertyStates.clear();
2124 
2125     // axis elements
2126     // -------------
2127     exportAxes( xDiagram, xNewDiagram, bExportContent );
2128 
2129     // series elements
2130     // ---------------
2131     Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false );
2132     exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() );
2133 
2134     // stock-chart elements
2135     OUString sChartType ( xDiagram->getDiagramType());
2136     if( 0 == sChartType.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.chart.StockDiagram" )))
2137     {
2138         Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY );
2139         if( xStockPropProvider.is())
2140         {
2141             // stock-gain-marker
2142             Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar();
2143             if( xStockPropSet.is())
2144             {
2145                 aPropertyStates.clear();
2146                 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2147 
2148                 if( !aPropertyStates.empty() )
2149                 {
2150                     if( bExportContent )
2151                     {
2152                         AddAutoStyleAttribute( aPropertyStates );
2153 
2154                         SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_GAIN_MARKER, sal_True, sal_True );
2155                     }
2156                     else
2157                     {
2158                         CollectAutoStyle( aPropertyStates );
2159                     }
2160                 }
2161             }
2162 
2163             // stock-loss-marker
2164             xStockPropSet = xStockPropProvider->getDownBar();
2165             if( xStockPropSet.is())
2166             {
2167                 aPropertyStates.clear();
2168                 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2169 
2170                 if( !aPropertyStates.empty() )
2171                 {
2172                     if( bExportContent )
2173                     {
2174                         AddAutoStyleAttribute( aPropertyStates );
2175 
2176                         SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_LOSS_MARKER, sal_True, sal_True );
2177                     }
2178                     else
2179                     {
2180                         CollectAutoStyle( aPropertyStates );
2181                     }
2182                 }
2183             }
2184 
2185             // stock-range-line
2186             xStockPropSet = xStockPropProvider->getMinMaxLine();
2187             if( xStockPropSet.is())
2188             {
2189                 aPropertyStates.clear();
2190                 aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2191 
2192                 if( !aPropertyStates.empty() )
2193                 {
2194                     if( bExportContent )
2195                     {
2196                         AddAutoStyleAttribute( aPropertyStates );
2197 
2198                         SvXMLElementExport aGain( mrExport, XML_NAMESPACE_CHART, XML_STOCK_RANGE_LINE, sal_True, sal_True );
2199                     }
2200                     else
2201                     {
2202                         CollectAutoStyle( aPropertyStates );
2203                     }
2204                 }
2205             }
2206         }
2207     }
2208 
2209     // wall and floor element
2210     // ----------------------
2211 
2212     Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY );
2213     if( mxExpPropMapper.is() &&
2214         xWallFloorSupplier.is())
2215     {
2216         // remove property states for autostyles
2217         aPropertyStates.clear();
2218 
2219         Reference< beans::XPropertySet > xWallPropSet( xWallFloorSupplier->getWall(), uno::UNO_QUERY );
2220         if( xWallPropSet.is())
2221         {
2222             aPropertyStates = mxExpPropMapper->Filter( xWallPropSet );
2223 
2224             if( !aPropertyStates.empty() )
2225             {
2226                 // write element
2227                 if( bExportContent )
2228                 {
2229                     // add style name attribute
2230                     AddAutoStyleAttribute( aPropertyStates );
2231 
2232                     SvXMLElementExport aWall( mrExport, XML_NAMESPACE_CHART, XML_WALL, sal_True, sal_True );
2233                 }
2234                 else    // autostyles
2235                 {
2236                     CollectAutoStyle( aPropertyStates );
2237                 }
2238             }
2239         }
2240 
2241         // floor element
2242         // -------------
2243 
2244         // remove property states for autostyles
2245         aPropertyStates.clear();
2246 
2247         Reference< beans::XPropertySet > xFloorPropSet( xWallFloorSupplier->getFloor(), uno::UNO_QUERY );
2248         if( xFloorPropSet.is())
2249         {
2250             aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet );
2251 
2252             if( !aPropertyStates.empty() )
2253             {
2254                 // write element
2255                 if( bExportContent )
2256                 {
2257                     // add style name attribute
2258                     AddAutoStyleAttribute( aPropertyStates );
2259 
2260                     SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, sal_True, sal_True );
2261                 }
2262                 else    // autostyles
2263                 {
2264                     CollectAutoStyle( aPropertyStates );
2265                 }
2266             }
2267         }
2268     }
2269 
2270     if( pElPlotArea )
2271         delete pElPlotArea;
2272 }
2273 
exportCoordinateRegion(const uno::Reference<chart::XDiagram> & xDiagram)2274 void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram )
2275 {
2276     const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2277     if( nCurrentODFVersion <= SvtSaveOptions::ODFVER_012 )//do not export to ODF 1.2 or older
2278         return;
2279     if( nCurrentODFVersion != SvtSaveOptions::ODFVER_LATEST )//export only if extensions are enabled //#i100778# todo: change this dependent on fileformat evolution
2280         return;
2281 
2282     Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY );
2283     DBG_ASSERT( xDiaPos.is(), "Invalid xDiaPos as parameter" );
2284     if( !xDiaPos.is() )
2285         return;
2286 
2287     awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() );
2288     addPosition( awt::Point(aRect.X,aRect.Y) );
2289     addSize( awt::Size(aRect.Width,aRect.Height) );
2290 
2291     SvXMLElementExport aCoordinateRegion( mrExport, XML_NAMESPACE_CHART_EXT, XML_COORDINATE_REGION, sal_True, sal_True );//#i100778# todo: change to chart namespace in future - dependent on fileformat
2292 }
2293 
2294 namespace
2295 {
lcl_getTimeUnitToken(sal_Int32 nTimeUnit)2296     XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit )
2297     {
2298         XMLTokenEnum eToken = XML_DAYS;
2299         switch( nTimeUnit )
2300         {
2301         case ::com::sun::star::chart::TimeUnit::YEAR:
2302             eToken = XML_YEARS;
2303             break;
2304         case ::com::sun::star::chart::TimeUnit::MONTH:
2305             eToken = XML_MONTHS;
2306             break;
2307         default://days
2308             break;
2309         }
2310         return eToken;
2311     }
2312 }
2313 
exportDateScale(const Reference<beans::XPropertySet> xAxisProps)2314 void SchXMLExportHelper_Impl::exportDateScale( const Reference< beans::XPropertySet > xAxisProps )
2315 {
2316     if( !xAxisProps.is() )
2317         return;
2318 
2319     chart::TimeIncrement aIncrement;
2320     if( (xAxisProps->getPropertyValue( OUString::createFromAscii( "TimeIncrement" )) >>= aIncrement) )
2321     {
2322         sal_Int32 nTimeResolution = ::com::sun::star::chart::TimeUnit::DAY;
2323         if( aIncrement.TimeResolution >>= nTimeResolution )
2324             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) );
2325 
2326         OUStringBuffer aValue;
2327         chart::TimeInterval aInterval;
2328         if( aIncrement.MajorTimeInterval >>= aInterval )
2329         {
2330             SvXMLUnitConverter::convertNumber( aValue, aInterval.Number );
2331             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2332             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2333         }
2334         if( aIncrement.MinorTimeInterval >>= aInterval )
2335         {
2336             SvXMLUnitConverter::convertNumber( aValue, aInterval.Number );
2337             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, aValue.makeStringAndClear() );
2338             mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2339         }
2340 
2341         SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, sal_True, sal_True );//#i25706#todo: change namespace for next ODF version
2342     }
2343 }
2344 
exportAxisTitle(const Reference<beans::XPropertySet> xTitleProps,bool bExportContent)2345 void SchXMLExportHelper_Impl::exportAxisTitle( const Reference< beans::XPropertySet > xTitleProps, bool bExportContent )
2346 {
2347     if( !xTitleProps.is() )
2348         return;
2349     std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xTitleProps );
2350     if( bExportContent )
2351     {
2352         OUString aText;
2353         Any aAny( xTitleProps->getPropertyValue(
2354             OUString( RTL_CONSTASCII_USTRINGPARAM( "String" ))));
2355         aAny >>= aText;
2356 
2357         Reference< drawing::XShape > xShape( xTitleProps, uno::UNO_QUERY );
2358         if( xShape.is())
2359             addPosition( xShape );
2360 
2361         AddAutoStyleAttribute( aPropertyStates );
2362         SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, sal_True, sal_True );
2363 
2364         // paragraph containing title
2365         exportText( aText );
2366     }
2367     else
2368     {
2369         CollectAutoStyle( aPropertyStates );
2370     }
2371     aPropertyStates.clear();
2372 }
2373 
exportGrid(const Reference<beans::XPropertySet> xGridProperties,bool bMajor,bool bExportContent)2374 void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet > xGridProperties, bool bMajor, bool bExportContent )
2375 {
2376     if( !xGridProperties.is() )
2377         return;
2378     std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xGridProperties );
2379     if( bExportContent )
2380     {
2381         AddAutoStyleAttribute( aPropertyStates );
2382         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS, bMajor ? XML_MAJOR : XML_MINOR );
2383         SvXMLElementExport aGrid( mrExport, XML_NAMESPACE_CHART, XML_GRID, sal_True, sal_True );
2384     }
2385     else
2386     {
2387         CollectAutoStyle( aPropertyStates );
2388     }
2389     aPropertyStates.clear();
2390 }
2391 
2392 namespace
2393 {
2394 
2395 //returns true if a date scale needs to be exported
lcl_exportAxisType(const Reference<chart2::XAxis> xChart2Axis,SvXMLExport & rExport)2396 bool lcl_exportAxisType( const Reference< chart2::XAxis > xChart2Axis, SvXMLExport& rExport)
2397 {
2398     bool bExportDateScale = false;
2399     if( !xChart2Axis.is() )
2400         return bExportDateScale;
2401 
2402     const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2403     if( nCurrentODFVersion != SvtSaveOptions::ODFVER_LATEST ) //#i25706#todo: change version for next ODF version
2404         return bExportDateScale;
2405 
2406     chart2::ScaleData aScale( xChart2Axis->getScaleData() );
2407     //#i25706#todo: change namespace for next ODF version
2408     sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT;
2409 
2410     switch(aScale.AxisType)
2411     {
2412     case chart2::AxisType::CATEGORY:
2413         if( aScale.AutoDateAxis )
2414         {
2415             rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2416             bExportDateScale = true;
2417         }
2418         else
2419             rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT );
2420         break;
2421     case chart2::AxisType::DATE:
2422         rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE );
2423         bExportDateScale = true;
2424         break;
2425     default: //AUTOMATIC
2426         rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2427         break;
2428     }
2429 
2430     return bExportDateScale;
2431 }
2432 
2433 }
2434 
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)2435 void SchXMLExportHelper_Impl::exportAxis(
2436     enum XMLTokenEnum eDimension,
2437     enum XMLTokenEnum eAxisName,
2438     const Reference< beans::XPropertySet > xAxisProps,
2439     const Reference< chart2::XAxis >& xChart2Axis,
2440     const OUString& rCategoriesRange,
2441     bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
2442     bool bExportContent )
2443 {
2444     static const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" ));
2445     std::vector< XMLPropertyState > aPropertyStates;
2446     SvXMLElementExport* pAxis = NULL;
2447 
2448     // get property states for autostyles
2449     if( xAxisProps.is() && mxExpPropMapper.is() )
2450     {
2451         lcl_exportNumberFormat( sNumFormat, xAxisProps, mrExport );
2452         aPropertyStates = mxExpPropMapper->Filter( xAxisProps );
2453     }
2454 
2455     bool bExportDateScale = false;
2456     if( bExportContent )
2457     {
2458         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, eDimension );
2459         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_NAME, eAxisName );
2460         AddAutoStyleAttribute( aPropertyStates ); // write style name
2461         if( rCategoriesRange.getLength() )
2462             bExportDateScale = lcl_exportAxisType( xChart2Axis, mrExport );
2463 
2464         // open axis element
2465         pAxis = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, sal_True, sal_True );
2466     }
2467     else
2468     {
2469         CollectAutoStyle( aPropertyStates );
2470     }
2471     aPropertyStates.clear();
2472 
2473     //date scale
2474     if( bExportDateScale )
2475         exportDateScale( xAxisProps );
2476 
2477     Reference< beans::XPropertySet > xTitleProps;
2478     Reference< beans::XPropertySet > xMajorGridProps;
2479     Reference< beans::XPropertySet > xMinorGridProps;
2480     Reference< chart::XAxis > xAxis( xAxisProps, uno::UNO_QUERY );
2481     if( xAxis.is() )
2482     {
2483         xTitleProps = bHasTitle ? xAxis->getAxisTitle() : 0;
2484         xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : 0;
2485         xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : 0;
2486     }
2487 
2488     // axis-title
2489     exportAxisTitle( xTitleProps , bExportContent );
2490 
2491     // categories if we have a categories chart
2492     if( bExportContent && rCategoriesRange.getLength() )
2493     {
2494         mrExport.AddAttribute( XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, rCategoriesRange );
2495         SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, sal_True, sal_True );
2496     }
2497 
2498     // grid
2499     exportGrid( xMajorGridProps, true, bExportContent );
2500     exportGrid( xMinorGridProps, false, bExportContent );
2501 
2502     if( pAxis )
2503     {
2504         //close axis element
2505         delete pAxis;
2506         pAxis = NULL;
2507     }
2508 }
2509 
exportAxes(const Reference<chart::XDiagram> & xDiagram,const Reference<chart2::XDiagram> & xNewDiagram,sal_Bool bExportContent)2510 void SchXMLExportHelper_Impl::exportAxes(
2511     const Reference< chart::XDiagram > & xDiagram,
2512     const Reference< chart2::XDiagram > & xNewDiagram,
2513     sal_Bool bExportContent )
2514 {
2515     DBG_ASSERT( xDiagram.is(), "Invalid XDiagram as parameter" );
2516     if( ! xDiagram.is())
2517         return;
2518 
2519     // get some properties from document first
2520     sal_Bool bHasXAxis = sal_False,
2521         bHasYAxis = sal_False,
2522         bHasZAxis = sal_False,
2523         bHasSecondaryXAxis = sal_False,
2524         bHasSecondaryYAxis = sal_False;
2525     sal_Bool bHasXAxisTitle = sal_False,
2526         bHasYAxisTitle = sal_False,
2527         bHasZAxisTitle = sal_False,
2528         bHasSecondaryXAxisTitle = sal_False,
2529         bHasSecondaryYAxisTitle = sal_False;
2530     sal_Bool bHasXAxisMajorGrid = sal_False,
2531         bHasXAxisMinorGrid = sal_False,
2532         bHasYAxisMajorGrid = sal_False,
2533         bHasYAxisMinorGrid = sal_False,
2534         bHasZAxisMajorGrid = sal_False,
2535         bHasZAxisMinorGrid = sal_False;
2536 
2537     // get multiple properties using XMultiPropertySet
2538     MultiPropertySetHandler aDiagramProperties (xDiagram);
2539 
2540     aDiagramProperties.Add (
2541         OUString(RTL_CONSTASCII_USTRINGPARAM("HasXAxis")), bHasXAxis);
2542     aDiagramProperties.Add (
2543         OUString(RTL_CONSTASCII_USTRINGPARAM("HasYAxis")), bHasYAxis);
2544     aDiagramProperties.Add (
2545         OUString(RTL_CONSTASCII_USTRINGPARAM("HasZAxis")), bHasZAxis);
2546     aDiagramProperties.Add (
2547         OUString(RTL_CONSTASCII_USTRINGPARAM("HasSecondaryXAxis")), bHasSecondaryXAxis);
2548     aDiagramProperties.Add (
2549         OUString(RTL_CONSTASCII_USTRINGPARAM("HasSecondaryYAxis")), bHasSecondaryYAxis);
2550 
2551     aDiagramProperties.Add (
2552         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisTitle")), bHasXAxisTitle);
2553     aDiagramProperties.Add (
2554         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisTitle")), bHasYAxisTitle);
2555     aDiagramProperties.Add (
2556         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisTitle")), bHasZAxisTitle);
2557     aDiagramProperties.Add (
2558         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasSecondaryXAxisTitle")), bHasSecondaryXAxisTitle);
2559     aDiagramProperties.Add (
2560         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasSecondaryYAxisTitle")), bHasSecondaryYAxisTitle);
2561 
2562     aDiagramProperties.Add (
2563         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisGrid")), bHasXAxisMajorGrid);
2564     aDiagramProperties.Add (
2565         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisGrid")), bHasYAxisMajorGrid);
2566     aDiagramProperties.Add (
2567         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisGrid")), bHasZAxisMajorGrid);
2568 
2569     aDiagramProperties.Add (
2570         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasXAxisHelpGrid")), bHasXAxisMinorGrid);
2571     aDiagramProperties.Add (
2572         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasYAxisHelpGrid")), bHasYAxisMinorGrid);
2573     aDiagramProperties.Add (
2574         OUString (RTL_CONSTASCII_USTRINGPARAM ("HasZAxisHelpGrid")), bHasZAxisMinorGrid);
2575 
2576     if ( ! aDiagramProperties.GetProperties ())
2577     {
2578         DBG_WARNING ("Required properties not found in Chart diagram");
2579     }
2580 
2581     Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) );
2582 
2583     // write an axis element also if the axis itself is not visible, but a grid or a title
2584 
2585     OUString aCategoriesRange;
2586     Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );
2587 
2588     // x axis
2589     // -------
2590     Reference< ::com::sun::star::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X );
2591     if( xNewAxis.is() )
2592     {
2593         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : 0, uno::UNO_QUERY );
2594         if( mbHasCategoryLabels && bExportContent )
2595         {
2596             Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2597             if( xCategories.is() )
2598             {
2599                 Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2600                 if( xValues.is() )
2601                 {
2602                     Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2603                     maCategoriesRange = xValues->getSourceRangeRepresentation();
2604                     aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc );
2605                 }
2606             }
2607         }
2608         exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent );
2609         aCategoriesRange = OUString();
2610     }
2611 
2612     // secondary x axis
2613     // -------
2614     Reference< chart::XSecondAxisTitleSupplier > xSecondTitleSupp( xDiagram, uno::UNO_QUERY );
2615     xNewAxis = lcl_getAxis( xCooSys, XML_X, false );
2616     if( xNewAxis.is() )
2617     {
2618         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : 0, uno::UNO_QUERY );
2619         exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent );
2620     }
2621 
2622     // y axis
2623     // -------
2624     xNewAxis = lcl_getAxis( xCooSys, XML_Y );
2625     if( xNewAxis.is() )
2626     {
2627         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : 0, uno::UNO_QUERY );
2628         exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent );
2629     }
2630 
2631     // secondary y axis
2632     // -------
2633     xNewAxis = lcl_getAxis( xCooSys, XML_Y, false );
2634     if( xNewAxis.is() )
2635     {
2636         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : 0, uno::UNO_QUERY );
2637         exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent );
2638     }
2639 
2640     // z axis
2641     // -------
2642     xNewAxis = lcl_getAxis( xCooSys, XML_Z );
2643     if( xNewAxis.is() )
2644     {
2645         Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : 0, uno::UNO_QUERY );
2646         exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent );
2647     }
2648 }
2649 
2650 namespace
2651 {
lcl_hasNoValuesButText(const uno::Reference<chart2::data::XDataSequence> & xDataSequence)2652     bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
2653     {
2654         if( !xDataSequence.is() )
2655             return false;//have no data
2656 
2657         Sequence< uno::Any > aData;
2658         Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
2659         if( xNumericalDataSequence.is() )
2660         {
2661             Sequence< double >  aDoubles( xNumericalDataSequence->getNumericalData() );
2662             sal_Int32 nCount = aDoubles.getLength();
2663             for( sal_Int32 i = 0; i < nCount; ++i )
2664             {
2665                 if( !::rtl::math::isNan( aDoubles[i] ) )
2666                     return false;//have double value
2667             }
2668         }
2669         else
2670         {
2671             aData = xDataSequence->getData();
2672             double fDouble = 0.0;
2673             sal_Int32 nCount = aData.getLength();
2674             for( sal_Int32 i = 0; i < nCount; ++i )
2675             {
2676                 if( (aData[i] >>= fDouble) && !::rtl::math::isNan( fDouble ) )
2677                     return false;//have double value
2678             }
2679 
2680         }
2681         //no values found
2682 
2683         Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
2684         if( xTextualDataSequence.is() )
2685         {
2686             uno::Sequence< rtl::OUString > aStrings( xTextualDataSequence->getTextualData() );
2687             sal_Int32 nCount = aStrings.getLength();
2688             for( sal_Int32 i = 0; i < nCount; ++i )
2689             {
2690                 if( aStrings[i].getLength() )
2691                     return true;//have text
2692             }
2693         }
2694         else
2695         {
2696             if( !aData.getLength() )
2697                 aData = xDataSequence->getData();
2698             uno::Any aAny;
2699             OUString aString;
2700             sal_Int32 nCount = aData.getLength();
2701             for( sal_Int32 i = 0; i < nCount; ++i )
2702             {
2703                 if( (aData[i]>>=aString) && aString.getLength() )
2704                     return true;//have text
2705             }
2706         }
2707         //no doubles and no texts
2708         return false;
2709     }
2710 }
2711 
exportSeries(const Reference<chart2::XDiagram> & xNewDiagram,const awt::Size & rPageSize,sal_Bool bExportContent,sal_Bool bHasTwoYAxes)2712 void SchXMLExportHelper_Impl::exportSeries(
2713     const Reference< chart2::XDiagram > & xNewDiagram,
2714     const awt::Size & rPageSize,
2715     sal_Bool bExportContent,
2716     sal_Bool bHasTwoYAxes )
2717 {
2718     Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY );
2719     if( ! xBCooSysCnt.is())
2720         return;
2721     Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2722 
2723     OUString aFirstXDomainRange;
2724     OUString aFirstYDomainRange;
2725 
2726     std::vector< XMLPropertyState > aPropertyStates;
2727 
2728     const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" ));
2729     const OUString sPercentageNumFormat( OUString::createFromAscii( "PercentageNumberFormat" ));
2730 
2731     Sequence< Reference< chart2::XCoordinateSystem > >
2732         aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
2733     for( sal_Int32 nCSIdx=0; nCSIdx<aCooSysSeq.getLength(); ++nCSIdx )
2734     {
2735         Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCSIdx], uno::UNO_QUERY );
2736         if( ! xCTCnt.is())
2737             continue;
2738         Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
2739         for( sal_Int32 nCTIdx=0; nCTIdx<aCTSeq.getLength(); ++nCTIdx )
2740         {
2741             Reference< chart2::XDataSeriesContainer > xDSCnt( aCTSeq[nCTIdx], uno::UNO_QUERY );
2742             if( ! xDSCnt.is())
2743                 continue;
2744             // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
2745             OUString aChartType( aCTSeq[nCTIdx]->getChartType());
2746             OUString aLabelRole = aCTSeq[nCTIdx]->getRoleOfSequenceForSeriesLabel();
2747 
2748             // special export for stock charts
2749             if( aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.CandleStickChartType")))
2750             {
2751                 sal_Bool bJapaneseCandleSticks = sal_False;
2752                 Reference< beans::XPropertySet > xCTProp( aCTSeq[nCTIdx], uno::UNO_QUERY );
2753                 if( xCTProp.is())
2754                     xCTProp->getPropertyValue( OUString::createFromAscii("Japanese")) >>= bJapaneseCandleSticks;
2755                 exportCandleStickSeries(
2756                     xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent );
2757                 continue;
2758             }
2759 
2760             // export dataseries for current chart-type
2761             Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
2762             for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
2763             {
2764                 // export series
2765                 Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
2766                 if( xSource.is())
2767                 {
2768                     SvXMLElementExport* pSeries = NULL;
2769                     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2770                         xSource->getDataSequences());
2771                     sal_Int32 nMainSequenceIndex = -1;
2772                     sal_Int32 nSeriesLength = 0;
2773                     sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y;
2774                     sal_Bool bHasMeanValueLine = false;
2775                     chart::ChartRegressionCurveType eRegressionType( chart::ChartRegressionCurveType_NONE );
2776                     chart::ChartErrorIndicatorType eErrorType( chart::ChartErrorIndicatorType_NONE );
2777                     sal_Int32 nErrorBarStyle( chart::ErrorBarStyle::NONE );
2778                     Reference< beans::XPropertySet > xPropSet;
2779                     tLabelValuesDataPair aSeriesLabelValuesPair;
2780 
2781                     // search for main sequence and create a series element
2782                     {
2783                         Reference< chart2::data::XDataSequence > xValuesSeq;
2784                         Reference< chart2::data::XDataSequence > xLabelSeq;
2785                         sal_Int32 nSeqIdx=0;
2786                         for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
2787                         {
2788                             OUString aRole;
2789                             Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
2790                             if( nMainSequenceIndex==-1 )
2791                             {
2792                                 Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
2793                                 if( xSeqProp.is())
2794                                     xSeqProp->getPropertyValue(OUString::createFromAscii("Role")) >>= aRole;
2795                                 // "main" sequence
2796                                 if( aRole.equals( aLabelRole ))
2797                                 {
2798                                     xValuesSeq.set( xTempValueSeq );
2799                                     xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
2800                                     nMainSequenceIndex = nSeqIdx;
2801                                 }
2802                             }
2803                             sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
2804                             if( nSeriesLength < nSequenceLength )
2805                                 nSeriesLength = nSequenceLength;
2806                         }
2807 
2808                         // have found the main sequence, then xValuesSeq and
2809                         // xLabelSeq contain those.  Otherwise both are empty
2810                         {
2811                             // get property states for autostyles
2812                             try
2813                             {
2814                                 xPropSet = SchXMLSeriesHelper::createOldAPISeriesPropertySet(
2815                                     aSeriesSeq[nSeriesIdx], mrExport.GetModel() );
2816                             }
2817                             catch( uno::Exception & rEx )
2818                             {
2819                                 (void)rEx; // avoid warning for pro build
2820                                 OSL_TRACE(
2821                                     OUStringToOString(
2822                                         OUString( RTL_CONSTASCII_USTRINGPARAM(
2823                                                       "Series not found or no XPropertySet: " )) +
2824                                         rEx.Message,
2825                                         RTL_TEXTENCODING_ASCII_US ).getStr());
2826                                 continue;
2827                             }
2828                             if( xPropSet.is())
2829                             {
2830                                 // determine attached axis
2831                                 try
2832                                 {
2833                                     Any aAny( xPropSet->getPropertyValue(
2834                                                   OUString( RTL_CONSTASCII_USTRINGPARAM( "Axis" ))));
2835                                     aAny >>= nAttachedAxis;
2836 
2837                                     aAny = xPropSet->getPropertyValue(
2838                                         OUString( RTL_CONSTASCII_USTRINGPARAM ( "MeanValue" )));
2839                                     aAny >>= bHasMeanValueLine;
2840 
2841                                     aAny = xPropSet->getPropertyValue(
2842                                         OUString( RTL_CONSTASCII_USTRINGPARAM( "RegressionCurves" )));
2843                                     aAny >>= eRegressionType;
2844 
2845                                     aAny = xPropSet->getPropertyValue(
2846                                         OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorIndicator" )));
2847                                     aAny >>= eErrorType;
2848 
2849                                     aAny = xPropSet->getPropertyValue(
2850                                         OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorBarStyle" )));
2851                                     aAny >>= nErrorBarStyle;
2852                                 }
2853                                 catch( beans::UnknownPropertyException & rEx )
2854                                 {
2855                                     (void)rEx; // avoid warning for pro build
2856                                     OSL_TRACE(
2857                                         OUStringToOString(
2858                                             OUString( RTL_CONSTASCII_USTRINGPARAM(
2859                                                           "Required property not found in DataRowProperties: " )) +
2860                                             rEx.Message,
2861                                             RTL_TEXTENCODING_ASCII_US ).getStr());
2862                                 }
2863 
2864                                 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
2865                                 if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
2866                                 {
2867                                     lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
2868                                     lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
2869                                 }
2870 
2871                                 if( mxExpPropMapper.is())
2872                                     aPropertyStates = mxExpPropMapper->Filter( xPropSet );
2873                             }
2874 
2875                             if( bExportContent )
2876                             {
2877                                 if( bHasTwoYAxes )
2878                                 {
2879                                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
2880                                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
2881                                     else
2882                                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
2883                                 }
2884 
2885                                 // write style name
2886                                 AddAutoStyleAttribute( aPropertyStates );
2887 
2888                                 if( xValuesSeq.is())
2889                                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS,
2890                                                            lcl_ConvertRange(
2891                                                                xValuesSeq->getSourceRangeRepresentation(),
2892                                                                xNewDoc ));
2893                                 else
2894                                     // #i75297# allow empty series, export empty range to have all ranges on import
2895                                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, OUString());
2896 
2897                                 if( xLabelSeq.is())
2898                                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS,
2899                                                            lcl_ConvertRange(
2900                                                                xLabelSeq->getSourceRangeRepresentation(),
2901                                                                xNewDoc ));
2902                                 if( xLabelSeq.is() || xValuesSeq.is() )
2903                                     aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq );
2904 
2905                                 // chart-type for mixed types
2906                                 enum XMLTokenEnum eCTToken(
2907                                     SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ ));
2908                                 //@todo: get token for current charttype
2909                                 mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
2910                                                        mrExport.GetNamespaceMap().GetQNameByKey(
2911                                                            XML_NAMESPACE_CHART, GetXMLToken( eCTToken )));
2912 
2913                                 // open series element until end of for loop
2914                                 pSeries = new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
2915                             }
2916                             else    // autostyles
2917                             {
2918                                 CollectAutoStyle( aPropertyStates );
2919                             }
2920                             // remove property states for autostyles
2921                             aPropertyStates.clear();
2922                         }
2923                     }
2924 
2925                     // export domain elements if we have a series parent element
2926                     if( pSeries )
2927                     {
2928                         // domain elements
2929                         if( bExportContent )
2930                         {
2931                             bool bIsScatterChart = aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.ScatterChartType"));
2932                             bool bIsBubbleChart = aChartType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.chart2.BubbleChartType"));
2933                             Reference< chart2::data::XDataSequence > xYValuesForBubbleChart;
2934                             if( bIsBubbleChart )
2935                             {
2936                                 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii("values-y" ) ) );
2937                                 if( xSequence.is() )
2938                                 {
2939                                     xYValuesForBubbleChart = xSequence->getValues();
2940                                     if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) )
2941                                         xYValuesForBubbleChart = 0;
2942                                 }
2943                             }
2944                             if( bIsScatterChart || bIsBubbleChart )
2945                             {
2946                                 Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, OUString::createFromAscii("values-x" ) ) );
2947                                 if( xSequence.is() )
2948                                 {
2949                                     Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2950                                     if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) )
2951                                         m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, xValues ));
2952                                 }
2953                                 else if( nSeriesIdx==0 )
2954                                 {
2955                                     //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly
2956                                     Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2957                                     if( xCategories.is() )
2958                                     {
2959                                         Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2960                                         if( !lcl_hasNoValuesButText( xValues ) )
2961                                             lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport );
2962                                     }
2963                                 }
2964                             }
2965                             if( xYValuesForBubbleChart.is() )
2966                                 m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, xYValuesForBubbleChart ));
2967                         }
2968                     }
2969 
2970                     // add sequences for main sequence after domain sequences,
2971                     // so that the export of the local table has the correct order
2972                     if( bExportContent &&
2973                         (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is()))
2974                         m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair );
2975 
2976                     // statistical objects:
2977                     // regression curves and mean value lines
2978                     if( bHasMeanValueLine &&
2979                         xPropSet.is() &&
2980                         mxExpPropMapper.is() )
2981                     {
2982                         Reference< beans::XPropertySet > xStatProp;
2983                         try
2984                         {
2985                             Any aPropAny( xPropSet->getPropertyValue(
2986                                             OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMeanValueProperties" ))));
2987                             aPropAny >>= xStatProp;
2988                         }
2989                         catch( uno::Exception & rEx )
2990                         {
2991                             (void)rEx; // avoid warning for pro build
2992                             DBG_ERROR1( "Exception caught during Export of series - optional DataMeanValueProperties not available: %s",
2993                                         OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
2994                         }
2995 
2996                         if( xStatProp.is() )
2997                         {
2998                             aPropertyStates = mxExpPropMapper->Filter( xStatProp );
2999 
3000                             if( !aPropertyStates.empty() )
3001                             {
3002                                 // write element
3003                                 if( bExportContent )
3004                                 {
3005                                     // add style name attribute
3006                                     AddAutoStyleAttribute( aPropertyStates );
3007 
3008                                     SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_MEAN_VALUE, sal_True, sal_True );
3009                                 }
3010                                 else    // autostyles
3011                                 {
3012                                     CollectAutoStyle( aPropertyStates );
3013                                 }
3014                             }
3015                         }
3016                     }
3017 
3018                     if( eRegressionType != chart::ChartRegressionCurveType_NONE &&
3019                         xPropSet.is() &&
3020                         mxExpPropMapper.is() )
3021                     {
3022                         exportRegressionCurve( aSeriesSeq[nSeriesIdx], xPropSet, rPageSize, bExportContent );
3023                     }
3024 
3025                     if( nErrorBarStyle != chart::ErrorBarStyle::NONE &&
3026                         eErrorType != chart::ChartErrorIndicatorType_NONE &&
3027                         xPropSet.is() &&
3028                         mxExpPropMapper.is() )
3029                     {
3030                         Reference< beans::XPropertySet > xStatProp;
3031                         try
3032                         {
3033                             Any aPropAny( xPropSet->getPropertyValue(
3034                                             OUString( RTL_CONSTASCII_USTRINGPARAM( "DataErrorProperties" ))));
3035                             aPropAny >>= xStatProp;
3036                         }
3037                         catch( uno::Exception & rEx )
3038                         {
3039                             (void)rEx; // avoid warning for pro build
3040                             DBG_ERROR1( "Exception caught during Export of series - optional DataErrorProperties not available: %s",
3041                                         OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
3042                         }
3043 
3044                         if( xStatProp.is() )
3045                         {
3046                             if( bExportContent &&
3047                                 nErrorBarStyle == chart::ErrorBarStyle::FROM_DATA )
3048                             {
3049                                 // register data ranges for error bars for export in local table
3050                                 ::std::vector< Reference< chart2::data::XDataSequence > > aErrorBarSequences(
3051                                     lcl_getErrorBarSequences( xStatProp ));
3052                                 for( ::std::vector< Reference< chart2::data::XDataSequence > >::const_iterator aIt(
3053                                          aErrorBarSequences.begin()); aIt != aErrorBarSequences.end(); ++aIt )
3054                                 {
3055                                     m_aDataSequencesToExport.push_back( tLabelValuesDataPair( 0, *aIt ));
3056                                 }
3057                             }
3058 
3059                             aPropertyStates = mxExpPropMapper->Filter( xStatProp );
3060 
3061                             if( !aPropertyStates.empty() )
3062                             {
3063                                 // write element
3064                                 if( bExportContent )
3065                                 {
3066                                     // add style name attribute
3067                                     AddAutoStyleAttribute( aPropertyStates );
3068 
3069                                     const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
3070                                     if( nCurrentVersion >= SvtSaveOptions::ODFVER_012 )
3071                                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, XML_Y );//#i114149#
3072                                     SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_ERROR_INDICATOR, sal_True, sal_True );
3073                                 }
3074                                 else    // autostyles
3075                                 {
3076                                     CollectAutoStyle( aPropertyStates );
3077                                 }
3078                             }
3079                         }
3080                     }
3081 
3082                     exportDataPoints(
3083                         uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ),
3084                         nSeriesLength, xNewDiagram, bExportContent );
3085 
3086                     // close series element
3087                     if( pSeries )
3088                         delete pSeries;
3089                 }
3090             }
3091             aPropertyStates.clear();
3092         }
3093     }
3094 }
3095 
exportRegressionCurve(const Reference<chart2::XDataSeries> & xSeries,const Reference<beans::XPropertySet> & xSeriesProp,const awt::Size & rPageSize,sal_Bool bExportContent)3096 void SchXMLExportHelper_Impl::exportRegressionCurve(
3097     const Reference< chart2::XDataSeries > & xSeries,
3098     const Reference< beans::XPropertySet > & xSeriesProp,
3099     const awt::Size & rPageSize,
3100     sal_Bool bExportContent )
3101 {
3102     OSL_ASSERT( mxExpPropMapper.is());
3103 
3104     std::vector< XMLPropertyState > aPropertyStates;
3105     std::vector< XMLPropertyState > aEquationPropertyStates;
3106     Reference< beans::XPropertySet > xStatProp;
3107     try
3108     {
3109         Any aPropAny( xSeriesProp->getPropertyValue(
3110                           OUString( RTL_CONSTASCII_USTRINGPARAM( "DataRegressionProperties" ))));
3111         aPropAny >>= xStatProp;
3112     }
3113     catch( uno::Exception & rEx )
3114     {
3115         (void)rEx; // avoid warning for pro build
3116         DBG_ERROR1( "Exception caught during Export of series - optional DataRegressionProperties not available: %s",
3117                     OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
3118     }
3119 
3120     if( xStatProp.is() )
3121     {
3122         Reference< chart2::XRegressionCurve > xRegCurve( SchXMLTools::getRegressionCurve( xSeries ));
3123         Reference< beans::XPropertySet > xEquationProperties;
3124         if( xRegCurve.is())
3125             xEquationProperties.set( xRegCurve->getEquationProperties());
3126 
3127         bool bShowEquation = false;
3128         bool bShowRSquared = false;
3129         bool bExportEquation = false;
3130         aPropertyStates = mxExpPropMapper->Filter( xStatProp );
3131         if( xEquationProperties.is())
3132         {
3133             xEquationProperties->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ShowEquation" )))
3134                 >>= bShowEquation;
3135             xEquationProperties->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ShowCorrelationCoefficient" )))
3136                 >>= bShowRSquared;
3137             bExportEquation = ( bShowEquation || bShowRSquared );
3138             const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
3139             if( nCurrentVersion < SvtSaveOptions::ODFVER_012 )
3140                 bExportEquation=false;
3141             if( bExportEquation )
3142             {
3143                 // number format
3144                 sal_Int32 nNumberFormat = 0;
3145                 if( ( xEquationProperties->getPropertyValue(
3146                           OUString( RTL_CONSTASCII_USTRINGPARAM( "NumberFormat" ))) >>= nNumberFormat ) &&
3147                     nNumberFormat != -1 )
3148                 {
3149                     mrExport.addDataStyle( nNumberFormat );
3150                 }
3151                 aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties );
3152             }
3153         }
3154 
3155         if( !aPropertyStates.empty() || bExportEquation )
3156         {
3157             // write element
3158             if( bExportContent )
3159             {
3160                 // add style name attribute
3161                 if( !aPropertyStates.empty())
3162                     AddAutoStyleAttribute( aPropertyStates );
3163                 SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, sal_True, sal_True );
3164                 if( bExportEquation )
3165                 {
3166                     // default is true
3167                     if( !bShowEquation )
3168                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_EQUATION, XML_FALSE );
3169                     // default is false
3170                     if( bShowRSquared )
3171                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, XML_TRUE );
3172 
3173                     // export position
3174                     chart2::RelativePosition aRelativePosition;
3175                     if( xEquationProperties->getPropertyValue(
3176                             OUString( RTL_CONSTASCII_USTRINGPARAM("RelativePosition"))) >>= aRelativePosition )
3177                     {
3178                         double fX = aRelativePosition.Primary * rPageSize.Width;
3179                         double fY = aRelativePosition.Secondary * rPageSize.Height;
3180                         awt::Point aPos;
3181                         aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
3182                         aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
3183                         addPosition( aPos );
3184                     }
3185 
3186                     if( !aEquationPropertyStates.empty())
3187                         AddAutoStyleAttribute( aEquationPropertyStates );
3188 
3189                     SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_EQUATION, sal_True, sal_True );
3190                 }
3191             }
3192             else    // autostyles
3193             {
3194                 if( !aPropertyStates.empty())
3195                     CollectAutoStyle( aPropertyStates );
3196                 if( bExportEquation && !aEquationPropertyStates.empty())
3197                     CollectAutoStyle( aEquationPropertyStates );
3198             }
3199         }
3200     }
3201 }
3202 
exportCandleStickSeries(const Sequence<Reference<chart2::XDataSeries>> & aSeriesSeq,const Reference<chart2::XDiagram> & xDiagram,sal_Bool bJapaneseCandleSticks,sal_Bool bExportContent)3203 void SchXMLExportHelper_Impl::exportCandleStickSeries(
3204     const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
3205     const Reference< chart2::XDiagram > & xDiagram,
3206     sal_Bool bJapaneseCandleSticks,
3207     sal_Bool bExportContent )
3208 {
3209 //  std::vector< XMLPropertyState > aPropertyStates;
3210 
3211     for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
3212     {
3213         Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx] );
3214         sal_Int32 nAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries )
3215             ? chart::ChartAxisAssign::PRIMARY_Y
3216             : chart::ChartAxisAssign::SECONDARY_Y;
3217 
3218         Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
3219         if( xSource.is())
3220         {
3221             // export series in correct order (as we don't store roles)
3222             // with japanese candlesticks: open, low, high, close
3223             // otherwise: low, high, close
3224             Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
3225                 xSource->getDataSequences());
3226 
3227             sal_Int32 nSeriesLength =
3228                 lcl_getSequenceLengthByRole( aSeqCnt, OUString::createFromAscii("values-last"));
3229 
3230             if( bExportContent )
3231             {
3232                 Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
3233                 //@todo: export data points
3234 
3235                 // open
3236                 if( bJapaneseCandleSticks )
3237                 {
3238                     tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3239                         aSeqCnt, OUString::createFromAscii("values-first"),  xNewDoc, m_aDataSequencesToExport ));
3240                     if( aRanges.second.getLength())
3241                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3242                     if( aRanges.first.getLength())
3243                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3244                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3245                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3246                     else
3247                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3248                     SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3249                     // export empty data points
3250                     exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3251                 }
3252 
3253                 // low
3254                 {
3255                     tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3256                         aSeqCnt, OUString::createFromAscii("values-min"),  xNewDoc, m_aDataSequencesToExport ));
3257                     if( aRanges.second.getLength())
3258                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3259                     if( aRanges.first.getLength())
3260                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3261                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3262                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3263                     else
3264                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3265                     SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3266                     // export empty data points
3267                     exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3268                 }
3269 
3270                 // high
3271                 {
3272                     tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3273                         aSeqCnt, OUString::createFromAscii("values-max"),  xNewDoc, m_aDataSequencesToExport ));
3274                     if( aRanges.second.getLength())
3275                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3276                     if( aRanges.first.getLength())
3277                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3278                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3279                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3280                     else
3281                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3282                     SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3283                     // export empty data points
3284                     exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3285                 }
3286 
3287                 // close
3288                 {
3289                     tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3290                         aSeqCnt, OUString::createFromAscii("values-last"),  xNewDoc, m_aDataSequencesToExport ));
3291                     if( aRanges.second.getLength())
3292                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_VALUES_CELL_RANGE_ADDRESS, aRanges.second );
3293                     if( aRanges.first.getLength())
3294                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_LABEL_CELL_ADDRESS, aRanges.first );
3295                     if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3296                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_SECONDARY_Y );
3297                     else
3298                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_ATTACHED_AXIS, XML_PRIMARY_Y );
3299                     // write style name
3300 //                     AddAutoStyleAttribute( aPropertyStates );
3301                     // chart type
3302 //                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_CLASS,
3303 //                                            mrExport.GetNamespaceMap().GetQNameByKey(
3304 //                                                XML_NAMESPACE_CHART, GetXMLToken( XML_STOCK )));
3305                     SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, sal_True, sal_True );
3306                     // export empty data points
3307                     exportDataPoints( 0, nSeriesLength, xDiagram, bExportContent );
3308                 }
3309             }
3310             else    // autostyles
3311             {
3312                 // for close series
3313 //                 CollectAutoStyle( aPropertyStates );
3314             }
3315             // remove property states for autostyles
3316 //             aPropertyStates.clear();
3317         }
3318     }
3319 }
3320 
exportDataPoints(const uno::Reference<beans::XPropertySet> & xSeriesProperties,sal_Int32 nSeriesLength,const uno::Reference<chart2::XDiagram> & xDiagram,sal_Bool bExportContent)3321 void SchXMLExportHelper_Impl::exportDataPoints(
3322     const uno::Reference< beans::XPropertySet > & xSeriesProperties,
3323     sal_Int32 nSeriesLength,
3324     const uno::Reference< chart2::XDiagram > & xDiagram,
3325     sal_Bool bExportContent )
3326 {
3327     // data-points
3328     // -----------
3329     // write data-points only if they contain autostyles
3330     // objects with equal autostyles are grouped using the attribute
3331     // repeat="number"
3332 
3333     // Note: if only the nth data-point has autostyles there is an element
3334     // without style and repeat="n-1" attribute written in advance.
3335 
3336     // the sequence aDataPointSeq contains indices of data-points that
3337     // do have own attributes.  This increases the performance substantially.
3338 
3339     // more performant version for #93600#
3340     if( mxExpPropMapper.is())
3341     {
3342         uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
3343 
3344         std::vector< XMLPropertyState > aPropertyStates;
3345 
3346         const OUString sNumFormat( OUString::createFromAscii( "NumberFormat" ));
3347         const OUString sPercentageNumFormat( OUString::createFromAscii( "PercentageNumberFormat" ));
3348 
3349         bool bVaryColorsByPoint = false;
3350         Sequence< sal_Int32 > aDataPointSeq;
3351         if( xSeriesProperties.is())
3352         {
3353             Any aAny = xSeriesProperties->getPropertyValue(
3354                 OUString( RTL_CONSTASCII_USTRINGPARAM( "AttributedDataPoints" )));
3355             aAny >>= aDataPointSeq;
3356             xSeriesProperties->getPropertyValue(
3357                 OUString( RTL_CONSTASCII_USTRINGPARAM( "VaryColorsByPoint" ))) >>= bVaryColorsByPoint;
3358         }
3359 
3360 
3361         sal_Int32 nSize = aDataPointSeq.getLength();
3362         DBG_ASSERT( nSize <= nSeriesLength, "Too many point attributes" );
3363 
3364         const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
3365         sal_Int32 nElement;
3366         sal_Int32 nRepeat;
3367         Reference< chart2::XColorScheme > xColorScheme;
3368         if( xDiagram.is())
3369             xColorScheme.set( xDiagram->getDefaultColorScheme());
3370 
3371         ::std::list< SchXMLDataPointStruct > aDataPointList;
3372 
3373         sal_Int32 nLastIndex = -1;
3374         sal_Int32 nCurrIndex = 0;
3375 
3376         // collect elements
3377         if( bVaryColorsByPoint && xColorScheme.is() )
3378         {
3379             ::std::set< sal_Int32 > aAttrPointSet;
3380             ::std::copy( pPoints, pPoints + aDataPointSeq.getLength(),
3381                             ::std::inserter( aAttrPointSet, aAttrPointSet.begin()));
3382             const ::std::set< sal_Int32 >::const_iterator aEndIt( aAttrPointSet.end());
3383             for( nElement = 0; nElement < nSeriesLength; ++nElement )
3384             {
3385                 aPropertyStates.clear();
3386                 uno::Reference< beans::XPropertySet > xPropSet;
3387                 bool bExportNumFmt = false;
3388                 if( aAttrPointSet.find( nElement ) != aEndIt )
3389                 {
3390                     try
3391                     {
3392                         xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3393                                     xSeries, nElement, mrExport.GetModel() );
3394                         bExportNumFmt = true;
3395                     }
3396                     catch( uno::Exception & rEx )
3397                     {
3398                         (void)rEx; // avoid warning for pro build
3399                         DBG_ERROR1( "Exception caught during Export of data point: %s",
3400                                     OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
3401                     }
3402                 }
3403                 else
3404                 {
3405                     // property set only containing the color
3406                     xPropSet.set( new ::xmloff::chart::ColorPropertySet(
3407                                         xColorScheme->getColorByIndex( nElement )));
3408                 }
3409                 DBG_ASSERT( xPropSet.is(), "Pie Segments should have properties" );
3410                 if( xPropSet.is())
3411                 {
3412                     const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3413                     if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 && bExportNumFmt )
3414                     {
3415                         lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
3416                         lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
3417                     }
3418 
3419                     aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3420                     if( !aPropertyStates.empty() )
3421                     {
3422                         if( bExportContent )
3423                         {
3424                             // write data-point with style
3425                             DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" );
3426 
3427                             SchXMLDataPointStruct aPoint;
3428                             aPoint.maStyleName = maAutoStyleNameQueue.front();
3429                             maAutoStyleNameQueue.pop();
3430                             aDataPointList.push_back( aPoint );
3431                         }
3432                         else
3433                         {
3434                             CollectAutoStyle( aPropertyStates );
3435                         }
3436                     }
3437                 }
3438             }
3439             DBG_ASSERT( !bExportContent || (static_cast<sal_Int32>(aDataPointList.size()) == nSeriesLength),
3440                         "not enough data points on content export" );
3441         }
3442         else
3443         {
3444             for( nElement = 0; nElement < nSize; ++nElement )
3445             {
3446                 aPropertyStates.clear();
3447                 nCurrIndex = pPoints[ nElement ];
3448                 //assuming sorted indices in pPoints
3449 
3450                 if( nCurrIndex<0 || nCurrIndex>=nSeriesLength )
3451                     break;
3452 
3453                 // write leading empty data points
3454                 if( nCurrIndex - nLastIndex > 1 )
3455                 {
3456                     SchXMLDataPointStruct aPoint;
3457                     aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
3458                     aDataPointList.push_back( aPoint );
3459                 }
3460 
3461                 uno::Reference< beans::XPropertySet > xPropSet;
3462                 // get property states
3463                 try
3464                 {
3465                     xPropSet = SchXMLSeriesHelper::createOldAPIDataPointPropertySet(
3466                                     xSeries, nCurrIndex, mrExport.GetModel() );
3467                 }
3468                 catch( uno::Exception & rEx )
3469                 {
3470                     (void)rEx; // avoid warning for pro build
3471                     DBG_ERROR1( "Exception caught during Export of data point: %s",
3472                                 OUStringToOString( rEx.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
3473                 }
3474                 if( xPropSet.is())
3475                 {
3476                     const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
3477                     if( nCurrentODFVersion >= SvtSaveOptions::ODFVER_012 )
3478                     {
3479                         lcl_exportNumberFormat( sNumFormat, xPropSet, mrExport );
3480                         lcl_exportNumberFormat( sPercentageNumFormat, xPropSet, mrExport );
3481                     }
3482 
3483                     aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3484                     if( !aPropertyStates.empty() )
3485                     {
3486                         if( bExportContent )
3487                         {
3488                             // write data-point with style
3489                             DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" );
3490                             SchXMLDataPointStruct aPoint;
3491                             aPoint.maStyleName = maAutoStyleNameQueue.front();
3492                             maAutoStyleNameQueue.pop();
3493 
3494                             aDataPointList.push_back( aPoint );
3495                             nLastIndex = nCurrIndex;
3496                         }
3497                         else
3498                         {
3499                             CollectAutoStyle( aPropertyStates );
3500                         }
3501                         continue;
3502                     }
3503                 }
3504 
3505                 // if we get here the property states are empty
3506                 SchXMLDataPointStruct aPoint;
3507                 aDataPointList.push_back( aPoint );
3508 
3509                 nLastIndex = nCurrIndex;
3510             }
3511             // final empty elements
3512             nRepeat = nSeriesLength - nLastIndex - 1;
3513             if( nRepeat > 0 )
3514             {
3515                 SchXMLDataPointStruct aPoint;
3516                 aPoint.mnRepeat = nRepeat;
3517                 aDataPointList.push_back( aPoint );
3518             }
3519         }
3520 
3521         if( bExportContent )
3522         {
3523             // write elements (merge equal ones)
3524             ::std::list< SchXMLDataPointStruct >::iterator aIter = aDataPointList.begin();
3525             SchXMLDataPointStruct aPoint;
3526             SchXMLDataPointStruct aLastPoint;
3527 
3528             // initialize so that it doesn't matter if
3529             // the element is counted in the first iteration
3530             aLastPoint.mnRepeat = 0;
3531 
3532             for( ; aIter != aDataPointList.end(); ++aIter )
3533             {
3534                 aPoint = (*aIter);
3535 
3536                 if( aPoint.maStyleName == aLastPoint.maStyleName )
3537                     aPoint.mnRepeat += aLastPoint.mnRepeat;
3538                 else if( aLastPoint.mnRepeat > 0 )
3539                 {
3540                     // write last element
3541                     if( aLastPoint.maStyleName.getLength() )
3542                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3543 
3544                     if( aLastPoint.mnRepeat > 1 )
3545                         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3546                                             OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) ));
3547 
3548                     SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True );
3549                 }
3550                 aLastPoint = aPoint;
3551             }
3552             // write last element if it hasn't been written in last iteration
3553             if( aPoint.maStyleName == aLastPoint.maStyleName )
3554             {
3555                 if( aLastPoint.maStyleName.getLength() )
3556                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3557 
3558                 if( aLastPoint.mnRepeat > 1 )
3559                     mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_REPEATED,
3560                                         OUString::valueOf( (sal_Int64)( aLastPoint.mnRepeat ) ));
3561 
3562                 SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, sal_True, sal_True );
3563             }
3564         }
3565     }
3566 }
3567 
3568 
getCellAddress(sal_Int32 nCol,sal_Int32 nRow)3569 void SchXMLExportHelper_Impl::getCellAddress( sal_Int32 nCol, sal_Int32 nRow )
3570 {
3571     msStringBuffer.append( (sal_Unicode)'.' );
3572     if( nCol < 26 )
3573         msStringBuffer.append( (sal_Unicode)('A' + nCol) );
3574     else if( nCol < 702 )
3575     {
3576         msStringBuffer.append( (sal_Unicode)('A' + nCol / 26 - 1 ));
3577         msStringBuffer.append( (sal_Unicode)('A' + nCol % 26) );
3578     }
3579     else
3580     {
3581         msStringBuffer.append( (sal_Unicode)('A' + nCol / 702 - 1 ));
3582         msStringBuffer.append( (sal_Unicode)('A' + (nCol % 702) / 26 ));
3583         msStringBuffer.append( (sal_Unicode)('A' + nCol % 26) );
3584     }
3585 
3586     msStringBuffer.append( nRow + (sal_Int32)1 );
3587 }
3588 
addPosition(const awt::Point & rPosition)3589 void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition )
3590 {
3591     mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rPosition.X );
3592     msString = msStringBuffer.makeStringAndClear();
3593     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, msString );
3594 
3595     mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rPosition.Y );
3596     msString = msStringBuffer.makeStringAndClear();
3597     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, msString );
3598 }
3599 
addPosition(Reference<drawing::XShape> xShape)3600 void SchXMLExportHelper_Impl::addPosition( Reference< drawing::XShape > xShape )
3601 {
3602     if( xShape.is())
3603         addPosition( xShape->getPosition());
3604 }
3605 
addSize(const awt::Size & rSize,bool bIsOOoNamespace)3606 void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace)
3607 {
3608     mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rSize.Width );
3609     msString = msStringBuffer.makeStringAndClear();
3610     mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG , XML_WIDTH,  msString );
3611 
3612 
3613     mrExport.GetMM100UnitConverter().convertMeasure( msStringBuffer, rSize.Height);
3614     msString = msStringBuffer.makeStringAndClear();
3615     mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString );
3616 }
3617 
addSize(Reference<drawing::XShape> xShape,bool bIsOOoNamespace)3618 void SchXMLExportHelper_Impl::addSize( Reference< drawing::XShape > xShape, bool bIsOOoNamespace )
3619 {
3620     if( xShape.is())
3621         addSize( xShape->getSize(), bIsOOoNamespace );
3622 }
3623 
getPageSize(const Reference<chart2::XChartDocument> & xChartDoc) const3624 awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc ) const
3625 {
3626     awt::Size aSize( 8000, 7000 );
3627     uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
3628     DBG_ASSERT( xVisualObject.is(),"need XVisualObject for page size" );
3629     if( xVisualObject.is() )
3630         aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
3631 
3632     return aSize;
3633 }
3634 
CollectAutoStyle(const std::vector<XMLPropertyState> & aStates)3635 void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates )
3636 {
3637     if( !aStates.empty() )
3638         maAutoStyleNameQueue.push( GetAutoStylePoolP().Add( XML_STYLE_FAMILY_SCH_CHART_ID, aStates ));
3639 }
3640 
AddAutoStyleAttribute(const std::vector<XMLPropertyState> & aStates)3641 void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates )
3642 {
3643     if( !aStates.empty() )
3644     {
3645         DBG_ASSERT( ! maAutoStyleNameQueue.empty(), "Autostyle queue empty!" );
3646 
3647         mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME,  maAutoStyleNameQueue.front() );
3648         maAutoStyleNameQueue.pop();
3649     }
3650 }
3651 
exportText(const OUString & rText,bool bConvertTabsLFs)3652 void SchXMLExportHelper_Impl::exportText( const OUString& rText, bool bConvertTabsLFs )
3653 {
3654     SchXMLTools::exportText( mrExport, rText, bConvertTabsLFs );
3655 }
3656 
3657 // ========================================
3658 // class SchXMLExport
3659 // ========================================
3660 
3661 // #110680#
SchXMLExport(const Reference<lang::XMultiServiceFactory> & xServiceFactory,sal_uInt16 nExportFlags)3662 SchXMLExport::SchXMLExport(
3663     const Reference< lang::XMultiServiceFactory >& xServiceFactory,
3664     sal_uInt16 nExportFlags )
3665 :   SvXMLExport( xServiceFactory, MAP_CM, ::xmloff::token::XML_CHART, nExportFlags ),
3666     maAutoStylePool( *this ),
3667     maExportHelper( *this, maAutoStylePool )
3668 {
3669     if( getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST )
3670         _GetNamespaceMap().Add( GetXMLToken(XML_NP_CHART_EXT), GetXMLToken(XML_N_CHART_EXT), XML_NAMESPACE_CHART_EXT);
3671 }
3672 
3673 
~SchXMLExport()3674 SchXMLExport::~SchXMLExport()
3675 {
3676     // stop progress view
3677     if( mxStatusIndicator.is())
3678     {
3679         mxStatusIndicator->end();
3680         mxStatusIndicator->reset();
3681     }
3682 }
3683 
exportDoc(enum::xmloff::token::XMLTokenEnum eClass)3684 sal_uInt32 SchXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )
3685 {
3686     Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3687     maExportHelper.m_pImpl->InitRangeSegmentationProperties( xChartDoc );
3688     return SvXMLExport::exportDoc( eClass );
3689 }
3690 
_ExportStyles(sal_Bool bUsed)3691 void SchXMLExport::_ExportStyles( sal_Bool bUsed )
3692 {
3693     SvXMLExport::_ExportStyles( bUsed );
3694 }
3695 
_ExportMasterStyles()3696 void SchXMLExport::_ExportMasterStyles()
3697 {
3698     // not available in chart
3699     DBG_WARNING( "Master Style Export requested. Not available for Chart" );
3700 }
3701 
_ExportAutoStyles()3702 void SchXMLExport::_ExportAutoStyles()
3703 {
3704     // there are no styles that require their own autostyles
3705     if( getExportFlags() & EXPORT_CONTENT )
3706     {
3707         Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3708         if( xChartDoc.is())
3709         {
3710             maExportHelper.m_pImpl->collectAutoStyles( xChartDoc );
3711             maExportHelper.m_pImpl->exportAutoStyles();
3712         }
3713         else
3714         {
3715             DBG_ERROR( "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3716         }
3717     }
3718 }
3719 
_ExportContent()3720 void SchXMLExport::_ExportContent()
3721 {
3722     Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3723     if( xChartDoc.is())
3724     {
3725         // determine if data comes from the outside
3726         sal_Bool bIncludeTable = sal_True;
3727 
3728         Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
3729         if( xNewDoc.is())
3730         {
3731             // check if we have own data.  If so we must not export the complete
3732             // range string, as this is our only indicator for having own or
3733             // external data. @todo: fix this in the file format!
3734             Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
3735             if( ! (xDPServiceInfo.is() &&
3736                    xDPServiceInfo->getImplementationName().equalsAsciiL(
3737                        RTL_CONSTASCII_STRINGPARAM( "com.sun.star.comp.chart.InternalDataProvider" ))))
3738             {
3739                 bIncludeTable = sal_False;
3740             }
3741         }
3742         else
3743         {
3744             Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
3745             if( xServ.is())
3746             {
3747                 if( xServ->supportsService(
3748                         OUString::createFromAscii( "com.sun.star.chart.ChartTableAddressSupplier" )))
3749                 {
3750                     Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
3751                     if( xProp.is())
3752                     {
3753                         Any aAny;
3754                         try
3755                         {
3756                             OUString sChartAddress;
3757                             aAny = xProp->getPropertyValue(
3758                                 OUString::createFromAscii( "ChartRangeAddress" ));
3759                             aAny >>= sChartAddress;
3760                             maExportHelper.m_pImpl->SetChartRangeAddress( sChartAddress );
3761 
3762                             OUString sTableNumberList;
3763                             aAny = xProp->getPropertyValue(
3764                                 OUString::createFromAscii( "TableNumberList" ));
3765                             aAny >>= sTableNumberList;
3766                             maExportHelper.m_pImpl->SetTableNumberList( sTableNumberList );
3767 
3768                             // do not include own table if there are external addresses
3769                             bIncludeTable = (sChartAddress.getLength() == 0);
3770                         }
3771                         catch( beans::UnknownPropertyException & )
3772                         {
3773                             DBG_ERROR( "Property ChartRangeAddress not supported by ChartDocument" );
3774                         }
3775                     }
3776                 }
3777             }
3778         }
3779         maExportHelper.m_pImpl->exportChart( xChartDoc, bIncludeTable );
3780     }
3781     else
3782     {
3783         DBG_ERROR( "Couldn't export chart due to wrong XModel" );
3784     }
3785 }
3786 
SetProgress(sal_Int32 nPercentage)3787 void SchXMLExport::SetProgress( sal_Int32 nPercentage )
3788 {
3789     // set progress view
3790     if( mxStatusIndicator.is())
3791         mxStatusIndicator->setValue( nPercentage );
3792 }
3793 
GetPropertySetMapper() const3794 UniReference< XMLPropertySetMapper > SchXMLExport::GetPropertySetMapper() const
3795 {
3796     return maExportHelper.m_pImpl->GetPropertySetMapper();
3797 }
3798 
InitRangeSegmentationProperties(const Reference<chart2::XChartDocument> & xChartDoc)3799 void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
3800 {
3801     if( xChartDoc.is())
3802         try
3803         {
3804             Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
3805             OSL_ENSURE( xDataProvider.is(), "No DataProvider" );
3806             if( xDataProvider.is())
3807             {
3808                 Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
3809                 Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
3810                 ::rtl::OUString sCellRange, sBrokenRange;
3811                 bool bBrokenRangeAvailable = false;
3812                 for( sal_Int32 i=0; i<aArgs.getLength(); ++i )
3813                 {
3814                     if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
3815                         aArgs[i].Value >>= sCellRange;
3816                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("BrokenCellRangeForExport")))
3817                     {
3818                         if( aArgs[i].Value >>= sBrokenRange )
3819                             bBrokenRangeAvailable = true;
3820                     }
3821                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DataRowSource")))
3822                     {
3823                         chart::ChartDataRowSource eRowSource;
3824                         aArgs[i].Value >>= eRowSource;
3825                         mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS );
3826                     }
3827                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("FirstCellAsLabel")))
3828                         aArgs[i].Value >>= mbHasSeriesLabels;
3829                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
3830                         aArgs[i].Value >>= maSequenceMapping;
3831                     else if( aArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("TableNumberList")))
3832                         aArgs[i].Value >>= msTableNumberList;
3833                 }
3834 
3835                 // #i79009# For Writer we have to export a broken version of the
3836                 // range, where every row number is noe too large, so that older
3837                 // version can correctly read those files.
3838                 msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
3839                 if( msChartAddress.getLength() > 0 )
3840                 {
3841                     // convert format to XML-conform one
3842                     Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
3843                     if( xConversion.is())
3844                         msChartAddress = xConversion->convertRangeToXML( msChartAddress );
3845                 }
3846             }
3847         }
3848         catch( uno::Exception & ex )
3849         {
3850             (void)ex; // avoid warning for pro build
3851             OSL_ENSURE( false, OUStringToOString(
3852                             OUString( RTL_CONSTASCII_USTRINGPARAM( "Exception caught. Type: " )) +
3853                             OUString::createFromAscii( typeid( ex ).name()) +
3854                             OUString( RTL_CONSTASCII_USTRINGPARAM( ", Message: " )) +
3855                             ex.Message, RTL_TEXTENCODING_ASCII_US ).getStr());
3856         }
3857 }
3858 
3859 // export components ========================================
3860 
3861 // first version: everything goes in one storage
3862 
SchXMLExport_getSupportedServiceNames()3863 Sequence< OUString > SAL_CALL SchXMLExport_getSupportedServiceNames() throw()
3864 {
3865     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLExporter" ) );
3866     const Sequence< OUString > aSeq( &aServiceName, 1 );
3867     return aSeq;
3868 }
3869 
SchXMLExport_getImplementationName()3870 OUString SAL_CALL SchXMLExport_getImplementationName() throw()
3871 {
3872     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Compact" ) );
3873 }
3874 
SchXMLExport_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3875 Reference< uno::XInterface > SAL_CALL SchXMLExport_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3876 {
3877     // #110680#
3878     // #103997# removed some flags from EXPORT_ALL
3879     // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS ));
3880     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS ));
3881 }
3882 
3883 // Oasis format
SchXMLExport_Oasis_getSupportedServiceNames()3884 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_getSupportedServiceNames() throw()
3885 {
3886     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisExporter" ) );
3887     const Sequence< OUString > aSeq( &aServiceName, 1 );
3888     return aSeq;
3889 }
3890 
SchXMLExport_Oasis_getImplementationName()3891 OUString SAL_CALL SchXMLExport_Oasis_getImplementationName() throw()
3892 {
3893     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Compact" ) );
3894 }
3895 
SchXMLExport_Oasis_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3896 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3897 {
3898     // #103997# removed some flags from EXPORT_ALL
3899     return (cppu::OWeakObject*)new SchXMLExport( rSMgr,
3900         (EXPORT_ALL ^ ( EXPORT_SETTINGS | EXPORT_MASTERSTYLES | EXPORT_SCRIPTS )) | EXPORT_OASIS );
3901 }
3902 
3903 // ============================================================
3904 
3905 // multiple storage version: one for content / styles / meta
3906 
SchXMLExport_Styles_getSupportedServiceNames()3907 Sequence< OUString > SAL_CALL SchXMLExport_Styles_getSupportedServiceNames() throw()
3908 {
3909     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLStylesExporter" ));
3910     const Sequence< OUString > aSeq( &aServiceName, 1 );
3911     return aSeq;
3912 }
3913 
SchXMLExport_Styles_getImplementationName()3914 OUString SAL_CALL SchXMLExport_Styles_getImplementationName() throw()
3915 {
3916     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Styles" ));
3917 }
3918 
SchXMLExport_Styles_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3919 Reference< uno::XInterface > SAL_CALL SchXMLExport_Styles_createInstance(const Reference< lang::XMultiServiceFactory >& rSMgr)
3920 {
3921     // #110680#
3922     // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_STYLES );
3923     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_STYLES );
3924 }
3925 
3926 // Oasis format
SchXMLExport_Oasis_Styles_getSupportedServiceNames()3927 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Styles_getSupportedServiceNames() throw()
3928 {
3929     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisStylesExporter" ));
3930     const Sequence< OUString > aSeq( &aServiceName, 1 );
3931     return aSeq;
3932 }
3933 
SchXMLExport_Oasis_Styles_getImplementationName()3934 OUString SAL_CALL SchXMLExport_Oasis_Styles_getImplementationName() throw()
3935 {
3936     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Styles" ));
3937 }
3938 
SchXMLExport_Oasis_Styles_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3939 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Styles_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3940 {
3941     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_STYLES | EXPORT_OASIS );
3942 }
3943 
3944 // ------------------------------------------------------------
3945 
SchXMLExport_Content_getSupportedServiceNames()3946 Sequence< OUString > SAL_CALL SchXMLExport_Content_getSupportedServiceNames() throw()
3947 {
3948     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLContentExporter" ));
3949     const Sequence< OUString > aSeq( &aServiceName, 1 );
3950     return aSeq;
3951 }
3952 
SchXMLExport_Content_getImplementationName()3953 OUString SAL_CALL SchXMLExport_Content_getImplementationName() throw()
3954 {
3955     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Content" ));
3956 }
3957 
SchXMLExport_Content_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3958 Reference< uno::XInterface > SAL_CALL SchXMLExport_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3959 {
3960     // #110680#
3961     // return (cppu::OWeakObject*)new SchXMLExport( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS );
3962     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS );
3963 }
3964 
3965 // Oasis format
SchXMLExport_Oasis_Content_getSupportedServiceNames()3966 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Content_getSupportedServiceNames() throw()
3967 {
3968     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisContentExporter" ));
3969     const Sequence< OUString > aSeq( &aServiceName, 1 );
3970     return aSeq;
3971 }
3972 
SchXMLExport_Oasis_Content_getImplementationName()3973 OUString SAL_CALL SchXMLExport_Oasis_Content_getImplementationName() throw()
3974 {
3975     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Content" ));
3976 }
3977 
SchXMLExport_Oasis_Content_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)3978 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Content_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
3979 {
3980     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS );
3981 }
3982 
3983 // ------------------------------------------------------------
3984 
3985 // Sequence< OUString > SAL_CALL SchXMLExport_Meta_getSupportedServiceNames() throw()
3986 // {
3987 //  const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLMetaExporter" ));
3988 //  const Sequence< OUString > aSeq( &aServiceName, 1 );
3989 //  return aSeq;
3990 // }
3991 
3992 // OUString SAL_CALL SchXMLExport_Meta_getImplementationName() throw()
3993 // {
3994 //  return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Meta" ));
3995 // }
3996 
3997 // Reference< uno::XInterface > SAL_CALL SchXMLExport_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr) throw( uno::Exception )
3998 // {
3999 //  return (cppu::OWeakObject*)new SchXMLExport( EXPORT_META );
4000 // }
4001 
4002 // Oasis format
SchXMLExport_Oasis_Meta_getSupportedServiceNames()4003 Sequence< OUString > SAL_CALL SchXMLExport_Oasis_Meta_getSupportedServiceNames() throw()
4004 {
4005     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Chart.XMLOasisMetaExporter" ));
4006     const Sequence< OUString > aSeq( &aServiceName, 1 );
4007     return aSeq;
4008 }
4009 
SchXMLExport_Oasis_Meta_getImplementationName()4010 OUString SAL_CALL SchXMLExport_Oasis_Meta_getImplementationName() throw()
4011 {
4012     return OUString( RTL_CONSTASCII_USTRINGPARAM( "SchXMLExport.Oasis.Meta" ));
4013 }
4014 
SchXMLExport_Oasis_Meta_createInstance(const Reference<lang::XMultiServiceFactory> & rSMgr)4015 Reference< uno::XInterface > SAL_CALL SchXMLExport_Oasis_Meta_createInstance(const Reference< lang::XMultiServiceFactory > & rSMgr)
4016 {
4017     return (cppu::OWeakObject*)new SchXMLExport( rSMgr, EXPORT_META | EXPORT_OASIS  );
4018 }
4019 
4020 
4021 // XServiceInfo
getImplementationName()4022 OUString SAL_CALL SchXMLExport::getImplementationName()
4023 {
4024     switch( getExportFlags())
4025     {
4026         case EXPORT_ALL:
4027             return SchXMLExport_getImplementationName();
4028         case EXPORT_STYLES:
4029             return SchXMLExport_Styles_getImplementationName();
4030         case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS ):
4031             return SchXMLExport_Content_getImplementationName();
4032 //         case EXPORT_META:
4033 //             return SchXMLExport_Meta_getImplementationName();
4034 
4035         // Oasis format
4036         case ( EXPORT_ALL | EXPORT_OASIS ):
4037             return SchXMLExport_Oasis_getImplementationName();
4038         case ( EXPORT_STYLES | EXPORT_OASIS ):
4039             return SchXMLExport_Oasis_Styles_getImplementationName();
4040         case ( EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_FONTDECLS | EXPORT_OASIS  ):
4041             return SchXMLExport_Oasis_Content_getImplementationName();
4042         case ( EXPORT_META | EXPORT_OASIS ):
4043             return SchXMLExport_Oasis_Meta_getImplementationName();
4044 
4045         case EXPORT_SETTINGS:
4046         // there is no settings component in chart
4047         default:
4048             return OUString::createFromAscii( "SchXMLExport" );
4049     }
4050 }
4051