| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_chart2.hxx" |
| #include "DataSeriesHelper.hxx" |
| #include "DiagramHelper.hxx" |
| #include "DataSource.hxx" |
| #include "macros.hxx" |
| #include "ContainerHelper.hxx" |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/chart2/DataPointLabel.hpp> |
| #include <com/sun/star/chart2/data/XTextualDataSequence.hpp> |
| #include <com/sun/star/chart2/StackingDirection.hpp> |
| #include <com/sun/star/chart2/data/LabelOrigin.hpp> |
| #include <com/sun/star/chart2/AxisType.hpp> |
| #include <com/sun/star/chart2/SymbolStyle.hpp> |
| #include <com/sun/star/chart2/Symbol.hpp> |
| #include <com/sun/star/drawing/LineStyle.hpp> |
| |
| |
| #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> |
| #include <com/sun/star/chart2/XChartTypeContainer.hpp> |
| #include <com/sun/star/chart2/XDataSeriesContainer.hpp> |
| #include <rtl/ustrbuf.hxx> |
| |
| #include <functional> |
| #include <algorithm> |
| #include <iterator> |
| #include <vector> |
| #include <set> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::chart2; |
| |
| using ::com::sun::star::uno::Reference; |
| using ::com::sun::star::uno::Sequence; |
| using ::rtl::OUString; |
| using ::rtl::OUStringBuffer; |
| |
| // ---------------------------------------- |
| namespace |
| { |
| |
| class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool > |
| { |
| public: |
| explicit lcl_MatchesRole( const OUString & aRole, bool bMatchPrefix ) : |
| m_aRole( aRole ), |
| m_bMatchPrefix( bMatchPrefix ) |
| {} |
| |
| bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const |
| { |
| if(!xSeq.is()) |
| return false; |
| Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY ); |
| OUString aRole; |
| |
| if( m_bMatchPrefix ) |
| return ( xProp.is() && |
| (xProp->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) && |
| aRole.match( m_aRole )); |
| |
| return ( xProp.is() && |
| (xProp->getPropertyValue( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )) ) >>= aRole ) && |
| m_aRole.equals( aRole )); |
| } |
| |
| private: |
| OUString m_aRole; |
| bool m_bMatchPrefix; |
| }; |
| |
| Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel( |
| const Reference< chart2::data::XDataSource > & xDataSource ) |
| { |
| Reference< chart2::data::XLabeledDataSequence > xResult; |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences()); |
| |
| for( sal_Int32 i=0; i<aSequences.getLength(); ++i ) |
| { |
| OSL_ENSURE( aSequences[i].is(), "empty LabeledDataSequence" ); |
| // no values are set but a label exists |
| if( aSequences[i].is() && |
| ( ! aSequences[i]->getValues().is() && |
| aSequences[i]->getLabel().is())) |
| { |
| xResult.set( aSequences[i] ); |
| break; |
| } |
| } |
| |
| return xResult; |
| } |
| |
| void lcl_getCooSysAndChartTypeOfSeries( |
| const Reference< chart2::XDataSeries > & xSeries, |
| const Reference< chart2::XDiagram > & xDiagram, |
| Reference< chart2::XCoordinateSystem > & xOutCooSys, |
| Reference< chart2::XChartType > & xOutChartType ) |
| { |
| Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY ); |
| if( xCooSysCnt.is()) |
| { |
| Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); |
| for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx ) |
| { |
| Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW ); |
| Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes()); |
| for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx ) |
| { |
| Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY ); |
| if( xSeriesCnt.is()) |
| { |
| Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries()); |
| for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx ) |
| { |
| if( aSeries[nSeriesIdx] == xSeries ) |
| { |
| xOutCooSys.set( aCooSysSeq[nCooSysIdx] ); |
| xOutChartType.set( aChartTypes[nCTIdx] ); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| void lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries, bool bInsert ) |
| { |
| try |
| { |
| Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); |
| if( xSeriesProperties.is() ) |
| { |
| DataPointLabel aLabelAtSeries; |
| xSeriesProperties->getPropertyValue( C2U( "Label" ) ) >>= aLabelAtSeries; |
| aLabelAtSeries.ShowNumber = bInsert; |
| if( !bInsert ) |
| { |
| aLabelAtSeries.ShowNumberInPercent = false; |
| aLabelAtSeries.ShowCategoryName = false; |
| } |
| xSeriesProperties->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabelAtSeries ) ); |
| uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; |
| if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) |
| { |
| for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) |
| { |
| Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) ); |
| if( xPointProp.is() ) |
| { |
| DataPointLabel aLabel; |
| xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel; |
| aLabel.ShowNumber = bInsert; |
| if( !bInsert ) |
| { |
| aLabel.ShowNumberInPercent = false; |
| aLabel.ShowCategoryName = false; |
| } |
| xPointProp->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabel ) ); |
| } |
| } |
| } |
| } |
| } |
| catch( uno::Exception &e) |
| { |
| ASSERT_EXCEPTION( e ); |
| } |
| } |
| |
| } // anonymous namespace |
| // ---------------------------------------- |
| |
| namespace chart |
| { |
| |
| namespace DataSeriesHelper |
| { |
| |
| OUString GetRole( const uno::Reference< chart2::data::XLabeledDataSequence >& xLabeledDataSequence ) |
| { |
| OUString aRet; |
| if( xLabeledDataSequence.is() ) |
| { |
| Reference< beans::XPropertySet > xProp( xLabeledDataSequence->getValues(), uno::UNO_QUERY ); |
| if( xProp.is() ) |
| xProp->getPropertyValue( C2U("Role") ) >>= aRet; |
| } |
| return aRet; |
| } |
| |
| Reference< chart2::data::XLabeledDataSequence > |
| getDataSequenceByRole( |
| const Reference< chart2::data::XDataSource > & xSource, OUString aRole, |
| bool bMatchPrefix /* = false */ ) |
| { |
| Reference< chart2::data::XLabeledDataSequence > aNoResult; |
| if( ! xSource.is()) |
| return aNoResult; |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences()); |
| |
| const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray(); |
| const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength(); |
| const Reference< chart2::data::XLabeledDataSequence > * pMatch = |
| ::std::find_if( pBegin, pEnd, lcl_MatchesRole( aRole, bMatchPrefix )); |
| |
| if( pMatch != pEnd ) |
| return *pMatch; |
| |
| return aNoResult; |
| } |
| |
| ::std::vector< Reference< chart2::data::XLabeledDataSequence > > |
| getAllDataSequencesByRole( const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aDataSequences, |
| OUString aRole, bool bMatchPrefix /* = false */ ) |
| { |
| ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVec; |
| ::std::remove_copy_if( aDataSequences.getConstArray(), aDataSequences.getConstArray() + aDataSequences.getLength(), |
| ::std::back_inserter( aResultVec ), |
| ::std::not1( lcl_MatchesRole( aRole, bMatchPrefix ))); |
| return aResultVec; |
| } |
| |
| Reference< chart2::data::XDataSource > |
| getDataSource( const Sequence< Reference< chart2::XDataSeries > > & aSeries ) |
| { |
| ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVec; |
| |
| for( sal_Int32 i = 0; i < aSeries.getLength(); ++i ) |
| { |
| Reference< chart2::data::XDataSource > xSource( aSeries[ i ], uno::UNO_QUERY ); |
| if( xSource.is()) |
| { |
| Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences()); |
| ::std::copy( aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength(), |
| ::std::back_inserter( aSeqVec )); |
| } |
| } |
| |
| return Reference< chart2::data::XDataSource >( |
| new DataSource( ContainerHelper::ContainerToSequence( aSeqVec ))); |
| } |
| |
| namespace |
| { |
| OUString lcl_getDataSequenceLabel( const Reference< chart2::data::XDataSequence > & xSequence ) |
| { |
| OUString aResult; |
| |
| Reference< chart2::data::XTextualDataSequence > xTextSeq( xSequence, uno::UNO_QUERY ); |
| if( xTextSeq.is()) |
| { |
| Sequence< OUString > aSeq( xTextSeq->getTextualData()); |
| |
| const sal_Int32 nMax = aSeq.getLength() - 1; |
| OUString aVal; |
| OUStringBuffer aBuf; |
| |
| for( sal_Int32 i = 0; i <= nMax; ++i ) |
| { |
| aBuf.append( aSeq[i] ); |
| if( i < nMax ) |
| aBuf.append( sal_Unicode( ' ' )); |
| } |
| aResult = aBuf.makeStringAndClear(); |
| } |
| else if( xSequence.is()) |
| { |
| Sequence< uno::Any > aSeq( xSequence->getData()); |
| |
| const sal_Int32 nMax = aSeq.getLength() - 1; |
| OUString aVal; |
| OUStringBuffer aBuf; |
| double fNum = 0; |
| |
| for( sal_Int32 i = 0; i <= nMax; ++i ) |
| { |
| if( aSeq[i] >>= aVal ) |
| { |
| aBuf.append( aVal ); |
| if( i < nMax ) |
| aBuf.append( sal_Unicode( ' ' )); |
| } |
| else if( aSeq[ i ] >>= fNum ) |
| { |
| aBuf.append( fNum ); |
| if( i < nMax ) |
| aBuf.append( sal_Unicode( ' ' )); |
| } |
| } |
| aResult = aBuf.makeStringAndClear(); |
| } |
| |
| return aResult; |
| } |
| } |
| |
| OUString getLabelForLabeledDataSequence( |
| const Reference< chart2::data::XLabeledDataSequence > & xLabeledSeq ) |
| { |
| OUString aResult; |
| if( xLabeledSeq.is()) |
| { |
| Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel()); |
| if( xSeq.is() ) |
| aResult = lcl_getDataSequenceLabel( xSeq ); |
| if( !xSeq.is() || aResult.isEmpty() ) |
| { |
| // no label set or label content is empty -> use auto-generated one |
| Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() ); |
| if( xValueSeq.is() ) |
| { |
| Sequence< OUString > aLabels( xValueSeq->generateLabel( |
| chart2::data::LabelOrigin_SHORT_SIDE ) ); |
| // no labels returned is interpreted as: auto-generation not |
| // supported by sequence |
| if( aLabels.getLength() ) |
| aResult=aLabels[0]; |
| else |
| { |
| //todo?: maybe use the index of the series as name |
| //but as the index may change it would be better to have such a name persistent |
| //what is not possible at the moment |
| //--> maybe use the identifier as part of the name ... |
| aResult = lcl_getDataSequenceLabel( xValueSeq ); |
| } |
| } |
| } |
| } |
| return aResult; |
| } |
| |
| OUString getDataSeriesLabel( |
| const Reference< chart2::XDataSeries > & xSeries, |
| const OUString & rLabelSequenceRole ) |
| { |
| OUString aResult; |
| |
| Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); |
| if( xSource.is()) |
| { |
| Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( |
| ::chart::DataSeriesHelper::getDataSequenceByRole( xSource, rLabelSequenceRole )); |
| if( xLabeledSeq.is()) |
| aResult = getLabelForLabeledDataSequence( xLabeledSeq ); |
| else |
| { |
| // special case: labeled data series with only a label and no values may |
| // serve as label |
| xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource )); |
| if( xLabeledSeq.is()) |
| { |
| Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel()); |
| if( xSeq.is()) |
| aResult = lcl_getDataSequenceLabel( xSeq ); |
| } |
| } |
| |
| } |
| |
| return aResult; |
| } |
| |
| void setStackModeAtSeries( |
| const Sequence< Reference< chart2::XDataSeries > > & aSeries, |
| const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem, |
| StackMode eStackMode ) |
| { |
| if( eStackMode == StackMode_AMBIGUOUS ) |
| return; |
| |
| const OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( "StackingDirection" )); |
| const uno::Any aPropValue = uno::makeAny( |
| ( (eStackMode == StackMode_Y_STACKED) || |
| (eStackMode == StackMode_Y_STACKED_PERCENT) ) |
| ? chart2::StackingDirection_Y_STACKING |
| : (eStackMode == StackMode_Z_STACKED ) |
| ? chart2::StackingDirection_Z_STACKING |
| : chart2::StackingDirection_NO_STACKING ); |
| |
| std::set< sal_Int32 > aAxisIndexSet; |
| for( sal_Int32 i=0; i<aSeries.getLength(); ++i ) |
| { |
| try |
| { |
| Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY ); |
| if( xProp.is() ) |
| { |
| xProp->setPropertyValue( aPropName, aPropValue ); |
| |
| sal_Int32 nAxisIndex; |
| xProp->getPropertyValue( C2U("AttachedAxisIndex") ) >>= nAxisIndex; |
| aAxisIndexSet.insert(nAxisIndex); |
| } |
| } |
| catch( uno::Exception & ex ) |
| { |
| ASSERT_EXCEPTION( ex ); |
| } |
| } |
| |
| if( xCorrespondingCoordinateSystem.is() && |
| 1 < xCorrespondingCoordinateSystem->getDimension() ) |
| { |
| sal_Int32 nAxisIndexCount = aAxisIndexSet.size(); |
| if( !nAxisIndexCount ) |
| { |
| aAxisIndexSet.insert(0); |
| nAxisIndexCount = aAxisIndexSet.size(); |
| } |
| |
| for( ::std::set< sal_Int32 >::const_iterator aIt = aAxisIndexSet.begin(); |
| aIt != aAxisIndexSet.end(); ++aIt ) |
| { |
| sal_Int32 nAxisIndex = *aIt; |
| Reference< chart2::XAxis > xAxis( |
| xCorrespondingCoordinateSystem->getAxisByDimension( 1, nAxisIndex )); |
| if( xAxis.is()) |
| { |
| sal_Bool bPercent = (eStackMode == StackMode_Y_STACKED_PERCENT); |
| chart2::ScaleData aScaleData = xAxis->getScaleData(); |
| |
| if( bPercent != (aScaleData.AxisType==chart2::AxisType::PERCENT) ) |
| { |
| if( bPercent ) |
| aScaleData.AxisType = chart2::AxisType::PERCENT; |
| else |
| aScaleData.AxisType = chart2::AxisType::REALNUMBER; |
| xAxis->setScaleData( aScaleData ); |
| } |
| } |
| } |
| } |
| } |
| |
| sal_Int32 getAttachedAxisIndex( const Reference< chart2::XDataSeries > & xSeries ) |
| { |
| sal_Int32 nRet = 0; |
| try |
| { |
| Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); |
| if( xProp.is() ) |
| { |
| xProp->getPropertyValue( C2U("AttachedAxisIndex") ) >>= nRet; |
| } |
| } |
| catch( uno::Exception & ex ) |
| { |
| ASSERT_EXCEPTION( ex ); |
| } |
| return nRet; |
| } |
| |
| sal_Int32 getNumberFormatKeyFromAxis( |
| const Reference< chart2::XDataSeries > & xSeries, |
| const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem, |
| sal_Int32 nDimensionIndex, |
| sal_Int32 nAxisIndex /* = -1 */ ) |
| { |
| sal_Int32 nResult = 0; |
| if( nAxisIndex == -1 ) |
| nAxisIndex = getAttachedAxisIndex( xSeries ); |
| try |
| { |
| Reference< beans::XPropertySet > xAxisProp( |
| xCorrespondingCoordinateSystem->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY ); |
| if( xAxisProp.is()) |
| xAxisProp->getPropertyValue( C2U("NumberFormat")) >>= nResult; |
| } |
| catch( const uno::Exception & ex ) |
| { |
| ASSERT_EXCEPTION( ex ); |
| } |
| |
| return nResult; |
| } |
| |
| Reference< chart2::XCoordinateSystem > getCoordinateSystemOfSeries( |
| const Reference< chart2::XDataSeries > & xSeries, |
| const Reference< chart2::XDiagram > & xDiagram ) |
| { |
| Reference< chart2::XCoordinateSystem > xResult; |
| Reference< chart2::XChartType > xDummy; |
| lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xResult, xDummy ); |
| |
| return xResult; |
| } |
| |
| Reference< chart2::XChartType > getChartTypeOfSeries( |
| const Reference< chart2::XDataSeries > & xSeries, |
| const Reference< chart2::XDiagram > & xDiagram ) |
| { |
| Reference< chart2::XChartType > xResult; |
| Reference< chart2::XCoordinateSystem > xDummy; |
| lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xDummy, xResult ); |
| |
| return xResult; |
| } |
| |
| void deleteSeries( |
| const Reference< chart2::XDataSeries > & xSeries, |
| const Reference< chart2::XChartType > & xChartType ) |
| { |
| try |
| { |
| Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW ); |
| ::std::vector< Reference< chart2::XDataSeries > > aSeries( |
| ContainerHelper::SequenceToVector( xSeriesCnt->getDataSeries())); |
| ::std::vector< Reference< chart2::XDataSeries > >::iterator aIt = |
| ::std::find( aSeries.begin(), aSeries.end(), xSeries ); |
| if( aIt != aSeries.end()) |
| { |
| aSeries.erase( aIt ); |
| xSeriesCnt->setDataSeries( ContainerHelper::ContainerToSequence( aSeries )); |
| } |
| } |
| catch( uno::Exception & ex ) |
| { |
| ASSERT_EXCEPTION( ex ); |
| } |
| } |
| |
| void switchSymbolsOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, |
| bool bSymbolsOn, sal_Int32 nSeriesIndex ) |
| { |
| if( !xSeriesProperties.is() ) |
| return; |
| |
| chart2::Symbol aSymbProp; |
| if( (xSeriesProperties->getPropertyValue( C2U( "Symbol" )) >>= aSymbProp ) ) |
| { |
| if( !bSymbolsOn ) |
| aSymbProp.Style = chart2::SymbolStyle_NONE; |
| else if( aSymbProp.Style == chart2::SymbolStyle_NONE ) |
| { |
| aSymbProp.Style = chart2::SymbolStyle_STANDARD; |
| aSymbProp.StandardSymbol = nSeriesIndex; |
| } |
| xSeriesProperties->setPropertyValue( C2U( "Symbol" ), uno::makeAny( aSymbProp )); |
| } |
| //todo: check attributed data points |
| } |
| |
| void switchLinesOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, bool bLinesOn ) |
| { |
| if( !xSeriesProperties.is() ) |
| return; |
| |
| if( bLinesOn ) |
| { |
| // keep line-styles that are not NONE |
| drawing::LineStyle eLineStyle; |
| if( (xSeriesProperties->getPropertyValue( C2U( "LineStyle" )) >>= eLineStyle ) && |
| eLineStyle == drawing::LineStyle_NONE ) |
| { |
| xSeriesProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_SOLID ) ); |
| } |
| } |
| else |
| xSeriesProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE ) ); |
| } |
| |
| void makeLinesThickOrThin( const Reference< beans::XPropertySet > & xSeriesProperties, bool bThick ) |
| { |
| if( !xSeriesProperties.is() ) |
| return; |
| |
| sal_Int32 nNewValue = bThick ? 80 : 0; |
| sal_Int32 nOldValue = 0; |
| if( (xSeriesProperties->getPropertyValue( C2U( "LineWidth" )) >>= nOldValue ) && |
| nOldValue != nNewValue ) |
| { |
| if( !(bThick && nOldValue>0)) |
| xSeriesProperties->setPropertyValue( C2U( "LineWidth" ), uno::makeAny( nNewValue ) ); |
| } |
| } |
| |
| void setPropertyAlsoToAllAttributedDataPoints( const Reference< chart2::XDataSeries >& xSeries, |
| const OUString& rPropertyName, const uno::Any& rPropertyValue ) |
| { |
| Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); |
| if( !xSeriesProperties.is() ) |
| return; |
| |
| xSeriesProperties->setPropertyValue( rPropertyName, rPropertyValue ); |
| uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; |
| if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) |
| { |
| for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) |
| { |
| Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) ); |
| if(!xPointProp.is()) |
| continue; |
| xPointProp->setPropertyValue( rPropertyName, rPropertyValue ); |
| } |
| } |
| } |
| |
| bool hasAttributedDataPointDifferentValue( const Reference< chart2::XDataSeries >& xSeries, |
| const OUString& rPropertyName, const uno::Any& rPropertyValue ) |
| { |
| Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); |
| if( !xSeriesProperties.is() ) |
| return false; |
| |
| uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; |
| if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) |
| { |
| for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) |
| { |
| Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) ); |
| if(!xPointProp.is()) |
| continue; |
| uno::Any aPointValue( xPointProp->getPropertyValue( rPropertyName ) ); |
| if( !( rPropertyValue==aPointValue ) ) |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool areAllSeriesAttachedToSameAxis( const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 & rOutAxisIndex ) |
| { |
| try |
| { |
| uno::Reference< chart2::XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY_THROW ); |
| uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDataSeriesContainer->getDataSeries()); |
| |
| const sal_Int32 nSeriesCount( aSeriesSeq.getLength()); |
| // AxisIndex can only be 0 or 1 |
| sal_Int32 nSeriesAtFirstAxis = 0; |
| sal_Int32 nSeriesAtSecondAxis = 0; |
| |
| for( sal_Int32 nI = 0; nI < nSeriesCount; ++nI ) |
| { |
| uno::Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nI], uno::UNO_QUERY ); |
| sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex( xSeries ); |
| if( nAxisIndex == 0 ) |
| ++nSeriesAtFirstAxis; |
| else if( nAxisIndex == 1 ) |
| ++nSeriesAtSecondAxis; |
| } |
| OSL_ENSURE( nSeriesAtFirstAxis + nSeriesAtSecondAxis == nSeriesCount, "Invalid axis index found" ); |
| |
| if( nSeriesAtFirstAxis == nSeriesCount ) |
| rOutAxisIndex = 0; |
| else if( nSeriesAtSecondAxis == nSeriesCount ) |
| rOutAxisIndex = 1; |
| |
| return ( nSeriesAtFirstAxis == nSeriesCount || |
| nSeriesAtSecondAxis == nSeriesCount ); |
| } |
| catch( const uno::Exception & ex ) |
| { |
| ASSERT_EXCEPTION( ex ); |
| return false; |
| } |
| } |
| |
| namespace |
| { |
| |
| bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence ) |
| { |
| if( !xDataSequence.is() ) |
| return false; |
| uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY ); |
| if( xProp.is() ) |
| { |
| uno::Sequence< sal_Int32 > aHiddenValues; |
| try |
| { |
| xProp->getPropertyValue( C2U( "HiddenValues" ) ) >>= aHiddenValues; |
| if( !aHiddenValues.getLength() ) |
| return true; |
| } |
| catch( uno::Exception& e ) |
| { |
| (void)e; // avoid warning |
| return true; |
| } |
| } |
| if( xDataSequence->getData().getLength() ) |
| return true; |
| return false; |
| } |
| |
| } |
| |
| bool hasUnhiddenData( const uno::Reference< chart2::XDataSeries >& xSeries ) |
| { |
| uno::Reference< chart2::data::XDataSource > xDataSource = |
| uno::Reference< chart2::data::XDataSource >( xSeries, uno::UNO_QUERY ); |
| |
| uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDataSequences = xDataSource->getDataSequences(); |
| |
| for(sal_Int32 nN = aDataSequences.getLength();nN--;) |
| { |
| if( !aDataSequences[nN].is() ) |
| continue; |
| if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getValues() ) ) |
| return true; |
| if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getLabel() ) ) |
| return true; |
| } |
| return false; |
| } |
| |
| struct lcl_LessIndex |
| { |
| inline bool operator() ( const sal_Int32& first, const sal_Int32& second ) |
| { |
| return ( first < second ); |
| } |
| }; |
| |
| sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nIndex, const Reference< chart2::data::XDataSequence >& xDataSequence, bool bTranslate ) |
| { |
| if( !bTranslate ) |
| return nIndex; |
| |
| try |
| { |
| uno::Reference<beans::XPropertySet> xProp( xDataSequence, uno::UNO_QUERY ); |
| if( xProp.is()) |
| { |
| Sequence<sal_Int32> aHiddenIndicesSeq; |
| xProp->getPropertyValue( C2U("HiddenValues") ) >>= aHiddenIndicesSeq; |
| if( aHiddenIndicesSeq.getLength() ) |
| { |
| ::std::vector< sal_Int32 > aHiddenIndices( ContainerHelper::SequenceToVector( aHiddenIndicesSeq ) ); |
| ::std::sort( aHiddenIndices.begin(), aHiddenIndices.end(), lcl_LessIndex() ); |
| |
| sal_Int32 nHiddenCount = static_cast<sal_Int32>(aHiddenIndices.size()); |
| for( sal_Int32 nN = 0; nN < nHiddenCount; ++nN) |
| { |
| if( aHiddenIndices[nN] <= nIndex ) |
| nIndex += 1; |
| else |
| break; |
| } |
| } |
| } |
| } |
| catch (const beans::UnknownPropertyException&) |
| { |
| } |
| return nIndex; |
| } |
| |
| bool hasDataLabelsAtSeries( const Reference< chart2::XDataSeries >& xSeries ) |
| { |
| bool bRet = false; |
| try |
| { |
| Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); |
| if( xProp.is() ) |
| { |
| DataPointLabel aLabel; |
| if( (xProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel) ) |
| bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName; |
| } |
| } |
| catch( uno::Exception &e) |
| { |
| ASSERT_EXCEPTION( e ); |
| } |
| return bRet; |
| } |
| |
| bool hasDataLabelsAtPoints( const Reference< chart2::XDataSeries >& xSeries ) |
| { |
| bool bRet = false; |
| try |
| { |
| Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); |
| if( xSeriesProperties.is() ) |
| { |
| uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; |
| if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) |
| { |
| for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) |
| { |
| Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) ); |
| if( xPointProp.is() ) |
| { |
| DataPointLabel aLabel; |
| if( (xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel) ) |
| bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName; |
| if( bRet ) |
| break; |
| } |
| } |
| } |
| } |
| } |
| catch( uno::Exception &e) |
| { |
| ASSERT_EXCEPTION( e ); |
| } |
| return bRet; |
| } |
| |
| bool hasDataLabelAtPoint( const Reference< chart2::XDataSeries >& xSeries, sal_Int32 nPointIndex ) |
| { |
| bool bRet = false; |
| try |
| { |
| Reference< beans::XPropertySet > xProp; |
| Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); |
| if( xSeriesProperties.is() ) |
| { |
| uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; |
| if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) |
| { |
| ::std::vector< sal_Int32 > aIndices( ContainerHelper::SequenceToVector( aAttributedDataPointIndexList ) ); |
| ::std::vector< sal_Int32 >::iterator aIt = ::std::find( aIndices.begin(), aIndices.end(), nPointIndex ); |
| if( aIt != aIndices.end()) |
| xProp = xSeries->getDataPointByIndex(nPointIndex); |
| else |
| xProp = xSeriesProperties; |
| } |
| if( xProp.is() ) |
| { |
| DataPointLabel aLabel; |
| if( (xProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel) ) |
| bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName; |
| } |
| } |
| } |
| catch( uno::Exception &e) |
| { |
| ASSERT_EXCEPTION( e ); |
| } |
| return bRet; |
| } |
| |
| void insertDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries ) |
| { |
| lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, true /*bInsert*/ ); |
| } |
| |
| void deleteDataLabelsFromSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries ) |
| { |
| lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, false /*bInsert*/ ); |
| } |
| |
| |
| void insertDataLabelToPoint( const Reference< beans::XPropertySet >& xPointProp ) |
| { |
| try |
| { |
| if( xPointProp.is() ) |
| { |
| DataPointLabel aLabel; |
| xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel; |
| aLabel.ShowNumber = true; |
| xPointProp->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabel ) ); |
| } |
| } |
| catch( uno::Exception &e) |
| { |
| ASSERT_EXCEPTION( e ); |
| } |
| } |
| |
| void deleteDataLabelsFromPoint( const Reference< beans::XPropertySet >& xPointProp ) |
| { |
| try |
| { |
| if( xPointProp.is() ) |
| { |
| DataPointLabel aLabel; |
| xPointProp->getPropertyValue( C2U( "Label" ) ) >>= aLabel; |
| aLabel.ShowNumber = false; |
| aLabel.ShowNumberInPercent = false; |
| aLabel.ShowCategoryName = false; |
| xPointProp->setPropertyValue( C2U( "Label" ), uno::makeAny( aLabel ) ); |
| } |
| } |
| catch( uno::Exception &e) |
| { |
| ASSERT_EXCEPTION( e ); |
| } |
| } |
| |
| } // namespace DataSeriesHelper |
| } // namespace chart |