diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /chart2/source/controller/dialogs/DialogModel.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'chart2/source/controller/dialogs/DialogModel.cxx')
-rw-r--r-- | chart2/source/controller/dialogs/DialogModel.cxx | 860 |
1 files changed, 860 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..b4bdbae65 --- /dev/null +++ b/chart2/source/controller/dialogs/DialogModel.cxx @@ -0,0 +1,860 @@ +/* -*- 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 <DataSeriesHelper.hxx> +#include <DataSourceHelper.hxx> +#include <DiagramHelper.hxx> +#include <strings.hrc> +#include <ResId.hxx> +#include <ControllerLockGuard.hxx> +#include <ChartTypeHelper.hxx> +#include <ThreeDHelper.hxx> +#include <ChartModel.hxx> + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart2/data/XDataSink.hpp> +#include <comphelper/sequence.hxx> +#include <tools/diagnose_ex.h> + +#include <rtl/ustring.hxx> + +#include <utility> +#include <algorithm> +#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 +{ +const OUString lcl_aLabelRole( "label" ); + +struct lcl_ChartTypeToSeriesCnt +{ + Reference< XDataSeriesContainer > operator() ( + const Reference< XChartType > & xChartType ) + { + return Reference< XDataSeriesContainer >::query( xChartType ); + } +}; + +OUString lcl_ConvertRole( const OUString & rRoleString ) +{ + OUString aResult( rRoleString ); + + typedef std::map< OUString, OUString > tTranslationMap; + static 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_DataSeriesContainerAppend +{ + typedef Reference< XDataSeriesContainer > value_type; + 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()) + { + const Sequence< Reference< XDataSeries > > aSeq( xVal->getDataSeries()); + OUString aRole( "values-y" ); + Reference< XChartType > xCT( xVal, uno::UNO_QUERY ); + if( xCT.is()) + aRole = xCT->getRoleOfSequenceForSeriesLabel(); + for( Reference< XDataSeries > const & dataSeries : aSeq ) + { + m_rDestCnt->push_back( + ::chart::DialogModel::tSeriesWithChartTypeByName( + ::chart::DataSeriesHelper::getDataSeriesLabel( dataSeries, aRole ), + std::make_pair( dataSeries, xCT ))); + } + } + } + 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_DataSeriesContainerAppend & operator* () { return *this; } + lcl_DataSeriesContainerAppend & operator++ () { return operator++(0); } + lcl_DataSeriesContainerAppend & operator++ (int) { return *this; } + +private: + tContainerType * m_rDestCnt; +}; + +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_DataSeriesContainerAppend> + { + typedef std::output_iterator_tag iterator_category; + typedef Reference< XDataSeriesContainer > value_type; + }; + + template<> struct iterator_traits<lcl_RolesWithRangeAppend> + { + typedef std::output_iterator_tag iterator_category; + typedef Reference< data::XLabeledDataSequence > value_type; + }; +} + +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 )); +} + +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( + "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( "Color" , uno::Any( 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(::chart::SchResId(STR_DATA_UNNAMED_SERIES)); + const Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles()); + const Sequence< OUString > aOptRoles( xChartType->getSupportedOptionalRoles()); + + 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 )); + } + + xSink->setData( comphelper::containerToSequence( 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 Reference< XChartDocument > & xChartDocument, + const Reference< uno::XComponentContext > & xContext ) : + m_xChartDocument( xChartDocument ), + m_xContext( xContext ), + m_aTimerTriggeredControllerLock( m_xChartDocument ) +{ +} + +DialogModel::~DialogModel() +{ + if(maTimeBasedInfo.bTimeBased) + { + getModel().setTimeBasedRange(maTimeBasedInfo.nStart, maTimeBasedInfo.nEnd); + } +} + +void DialogModel::setTemplate( + const Reference< XChartTypeTemplate > & 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; +} + +Reference< frame::XModel > 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< 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 ); + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + std::transform( + aChartTypeSeq.begin(), aChartTypeSeq.end(), + std::back_inserter( aResult ), + lcl_ChartTypeToSeriesCnt() ); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + 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; +} + +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 Reference<XChartType>& xChartType, + const Reference<XDataSeries>& xSeries, + const Reference<XDataSeries>& xNewSeries ) +{ + Reference<XDataSeriesContainer> xSeriesCnt(xChartType, uno::UNO_QUERY_THROW); + auto aSeries = comphelper::sequenceToContainer<std::vector<Reference<XDataSeries> >>(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(comphelper::containerToSequence(aSeries)); +} + +} + +DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges( + const Reference< XDataSeries > & xSeries, + const OUString & aRoleOfSequenceForLabel, + const Reference< chart2::XChartType > & 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 ); + + Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MoveDirection::Down ); +} + +Reference< chart2::XDataSeries > DialogModel::insertSeriesAfter( + const Reference< XDataSeries > & xSeries, + const Reference< XChartType > & xChartType, + bool bCreateDataCachedSequences /* = false */ ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + Reference< XDataSeries > xNewSeries; + + try + { + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); + ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); + + 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, + 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 Reference< XChartType > & xChartType ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + 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( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xResult; +} + +void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories ) +{ + if( !m_xChartDocument.is()) + return; + + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + if( !xDiagram.is()) + return; + + // 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( 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 ) ); + + Reference< chart2::XDataInterpreter > xInterpreter( + m_xTemplate->getDataInterpreter()); + if( xInterpreter.is()) + { + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); + ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); + + std::vector< Reference< XDataSeries > > aSeriesToReUse( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + applyInterpretedData( + xInterpreter->interpretDataSource( + xDataSource, rArguments, + comphelper::containerToSequence( 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< Reference< XDataSeries > > & rSeriesToReUse ) +{ + if( ! m_xChartDocument.is()) + return; + + m_aTimerTriggeredControllerLock.startTimer(); + Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + 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.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( "Color" , + uno::Any( xColorScheme->getColorByIndex( nSeriesCounter ))); + } + m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup ); + } + } + } + } + + // data series + std::vector< Reference< XDataSeriesContainer > > aSeriesCnt( getAllDataSeriesContainers()); + auto aNewSeries( + comphelper::sequenceToContainer<std::vector< Sequence< Reference< XDataSeries > > >>( 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( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + DialogModel::setCategories(rNewData.Categories); +} + +sal_Int32 DialogModel::countSeries() const +{ + std::vector< Reference< XDataSeriesContainer > > aCnt( getAllDataSeriesContainers()); + return std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber()); +} + +ChartModel& DialogModel::getModel() const +{ + uno::Reference< frame::XModel > xModel = getChartModel(); + ChartModel* pModel = dynamic_cast<ChartModel*>(xModel.get()); + assert(pModel); + return *pModel; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |