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