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_chart2.hxx"
26 #include "ChartDataWrapper.hxx"
27 #include "macros.hxx"
28 #include "DiagramHelper.hxx"
29 #include "DataSourceHelper.hxx"
30 #include "servicenames_charttypes.hxx"
31 #include "ContainerHelper.hxx"
32 #include "CommonFunctors.hxx"
33 #include "ChartModelHelper.hxx"
34 #include "DataSeriesHelper.hxx"
35 #include "ControllerLockGuard.hxx"
36 #include "Chart2ModelContact.hxx"
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <com/sun/star/chart2/XTitled.hpp>
39 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
40 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
41 #include <com/sun/star/chart2/data/XDataSource.hpp>
42 #include <com/sun/star/chart2/XDataSeries.hpp>
43 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
44 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
45 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
46 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
47 #include <com/sun/star/chart/ChartDataRowSource.hpp>
48 #include <com/sun/star/chart/XChartDocument.hpp>
49 
50 #include "CharacterProperties.hxx"
51 #include "LineProperties.hxx"
52 #include "FillProperties.hxx"
53 
54 #include <map>
55 #include <algorithm>
56 #include <rtl/math.hxx>
57 
58 using namespace ::com::sun::star;
59 using ::com::sun::star::uno::Reference;
60 using ::com::sun::star::uno::Sequence;
61 using ::rtl::OUString;
62 using ::osl::MutexGuard;
63 using ::com::sun::star::chart2::XAnyDescriptionAccess;
64 using ::com::sun::star::chart::XComplexDescriptionAccess;
65 using ::com::sun::star::chart::XChartData;
66 using ::com::sun::star::chart::XChartDataArray;
67 using ::com::sun::star::chart::XDateCategories;
68 
69 namespace
70 {
71 static const ::rtl::OUString lcl_aServiceName(
72     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.ChartData" ));
73 
lcl_getNANInsteadDBL_MIN(const uno::Sequence<uno::Sequence<double>> & rData)74 uno::Sequence< uno::Sequence< double > > lcl_getNANInsteadDBL_MIN( const uno::Sequence< uno::Sequence< double > >& rData )
75 {
76     uno::Sequence< uno::Sequence< double > > aRet;
77     const sal_Int32 nOuterSize = rData.getLength();
78     aRet.realloc( nOuterSize );
79     for( sal_Int32 nOuter=0; nOuter<nOuterSize; ++nOuter )
80     {
81         sal_Int32 nInnerSize = rData[nOuter].getLength();
82         aRet[nOuter].realloc( nInnerSize );
83         for( sal_Int32 nInner=0; nInner<nInnerSize; ++nInner )
84         {
85             aRet[nOuter][nInner] = rData[nOuter][nInner];
86             double& rValue = aRet[nOuter][nInner];
87             if( rValue == DBL_MIN )
88                 ::rtl::math::setNan( &rValue );
89         }
90     }
91     return aRet;
92 }
93 
lcl_getDBL_MINInsteadNAN(const uno::Sequence<uno::Sequence<double>> & rData)94 uno::Sequence< uno::Sequence< double > > lcl_getDBL_MINInsteadNAN( const uno::Sequence< uno::Sequence< double > >& rData )
95 {
96     uno::Sequence< uno::Sequence< double > > aRet;
97     const sal_Int32 nOuterSize = rData.getLength();
98     aRet.realloc( nOuterSize );
99     for( sal_Int32 nOuter=0; nOuter<nOuterSize; ++nOuter )
100     {
101         sal_Int32 nInnerSize = rData[nOuter].getLength();
102         aRet[nOuter].realloc( nInnerSize );
103         for( sal_Int32 nInner=0; nInner<nInnerSize; ++nInner )
104         {
105             aRet[nOuter][nInner] = rData[nOuter][nInner];
106             double& rValue = aRet[nOuter][nInner];
107             if( ::rtl::math::isNan( rValue ) )
108                 rValue = DBL_MIN;
109         }
110     }
111     return aRet;
112 }
113 
114 } // anonymous namespace
115 
116 // --------------------------------------------------------------------------------
117 
118 namespace chart
119 {
120 namespace wrapper
121 {
122 
123 //--------------------------------------------------------------------------------------
124 
125 struct lcl_Operator
126 {
lcl_Operatorchart::wrapper::lcl_Operator127     lcl_Operator()
128     {
129     }
~lcl_Operatorchart::wrapper::lcl_Operator130     virtual ~lcl_Operator()
131     {
132     }
133     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) = 0;
134 
setsCategorieschart::wrapper::lcl_Operator135     virtual bool setsCategories( bool /*bDataInColumns*/ )
136     {
137         return false;
138     }
139 };
140 
141 //--------------------------------------------------------------------------
142 
143 struct lcl_AllOperator : public lcl_Operator
144 {
lcl_AllOperatorchart::wrapper::lcl_AllOperator145     lcl_AllOperator( const Reference< XChartData >& xDataToApply )
146         : lcl_Operator()
147         , m_xDataToApply( xDataToApply )
148     {
149     }
150 
setsCategorieschart::wrapper::lcl_AllOperator151     virtual bool setsCategories( bool /*bDataInColumns*/ )
152     {
153         return true;
154     }
155 
applychart::wrapper::lcl_AllOperator156     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess )
157     {
158         if( !xDataAccess.is() )
159             return;
160 
161         Reference< XAnyDescriptionAccess > xNewAny( m_xDataToApply, uno::UNO_QUERY );
162         Reference< XComplexDescriptionAccess > xNewComplex( m_xDataToApply, uno::UNO_QUERY );
163         if( xNewAny.is() )
164         {
165             xDataAccess->setData( xNewAny->getData() );
166             xDataAccess->setComplexRowDescriptions( xNewAny->getComplexRowDescriptions() );
167             xDataAccess->setComplexColumnDescriptions( xNewAny->getComplexColumnDescriptions() );
168         }
169         else if( xNewComplex.is() )
170         {
171             xDataAccess->setData( xNewComplex->getData() );
172             xDataAccess->setComplexRowDescriptions( xNewComplex->getComplexRowDescriptions() );
173             xDataAccess->setComplexColumnDescriptions( xNewComplex->getComplexColumnDescriptions() );
174         }
175         else
176         {
177             Reference< XChartDataArray > xNew( m_xDataToApply, uno::UNO_QUERY );
178             if( xNew.is() )
179             {
180                 xDataAccess->setData( xNew->getData() );
181                 xDataAccess->setRowDescriptions( xNew->getRowDescriptions() );
182                 xDataAccess->setColumnDescriptions( xNew->getColumnDescriptions() );
183             }
184         }
185     }
186 
187     Reference< XChartData > m_xDataToApply;
188 };
189 
190 //--------------------------------------------------------------------------
191 
192 struct lcl_DataOperator : public lcl_Operator
193 {
lcl_DataOperatorchart::wrapper::lcl_DataOperator194     lcl_DataOperator( const Sequence< Sequence< double > >& rData )
195         : lcl_Operator()
196         , m_rData( rData )
197     {
198     }
199 
applychart::wrapper::lcl_DataOperator200     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess )
201     {
202         if( xDataAccess.is() )
203             xDataAccess->setData( lcl_getNANInsteadDBL_MIN( m_rData ) );
204     }
205 
206     const Sequence< Sequence< double > >& m_rData;
207 };
208 
209 //--------------------------------------------------------------------------
210 
211 struct lcl_RowDescriptionsOperator : public lcl_Operator
212 {
lcl_RowDescriptionsOperatorchart::wrapper::lcl_RowDescriptionsOperator213     lcl_RowDescriptionsOperator( const Sequence< OUString >& rRowDescriptions
214         , const Reference< chart2::XChartDocument >& xChartDoc )
215         : lcl_Operator()
216         , m_rRowDescriptions( rRowDescriptions )
217         , m_xChartDoc(xChartDoc)
218         , m_bDataInColumns(true)
219     {
220     }
221 
setsCategorieschart::wrapper::lcl_RowDescriptionsOperator222     virtual bool setsCategories( bool bDataInColumns )
223     {
224         m_bDataInColumns = bDataInColumns;
225         return bDataInColumns;
226     }
227 
applychart::wrapper::lcl_RowDescriptionsOperator228     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess )
229     {
230         if( xDataAccess.is() )
231         {
232             xDataAccess->setRowDescriptions( m_rRowDescriptions );
233             if( m_bDataInColumns )
234                 DiagramHelper::switchToTextCategories( m_xChartDoc );
235         }
236     }
237 
238     const Sequence< OUString >& m_rRowDescriptions;
239     Reference< chart2::XChartDocument > m_xChartDoc;
240     bool m_bDataInColumns;
241 };
242 
243 //--------------------------------------------------------------------------
244 
245 struct lcl_ComplexRowDescriptionsOperator : public lcl_Operator
246 {
lcl_ComplexRowDescriptionsOperatorchart::wrapper::lcl_ComplexRowDescriptionsOperator247     lcl_ComplexRowDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexRowDescriptions
248         , const Reference< chart2::XChartDocument >& xChartDoc )
249         : lcl_Operator()
250         , m_rComplexRowDescriptions( rComplexRowDescriptions )
251         , m_xChartDoc(xChartDoc)
252         , m_bDataInColumns(true)
253     {
254     }
255 
setsCategorieschart::wrapper::lcl_ComplexRowDescriptionsOperator256     virtual bool setsCategories( bool bDataInColumns )
257     {
258         m_bDataInColumns = bDataInColumns;
259         return bDataInColumns;
260     }
261 
applychart::wrapper::lcl_ComplexRowDescriptionsOperator262     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess )
263     {
264         if( xDataAccess.is() )
265         {
266             xDataAccess->setComplexRowDescriptions( m_rComplexRowDescriptions );
267             if( m_bDataInColumns )
268                 DiagramHelper::switchToTextCategories( m_xChartDoc );
269         }
270     }
271 
272     const Sequence< Sequence< OUString > >& m_rComplexRowDescriptions;
273     Reference< chart2::XChartDocument > m_xChartDoc;
274     bool m_bDataInColumns;
275 };
276 //--------------------------------------------------------------------------
277 
278 struct lcl_AnyRowDescriptionsOperator : public lcl_Operator
279 {
lcl_AnyRowDescriptionsOperatorchart::wrapper::lcl_AnyRowDescriptionsOperator280     lcl_AnyRowDescriptionsOperator( const Sequence< Sequence< uno::Any > >& rAnyRowDescriptions )
281         : lcl_Operator()
282         , m_rAnyRowDescriptions( rAnyRowDescriptions )
283     {
284     }
285 
setsCategorieschart::wrapper::lcl_AnyRowDescriptionsOperator286     virtual bool setsCategories( bool bDataInColumns )
287     {
288         return bDataInColumns;
289     }
290 
applychart::wrapper::lcl_AnyRowDescriptionsOperator291     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess )
292     {
293         if( xDataAccess.is() )
294             xDataAccess->setAnyRowDescriptions( m_rAnyRowDescriptions );
295     }
296 
297     const Sequence< Sequence< uno::Any > >& m_rAnyRowDescriptions;
298 };
299 
300 //--------------------------------------------------------------------------
301 
302 struct lcl_ColumnDescriptionsOperator : public lcl_Operator
303 {
lcl_ColumnDescriptionsOperatorchart::wrapper::lcl_ColumnDescriptionsOperator304     lcl_ColumnDescriptionsOperator( const Sequence< OUString >& rColumnDescriptions
305         , const Reference< chart2::XChartDocument >& xChartDoc )
306         : lcl_Operator()
307         , m_rColumnDescriptions( rColumnDescriptions )
308         , m_xChartDoc(xChartDoc)
309         , m_bDataInColumns(true)
310     {
311     }
312 
setsCategorieschart::wrapper::lcl_ColumnDescriptionsOperator313     virtual bool setsCategories( bool bDataInColumns )
314     {
315         m_bDataInColumns = bDataInColumns;
316         return !bDataInColumns;
317     }
318 
applychart::wrapper::lcl_ColumnDescriptionsOperator319     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess )
320     {
321         if( xDataAccess.is() )
322         {
323             xDataAccess->setColumnDescriptions( m_rColumnDescriptions );
324             if( !m_bDataInColumns )
325                 DiagramHelper::switchToTextCategories( m_xChartDoc );
326         }
327     }
328 
329     const Sequence< OUString >& m_rColumnDescriptions;
330     Reference< chart2::XChartDocument > m_xChartDoc;
331     bool m_bDataInColumns;
332 };
333 
334 //--------------------------------------------------------------------------
335 
336 struct lcl_ComplexColumnDescriptionsOperator : public lcl_Operator
337 {
lcl_ComplexColumnDescriptionsOperatorchart::wrapper::lcl_ComplexColumnDescriptionsOperator338     lcl_ComplexColumnDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexColumnDescriptions
339         , const Reference< chart2::XChartDocument >& xChartDoc )
340         : lcl_Operator()
341         , m_rComplexColumnDescriptions( rComplexColumnDescriptions )
342         , m_xChartDoc(xChartDoc)
343         , m_bDataInColumns(true)
344     {
345     }
346 
setsCategorieschart::wrapper::lcl_ComplexColumnDescriptionsOperator347     virtual bool setsCategories( bool bDataInColumns )
348     {
349         m_bDataInColumns = bDataInColumns;
350         return !bDataInColumns;
351     }
352 
applychart::wrapper::lcl_ComplexColumnDescriptionsOperator353     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess )
354     {
355         if( xDataAccess.is() )
356         {
357             xDataAccess->setComplexColumnDescriptions( m_rComplexColumnDescriptions );
358             if( !m_bDataInColumns )
359                 DiagramHelper::switchToTextCategories( m_xChartDoc );
360         }
361     }
362 
363     const Sequence< Sequence< OUString > >& m_rComplexColumnDescriptions;
364     Reference< chart2::XChartDocument > m_xChartDoc;
365     bool m_bDataInColumns;
366 };
367 
368 //--------------------------------------------------------------------------
369 
370 struct lcl_AnyColumnDescriptionsOperator : public lcl_Operator
371 {
lcl_AnyColumnDescriptionsOperatorchart::wrapper::lcl_AnyColumnDescriptionsOperator372     lcl_AnyColumnDescriptionsOperator( const Sequence< Sequence< uno::Any > >& rAnyColumnDescriptions )
373         : lcl_Operator()
374         , m_rAnyColumnDescriptions( rAnyColumnDescriptions )
375     {
376     }
377 
setsCategorieschart::wrapper::lcl_AnyColumnDescriptionsOperator378     virtual bool setsCategories( bool bDataInColumns )
379     {
380         return bDataInColumns;
381     }
382 
applychart::wrapper::lcl_AnyColumnDescriptionsOperator383     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess )
384     {
385         if( xDataAccess.is() )
386             xDataAccess->setAnyColumnDescriptions( m_rAnyColumnDescriptions );
387     }
388 
389     const Sequence< Sequence< uno::Any > >& m_rAnyColumnDescriptions;
390 };
391 
392 //--------------------------------------------------------------------------
393 
394 struct lcl_DateCategoriesOperator : public lcl_Operator
395 {
lcl_DateCategoriesOperatorchart::wrapper::lcl_DateCategoriesOperator396     lcl_DateCategoriesOperator( const Sequence< double >& rDates )
397         : lcl_Operator()
398         , m_rDates( rDates )
399     {
400     }
401 
setsCategorieschart::wrapper::lcl_DateCategoriesOperator402     virtual bool setsCategories( bool /*bDataInColumns*/ )
403     {
404         return true;
405     }
406 
applychart::wrapper::lcl_DateCategoriesOperator407     virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess )
408     {
409         Reference< XDateCategories > xDateCategories( xDataAccess, uno::UNO_QUERY );
410         if( xDateCategories.is() )
411             xDateCategories->setDateCategories( m_rDates );
412     }
413 
414     const Sequence< double >& m_rDates;
415 };
416 
417 //--------------------------------------------------------------------------
418 
ChartDataWrapper(::boost::shared_ptr<Chart2ModelContact> spChart2ModelContact)419 ChartDataWrapper::ChartDataWrapper( ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact ) :
420         m_spChart2ModelContact( spChart2ModelContact ),
421         m_aEventListenerContainer( m_aMutex )
422 {
423     osl_incrementInterlockedCount( &m_refCount );
424     initDataAccess();
425     osl_decrementInterlockedCount( &m_refCount );
426 }
427 
ChartDataWrapper(::boost::shared_ptr<Chart2ModelContact> spChart2ModelContact,const Reference<XChartData> & xNewData)428 ChartDataWrapper::ChartDataWrapper( ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact,
429                                     const Reference< XChartData >& xNewData ) :
430         m_spChart2ModelContact( spChart2ModelContact ),
431         m_aEventListenerContainer( m_aMutex )
432 {
433     osl_incrementInterlockedCount( &m_refCount );
434     lcl_AllOperator aOperator( xNewData );
435     applyData( aOperator );
436     osl_decrementInterlockedCount( &m_refCount );
437 }
438 
~ChartDataWrapper()439 ChartDataWrapper::~ChartDataWrapper()
440 {
441     // @todo: implement XComponent and call this in dispose().  In the DTOR the
442     // ref-count is 0, thus creating a stack reference to this calls the DTOR at
443     // the end of the block recursively
444 //     uno::Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
445 //     m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) );
446 }
447 
448 // ____ XChartDataArray (read)____
getData()449 Sequence< Sequence< double > > SAL_CALL ChartDataWrapper::getData()
450     throw (uno::RuntimeException)
451 {
452     initDataAccess();
453     if( m_xDataAccess.is() )
454         return lcl_getDBL_MINInsteadNAN( m_xDataAccess->getData() );
455     return Sequence< Sequence< double > >();
456 }
getRowDescriptions()457 Sequence< OUString > SAL_CALL ChartDataWrapper::getRowDescriptions()
458     throw (uno::RuntimeException)
459 {
460     initDataAccess();
461     if( m_xDataAccess.is() )
462         return m_xDataAccess->getRowDescriptions();
463     return Sequence< OUString >();
464 }
getColumnDescriptions()465 Sequence< OUString > SAL_CALL ChartDataWrapper::getColumnDescriptions()
466     throw (uno::RuntimeException)
467 {
468     initDataAccess();
469     if( m_xDataAccess.is() )
470         return m_xDataAccess->getColumnDescriptions();
471     return Sequence< OUString > ();
472 }
473 
474 // ____ XComplexDescriptionAccess (read) ____
getComplexRowDescriptions()475 Sequence< Sequence< OUString > > SAL_CALL ChartDataWrapper::getComplexRowDescriptions() throw (uno::RuntimeException)
476 {
477     initDataAccess();
478     if( m_xDataAccess.is() )
479         return m_xDataAccess->getComplexRowDescriptions();
480     return Sequence< Sequence< OUString > >();
481 }
getComplexColumnDescriptions()482 Sequence< Sequence< OUString > > SAL_CALL ChartDataWrapper::getComplexColumnDescriptions() throw (uno::RuntimeException)
483 {
484     initDataAccess();
485     if( m_xDataAccess.is() )
486         return m_xDataAccess->getComplexColumnDescriptions();
487     return Sequence< Sequence< OUString > >();
488 }
489 
490 // ____ XAnyDescriptionAccess (read) ____
getAnyRowDescriptions()491 Sequence< Sequence< uno::Any > > SAL_CALL ChartDataWrapper::getAnyRowDescriptions() throw (uno::RuntimeException)
492 {
493     initDataAccess();
494     if( m_xDataAccess.is() )
495         return m_xDataAccess->getAnyRowDescriptions();
496     return Sequence< Sequence< uno::Any > >();
497 }
getAnyColumnDescriptions()498 Sequence< Sequence< uno::Any > > SAL_CALL ChartDataWrapper::getAnyColumnDescriptions() throw (uno::RuntimeException)
499 {
500     initDataAccess();
501     if( m_xDataAccess.is() )
502         return m_xDataAccess->getAnyColumnDescriptions();
503     return Sequence< Sequence< uno::Any > >();
504 }
505 
506 // ____ XDateCategories (read) ____
getDateCategories()507 Sequence< double > SAL_CALL ChartDataWrapper::getDateCategories() throw (uno::RuntimeException)
508 {
509     initDataAccess();
510     Reference< XDateCategories > xDateCategories( m_xDataAccess, uno::UNO_QUERY );
511     if( xDateCategories.is() )
512         return xDateCategories->getDateCategories();
513     return Sequence< double >();
514 }
515 
516 // ____ XChartDataArray (write)____
setData(const Sequence<Sequence<double>> & rData)517 void SAL_CALL ChartDataWrapper::setData( const Sequence< Sequence< double > >& rData )
518     throw (uno::RuntimeException)
519 {
520     lcl_DataOperator aOperator( rData );
521     applyData( aOperator );
522 }
setRowDescriptions(const Sequence<OUString> & rRowDescriptions)523 void SAL_CALL ChartDataWrapper::setRowDescriptions( const Sequence< OUString >& rRowDescriptions )
524     throw (uno::RuntimeException)
525 {
526     lcl_RowDescriptionsOperator aOperator( rRowDescriptions, m_spChart2ModelContact->getChart2Document() );
527     applyData( aOperator );
528 }
setColumnDescriptions(const Sequence<OUString> & rColumnDescriptions)529 void SAL_CALL ChartDataWrapper::setColumnDescriptions( const Sequence< OUString >& rColumnDescriptions )
530     throw (uno::RuntimeException)
531 {
532     lcl_ColumnDescriptionsOperator aOperator( rColumnDescriptions, m_spChart2ModelContact->getChart2Document() );
533     applyData( aOperator );
534 }
535 
536 // ____ XComplexDescriptionAccess (write) ____
setComplexRowDescriptions(const Sequence<Sequence<::rtl::OUString>> & rRowDescriptions)537 void SAL_CALL ChartDataWrapper::setComplexRowDescriptions( const Sequence< Sequence< ::rtl::OUString > >& rRowDescriptions ) throw (uno::RuntimeException)
538 {
539     lcl_ComplexRowDescriptionsOperator aOperator( rRowDescriptions, m_spChart2ModelContact->getChart2Document() );
540     applyData( aOperator );
541 }
setComplexColumnDescriptions(const Sequence<Sequence<::rtl::OUString>> & rColumnDescriptions)542 void SAL_CALL ChartDataWrapper::setComplexColumnDescriptions( const Sequence< Sequence< ::rtl::OUString > >& rColumnDescriptions ) throw (uno::RuntimeException)
543 {
544     lcl_ComplexColumnDescriptionsOperator aOperator( rColumnDescriptions, m_spChart2ModelContact->getChart2Document() );
545     applyData( aOperator );
546 }
547 
548 // ____ XAnyDescriptionAccess (write) ____
setAnyRowDescriptions(const Sequence<Sequence<uno::Any>> & rRowDescriptions)549 void SAL_CALL ChartDataWrapper::setAnyRowDescriptions( const Sequence< Sequence< uno::Any > >& rRowDescriptions ) throw (uno::RuntimeException)
550 {
551     lcl_AnyRowDescriptionsOperator aOperator( rRowDescriptions );
552     applyData( aOperator );
553 }
setAnyColumnDescriptions(const Sequence<Sequence<uno::Any>> & rColumnDescriptions)554 void SAL_CALL ChartDataWrapper::setAnyColumnDescriptions( const Sequence< Sequence< uno::Any > >& rColumnDescriptions ) throw (uno::RuntimeException)
555 {
556     lcl_AnyColumnDescriptionsOperator aOperator( rColumnDescriptions );
557     applyData( aOperator );
558 }
559 
560 // ____ XDateCategories (write) ____
setDateCategories(const Sequence<double> & rDates)561 void SAL_CALL ChartDataWrapper::setDateCategories( const Sequence< double >& rDates ) throw (uno::RuntimeException)
562 {
563     Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() );
564     ControllerLockGuard aCtrlLockGuard( uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ));
565     lcl_DateCategoriesOperator aOperator( rDates );
566     applyData( aOperator );
567     DiagramHelper::switchToDateCategories( xChartDoc );
568 }
569 
570 //--------------------------------------------------------------------------------------
571 
572 // ____ XChartData (base of XChartDataArray) ____
addChartDataChangeEventListener(const uno::Reference<::com::sun::star::chart::XChartDataChangeEventListener> & aListener)573 void SAL_CALL ChartDataWrapper::addChartDataChangeEventListener(
574     const uno::Reference<
575         ::com::sun::star::chart::XChartDataChangeEventListener >& aListener )
576     throw (uno::RuntimeException)
577 {
578     m_aEventListenerContainer.addInterface( aListener );
579 }
580 
removeChartDataChangeEventListener(const uno::Reference<::com::sun::star::chart::XChartDataChangeEventListener> & aListener)581 void SAL_CALL ChartDataWrapper::removeChartDataChangeEventListener(
582     const uno::Reference<
583         ::com::sun::star::chart::XChartDataChangeEventListener >& aListener )
584     throw (uno::RuntimeException)
585 {
586     m_aEventListenerContainer.removeInterface( aListener );
587 }
588 
getNotANumber()589 double SAL_CALL ChartDataWrapper::getNotANumber()
590     throw (uno::RuntimeException)
591 {
592     return DBL_MIN;
593 }
594 
isNotANumber(double nNumber)595 sal_Bool SAL_CALL ChartDataWrapper::isNotANumber( double nNumber )
596     throw (uno::RuntimeException)
597 {
598     return DBL_MIN == nNumber
599         || ::rtl::math::isNan( nNumber )
600         || ::rtl::math::isInf( nNumber );
601 }
602 
603 // ____ XComponent ____
dispose()604 void SAL_CALL ChartDataWrapper::dispose()
605     throw (uno::RuntimeException)
606 {
607     m_aEventListenerContainer.disposeAndClear( lang::EventObject( static_cast< ::cppu::OWeakObject* >( this )));
608     m_xDataAccess=0;
609 }
610 
addEventListener(const uno::Reference<lang::XEventListener> & xListener)611 void SAL_CALL ChartDataWrapper::addEventListener(
612     const uno::Reference< lang::XEventListener > & xListener )
613     throw (uno::RuntimeException)
614 {
615 	m_aEventListenerContainer.addInterface( xListener );
616 }
617 
removeEventListener(const uno::Reference<lang::XEventListener> & aListener)618 void SAL_CALL ChartDataWrapper::removeEventListener(
619     const uno::Reference< lang::XEventListener >& aListener )
620     throw (uno::RuntimeException)
621 {
622 	m_aEventListenerContainer.removeInterface( aListener );
623 }
624 
625 // ____ XEventListener ____
disposing(const lang::EventObject &)626 void SAL_CALL ChartDataWrapper::disposing( const lang::EventObject& /* Source */ )
627     throw (uno::RuntimeException)
628 {
629 }
630 
631 //  ::com::sun::star::chart::ChartDataChangeEvent aEvent;
632 //  aEvent.Type = chart::ChartDataChangeType_ALL;
633 //  aEvent.StartColumn = 0;
634 //  aEvent.EndColumn = 0;
635 //  aEvent.StartRow = 0;
636 //  aEvent.EndRow = 0;
fireChartDataChangeEvent(::com::sun::star::chart::ChartDataChangeEvent & aEvent)637 void ChartDataWrapper::fireChartDataChangeEvent(
638     ::com::sun::star::chart::ChartDataChangeEvent& aEvent )
639 {
640     if( ! m_aEventListenerContainer.getLength() )
641         return;
642 
643     uno::Reference< uno::XInterface > xSrc( static_cast< cppu::OWeakObject* >( this ));
644     OSL_ASSERT( xSrc.is());
645     if( xSrc.is() )
646         aEvent.Source = xSrc;
647 
648     ::cppu::OInterfaceIteratorHelper aIter( m_aEventListenerContainer );
649 
650     while( aIter.hasMoreElements() )
651     {
652         uno::Reference<
653             ::com::sun::star::chart::XChartDataChangeEventListener > xListener(
654                 aIter.next(), uno::UNO_QUERY );
655         if( xListener.is() )
656             xListener->chartDataChanged( aEvent );
657     }
658 }
659 
660 // --------------------------------------------------------------------------------
661 
switchToInternalDataProvider()662 void ChartDataWrapper::switchToInternalDataProvider()
663 {
664     //create an internal data provider that is connected to the model
665     Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() );
666     if( xChartDoc.is() )
667         xChartDoc->createInternalDataProvider( true /*bCloneExistingData*/ );
668     initDataAccess();
669 }
670 
initDataAccess()671 void ChartDataWrapper::initDataAccess()
672 {
673     Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() );
674     if( !xChartDoc.is() )
675         return;
676     if( xChartDoc->hasInternalDataProvider() )
677         m_xDataAccess = Reference< XAnyDescriptionAccess >( xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW );
678     else
679     {
680         //create a separate "internal data provider" that is not connected to the model
681         m_xDataAccess = Reference< XAnyDescriptionAccess >( ChartModelHelper::createInternalDataProvider(
682             xChartDoc, false /*bConnectToModel*/ ), uno::UNO_QUERY_THROW );
683     }
684 }
685 
applyData(lcl_Operator & rDataOperator)686 void ChartDataWrapper::applyData( lcl_Operator& rDataOperator )
687 {
688     //bool bSetValues, bool bSetRowDescriptions, bool bSetColumnDescriptions
689     Reference< chart2::XChartDocument > xChartDoc( m_spChart2ModelContact->getChart2Document() );
690     if( !xChartDoc.is() )
691         return;
692 
693     // remember some diagram properties to reset later
694     sal_Bool bStacked = sal_False;
695     sal_Bool bPercent = sal_False;
696     sal_Bool bDeep = sal_False;
697     uno::Reference< ::com::sun::star::chart::XChartDocument > xOldDoc( xChartDoc, uno::UNO_QUERY );
698     OSL_ASSERT( xOldDoc.is());
699     uno::Reference< beans::XPropertySet > xDiaProp( xOldDoc->getDiagram(), uno::UNO_QUERY );
700     if( xDiaProp.is())
701     {
702         xDiaProp->getPropertyValue( C2U("Stacked")) >>= bStacked;
703         xDiaProp->getPropertyValue( C2U("Percent")) >>= bPercent;
704         xDiaProp->getPropertyValue( C2U("Deep")) >>= bDeep;
705     }
706 
707     //detect arguments for the new data source
708     ::rtl::OUString aRangeString;
709     bool bUseColumns = true;
710     bool bFirstCellAsLabel = true;
711     bool bHasCategories = true;
712     uno::Sequence< sal_Int32 > aSequenceMapping;
713 
714     DataSourceHelper::detectRangeSegmentation(
715         uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ),
716         aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories );
717 
718     if( !bHasCategories && rDataOperator.setsCategories( bUseColumns ) )
719         bHasCategories = true;
720 
721     aRangeString = C2U("all");
722     uno::Sequence< beans::PropertyValue > aArguments( DataSourceHelper::createArguments(
723             aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ) );
724 
725 
726     // /-- locked controllers
727     ControllerLockGuard aCtrlLockGuard( uno::Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ));
728 
729     // create and attach new data source
730     switchToInternalDataProvider();
731     rDataOperator.apply(m_xDataAccess);
732     uno::Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
733     OSL_ASSERT( xDataProvider.is() );
734     if( !xDataProvider.is() )
735         return;
736     uno::Reference< chart2::data::XDataSource > xSource( xDataProvider->createDataSource( aArguments ) );
737 
738     uno::Reference< chart2::XDiagram > xDia( xChartDoc->getFirstDiagram() );
739     if( xDia.is() )
740         xDia->setDiagramData( xSource, aArguments );
741 
742     //correct stacking mode
743     if( bStacked || bPercent || bDeep )
744     {
745         StackMode eStackMode = StackMode_Y_STACKED;
746         if( bDeep )
747             eStackMode = StackMode_Z_STACKED;
748         else if( bPercent )
749             eStackMode = StackMode_Y_STACKED_PERCENT;
750         DiagramHelper::setStackMode( xDia, eStackMode );
751     }
752 
753     // notify listeners
754     ::com::sun::star::chart::ChartDataChangeEvent aEvent(
755         static_cast< ::cppu::OWeakObject* >( this ),
756         ::com::sun::star::chart::ChartDataChangeType_ALL, 0, 0, 0, 0 );
757     fireChartDataChangeEvent( aEvent );
758     // \-- locked controllers
759 }
760 
761 // --------------------------------------------------------------------------------
762 
getSupportedServiceNames_Static()763 uno::Sequence< ::rtl::OUString > ChartDataWrapper::getSupportedServiceNames_Static()
764 {
765     uno::Sequence< ::rtl::OUString > aServices( 2 );
766     aServices[ 0 ] = C2U( "com.sun.star.chart.ChartDataArray" );
767     aServices[ 1 ] = C2U( "com.sun.star.chart.ChartData" );
768 
769     return aServices;
770 }
771 
772 // ================================================================================
773 
774 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
775 APPHELPER_XSERVICEINFO_IMPL( ChartDataWrapper, lcl_aServiceName );
776 
777 } //  namespace wrapper
778 } //  namespace chart
779