merge the formfield patch from ooo-build
[ooovba.git] / chart2 / source / controller / dialogs / DataBrowserModel.cxx
blobea396003786cf1b1dd5657b164ffaea1665b9a11
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DataBrowserModel.cxx,v $
10 * $Revision: 1.6.16.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
34 #include "DataBrowserModel.hxx"
35 #include "DialogModel.hxx"
36 #include "ChartModelHelper.hxx"
37 #include "DiagramHelper.hxx"
38 #include "DataSeriesHelper.hxx"
39 #include "PropertyHelper.hxx"
40 #include "ControllerLockGuard.hxx"
41 #include "macros.hxx"
42 #include "StatisticsHelper.hxx"
43 #include "ContainerHelper.hxx"
44 #include "ChartTypeHelper.hxx"
45 #include "chartview/ExplicitValueProvider.hxx"
47 #include <com/sun/star/container/XIndexReplace.hpp>
48 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
49 #include <com/sun/star/chart2/XInternalDataProvider.hpp>
50 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
51 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
52 #include <com/sun/star/chart2/data/XDataSource.hpp>
53 #include <com/sun/star/chart2/data/XDataSink.hpp>
54 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
55 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
56 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
58 #include <rtl/math.hxx>
60 #include <algorithm>
62 #if OSL_DEBUG_LEVEL > 1
63 #include <cstdio>
64 #endif
66 using namespace ::com::sun::star;
68 using ::com::sun::star::uno::Reference;
69 using ::com::sun::star::uno::Sequence;
70 using ::rtl::OUString;
72 namespace
74 OUString lcl_getRole(
75 const Reference< chart2::data::XDataSequence > & xSeq )
77 OUString aResult;
78 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
79 if( xProp.is())
81 try
83 xProp->getPropertyValue( C2U("Role")) >>= aResult;
85 catch( const uno::Exception & ex )
87 ASSERT_EXCEPTION( ex );
90 return aResult;
94 OUString lcl_getRole(
95 const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
97 OUString aResult;
98 if( xLSeq.is())
99 aResult = lcl_getRole( xLSeq->getValues());
100 return aResult;
103 OUString lcl_getUIRoleName(
104 const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
106 OUString aResult( lcl_getRole( xLSeq ));
107 if( aResult.getLength())
108 aResult = ::chart::DialogModel::ConvertRoleFromInternalToUI( aResult );
109 return aResult;
112 void lcl_copyDataSequenceProperties(
113 const Reference< chart2::data::XDataSequence > & xOldSequence,
114 const Reference< chart2::data::XDataSequence > & xNewSequence )
116 Reference< beans::XPropertySet > xOldSeqProp( xOldSequence, uno::UNO_QUERY );
117 Reference< beans::XPropertySet > xNewSeqProp( xNewSequence, uno::UNO_QUERY );
118 comphelper::copyProperties( xOldSeqProp, xNewSeqProp );
121 bool lcl_SequenceOfSeriesIsShared(
122 const Reference< chart2::XDataSeries > & xSeries,
123 const Reference< chart2::data::XDataSequence > & xValues )
125 bool bResult = false;
126 if( !xValues.is())
127 return bResult;
130 OUString aValuesRole( lcl_getRole( xValues ));
131 OUString aValuesRep( xValues->getSourceRangeRepresentation());
132 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW );
133 Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences());
134 for( sal_Int32 i=0; i<aLSeq.getLength(); ++i )
135 if( aLSeq[i].is() &&
136 lcl_getRole( aLSeq[i] ).equals( aValuesRole ))
138 // getValues().is(), because lcl_getRole checked that already
139 bResult = (aValuesRep == aLSeq[i]->getValues()->getSourceRangeRepresentation());
140 // assumption: a role appears only once in a series
141 break;
144 catch( const uno::Exception & ex )
146 ASSERT_EXCEPTION( ex );
148 return bResult;
151 typedef ::std::vector< Reference< chart2::data::XLabeledDataSequence > > lcl_tSharedSeqVec;
153 lcl_tSharedSeqVec lcl_getSharedSequences( const Sequence< Reference< chart2::XDataSeries > > & rSeries )
155 // @todo: if only some series share a sequence, those have to be duplicated
156 // and made unshared for all series
157 lcl_tSharedSeqVec aResult;
158 // if we have only one series, we don't want any shared sequences
159 if( rSeries.getLength() <= 1 )
160 return aResult;
162 Reference< chart2::data::XDataSource > xSource( rSeries[0], uno::UNO_QUERY );
163 Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences());
164 for( sal_Int32 nIdx=0; nIdx<aLSeq.getLength(); ++nIdx )
166 Reference< chart2::data::XDataSequence > xValues( aLSeq[nIdx]->getValues());
167 bool bShared = true;
168 for( sal_Int32 nSeriesIdx=1; nSeriesIdx<rSeries.getLength(); ++nSeriesIdx )
170 bShared = lcl_SequenceOfSeriesIsShared( rSeries[nSeriesIdx], xValues );
171 if( !bShared )
172 break;
174 if( bShared )
175 aResult.push_back( aLSeq[nIdx] );
178 return aResult;
181 sal_Int32 lcl_getValuesRepresentationIndex(
182 const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
184 sal_Int32 nResult = -1;
185 if( xLSeq.is())
187 Reference< chart2::data::XDataSequence > xSeq( xLSeq->getValues());
188 if( xSeq.is())
190 OUString aRep( xSeq->getSourceRangeRepresentation());
191 nResult = aRep.toInt32();
194 return nResult;
197 struct lcl_RepresentationsOfLSeqMatch : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
199 lcl_RepresentationsOfLSeqMatch( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) :
200 m_aValuesRep( xLSeq.is() ?
201 (xLSeq->getValues().is() ? xLSeq->getValues()->getSourceRangeRepresentation() : OUString())
202 : OUString() )
204 bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
206 return (xLSeq.is() &&
207 xLSeq->getValues().is() &&
208 (xLSeq->getValues()->getSourceRangeRepresentation() == m_aValuesRep ));
210 private:
211 OUString m_aValuesRep;
214 struct lcl_RolesOfLSeqMatch : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
216 lcl_RolesOfLSeqMatch( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) :
217 m_aRole( lcl_getRole( xLSeq ))
219 bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
221 return lcl_getRole( xLSeq ).equals( m_aRole );
223 private:
224 OUString m_aRole;
227 bool lcl_ShowCategories( const Reference< chart2::XDiagram > & /* xDiagram */ )
229 // show categories for all charts
230 return true;
231 // return DiagramHelper::isCategoryDiagram( xDiagram );
234 bool lcl_ShowCategoriesAsDataLabel( const Reference< chart2::XDiagram > & xDiagram )
236 return ! ::chart::DiagramHelper::isCategoryDiagram( xDiagram );
239 } // anonymous namespace
241 namespace chart
245 struct DataBrowserModel::tDataColumn
247 ::com::sun::star::uno::Reference<
248 ::com::sun::star::chart2::XDataSeries > m_xDataSeries;
249 sal_Int32 m_nIndexInDataSeries;
250 ::rtl::OUString m_aUIRoleName;
251 ::com::sun::star::uno::Reference<
252 ::com::sun::star::chart2::data::XLabeledDataSequence > m_xLabeledDataSequence;
253 eCellType m_eCellType;
254 sal_Int32 m_nNumberFormatKey;
256 // default CTOR
257 tDataColumn() : m_nIndexInDataSeries( -1 ), m_eCellType( TEXT ), m_nNumberFormatKey( 0 ) {}
258 // "full" CTOR
259 tDataColumn(
260 const ::com::sun::star::uno::Reference<
261 ::com::sun::star::chart2::XDataSeries > & xDataSeries,
262 sal_Int32 nIndexInDataSeries,
263 ::rtl::OUString aUIRoleName,
264 ::com::sun::star::uno::Reference<
265 ::com::sun::star::chart2::data::XLabeledDataSequence > xLabeledDataSequence,
266 eCellType aCellType,
267 sal_Int32 nNumberFormatKey ) :
268 m_xDataSeries( xDataSeries ),
269 m_nIndexInDataSeries( nIndexInDataSeries ),
270 m_aUIRoleName( aUIRoleName ),
271 m_xLabeledDataSequence( xLabeledDataSequence ),
272 m_eCellType( aCellType ),
273 m_nNumberFormatKey( nNumberFormatKey )
277 struct DataBrowserModel::implColumnLess : public ::std::binary_function<
278 DataBrowserModel::tDataColumn, DataBrowserModel::tDataColumn, bool >
280 bool operator() ( const first_argument_type & rLeft, const second_argument_type & rRight )
282 if( rLeft.m_xLabeledDataSequence.is() && rRight.m_xLabeledDataSequence.is())
284 return DialogModel::GetRoleIndexForSorting( lcl_getRole( rLeft.m_xLabeledDataSequence )) <
285 DialogModel::GetRoleIndexForSorting( lcl_getRole( rRight.m_xLabeledDataSequence ));
287 return true;
291 DataBrowserModel::DataBrowserModel(
292 const Reference< chart2::XChartDocument > & xChartDoc,
293 const Reference< uno::XComponentContext > & xContext ) :
294 m_xChartDocument( xChartDoc ),
295 m_xContext( xContext ),
296 m_apDialogModel( new DialogModel( xChartDoc, xContext ))
298 updateFromModel();
301 DataBrowserModel::~DataBrowserModel()
304 namespace
306 struct lcl_DataSeriesOfHeaderMatches : public ::std::unary_function< ::chart::DataBrowserModel::tDataHeader, bool >
308 lcl_DataSeriesOfHeaderMatches(
309 const Reference< chart2::XDataSeries > & xSeriesToCompareWith ) :
310 m_xSeries( xSeriesToCompareWith )
312 bool operator() ( const ::chart::DataBrowserModel::tDataHeader & rHeader )
314 return (m_xSeries == rHeader.m_xDataSeries);
316 private:
317 Reference< chart2::XDataSeries > m_xSeries;
321 void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex )
323 OSL_ASSERT( m_apDialogModel.get());
324 Reference< chart2::XInternalDataProvider > xDataProvider(
325 m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
326 if( xDataProvider.is())
328 sal_Int32 nStartCol = 0;
329 Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDocument ));
330 Reference< chart2::XChartType > xChartType;
331 Reference< chart2::XDataSeries > xSeries;
332 if( static_cast< tDataColumnVector::size_type >( nAfterColumnIndex ) <= m_aColumns.size())
333 xSeries.set( m_aColumns[nAfterColumnIndex].m_xDataSeries );
335 sal_Int32 nSeriesNumberFormat = 0;
336 if( xSeries.is())
338 xChartType.set( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ));
339 tDataHeaderVector::const_iterator aIt(
340 ::std::find_if( m_aHeaders.begin(), m_aHeaders.end(),
341 lcl_DataSeriesOfHeaderMatches( xSeries )));
342 if( aIt != m_aHeaders.end())
343 nStartCol = aIt->m_nEndColumn;
345 Reference< beans::XPropertySet > xSeriesProps( xSeries, uno::UNO_QUERY );
346 if( xSeriesProps.is() )
347 xSeriesProps->getPropertyValue( C2U( "NumberFormat" )) >>= nSeriesNumberFormat;
349 else
351 xChartType.set( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ));
352 nStartCol = nAfterColumnIndex;
355 if( xChartType.is())
357 sal_Int32 nOffset = 0;
358 if( xDiagram.is() && lcl_ShowCategories( xDiagram ))
359 ++nOffset;
360 // get shared sequences of current series
361 Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY );
362 lcl_tSharedSeqVec aSharedSequences;
363 if( xSeriesCnt.is())
364 aSharedSequences = lcl_getSharedSequences( xSeriesCnt->getDataSeries());
365 Reference< chart2::XDataSeries > xNewSeries(
366 m_apDialogModel->insertSeriesAfter( xSeries, xChartType, true /* bCreateDataCachedSequences */ ));
367 if( xNewSeries.is())
370 Reference< chart2::data::XDataSource > xSource( xNewSeries, uno::UNO_QUERY );
371 if( xSource.is())
373 Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSequences(
374 xSource->getDataSequences());
375 sal_Int32 nSeqIdx = 0;
376 sal_Int32 nSeqSize = aLSequences.getLength();
377 nStartCol -= (nOffset - 1);
378 for( sal_Int32 nIndex = nStartCol;
379 (nSeqIdx < nSeqSize);
380 ++nSeqIdx )
382 lcl_tSharedSeqVec::const_iterator aSharedIt(
383 ::std::find_if( aSharedSequences.begin(), aSharedSequences.end(),
384 lcl_RolesOfLSeqMatch( aLSequences[nSeqIdx] )));
385 if( aSharedIt != aSharedSequences.end())
387 aLSequences[nSeqIdx]->setValues( (*aSharedIt)->getValues());
388 aLSequences[nSeqIdx]->setLabel( (*aSharedIt)->getLabel());
390 else
392 xDataProvider->insertSequence( nIndex - 1 );
394 // values
395 Reference< chart2::data::XDataSequence > xNewSeq(
396 xDataProvider->createDataSequenceByRangeRepresentation(
397 OUString::valueOf( nIndex )));
398 lcl_copyDataSequenceProperties(
399 aLSequences[nSeqIdx]->getValues(), xNewSeq );
400 aLSequences[nSeqIdx]->setValues( xNewSeq );
402 // labels
403 Reference< chart2::data::XDataSequence > xNewLabelSeq(
404 xDataProvider->createDataSequenceByRangeRepresentation(
405 OUString( RTL_CONSTASCII_USTRINGPARAM( "label " )) +
406 OUString::valueOf( nIndex )));
407 lcl_copyDataSequenceProperties(
408 aLSequences[nSeqIdx]->getLabel(), xNewLabelSeq );
409 aLSequences[nSeqIdx]->setLabel( xNewLabelSeq );
410 ++nIndex;
415 if( nSeriesNumberFormat != 0 )
417 //give the new series the same number format as the former series especially for bubble charts thus the bubble size values can be edited with same format immidiately
418 Reference< beans::XPropertySet > xNewSeriesProps( xNewSeries, uno::UNO_QUERY );
419 if( xNewSeriesProps.is() )
420 xNewSeriesProps->setPropertyValue( C2U( "NumberFormat" ), uno::makeAny( nSeriesNumberFormat ) );
423 updateFromModel();
429 void DataBrowserModel::removeDataSeries( sal_Int32 nAtColumnIndex )
431 OSL_ASSERT( m_apDialogModel.get());
432 if( static_cast< tDataColumnVector::size_type >( nAtColumnIndex ) < m_aColumns.size())
434 Reference< chart2::XDataSeries > xSeries( m_aColumns[nAtColumnIndex].m_xDataSeries );
435 if( xSeries.is())
437 m_apDialogModel->deleteSeries(
438 xSeries, getHeaderForSeries( xSeries ).m_xChartType );
440 //delete sequences from internal data provider that are not used anymore
441 //but do not delete sequences that are still in use by the remaining series
442 Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
443 Reference< chart2::data::XDataSource > xSourceOfDeletedSeries( xSeries, uno::UNO_QUERY );
444 if( xDataProvider.is() && xSourceOfDeletedSeries.is())
446 ::std::vector< sal_Int32 > aSequenceIndexesToDelete;
447 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequencesOfDeletedSeries( xSourceOfDeletedSeries->getDataSequences() );
448 Reference< chart2::XDataSeriesContainer > xSeriesCnt( getHeaderForSeries( xSeries ).m_xChartType, uno::UNO_QUERY );
449 if( xSeriesCnt.is())
451 Reference< chart2::data::XDataSource > xRemainingDataSource( DataSeriesHelper::getDataSource( xSeriesCnt->getDataSeries() ) );
452 if( xRemainingDataSource.is() )
454 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aRemainingSeq( ContainerHelper::SequenceToVector( xRemainingDataSource->getDataSequences() ) );
455 for( sal_Int32 i=0; i<aSequencesOfDeletedSeries.getLength(); ++i )
457 ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::const_iterator aHitIt(
458 ::std::find_if( aRemainingSeq.begin(), aRemainingSeq.end(),
459 lcl_RepresentationsOfLSeqMatch( aSequencesOfDeletedSeries[i] )));
460 // if not used by the remaining series this sequence can be deleted
461 if( aHitIt == aRemainingSeq.end() )
462 aSequenceIndexesToDelete.push_back( lcl_getValuesRepresentationIndex( aSequencesOfDeletedSeries[i] ) );
467 // delete unnecessary sequences of the internal data
468 // iterate using greatest index first, so that deletion does not
469 // shift other sequences that will be deleted later
470 ::std::sort( aSequenceIndexesToDelete.begin(), aSequenceIndexesToDelete.end());
471 for( ::std::vector< sal_Int32 >::reverse_iterator aIt(
472 aSequenceIndexesToDelete.rbegin()); aIt != aSequenceIndexesToDelete.rend(); ++aIt )
474 if( *aIt != -1 )
475 xDataProvider->deleteSequence( *aIt );
478 updateFromModel();
483 void DataBrowserModel::swapDataSeries( sal_Int32 nFirstColumnIndex )
485 OSL_ASSERT( m_apDialogModel.get());
486 if( static_cast< tDataColumnVector::size_type >( nFirstColumnIndex ) < m_aColumns.size() - 1 )
488 Reference< chart2::XDataSeries > xSeries( m_aColumns[nFirstColumnIndex].m_xDataSeries );
489 if( xSeries.is())
491 m_apDialogModel->moveSeries( xSeries, DialogModel::MOVE_DOWN );
492 updateFromModel();
497 void DataBrowserModel::swapDataPointForAllSeries( sal_Int32 nFirstIndex )
499 OSL_ASSERT( m_apDialogModel.get());
500 Reference< chart2::XInternalDataProvider > xDataProvider(
501 m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
502 // lockControllers
503 ControllerLockGuard aGuard( m_apDialogModel->getChartModel());
504 if( xDataProvider.is())
505 xDataProvider->swapDataPointWithNextOneForAllSequences( nFirstIndex );
506 // unlockControllers
509 void DataBrowserModel::insertDataPointForAllSeries( sal_Int32 nAfterIndex )
511 Reference< chart2::XInternalDataProvider > xDataProvider(
512 m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
513 // lockControllers
514 ControllerLockGuard aGuard( m_apDialogModel->getChartModel());
515 if( xDataProvider.is())
516 xDataProvider->insertDataPointForAllSequences( nAfterIndex );
517 // unlockControllers
520 void DataBrowserModel::removeDataPointForAllSeries( sal_Int32 nAtIndex )
522 Reference< chart2::XInternalDataProvider > xDataProvider(
523 m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
524 // lockControllers
525 ControllerLockGuard aGuard( m_apDialogModel->getChartModel());
526 if( xDataProvider.is())
527 xDataProvider->deleteDataPointForAllSequences( nAtIndex );
528 // unlockControllers
531 DataBrowserModel::tDataHeader DataBrowserModel::getHeaderForSeries(
532 const Reference< chart2::XDataSeries > & xSeries ) const
534 for( tDataHeaderVector::const_iterator aIt( m_aHeaders.begin());
535 aIt != m_aHeaders.end(); ++aIt )
537 if( aIt->m_xDataSeries == xSeries )
538 return (*aIt);
540 return tDataHeader();
543 Reference< chart2::XDataSeries >
544 DataBrowserModel::getDataSeriesByColumn( sal_Int32 nColumn ) const
546 tDataColumnVector::size_type nIndex( nColumn );
547 if( nIndex < m_aColumns.size())
548 return m_aColumns[nIndex].m_xDataSeries;
549 return 0;
552 DataBrowserModel::eCellType DataBrowserModel::getCellType( sal_Int32 nAtColumn, sal_Int32 /* nAtRow */ )
554 eCellType eResult = TEXT;
555 tDataColumnVector::size_type nIndex( nAtColumn );
556 if( nIndex < m_aColumns.size())
557 eResult = m_aColumns[nIndex].m_eCellType;
558 return eResult;
561 double DataBrowserModel::getCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow )
563 double fResult;
564 ::rtl::math::setNan( & fResult );
566 tDataColumnVector::size_type nIndex( nAtColumn );
567 if( nIndex < m_aColumns.size() &&
568 m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
570 Reference< chart2::data::XNumericalDataSequence > xData(
571 m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY );
572 if( xData.is())
574 Sequence< double > aValues( xData->getNumericalData());
575 if( nAtRow < aValues.getLength())
576 fResult = aValues[nAtRow];
579 return fResult;
582 OUString DataBrowserModel::getCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow )
584 OUString aResult;
586 tDataColumnVector::size_type nIndex( nAtColumn );
587 if( nIndex < m_aColumns.size() &&
588 m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
590 Reference< chart2::data::XTextualDataSequence > xData(
591 m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY );
592 if( xData.is())
594 Sequence< OUString > aValues( xData->getTextualData());
595 if( nAtRow < aValues.getLength())
596 aResult = aValues[nAtRow];
599 return aResult;
602 sal_uInt32 DataBrowserModel::getNumberFormatKey( sal_Int32 nAtColumn, sal_Int32 /* nAtRow */ )
604 tDataColumnVector::size_type nIndex( nAtColumn );
605 if( nIndex < m_aColumns.size())
606 return m_aColumns[ nIndex ].m_nNumberFormatKey;
607 return 0;
610 bool DataBrowserModel::setCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow, const uno::Any & rValue )
612 bool bResult = false;
613 tDataColumnVector::size_type nIndex( nAtColumn );
614 if( nIndex < m_aColumns.size() &&
615 m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
617 bResult = true;
620 // label
621 if( nAtRow == -1 )
623 Reference< container::XIndexReplace > xIndexReplace(
624 m_aColumns[ nIndex ].m_xLabeledDataSequence->getLabel(), uno::UNO_QUERY_THROW );
625 xIndexReplace->replaceByIndex( 0, rValue );
627 else
629 Reference< container::XIndexReplace > xIndexReplace(
630 m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY_THROW );
631 xIndexReplace->replaceByIndex( nAtRow, rValue );
634 catch( const uno::Exception & ex )
636 (void)(ex);
637 bResult = false;
640 return bResult;
643 bool DataBrowserModel::setCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow, double fValue )
645 return (getCellType( nAtColumn, nAtRow ) == NUMBER) &&
646 setCellAny( nAtColumn, nAtRow, uno::makeAny( fValue ));
649 bool DataBrowserModel::setCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow, const ::rtl::OUString & rText )
651 return (getCellType( nAtColumn, nAtRow ) == TEXT) &&
652 setCellAny( nAtColumn, nAtRow, uno::makeAny( rText ));
655 sal_Int32 DataBrowserModel::getColumnCount() const
657 return static_cast< sal_Int32 >( m_aColumns.size());
660 sal_Int32 DataBrowserModel::getMaxRowCount() const
662 sal_Int32 nResult = 0;
663 tDataColumnVector::const_iterator aIt( m_aColumns.begin());
664 for( ; aIt != m_aColumns.end(); ++aIt )
666 if( aIt->m_xLabeledDataSequence.is())
668 Reference< chart2::data::XDataSequence > xSeq(
669 aIt->m_xLabeledDataSequence->getValues());
670 if( !xSeq.is())
671 continue;
672 sal_Int32 nLength( xSeq->getData().getLength());
673 if( nLength > nResult )
674 nResult = nLength;
678 return nResult;
681 OUString DataBrowserModel::getRoleOfColumn( sal_Int32 nColumnIndex ) const
683 if( nColumnIndex != -1 &&
684 static_cast< sal_uInt32 >( nColumnIndex ) < m_aColumns.size())
685 return m_aColumns[ nColumnIndex ].m_aUIRoleName;
686 return OUString();
689 Reference< chart2::data::XLabeledDataSequence >
690 DataBrowserModel::getCategories() const throw()
692 OSL_ASSERT( m_apDialogModel.get());
693 return m_apDialogModel->getCategories();
696 const DataBrowserModel::tDataHeaderVector& DataBrowserModel::getDataHeaders() const
698 return m_aHeaders;
701 void DataBrowserModel::updateFromModel()
703 if( !m_xChartDocument.is())
704 return;
705 m_aColumns.clear();
706 m_aHeaders.clear();
708 Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDocument ));
709 if( !xDiagram.is())
710 return;
712 // set template at DialogModel
713 uno::Reference< lang::XMultiServiceFactory > xFact( m_xChartDocument->getChartTypeManager(), uno::UNO_QUERY );
714 DiagramHelper::tTemplateWithServiceName aTemplateAndService =
715 DiagramHelper::getTemplateForDiagram( xDiagram, xFact );
716 if( aTemplateAndService.first.is())
717 m_apDialogModel->setTemplate( aTemplateAndService.first );
719 sal_Int32 nHeaderStart = 0;
720 sal_Int32 nHeaderEnd = 0;
721 if( lcl_ShowCategories( xDiagram ))
723 Reference< chart2::data::XLabeledDataSequence > xCategories( this->getCategories());
724 tDataColumn aCategories;
725 aCategories.m_xLabeledDataSequence.set( xCategories );
726 if( lcl_ShowCategoriesAsDataLabel( xDiagram ))
727 aCategories.m_aUIRoleName = DialogModel::GetRoleDataLabel();
728 else
729 aCategories.m_aUIRoleName = lcl_getUIRoleName( xCategories );
730 aCategories.m_eCellType = TEXT;
731 m_aColumns.push_back( aCategories );
732 ++nHeaderStart;
735 Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
736 if( !xCooSysCnt.is())
737 return;
738 Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
739 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
741 Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
742 Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
743 sal_Int32 nXAxisNumberFormat = DataSeriesHelper::getNumberFormatKeyFromAxis( 0, aCooSysSeq[nCooSysIdx], 0, 0 );
745 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
747 Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY );
748 if( xSeriesCnt.is())
750 rtl::OUString aRoleForDataLabelNumberFormat = ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( aChartTypes[nCTIdx] );
752 Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries());
753 lcl_tSharedSeqVec aSharedSequences( lcl_getSharedSequences( aSeries ));
754 for( lcl_tSharedSeqVec::const_iterator aIt( aSharedSequences.begin());
755 aIt != aSharedSequences.end(); ++aIt )
757 tDataColumn aSharedSequence;
758 aSharedSequence.m_xLabeledDataSequence = *aIt;
759 aSharedSequence.m_aUIRoleName = lcl_getUIRoleName( *aIt );
760 aSharedSequence.m_eCellType = NUMBER;
761 // as the sequences are shared it should be ok to take the first series
762 // @todo: dimension index 0 for x-values used here. This is just a guess.
763 // Also, the axis index is 0, as there is usually only one x-axis
764 aSharedSequence.m_nNumberFormatKey = nXAxisNumberFormat;
765 m_aColumns.push_back( aSharedSequence );
766 ++nHeaderStart;
768 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
770 tDataColumnVector::size_type nStartColIndex = m_aColumns.size();
771 Reference< chart2::XDataSeries > xSeries( aSeries[nSeriesIdx] );
772 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
773 if( xSource.is())
775 Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqs( xSource->getDataSequences());
776 if( aLSeqs.getLength() == 0 )
777 continue;
778 nHeaderEnd = nHeaderStart;
780 // @todo: dimension index 1 for y-values used here. This is just a guess
781 sal_Int32 nYAxisNumberFormatKey =
782 DataSeriesHelper::getNumberFormatKeyFromAxis(
783 aSeries[nSeriesIdx], aCooSysSeq[nCooSysIdx], 1 );
785 sal_Int32 nSeqIdx=0;
786 for( ; nSeqIdx<aLSeqs.getLength(); ++nSeqIdx )
788 sal_Int32 nSequenceNumberFormatKey = nYAxisNumberFormatKey;
789 OUString aRole = lcl_getRole( aLSeqs[nSeqIdx] );
791 if( aRole.equals( aRoleForDataLabelNumberFormat ) )
793 nSequenceNumberFormatKey = ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
794 Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY ), xSeries, -1, xDiagram );
796 else if( aRole.equals( C2U( "values-x" ) ) )
797 nSequenceNumberFormatKey = nXAxisNumberFormat;
799 if( ::std::find_if( aSharedSequences.begin(), aSharedSequences.end(),
800 lcl_RepresentationsOfLSeqMatch( aLSeqs[nSeqIdx] )) == aSharedSequences.end())
802 // no shared sequence
803 m_aColumns.push_back(
804 tDataColumn(
805 aSeries[nSeriesIdx],
806 nSeqIdx,
807 lcl_getUIRoleName( aLSeqs[nSeqIdx] ),
808 aLSeqs[nSeqIdx],
809 NUMBER,
810 nSequenceNumberFormatKey ));
811 ++nHeaderEnd;
813 // else skip
815 bool bSwapXAndYAxis = false;
818 Reference< beans::XPropertySet > xProp( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
819 xProp->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("SwapXAndYAxis"))) >>= bSwapXAndYAxis;
821 catch( const beans::UnknownPropertyException & ex )
823 (void)ex;
826 // add ranges for error bars if present for a series
827 if( StatisticsHelper::usesErrorBarRanges( aSeries[nSeriesIdx], /* bYError = */ true ))
828 addErrorBarRanges( aSeries[nSeriesIdx], nYAxisNumberFormatKey, nSeqIdx, nHeaderEnd );
830 m_aHeaders.push_back(
831 tDataHeader(
832 aSeries[nSeriesIdx],
833 aChartTypes[nCTIdx],
834 bSwapXAndYAxis,
835 nHeaderStart,
836 nHeaderEnd - 1 ));
838 nHeaderStart = nHeaderEnd;
840 ::std::sort( m_aColumns.begin() + nStartColIndex, m_aColumns.end(), implColumnLess() );
848 void DataBrowserModel::addErrorBarRanges(
849 const Reference< chart2::XDataSeries > & xDataSeries,
850 sal_Int32 nNumberFormatKey,
851 sal_Int32 & rInOutSequenceIndex,
852 sal_Int32 & rInOutHeaderEnd )
856 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSequences;
858 // x error bars
859 // ------------
860 Reference< chart2::data::XDataSource > xErrorSource(
861 StatisticsHelper::getErrorBars( xDataSeries, /* bYError = */ false ), uno::UNO_QUERY );
863 // positive x error bars
864 Reference< chart2::data::XLabeledDataSequence > xErrorLSequence(
865 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
866 xErrorSource,
867 /* bPositiveValue = */ true,
868 /* bYError = */ false ));
869 if( xErrorLSequence.is())
870 aSequences.push_back( xErrorLSequence );
872 // negative x error bars
873 xErrorLSequence.set(
874 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
875 xErrorSource,
876 /* bPositiveValue = */ false,
877 /* bYError = */ false ));
878 if( xErrorLSequence.is())
879 aSequences.push_back( xErrorLSequence );
881 // y error bars
882 // ------------
883 xErrorSource.set(
884 StatisticsHelper::getErrorBars( xDataSeries, /* bYError = */ true ), uno::UNO_QUERY );
886 // positive y error bars
887 xErrorLSequence.set(
888 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
889 xErrorSource,
890 /* bPositiveValue = */ true,
891 /* bYError = */ true ));
892 if( xErrorLSequence.is())
893 aSequences.push_back( xErrorLSequence );
895 // negative y error bars
896 xErrorLSequence.set(
897 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
898 xErrorSource,
899 /* bPositiveValue = */ false,
900 /* bYError = */ true ));
901 if( xErrorLSequence.is())
902 aSequences.push_back( xErrorLSequence );
905 for( ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::const_iterator aIt( aSequences.begin());
906 aIt != aSequences.end(); ++aIt )
908 m_aColumns.push_back(
909 tDataColumn(
910 xDataSeries,
911 rInOutSequenceIndex,
912 lcl_getUIRoleName( *aIt ),
913 *aIt,
914 NUMBER,
915 nNumberFormatKey ));
916 ++rInOutSequenceIndex;
917 ++rInOutHeaderEnd;
920 catch( const uno::Exception & ex )
922 ASSERT_EXCEPTION( ex );
926 } // namespace chart