Add 'reference' to the iterator_traits, needed by LegacyIterator reqs
[LibreOffice.git] / chart2 / source / controller / dialogs / DialogModel.cxx
blob9c735a489b5e08f176d55460a8190c05f8727a50
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "DialogModel.hxx"
21 #include <RangeSelectionHelper.hxx>
22 #include <DataSeriesHelper.hxx>
23 #include <DataSourceHelper.hxx>
24 #include <DiagramHelper.hxx>
25 #include <strings.hrc>
26 #include <ResId.hxx>
27 #include <ControllerLockGuard.hxx>
28 #include <ChartTypeHelper.hxx>
29 #include <ThreeDHelper.hxx>
30 #include <ChartModel.hxx>
32 #include <com/sun/star/uno/XComponentContext.hpp>
33 #include <com/sun/star/chart2/AxisType.hpp>
34 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
35 #include <com/sun/star/chart2/XChartDocument.hpp>
36 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
37 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
38 #include <com/sun/star/chart2/data/XDataSink.hpp>
39 #include <comphelper/sequence.hxx>
40 #include <tools/diagnose_ex.h>
42 #include <rtl/ustring.hxx>
44 #include <utility>
45 #include <algorithm>
46 #include <iterator>
47 #include <numeric>
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::chart2;
52 using ::com::sun::star::uno::Reference;
53 using ::com::sun::star::uno::Sequence;
55 namespace
57 constexpr OUStringLiteral lcl_aLabelRole( u"label" );
59 struct lcl_ChartTypeToSeriesCnt
61 Reference< XDataSeriesContainer > operator() (
62 const Reference< XChartType > & xChartType )
64 return Reference< XDataSeriesContainer >::query( xChartType );
68 OUString lcl_ConvertRole( const OUString & rRoleString )
70 OUString aResult( rRoleString );
72 typedef std::map< OUString, OUString > tTranslationMap;
73 static const tTranslationMap aTranslationMap =
75 { "categories", ::chart::SchResId( STR_DATA_ROLE_CATEGORIES ) },
76 { "error-bars-x", ::chart::SchResId( STR_DATA_ROLE_X_ERROR ) },
77 { "error-bars-x-positive", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_POSITIVE ) },
78 { "error-bars-x-negative", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_NEGATIVE ) },
79 { "error-bars-y", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR ) },
80 { "error-bars-y-positive", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_POSITIVE ) },
81 { "error-bars-y-negative", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_NEGATIVE ) },
82 { "label", ::chart::SchResId( STR_DATA_ROLE_LABEL ) },
83 { "values-first", ::chart::SchResId( STR_DATA_ROLE_FIRST ) },
84 { "values-last", ::chart::SchResId( STR_DATA_ROLE_LAST ) },
85 { "values-max", ::chart::SchResId( STR_DATA_ROLE_MAX ) },
86 { "values-min", ::chart::SchResId( STR_DATA_ROLE_MIN ) },
87 { "values-x", ::chart::SchResId( STR_DATA_ROLE_X ) },
88 { "values-y", ::chart::SchResId( STR_DATA_ROLE_Y ) },
89 { "values-size", ::chart::SchResId( STR_DATA_ROLE_SIZE ) },
90 { "FillColor", ::chart::SchResId( STR_PROPERTY_ROLE_FILLCOLOR ) },
91 { "BorderColor", ::chart::SchResId( STR_PROPERTY_ROLE_BORDERCOLOR ) },
94 tTranslationMap::const_iterator aIt( aTranslationMap.find( rRoleString ));
95 if( aIt != aTranslationMap.end())
97 aResult = (*aIt).second;
99 return aResult;
102 typedef std::map< OUString, sal_Int32 > lcl_tRoleIndexMap;
104 lcl_tRoleIndexMap lcl_createRoleIndexMap()
106 lcl_tRoleIndexMap aMap;
107 sal_Int32 nIndex = 0;
109 aMap[ "label" ] = ++nIndex;
110 aMap[ "categories" ] = ++nIndex;
111 aMap[ "values-x" ] = ++nIndex;
112 aMap[ "values-y" ] = ++nIndex;
113 aMap[ "error-bars-x" ] = ++nIndex;
114 aMap[ "error-bars-x-positive" ] = ++nIndex;
115 aMap[ "error-bars-x-negative" ] = ++nIndex;
116 aMap[ "error-bars-y" ] = ++nIndex;
117 aMap[ "error-bars-y-positive" ] = ++nIndex;
118 aMap[ "error-bars-y-negative" ] = ++nIndex;
119 aMap[ "values-first" ] = ++nIndex;
120 aMap[ "values-min" ] = ++nIndex;
121 aMap[ "values-max" ] = ++nIndex;
122 aMap[ "values-last" ] = ++nIndex;
123 aMap[ "values-size" ] = ++nIndex;
125 return aMap;
128 struct lcl_DataSeriesContainerAppend
130 typedef Reference< XDataSeriesContainer > value_type;
131 typedef std::vector< ::chart::DialogModel::tSeriesWithChartTypeByName > tContainerType;
133 explicit lcl_DataSeriesContainerAppend( tContainerType * rCnt )
134 : m_rDestCnt( rCnt )
137 lcl_DataSeriesContainerAppend & operator= ( const value_type & xVal )
141 if( xVal.is())
143 const Sequence< Reference< XDataSeries > > aSeq( xVal->getDataSeries());
144 OUString aRole( "values-y" );
145 Reference< XChartType > xCT( xVal, uno::UNO_QUERY );
146 if( xCT.is())
147 aRole = xCT->getRoleOfSequenceForSeriesLabel();
148 for( Reference< XDataSeries > const & dataSeries : aSeq )
150 m_rDestCnt->push_back(
151 ::chart::DialogModel::tSeriesWithChartTypeByName(
152 ::chart::DataSeriesHelper::getDataSeriesLabel( dataSeries, aRole ),
153 std::make_pair( dataSeries, xCT )));
157 catch( const uno::Exception & )
159 DBG_UNHANDLED_EXCEPTION("chart2");
161 return *this;
164 // Implement output operator requirements as required by std::copy (and
165 // implement prefix increment in terms of postfix increment to avoid unused
166 // member function warnings for the latter in the common case where
167 // std::copy would not actually need it):
168 lcl_DataSeriesContainerAppend & operator* () { return *this; }
169 lcl_DataSeriesContainerAppend & operator++ () { return operator++(0); }
170 lcl_DataSeriesContainerAppend & operator++ (int) { return *this; }
172 private:
173 tContainerType * m_rDestCnt;
176 struct lcl_RolesWithRangeAppend
178 typedef Reference< data::XLabeledDataSequence > value_type;
179 typedef ::chart::DialogModel::tRolesWithRanges tContainerType;
181 explicit lcl_RolesWithRangeAppend( tContainerType * rCnt,
182 const OUString & aLabelRole )
183 : m_rDestCnt( rCnt ),
184 m_aRoleForLabelSeq( aLabelRole )
187 lcl_RolesWithRangeAppend & operator= ( const value_type & xVal )
191 if( xVal.is())
193 // data sequence
194 Reference< data::XDataSequence > xSeq( xVal->getValues());
195 if( xSeq.is())
197 OUString aRole;
198 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
199 if( xProp->getPropertyValue( "Role" ) >>= aRole )
201 m_rDestCnt->emplace(aRole, xSeq->getSourceRangeRepresentation());
202 // label
203 if( aRole == m_aRoleForLabelSeq )
205 Reference< data::XDataSequence > xLabelSeq( xVal->getLabel());
206 if( xLabelSeq.is())
208 m_rDestCnt->emplace(
209 lcl_aLabelRole, xLabelSeq->getSourceRangeRepresentation());
216 catch( const uno::Exception & )
218 DBG_UNHANDLED_EXCEPTION("chart2");
220 return *this;
223 // Implement output operator requirements as required by std::copy (and
224 // implement prefix increment in terms of postfix increment to avoid unused
225 // member function warnings for the latter in the common case where
226 // std::copy would not actually need it):
227 lcl_RolesWithRangeAppend & operator* () { return *this; }
228 lcl_RolesWithRangeAppend & operator++ () { return operator++(0); }
229 lcl_RolesWithRangeAppend & operator++ (int) { return *this; }
231 private:
232 tContainerType * m_rDestCnt;
233 OUString m_aRoleForLabelSeq;
238 namespace std
240 template<> struct iterator_traits<lcl_DataSeriesContainerAppend>
242 typedef std::output_iterator_tag iterator_category;
243 typedef Reference< XDataSeriesContainer > value_type;
244 typedef value_type& reference;
247 template<> struct iterator_traits<lcl_RolesWithRangeAppend>
249 typedef std::output_iterator_tag iterator_category;
250 typedef Reference< data::XLabeledDataSequence > value_type;
251 typedef value_type& reference;
255 namespace {
257 void lcl_SetSequenceRole(
258 const Reference< data::XDataSequence > & xSeq,
259 const OUString & rRole )
261 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
262 if( xProp.is())
263 xProp->setPropertyValue( "Role" , uno::Any( rRole ));
266 Sequence< OUString > lcl_CopyExcludingValuesFirst(
267 Sequence< OUString > const & i_aInput )
269 Sequence< OUString > aOutput( i_aInput.getLength());
270 auto pOutput = aOutput.getArray();
271 int nSourceIndex, nDestIndex;
272 for( nSourceIndex = nDestIndex = 0; nSourceIndex < i_aInput.getLength(); nSourceIndex++ )
274 if( i_aInput[nSourceIndex] == "values-first" )
276 aOutput.realloc( aOutput.getLength() - 1 );
277 pOutput = aOutput.getArray();
279 else
281 pOutput[nDestIndex] = i_aInput[nSourceIndex];
282 nDestIndex++;
285 return aOutput;
288 Reference< XDataSeries > lcl_CreateNewSeries(
289 const Reference< uno::XComponentContext > & xContext,
290 const Reference< XChartType > & xChartType,
291 sal_Int32 nNewSeriesIndex,
292 sal_Int32 nTotalNumberOfSeriesInCTGroup,
293 const Reference< XDiagram > & xDiagram,
294 const Reference< XChartTypeTemplate > & xTemplate,
295 bool bCreateDataCachedSequences )
297 // create plain series
298 Reference< XDataSeries > xResult(
299 xContext->getServiceManager()->createInstanceWithContext(
300 "com.sun.star.chart2.DataSeries" ,
301 xContext ), uno::UNO_QUERY );
302 if( xTemplate.is())
304 Reference< beans::XPropertySet > xResultProp( xResult, uno::UNO_QUERY );
305 if( xResultProp.is())
307 // @deprecated: correct default color should be found by view
308 // without setting it as hard attribute
309 Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
310 if( xColorScheme.is())
311 xResultProp->setPropertyValue( "Color" , uno::Any( xColorScheme->getColorByIndex( nNewSeriesIndex )));
313 sal_Int32 nGroupIndex=0;
314 if( xChartType.is())
316 Sequence< Reference< XChartType > > aCTs(
317 ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ));
318 for( ; nGroupIndex<aCTs.getLength(); ++nGroupIndex)
319 if( aCTs[nGroupIndex] == xChartType )
320 break;
321 if( nGroupIndex == aCTs.getLength())
322 nGroupIndex = 0;
324 xTemplate->applyStyle( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup );
327 if( bCreateDataCachedSequences )
329 // set chart type specific roles
330 Reference< data::XDataSink > xSink( xResult, uno::UNO_QUERY );
331 if( xChartType.is() && xSink.is())
333 std::vector< Reference< data::XLabeledDataSequence > > aNewSequences;
334 const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel();
335 const OUString aLabel(::chart::SchResId(STR_DATA_UNNAMED_SERIES));
336 Sequence< OUString > aPossibleRoles( xChartType->getSupportedMandatoryRoles());
337 Sequence< OUString > aPossibleOptRoles( xChartType->getSupportedOptionalRoles());
339 //special handling for candlestick type
340 if( xTemplate.is())
342 Reference< XDataInterpreter > xInterpreter( xTemplate->getDataInterpreter());
343 if( xInterpreter.is())
345 sal_Int32 nStockVariant;
346 if( xInterpreter->getChartTypeSpecificData("stock variant") >>= nStockVariant )
348 if( nStockVariant == 0 || nStockVariant == 2) {
349 //delete "values-first" role
350 aPossibleRoles = lcl_CopyExcludingValuesFirst(aPossibleRoles);
351 aPossibleOptRoles = lcl_CopyExcludingValuesFirst(aPossibleOptRoles);
357 const Sequence< OUString > aRoles( aPossibleRoles );
358 const Sequence< OUString > aOptRoles( aPossibleOptRoles );
360 for(OUString const & role : aRoles)
362 if( role == lcl_aLabelRole )
363 continue;
364 Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence() );
365 lcl_SetSequenceRole( xSeq, role );
366 // assert that aRoleOfSeqForSeriesLabel is part of the mandatory roles
367 if( role == aRoleOfSeqForSeriesLabel )
369 Reference< data::XDataSequence > xLabel( ::chart::DataSourceHelper::createCachedDataSequence( aLabel ));
370 lcl_SetSequenceRole( xLabel, lcl_aLabelRole );
371 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq, xLabel ));
373 else
374 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
377 for(OUString const & role : aOptRoles)
379 if( role == lcl_aLabelRole )
380 continue;
381 Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence());
382 lcl_SetSequenceRole( xSeq, role );
383 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
386 xSink->setData( comphelper::containerToSequence( aNewSequences ));
390 return xResult;
393 struct lcl_addSeriesNumber
395 sal_Int32 operator() ( sal_Int32 nCurrentNumber, const Reference< XDataSeriesContainer > & xCnt ) const
397 if( xCnt.is())
398 return nCurrentNumber + (xCnt->getDataSeries().getLength());
399 return nCurrentNumber;
403 } // anonymous namespace
405 namespace chart
408 DialogModelTimeBasedInfo::DialogModelTimeBasedInfo():
409 bTimeBased(false),
410 nStart(0),
411 nEnd(0)
415 DialogModel::DialogModel(
416 const Reference< XChartDocument > & xChartDocument,
417 const Reference< uno::XComponentContext > & xContext ) :
418 m_xChartDocument( xChartDocument ),
419 m_xContext( xContext ),
420 m_aTimerTriggeredControllerLock( m_xChartDocument )
424 DialogModel::~DialogModel()
426 if(maTimeBasedInfo.bTimeBased)
428 getModel().setTimeBasedRange(maTimeBasedInfo.nStart, maTimeBasedInfo.nEnd);
432 void DialogModel::setTemplate(
433 const Reference< XChartTypeTemplate > & xTemplate )
435 m_xTemplate = xTemplate;
438 std::shared_ptr< RangeSelectionHelper > const &
439 DialogModel::getRangeSelectionHelper() const
441 if( ! m_spRangeSelectionHelper)
442 m_spRangeSelectionHelper =
443 std::make_shared<RangeSelectionHelper>( m_xChartDocument );
445 return m_spRangeSelectionHelper;
448 Reference< frame::XModel > DialogModel::getChartModel() const
450 return m_xChartDocument;
453 Reference< data::XDataProvider > DialogModel::getDataProvider() const
455 Reference< data::XDataProvider > xResult;
456 if( m_xChartDocument.is())
457 xResult.set( m_xChartDocument->getDataProvider());
458 return xResult;
461 std::vector< Reference< XDataSeriesContainer > >
462 DialogModel::getAllDataSeriesContainers() const
464 std::vector< Reference< XDataSeriesContainer > > aResult;
468 Reference< XDiagram > xDiagram;
469 if( m_xChartDocument.is())
470 xDiagram.set( m_xChartDocument->getFirstDiagram());
471 if( xDiagram.is())
473 Reference< XCoordinateSystemContainer > xCooSysCnt(
474 xDiagram, uno::UNO_QUERY_THROW );
475 const Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
476 xCooSysCnt->getCoordinateSystems());
477 for( Reference< XCoordinateSystem > const & coords : aCooSysSeq )
479 Reference< XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW );
480 const Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
481 std::transform(
482 aChartTypeSeq.begin(), aChartTypeSeq.end(),
483 std::back_inserter( aResult ),
484 lcl_ChartTypeToSeriesCnt() );
488 catch( const uno::Exception & )
490 DBG_UNHANDLED_EXCEPTION("chart2");
493 return aResult;
496 std::vector< DialogModel::tSeriesWithChartTypeByName >
497 DialogModel::getAllDataSeriesWithLabel() const
499 std::vector< tSeriesWithChartTypeByName > aResult;
500 std::vector< Reference< XDataSeriesContainer > > aContainers(
501 getAllDataSeriesContainers());
503 std::copy( aContainers.begin(), aContainers.end(),
504 lcl_DataSeriesContainerAppend( &aResult ));
505 return aResult;
508 namespace {
510 void addMissingRoles(DialogModel::tRolesWithRanges& rResult, const uno::Sequence<OUString>& rRoles)
512 for(OUString const & role : rRoles)
514 if(rResult.find(role) == rResult.end())
515 rResult.emplace(role, OUString());
520 * Insert a new data series to chart type at position after specified series
521 * position.
523 * @param xChartType chart type that contains data series.
524 * @param xSeries insertion position. The new series will be inserted after
525 * this one.
526 * @param xNewSeries new data series to insert.
528 void addNewSeriesToContainer(
529 const Reference<XChartType>& xChartType,
530 const Reference<XDataSeries>& xSeries,
531 const Reference<XDataSeries>& xNewSeries )
533 Reference<XDataSeriesContainer> xSeriesCnt(xChartType, uno::UNO_QUERY_THROW);
534 auto aSeries = comphelper::sequenceToContainer<std::vector<Reference<XDataSeries> >>(xSeriesCnt->getDataSeries());
536 std::vector<Reference<XDataSeries> >::iterator aIt =
537 std::find( aSeries.begin(), aSeries.end(), xSeries);
539 if( aIt == aSeries.end())
540 // if we have no series we insert at the first position.
541 aIt = aSeries.begin();
542 else
543 // vector::insert inserts before, so we have to advance
544 ++aIt;
546 aSeries.insert(aIt, xNewSeries);
547 xSeriesCnt->setDataSeries(comphelper::containerToSequence(aSeries));
552 DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges(
553 const Reference< XDataSeries > & xSeries,
554 const OUString & aRoleOfSequenceForLabel,
555 const Reference< chart2::XChartType > & xChartType )
557 DialogModel::tRolesWithRanges aResult;
560 Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW );
561 const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
562 std::copy( aSeq.begin(), aSeq.end(),
563 lcl_RolesWithRangeAppend( &aResult, aRoleOfSequenceForLabel ));
564 if( xChartType.is())
566 // add missing mandatory roles
567 Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles());
568 addMissingRoles(aResult, aRoles);
570 // add missing optional roles
571 aRoles = xChartType->getSupportedOptionalRoles();
572 addMissingRoles(aResult, aRoles);
574 // add missing property roles
575 aRoles = xChartType->getSupportedPropertyRoles();
576 addMissingRoles(aResult, aRoles);
579 catch( const uno::Exception & )
581 DBG_UNHANDLED_EXCEPTION("chart2");
583 return aResult;
586 void DialogModel::moveSeries(
587 const Reference< XDataSeries > & xSeries,
588 MoveDirection eDirection )
590 m_aTimerTriggeredControllerLock.startTimer();
591 ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
593 Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
594 DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MoveDirection::Down );
597 Reference< chart2::XDataSeries > DialogModel::insertSeriesAfter(
598 const Reference< XDataSeries > & xSeries,
599 const Reference< XChartType > & xChartType,
600 bool bCreateDataCachedSequences /* = false */ )
602 m_aTimerTriggeredControllerLock.startTimer();
603 ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
604 Reference< XDataSeries > xNewSeries;
608 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() );
609 ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram );
611 sal_Int32 nSeriesInChartType = 0;
612 const sal_Int32 nTotalSeries = countSeries();
613 if( xChartType.is())
615 Reference< XDataSeriesContainer > xCnt( xChartType, uno::UNO_QUERY_THROW );
616 nSeriesInChartType = xCnt->getDataSeries().getLength();
619 // create new series
620 xNewSeries.set(
621 lcl_CreateNewSeries(
622 m_xContext,
623 xChartType,
624 nTotalSeries, // new series' index
625 nSeriesInChartType,
626 xDiagram,
627 m_xTemplate,
628 bCreateDataCachedSequences ));
630 // add new series to container
631 if( xNewSeries.is())
632 addNewSeriesToContainer(xChartType, xSeries, xNewSeries);
634 ThreeDHelper::setScheme( xDiagram, e3DScheme );
636 catch( const uno::Exception & )
638 DBG_UNHANDLED_EXCEPTION("chart2");
640 return xNewSeries;
643 void DialogModel::deleteSeries(
644 const Reference< XDataSeries > & xSeries,
645 const Reference< XChartType > & xChartType )
647 m_aTimerTriggeredControllerLock.startTimer();
648 ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
650 DataSeriesHelper::deleteSeries( xSeries, xChartType );
653 Reference< data::XLabeledDataSequence > DialogModel::getCategories() const
655 Reference< data::XLabeledDataSequence > xResult;
658 if( m_xChartDocument.is())
660 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
661 xResult.set( DiagramHelper::getCategoriesFromDiagram( xDiagram ));
664 catch( const uno::Exception & )
666 DBG_UNHANDLED_EXCEPTION("chart2");
668 return xResult;
671 void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories )
673 if( !m_xChartDocument.is())
674 return;
676 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
677 if( !xDiagram.is())
678 return;
680 // categories
681 bool bSupportsCategories = true;
683 Reference< XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
684 if( xFirstChartType.is() )
686 sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis
687 bSupportsCategories = (nAxisType == AxisType::CATEGORY);
689 DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram, true, bSupportsCategories );
692 OUString DialogModel::getCategoriesRange() const
694 Reference< data::XLabeledDataSequence > xLSeq( getCategories());
695 OUString aRange;
696 if( xLSeq.is())
698 Reference< data::XDataSequence > xSeq( xLSeq->getValues());
699 if( xSeq.is())
700 aRange = xSeq->getSourceRangeRepresentation();
702 return aRange;
705 bool DialogModel::isCategoryDiagram() const
707 bool bRet = false;
708 if( m_xChartDocument.is())
709 bRet = DiagramHelper::isCategoryDiagram( m_xChartDocument->getFirstDiagram() );
710 return bRet;
713 void DialogModel::detectArguments(
714 OUString & rOutRangeString,
715 bool & rOutUseColumns,
716 bool & rOutFirstCellAsLabel,
717 bool & rOutHasCategories ) const
721 uno::Sequence< sal_Int32 > aSequenceMapping;//todo YYYX
723 // Note: unused data is currently not supported in being passed to detectRangeSegmentation
724 if( m_xChartDocument.is())
726 (void)DataSourceHelper::detectRangeSegmentation(
727 Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY_THROW ),
728 rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories );
731 catch( const uno::Exception & )
733 DBG_UNHANDLED_EXCEPTION("chart2");
737 bool DialogModel::allArgumentsForRectRangeDetected() const
739 return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument );
742 void DialogModel::startControllerLockTimer()
744 m_aTimerTriggeredControllerLock.startTimer();
747 void DialogModel::setData(
748 const Sequence< beans::PropertyValue > & rArguments )
750 m_aTimerTriggeredControllerLock.startTimer();
751 ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
753 Reference< data::XDataProvider > xDataProvider( getDataProvider());
754 if( ! xDataProvider.is() ||
755 ! m_xTemplate.is() )
757 OSL_FAIL( "Model objects missing" );
758 return;
763 Reference< chart2::data::XDataSource > xDataSource(
764 xDataProvider->createDataSource( rArguments ) );
766 Reference< chart2::XDataInterpreter > xInterpreter(
767 m_xTemplate->getDataInterpreter());
768 if( xInterpreter.is())
770 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() );
771 ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram );
773 std::vector< Reference< XDataSeries > > aSeriesToReUse(
774 DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
775 applyInterpretedData(
776 xInterpreter->interpretDataSource(
777 xDataSource, rArguments,
778 comphelper::containerToSequence( aSeriesToReUse )),
779 aSeriesToReUse);
781 ThreeDHelper::setScheme( xDiagram, e3DScheme );
784 catch( const uno::Exception & )
786 DBG_UNHANDLED_EXCEPTION("chart2");
790 void DialogModel::setTimeBasedRange( bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const
792 maTimeBasedInfo.nStart = nStart;
793 maTimeBasedInfo.nEnd = nEnd;
794 maTimeBasedInfo.bTimeBased = bTimeBased;
797 OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString )
799 return lcl_ConvertRole( rRoleString );
802 OUString DialogModel::GetRoleDataLabel()
804 return ::chart::SchResId(STR_OBJECT_DATALABELS);
807 sal_Int32 DialogModel::GetRoleIndexForSorting( const OUString & rInternalRoleString )
809 static lcl_tRoleIndexMap aRoleIndexMap = lcl_createRoleIndexMap();
811 lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString ));
812 if( aIt != aRoleIndexMap.end())
813 return aIt->second;
815 return 0;
818 // private methods
820 void DialogModel::applyInterpretedData(
821 const InterpretedData & rNewData,
822 const std::vector< Reference< XDataSeries > > & rSeriesToReUse )
824 if( ! m_xChartDocument.is())
825 return;
827 m_aTimerTriggeredControllerLock.startTimer();
828 Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
829 if( !xDiagram.is())
830 return;
832 // styles
833 if( m_xTemplate.is() )
835 sal_Int32 nGroup = 0;
836 sal_Int32 nSeriesCounter = 0;
837 sal_Int32 nNewSeriesIndex = static_cast< sal_Int32 >( rSeriesToReUse.size());
838 const sal_Int32 nOuterSize=rNewData.Series.getLength();
840 for(; nGroup < nOuterSize; ++nGroup)
842 Sequence< Reference< XDataSeries > > aSeries( rNewData.Series[ nGroup ] );
843 const sal_Int32 nSeriesInGroup = aSeries.getLength();
844 for( sal_Int32 nSeries=0; nSeries<nSeriesInGroup; ++nSeries, ++nSeriesCounter )
846 if( std::find( rSeriesToReUse.begin(), rSeriesToReUse.end(), aSeries[nSeries] )
847 == rSeriesToReUse.end())
849 Reference< beans::XPropertySet > xSeriesProp( aSeries[nSeries], uno::UNO_QUERY );
850 if( xSeriesProp.is())
852 // @deprecated: correct default color should be found by view
853 // without setting it as hard attribute
854 Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
855 if( xColorScheme.is())
856 xSeriesProp->setPropertyValue( "Color" ,
857 uno::Any( xColorScheme->getColorByIndex( nSeriesCounter )));
859 m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup );
865 // data series
866 std::vector< Reference< XDataSeriesContainer > > aSeriesCnt( getAllDataSeriesContainers());
867 auto aNewSeries(
868 comphelper::sequenceToContainer<std::vector< Sequence< Reference< XDataSeries > > >>( rNewData.Series ));
870 OSL_ASSERT( aSeriesCnt.size() == aNewSeries.size());
872 std::vector< Sequence< Reference< XDataSeries > > >::const_iterator aSrcIt( aNewSeries.begin());
873 std::vector< Reference< XDataSeriesContainer > >::iterator aDestIt( aSeriesCnt.begin());
874 for(; aSrcIt != aNewSeries.end() && aDestIt != aSeriesCnt.end();
875 ++aSrcIt, ++aDestIt )
879 OSL_ASSERT( (*aDestIt).is());
880 (*aDestIt)->setDataSeries( *aSrcIt );
882 catch( const uno::Exception & )
884 DBG_UNHANDLED_EXCEPTION("chart2");
888 DialogModel::setCategories(rNewData.Categories);
891 sal_Int32 DialogModel::countSeries() const
893 std::vector< Reference< XDataSeriesContainer > > aCnt( getAllDataSeriesContainers());
894 return std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber());
897 ChartModel& DialogModel::getModel() const
899 uno::Reference< frame::XModel > xModel = getChartModel();
900 ChartModel* pModel = dynamic_cast<ChartModel*>(xModel.get());
901 assert(pModel);
902 return *pModel;
905 } // namespace chart
907 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */