Files
loongoffice/chart2/source/controller/dialogs/DataBrowserModel.cxx
Kurt Zenker a3acf41195 CWS-TOOLING: integrate CWS chart37
2009-05-22 09:10:36 +0200 iha  r272170 : #i102130# color of pies is not loaded correctly
2009-04-27 17:16:20 +0200 iha  r271294 : #i24203# compiler problem
2009-04-27 16:43:21 +0200 iha  r271292 : #i101281# missing API documentation for secondary axis title properties
2009-04-27 15:26:05 +0200 hde  r271276 : #i100987
2009-04-27 15:24:42 +0200 hde  r271273 : #i100987
2009-04-24 15:08:33 +0200 iha  r271214 : #i100995# crash with some logarithmic scalings
2009-04-22 18:50:56 +0200 dr  r271134 : #i82177# write out deleted point labels
2009-04-22 18:40:48 +0200 iha  r271133 : #i101281# missing API documentation for secondary axis title properties
2009-04-22 16:39:42 +0200 dr  r271128 : #i82177# extensions for bubble charts
2009-04-22 14:37:00 +0200 dr  r271114 : #i82177# import/export data label type and separator
2009-04-22 14:36:24 +0200 dr  r271113 : #i82177# import/export data label type and separator
2009-04-21 15:25:26 +0200 dr  r271038 : #i82177# import data label type and separator from BIFF8 CHFR records
2009-04-21 14:37:16 +0200 dr  r271037 : #i82177# dump BIFF8 chart future records
2009-04-20 17:44:27 +0200 iha  r271002 : #i96898# reduce library exports
2009-04-20 13:01:13 +0200 iha  r270975 : #i24203# rotate data labels - help ids
2009-04-20 11:40:33 +0200 dr  r270969 : #i96600# export of axis scaling/positioning properties
2009-04-16 16:02:31 +0200 dr  r270892 : #i69599# keep Y axis left in 3d charts
2009-04-15 18:16:46 +0200 dr  r270859 : #i69599# import of axis position settings
2009-04-15 18:16:01 +0200 dr  r270858 : #i69599# correct handling of logarithmic crossing axes
2009-04-14 16:27:48 +0200 dr  r270794 : #i96599# handle auto axis position on logarithmic axes
2009-04-09 19:59:51 +0200 dr  r270722 : #i96599# import axis crossing settings, fix import of logarithmic scaling settings
2009-04-09 18:26:00 +0200 iha  r270720 : #i96898# reduce library exports
2009-04-09 15:17:04 +0200 iha  r270710 : #i96898# reduce library exports
2009-04-09 10:50:14 +0200 dr  r270682 : #i24203# import/export of data label rotation, fixed some other broken stuff too
2009-04-08 16:54:54 +0200 dr  r270657 : #i24203# import rotation for data point labels
2009-04-06 18:19:17 +0200 iha  r270571 : #i100876# Axis scaling settings dialog wrong after API usage (anys different from double type)
2009-04-06 15:57:05 +0200 iha  r270567 : #i100105# #i58585# leftover  -> 
2009-04-06 15:55:48 +0200 iha  r270564 : #i58585# leftover  -> 
2009-04-02 16:41:07 +0200 iha  r270422 : #i99721# remove unused code
2009-04-02 14:29:03 +0200 iha  r270407 : #i99721# remove unused code
2009-03-26 10:58:23 +0100 iha  r270059 : #i96898# reduce library exports
2009-03-26 10:13:49 +0100 iha  r270055 : #i96898# reduce library exports
2009-03-25 09:39:13 +0100 iha  r269998 : CWS-TOOLING: rebase CWS chart37 to trunk@269781 (milestone: DEV300:m44)
2009-03-24 17:56:56 +0100 iha  r269986 : #i96898# reduce library exports
2009-03-24 16:56:44 +0100 iha  r269974 : #i99721# remove unused code
2009-03-24 16:48:48 +0100 iha  r269970 : #i89731# remove unused string
2009-03-24 15:44:04 +0100 iha  r269961 : remove unused code
2009-03-24 15:22:45 +0100 iha  r269959 : remove unused code
2009-03-24 15:17:17 +0100 iha  r269957 : remove unused code
2009-03-24 11:14:53 +0100 iha  r269923 : #i24203# rotate data labels
2009-03-09 12:10:25 +0100 hde  r269076 : #i99300#
2009-03-06 15:56:26 +0100 iha  r269011 : #i93953# Source Format for secondary axis without data
2009-02-17 15:59:05 +0100 iha  r268177 : avoid warning during build
2009-02-17 15:01:59 +0100 iha  r268173 : avoid warning during build
2009-02-13 09:39:03 +0100 ufi  r267693 : i96999
2009-02-11 15:12:35 +0100 iha  r267604 : removed unused string
2009-02-11 14:00:29 +0100 iha  r267600 : #i96999# Corrected wording from 'correlation coefficient' to 'coefficient of determination'
2009-02-11 10:56:45 +0100 iha  r267584 : #i89731# typo in resource string
2009-02-11 10:01:29 +0100 iha  r267582 : #i89031# compile error on asian windows systems
2009-02-10 16:15:16 +0100 iha  r267552 : #i24203# rotate data labels
2009-02-04 18:00:33 +0100 iha  r267395 : #i98893# don't export defaults to file
2009-02-04 15:48:15 +0100 iha  r267390 : #i92128# asian typography for chart elements
2009-02-04 15:17:41 +0100 iha  r267386 : #i92128# asian typography for chart elements
2009-01-30 14:41:10 +0100 iha  r267197 : CWS-TOOLING: rebase CWS chart37 to trunk@267171 (milestone: DEV300:m41)
2009-06-04 09:41:18 +00:00

903 lines
35 KiB
C++

/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: DataBrowserModel.cxx,v $
* $Revision: 1.6.16.2 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include "DataBrowserModel.hxx"
#include "DialogModel.hxx"
#include "ChartModelHelper.hxx"
#include "DiagramHelper.hxx"
#include "DataSeriesHelper.hxx"
#include "PropertyHelper.hxx"
#include "ControllerLockGuard.hxx"
#include "macros.hxx"
#include "StatisticsHelper.hxx"
#include "ContainerHelper.hxx"
#include <com/sun/star/container/XIndexReplace.hpp>
#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
#include <com/sun/star/chart2/XInternalDataProvider.hpp>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
#include <com/sun/star/chart2/XChartTypeContainer.hpp>
#include <com/sun/star/chart2/data/XDataSource.hpp>
#include <com/sun/star/chart2/data/XDataSink.hpp>
#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
#include <rtl/math.hxx>
#include <algorithm>
#if OSL_DEBUG_LEVEL > 1
#include <cstdio>
#endif
using namespace ::com::sun::star;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::rtl::OUString;
namespace
{
OUString lcl_getRole(
const Reference< chart2::data::XDataSequence > & xSeq )
{
OUString aResult;
Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
if( xProp.is())
{
try
{
xProp->getPropertyValue( C2U("Role")) >>= aResult;
}
catch( const uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
}
return aResult;
}
OUString lcl_getRole(
const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
{
OUString aResult;
if( xLSeq.is())
aResult = lcl_getRole( xLSeq->getValues());
return aResult;
}
OUString lcl_getUIRoleName(
const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
{
OUString aResult( lcl_getRole( xLSeq ));
if( aResult.getLength())
aResult = ::chart::DialogModel::ConvertRoleFromInternalToUI( aResult );
return aResult;
}
void lcl_copyDataSequenceProperties(
const Reference< chart2::data::XDataSequence > & xOldSequence,
const Reference< chart2::data::XDataSequence > & xNewSequence )
{
Reference< beans::XPropertySet > xOldSeqProp( xOldSequence, uno::UNO_QUERY );
Reference< beans::XPropertySet > xNewSeqProp( xNewSequence, uno::UNO_QUERY );
comphelper::copyProperties( xOldSeqProp, xNewSeqProp );
}
bool lcl_SequenceOfSeriesIsShared(
const Reference< chart2::XDataSeries > & xSeries,
const Reference< chart2::data::XDataSequence > & xValues )
{
bool bResult = false;
if( !xValues.is())
return bResult;
try
{
OUString aValuesRole( lcl_getRole( xValues ));
OUString aValuesRep( xValues->getSourceRangeRepresentation());
Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW );
Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences());
for( sal_Int32 i=0; i<aLSeq.getLength(); ++i )
if( aLSeq[i].is() &&
lcl_getRole( aLSeq[i] ).equals( aValuesRole ))
{
// getValues().is(), because lcl_getRole checked that already
bResult = (aValuesRep == aLSeq[i]->getValues()->getSourceRangeRepresentation());
// assumption: a role appears only once in a series
break;
}
}
catch( const uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
return bResult;
}
typedef ::std::vector< Reference< chart2::data::XLabeledDataSequence > > lcl_tSharedSeqVec;
lcl_tSharedSeqVec lcl_getSharedSequences( const Sequence< Reference< chart2::XDataSeries > > & rSeries )
{
// @todo: if only some series share a sequence, those have to be duplicated
// and made unshared for all series
lcl_tSharedSeqVec aResult;
// if we have only one series, we don't want any shared sequences
if( rSeries.getLength() <= 1 )
return aResult;
Reference< chart2::data::XDataSource > xSource( rSeries[0], uno::UNO_QUERY );
Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences());
for( sal_Int32 nIdx=0; nIdx<aLSeq.getLength(); ++nIdx )
{
Reference< chart2::data::XDataSequence > xValues( aLSeq[nIdx]->getValues());
bool bShared = true;
for( sal_Int32 nSeriesIdx=1; nSeriesIdx<rSeries.getLength(); ++nSeriesIdx )
{
bShared = lcl_SequenceOfSeriesIsShared( rSeries[nSeriesIdx], xValues );
if( !bShared )
break;
}
if( bShared )
aResult.push_back( aLSeq[nIdx] );
}
return aResult;
}
sal_Int32 lcl_getValuesRepresentationIndex(
const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
{
sal_Int32 nResult = -1;
if( xLSeq.is())
{
Reference< chart2::data::XDataSequence > xSeq( xLSeq->getValues());
if( xSeq.is())
{
OUString aRep( xSeq->getSourceRangeRepresentation());
nResult = aRep.toInt32();
}
}
return nResult;
}
struct lcl_RepresentationsOfLSeqMatch : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
{
lcl_RepresentationsOfLSeqMatch( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) :
m_aValuesRep( xLSeq.is() ?
(xLSeq->getValues().is() ? xLSeq->getValues()->getSourceRangeRepresentation() : OUString())
: OUString() )
{}
bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
{
return (xLSeq.is() &&
xLSeq->getValues().is() &&
(xLSeq->getValues()->getSourceRangeRepresentation() == m_aValuesRep ));
}
private:
OUString m_aValuesRep;
};
struct lcl_RolesOfLSeqMatch : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
{
lcl_RolesOfLSeqMatch( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) :
m_aRole( lcl_getRole( xLSeq ))
{}
bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
{
return lcl_getRole( xLSeq ).equals( m_aRole );
}
private:
OUString m_aRole;
};
bool lcl_ShowCategories( const Reference< chart2::XDiagram > & /* xDiagram */ )
{
// show categories for all charts
return true;
// return DiagramHelper::isCategoryDiagram( xDiagram );
}
bool lcl_ShowCategoriesAsDataLabel( const Reference< chart2::XDiagram > & xDiagram )
{
return ! ::chart::DiagramHelper::isCategoryDiagram( xDiagram );
}
} // anonymous namespace
namespace chart
{
struct DataBrowserModel::tDataColumn
{
::com::sun::star::uno::Reference<
::com::sun::star::chart2::XDataSeries > m_xDataSeries;
sal_Int32 m_nIndexInDataSeries;
::rtl::OUString m_aUIRoleName;
::com::sun::star::uno::Reference<
::com::sun::star::chart2::data::XLabeledDataSequence > m_xLabeledDataSequence;
eCellType m_eCellType;
sal_Int32 m_nNumberFormatKey;
// default CTOR
tDataColumn() : m_nIndexInDataSeries( -1 ), m_eCellType( TEXT ), m_nNumberFormatKey( 0 ) {}
// "full" CTOR
tDataColumn(
const ::com::sun::star::uno::Reference<
::com::sun::star::chart2::XDataSeries > & xDataSeries,
sal_Int32 nIndexInDataSeries,
::rtl::OUString aUIRoleName,
::com::sun::star::uno::Reference<
::com::sun::star::chart2::data::XLabeledDataSequence > xLabeledDataSequence,
eCellType aCellType,
sal_Int32 nNumberFormatKey ) :
m_xDataSeries( xDataSeries ),
m_nIndexInDataSeries( nIndexInDataSeries ),
m_aUIRoleName( aUIRoleName ),
m_xLabeledDataSequence( xLabeledDataSequence ),
m_eCellType( aCellType ),
m_nNumberFormatKey( nNumberFormatKey )
{}
};
struct DataBrowserModel::implColumnLess : public ::std::binary_function<
DataBrowserModel::tDataColumn, DataBrowserModel::tDataColumn, bool >
{
bool operator() ( const first_argument_type & rLeft, const second_argument_type & rRight )
{
if( rLeft.m_xLabeledDataSequence.is() && rRight.m_xLabeledDataSequence.is())
{
return DialogModel::GetRoleIndexForSorting( lcl_getRole( rLeft.m_xLabeledDataSequence )) <
DialogModel::GetRoleIndexForSorting( lcl_getRole( rRight.m_xLabeledDataSequence ));
}
return true;
}
};
DataBrowserModel::DataBrowserModel(
const Reference< chart2::XChartDocument > & xChartDoc,
const Reference< uno::XComponentContext > & xContext ) :
m_xChartDocument( xChartDoc ),
m_xContext( xContext ),
m_apDialogModel( new DialogModel( xChartDoc, xContext ))
{
updateFromModel();
}
DataBrowserModel::~DataBrowserModel()
{}
namespace
{
struct lcl_DataSeriesOfHeaderMatches : public ::std::unary_function< ::chart::DataBrowserModel::tDataHeader, bool >
{
lcl_DataSeriesOfHeaderMatches(
const Reference< chart2::XDataSeries > & xSeriesToCompareWith ) :
m_xSeries( xSeriesToCompareWith )
{}
bool operator() ( const ::chart::DataBrowserModel::tDataHeader & rHeader )
{
return (m_xSeries == rHeader.m_xDataSeries);
}
private:
Reference< chart2::XDataSeries > m_xSeries;
};
}
void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex )
{
OSL_ASSERT( m_apDialogModel.get());
Reference< chart2::XInternalDataProvider > xDataProvider(
m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
if( xDataProvider.is())
{
sal_Int32 nStartCol = 0;
Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDocument ));
Reference< chart2::XChartType > xChartType;
Reference< chart2::XDataSeries > xSeries;
if( static_cast< tDataColumnVector::size_type >( nAfterColumnIndex ) <= m_aColumns.size())
xSeries.set( m_aColumns[nAfterColumnIndex].m_xDataSeries );
if( xSeries.is())
{
xChartType.set( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ));
tDataHeaderVector::const_iterator aIt(
::std::find_if( m_aHeaders.begin(), m_aHeaders.end(),
lcl_DataSeriesOfHeaderMatches( xSeries )));
if( aIt != m_aHeaders.end())
nStartCol = aIt->m_nEndColumn;
}
else
{
xChartType.set( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ));
nStartCol = nAfterColumnIndex;
}
if( xChartType.is())
{
sal_Int32 nOffset = 0;
if( xDiagram.is() && lcl_ShowCategories( xDiagram ))
++nOffset;
// get shared sequences of current series
Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY );
lcl_tSharedSeqVec aSharedSequences;
if( xSeriesCnt.is())
aSharedSequences = lcl_getSharedSequences( xSeriesCnt->getDataSeries());
Reference< chart2::XDataSeries > xNewSeries(
m_apDialogModel->insertSeriesAfter( xSeries, xChartType, true /* bCreateDataCachedSequences */ ));
if( xNewSeries.is())
{
{
Reference< chart2::data::XDataSource > xSource( xNewSeries, uno::UNO_QUERY );
if( xSource.is())
{
Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSequences(
xSource->getDataSequences());
sal_Int32 nSeqIdx = 0;
sal_Int32 nSeqSize = aLSequences.getLength();
nStartCol -= (nOffset - 1);
for( sal_Int32 nIndex = nStartCol;
(nSeqIdx < nSeqSize);
++nSeqIdx )
{
lcl_tSharedSeqVec::const_iterator aSharedIt(
::std::find_if( aSharedSequences.begin(), aSharedSequences.end(),
lcl_RolesOfLSeqMatch( aLSequences[nSeqIdx] )));
if( aSharedIt != aSharedSequences.end())
{
aLSequences[nSeqIdx]->setValues( (*aSharedIt)->getValues());
aLSequences[nSeqIdx]->setLabel( (*aSharedIt)->getLabel());
}
else
{
xDataProvider->insertSequence( nIndex - 1 );
// values
Reference< chart2::data::XDataSequence > xNewSeq(
xDataProvider->createDataSequenceByRangeRepresentation(
OUString::valueOf( nIndex )));
lcl_copyDataSequenceProperties(
aLSequences[nSeqIdx]->getValues(), xNewSeq );
aLSequences[nSeqIdx]->setValues( xNewSeq );
// labels
Reference< chart2::data::XDataSequence > xNewLabelSeq(
xDataProvider->createDataSequenceByRangeRepresentation(
OUString( RTL_CONSTASCII_USTRINGPARAM( "label " )) +
OUString::valueOf( nIndex )));
lcl_copyDataSequenceProperties(
aLSequences[nSeqIdx]->getLabel(), xNewLabelSeq );
aLSequences[nSeqIdx]->setLabel( xNewLabelSeq );
++nIndex;
}
}
}
}
updateFromModel();
}
}
}
}
void DataBrowserModel::removeDataSeries( sal_Int32 nAtColumnIndex )
{
OSL_ASSERT( m_apDialogModel.get());
if( static_cast< tDataColumnVector::size_type >( nAtColumnIndex ) < m_aColumns.size())
{
Reference< chart2::XDataSeries > xSeries( m_aColumns[nAtColumnIndex].m_xDataSeries );
if( xSeries.is())
{
m_apDialogModel->deleteSeries(
xSeries, getHeaderForSeries( xSeries ).m_xChartType );
//delete sequences from internal data provider that are not used anymore
//but do not delete sequences that are still in use by the remaining series
Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
Reference< chart2::data::XDataSource > xSourceOfDeletedSeries( xSeries, uno::UNO_QUERY );
if( xDataProvider.is() && xSourceOfDeletedSeries.is())
{
::std::vector< sal_Int32 > aSequenceIndexesToDelete;
Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequencesOfDeletedSeries( xSourceOfDeletedSeries->getDataSequences() );
Reference< chart2::XDataSeriesContainer > xSeriesCnt( getHeaderForSeries( xSeries ).m_xChartType, uno::UNO_QUERY );
if( xSeriesCnt.is())
{
Reference< chart2::data::XDataSource > xRemainingDataSource( DataSeriesHelper::getDataSource( xSeriesCnt->getDataSeries() ) );
if( xRemainingDataSource.is() )
{
::std::vector< Reference< chart2::data::XLabeledDataSequence > > aRemainingSeq( ContainerHelper::SequenceToVector( xRemainingDataSource->getDataSequences() ) );
for( sal_Int32 i=0; i<aSequencesOfDeletedSeries.getLength(); ++i )
{
::std::vector< Reference< chart2::data::XLabeledDataSequence > >::const_iterator aHitIt(
::std::find_if( aRemainingSeq.begin(), aRemainingSeq.end(),
lcl_RepresentationsOfLSeqMatch( aSequencesOfDeletedSeries[i] )));
// if not used by the remaining series this sequence can be deleted
if( aHitIt == aRemainingSeq.end() )
aSequenceIndexesToDelete.push_back( lcl_getValuesRepresentationIndex( aSequencesOfDeletedSeries[i] ) );
}
}
}
// delete unnecessary sequences of the internal data
// iterate using greatest index first, so that deletion does not
// shift other sequences that will be deleted later
::std::sort( aSequenceIndexesToDelete.begin(), aSequenceIndexesToDelete.end());
for( ::std::vector< sal_Int32 >::reverse_iterator aIt(
aSequenceIndexesToDelete.rbegin()); aIt != aSequenceIndexesToDelete.rend(); ++aIt )
{
if( *aIt != -1 )
xDataProvider->deleteSequence( *aIt );
}
}
updateFromModel();
}
}
}
void DataBrowserModel::swapDataSeries( sal_Int32 nFirstColumnIndex )
{
OSL_ASSERT( m_apDialogModel.get());
if( static_cast< tDataColumnVector::size_type >( nFirstColumnIndex ) < m_aColumns.size() - 1 )
{
Reference< chart2::XDataSeries > xSeries( m_aColumns[nFirstColumnIndex].m_xDataSeries );
if( xSeries.is())
{
m_apDialogModel->moveSeries( xSeries, DialogModel::MOVE_DOWN );
updateFromModel();
}
}
}
void DataBrowserModel::swapDataPointForAllSeries( sal_Int32 nFirstIndex )
{
OSL_ASSERT( m_apDialogModel.get());
Reference< chart2::XInternalDataProvider > xDataProvider(
m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
// lockControllers
ControllerLockGuard aGuard( m_apDialogModel->getChartModel());
if( xDataProvider.is())
xDataProvider->swapDataPointWithNextOneForAllSequences( nFirstIndex );
// unlockControllers
}
void DataBrowserModel::insertDataPointForAllSeries( sal_Int32 nAfterIndex )
{
Reference< chart2::XInternalDataProvider > xDataProvider(
m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
// lockControllers
ControllerLockGuard aGuard( m_apDialogModel->getChartModel());
if( xDataProvider.is())
xDataProvider->insertDataPointForAllSequences( nAfterIndex );
// unlockControllers
}
void DataBrowserModel::removeDataPointForAllSeries( sal_Int32 nAtIndex )
{
Reference< chart2::XInternalDataProvider > xDataProvider(
m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
// lockControllers
ControllerLockGuard aGuard( m_apDialogModel->getChartModel());
if( xDataProvider.is())
xDataProvider->deleteDataPointForAllSequences( nAtIndex );
// unlockControllers
}
DataBrowserModel::tDataHeader DataBrowserModel::getHeaderForSeries(
const Reference< chart2::XDataSeries > & xSeries ) const
{
for( tDataHeaderVector::const_iterator aIt( m_aHeaders.begin());
aIt != m_aHeaders.end(); ++aIt )
{
if( aIt->m_xDataSeries == xSeries )
return (*aIt);
}
return tDataHeader();
}
Reference< chart2::XDataSeries >
DataBrowserModel::getDataSeriesByColumn( sal_Int32 nColumn ) const
{
tDataColumnVector::size_type nIndex( nColumn );
if( nIndex < m_aColumns.size())
return m_aColumns[nIndex].m_xDataSeries;
return 0;
}
DataBrowserModel::eCellType DataBrowserModel::getCellType( sal_Int32 nAtColumn, sal_Int32 /* nAtRow */ )
{
eCellType eResult = TEXT;
tDataColumnVector::size_type nIndex( nAtColumn );
if( nIndex < m_aColumns.size())
eResult = m_aColumns[nIndex].m_eCellType;
return eResult;
}
double DataBrowserModel::getCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow )
{
double fResult;
::rtl::math::setNan( & fResult );
tDataColumnVector::size_type nIndex( nAtColumn );
if( nIndex < m_aColumns.size() &&
m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
{
Reference< chart2::data::XNumericalDataSequence > xData(
m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY );
if( xData.is())
{
Sequence< double > aValues( xData->getNumericalData());
if( nAtRow < aValues.getLength())
fResult = aValues[nAtRow];
}
}
return fResult;
}
OUString DataBrowserModel::getCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow )
{
OUString aResult;
tDataColumnVector::size_type nIndex( nAtColumn );
if( nIndex < m_aColumns.size() &&
m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
{
Reference< chart2::data::XTextualDataSequence > xData(
m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY );
if( xData.is())
{
Sequence< OUString > aValues( xData->getTextualData());
if( nAtRow < aValues.getLength())
aResult = aValues[nAtRow];
}
}
return aResult;
}
sal_uInt32 DataBrowserModel::getNumberFormatKey( sal_Int32 nAtColumn, sal_Int32 /* nAtRow */ )
{
tDataColumnVector::size_type nIndex( nAtColumn );
if( nIndex < m_aColumns.size())
return m_aColumns[ nIndex ].m_nNumberFormatKey;
return 0;
}
bool DataBrowserModel::setCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow, const uno::Any & rValue )
{
bool bResult = false;
tDataColumnVector::size_type nIndex( nAtColumn );
if( nIndex < m_aColumns.size() &&
m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
{
bResult = true;
try
{
// label
if( nAtRow == -1 )
{
Reference< container::XIndexReplace > xIndexReplace(
m_aColumns[ nIndex ].m_xLabeledDataSequence->getLabel(), uno::UNO_QUERY_THROW );
xIndexReplace->replaceByIndex( 0, rValue );
}
else
{
Reference< container::XIndexReplace > xIndexReplace(
m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY_THROW );
xIndexReplace->replaceByIndex( nAtRow, rValue );
}
}
catch( const uno::Exception & ex )
{
(void)(ex);
bResult = false;
}
}
return bResult;
}
bool DataBrowserModel::setCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow, double fValue )
{
return (getCellType( nAtColumn, nAtRow ) == NUMBER) &&
setCellAny( nAtColumn, nAtRow, uno::makeAny( fValue ));
}
bool DataBrowserModel::setCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow, const ::rtl::OUString & rText )
{
return (getCellType( nAtColumn, nAtRow ) == TEXT) &&
setCellAny( nAtColumn, nAtRow, uno::makeAny( rText ));
}
sal_Int32 DataBrowserModel::getColumnCount() const
{
return static_cast< sal_Int32 >( m_aColumns.size());
}
sal_Int32 DataBrowserModel::getMaxRowCount() const
{
sal_Int32 nResult = 0;
tDataColumnVector::const_iterator aIt( m_aColumns.begin());
for( ; aIt != m_aColumns.end(); ++aIt )
{
if( aIt->m_xLabeledDataSequence.is())
{
Reference< chart2::data::XDataSequence > xSeq(
aIt->m_xLabeledDataSequence->getValues());
if( !xSeq.is())
continue;
sal_Int32 nLength( xSeq->getData().getLength());
if( nLength > nResult )
nResult = nLength;
}
}
return nResult;
}
OUString DataBrowserModel::getRoleOfColumn( sal_Int32 nColumnIndex ) const
{
if( nColumnIndex != -1 &&
static_cast< sal_uInt32 >( nColumnIndex ) < m_aColumns.size())
return m_aColumns[ nColumnIndex ].m_aUIRoleName;
return OUString();
}
Reference< chart2::data::XLabeledDataSequence >
DataBrowserModel::getCategories() const throw()
{
OSL_ASSERT( m_apDialogModel.get());
return m_apDialogModel->getCategories();
}
const DataBrowserModel::tDataHeaderVector& DataBrowserModel::getDataHeaders() const
{
return m_aHeaders;
}
void DataBrowserModel::updateFromModel()
{
if( !m_xChartDocument.is())
return;
m_aColumns.clear();
m_aHeaders.clear();
Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDocument ));
if( !xDiagram.is())
return;
// set template at DialogModel
uno::Reference< lang::XMultiServiceFactory > xFact( m_xChartDocument->getChartTypeManager(), uno::UNO_QUERY );
DiagramHelper::tTemplateWithServiceName aTemplateAndService =
DiagramHelper::getTemplateForDiagram( xDiagram, xFact );
if( aTemplateAndService.first.is())
m_apDialogModel->setTemplate( aTemplateAndService.first );
sal_Int32 nHeaderStart = 0;
sal_Int32 nHeaderEnd = 0;
if( lcl_ShowCategories( xDiagram ))
{
Reference< chart2::data::XLabeledDataSequence > xCategories( this->getCategories());
tDataColumn aCategories;
aCategories.m_xLabeledDataSequence.set( xCategories );
if( lcl_ShowCategoriesAsDataLabel( xDiagram ))
aCategories.m_aUIRoleName = DialogModel::GetRoleDataLabel();
else
aCategories.m_aUIRoleName = lcl_getUIRoleName( xCategories );
aCategories.m_eCellType = TEXT;
m_aColumns.push_back( aCategories );
++nHeaderStart;
}
Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
if( !xCooSysCnt.is())
return;
Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
{
Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
{
Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY );
if( xSeriesCnt.is())
{
Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries());
lcl_tSharedSeqVec aSharedSequences( lcl_getSharedSequences( aSeries ));
for( lcl_tSharedSeqVec::const_iterator aIt( aSharedSequences.begin());
aIt != aSharedSequences.end(); ++aIt )
{
tDataColumn aSharedSequence;
aSharedSequence.m_xLabeledDataSequence = *aIt;
aSharedSequence.m_aUIRoleName = lcl_getUIRoleName( *aIt );
aSharedSequence.m_eCellType = NUMBER;
// as the sequences are shared it should be ok to take the first series
// @todo: dimension index 0 for x-values used here. This is just a guess.
// Also, the axis index is 0, as there is usually only one x-axis
aSharedSequence.m_nNumberFormatKey =
DataSeriesHelper::getNumberFormatKeyFromAxis(
aSeries[0], aCooSysSeq[nCooSysIdx], 0, 0 );
m_aColumns.push_back( aSharedSequence );
++nHeaderStart;
}
for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
{
tDataColumnVector::size_type nStartColIndex = m_aColumns.size();
Reference< chart2::data::XDataSource > xSource( aSeries[nSeriesIdx], uno::UNO_QUERY );
if( xSource.is())
{
Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqs( xSource->getDataSequences());
if( aLSeqs.getLength() == 0 )
continue;
nHeaderEnd = nHeaderStart;
// @todo: dimension index 1 for y-values used here. This is just a guess
sal_Int32 nYAxisNumberFormatKey =
DataSeriesHelper::getNumberFormatKeyFromAxis(
aSeries[nSeriesIdx], aCooSysSeq[nCooSysIdx], 1 );
sal_Int32 nSeqIdx=0;
for( ; nSeqIdx<aLSeqs.getLength(); ++nSeqIdx )
{
sal_Int32 nSequenceNumberFormatKey = nYAxisNumberFormatKey;
OUString aRole = lcl_getRole( aLSeqs[nSeqIdx] );
if( aRole.equals( C2U( "values-x" ) ) )
nSequenceNumberFormatKey = DataSeriesHelper::getNumberFormatKeyFromAxis(
aSeries[nSeriesIdx], aCooSysSeq[nCooSysIdx], 0, 0 );
if( ::std::find_if( aSharedSequences.begin(), aSharedSequences.end(),
lcl_RepresentationsOfLSeqMatch( aLSeqs[nSeqIdx] )) == aSharedSequences.end())
{
// no shared sequence
m_aColumns.push_back(
tDataColumn(
aSeries[nSeriesIdx],
nSeqIdx,
lcl_getUIRoleName( aLSeqs[nSeqIdx] ),
aLSeqs[nSeqIdx],
NUMBER,
nSequenceNumberFormatKey ));
++nHeaderEnd;
}
// else skip
}
bool bSwapXAndYAxis = false;
try
{
Reference< beans::XPropertySet > xProp( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
xProp->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("SwapXAndYAxis"))) >>= bSwapXAndYAxis;
}
catch( const beans::UnknownPropertyException & ex )
{
(void)ex;
}
// add ranges for error bars if present for a series
if( StatisticsHelper::usesErrorBarRanges( aSeries[nSeriesIdx], /* bYError = */ true ))
addErrorBarRanges( aSeries[nSeriesIdx], nYAxisNumberFormatKey, nSeqIdx, nHeaderEnd );
m_aHeaders.push_back(
tDataHeader(
aSeries[nSeriesIdx],
aChartTypes[nCTIdx],
bSwapXAndYAxis,
nHeaderStart,
nHeaderEnd - 1 ));
nHeaderStart = nHeaderEnd;
::std::sort( m_aColumns.begin() + nStartColIndex, m_aColumns.end(), implColumnLess() );
}
}
}
}
}
}
void DataBrowserModel::addErrorBarRanges(
const Reference< chart2::XDataSeries > & xDataSeries,
sal_Int32 nNumberFormatKey,
sal_Int32 & rInOutSequenceIndex,
sal_Int32 & rInOutHeaderEnd )
{
try
{
::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSequences;
// x error bars
// ------------
Reference< chart2::data::XDataSource > xErrorSource(
StatisticsHelper::getErrorBars( xDataSeries, /* bYError = */ false ), uno::UNO_QUERY );
// positive x error bars
Reference< chart2::data::XLabeledDataSequence > xErrorLSequence(
StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
xErrorSource,
/* bPositiveValue = */ true,
/* bYError = */ false ));
if( xErrorLSequence.is())
aSequences.push_back( xErrorLSequence );
// negative x error bars
xErrorLSequence.set(
StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
xErrorSource,
/* bPositiveValue = */ false,
/* bYError = */ false ));
if( xErrorLSequence.is())
aSequences.push_back( xErrorLSequence );
// y error bars
// ------------
xErrorSource.set(
StatisticsHelper::getErrorBars( xDataSeries, /* bYError = */ true ), uno::UNO_QUERY );
// positive y error bars
xErrorLSequence.set(
StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
xErrorSource,
/* bPositiveValue = */ true,
/* bYError = */ true ));
if( xErrorLSequence.is())
aSequences.push_back( xErrorLSequence );
// negative y error bars
xErrorLSequence.set(
StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
xErrorSource,
/* bPositiveValue = */ false,
/* bYError = */ true ));
if( xErrorLSequence.is())
aSequences.push_back( xErrorLSequence );
for( ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::const_iterator aIt( aSequences.begin());
aIt != aSequences.end(); ++aIt )
{
m_aColumns.push_back(
tDataColumn(
xDataSeries,
rInOutSequenceIndex,
lcl_getUIRoleName( *aIt ),
*aIt,
NUMBER,
nNumberFormatKey ));
++rInOutSequenceIndex;
++rInOutHeaderEnd;
}
}
catch( const uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
}
} // namespace chart