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 "LegendHelper.hxx"
22 #include "PropertyHelper.hxx"
24 #include "DataSeriesHelper.hxx"
25 #include "AxisHelper.hxx"
26 #include "ContainerHelper.hxx"
27 #include "ChartTypeHelper.hxx"
28 #include "ChartModelHelper.hxx"
29 #include "CommonConverters.hxx"
30 #include "ExplicitCategoriesProvider.hxx"
31 #include "servicenames_charttypes.hxx"
32 #include "RelativePositionHelper.hxx"
33 #include "ControllerLockGuard.hxx"
34 #include "NumberFormatterWrapper.hxx"
36 #include <com/sun/star/chart/MissingValueTreatment.hpp>
37 #include <com/sun/star/chart/XChartDocument.hpp>
38 #include <com/sun/star/chart/XDiagramPositioning.hpp>
39 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
40 #include <com/sun/star/chart2/XTitled.hpp>
41 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
42 #include <com/sun/star/chart2/XChartTypeTemplate.hpp>
43 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
44 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
45 #include <com/sun/star/chart2/InterpretedData.hpp>
46 #include <com/sun/star/chart2/AxisType.hpp>
47 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
48 #include <com/sun/star/chart2/RelativePosition.hpp>
49 #include <com/sun/star/chart2/RelativeSize.hpp>
51 #include <com/sun/star/util/NumberFormat.hpp>
52 #include <com/sun/star/util/XModifiable.hpp>
53 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
55 #include <unotools/saveopt.hxx>
56 #include <rtl/math.hxx>
57 #include <svl/zformat.hxx>
58 // header for class Application
59 #include <vcl/svapp.hxx>
61 using namespace ::com::sun::star
;
62 using namespace ::com::sun::star::chart2
;
63 using namespace ::std
;
65 using ::com::sun::star::uno::Reference
;
66 using ::com::sun::star::uno::Sequence
;
67 using ::com::sun::star::uno::Any
;
68 using ::com::sun::star::chart2::XAnyDescriptionAccess
;
73 DiagramHelper::tTemplateWithServiceName
74 DiagramHelper::getTemplateForDiagram(
75 const Reference
< XDiagram
> & xDiagram
,
76 const Reference
< lang::XMultiServiceFactory
> & xChartTypeManager
,
77 const OUString
& rPreferredTemplateName
)
79 DiagramHelper::tTemplateWithServiceName aResult
;
81 if( ! (xChartTypeManager
.is() && xDiagram
.is()))
84 Sequence
< OUString
> aServiceNames( xChartTypeManager
->getAvailableServiceNames());
85 const sal_Int32 nLength
= aServiceNames
.getLength();
87 bool bHasPreferredTemplate
= !rPreferredTemplateName
.isEmpty();
88 bool bTemplateFound
= false;
90 if( bHasPreferredTemplate
)
92 Reference
< XChartTypeTemplate
> xTempl(
93 xChartTypeManager
->createInstance( rPreferredTemplateName
), uno::UNO_QUERY
);
96 xTempl
->matchesTemplate( xDiagram
, sal_True
))
98 aResult
.first
= xTempl
;
99 aResult
.second
= rPreferredTemplateName
;
100 bTemplateFound
= true;
104 for( sal_Int32 i
= 0; ! bTemplateFound
&& i
< nLength
; ++i
)
108 if( ! bHasPreferredTemplate
||
109 ! rPreferredTemplateName
.equals( aServiceNames
[ i
] ))
111 Reference
< XChartTypeTemplate
> xTempl(
112 xChartTypeManager
->createInstance( aServiceNames
[ i
] ), uno::UNO_QUERY_THROW
);
114 if( xTempl
->matchesTemplate( xDiagram
, sal_True
))
116 aResult
.first
= xTempl
;
117 aResult
.second
= aServiceNames
[ i
];
118 bTemplateFound
= true;
122 catch( const uno::Exception
& ex
)
124 ASSERT_EXCEPTION( ex
);
131 void DiagramHelper::setVertical(
132 const Reference
< XDiagram
> & xDiagram
,
133 bool bVertical
/* = true */ )
137 Reference
< XCoordinateSystemContainer
> xCnt( xDiagram
, uno::UNO_QUERY
);
140 Sequence
< Reference
< XCoordinateSystem
> > aCooSys(
141 xCnt
->getCoordinateSystems());
143 aValue
<<= bVertical
;
144 for( sal_Int32 i
=0; i
<aCooSys
.getLength(); ++i
)
146 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSys
[i
] );
147 Reference
< beans::XPropertySet
> xProp( xCooSys
, uno::UNO_QUERY
);
148 bool bChanged
= false;
151 bool bOldSwap
= sal_False
;
152 if( !(xProp
->getPropertyValue( "SwapXAndYAxis" ) >>= bOldSwap
)
153 || bVertical
!= bOldSwap
)
157 xProp
->setPropertyValue( "SwapXAndYAxis", aValue
);
161 const sal_Int32
nDimensionCount( xCooSys
->getDimension() );
162 sal_Int32 nDimIndex
= 0;
163 for(nDimIndex
=0; nDimIndex
<nDimensionCount
; ++nDimIndex
)
165 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimIndex
);
166 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
168 Reference
< chart2::XAxis
> xAxis( xCooSys
->getAxisByDimension( nDimIndex
,nI
));
171 //adapt title rotation only when axis swapping has changed
174 Reference
< XTitled
> xTitled( xAxis
, uno::UNO_QUERY
);
177 Reference
< beans::XPropertySet
> xTitleProps( xTitled
->getTitleObject(), uno::UNO_QUERY
);
178 if( !xTitleProps
.is() )
180 double fAngleDegree
= 0.0;
181 xTitleProps
->getPropertyValue( "TextRotation" ) >>= fAngleDegree
;
182 if( !::rtl::math::approxEqual( fAngleDegree
, 0.0 )
183 && !::rtl::math::approxEqual( fAngleDegree
, 90.0 ) )
186 double fNewAngleDegree
= 0.0;
187 if( !bVertical
&& nDimIndex
== 1 )
188 fNewAngleDegree
= 90.0;
189 else if( bVertical
&& nDimIndex
== 0 )
190 fNewAngleDegree
= 90.0;
192 xTitleProps
->setPropertyValue( "TextRotation", uno::makeAny( fNewAngleDegree
));
202 catch( const uno::Exception
& ex
)
204 ASSERT_EXCEPTION( ex
);
208 bool DiagramHelper::getVertical( const uno::Reference
< chart2::XDiagram
> & xDiagram
,
209 bool& rbFound
, bool& rbAmbiguous
)
215 Reference
< XCoordinateSystemContainer
> xCnt( xDiagram
, uno::UNO_QUERY
);
218 Sequence
< Reference
< XCoordinateSystem
> > aCooSys(
219 xCnt
->getCoordinateSystems());
220 for( sal_Int32 i
=0; i
<aCooSys
.getLength(); ++i
)
222 Reference
< beans::XPropertySet
> xProp( aCooSys
[i
], uno::UNO_QUERY
);
225 bool bCurrent
= false;
226 if( xProp
->getPropertyValue( "SwapXAndYAxis" ) >>= bCurrent
)
233 else if( bCurrent
!= bValue
)
235 // ambiguous -> choose always first found
245 void DiagramHelper::setStackMode(
246 const Reference
< XDiagram
> & xDiagram
,
247 StackMode eStackMode
,
248 bool bOnlyAtFirstChartType
/* = true */
253 if( eStackMode
== StackMode_AMBIGUOUS
)
256 bool bValueFound
= false;
257 bool bIsAmbiguous
= false;
258 StackMode eOldStackMode
= DiagramHelper::getStackMode( xDiagram
, bValueFound
, bIsAmbiguous
);
260 if( eStackMode
== eOldStackMode
&& !bIsAmbiguous
)
263 StackingDirection eNewDirection
= StackingDirection_NO_STACKING
;
264 if( eStackMode
== StackMode_Y_STACKED
|| eStackMode
== StackMode_Y_STACKED_PERCENT
)
265 eNewDirection
= StackingDirection_Y_STACKING
;
266 else if( eStackMode
== StackMode_Z_STACKED
)
267 eNewDirection
= StackingDirection_Z_STACKING
;
269 uno::Any
aNewDirection( uno::makeAny(eNewDirection
) );
271 sal_Bool bPercent
= sal_False
;
272 if( eStackMode
== StackMode_Y_STACKED_PERCENT
)
275 //iterate through all coordinate systems
276 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
277 if( !xCooSysContainer
.is() )
279 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
280 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
282 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
283 //set correct percent stacking
284 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(1);
285 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
287 Reference
< chart2::XAxis
> xAxis( xCooSys
->getAxisByDimension( 1,nI
));
290 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
291 if( (aScaleData
.AxisType
==AxisType::PERCENT
) != bPercent
)
294 aScaleData
.AxisType
= AxisType::PERCENT
;
296 aScaleData
.AxisType
= AxisType::REALNUMBER
;
297 xAxis
->setScaleData( aScaleData
);
301 //iterate through all chart types in the current coordinate system
302 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
303 if( !xChartTypeContainer
.is() )
305 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
306 sal_Int32 nMax
= aChartTypeList
.getLength();
307 if( bOnlyAtFirstChartType
310 for( sal_Int32 nT
= 0; nT
< nMax
; ++nT
)
312 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
314 //iterate through all series in this chart type
315 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xChartType
, uno::UNO_QUERY
);
316 OSL_ASSERT( xDataSeriesContainer
.is());
317 if( !xDataSeriesContainer
.is() )
320 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
321 for( sal_Int32 nS
= 0; nS
< aSeriesList
.getLength(); ++nS
)
323 Reference
< beans::XPropertySet
> xProp( aSeriesList
[nS
], uno::UNO_QUERY
);
325 xProp
->setPropertyValue( "StackingDirection", aNewDirection
);
330 catch( const uno::Exception
& ex
)
332 ASSERT_EXCEPTION( ex
);
336 StackMode
DiagramHelper::getStackMode( const Reference
< XDiagram
> & xDiagram
, bool& rbFound
, bool& rbAmbiguous
)
341 StackMode eGlobalStackMode
= StackMode_NONE
;
343 //iterate through all coordinate systems
344 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
345 if( !xCooSysContainer
.is() )
346 return eGlobalStackMode
;
347 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
348 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
350 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
352 //iterate through all chart types in the current coordinate system
353 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
354 if( !xChartTypeContainer
.is() )
356 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
357 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
359 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
361 StackMode eLocalStackMode
= DiagramHelper::getStackModeFromChartType(
362 xChartType
, rbFound
, rbAmbiguous
, xCooSys
);
364 if( rbFound
&& eLocalStackMode
!= eGlobalStackMode
&& nT
>0 )
367 return eGlobalStackMode
;
370 eGlobalStackMode
= eLocalStackMode
;
374 return eGlobalStackMode
;
377 StackMode
DiagramHelper::getStackModeFromChartType(
378 const Reference
< XChartType
> & xChartType
,
379 bool& rbFound
, bool& rbAmbiguous
,
380 const Reference
< XCoordinateSystem
> & xCorrespondingCoordinateSystem
)
382 StackMode eStackMode
= StackMode_NONE
;
388 Reference
< XDataSeriesContainer
> xDSCnt( xChartType
, uno::UNO_QUERY_THROW
);
389 Sequence
< Reference
< chart2::XDataSeries
> > aSeries( xDSCnt
->getDataSeries());
391 chart2::StackingDirection eCommonDirection
= chart2::StackingDirection_NO_STACKING
;
392 bool bDirectionInitialized
= false;
394 // first series is irrelvant for stacking, start with second, unless
395 // there is only one series
396 const sal_Int32 nSeriesCount
= aSeries
.getLength();
397 sal_Int32 i
= (nSeriesCount
== 1) ? 0: 1;
398 for( ; i
<nSeriesCount
; ++i
)
401 Reference
< beans::XPropertySet
> xProp( aSeries
[i
], uno::UNO_QUERY_THROW
);
402 chart2::StackingDirection eCurrentDirection
= eCommonDirection
;
403 // property is not MAYBEVOID
404 bool bSuccess
= ( xProp
->getPropertyValue( "StackingDirection" ) >>= eCurrentDirection
);
405 OSL_ASSERT( bSuccess
);
406 (void)(bSuccess
); // avoid warning in non-debug builds
407 if( ! bDirectionInitialized
)
409 eCommonDirection
= eCurrentDirection
;
410 bDirectionInitialized
= true;
414 if( eCommonDirection
!= eCurrentDirection
)
424 if( eCommonDirection
== chart2::StackingDirection_Z_STACKING
)
425 eStackMode
= StackMode_Z_STACKED
;
426 else if( eCommonDirection
== chart2::StackingDirection_Y_STACKING
)
428 eStackMode
= StackMode_Y_STACKED
;
431 if( xCorrespondingCoordinateSystem
.is() )
433 if( 1 < xCorrespondingCoordinateSystem
->getDimension() )
435 sal_Int32 nAxisIndex
= 0;
437 nAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(aSeries
[0]);
439 Reference
< chart2::XAxis
> xAxis(
440 xCorrespondingCoordinateSystem
->getAxisByDimension( 1,nAxisIndex
));
443 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
444 if( aScaleData
.AxisType
==chart2::AxisType::PERCENT
)
445 eStackMode
= StackMode_Y_STACKED_PERCENT
;
452 catch( const uno::Exception
& ex
)
454 ASSERT_EXCEPTION( ex
);
460 sal_Int32
DiagramHelper::getDimension( const Reference
< XDiagram
> & xDiagram
)
463 sal_Int32 nResult
= -1;
467 Reference
< XCoordinateSystemContainer
> xCooSysCnt( xDiagram
, uno::UNO_QUERY
);
468 if( xCooSysCnt
.is() )
470 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
471 xCooSysCnt
->getCoordinateSystems());
473 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
475 Reference
< XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
478 nResult
= xCooSys
->getDimension();
484 catch( const uno::Exception
& ex
)
486 ASSERT_EXCEPTION( ex
);
492 void DiagramHelper::setDimension(
493 const Reference
< XDiagram
> & xDiagram
,
494 sal_Int32 nNewDimensionCount
)
499 if( DiagramHelper::getDimension( xDiagram
) == nNewDimensionCount
)
504 bool rbFound
= false;
505 bool rbAmbiguous
= true;
506 StackMode eStackMode
= DiagramHelper::getStackMode( xDiagram
, rbFound
, rbAmbiguous
);
507 bool bIsSupportingOnlyDeepStackingFor3D
=false;
509 //change all coordinate systems:
510 Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY_THROW
);
511 Sequence
< Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
512 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
514 Reference
< XCoordinateSystem
> xOldCooSys( aCooSysList
[nCS
], uno::UNO_QUERY
);
515 Reference
< XCoordinateSystem
> xNewCooSys
;
517 Reference
< XChartTypeContainer
> xChartTypeContainer( xOldCooSys
, uno::UNO_QUERY
);
518 if( !xChartTypeContainer
.is() )
521 Sequence
< Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
522 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
524 Reference
< XChartType
> xChartType( aChartTypeList
[nT
], uno::UNO_QUERY
);
525 bIsSupportingOnlyDeepStackingFor3D
= ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType
);
528 xNewCooSys
= xChartType
->createCoordinateSystem( nNewDimensionCount
);
531 //@todo make sure that all following charttypes are also capable of the new dimension
532 //otherwise separate them in a different group
533 //BM: might be done in replaceCoordinateSystem()
536 // replace the old coordinate system at all places where it was used
537 DiagramHelper::replaceCoordinateSystem( xDiagram
, xOldCooSys
, xNewCooSys
);
540 //correct stack mode if necessary
541 if( nNewDimensionCount
==3 && eStackMode
!= StackMode_Z_STACKED
&& bIsSupportingOnlyDeepStackingFor3D
)
542 DiagramHelper::setStackMode( xDiagram
, StackMode_Z_STACKED
);
543 else if( nNewDimensionCount
==2 && eStackMode
== StackMode_Z_STACKED
)
544 DiagramHelper::setStackMode( xDiagram
, StackMode_NONE
);
546 catch( const uno::Exception
& ex
)
548 ASSERT_EXCEPTION( ex
);
552 void DiagramHelper::replaceCoordinateSystem(
553 const Reference
< XDiagram
> & xDiagram
,
554 const Reference
< XCoordinateSystem
> & xCooSysToReplace
,
555 const Reference
< XCoordinateSystem
> & xReplacement
)
557 OSL_ASSERT( xDiagram
.is());
561 // update the coordinate-system container
562 Reference
< XCoordinateSystemContainer
> xCont( xDiagram
, uno::UNO_QUERY
);
567 Reference
< chart2::data::XLabeledDataSequence
> xCategories
= DiagramHelper::getCategoriesFromDiagram( xDiagram
);
569 // move chart types of xCooSysToReplace to xReplacement
570 Reference
< XChartTypeContainer
> xCTCntCooSys( xCooSysToReplace
, uno::UNO_QUERY_THROW
);
571 Reference
< XChartTypeContainer
> xCTCntReplacement( xReplacement
, uno::UNO_QUERY_THROW
);
572 xCTCntReplacement
->setChartTypes( xCTCntCooSys
->getChartTypes());
574 xCont
->removeCoordinateSystem( xCooSysToReplace
);
575 xCont
->addCoordinateSystem( xReplacement
);
577 if( xCategories
.is() )
578 DiagramHelper::setCategoriesToDiagram( xCategories
, xDiagram
);
580 catch( const uno::Exception
& ex
)
582 ASSERT_EXCEPTION( ex
);
587 bool DiagramHelper::isSeriesAttachedToMainAxis(
588 const uno::Reference
< chart2::XDataSeries
>& xDataSeries
)
590 sal_Int32 nAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(xDataSeries
);
591 return (nAxisIndex
==0);
594 bool DiagramHelper::attachSeriesToAxis( bool bAttachToMainAxis
595 , const uno::Reference
< chart2::XDataSeries
>& xDataSeries
596 , const uno::Reference
< chart2::XDiagram
>& xDiagram
597 , const uno::Reference
< uno::XComponentContext
> & xContext
600 bool bChanged
= false;
602 //set property at axis
603 Reference
< beans::XPropertySet
> xProp( xDataSeries
, uno::UNO_QUERY_THROW
);
607 sal_Int32 nNewAxisIndex
= bAttachToMainAxis
? 0 : 1;
608 sal_Int32 nOldAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(xDataSeries
);
609 uno::Reference
< chart2::XAxis
> xOldAxis( DiagramHelper::getAttachedAxis( xDataSeries
, xDiagram
) );
611 if( nOldAxisIndex
!= nNewAxisIndex
)
615 xProp
->setPropertyValue( "AttachedAxisIndex", uno::makeAny( nNewAxisIndex
) );
618 catch( const uno::Exception
& ex
)
620 ASSERT_EXCEPTION( ex
);
624 if( bChanged
&& xDiagram
.is() )
626 uno::Reference
< XAxis
> xAxis( AxisHelper::getAxis( 1, bAttachToMainAxis
, xDiagram
) );
627 if(!xAxis
.is()) //create an axis if necessary
628 xAxis
= AxisHelper::createAxis( 1, bAttachToMainAxis
, xDiagram
, xContext
);
631 AxisHelper::makeAxisVisible( xAxis
);
632 AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis
, xDiagram
);
639 uno::Reference
< XAxis
> DiagramHelper::getAttachedAxis(
640 const uno::Reference
< XDataSeries
>& xSeries
,
641 const uno::Reference
< XDiagram
>& xDiagram
)
643 return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries
), xDiagram
);
646 uno::Reference
< XChartType
> DiagramHelper::getChartTypeOfSeries(
647 const uno::Reference
< chart2::XDiagram
>& xDiagram
648 , const uno::Reference
< XDataSeries
>& xGivenDataSeries
)
650 if( !xGivenDataSeries
.is() )
655 //iterate through the model to find the given xSeries
656 //the found parent indicates the charttype
658 //iterate through all coordinate systems
659 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
660 if( !xCooSysContainer
.is())
663 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
664 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
666 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
668 //iterate through all chart types in the current coordinate system
669 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
670 OSL_ASSERT( xChartTypeContainer
.is());
671 if( !xChartTypeContainer
.is() )
673 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
674 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
676 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
678 //iterate through all series in this chart type
679 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xChartType
, uno::UNO_QUERY
);
680 OSL_ASSERT( xDataSeriesContainer
.is());
681 if( !xDataSeriesContainer
.is() )
684 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
685 for( sal_Int32 nS
= 0; nS
< aSeriesList
.getLength(); ++nS
)
687 if( xGivenDataSeries
==aSeriesList
[nS
] )
695 ::std::vector
< Reference
< XDataSeries
> >
696 DiagramHelper::getDataSeriesFromDiagram(
697 const Reference
< XDiagram
> & xDiagram
)
699 ::std::vector
< Reference
< XDataSeries
> > aResult
;
703 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
704 xDiagram
, uno::UNO_QUERY_THROW
);
705 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
706 xCooSysCnt
->getCoordinateSystems());
707 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
709 Reference
< XChartTypeContainer
> xCTCnt( aCooSysSeq
[i
], uno::UNO_QUERY_THROW
);
710 Sequence
< Reference
< XChartType
> > aChartTypeSeq( xCTCnt
->getChartTypes());
711 for( sal_Int32 j
=0; j
<aChartTypeSeq
.getLength(); ++j
)
713 Reference
< XDataSeriesContainer
> xDSCnt( aChartTypeSeq
[j
], uno::UNO_QUERY_THROW
);
714 Sequence
< Reference
< XDataSeries
> > aSeriesSeq( xDSCnt
->getDataSeries() );
715 ::std::copy( aSeriesSeq
.getConstArray(), aSeriesSeq
.getConstArray() + aSeriesSeq
.getLength(),
716 ::std::back_inserter( aResult
));
720 catch( const uno::Exception
& ex
)
722 ASSERT_EXCEPTION( ex
);
728 Sequence
< Sequence
< Reference
< XDataSeries
> > >
729 DiagramHelper::getDataSeriesGroups( const Reference
< XDiagram
> & xDiagram
)
731 vector
< Sequence
< Reference
< XDataSeries
> > > aResult
;
733 //iterate through all coordinate systems
734 Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
735 if( xCooSysContainer
.is() )
737 Sequence
< Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
738 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
740 //iterate through all chart types in the current coordinate system
741 Reference
< XChartTypeContainer
> xChartTypeContainer( aCooSysList
[nCS
], uno::UNO_QUERY
);
742 if( !xChartTypeContainer
.is() )
744 Sequence
< Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
745 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
747 Reference
< XDataSeriesContainer
> xDataSeriesContainer( aChartTypeList
[nT
], uno::UNO_QUERY
);
748 if( !xDataSeriesContainer
.is() )
750 aResult
.push_back( xDataSeriesContainer
->getDataSeries() );
754 return ContainerHelper::ContainerToSequence( aResult
);
757 Reference
< XChartType
>
758 DiagramHelper::getChartTypeByIndex( const Reference
< XDiagram
>& xDiagram
, sal_Int32 nIndex
)
760 Reference
< XChartType
> xChartType
;
762 //iterate through all coordinate systems
763 Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
764 if( ! xCooSysContainer
.is())
767 Sequence
< Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
768 sal_Int32 nTypesSoFar
= 0;
769 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
771 Reference
< XChartTypeContainer
> xChartTypeContainer( aCooSysList
[nCS
], uno::UNO_QUERY
);
772 if( !xChartTypeContainer
.is() )
774 Sequence
< Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
775 if( nIndex
>= 0 && nIndex
< (nTypesSoFar
+ aChartTypeList
.getLength()) )
777 xChartType
.set( aChartTypeList
[nIndex
- nTypesSoFar
] );
780 nTypesSoFar
+= aChartTypeList
.getLength();
789 std::vector
< Reference
< XAxis
> > lcl_getAxisHoldingCategoriesFromDiagram(
790 const Reference
< XDiagram
> & xDiagram
)
792 std::vector
< Reference
< XAxis
> > aRet
;
794 Reference
< XAxis
> xResult
;
795 // return first x-axis as fall-back
796 Reference
< XAxis
> xFallBack
;
799 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
800 xDiagram
, uno::UNO_QUERY_THROW
);
801 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
802 xCooSysCnt
->getCoordinateSystems());
803 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
805 Reference
< XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
806 OSL_ASSERT( xCooSys
.is());
807 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
809 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
810 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
812 Reference
< XAxis
> xAxis
= xCooSys
->getAxisByDimension( nN
,nI
);
813 OSL_ASSERT( xAxis
.is());
816 ScaleData aScaleData
= xAxis
->getScaleData();
817 if( aScaleData
.Categories
.is() || (aScaleData
.AxisType
== AxisType::CATEGORY
) )
819 aRet
.push_back(xAxis
);
821 if( (nN
== 0) && !xFallBack
.is())
822 xFallBack
.set( xAxis
);
828 catch( const uno::Exception
& ex
)
830 ASSERT_EXCEPTION( ex
);
834 aRet
.push_back(xFallBack
);
839 } // anonymous namespace
841 bool DiagramHelper::isCategoryDiagram(
842 const Reference
< XDiagram
>& xDiagram
)
846 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
847 xDiagram
, uno::UNO_QUERY_THROW
);
848 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
849 xCooSysCnt
->getCoordinateSystems());
850 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
852 Reference
< XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
853 OSL_ASSERT( xCooSys
.is());
854 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
856 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
857 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
859 Reference
< XAxis
> xAxis
= xCooSys
->getAxisByDimension( nN
,nI
);
860 OSL_ASSERT( xAxis
.is());
863 ScaleData aScaleData
= xAxis
->getScaleData();
864 if( aScaleData
.AxisType
== AxisType::CATEGORY
|| aScaleData
.AxisType
== AxisType::DATE
)
871 catch( const uno::Exception
& ex
)
873 ASSERT_EXCEPTION( ex
);
879 void DiagramHelper::setCategoriesToDiagram(
880 const Reference
< chart2::data::XLabeledDataSequence
>& xCategories
,
881 const Reference
< XDiagram
>& xDiagram
,
882 bool bSetAxisType
/* = false */,
883 bool bCategoryAxis
/* = true */ )
885 std::vector
< Reference
< chart2::XAxis
> > aCatAxes(
886 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram
));
888 std::vector
< Reference
< chart2::XAxis
> >::iterator
aIt( aCatAxes
.begin() );
889 std::vector
< Reference
< chart2::XAxis
> >::const_iterator
aEnd( aCatAxes
.end() );
891 for( aIt
= aCatAxes
.begin(); aIt
!= aEnd
; ++aIt
)
893 Reference
< chart2::XAxis
> xCatAxis(*aIt
);
896 ScaleData
aScaleData( xCatAxis
->getScaleData());
897 aScaleData
.Categories
= xCategories
;
901 aScaleData
.AxisType
= AxisType::CATEGORY
;
902 else if( aScaleData
.AxisType
== AxisType::CATEGORY
|| aScaleData
.AxisType
== AxisType::DATE
)
903 aScaleData
.AxisType
= AxisType::REALNUMBER
;
905 xCatAxis
->setScaleData( aScaleData
);
910 Reference
< data::XLabeledDataSequence
>
911 DiagramHelper::getCategoriesFromDiagram(
912 const Reference
< XDiagram
> & xDiagram
)
914 Reference
< data::XLabeledDataSequence
> xResult
;
918 std::vector
< Reference
< chart2::XAxis
> > aCatAxes(
919 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram
));
920 std::vector
< Reference
< chart2::XAxis
> >::iterator
aIt( aCatAxes
.begin() );
921 std::vector
< Reference
< chart2::XAxis
> >::const_iterator
aEnd( aCatAxes
.end() );
922 //search for first categories
925 Reference
< chart2::XAxis
> xCatAxis(*aIt
);
928 ScaleData
aScaleData( xCatAxis
->getScaleData());
929 if( aScaleData
.Categories
.is() )
931 xResult
.set( aScaleData
.Categories
);
932 uno::Reference
<beans::XPropertySet
> xProp(aScaleData
.Categories
->getValues(), uno::UNO_QUERY
);
937 xProp
->setPropertyValue( "Role", uno::makeAny( OUString("categories") ) );
939 catch( const uno::Exception
& ex
)
941 ASSERT_EXCEPTION( ex
);
948 catch( const uno::Exception
& ex
)
950 ASSERT_EXCEPTION( ex
);
956 void lcl_generateAutomaticCategoriesFromChartType(
957 Sequence
< OUString
>& rRet
,
958 const Reference
< XChartType
>& xChartType
)
962 OUString
aMainSeq( xChartType
->getRoleOfSequenceForSeriesLabel() );
963 Reference
< XDataSeriesContainer
> xSeriesCnt( xChartType
, uno::UNO_QUERY
);
964 if( xSeriesCnt
.is() )
966 Sequence
< Reference
< XDataSeries
> > aSeriesSeq( xSeriesCnt
->getDataSeries() );
967 for( sal_Int32 nS
= 0; nS
< aSeriesSeq
.getLength(); nS
++ )
969 Reference
< data::XDataSource
> xDataSource( aSeriesSeq
[nS
], uno::UNO_QUERY
);
970 if( !xDataSource
.is() )
972 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq(
973 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aMainSeq
));
974 if( !xLabeledSeq
.is() )
976 Reference
< chart2::data::XDataSequence
> xValueSeq( xLabeledSeq
->getValues() );
977 if( !xValueSeq
.is() )
979 rRet
= xValueSeq
->generateLabel( chart2::data::LabelOrigin_LONG_SIDE
);
980 if( rRet
.getLength() )
986 Sequence
< OUString
> DiagramHelper::generateAutomaticCategoriesFromCooSys( const Reference
< XCoordinateSystem
> & xCooSys
)
988 Sequence
< OUString
> aRet
;
990 Reference
< XChartTypeContainer
> xTypeCntr( xCooSys
, uno::UNO_QUERY
);
993 Sequence
< Reference
< XChartType
> > aChartTypes( xTypeCntr
->getChartTypes() );
994 for( sal_Int32 nN
=0; nN
<aChartTypes
.getLength(); nN
++ )
996 lcl_generateAutomaticCategoriesFromChartType( aRet
, aChartTypes
[nN
] );
997 if( aRet
.getLength() )
1004 Sequence
< OUString
> DiagramHelper::getExplicitSimpleCategories(
1005 const Reference
< XChartDocument
>& xChartDoc
)
1007 Sequence
< OUString
> aRet
;
1008 uno::Reference
< frame::XModel
> xChartModel( xChartDoc
, uno::UNO_QUERY
);
1009 if(xChartModel
.is())
1011 uno::Reference
< chart2::XCoordinateSystem
> xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel
) );
1012 ExplicitCategoriesProvider
aExplicitCategoriesProvider( xCooSys
, xChartModel
);
1013 aRet
= aExplicitCategoriesProvider
.getSimpleCategories();
1020 void lcl_switchToDateCategories( const Reference
< XChartDocument
>& xChartDoc
, const Reference
< XAxis
>& xAxis
)
1024 if( !xChartDoc
.is() )
1027 ScaleData
aScale( xAxis
->getScaleData() );
1028 if( xChartDoc
->hasInternalDataProvider() )
1030 //remove all content the is not of type double and remove multiple level
1031 Reference
< XAnyDescriptionAccess
> xDataAccess( xChartDoc
->getDataProvider(), uno::UNO_QUERY
);
1032 if( xDataAccess
.is() )
1034 Sequence
< Sequence
< Any
> > aAnyCategories( xDataAccess
->getAnyRowDescriptions() );
1037 ::rtl::math::setNan( & fNan
);
1038 sal_Int32 nN
= aAnyCategories
.getLength();
1041 Sequence
< Any
>& rCat
= aAnyCategories
[nN
];
1042 if( rCat
.getLength() > 1 )
1044 if( rCat
.getLength() == 1 )
1046 Any
& rAny
= rCat
[0];
1047 if( !(rAny
>>=fTest
) )
1049 rAny
= uno::makeAny(fNan
);
1053 xDataAccess
->setAnyRowDescriptions( aAnyCategories
);
1055 //check the numberformat at the axis
1056 Reference
< beans::XPropertySet
> xAxisProps( xAxis
, uno::UNO_QUERY
);
1057 Reference
< util::XNumberFormatsSupplier
> xNumberFormatsSupplier( xChartDoc
, uno::UNO_QUERY
);
1058 if( xAxisProps
.is() && xNumberFormatsSupplier
.is() )
1060 sal_Int32 nNumberFormat
= -1;
1061 xAxisProps
->getPropertyValue( "NumberFormat" ) >>= nNumberFormat
;
1063 Reference
< util::XNumberFormats
> xNumberFormats
= Reference
< util::XNumberFormats
>( xNumberFormatsSupplier
->getNumberFormats() );
1064 if( xNumberFormats
.is() )
1066 Reference
< beans::XPropertySet
> xKeyProps
;
1069 xKeyProps
= xNumberFormats
->getByKey( nNumberFormat
);
1071 catch( const uno::Exception
& ex
)
1073 ASSERT_EXCEPTION( ex
);
1075 sal_Int32 nType
= util::NumberFormat::UNDEFINED
;
1076 if( xKeyProps
.is() )
1077 xKeyProps
->getPropertyValue( "Type" ) >>= nType
;
1078 if( !( nType
& util::NumberFormat::DATE
) )
1080 //set a date format to the axis
1081 sal_Bool bCreate
= sal_True
;
1082 const LocaleDataWrapper
& rLocaleDataWrapper
= Application::GetSettings().GetLocaleDataWrapper();
1083 Sequence
<sal_Int32
> aKeySeq
= xNumberFormats
->queryKeys( util::NumberFormat::DATE
, rLocaleDataWrapper
.getLanguageTag().getLocale(), bCreate
);
1084 if( aKeySeq
.getLength() )
1086 xAxisProps
->setPropertyValue( "NumberFormat", uno::makeAny(aKeySeq
[0]) );
1092 if( aScale
.AxisType
!= chart2::AxisType::DATE
)
1093 AxisHelper::removeExplicitScaling( aScale
);
1094 aScale
.AxisType
= chart2::AxisType::DATE
;
1095 xAxis
->setScaleData( aScale
);
1098 void lcl_switchToTextCategories( const Reference
< XChartDocument
>& xChartDoc
, const Reference
< XAxis
>& xAxis
)
1102 if( !xChartDoc
.is() )
1104 ScaleData
aScale( xAxis
->getScaleData() );
1105 if( aScale
.AxisType
!= chart2::AxisType::CATEGORY
)
1106 AxisHelper::removeExplicitScaling( aScale
);
1107 //todo migrate dates to text?
1108 aScale
.AxisType
= chart2::AxisType::CATEGORY
;
1109 aScale
.AutoDateAxis
= false;
1110 xAxis
->setScaleData( aScale
);
1115 void DiagramHelper::switchToDateCategories( const Reference
< XChartDocument
>& xChartDoc
)
1117 Reference
< frame::XModel
> xChartModel( xChartDoc
, uno::UNO_QUERY
);
1118 if(xChartModel
.is())
1120 ControllerLockGuard
aCtrlLockGuard( xChartModel
);
1122 Reference
< chart2::XCoordinateSystem
> xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel
) );
1125 Reference
< XAxis
> xAxis( xCooSys
->getAxisByDimension(0,0) );
1126 lcl_switchToDateCategories( xChartDoc
, xAxis
);
1131 void DiagramHelper::switchToTextCategories( const Reference
< XChartDocument
>& xChartDoc
)
1133 Reference
< frame::XModel
> xChartModel( xChartDoc
, uno::UNO_QUERY
);
1134 if(xChartModel
.is())
1136 ControllerLockGuard
aCtrlLockGuard( xChartModel
);
1138 Reference
< chart2::XCoordinateSystem
> xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel
) );
1141 Reference
< XAxis
> xAxis( xCooSys
->getAxisByDimension(0,0) );
1142 lcl_switchToTextCategories( xChartDoc
, xAxis
);
1147 bool DiagramHelper::isSupportingDateAxis( const Reference
< chart2::XDiagram
>& xDiagram
)
1149 return ::chart::ChartTypeHelper::isSupportingDateAxis(
1150 DiagramHelper::getChartTypeByIndex( xDiagram
, 0 ), DiagramHelper::getDimension( xDiagram
), 0 );
1153 bool DiagramHelper::isDateNumberFormat( sal_Int32 nNumberFormat
, const Reference
< util::XNumberFormats
>& xNumberFormats
)
1155 bool bIsDate
= false;
1156 if( !xNumberFormats
.is() )
1159 Reference
< beans::XPropertySet
> xKeyProps
= xNumberFormats
->getByKey( nNumberFormat
);
1160 if( xKeyProps
.is() )
1162 sal_Int32 nType
= util::NumberFormat::UNDEFINED
;
1163 xKeyProps
->getPropertyValue( "Type" ) >>= nType
;
1164 bIsDate
= nType
& util::NumberFormat::DATE
;
1169 sal_Int32
DiagramHelper::getDateNumberFormat( const Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
)
1172 Reference
< util::XNumberFormats
> xNumberFormats( xNumberFormatsSupplier
->getNumberFormats() );
1173 if( xNumberFormats
.is() )
1175 sal_Bool bCreate
= sal_True
;
1176 const LocaleDataWrapper
& rLocaleDataWrapper
= Application::GetSettings().GetLocaleDataWrapper();
1177 Sequence
<sal_Int32
> aKeySeq
= xNumberFormats
->queryKeys( util::NumberFormat::DATE
,
1178 rLocaleDataWrapper
.getLanguageTag().getLocale(), bCreate
);
1179 if( aKeySeq
.getLength() )
1185 //try to get a date format with full year display
1186 NumberFormatterWrapper
aNumberFormatterWrapper( xNumberFormatsSupplier
);
1187 SvNumberFormatter
* pNumFormatter
= aNumberFormatterWrapper
.getSvNumberFormatter();
1190 const SvNumberformat
* pFormat
= pNumFormatter
->GetEntry( nRet
);
1192 nRet
= pNumFormatter
->GetFormatIndex( NF_DATE_SYS_DDMMYYYY
, pFormat
->GetLanguage() );
1197 sal_Int32
DiagramHelper::getPercentNumberFormat( const Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
)
1200 Reference
< util::XNumberFormats
> xNumberFormats( xNumberFormatsSupplier
->getNumberFormats() );
1201 if( xNumberFormats
.is() )
1203 sal_Bool bCreate
= sal_True
;
1204 const LocaleDataWrapper
& rLocaleDataWrapper
= Application::GetSettings().GetLocaleDataWrapper();
1205 Sequence
<sal_Int32
> aKeySeq
= xNumberFormats
->queryKeys( util::NumberFormat::PERCENT
,
1206 rLocaleDataWrapper
.getLanguageTag().getLocale(), bCreate
);
1207 if( aKeySeq
.getLength() )
1215 Sequence
< Reference
< XChartType
> >
1216 DiagramHelper::getChartTypesFromDiagram(
1217 const Reference
< XDiagram
> & xDiagram
)
1219 ::std::vector
< Reference
< XChartType
> > aResult
;
1225 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
1226 xDiagram
, uno::UNO_QUERY_THROW
);
1227 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
1228 xCooSysCnt
->getCoordinateSystems());
1229 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
1231 Reference
< XChartTypeContainer
> xCTCnt( aCooSysSeq
[i
], uno::UNO_QUERY_THROW
);
1232 Sequence
< Reference
< XChartType
> > aChartTypeSeq( xCTCnt
->getChartTypes());
1233 ::std::copy( aChartTypeSeq
.getConstArray(),
1234 aChartTypeSeq
.getConstArray() + aChartTypeSeq
.getLength(),
1235 ::std::back_inserter( aResult
));
1238 catch( const uno::Exception
& ex
)
1240 ASSERT_EXCEPTION( ex
);
1244 return ContainerHelper::ContainerToSequence( aResult
);
1247 bool DiagramHelper::areChartTypesCompatible( const Reference
< ::chart2::XChartType
>& xFirstType
,
1248 const Reference
< ::chart2::XChartType
>& xSecondType
)
1250 if( !xFirstType
.is() || !xSecondType
.is() )
1253 ::std::vector
< OUString
> aFirstRoles( ContainerHelper::SequenceToVector( xFirstType
->getSupportedMandatoryRoles() ) );
1254 ::std::vector
< OUString
> aSecondRoles( ContainerHelper::SequenceToVector( xSecondType
->getSupportedMandatoryRoles() ) );
1255 ::std::sort( aFirstRoles
.begin(), aFirstRoles
.end() );
1256 ::std::sort( aSecondRoles
.begin(), aSecondRoles
.end() );
1257 return ( aFirstRoles
== aSecondRoles
);
1263 * This method implements the logic of checking if a series can be moved
1264 * forward/backward. Depending on the "bDoMove" parameter the series will
1265 * be moved (bDoMove = true) or the function just will test if the
1266 * series can be moved without doing the move (bDoMove = false).
1269 * Reference to the diagram that contains the series.
1271 * @param xGivenDataSeries
1272 * Reference to the series that should moved or tested for moving.
1275 * Direction in which the series should be moved or tested for moving.
1278 * Should this function really move the series (true) or just test if it is
1283 * in case of bDoMove == true
1284 * - True : if the move was done
1285 * - False : the move failed
1286 * in case of bDoMove == false
1287 * - True : the series can be moved
1288 * - False : the series can not be moved
1292 bool lcl_moveSeriesOrCheckIfMoveIsAllowed(
1293 const Reference
< XDiagram
>& xDiagram
,
1294 const Reference
< XDataSeries
>& xGivenDataSeries
,
1298 bool bMovedOrMoveAllowed
= false;
1302 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
1304 //find position of series.
1305 bool bFound
= false;
1307 if( xGivenDataSeries
.is() && xCooSysContainer
.is() )
1309 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
1311 for( sal_Int32 nCS
= 0; !bFound
&& nCS
< aCooSysList
.getLength(); ++nCS
)
1313 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
1315 //iterate through all chart types in the current coordinate system
1316 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
1317 OSL_ASSERT( xChartTypeContainer
.is());
1318 if( !xChartTypeContainer
.is() )
1320 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
1321 uno::Reference
< XChartType
> xFormerChartType
;
1323 for( sal_Int32 nT
= 0; !bFound
&& nT
< aChartTypeList
.getLength(); ++nT
)
1325 uno::Reference
< XChartType
> xCurrentChartType( aChartTypeList
[nT
] );
1327 //iterate through all series in this chart type
1328 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xCurrentChartType
, uno::UNO_QUERY
);
1329 OSL_ASSERT( xDataSeriesContainer
.is());
1330 if( !xDataSeriesContainer
.is() )
1333 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
1335 for( sal_Int32 nS
= 0; !bFound
&& nS
< aSeriesList
.getLength(); ++nS
)
1338 // We found the series we are interrested in !
1339 if( xGivenDataSeries
==aSeriesList
[nS
] )
1341 sal_Int32 nOldSeriesIndex
= nS
;
1346 sal_Int32 nNewSeriesIndex
= nS
;
1354 if( nNewSeriesIndex
>= 0 && nNewSeriesIndex
< aSeriesList
.getLength() )
1356 //move series in the same charttype
1357 bMovedOrMoveAllowed
= true;
1360 aSeriesList
[ nOldSeriesIndex
] = aSeriesList
[ nNewSeriesIndex
];
1361 aSeriesList
[ nNewSeriesIndex
] = xGivenDataSeries
;
1362 xDataSeriesContainer
->setDataSeries( aSeriesList
);
1365 else if( nNewSeriesIndex
<0 )
1367 //exchange series with former charttype
1368 if( xFormerChartType
.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType
, xCurrentChartType
) )
1370 bMovedOrMoveAllowed
= true;
1373 uno::Reference
< XDataSeriesContainer
> xOtherDataSeriesContainer( xFormerChartType
, uno::UNO_QUERY
);
1374 if( xOtherDataSeriesContainer
.is() )
1376 uno::Sequence
< uno::Reference
< XDataSeries
> > aOtherSeriesList( xOtherDataSeriesContainer
->getDataSeries() );
1377 sal_Int32 nOtherSeriesIndex
= aOtherSeriesList
.getLength()-1;
1378 if( nOtherSeriesIndex
>= 0 && nOtherSeriesIndex
< aOtherSeriesList
.getLength() )
1380 uno::Reference
< XDataSeries
> xExchangeSeries( aOtherSeriesList
[nOtherSeriesIndex
] );
1381 aOtherSeriesList
[nOtherSeriesIndex
] = xGivenDataSeries
;
1382 xOtherDataSeriesContainer
->setDataSeries(aOtherSeriesList
);
1384 aSeriesList
[nOldSeriesIndex
]=xExchangeSeries
;
1385 xDataSeriesContainer
->setDataSeries(aSeriesList
);
1391 else if( nT
+1 < aChartTypeList
.getLength() )
1393 //exchange series with next charttype
1394 uno::Reference
< XChartType
> xOtherChartType( aChartTypeList
[nT
+1] );
1395 if( xOtherChartType
.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType
, xCurrentChartType
) )
1397 bMovedOrMoveAllowed
= true;
1400 uno::Reference
< XDataSeriesContainer
> xOtherDataSeriesContainer( xOtherChartType
, uno::UNO_QUERY
);
1401 if( xOtherDataSeriesContainer
.is() )
1403 uno::Sequence
< uno::Reference
< XDataSeries
> > aOtherSeriesList( xOtherDataSeriesContainer
->getDataSeries() );
1404 sal_Int32 nOtherSeriesIndex
= 0;
1405 if( nOtherSeriesIndex
>= 0 && nOtherSeriesIndex
< aOtherSeriesList
.getLength() )
1407 uno::Reference
< XDataSeries
> xExchangeSeries( aOtherSeriesList
[nOtherSeriesIndex
] );
1408 aOtherSeriesList
[nOtherSeriesIndex
] = xGivenDataSeries
;
1409 xOtherDataSeriesContainer
->setDataSeries(aOtherSeriesList
);
1411 aSeriesList
[nOldSeriesIndex
]=xExchangeSeries
;
1412 xDataSeriesContainer
->setDataSeries(aSeriesList
);
1419 catch( const util::CloseVetoException
& )
1422 catch( const uno::RuntimeException
& )
1427 xFormerChartType
= xCurrentChartType
;
1432 catch( const util::CloseVetoException
& )
1435 catch( const uno::RuntimeException
& )
1438 return bMovedOrMoveAllowed
;
1440 } // anonymous namespace
1443 bool DiagramHelper::isSeriesMoveable(
1444 const Reference
< XDiagram
>& xDiagram
,
1445 const Reference
< XDataSeries
>& xGivenDataSeries
,
1448 bool bIsMoveable
= false;
1449 const bool bDoMove
= false;
1451 bIsMoveable
= lcl_moveSeriesOrCheckIfMoveIsAllowed(
1452 xDiagram
, xGivenDataSeries
, bForward
, bDoMove
);
1458 bool DiagramHelper::moveSeries( const Reference
< XDiagram
>& xDiagram
, const Reference
< XDataSeries
>& xGivenDataSeries
, bool bForward
)
1460 bool bMoved
= false;
1461 const bool bDoMove
= true;
1463 bMoved
= lcl_moveSeriesOrCheckIfMoveIsAllowed(
1464 xDiagram
, xGivenDataSeries
, bForward
, bDoMove
);
1469 bool DiagramHelper::isSupportingFloorAndWall( const Reference
<
1470 chart2::XDiagram
>& xDiagram
)
1472 //pies and donuts currently do not support this because of wrong files from older versions
1473 //todo: allow this in future again, if fileversion are available for ole objects (metastream)
1474 //thus the wrong bottom can be removed on import
1476 Sequence
< Reference
< chart2::XChartType
> > aTypes(
1477 ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram
) );
1478 for( sal_Int32 nN
= 0; nN
< aTypes
.getLength(); nN
++ )
1480 Reference
< chart2::XChartType
> xType( aTypes
[nN
] );
1481 if( xType
.is() && xType
->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_PIE
) )
1483 if( xType
.is() && xType
->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_NET
) )
1485 if( xType
.is() && xType
->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET
) )
1491 bool DiagramHelper::isPieOrDonutChart( const ::com::sun::star::uno::Reference
<
1492 ::com::sun::star::chart2::XDiagram
>& xDiagram
)
1494 uno::Reference
< chart2::XChartType
> xChartType( DiagramHelper::getChartTypeByIndex(
1497 if( xChartType
.is() )
1499 OUString aChartType
= xChartType
->getChartType();
1500 if( aChartType
.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE
) )
1506 sal_Int32
DiagramHelper::getGeometry3D(
1507 const uno::Reference
< chart2::XDiagram
> & xDiagram
,
1508 bool& rbFound
, bool& rbAmbiguous
)
1510 sal_Int32
nCommonGeom( DataPointGeometry3D::CUBOID
);
1512 rbAmbiguous
= false;
1514 ::std::vector
< Reference
< chart2::XDataSeries
> > aSeriesVec(
1515 DiagramHelper::getDataSeriesFromDiagram( xDiagram
));
1517 if( aSeriesVec
.empty())
1520 for( ::std::vector
< Reference
< chart2::XDataSeries
> >::const_iterator aIt
=
1521 aSeriesVec
.begin(); aIt
!= aSeriesVec
.end(); ++aIt
)
1525 sal_Int32 nGeom
= 0;
1526 Reference
< beans::XPropertySet
> xProp( *aIt
, uno::UNO_QUERY_THROW
);
1527 if( xProp
->getPropertyValue( "Geometry3D") >>= nGeom
)
1532 nCommonGeom
= nGeom
;
1535 // further series: compare for uniqueness
1536 else if( nCommonGeom
!= nGeom
)
1543 catch( const uno::Exception
& ex
)
1545 ASSERT_EXCEPTION( ex
);
1552 void DiagramHelper::setGeometry3D(
1553 const Reference
< chart2::XDiagram
> & xDiagram
,
1554 sal_Int32 nNewGeometry
)
1556 ::std::vector
< Reference
< chart2::XDataSeries
> > aSeriesVec(
1557 DiagramHelper::getDataSeriesFromDiagram( xDiagram
));
1559 for( ::std::vector
< Reference
< chart2::XDataSeries
> >::const_iterator aIt
=
1560 aSeriesVec
.begin(); aIt
!= aSeriesVec
.end(); ++aIt
)
1562 DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(
1563 *aIt
, "Geometry3D", uno::makeAny( nNewGeometry
));
1567 sal_Int32
DiagramHelper::getCorrectedMissingValueTreatment(
1568 const Reference
< chart2::XDiagram
> & xDiagram
,
1569 const Reference
< chart2::XChartType
>& xChartType
)
1571 sal_Int32 nResult
= ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP
;
1572 uno::Sequence
< sal_Int32
> aAvailableMissingValueTreatments(
1573 ChartTypeHelper::getSupportedMissingValueTreatments( xChartType
) );
1575 uno::Reference
< beans::XPropertySet
> xDiaProp( xDiagram
, uno::UNO_QUERY
);
1576 if( xDiaProp
.is() && (xDiaProp
->getPropertyValue( "MissingValueTreatment" ) >>= nResult
) )
1578 //ensure that the set value is supported by this charttype
1579 for( sal_Int32 nN
= 0; nN
< aAvailableMissingValueTreatments
.getLength(); nN
++ )
1580 if( aAvailableMissingValueTreatments
[nN
] == nResult
)
1581 return nResult
; //ok
1584 //otherwise use the first supported one
1585 if( aAvailableMissingValueTreatments
.getLength() )
1587 nResult
= aAvailableMissingValueTreatments
[0];
1594 DiagramPositioningMode
DiagramHelper::getDiagramPositioningMode( const uno::Reference
<
1595 chart2::XDiagram
> & xDiagram
)
1597 DiagramPositioningMode eMode
= DiagramPositioningMode_AUTO
;
1598 uno::Reference
< beans::XPropertySet
> xDiaProps( xDiagram
, uno::UNO_QUERY
);
1599 if( xDiaProps
.is() )
1601 RelativePosition aRelPos
;
1602 RelativeSize aRelSize
;
1603 if( (xDiaProps
->getPropertyValue("RelativePosition") >>= aRelPos
) &&
1604 (xDiaProps
->getPropertyValue("RelativeSize") >>= aRelSize
) )
1606 bool bPosSizeExcludeAxes
=false;
1607 xDiaProps
->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxes
;
1608 if( bPosSizeExcludeAxes
)
1609 eMode
= DiagramPositioningMode_EXCLUDING
;
1611 eMode
= DiagramPositioningMode_INCLUDING
;
1617 void lcl_ensureRange0to1( double& rValue
)
1625 bool DiagramHelper::setDiagramPositioning( const uno::Reference
< frame::XModel
>& xChartModel
,
1626 const awt::Rectangle
& rPosRect
/*100th mm*/ )
1628 ControllerLockGuard
aCtrlLockGuard( xChartModel
);
1630 bool bChanged
= false;
1631 awt::Size
aPageSize( ChartModelHelper::getPageSize(xChartModel
) );
1632 uno::Reference
< beans::XPropertySet
> xDiaProps( ChartModelHelper::findDiagram( xChartModel
), uno::UNO_QUERY
);
1633 if( !xDiaProps
.is() )
1636 RelativePosition aOldPos
;
1637 RelativeSize aOldSize
;
1638 xDiaProps
->getPropertyValue("RelativePosition" ) >>= aOldPos
;
1639 xDiaProps
->getPropertyValue("RelativeSize" ) >>= aOldSize
;
1641 RelativePosition aNewPos
;
1642 aNewPos
.Anchor
= drawing::Alignment_TOP_LEFT
;
1643 aNewPos
.Primary
= double(rPosRect
.X
)/double(aPageSize
.Width
);
1644 aNewPos
.Secondary
= double(rPosRect
.Y
)/double(aPageSize
.Height
);
1646 chart2::RelativeSize aNewSize
;
1647 aNewSize
.Primary
= double(rPosRect
.Width
)/double(aPageSize
.Width
);
1648 aNewSize
.Secondary
= double(rPosRect
.Height
)/double(aPageSize
.Height
);
1650 lcl_ensureRange0to1( aNewPos
.Primary
);
1651 lcl_ensureRange0to1( aNewPos
.Secondary
);
1652 lcl_ensureRange0to1( aNewSize
.Primary
);
1653 lcl_ensureRange0to1( aNewSize
.Secondary
);
1654 if( (aNewPos
.Primary
+ aNewSize
.Primary
) > 1.0 )
1655 aNewPos
.Primary
= 1.0 - aNewSize
.Primary
;
1656 if( (aNewPos
.Secondary
+ aNewSize
.Secondary
) > 1.0 )
1657 aNewPos
.Secondary
= 1.0 - aNewSize
.Secondary
;
1659 xDiaProps
->setPropertyValue( "RelativePosition", uno::makeAny(aNewPos
) );
1660 xDiaProps
->setPropertyValue( "RelativeSize", uno::makeAny(aNewSize
) );
1662 bChanged
= (aOldPos
.Anchor
!=aNewPos
.Anchor
) ||
1663 (aOldPos
.Primary
!=aNewPos
.Primary
) ||
1664 (aOldPos
.Secondary
!=aNewPos
.Secondary
) ||
1665 (aOldSize
.Primary
!=aNewSize
.Primary
) ||
1666 (aOldSize
.Secondary
!=aNewSize
.Secondary
);
1670 awt::Rectangle
DiagramHelper::getDiagramRectangleFromModel( const uno::Reference
< frame::XModel
>& xChartModel
)
1672 awt::Rectangle
aRet(-1,-1,-1,-1);
1674 uno::Reference
< beans::XPropertySet
> xDiaProps( ChartModelHelper::findDiagram( xChartModel
), uno::UNO_QUERY
);
1675 if( !xDiaProps
.is() )
1678 awt::Size
aPageSize( ChartModelHelper::getPageSize(xChartModel
) );
1680 RelativePosition aRelPos
;
1681 RelativeSize aRelSize
;
1682 xDiaProps
->getPropertyValue("RelativePosition" ) >>= aRelPos
;
1683 xDiaProps
->getPropertyValue("RelativeSize" ) >>= aRelSize
;
1686 static_cast< sal_Int32
>( aRelSize
.Primary
* aPageSize
.Width
),
1687 static_cast< sal_Int32
>( aRelSize
.Secondary
* aPageSize
.Height
));
1690 static_cast< sal_Int32
>( aRelPos
.Primary
* aPageSize
.Width
),
1691 static_cast< sal_Int32
>( aRelPos
.Secondary
* aPageSize
.Height
));
1693 awt::Point aAbsPosLeftTop
= RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( aAbsPos
, aAbsSize
, aRelPos
.Anchor
);
1695 aRet
= awt::Rectangle(aAbsPosLeftTop
.X
, aAbsPosLeftTop
.Y
, aAbsSize
.Width
, aAbsSize
.Height
);
1700 bool DiagramHelper::switchDiagramPositioningToExcludingPositioning(
1701 const uno::Reference
< frame::XModel
>& xChartModel
1702 , bool bResetModifiedState
, bool bConvertAlsoFromAutoPositioning
)
1704 //return true if something was changed
1705 const SvtSaveOptions::ODFDefaultVersion
nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1706 if( nCurrentODFVersion
> SvtSaveOptions::ODFVER_012
)
1708 uno::Reference
< ::com::sun::star::chart::XChartDocument
> xOldDoc( xChartModel
, uno::UNO_QUERY
) ;
1711 uno::Reference
< ::com::sun::star::chart::XDiagramPositioning
> xDiagramPositioning( xOldDoc
->getDiagram(), uno::UNO_QUERY
);
1712 if( xDiagramPositioning
.is() && ( bConvertAlsoFromAutoPositioning
|| !xDiagramPositioning
->isAutomaticDiagramPositioning() )
1713 && !xDiagramPositioning
->isExcludingDiagramPositioning() )
1715 ControllerLockGuard
aCtrlLockGuard( xChartModel
);
1716 uno::Reference
< util::XModifiable
> xModifiable( xChartModel
, uno::UNO_QUERY
);
1717 bool bModelWasModified
= xModifiable
.is() && xModifiable
->isModified();
1718 xDiagramPositioning
->setDiagramPositionExcludingAxes( xDiagramPositioning
->calculateDiagramPositionExcludingAxes() );
1719 if(bResetModifiedState
&& !bModelWasModified
&& xModifiable
.is() )
1720 xModifiable
->setModified(sal_False
);
1728 } // namespace chart
1730 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */