diff options
Diffstat (limited to '')
-rw-r--r-- | chart2/source/controller/dialogs/DialogModel.cxx | 841 |
1 files changed, 841 insertions, 0 deletions
diff --git a/chart2/source/controller/dialogs/DialogModel.cxx b/chart2/source/controller/dialogs/DialogModel.cxx new file mode 100644 index 000000000..2d12bc6cd --- /dev/null +++ b/chart2/source/controller/dialogs/DialogModel.cxx @@ -0,0 +1,841 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "DialogModel.hxx" +#include <RangeSelectionHelper.hxx> +#include <DataInterpreter.hxx> +#include <DataSeries.hxx> +#include <DataSeriesHelper.hxx> +#include <DataSourceHelper.hxx> +#include <DiagramHelper.hxx> +#include <Diagram.hxx> +#include <strings.hrc> +#include <ResId.hxx> +#include <ControllerLockGuard.hxx> +#include <ChartType.hxx> +#include <ChartTypeHelper.hxx> +#include <ChartTypeTemplate.hxx> +#include <ThreeDHelper.hxx> +#include <ChartModel.hxx> +#include <BaseCoordinateSystem.hxx> +#include <LabeledDataSequence.hxx> + +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <tools/diagnose_ex.h> + +#include <rtl/ustring.hxx> + +#include <utility> +#include <algorithm> +#include <cstddef> +#include <iterator> +#include <numeric> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ +constexpr OUStringLiteral lcl_aLabelRole( u"label" ); + + +OUString lcl_ConvertRole( const OUString & rRoleString ) +{ + OUString aResult( rRoleString ); + + typedef std::map< OUString, OUString > tTranslationMap; + static const tTranslationMap aTranslationMap = + { + { "categories", ::chart::SchResId( STR_DATA_ROLE_CATEGORIES ) }, + { "error-bars-x", ::chart::SchResId( STR_DATA_ROLE_X_ERROR ) }, + { "error-bars-x-positive", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_POSITIVE ) }, + { "error-bars-x-negative", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_NEGATIVE ) }, + { "error-bars-y", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR ) }, + { "error-bars-y-positive", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_POSITIVE ) }, + { "error-bars-y-negative", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_NEGATIVE ) }, + { "label", ::chart::SchResId( STR_DATA_ROLE_LABEL ) }, + { "values-first", ::chart::SchResId( STR_DATA_ROLE_FIRST ) }, + { "values-last", ::chart::SchResId( STR_DATA_ROLE_LAST ) }, + { "values-max", ::chart::SchResId( STR_DATA_ROLE_MAX ) }, + { "values-min", ::chart::SchResId( STR_DATA_ROLE_MIN ) }, + { "values-x", ::chart::SchResId( STR_DATA_ROLE_X ) }, + { "values-y", ::chart::SchResId( STR_DATA_ROLE_Y ) }, + { "values-size", ::chart::SchResId( STR_DATA_ROLE_SIZE ) }, + { "FillColor", ::chart::SchResId( STR_PROPERTY_ROLE_FILLCOLOR ) }, + { "BorderColor", ::chart::SchResId( STR_PROPERTY_ROLE_BORDERCOLOR ) }, + }; + + tTranslationMap::const_iterator aIt( aTranslationMap.find( rRoleString )); + if( aIt != aTranslationMap.end()) + { + aResult = (*aIt).second; + } + return aResult; +} + +typedef std::map< OUString, sal_Int32 > lcl_tRoleIndexMap; + +lcl_tRoleIndexMap lcl_createRoleIndexMap() +{ + lcl_tRoleIndexMap aMap; + sal_Int32 nIndex = 0; + + aMap[ "label" ] = ++nIndex; + aMap[ "categories" ] = ++nIndex; + aMap[ "values-x" ] = ++nIndex; + aMap[ "values-y" ] = ++nIndex; + aMap[ "error-bars-x" ] = ++nIndex; + aMap[ "error-bars-x-positive" ] = ++nIndex; + aMap[ "error-bars-x-negative" ] = ++nIndex; + aMap[ "error-bars-y" ] = ++nIndex; + aMap[ "error-bars-y-positive" ] = ++nIndex; + aMap[ "error-bars-y-negative" ] = ++nIndex; + aMap[ "values-first" ] = ++nIndex; + aMap[ "values-min" ] = ++nIndex; + aMap[ "values-max" ] = ++nIndex; + aMap[ "values-last" ] = ++nIndex; + aMap[ "values-size" ] = ++nIndex; + + return aMap; +} + + +struct lcl_RolesWithRangeAppend +{ + typedef Reference< data::XLabeledDataSequence > value_type; + typedef ::chart::DialogModel::tRolesWithRanges tContainerType; + + explicit lcl_RolesWithRangeAppend( tContainerType * rCnt, + const 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( "Role" ) >>= aRole ) + { + m_rDestCnt->emplace(aRole, xSeq->getSourceRangeRepresentation()); + // label + if( aRole == m_aRoleForLabelSeq ) + { + Reference< data::XDataSequence > xLabelSeq( xVal->getLabel()); + if( xLabelSeq.is()) + { + m_rDestCnt->emplace( + lcl_aLabelRole, xLabelSeq->getSourceRangeRepresentation()); + } + } + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return *this; + } + + // Implement output operator requirements as required by std::copy (and + // implement prefix increment in terms of postfix increment to avoid unused + // member function warnings for the latter in the common case where + // std::copy would not actually need it): + lcl_RolesWithRangeAppend & operator* () { return *this; } + lcl_RolesWithRangeAppend & operator++ () { return operator++(0); } + lcl_RolesWithRangeAppend & operator++ (int) { return *this; } + +private: + tContainerType * m_rDestCnt; + OUString m_aRoleForLabelSeq; +}; + +} + +namespace std +{ + template<> struct iterator_traits<lcl_RolesWithRangeAppend> + { + typedef std::output_iterator_tag iterator_category; + typedef Reference< data::XLabeledDataSequence > value_type; + typedef value_type& reference; + }; +} + +namespace { + +void lcl_SetSequenceRole( + const Reference< data::XDataSequence > & xSeq, + const OUString & rRole ) +{ + Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY ); + if( xProp.is()) + xProp->setPropertyValue( "Role" , uno::Any( rRole )); +} + +Sequence< OUString > lcl_CopyExcludingValuesFirst( + Sequence< OUString > const & i_aInput ) +{ + Sequence< OUString > aOutput( i_aInput.getLength()); + auto pOutput = aOutput.getArray(); + int nSourceIndex, nDestIndex; + for( nSourceIndex = nDestIndex = 0; nSourceIndex < i_aInput.getLength(); nSourceIndex++ ) + { + if( i_aInput[nSourceIndex] == "values-first" ) + { + aOutput.realloc( aOutput.getLength() - 1 ); + pOutput = aOutput.getArray(); + } + else + { + pOutput[nDestIndex] = i_aInput[nSourceIndex]; + nDestIndex++; + } + } + return aOutput; +} + +rtl::Reference< ::chart::DataSeries > lcl_CreateNewSeries( + const rtl::Reference< ::chart::ChartType > & xChartType, + sal_Int32 nNewSeriesIndex, + sal_Int32 nTotalNumberOfSeriesInCTGroup, + const rtl::Reference< ::chart::Diagram > & xDiagram, + const rtl::Reference< ::chart::ChartTypeTemplate > & xTemplate, + bool bCreateDataCachedSequences ) +{ + // create plain series + rtl::Reference< ::chart::DataSeries > xResult = new ::chart::DataSeries(); + if( xTemplate.is()) + { + // @deprecated: correct default color should be found by view + // without setting it as hard attribute + Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + if( xColorScheme.is()) + xResult->setPropertyValue( "Color" , uno::Any( xColorScheme->getColorByIndex( nNewSeriesIndex ))); + std::size_t nGroupIndex=0; + if( xChartType.is()) + { + std::vector< rtl::Reference< ::chart::ChartType > > aCTs( + ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram )); + for( ; nGroupIndex < aCTs.size(); ++nGroupIndex) + if( aCTs[nGroupIndex] == xChartType ) + break; + if( nGroupIndex == aCTs.size()) + nGroupIndex = 0; + } + xTemplate->applyStyle2( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup ); + } + + if( bCreateDataCachedSequences ) + { + // set chart type specific roles + if( xChartType.is() ) + { + std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences; + const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel(); + const OUString aLabel(::chart::SchResId(STR_DATA_UNNAMED_SERIES)); + Sequence< OUString > aPossibleRoles( xChartType->getSupportedMandatoryRoles()); + Sequence< OUString > aPossibleOptRoles( xChartType->getSupportedOptionalRoles()); + + //special handling for candlestick type + if( xTemplate.is()) + { + rtl::Reference< ::chart::DataInterpreter > xInterpreter( xTemplate->getDataInterpreter2()); + if( xInterpreter.is()) + { + sal_Int32 nStockVariant; + if( xInterpreter->getChartTypeSpecificData("stock variant") >>= nStockVariant ) + { + if( nStockVariant == 0 || nStockVariant == 2) { + //delete "values-first" role + aPossibleRoles = lcl_CopyExcludingValuesFirst(aPossibleRoles); + aPossibleOptRoles = lcl_CopyExcludingValuesFirst(aPossibleOptRoles); + } + } + } + } + + const Sequence< OUString > aRoles( aPossibleRoles ); + const Sequence< OUString > aOptRoles( aPossibleOptRoles ); + + for(OUString const & role : aRoles) + { + if( role == lcl_aLabelRole ) + continue; + Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence() ); + lcl_SetSequenceRole( xSeq, role ); + // assert that aRoleOfSeqForSeriesLabel is part of the mandatory roles + if( role == 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(OUString const & role : aOptRoles) + { + if( role == lcl_aLabelRole ) + continue; + Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence()); + lcl_SetSequenceRole( xSeq, role ); + aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq )); + } + + xResult->setData( aNewSequences ); + } + } + + return xResult; +} + +struct lcl_addSeriesNumber +{ + 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 +{ + +DialogModelTimeBasedInfo::DialogModelTimeBasedInfo(): + bTimeBased(false), + nStart(0), + nEnd(0) +{ +} + +DialogModel::DialogModel( + const rtl::Reference<::chart::ChartModel> & xChartDocument ) : + m_xChartDocument( xChartDocument ), + m_aTimerTriggeredControllerLock( m_xChartDocument ) +{ +} + +DialogModel::~DialogModel() +{ + if(maTimeBasedInfo.bTimeBased) + { + getModel().setTimeBasedRange(maTimeBasedInfo.nStart, maTimeBasedInfo.nEnd); + } +} + +void DialogModel::setTemplate( + const rtl::Reference< ChartTypeTemplate > & xTemplate ) +{ + m_xTemplate = xTemplate; +} + +std::shared_ptr< RangeSelectionHelper > const & + DialogModel::getRangeSelectionHelper() const +{ + if( ! m_spRangeSelectionHelper) + m_spRangeSelectionHelper = + std::make_shared<RangeSelectionHelper>( m_xChartDocument ); + + return m_spRangeSelectionHelper; +} + +const rtl::Reference<::chart::ChartModel> & DialogModel::getChartModel() const +{ + return m_xChartDocument; +} + +Reference< data::XDataProvider > DialogModel::getDataProvider() const +{ + Reference< data::XDataProvider > xResult; + if( m_xChartDocument.is()) + xResult.set( m_xChartDocument->getDataProvider()); + return xResult; +} + +std::vector< rtl::Reference< ChartType > > + DialogModel::getAllDataSeriesContainers() const +{ + std::vector< rtl::Reference< ChartType > > aResult; + + try + { + if( !m_xChartDocument ) + return {}; + rtl::Reference< Diagram > xDiagram = m_xChartDocument->getFirstChartDiagram(); + if( xDiagram.is()) + { + const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq( + xDiagram->getBaseCoordinateSystems()); + for( rtl::Reference< BaseCoordinateSystem > const & coords : aCooSysSeq ) + { + + for (const auto & rxChartType : coords->getChartTypes2()) + aResult.push_back(rxChartType); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return aResult; +} + +std::vector< DialogModel::tSeriesWithChartTypeByName > + DialogModel::getAllDataSeriesWithLabel() const +{ + std::vector< tSeriesWithChartTypeByName > aResult; + std::vector< rtl::Reference< ChartType > > aContainers( + getAllDataSeriesContainers()); + + for (const auto & rxChartType : aContainers ) + { + try + { + const std::vector< rtl::Reference< DataSeries > > & aSeq = rxChartType->getDataSeries2(); + OUString aRole = rxChartType->getRoleOfSequenceForSeriesLabel(); + for( rtl::Reference< DataSeries > const & dataSeries : aSeq ) + { + aResult.push_back( + ::chart::DialogModel::tSeriesWithChartTypeByName( + ::chart::DataSeriesHelper::getDataSeriesLabel( dataSeries, aRole ), + std::make_pair( dataSeries, rxChartType ))); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return aResult; +} + +namespace { + +void addMissingRoles(DialogModel::tRolesWithRanges& rResult, const uno::Sequence<OUString>& rRoles) +{ + for(OUString const & role : rRoles) + { + if(rResult.find(role) == rResult.end()) + rResult.emplace(role, OUString()); + } +} + +/** + * Insert a new data series to chart type at position after specified series + * position. + * + * @param xChartType chart type that contains data series. + * @param xSeries insertion position. The new series will be inserted after + * this one. + * @param xNewSeries new data series to insert. + */ +void addNewSeriesToContainer( + const rtl::Reference<ChartType>& xChartType, + const rtl::Reference<DataSeries>& xSeries, + const rtl::Reference<DataSeries>& xNewSeries ) +{ + auto aSeries = xChartType->getDataSeries2(); + + auto 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); + xChartType->setDataSeries(aSeries); +} + +} + +DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges( + const Reference< XDataSeries > & xSeries, + const OUString & aRoleOfSequenceForLabel, + const rtl::Reference< ::chart::ChartType > & xChartType ) +{ + DialogModel::tRolesWithRanges aResult; + try + { + Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW ); + const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences()); + std::copy( aSeq.begin(), aSeq.end(), + lcl_RolesWithRangeAppend( &aResult, aRoleOfSequenceForLabel )); + if( xChartType.is()) + { + // add missing mandatory roles + Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles()); + addMissingRoles(aResult, aRoles); + + // add missing optional roles + aRoles = xChartType->getSupportedOptionalRoles(); + addMissingRoles(aResult, aRoles); + + // add missing property roles + aRoles = xChartType->getSupportedPropertyRoles(); + addMissingRoles(aResult, aRoles); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return aResult; +} + +void DialogModel::moveSeries( + const Reference< XDataSeries > & xSeries, + MoveDirection eDirection ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram()); + DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MoveDirection::Down ); +} + +rtl::Reference< ::chart::DataSeries > DialogModel::insertSeriesAfter( + const Reference< XDataSeries > & xUnoSeries, + const rtl::Reference< ::chart::ChartType > & xChartType, + bool bCreateDataCachedSequences /* = false */ ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + rtl::Reference< ::chart::DataSeries > xNewSeries; + rtl::Reference<DataSeries> xSeries = dynamic_cast<DataSeries*>(xUnoSeries.get()); + assert(xSeries || !xUnoSeries); + + try + { + rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram() ); + ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); + + sal_Int32 nSeriesInChartType = 0; + const sal_Int32 nTotalSeries = countSeries(); + if( xChartType.is()) + { + nSeriesInChartType = xChartType->getDataSeries().getLength(); + } + + // create new series + xNewSeries = + lcl_CreateNewSeries( + xChartType, + nTotalSeries, // new series' index + nSeriesInChartType, + xDiagram, + m_xTemplate, + bCreateDataCachedSequences ); + + // add new series to container + if( xNewSeries.is()) + addNewSeriesToContainer(xChartType, xSeries, xNewSeries); + + ThreeDHelper::setScheme( xDiagram, e3DScheme ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xNewSeries; +} + +void DialogModel::deleteSeries( + const Reference< XDataSeries > & xSeries, + const rtl::Reference< ChartType > & xChartType ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + DataSeriesHelper::deleteSeries( xSeries, xChartType ); +} + +uno::Reference< chart2::data::XLabeledDataSequence > DialogModel::getCategories() const +{ + uno::Reference< chart2::data::XLabeledDataSequence > xResult; + try + { + if( m_xChartDocument.is()) + { + rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram()); + xResult = DiagramHelper::getCategoriesFromDiagram( xDiagram ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xResult; +} + +void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories ) +{ + if( !m_xChartDocument.is()) + return; + + rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram()); + if( !xDiagram.is()) + return; + + // categories + bool bSupportsCategories = true; + + rtl::Reference< ChartType > 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 +{ + uno::Reference< chart2::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->getFirstChartDiagram() ); + 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()) + { + (void)DataSourceHelper::detectRangeSegmentation( + m_xChartDocument, + rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +bool DialogModel::allArgumentsForRectRangeDetected() const +{ + return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument ); +} + +void DialogModel::startControllerLockTimer() +{ + m_aTimerTriggeredControllerLock.startTimer(); +} + +void DialogModel::setData( + const Sequence< beans::PropertyValue > & rArguments ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + Reference< data::XDataProvider > xDataProvider( getDataProvider()); + if( ! xDataProvider.is() || + ! m_xTemplate.is() ) + { + OSL_FAIL( "Model objects missing" ); + return; + } + + try + { + Reference< chart2::data::XDataSource > xDataSource( + xDataProvider->createDataSource( rArguments ) ); + + rtl::Reference< ::chart::DataInterpreter > xInterpreter( + m_xTemplate->getDataInterpreter2()); + if( xInterpreter.is()) + { + rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram() ); + ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); + + std::vector< rtl::Reference< DataSeries > > aSeriesToReUse = + DiagramHelper::getDataSeriesFromDiagram( xDiagram ); + applyInterpretedData( + xInterpreter->interpretDataSource( + xDataSource, rArguments, + aSeriesToReUse ), + aSeriesToReUse); + + ThreeDHelper::setScheme( xDiagram, e3DScheme ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void DialogModel::setTimeBasedRange( bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const +{ + maTimeBasedInfo.nStart = nStart; + maTimeBasedInfo.nEnd = nEnd; + maTimeBasedInfo.bTimeBased = bTimeBased; +} + +OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString ) +{ + return lcl_ConvertRole( rRoleString ); +} + +OUString DialogModel::GetRoleDataLabel() +{ + return ::chart::SchResId(STR_OBJECT_DATALABELS); +} + +sal_Int32 DialogModel::GetRoleIndexForSorting( const OUString & rInternalRoleString ) +{ + static lcl_tRoleIndexMap aRoleIndexMap = lcl_createRoleIndexMap(); + + lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString )); + if( aIt != aRoleIndexMap.end()) + return aIt->second; + + return 0; +} + +// private methods + +void DialogModel::applyInterpretedData( + const InterpretedData & rNewData, + const std::vector< rtl::Reference< DataSeries > > & rSeriesToReUse ) +{ + if( ! m_xChartDocument.is()) + return; + + m_aTimerTriggeredControllerLock.startTimer(); + rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram()); + if( !xDiagram.is()) + return; + + // styles + if( 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.size(); + + for(; nGroup < nOuterSize; ++nGroup) + { + const std::vector< rtl::Reference< DataSeries > > & aSeries( rNewData.Series[ nGroup ] ); + const sal_Int32 nSeriesInGroup = aSeries.size(); + for( sal_Int32 nSeries=0; nSeries<nSeriesInGroup; ++nSeries, ++nSeriesCounter ) + { + if( std::find( rSeriesToReUse.begin(), rSeriesToReUse.end(), aSeries[nSeries] ) + == rSeriesToReUse.end()) + { + if( aSeries[nSeries].is()) + { + // @deprecated: correct default color should be found by view + // without setting it as hard attribute + Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + if( xColorScheme.is()) + aSeries[nSeries]->setPropertyValue( "Color" , + uno::Any( xColorScheme->getColorByIndex( nSeriesCounter ))); + } + m_xTemplate->applyStyle2( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup ); + } + } + } + } + + // data series + std::vector< rtl::Reference< ChartType > > aSeriesCnt = getAllDataSeriesContainers(); + + OSL_ASSERT( aSeriesCnt.size() == rNewData.Series.size()); + + auto aSrcIt = rNewData.Series.begin(); + auto aDestIt = aSeriesCnt.begin(); + for(; aSrcIt != rNewData.Series.end() && aDestIt != aSeriesCnt.end(); + ++aSrcIt, ++aDestIt ) + { + try + { + OSL_ASSERT( (*aDestIt).is()); + (*aDestIt)->setDataSeries( *aSrcIt ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + DialogModel::setCategories(rNewData.Categories); +} + +sal_Int32 DialogModel::countSeries() const +{ + std::vector< rtl::Reference< ChartType > > aCnt( getAllDataSeriesContainers()); + return std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber()); +} + +ChartModel& DialogModel::getModel() const +{ + return *m_xChartDocument; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |