LibreOffice Module chart2 (master) 1
ChartTypeTemplate.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <ChartTypeTemplate.hxx>
21#include <DataInterpreter.hxx>
22#include <CommonConverters.hxx>
23#include <ChartTypeHelper.hxx>
24#include <ChartType.hxx>
25#include <DataSeries.hxx>
27#include <DataSource.hxx>
28#include <GridProperties.hxx>
29
30#include <Axis.hxx>
31#include <AxisHelper.hxx>
32#include <Diagram.hxx>
33#include <DiagramHelper.hxx>
34#include <AxisIndexDefines.hxx>
36#include <unonames.hxx>
37
38#include <com/sun/star/uno/XComponentContext.hpp>
39#include <com/sun/star/chart2/AxisType.hpp>
40#include <com/sun/star/chart2/StackingDirection.hpp>
41#include <com/sun/star/chart2/XColorScheme.hpp>
44
45#include <algorithm>
46#include <cstddef>
47#include <utility>
48
49using namespace ::com::sun::star;
50using namespace ::com::sun::star::chart2;
51using namespace ::chart::DataSeriesProperties;
52
53using ::com::sun::star::uno::Sequence;
54using ::com::sun::star::uno::Reference;
55
56namespace
57{
58
59void lcl_applyDefaultStyle(
61 sal_Int32 nIndex,
62 const rtl::Reference< ::chart::Diagram > & xDiagram )
63{
64 // @deprecated: correct default color should be found by view without
65 // setting color as hard attribute
66 if( xSeries.is() && xDiagram.is())
67 {
68 Reference< chart2::XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
69 if( xColorScheme.is() )
70 xSeries->setPropertyValue(
71 "Color",
72 uno::Any( xColorScheme->getColorByIndex( nIndex )));
73 }
74}
75
76void lcl_ensureCorrectLabelPlacement( const Reference< beans::XPropertySet >& xProp, const uno::Sequence < sal_Int32 >& rAvailablePlacements )
77{
78 sal_Int32 nLabelPlacement=0;
79 if( !(xProp.is() && (xProp->getPropertyValue( "LabelPlacement" ) >>= nLabelPlacement)) )
80 return;
81
82 bool bValid = false;
83 for( sal_Int32 i : rAvailablePlacements )
84 {
85 if( i == nLabelPlacement )
86 {
87 bValid = true;
88 break;
89 }
90 }
91 if( !bValid )
92 {
93 uno::Any aNewValue;
94 //otherwise use the first supported one
95 if( rAvailablePlacements.hasElements() )
96 aNewValue <<=rAvailablePlacements[0];
97 xProp->setPropertyValue( "LabelPlacement", aNewValue );
98 }
99}
100
101void lcl_resetLabelPlacementIfDefault( const Reference< beans::XPropertySet >& xProp, sal_Int32 nDefaultPlacement )
102{
103
104 sal_Int32 nLabelPlacement=0;
105 if( xProp.is() && (xProp->getPropertyValue( "LabelPlacement" ) >>= nLabelPlacement) )
106 {
107 if( nDefaultPlacement == nLabelPlacement )
108 xProp->setPropertyValue( "LabelPlacement", uno::Any() );
109 }
110}
111
112void lcl_ensureCorrectMissingValueTreatment( const rtl::Reference< ::chart::Diagram >& xDiagram, const rtl::Reference< ::chart::ChartType >& xChartType )
113{
114 if( xDiagram.is() )
115 {
116 uno::Sequence < sal_Int32 > aAvailableMissingValueTreatment(
118
119 if( aAvailableMissingValueTreatment.hasElements() )
120 xDiagram->setPropertyValue( "MissingValueTreatment", uno::Any( aAvailableMissingValueTreatment[0] ) );
121 else
122 xDiagram->setPropertyValue( "MissingValueTreatment", uno::Any() );
123 }
124}
125
126} // anonymous namespace
127
128namespace chart
129{
130
133 OUString aServiceName ) :
134 m_xContext( xContext ),
135 m_aServiceName(std::move( aServiceName ))
136{
137}
138
140{}
141
142// ____ ChartTypeTemplate ____
144 const uno::Reference< data::XDataSource >& xDataSource,
145 const uno::Sequence< beans::PropertyValue >& aArguments )
146{
148
149 try
150 {
151 // create diagram
152 xDia = new Diagram(GetComponentContext());
153
154 // modify diagram
157 xInterpreter->interpretDataSource(
158 xDataSource, aArguments, {} ));
159
160 sal_Int32 nCount = 0;
161 for( auto const & i : aData.Series )
162 for( auto const & j : i )
163 lcl_applyDefaultStyle( j, nCount++, xDia );
164
165 std::vector< rtl::Reference< ChartType > > aOldChartTypesSeq;
166 FillDiagram( xDia, aData.Series, aData.Categories, aOldChartTypesSeq );
167 }
168 catch( const uno::Exception & )
169 {
170 DBG_UNHANDLED_EXCEPTION("chart2");
171 }
172
173 return xDia;
174}
175
177{
178 return true;
179}
180
182{
183 if( ! xDiagram.is())
184 return;
185
186 try
187 {
188 std::vector< std::vector< rtl::Reference< DataSeries > > > aSeriesSeq =
189 xDiagram->getDataSeriesGroups();
190 std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq ));
191 const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.size();
192
193 // chart-type specific interpretation of existing data series
196 aData.Series = aSeriesSeq;
197 aData.Categories = xDiagram->getCategories();
198
199 if( xInterpreter->isDataCompatible( aData ) )
200 {
201 aData = xInterpreter->reinterpretDataSeries( aData );
202 }
203 else
204 {
206 // todo: get a "range-union" from the data provider by calling
207 // OUString aRange = getRangeRepresentationByData( xSource );
208 // xSource.set( getDataByRangeRepresentation( aRange, aParam ));
209 // where aParam == ??
210 Sequence< beans::PropertyValue > aParam;
211 if( aData.Categories.is())
212 {
213 aParam = { beans::PropertyValue( "HasCategories", -1, uno::Any( true ),
214 beans::PropertyState_DIRECT_VALUE ) };
215 }
216 aData = xInterpreter->interpretDataSource( xSource, aParam, aFlatSeriesSeq );
217 }
218 aSeriesSeq = aData.Series;
219
220 sal_Int32 nIndex = 0;
221 for( auto const & i : std::as_const(aSeriesSeq) )
222 for( auto const & j : i )
223 {
224 if( nIndex >= nFormerSeriesCount )
225 lcl_applyDefaultStyle( j, nIndex++, xDiagram );
226 }
227
228 // remove charttype groups from all coordinate systems
229 std::vector< rtl::Reference< ChartType > > aOldChartTypesSeq =
230 xDiagram->getChartTypes();
231
232 for( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() )
233 {
234 coords->setChartTypes( Sequence< Reference< XChartType > >() );
235 }
236
237 FillDiagram( xDiagram, aSeriesSeq, aData.Categories, aOldChartTypesSeq );
238 }
239 catch( const uno::Exception & )
240 {
241 DBG_UNHANDLED_EXCEPTION("chart2");
242 }
243}
244
246 const rtl::Reference< Diagram >& xDiagram,
247 const Reference< chart2::data::XDataSource >& xDataSource,
248 const Sequence< beans::PropertyValue >& aArguments )
249{
250 if( ! (xDiagram.is() &&
251 xDataSource.is()) )
252 return;
253
254 try
255 {
256 // interpret new data and re-use existing series
257 std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq =
258 xDiagram->getDataSeries();
259 const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.size();
261 InterpretedData aData =
262 xInterpreter->interpretDataSource( xDataSource, aArguments, aFlatSeriesSeq );
263
264 // data series
265 sal_Int32 nIndex = 0;
266 for( std::size_t i=0; i<aData.Series.size(); ++i )
267 for( std::size_t j=0; j<aData.Series[i].size(); ++j, ++nIndex )
268 {
269 if( nIndex >= nFormerSeriesCount )
270 {
271 lcl_applyDefaultStyle( aData.Series[i][j], nIndex, xDiagram );
272 applyStyle2( aData.Series[i][j], i, j, aData.Series[i].size() );
273 }
274 }
275
276 // categories
277 xDiagram->setCategories( aData.Categories, true, supportsCategories() );
278
279 std::vector< rtl::Reference< ChartType > > aChartTypes =
280 xDiagram->getChartTypes();
281 sal_Int32 nMax = std::min( aChartTypes.size(), aData.Series.size());
282 for( sal_Int32 i=0; i<nMax; ++i )
283 {
284 aChartTypes[i]->setDataSeries( aData.Series[i] );
285 }
286 }
287 catch( const uno::Exception & )
288 {
289 DBG_UNHANDLED_EXCEPTION("chart2");
290 }
291}
292
295 bool /* bAdaptProperties */ )
296{
297 bool bResult = false;
298
299 if( ! xDiagram.is())
300 return bResult;
301
302 try
303 {
304 const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq(
305 xDiagram->getBaseCoordinateSystems());
306
307 // need to have at least one coordinate system
308 bResult = !aCooSysSeq.empty();
309 if( bResult )
310 {
311 std::vector< rtl::Reference< ChartType > > aFormerlyUsedChartTypes;
312 rtl::Reference<ChartType> xOldCT = getChartTypeForNewSeries2(aFormerlyUsedChartTypes);
313 if (!xOldCT.is())
314 return false;
315
316 const OUString aChartTypeToMatch = xOldCT->getChartType();
317 const sal_Int32 nDimensionToMatch = getDimension();
318 for( std::size_t nCooSysIdx=0; bResult && (nCooSysIdx < aCooSysSeq.size()); ++nCooSysIdx )
319 {
320 // match dimension
321 bResult = bResult && (aCooSysSeq[nCooSysIdx]->getDimension() == nDimensionToMatch);
322
323 const std::vector< rtl::Reference< ChartType > > & aChartTypeSeq( aCooSysSeq[nCooSysIdx]->getChartTypes2());
324 for( std::size_t nCTIdx=0; bResult && (nCTIdx < aChartTypeSeq.size()); ++nCTIdx )
325 {
326 // match chart type
327 bResult = bResult && aChartTypeSeq[nCTIdx]->getChartType() == aChartTypeToMatch;
328 bool bFound=false;
329 bool bAmbiguous=false;
330 // match stacking mode
331 bResult = bResult &&
333 aChartTypeSeq[nCTIdx], bFound, bAmbiguous,
334 aCooSysSeq[nCooSysIdx] )
335 == getStackMode( nCTIdx ) );
336 }
337 }
338 }
339 }
340 catch( const uno::Exception & )
341 {
342 DBG_UNHANDLED_EXCEPTION("chart2");
343 }
344
345 return bResult;
346}
347
349{
350 if( ! m_xDataInterpreter.is())
352
353 return m_xDataInterpreter;
354}
355
357 const rtl::Reference< DataSeries >& xSeries,
358 ::sal_Int32 nChartTypeIndex,
359 ::sal_Int32 /* nSeriesIndex */,
360 ::sal_Int32 /* nSeriesCount */ )
361{
362 // sset stacking mode
363 if( !xSeries.is())
364 return;
365
366 try
367 {
368 StackMode eStackMode = getStackMode( nChartTypeIndex );
369 const uno::Any aPropValue(
370 ( (eStackMode == StackMode::YStacked) ||
371 (eStackMode == StackMode::YStackedPercent) )
372 ? chart2::StackingDirection_Y_STACKING
373 : (eStackMode == StackMode::ZStacked )
374 ? chart2::StackingDirection_Z_STACKING
375 : chart2::StackingDirection_NO_STACKING );
376 xSeries->setPropertyValue( "StackingDirection", aPropValue );
377
378 //ensure valid label placement
379 {
381 getChartTypeForIndex( nChartTypeIndex ), isSwapXAndY(), xSeries ) );
382 lcl_ensureCorrectLabelPlacement( xSeries, aAvailablePlacements );
383
384 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
385 // "AttributedDataPoints"
386 if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
387 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
388 lcl_ensureCorrectLabelPlacement( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), aAvailablePlacements );
389 }
390 }
391 catch( const uno::Exception & )
392 {
393 DBG_UNHANDLED_EXCEPTION("chart2");
394 }
395}
396
398{
399 // apply chart-type specific styles, like "symbols on" for example
400 std::vector< std::vector< rtl::Reference< DataSeries > > > aNewSeriesSeq(
401 xDiagram->getDataSeriesGroups());
402 for( std::size_t i=0; i<aNewSeriesSeq.size(); ++i )
403 {
404 const sal_Int32 nNumSeries = aNewSeriesSeq[i].size();
405 for( sal_Int32 j=0; j<nNumSeries; ++j )
406 applyStyle2( aNewSeriesSeq[i][j], i, j, nNumSeries );
407 }
408
409 //ensure valid empty cell handling (for first chart type...)
410 lcl_ensureCorrectMissingValueTreatment( xDiagram, getChartTypeForIndex( 0 ) );
411}
412
414{
415 // reset number format if we had percent stacking on
416 bool bPercent = (getStackMode(0) == StackMode::YStackedPercent);
417 if( bPercent )
418 {
419 const std::vector< rtl::Reference< Axis > > aAxisSeq( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
420 for( rtl::Reference< Axis > const & axis : aAxisSeq )
421 {
422 if( AxisHelper::getDimensionIndexOfAxis( axis, xDiagram )== 1 )
423 {
424 // set number format to source format
425 axis->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(true));
426 axis->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any());
427 }
428 }
429 }
430
431 //reset label placement if default
432 for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : xDiagram->getBaseCoordinateSystems() )
433 {
434 //iterate through all chart types in the current coordinate system
435 for( rtl::Reference< ChartType > const & xChartType : xCooSys->getChartTypes2() )
436 {
437 //iterate through all series in this chart type
438 for( rtl::Reference< DataSeries > const & xSeries : xChartType->getDataSeries2() )
439 {
441 xChartType, isSwapXAndY(), xSeries ) );
442 if(!aAvailablePlacements.hasElements())
443 continue;
444
445 sal_Int32 nDefaultPlacement = aAvailablePlacements[0];
446
447 lcl_resetLabelPlacementIfDefault( xSeries, nDefaultPlacement );
448
449 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
450 // "AttributedDataPoints"
451 if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
452 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
453 lcl_resetLabelPlacementIfDefault( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), nDefaultPlacement );
454 }
455 }
456 }
457
458}
459
460// ____ XServiceName ____
462{
463 return m_aServiceName;
464}
465
467{
468 return 2;
469}
470
471StackMode ChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
472{
473 return StackMode::NONE;
474}
475
477{
478 return false;
479}
480
482 const rtl::Reference< ::chart::Diagram > & xDiagram )
483{
484 if( ! xDiagram.is())
485 return;
486 std::vector< rtl::Reference< ChartType > > aFormerlyUsedChartTypes;
487 rtl::Reference< ChartType > xChartType( getChartTypeForNewSeries2(aFormerlyUsedChartTypes));
488 if( ! xChartType.is())
489 return;
490 rtl::Reference< BaseCoordinateSystem > xCooSys = xChartType->createCoordinateSystem2( getDimension());
491 if( ! xCooSys.is())
492 {
493 // chart type wants no coordinate systems
494 xDiagram->setCoordinateSystems( Sequence< Reference< XCoordinateSystem > >());
495 return;
496 }
497 // #i69680# make grid of first y-axis visible (was in the CooSys CTOR before)
498 if( xCooSys->getDimension() >= 2 )
499 {
500 rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( 1, 0 );
501 if( xAxis.is())
502 AxisHelper::makeGridVisible( xAxis->getGridProperties2() );
503 }
504
505 std::vector< rtl::Reference< BaseCoordinateSystem > > aCoordinateSystems(
506 xDiagram->getBaseCoordinateSystems());
507
508 if( !aCoordinateSystems.empty() )
509 {
510 bool bOk = true;
511 for( std::size_t i=0; bOk && i<aCoordinateSystems.size(); ++i )
512 bOk = bOk && ( xCooSys->getCoordinateSystemType() == aCoordinateSystems[i]->getCoordinateSystemType() &&
513 (xCooSys->getDimension() == aCoordinateSystems[i]->getDimension()) );
514 // coordinate systems are ok
515 if( bOk )
516 return;
517 // there are coordinate systems but they do not fit. So overwrite them.
518 }
519
520 //copy as much info from former coordinate system as possible:
521 if( !aCoordinateSystems.empty() )
522 {
523 rtl::Reference< BaseCoordinateSystem > xOldCooSys( aCoordinateSystems[0] );
524 sal_Int32 nMaxDimensionCount = std::min( xCooSys->getDimension(), xOldCooSys->getDimension() );
525
526 for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nMaxDimensionCount; nDimensionIndex++)
527 {
528 const sal_Int32 nMaximumAxisIndex = xOldCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
529 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
530 {
531 rtl::Reference< Axis > xAxis = xOldCooSys->getAxisByDimension2( nDimensionIndex, nAxisIndex );
532 if( xAxis.is())
533 {
534 xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
535 }
536 }
537 }
538 }
539
540 // set new coordinate systems
541 aCoordinateSystems = { xCooSys };
542
543 xDiagram->setCoordinateSystems( aCoordinateSystems );
544}
545
547 const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq,
548 const Reference< data::XLabeledDataSequence > & xCategories //@todo: in future there may be more than one sequence of categories (e.g. charttype with categories at x and y axis )
549 )
550{
551 bool bSupportsCategories( supportsCategories() );
552 for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : aCooSysSeq )
553 {
554 try
555 {
556 // attach categories to first axis
557 sal_Int32 nDim( xCooSys->getDimension());
558 if( nDim > 0 )
559 {
560 const sal_Int32 nDimensionX = 0;
561 const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionX);
562 for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
563 {
564 rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2(nDimensionX,nI);
565 if( xAxis.is())
566 {
567 ScaleData aData( xAxis->getScaleData() );
568 aData.Categories = xCategories;
569 if(bSupportsCategories)
570 {
572 if( aData.AxisType == AxisType::CATEGORY )
573 {
574 aData.ShiftedCategoryPosition = m_aServiceName.indexOf("Column") != -1 || m_aServiceName.indexOf("Bar") != -1 || m_aServiceName.endsWith("Close");
575 }
576 bool bSupportsDates = ::chart::ChartTypeHelper::isSupportingDateAxis( xChartType, nDimensionX );
577 if( aData.AxisType != AxisType::CATEGORY && ( aData.AxisType != AxisType::DATE || !bSupportsDates) )
578 {
579 aData.AxisType = AxisType::CATEGORY;
580 aData.AutoDateAxis = true;
582 }
583 }
584 else
585 aData.AxisType = AxisType::REALNUMBER;
586
587 xAxis->setScaleData( aData );
588 }
589 }
590 }
591 // set percent stacking mode at second axis
592 if( nDim > 1 )
593 {
594 const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(1);
595 for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
596 {
597 rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( 1,nI );
598 if( xAxis.is())
599 {
600 bool bPercent = (getStackMode(0) == StackMode::YStackedPercent);
601 chart2::ScaleData aScaleData = xAxis->getScaleData();
602
603 if( bPercent != (aScaleData.AxisType==AxisType::PERCENT) )
604 {
605 if( bPercent )
606 aScaleData.AxisType = AxisType::PERCENT;
607 else
608 aScaleData.AxisType = AxisType::REALNUMBER;
609 xAxis->setScaleData( aScaleData );
610 }
611 }
612 }
613 }
614 }
615 catch( const uno::Exception & )
616 {
617 DBG_UNHANDLED_EXCEPTION("chart2");
618 }
619 }
620}
621
623{
624}
625
627 const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys )
628{
629 //create missing axes
630 if( rCoordSys.empty() )
631 return;
632
633 rtl::Reference< BaseCoordinateSystem > xCooSys( rCoordSys[0] );
634 if(!xCooSys.is())
635 return;
636
637 //create main axis in first coordinate system
638 sal_Int32 nDimCount = xCooSys->getDimension();
639 sal_Int32 nDim=0;
640 for( nDim=0; nDim<nDimCount; ++nDim )
641 {
642 sal_Int32 nAxisCount = getAxisCountByDimension( nDim );
643 if( nDim == 1 &&
644 nAxisCount < 2 && AxisHelper::isSecondaryYAxisNeeded( xCooSys ))
645 nAxisCount = 2;
646 for( sal_Int32 nAxisIndex = 0; nAxisIndex < nAxisCount; ++nAxisIndex )
647 {
648 Reference< XAxis > xAxis = AxisHelper::getAxis( nDim, nAxisIndex, xCooSys );
649 if( !xAxis.is())
650 {
651 // create and add axis
652 xAxis.set( AxisHelper::createAxis(
653 nDim, nAxisIndex, xCooSys, GetComponentContext() ));
654 }
655 }
656 }
657}
658
660 const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys )
661{
662 //adapt properties of existing axes and remove superfluous axes
663
664 if( rCoordSys.empty() )
665 return;
666
667 for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : rCoordSys )
668 {
669 if( !xCooSys.is() )
670 continue;
671 sal_Int32 nDimCount = xCooSys->getDimension();
672 for( sal_Int32 nDim=0; nDim<nDimCount; ++nDim )
673 {
674 sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension( nDim );
675 for( sal_Int32 nAxisIndex=0; nAxisIndex<=nMaxAxisIndex; nAxisIndex++ )
676 {
677 rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDim, nAxisIndex, xCooSys );
678 if( !xAxis.is() )
679 continue;
680
681 if( nAxisIndex == MAIN_AXIS_INDEX || nAxisIndex == SECONDARY_AXIS_INDEX )
682 {
683 // adapt scales
684 bool bPercent = (getStackMode(0) == StackMode::YStackedPercent);
685 if( bPercent && nDim == 1 )
686 {
687 // set number format to source format
688 xAxis->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(true));
689 xAxis->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any());
690 }
691 }
692 }
693 }
694 }
695}
696
697sal_Int32 ChartTypeTemplate::getAxisCountByDimension( sal_Int32 nDimension )
698{
699 return (nDimension < getDimension()) ? 1 : 0;
700}
701
704 const std::vector< std::vector< rtl::Reference< DataSeries > > >& aSeriesSeq,
706 const std::vector< rtl::Reference< ChartType > >& aOldChartTypesSeq )
707{
708 adaptDiagram( xDiagram );
709
710 try
711 {
712 // create coordinate systems and scales
713 createCoordinateSystems( xDiagram );
714 std::vector< rtl::Reference< BaseCoordinateSystem > > aCoordinateSystems( xDiagram->getBaseCoordinateSystems());
715 createAxes( aCoordinateSystems );
716 adaptAxes( aCoordinateSystems );
717 adaptScales( aCoordinateSystems, xCategories );
718
719 // chart types
720 createChartTypes( aSeriesSeq, aCoordinateSystems, aOldChartTypesSeq );
721 applyStyles( xDiagram );
722 }
723 catch( const uno::Exception & )
724 {
725 DBG_UNHANDLED_EXCEPTION("chart2");
726 }
727}
728
730 const std::vector< std::vector< rtl::Reference< DataSeries > > > & aSeriesSeq,
731 const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys,
732 const std::vector< rtl::Reference< ChartType > >& aOldChartTypesSeq )
733{
734 if( rCoordSys.empty() )
735 return;
736
737 try
738 {
739 std::size_t nCooSysIdx=0;
741 if( aSeriesSeq.empty() )
742 {
743 // we need a new chart type
744 xCT = getChartTypeForNewSeries2( aOldChartTypesSeq );
745 rCoordSys[nCooSysIdx]->setChartTypes(std::vector{ xCT });
746 }
747 else
748 {
749 for( std::size_t nSeriesIdx=0; nSeriesIdx<aSeriesSeq.size(); ++nSeriesIdx )
750 {
751 if( nSeriesIdx == nCooSysIdx )
752 {
753 // we need a new chart type
754 xCT = getChartTypeForNewSeries2( aOldChartTypesSeq );
755 std::vector< rtl::Reference< ChartType > > aCTSeq( rCoordSys[nCooSysIdx]->getChartTypes2());
756 if( !aCTSeq.empty())
757 {
758 aCTSeq[0] = xCT;
759 rCoordSys[nCooSysIdx]->setChartTypes( aCTSeq );
760 }
761 else
762 rCoordSys[nCooSysIdx]->addChartType( xCT );
763
764 xCT->setDataSeries( aSeriesSeq[nSeriesIdx] );
765 }
766 else
767 {
768 // reuse existing chart type
769 OSL_ASSERT( xCT.is());
770 std::vector< rtl::Reference< DataSeries > > aNewSeriesSeq = xCT->getDataSeries2();
771 sal_Int32 nNewStartIndex = aNewSeriesSeq.size();
772 aNewSeriesSeq.resize( nNewStartIndex + aSeriesSeq[nSeriesIdx].size() );
773 std::copy( aSeriesSeq[nSeriesIdx].begin(),
774 aSeriesSeq[nSeriesIdx].end(),
775 aNewSeriesSeq.begin() + nNewStartIndex );
776 xCT->setDataSeries( aNewSeriesSeq );
777 }
778
779 // spread the series over the available coordinate systems
780 if( rCoordSys.size() > (nCooSysIdx + 1) )
781 ++nCooSysIdx;
782 }
783 }
784 }
785 catch( const uno::Exception & )
786 {
787 DBG_UNHANDLED_EXCEPTION("chart2");
788 }
789}
790
792 const std::vector< rtl::Reference< ChartType > > & rOldChartTypesSeq,
793 const rtl::Reference< ChartType > & xNewChartType )
794{
795 if( !xNewChartType.is() )
796 return;
797
798 OUString aNewChartType( xNewChartType->getChartType() );
799
801 for( rtl::Reference< ChartType > const & xOldType : rOldChartTypesSeq )
802 {
803 if( xOldType.is() && xOldType->getChartType() == aNewChartType )
804 {
805 xSource = xOldType;
806 if( xSource.is() )
807 break;
808 }
809 }
810 if( xSource.is() )
811 comphelper::copyProperties( xSource, xNewChartType );
812}
813
814css::uno::Reference< css::uno::XInterface > ChartTypeTemplate::getDataInterpreter()
815{
816 return static_cast<cppu::OWeakObject*>(getDataInterpreter2().get());
817}
818css::uno::Reference< css::chart2::XDiagram > ChartTypeTemplate::createDiagramByDataSource(
819 const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource,
820 const css::uno::Sequence< css::beans::PropertyValue >& aArguments )
821{
822 return createDiagramByDataSource2(xDataSource, aArguments);
823}
825 const css::uno::Reference< css::chart2::XDiagram >& xDiagram )
826{
827 changeDiagram(rtl::Reference<Diagram>(dynamic_cast<Diagram*>(xDiagram.get())));
828}
830 const css::uno::Reference< css::chart2::XDiagram >& xDiagram,
831 const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource,
832 const css::uno::Sequence< css::beans::PropertyValue >& aArguments )
833{
834 changeDiagramData(rtl::Reference<Diagram>(dynamic_cast<Diagram*>(xDiagram.get())), xDataSource, aArguments);
835}
837 const css::uno::Reference<css::chart2::XDiagram >& xDiagram,
838 sal_Bool bAdaptProperties )
839{
840 return matchesTemplate2(dynamic_cast<Diagram*>(xDiagram.get()), static_cast<bool>(bAdaptProperties));
841}
842css::uno::Reference< ::css::chart2::XChartType > ChartTypeTemplate::getChartTypeForNewSeries(
843 const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes )
844{
845 std::vector< rtl::Reference< ::chart::ChartType > > aTmp;
846 aTmp.reserve(aFormerlyUsedChartTypes.getLength());
847 for (auto const & rxChartType : aFormerlyUsedChartTypes)
848 aTmp.push_back(dynamic_cast<ChartType*>(rxChartType.get()));
849 return getChartTypeForNewSeries2(aTmp);
850}
852 const css::uno::Reference< css::chart2::XDataSeries >& xSeries,
853 ::sal_Int32 nChartTypeIndex,
854 ::sal_Int32 nSeriesIndex,
855 ::sal_Int32 nSeriesCount )
856{
857 applyStyle2(dynamic_cast<DataSeries*>(xSeries.get()), nChartTypeIndex, nSeriesIndex, nSeriesCount);
858}
860 const css::uno::Reference< css::chart2::XDiagram >& xDiagram )
861{
862 resetStyles2(dynamic_cast<Diagram*>(xDiagram.get()));
863}
864
865} // namespace chart
866
867/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< uno::XComponentContext > m_xContext
int nDimCount
static rtl::Reference< ::chart::Axis > getAxis(sal_Int32 nDimensionIndex, bool bMainAxis, const rtl::Reference< ::chart::Diagram > &xDiagram)
static rtl::Reference< ::chart::Axis > createAxis(sal_Int32 nDimensionIndex, bool bMainAxis, const rtl::Reference< ::chart::Diagram > &xDiagram, const css::uno::Reference< css::uno::XComponentContext > &xContext, ReferenceSizeProvider *pRefSizeProvider=nullptr)
static std::vector< rtl::Reference< ::chart::Axis > > getAllAxesOfDiagram(const rtl::Reference< ::chart::Diagram > &xDiagram, bool bOnlyVisible=false)
Definition: AxisHelper.cxx:809
static sal_Int32 getDimensionIndexOfAxis(const rtl::Reference< ::chart::Axis > &xAxis, const rtl::Reference< ::chart::Diagram > &xDiagram)
Definition: AxisHelper.cxx:700
static void removeExplicitScaling(css::chart2::ScaleData &rScaleData)
Definition: AxisHelper.cxx:86
static void makeGridVisible(const rtl::Reference< ::chart::GridProperties > &xGridProperties)
Definition: AxisHelper.cxx:452
static bool isSecondaryYAxisNeeded(const rtl::Reference< ::chart::BaseCoordinateSystem > &xCooSys)
Definition: AxisHelper.cxx:870
static css::uno::Sequence< sal_Int32 > getSupportedLabelPlacements(const rtl::Reference< ::chart::ChartType > &xChartType, bool bSwapXAndY, const rtl::Reference< ::chart::DataSeries > &xSeries)
static css::uno::Sequence< sal_Int32 > getSupportedMissingValueTreatments(const rtl::Reference< ::chart::ChartType > &xChartType)
static bool isSupportingDateAxis(const rtl::Reference< ::chart::ChartType > &xChartType, sal_Int32 nDimensionIndex)
virtual sal_Bool SAL_CALL matchesTemplate(const css::uno::Reference< css::chart2::XDiagram > &xDiagram, sal_Bool bAdaptProperties) override final
void FillDiagram(const rtl::Reference< ::chart::Diagram > &xDiagram, const std::vector< std::vector< rtl::Reference< ::chart::DataSeries > > > &aSeriesSeq, const css::uno::Reference< css::chart2::data::XLabeledDataSequence > &xCategories, const std::vector< rtl::Reference< ChartType > > &aOldChartTypesSeq)
modifies the given diagram
virtual css::uno::Reference< ::css::chart2::XChartType > SAL_CALL getChartTypeForNewSeries(const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > > &aFormerlyUsedChartTypes) override final
rtl::Reference< ::chart::Diagram > createDiagramByDataSource2(const css::uno::Reference< css::chart2::data::XDataSource > &xDataSource, const css::uno::Sequence< css::beans::PropertyValue > &aArguments)
virtual sal_Bool SAL_CALL supportsCategories() override
denotes if the chart needs categories at the first scale
virtual sal_Int32 getAxisCountByDimension(sal_Int32 nDimension)
Give the number of requested axis per dimension here.
virtual bool matchesTemplate2(const rtl::Reference< ::chart::Diagram > &xDiagram, bool bAdaptProperties)
virtual void SAL_CALL applyStyle(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, ::sal_Int32 nChartTypeIndex, ::sal_Int32 nSeriesIndex, ::sal_Int32 nSeriesCount) override final
virtual sal_Int32 getDimension() const
returns 2 by default. Supported are 2 and 3
virtual OUString SAL_CALL getServiceName() override
virtual rtl::Reference< ::chart::ChartType > getChartTypeForIndex(sal_Int32 nChartTypeIndex)=0
void createAxes(const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > &rCoordSys)
create axes and add them to the given container.
virtual void createChartTypes(const std::vector< std::vector< rtl::Reference< ::chart::DataSeries > > > &aSeriesSeq, const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > &rCoordSys, const std::vector< rtl::Reference< ChartType > > &aOldChartTypesSeq)
create a data series tree, that fits the requirements of the chart type.
virtual void adaptAxes(const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > &rCoordSys)
adapt properties of existing axes and remove superfluous axes
virtual StackMode getStackMode(sal_Int32 nChartTypeIndex) const
returns StackMode::NONE by default.
virtual void adaptScales(const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > &aCooSysSeq, const css::uno::Reference< css::chart2::data::XLabeledDataSequence > &xCategories)
Sets categories at the scales of dimension 0 and the percent stacking at the scales of dimension 1 of...
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getDataInterpreter() override final
virtual void SAL_CALL changeDiagram(const css::uno::Reference< css::chart2::XDiagram > &xDiagram) override final
ChartTypeTemplate(css::uno::Reference< css::uno::XComponentContext > const &xContext, OUString aServiceName)
virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2()
static void copyPropertiesFromOldToNewCoordinateSystem(const std::vector< rtl::Reference< ChartType > > &rOldChartTypesSeq, const rtl::Reference< ChartType > &xNewChartType)
virtual void SAL_CALL changeDiagramData(const css::uno::Reference< css::chart2::XDiagram > &xDiagram, const css::uno::Reference< css::chart2::data::XDataSource > &xDataSource, const css::uno::Sequence< css::beans::PropertyValue > &aArguments) override final
virtual void SAL_CALL resetStyles(const css::uno::Reference< css::chart2::XDiagram > &xDiagram) override final
const css::uno::Reference< css::uno::XComponentContext > & GetComponentContext() const
virtual bool isSwapXAndY() const
virtual void adaptDiagram(const rtl::Reference< ::chart::Diagram > &xDiagram)
Allows derived classes to manipulate the diagrams whole, like changing the wall color.
void applyStyles(const rtl::Reference< ::chart::Diagram > &xDiagram)
rtl::Reference< ::chart::DataInterpreter > m_xDataInterpreter
virtual void applyStyle2(const rtl::Reference< ::chart::DataSeries > &xSeries, ::sal_Int32 nChartTypeIndex, ::sal_Int32 nSeriesIndex, ::sal_Int32 nSeriesCount)
virtual void createCoordinateSystems(const rtl::Reference< ::chart::Diagram > &xDiagram)
Creates a 2d or 3d cartesian coordinate system with mathematically oriented, linear scales with auto-...
virtual rtl::Reference< ::chart::ChartType > getChartTypeForNewSeries2(const std::vector< rtl::Reference< ::chart::ChartType > > &aFormerlyUsedChartTypes)=0
virtual css::uno::Reference< css::chart2::XDiagram > SAL_CALL createDiagramByDataSource(const css::uno::Reference< css::chart2::data::XDataSource > &xDataSource, const css::uno::Sequence< css::beans::PropertyValue > &aArguments) override final
virtual ~ChartTypeTemplate() override
virtual void resetStyles2(const rtl::Reference< ::chart::Diagram > &xDiagram)
offers tooling to interpret different data sources in a structural and chart-type-dependent way.
static rtl::Reference< ::chart::DataSource > mergeInterpretedData(const InterpretedData &aInterpretedData)
Try to reverse the operation done in interpretDataSource().
static StackMode getStackModeFromChartType(const rtl::Reference< ::chart::ChartType > &xChartType, bool &rbFound, bool &rbAmbiguous, const rtl::Reference< ::chart::BaseCoordinateSystem > &xCorrespondingCoordinateSystem)
Retrieves the stackmode of the first DataSeries or none.
int nCount
#define DBG_UNHANDLED_EXCEPTION(...)
Sequence< PropertyValue > aArguments
sal_Int32 nIndex
constexpr OUStringLiteral aData
size
const sal_Int32 SECONDARY_AXIS_INDEX
std::vector< T > FlattenSequence(const std::vector< std::vector< T > > &aSeqSeq)
std::vector< std::vector< T > > -> std::vector< T >
const sal_Int32 MAIN_AXIS_INDEX
void copyProperties(const Reference< XPropertySet > &_rxSource, const Reference< XPropertySet > &_rxDest)
int i
enumrange< T >::Iterator begin(enumrange< T >)
end
offers tooling to interpret different data sources in a structural and chart-type-dependent way.
unsigned char sal_Bool
constexpr OUStringLiteral CHART_UNONAME_LINK_TO_SRC_NUMFMT
Definition: unonames.hxx:21
constexpr OUStringLiteral CHART_UNONAME_NUMFMT
Definition: unonames.hxx:20