1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
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>
62 #if OSL_DEBUG_LEVEL > 1
66 using namespace ::com::sun::star
;
68 using ::com::sun::star::uno::Reference
;
69 using ::com::sun::star::uno::Sequence
;
70 using ::rtl::OUString
;
75 const Reference
< chart2::data::XDataSequence
> & xSeq
)
78 Reference
< beans::XPropertySet
> xProp( xSeq
, uno::UNO_QUERY
);
83 xProp
->getPropertyValue( C2U("Role")) >>= aResult
;
85 catch( const uno::Exception
& ex
)
87 ASSERT_EXCEPTION( ex
);
95 const Reference
< chart2::data::XLabeledDataSequence
> & xLSeq
)
99 aResult
= lcl_getRole( xLSeq
->getValues());
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
);
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;
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
)
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
144 catch( const uno::Exception
& ex
)
146 ASSERT_EXCEPTION( ex
);
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 )
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());
168 for( sal_Int32 nSeriesIdx
=1; nSeriesIdx
<rSeries
.getLength(); ++nSeriesIdx
)
170 bShared
= lcl_SequenceOfSeriesIsShared( rSeries
[nSeriesIdx
], xValues
);
175 aResult
.push_back( aLSeq
[nIdx
] );
181 sal_Int32
lcl_getValuesRepresentationIndex(
182 const Reference
< chart2::data::XLabeledDataSequence
> & xLSeq
)
184 sal_Int32 nResult
= -1;
187 Reference
< chart2::data::XDataSequence
> xSeq( xLSeq
->getValues());
190 OUString
aRep( xSeq
->getSourceRangeRepresentation());
191 nResult
= aRep
.toInt32();
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())
204 bool operator() ( const Reference
< chart2::data::XLabeledDataSequence
> & xLSeq
)
206 return (xLSeq
.is() &&
207 xLSeq
->getValues().is() &&
208 (xLSeq
->getValues()->getSourceRangeRepresentation() == m_aValuesRep
));
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
);
227 bool lcl_ShowCategories( const Reference
< chart2::XDiagram
> & /* xDiagram */ )
229 // show categories for all charts
231 // return DiagramHelper::isCategoryDiagram( xDiagram );
234 bool lcl_ShowCategoriesAsDataLabel( const Reference
< chart2::XDiagram
> & xDiagram
)
236 return ! ::chart::DiagramHelper::isCategoryDiagram( xDiagram
);
239 } // anonymous namespace
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
;
257 tDataColumn() : m_nIndexInDataSeries( -1 ), m_eCellType( TEXT
), m_nNumberFormatKey( 0 ) {}
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
,
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
));
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
))
301 DataBrowserModel::~DataBrowserModel()
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
);
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;
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
;
351 xChartType
.set( DiagramHelper::getChartTypeByIndex( xDiagram
, 0 ));
352 nStartCol
= nAfterColumnIndex
;
357 sal_Int32 nOffset
= 0;
358 if( xDiagram
.is() && lcl_ShowCategories( xDiagram
))
360 // get shared sequences of current series
361 Reference
< chart2::XDataSeriesContainer
> xSeriesCnt( xChartType
, uno::UNO_QUERY
);
362 lcl_tSharedSeqVec aSharedSequences
;
364 aSharedSequences
= lcl_getSharedSequences( xSeriesCnt
->getDataSeries());
365 Reference
< chart2::XDataSeries
> xNewSeries(
366 m_apDialogModel
->insertSeriesAfter( xSeries
, xChartType
, true /* bCreateDataCachedSequences */ ));
370 Reference
< chart2::data::XDataSource
> xSource( xNewSeries
, uno::UNO_QUERY
);
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
);
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());
392 xDataProvider
->insertSequence( nIndex
- 1 );
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
);
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
);
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
) );
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
);
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
);
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
)
475 xDataProvider
->deleteSequence( *aIt
);
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
);
491 m_apDialogModel
->moveSeries( xSeries
, DialogModel::MOVE_DOWN
);
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
);
503 ControllerLockGuard
aGuard( m_apDialogModel
->getChartModel());
504 if( xDataProvider
.is())
505 xDataProvider
->swapDataPointWithNextOneForAllSequences( nFirstIndex
);
509 void DataBrowserModel::insertDataPointForAllSeries( sal_Int32 nAfterIndex
)
511 Reference
< chart2::XInternalDataProvider
> xDataProvider(
512 m_apDialogModel
->getDataProvider(), uno::UNO_QUERY
);
514 ControllerLockGuard
aGuard( m_apDialogModel
->getChartModel());
515 if( xDataProvider
.is())
516 xDataProvider
->insertDataPointForAllSequences( nAfterIndex
);
520 void DataBrowserModel::removeDataPointForAllSeries( sal_Int32 nAtIndex
)
522 Reference
< chart2::XInternalDataProvider
> xDataProvider(
523 m_apDialogModel
->getDataProvider(), uno::UNO_QUERY
);
525 ControllerLockGuard
aGuard( m_apDialogModel
->getChartModel());
526 if( xDataProvider
.is())
527 xDataProvider
->deleteDataPointForAllSequences( nAtIndex
);
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
)
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
;
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
;
561 double DataBrowserModel::getCellNumber( sal_Int32 nAtColumn
, sal_Int32 nAtRow
)
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
);
574 Sequence
< double > aValues( xData
->getNumericalData());
575 if( nAtRow
< aValues
.getLength())
576 fResult
= aValues
[nAtRow
];
582 OUString
DataBrowserModel::getCellText( sal_Int32 nAtColumn
, sal_Int32 nAtRow
)
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
);
594 Sequence
< OUString
> aValues( xData
->getTextualData());
595 if( nAtRow
< aValues
.getLength())
596 aResult
= aValues
[nAtRow
];
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
;
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())
623 Reference
< container::XIndexReplace
> xIndexReplace(
624 m_aColumns
[ nIndex
].m_xLabeledDataSequence
->getLabel(), uno::UNO_QUERY_THROW
);
625 xIndexReplace
->replaceByIndex( 0, rValue
);
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
)
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());
672 sal_Int32
nLength( xSeq
->getData().getLength());
673 if( nLength
> 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
;
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
701 void DataBrowserModel::updateFromModel()
703 if( !m_xChartDocument
.is())
708 Reference
< chart2::XDiagram
> xDiagram( ChartModelHelper::findDiagram( m_xChartDocument
));
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();
729 aCategories
.m_aUIRoleName
= lcl_getUIRoleName( xCategories
);
730 aCategories
.m_eCellType
= TEXT
;
731 m_aColumns
.push_back( aCategories
);
735 Reference
< chart2::XCoordinateSystemContainer
> xCooSysCnt( xDiagram
, uno::UNO_QUERY
);
736 if( !xCooSysCnt
.is())
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
);
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
);
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
);
775 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aLSeqs( xSource
->getDataSequences());
776 if( aLSeqs
.getLength() == 0 )
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 );
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(
807 lcl_getUIRoleName( aLSeqs
[nSeqIdx
] ),
810 nSequenceNumberFormatKey
));
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
)
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(
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
;
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(
867 /* bPositiveValue = */ true,
868 /* bYError = */ false ));
869 if( xErrorLSequence
.is())
870 aSequences
.push_back( xErrorLSequence
);
872 // negative x error bars
874 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
876 /* bPositiveValue = */ false,
877 /* bYError = */ false ));
878 if( xErrorLSequence
.is())
879 aSequences
.push_back( xErrorLSequence
);
884 StatisticsHelper::getErrorBars( xDataSeries
, /* bYError = */ true ), uno::UNO_QUERY
);
886 // positive y error bars
888 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
890 /* bPositiveValue = */ true,
891 /* bYError = */ true ));
892 if( xErrorLSequence
.is())
893 aSequences
.push_back( xErrorLSequence
);
895 // negative y error bars
897 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
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(
912 lcl_getUIRoleName( *aIt
),
916 ++rInOutSequenceIndex
;
920 catch( const uno::Exception
& ex
)
922 ASSERT_EXCEPTION( ex
);