bump product version to 5.0.4.1
[LibreOffice.git] / chart2 / source / tools / AxisHelper.cxx
blob045ba71cce0e3e1456af94a046b841a17ca52a12
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 .
20 #include "AxisHelper.hxx"
21 #include "DiagramHelper.hxx"
22 #include "ChartTypeHelper.hxx"
23 #include "macros.hxx"
24 #include "AxisIndexDefines.hxx"
25 #include "LinePropertiesHelper.hxx"
26 #include "ContainerHelper.hxx"
27 #include "servicenames_coosystems.hxx"
28 #include "DataSeriesHelper.hxx"
29 #include "Scaling.hxx"
30 #include "ChartModelHelper.hxx"
31 #include "DataSourceHelper.hxx"
32 #include <unonames.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 #include <rtl/ustrbuf.hxx>
44 #include <rtl/math.hxx>
46 #include <com/sun/star/util/XCloneable.hpp>
47 #include <com/sun/star/lang/XServiceName.hpp>
49 #include <map>
51 namespace chart
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::chart2;
55 using ::com::sun::star::uno::Reference;
56 using ::com::sun::star::uno::Sequence;
58 Reference< chart2::XScaling > AxisHelper::createLinearScaling()
60 return new LinearScaling( 1.0, 0.0 );
63 Reference< chart2::XScaling > AxisHelper::createLogarithmicScaling( double fBase )
65 return new LogarithmicScaling( fBase );
68 ScaleData AxisHelper::createDefaultScale()
70 ScaleData aScaleData;
71 aScaleData.AxisType = chart2::AxisType::REALNUMBER;
72 aScaleData.AutoDateAxis = true;
73 aScaleData.ShiftedCategoryPosition = false;//this is adapted in the view code currently
74 Sequence< SubIncrement > aSubIncrements(1);
75 aSubIncrements[0] = SubIncrement();
76 aScaleData.IncrementData.SubIncrements = aSubIncrements;
77 return aScaleData;
80 void AxisHelper::removeExplicitScaling( ScaleData& rScaleData )
82 uno::Any aEmpty;
83 rScaleData.Minimum = rScaleData.Maximum = rScaleData.Origin = aEmpty;
84 rScaleData.Scaling = 0;
85 ScaleData aDefaultScale( createDefaultScale() );
86 rScaleData.IncrementData = aDefaultScale.IncrementData;
87 rScaleData.TimeIncrement = aDefaultScale.TimeIncrement;
90 bool AxisHelper::isLogarithmic( const Reference< XScaling >& xScaling )
92 Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY );
93 return xServiceName.is()
94 && xServiceName->getServiceName() == "com.sun.star.chart2.LogarithmicScaling";
97 chart2::ScaleData AxisHelper::getDateCheckedScale( const Reference< chart2::XAxis >& xAxis, ChartModel& rModel )
99 ScaleData aScale = xAxis->getScaleData();
100 Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( rModel ) );
101 if( aScale.AutoDateAxis && aScale.AxisType == AxisType::CATEGORY )
103 sal_Int32 nDimensionIndex=0; sal_Int32 nAxisIndex=0;
104 AxisHelper::getIndicesForAxis(xAxis, xCooSys, nDimensionIndex, nAxisIndex );
105 bool bChartTypeAllowsDateAxis = ChartTypeHelper::isSupportingDateAxis( AxisHelper::getChartTypeByIndex( xCooSys, 0 ), 2, nDimensionIndex );
106 if( bChartTypeAllowsDateAxis )
107 aScale.AxisType = AxisType::DATE;
109 if( aScale.AxisType == AxisType::DATE )
111 ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, rModel );
112 if( !aExplicitCategoriesProvider.isDateAxis() )
113 aScale.AxisType = AxisType::CATEGORY;
115 return aScale;
118 void AxisHelper::checkDateAxis( chart2::ScaleData& rScale, ExplicitCategoriesProvider* pExplicitCategoriesProvider, bool bChartTypeAllowsDateAxis )
120 if( rScale.AutoDateAxis && rScale.AxisType == AxisType::CATEGORY && bChartTypeAllowsDateAxis )
122 rScale.AxisType = AxisType::DATE;
123 removeExplicitScaling( rScale );
125 if( rScale.AxisType == AxisType::DATE && (!pExplicitCategoriesProvider || !pExplicitCategoriesProvider->isDateAxis()) )
127 rScale.AxisType = AxisType::CATEGORY;
128 removeExplicitScaling( rScale );
132 sal_Int32 AxisHelper::getExplicitNumberFormatKeyForAxis(
133 const Reference< chart2::XAxis >& xAxis
134 , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
135 , const Reference<chart2::XChartDocument>& xChartDoc
136 , bool bSearchForParallelAxisIfNothingIsFound )
138 sal_Int32 nNumberFormatKey(0);
139 sal_Int32 nAxisIndex = 0;
140 sal_Int32 nDimensionIndex = 1;
141 AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex );
142 Reference<util::XNumberFormatsSupplier> const xNumberFormatsSupplier(xChartDoc, uno::UNO_QUERY);
144 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
145 if (!xProp.is())
146 return 0;
148 bool bLinkToSource = true;
149 xProp->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource;
150 xProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormatKey;
152 sal_Int32 nOldNumberFormat = nNumberFormatKey;
154 if (bLinkToSource)
156 bool bFormatSet = false;
157 //check whether we have a percent scale -> use percent format
158 ChartModel* pModel = NULL;
159 if( xNumberFormatsSupplier.is() )
161 pModel = dynamic_cast<ChartModel*>( xChartDoc.get() );
162 assert(pModel);
164 if (pModel)
166 ScaleData aData = AxisHelper::getDateCheckedScale( xAxis, *pModel );
167 if( aData.AxisType==AxisType::PERCENT )
169 sal_Int32 nPercentFormat = DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier );
170 if( nPercentFormat != -1 )
172 nNumberFormatKey = nPercentFormat;
173 bFormatSet = true;
176 else if( aData.AxisType==AxisType::DATE )
178 if( aData.Categories.is() )
180 Reference< data::XDataSequence > xSeq( aData.Categories->getValues());
181 if( xSeq.is() && !( xChartDoc.is() && xChartDoc->hasInternalDataProvider()) )
182 nNumberFormatKey = xSeq->getNumberFormatKeyByIndex( -1 );
183 else
184 nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
185 bFormatSet = true;
188 else if( xChartDoc.is() && xChartDoc->hasInternalDataProvider() && nDimensionIndex == 0 ) //maybe date axis
190 Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram() );
191 if( DiagramHelper::isSupportingDateAxis( xDiagram ) )
193 nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
195 else
197 Reference< data::XDataSource > xSource( DataSourceHelper::getUsedData( xChartDoc ) );
198 if( xSource.is() )
200 ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aXValues(
201 DataSeriesHelper::getAllDataSequencesByRole( xSource->getDataSequences(), "values-x", true ) );
202 if( aXValues.empty() )
204 Reference< data::XLabeledDataSequence > xCategories( DiagramHelper::getCategoriesFromDiagram( xDiagram ) );
205 if( xCategories.is() )
207 Reference< data::XDataSequence > xSeq( xCategories->getValues());
208 if( xSeq.is() )
210 bool bHasValidDoubles = false;
211 double fTest=0.0;
212 Sequence< uno::Any > aCats( xSeq->getData() );
213 sal_Int32 nCount = aCats.getLength();
214 for( sal_Int32 i = 0; i < nCount; ++i )
216 if( (aCats[i]>>=fTest) && !::rtl::math::isNan(fTest) )
218 bHasValidDoubles=true;
219 break;
222 if( bHasValidDoubles )
223 nNumberFormatKey = DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
229 bFormatSet = true;
233 if( !bFormatSet )
235 typedef ::std::map< sal_Int32, sal_Int32 > tNumberformatFrequency;
236 tNumberformatFrequency aKeyMap;
237 bool bNumberFormatKeyFoundViaAttachedData = false;
241 Reference< XChartTypeContainer > xCTCnt( xCorrespondingCoordinateSystem, uno::UNO_QUERY_THROW );
242 if( xCTCnt.is() )
244 OUString aRoleToMatch;
245 if( nDimensionIndex == 0 )
246 aRoleToMatch = "values-x";
247 Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes());
248 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
250 if( nDimensionIndex != 0 )
251 aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( aChartTypes[nCTIdx] );
252 Reference< XDataSeriesContainer > xDSCnt( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
253 Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries());
254 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aDataSeriesSeq.getLength(); ++nSeriesIdx )
256 Reference< chart2::XDataSeries > xDataSeries(aDataSeriesSeq[nSeriesIdx]);
257 Reference< data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY_THROW );
259 if( nDimensionIndex == 1 )
261 //only take those series into accoutn that are attached to this axis
262 sal_Int32 nAttachedAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
263 if( nAttachedAxisIndex != nAxisIndex )
264 continue;
267 Reference< data::XLabeledDataSequence > xLabeledSeq(
268 DataSeriesHelper::getDataSequenceByRole( xSource, aRoleToMatch ) );
270 if( !xLabeledSeq.is() && nDimensionIndex==0 )
272 ScaleData aData = xAxis->getScaleData();
273 xLabeledSeq = aData.Categories;
276 if( xLabeledSeq.is() )
278 Reference< data::XDataSequence > xSeq( xLabeledSeq->getValues());
279 if( xSeq.is() )
281 sal_Int32 nKey = xSeq->getNumberFormatKeyByIndex( -1 );
282 // initialize the value
283 if( aKeyMap.find( nKey ) == aKeyMap.end())
284 aKeyMap[ nKey ] = 0;
285 // increase frequency
286 aKeyMap[ nKey ] = (aKeyMap[ nKey ] + 1);
293 catch( const uno::Exception & ex )
295 ASSERT_EXCEPTION( ex );
298 if( ! aKeyMap.empty())
300 sal_Int32 nMaxFreq = 0;
301 // find most frequent key
302 for( tNumberformatFrequency::const_iterator aIt = aKeyMap.begin();
303 aIt != aKeyMap.end(); ++aIt )
305 SAL_INFO(
306 "chart2.tools",
307 "NumberFormatKey " << (*aIt).first << " appears "
308 << (*aIt).second << " times");
309 // all values must at least be 1
310 if( (*aIt).second > nMaxFreq )
312 nNumberFormatKey = (*aIt).first;
313 bNumberFormatKeyFoundViaAttachedData = true;
314 nMaxFreq = (*aIt).second;
319 if( bSearchForParallelAxisIfNothingIsFound )
321 //no format is set to this axis and no data is set to this axis
322 //--> try to obtain the format from the parallel y-axis
323 if( !bNumberFormatKeyFoundViaAttachedData && nDimensionIndex == 1 )
325 sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
326 Reference< XAxis > xParallelAxis( AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem ) );
327 nNumberFormatKey = AxisHelper::getExplicitNumberFormatKeyForAxis(xParallelAxis, xCorrespondingCoordinateSystem, xChartDoc, false);
332 if (nOldNumberFormat != nNumberFormatKey)
333 xProp->setPropertyValue(CHART_UNONAME_NUMFMT, uno::makeAny(nNumberFormatKey));
336 return nNumberFormatKey;
339 Reference< XAxis > AxisHelper::createAxis(
340 sal_Int32 nDimensionIndex
341 , sal_Int32 nAxisIndex // 0==main or 1==secondary axis
342 , const Reference< XCoordinateSystem >& xCooSys
343 , const Reference< uno::XComponentContext > & xContext
344 , ReferenceSizeProvider * pRefSizeProvider )
346 if( !xContext.is() || !xCooSys.is() )
347 return NULL;
348 if( nDimensionIndex >= xCooSys->getDimension() )
349 return NULL;
351 Reference< XAxis > xAxis( xContext->getServiceManager()->createInstanceWithContext(
352 "com.sun.star.chart2.Axis", xContext ), uno::UNO_QUERY );
354 OSL_ASSERT( xAxis.is());
355 if( xAxis.is())
357 xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
359 if( nAxisIndex>0 )//when inserting secondary axes copy some things from the main axis
361 ::com::sun::star::chart::ChartAxisPosition eNewAxisPos( ::com::sun::star::chart::ChartAxisPosition_END );
363 Reference< XAxis > xMainAxis( xCooSys->getAxisByDimension( nDimensionIndex, 0 ) );
364 if( xMainAxis.is() )
366 ScaleData aScale = xAxis->getScaleData();
367 ScaleData aMainScale = xMainAxis->getScaleData();
369 aScale.AxisType = aMainScale.AxisType;
370 aScale.AutoDateAxis = aMainScale.AutoDateAxis;
371 aScale.Categories = aMainScale.Categories;
372 aScale.Orientation = aMainScale.Orientation;
374 xAxis->setScaleData( aScale );
376 //ensure that the second axis is not placed on the main axis
377 Reference< beans::XPropertySet > xMainProp( xMainAxis, uno::UNO_QUERY );
378 if( xMainProp.is() )
380 ::com::sun::star::chart::ChartAxisPosition eMainAxisPos( ::com::sun::star::chart::ChartAxisPosition_ZERO );
381 xMainProp->getPropertyValue("CrossoverPosition") >>= eMainAxisPos;
382 if( ::com::sun::star::chart::ChartAxisPosition_END == eMainAxisPos )
383 eNewAxisPos = ::com::sun::star::chart::ChartAxisPosition_START;
387 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
388 if( xProp.is() )
389 xProp->setPropertyValue("CrossoverPosition", uno::makeAny(eNewAxisPos) );
392 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
393 if( xProp.is() ) try
395 // set correct initial AutoScale
396 if( pRefSizeProvider )
397 pRefSizeProvider->setValuesAtPropertySet( xProp );
399 catch( const uno::Exception& e )
401 ASSERT_EXCEPTION( e );
404 return xAxis;
407 Reference< XAxis > AxisHelper::createAxis( sal_Int32 nDimensionIndex, bool bMainAxis
408 , const Reference< chart2::XDiagram >& xDiagram
409 , const Reference< uno::XComponentContext >& xContext
410 , ReferenceSizeProvider * pRefSizeProvider )
412 OSL_ENSURE( xContext.is(), "need a context to create an axis" );
413 if( !xContext.is() )
414 return NULL;
416 sal_Int32 nAxisIndex = bMainAxis ? MAIN_AXIS_INDEX : SECONDARY_AXIS_INDEX;
417 sal_Int32 nCooSysIndex = 0;
418 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
420 // create axis
421 return AxisHelper::createAxis(
422 nDimensionIndex, nAxisIndex, xCooSys, xContext, pRefSizeProvider );
425 void AxisHelper::showAxis( sal_Int32 nDimensionIndex, bool bMainAxis
426 , const Reference< chart2::XDiagram >& xDiagram
427 , const Reference< uno::XComponentContext >& xContext
428 , ReferenceSizeProvider * pRefSizeProvider )
430 if( !xDiagram.is() )
431 return;
433 bool bNewAxisCreated = false;
434 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
435 if( !xAxis.is() && xContext.is() )
437 // create axis
438 bNewAxisCreated = true;
439 xAxis.set( AxisHelper::createAxis( nDimensionIndex, bMainAxis, xDiagram, xContext, pRefSizeProvider ) );
442 OSL_ASSERT( xAxis.is());
443 if( !bNewAxisCreated ) //default is true already if created
444 AxisHelper::makeAxisVisible( xAxis );
447 void AxisHelper::showGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
448 , const Reference< XDiagram >& xDiagram
449 , const Reference< uno::XComponentContext >& /*xContext*/ )
451 if( !xDiagram.is() )
452 return;
454 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
455 if(!xCooSys.is())
456 return;
458 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
459 if(!xAxis.is())
461 //hhhh todo create axis without axis visibility
463 if(!xAxis.is())
464 return;
466 if( bMainGrid )
467 AxisHelper::makeGridVisible( xAxis->getGridProperties() );
468 else
470 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
471 for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++)
472 AxisHelper::makeGridVisible( aSubGrids[nN] );
476 void AxisHelper::makeAxisVisible( const Reference< XAxis >& xAxis )
478 Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
479 if( xProps.is() )
481 xProps->setPropertyValue( "Show", uno::makeAny( sal_True ) );
482 LinePropertiesHelper::SetLineVisible( xProps );
483 xProps->setPropertyValue( "DisplayLabels", uno::makeAny( sal_True ) );
487 void AxisHelper::makeGridVisible( const Reference< beans::XPropertySet >& xGridProperties )
489 if( xGridProperties.is() )
491 xGridProperties->setPropertyValue( "Show", uno::makeAny( sal_True ) );
492 LinePropertiesHelper::SetLineVisible( xGridProperties );
496 void AxisHelper::hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis
497 , const Reference< XDiagram >& xDiagram )
499 AxisHelper::makeAxisInvisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
502 void AxisHelper::makeAxisInvisible( const Reference< XAxis >& xAxis )
504 Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
505 if( xProps.is() )
507 xProps->setPropertyValue( "Show", uno::makeAny( sal_False ) );
511 void AxisHelper::hideAxisIfNoDataIsAttached( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram )
513 //axis is hidden if no data is attached anymore but data is available
514 bool bOtherSeriesAttachedToThisAxis = false;
515 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
516 ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt = aSeriesVector.begin();
517 for( ; aIt != aSeriesVector.end(); ++aIt)
519 uno::Reference< chart2::XAxis > xCurrentAxis( DiagramHelper::getAttachedAxis( *aIt, xDiagram ), uno::UNO_QUERY );
520 if( xCurrentAxis==xAxis )
522 bOtherSeriesAttachedToThisAxis = true;
523 break;
526 if(!bOtherSeriesAttachedToThisAxis && !aSeriesVector.empty() )
527 AxisHelper::makeAxisInvisible( xAxis );
530 void AxisHelper::hideGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
531 , const Reference< XDiagram >& xDiagram )
533 if( !xDiagram.is() )
534 return;
536 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
537 if(!xCooSys.is())
538 return;
540 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
541 if(!xAxis.is())
542 return;
544 if( bMainGrid )
545 AxisHelper::makeGridInvisible( xAxis->getGridProperties() );
546 else
548 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
549 for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++)
550 AxisHelper::makeGridInvisible( aSubGrids[nN] );
554 void AxisHelper::makeGridInvisible( const Reference< beans::XPropertySet >& xGridProperties )
556 if( xGridProperties.is() )
558 xGridProperties->setPropertyValue( "Show", uno::makeAny( sal_False ) );
562 bool AxisHelper::isGridShown( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
563 , const Reference< ::com::sun::star::chart2::XDiagram >& xDiagram )
565 bool bRet = false;
567 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
568 if(!xCooSys.is())
569 return bRet;
571 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys ) );
572 if(!xAxis.is())
573 return bRet;
575 if( bMainGrid )
576 bRet = AxisHelper::isGridVisible( xAxis->getGridProperties() );
577 else
579 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
580 if( aSubGrids.getLength() )
581 bRet = AxisHelper::isGridVisible( aSubGrids[0] );
584 return bRet;
587 Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemByIndex(
588 const Reference< XDiagram >& xDiagram, sal_Int32 nIndex )
590 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
591 if(!xCooSysContainer.is())
592 return NULL;
593 Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
594 if(0<=nIndex && nIndex<aCooSysList.getLength())
595 return aCooSysList[nIndex];
596 return NULL;
599 Reference< XAxis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, bool bMainAxis
600 , const Reference< XDiagram >& xDiagram )
602 Reference< XAxis > xRet;
605 Reference< XCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 );
606 xRet.set( AxisHelper::getAxis( nDimensionIndex, bMainAxis ? 0 : 1, xCooSys ) );
608 catch( const uno::Exception & )
611 return xRet;
614 Reference< XAxis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex
615 , const Reference< XCoordinateSystem >& xCooSys )
617 Reference< XAxis > xRet;
618 if(!xCooSys.is())
619 return xRet;
621 if(nDimensionIndex >= xCooSys->getDimension())
622 return xRet;
624 if(nAxisIndex > xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex))
625 return xRet;
627 assert(nAxisIndex >= 0);
628 assert(nDimensionIndex >= 0);
629 xRet.set( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
630 return xRet;
633 Reference< XAxis > AxisHelper::getCrossingMainAxis( const Reference< XAxis >& xAxis
634 , const Reference< XCoordinateSystem >& xCooSys )
636 sal_Int32 nDimensionIndex = 0;
637 sal_Int32 nAxisIndex = 0;
638 AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex );
639 if( 2==nDimensionIndex )
641 nDimensionIndex=1;
642 bool bSwapXY = false;
643 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
644 if( xCooSysProp.is() && (xCooSysProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXY) && bSwapXY )
645 nDimensionIndex=0;
647 else if( 1==nDimensionIndex )
648 nDimensionIndex=0;
649 else
650 nDimensionIndex=1;
651 return AxisHelper::getAxis( nDimensionIndex, 0, xCooSys );
654 Reference< XAxis > AxisHelper::getParallelAxis( const Reference< XAxis >& xAxis
655 , const Reference< XDiagram >& xDiagram )
659 sal_Int32 nCooSysIndex=-1;
660 sal_Int32 nDimensionIndex=-1;
661 sal_Int32 nAxisIndex=-1;
662 if( getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ) )
664 sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
665 return getAxis( nDimensionIndex, nParallelAxisIndex, getCoordinateSystemByIndex( xDiagram, nCooSysIndex ) );
668 catch( const uno::RuntimeException& )
671 return 0;
674 bool AxisHelper::isAxisShown( sal_Int32 nDimensionIndex, bool bMainAxis
675 , const Reference< XDiagram >& xDiagram )
677 return AxisHelper::isAxisVisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
680 bool AxisHelper::isAxisVisible( const Reference< XAxis >& xAxis )
682 bool bRet = false;
684 Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
685 if( xProps.is() )
687 xProps->getPropertyValue( "Show" ) >>= bRet;
688 bRet = bRet && ( LinePropertiesHelper::IsLineVisible( xProps )
689 || areAxisLabelsVisible( xProps ) );
692 return bRet;
695 bool AxisHelper::areAxisLabelsVisible( const Reference< beans::XPropertySet >& xAxisProperties )
697 bool bRet = false;
698 if( xAxisProperties.is() )
700 xAxisProperties->getPropertyValue( "DisplayLabels" ) >>= bRet;
702 return bRet;
705 bool AxisHelper::isGridVisible( const Reference< beans::XPropertySet >& xGridProperies )
707 bool bRet = false;
709 if( xGridProperies.is() )
711 xGridProperies->getPropertyValue( "Show" ) >>= bRet;
712 bRet = bRet && LinePropertiesHelper::IsLineVisible( xGridProperies );
715 return bRet;
718 Reference< beans::XPropertySet > AxisHelper::getGridProperties(
719 const Reference< XCoordinateSystem >& xCooSys
720 , sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex, sal_Int32 nSubGridIndex )
722 Reference< beans::XPropertySet > xRet;
724 Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) );
725 if( xAxis.is() )
727 if( nSubGridIndex<0 )
728 xRet.set( xAxis->getGridProperties() );
729 else
731 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
732 if( nSubGridIndex >= 0 && nSubGridIndex < aSubGrids.getLength() )
733 xRet.set( aSubGrids[nSubGridIndex] );
737 return xRet;
740 sal_Int32 AxisHelper::getDimensionIndexOfAxis(
741 const Reference< XAxis >& xAxis
742 , const Reference< XDiagram >& xDiagram )
744 sal_Int32 nDimensionIndex = -1;
745 sal_Int32 nCooSysIndex = -1;
746 sal_Int32 nAxisIndex = -1;
747 AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex , nDimensionIndex, nAxisIndex );
748 return nDimensionIndex;
751 bool AxisHelper::getIndicesForAxis(
752 const Reference< XAxis >& xAxis
753 , const Reference< XCoordinateSystem >& xCooSys
754 , sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
756 //returns true if indices are found
758 rOutDimensionIndex = -1;
759 rOutAxisIndex = -1;
761 if( xCooSys.is() && xAxis.is() )
763 Reference< XAxis > xCurrentAxis;
764 sal_Int32 nDimensionCount( xCooSys->getDimension() );
765 for( sal_Int32 nDimensionIndex = 0; nDimensionIndex < nDimensionCount; nDimensionIndex++ )
767 sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
768 for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ )
770 xCurrentAxis = xCooSys->getAxisByDimension(nDimensionIndex,nAxisIndex);
771 if( xCurrentAxis == xAxis )
773 rOutDimensionIndex = nDimensionIndex;
774 rOutAxisIndex = nAxisIndex;
775 return true;
780 return false;
783 bool AxisHelper::getIndicesForAxis( const Reference< XAxis >& xAxis, const Reference< XDiagram >& xDiagram
784 , sal_Int32& rOutCooSysIndex, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
786 //returns true if indices are found
788 rOutCooSysIndex = -1;
789 rOutDimensionIndex = -1;
790 rOutAxisIndex = -1;
792 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
793 if(xCooSysContainer.is())
795 Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
796 for( sal_Int32 nC=0; nC<aCooSysList.getLength(); ++nC )
798 if( AxisHelper::getIndicesForAxis( xAxis, aCooSysList[nC], rOutDimensionIndex, rOutAxisIndex ) )
800 rOutCooSysIndex = nC;
801 return true;
806 return false;
809 std::vector< Reference< XAxis > > AxisHelper::getAllAxesOfCoordinateSystem(
810 const Reference< XCoordinateSystem >& xCooSys
811 , bool bOnlyVisible /* = false */ )
813 std::vector< Reference< XAxis > > aAxisVector;
815 if(xCooSys.is())
817 sal_Int32 nMaxDimensionIndex = xCooSys->getDimension() -1;
818 if( nMaxDimensionIndex>=0 )
820 sal_Int32 nDimensionIndex = 0;
821 for(; nDimensionIndex<=nMaxDimensionIndex; ++nDimensionIndex)
823 const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
824 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
828 Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
829 if( xAxis.is() )
831 bool bAddAxis = true;
832 if( bOnlyVisible )
834 Reference< beans::XPropertySet > xAxisProp( xAxis, uno::UNO_QUERY );
835 if( !xAxisProp.is() ||
836 !(xAxisProp->getPropertyValue( "Show") >>= bAddAxis) )
837 bAddAxis = false;
839 if( bAddAxis )
840 aAxisVector.push_back( xAxis );
843 catch( const uno::Exception & ex )
845 ASSERT_EXCEPTION( ex );
852 return aAxisVector;
855 Sequence< Reference< XAxis > > AxisHelper::getAllAxesOfDiagram(
856 const Reference< XDiagram >& xDiagram
857 , bool bOnlyVisible )
859 std::vector< Reference< XAxis > > aAxisVector;
861 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
862 if(xCooSysContainer.is())
864 Sequence< Reference< XCoordinateSystem > > aCooSysList = xCooSysContainer->getCoordinateSystems();
865 sal_Int32 nC = 0;
866 for( nC=0; nC<aCooSysList.getLength(); ++nC )
868 std::vector< Reference< XAxis > > aAxesPerCooSys( AxisHelper::getAllAxesOfCoordinateSystem( aCooSysList[nC], bOnlyVisible ) );
869 aAxisVector.insert( aAxisVector.end(), aAxesPerCooSys.begin(), aAxesPerCooSys.end() );
873 return ContainerHelper::ContainerToSequence( aAxisVector );
876 Sequence< Reference< beans::XPropertySet > > AxisHelper::getAllGrids( const Reference< XDiagram >& xDiagram )
878 Sequence< Reference< XAxis > > aAllAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
879 std::vector< Reference< beans::XPropertySet > > aGridVector;
881 sal_Int32 nA = 0;
882 for( nA=0; nA<aAllAxes.getLength(); ++nA )
884 Reference< XAxis > xAxis( aAllAxes[nA] );
885 if(!xAxis.is())
886 continue;
887 Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
888 if( xGridProperties.is() )
889 aGridVector.push_back( xGridProperties );
891 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );;
892 sal_Int32 nSubGrid = 0;
893 for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid )
895 Reference< beans::XPropertySet > xSubGrid( aSubGrids[nSubGrid] );
896 if( xSubGrid.is() )
897 aGridVector.push_back( xSubGrid );
901 return ContainerHelper::ContainerToSequence( aGridVector );
904 void AxisHelper::getAxisOrGridPossibilities( Sequence< sal_Bool >& rPossibilityList
905 , const Reference< XDiagram>& xDiagram, bool bAxis )
907 rPossibilityList.realloc(6);
909 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
911 //set possibilities:
912 sal_Int32 nIndex=0;
913 Reference< XChartType > xChartType = DiagramHelper::getChartTypeByIndex( xDiagram, 0 );
914 for(nIndex=0;nIndex<3;nIndex++)
915 rPossibilityList[nIndex]=ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nIndex);
916 for(nIndex=3;nIndex<6;nIndex++)
917 if( bAxis )
918 rPossibilityList[nIndex]=ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount,nIndex-3);
919 else
920 rPossibilityList[nIndex] = rPossibilityList[nIndex-3];
923 bool AxisHelper::isSecondaryYAxisNeeded( const Reference< XCoordinateSystem >& xCooSys )
925 Reference< chart2::XChartTypeContainer > xCTCnt( xCooSys, uno::UNO_QUERY );
926 if( xCTCnt.is() )
928 Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes() );
929 for( sal_Int32 i=0; i<aChartTypes.getLength(); ++i )
931 Reference< XDataSeriesContainer > xSeriesContainer( aChartTypes[i] , uno::UNO_QUERY );
932 if( !xSeriesContainer.is() )
933 continue;
935 Sequence< Reference< XDataSeries > > aSeriesList( xSeriesContainer->getDataSeries() );
936 for( sal_Int32 nS = aSeriesList.getLength(); nS-- ; )
938 Reference< beans::XPropertySet > xProp( aSeriesList[nS], uno::UNO_QUERY );
939 if(xProp.is())
941 sal_Int32 nAttachedAxisIndex = 0;
942 if( ( xProp->getPropertyValue( "AttachedAxisIndex" ) >>= nAttachedAxisIndex ) && nAttachedAxisIndex>0 )
943 return true;
948 return false;
951 bool AxisHelper::shouldAxisBeDisplayed( const Reference< XAxis >& xAxis
952 , const Reference< XCoordinateSystem >& xCooSys )
954 bool bRet = false;
956 if( xAxis.is() && xCooSys.is() )
958 sal_Int32 nDimensionIndex=-1;
959 sal_Int32 nAxisIndex=-1;
960 if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
962 sal_Int32 nDimensionCount = xCooSys->getDimension();
963 Reference< XChartType > xChartType( AxisHelper::getChartTypeByIndex( xCooSys, 0 ) );
965 bool bMainAxis = (nAxisIndex==MAIN_AXIS_INDEX);
966 if( bMainAxis )
967 bRet = ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nDimensionIndex);
968 else
969 bRet = ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount,nDimensionIndex);
973 return bRet;
976 void AxisHelper::getAxisOrGridExcistence( Sequence< sal_Bool >& rExistenceList
977 , const Reference< XDiagram>& xDiagram, bool bAxis )
979 rExistenceList.realloc(6);
981 if(bAxis)
983 sal_Int32 nN;
984 Reference< XAxis > xAxis;
985 for(nN=0;nN<3;nN++)
986 rExistenceList[nN] = AxisHelper::isAxisShown( nN, true, xDiagram );
987 for(nN=3;nN<6;nN++)
988 rExistenceList[nN] = AxisHelper::isAxisShown( nN%3, false, xDiagram );
990 else
992 sal_Int32 nN;
994 for(nN=0;nN<3;nN++)
995 rExistenceList[nN] = AxisHelper::isGridShown( nN, 0, true, xDiagram );
996 for(nN=3;nN<6;nN++)
997 rExistenceList[nN] = AxisHelper::isGridShown( nN%3, 0, false, xDiagram );
1001 bool AxisHelper::changeVisibilityOfAxes( const Reference< XDiagram >& xDiagram
1002 , const Sequence< sal_Bool >& rOldExistenceList
1003 , const Sequence< sal_Bool >& rNewExistenceList
1004 , const Reference< uno::XComponentContext >& xContext
1005 , ReferenceSizeProvider * pRefSizeProvider )
1007 bool bChanged = false;
1008 for(sal_Int32 nN=0;nN<6;nN++)
1010 if(rOldExistenceList[nN]!=rNewExistenceList[nN])
1012 bChanged = true;
1013 if(rNewExistenceList[nN])
1015 AxisHelper::showAxis( nN%3, nN<3, xDiagram, xContext, pRefSizeProvider );
1017 else
1018 AxisHelper::hideAxis( nN%3, nN<3, xDiagram );
1021 return bChanged;
1024 bool AxisHelper::changeVisibilityOfGrids( const Reference< XDiagram >& xDiagram
1025 , const Sequence< sal_Bool >& rOldExistenceList
1026 , const Sequence< sal_Bool >& rNewExistenceList
1027 , const Reference< uno::XComponentContext >& xContext )
1029 bool bChanged = false;
1030 for(sal_Int32 nN=0;nN<6;nN++)
1032 if(rOldExistenceList[nN]!=rNewExistenceList[nN])
1034 bChanged = true;
1035 if(rNewExistenceList[nN])
1036 AxisHelper::showGrid( nN%3, 0, nN<3, xDiagram, xContext );
1037 else
1038 AxisHelper::hideGrid( nN%3, 0, nN<3, xDiagram );
1041 return bChanged;
1044 Reference< XCoordinateSystem > AxisHelper::getCoordinateSystemOfAxis(
1045 const Reference< XAxis >& xAxis
1046 , const Reference< XDiagram >& xDiagram )
1048 Reference< XCoordinateSystem > xRet;
1050 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
1051 if( xCooSysContainer.is() )
1053 Reference< XCoordinateSystem > xCooSys;
1054 Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
1055 for( sal_Int32 nCooSysIndex = 0; nCooSysIndex < aCooSysList.getLength(); ++nCooSysIndex )
1057 xCooSys = aCooSysList[nCooSysIndex];
1058 std::vector< Reference< XAxis > > aAllAxis( AxisHelper::getAllAxesOfCoordinateSystem( xCooSys ) );
1060 ::std::vector< Reference< XAxis > >::iterator aFound =
1061 ::std::find( aAllAxis.begin(), aAllAxis.end(), xAxis );
1062 if( aFound != aAllAxis.end())
1064 xRet.set( xCooSys );
1065 break;
1069 return xRet;
1072 Reference< XChartType > AxisHelper::getChartTypeByIndex( const Reference< XCoordinateSystem >& xCooSys, sal_Int32 nIndex )
1074 Reference< XChartType > xChartType;
1076 Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
1077 if( xChartTypeContainer.is() )
1079 Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
1080 if( nIndex >= 0 && nIndex < aChartTypeList.getLength() )
1081 xChartType.set( aChartTypeList[nIndex] );
1084 return xChartType;
1087 void AxisHelper::setRTLAxisLayout( const Reference< XCoordinateSystem >& xCooSys )
1089 if( xCooSys.is() )
1091 bool bCartesian = xCooSys->getViewServiceName() == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME;
1092 if( bCartesian )
1094 bool bVertical = false;
1095 Reference< beans::XPropertySet > xCooSysProp( xCooSys, uno::UNO_QUERY );
1096 if( xCooSysProp.is() )
1097 xCooSysProp->getPropertyValue( "SwapXAndYAxis" ) >>= bVertical;
1099 sal_Int32 nHorizontalAxisDimension = bVertical ? 1 : 0;
1100 sal_Int32 nVerticalAxisDimension = bVertical ? 0 : 1;
1104 //reverse direction for horizontal main axis
1105 Reference< chart2::XAxis > xHorizontalMainAxis( AxisHelper::getAxis( nHorizontalAxisDimension, MAIN_AXIS_INDEX, xCooSys ) );
1106 if( xHorizontalMainAxis.is() )
1108 chart2::ScaleData aScale = xHorizontalMainAxis->getScaleData();
1109 aScale.Orientation = chart2::AxisOrientation_REVERSE;
1110 xHorizontalMainAxis->setScaleData(aScale);
1113 //mathematical direction for vertical main axis
1114 Reference< chart2::XAxis > xVerticalMainAxis( AxisHelper::getAxis( nVerticalAxisDimension, MAIN_AXIS_INDEX, xCooSys ) );
1115 if( xVerticalMainAxis.is() )
1117 chart2::ScaleData aScale = xVerticalMainAxis->getScaleData();
1118 aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
1119 xVerticalMainAxis->setScaleData(aScale);
1122 catch( const uno::Exception & ex )
1124 ASSERT_EXCEPTION( ex );
1129 //reverse direction for horizontal secondary axis
1130 Reference< chart2::XAxis > xHorizontalSecondaryAxis( AxisHelper::getAxis( nHorizontalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys ) );
1131 if( xHorizontalSecondaryAxis.is() )
1133 chart2::ScaleData aScale = xHorizontalSecondaryAxis->getScaleData();
1134 aScale.Orientation = chart2::AxisOrientation_REVERSE;
1135 xHorizontalSecondaryAxis->setScaleData(aScale);
1138 //mathematical direction for vertical secondary axis
1139 Reference< chart2::XAxis > xVerticalSecondaryAxis( AxisHelper::getAxis( nVerticalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys ) );
1140 if( xVerticalSecondaryAxis.is() )
1142 chart2::ScaleData aScale = xVerticalSecondaryAxis->getScaleData();
1143 aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
1144 xVerticalSecondaryAxis->setScaleData(aScale);
1147 catch( const uno::Exception & ex )
1149 ASSERT_EXCEPTION( ex );
1155 Reference< XChartType > AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( const Reference< chart2::XDiagram >& xDiagram, const sal_Int32 nAttachedAxisIndex )
1157 Reference< XChartType > xChartType;
1158 ::std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
1159 ::std::vector< Reference< XDataSeries > >::const_iterator aIter = aSeriesVector.begin();
1160 for( ; aIter != aSeriesVector.end(); ++aIter )
1162 sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex( *aIter );
1163 if( nAttachedAxisIndex == nCurrentIndex )
1165 xChartType = DiagramHelper::getChartTypeOfSeries( xDiagram, *aIter );
1166 if(xChartType.is())
1167 break;
1170 return xChartType;
1173 bool AxisHelper::isAxisPositioningEnabled()
1175 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
1176 return nCurrentVersion >= SvtSaveOptions::ODFVER_012;
1179 } //namespace chart
1181 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */