bump product version to 4.1.6.2
[LibreOffice.git] / chart2 / source / tools / AxisHelper.cxx
blob8a769f808f3ae29a6b963611a9d742e2ed1a8a96
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "AxisHelper.hxx"
22 #include "DiagramHelper.hxx"
23 #include "ChartTypeHelper.hxx"
24 #include "macros.hxx"
25 #include "AxisIndexDefines.hxx"
26 #include "LinePropertiesHelper.hxx"
27 #include "ContainerHelper.hxx"
28 #include "servicenames_coosystems.hxx"
29 #include "DataSeriesHelper.hxx"
30 #include "Scaling.hxx"
31 #include "ChartModelHelper.hxx"
32 #include "DataSourceHelper.hxx"
34 #include <unotools/saveopt.hxx>
36 #include <com/sun/star/chart/ChartAxisPosition.hpp>
38 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
39 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
40 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
41 #include <com/sun/star/chart2/data/XDataSource.hpp>
43 // header for class OUStringBuffer
44 #include <rtl/ustrbuf.hxx>
45 #include <rtl/math.hxx>
47 #include <com/sun/star/util/XCloneable.hpp>
48 #include <com/sun/star/lang/XServiceName.hpp>
50 #include <map>
52 //.............................................................................
53 namespace chart
55 //.............................................................................
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::chart2;
58 using ::com::sun::star::uno::Reference;
59 using ::com::sun::star::uno::Sequence;
61 Reference< chart2::XScaling > AxisHelper::createLinearScaling()
63 return new LinearScaling( 1.0, 0.0 );
66 Reference< chart2::XScaling > AxisHelper::createLogarithmicScaling( double fBase )
68 return new LogarithmicScaling( fBase );
71 ScaleData AxisHelper::createDefaultScale()
73 ScaleData aScaleData;
74 aScaleData.AxisType = chart2::AxisType::REALNUMBER;
75 aScaleData.AutoDateAxis = true;
76 aScaleData.ShiftedCategoryPosition = false;//this is adapted in the view code currently
77 Sequence< SubIncrement > aSubIncrements(1);
78 aSubIncrements[0] = SubIncrement();
79 aScaleData.IncrementData.SubIncrements = aSubIncrements;
80 return aScaleData;
83 void AxisHelper::removeExplicitScaling( ScaleData& rScaleData )
85 uno::Any aEmpty;
86 rScaleData.Minimum = rScaleData.Maximum = rScaleData.Origin = aEmpty;
87 rScaleData.Scaling = 0;
88 ScaleData aDefaultScale( createDefaultScale() );
89 rScaleData.IncrementData = aDefaultScale.IncrementData;
90 rScaleData.TimeIncrement = aDefaultScale.TimeIncrement;
93 bool AxisHelper::isLogarithmic( const Reference< XScaling >& xScaling )
95 bool bReturn = false;
96 Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY );
97 bReturn =( xServiceName.is() && (xServiceName->getServiceName()).equals(
98 "com.sun.star.chart2.LogarithmicScaling"));
99 return bReturn;
102 chart2::ScaleData AxisHelper::getDateCheckedScale( const Reference< chart2::XAxis >& xAxis, const Reference< frame::XModel >& xChartModel )
104 OSL_ENSURE(xChartModel.is(),"missing chart model");
105 ScaleData aScale = xAxis->getScaleData();
106 Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
107 if( aScale.AutoDateAxis && aScale.AxisType == AxisType::CATEGORY )
109 sal_Int32 nDimensionIndex=0; sal_Int32 nAxisIndex=0;
110 AxisHelper::getIndicesForAxis(xAxis, xCooSys, nDimensionIndex, nAxisIndex );
111 bool bChartTypeAllowsDateAxis = ChartTypeHelper::isSupportingDateAxis( AxisHelper::getChartTypeByIndex( xCooSys, 0 ), 2, nDimensionIndex );
112 if( bChartTypeAllowsDateAxis )
113 aScale.AxisType = AxisType::DATE;
115 if( aScale.AxisType == AxisType::DATE )
117 ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys,xChartModel );
118 if( !aExplicitCategoriesProvider.isDateAxis() )
119 aScale.AxisType = AxisType::CATEGORY;
121 return aScale;
124 void AxisHelper::checkDateAxis( chart2::ScaleData& rScale, ExplicitCategoriesProvider* pExplicitCategoriesProvider, bool bChartTypeAllowsDateAxis )
126 if( rScale.AutoDateAxis && rScale.AxisType == AxisType::CATEGORY && bChartTypeAllowsDateAxis )
128 rScale.AxisType = AxisType::DATE;
129 removeExplicitScaling( rScale );
131 if( rScale.AxisType == AxisType::DATE && (!pExplicitCategoriesProvider || !pExplicitCategoriesProvider->isDateAxis()) )
133 rScale.AxisType = AxisType::CATEGORY;
134 removeExplicitScaling( rScale );
138 sal_Int32 AxisHelper::getExplicitNumberFormatKeyForAxis(
139 const Reference< chart2::XAxis >& xAxis
140 , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
141 , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
142 , bool bSearchForParallelAxisIfNothingIsFound )
144 sal_Int32 nNumberFormatKey(0);
145 bool bNumberFormatKeyFoundViaAttachedData = false;
146 sal_Int32 nAxisIndex = 0;
147 sal_Int32 nDimensionIndex = 1;
148 AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex );
149 Reference< chart2::XChartDocument > xChartDoc( xNumberFormatsSupplier, uno::UNO_QUERY );
151 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
152 if( xProp.is() && !( xProp->getPropertyValue( "NumberFormat" ) >>= nNumberFormatKey ) )
154 bool bFormatSet = false;
155 //check whether we have a percent scale -> use percent format
156 if( xNumberFormatsSupplier.is() )
158 ScaleData aData = AxisHelper::getDateCheckedScale( xAxis, Reference< frame::XModel >( xNumberFormatsSupplier, uno::UNO_QUERY ) );
159 if( aData.AxisType==AxisType::PERCENT )
161 sal_Int32 nPercentFormat = DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier );
162 if( nPercentFormat != -1 )
164 nNumberFormatKey = nPercentFormat;
165 bFormatSet = true;
168 else if( aData.AxisType==AxisType::DATE )
170 if( aData.Categories.is() )
172 Reference< data::XDataSequence > xSeq( aData.Categories->getValues());
173 if( xSeq.is() && !( xChartDoc.is() && xChartDoc->hasInternalDataProvider()) )
174 nNumberFormatKey = xSeq->getNumberFormatKeyByIndex( -1 );
175 else
176 nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
177 bFormatSet = true;
180 else if( xChartDoc.is() && xChartDoc->hasInternalDataProvider() && nDimensionIndex == 0 ) //maybe date axis
182 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram() );
183 if( DiagramHelper::isSupportingDateAxis( xDiagram ) )
185 nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
187 else
189 Reference< data::XDataSource > xSource( DataSourceHelper::getUsedData( xChartDoc ) );
190 if( xSource.is() )
192 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aXValues(
193 DataSeriesHelper::getAllDataSequencesByRole( xSource->getDataSequences(), "values-x", true ) );
194 if( aXValues.empty() )
196 Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) );
197 if( xCategories.is() )
199 Reference< data::XDataSequence > xSeq( xCategories->getValues());
200 if( xSeq.is() )
202 bool bHasValidDoubles = false;
203 double fTest=0.0;
204 Sequence< uno::Any > aCats( xSeq->getData() );
205 sal_Int32 nCount = aCats.getLength();
206 for( sal_Int32 i = 0; i < nCount; ++i )
208 if( (aCats[i]>>=fTest) && !::rtl::math::isNan(fTest) )
210 bHasValidDoubles=true;
211 break;
214 if( bHasValidDoubles )
215 nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
221 bFormatSet = true;
225 if( !bFormatSet )
227 typedef ::std::map< sal_Int32, sal_Int32 > tNumberformatFrequency;
228 tNumberformatFrequency aKeyMap;
232 Reference< XChartTypeContainer > xCTCnt( xCorrespondingCoordinateSystem, uno::UNO_QUERY_THROW );
233 if( xCTCnt.is() )
235 OUString aRoleToMatch;
236 if( nDimensionIndex == 0 )
237 aRoleToMatch = "values-x";
238 Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes());
239 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
241 if( nDimensionIndex != 0 )
242 aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( aChartTypes[nCTIdx] );
243 Reference< XDataSeriesContainer > xDSCnt( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
244 Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries());
245 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aDataSeriesSeq.getLength(); ++nSeriesIdx )
247 Reference< chart2::XDataSeries > xDataSeries(aDataSeriesSeq[nSeriesIdx]);
248 Reference< data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY_THROW );
250 if( nDimensionIndex == 1 )
252 //only take those series into accoutn that are attached to this axis
253 sal_Int32 nAttachedAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
254 if( nAttachedAxisIndex != nAxisIndex )
255 continue;
258 Reference< data::XLabeledDataSequence > xLabeledSeq(
259 DataSeriesHelper::getDataSequenceByRole( xSource, aRoleToMatch ) );
261 if( !xLabeledSeq.is() && nDimensionIndex==0 )
263 ScaleData aData = xAxis->getScaleData();
264 xLabeledSeq = aData.Categories;
267 if( xLabeledSeq.is() )
269 Reference< data::XDataSequence > xSeq( xLabeledSeq->getValues());
270 if( xSeq.is() )
272 sal_Int32 nKey = xSeq->getNumberFormatKeyByIndex( -1 );
273 // initialize the value
274 if( aKeyMap.find( nKey ) == aKeyMap.end())
275 aKeyMap[ nKey ] = 0;
276 // increase frequency
277 aKeyMap[ nKey ] = (aKeyMap[ nKey ] + 1);
284 catch( const uno::Exception & ex )
286 ASSERT_EXCEPTION( ex );
289 if( ! aKeyMap.empty())
291 sal_Int32 nMaxFreq = 0;
292 // find most frequent key
293 for( tNumberformatFrequency::const_iterator aIt = aKeyMap.begin();
294 aIt != aKeyMap.end(); ++aIt )
296 OSL_TRACE( "NumberFormatKey %d appears %d times", (*aIt).first, (*aIt).second );
297 // all values must at least be 1
298 if( (*aIt).second > nMaxFreq )
300 nNumberFormatKey = (*aIt).first;
301 bNumberFormatKeyFoundViaAttachedData = true;
302 nMaxFreq = (*aIt).second;
307 if( bSearchForParallelAxisIfNothingIsFound )
309 //no format is set to this axis and no data is set to this axis
310 //--> try to obtain the format from the parallel y-axis
311 if( !bNumberFormatKeyFoundViaAttachedData && nDimensionIndex == 1 )
313 sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
314 Reference< XAxis > xParallelAxis( AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem ) );
315 nNumberFormatKey = AxisHelper::getExplicitNumberFormatKeyForAxis( xParallelAxis, xCorrespondingCoordinateSystem, xNumberFormatsSupplier, false );
320 return nNumberFormatKey;
323 Reference< XAxis > AxisHelper::createAxis(
324 sal_Int32 nDimensionIndex
325 , sal_Int32 nAxisIndex // 0==main or 1==secondary axis
326 , const Reference< XCoordinateSystem >& xCooSys
327 , const Reference< uno::XComponentContext > & xContext
328 , ReferenceSizeProvider * pRefSizeProvider )
330 if( !xContext.is() || !xCooSys.is() )
331 return NULL;
332 if( nDimensionIndex >= xCooSys->getDimension() )
333 return NULL;
335 Reference< XAxis > xAxis( xContext->getServiceManager()->createInstanceWithContext(
336 "com.sun.star.chart2.Axis", xContext ), uno::UNO_QUERY );
338 OSL_ASSERT( xAxis.is());
339 if( xAxis.is())
341 xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
343 if( nAxisIndex>0 )//when inserting secondary axes copy some things from the main axis
345 ::com::sun::star::chart::ChartAxisPosition eNewAxisPos( ::com::sun::star::chart::ChartAxisPosition_END );
347 Reference< XAxis > xMainAxis( xCooSys->getAxisByDimension( nDimensionIndex, 0 ) );
348 if( xMainAxis.is() )
350 ScaleData aScale = xAxis->getScaleData();
351 ScaleData aMainScale = xMainAxis->getScaleData();
353 aScale.AxisType = aMainScale.AxisType;
354 aScale.AutoDateAxis = aMainScale.AutoDateAxis;
355 aScale.Categories = aMainScale.Categories;
356 aScale.Orientation = aMainScale.Orientation;
358 xAxis->setScaleData( aScale );
360 //ensure that the second axis is not placed on the main axis
361 Reference< beans::XPropertySet > xMainProp( xMainAxis, uno::UNO_QUERY );
362 if( xMainProp.is() )
364 ::com::sun::star::chart::ChartAxisPosition eMainAxisPos( ::com::sun::star::chart::ChartAxisPosition_ZERO );
365 xMainProp->getPropertyValue("CrossoverPosition") >>= eMainAxisPos;
366 if( ::com::sun::star::chart::ChartAxisPosition_END == eMainAxisPos )
367 eNewAxisPos = ::com::sun::star::chart::ChartAxisPosition_START;
371 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
372 if( xProp.is() )
373 xProp->setPropertyValue("CrossoverPosition", uno::makeAny(eNewAxisPos) );
376 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
377 if( xProp.is() ) try
379 // set correct initial AutoScale
380 if( pRefSizeProvider )
381 pRefSizeProvider->setValuesAtPropertySet( xProp );
383 catch( const uno::Exception& e )
385 ASSERT_EXCEPTION( e );
388 return xAxis;
391 Reference< XAxis > AxisHelper::createAxis( sal_Int32 nDimensionIndex, bool bMainAxis
392 , const Reference< chart2::XDiagram >& xDiagram
393 , const Reference< uno::XComponentContext >& xContext
394 , ReferenceSizeProvider * pRefSizeProvider )
396 OSL_ENSURE( xContext.is(), "need a context to create an axis" );
397 if( !xContext.is() )
398 return NULL;
400 sal_Int32 nAxisIndex = bMainAxis ? MAIN_AXIS_INDEX : SECONDARY_AXIS_INDEX;
401 sal_Int32 nCooSysIndex = 0;
402 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
404 // create axis
405 return AxisHelper::createAxis(
406 nDimensionIndex, nAxisIndex, xCooSys, xContext, pRefSizeProvider );
409 void AxisHelper::showAxis( sal_Int32 nDimensionIndex, bool bMainAxis
410 , const Reference< chart2::XDiagram >& xDiagram
411 , const Reference< uno::XComponentContext >& xContext
412 , ReferenceSizeProvider * pRefSizeProvider )
414 if( !xDiagram.is() )
415 return;
417 bool bNewAxisCreated = false;
418 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
419 if( !xAxis.is() && xContext.is() )
421 // create axis
422 bNewAxisCreated = true;
423 xAxis.set( AxisHelper::createAxis( nDimensionIndex, bMainAxis, xDiagram, xContext, pRefSizeProvider ) );
426 OSL_ASSERT( xAxis.is());
427 if( !bNewAxisCreated ) //default is true already if created
428 AxisHelper::makeAxisVisible( xAxis );
431 void AxisHelper::showGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
432 , const Reference< XDiagram >& xDiagram
433 , const Reference< uno::XComponentContext >& /*xContext*/ )
435 if( !xDiagram.is() )
436 return;
438 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
439 if(!xCooSys.is())
440 return;
442 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
443 if(!xAxis.is())
445 //hhhh todo create axis without axis visibility
447 if(!xAxis.is())
448 return;
450 if( bMainGrid )
451 AxisHelper::makeGridVisible( xAxis->getGridProperties() );
452 else
454 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
455 for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++)
456 AxisHelper::makeGridVisible( aSubGrids[nN] );
460 void AxisHelper::makeAxisVisible( const Reference< XAxis >& xAxis )
462 Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
463 if( xProps.is() )
465 xProps->setPropertyValue( "Show", uno::makeAny( sal_True ) );
466 LinePropertiesHelper::SetLineVisible( xProps );
467 xProps->setPropertyValue( "DisplayLabels", uno::makeAny( sal_True ) );
471 void AxisHelper::makeGridVisible( const Reference< beans::XPropertySet >& xGridProperties )
473 if( xGridProperties.is() )
475 xGridProperties->setPropertyValue( "Show", uno::makeAny( sal_True ) );
476 LinePropertiesHelper::SetLineVisible( xGridProperties );
480 void AxisHelper::hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis
481 , const Reference< XDiagram >& xDiagram )
483 AxisHelper::makeAxisInvisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
486 void AxisHelper::makeAxisInvisible( const Reference< XAxis >& xAxis )
488 Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
489 if( xProps.is() )
491 xProps->setPropertyValue( "Show", uno::makeAny( sal_False ) );
495 void AxisHelper::hideAxisIfNoDataIsAttached( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram )
497 //axis is hidden if no data is attached anymore but data is available
498 bool bOtherSeriesAttachedToThisAxis = false;
499 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
500 ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt = aSeriesVector.begin();
501 for( ; aIt != aSeriesVector.end(); ++aIt)
503 uno::Reference< chart2::XAxis > xCurrentAxis( DiagramHelper::getAttachedAxis( *aIt, xDiagram ), uno::UNO_QUERY );
504 if( xCurrentAxis==xAxis )
506 bOtherSeriesAttachedToThisAxis = true;
507 break;
510 if(!bOtherSeriesAttachedToThisAxis && !aSeriesVector.empty() )
511 AxisHelper::makeAxisInvisible( xAxis );
514 void AxisHelper::hideGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
515 , const Reference< XDiagram >& xDiagram )
517 if( !xDiagram.is() )
518 return;
520 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
521 if(!xCooSys.is())
522 return;
524 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
525 if(!xAxis.is())
526 return;
528 if( bMainGrid )
529 AxisHelper::makeGridInvisible( xAxis->getGridProperties() );
530 else
532 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
533 for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++)
534 AxisHelper::makeGridInvisible( aSubGrids[nN] );
538 void AxisHelper::makeGridInvisible( const Reference< beans::XPropertySet >& xGridProperties )
540 if( xGridProperties.is() )
542 xGridProperties->setPropertyValue( "Show", uno::makeAny( sal_False ) );
546 sal_Bool AxisHelper::isGridShown( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
547 , const Reference< ::com::sun::star::chart2::XDiagram >& xDiagram )
549 sal_Bool bRet = false;
551 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
552 if(!xCooSys.is())
553 return bRet;
555 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
556 if(!xAxis.is())
557 return bRet;
559 if( bMainGrid )
560 bRet = AxisHelper::isGridVisible( xAxis->getGridProperties() );
561 else
563 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
564 if( aSubGrids.getLength() )
565 bRet = AxisHelper::isGridVisible( aSubGrids[0] );
568 return bRet;
571 Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemByIndex(
572 const Reference< XDiagram >& xDiagram, sal_Int32 nIndex )
574 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
575 if(!xCooSysContainer.is())
576 return NULL;
577 Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
578 if(0<=nIndex && nIndex<aCooSysList.getLength())
579 return aCooSysList[nIndex];
580 return NULL;
583 Reference< XAxis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, bool bMainAxis
584 , const Reference< XDiagram >& xDiagram )
586 Reference< XAxis > xRet;
589 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 );
590 xRet.set( AxisHelper::getAxis( nDimensionIndex, bMainAxis ? 0 : 1, xCooSys ) );
592 catch( const uno::Exception & )
595 return xRet;
598 Reference< XAxis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex
599 , const Reference< XCoordinateSystem >& xCooSys )
601 Reference< XAxis > xRet;
604 if( xCooSys.is() )
605 xRet.set( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
607 catch( const uno::Exception & )
610 return xRet;
613 Reference< XAxis > AxisHelper::getCrossingMainAxis( const Reference< XAxis >& xAxis
614 , const Reference< XCoordinateSystem >& xCooSys )
616 sal_Int32 nDimensionIndex = 0;
617 sal_Int32 nAxisIndex = 0;
618 AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex );
619 if( 2==nDimensionIndex )
621 nDimensionIndex=1;
622 bool bSwapXY = false;
623 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
624 if( xCooSysProp.is() && (xCooSysProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXY) && bSwapXY )
625 nDimensionIndex=0;
627 else if( 1==nDimensionIndex )
628 nDimensionIndex=0;
629 else
630 nDimensionIndex=1;
631 return AxisHelper::getAxis( nDimensionIndex, 0, xCooSys );
634 Reference< XAxis > AxisHelper::getParallelAxis( const Reference< XAxis >& xAxis
635 , const Reference< XDiagram >& xDiagram )
639 sal_Int32 nCooSysIndex=-1;
640 sal_Int32 nDimensionIndex=-1;
641 sal_Int32 nAxisIndex=-1;
642 if( getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ) )
644 sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
645 return getAxis( nDimensionIndex, nParallelAxisIndex, getCoordinateSystemByIndex( xDiagram, nCooSysIndex ) );
648 catch( const uno::RuntimeException& )
651 return 0;
654 sal_Bool AxisHelper::isAxisShown( sal_Int32 nDimensionIndex, bool bMainAxis
655 , const Reference< XDiagram >& xDiagram )
657 return AxisHelper::isAxisVisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
660 sal_Bool AxisHelper::isAxisVisible( const Reference< XAxis >& xAxis )
662 sal_Bool bRet = false;
664 Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
665 if( xProps.is() )
667 xProps->getPropertyValue( "Show" ) >>= bRet;
668 bRet = bRet && ( LinePropertiesHelper::IsLineVisible( xProps )
669 || areAxisLabelsVisible( xProps ) );
672 return bRet;
675 sal_Bool AxisHelper::areAxisLabelsVisible( const Reference< beans::XPropertySet >& xAxisProperties )
677 sal_Bool bRet = false;
678 if( xAxisProperties.is() )
680 xAxisProperties->getPropertyValue( "DisplayLabels" ) >>= bRet;
682 return bRet;
685 sal_Bool AxisHelper::isGridVisible( const Reference< beans::XPropertySet >& xGridProperies )
687 sal_Bool bRet = false;
689 if( xGridProperies.is() )
691 xGridProperies->getPropertyValue( "Show" ) >>= bRet;
692 bRet = bRet && LinePropertiesHelper::IsLineVisible( xGridProperies );
695 return bRet;
698 Reference< beans::XPropertySet > AxisHelper::getGridProperties(
699 const Reference< XCoordinateSystem >& xCooSys
700 , sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex, sal_Int32 nSubGridIndex )
702 Reference< beans::XPropertySet > xRet;
704 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) );
705 if( xAxis.is() )
707 if( nSubGridIndex<0 )
708 xRet.set( xAxis->getGridProperties() );
709 else
711 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
712 if( nSubGridIndex >= 0 && nSubGridIndex < aSubGrids.getLength() )
713 xRet.set( aSubGrids[nSubGridIndex] );
717 return xRet;
720 sal_Int32 AxisHelper::getDimensionIndexOfAxis(
721 const Reference< XAxis >& xAxis
722 , const Reference< XDiagram >& xDiagram )
724 sal_Int32 nDimensionIndex = -1;
725 sal_Int32 nCooSysIndex = -1;
726 sal_Int32 nAxisIndex = -1;
727 AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex , nDimensionIndex, nAxisIndex );
728 return nDimensionIndex;
731 bool AxisHelper::getIndicesForAxis(
732 const Reference< XAxis >& xAxis
733 , const Reference< XCoordinateSystem >& xCooSys
734 , sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
736 //returns true if indices are found
738 rOutDimensionIndex = -1;
739 rOutAxisIndex = -1;
741 if( xCooSys.is() && xAxis.is() )
743 Reference< XAxis > xCurrentAxis;
744 sal_Int32 nDimensionCount( xCooSys->getDimension() );
745 for( sal_Int32 nDimensionIndex = 0; nDimensionIndex < nDimensionCount; nDimensionIndex++ )
747 sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
748 for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ )
750 xCurrentAxis = xCooSys->getAxisByDimension(nDimensionIndex,nAxisIndex);
751 if( xCurrentAxis == xAxis )
753 rOutDimensionIndex = nDimensionIndex;
754 rOutAxisIndex = nAxisIndex;
755 return true;
760 return false;
763 bool AxisHelper::getIndicesForAxis( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram
764 , sal_Int32& rOutCooSysIndex, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
766 //returns true if indices are found
768 rOutCooSysIndex = -1;
769 rOutDimensionIndex = -1;
770 rOutAxisIndex = -1;
772 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
773 if(xCooSysContainer.is())
775 Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
776 for( sal_Int32 nC=0; nC<aCooSysList.getLength(); ++nC )
778 if( AxisHelper::getIndicesForAxis( xAxis, aCooSysList[nC], rOutDimensionIndex, rOutAxisIndex ) )
780 rOutCooSysIndex = nC;
781 return true;
786 return false;
789 std::vector< Reference< XAxis > > AxisHelper::getAllAxesOfCoordinateSystem(
790 const Reference< XCoordinateSystem >& xCooSys
791 , bool bOnlyVisible /* = false */ )
793 std::vector< Reference< XAxis > > aAxisVector;
795 if(xCooSys.is())
797 sal_Int32 nMaxDimensionIndex = xCooSys->getDimension() -1;
798 if( nMaxDimensionIndex>=0 )
800 sal_Int32 nDimensionIndex = 0;
801 for(; nDimensionIndex<=nMaxDimensionIndex; ++nDimensionIndex)
803 const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
804 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
808 Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
809 bool bAddAxis = true;
810 if( xAxis.is() )
812 if( bOnlyVisible )
814 Reference< beans::XPropertySet > xAxisProp( xAxis, uno::UNO_QUERY );
815 if( !xAxisProp.is() ||
816 !(xAxisProp->getPropertyValue( "Show") >>= bAddAxis) )
817 bAddAxis = false;
819 if( bAddAxis )
820 aAxisVector.push_back( xAxis );
823 catch( const uno::Exception & ex )
825 ASSERT_EXCEPTION( ex );
832 return aAxisVector;
835 Sequence< Reference< XAxis > > AxisHelper::getAllAxesOfDiagram(
836 const Reference< XDiagram >& xDiagram
837 , bool bOnlyVisible )
839 std::vector< Reference< XAxis > > aAxisVector;
841 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
842 if(xCooSysContainer.is())
844 Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
845 sal_Int32 nC = 0;
846 for( nC=0; nC<aCooSysList.getLength(); ++nC )
848 std::vector< Reference< XAxis > > aAxesPerCooSys( AxisHelper::getAllAxesOfCoordinateSystem( aCooSysList[nC], bOnlyVisible ) );
849 aAxisVector.insert( aAxisVector.end(), aAxesPerCooSys.begin(), aAxesPerCooSys.end() );
853 return ContainerHelper::ContainerToSequence( aAxisVector );
856 Sequence< Reference< beans::XPropertySet > > AxisHelper::getAllGrids( const Reference< XDiagram >& xDiagram )
858 Sequence< Reference< XAxis > > aAllAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
859 std::vector< Reference< beans::XPropertySet > > aGridVector;
861 sal_Int32 nA = 0;
862 for( nA=0; nA<aAllAxes.getLength(); ++nA )
864 Reference< XAxis > xAxis( aAllAxes[nA] );
865 if(!xAxis.is())
866 continue;
867 Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
868 if( xGridProperties.is() )
869 aGridVector.push_back( xGridProperties );
871 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );;
872 sal_Int32 nSubGrid = 0;
873 for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid )
875 Reference< beans::XPropertySet > xSubGrid( aSubGrids[nSubGrid] );
876 if( xSubGrid.is() )
877 aGridVector.push_back( xSubGrid );
881 return ContainerHelper::ContainerToSequence( aGridVector );
884 void AxisHelper::getAxisOrGridPossibilities( Sequence< sal_Bool >& rPossibilityList
885 , const Reference< XDiagram>& xDiagram, sal_Bool bAxis )
887 rPossibilityList.realloc(6);
889 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
891 //set possibilities:
892 sal_Int32 nIndex=0;
893 Reference< XChartType > xChartType = DiagramHelper::getChartTypeByIndex( xDiagram, 0 );
894 for(nIndex=0;nIndex<3;nIndex++)
895 rPossibilityList[nIndex]=ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nIndex);
896 for(nIndex=3;nIndex<6;nIndex++)
897 if( bAxis )
898 rPossibilityList[nIndex]=ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount,nIndex-3);
899 else
900 rPossibilityList[nIndex] = rPossibilityList[nIndex-3];
903 bool AxisHelper::isSecondaryYAxisNeeded( const Reference< XCoordinateSystem >& xCooSys )
905 Reference< chart2::XChartTypeContainer > xCTCnt( xCooSys, uno::UNO_QUERY );
906 if( xCTCnt.is() )
908 Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes() );
909 for( sal_Int32 i=0; i<aChartTypes.getLength(); ++i )
911 Reference< XDataSeriesContainer > xSeriesContainer( aChartTypes[i] , uno::UNO_QUERY );
912 if( !xSeriesContainer.is() )
913 continue;
915 Sequence< Reference< XDataSeries > > aSeriesList( xSeriesContainer->getDataSeries() );
916 for( sal_Int32 nS = aSeriesList.getLength(); nS-- ; )
918 Reference< beans::XPropertySet > xProp( aSeriesList[nS], uno::UNO_QUERY );
919 if(xProp.is())
921 sal_Int32 nAttachedAxisIndex = 0;
922 if( ( xProp->getPropertyValue( "AttachedAxisIndex" ) >>= nAttachedAxisIndex ) && nAttachedAxisIndex>0 )
923 return true;
928 return false;
931 bool AxisHelper::shouldAxisBeDisplayed( const Reference< XAxis >& xAxis
932 , const Reference< XCoordinateSystem >& xCooSys )
934 bool bRet = false;
936 if( xAxis.is() && xCooSys.is() )
938 sal_Int32 nDimensionIndex=-1;
939 sal_Int32 nAxisIndex=-1;
940 if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
942 sal_Int32 nDimensionCount = xCooSys->getDimension();
943 Reference< XChartType > xChartType( AxisHelper::getChartTypeByIndex( xCooSys, 0 ) );
945 bool bMainAxis = (nAxisIndex==MAIN_AXIS_INDEX);
946 if( bMainAxis )
947 bRet = ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nDimensionIndex);
948 else
949 bRet = ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount,nDimensionIndex);
953 return bRet;
956 void AxisHelper::getAxisOrGridExcistence( Sequence< sal_Bool >& rExistenceList
957 , const Reference< XDiagram>& xDiagram, sal_Bool bAxis )
959 rExistenceList.realloc(6);
961 if(bAxis)
963 sal_Int32 nN;
964 Reference< XAxis > xAxis;
965 for(nN=0;nN<3;nN++)
966 rExistenceList[nN] = AxisHelper::isAxisShown( nN, true, xDiagram );
967 for(nN=3;nN<6;nN++)
968 rExistenceList[nN] = AxisHelper::isAxisShown( nN%3, false, xDiagram );
970 else
972 sal_Int32 nN;
974 for(nN=0;nN<3;nN++)
975 rExistenceList[nN] = AxisHelper::isGridShown( nN, 0, true, xDiagram );
976 for(nN=3;nN<6;nN++)
977 rExistenceList[nN] = AxisHelper::isGridShown( nN%3, 0, false, xDiagram );
981 bool AxisHelper::changeVisibilityOfAxes( const Reference< XDiagram >& xDiagram
982 , const Sequence< sal_Bool >& rOldExistenceList
983 , const Sequence< sal_Bool >& rNewExistenceList
984 , const Reference< uno::XComponentContext >& xContext
985 , ReferenceSizeProvider * pRefSizeProvider )
987 bool bChanged = false;
988 for(sal_Int32 nN=0;nN<6;nN++)
990 if(rOldExistenceList[nN]!=rNewExistenceList[nN])
992 bChanged = true;
993 if(rNewExistenceList[nN])
995 AxisHelper::showAxis( nN%3, nN<3, xDiagram, xContext, pRefSizeProvider );
997 else
998 AxisHelper::hideAxis( nN%3, nN<3, xDiagram );
1001 return bChanged;
1004 bool AxisHelper::changeVisibilityOfGrids( const Reference< XDiagram >& xDiagram
1005 , const Sequence< sal_Bool >& rOldExistenceList
1006 , const Sequence< sal_Bool >& rNewExistenceList
1007 , const Reference< uno::XComponentContext >& xContext )
1009 bool bChanged = false;
1010 for(sal_Int32 nN=0;nN<6;nN++)
1012 if(rOldExistenceList[nN]!=rNewExistenceList[nN])
1014 bChanged = true;
1015 if(rNewExistenceList[nN])
1016 AxisHelper::showGrid( nN%3, 0, nN<3, xDiagram, xContext );
1017 else
1018 AxisHelper::hideGrid( nN%3, 0, nN<3, xDiagram );
1021 return bChanged;
1024 Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemOfAxis(
1025 const Reference< XAxis >& xAxis
1026 , const Reference< XDiagram >& xDiagram )
1028 Reference< XCoordinateSystem > xRet;
1030 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
1031 if( xCooSysContainer.is() )
1033 Reference< XCoordinateSystem > xCooSys;
1034 Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
1035 for( sal_Int32 nCooSysIndex = 0; nCooSysIndex < aCooSysList.getLength(); ++nCooSysIndex )
1037 xCooSys = aCooSysList[nCooSysIndex];
1038 std::vector< Reference< XAxis > > aAllAxis( AxisHelper::getAllAxesOfCoordinateSystem( xCooSys ) );
1040 ::std::vector< Reference< XAxis > >::iterator aFound =
1041 ::std::find( aAllAxis.begin(), aAllAxis.end(), xAxis );
1042 if( aFound != aAllAxis.end())
1044 xRet.set( xCooSys );
1045 break;
1049 return xRet;
1052 Reference< XChartType > AxisHelper::getChartTypeByIndex( const Reference< XCoordinateSystem >& xCooSys, sal_Int32 nIndex )
1054 Reference< XChartType > xChartType;
1056 Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
1057 if( xChartTypeContainer.is() )
1059 Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
1060 if( nIndex >= 0 && nIndex < aChartTypeList.getLength() )
1061 xChartType.set( aChartTypeList[nIndex] );
1064 return xChartType;
1067 void AxisHelper::setRTLAxisLayout( const Reference< XCoordinateSystem >& xCooSys )
1069 if( xCooSys.is() )
1071 bool bCartesian = xCooSys->getViewServiceName().equals( CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME );
1072 if( bCartesian )
1074 bool bVertical = false;
1075 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
1076 if( xCooSysProp.is() )
1077 xCooSysProp->getPropertyValue( "SwapXAndYAxis" ) >>= bVertical;
1079 sal_Int32 nHorizontalAxisDimension = bVertical ? 1 : 0;
1080 sal_Int32 nVerticalAxisDimension = bVertical ? 0 : 1;
1084 //reverse direction for horizontal main axis
1085 Reference< chart2::XAxis > xHorizontalMainAxis( AxisHelper::getAxis( nHorizontalAxisDimension, MAIN_AXIS_INDEX, xCooSys ) );
1086 if( xHorizontalMainAxis.is() )
1088 chart2::ScaleData aScale = xHorizontalMainAxis->getScaleData();
1089 aScale.Orientation = chart2::AxisOrientation_REVERSE;
1090 xHorizontalMainAxis->setScaleData(aScale);
1093 //mathematical direction for vertical main axis
1094 Reference< chart2::XAxis > xVerticalMainAxis( AxisHelper::getAxis( nVerticalAxisDimension, MAIN_AXIS_INDEX, xCooSys ) );
1095 if( xVerticalMainAxis.is() )
1097 chart2::ScaleData aScale = xVerticalMainAxis->getScaleData();
1098 aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
1099 xVerticalMainAxis->setScaleData(aScale);
1102 catch( const uno::Exception & ex )
1104 ASSERT_EXCEPTION( ex );
1109 //reverse direction for horizontal secondary axis
1110 Reference< chart2::XAxis > xHorizontalSecondaryAxis( AxisHelper::getAxis( nHorizontalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys ) );
1111 if( xHorizontalSecondaryAxis.is() )
1113 chart2::ScaleData aScale = xHorizontalSecondaryAxis->getScaleData();
1114 aScale.Orientation = chart2::AxisOrientation_REVERSE;
1115 xHorizontalSecondaryAxis->setScaleData(aScale);
1118 //mathematical direction for vertical secondary axis
1119 Reference< chart2::XAxis > xVerticalSecondaryAxis( AxisHelper::getAxis( nVerticalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys ) );
1120 if( xVerticalSecondaryAxis.is() )
1122 chart2::ScaleData aScale = xVerticalSecondaryAxis->getScaleData();
1123 aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
1124 xVerticalSecondaryAxis->setScaleData(aScale);
1127 catch( const uno::Exception & ex )
1129 ASSERT_EXCEPTION( ex );
1135 Reference< XChartType > AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( const Reference< chart2::XDiagram >& xDiagram, const sal_Int32 nAttachedAxisIndex )
1137 Reference< XChartType > xChartType;
1138 ::std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
1139 ::std::vector< Reference< XDataSeries > >::const_iterator aIter = aSeriesVector.begin();
1140 for( ; aIter != aSeriesVector.end(); ++aIter )
1142 sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex( *aIter );
1143 if( nAttachedAxisIndex == nCurrentIndex )
1145 xChartType = DiagramHelper::getChartTypeOfSeries( xDiagram, *aIter );
1146 if(xChartType.is())
1147 break;
1150 return xChartType;
1153 bool AxisHelper::isAxisPositioningEnabled()
1155 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
1156 return nCurrentVersion >= SvtSaveOptions::ODFVER_012;
1159 //.............................................................................
1160 } //namespace chart
1161 //.............................................................................
1163 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */