1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <DiagramHelper.hxx>
21 #include <DataSeriesHelper.hxx>
22 #include <AxisHelper.hxx>
23 #include <ChartTypeHelper.hxx>
24 #include <ChartModel.hxx>
25 #include <ChartModelHelper.hxx>
26 #include <ExplicitCategoriesProvider.hxx>
27 #include <servicenames_charttypes.hxx>
28 #include <RelativePositionHelper.hxx>
29 #include <ControllerLockGuard.hxx>
30 #include <NumberFormatterWrapper.hxx>
31 #include <unonames.hxx>
33 #include <com/sun/star/chart/MissingValueTreatment.hpp>
34 #include <com/sun/star/chart/XDiagramPositioning.hpp>
35 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
36 #include <com/sun/star/chart2/XTitled.hpp>
37 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
38 #include <com/sun/star/chart2/XChartTypeTemplate.hpp>
39 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
40 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
41 #include <com/sun/star/chart2/AxisType.hpp>
42 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
43 #include <com/sun/star/chart2/RelativePosition.hpp>
44 #include <com/sun/star/chart2/RelativeSize.hpp>
45 #include <com/sun/star/chart2/StackingDirection.hpp>
47 #include <com/sun/star/util/CloseVetoException.hpp>
48 #include <com/sun/star/util/NumberFormat.hpp>
49 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
51 #include <unotools/saveopt.hxx>
52 #include <rtl/math.hxx>
53 #include <svl/zforlist.hxx>
54 #include <vcl/svapp.hxx>
55 #include <vcl/settings.hxx>
56 #include <comphelper/sequence.hxx>
57 #include <tools/diagnose_ex.h>
58 #include <sal/log.hxx>
60 using namespace ::com::sun::star
;
61 using namespace ::com::sun::star::chart2
;
62 using namespace ::std
;
64 using ::com::sun::star::uno::Reference
;
65 using ::com::sun::star::uno::Sequence
;
66 using ::com::sun::star::uno::Any
;
67 using ::com::sun::star::chart2::XAnyDescriptionAccess
;
72 DiagramHelper::tTemplateWithServiceName
73 DiagramHelper::getTemplateForDiagram(
74 const Reference
< XDiagram
> & xDiagram
,
75 const Reference
< lang::XMultiServiceFactory
> & xChartTypeManager
)
77 DiagramHelper::tTemplateWithServiceName aResult
;
79 if( ! (xChartTypeManager
.is() && xDiagram
.is()))
82 Sequence
< OUString
> aServiceNames( xChartTypeManager
->getAvailableServiceNames());
83 const sal_Int32 nLength
= aServiceNames
.getLength();
85 bool bTemplateFound
= false;
87 for( sal_Int32 i
= 0; ! bTemplateFound
&& i
< nLength
; ++i
)
91 Reference
< XChartTypeTemplate
> xTempl(
92 xChartTypeManager
->createInstance( aServiceNames
[ i
] ), uno::UNO_QUERY_THROW
);
94 if (xTempl
.is() && xTempl
->matchesTemplate(xDiagram
, true))
96 aResult
.first
= xTempl
;
97 aResult
.second
= aServiceNames
[ i
];
98 bTemplateFound
= true;
101 catch( const uno::Exception
& )
103 DBG_UNHANDLED_EXCEPTION("chart2");
110 void DiagramHelper::setVertical(
111 const Reference
< XDiagram
> & xDiagram
,
112 bool bVertical
/* = true */ )
116 Reference
< XCoordinateSystemContainer
> xCnt( xDiagram
, uno::UNO_QUERY
);
120 Sequence
< Reference
<XCoordinateSystem
> > aCooSys
= xCnt
->getCoordinateSystems();
122 aValue
<<= bVertical
;
123 for( sal_Int32 i
=0; i
<aCooSys
.getLength(); ++i
)
125 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSys
[i
] );
126 Reference
< beans::XPropertySet
> xProp( xCooSys
, uno::UNO_QUERY
);
127 bool bChanged
= false;
130 bool bOldSwap
= false;
131 if( !(xProp
->getPropertyValue("SwapXAndYAxis") >>= bOldSwap
)
132 || bVertical
!= bOldSwap
)
136 xProp
->setPropertyValue("SwapXAndYAxis", aValue
);
142 const sal_Int32 nDimensionCount
= xCooSys
->getDimension();
143 sal_Int32 nDimIndex
= 0;
144 for (nDimIndex
=0; nDimIndex
< nDimensionCount
; ++nDimIndex
)
146 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimIndex
);
147 for (sal_Int32 nI
= 0; nI
<= nMaximumScaleIndex
; ++nI
)
149 Reference
<chart2::XAxis
> xAxis
= xCooSys
->getAxisByDimension(nDimIndex
,nI
);
153 //adapt title rotation only when axis swapping has changed
157 Reference
< XTitled
> xTitled( xAxis
, uno::UNO_QUERY
);
161 Reference
< beans::XPropertySet
> xTitleProps( xTitled
->getTitleObject(), uno::UNO_QUERY
);
162 if (!xTitleProps
.is())
165 double fAngleDegree
= 0.0;
166 xTitleProps
->getPropertyValue("TextRotation") >>= fAngleDegree
;
167 if (fAngleDegree
!= 0.0 &&
168 !rtl::math::approxEqual(fAngleDegree
, 90.0))
171 double fNewAngleDegree
= 0.0;
172 if( !bVertical
&& nDimIndex
== 1 )
173 fNewAngleDegree
= 90.0;
174 else if( bVertical
&& nDimIndex
== 0 )
175 fNewAngleDegree
= 90.0;
177 xTitleProps
->setPropertyValue("TextRotation", uno::Any(fNewAngleDegree
));
182 catch( const uno::Exception
& )
184 DBG_UNHANDLED_EXCEPTION("chart2");
188 bool DiagramHelper::getVertical( const uno::Reference
< chart2::XDiagram
> & xDiagram
,
189 bool& rbFound
, bool& rbAmbiguous
)
195 Reference
< XCoordinateSystemContainer
> xCnt( xDiagram
, uno::UNO_QUERY
);
199 Sequence
< Reference
<XCoordinateSystem
> > aCooSys
= xCnt
->getCoordinateSystems();
201 for (sal_Int32 i
= 0; i
< aCooSys
.getLength(); ++i
)
203 Reference
<beans::XPropertySet
> xProp(aCooSys
[i
], uno::UNO_QUERY
);
207 bool bCurrent
= false;
208 if (xProp
->getPropertyValue("SwapXAndYAxis") >>= bCurrent
)
215 else if (bCurrent
!= bValue
)
217 // ambiguous -> choose always first found
225 void DiagramHelper::setStackMode(
226 const Reference
< XDiagram
> & xDiagram
,
232 bool bValueFound
= false;
233 bool bIsAmbiguous
= false;
234 StackMode eOldStackMode
= DiagramHelper::getStackMode( xDiagram
, bValueFound
, bIsAmbiguous
);
236 if( eStackMode
== eOldStackMode
&& !bIsAmbiguous
)
239 StackingDirection eNewDirection
= StackingDirection_NO_STACKING
;
240 if( eStackMode
== StackMode::YStacked
|| eStackMode
== StackMode::YStackedPercent
)
241 eNewDirection
= StackingDirection_Y_STACKING
;
242 else if( eStackMode
== StackMode::ZStacked
)
243 eNewDirection
= StackingDirection_Z_STACKING
;
245 uno::Any
aNewDirection( eNewDirection
);
247 bool bPercent
= false;
248 if( eStackMode
== StackMode::YStackedPercent
)
251 //iterate through all coordinate systems
252 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
253 if( !xCooSysContainer
.is() )
255 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
256 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
258 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
259 //set correct percent stacking
260 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(1);
261 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
263 Reference
< chart2::XAxis
> xAxis( xCooSys
->getAxisByDimension( 1,nI
));
266 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
267 if( (aScaleData
.AxisType
==AxisType::PERCENT
) != bPercent
)
270 aScaleData
.AxisType
= AxisType::PERCENT
;
272 aScaleData
.AxisType
= AxisType::REALNUMBER
;
273 xAxis
->setScaleData( aScaleData
);
277 //iterate through all chart types in the current coordinate system
278 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
279 if( !xChartTypeContainer
.is() )
281 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
282 if (!aChartTypeList
.hasElements())
285 uno::Reference
< XChartType
> xChartType( aChartTypeList
[0] );
287 //iterate through all series in this chart type
288 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xChartType
, uno::UNO_QUERY
);
289 OSL_ASSERT( xDataSeriesContainer
.is());
290 if( !xDataSeriesContainer
.is() )
293 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
294 for( sal_Int32 nS
= 0; nS
< aSeriesList
.getLength(); ++nS
)
296 Reference
< beans::XPropertySet
> xProp( aSeriesList
[nS
], uno::UNO_QUERY
);
298 xProp
->setPropertyValue( "StackingDirection", aNewDirection
);
302 catch( const uno::Exception
& )
304 DBG_UNHANDLED_EXCEPTION("chart2");
308 StackMode
DiagramHelper::getStackMode( const Reference
< XDiagram
> & xDiagram
, bool& rbFound
, bool& rbAmbiguous
)
313 StackMode eGlobalStackMode
= StackMode::NONE
;
315 //iterate through all coordinate systems
316 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
317 if( !xCooSysContainer
.is() )
318 return eGlobalStackMode
;
319 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
320 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
322 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
324 //iterate through all chart types in the current coordinate system
325 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
326 if( !xChartTypeContainer
.is() )
328 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
329 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
331 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
333 StackMode eLocalStackMode
= DiagramHelper::getStackModeFromChartType(
334 xChartType
, rbFound
, rbAmbiguous
, xCooSys
);
336 if( rbFound
&& eLocalStackMode
!= eGlobalStackMode
&& nT
>0 )
339 return eGlobalStackMode
;
342 eGlobalStackMode
= eLocalStackMode
;
346 return eGlobalStackMode
;
349 StackMode
DiagramHelper::getStackModeFromChartType(
350 const Reference
< XChartType
> & xChartType
,
351 bool& rbFound
, bool& rbAmbiguous
,
352 const Reference
< XCoordinateSystem
> & xCorrespondingCoordinateSystem
)
354 StackMode eStackMode
= StackMode::NONE
;
360 Reference
< XDataSeriesContainer
> xDSCnt( xChartType
, uno::UNO_QUERY_THROW
);
361 Sequence
< Reference
< chart2::XDataSeries
> > aSeries( xDSCnt
->getDataSeries());
363 chart2::StackingDirection eCommonDirection
= chart2::StackingDirection_NO_STACKING
;
364 bool bDirectionInitialized
= false;
366 // first series is irrelevant for stacking, start with second, unless
367 // there is only one series
368 const sal_Int32 nSeriesCount
= aSeries
.getLength();
369 sal_Int32 i
= (nSeriesCount
== 1) ? 0: 1;
370 for( ; i
<nSeriesCount
; ++i
)
373 Reference
< beans::XPropertySet
> xProp( aSeries
[i
], uno::UNO_QUERY_THROW
);
374 chart2::StackingDirection eCurrentDirection
= eCommonDirection
;
375 // property is not MAYBEVOID
376 bool bSuccess
= ( xProp
->getPropertyValue( "StackingDirection" ) >>= eCurrentDirection
);
377 OSL_ASSERT( bSuccess
);
378 if( ! bDirectionInitialized
)
380 eCommonDirection
= eCurrentDirection
;
381 bDirectionInitialized
= true;
385 if( eCommonDirection
!= eCurrentDirection
)
395 if( eCommonDirection
== chart2::StackingDirection_Z_STACKING
)
396 eStackMode
= StackMode::ZStacked
;
397 else if( eCommonDirection
== chart2::StackingDirection_Y_STACKING
)
399 eStackMode
= StackMode::YStacked
;
402 if( xCorrespondingCoordinateSystem
.is() )
404 if( 1 < xCorrespondingCoordinateSystem
->getDimension() )
406 sal_Int32 nAxisIndex
= 0;
408 nAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(aSeries
[0]);
410 Reference
< chart2::XAxis
> xAxis(
411 xCorrespondingCoordinateSystem
->getAxisByDimension( 1,nAxisIndex
));
414 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
415 if( aScaleData
.AxisType
==chart2::AxisType::PERCENT
)
416 eStackMode
= StackMode::YStackedPercent
;
423 catch( const uno::Exception
& )
425 DBG_UNHANDLED_EXCEPTION("chart2");
431 sal_Int32
DiagramHelper::getDimension( const Reference
< XDiagram
> & xDiagram
)
434 sal_Int32 nResult
= -1;
438 Reference
< XCoordinateSystemContainer
> xCooSysCnt( xDiagram
, uno::UNO_QUERY
);
439 if( xCooSysCnt
.is() )
441 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
442 xCooSysCnt
->getCoordinateSystems());
444 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
446 Reference
< XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
449 nResult
= xCooSys
->getDimension();
455 catch( const uno::Exception
& )
457 DBG_UNHANDLED_EXCEPTION("chart2");
463 void DiagramHelper::setDimension(
464 const Reference
< XDiagram
> & xDiagram
,
465 sal_Int32 nNewDimensionCount
)
470 if( DiagramHelper::getDimension( xDiagram
) == nNewDimensionCount
)
475 bool rbFound
= false;
476 bool rbAmbiguous
= true;
477 StackMode eStackMode
= DiagramHelper::getStackMode( xDiagram
, rbFound
, rbAmbiguous
);
478 bool bIsSupportingOnlyDeepStackingFor3D
=false;
480 //change all coordinate systems:
481 Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY_THROW
);
482 Sequence
< Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
483 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
485 Reference
< XCoordinateSystem
> xOldCooSys( aCooSysList
[nCS
], uno::UNO_QUERY
);
486 Reference
< XCoordinateSystem
> xNewCooSys
;
488 Reference
< XChartTypeContainer
> xChartTypeContainer( xOldCooSys
, uno::UNO_QUERY
);
489 if( !xChartTypeContainer
.is() )
492 Sequence
< Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
493 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
495 Reference
< XChartType
> xChartType( aChartTypeList
[nT
], uno::UNO_QUERY
);
496 bIsSupportingOnlyDeepStackingFor3D
= ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType
);
499 xNewCooSys
= xChartType
->createCoordinateSystem( nNewDimensionCount
);
502 //@todo make sure that all following charttypes are also capable of the new dimension
503 //otherwise separate them in a different group
504 //BM: might be done in replaceCoordinateSystem()
507 // replace the old coordinate system at all places where it was used
508 DiagramHelper::replaceCoordinateSystem( xDiagram
, xOldCooSys
, xNewCooSys
);
511 //correct stack mode if necessary
512 if( nNewDimensionCount
==3 && eStackMode
!= StackMode::ZStacked
&& bIsSupportingOnlyDeepStackingFor3D
)
513 DiagramHelper::setStackMode( xDiagram
, StackMode::ZStacked
);
514 else if( nNewDimensionCount
==2 && eStackMode
== StackMode::ZStacked
)
515 DiagramHelper::setStackMode( xDiagram
, StackMode::NONE
);
517 catch( const uno::Exception
& )
519 DBG_UNHANDLED_EXCEPTION("chart2");
523 void DiagramHelper::replaceCoordinateSystem(
524 const Reference
< XDiagram
> & xDiagram
,
525 const Reference
< XCoordinateSystem
> & xCooSysToReplace
,
526 const Reference
< XCoordinateSystem
> & xReplacement
)
528 OSL_ASSERT( xDiagram
.is());
532 // update the coordinate-system container
533 Reference
< XCoordinateSystemContainer
> xCont( xDiagram
, uno::UNO_QUERY
);
538 Reference
< chart2::data::XLabeledDataSequence
> xCategories
= DiagramHelper::getCategoriesFromDiagram( xDiagram
);
540 // move chart types of xCooSysToReplace to xReplacement
541 Reference
< XChartTypeContainer
> xCTCntCooSys( xCooSysToReplace
, uno::UNO_QUERY_THROW
);
542 Reference
< XChartTypeContainer
> xCTCntReplacement( xReplacement
, uno::UNO_QUERY_THROW
);
543 xCTCntReplacement
->setChartTypes( xCTCntCooSys
->getChartTypes());
545 xCont
->removeCoordinateSystem( xCooSysToReplace
);
546 xCont
->addCoordinateSystem( xReplacement
);
548 if( xCategories
.is() )
549 DiagramHelper::setCategoriesToDiagram( xCategories
, xDiagram
);
551 catch( const uno::Exception
& )
553 DBG_UNHANDLED_EXCEPTION("chart2");
558 bool DiagramHelper::isSeriesAttachedToMainAxis(
559 const uno::Reference
< chart2::XDataSeries
>& xDataSeries
)
561 sal_Int32 nAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(xDataSeries
);
562 return (nAxisIndex
==0);
565 bool DiagramHelper::attachSeriesToAxis( bool bAttachToMainAxis
566 , const uno::Reference
< chart2::XDataSeries
>& xDataSeries
567 , const uno::Reference
< chart2::XDiagram
>& xDiagram
568 , const uno::Reference
< uno::XComponentContext
> & xContext
571 bool bChanged
= false;
573 //set property at axis
574 Reference
< beans::XPropertySet
> xProp( xDataSeries
, uno::UNO_QUERY_THROW
);
576 sal_Int32 nNewAxisIndex
= bAttachToMainAxis
? 0 : 1;
577 sal_Int32 nOldAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(xDataSeries
);
578 uno::Reference
< chart2::XAxis
> xOldAxis( DiagramHelper::getAttachedAxis( xDataSeries
, xDiagram
) );
580 if( nOldAxisIndex
!= nNewAxisIndex
)
584 xProp
->setPropertyValue( "AttachedAxisIndex", uno::Any( nNewAxisIndex
) );
587 catch( const uno::Exception
& )
589 DBG_UNHANDLED_EXCEPTION("chart2");
593 if( bChanged
&& xDiagram
.is() )
595 uno::Reference
< XAxis
> xAxis( AxisHelper::getAxis( 1, bAttachToMainAxis
, xDiagram
) );
596 if(!xAxis
.is()) //create an axis if necessary
597 xAxis
= AxisHelper::createAxis( 1, bAttachToMainAxis
, xDiagram
, xContext
);
600 AxisHelper::makeAxisVisible( xAxis
);
601 AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis
, xDiagram
);
608 uno::Reference
< XAxis
> DiagramHelper::getAttachedAxis(
609 const uno::Reference
< XDataSeries
>& xSeries
,
610 const uno::Reference
< XDiagram
>& xDiagram
)
612 return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries
), xDiagram
);
615 uno::Reference
< XChartType
> DiagramHelper::getChartTypeOfSeries(
616 const uno::Reference
< chart2::XDiagram
>& xDiagram
617 , const uno::Reference
< XDataSeries
>& xGivenDataSeries
)
619 if( !xGivenDataSeries
.is() )
624 //iterate through the model to find the given xSeries
625 //the found parent indicates the charttype
627 //iterate through all coordinate systems
628 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
629 if( !xCooSysContainer
.is())
632 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
633 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
635 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
637 //iterate through all chart types in the current coordinate system
638 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
639 OSL_ASSERT( xChartTypeContainer
.is());
640 if( !xChartTypeContainer
.is() )
642 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
643 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
645 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
647 //iterate through all series in this chart type
648 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xChartType
, uno::UNO_QUERY
);
649 OSL_ASSERT( xDataSeriesContainer
.is());
650 if( !xDataSeriesContainer
.is() )
653 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
654 for( sal_Int32 nS
= 0; nS
< aSeriesList
.getLength(); ++nS
)
656 if( xGivenDataSeries
==aSeriesList
[nS
] )
664 std::vector
< Reference
< XDataSeries
> >
665 DiagramHelper::getDataSeriesFromDiagram(
666 const Reference
< XDiagram
> & xDiagram
)
668 std::vector
< Reference
< XDataSeries
> > aResult
;
672 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
673 xDiagram
, uno::UNO_QUERY_THROW
);
674 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
675 xCooSysCnt
->getCoordinateSystems());
676 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
678 Reference
< XChartTypeContainer
> xCTCnt( aCooSysSeq
[i
], uno::UNO_QUERY_THROW
);
679 Sequence
< Reference
< XChartType
> > aChartTypeSeq( xCTCnt
->getChartTypes());
680 for( sal_Int32 j
=0; j
<aChartTypeSeq
.getLength(); ++j
)
682 Reference
< XDataSeriesContainer
> xDSCnt( aChartTypeSeq
[j
], uno::UNO_QUERY_THROW
);
683 Sequence
< Reference
< XDataSeries
> > aSeriesSeq( xDSCnt
->getDataSeries() );
684 std::copy( aSeriesSeq
.begin(), aSeriesSeq
.end(),
685 std::back_inserter( aResult
));
689 catch( const uno::Exception
& )
691 DBG_UNHANDLED_EXCEPTION("chart2");
697 Sequence
< Sequence
< Reference
< XDataSeries
> > >
698 DiagramHelper::getDataSeriesGroups( const Reference
< XDiagram
> & xDiagram
)
700 vector
< Sequence
< Reference
< XDataSeries
> > > aResult
;
702 //iterate through all coordinate systems
703 Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
704 if( xCooSysContainer
.is() )
706 Sequence
< Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
707 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
709 //iterate through all chart types in the current coordinate system
710 Reference
< XChartTypeContainer
> xChartTypeContainer( aCooSysList
[nCS
], uno::UNO_QUERY
);
711 if( !xChartTypeContainer
.is() )
713 Sequence
< Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
714 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
716 Reference
< XDataSeriesContainer
> xDataSeriesContainer( aChartTypeList
[nT
], uno::UNO_QUERY
);
717 if( !xDataSeriesContainer
.is() )
719 aResult
.push_back( xDataSeriesContainer
->getDataSeries() );
723 return comphelper::containerToSequence( aResult
);
726 Reference
< XChartType
>
727 DiagramHelper::getChartTypeByIndex( const Reference
< XDiagram
>& xDiagram
, sal_Int32 nIndex
)
729 Reference
< XChartType
> xChartType
;
731 //iterate through all coordinate systems
732 Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
733 if( ! xCooSysContainer
.is())
736 Sequence
< Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
737 sal_Int32 nTypesSoFar
= 0;
738 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
740 Reference
< XChartTypeContainer
> xChartTypeContainer( aCooSysList
[nCS
], uno::UNO_QUERY
);
741 if( !xChartTypeContainer
.is() )
743 Sequence
< Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
744 if( nIndex
>= 0 && nIndex
< (nTypesSoFar
+ aChartTypeList
.getLength()) )
746 xChartType
.set( aChartTypeList
[nIndex
- nTypesSoFar
] );
749 nTypesSoFar
+= aChartTypeList
.getLength();
758 std::vector
< Reference
< XAxis
> > lcl_getAxisHoldingCategoriesFromDiagram(
759 const Reference
< XDiagram
> & xDiagram
)
761 std::vector
< Reference
< XAxis
> > aRet
;
763 // return first x-axis as fall-back
764 Reference
< XAxis
> xFallBack
;
767 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
768 xDiagram
, uno::UNO_QUERY_THROW
);
769 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
770 xCooSysCnt
->getCoordinateSystems());
771 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
773 Reference
< XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
774 OSL_ASSERT( xCooSys
.is());
775 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
777 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
778 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
780 Reference
< XAxis
> xAxis
= xCooSys
->getAxisByDimension( nN
,nI
);
781 OSL_ASSERT( xAxis
.is());
784 ScaleData aScaleData
= xAxis
->getScaleData();
785 if( aScaleData
.Categories
.is() || (aScaleData
.AxisType
== AxisType::CATEGORY
) )
787 aRet
.push_back(xAxis
);
789 if( (nN
== 0) && !xFallBack
.is())
790 xFallBack
.set( xAxis
);
796 catch( const uno::Exception
& )
798 DBG_UNHANDLED_EXCEPTION("chart2" );
802 aRet
.push_back(xFallBack
);
807 } // anonymous namespace
809 bool DiagramHelper::isCategoryDiagram(
810 const Reference
< XDiagram
>& xDiagram
)
814 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
815 xDiagram
, uno::UNO_QUERY_THROW
);
816 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
817 xCooSysCnt
->getCoordinateSystems());
818 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
820 Reference
< XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
821 OSL_ASSERT( xCooSys
.is());
822 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
824 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
825 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
827 Reference
< XAxis
> xAxis
= xCooSys
->getAxisByDimension( nN
,nI
);
828 OSL_ASSERT( xAxis
.is());
831 ScaleData aScaleData
= xAxis
->getScaleData();
832 if( aScaleData
.AxisType
== AxisType::CATEGORY
|| aScaleData
.AxisType
== AxisType::DATE
)
839 catch( const uno::Exception
& )
841 DBG_UNHANDLED_EXCEPTION("chart2");
847 void DiagramHelper::setCategoriesToDiagram(
848 const Reference
< chart2::data::XLabeledDataSequence
>& xCategories
,
849 const Reference
< XDiagram
>& xDiagram
,
850 bool bSetAxisType
/* = false */,
851 bool bCategoryAxis
/* = true */ )
853 std::vector
< Reference
< chart2::XAxis
> > aCatAxes(
854 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram
));
856 for (const Reference
< chart2::XAxis
>& xCatAxis
: aCatAxes
)
860 ScaleData
aScaleData( xCatAxis
->getScaleData());
861 aScaleData
.Categories
= xCategories
;
865 aScaleData
.AxisType
= AxisType::CATEGORY
;
866 else if( aScaleData
.AxisType
== AxisType::CATEGORY
|| aScaleData
.AxisType
== AxisType::DATE
)
867 aScaleData
.AxisType
= AxisType::REALNUMBER
;
869 xCatAxis
->setScaleData( aScaleData
);
874 Reference
< data::XLabeledDataSequence
>
875 DiagramHelper::getCategoriesFromDiagram(
876 const Reference
< XDiagram
> & xDiagram
)
878 Reference
< data::XLabeledDataSequence
> xResult
;
882 std::vector
< Reference
< chart2::XAxis
> > aCatAxes(
883 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram
));
884 //search for first categories
885 if (!aCatAxes
.empty())
887 Reference
< chart2::XAxis
> xCatAxis(aCatAxes
[0]);
890 ScaleData
aScaleData( xCatAxis
->getScaleData());
891 if( aScaleData
.Categories
.is() )
893 xResult
.set( aScaleData
.Categories
);
894 uno::Reference
<beans::XPropertySet
> xProp(aScaleData
.Categories
->getValues(), uno::UNO_QUERY
);
899 xProp
->setPropertyValue( "Role", uno::Any( OUString("categories") ) );
901 catch( const uno::Exception
& )
903 DBG_UNHANDLED_EXCEPTION("chart2");
910 catch( const uno::Exception
& )
912 DBG_UNHANDLED_EXCEPTION("chart2");
918 static void lcl_generateAutomaticCategoriesFromChartType(
919 Sequence
< OUString
>& rRet
,
920 const Reference
< XChartType
>& xChartType
)
924 OUString
aMainSeq( xChartType
->getRoleOfSequenceForSeriesLabel() );
925 Reference
< XDataSeriesContainer
> xSeriesCnt( xChartType
, uno::UNO_QUERY
);
926 if( xSeriesCnt
.is() )
928 Sequence
< Reference
< XDataSeries
> > aSeriesSeq( xSeriesCnt
->getDataSeries() );
929 for( sal_Int32 nS
= 0; nS
< aSeriesSeq
.getLength(); nS
++ )
931 Reference
< data::XDataSource
> xDataSource( aSeriesSeq
[nS
], uno::UNO_QUERY
);
932 if( !xDataSource
.is() )
934 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq(
935 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aMainSeq
));
936 if( !xLabeledSeq
.is() )
938 Reference
< chart2::data::XDataSequence
> xValueSeq( xLabeledSeq
->getValues() );
939 if( !xValueSeq
.is() )
941 rRet
= xValueSeq
->generateLabel( chart2::data::LabelOrigin_LONG_SIDE
);
942 if( rRet
.hasElements() )
948 Sequence
< OUString
> DiagramHelper::generateAutomaticCategoriesFromCooSys( const Reference
< XCoordinateSystem
> & xCooSys
)
950 Sequence
< OUString
> aRet
;
952 Reference
< XChartTypeContainer
> xTypeCntr( xCooSys
, uno::UNO_QUERY
);
955 Sequence
< Reference
< XChartType
> > aChartTypes( xTypeCntr
->getChartTypes() );
956 for( sal_Int32 nN
=0; nN
<aChartTypes
.getLength(); nN
++ )
958 lcl_generateAutomaticCategoriesFromChartType( aRet
, aChartTypes
[nN
] );
959 if( aRet
.hasElements() )
966 Sequence
< OUString
> DiagramHelper::getExplicitSimpleCategories(
969 uno::Reference
< chart2::XCoordinateSystem
> xCooSys( ChartModelHelper::getFirstCoordinateSystem( rModel
) );
970 ExplicitCategoriesProvider
aExplicitCategoriesProvider( xCooSys
, rModel
);
971 return aExplicitCategoriesProvider
.getSimpleCategories();
976 void lcl_switchToDateCategories( const Reference
< XChartDocument
>& xChartDoc
, const Reference
< XAxis
>& xAxis
)
980 if( !xChartDoc
.is() )
983 ScaleData
aScale( xAxis
->getScaleData() );
984 if( xChartDoc
->hasInternalDataProvider() )
986 //remove all content the is not of type double and remove multiple level
987 Reference
< XAnyDescriptionAccess
> xDataAccess( xChartDoc
->getDataProvider(), uno::UNO_QUERY
);
988 if( xDataAccess
.is() )
990 Sequence
< Sequence
< Any
> > aAnyCategories( xDataAccess
->getAnyRowDescriptions() );
993 ::rtl::math::setNan( & fNan
);
994 sal_Int32 nN
= aAnyCategories
.getLength();
997 Sequence
< Any
>& rCat
= aAnyCategories
[nN
];
998 if( rCat
.getLength() > 1 )
1000 if( rCat
.getLength() == 1 )
1002 Any
& rAny
= rCat
[0];
1003 if( !(rAny
>>=fTest
) )
1009 xDataAccess
->setAnyRowDescriptions( aAnyCategories
);
1011 //check the numberformat at the axis
1012 Reference
< beans::XPropertySet
> xAxisProps( xAxis
, uno::UNO_QUERY
);
1013 Reference
< util::XNumberFormatsSupplier
> xNumberFormatsSupplier( xChartDoc
, uno::UNO_QUERY
);
1014 if( xAxisProps
.is() && xNumberFormatsSupplier
.is() )
1016 sal_Int32 nNumberFormat
= -1;
1017 xAxisProps
->getPropertyValue(CHART_UNONAME_NUMFMT
) >>= nNumberFormat
;
1019 Reference
< util::XNumberFormats
> xNumberFormats( xNumberFormatsSupplier
->getNumberFormats() );
1020 if( xNumberFormats
.is() )
1022 Reference
< beans::XPropertySet
> xKeyProps
;
1025 xKeyProps
= xNumberFormats
->getByKey( nNumberFormat
);
1027 catch( const uno::Exception
& )
1029 DBG_UNHANDLED_EXCEPTION("chart2");
1031 sal_Int32 nType
= util::NumberFormat::UNDEFINED
;
1032 if( xKeyProps
.is() )
1033 xKeyProps
->getPropertyValue( "Type" ) >>= nType
;
1034 if( !( nType
& util::NumberFormat::DATE
) )
1036 //set a date format to the axis
1037 const LocaleDataWrapper
& rLocaleDataWrapper
= Application::GetSettings().GetLocaleDataWrapper();
1038 Sequence
<sal_Int32
> aKeySeq
= xNumberFormats
->queryKeys( util::NumberFormat::DATE
, rLocaleDataWrapper
.getLanguageTag().getLocale(), true/*bCreate*/ );
1039 if( aKeySeq
.hasElements() )
1041 xAxisProps
->setPropertyValue(CHART_UNONAME_NUMFMT
, uno::Any(aKeySeq
[0]));
1047 if( aScale
.AxisType
!= chart2::AxisType::DATE
)
1048 AxisHelper::removeExplicitScaling( aScale
);
1049 aScale
.AxisType
= chart2::AxisType::DATE
;
1050 xAxis
->setScaleData( aScale
);
1053 void lcl_switchToTextCategories( const Reference
< XChartDocument
>& xChartDoc
, const Reference
< XAxis
>& xAxis
)
1057 if( !xChartDoc
.is() )
1059 ScaleData
aScale( xAxis
->getScaleData() );
1060 if( aScale
.AxisType
!= chart2::AxisType::CATEGORY
)
1061 AxisHelper::removeExplicitScaling( aScale
);
1062 //todo migrate dates to text?
1063 aScale
.AxisType
= chart2::AxisType::CATEGORY
;
1064 aScale
.AutoDateAxis
= false;
1065 xAxis
->setScaleData( aScale
);
1070 void DiagramHelper::switchToDateCategories( const Reference
< XChartDocument
>& xChartDoc
)
1074 ControllerLockGuardUNO
aCtrlLockGuard( xChartDoc
);
1076 Reference
< chart2::XCoordinateSystem
> xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartDoc
) );
1079 Reference
< XAxis
> xAxis( xCooSys
->getAxisByDimension(0,0) );
1080 lcl_switchToDateCategories( xChartDoc
, xAxis
);
1085 void DiagramHelper::switchToTextCategories( const Reference
< XChartDocument
>& xChartDoc
)
1089 ControllerLockGuardUNO
aCtrlLockGuard( xChartDoc
);
1091 Reference
< chart2::XCoordinateSystem
> xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartDoc
) );
1094 Reference
< XAxis
> xAxis( xCooSys
->getAxisByDimension(0,0) );
1095 lcl_switchToTextCategories( xChartDoc
, xAxis
);
1100 bool DiagramHelper::isSupportingDateAxis( const Reference
< chart2::XDiagram
>& xDiagram
)
1102 return ::chart::ChartTypeHelper::isSupportingDateAxis(
1103 DiagramHelper::getChartTypeByIndex( xDiagram
, 0 ), 0 );
1106 bool DiagramHelper::isDateNumberFormat( sal_Int32 nNumberFormat
, const Reference
< util::XNumberFormats
>& xNumberFormats
)
1108 bool bIsDate
= false;
1109 if( !xNumberFormats
.is() )
1112 Reference
< beans::XPropertySet
> xKeyProps
= xNumberFormats
->getByKey( nNumberFormat
);
1113 if( xKeyProps
.is() )
1115 sal_Int32 nType
= util::NumberFormat::UNDEFINED
;
1116 xKeyProps
->getPropertyValue( "Type" ) >>= nType
;
1117 bIsDate
= nType
& util::NumberFormat::DATE
;
1122 sal_Int32
DiagramHelper::getDateNumberFormat( const Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
)
1126 //try to get a date format with full year display
1127 const LanguageTag
& rLanguageTag
= Application::GetSettings().GetLanguageTag();
1128 NumberFormatterWrapper
aNumberFormatterWrapper( xNumberFormatsSupplier
);
1129 SvNumberFormatter
* pNumFormatter
= aNumberFormatterWrapper
.getSvNumberFormatter();
1132 nRet
= pNumFormatter
->GetFormatIndex( NF_DATE_SYS_DDMMYYYY
, rLanguageTag
.getLanguageType() );
1136 Reference
< util::XNumberFormats
> xNumberFormats( xNumberFormatsSupplier
->getNumberFormats() );
1137 if( xNumberFormats
.is() )
1139 Sequence
<sal_Int32
> aKeySeq
= xNumberFormats
->queryKeys( util::NumberFormat::DATE
,
1140 rLanguageTag
.getLocale(), true/*bCreate */);
1141 if( aKeySeq
.hasElements() )
1150 sal_Int32
DiagramHelper::getDateTimeInputNumberFormat( const Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
, double fNumber
)
1154 // Get the most detailed date/time format according to fNumber.
1155 NumberFormatterWrapper
aNumberFormatterWrapper( xNumberFormatsSupplier
);
1156 SvNumberFormatter
* pNumFormatter
= aNumberFormatterWrapper
.getSvNumberFormatter();
1158 SAL_WARN("chart2", "DiagramHelper::getDateTimeInputNumberFormat - no SvNumberFormatter");
1161 SvNumFormatType nType
;
1162 // Obtain best matching date, time or datetime format.
1163 nRet
= pNumFormatter
->GuessDateTimeFormat( nType
, fNumber
, LANGUAGE_SYSTEM
);
1164 // Obtain the corresponding edit format.
1165 nRet
= pNumFormatter
->GetEditFormat( fNumber
, nRet
, nType
, LANGUAGE_SYSTEM
, nullptr);
1170 sal_Int32
DiagramHelper::getPercentNumberFormat( const Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
)
1173 const LanguageTag
& rLanguageTag
= Application::GetSettings().GetLanguageTag();
1174 NumberFormatterWrapper
aNumberFormatterWrapper( xNumberFormatsSupplier
);
1175 SvNumberFormatter
* pNumFormatter
= aNumberFormatterWrapper
.getSvNumberFormatter();
1178 nRet
= pNumFormatter
->GetFormatIndex( NF_PERCENT_INT
, rLanguageTag
.getLanguageType() );
1182 Reference
< util::XNumberFormats
> xNumberFormats( xNumberFormatsSupplier
->getNumberFormats() );
1183 if( xNumberFormats
.is() )
1185 Sequence
<sal_Int32
> aKeySeq
= xNumberFormats
->queryKeys( util::NumberFormat::PERCENT
,
1186 rLanguageTag
.getLocale(), true/*bCreate*/ );
1187 if( aKeySeq
.hasElements() )
1189 // This *assumes* the sequence is sorted as in
1190 // NfIndexTableOffset and the first format is the integer 0%
1191 // format by chance... which usually is the case, but... anyway,
1192 // we usually also have a number formatter so don't reach here.
1200 Sequence
< Reference
< XChartType
> >
1201 DiagramHelper::getChartTypesFromDiagram(
1202 const Reference
< XDiagram
> & xDiagram
)
1204 std::vector
< Reference
< XChartType
> > aResult
;
1210 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
1211 xDiagram
, uno::UNO_QUERY_THROW
);
1212 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
1213 xCooSysCnt
->getCoordinateSystems());
1214 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
1216 Reference
< XChartTypeContainer
> xCTCnt( aCooSysSeq
[i
], uno::UNO_QUERY_THROW
);
1217 Sequence
< Reference
< XChartType
> > aChartTypeSeq( xCTCnt
->getChartTypes());
1218 std::copy( aChartTypeSeq
.begin(), aChartTypeSeq
.end(),
1219 std::back_inserter( aResult
));
1222 catch( const uno::Exception
& )
1224 DBG_UNHANDLED_EXCEPTION("chart2");
1228 return comphelper::containerToSequence( aResult
);
1231 bool DiagramHelper::areChartTypesCompatible( const Reference
< ::chart2::XChartType
>& xFirstType
,
1232 const Reference
< ::chart2::XChartType
>& xSecondType
)
1234 if( !xFirstType
.is() || !xSecondType
.is() )
1237 auto aFirstRoles( comphelper::sequenceToContainer
<std::vector
< OUString
>>( xFirstType
->getSupportedMandatoryRoles() ) );
1238 auto aSecondRoles( comphelper::sequenceToContainer
<std::vector
< OUString
>>( xSecondType
->getSupportedMandatoryRoles() ) );
1239 std::sort( aFirstRoles
.begin(), aFirstRoles
.end() );
1240 std::sort( aSecondRoles
.begin(), aSecondRoles
.end() );
1241 return ( aFirstRoles
== aSecondRoles
);
1247 * This method implements the logic of checking if a series can be moved
1248 * forward/backward. Depending on the "bDoMove" parameter the series will
1249 * be moved (bDoMove = true) or the function just will test if the
1250 * series can be moved without doing the move (bDoMove = false).
1253 * Reference to the diagram that contains the series.
1255 * @param xGivenDataSeries
1256 * Reference to the series that should moved or tested for moving.
1259 * Direction in which the series should be moved or tested for moving.
1262 * Should this function really move the series (true) or just test if it is
1267 * in case of bDoMove == true
1268 * - True : if the move was done
1269 * - False : the move failed
1270 * in case of bDoMove == false
1271 * - True : the series can be moved
1272 * - False : the series can not be moved
1276 bool lcl_moveSeriesOrCheckIfMoveIsAllowed(
1277 const Reference
< XDiagram
>& xDiagram
,
1278 const Reference
< XDataSeries
>& xGivenDataSeries
,
1282 bool bMovedOrMoveAllowed
= false;
1286 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
1288 if( xGivenDataSeries
.is() && xCooSysContainer
.is() )
1290 //find position of series.
1291 bool bFound
= false;
1292 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
1294 for( sal_Int32 nCS
= 0; !bFound
&& nCS
< aCooSysList
.getLength(); ++nCS
)
1296 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
1298 //iterate through all chart types in the current coordinate system
1299 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
1300 OSL_ASSERT( xChartTypeContainer
.is());
1301 if( !xChartTypeContainer
.is() )
1303 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
1304 uno::Reference
< XChartType
> xFormerChartType
;
1306 for( sal_Int32 nT
= 0; !bFound
&& nT
< aChartTypeList
.getLength(); ++nT
)
1308 uno::Reference
< XChartType
> xCurrentChartType( aChartTypeList
[nT
] );
1310 //iterate through all series in this chart type
1311 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xCurrentChartType
, uno::UNO_QUERY
);
1312 OSL_ASSERT( xDataSeriesContainer
.is());
1313 if( !xDataSeriesContainer
.is() )
1316 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
1318 for( sal_Int32 nS
= 0; !bFound
&& nS
< aSeriesList
.getLength(); ++nS
)
1321 // We found the series we are interested in!
1322 if( xGivenDataSeries
==aSeriesList
[nS
] )
1324 sal_Int32 nOldSeriesIndex
= nS
;
1329 sal_Int32 nNewSeriesIndex
= nS
;
1336 if( nNewSeriesIndex
>= 0 && nNewSeriesIndex
< aSeriesList
.getLength() )
1338 //move series in the same charttype
1339 bMovedOrMoveAllowed
= true;
1342 aSeriesList
[ nOldSeriesIndex
] = aSeriesList
[ nNewSeriesIndex
];
1343 aSeriesList
[ nNewSeriesIndex
] = xGivenDataSeries
;
1344 xDataSeriesContainer
->setDataSeries( aSeriesList
);
1347 else if( nNewSeriesIndex
<0 )
1349 //exchange series with former charttype
1350 if( xFormerChartType
.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType
, xCurrentChartType
) )
1352 bMovedOrMoveAllowed
= true;
1355 uno::Reference
< XDataSeriesContainer
> xOtherDataSeriesContainer( xFormerChartType
, uno::UNO_QUERY
);
1356 if( xOtherDataSeriesContainer
.is() )
1358 uno::Sequence
< uno::Reference
< XDataSeries
> > aOtherSeriesList( xOtherDataSeriesContainer
->getDataSeries() );
1359 sal_Int32 nOtherSeriesIndex
= aOtherSeriesList
.getLength()-1;
1360 if( nOtherSeriesIndex
>= 0 && nOtherSeriesIndex
< aOtherSeriesList
.getLength() )
1362 uno::Reference
< XDataSeries
> xExchangeSeries( aOtherSeriesList
[nOtherSeriesIndex
] );
1363 aOtherSeriesList
[nOtherSeriesIndex
] = xGivenDataSeries
;
1364 xOtherDataSeriesContainer
->setDataSeries(aOtherSeriesList
);
1366 aSeriesList
[nOldSeriesIndex
]=xExchangeSeries
;
1367 xDataSeriesContainer
->setDataSeries(aSeriesList
);
1373 else if( nT
+1 < aChartTypeList
.getLength() )
1375 //exchange series with next charttype
1376 uno::Reference
< XChartType
> xOtherChartType( aChartTypeList
[nT
+1] );
1377 if( xOtherChartType
.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType
, xCurrentChartType
) )
1379 bMovedOrMoveAllowed
= true;
1382 uno::Reference
< XDataSeriesContainer
> xOtherDataSeriesContainer( xOtherChartType
, uno::UNO_QUERY
);
1383 if( xOtherDataSeriesContainer
.is() )
1385 uno::Sequence
< uno::Reference
< XDataSeries
> > aOtherSeriesList( xOtherDataSeriesContainer
->getDataSeries() );
1386 if( aOtherSeriesList
.hasElements() )
1388 uno::Reference
< XDataSeries
> xExchangeSeries( aOtherSeriesList
[0] );
1389 aOtherSeriesList
[0] = xGivenDataSeries
;
1390 xOtherDataSeriesContainer
->setDataSeries(aOtherSeriesList
);
1392 aSeriesList
[nOldSeriesIndex
]=xExchangeSeries
;
1393 xDataSeriesContainer
->setDataSeries(aSeriesList
);
1400 catch( const util::CloseVetoException
& )
1403 catch( const uno::RuntimeException
& )
1408 xFormerChartType
= xCurrentChartType
;
1413 catch( const util::CloseVetoException
& )
1416 catch( const uno::RuntimeException
& )
1419 return bMovedOrMoveAllowed
;
1421 } // anonymous namespace
1423 bool DiagramHelper::isSeriesMoveable(
1424 const Reference
< XDiagram
>& xDiagram
,
1425 const Reference
< XDataSeries
>& xGivenDataSeries
,
1428 const bool bDoMove
= false;
1430 bool bIsMoveable
= lcl_moveSeriesOrCheckIfMoveIsAllowed(
1431 xDiagram
, xGivenDataSeries
, bForward
, bDoMove
);
1436 bool DiagramHelper::moveSeries( const Reference
< XDiagram
>& xDiagram
, const Reference
< XDataSeries
>& xGivenDataSeries
, bool bForward
)
1438 const bool bDoMove
= true;
1440 bool bMoved
= lcl_moveSeriesOrCheckIfMoveIsAllowed(
1441 xDiagram
, xGivenDataSeries
, bForward
, bDoMove
);
1446 bool DiagramHelper::isSupportingFloorAndWall( const Reference
<
1447 chart2::XDiagram
>& xDiagram
)
1449 //pies and donuts currently do not support this because of wrong files from older versions
1450 //todo: allow this in future again, if fileversion are available for ole objects (metastream)
1451 //thus the wrong bottom can be removed on import
1453 Sequence
< Reference
< chart2::XChartType
> > aTypes(
1454 ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram
) );
1455 for( sal_Int32 nN
= 0; nN
< aTypes
.getLength(); nN
++ )
1457 Reference
< chart2::XChartType
> xType( aTypes
[nN
] );
1458 if( xType
.is() && xType
->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_PIE
) )
1460 if( xType
.is() && xType
->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_NET
) )
1462 if( xType
.is() && xType
->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET
) )
1468 bool DiagramHelper::isPieOrDonutChart( const css::uno::Reference
< css::chart2::XDiagram
>& xDiagram
)
1470 uno::Reference
< chart2::XChartType
> xChartType( DiagramHelper::getChartTypeByIndex(
1473 if( xChartType
.is() )
1475 OUString aChartType
= xChartType
->getChartType();
1476 if( aChartType
== CHART2_SERVICE_NAME_CHARTTYPE_PIE
)
1482 sal_Int32
DiagramHelper::getGeometry3D(
1483 const uno::Reference
< chart2::XDiagram
> & xDiagram
,
1484 bool& rbFound
, bool& rbAmbiguous
)
1486 sal_Int32
nCommonGeom( DataPointGeometry3D::CUBOID
);
1488 rbAmbiguous
= false;
1490 std::vector
< Reference
< chart2::XDataSeries
> > aSeriesVec(
1491 DiagramHelper::getDataSeriesFromDiagram( xDiagram
));
1493 if( aSeriesVec
.empty())
1496 for (auto const& series
: aSeriesVec
)
1500 sal_Int32 nGeom
= 0;
1501 Reference
< beans::XPropertySet
> xProp(series
, uno::UNO_QUERY_THROW
);
1502 if( xProp
->getPropertyValue( "Geometry3D") >>= nGeom
)
1507 nCommonGeom
= nGeom
;
1510 // further series: compare for uniqueness
1511 else if( nCommonGeom
!= nGeom
)
1518 catch( const uno::Exception
& )
1520 DBG_UNHANDLED_EXCEPTION("chart2");
1527 void DiagramHelper::setGeometry3D(
1528 const Reference
< chart2::XDiagram
> & xDiagram
,
1529 sal_Int32 nNewGeometry
)
1531 std::vector
< Reference
< chart2::XDataSeries
> > aSeriesVec(
1532 DiagramHelper::getDataSeriesFromDiagram( xDiagram
));
1534 for (auto const& series
: aSeriesVec
)
1536 DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(
1537 series
, "Geometry3D", uno::Any( nNewGeometry
));
1541 sal_Int32
DiagramHelper::getCorrectedMissingValueTreatment(
1542 const Reference
< chart2::XDiagram
> & xDiagram
,
1543 const Reference
< chart2::XChartType
>& xChartType
)
1545 sal_Int32 nResult
= css::chart::MissingValueTreatment::LEAVE_GAP
;
1546 uno::Sequence
< sal_Int32
> aAvailableMissingValueTreatments(
1547 ChartTypeHelper::getSupportedMissingValueTreatments( xChartType
) );
1549 uno::Reference
< beans::XPropertySet
> xDiaProp( xDiagram
, uno::UNO_QUERY
);
1550 if( xDiaProp
.is() && (xDiaProp
->getPropertyValue( "MissingValueTreatment" ) >>= nResult
) )
1552 //ensure that the set value is supported by this charttype
1553 for( sal_Int32 nN
= 0; nN
< aAvailableMissingValueTreatments
.getLength(); nN
++ )
1554 if( aAvailableMissingValueTreatments
[nN
] == nResult
)
1555 return nResult
; //ok
1558 //otherwise use the first supported one
1559 if( aAvailableMissingValueTreatments
.hasElements() )
1561 nResult
= aAvailableMissingValueTreatments
[0];
1568 DiagramPositioningMode
DiagramHelper::getDiagramPositioningMode( const uno::Reference
<
1569 chart2::XDiagram
> & xDiagram
)
1571 DiagramPositioningMode eMode
= DiagramPositioningMode_AUTO
;
1572 uno::Reference
< beans::XPropertySet
> xDiaProps( xDiagram
, uno::UNO_QUERY
);
1573 if( xDiaProps
.is() )
1575 RelativePosition aRelPos
;
1576 RelativeSize aRelSize
;
1577 if( (xDiaProps
->getPropertyValue("RelativePosition") >>= aRelPos
) &&
1578 (xDiaProps
->getPropertyValue("RelativeSize") >>= aRelSize
) )
1580 bool bPosSizeExcludeAxes
=false;
1581 xDiaProps
->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxes
;
1582 if( bPosSizeExcludeAxes
)
1583 eMode
= DiagramPositioningMode_EXCLUDING
;
1585 eMode
= DiagramPositioningMode_INCLUDING
;
1591 static void lcl_ensureRange0to1( double& rValue
)
1599 bool DiagramHelper::setDiagramPositioning( const uno::Reference
< frame::XModel
>& xChartModel
,
1600 const awt::Rectangle
& rPosRect
/*100th mm*/ )
1602 ControllerLockGuardUNO
aCtrlLockGuard( xChartModel
);
1604 bool bChanged
= false;
1605 awt::Size
aPageSize( ChartModelHelper::getPageSize(xChartModel
) );
1606 uno::Reference
< beans::XPropertySet
> xDiaProps( ChartModelHelper::findDiagram( xChartModel
), uno::UNO_QUERY
);
1607 if( !xDiaProps
.is() )
1610 RelativePosition aOldPos
;
1611 RelativeSize aOldSize
;
1612 xDiaProps
->getPropertyValue("RelativePosition" ) >>= aOldPos
;
1613 xDiaProps
->getPropertyValue("RelativeSize" ) >>= aOldSize
;
1615 RelativePosition aNewPos
;
1616 aNewPos
.Anchor
= drawing::Alignment_TOP_LEFT
;
1617 aNewPos
.Primary
= double(rPosRect
.X
)/double(aPageSize
.Width
);
1618 aNewPos
.Secondary
= double(rPosRect
.Y
)/double(aPageSize
.Height
);
1620 chart2::RelativeSize aNewSize
;
1621 aNewSize
.Primary
= double(rPosRect
.Width
)/double(aPageSize
.Width
);
1622 aNewSize
.Secondary
= double(rPosRect
.Height
)/double(aPageSize
.Height
);
1624 lcl_ensureRange0to1( aNewPos
.Primary
);
1625 lcl_ensureRange0to1( aNewPos
.Secondary
);
1626 lcl_ensureRange0to1( aNewSize
.Primary
);
1627 lcl_ensureRange0to1( aNewSize
.Secondary
);
1628 if( (aNewPos
.Primary
+ aNewSize
.Primary
) > 1.0 )
1629 aNewPos
.Primary
= 1.0 - aNewSize
.Primary
;
1630 if( (aNewPos
.Secondary
+ aNewSize
.Secondary
) > 1.0 )
1631 aNewPos
.Secondary
= 1.0 - aNewSize
.Secondary
;
1633 xDiaProps
->setPropertyValue( "RelativePosition", uno::Any(aNewPos
) );
1634 xDiaProps
->setPropertyValue( "RelativeSize", uno::Any(aNewSize
) );
1636 bChanged
= (aOldPos
.Anchor
!=aNewPos
.Anchor
) ||
1637 (aOldPos
.Primary
!=aNewPos
.Primary
) ||
1638 (aOldPos
.Secondary
!=aNewPos
.Secondary
) ||
1639 (aOldSize
.Primary
!=aNewSize
.Primary
) ||
1640 (aOldSize
.Secondary
!=aNewSize
.Secondary
);
1644 awt::Rectangle
DiagramHelper::getDiagramRectangleFromModel( const uno::Reference
< frame::XModel
>& xChartModel
)
1646 awt::Rectangle
aRet(-1,-1,-1,-1);
1648 uno::Reference
< beans::XPropertySet
> xDiaProps( ChartModelHelper::findDiagram( xChartModel
), uno::UNO_QUERY
);
1649 if( !xDiaProps
.is() )
1652 awt::Size
aPageSize( ChartModelHelper::getPageSize(xChartModel
) );
1654 RelativePosition aRelPos
;
1655 RelativeSize aRelSize
;
1656 xDiaProps
->getPropertyValue("RelativePosition" ) >>= aRelPos
;
1657 xDiaProps
->getPropertyValue("RelativeSize" ) >>= aRelSize
;
1660 static_cast< sal_Int32
>( aRelSize
.Primary
* aPageSize
.Width
),
1661 static_cast< sal_Int32
>( aRelSize
.Secondary
* aPageSize
.Height
));
1664 static_cast< sal_Int32
>( aRelPos
.Primary
* aPageSize
.Width
),
1665 static_cast< sal_Int32
>( aRelPos
.Secondary
* aPageSize
.Height
));
1667 awt::Point aAbsPosLeftTop
= RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( aAbsPos
, aAbsSize
, aRelPos
.Anchor
);
1669 aRet
= awt::Rectangle(aAbsPosLeftTop
.X
, aAbsPosLeftTop
.Y
, aAbsSize
.Width
, aAbsSize
.Height
);
1674 bool DiagramHelper::switchDiagramPositioningToExcludingPositioning(
1675 ChartModel
& rModel
, bool bResetModifiedState
, bool bConvertAlsoFromAutoPositioning
)
1677 //return true if something was changed
1678 const SvtSaveOptions::ODFDefaultVersion
nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1679 if( nCurrentODFVersion
> SvtSaveOptions::ODFVER_012
)
1681 uno::Reference
< css::chart::XDiagramPositioning
> xDiagramPositioning( rModel
.getFirstDiagram(), uno::UNO_QUERY
);
1682 if( xDiagramPositioning
.is() && ( bConvertAlsoFromAutoPositioning
|| !xDiagramPositioning
->isAutomaticDiagramPositioning() )
1683 && !xDiagramPositioning
->isExcludingDiagramPositioning() )
1685 ControllerLockGuard
aCtrlLockGuard( rModel
);
1686 bool bModelWasModified
= rModel
.isModified();
1687 xDiagramPositioning
->setDiagramPositionExcludingAxes( xDiagramPositioning
->calculateDiagramPositionExcludingAxes() );
1688 if(bResetModifiedState
&& !bModelWasModified
)
1689 rModel
.setModified(false);
1696 } // namespace chart
1698 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */