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"
35 #include <unonames.hxx>
37 #include <com/sun/star/chart/MissingValueTreatment.hpp>
38 #include <com/sun/star/chart/XChartDocument.hpp>
39 #include <com/sun/star/chart/XDiagramPositioning.hpp>
40 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
41 #include <com/sun/star/chart2/XTitled.hpp>
42 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
43 #include <com/sun/star/chart2/XChartTypeTemplate.hpp>
44 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
45 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
46 #include <com/sun/star/chart2/InterpretedData.hpp>
47 #include <com/sun/star/chart2/AxisType.hpp>
48 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
49 #include <com/sun/star/chart2/RelativePosition.hpp>
50 #include <com/sun/star/chart2/RelativeSize.hpp>
52 #include <com/sun/star/util/NumberFormat.hpp>
53 #include <com/sun/star/util/XModifiable.hpp>
54 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
56 #include <unotools/saveopt.hxx>
57 #include <rtl/math.hxx>
58 #include <svl/zformat.hxx>
59 #include <vcl/svapp.hxx>
60 #include <vcl/settings.hxx>
62 using namespace ::com::sun::star
;
63 using namespace ::com::sun::star::chart2
;
64 using namespace ::std
;
66 using ::com::sun::star::uno::Reference
;
67 using ::com::sun::star::uno::Sequence
;
68 using ::com::sun::star::uno::Any
;
69 using ::com::sun::star::chart2::XAnyDescriptionAccess
;
74 DiagramHelper::tTemplateWithServiceName
75 DiagramHelper::getTemplateForDiagram(
76 const Reference
< XDiagram
> & xDiagram
,
77 const Reference
< lang::XMultiServiceFactory
> & xChartTypeManager
,
78 const OUString
& rPreferredTemplateName
)
80 DiagramHelper::tTemplateWithServiceName aResult
;
82 if( ! (xChartTypeManager
.is() && xDiagram
.is()))
85 Sequence
< OUString
> aServiceNames( xChartTypeManager
->getAvailableServiceNames());
86 const sal_Int32 nLength
= aServiceNames
.getLength();
88 bool bHasPreferredTemplate
= !rPreferredTemplateName
.isEmpty();
89 bool bTemplateFound
= false;
91 if( bHasPreferredTemplate
)
93 Reference
< XChartTypeTemplate
> xTempl(
94 xChartTypeManager
->createInstance( rPreferredTemplateName
), uno::UNO_QUERY
);
97 xTempl
->matchesTemplate( xDiagram
, sal_True
))
99 aResult
.first
= xTempl
;
100 aResult
.second
= rPreferredTemplateName
;
101 bTemplateFound
= true;
105 for( sal_Int32 i
= 0; ! bTemplateFound
&& i
< nLength
; ++i
)
109 if( ! bHasPreferredTemplate
||
110 ! rPreferredTemplateName
.equals( aServiceNames
[ i
] ))
112 Reference
< XChartTypeTemplate
> xTempl(
113 xChartTypeManager
->createInstance( aServiceNames
[ i
] ), uno::UNO_QUERY_THROW
);
115 if (xTempl
.is() && xTempl
->matchesTemplate(xDiagram
, true))
117 aResult
.first
= xTempl
;
118 aResult
.second
= aServiceNames
[ i
];
119 bTemplateFound
= true;
123 catch( const uno::Exception
& ex
)
125 ASSERT_EXCEPTION( ex
);
132 void DiagramHelper::setVertical(
133 const Reference
< XDiagram
> & xDiagram
,
134 bool bVertical
/* = true */ )
138 Reference
< XCoordinateSystemContainer
> xCnt( xDiagram
, uno::UNO_QUERY
);
142 Sequence
< Reference
<XCoordinateSystem
> > aCooSys
= xCnt
->getCoordinateSystems();
144 aValue
<<= bVertical
;
145 for( sal_Int32 i
=0; i
<aCooSys
.getLength(); ++i
)
147 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSys
[i
] );
148 Reference
< beans::XPropertySet
> xProp( xCooSys
, uno::UNO_QUERY
);
149 bool bChanged
= false;
152 bool bOldSwap
= false;
153 if( !(xProp
->getPropertyValue("SwapXAndYAxis") >>= bOldSwap
)
154 || bVertical
!= bOldSwap
)
158 xProp
->setPropertyValue("SwapXAndYAxis", aValue
);
164 const sal_Int32 nDimensionCount
= xCooSys
->getDimension();
165 sal_Int32 nDimIndex
= 0;
166 for (nDimIndex
=0; nDimIndex
< nDimensionCount
; ++nDimIndex
)
168 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimIndex
);
169 for (sal_Int32 nI
= 0; nI
<= nMaximumScaleIndex
; ++nI
)
171 Reference
<chart2::XAxis
> xAxis
= xCooSys
->getAxisByDimension(nDimIndex
,nI
);
175 //adapt title rotation only when axis swapping has changed
179 Reference
< XTitled
> xTitled( xAxis
, uno::UNO_QUERY
);
183 Reference
< beans::XPropertySet
> xTitleProps( xTitled
->getTitleObject(), uno::UNO_QUERY
);
184 if (!xTitleProps
.is())
187 double fAngleDegree
= 0.0;
188 xTitleProps
->getPropertyValue("TextRotation") >>= fAngleDegree
;
189 if (!rtl::math::approxEqual(fAngleDegree
, 0.0) &&
190 !rtl::math::approxEqual(fAngleDegree
, 90.0))
193 double fNewAngleDegree
= 0.0;
194 if( !bVertical
&& nDimIndex
== 1 )
195 fNewAngleDegree
= 90.0;
196 else if( bVertical
&& nDimIndex
== 0 )
197 fNewAngleDegree
= 90.0;
199 xTitleProps
->setPropertyValue("TextRotation", uno::makeAny(fNewAngleDegree
));
204 catch( const uno::Exception
& ex
)
206 ASSERT_EXCEPTION( ex
);
210 bool DiagramHelper::getVertical( const uno::Reference
< chart2::XDiagram
> & xDiagram
,
211 bool& rbFound
, bool& rbAmbiguous
)
217 Reference
< XCoordinateSystemContainer
> xCnt( xDiagram
, uno::UNO_QUERY
);
221 Sequence
< Reference
<XCoordinateSystem
> > aCooSys
= xCnt
->getCoordinateSystems();
223 for (sal_Int32 i
= 0; i
< aCooSys
.getLength(); ++i
)
225 Reference
<beans::XPropertySet
> xProp(aCooSys
[i
], uno::UNO_QUERY
);
229 bool bCurrent
= false;
230 if (xProp
->getPropertyValue("SwapXAndYAxis") >>= bCurrent
)
237 else if (bCurrent
!= bValue
)
239 // ambiguous -> choose always first found
247 void DiagramHelper::setStackMode(
248 const Reference
< XDiagram
> & xDiagram
,
249 StackMode eStackMode
,
250 bool bOnlyAtFirstChartType
/* = true */
255 if( eStackMode
== StackMode_AMBIGUOUS
)
258 bool bValueFound
= false;
259 bool bIsAmbiguous
= false;
260 StackMode eOldStackMode
= DiagramHelper::getStackMode( xDiagram
, bValueFound
, bIsAmbiguous
);
262 if( eStackMode
== eOldStackMode
&& !bIsAmbiguous
)
265 StackingDirection eNewDirection
= StackingDirection_NO_STACKING
;
266 if( eStackMode
== StackMode_Y_STACKED
|| eStackMode
== StackMode_Y_STACKED_PERCENT
)
267 eNewDirection
= StackingDirection_Y_STACKING
;
268 else if( eStackMode
== StackMode_Z_STACKED
)
269 eNewDirection
= StackingDirection_Z_STACKING
;
271 uno::Any
aNewDirection( uno::makeAny(eNewDirection
) );
273 bool bPercent
= false;
274 if( eStackMode
== StackMode_Y_STACKED_PERCENT
)
277 //iterate through all coordinate systems
278 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
279 if( !xCooSysContainer
.is() )
281 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
282 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
284 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
285 //set correct percent stacking
286 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(1);
287 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
289 Reference
< chart2::XAxis
> xAxis( xCooSys
->getAxisByDimension( 1,nI
));
292 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
293 if( (aScaleData
.AxisType
==AxisType::PERCENT
) != bPercent
)
296 aScaleData
.AxisType
= AxisType::PERCENT
;
298 aScaleData
.AxisType
= AxisType::REALNUMBER
;
299 xAxis
->setScaleData( aScaleData
);
303 //iterate through all chart types in the current coordinate system
304 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
305 if( !xChartTypeContainer
.is() )
307 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
308 sal_Int32 nMax
= aChartTypeList
.getLength();
309 if( bOnlyAtFirstChartType
312 for( sal_Int32 nT
= 0; nT
< nMax
; ++nT
)
314 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
316 //iterate through all series in this chart type
317 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xChartType
, uno::UNO_QUERY
);
318 OSL_ASSERT( xDataSeriesContainer
.is());
319 if( !xDataSeriesContainer
.is() )
322 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
323 for( sal_Int32 nS
= 0; nS
< aSeriesList
.getLength(); ++nS
)
325 Reference
< beans::XPropertySet
> xProp( aSeriesList
[nS
], uno::UNO_QUERY
);
327 xProp
->setPropertyValue( "StackingDirection", aNewDirection
);
332 catch( const uno::Exception
& ex
)
334 ASSERT_EXCEPTION( ex
);
338 StackMode
DiagramHelper::getStackMode( const Reference
< XDiagram
> & xDiagram
, bool& rbFound
, bool& rbAmbiguous
)
343 StackMode eGlobalStackMode
= StackMode_NONE
;
345 //iterate through all coordinate systems
346 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
347 if( !xCooSysContainer
.is() )
348 return eGlobalStackMode
;
349 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
350 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
352 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
354 //iterate through all chart types in the current coordinate system
355 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
356 if( !xChartTypeContainer
.is() )
358 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
359 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
361 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
363 StackMode eLocalStackMode
= DiagramHelper::getStackModeFromChartType(
364 xChartType
, rbFound
, rbAmbiguous
, xCooSys
);
366 if( rbFound
&& eLocalStackMode
!= eGlobalStackMode
&& nT
>0 )
369 return eGlobalStackMode
;
372 eGlobalStackMode
= eLocalStackMode
;
376 return eGlobalStackMode
;
379 StackMode
DiagramHelper::getStackModeFromChartType(
380 const Reference
< XChartType
> & xChartType
,
381 bool& rbFound
, bool& rbAmbiguous
,
382 const Reference
< XCoordinateSystem
> & xCorrespondingCoordinateSystem
)
384 StackMode eStackMode
= StackMode_NONE
;
390 Reference
< XDataSeriesContainer
> xDSCnt( xChartType
, uno::UNO_QUERY_THROW
);
391 Sequence
< Reference
< chart2::XDataSeries
> > aSeries( xDSCnt
->getDataSeries());
393 chart2::StackingDirection eCommonDirection
= chart2::StackingDirection_NO_STACKING
;
394 bool bDirectionInitialized
= false;
396 // first series is irrelvant for stacking, start with second, unless
397 // there is only one series
398 const sal_Int32 nSeriesCount
= aSeries
.getLength();
399 sal_Int32 i
= (nSeriesCount
== 1) ? 0: 1;
400 for( ; i
<nSeriesCount
; ++i
)
403 Reference
< beans::XPropertySet
> xProp( aSeries
[i
], uno::UNO_QUERY_THROW
);
404 chart2::StackingDirection eCurrentDirection
= eCommonDirection
;
405 // property is not MAYBEVOID
406 bool bSuccess
= ( xProp
->getPropertyValue( "StackingDirection" ) >>= eCurrentDirection
);
407 OSL_ASSERT( bSuccess
);
408 (void)(bSuccess
); // avoid warning in non-debug builds
409 if( ! bDirectionInitialized
)
411 eCommonDirection
= eCurrentDirection
;
412 bDirectionInitialized
= true;
416 if( eCommonDirection
!= eCurrentDirection
)
426 if( eCommonDirection
== chart2::StackingDirection_Z_STACKING
)
427 eStackMode
= StackMode_Z_STACKED
;
428 else if( eCommonDirection
== chart2::StackingDirection_Y_STACKING
)
430 eStackMode
= StackMode_Y_STACKED
;
433 if( xCorrespondingCoordinateSystem
.is() )
435 if( 1 < xCorrespondingCoordinateSystem
->getDimension() )
437 sal_Int32 nAxisIndex
= 0;
439 nAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(aSeries
[0]);
441 Reference
< chart2::XAxis
> xAxis(
442 xCorrespondingCoordinateSystem
->getAxisByDimension( 1,nAxisIndex
));
445 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
446 if( aScaleData
.AxisType
==chart2::AxisType::PERCENT
)
447 eStackMode
= StackMode_Y_STACKED_PERCENT
;
454 catch( const uno::Exception
& ex
)
456 ASSERT_EXCEPTION( ex
);
462 sal_Int32
DiagramHelper::getDimension( const Reference
< XDiagram
> & xDiagram
)
465 sal_Int32 nResult
= -1;
469 Reference
< XCoordinateSystemContainer
> xCooSysCnt( xDiagram
, uno::UNO_QUERY
);
470 if( xCooSysCnt
.is() )
472 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
473 xCooSysCnt
->getCoordinateSystems());
475 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
477 Reference
< XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
480 nResult
= xCooSys
->getDimension();
486 catch( const uno::Exception
& ex
)
488 ASSERT_EXCEPTION( ex
);
494 void DiagramHelper::setDimension(
495 const Reference
< XDiagram
> & xDiagram
,
496 sal_Int32 nNewDimensionCount
)
501 if( DiagramHelper::getDimension( xDiagram
) == nNewDimensionCount
)
506 bool rbFound
= false;
507 bool rbAmbiguous
= true;
508 StackMode eStackMode
= DiagramHelper::getStackMode( xDiagram
, rbFound
, rbAmbiguous
);
509 bool bIsSupportingOnlyDeepStackingFor3D
=false;
511 //change all coordinate systems:
512 Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY_THROW
);
513 Sequence
< Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
514 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
516 Reference
< XCoordinateSystem
> xOldCooSys( aCooSysList
[nCS
], uno::UNO_QUERY
);
517 Reference
< XCoordinateSystem
> xNewCooSys
;
519 Reference
< XChartTypeContainer
> xChartTypeContainer( xOldCooSys
, uno::UNO_QUERY
);
520 if( !xChartTypeContainer
.is() )
523 Sequence
< Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
524 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
526 Reference
< XChartType
> xChartType( aChartTypeList
[nT
], uno::UNO_QUERY
);
527 bIsSupportingOnlyDeepStackingFor3D
= ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType
);
530 xNewCooSys
= xChartType
->createCoordinateSystem( nNewDimensionCount
);
533 //@todo make sure that all following charttypes are also capable of the new dimension
534 //otherwise separate them in a different group
535 //BM: might be done in replaceCoordinateSystem()
538 // replace the old coordinate system at all places where it was used
539 DiagramHelper::replaceCoordinateSystem( xDiagram
, xOldCooSys
, xNewCooSys
);
542 //correct stack mode if necessary
543 if( nNewDimensionCount
==3 && eStackMode
!= StackMode_Z_STACKED
&& bIsSupportingOnlyDeepStackingFor3D
)
544 DiagramHelper::setStackMode( xDiagram
, StackMode_Z_STACKED
);
545 else if( nNewDimensionCount
==2 && eStackMode
== StackMode_Z_STACKED
)
546 DiagramHelper::setStackMode( xDiagram
, StackMode_NONE
);
548 catch( const uno::Exception
& ex
)
550 ASSERT_EXCEPTION( ex
);
554 void DiagramHelper::replaceCoordinateSystem(
555 const Reference
< XDiagram
> & xDiagram
,
556 const Reference
< XCoordinateSystem
> & xCooSysToReplace
,
557 const Reference
< XCoordinateSystem
> & xReplacement
)
559 OSL_ASSERT( xDiagram
.is());
563 // update the coordinate-system container
564 Reference
< XCoordinateSystemContainer
> xCont( xDiagram
, uno::UNO_QUERY
);
569 Reference
< chart2::data::XLabeledDataSequence
> xCategories
= DiagramHelper::getCategoriesFromDiagram( xDiagram
);
571 // move chart types of xCooSysToReplace to xReplacement
572 Reference
< XChartTypeContainer
> xCTCntCooSys( xCooSysToReplace
, uno::UNO_QUERY_THROW
);
573 Reference
< XChartTypeContainer
> xCTCntReplacement( xReplacement
, uno::UNO_QUERY_THROW
);
574 xCTCntReplacement
->setChartTypes( xCTCntCooSys
->getChartTypes());
576 xCont
->removeCoordinateSystem( xCooSysToReplace
);
577 xCont
->addCoordinateSystem( xReplacement
);
579 if( xCategories
.is() )
580 DiagramHelper::setCategoriesToDiagram( xCategories
, xDiagram
);
582 catch( const uno::Exception
& ex
)
584 ASSERT_EXCEPTION( ex
);
589 bool DiagramHelper::isSeriesAttachedToMainAxis(
590 const uno::Reference
< chart2::XDataSeries
>& xDataSeries
)
592 sal_Int32 nAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(xDataSeries
);
593 return (nAxisIndex
==0);
596 bool DiagramHelper::attachSeriesToAxis( bool bAttachToMainAxis
597 , const uno::Reference
< chart2::XDataSeries
>& xDataSeries
598 , const uno::Reference
< chart2::XDiagram
>& xDiagram
599 , const uno::Reference
< uno::XComponentContext
> & xContext
602 bool bChanged
= false;
604 //set property at axis
605 Reference
< beans::XPropertySet
> xProp( xDataSeries
, uno::UNO_QUERY_THROW
);
609 sal_Int32 nNewAxisIndex
= bAttachToMainAxis
? 0 : 1;
610 sal_Int32 nOldAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(xDataSeries
);
611 uno::Reference
< chart2::XAxis
> xOldAxis( DiagramHelper::getAttachedAxis( xDataSeries
, xDiagram
) );
613 if( nOldAxisIndex
!= nNewAxisIndex
)
617 xProp
->setPropertyValue( "AttachedAxisIndex", uno::makeAny( nNewAxisIndex
) );
620 catch( const uno::Exception
& ex
)
622 ASSERT_EXCEPTION( ex
);
626 if( bChanged
&& xDiagram
.is() )
628 uno::Reference
< XAxis
> xAxis( AxisHelper::getAxis( 1, bAttachToMainAxis
, xDiagram
) );
629 if(!xAxis
.is()) //create an axis if necessary
630 xAxis
= AxisHelper::createAxis( 1, bAttachToMainAxis
, xDiagram
, xContext
);
633 AxisHelper::makeAxisVisible( xAxis
);
634 AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis
, xDiagram
);
641 uno::Reference
< XAxis
> DiagramHelper::getAttachedAxis(
642 const uno::Reference
< XDataSeries
>& xSeries
,
643 const uno::Reference
< XDiagram
>& xDiagram
)
645 return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries
), xDiagram
);
648 uno::Reference
< XChartType
> DiagramHelper::getChartTypeOfSeries(
649 const uno::Reference
< chart2::XDiagram
>& xDiagram
650 , const uno::Reference
< XDataSeries
>& xGivenDataSeries
)
652 if( !xGivenDataSeries
.is() )
657 //iterate through the model to find the given xSeries
658 //the found parent indicates the charttype
660 //iterate through all coordinate systems
661 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
662 if( !xCooSysContainer
.is())
665 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
666 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
668 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
670 //iterate through all chart types in the current coordinate system
671 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
672 OSL_ASSERT( xChartTypeContainer
.is());
673 if( !xChartTypeContainer
.is() )
675 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
676 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
678 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
680 //iterate through all series in this chart type
681 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xChartType
, uno::UNO_QUERY
);
682 OSL_ASSERT( xDataSeriesContainer
.is());
683 if( !xDataSeriesContainer
.is() )
686 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
687 for( sal_Int32 nS
= 0; nS
< aSeriesList
.getLength(); ++nS
)
689 if( xGivenDataSeries
==aSeriesList
[nS
] )
697 ::std::vector
< Reference
< XDataSeries
> >
698 DiagramHelper::getDataSeriesFromDiagram(
699 const Reference
< XDiagram
> & xDiagram
)
701 ::std::vector
< Reference
< XDataSeries
> > aResult
;
705 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
706 xDiagram
, uno::UNO_QUERY_THROW
);
707 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
708 xCooSysCnt
->getCoordinateSystems());
709 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
711 Reference
< XChartTypeContainer
> xCTCnt( aCooSysSeq
[i
], uno::UNO_QUERY_THROW
);
712 Sequence
< Reference
< XChartType
> > aChartTypeSeq( xCTCnt
->getChartTypes());
713 for( sal_Int32 j
=0; j
<aChartTypeSeq
.getLength(); ++j
)
715 Reference
< XDataSeriesContainer
> xDSCnt( aChartTypeSeq
[j
], uno::UNO_QUERY_THROW
);
716 Sequence
< Reference
< XDataSeries
> > aSeriesSeq( xDSCnt
->getDataSeries() );
717 ::std::copy( aSeriesSeq
.getConstArray(), aSeriesSeq
.getConstArray() + aSeriesSeq
.getLength(),
718 ::std::back_inserter( aResult
));
722 catch( const uno::Exception
& ex
)
724 ASSERT_EXCEPTION( ex
);
730 Sequence
< Sequence
< Reference
< XDataSeries
> > >
731 DiagramHelper::getDataSeriesGroups( const Reference
< XDiagram
> & xDiagram
)
733 vector
< Sequence
< Reference
< XDataSeries
> > > aResult
;
735 //iterate through all coordinate systems
736 Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
737 if( xCooSysContainer
.is() )
739 Sequence
< Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
740 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
742 //iterate through all chart types in the current coordinate system
743 Reference
< XChartTypeContainer
> xChartTypeContainer( aCooSysList
[nCS
], uno::UNO_QUERY
);
744 if( !xChartTypeContainer
.is() )
746 Sequence
< Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
747 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
749 Reference
< XDataSeriesContainer
> xDataSeriesContainer( aChartTypeList
[nT
], uno::UNO_QUERY
);
750 if( !xDataSeriesContainer
.is() )
752 aResult
.push_back( xDataSeriesContainer
->getDataSeries() );
756 return ContainerHelper::ContainerToSequence( aResult
);
759 Reference
< XChartType
>
760 DiagramHelper::getChartTypeByIndex( const Reference
< XDiagram
>& xDiagram
, sal_Int32 nIndex
)
762 Reference
< XChartType
> xChartType
;
764 //iterate through all coordinate systems
765 Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
766 if( ! xCooSysContainer
.is())
769 Sequence
< Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
770 sal_Int32 nTypesSoFar
= 0;
771 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
773 Reference
< XChartTypeContainer
> xChartTypeContainer( aCooSysList
[nCS
], uno::UNO_QUERY
);
774 if( !xChartTypeContainer
.is() )
776 Sequence
< Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
777 if( nIndex
>= 0 && nIndex
< (nTypesSoFar
+ aChartTypeList
.getLength()) )
779 xChartType
.set( aChartTypeList
[nIndex
- nTypesSoFar
] );
782 nTypesSoFar
+= aChartTypeList
.getLength();
791 std::vector
< Reference
< XAxis
> > lcl_getAxisHoldingCategoriesFromDiagram(
792 const Reference
< XDiagram
> & xDiagram
)
794 std::vector
< Reference
< XAxis
> > aRet
;
796 Reference
< XAxis
> xResult
;
797 // return first x-axis as fall-back
798 Reference
< XAxis
> xFallBack
;
801 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
802 xDiagram
, uno::UNO_QUERY_THROW
);
803 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
804 xCooSysCnt
->getCoordinateSystems());
805 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
807 Reference
< XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
808 OSL_ASSERT( xCooSys
.is());
809 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
811 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
812 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
814 Reference
< XAxis
> xAxis
= xCooSys
->getAxisByDimension( nN
,nI
);
815 OSL_ASSERT( xAxis
.is());
818 ScaleData aScaleData
= xAxis
->getScaleData();
819 if( aScaleData
.Categories
.is() || (aScaleData
.AxisType
== AxisType::CATEGORY
) )
821 aRet
.push_back(xAxis
);
823 if( (nN
== 0) && !xFallBack
.is())
824 xFallBack
.set( xAxis
);
830 catch( const uno::Exception
& ex
)
832 ASSERT_EXCEPTION( ex
);
836 aRet
.push_back(xFallBack
);
841 } // anonymous namespace
843 bool DiagramHelper::isCategoryDiagram(
844 const Reference
< XDiagram
>& xDiagram
)
848 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
849 xDiagram
, uno::UNO_QUERY_THROW
);
850 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
851 xCooSysCnt
->getCoordinateSystems());
852 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
854 Reference
< XCoordinateSystem
> xCooSys( aCooSysSeq
[i
] );
855 OSL_ASSERT( xCooSys
.is());
856 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
858 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
859 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
861 Reference
< XAxis
> xAxis
= xCooSys
->getAxisByDimension( nN
,nI
);
862 OSL_ASSERT( xAxis
.is());
865 ScaleData aScaleData
= xAxis
->getScaleData();
866 if( aScaleData
.AxisType
== AxisType::CATEGORY
|| aScaleData
.AxisType
== AxisType::DATE
)
873 catch( const uno::Exception
& ex
)
875 ASSERT_EXCEPTION( ex
);
881 void DiagramHelper::setCategoriesToDiagram(
882 const Reference
< chart2::data::XLabeledDataSequence
>& xCategories
,
883 const Reference
< XDiagram
>& xDiagram
,
884 bool bSetAxisType
/* = false */,
885 bool bCategoryAxis
/* = true */ )
887 std::vector
< Reference
< chart2::XAxis
> > aCatAxes(
888 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram
));
890 std::vector
< Reference
< chart2::XAxis
> >::iterator
aIt( aCatAxes
.begin() );
891 std::vector
< Reference
< chart2::XAxis
> >::const_iterator
aEnd( aCatAxes
.end() );
893 for( aIt
= aCatAxes
.begin(); aIt
!= aEnd
; ++aIt
)
895 Reference
< chart2::XAxis
> xCatAxis(*aIt
);
898 ScaleData
aScaleData( xCatAxis
->getScaleData());
899 aScaleData
.Categories
= xCategories
;
903 aScaleData
.AxisType
= AxisType::CATEGORY
;
904 else if( aScaleData
.AxisType
== AxisType::CATEGORY
|| aScaleData
.AxisType
== AxisType::DATE
)
905 aScaleData
.AxisType
= AxisType::REALNUMBER
;
907 xCatAxis
->setScaleData( aScaleData
);
912 Reference
< data::XLabeledDataSequence
>
913 DiagramHelper::getCategoriesFromDiagram(
914 const Reference
< XDiagram
> & xDiagram
)
916 Reference
< data::XLabeledDataSequence
> xResult
;
920 std::vector
< Reference
< chart2::XAxis
> > aCatAxes(
921 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram
));
922 std::vector
< Reference
< chart2::XAxis
> >::iterator
aIt( aCatAxes
.begin() );
923 std::vector
< Reference
< chart2::XAxis
> >::const_iterator
aEnd( aCatAxes
.end() );
924 //search for first categories
927 Reference
< chart2::XAxis
> xCatAxis(*aIt
);
930 ScaleData
aScaleData( xCatAxis
->getScaleData());
931 if( aScaleData
.Categories
.is() )
933 xResult
.set( aScaleData
.Categories
);
934 uno::Reference
<beans::XPropertySet
> xProp(aScaleData
.Categories
->getValues(), uno::UNO_QUERY
);
939 xProp
->setPropertyValue( "Role", uno::makeAny( OUString("categories") ) );
941 catch( const uno::Exception
& ex
)
943 ASSERT_EXCEPTION( ex
);
950 catch( const uno::Exception
& ex
)
952 ASSERT_EXCEPTION( ex
);
958 void lcl_generateAutomaticCategoriesFromChartType(
959 Sequence
< OUString
>& rRet
,
960 const Reference
< XChartType
>& xChartType
)
964 OUString
aMainSeq( xChartType
->getRoleOfSequenceForSeriesLabel() );
965 Reference
< XDataSeriesContainer
> xSeriesCnt( xChartType
, uno::UNO_QUERY
);
966 if( xSeriesCnt
.is() )
968 Sequence
< Reference
< XDataSeries
> > aSeriesSeq( xSeriesCnt
->getDataSeries() );
969 for( sal_Int32 nS
= 0; nS
< aSeriesSeq
.getLength(); nS
++ )
971 Reference
< data::XDataSource
> xDataSource( aSeriesSeq
[nS
], uno::UNO_QUERY
);
972 if( !xDataSource
.is() )
974 Reference
< chart2::data::XLabeledDataSequence
> xLabeledSeq(
975 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aMainSeq
));
976 if( !xLabeledSeq
.is() )
978 Reference
< chart2::data::XDataSequence
> xValueSeq( xLabeledSeq
->getValues() );
979 if( !xValueSeq
.is() )
981 rRet
= xValueSeq
->generateLabel( chart2::data::LabelOrigin_LONG_SIDE
);
982 if( rRet
.getLength() )
988 Sequence
< OUString
> DiagramHelper::generateAutomaticCategoriesFromCooSys( const Reference
< XCoordinateSystem
> & xCooSys
)
990 Sequence
< OUString
> aRet
;
992 Reference
< XChartTypeContainer
> xTypeCntr( xCooSys
, uno::UNO_QUERY
);
995 Sequence
< Reference
< XChartType
> > aChartTypes( xTypeCntr
->getChartTypes() );
996 for( sal_Int32 nN
=0; nN
<aChartTypes
.getLength(); nN
++ )
998 lcl_generateAutomaticCategoriesFromChartType( aRet
, aChartTypes
[nN
] );
999 if( aRet
.getLength() )
1006 Sequence
< OUString
> DiagramHelper::getExplicitSimpleCategories(
1007 ChartModel
& rModel
)
1009 uno::Reference
< chart2::XCoordinateSystem
> xCooSys( ChartModelHelper::getFirstCoordinateSystem( rModel
) );
1010 ExplicitCategoriesProvider
aExplicitCategoriesProvider( xCooSys
, rModel
);
1011 return aExplicitCategoriesProvider
.getSimpleCategories();
1016 void lcl_switchToDateCategories( const Reference
< XChartDocument
>& xChartDoc
, const Reference
< XAxis
>& xAxis
)
1020 if( !xChartDoc
.is() )
1023 ScaleData
aScale( xAxis
->getScaleData() );
1024 if( xChartDoc
->hasInternalDataProvider() )
1026 //remove all content the is not of type double and remove multiple level
1027 Reference
< XAnyDescriptionAccess
> xDataAccess( xChartDoc
->getDataProvider(), uno::UNO_QUERY
);
1028 if( xDataAccess
.is() )
1030 Sequence
< Sequence
< Any
> > aAnyCategories( xDataAccess
->getAnyRowDescriptions() );
1033 ::rtl::math::setNan( & fNan
);
1034 sal_Int32 nN
= aAnyCategories
.getLength();
1037 Sequence
< Any
>& rCat
= aAnyCategories
[nN
];
1038 if( rCat
.getLength() > 1 )
1040 if( rCat
.getLength() == 1 )
1042 Any
& rAny
= rCat
[0];
1043 if( !(rAny
>>=fTest
) )
1045 rAny
= uno::makeAny(fNan
);
1049 xDataAccess
->setAnyRowDescriptions( aAnyCategories
);
1051 //check the numberformat at the axis
1052 Reference
< beans::XPropertySet
> xAxisProps( xAxis
, uno::UNO_QUERY
);
1053 Reference
< util::XNumberFormatsSupplier
> xNumberFormatsSupplier( xChartDoc
, uno::UNO_QUERY
);
1054 if( xAxisProps
.is() && xNumberFormatsSupplier
.is() )
1056 sal_Int32 nNumberFormat
= -1;
1057 xAxisProps
->getPropertyValue(CHART_UNONAME_NUMFMT
) >>= nNumberFormat
;
1059 Reference
< util::XNumberFormats
> xNumberFormats
= Reference
< util::XNumberFormats
>( xNumberFormatsSupplier
->getNumberFormats() );
1060 if( xNumberFormats
.is() )
1062 Reference
< beans::XPropertySet
> xKeyProps
;
1065 xKeyProps
= xNumberFormats
->getByKey( nNumberFormat
);
1067 catch( const uno::Exception
& ex
)
1069 ASSERT_EXCEPTION( ex
);
1071 sal_Int32 nType
= util::NumberFormat::UNDEFINED
;
1072 if( xKeyProps
.is() )
1073 xKeyProps
->getPropertyValue( "Type" ) >>= nType
;
1074 if( !( nType
& util::NumberFormat::DATE
) )
1076 //set a date format to the axis
1077 bool bCreate
= true;
1078 const LocaleDataWrapper
& rLocaleDataWrapper
= Application::GetSettings().GetLocaleDataWrapper();
1079 Sequence
<sal_Int32
> aKeySeq
= xNumberFormats
->queryKeys( util::NumberFormat::DATE
, rLocaleDataWrapper
.getLanguageTag().getLocale(), bCreate
);
1080 if( aKeySeq
.getLength() )
1082 xAxisProps
->setPropertyValue(CHART_UNONAME_NUMFMT
, uno::makeAny(aKeySeq
[0]));
1088 if( aScale
.AxisType
!= chart2::AxisType::DATE
)
1089 AxisHelper::removeExplicitScaling( aScale
);
1090 aScale
.AxisType
= chart2::AxisType::DATE
;
1091 xAxis
->setScaleData( aScale
);
1094 void lcl_switchToTextCategories( const Reference
< XChartDocument
>& xChartDoc
, const Reference
< XAxis
>& xAxis
)
1098 if( !xChartDoc
.is() )
1100 ScaleData
aScale( xAxis
->getScaleData() );
1101 if( aScale
.AxisType
!= chart2::AxisType::CATEGORY
)
1102 AxisHelper::removeExplicitScaling( aScale
);
1103 //todo migrate dates to text?
1104 aScale
.AxisType
= chart2::AxisType::CATEGORY
;
1105 aScale
.AutoDateAxis
= false;
1106 xAxis
->setScaleData( aScale
);
1111 void DiagramHelper::switchToDateCategories( const Reference
< XChartDocument
>& xChartDoc
)
1113 Reference
< frame::XModel
> xChartModel( xChartDoc
, uno::UNO_QUERY
);
1114 if(xChartModel
.is())
1116 ControllerLockGuardUNO
aCtrlLockGuard( xChartModel
);
1118 Reference
< chart2::XCoordinateSystem
> xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel
) );
1121 Reference
< XAxis
> xAxis( xCooSys
->getAxisByDimension(0,0) );
1122 lcl_switchToDateCategories( xChartDoc
, xAxis
);
1127 void DiagramHelper::switchToTextCategories( const Reference
< XChartDocument
>& xChartDoc
)
1129 Reference
< frame::XModel
> xChartModel( xChartDoc
, uno::UNO_QUERY
);
1130 if(xChartModel
.is())
1132 ControllerLockGuardUNO
aCtrlLockGuard( xChartModel
);
1134 Reference
< chart2::XCoordinateSystem
> xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel
) );
1137 Reference
< XAxis
> xAxis( xCooSys
->getAxisByDimension(0,0) );
1138 lcl_switchToTextCategories( xChartDoc
, xAxis
);
1143 bool DiagramHelper::isSupportingDateAxis( const Reference
< chart2::XDiagram
>& xDiagram
)
1145 return ::chart::ChartTypeHelper::isSupportingDateAxis(
1146 DiagramHelper::getChartTypeByIndex( xDiagram
, 0 ), DiagramHelper::getDimension( xDiagram
), 0 );
1149 bool DiagramHelper::isDateNumberFormat( sal_Int32 nNumberFormat
, const Reference
< util::XNumberFormats
>& xNumberFormats
)
1151 bool bIsDate
= false;
1152 if( !xNumberFormats
.is() )
1155 Reference
< beans::XPropertySet
> xKeyProps
= xNumberFormats
->getByKey( nNumberFormat
);
1156 if( xKeyProps
.is() )
1158 sal_Int32 nType
= util::NumberFormat::UNDEFINED
;
1159 xKeyProps
->getPropertyValue( "Type" ) >>= nType
;
1160 bIsDate
= nType
& util::NumberFormat::DATE
;
1165 sal_Int32
DiagramHelper::getDateNumberFormat( const Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
)
1168 Reference
< util::XNumberFormats
> xNumberFormats( xNumberFormatsSupplier
->getNumberFormats() );
1169 if( xNumberFormats
.is() )
1171 bool bCreate
= true;
1172 const LocaleDataWrapper
& rLocaleDataWrapper
= Application::GetSettings().GetLocaleDataWrapper();
1173 Sequence
<sal_Int32
> aKeySeq
= xNumberFormats
->queryKeys( util::NumberFormat::DATE
,
1174 rLocaleDataWrapper
.getLanguageTag().getLocale(), bCreate
);
1175 if( aKeySeq
.getLength() )
1181 //try to get a date format with full year display
1182 NumberFormatterWrapper
aNumberFormatterWrapper( xNumberFormatsSupplier
);
1183 SvNumberFormatter
* pNumFormatter
= aNumberFormatterWrapper
.getSvNumberFormatter();
1186 const SvNumberformat
* pFormat
= pNumFormatter
->GetEntry( nRet
);
1188 nRet
= pNumFormatter
->GetFormatIndex( NF_DATE_SYS_DDMMYYYY
, pFormat
->GetLanguage() );
1193 sal_Int32
DiagramHelper::getDateTimeInputNumberFormat( const Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
, double fNumber
)
1197 // Get the most detailed date/time format according to fNumber.
1198 NumberFormatterWrapper
aNumberFormatterWrapper( xNumberFormatsSupplier
);
1199 SvNumberFormatter
* pNumFormatter
= aNumberFormatterWrapper
.getSvNumberFormatter();
1201 SAL_WARN("chart2", "DiagramHelper::getDateTimeInputNumberFormat - no SvNumberFormatter");
1204 // Categorize the format according to the implementation of
1205 // SvNumberFormatter::GetEditFormat(), making assumptions about what
1206 // would be time only.
1207 /* TODO: implement a method at SvNumberFormatter that does this and
1208 * call instead, if Chart isn't able transport the proper format of the
1209 * Axis, which of course would be much better.. */
1211 if (0.0 <= fNumber
&& fNumber
< 1.0)
1214 nType
= util::NumberFormat::TIME
;
1215 nRet
= pNumFormatter
->GetFormatIndex( NF_TIME_HHMM
, LANGUAGE_SYSTEM
);
1217 else if (fabs( fNumber
) * 24 < 0x7fff)
1219 // Assuming time within 32k hours or 3.7 years.
1220 nType
= util::NumberFormat::TIME
;
1221 nRet
= pNumFormatter
->GetFormatIndex( NF_TIME_HH_MMSS
, LANGUAGE_SYSTEM
);
1223 else if (rtl::math::approxFloor( fNumber
) != fNumber
)
1226 nType
= util::NumberFormat::DATETIME
;
1227 nRet
= pNumFormatter
->GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS
, LANGUAGE_SYSTEM
);
1232 nType
= util::NumberFormat::DATE
;
1233 nRet
= pNumFormatter
->GetFormatIndex( NF_DATE_SYS_DDMMYYYY
, LANGUAGE_SYSTEM
);
1236 // Obtain the corresponding edit format.
1237 nRet
= pNumFormatter
->GetEditFormat( fNumber
, nRet
, nType
, LANGUAGE_SYSTEM
, NULL
);
1242 sal_Int32
DiagramHelper::getPercentNumberFormat( const Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
)
1245 Reference
< util::XNumberFormats
> xNumberFormats( xNumberFormatsSupplier
->getNumberFormats() );
1246 if( xNumberFormats
.is() )
1248 bool bCreate
= true;
1249 const LocaleDataWrapper
& rLocaleDataWrapper
= Application::GetSettings().GetLocaleDataWrapper();
1250 Sequence
<sal_Int32
> aKeySeq
= xNumberFormats
->queryKeys( util::NumberFormat::PERCENT
,
1251 rLocaleDataWrapper
.getLanguageTag().getLocale(), bCreate
);
1252 if( aKeySeq
.getLength() )
1260 Sequence
< Reference
< XChartType
> >
1261 DiagramHelper::getChartTypesFromDiagram(
1262 const Reference
< XDiagram
> & xDiagram
)
1264 ::std::vector
< Reference
< XChartType
> > aResult
;
1270 Reference
< XCoordinateSystemContainer
> xCooSysCnt(
1271 xDiagram
, uno::UNO_QUERY_THROW
);
1272 Sequence
< Reference
< XCoordinateSystem
> > aCooSysSeq(
1273 xCooSysCnt
->getCoordinateSystems());
1274 for( sal_Int32 i
=0; i
<aCooSysSeq
.getLength(); ++i
)
1276 Reference
< XChartTypeContainer
> xCTCnt( aCooSysSeq
[i
], uno::UNO_QUERY_THROW
);
1277 Sequence
< Reference
< XChartType
> > aChartTypeSeq( xCTCnt
->getChartTypes());
1278 ::std::copy( aChartTypeSeq
.getConstArray(),
1279 aChartTypeSeq
.getConstArray() + aChartTypeSeq
.getLength(),
1280 ::std::back_inserter( aResult
));
1283 catch( const uno::Exception
& ex
)
1285 ASSERT_EXCEPTION( ex
);
1289 return ContainerHelper::ContainerToSequence( aResult
);
1292 bool DiagramHelper::areChartTypesCompatible( const Reference
< ::chart2::XChartType
>& xFirstType
,
1293 const Reference
< ::chart2::XChartType
>& xSecondType
)
1295 if( !xFirstType
.is() || !xSecondType
.is() )
1298 ::std::vector
< OUString
> aFirstRoles( ContainerHelper::SequenceToVector( xFirstType
->getSupportedMandatoryRoles() ) );
1299 ::std::vector
< OUString
> aSecondRoles( ContainerHelper::SequenceToVector( xSecondType
->getSupportedMandatoryRoles() ) );
1300 ::std::sort( aFirstRoles
.begin(), aFirstRoles
.end() );
1301 ::std::sort( aSecondRoles
.begin(), aSecondRoles
.end() );
1302 return ( aFirstRoles
== aSecondRoles
);
1308 * This method implements the logic of checking if a series can be moved
1309 * forward/backward. Depending on the "bDoMove" parameter the series will
1310 * be moved (bDoMove = true) or the function just will test if the
1311 * series can be moved without doing the move (bDoMove = false).
1314 * Reference to the diagram that contains the series.
1316 * @param xGivenDataSeries
1317 * Reference to the series that should moved or tested for moving.
1320 * Direction in which the series should be moved or tested for moving.
1323 * Should this function really move the series (true) or just test if it is
1328 * in case of bDoMove == true
1329 * - True : if the move was done
1330 * - False : the move failed
1331 * in case of bDoMove == false
1332 * - True : the series can be moved
1333 * - False : the series can not be moved
1337 bool lcl_moveSeriesOrCheckIfMoveIsAllowed(
1338 const Reference
< XDiagram
>& xDiagram
,
1339 const Reference
< XDataSeries
>& xGivenDataSeries
,
1343 bool bMovedOrMoveAllowed
= false;
1347 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
1349 if( xGivenDataSeries
.is() && xCooSysContainer
.is() )
1351 //find position of series.
1352 bool bFound
= false;
1353 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
1355 for( sal_Int32 nCS
= 0; !bFound
&& nCS
< aCooSysList
.getLength(); ++nCS
)
1357 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
1359 //iterate through all chart types in the current coordinate system
1360 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
1361 OSL_ASSERT( xChartTypeContainer
.is());
1362 if( !xChartTypeContainer
.is() )
1364 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
1365 uno::Reference
< XChartType
> xFormerChartType
;
1367 for( sal_Int32 nT
= 0; !bFound
&& nT
< aChartTypeList
.getLength(); ++nT
)
1369 uno::Reference
< XChartType
> xCurrentChartType( aChartTypeList
[nT
] );
1371 //iterate through all series in this chart type
1372 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xCurrentChartType
, uno::UNO_QUERY
);
1373 OSL_ASSERT( xDataSeriesContainer
.is());
1374 if( !xDataSeriesContainer
.is() )
1377 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
1379 for( sal_Int32 nS
= 0; !bFound
&& nS
< aSeriesList
.getLength(); ++nS
)
1382 // We found the series we are interrested in !
1383 if( xGivenDataSeries
==aSeriesList
[nS
] )
1385 sal_Int32 nOldSeriesIndex
= nS
;
1390 sal_Int32 nNewSeriesIndex
= nS
;
1397 if( nNewSeriesIndex
>= 0 && nNewSeriesIndex
< aSeriesList
.getLength() )
1399 //move series in the same charttype
1400 bMovedOrMoveAllowed
= true;
1403 aSeriesList
[ nOldSeriesIndex
] = aSeriesList
[ nNewSeriesIndex
];
1404 aSeriesList
[ nNewSeriesIndex
] = xGivenDataSeries
;
1405 xDataSeriesContainer
->setDataSeries( aSeriesList
);
1408 else if( nNewSeriesIndex
<0 )
1410 //exchange series with former charttype
1411 if( xFormerChartType
.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType
, xCurrentChartType
) )
1413 bMovedOrMoveAllowed
= true;
1416 uno::Reference
< XDataSeriesContainer
> xOtherDataSeriesContainer( xFormerChartType
, uno::UNO_QUERY
);
1417 if( xOtherDataSeriesContainer
.is() )
1419 uno::Sequence
< uno::Reference
< XDataSeries
> > aOtherSeriesList( xOtherDataSeriesContainer
->getDataSeries() );
1420 sal_Int32 nOtherSeriesIndex
= aOtherSeriesList
.getLength()-1;
1421 if( nOtherSeriesIndex
>= 0 && nOtherSeriesIndex
< aOtherSeriesList
.getLength() )
1423 uno::Reference
< XDataSeries
> xExchangeSeries( aOtherSeriesList
[nOtherSeriesIndex
] );
1424 aOtherSeriesList
[nOtherSeriesIndex
] = xGivenDataSeries
;
1425 xOtherDataSeriesContainer
->setDataSeries(aOtherSeriesList
);
1427 aSeriesList
[nOldSeriesIndex
]=xExchangeSeries
;
1428 xDataSeriesContainer
->setDataSeries(aSeriesList
);
1434 else if( nT
+1 < aChartTypeList
.getLength() )
1436 //exchange series with next charttype
1437 uno::Reference
< XChartType
> xOtherChartType( aChartTypeList
[nT
+1] );
1438 if( xOtherChartType
.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType
, xCurrentChartType
) )
1440 bMovedOrMoveAllowed
= true;
1443 uno::Reference
< XDataSeriesContainer
> xOtherDataSeriesContainer( xOtherChartType
, uno::UNO_QUERY
);
1444 if( xOtherDataSeriesContainer
.is() )
1446 uno::Sequence
< uno::Reference
< XDataSeries
> > aOtherSeriesList( xOtherDataSeriesContainer
->getDataSeries() );
1447 sal_Int32 nOtherSeriesIndex
= 0;
1448 if( nOtherSeriesIndex
>= 0 && nOtherSeriesIndex
< aOtherSeriesList
.getLength() )
1450 uno::Reference
< XDataSeries
> xExchangeSeries( aOtherSeriesList
[nOtherSeriesIndex
] );
1451 aOtherSeriesList
[nOtherSeriesIndex
] = xGivenDataSeries
;
1452 xOtherDataSeriesContainer
->setDataSeries(aOtherSeriesList
);
1454 aSeriesList
[nOldSeriesIndex
]=xExchangeSeries
;
1455 xDataSeriesContainer
->setDataSeries(aSeriesList
);
1462 catch( const util::CloseVetoException
& )
1465 catch( const uno::RuntimeException
& )
1470 xFormerChartType
= xCurrentChartType
;
1475 catch( const util::CloseVetoException
& )
1478 catch( const uno::RuntimeException
& )
1481 return bMovedOrMoveAllowed
;
1483 } // anonymous namespace
1485 bool DiagramHelper::isSeriesMoveable(
1486 const Reference
< XDiagram
>& xDiagram
,
1487 const Reference
< XDataSeries
>& xGivenDataSeries
,
1490 const bool bDoMove
= false;
1492 bool bIsMoveable
= lcl_moveSeriesOrCheckIfMoveIsAllowed(
1493 xDiagram
, xGivenDataSeries
, bForward
, bDoMove
);
1498 bool DiagramHelper::moveSeries( const Reference
< XDiagram
>& xDiagram
, const Reference
< XDataSeries
>& xGivenDataSeries
, bool bForward
)
1500 const bool bDoMove
= true;
1502 bool bMoved
= lcl_moveSeriesOrCheckIfMoveIsAllowed(
1503 xDiagram
, xGivenDataSeries
, bForward
, bDoMove
);
1508 bool DiagramHelper::isSupportingFloorAndWall( const Reference
<
1509 chart2::XDiagram
>& xDiagram
)
1511 //pies and donuts currently do not support this because of wrong files from older versions
1512 //todo: allow this in future again, if fileversion are available for ole objects (metastream)
1513 //thus the wrong bottom can be removed on import
1515 Sequence
< Reference
< chart2::XChartType
> > aTypes(
1516 ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram
) );
1517 for( sal_Int32 nN
= 0; nN
< aTypes
.getLength(); nN
++ )
1519 Reference
< chart2::XChartType
> xType( aTypes
[nN
] );
1520 if( xType
.is() && xType
->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_PIE
) )
1522 if( xType
.is() && xType
->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_NET
) )
1524 if( xType
.is() && xType
->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET
) )
1530 bool DiagramHelper::isPieOrDonutChart( const ::com::sun::star::uno::Reference
<
1531 ::com::sun::star::chart2::XDiagram
>& xDiagram
)
1533 uno::Reference
< chart2::XChartType
> xChartType( DiagramHelper::getChartTypeByIndex(
1536 if( xChartType
.is() )
1538 OUString aChartType
= xChartType
->getChartType();
1539 if( aChartType
== CHART2_SERVICE_NAME_CHARTTYPE_PIE
)
1545 sal_Int32
DiagramHelper::getGeometry3D(
1546 const uno::Reference
< chart2::XDiagram
> & xDiagram
,
1547 bool& rbFound
, bool& rbAmbiguous
)
1549 sal_Int32
nCommonGeom( DataPointGeometry3D::CUBOID
);
1551 rbAmbiguous
= false;
1553 ::std::vector
< Reference
< chart2::XDataSeries
> > aSeriesVec(
1554 DiagramHelper::getDataSeriesFromDiagram( xDiagram
));
1556 if( aSeriesVec
.empty())
1559 for( ::std::vector
< Reference
< chart2::XDataSeries
> >::const_iterator aIt
=
1560 aSeriesVec
.begin(); aIt
!= aSeriesVec
.end(); ++aIt
)
1564 sal_Int32 nGeom
= 0;
1565 Reference
< beans::XPropertySet
> xProp( *aIt
, uno::UNO_QUERY_THROW
);
1566 if( xProp
->getPropertyValue( "Geometry3D") >>= nGeom
)
1571 nCommonGeom
= nGeom
;
1574 // further series: compare for uniqueness
1575 else if( nCommonGeom
!= nGeom
)
1582 catch( const uno::Exception
& ex
)
1584 ASSERT_EXCEPTION( ex
);
1591 void DiagramHelper::setGeometry3D(
1592 const Reference
< chart2::XDiagram
> & xDiagram
,
1593 sal_Int32 nNewGeometry
)
1595 ::std::vector
< Reference
< chart2::XDataSeries
> > aSeriesVec(
1596 DiagramHelper::getDataSeriesFromDiagram( xDiagram
));
1598 for( ::std::vector
< Reference
< chart2::XDataSeries
> >::const_iterator aIt
=
1599 aSeriesVec
.begin(); aIt
!= aSeriesVec
.end(); ++aIt
)
1601 DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(
1602 *aIt
, "Geometry3D", uno::makeAny( nNewGeometry
));
1606 sal_Int32
DiagramHelper::getCorrectedMissingValueTreatment(
1607 const Reference
< chart2::XDiagram
> & xDiagram
,
1608 const Reference
< chart2::XChartType
>& xChartType
)
1610 sal_Int32 nResult
= ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP
;
1611 uno::Sequence
< sal_Int32
> aAvailableMissingValueTreatments(
1612 ChartTypeHelper::getSupportedMissingValueTreatments( xChartType
) );
1614 uno::Reference
< beans::XPropertySet
> xDiaProp( xDiagram
, uno::UNO_QUERY
);
1615 if( xDiaProp
.is() && (xDiaProp
->getPropertyValue( "MissingValueTreatment" ) >>= nResult
) )
1617 //ensure that the set value is supported by this charttype
1618 for( sal_Int32 nN
= 0; nN
< aAvailableMissingValueTreatments
.getLength(); nN
++ )
1619 if( aAvailableMissingValueTreatments
[nN
] == nResult
)
1620 return nResult
; //ok
1623 //otherwise use the first supported one
1624 if( aAvailableMissingValueTreatments
.getLength() )
1626 nResult
= aAvailableMissingValueTreatments
[0];
1633 DiagramPositioningMode
DiagramHelper::getDiagramPositioningMode( const uno::Reference
<
1634 chart2::XDiagram
> & xDiagram
)
1636 DiagramPositioningMode eMode
= DiagramPositioningMode_AUTO
;
1637 uno::Reference
< beans::XPropertySet
> xDiaProps( xDiagram
, uno::UNO_QUERY
);
1638 if( xDiaProps
.is() )
1640 RelativePosition aRelPos
;
1641 RelativeSize aRelSize
;
1642 if( (xDiaProps
->getPropertyValue("RelativePosition") >>= aRelPos
) &&
1643 (xDiaProps
->getPropertyValue("RelativeSize") >>= aRelSize
) )
1645 bool bPosSizeExcludeAxes
=false;
1646 xDiaProps
->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxes
;
1647 if( bPosSizeExcludeAxes
)
1648 eMode
= DiagramPositioningMode_EXCLUDING
;
1650 eMode
= DiagramPositioningMode_INCLUDING
;
1656 void lcl_ensureRange0to1( double& rValue
)
1664 bool DiagramHelper::setDiagramPositioning( const uno::Reference
< frame::XModel
>& xChartModel
,
1665 const awt::Rectangle
& rPosRect
/*100th mm*/ )
1667 ControllerLockGuardUNO
aCtrlLockGuard( xChartModel
);
1669 bool bChanged
= false;
1670 awt::Size
aPageSize( ChartModelHelper::getPageSize(xChartModel
) );
1671 uno::Reference
< beans::XPropertySet
> xDiaProps( ChartModelHelper::findDiagram( xChartModel
), uno::UNO_QUERY
);
1672 if( !xDiaProps
.is() )
1675 RelativePosition aOldPos
;
1676 RelativeSize aOldSize
;
1677 xDiaProps
->getPropertyValue("RelativePosition" ) >>= aOldPos
;
1678 xDiaProps
->getPropertyValue("RelativeSize" ) >>= aOldSize
;
1680 RelativePosition aNewPos
;
1681 aNewPos
.Anchor
= drawing::Alignment_TOP_LEFT
;
1682 aNewPos
.Primary
= double(rPosRect
.X
)/double(aPageSize
.Width
);
1683 aNewPos
.Secondary
= double(rPosRect
.Y
)/double(aPageSize
.Height
);
1685 chart2::RelativeSize aNewSize
;
1686 aNewSize
.Primary
= double(rPosRect
.Width
)/double(aPageSize
.Width
);
1687 aNewSize
.Secondary
= double(rPosRect
.Height
)/double(aPageSize
.Height
);
1689 lcl_ensureRange0to1( aNewPos
.Primary
);
1690 lcl_ensureRange0to1( aNewPos
.Secondary
);
1691 lcl_ensureRange0to1( aNewSize
.Primary
);
1692 lcl_ensureRange0to1( aNewSize
.Secondary
);
1693 if( (aNewPos
.Primary
+ aNewSize
.Primary
) > 1.0 )
1694 aNewPos
.Primary
= 1.0 - aNewSize
.Primary
;
1695 if( (aNewPos
.Secondary
+ aNewSize
.Secondary
) > 1.0 )
1696 aNewPos
.Secondary
= 1.0 - aNewSize
.Secondary
;
1698 xDiaProps
->setPropertyValue( "RelativePosition", uno::makeAny(aNewPos
) );
1699 xDiaProps
->setPropertyValue( "RelativeSize", uno::makeAny(aNewSize
) );
1701 bChanged
= (aOldPos
.Anchor
!=aNewPos
.Anchor
) ||
1702 (aOldPos
.Primary
!=aNewPos
.Primary
) ||
1703 (aOldPos
.Secondary
!=aNewPos
.Secondary
) ||
1704 (aOldSize
.Primary
!=aNewSize
.Primary
) ||
1705 (aOldSize
.Secondary
!=aNewSize
.Secondary
);
1709 awt::Rectangle
DiagramHelper::getDiagramRectangleFromModel( const uno::Reference
< frame::XModel
>& xChartModel
)
1711 awt::Rectangle
aRet(-1,-1,-1,-1);
1713 uno::Reference
< beans::XPropertySet
> xDiaProps( ChartModelHelper::findDiagram( xChartModel
), uno::UNO_QUERY
);
1714 if( !xDiaProps
.is() )
1717 awt::Size
aPageSize( ChartModelHelper::getPageSize(xChartModel
) );
1719 RelativePosition aRelPos
;
1720 RelativeSize aRelSize
;
1721 xDiaProps
->getPropertyValue("RelativePosition" ) >>= aRelPos
;
1722 xDiaProps
->getPropertyValue("RelativeSize" ) >>= aRelSize
;
1725 static_cast< sal_Int32
>( aRelSize
.Primary
* aPageSize
.Width
),
1726 static_cast< sal_Int32
>( aRelSize
.Secondary
* aPageSize
.Height
));
1729 static_cast< sal_Int32
>( aRelPos
.Primary
* aPageSize
.Width
),
1730 static_cast< sal_Int32
>( aRelPos
.Secondary
* aPageSize
.Height
));
1732 awt::Point aAbsPosLeftTop
= RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( aAbsPos
, aAbsSize
, aRelPos
.Anchor
);
1734 aRet
= awt::Rectangle(aAbsPosLeftTop
.X
, aAbsPosLeftTop
.Y
, aAbsSize
.Width
, aAbsSize
.Height
);
1739 bool DiagramHelper::switchDiagramPositioningToExcludingPositioning(
1740 ChartModel
& rModel
, bool bResetModifiedState
, bool bConvertAlsoFromAutoPositioning
)
1742 //return true if something was changed
1743 const SvtSaveOptions::ODFDefaultVersion
nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1744 if( nCurrentODFVersion
> SvtSaveOptions::ODFVER_012
)
1746 uno::Reference
< ::com::sun::star::chart::XDiagramPositioning
> xDiagramPositioning( rModel
.getFirstDiagram(), uno::UNO_QUERY
);
1747 if( xDiagramPositioning
.is() && ( bConvertAlsoFromAutoPositioning
|| !xDiagramPositioning
->isAutomaticDiagramPositioning() )
1748 && !xDiagramPositioning
->isExcludingDiagramPositioning() )
1750 ControllerLockGuard
aCtrlLockGuard( rModel
);
1751 bool bModelWasModified
= rModel
.isModified();
1752 xDiagramPositioning
->setDiagramPositionExcludingAxes( xDiagramPositioning
->calculateDiagramPositionExcludingAxes() );
1753 if(bResetModifiedState
&& !bModelWasModified
)
1754 rModel
.setModified(sal_False
);
1761 } // namespace chart
1763 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */