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