Files
libreoffice/chart2/source/controller/dialogs/DialogModel.cxx
Release Engineers 44569a657c CWS-TOOLING: integrate CWS bubblechart
2009-06-17 08:41:14 +0200 hde  r273051 : i101635: added new charttype bubble
2009-06-17 08:39:37 +0200 hde  r273050 : i101635: created new testcase tCreateNewBubbleChart
2009-06-17 08:38:07 +0200 hde  r273049 : i101635: created new testcase tCreateNewBubbleChart
2009-06-15 15:22:32 +0200 hde  r272991 : 101635
2009-06-11 12:44:01 +0200 iha  r272864 : rebase to dev300m50
2009-06-10 23:27:54 +0200 iha  r272841 : CWS-TOOLING: rebase CWS bubblechart to trunk@272827 (milestone: DEV300:m50)
2009-06-04 18:07:35 +0200 iha  r272649 : #i64689# Bubble Chart
2009-06-04 17:26:44 +0200 iha  r272647 : #i64689# Bubble Chart
2009-06-04 11:24:25 +0200 iha  r272618 : #i64689# add more spacing between bubbles and data labels
2009-05-26 18:05:23 +0200 ufi  r272314 : i101637
2009-04-22 14:37:50 +0200 iha  r271115 : #i64689# bubble chart
2009-04-21 17:52:23 +0200 iha  r271052 : #i64689# bubble chart
2009-04-21 17:50:48 +0200 iha  r271051 : #i76728# type icon for xy chart
2009-04-21 17:25:52 +0200 iha  r271049 : #i76728# type icon for xy chart
2009-04-09 11:18:09 +0200 iha  r270685 : #i100977# autoscaling works not correct if missing values should be treated as zero
2009-04-08 16:39:43 +0200 iha  r270656 : #i64689# bubble chart - missing value treatment
2009-04-08 15:13:25 +0200 iha  r270655 : #i64689# bubble chart - remove unused code
2009-04-08 15:12:19 +0200 iha  r270653 : #i64689# bubble chart - determine sereis length correctly on export
2009-04-08 14:22:43 +0200 iha  r270650 : #i64689# bubble chart - remove unused code
2009-04-08 14:12:09 +0200 iha  r270646 : #i64689# bubble chart - export domains even if no main sequence was found
2009-04-08 14:11:07 +0200 iha  r270645 : #i64689# bubble chart - don't replace missing size values with 1.0
2009-04-07 16:20:22 +0200 iha  r270602 : #i64689# bubble chart - do not offer percent values for data label display for xy and bubble chart
2009-04-07 16:17:42 +0200 iha  r270601 : remove superfluous code
2009-04-06 16:39:32 +0200 iha  r270569 : #i64689# bubble chart -correct automatic numberformat detection for axis, data table and data label + transport data label numberformat during copy paste in addition to axis numberformat
2009-04-02 17:33:33 +0200 iha  r270427 : use input string for formatting in data table during edit
2009-04-02 16:00:29 +0200 iha  r270413 : #i64689# bubble chart - when creating a new series within the data table give it the same number format as the former series, thus the new bubble size values can be edited with the same format immidiately
2009-04-02 11:25:33 +0200 iha  r270385 : #i64689# bubble chart -correct automatic numberformat detection for axis, data table and data label + transport data label numberformat during copy paste in addition to axis numberformat
2009-04-01 11:32:03 +0200 iha  r270312 : #i64689# bubble chart - add further parameter for view creation
2009-03-31 17:52:08 +0200 iha  r270291 : #i64689# bubble chart - scale bubble size with diagram size
2009-03-31 13:38:13 +0200 iha  r270278 : #i64689# bubble chart - wrong size for small values < 1
2009-03-27 19:11:07 +0100 iha  r270169 : #i64689# bubble chart
2009-03-27 19:07:11 +0100 iha  r270168 : #i64689# bubble chart - remove unused code
2009-03-27 18:33:57 +0100 iha  r270167 : #i64689# bubble chart - create no shape for invalid sizes
2009-03-27 15:18:21 +0100 iha  r270157 : #i76728# type icon for xy chart
2009-03-27 14:34:38 +0100 iha  r270156 : #i64689# bubble chart - correct scaling
2009-03-27 14:27:27 +0100 iha  r270155 : #i64689# bubble chart - images
2009-03-27 14:25:45 +0100 iha  r270154 : #i64689# bubble chart - images
2009-03-27 11:38:57 +0100 iha  r270142 : #i64689# bubble chart - values-size is the main series
2009-03-27 11:30:20 +0100 iha  r270140 : #i64689# correct order of sequences after load thus switching charttypes afterwards produces expected results now
2009-03-26 10:22:55 +0100 iha  r270056 : #i64689# bubble chart
2009-03-24 17:45:15 +0100 iha  r269984 : #i64689# bubble chart - user properties from points (not only from the series)
2009-03-24 15:10:57 +0100 dr  r269954 : #i64989# export bubble charts to xls
2009-03-24 14:55:29 +0100 dr  r269952 : #i64989# import bubble charts from xls
2009-03-24 14:54:46 +0100 dr  r269950 : #i64989# import bubble charts from ooxml
2009-03-23 18:59:08 +0100 iha  r269895 : further cleanups possible with new member m_aGlobalSeriesImportInfo
2009-03-23 16:54:04 +0100 iha  r269886 : #i64689# bubble chart - a single sequence must be interpreted as sizes because of ODF specification
2009-03-23 16:50:43 +0100 iha  r269885 : #i64689# save&load bubble chart
2009-03-20 19:30:29 +0100 iha  r269826 : CWS-TOOLING: rebase CWS bubblechart to trunk@269781 (milestone: DEV300:m44)
2009-03-19 11:30:33 +0100 iha  r269732 : #i64689# rename SchXMLCategoriesDomainContext to SchXMLCategoriesContext avoid confusion with domains
2009-03-18 17:11:13 +0100 iha  r269693 : #i64689# add charttype bubble
2009-03-18 17:09:22 +0100 iha  r269692 : #i64689# remove unused code
2009-03-13 12:18:26 +0100 iha  r269467 : #i64689# corrected lineends
2009-03-12 11:25:14 +0100 iha  r269376 : #i64689# bubble chart (part 1)
2009-07-02 19:17:43 +00:00

844 lines
30 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: DialogModel.cxx,v $
* $Revision: 1.7.16.1 $
*
* 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 "DialogModel.hxx"
#include "RangeSelectionHelper.hxx"
#include "PropertyHelper.hxx"
#include "DataSeriesHelper.hxx"
#include "DataSourceHelper.hxx"
#include "DiagramHelper.hxx"
#include "macros.hxx"
#include "Strings.hrc"
#include "ResId.hxx"
#include "ContainerHelper.hxx"
#include "CommonFunctors.hxx"
#include "ControllerLockGuard.hxx"
#include "ChartTypeHelper.hxx"
#include <com/sun/star/util/XCloneable.hpp>
#include <com/sun/star/chart2/AxisType.hpp>
#include <com/sun/star/chart2/XTitled.hpp>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
#include <com/sun/star/chart2/XChartTypeContainer.hpp>
#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
#include <com/sun/star/chart2/data/XDataSink.hpp>
#include <tools/string.hxx>
#include <utility>
#include <algorithm>
#include <iterator>
#include <functional>
#include <numeric>
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;
using namespace ::chart::ContainerHelper;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::rtl::OUString;
// ----------------------------------------
namespace
{
const OUString lcl_aLabelRole( RTL_CONSTASCII_USTRINGPARAM( "label" ));
struct lcl_ChartTypeToSeriesCnt : ::std::unary_function<
Reference< XChartType >, Reference< XDataSeriesContainer > >
{
Reference< XDataSeriesContainer > operator() (
const Reference< XChartType > & xChartType )
{
return Reference< XDataSeriesContainer >::query( xChartType );
}
};
OUString lcl_ConvertRole( const OUString & rRoleString, bool bFromInternalToUI )
{
OUString aResult( rRoleString );
typedef ::std::map< OUString, OUString > tTranslationMap;
static tTranslationMap aTranslationMap;
if( aTranslationMap.size() == 0 )
{
aTranslationMap[ C2U( "categories" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_CATEGORIES )));
aTranslationMap[ C2U( "error-bars-x" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X_ERROR )));
aTranslationMap[ C2U( "error-bars-x-positive" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X_ERROR_POSITIVE )));
aTranslationMap[ C2U( "error-bars-x-negative" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X_ERROR_NEGATIVE )));
aTranslationMap[ C2U( "error-bars-y" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y_ERROR )));
aTranslationMap[ C2U( "error-bars-y-positive" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_POSITIVE )));
aTranslationMap[ C2U( "error-bars-y-negative" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_NEGATIVE )));
aTranslationMap[ C2U( "label" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_LABEL )));
aTranslationMap[ C2U( "values-first" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_FIRST )));
aTranslationMap[ C2U( "values-last" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_LAST )));
aTranslationMap[ C2U( "values-max" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_MAX )));
aTranslationMap[ C2U( "values-min" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_MIN )));
aTranslationMap[ C2U( "values-x" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X )));
aTranslationMap[ C2U( "values-y" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y )));
aTranslationMap[ C2U( "values-size" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_SIZE )));
}
if( bFromInternalToUI )
{
tTranslationMap::const_iterator aIt( aTranslationMap.find( rRoleString ));
if( aIt != aTranslationMap.end())
{
aResult = (*aIt).second;
}
}
else
{
tTranslationMap::const_iterator aIt(
::std::find_if( aTranslationMap.begin(), aTranslationMap.end(),
::std::compose1( ::std::bind2nd(
::std::equal_to< tTranslationMap::mapped_type >(),
rRoleString ),
::std::select2nd< tTranslationMap::value_type >())));
if( aIt != aTranslationMap.end())
aResult = (*aIt).first;
}
return aResult;
}
typedef ::std::map< ::rtl::OUString, sal_Int32 > lcl_tRoleIndexMap;
void lcl_createRoleIndexMap( lcl_tRoleIndexMap & rOutMap )
{
rOutMap.clear();
sal_Int32 nIndex = 0;
rOutMap[ C2U( "label" ) ] = ++nIndex;
rOutMap[ C2U( "categories" ) ] = ++nIndex;
rOutMap[ C2U( "values-x" ) ] = ++nIndex;
rOutMap[ C2U( "values-y" ) ] = ++nIndex;
rOutMap[ C2U( "error-bars-x" ) ] = ++nIndex;
rOutMap[ C2U( "error-bars-x-positive" ) ] = ++nIndex;
rOutMap[ C2U( "error-bars-x-negative" ) ] = ++nIndex;
rOutMap[ C2U( "error-bars-y" ) ] = ++nIndex;
rOutMap[ C2U( "error-bars-y-positive" ) ] = ++nIndex;
rOutMap[ C2U( "error-bars-y-negative" ) ] = ++nIndex;
rOutMap[ C2U( "values-first" ) ] = ++nIndex;
rOutMap[ C2U( "values-min" ) ] = ++nIndex;
rOutMap[ C2U( "values-max" ) ] = ++nIndex;
rOutMap[ C2U( "values-last" ) ] = ++nIndex;
rOutMap[ C2U( "values-size" ) ] = ++nIndex;
}
struct lcl_DataSeriesContainerAppend : public
::std::iterator< ::std::output_iterator_tag, Reference< XDataSeriesContainer > >
{
typedef ::std::vector< chart::DialogModel::tSeriesWithChartTypeByName > tContainerType;
explicit lcl_DataSeriesContainerAppend( tContainerType & rCnt )
: m_rDestCnt( rCnt )
{}
lcl_DataSeriesContainerAppend & operator= ( const value_type & xVal )
{
try
{
if( xVal.is())
{
Sequence< Reference< XDataSeries > > aSeq( xVal->getDataSeries());
OUString aRole( RTL_CONSTASCII_USTRINGPARAM("values-y"));
Reference< XChartType > xCT( xVal, uno::UNO_QUERY );
if( xCT.is())
aRole = xCT->getRoleOfSequenceForSeriesLabel();
for( sal_Int32 nI = 0; nI < aSeq.getLength(); ++ nI )
{
m_rDestCnt.push_back(
chart::DialogModel::tSeriesWithChartTypeByName(
::chart::DataSeriesHelper::getDataSeriesLabel( aSeq[nI], aRole ),
::std::make_pair( aSeq[nI], xCT )));
}
}
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
return *this;
}
lcl_DataSeriesContainerAppend & operator* () { return *this; }
lcl_DataSeriesContainerAppend & operator++ () { return *this; }
lcl_DataSeriesContainerAppend & operator++ (int) { return *this; }
private:
tContainerType & m_rDestCnt;
};
struct lcl_RolesWithRangeAppend : public
::std::iterator< ::std::output_iterator_tag, Reference< data::XLabeledDataSequence > >
{
typedef ::chart::DialogModel::tRolesWithRanges tContainerType;
explicit lcl_RolesWithRangeAppend( tContainerType & rCnt,
const ::rtl::OUString & aLabelRole )
: m_rDestCnt( rCnt ),
m_aRoleForLabelSeq( aLabelRole )
{}
lcl_RolesWithRangeAppend & operator= ( const value_type & xVal )
{
try
{
if( xVal.is())
{
// data sequence
Reference< data::XDataSequence > xSeq( xVal->getValues());
if( xSeq.is())
{
OUString aRole;
Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
if( xProp->getPropertyValue( C2U("Role")) >>= aRole )
{
m_rDestCnt.insert(
tContainerType::value_type(
aRole, xSeq->getSourceRangeRepresentation()));
// label
if( aRole.equals( m_aRoleForLabelSeq ))
{
Reference< data::XDataSequence > xLabelSeq( xVal->getLabel());
if( xLabelSeq.is())
{
m_rDestCnt.insert(
tContainerType::value_type(
lcl_aLabelRole, xLabelSeq->getSourceRangeRepresentation()));
}
}
}
}
}
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
return *this;
}
lcl_RolesWithRangeAppend & operator* () { return *this; }
lcl_RolesWithRangeAppend & operator++ () { return *this; }
lcl_RolesWithRangeAppend & operator++ (int) { return *this; }
private:
tContainerType & m_rDestCnt;
OUString m_aRoleForLabelSeq;
};
void lcl_SetSequenceRole(
const Reference< data::XDataSequence > & xSeq,
const OUString & rRole )
{
Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
if( xProp.is())
xProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole ));
}
Reference< XDataSeries > lcl_CreateNewSeries(
const Reference< uno::XComponentContext > & xContext,
const Reference< XChartType > & xChartType,
sal_Int32 nNewSeriesIndex,
sal_Int32 nTotalNumberOfSeriesInCTGroup,
const Reference< XDiagram > & xDiagram,
const Reference< XChartTypeTemplate > & xTemplate,
bool bCreateDataCachedSequences )
{
// create plain series
Reference< XDataSeries > xResult(
xContext->getServiceManager()->createInstanceWithContext(
C2U( "com.sun.star.chart2.DataSeries" ),
xContext ), uno::UNO_QUERY );
if( xTemplate.is())
{
Reference< beans::XPropertySet > xResultProp( xResult, uno::UNO_QUERY );
if( xResultProp.is())
{
// @deprecated: correct default color should be found by view
// without setting it as hard attribute
Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
if( xColorScheme.is())
xResultProp->setPropertyValue(
C2U("Color"), uno::makeAny( xColorScheme->getColorByIndex( nNewSeriesIndex )));
}
sal_Int32 nGroupIndex=0;
if( xChartType.is())
{
Sequence< Reference< XChartType > > aCTs(
::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ));
for( ; nGroupIndex<aCTs.getLength(); ++nGroupIndex)
if( aCTs[nGroupIndex] == xChartType )
break;
if( nGroupIndex == aCTs.getLength())
nGroupIndex = 0;
}
xTemplate->applyStyle( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup );
}
if( bCreateDataCachedSequences )
{
// set chart type specific roles
Reference< data::XDataSink > xSink( xResult, uno::UNO_QUERY );
if( xChartType.is() && xSink.is())
{
::std::vector< Reference< data::XLabeledDataSequence > > aNewSequences;
const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel();
const OUString aLabel( String( ::chart::SchResId( STR_DATA_UNNAMED_SERIES )));
const Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles());
const Sequence< OUString > aOptRoles( xChartType->getSupportedOptionalRoles());
sal_Int32 nI = 0;
for(nI=0; nI<aRoles.getLength(); ++nI)
{
if( aRoles[nI].equals( lcl_aLabelRole ))
continue;
Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence() );
lcl_SetSequenceRole( xSeq, aRoles[nI] );
// assert that aRoleOfSeqForSeriesLabel is part of the mandatory roles
if( aRoles[nI].equals( aRoleOfSeqForSeriesLabel ))
{
Reference< data::XDataSequence > xLabel( ::chart::DataSourceHelper::createCachedDataSequence( aLabel ));
lcl_SetSequenceRole( xLabel, lcl_aLabelRole );
aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq, xLabel ));
}
else
aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
}
for(nI=0; nI<aOptRoles.getLength(); ++nI)
{
if( aOptRoles[nI].equals( lcl_aLabelRole ))
continue;
Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence());
lcl_SetSequenceRole( xSeq, aOptRoles[nI] );
aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
}
xSink->setData( ContainerToSequence( aNewSequences ));
}
}
return xResult;
}
struct lcl_addSeriesNumber : public ::std::binary_function<
sal_Int32, Reference< XDataSeriesContainer >, sal_Int32 >
{
sal_Int32 operator() ( sal_Int32 nCurrentNumber, const Reference< XDataSeriesContainer > & xCnt ) const
{
if( xCnt.is())
return nCurrentNumber + (xCnt->getDataSeries().getLength());
return nCurrentNumber;
}
};
} // anonymous namespace
// ----------------------------------------
namespace chart
{
DialogModel::DialogModel(
const Reference< XChartDocument > & xChartDocument,
const Reference< uno::XComponentContext > & xContext ) :
m_xChartDocument( xChartDocument ),
m_xContext( xContext ),
m_aTimerTriggeredControllerLock( uno::Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) )
{
createBackup();
}
DialogModel::~DialogModel()
{}
void DialogModel::setTemplate(
const Reference< XChartTypeTemplate > & xTemplate )
{
m_xTemplate = xTemplate;
}
::boost::shared_ptr< RangeSelectionHelper >
DialogModel::getRangeSelectionHelper() const
{
if( ! m_spRangeSelectionHelper.get())
m_spRangeSelectionHelper.reset(
new RangeSelectionHelper( m_xChartDocument ));
return m_spRangeSelectionHelper;
}
Reference< frame::XModel > DialogModel::getChartModel() const
{
Reference< frame::XModel > xResult( m_xChartDocument, uno::UNO_QUERY );
return xResult;
}
Reference< data::XDataProvider > DialogModel::getDataProvider() const
{
Reference< data::XDataProvider > xResult;
if( m_xChartDocument.is())
xResult.set( m_xChartDocument->getDataProvider());
return xResult;
}
::std::vector< Reference< XDataSeriesContainer > >
DialogModel::getAllDataSeriesContainers() const
{
::std::vector< Reference< XDataSeriesContainer > > aResult;
try
{
Reference< XDiagram > xDiagram;
if( m_xChartDocument.is())
xDiagram.set( m_xChartDocument->getFirstDiagram());
if( xDiagram.is())
{
Reference< XCoordinateSystemContainer > xCooSysCnt(
xDiagram, uno::UNO_QUERY_THROW );
Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
xCooSysCnt->getCoordinateSystems());
for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
{
Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
::std::transform(
aChartTypeSeq.getConstArray(), aChartTypeSeq.getConstArray() + aChartTypeSeq.getLength(),
::std::back_inserter( aResult ),
lcl_ChartTypeToSeriesCnt() );
}
}
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
return aResult;
}
::std::vector< DialogModel::tSeriesWithChartTypeByName >
DialogModel::getAllDataSeriesWithLabel() const
{
::std::vector< tSeriesWithChartTypeByName > aResult;
::std::vector< Reference< XDataSeriesContainer > > aContainers(
getAllDataSeriesContainers());
::std::copy( aContainers.begin(), aContainers.end(),
lcl_DataSeriesContainerAppend( aResult ));
return aResult;
}
DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges(
const Reference< XDataSeries > & xSeries,
const ::rtl::OUString & aRoleOfSequenceForLabel,
const Reference< chart2::XChartType > & xChartType ) const
{
DialogModel::tRolesWithRanges aResult;
try
{
Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW );
const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
::std::copy( aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength(),
lcl_RolesWithRangeAppend( aResult, aRoleOfSequenceForLabel ));
if( xChartType.is())
{
// add missing mandatory roles
Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles());
OUString aEmptyString;
sal_Int32 nI = 0;
for( nI=0; nI < aRoles.getLength(); ++nI )
{
if( aResult.find( aRoles[nI] ) == aResult.end() )
aResult.insert( DialogModel::tRolesWithRanges::value_type( aRoles[nI], aEmptyString ));
}
// add missing optional roles
aRoles = xChartType->getSupportedOptionalRoles();
for( nI=0; nI < aRoles.getLength(); ++nI )
{
if( aResult.find( aRoles[nI] ) == aResult.end() )
aResult.insert( DialogModel::tRolesWithRanges::value_type( aRoles[nI], aEmptyString ));
}
}
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
return aResult;
}
void DialogModel::moveSeries(
const Reference< XDataSeries > & xSeries,
eMoveDirection eDirection )
{
m_aTimerTriggeredControllerLock.startTimer();
ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MOVE_UP );
}
Reference< chart2::XDataSeries > DialogModel::insertSeriesAfter(
const Reference< XDataSeries > & xSeries,
const Reference< XChartType > & xChartType,
bool bCreateDataCachedSequences /* = false */ )
{
m_aTimerTriggeredControllerLock.startTimer();
ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
Reference< XDataSeries > xNewSeries;
try
{
sal_Int32 nSeriesInChartType = 0;
const sal_Int32 nTotalSeries = countSeries();
if( xChartType.is())
{
Reference< XDataSeriesContainer > xCnt( xChartType, uno::UNO_QUERY_THROW );
nSeriesInChartType = xCnt->getDataSeries().getLength();
}
// create new series
xNewSeries.set(
lcl_CreateNewSeries(
m_xContext,
xChartType,
nTotalSeries, // new series' index
nSeriesInChartType,
m_xChartDocument->getFirstDiagram(),
m_xTemplate,
bCreateDataCachedSequences ));
// add new series to container
if( xNewSeries.is())
{
Reference< XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW );
::std::vector< Reference< XDataSeries > > aSeries(
SequenceToVector( xSeriesCnt->getDataSeries()));
::std::vector< Reference< XDataSeries > >::iterator aIt =
::std::find( aSeries.begin(), aSeries.end(), xSeries );
if( aIt == aSeries.end())
// if we have no series we insert at the first position.
aIt = aSeries.begin();
else
// vector::insert inserts before, so we have to advance
++aIt;
aSeries.insert( aIt, xNewSeries );
xSeriesCnt->setDataSeries( ContainerToSequence( aSeries ));
}
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
return xNewSeries;
}
void DialogModel::deleteSeries(
const Reference< XDataSeries > & xSeries,
const Reference< XChartType > & xChartType )
{
m_aTimerTriggeredControllerLock.startTimer();
ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
DataSeriesHelper::deleteSeries( xSeries, xChartType );
}
Reference< data::XLabeledDataSequence > DialogModel::getCategories() const
{
Reference< data::XLabeledDataSequence > xResult;
try
{
if( m_xChartDocument.is())
{
Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
xResult.set( DiagramHelper::getCategoriesFromDiagram( xDiagram ));
}
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
return xResult;
}
void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories )
{
if( m_xChartDocument.is())
{
Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
if( xDiagram.is())
{
// categories
bool bSupportsCategories = true;
Reference< XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
if( xFirstChartType.is() )
{
sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis
bSupportsCategories = (nAxisType == AxisType::CATEGORY);
}
DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram, true, bSupportsCategories );
}
}
}
OUString DialogModel::getCategoriesRange() const
{
Reference< data::XLabeledDataSequence > xLSeq( getCategories());
OUString aRange;
if( xLSeq.is())
{
Reference< data::XDataSequence > xSeq( xLSeq->getValues());
if( xSeq.is())
aRange = xSeq->getSourceRangeRepresentation();
}
return aRange;
}
bool DialogModel::isCategoryDiagram() const
{
bool bRet = false;
if( m_xChartDocument.is())
bRet = DiagramHelper::isCategoryDiagram( m_xChartDocument->getFirstDiagram() );
return bRet;
}
void DialogModel::detectArguments(
OUString & rOutRangeString,
bool & rOutUseColumns,
bool & rOutFirstCellAsLabel,
bool & rOutHasCategories ) const
{
try
{
uno::Sequence< sal_Int32 > aSequenceMapping;//todo YYYX
// Note: unused data is currently not supported in being passed to detectRangeSegmentation
if( m_xChartDocument.is())
DataSourceHelper::detectRangeSegmentation(
Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY_THROW ),
rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories );
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
}
bool DialogModel::allArgumentsForRectRangeDetected() const
{
return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument );
}
void DialogModel::startControllerLockTimer()
{
m_aTimerTriggeredControllerLock.startTimer();
}
bool DialogModel::setData(
const Sequence< beans::PropertyValue > & rArguments )
{
m_aTimerTriggeredControllerLock.startTimer();
ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
Reference< data::XDataProvider > xDataProvider( getDataProvider());
if( ! xDataProvider.is() ||
! m_xTemplate.is() )
{
OSL_ENSURE( false, "Model objects missing" );
return false;
}
try
{
Reference< chart2::data::XDataSource > xDataSource(
xDataProvider->createDataSource( rArguments ) );
Reference< chart2::XDataInterpreter > xInterpreter(
m_xTemplate->getDataInterpreter());
if( xInterpreter.is())
{
::std::vector< Reference< XDataSeries > > aSeriesToReUse(
DiagramHelper::getDataSeriesFromDiagram( m_xChartDocument->getFirstDiagram()));
applyInterpretedData(
xInterpreter->interpretDataSource(
xDataSource, rArguments,
ContainerToSequence( aSeriesToReUse )),
aSeriesToReUse,
true /* bSetStyles */);
}
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
return false;
}
return true;
}
// static
OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString )
{
return lcl_ConvertRole( rRoleString, true );
}
// static
OUString DialogModel::GetRoleDataLabel()
{
return OUString( String( ::chart::SchResId( STR_OBJECT_DATALABELS )));
}
// static
sal_Int32 DialogModel::GetRoleIndexForSorting( const ::rtl::OUString & rInternalRoleString )
{
static lcl_tRoleIndexMap aRoleIndexMap;
if( aRoleIndexMap.empty())
lcl_createRoleIndexMap( aRoleIndexMap );
lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString ));
if( aIt != aRoleIndexMap.end())
return aIt->second;
return 0;
}
// private methods
void DialogModel::createBackup()
{
OSL_ENSURE( ! m_xBackupChartDocument.is(), "Cloning already cloned model" );
try
{
Reference< util::XCloneable > xCloneable( m_xChartDocument, uno::UNO_QUERY_THROW );
m_xBackupChartDocument.set( xCloneable->createClone(), uno::UNO_QUERY_THROW );
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
}
void DialogModel::applyInterpretedData(
const InterpretedData & rNewData,
const ::std::vector< Reference< XDataSeries > > & rSeriesToReUse,
bool bSetStyles )
{
if( ! m_xChartDocument.is())
return;
m_aTimerTriggeredControllerLock.startTimer();
Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
if( xDiagram.is())
{
// styles
if( bSetStyles && m_xTemplate.is() )
{
sal_Int32 nGroup = 0;
sal_Int32 nSeriesCounter = 0;
sal_Int32 nNewSeriesIndex = static_cast< sal_Int32 >( rSeriesToReUse.size());
const sal_Int32 nOuterSize=rNewData.Series.getLength();
for(; nGroup < nOuterSize; ++nGroup)
{
Sequence< Reference< XDataSeries > > aSeries( rNewData.Series[ nGroup ] );
const sal_Int32 nSeriesInGroup = aSeries.getLength();
for( sal_Int32 nSeries=0; nSeries<nSeriesInGroup; ++nSeries, ++nSeriesCounter )
{
if( ::std::find( rSeriesToReUse.begin(), rSeriesToReUse.end(), aSeries[nSeries] )
== rSeriesToReUse.end())
{
Reference< beans::XPropertySet > xSeriesProp( aSeries[nSeries], uno::UNO_QUERY );
if( xSeriesProp.is())
{
// @deprecated: correct default color should be found by view
// without setting it as hard attribute
Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
if( xColorScheme.is())
xSeriesProp->setPropertyValue(
C2U("Color"), uno::makeAny( xColorScheme->getColorByIndex( nSeriesCounter )));
}
m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup );
}
}
}
}
// data series
::std::vector< Reference< XDataSeriesContainer > > aSeriesCnt( getAllDataSeriesContainers());
::std::vector< Sequence< Reference< XDataSeries > > > aNewSeries(
SequenceToVector( rNewData.Series ));
OSL_ASSERT( aSeriesCnt.size() == aNewSeries.size());
::std::vector< Sequence< Reference< XDataSeries > > >::const_iterator aSrcIt( aNewSeries.begin());
::std::vector< Reference< XDataSeriesContainer > >::iterator aDestIt( aSeriesCnt.begin());
for(; aSrcIt != aNewSeries.end() && aDestIt != aSeriesCnt.end();
++aSrcIt, ++aDestIt )
{
try
{
OSL_ASSERT( (*aDestIt).is());
(*aDestIt)->setDataSeries( *aSrcIt );
}
catch( uno::Exception & ex )
{
ASSERT_EXCEPTION( ex );
}
}
DialogModel::setCategories(rNewData.Categories);
}
OSL_ASSERT( ! rNewData.UnusedData.hasElements());
}
sal_Int32 DialogModel::countSeries() const
{
::std::vector< Reference< XDataSeriesContainer > > aCnt( getAllDataSeriesContainers());
return ::std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber());
}
} // namespace chart