1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
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"
45 #include "NumberFormatterWrapper.hxx"
46 
47 #include <com/sun/star/chart/MissingValueTreatment.hpp>
48 #include <com/sun/star/chart/XChartDocument.hpp>
49 #include <com/sun/star/chart/XDiagramPositioning.hpp>
50 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
51 #include <com/sun/star/chart2/XTitled.hpp>
52 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
53 #include <com/sun/star/chart2/XChartTypeTemplate.hpp>
54 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
55 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
56 #include <com/sun/star/chart2/InterpretedData.hpp>
57 #include <com/sun/star/chart2/AxisType.hpp>
58 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
59 #include <com/sun/star/chart2/RelativePosition.hpp>
60 #include <com/sun/star/chart2/RelativeSize.hpp>
61 
62 #include <com/sun/star/util/NumberFormat.hpp>
63 #include <com/sun/star/util/XModifiable.hpp>
64 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
65 
66 #include <unotools/saveopt.hxx>
67 #include <rtl/math.hxx>
68 #include <svl/zformat.hxx>
69 // header for class Application
70 #include <vcl/svapp.hxx>
71 
72 using namespace ::com::sun::star;
73 using namespace ::com::sun::star::chart2;
74 using namespace ::std;
75 
76 using ::com::sun::star::uno::Reference;
77 using ::com::sun::star::uno::Sequence;
78 using ::com::sun::star::uno::Any;
79 using ::rtl::OUString;
80 using ::com::sun::star::chart2::XAnyDescriptionAccess;
81 
82 namespace chart
83 {
84 
85 DiagramHelper::tTemplateWithServiceName
86     DiagramHelper::getTemplateForDiagram(
87         const Reference< XDiagram > & xDiagram,
88         const Reference< lang::XMultiServiceFactory > & xChartTypeManager,
89         const OUString & rPreferredTemplateName )
90 {
91     DiagramHelper::tTemplateWithServiceName aResult;
92 
93     if( ! (xChartTypeManager.is() && xDiagram.is()))
94         return aResult;
95 
96     Sequence< OUString > aServiceNames( xChartTypeManager->getAvailableServiceNames());
97     const sal_Int32 nLength = aServiceNames.getLength();
98 
99     bool bHasPreferredTemplate = (rPreferredTemplateName.getLength() > 0);
100     bool bTemplateFound = false;
101 
102     if( bHasPreferredTemplate )
103     {
104         Reference< XChartTypeTemplate > xTempl(
105             xChartTypeManager->createInstance( rPreferredTemplateName ), uno::UNO_QUERY );
106 
107         if( xTempl.is() &&
108             xTempl->matchesTemplate( xDiagram, sal_True ))
109         {
110             aResult.first = xTempl;
111             aResult.second = rPreferredTemplateName;
112             bTemplateFound = true;
113         }
114     }
115 
116     for( sal_Int32 i = 0; ! bTemplateFound && i < nLength; ++i )
117     {
118         try
119         {
120             if( ! bHasPreferredTemplate ||
121                 ! rPreferredTemplateName.equals( aServiceNames[ i ] ))
122             {
123                 Reference< XChartTypeTemplate > xTempl(
124                     xChartTypeManager->createInstance( aServiceNames[ i ] ), uno::UNO_QUERY_THROW );
125 
126                 if( xTempl->matchesTemplate( xDiagram, sal_True ))
127                 {
128                     aResult.first = xTempl;
129                     aResult.second = aServiceNames[ i ];
130                     bTemplateFound = true;
131                 }
132             }
133         }
134         catch( uno::Exception & ex )
135         {
136             ASSERT_EXCEPTION( ex );
137         }
138     }
139 
140     return aResult;
141 }
142 
143 void DiagramHelper::setVertical(
144     const Reference< XDiagram > & xDiagram,
145     bool bVertical /* = true */ )
146 {
147     try
148     {
149         Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY );
150         if( xCnt.is())
151         {
152             Sequence< Reference< XCoordinateSystem > > aCooSys(
153                 xCnt->getCoordinateSystems());
154             uno::Any aValue;
155             aValue <<= bVertical;
156             for( sal_Int32 i=0; i<aCooSys.getLength(); ++i )
157             {
158                 uno::Reference< XCoordinateSystem > xCooSys( aCooSys[i] );
159                 Reference< beans::XPropertySet > xProp( xCooSys, uno::UNO_QUERY );
160                 bool bChanged = false;
161                 if( xProp.is() )
162                 {
163                     bool bOldSwap = sal_False;
164                     if( !(xProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bOldSwap)
165                         || bVertical != bOldSwap )
166                         bChanged = true;
167 
168                     if( bChanged )
169                         xProp->setPropertyValue( C2U("SwapXAndYAxis"), aValue );
170                 }
171                 if( xCooSys.is() )
172                 {
173                     const sal_Int32 nDimensionCount( xCooSys->getDimension() );
174                     sal_Int32 nDimIndex = 0;
175                     for(nDimIndex=0; nDimIndex<nDimensionCount; ++nDimIndex)
176                     {
177                         const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
178                         for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
179                         {
180                             Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( nDimIndex,nI ));
181                             if( xAxis.is() )
182                             {
183                                 //adapt title rotation only when axis swapping has changed
184                                 if( bChanged )
185                                 {
186                                     Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY );
187                                     if( xTitled.is())
188                                     {
189                                         Reference< beans::XPropertySet > xTitleProps( xTitled->getTitleObject(), uno::UNO_QUERY );
190                                         if( !xTitleProps.is() )
191                                             continue;
192                                         double fAngleDegree = 0.0;
193                                         xTitleProps->getPropertyValue( C2U( "TextRotation" ) ) >>= fAngleDegree;
194                                         if( !::rtl::math::approxEqual( fAngleDegree, 0.0 )
195                                             && !::rtl::math::approxEqual( fAngleDegree, 90.0 ) )
196                                             continue;
197 
198                                         double fNewAngleDegree = 0.0;
199                                         if( !bVertical && nDimIndex == 1 )
200                                             fNewAngleDegree = 90.0;
201                                         else if( bVertical && nDimIndex == 0 )
202                                             fNewAngleDegree = 90.0;
203 
204                                         xTitleProps->setPropertyValue( C2U( "TextRotation" ), uno::makeAny( fNewAngleDegree ));
205                                     }
206                                 }
207                             }
208                         }
209                     }
210                 }
211             }
212         }
213     }
214     catch( uno::Exception & ex )
215     {
216         ASSERT_EXCEPTION( ex );
217     }
218 }
219 
220 bool DiagramHelper::getVertical( const uno::Reference< chart2::XDiagram > & xDiagram,
221                              bool& rbFound, bool& rbAmbiguous )
222 {
223     bool bValue = false;
224     rbFound = false;
225     rbAmbiguous = false;
226 
227     Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY );
228     if( xCnt.is())
229     {
230         Sequence< Reference< XCoordinateSystem > > aCooSys(
231             xCnt->getCoordinateSystems());
232         for( sal_Int32 i=0; i<aCooSys.getLength(); ++i )
233         {
234             Reference< beans::XPropertySet > xProp( aCooSys[i], uno::UNO_QUERY );
235             if( xProp.is())
236             {
237                 bool bCurrent = false;
238                 if( xProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bCurrent )
239                 {
240                     if( !rbFound )
241                     {
242                         bValue = bCurrent;
243                         rbFound = true;
244                     }
245                     else if( bCurrent != bValue )
246                     {
247                         // ambiguous -> choose always first found
248                         rbAmbiguous = true;
249                     }
250                 }
251             }
252         }
253     }
254     return bValue;
255 }
256 
257 void DiagramHelper::setStackMode(
258     const Reference< XDiagram > & xDiagram,
259     StackMode eStackMode,
260     bool bOnlyAtFirstChartType /* = true */
261 )
262 {
263     try
264     {
265         if( eStackMode == StackMode_AMBIGUOUS )
266             return;
267 
268         bool bValueFound = false;
269         bool bIsAmbiguous = false;
270         StackMode eOldStackMode = DiagramHelper::getStackMode( xDiagram, bValueFound, bIsAmbiguous );
271 
272         if( eStackMode == eOldStackMode && !bIsAmbiguous )
273             return;
274 
275         StackingDirection eNewDirection = StackingDirection_NO_STACKING;
276         if( eStackMode == StackMode_Y_STACKED || eStackMode == StackMode_Y_STACKED_PERCENT )
277             eNewDirection = StackingDirection_Y_STACKING;
278         else if( eStackMode == StackMode_Z_STACKED )
279             eNewDirection = StackingDirection_Z_STACKING;
280 
281         uno::Any aNewDirection( uno::makeAny(eNewDirection) );
282 
283         sal_Bool bPercent = sal_False;
284         if( eStackMode == StackMode_Y_STACKED_PERCENT )
285             bPercent = sal_True;
286 
287         //iterate through all coordinate systems
288         uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
289         if( !xCooSysContainer.is() )
290             return;
291         uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
292         for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
293         {
294             uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
295             //set correct percent stacking
296             const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(1);
297             for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
298             {
299                 Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1,nI ));
300                 if( xAxis.is())
301                 {
302                     chart2::ScaleData aScaleData = xAxis->getScaleData();
303                     if( (aScaleData.AxisType==AxisType::PERCENT) != bPercent )
304                     {
305                         if( bPercent )
306                             aScaleData.AxisType = AxisType::PERCENT;
307                         else
308                             aScaleData.AxisType = AxisType::REALNUMBER;
309                         xAxis->setScaleData( aScaleData );
310                     }
311                 }
312             }
313             //iterate through all chart types in the current coordinate system
314             uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
315             if( !xChartTypeContainer.is() )
316                 continue;
317             uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
318             sal_Int32 nMax = aChartTypeList.getLength();
319             if( bOnlyAtFirstChartType
320                 && nMax >= 1 )
321                 nMax = 1;
322             for( sal_Int32 nT = 0; nT < nMax; ++nT )
323             {
324                 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
325 
326                 //iterate through all series in this chart type
327                 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
328                 OSL_ASSERT( xDataSeriesContainer.is());
329                 if( !xDataSeriesContainer.is() )
330                     continue;
331 
332                 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
333                 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
334                 {
335                     Reference< beans::XPropertySet > xProp( aSeriesList[nS], uno::UNO_QUERY );
336 		            if(xProp.is())
337                         xProp->setPropertyValue( C2U( "StackingDirection" ), aNewDirection );
338                 }
339             }
340         }
341     }
342     catch( uno::Exception & ex )
343     {
344         ASSERT_EXCEPTION( ex );
345     }
346 }
347 
348 StackMode DiagramHelper::getStackMode( const Reference< XDiagram > & xDiagram, bool& rbFound, bool& rbAmbiguous )
349 {
350     rbFound=false;
351     rbAmbiguous=false;
352 
353     StackMode eGlobalStackMode = StackMode_NONE;
354 
355     //iterate through all coordinate systems
356     uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
357     if( !xCooSysContainer.is() )
358         return eGlobalStackMode;
359     uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
360     for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
361     {
362         uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
363 
364         //iterate through all chart types in the current coordinate system
365         uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
366         if( !xChartTypeContainer.is() )
367             continue;
368         uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
369         for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
370         {
371             uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
372 
373             StackMode eLocalStackMode = DiagramHelper::getStackModeFromChartType(
374                 xChartType, rbFound, rbAmbiguous, xCooSys );
375 
376             if( rbFound && eLocalStackMode != eGlobalStackMode && nT>0 )
377             {
378                 rbAmbiguous = true;
379                 return eGlobalStackMode;
380             }
381 
382             eGlobalStackMode = eLocalStackMode;
383         }
384     }
385 
386     return eGlobalStackMode;
387 }
388 
389 StackMode DiagramHelper::getStackModeFromChartType(
390     const Reference< XChartType > & xChartType,
391     bool& rbFound, bool& rbAmbiguous,
392     const Reference< XCoordinateSystem > & xCorrespondingCoordinateSystem )
393 {
394     StackMode eStackMode = StackMode_NONE;
395     rbFound = false;
396     rbAmbiguous = false;
397 
398     try
399     {
400         Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW );
401         Sequence< Reference< chart2::XDataSeries > > aSeries( xDSCnt->getDataSeries());
402 
403         chart2::StackingDirection eCommonDirection = chart2::StackingDirection_NO_STACKING;
404         bool bDirectionInitialized = false;
405 
406         // first series is irrelvant for stacking, start with second, unless
407         // there is only one series
408         const sal_Int32 nSeriesCount = aSeries.getLength();
409         sal_Int32 i = (nSeriesCount == 1) ? 0: 1;
410         for( ; i<nSeriesCount; ++i )
411         {
412             rbFound = true;
413             Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY_THROW );
414             chart2::StackingDirection eCurrentDirection = eCommonDirection;
415             // property is not MAYBEVOID
416             bool bSuccess = ( xProp->getPropertyValue( C2U("StackingDirection") ) >>= eCurrentDirection );
417             OSL_ASSERT( bSuccess );
418             (void)(bSuccess);  // avoid warning in non-debug builds
419             if( ! bDirectionInitialized )
420             {
421                 eCommonDirection = eCurrentDirection;
422                 bDirectionInitialized = true;
423             }
424             else
425             {
426                 if( eCommonDirection != eCurrentDirection )
427                 {
428                     rbAmbiguous = true;
429                     break;
430                 }
431             }
432         }
433 
434         if( rbFound )
435         {
436             if( eCommonDirection == chart2::StackingDirection_Z_STACKING )
437                 eStackMode = StackMode_Z_STACKED;
438             else if( eCommonDirection == chart2::StackingDirection_Y_STACKING )
439             {
440                 eStackMode = StackMode_Y_STACKED;
441 
442                 // percent stacking
443                 if( xCorrespondingCoordinateSystem.is() )
444                 {
445                     if( 1 < xCorrespondingCoordinateSystem->getDimension() )
446                     {
447                         sal_Int32 nAxisIndex = 0;
448                         if( nSeriesCount )
449                             nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(aSeries[0]);
450 
451                         Reference< chart2::XAxis > xAxis(
452                             xCorrespondingCoordinateSystem->getAxisByDimension( 1,nAxisIndex ));
453                         if( xAxis.is())
454                         {
455                             chart2::ScaleData aScaleData = xAxis->getScaleData();
456                             if( aScaleData.AxisType==chart2::AxisType::PERCENT )
457                                 eStackMode = StackMode_Y_STACKED_PERCENT;
458                         }
459                     }
460                 }
461             }
462         }
463     }
464     catch( uno::Exception & ex )
465     {
466         ASSERT_EXCEPTION( ex );
467     }
468 
469     return eStackMode;
470 }
471 
472 sal_Int32 DiagramHelper::getDimension( const Reference< XDiagram > & xDiagram )
473 {
474     // -1: not yet set
475     sal_Int32 nResult = -1;
476 
477     try
478     {
479         Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
480         if( xCooSysCnt.is() )
481         {
482             Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
483                 xCooSysCnt->getCoordinateSystems());
484 
485             for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
486             {
487                 Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] );
488                 if(xCooSys.is())
489                 {
490                     nResult = xCooSys->getDimension();
491                     break;
492                 }
493             }
494         }
495     }
496     catch( uno::Exception & ex )
497     {
498         ASSERT_EXCEPTION( ex );
499     }
500 
501     return nResult;
502 }
503 
504 void DiagramHelper::setDimension(
505     const Reference< XDiagram > & xDiagram,
506     sal_Int32 nNewDimensionCount )
507 {
508     if( ! xDiagram.is())
509         return;
510 
511     if( DiagramHelper::getDimension( xDiagram ) == nNewDimensionCount )
512         return;
513 
514     try
515     {
516         bool rbFound = false;
517         bool rbAmbiguous = true;
518         StackMode eStackMode = DiagramHelper::getStackMode( xDiagram, rbFound, rbAmbiguous );
519         bool bIsSupportingOnlyDeepStackingFor3D=false;
520 
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 )
525         {
526             Reference< XCoordinateSystem > xOldCooSys( aCooSysList[nCS], uno::UNO_QUERY );
527             Reference< XCoordinateSystem > xNewCooSys;
528 
529             Reference< XChartTypeContainer > xChartTypeContainer( xOldCooSys, uno::UNO_QUERY );
530             if( !xChartTypeContainer.is() )
531                 continue;
532 
533             Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
534             for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
535             {
536                 Reference< XChartType > xChartType( aChartTypeList[nT], uno::UNO_QUERY );
537                 bIsSupportingOnlyDeepStackingFor3D = ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType );
538                 if(!xNewCooSys.is())
539                 {
540                     xNewCooSys = xChartType->createCoordinateSystem( nNewDimensionCount );
541                     break;
542                 }
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()
546             }
547 
548             // replace the old coordinate system at all places where it was used
549             DiagramHelper::replaceCoordinateSystem( xDiagram, xOldCooSys, xNewCooSys );
550         }
551 
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 );
557     }
558     catch( uno::Exception & ex )
559     {
560         ASSERT_EXCEPTION( ex );
561     }
562 }
563 
564 void DiagramHelper::replaceCoordinateSystem(
565     const Reference< XDiagram > & xDiagram,
566     const Reference< XCoordinateSystem > & xCooSysToReplace,
567     const Reference< XCoordinateSystem > & xReplacement )
568 {
569     OSL_ASSERT( xDiagram.is());
570     if( ! xDiagram.is())
571         return;
572 
573     // update the coordinate-system container
574     Reference< XCoordinateSystemContainer > xCont( xDiagram, uno::UNO_QUERY );
575     if( xCont.is())
576     {
577         try
578         {
579             Reference< chart2::data::XLabeledDataSequence > xCategories = DiagramHelper::getCategoriesFromDiagram( xDiagram );
580 
581             // move chart types of xCooSysToReplace to xReplacement
582             Reference< XChartTypeContainer > xCTCntCooSys( xCooSysToReplace, uno::UNO_QUERY_THROW );
583             Reference< XChartTypeContainer > xCTCntReplacement( xReplacement, uno::UNO_QUERY_THROW );
584             xCTCntReplacement->setChartTypes( xCTCntCooSys->getChartTypes());
585 
586             xCont->removeCoordinateSystem( xCooSysToReplace );
587             xCont->addCoordinateSystem( xReplacement );
588 
589             if( xCategories.is() )
590                 DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram );
591         }
592         catch( uno::Exception & ex )
593         {
594             ASSERT_EXCEPTION( ex );
595         }
596     }
597 }
598 
599 bool DiagramHelper::isSeriesAttachedToMainAxis(
600 			              const uno::Reference< chart2::XDataSeries >& xDataSeries )
601 {
602     sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
603     return (nAxisIndex==0);
604 }
605 
606 bool DiagramHelper::attachSeriesToAxis( bool bAttachToMainAxis
607 			            , const uno::Reference< chart2::XDataSeries >& xDataSeries
608                         , const uno::Reference< chart2::XDiagram >& xDiagram
609                         , const uno::Reference< uno::XComponentContext > & xContext
610                         , bool bAdaptAxes )
611 {
612     bool bChanged = false;
613 
614     //set property at axis
615     Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
616     if( !xProp.is() )
617         return bChanged;
618 
619     sal_Int32 nNewAxisIndex = bAttachToMainAxis ? 0 : 1;
620     sal_Int32 nOldAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
621     uno::Reference< chart2::XAxis > xOldAxis( DiagramHelper::getAttachedAxis( xDataSeries, xDiagram ) );
622 
623     if( nOldAxisIndex != nNewAxisIndex )
624     {
625         try
626         {
627             xProp->setPropertyValue( C2U("AttachedAxisIndex"), uno::makeAny( nNewAxisIndex ) );
628             bChanged = true;
629         }
630         catch( const uno::Exception & ex )
631         {
632             ASSERT_EXCEPTION( ex );
633         }
634     }
635 
636     if( bChanged && xDiagram.is() )
637     {
638         uno::Reference< XAxis > xAxis( AxisHelper::getAxis( 1, bAttachToMainAxis, xDiagram ) );
639         if(!xAxis.is()) //create an axis if necessary
640             xAxis = AxisHelper::createAxis( 1, bAttachToMainAxis, xDiagram, xContext );
641         if( bAdaptAxes )
642         {
643             AxisHelper::makeAxisVisible( xAxis );
644             AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis, xDiagram );
645         }
646     }
647 
648     return bChanged;
649 }
650 
651 uno::Reference< XAxis > DiagramHelper::getAttachedAxis(
652         const uno::Reference< XDataSeries >& xSeries,
653         const uno::Reference< XDiagram >& xDiagram )
654 {
655     return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries ), xDiagram );
656 }
657 
658 uno::Reference< XChartType > DiagramHelper::getChartTypeOfSeries(
659 								const uno::Reference< chart2::XDiagram >&   xDiagram
660 						      , const uno::Reference< XDataSeries >&        xGivenDataSeries )
661 {
662     if( !xGivenDataSeries.is() )
663         return 0;
664     if(!xDiagram.is())
665         return 0;
666 
667 	//iterate through the model to find the given xSeries
668 	//the found parent indicates the charttype
669 
670     //iterate through all coordinate systems
671     uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
672     if( !xCooSysContainer.is())
673         return 0;
674 
675     uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
676     for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
677     {
678         uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
679 
680         //iterate through all chart types in the current coordinate system
681         uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
682         OSL_ASSERT( xChartTypeContainer.is());
683         if( !xChartTypeContainer.is() )
684             continue;
685         uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
686         for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
687         {
688             uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
689 
690             //iterate through all series in this chart type
691             uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
692             OSL_ASSERT( xDataSeriesContainer.is());
693             if( !xDataSeriesContainer.is() )
694                 continue;
695 
696             uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
697             for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
698             {
699 			    if( xGivenDataSeries==aSeriesList[nS] )
700                     return xChartType;
701             }
702         }
703     }
704 	return 0;
705 }
706 
707 ::std::vector< Reference< XDataSeries > >
708     DiagramHelper::getDataSeriesFromDiagram(
709         const Reference< XDiagram > & xDiagram )
710 {
711     ::std::vector< Reference< XDataSeries > > aResult;
712 
713     try
714     {
715         Reference< XCoordinateSystemContainer > xCooSysCnt(
716             xDiagram, uno::UNO_QUERY_THROW );
717         Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
718             xCooSysCnt->getCoordinateSystems());
719         for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
720         {
721             Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
722             Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
723             for( sal_Int32 j=0; j<aChartTypeSeq.getLength(); ++j )
724             {
725                 Reference< XDataSeriesContainer > xDSCnt( aChartTypeSeq[j], uno::UNO_QUERY_THROW );
726                 Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
727                 ::std::copy( aSeriesSeq.getConstArray(), aSeriesSeq.getConstArray() + aSeriesSeq.getLength(),
728                              ::std::back_inserter( aResult ));
729             }
730         }
731     }
732     catch( uno::Exception & ex )
733     {
734         ASSERT_EXCEPTION( ex );
735     }
736 
737     return aResult;
738 }
739 
740 Sequence< Sequence< Reference< XDataSeries > > >
741         DiagramHelper::getDataSeriesGroups( const Reference< XDiagram > & xDiagram )
742 {
743     vector< Sequence< Reference< XDataSeries > > > aResult;
744 
745     //iterate through all coordinate systems
746     Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
747     if( xCooSysContainer.is() )
748     {
749         Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
750         for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
751         {
752             //iterate through all chart types in the current coordinate system
753             Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY );
754             if( !xChartTypeContainer.is() )
755                 continue;
756             Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
757             for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
758             {
759                 Reference< XDataSeriesContainer > xDataSeriesContainer( aChartTypeList[nT], uno::UNO_QUERY );
760                 if( !xDataSeriesContainer.is() )
761                     continue;
762                 aResult.push_back( xDataSeriesContainer->getDataSeries() );
763             }
764         }
765     }
766     return ContainerHelper::ContainerToSequence( aResult );
767 }
768 
769 Reference< XChartType >
770     DiagramHelper::getChartTypeByIndex( const Reference< XDiagram >& xDiagram, sal_Int32 nIndex )
771 {
772     Reference< XChartType > xChartType;
773 
774     //iterate through all coordinate systems
775     Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
776     if( ! xCooSysContainer.is())
777         return xChartType;
778 
779     Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
780     sal_Int32 nTypesSoFar = 0;
781     for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
782     {
783         Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY );
784         if( !xChartTypeContainer.is() )
785             continue;
786         Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
787         if( nIndex >= 0 && nIndex < (nTypesSoFar + aChartTypeList.getLength()) )
788         {
789             xChartType.set( aChartTypeList[nIndex - nTypesSoFar] );
790             break;
791         }
792         nTypesSoFar += aChartTypeList.getLength();
793     }
794 
795     return xChartType;
796 }
797 
798 namespace
799 {
800 
801 std::vector< Reference< XAxis > > lcl_getAxisHoldingCategoriesFromDiagram(
802     const Reference< XDiagram > & xDiagram )
803 {
804     std::vector< Reference< XAxis > > aRet;
805 
806     Reference< XAxis > xResult;
807     // return first x-axis as fall-back
808     Reference< XAxis > xFallBack;
809     try
810     {
811         Reference< XCoordinateSystemContainer > xCooSysCnt(
812             xDiagram, uno::UNO_QUERY_THROW );
813         Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
814             xCooSysCnt->getCoordinateSystems());
815         for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
816         {
817             Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] );
818             OSL_ASSERT( xCooSys.is());
819             for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
820             {
821                 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
822                 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
823                 {
824                     Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI );
825                     OSL_ASSERT( xAxis.is());
826                     if( xAxis.is())
827                     {
828                         ScaleData aScaleData = xAxis->getScaleData();
829                         if( aScaleData.Categories.is() || (aScaleData.AxisType == AxisType::CATEGORY) )
830                         {
831                             aRet.push_back(xAxis);
832                         }
833                         if( (nN == 0) && !xFallBack.is())
834                             xFallBack.set( xAxis );
835                     }
836                 }
837             }
838         }
839     }
840     catch( uno::Exception & ex )
841     {
842         ASSERT_EXCEPTION( ex );
843     }
844 
845     if( aRet.empty() )
846         aRet.push_back(xFallBack);
847 
848     return aRet;
849 }
850 
851 } // anonymous namespace
852 
853 bool DiagramHelper::isCategoryDiagram(
854             const Reference< XDiagram >& xDiagram )
855 {
856     try
857     {
858         Reference< XCoordinateSystemContainer > xCooSysCnt(
859             xDiagram, uno::UNO_QUERY_THROW );
860         Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
861             xCooSysCnt->getCoordinateSystems());
862         for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
863         {
864             Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] );
865             OSL_ASSERT( xCooSys.is());
866             for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
867             {
868                 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
869                 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
870                 {
871                     Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI );
872                     OSL_ASSERT( xAxis.is());
873                     if( xAxis.is())
874                     {
875                         ScaleData aScaleData = xAxis->getScaleData();
876                         if( aScaleData.AxisType == AxisType::CATEGORY || aScaleData.AxisType == AxisType::DATE )
877                             return true;
878                     }
879                 }
880             }
881         }
882     }
883     catch( uno::Exception & ex )
884     {
885         ASSERT_EXCEPTION( ex );
886     }
887 
888     return false;
889 }
890 
891 void DiagramHelper::setCategoriesToDiagram(
892     const Reference< chart2::data::XLabeledDataSequence >& xCategories,
893     const Reference< XDiagram >& xDiagram,
894     bool bSetAxisType  /* = false */,
895     bool bCategoryAxis /* = true */ )
896 {
897     std::vector< Reference< chart2::XAxis > > aCatAxes(
898         lcl_getAxisHoldingCategoriesFromDiagram( xDiagram ));
899 
900     std::vector< Reference< chart2::XAxis > >::iterator aIt( aCatAxes.begin() );
901     std::vector< Reference< chart2::XAxis > >::const_iterator aEnd( aCatAxes.end() );
902 
903     for( aIt = aCatAxes.begin(); aIt != aEnd; ++aIt )
904     {
905         Reference< chart2::XAxis > xCatAxis(*aIt);
906         if( xCatAxis.is())
907         {
908             ScaleData aScaleData( xCatAxis->getScaleData());
909             aScaleData.Categories = xCategories;
910             if( bSetAxisType )
911             {
912                 if( bCategoryAxis )
913                     aScaleData.AxisType = AxisType::CATEGORY;
914                 else if( aScaleData.AxisType == AxisType::CATEGORY || aScaleData.AxisType == AxisType::DATE )
915                     aScaleData.AxisType = AxisType::REALNUMBER;
916             }
917             xCatAxis->setScaleData( aScaleData );
918         }
919     }
920 }
921 
922 Reference< data::XLabeledDataSequence >
923     DiagramHelper::getCategoriesFromDiagram(
924         const Reference< XDiagram > & xDiagram )
925 {
926     Reference< data::XLabeledDataSequence > xResult;
927 
928     try
929     {
930         std::vector< Reference< chart2::XAxis > > aCatAxes(
931             lcl_getAxisHoldingCategoriesFromDiagram( xDiagram ));
932         std::vector< Reference< chart2::XAxis > >::iterator aIt( aCatAxes.begin() );
933         std::vector< Reference< chart2::XAxis > >::const_iterator aEnd( aCatAxes.end() );
934         //search for first categories
935         if( aIt != aEnd )
936         {
937             Reference< chart2::XAxis > xCatAxis(*aIt);
938             if( xCatAxis.is())
939             {
940                 ScaleData aScaleData( xCatAxis->getScaleData());
941                 if( aScaleData.Categories.is() )
942                 {
943                     xResult.set( aScaleData.Categories );
944                     uno::Reference<beans::XPropertySet> xProp(aScaleData.Categories->getValues(), uno::UNO_QUERY );
945                     if( xProp.is() )
946                     {
947                         try
948                         {
949                             xProp->setPropertyValue( C2U( "Role" ), uno::makeAny( C2U("categories") ) );
950                         }
951                         catch( uno::Exception & ex )
952                         {
953                             ASSERT_EXCEPTION( ex );
954                         }
955                     }
956                 }
957             }
958         }
959     }
960     catch( uno::Exception & ex )
961     {
962         ASSERT_EXCEPTION( ex );
963     }
964 
965     return xResult;
966 }
967 
968 void lcl_generateAutomaticCategoriesFromChartType(
969             Sequence< rtl::OUString >& rRet,
970             const Reference< XChartType >& xChartType )
971 {
972     if(!xChartType.is())
973         return;
974     rtl::OUString aMainSeq( xChartType->getRoleOfSequenceForSeriesLabel() );
975         Reference< XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY );
976     if( xSeriesCnt.is() )
977     {
978         Sequence< Reference< XDataSeries > > aSeriesSeq( xSeriesCnt->getDataSeries() );
979         for( sal_Int32 nS = 0; nS < aSeriesSeq.getLength(); nS++ )
980         {
981             Reference< data::XDataSource > xDataSource( aSeriesSeq[nS], uno::UNO_QUERY );
982             if( !xDataSource.is() )
983                 continue;
984             Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
985                 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aMainSeq ));
986             if( !xLabeledSeq.is() )
987                 continue;
988             Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
989             if( !xValueSeq.is() )
990                 continue;
991             rRet = xValueSeq->generateLabel( chart2::data::LabelOrigin_LONG_SIDE );
992             if( rRet.getLength() )
993                 return;
994         }
995     }
996 }
997 
998 Sequence< rtl::OUString > DiagramHelper::generateAutomaticCategoriesFromCooSys( const Reference< XCoordinateSystem > & xCooSys )
999 {
1000     Sequence< rtl::OUString > aRet;
1001 
1002     Reference< XChartTypeContainer > xTypeCntr( xCooSys, uno::UNO_QUERY );
1003     if( xTypeCntr.is() )
1004     {
1005         Sequence< Reference< XChartType > > aChartTypes( xTypeCntr->getChartTypes() );
1006         for( sal_Int32 nN=0; nN<aChartTypes.getLength(); nN++ )
1007         {
1008             lcl_generateAutomaticCategoriesFromChartType( aRet, aChartTypes[nN] );
1009             if( aRet.getLength() )
1010                 return aRet;
1011         }
1012     }
1013     return aRet;
1014 }
1015 
1016 Sequence< rtl::OUString > DiagramHelper::getExplicitSimpleCategories(
1017             const Reference< XChartDocument >& xChartDoc )
1018 {
1019     Sequence< rtl::OUString > aRet;
1020     uno::Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
1021     if(xChartModel.is())
1022     {
1023         uno::Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
1024         ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, xChartModel );
1025         aRet = aExplicitCategoriesProvider.getSimpleCategories();
1026     }
1027     return aRet;
1028 }
1029 
1030 namespace
1031 {
1032 void lcl_switchToDateCategories( const Reference< XChartDocument >& xChartDoc, const Reference< XAxis >& xAxis )
1033 {
1034     if( !xAxis.is() )
1035         return;
1036     if( !xChartDoc.is() )
1037         return;
1038 
1039     ScaleData aScale( xAxis->getScaleData() );
1040     if( xChartDoc->hasInternalDataProvider() )
1041     {
1042         //remove all content the is not of type double and remove multiple level
1043         Reference< XAnyDescriptionAccess > xDataAccess( xChartDoc->getDataProvider(), uno::UNO_QUERY );
1044         if( xDataAccess.is() )
1045         {
1046             Sequence< Sequence< Any > > aAnyCategories( xDataAccess->getAnyRowDescriptions() );
1047             double fTest = 0.0;
1048             double fNan = 0.0;
1049             ::rtl::math::setNan( & fNan );
1050             sal_Int32 nN = aAnyCategories.getLength();
1051             for( ; nN--; )
1052             {
1053                 Sequence< Any >& rCat = aAnyCategories[nN];
1054                 if( rCat.getLength() > 1 )
1055                     rCat.realloc(1);
1056                 if( rCat.getLength() == 1 )
1057                 {
1058                     Any& rAny = rCat[0];
1059                     if( !(rAny>>=fTest) )
1060                     {
1061                         rAny = uno::makeAny(fNan);
1062                     }
1063                 }
1064             }
1065             xDataAccess->setAnyRowDescriptions( aAnyCategories );
1066         }
1067         //check the numberformat at the axis
1068         Reference< beans::XPropertySet > xAxisProps( xAxis, uno::UNO_QUERY );
1069         Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartDoc, uno::UNO_QUERY );
1070         if( xAxisProps.is() && xNumberFormatsSupplier.is() )
1071         {
1072             sal_Int32 nNumberFormat = -1;
1073             xAxisProps->getPropertyValue( C2U("NumberFormat") ) >>= nNumberFormat;
1074 
1075             Reference< util::XNumberFormats > xNumberFormats = Reference< util::XNumberFormats >( xNumberFormatsSupplier->getNumberFormats() );
1076             if( xNumberFormats.is() )
1077             {
1078                 Reference< beans::XPropertySet > xKeyProps;
1079                 try
1080                 {
1081                     xKeyProps = xNumberFormats->getByKey( nNumberFormat );
1082                 }
1083                 catch( uno::Exception & ex )
1084                 {
1085                     ASSERT_EXCEPTION( ex );
1086                 }
1087                 sal_Int32 nType = util::NumberFormat::UNDEFINED;
1088                 if( xKeyProps.is() )
1089                     xKeyProps->getPropertyValue( C2U("Type") ) >>= nType;
1090                 if( !( nType & util::NumberFormat::DATE ) )
1091                 {
1092                     //set a date format to the axis
1093                     sal_Bool bCreate = sal_True;
1094                     const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
1095                     Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::DATE,  rLocaleDataWrapper.getLocale(), bCreate );
1096                     if( aKeySeq.getLength() )
1097                     {
1098                         xAxisProps->setPropertyValue( C2U("NumberFormat"), uno::makeAny(aKeySeq[0]) );
1099                     }
1100                 }
1101             }
1102         }
1103     }
1104     if( aScale.AxisType != chart2::AxisType::DATE )
1105         AxisHelper::removeExplicitScaling( aScale );
1106     aScale.AxisType = chart2::AxisType::DATE;
1107     xAxis->setScaleData( aScale );
1108 }
1109 
1110 void lcl_switchToTextCategories( const Reference< XChartDocument >& xChartDoc, const Reference< XAxis >& xAxis )
1111 {
1112     if( !xAxis.is() )
1113         return;
1114     if( !xChartDoc.is() )
1115         return;
1116     ScaleData aScale( xAxis->getScaleData() );
1117     if( aScale.AxisType != chart2::AxisType::CATEGORY )
1118         AxisHelper::removeExplicitScaling( aScale );
1119     //todo migrate dates to text?
1120     aScale.AxisType = chart2::AxisType::CATEGORY;
1121     aScale.AutoDateAxis = false;
1122     xAxis->setScaleData( aScale );
1123 }
1124 
1125 }
1126 
1127 void DiagramHelper::switchToDateCategories( const Reference< XChartDocument >& xChartDoc )
1128 {
1129     Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
1130     if(xChartModel.is())
1131     {
1132         ControllerLockGuard aCtrlLockGuard( xChartModel );
1133 
1134         Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
1135         if( xCooSys.is() )
1136         {
1137             Reference< XAxis > xAxis( xCooSys->getAxisByDimension(0,0) );
1138             lcl_switchToDateCategories( xChartDoc, xAxis );
1139         }
1140     }
1141 }
1142 
1143 void DiagramHelper::switchToTextCategories( const Reference< XChartDocument >& xChartDoc )
1144 {
1145     Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
1146     if(xChartModel.is())
1147     {
1148         ControllerLockGuard aCtrlLockGuard( xChartModel );
1149 
1150         Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
1151         if( xCooSys.is() )
1152         {
1153             Reference< XAxis > xAxis( xCooSys->getAxisByDimension(0,0) );
1154             lcl_switchToTextCategories( xChartDoc, xAxis );
1155         }
1156     }
1157 }
1158 
1159 bool DiagramHelper::isSupportingDateAxis( const Reference< chart2::XDiagram >& xDiagram )
1160 {
1161     return ::chart::ChartTypeHelper::isSupportingDateAxis(
1162             DiagramHelper::getChartTypeByIndex( xDiagram, 0 ), DiagramHelper::getDimension( xDiagram ), 0 );
1163 }
1164 
1165 bool DiagramHelper::isDateNumberFormat( sal_Int32 nNumberFormat, const Reference< util::XNumberFormats >& xNumberFormats )
1166 {
1167     bool bIsDate = false;
1168     if( !xNumberFormats.is() )
1169         return bIsDate;
1170 
1171     Reference< beans::XPropertySet > xKeyProps = xNumberFormats->getByKey( nNumberFormat );
1172     if( xKeyProps.is() )
1173     {
1174         sal_Int32 nType = util::NumberFormat::UNDEFINED;
1175         xKeyProps->getPropertyValue( C2U("Type") ) >>= nType;
1176         bIsDate = nType & util::NumberFormat::DATE;
1177     }
1178     return bIsDate;
1179 }
1180 
1181 sal_Int32 DiagramHelper::getDateNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
1182 {
1183     sal_Int32 nRet=-1;
1184     Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
1185     if( xNumberFormats.is() )
1186     {
1187         sal_Bool bCreate = sal_True;
1188         const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
1189         Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::DATE,
1190 			rLocaleDataWrapper.getLocale(), bCreate );
1191         if( aKeySeq.getLength() )
1192         {
1193             nRet = aKeySeq[0];
1194         }
1195     }
1196 
1197     //try to get a date format with full year display
1198     NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
1199     SvNumberFormatter* pNumFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
1200     if( pNumFormatter )
1201     {
1202         const SvNumberformat* pFormat = pNumFormatter->GetEntry( nRet );
1203         if( pFormat )
1204             nRet = pNumFormatter->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, pFormat->GetLanguage() );
1205     }
1206     return nRet;
1207 }
1208 
1209 sal_Int32 DiagramHelper::getPercentNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
1210 {
1211     sal_Int32 nRet=-1;
1212     Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
1213     if( xNumberFormats.is() )
1214     {
1215         sal_Bool bCreate = sal_True;
1216         const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
1217         Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::PERCENT,
1218 			rLocaleDataWrapper.getLocale(), bCreate );
1219         if( aKeySeq.getLength() )
1220         {
1221             nRet = aKeySeq[0];
1222         }
1223     }
1224     return nRet;
1225 }
1226 
1227 Sequence< Reference< XChartType > >
1228     DiagramHelper::getChartTypesFromDiagram(
1229         const Reference< XDiagram > & xDiagram )
1230 {
1231     ::std::vector< Reference< XChartType > > aResult;
1232 
1233     if(xDiagram.is())
1234     try
1235     {
1236         Reference< XCoordinateSystemContainer > xCooSysCnt(
1237             xDiagram, uno::UNO_QUERY_THROW );
1238         Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
1239             xCooSysCnt->getCoordinateSystems());
1240         for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
1241         {
1242             Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
1243             Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
1244             ::std::copy( aChartTypeSeq.getConstArray(), aChartTypeSeq.getConstArray() + aChartTypeSeq.getLength(),
1245                          ::std::back_inserter( aResult ));
1246         }
1247     }
1248     catch( uno::Exception & ex )
1249     {
1250         ASSERT_EXCEPTION( ex );
1251     }
1252 
1253     return ContainerHelper::ContainerToSequence( aResult );
1254 }
1255 
1256 bool DiagramHelper::areChartTypesCompatible( const Reference< ::chart2::XChartType >& xFirstType,
1257                 const Reference< ::chart2::XChartType >& xSecondType )
1258 {
1259     if( !xFirstType.is() || !xSecondType.is() )
1260         return false;
1261 
1262     ::std::vector< ::rtl::OUString > aFirstRoles( ContainerHelper::SequenceToVector( xFirstType->getSupportedMandatoryRoles() ) );
1263     ::std::vector< ::rtl::OUString > aSecondRoles( ContainerHelper::SequenceToVector( xSecondType->getSupportedMandatoryRoles() ) );
1264     ::std::sort( aFirstRoles.begin(), aFirstRoles.end() );
1265     ::std::sort( aSecondRoles.begin(), aSecondRoles.end() );
1266     return ( aFirstRoles == aSecondRoles );
1267 }
1268 
1269 namespace
1270 {
1271      /**
1272      * This method implements the logic of checking if a series can be moved
1273      * forward/backward. Depending on the "bDoMove" parameter the series will
1274      * be moved (bDoMove = true) or the function just will test if the
1275      * series can be moved without doing the move (bDoMove = false).
1276      *
1277      * @param xDiagram
1278      *  Reference to the diagram that contains the series.
1279      *
1280      * @param xGivenDataSeries
1281      *  Reference to the series that should moved or tested for moving.
1282      *
1283      * @param bForward
1284      *  Direction in which the series should be moved or tested for moving.
1285      *
1286      * @param bDoMove
1287      *  Should this function really move the series (true) or just test if it is
1288      *  possible (false).
1289      *
1290      *
1291      * @returns
1292      *  in case of bDoMove == true
1293      *      - True : if the move was done
1294      *      - False : the move failed
1295      *  in case of bDoMove == false
1296      *      - True : the series can be moved
1297      *      - False : the series can not be moved
1298      *
1299      */
1300 
1301 bool lcl_moveSeriesOrCheckIfMoveIsAllowed(
1302     const Reference< XDiagram >& xDiagram,
1303     const Reference< XDataSeries >& xGivenDataSeries,
1304     bool bForward,
1305     bool bDoMove )
1306 {
1307     bool bMovedOrMoveAllowed = false;
1308 
1309     try
1310     {
1311         uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
1312 
1313         //find position of series.
1314         bool bFound = false;
1315 
1316         if( xGivenDataSeries.is() && xCooSysContainer.is() )
1317         {
1318             uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
1319 
1320             for( sal_Int32 nCS = 0; !bFound && nCS < aCooSysList.getLength(); ++nCS )
1321             {
1322                 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
1323 
1324                 //iterate through all chart types in the current coordinate system
1325                 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
1326                 OSL_ASSERT( xChartTypeContainer.is());
1327                 if( !xChartTypeContainer.is() )
1328                     continue;
1329                 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
1330                 uno::Reference< XChartType > xFormerChartType;
1331 
1332                 for( sal_Int32 nT = 0; !bFound && nT < aChartTypeList.getLength(); ++nT )
1333                 {
1334                     uno::Reference< XChartType > xCurrentChartType( aChartTypeList[nT] );
1335 
1336                     //iterate through all series in this chart type
1337                     uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xCurrentChartType, uno::UNO_QUERY );
1338                     OSL_ASSERT( xDataSeriesContainer.is());
1339                     if( !xDataSeriesContainer.is() )
1340                         continue;
1341 
1342                     uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
1343 
1344                     for( sal_Int32 nS = 0; !bFound && nS < aSeriesList.getLength(); ++nS )
1345                     {
1346 
1347                         // We found the series we are interrested in !
1348                         if( xGivenDataSeries==aSeriesList[nS] )
1349                         {
1350                             sal_Int32 nOldSeriesIndex = nS;
1351                             bFound = true;
1352 
1353                             try
1354                             {
1355                                 sal_Int32 nNewSeriesIndex = nS;
1356 
1357                                 if( bForward )
1358                                     nNewSeriesIndex--;
1359                                 else
1360                                     nNewSeriesIndex++;
1361 
1362 
1363                                 if( nNewSeriesIndex >= 0 && nNewSeriesIndex < aSeriesList.getLength() )
1364                                 {
1365                                     //move series in the same charttype
1366                                     bMovedOrMoveAllowed = true;
1367                                     if( bDoMove )
1368                                     {
1369                                         aSeriesList[ nOldSeriesIndex ] = aSeriesList[ nNewSeriesIndex ];
1370                                         aSeriesList[ nNewSeriesIndex ] = xGivenDataSeries;
1371                                         xDataSeriesContainer->setDataSeries( aSeriesList );
1372                                     }
1373                                 }
1374                                 else if( nNewSeriesIndex<0 )
1375                                 {
1376                                     //exchange series with former charttype
1377                                     if( xFormerChartType.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType, xCurrentChartType ) )
1378                                     {
1379                                         bMovedOrMoveAllowed = true;
1380                                         if( bDoMove )
1381                                         {
1382                                             uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xFormerChartType, uno::UNO_QUERY );
1383                                             if( xOtherDataSeriesContainer.is() )
1384                                             {
1385                                                 uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() );
1386                                                 sal_Int32 nOtherSeriesIndex = aOtherSeriesList.getLength()-1;
1387                                                 if( nOtherSeriesIndex >= 0 && nOtherSeriesIndex < aOtherSeriesList.getLength() )
1388                                                 {
1389                                                     uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] );
1390                                                     aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries;
1391                                                     xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList);
1392 
1393                                                     aSeriesList[nOldSeriesIndex]=xExchangeSeries;
1394                                                     xDataSeriesContainer->setDataSeries(aSeriesList);
1395                                                 }
1396                                             }
1397                                         }
1398                                     }
1399                                 }
1400                                 else if( nT+1 < aChartTypeList.getLength() )
1401                                 {
1402                                     //exchange series with next charttype
1403                                     uno::Reference< XChartType > xOtherChartType( aChartTypeList[nT+1] );
1404                                     if( xOtherChartType.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType, xCurrentChartType ) )
1405                                     {
1406                                         bMovedOrMoveAllowed = true;
1407                                         if( bDoMove )
1408                                         {
1409                                             uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xOtherChartType, uno::UNO_QUERY );
1410                                             if( xOtherDataSeriesContainer.is() )
1411                                             {
1412                                                 uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() );
1413                                                 sal_Int32 nOtherSeriesIndex = 0;
1414                                                 if( nOtherSeriesIndex >= 0 && nOtherSeriesIndex < aOtherSeriesList.getLength() )
1415                                                 {
1416                                                     uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] );
1417                                                     aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries;
1418                                                     xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList);
1419 
1420                                                     aSeriesList[nOldSeriesIndex]=xExchangeSeries;
1421                                                     xDataSeriesContainer->setDataSeries(aSeriesList);
1422                                                 }
1423                                             }
1424                                         }
1425                                     }
1426                                 }
1427                             }
1428                             catch( util::CloseVetoException& )
1429                             {
1430                             }
1431                             catch( uno::RuntimeException& )
1432                             {
1433                             }
1434                         }
1435                     }
1436                     xFormerChartType = xCurrentChartType;
1437                 }
1438             }
1439         }
1440     }
1441     catch( util::CloseVetoException& )
1442     {
1443     }
1444     catch( uno::RuntimeException& )
1445     {
1446     }
1447     return bMovedOrMoveAllowed;
1448 }
1449 } // anonymous namespace
1450 
1451 
1452 bool DiagramHelper::isSeriesMoveable(
1453     const Reference< XDiagram >& xDiagram,
1454     const Reference< XDataSeries >& xGivenDataSeries,
1455     bool bForward )
1456 {
1457     bool bIsMoveable = false;
1458     const bool bDoMove = false;
1459 
1460     bIsMoveable = lcl_moveSeriesOrCheckIfMoveIsAllowed(
1461         xDiagram, xGivenDataSeries, bForward, bDoMove );
1462 
1463     return bIsMoveable;
1464 }
1465 
1466 
1467 bool DiagramHelper::moveSeries( const Reference< XDiagram >& xDiagram, const Reference< XDataSeries >& xGivenDataSeries, bool bForward )
1468 {
1469     bool bMoved = false;
1470     const bool bDoMove = true;
1471 
1472     bMoved = lcl_moveSeriesOrCheckIfMoveIsAllowed(
1473         xDiagram, xGivenDataSeries, bForward, bDoMove );
1474 
1475     return bMoved;
1476 }
1477 
1478 bool DiagramHelper::isSupportingFloorAndWall( const Reference<
1479                 chart2::XDiagram >& xDiagram )
1480 {
1481     //pies and donuts currently do not support this because of wrong files from older versions
1482     //todo: allow this in future again, if fileversion are available for ole objects (metastream)
1483     //thus the wrong bottom can be removed on import
1484 
1485     Sequence< Reference< chart2::XChartType > > aTypes(
1486             ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ) );
1487     for( sal_Int32 nN = 0; nN < aTypes.getLength(); nN++ )
1488     {
1489         Reference< chart2::XChartType > xType( aTypes[nN] );
1490         if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
1491             return false;
1492         if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
1493             return false;
1494         if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
1495             return false;
1496     }
1497     return true;
1498 }
1499 
1500 bool DiagramHelper::isPieOrDonutChart( const ::com::sun::star::uno::Reference<
1501                 ::com::sun::star::chart2::XDiagram >& xDiagram )
1502 {
1503     uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex(
1504         xDiagram, 0 ) );
1505 
1506     if( xChartType .is() )
1507     {
1508         rtl::OUString aChartType = xChartType->getChartType();
1509         if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
1510             return true;
1511     }
1512     return false;
1513 }
1514 
1515 sal_Int32 DiagramHelper::getGeometry3D(
1516     const uno::Reference< chart2::XDiagram > & xDiagram,
1517     bool& rbFound, bool& rbAmbiguous )
1518 {
1519     sal_Int32 nCommonGeom( DataPointGeometry3D::CUBOID );
1520     rbFound = false;
1521     rbAmbiguous = false;
1522 
1523     ::std::vector< Reference< chart2::XDataSeries > > aSeriesVec(
1524         DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
1525 
1526     if( aSeriesVec.empty())
1527         rbAmbiguous = true;
1528 
1529     for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt =
1530              aSeriesVec.begin(); aIt != aSeriesVec.end(); ++aIt )
1531     {
1532         try
1533         {
1534             sal_Int32 nGeom = 0;
1535             Reference< beans::XPropertySet > xProp( *aIt, uno::UNO_QUERY_THROW );
1536             if( xProp->getPropertyValue( C2U( "Geometry3D" )) >>= nGeom )
1537             {
1538                 if( ! rbFound )
1539                 {
1540                     // first series
1541                     nCommonGeom = nGeom;
1542                     rbFound = true;
1543                 }
1544                 // further series: compare for uniqueness
1545                 else if( nCommonGeom != nGeom )
1546                 {
1547                     rbAmbiguous = true;
1548                     break;
1549                 }
1550             }
1551         }
1552         catch( uno::Exception & ex )
1553         {
1554             ASSERT_EXCEPTION( ex );
1555         }
1556     }
1557 
1558     return nCommonGeom;
1559 }
1560 
1561 void DiagramHelper::setGeometry3D(
1562     const Reference< chart2::XDiagram > & xDiagram,
1563     sal_Int32 nNewGeometry )
1564 {
1565     ::std::vector< Reference< chart2::XDataSeries > > aSeriesVec(
1566         DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
1567 
1568     for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt =
1569              aSeriesVec.begin(); aIt != aSeriesVec.end(); ++aIt )
1570     {
1571         DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(
1572             *aIt, C2U( "Geometry3D" ), uno::makeAny( nNewGeometry ));
1573     }
1574 }
1575 
1576 sal_Int32 DiagramHelper::getCorrectedMissingValueTreatment(
1577             const Reference< chart2::XDiagram > & xDiagram,
1578             const Reference< chart2::XChartType >& xChartType )
1579 {
1580     sal_Int32 nResult = ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP;
1581     uno::Sequence < sal_Int32 > aAvailableMissingValueTreatments(
1582                 ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) );
1583 
1584     uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
1585     if( xDiaProp.is() && (xDiaProp->getPropertyValue( C2U( "MissingValueTreatment" ) ) >>= nResult) )
1586     {
1587         //ensure that the set value is supported by this charttype
1588         for( sal_Int32 nN = 0; nN < aAvailableMissingValueTreatments.getLength(); nN++ )
1589             if( aAvailableMissingValueTreatments[nN] == nResult )
1590                 return nResult; //ok
1591     }
1592 
1593     //otherwise use the first supported one
1594     if( aAvailableMissingValueTreatments.getLength() )
1595     {
1596         nResult = aAvailableMissingValueTreatments[0];
1597         return nResult;
1598     }
1599 
1600     return nResult;
1601 }
1602 
1603 DiagramPositioningMode DiagramHelper::getDiagramPositioningMode( const uno::Reference<
1604                 chart2::XDiagram > & xDiagram )
1605 {
1606     DiagramPositioningMode eMode = DiagramPositioningMode_AUTO;
1607     uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY );
1608     if( xDiaProps.is() )
1609     {
1610         RelativePosition aRelPos;
1611         RelativeSize aRelSize;
1612         if( (xDiaProps->getPropertyValue(C2U("RelativePosition")) >>= aRelPos ) &&
1613             (xDiaProps->getPropertyValue(C2U("RelativeSize")) >>= aRelSize ) )
1614         {
1615             bool bPosSizeExcludeAxes=false;
1616             xDiaProps->getPropertyValue(C2U("PosSizeExcludeAxes")) >>= bPosSizeExcludeAxes;
1617             if( bPosSizeExcludeAxes )
1618                 eMode = DiagramPositioningMode_EXCLUDING;
1619             else
1620                 eMode = DiagramPositioningMode_INCLUDING;
1621         }
1622     }
1623     return eMode;
1624 }
1625 
1626 void lcl_ensureRange0to1( double& rValue )
1627 {
1628     if(rValue<0.0)
1629         rValue=0.0;
1630     if(rValue>1.0)
1631         rValue=1.0;
1632 }
1633 
1634 bool DiagramHelper::setDiagramPositioning( const uno::Reference< frame::XModel >& xChartModel,
1635         const awt::Rectangle& rPosRect /*100th mm*/ )
1636 {
1637     ControllerLockGuard aCtrlLockGuard( xChartModel );
1638 
1639     bool bChanged = false;
1640     awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) );
1641     uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY );
1642     if( !xDiaProps.is() )
1643         return bChanged;
1644 
1645     RelativePosition aOldPos;
1646     RelativeSize aOldSize;
1647     xDiaProps->getPropertyValue(C2U("RelativePosition") ) >>= aOldPos;
1648     xDiaProps->getPropertyValue(C2U("RelativeSize") ) >>= aOldSize;
1649 
1650     RelativePosition aNewPos;
1651     aNewPos.Anchor = drawing::Alignment_TOP_LEFT;
1652     aNewPos.Primary = double(rPosRect.X)/double(aPageSize.Width);
1653     aNewPos.Secondary = double(rPosRect.Y)/double(aPageSize.Height);
1654 
1655     chart2::RelativeSize aNewSize;
1656     aNewSize.Primary = double(rPosRect.Width)/double(aPageSize.Width);
1657     aNewSize.Secondary = double(rPosRect.Height)/double(aPageSize.Height);
1658 
1659     lcl_ensureRange0to1( aNewPos.Primary );
1660     lcl_ensureRange0to1( aNewPos.Secondary );
1661     lcl_ensureRange0to1( aNewSize.Primary );
1662     lcl_ensureRange0to1( aNewSize.Secondary );
1663     if( (aNewPos.Primary + aNewSize.Primary) > 1.0 )
1664         aNewPos.Primary = 1.0 - aNewSize.Primary;
1665     if( (aNewPos.Secondary + aNewSize.Secondary) > 1.0 )
1666         aNewPos.Secondary = 1.0 - aNewSize.Secondary;
1667 
1668     xDiaProps->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aNewPos) );
1669     xDiaProps->setPropertyValue( C2U( "RelativeSize" ), uno::makeAny(aNewSize) );
1670 
1671     bChanged = (aOldPos.Anchor!=aNewPos.Anchor) ||
1672         (aOldPos.Primary!=aNewPos.Primary) ||
1673         (aOldPos.Secondary!=aNewPos.Secondary) ||
1674         (aOldSize.Primary!=aNewSize.Primary) ||
1675         (aOldSize.Secondary!=aNewSize.Secondary);
1676     return bChanged;
1677 }
1678 
1679 awt::Rectangle DiagramHelper::getDiagramRectangleFromModel( const uno::Reference< frame::XModel >& xChartModel )
1680 {
1681     awt::Rectangle aRet(-1,-1,-1,-1);
1682 
1683     uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY );
1684     if( !xDiaProps.is() )
1685         return aRet;
1686 
1687     awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) );
1688 
1689     RelativePosition aRelPos;
1690     RelativeSize aRelSize;
1691     xDiaProps->getPropertyValue(C2U("RelativePosition") ) >>= aRelPos;
1692     xDiaProps->getPropertyValue(C2U("RelativeSize") ) >>= aRelSize;
1693 
1694     awt::Size aAbsSize(
1695         static_cast< sal_Int32 >( aRelSize.Primary * aPageSize.Width ),
1696         static_cast< sal_Int32 >( aRelSize.Secondary * aPageSize.Height ));
1697 
1698     awt::Point aAbsPos(
1699         static_cast< sal_Int32 >( aRelPos.Primary * aPageSize.Width ),
1700         static_cast< sal_Int32 >( aRelPos.Secondary * aPageSize.Height ));
1701 
1702     awt::Point aAbsPosLeftTop = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( aAbsPos, aAbsSize, aRelPos.Anchor );
1703 
1704     aRet = awt::Rectangle(aAbsPosLeftTop.X, aAbsPosLeftTop.Y, aAbsSize.Width, aAbsSize.Height );
1705 
1706     return aRet;
1707 }
1708 
1709 bool DiagramHelper::switchDiagramPositioningToExcludingPositioning(
1710     const uno::Reference< frame::XModel >& xChartModel
1711     , bool bResetModifiedState, bool bConvertAlsoFromAutoPositioning )
1712 {
1713     //return true if something was changed
1714     const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1715     if( nCurrentODFVersion == SvtSaveOptions::ODFVER_LATEST )//#i100778# todo: change this dependent on fileformat evolution
1716     {
1717         uno::Reference< ::com::sun::star::chart::XChartDocument > xOldDoc( xChartModel, uno::UNO_QUERY ) ;
1718         if( xOldDoc.is() )
1719         {
1720             uno::Reference< ::com::sun::star::chart::XDiagramPositioning > xDiagramPositioning( xOldDoc->getDiagram(), uno::UNO_QUERY );
1721             if( xDiagramPositioning.is() && ( bConvertAlsoFromAutoPositioning || !xDiagramPositioning->isAutomaticDiagramPositioning() )
1722                 && !xDiagramPositioning->isExcludingDiagramPositioning() )
1723             {
1724                 ControllerLockGuard aCtrlLockGuard( xChartModel );
1725                 uno::Reference< util::XModifiable > xModifiable( xChartModel, uno::UNO_QUERY );
1726                 bool bModelWasModified = xModifiable.is() && xModifiable->isModified();
1727                 xDiagramPositioning->setDiagramPositionExcludingAxes( xDiagramPositioning->calculateDiagramPositionExcludingAxes() );
1728                 if(bResetModifiedState && !bModelWasModified && xModifiable.is() )
1729                     xModifiable->setModified(sal_False);
1730                 return true;
1731             }
1732         }
1733     }
1734     return false;
1735 }
1736 
1737 } //  namespace chart
1738