merged tag ooo/OOO330_m14
[LibreOffice.git] / chart2 / source / tools / DiagramHelper.cxx
blob36afef60a6d4d94d64c3c1e1f4939addb3f34805
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 #include "DiagramHelper.hxx"
31 #include "LegendHelper.hxx"
32 #include "PropertyHelper.hxx"
33 #include "macros.hxx"
34 #include "DataSeriesHelper.hxx"
35 #include "AxisHelper.hxx"
36 #include "ContainerHelper.hxx"
37 #include "ChartTypeHelper.hxx"
38 #include "ChartModelHelper.hxx"
39 #include "CommonConverters.hxx"
40 #include "ExplicitCategoriesProvider.hxx"
41 #include "servicenames_charttypes.hxx"
42 #include "ChartModelHelper.hxx"
43 #include "RelativePositionHelper.hxx"
44 #include "ControllerLockGuard.hxx"
46 #include <com/sun/star/chart/MissingValueTreatment.hpp>
47 #include <com/sun/star/chart/XChartDocument.hpp>
48 #include <com/sun/star/chart/XDiagramPositioning.hpp>
49 #include <com/sun/star/chart2/XTitled.hpp>
50 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
51 #include <com/sun/star/chart2/XChartTypeTemplate.hpp>
52 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
53 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
54 #include <com/sun/star/chart2/InterpretedData.hpp>
55 #include <com/sun/star/chart2/AxisType.hpp>
56 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
57 #include <com/sun/star/chart2/RelativePosition.hpp>
58 #include <com/sun/star/chart2/RelativeSize.hpp>
60 #include <unotools/saveopt.hxx>
61 #include <rtl/math.hxx>
63 #include <com/sun/star/util/XModifiable.hpp>
65 using namespace ::com::sun::star;
66 using namespace ::com::sun::star::chart2;
67 using namespace ::std;
69 using ::com::sun::star::uno::Reference;
70 using ::com::sun::star::uno::Sequence;
71 using ::rtl::OUString;
73 namespace chart
76 // static
77 DiagramHelper::tTemplateWithServiceName
78 DiagramHelper::getTemplateForDiagram(
79 const Reference< XDiagram > & xDiagram,
80 const Reference< lang::XMultiServiceFactory > & xChartTypeManager,
81 const OUString & rPreferredTemplateName )
83 DiagramHelper::tTemplateWithServiceName aResult;
85 if( ! (xChartTypeManager.is() && xDiagram.is()))
86 return aResult;
88 Sequence< OUString > aServiceNames( xChartTypeManager->getAvailableServiceNames());
89 const sal_Int32 nLength = aServiceNames.getLength();
91 bool bHasPreferredTemplate = (rPreferredTemplateName.getLength() > 0);
92 bool bTemplateFound = false;
94 if( bHasPreferredTemplate )
96 Reference< XChartTypeTemplate > xTempl(
97 xChartTypeManager->createInstance( rPreferredTemplateName ), uno::UNO_QUERY );
99 if( xTempl.is() &&
100 xTempl->matchesTemplate( xDiagram, sal_True ))
102 aResult.first = xTempl;
103 aResult.second = rPreferredTemplateName;
104 bTemplateFound = true;
108 for( sal_Int32 i = 0; ! bTemplateFound && i < nLength; ++i )
112 if( ! bHasPreferredTemplate ||
113 ! rPreferredTemplateName.equals( aServiceNames[ i ] ))
115 Reference< XChartTypeTemplate > xTempl(
116 xChartTypeManager->createInstance( aServiceNames[ i ] ), uno::UNO_QUERY_THROW );
118 if( xTempl->matchesTemplate( xDiagram, sal_True ))
120 aResult.first = xTempl;
121 aResult.second = aServiceNames[ i ];
122 bTemplateFound = true;
126 catch( uno::Exception & ex )
128 ASSERT_EXCEPTION( ex );
132 return aResult;
135 // static
136 void DiagramHelper::setVertical(
137 const Reference< XDiagram > & xDiagram,
138 bool bVertical /* = true */ )
142 Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY );
143 if( xCnt.is())
145 Sequence< Reference< XCoordinateSystem > > aCooSys(
146 xCnt->getCoordinateSystems());
147 uno::Any aValue;
148 aValue <<= bVertical;
149 for( sal_Int32 i=0; i<aCooSys.getLength(); ++i )
151 uno::Reference< XCoordinateSystem > xCooSys( aCooSys[i] );
152 Reference< beans::XPropertySet > xProp( xCooSys, uno::UNO_QUERY );
153 bool bChanged = false;
154 if( xProp.is() )
156 bool bOldSwap = sal_False;
157 if( !(xProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bOldSwap)
158 || bVertical != bOldSwap )
159 bChanged = true;
161 if( bChanged )
162 xProp->setPropertyValue( C2U("SwapXAndYAxis"), aValue );
164 if( xCooSys.is() )
166 const sal_Int32 nDimensionCount( xCooSys->getDimension() );
167 sal_Int32 nDimIndex = 0;
168 for(nDimIndex=0; nDimIndex<nDimensionCount; ++nDimIndex)
170 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
171 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
173 Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( nDimIndex,nI ));
174 if( xAxis.is() )
176 //adapt title rotation only when axis swapping has changed
177 if( bChanged )
179 Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY );
180 if( xTitled.is())
182 Reference< beans::XPropertySet > xTitleProps( xTitled->getTitleObject(), uno::UNO_QUERY );
183 if( !xTitleProps.is() )
184 continue;
185 double fAngleDegree = 0.0;
186 xTitleProps->getPropertyValue( C2U( "TextRotation" ) ) >>= fAngleDegree;
187 if( !::rtl::math::approxEqual( fAngleDegree, 0.0 )
188 && !::rtl::math::approxEqual( fAngleDegree, 90.0 ) )
189 continue;
191 double fNewAngleDegree = 0.0;
192 if( !bVertical && nDimIndex == 1 )
193 fNewAngleDegree = 90.0;
194 else if( bVertical && nDimIndex == 0 )
195 fNewAngleDegree = 90.0;
197 xTitleProps->setPropertyValue( C2U( "TextRotation" ), uno::makeAny( fNewAngleDegree ));
207 catch( uno::Exception & ex )
209 ASSERT_EXCEPTION( ex );
213 //static
214 bool DiagramHelper::getVertical( const uno::Reference< chart2::XDiagram > & xDiagram,
215 bool& rbFound, bool& rbAmbiguous )
217 bool bValue = false;
218 rbFound = false;
219 rbAmbiguous = false;
221 Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY );
222 if( xCnt.is())
224 Sequence< Reference< XCoordinateSystem > > aCooSys(
225 xCnt->getCoordinateSystems());
226 for( sal_Int32 i=0; i<aCooSys.getLength(); ++i )
228 Reference< beans::XPropertySet > xProp( aCooSys[i], uno::UNO_QUERY );
229 if( xProp.is())
231 bool bCurrent = false;
232 if( xProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bCurrent )
234 if( !rbFound )
236 bValue = bCurrent;
237 rbFound = true;
239 else if( bCurrent != bValue )
241 // ambiguous -> choose always first found
242 rbAmbiguous = true;
248 return bValue;
251 //static
252 void DiagramHelper::setStackMode(
253 const Reference< XDiagram > & xDiagram,
254 StackMode eStackMode,
255 bool bOnlyAtFirstChartType /* = true */
260 if( eStackMode == StackMode_AMBIGUOUS )
261 return;
263 bool bValueFound = false;
264 bool bIsAmbiguous = false;
265 StackMode eOldStackMode = DiagramHelper::getStackMode( xDiagram, bValueFound, bIsAmbiguous );
267 if( eStackMode == eOldStackMode && !bIsAmbiguous )
268 return;
270 StackingDirection eNewDirection = StackingDirection_NO_STACKING;
271 if( eStackMode == StackMode_Y_STACKED || eStackMode == StackMode_Y_STACKED_PERCENT )
272 eNewDirection = StackingDirection_Y_STACKING;
273 else if( eStackMode == StackMode_Z_STACKED )
274 eNewDirection = StackingDirection_Z_STACKING;
276 uno::Any aNewDirection( uno::makeAny(eNewDirection) );
278 sal_Bool bPercent = sal_False;
279 if( eStackMode == StackMode_Y_STACKED_PERCENT )
280 bPercent = sal_True;
282 //iterate through all coordinate systems
283 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
284 if( !xCooSysContainer.is() )
285 return;
286 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
287 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
289 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
290 //set correct percent stacking
291 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(1);
292 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
294 Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1,nI ));
295 if( xAxis.is())
297 chart2::ScaleData aScaleData = xAxis->getScaleData();
298 if( (aScaleData.AxisType==AxisType::PERCENT) != bPercent )
300 if( bPercent )
301 aScaleData.AxisType = AxisType::PERCENT;
302 else
303 aScaleData.AxisType = AxisType::REALNUMBER;
304 xAxis->setScaleData( aScaleData );
308 //iterate through all chart types in the current coordinate system
309 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
310 if( !xChartTypeContainer.is() )
311 continue;
312 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
313 sal_Int32 nMax = aChartTypeList.getLength();
314 if( bOnlyAtFirstChartType
315 && nMax >= 1 )
316 nMax = 1;
317 for( sal_Int32 nT = 0; nT < nMax; ++nT )
319 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
321 //iterate through all series in this chart type
322 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
323 OSL_ASSERT( xDataSeriesContainer.is());
324 if( !xDataSeriesContainer.is() )
325 continue;
327 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
328 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
330 Reference< beans::XPropertySet > xProp( aSeriesList[nS], uno::UNO_QUERY );
331 if(xProp.is())
332 xProp->setPropertyValue( C2U( "StackingDirection" ), aNewDirection );
337 catch( uno::Exception & ex )
339 ASSERT_EXCEPTION( ex );
343 //static
345 StackMode DiagramHelper::getStackMode( const Reference< XDiagram > & xDiagram, bool& rbFound, bool& rbAmbiguous )
347 rbFound=false;
348 rbAmbiguous=false;
350 StackMode eGlobalStackMode = StackMode_NONE;
352 //iterate through all coordinate systems
353 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
354 if( !xCooSysContainer.is() )
355 return eGlobalStackMode;
356 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
357 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
359 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
361 //iterate through all chart types in the current coordinate system
362 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
363 if( !xChartTypeContainer.is() )
364 continue;
365 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
366 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
368 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
370 StackMode eLocalStackMode = DiagramHelper::getStackModeFromChartType(
371 xChartType, rbFound, rbAmbiguous, xCooSys );
373 if( rbFound && eLocalStackMode != eGlobalStackMode && nT>0 )
375 rbAmbiguous = true;
376 return eGlobalStackMode;
379 eGlobalStackMode = eLocalStackMode;
383 return eGlobalStackMode;
386 // static
387 StackMode DiagramHelper::getStackModeFromChartType(
388 const Reference< XChartType > & xChartType,
389 bool& rbFound, bool& rbAmbiguous,
390 const Reference< XCoordinateSystem > & xCorrespondingCoordinateSystem )
392 StackMode eStackMode = StackMode_NONE;
393 rbFound = false;
394 rbAmbiguous = false;
398 Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW );
399 Sequence< Reference< chart2::XDataSeries > > aSeries( xDSCnt->getDataSeries());
401 chart2::StackingDirection eCommonDirection = chart2::StackingDirection_NO_STACKING;
402 bool bDirectionInitialized = false;
404 // first series is irrelvant for stacking, start with second, unless
405 // there is only one series
406 const sal_Int32 nSeriesCount = aSeries.getLength();
407 sal_Int32 i = (nSeriesCount == 1) ? 0: 1;
408 for( ; i<nSeriesCount; ++i )
410 rbFound = true;
411 Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY_THROW );
412 chart2::StackingDirection eCurrentDirection = eCommonDirection;
413 // property is not MAYBEVOID
414 bool bSuccess = ( xProp->getPropertyValue( C2U("StackingDirection") ) >>= eCurrentDirection );
415 OSL_ASSERT( bSuccess );
416 (void)(bSuccess); // avoid warning in non-debug builds
417 if( ! bDirectionInitialized )
419 eCommonDirection = eCurrentDirection;
420 bDirectionInitialized = true;
422 else
424 if( eCommonDirection != eCurrentDirection )
426 rbAmbiguous = true;
427 break;
432 if( rbFound )
434 if( eCommonDirection == chart2::StackingDirection_Z_STACKING )
435 eStackMode = StackMode_Z_STACKED;
436 else if( eCommonDirection == chart2::StackingDirection_Y_STACKING )
438 eStackMode = StackMode_Y_STACKED;
440 // percent stacking
441 if( xCorrespondingCoordinateSystem.is() )
443 if( 1 < xCorrespondingCoordinateSystem->getDimension() )
445 sal_Int32 nAxisIndex = 0;
446 if( nSeriesCount )
447 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(aSeries[0]);
449 Reference< chart2::XAxis > xAxis(
450 xCorrespondingCoordinateSystem->getAxisByDimension( 1,nAxisIndex ));
451 if( xAxis.is())
453 chart2::ScaleData aScaleData = xAxis->getScaleData();
454 if( aScaleData.AxisType==chart2::AxisType::PERCENT )
455 eStackMode = StackMode_Y_STACKED_PERCENT;
462 catch( uno::Exception & ex )
464 ASSERT_EXCEPTION( ex );
467 return eStackMode;
470 // static
471 sal_Int32 DiagramHelper::getDimension( const Reference< XDiagram > & xDiagram )
473 // -1: not yet set
474 sal_Int32 nResult = -1;
478 Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
479 if( xCooSysCnt.is() )
481 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
482 xCooSysCnt->getCoordinateSystems());
484 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
486 Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] );
487 if(xCooSys.is())
489 nResult = xCooSys->getDimension();
490 break;
495 catch( uno::Exception & ex )
497 ASSERT_EXCEPTION( ex );
500 return nResult;
503 // static
504 void DiagramHelper::setDimension(
505 const Reference< XDiagram > & xDiagram,
506 sal_Int32 nNewDimensionCount )
508 if( ! xDiagram.is())
509 return;
511 if( DiagramHelper::getDimension( xDiagram ) == nNewDimensionCount )
512 return;
516 bool rbFound = false;
517 bool rbAmbiguous = true;
518 StackMode eStackMode = DiagramHelper::getStackMode( xDiagram, rbFound, rbAmbiguous );
519 bool bIsSupportingOnlyDeepStackingFor3D=false;
521 //change all coordinate systems:
522 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY_THROW );
523 Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
524 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
526 Reference< XCoordinateSystem > xOldCooSys( aCooSysList[nCS], uno::UNO_QUERY );
527 Reference< XCoordinateSystem > xNewCooSys;
529 Reference< XChartTypeContainer > xChartTypeContainer( xOldCooSys, uno::UNO_QUERY );
530 if( !xChartTypeContainer.is() )
531 continue;
533 Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
534 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
536 Reference< XChartType > xChartType( aChartTypeList[nT], uno::UNO_QUERY );
537 bIsSupportingOnlyDeepStackingFor3D = ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType );
538 if(!xNewCooSys.is())
540 xNewCooSys = xChartType->createCoordinateSystem( nNewDimensionCount );
541 break;
543 //@todo make sure that all following charttypes are also capable of the new dimension
544 //otherwise separate them in a different group
545 //BM: might be done in replaceCoordinateSystem()
548 // replace the old coordinate system at all places where it was used
549 DiagramHelper::replaceCoordinateSystem( xDiagram, xOldCooSys, xNewCooSys );
552 //correct stack mode if necessary
553 if( nNewDimensionCount==3 && eStackMode != StackMode_Z_STACKED && bIsSupportingOnlyDeepStackingFor3D )
554 DiagramHelper::setStackMode( xDiagram, StackMode_Z_STACKED );
555 else if( nNewDimensionCount==2 && eStackMode == StackMode_Z_STACKED )
556 DiagramHelper::setStackMode( xDiagram, StackMode_NONE );
558 catch( uno::Exception & ex )
560 ASSERT_EXCEPTION( ex );
564 // static
565 void DiagramHelper::replaceCoordinateSystem(
566 const Reference< XDiagram > & xDiagram,
567 const Reference< XCoordinateSystem > & xCooSysToReplace,
568 const Reference< XCoordinateSystem > & xReplacement )
570 OSL_ASSERT( xDiagram.is());
571 if( ! xDiagram.is())
572 return;
574 // update the coordinate-system container
575 Reference< XCoordinateSystemContainer > xCont( xDiagram, uno::UNO_QUERY );
576 if( xCont.is())
580 Reference< chart2::data::XLabeledDataSequence > xCategories = DiagramHelper::getCategoriesFromDiagram( xDiagram );
582 // move chart types of xCooSysToReplace to xReplacement
583 Reference< XChartTypeContainer > xCTCntCooSys( xCooSysToReplace, uno::UNO_QUERY_THROW );
584 Reference< XChartTypeContainer > xCTCntReplacement( xReplacement, uno::UNO_QUERY_THROW );
585 xCTCntReplacement->setChartTypes( xCTCntCooSys->getChartTypes());
587 xCont->removeCoordinateSystem( xCooSysToReplace );
588 xCont->addCoordinateSystem( xReplacement );
590 if( xCategories.is() )
591 DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram );
593 catch( uno::Exception & ex )
595 ASSERT_EXCEPTION( ex );
600 //static
601 bool DiagramHelper::isSeriesAttachedToMainAxis(
602 const uno::Reference< chart2::XDataSeries >& xDataSeries )
604 sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
605 return (nAxisIndex==0);
608 //static
609 bool DiagramHelper::attachSeriesToAxis( bool bAttachToMainAxis
610 , const uno::Reference< chart2::XDataSeries >& xDataSeries
611 , const uno::Reference< chart2::XDiagram >& xDiagram
612 , const uno::Reference< uno::XComponentContext > & xContext
613 , bool bAdaptAxes )
615 bool bChanged = false;
617 //set property at axis
618 Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
619 if( !xProp.is() )
620 return bChanged;
622 sal_Int32 nNewAxisIndex = bAttachToMainAxis ? 0 : 1;
623 sal_Int32 nOldAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
624 uno::Reference< chart2::XAxis > xOldAxis( DiagramHelper::getAttachedAxis( xDataSeries, xDiagram ) );
626 if( nOldAxisIndex != nNewAxisIndex )
630 xProp->setPropertyValue( C2U("AttachedAxisIndex"), uno::makeAny( nNewAxisIndex ) );
631 bChanged = true;
633 catch( const uno::Exception & ex )
635 ASSERT_EXCEPTION( ex );
639 if( bChanged && xDiagram.is() )
641 uno::Reference< XAxis > xAxis( AxisHelper::getAxis( 1, bAttachToMainAxis, xDiagram ) );
642 if(!xAxis.is()) //create an axis if necessary
643 xAxis = AxisHelper::createAxis( 1, bAttachToMainAxis, xDiagram, xContext );
644 if( bAdaptAxes )
646 AxisHelper::makeAxisVisible( xAxis );
647 AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis, xDiagram );
651 return bChanged;
654 //static
655 uno::Reference< XAxis > DiagramHelper::getAttachedAxis(
656 const uno::Reference< XDataSeries >& xSeries,
657 const uno::Reference< XDiagram >& xDiagram )
659 return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries ), xDiagram );
662 //static
663 uno::Reference< XChartType > DiagramHelper::getChartTypeOfSeries(
664 const uno::Reference< chart2::XDiagram >& xDiagram
665 , const uno::Reference< XDataSeries >& xGivenDataSeries )
667 if( !xGivenDataSeries.is() )
668 return 0;
669 if(!xDiagram.is())
670 return 0;
672 //iterate through the model to find the given xSeries
673 //the found parent indicates the charttype
675 //iterate through all coordinate systems
676 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
677 if( !xCooSysContainer.is())
678 return 0;
680 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
681 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
683 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
685 //iterate through all chart types in the current coordinate system
686 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
687 OSL_ASSERT( xChartTypeContainer.is());
688 if( !xChartTypeContainer.is() )
689 continue;
690 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
691 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
693 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
695 //iterate through all series in this chart type
696 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
697 OSL_ASSERT( xDataSeriesContainer.is());
698 if( !xDataSeriesContainer.is() )
699 continue;
701 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
702 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
704 if( xGivenDataSeries==aSeriesList[nS] )
705 return xChartType;
709 return 0;
712 // static
713 ::std::vector< Reference< XDataSeries > >
714 DiagramHelper::getDataSeriesFromDiagram(
715 const Reference< XDiagram > & xDiagram )
717 ::std::vector< Reference< XDataSeries > > aResult;
721 Reference< XCoordinateSystemContainer > xCooSysCnt(
722 xDiagram, uno::UNO_QUERY_THROW );
723 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
724 xCooSysCnt->getCoordinateSystems());
725 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
727 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
728 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
729 for( sal_Int32 j=0; j<aChartTypeSeq.getLength(); ++j )
731 Reference< XDataSeriesContainer > xDSCnt( aChartTypeSeq[j], uno::UNO_QUERY_THROW );
732 Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
733 ::std::copy( aSeriesSeq.getConstArray(), aSeriesSeq.getConstArray() + aSeriesSeq.getLength(),
734 ::std::back_inserter( aResult ));
738 catch( uno::Exception & ex )
740 ASSERT_EXCEPTION( ex );
743 return aResult;
746 Sequence< Sequence< Reference< XDataSeries > > >
747 DiagramHelper::getDataSeriesGroups( const Reference< XDiagram > & xDiagram )
749 vector< Sequence< Reference< XDataSeries > > > aResult;
751 //iterate through all coordinate systems
752 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
753 if( xCooSysContainer.is() )
755 Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
756 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
758 //iterate through all chart types in the current coordinate system
759 Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY );
760 if( !xChartTypeContainer.is() )
761 continue;
762 Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
763 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
765 Reference< XDataSeriesContainer > xDataSeriesContainer( aChartTypeList[nT], uno::UNO_QUERY );
766 if( !xDataSeriesContainer.is() )
767 continue;
768 aResult.push_back( xDataSeriesContainer->getDataSeries() );
772 return ContainerHelper::ContainerToSequence( aResult );
775 Reference< XChartType >
776 DiagramHelper::getChartTypeByIndex( const Reference< XDiagram >& xDiagram, sal_Int32 nIndex )
778 Reference< XChartType > xChartType;
780 //iterate through all coordinate systems
781 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
782 if( ! xCooSysContainer.is())
783 return xChartType;
785 Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
786 sal_Int32 nTypesSoFar = 0;
787 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
789 Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY );
790 if( !xChartTypeContainer.is() )
791 continue;
792 Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
793 if( nIndex >= 0 && nIndex < (nTypesSoFar + aChartTypeList.getLength()) )
795 xChartType.set( aChartTypeList[nIndex - nTypesSoFar] );
796 break;
798 nTypesSoFar += aChartTypeList.getLength();
801 return xChartType;
804 namespace
807 std::vector< Reference< XAxis > > lcl_getAxisHoldingCategoriesFromDiagram(
808 const Reference< XDiagram > & xDiagram )
810 std::vector< Reference< XAxis > > aRet;
812 Reference< XAxis > xResult;
813 // return first x-axis as fall-back
814 Reference< XAxis > xFallBack;
817 Reference< XCoordinateSystemContainer > xCooSysCnt(
818 xDiagram, uno::UNO_QUERY_THROW );
819 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
820 xCooSysCnt->getCoordinateSystems());
821 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
823 Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] );
824 OSL_ASSERT( xCooSys.is());
825 for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
827 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
828 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
830 Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI );
831 OSL_ASSERT( xAxis.is());
832 if( xAxis.is())
834 ScaleData aScaleData = xAxis->getScaleData();
835 if( aScaleData.Categories.is() || (aScaleData.AxisType == AxisType::CATEGORY) )
837 aRet.push_back(xAxis);
839 if( (nN == 0) && !xFallBack.is())
840 xFallBack.set( xAxis );
846 catch( uno::Exception & ex )
848 ASSERT_EXCEPTION( ex );
851 if( aRet.empty() )
852 aRet.push_back(xFallBack);
854 return aRet;
857 } // anonymous namespace
859 //static
860 bool DiagramHelper::isCategoryDiagram(
861 const Reference< XDiagram >& xDiagram )
865 Reference< XCoordinateSystemContainer > xCooSysCnt(
866 xDiagram, uno::UNO_QUERY_THROW );
867 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
868 xCooSysCnt->getCoordinateSystems());
869 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
871 Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] );
872 OSL_ASSERT( xCooSys.is());
873 for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
875 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
876 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
878 Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI );
879 OSL_ASSERT( xAxis.is());
880 if( xAxis.is())
882 ScaleData aScaleData = xAxis->getScaleData();
883 if( aScaleData.AxisType == AxisType::CATEGORY )
884 return true;
890 catch( uno::Exception & ex )
892 ASSERT_EXCEPTION( ex );
895 return false;
898 // static
899 void DiagramHelper::setCategoriesToDiagram(
900 const Reference< chart2::data::XLabeledDataSequence >& xCategories,
901 const Reference< XDiagram >& xDiagram,
902 bool bSetAxisType /* = false */,
903 bool bCategoryAxis /* = true */ )
905 std::vector< Reference< chart2::XAxis > > aCatAxes(
906 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram ));
908 std::vector< Reference< chart2::XAxis > >::iterator aIt( aCatAxes.begin() );
909 std::vector< Reference< chart2::XAxis > >::const_iterator aEnd( aCatAxes.end() );
911 for( aIt = aCatAxes.begin(); aIt != aEnd; ++aIt )
913 Reference< chart2::XAxis > xCatAxis(*aIt);
914 if( xCatAxis.is())
916 ScaleData aScaleData( xCatAxis->getScaleData());
917 aScaleData.Categories = xCategories;
918 if( bSetAxisType )
920 if( bCategoryAxis )
921 aScaleData.AxisType = AxisType::CATEGORY;
922 else if( aScaleData.AxisType == AxisType::CATEGORY )
923 aScaleData.AxisType = AxisType::REALNUMBER;
925 xCatAxis->setScaleData( aScaleData );
930 // static
931 Reference< data::XLabeledDataSequence >
932 DiagramHelper::getCategoriesFromDiagram(
933 const Reference< XDiagram > & xDiagram )
935 Reference< data::XLabeledDataSequence > xResult;
939 std::vector< Reference< chart2::XAxis > > aCatAxes(
940 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram ));
941 std::vector< Reference< chart2::XAxis > >::iterator aIt( aCatAxes.begin() );
942 std::vector< Reference< chart2::XAxis > >::const_iterator aEnd( aCatAxes.end() );
943 //search for first categories
944 if( aIt != aEnd )
946 Reference< chart2::XAxis > xCatAxis(*aIt);
947 if( xCatAxis.is())
949 ScaleData aScaleData( xCatAxis->getScaleData());
950 if( aScaleData.Categories.is() )
952 xResult.set( aScaleData.Categories );
953 uno::Reference<beans::XPropertySet> xProp(aScaleData.Categories->getValues(), uno::UNO_QUERY );
954 if( xProp.is() )
958 xProp->setPropertyValue( C2U( "Role" ), uno::makeAny( C2U("categories") ) );
960 catch( uno::Exception & ex )
962 ASSERT_EXCEPTION( ex );
969 catch( uno::Exception & ex )
971 ASSERT_EXCEPTION( ex );
974 return xResult;
977 void lcl_generateAutomaticCategoriesFromChartType(
978 Sequence< rtl::OUString >& rRet,
979 const Reference< XChartType >& xChartType )
981 if(!xChartType.is())
982 return;
983 rtl::OUString aMainSeq( xChartType->getRoleOfSequenceForSeriesLabel() );
984 Reference< XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY );
985 if( xSeriesCnt.is() )
987 Sequence< Reference< XDataSeries > > aSeriesSeq( xSeriesCnt->getDataSeries() );
988 for( sal_Int32 nS = 0; nS < aSeriesSeq.getLength(); nS++ )
990 Reference< data::XDataSource > xDataSource( aSeriesSeq[nS], uno::UNO_QUERY );
991 if( !xDataSource.is() )
992 continue;
993 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
994 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aMainSeq ));
995 if( !xLabeledSeq.is() )
996 continue;
997 Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
998 if( !xValueSeq.is() )
999 continue;
1000 rRet = xValueSeq->generateLabel( chart2::data::LabelOrigin_LONG_SIDE );
1001 if( rRet.getLength() )
1002 return;
1007 Sequence< rtl::OUString > DiagramHelper::generateAutomaticCategoriesFromCooSys( const Reference< XCoordinateSystem > & xCooSys )
1009 Sequence< rtl::OUString > aRet;
1011 Reference< XChartTypeContainer > xTypeCntr( xCooSys, uno::UNO_QUERY );
1012 if( xTypeCntr.is() )
1014 Sequence< Reference< XChartType > > aChartTypes( xTypeCntr->getChartTypes() );
1015 for( sal_Int32 nN=0; nN<aChartTypes.getLength(); nN++ )
1017 lcl_generateAutomaticCategoriesFromChartType( aRet, aChartTypes[nN] );
1018 if( aRet.getLength() )
1019 return aRet;
1022 return aRet;
1025 //static
1026 Sequence< rtl::OUString > DiagramHelper::getExplicitSimpleCategories(
1027 const Reference< XChartDocument >& xChartDoc )
1029 Sequence< rtl::OUString > aRet;
1030 uno::Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
1031 if(xChartModel.is())
1033 uno::Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
1034 ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, xChartModel );
1035 aRet = aExplicitCategoriesProvider.getSimpleCategories();
1037 return aRet;
1040 // static
1041 Sequence< Reference< XChartType > >
1042 DiagramHelper::getChartTypesFromDiagram(
1043 const Reference< XDiagram > & xDiagram )
1045 ::std::vector< Reference< XChartType > > aResult;
1047 if(xDiagram.is())
1050 Reference< XCoordinateSystemContainer > xCooSysCnt(
1051 xDiagram, uno::UNO_QUERY_THROW );
1052 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
1053 xCooSysCnt->getCoordinateSystems());
1054 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
1056 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
1057 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
1058 ::std::copy( aChartTypeSeq.getConstArray(), aChartTypeSeq.getConstArray() + aChartTypeSeq.getLength(),
1059 ::std::back_inserter( aResult ));
1062 catch( uno::Exception & ex )
1064 ASSERT_EXCEPTION( ex );
1067 return ContainerHelper::ContainerToSequence( aResult );
1070 //static
1071 bool DiagramHelper::areChartTypesCompatible( const Reference< ::chart2::XChartType >& xFirstType,
1072 const Reference< ::chart2::XChartType >& xSecondType )
1074 if( !xFirstType.is() || !xSecondType.is() )
1075 return false;
1077 ::std::vector< ::rtl::OUString > aFirstRoles( ContainerHelper::SequenceToVector( xFirstType->getSupportedMandatoryRoles() ) );
1078 ::std::vector< ::rtl::OUString > aSecondRoles( ContainerHelper::SequenceToVector( xSecondType->getSupportedMandatoryRoles() ) );
1079 ::std::sort( aFirstRoles.begin(), aFirstRoles.end() );
1080 ::std::sort( aSecondRoles.begin(), aSecondRoles.end() );
1081 return ( aFirstRoles == aSecondRoles );
1084 namespace
1087 * This method implements the logic of checking if a series can be moved
1088 * forward/backward. Depending on the "bDoMove" parameter the series will
1089 * be moved (bDoMove = true) or the function just will test if the
1090 * series can be moved without doing the move (bDoMove = false).
1092 * @param xDiagram
1093 * Reference to the diagram that contains the series.
1095 * @param xGivenDataSeries
1096 * Reference to the series that should moved or tested for moving.
1098 * @param bForward
1099 * Direction in which the series should be moved or tested for moving.
1101 * @param bDoMove
1102 * Should this function really move the series (true) or just test if it is
1103 * possible (false).
1106 * @returns
1107 * in case of bDoMove == true
1108 * - True : if the move was done
1109 * - False : the move failed
1110 * in case of bDoMove == false
1111 * - True : the series can be moved
1112 * - False : the series can not be moved
1116 bool lcl_moveSeriesOrCheckIfMoveIsAllowed(
1117 const Reference< XDiagram >& xDiagram,
1118 const Reference< XDataSeries >& xGivenDataSeries,
1119 bool bForward,
1120 bool bDoMove )
1122 bool bMovedOrMoveAllowed = false;
1126 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
1128 //find position of series.
1129 bool bFound = false;
1131 if( xGivenDataSeries.is() && xCooSysContainer.is() )
1133 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
1135 for( sal_Int32 nCS = 0; !bFound && nCS < aCooSysList.getLength(); ++nCS )
1137 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
1139 //iterate through all chart types in the current coordinate system
1140 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
1141 OSL_ASSERT( xChartTypeContainer.is());
1142 if( !xChartTypeContainer.is() )
1143 continue;
1144 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
1145 uno::Reference< XChartType > xFormerChartType;
1147 for( sal_Int32 nT = 0; !bFound && nT < aChartTypeList.getLength(); ++nT )
1149 uno::Reference< XChartType > xCurrentChartType( aChartTypeList[nT] );
1151 //iterate through all series in this chart type
1152 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xCurrentChartType, uno::UNO_QUERY );
1153 OSL_ASSERT( xDataSeriesContainer.is());
1154 if( !xDataSeriesContainer.is() )
1155 continue;
1157 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
1159 for( sal_Int32 nS = 0; !bFound && nS < aSeriesList.getLength(); ++nS )
1162 // We found the series we are interrested in !
1163 if( xGivenDataSeries==aSeriesList[nS] )
1165 sal_Int32 nOldSeriesIndex = nS;
1166 bFound = true;
1170 sal_Int32 nNewSeriesIndex = nS;
1172 if( bForward )
1173 nNewSeriesIndex--;
1174 else
1175 nNewSeriesIndex++;
1178 if( nNewSeriesIndex >= 0 && nNewSeriesIndex < aSeriesList.getLength() )
1180 //move series in the same charttype
1181 bMovedOrMoveAllowed = true;
1182 if( bDoMove )
1184 aSeriesList[ nOldSeriesIndex ] = aSeriesList[ nNewSeriesIndex ];
1185 aSeriesList[ nNewSeriesIndex ] = xGivenDataSeries;
1186 xDataSeriesContainer->setDataSeries( aSeriesList );
1189 else if( nNewSeriesIndex<0 )
1191 //exchange series with former charttype
1192 if( xFormerChartType.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType, xCurrentChartType ) )
1194 bMovedOrMoveAllowed = true;
1195 if( bDoMove )
1197 uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xFormerChartType, uno::UNO_QUERY );
1198 if( xOtherDataSeriesContainer.is() )
1200 uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() );
1201 sal_Int32 nOtherSeriesIndex = aOtherSeriesList.getLength()-1;
1202 if( nOtherSeriesIndex >= 0 && nOtherSeriesIndex < aOtherSeriesList.getLength() )
1204 uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] );
1205 aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries;
1206 xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList);
1208 aSeriesList[nOldSeriesIndex]=xExchangeSeries;
1209 xDataSeriesContainer->setDataSeries(aSeriesList);
1215 else if( nT+1 < aChartTypeList.getLength() )
1217 //exchange series with next charttype
1218 uno::Reference< XChartType > xOtherChartType( aChartTypeList[nT+1] );
1219 if( xOtherChartType.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType, xCurrentChartType ) )
1221 bMovedOrMoveAllowed = true;
1222 if( bDoMove )
1224 uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xOtherChartType, uno::UNO_QUERY );
1225 if( xOtherDataSeriesContainer.is() )
1227 uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() );
1228 sal_Int32 nOtherSeriesIndex = 0;
1229 if( nOtherSeriesIndex >= 0 && nOtherSeriesIndex < aOtherSeriesList.getLength() )
1231 uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] );
1232 aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries;
1233 xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList);
1235 aSeriesList[nOldSeriesIndex]=xExchangeSeries;
1236 xDataSeriesContainer->setDataSeries(aSeriesList);
1243 catch( util::CloseVetoException& )
1246 catch( uno::RuntimeException& )
1251 xFormerChartType = xCurrentChartType;
1256 catch( util::CloseVetoException& )
1259 catch( uno::RuntimeException& )
1262 return bMovedOrMoveAllowed;
1264 } // anonymous namespace
1267 bool DiagramHelper::isSeriesMoveable(
1268 const Reference< XDiagram >& xDiagram,
1269 const Reference< XDataSeries >& xGivenDataSeries,
1270 bool bForward )
1272 bool bIsMoveable = false;
1273 const bool bDoMove = false;
1275 bIsMoveable = lcl_moveSeriesOrCheckIfMoveIsAllowed(
1276 xDiagram, xGivenDataSeries, bForward, bDoMove );
1278 return bIsMoveable;
1282 bool DiagramHelper::moveSeries( const Reference< XDiagram >& xDiagram, const Reference< XDataSeries >& xGivenDataSeries, bool bForward )
1284 bool bMoved = false;
1285 const bool bDoMove = true;
1287 bMoved = lcl_moveSeriesOrCheckIfMoveIsAllowed(
1288 xDiagram, xGivenDataSeries, bForward, bDoMove );
1290 return bMoved;
1293 bool DiagramHelper::isSupportingFloorAndWall( const Reference<
1294 chart2::XDiagram >& xDiagram )
1296 //pies and donuts currently do not support this because of wrong files from older versions
1297 //todo: allow this in future again, if fileversion are available for ole objects (metastream)
1298 //thus the wrong bottom can be removed on import
1300 Sequence< Reference< chart2::XChartType > > aTypes(
1301 ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ) );
1302 for( sal_Int32 nN = 0; nN < aTypes.getLength(); nN++ )
1304 Reference< chart2::XChartType > xType( aTypes[nN] );
1305 if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
1306 return false;
1307 if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
1308 return false;
1309 if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
1310 return false;
1312 return true;
1315 bool DiagramHelper::isPieOrDonutChart( const ::com::sun::star::uno::Reference<
1316 ::com::sun::star::chart2::XDiagram >& xDiagram )
1318 uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex(
1319 xDiagram, 0 ) );
1321 if( xChartType .is() )
1323 rtl::OUString aChartType = xChartType->getChartType();
1324 if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
1325 return true;
1327 return false;
1330 // static
1331 sal_Int32 DiagramHelper::getGeometry3D(
1332 const uno::Reference< chart2::XDiagram > & xDiagram,
1333 bool& rbFound, bool& rbAmbiguous )
1335 sal_Int32 nCommonGeom( DataPointGeometry3D::CUBOID );
1336 rbFound = false;
1337 rbAmbiguous = false;
1339 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVec(
1340 DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
1342 if( aSeriesVec.empty())
1343 rbAmbiguous = true;
1345 for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt =
1346 aSeriesVec.begin(); aIt != aSeriesVec.end(); ++aIt )
1350 sal_Int32 nGeom = 0;
1351 Reference< beans::XPropertySet > xProp( *aIt, uno::UNO_QUERY_THROW );
1352 if( xProp->getPropertyValue( C2U( "Geometry3D" )) >>= nGeom )
1354 if( ! rbFound )
1356 // first series
1357 nCommonGeom = nGeom;
1358 rbFound = true;
1360 // further series: compare for uniqueness
1361 else if( nCommonGeom != nGeom )
1363 rbAmbiguous = true;
1364 break;
1368 catch( uno::Exception & ex )
1370 ASSERT_EXCEPTION( ex );
1374 return nCommonGeom;
1377 // static
1378 void DiagramHelper::setGeometry3D(
1379 const Reference< chart2::XDiagram > & xDiagram,
1380 sal_Int32 nNewGeometry )
1382 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVec(
1383 DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
1385 for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt =
1386 aSeriesVec.begin(); aIt != aSeriesVec.end(); ++aIt )
1388 DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(
1389 *aIt, C2U( "Geometry3D" ), uno::makeAny( nNewGeometry ));
1393 //static
1394 sal_Int32 DiagramHelper::getCorrectedMissingValueTreatment(
1395 const Reference< chart2::XDiagram > & xDiagram,
1396 const Reference< chart2::XChartType >& xChartType )
1398 sal_Int32 nResult = ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP;
1399 uno::Sequence < sal_Int32 > aAvailableMissingValueTreatments(
1400 ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) );
1402 uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
1403 if( xDiaProp.is() && (xDiaProp->getPropertyValue( C2U( "MissingValueTreatment" ) ) >>= nResult) )
1405 //ensure that the set value is supported by this charttype
1406 for( sal_Int32 nN = 0; nN < aAvailableMissingValueTreatments.getLength(); nN++ )
1407 if( aAvailableMissingValueTreatments[nN] == nResult )
1408 return nResult; //ok
1411 //otherwise use the first supported one
1412 if( aAvailableMissingValueTreatments.getLength() )
1414 nResult = aAvailableMissingValueTreatments[0];
1415 return nResult;
1418 return nResult;
1421 //static
1422 DiagramPositioningMode DiagramHelper::getDiagramPositioningMode( const uno::Reference<
1423 chart2::XDiagram > & xDiagram )
1425 DiagramPositioningMode eMode = DiagramPositioningMode_AUTO;
1426 uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY );
1427 if( xDiaProps.is() )
1429 RelativePosition aRelPos;
1430 RelativeSize aRelSize;
1431 if( (xDiaProps->getPropertyValue(C2U("RelativePosition")) >>= aRelPos ) &&
1432 (xDiaProps->getPropertyValue(C2U("RelativeSize")) >>= aRelSize ) )
1434 bool bPosSizeExcludeAxes=false;
1435 xDiaProps->getPropertyValue(C2U("PosSizeExcludeAxes")) >>= bPosSizeExcludeAxes;
1436 if( bPosSizeExcludeAxes )
1437 eMode = DiagramPositioningMode_EXCLUDING;
1438 else
1439 eMode = DiagramPositioningMode_INCLUDING;
1442 return eMode;
1445 void lcl_ensureRange0to1( double& rValue )
1447 if(rValue<0.0)
1448 rValue=0.0;
1449 if(rValue>1.0)
1450 rValue=1.0;
1453 //static
1454 bool DiagramHelper::setDiagramPositioning( const uno::Reference< frame::XModel >& xChartModel,
1455 const awt::Rectangle& rPosRect /*100th mm*/ )
1457 ControllerLockGuard aCtrlLockGuard( xChartModel );
1459 bool bChanged = false;
1460 awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) );
1461 uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY );
1462 if( !xDiaProps.is() )
1463 return bChanged;
1465 RelativePosition aOldPos;
1466 RelativeSize aOldSize;
1467 xDiaProps->getPropertyValue(C2U("RelativePosition") ) >>= aOldPos;
1468 xDiaProps->getPropertyValue(C2U("RelativeSize") ) >>= aOldSize;
1470 RelativePosition aNewPos;
1471 aNewPos.Anchor = drawing::Alignment_TOP_LEFT;
1472 aNewPos.Primary = double(rPosRect.X)/double(aPageSize.Width);
1473 aNewPos.Secondary = double(rPosRect.Y)/double(aPageSize.Height);
1475 chart2::RelativeSize aNewSize;
1476 aNewSize.Primary = double(rPosRect.Width)/double(aPageSize.Width);
1477 aNewSize.Secondary = double(rPosRect.Height)/double(aPageSize.Height);
1479 lcl_ensureRange0to1( aNewPos.Primary );
1480 lcl_ensureRange0to1( aNewPos.Secondary );
1481 lcl_ensureRange0to1( aNewSize.Primary );
1482 lcl_ensureRange0to1( aNewSize.Secondary );
1483 if( (aNewPos.Primary + aNewSize.Primary) > 1.0 )
1484 aNewPos.Primary = 1.0 - aNewSize.Primary;
1485 if( (aNewPos.Secondary + aNewSize.Secondary) > 1.0 )
1486 aNewPos.Secondary = 1.0 - aNewSize.Secondary;
1488 xDiaProps->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aNewPos) );
1489 xDiaProps->setPropertyValue( C2U( "RelativeSize" ), uno::makeAny(aNewSize) );
1491 bChanged = (aOldPos.Anchor!=aNewPos.Anchor) ||
1492 (aOldPos.Primary!=aNewPos.Primary) ||
1493 (aOldPos.Secondary!=aNewPos.Secondary) ||
1494 (aOldSize.Primary!=aNewSize.Primary) ||
1495 (aOldSize.Secondary!=aNewSize.Secondary);
1496 return bChanged;
1499 //static
1500 awt::Rectangle DiagramHelper::getDiagramRectangleFromModel( const uno::Reference< frame::XModel >& xChartModel )
1502 awt::Rectangle aRet(-1,-1,-1,-1);
1504 uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY );
1505 if( !xDiaProps.is() )
1506 return aRet;
1508 awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) );
1510 RelativePosition aRelPos;
1511 RelativeSize aRelSize;
1512 xDiaProps->getPropertyValue(C2U("RelativePosition") ) >>= aRelPos;
1513 xDiaProps->getPropertyValue(C2U("RelativeSize") ) >>= aRelSize;
1515 awt::Size aAbsSize(
1516 aRelSize.Primary * aPageSize.Width,
1517 aRelSize.Secondary * aPageSize.Height );
1519 awt::Point aAbsPos(
1520 static_cast< sal_Int32 >( aRelPos.Primary * aPageSize.Width ),
1521 static_cast< sal_Int32 >( aRelPos.Secondary * aPageSize.Height ));
1523 awt::Point aAbsPosLeftTop = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( aAbsPos, aAbsSize, aRelPos.Anchor );
1525 aRet = awt::Rectangle(aAbsPosLeftTop.X, aAbsPosLeftTop.Y, aAbsSize.Width, aAbsSize.Height );
1527 return aRet;
1530 //static
1531 bool DiagramHelper::switchDiagramPositioningToExcludingPositioning(
1532 const uno::Reference< frame::XModel >& xChartModel
1533 , bool bResetModifiedState, bool bConvertAlsoFromAutoPositioning )
1535 //return true if something was changed
1536 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1537 if( nCurrentODFVersion == SvtSaveOptions::ODFVER_LATEST )//#i100778# todo: change this dependent on fileformat evolution
1539 uno::Reference< ::com::sun::star::chart::XChartDocument > xOldDoc( xChartModel, uno::UNO_QUERY ) ;
1540 if( xOldDoc.is() )
1542 uno::Reference< ::com::sun::star::chart::XDiagramPositioning > xDiagramPositioning( xOldDoc->getDiagram(), uno::UNO_QUERY );
1543 if( xDiagramPositioning.is() && ( bConvertAlsoFromAutoPositioning || !xDiagramPositioning->isAutomaticDiagramPositioning() )
1544 && !xDiagramPositioning->isExcludingDiagramPositioning() )
1546 ControllerLockGuard aCtrlLockGuard( xChartModel );
1547 uno::Reference< util::XModifiable > xModifiable( xChartModel, uno::UNO_QUERY );
1548 bool bModelWasModified = xModifiable.is() && xModifiable->isModified();
1549 xDiagramPositioning->setDiagramPositionExcludingAxes( xDiagramPositioning->calculateDiagramPositionExcludingAxes() );
1550 if(bResetModifiedState && !bModelWasModified && xModifiable.is() )
1551 xModifiable->setModified(sal_False);
1552 return true;
1556 return false;
1559 } // namespace chart