diff options
Diffstat (limited to 'chart2/source/view')
106 files changed, 8257 insertions, 6732 deletions
diff --git a/chart2/source/view/axes/DateHelper.cxx b/chart2/source/view/axes/DateHelper.cxx index f705a7346091..4c4a96dce2f8 100644 --- a/chart2/source/view/axes/DateHelper.cxx +++ b/chart2/source/view/axes/DateHelper.cxx @@ -66,7 +66,7 @@ bool DateHelper::IsLessThanOneYearAway( const Date& rD1, const Date& rD2 ) return rD2 > aDMin && rD2 < aDMax; } -double DateHelper::RasterizeDateValue( double fValue, const Date& rNullDate, long TimeResolution ) +double DateHelper::RasterizeDateValue( double fValue, const Date& rNullDate, tools::Long TimeResolution ) { if (std::isnan(fValue)) return fValue; diff --git a/chart2/source/view/axes/DateScaling.cxx b/chart2/source/view/axes/DateScaling.cxx index 60ffc14bbfae..f24f46a8e457 100644 --- a/chart2/source/view/axes/DateScaling.cxx +++ b/chart2/source/view/axes/DateScaling.cxx @@ -22,11 +22,14 @@ #include <rtl/math.hxx> #include <cppuhelper/supportsservice.hxx> +#include <limits> + namespace { -const char lcl_aServiceName_DateScaling[] = "com.sun.star.chart2.DateScaling"; -const char lcl_aServiceName_InverseDateScaling[] = "com.sun.star.chart2.InverseDateScaling"; +constexpr OUString lcl_aServiceName_DateScaling = u"com.sun.star.chart2.DateScaling"_ustr; +constexpr OUString lcl_aServiceName_InverseDateScaling + = u"com.sun.star.chart2.InverseDateScaling"_ustr; const double lcl_fNumberOfMonths = 12.0;//todo: this needs to be offered by basic tools Date class if it should be more generic } @@ -54,37 +57,36 @@ double SAL_CALL DateScaling::doScaling( double value ) { double fResult(value); if( std::isnan( value ) || std::isinf( value ) ) - ::rtl::math::setNan( & fResult ); - else + return std::numeric_limits<double>::quiet_NaN(); + switch( m_nTimeUnit ) { - Date aDate(m_aNullDate); - aDate.AddDays(::rtl::math::approxFloor(value)); - switch( m_nTimeUnit ) + case DAY: + fResult = value; + if(m_bShifted) + fResult+=0.5; + break; + case YEAR: + case MONTH: + default: { - case DAY: - fResult = value; - if(m_bShifted) - fResult+=0.5; - break; - case YEAR: - case MONTH: - default: - fResult = aDate.GetYear(); - fResult *= lcl_fNumberOfMonths;//assuming equal count of months in each year - fResult += aDate.GetMonth(); - - double fDayOfMonth = aDate.GetDay(); - fDayOfMonth -= 1.0; - double fDaysInMonth = aDate.GetDaysInMonth(); - fResult += fDayOfMonth/fDaysInMonth; - if(m_bShifted) - { - if( m_nTimeUnit==YEAR ) - fResult += 0.5*lcl_fNumberOfMonths; - else - fResult += 0.5; - } - break; + Date aDate(m_aNullDate); + aDate.AddDays(::rtl::math::approxFloor(value)); + fResult = aDate.GetYear(); + fResult *= lcl_fNumberOfMonths;//assuming equal count of months in each year + fResult += aDate.GetMonth(); + + double fDayOfMonth = aDate.GetDay(); + fDayOfMonth -= 1.0; + double fDaysInMonth = aDate.GetDaysInMonth(); + fResult += fDayOfMonth/fDaysInMonth; + if(m_bShifted) + { + if( m_nTimeUnit==YEAR ) + fResult += 0.5*lcl_fNumberOfMonths; + else + fResult += 0.5; + } + break; } } return fResult; @@ -130,7 +132,7 @@ double SAL_CALL InverseDateScaling::doScaling( double value ) { double fResult(value); if( std::isnan( value ) || std::isinf( value ) ) - ::rtl::math::setNan( & fResult ); + return std::numeric_limits<double>::quiet_NaN(); else { switch( m_nTimeUnit ) diff --git a/chart2/source/view/axes/DateScaling.hxx b/chart2/source/view/axes/DateScaling.hxx index 2c2f34dd6330..29b7a139ae32 100644 --- a/chart2/source/view/axes/DateScaling.hxx +++ b/chart2/source/view/axes/DateScaling.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_DATESCALING_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_DATESCALING_HXX +#pragma once #include <com/sun/star/chart2/XScaling.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> @@ -92,6 +91,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx b/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx index 2bb936567469..eaf5c4347379 100644 --- a/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx +++ b/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx @@ -21,7 +21,8 @@ #include <com/sun/star/chart/TimeUnit.hpp> -#include <rtl/math.hxx> +#include <cmath> +#include <limits> namespace chart { @@ -47,8 +48,7 @@ bool MergedMinimumAndMaximumSupplier::hasMinimumAndMaximumSupplier( MinimumAndMa double MergedMinimumAndMaximumSupplier::getMinimumX() { - double fGlobalExtremum; - ::rtl::math::setInf(&fGlobalExtremum, false); + double fGlobalExtremum = std::numeric_limits<double>::infinity(); for (auto const& elem : m_aMinimumAndMaximumSupplierList) { double fLocalExtremum = elem->getMinimumX(); @@ -56,14 +56,13 @@ double MergedMinimumAndMaximumSupplier::getMinimumX() fGlobalExtremum=fLocalExtremum; } if(std::isinf(fGlobalExtremum)) - ::rtl::math::setNan(&fGlobalExtremum); + return std::numeric_limits<double>::quiet_NaN(); return fGlobalExtremum; } double MergedMinimumAndMaximumSupplier::getMaximumX() { - double fGlobalExtremum; - ::rtl::math::setInf(&fGlobalExtremum, true); + double fGlobalExtremum = -std::numeric_limits<double>::infinity(); for (auto const& elem : m_aMinimumAndMaximumSupplierList) { double fLocalExtremum = elem->getMaximumX(); @@ -71,14 +70,13 @@ double MergedMinimumAndMaximumSupplier::getMaximumX() fGlobalExtremum=fLocalExtremum; } if(std::isinf(fGlobalExtremum)) - ::rtl::math::setNan(&fGlobalExtremum); + return std::numeric_limits<double>::quiet_NaN(); return fGlobalExtremum; } double MergedMinimumAndMaximumSupplier::getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) { - double fGlobalExtremum; - ::rtl::math::setInf(&fGlobalExtremum, false); + double fGlobalExtremum = std::numeric_limits<double>::infinity(); for (auto const& elem : m_aMinimumAndMaximumSupplierList) { double fLocalExtremum = elem->getMinimumYInRange( fMinimumX, fMaximumX, nAxisIndex ); @@ -86,14 +84,13 @@ double MergedMinimumAndMaximumSupplier::getMinimumYInRange( double fMinimumX, do fGlobalExtremum=fLocalExtremum; } if(std::isinf(fGlobalExtremum)) - ::rtl::math::setNan(&fGlobalExtremum); + return std::numeric_limits<double>::quiet_NaN(); return fGlobalExtremum; } double MergedMinimumAndMaximumSupplier::getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) { - double fGlobalExtremum; - ::rtl::math::setInf(&fGlobalExtremum, true); + double fGlobalExtremum = -std::numeric_limits<double>::infinity(); for (auto const& elem : m_aMinimumAndMaximumSupplierList) { double fLocalExtremum = elem->getMaximumYInRange( fMinimumX, fMaximumX, nAxisIndex ); @@ -101,14 +98,13 @@ double MergedMinimumAndMaximumSupplier::getMaximumYInRange( double fMinimumX, do fGlobalExtremum=fLocalExtremum; } if(std::isinf(fGlobalExtremum)) - ::rtl::math::setNan(&fGlobalExtremum); + return std::numeric_limits<double>::quiet_NaN(); return fGlobalExtremum; } double MergedMinimumAndMaximumSupplier::getMinimumZ() { - double fGlobalExtremum; - ::rtl::math::setInf(&fGlobalExtremum, false); + double fGlobalExtremum = std::numeric_limits<double>::infinity(); for (auto const& elem : m_aMinimumAndMaximumSupplierList) { double fLocalExtremum = elem->getMinimumZ(); @@ -116,14 +112,13 @@ double MergedMinimumAndMaximumSupplier::getMinimumZ() fGlobalExtremum=fLocalExtremum; } if(std::isinf(fGlobalExtremum)) - ::rtl::math::setNan(&fGlobalExtremum); + return std::numeric_limits<double>::quiet_NaN(); return fGlobalExtremum; } double MergedMinimumAndMaximumSupplier::getMaximumZ() { - double fGlobalExtremum; - ::rtl::math::setInf(&fGlobalExtremum, true); + double fGlobalExtremum = -std::numeric_limits<double>::infinity(); for (auto const& elem : m_aMinimumAndMaximumSupplierList) { double fLocalExtremum = elem->getMaximumZ(); @@ -131,7 +126,7 @@ double MergedMinimumAndMaximumSupplier::getMaximumZ() fGlobalExtremum=fLocalExtremum; } if(std::isinf(fGlobalExtremum)) - ::rtl::math::setNan(&fGlobalExtremum); + return std::numeric_limits<double>::quiet_NaN(); return fGlobalExtremum; } @@ -185,19 +180,19 @@ void MergedMinimumAndMaximumSupplier::clearMinimumAndMaximumSupplierList() m_aMinimumAndMaximumSupplierList.clear(); } -long MergedMinimumAndMaximumSupplier::calculateTimeResolutionOnXAxis() +tools::Long MergedMinimumAndMaximumSupplier::calculateTimeResolutionOnXAxis() { - long nRet = css::chart::TimeUnit::YEAR; + tools::Long nRet = css::chart::TimeUnit::YEAR; for (auto const& elem : m_aMinimumAndMaximumSupplierList) { - long nCurrent = elem->calculateTimeResolutionOnXAxis(); + tools::Long nCurrent = elem->calculateTimeResolutionOnXAxis(); if(nRet>nCurrent) nRet=nCurrent; } return nRet; } -void MergedMinimumAndMaximumSupplier::setTimeResolutionOnXAxis( long nTimeResolution, const Date& rNullDate ) +void MergedMinimumAndMaximumSupplier::setTimeResolutionOnXAxis( tools::Long nTimeResolution, const Date& rNullDate ) { for (auto const& elem : m_aMinimumAndMaximumSupplierList) elem->setTimeResolutionOnXAxis( nTimeResolution, rNullDate ); diff --git a/chart2/source/view/axes/ScaleAutomatism.cxx b/chart2/source/view/axes/ScaleAutomatism.cxx index 10fc3ccd4f56..24195c8fdc93 100644 --- a/chart2/source/view/axes/ScaleAutomatism.cxx +++ b/chart2/source/view/axes/ScaleAutomatism.cxx @@ -26,6 +26,7 @@ #include <com/sun/star/chart2/AxisType.hpp> #include <rtl/math.hxx> +#include <tools/long.hxx> #include <limits> namespace chart @@ -63,9 +64,8 @@ ExplicitScaleData::ExplicitScaleData() , Maximum(10.0) , Origin(0.0) , Orientation(css::chart2::AxisOrientation_MATHEMATICAL) - , Scaling() , AxisType(css::chart2::AxisType::REALNUMBER) - , ShiftedCategoryPosition(false) + , m_bShiftedCategoryPosition(false) , TimeResolution(css::chart::TimeUnit::DAY) , NullDate(30,12,1899) { @@ -83,7 +83,6 @@ ExplicitIncrementData::ExplicitIncrementData() , Distance(1.0) , PostEquidistant(true) , BaseValue(0.0) - , SubIncrements() { } @@ -108,8 +107,8 @@ ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale, const Date& rNu void ScaleAutomatism::resetValueRange( ) { - ::rtl::math::setNan( &m_fValueMinimum ); - ::rtl::math::setNan( &m_fValueMaximum ); + m_fValueMinimum = std::numeric_limits<double>::quiet_NaN(); + m_fValueMaximum = std::numeric_limits<double>::quiet_NaN(); } void ScaleAutomatism::expandValueRange( double fMinimum, double fMaximum ) @@ -203,7 +202,7 @@ void ScaleAutomatism::calculateExplicitScaleAndIncrement( //fill explicit increment - rExplicitScale.ShiftedCategoryPosition = m_aSourceScale.ShiftedCategoryPosition; + rExplicitScale.m_bShiftedCategoryPosition = m_aSourceScale.ShiftedCategoryPosition; bool bIsLogarithm = false; //minimum and maximum of the ExplicitScaleData may be changed if allowed @@ -243,7 +242,7 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForCategory( // no scaling for categories rExplicitScale.Scaling.clear(); - if( rExplicitScale.ShiftedCategoryPosition ) + if( rExplicitScale.m_bShiftedCategoryPosition ) rExplicitScale.Maximum += 1.0; // ensure that at least one category is visible @@ -566,13 +565,13 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis( switch( rExplicitScale.TimeResolution ) { case DAY: - if( rExplicitScale.ShiftedCategoryPosition ) + if( rExplicitScale.m_bShiftedCategoryPosition ) ++aMaxDate; //for explicit scales we need one interval more (maximum excluded) break; case MONTH: aMinDate.SetDay(1); aMaxDate.SetDay(1); - if( rExplicitScale.ShiftedCategoryPosition ) + if( rExplicitScale.m_bShiftedCategoryPosition ) aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,1);//for explicit scales we need one interval more (maximum excluded) if( DateHelper::IsLessThanOneMonthAway( aMinDate, aMaxDate ) ) { @@ -587,7 +586,7 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis( aMinDate.SetMonth(1); aMaxDate.SetDay(1); aMaxDate.SetMonth(1); - if( rExplicitScale.ShiftedCategoryPosition ) + if( rExplicitScale.m_bShiftedCategoryPosition ) aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate,1);//for explicit scales we need one interval more (maximum excluded) if( DateHelper::IsLessThanOneYearAway( aMinDate, aMaxDate ) ) { @@ -612,11 +611,11 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis( nMaxMainIncrementCount--; //choose major time interval: - long nDayCount = aMaxDate - aMinDate; - long nMainIncrementCount = 1; + tools::Long nDayCount = aMaxDate - aMinDate; + tools::Long nMainIncrementCount = 1; if( !bAutoMajor ) { - long nIntervalDayCount = rExplicitIncrement.MajorTimeInterval.Number; + tools::Long nIntervalDayCount = rExplicitIncrement.MajorTimeInterval.Number; if( rExplicitIncrement.MajorTimeInterval.TimeUnit < rExplicitScale.TimeResolution ) rExplicitIncrement.MajorTimeInterval.TimeUnit = rExplicitScale.TimeResolution; switch( rExplicitIncrement.MajorTimeInterval.TimeUnit ) @@ -636,8 +635,8 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis( } if( bAutoMajor ) { - long nNumer = 1; - long nIntervalDays = nDayCount / nMaxMainIncrementCount; + tools::Long nNumer = 1; + tools::Long nIntervalDays = nDayCount / nMaxMainIncrementCount; double nDaysPerInterval = 1.0; if( nIntervalDays>365 || rExplicitScale.TimeResolution==YEAR ) { @@ -655,7 +654,7 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis( nDaysPerInterval = 1.0; } - nNumer = static_cast<sal_Int32>( rtl::math::approxCeil( nIntervalDays/nDaysPerInterval ) ); + nNumer = static_cast<sal_Int32>( rtl::math::approxFloor( nIntervalDays/nDaysPerInterval ) ); if(nNumer<=0) nNumer=1; if( rExplicitIncrement.MajorTimeInterval.TimeUnit == DAY ) @@ -666,13 +665,13 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis( { rExplicitIncrement.MajorTimeInterval.TimeUnit = MONTH; nDaysPerInterval = 31.0; - nNumer = static_cast<sal_Int32>( rtl::math::approxCeil( nIntervalDays/nDaysPerInterval ) ); + nNumer = static_cast<sal_Int32>( rtl::math::approxFloor( nIntervalDays/nDaysPerInterval ) ); if(nNumer<=0) nNumer=1; } } rExplicitIncrement.MajorTimeInterval.Number = nNumer; - nMainIncrementCount = static_cast<long>(nDayCount/(nNumer*nDaysPerInterval)); + nMainIncrementCount = static_cast<tools::Long>(nDayCount/(nNumer*nDaysPerInterval)); } //choose minor time interval: @@ -680,7 +679,7 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis( { if( rExplicitIncrement.MinorTimeInterval.TimeUnit > rExplicitIncrement.MajorTimeInterval.TimeUnit ) rExplicitIncrement.MinorTimeInterval.TimeUnit = rExplicitIncrement.MajorTimeInterval.TimeUnit; - long nIntervalDayCount = rExplicitIncrement.MinorTimeInterval.Number; + tools::Long nIntervalDayCount = rExplicitIncrement.MinorTimeInterval.Number; switch( rExplicitIncrement.MinorTimeInterval.TimeUnit ) { case DAY: diff --git a/chart2/source/view/axes/TickmarkProperties.hxx b/chart2/source/view/axes/TickmarkProperties.hxx index 07dc623995e5..cbb0398b6a19 100644 --- a/chart2/source/view/axes/TickmarkProperties.hxx +++ b/chart2/source/view/axes/TickmarkProperties.hxx @@ -17,23 +17,21 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKPROPERTIES_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKPROPERTIES_HXX +#pragma once #include <VLineProperties.hxx> namespace chart { - struct TickmarkProperties { - sal_Int32 RelativePos;//Position in screen values relative to the axis where the tickmark line starts - sal_Int32 Length;//Length of the tickmark line in screen values + sal_Int32 + RelativePos; //Position in screen values relative to the axis where the tickmark line starts + sal_Int32 Length; //Length of the tickmark line in screen values VLineProperties aLineProperties; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/Tickmarks.cxx b/chart2/source/view/axes/Tickmarks.cxx index 8332f01ff9a2..c30f2f25d5e5 100644 --- a/chart2/source/view/axes/Tickmarks.cxx +++ b/chart2/source/view/axes/Tickmarks.cxx @@ -24,18 +24,19 @@ #include "VAxisProperties.hxx" #include <osl/diagnose.h> #include <com/sun/star/chart2/AxisType.hpp> +#include <utility> using namespace ::com::sun::star; using ::basegfx::B2DVector; namespace chart { -TickInfo::TickInfo( const uno::Reference<chart2::XScaling>& xInverse ) +TickInfo::TickInfo( uno::Reference<chart2::XScaling> xInverse ) : fScaledTickValue( 0.0 ) -, xInverseScaling( xInverse ) +, xInverseScaling(std::move( xInverse )) , aTickScreenPosition(0.0,0.0) -, bPaintIt( true ) , nFactorForLimitedTextWidth(1) +, bPaintIt( true ) { } @@ -85,9 +86,9 @@ TickInfo* PureTickIter::nextInfo() } TickFactory::TickFactory( - const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) - : m_rScale( rScale ) - , m_rIncrement( rIncrement ) + ExplicitScaleData aScale, ExplicitIncrementData aIncrement ) + : m_rScale(std::move( aScale )) + , m_rIncrement(std::move( aIncrement )) { //@todo: make sure that the scale is valid for the scaling @@ -175,7 +176,7 @@ bool TickFactory2D::isHorizontalAxis() const // for skew axes compare angle with horizontal vector double fInclination = std::abs(B2DVector(m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D).angle(B2DVector(1.0, 0.0))); - return fInclination < F_PI4 || fInclination > (F_PI-F_PI4); + return fInclination < M_PI_4 || fInclination > (M_PI-M_PI_4); } bool TickFactory2D::isVerticalAxis() const { @@ -187,7 +188,7 @@ bool TickFactory2D::isVerticalAxis() const // for skew axes compare angle with vertical vector double fInclination = std::abs(B2DVector(m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D).angle(B2DVector(0.0, -1.0))); - return fInclination < F_PI4 || fInclination > (F_PI-F_PI4); + return fInclination < M_PI_4 || fInclination > (M_PI-M_PI_4); } //static sal_Int32 TickFactory2D::getTickScreenDistance( TickIter& rIter ) @@ -203,11 +204,6 @@ sal_Int32 TickFactory2D::getTickScreenDistance( TickIter& rIter ) return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo ); } -B2DVector TickFactory2D::getXaxisStartPos() const -{ - return m_aAxisStartScreenPosition2D; -} - B2DVector TickFactory2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const { B2DVector aRet(m_aAxisStartScreenPosition2D); @@ -238,11 +234,9 @@ void TickFactory2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos; B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length; - rPoints[nSequenceIndex].realloc(2); - rPoints[nSequenceIndex][0].X = static_cast<sal_Int32>(aStart.getX()); - rPoints[nSequenceIndex][0].Y = static_cast<sal_Int32>(aStart.getY()); - rPoints[nSequenceIndex][1].X = static_cast<sal_Int32>(aEnd.getX()); - rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY()); + rPoints.getArray()[nSequenceIndex] + = { { static_cast<sal_Int32>(aStart.getX()), static_cast<sal_Int32>(aStart.getY()) }, + { static_cast<sal_Int32>(aEnd.getX()), static_cast<sal_Int32>(aEnd.getY()) } }; } B2DVector TickFactory2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const @@ -300,11 +294,10 @@ B2DVector TickFactory2D::getDistanceAxisTickToText( const AxisProperties& rAxisP void TickFactory2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const { - rPoints[0].realloc(2); - rPoints[0][0].X = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX()); - rPoints[0][0].Y = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY()); - rPoints[0][1].X = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX()); - rPoints[0][1].Y = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY()); + rPoints.getArray()[0] = { { static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX()), + static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY()) }, + { static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX()), + static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY()) } }; } void TickFactory2D::updateScreenValues( TickInfoArraysType& rAllTickInfos ) const diff --git a/chart2/source/view/axes/Tickmarks.hxx b/chart2/source/view/axes/Tickmarks.hxx index cab62aaa4477..2266c03c91d2 100644 --- a/chart2/source/view/axes/Tickmarks.hxx +++ b/chart2/source/view/axes/Tickmarks.hxx @@ -16,13 +16,13 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_HXX +#pragma once #include <chartview/ExplicitScaleValues.hxx> #include <basegfx/vector/b2dvector.hxx> #include <com/sun/star/drawing/PointSequenceSequence.hpp> - +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> #include <vector> namespace chart { struct AxisProperties; } @@ -36,18 +36,15 @@ struct TickInfo { double fScaledTickValue; css::uno::Reference<css::chart2::XScaling> xInverseScaling; - - ::basegfx::B2DVector aTickScreenPosition; - bool bPaintIt; - - css::uno::Reference<css::drawing::XShape> xTextShape; - + rtl::Reference<SvxShapeText> xTextShape; OUString aText;//used only for complex categories so far + ::basegfx::B2DVector aTickScreenPosition; sal_Int32 nFactorForLimitedTextWidth;//categories in higher levels of complex categories can have more place than a single simple category + bool bPaintIt; //methods: TickInfo() = delete; - explicit TickInfo( const css::uno::Reference<css::chart2::XScaling>& xInverse ); + explicit TickInfo( css::uno::Reference<css::chart2::XScaling> xInverse ); /** * Return a value associated with the tick mark. It's normally an original @@ -86,8 +83,8 @@ class TickFactory { public: TickFactory( - const ExplicitScaleData& rScale - , const ExplicitIncrementData& rIncrement ); + ExplicitScaleData aScale + , ExplicitIncrementData aIncrement ); virtual ~TickFactory(); void getAllTicks( TickInfoArraysType& rAllTickInfos ) const; @@ -135,7 +132,16 @@ public: bool isHorizontalAxis() const; bool isVerticalAxis() const; - ::basegfx::B2DVector getXaxisStartPos() const; + + const ::basegfx::B2DVector & getXaxisStartPos() const + { + return m_aAxisStartScreenPosition2D; + } + + const ::basegfx::B2DVector & getXaxisEndPos() const + { + return m_aAxisEndScreenPosition2D; + } private: ::basegfx::B2DVector getTickScreenPosition2D( double fScaledLogicTickValue ) const; @@ -153,6 +159,4 @@ private: } //namespace chart -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/Tickmarks_Dates.cxx b/chart2/source/view/axes/Tickmarks_Dates.cxx index 854e661f67b4..869d46603fb7 100644 --- a/chart2/source/view/axes/Tickmarks_Dates.cxx +++ b/chart2/source/view/axes/Tickmarks_Dates.cxx @@ -23,6 +23,7 @@ #include <osl/diagnose.h> #include <DateHelper.hxx> #include <com/sun/star/chart/TimeUnit.hpp> +#include <utility> namespace chart { @@ -34,9 +35,9 @@ using ::com::sun::star::chart::TimeUnit::MONTH; using ::com::sun::star::chart::TimeUnit::YEAR; DateTickFactory::DateTickFactory( - const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) - : m_aScale( rScale ) - , m_aIncrement( rIncrement ) + ExplicitScaleData aScale, ExplicitIncrementData aIncrement ) + : m_aScale(std::move( aScale )) + , m_aIncrement(std::move( aIncrement )) { //@todo: make sure that the scale is valid for the scaling diff --git a/chart2/source/view/axes/Tickmarks_Dates.hxx b/chart2/source/view/axes/Tickmarks_Dates.hxx index 2e4e3b35b58a..bc75bad4e04b 100644 --- a/chart2/source/view/axes/Tickmarks_Dates.hxx +++ b/chart2/source/view/axes/Tickmarks_Dates.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_DATES_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_DATES_HXX +#pragma once #include "Tickmarks.hxx" @@ -28,8 +27,8 @@ class DateTickFactory { public: DateTickFactory( - const ExplicitScaleData& rScale - , const ExplicitIncrementData& rIncrement ); + ExplicitScaleData aScale + , ExplicitIncrementData aIncrement ); ~DateTickFactory(); void getAllTicks( TickInfoArraysType& rAllTickInfos ) const; @@ -46,6 +45,5 @@ private: //member }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/Tickmarks_Equidistant.cxx b/chart2/source/view/axes/Tickmarks_Equidistant.cxx index 60f6e63311ad..c1991fb3ba6e 100644 --- a/chart2/source/view/axes/Tickmarks_Equidistant.cxx +++ b/chart2/source/view/axes/Tickmarks_Equidistant.cxx @@ -23,6 +23,7 @@ #include <float.h> #include <limits> +#include <utility> namespace chart { @@ -70,9 +71,9 @@ double EquidistantTickFactory::getMaximumAtIncrement( double fMax, const Explici } EquidistantTickFactory::EquidistantTickFactory( - const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) - : m_rScale( rScale ) - , m_rIncrement( rIncrement ) + ExplicitScaleData aScale, ExplicitIncrementData aIncrement ) + : m_rScale(std::move( aScale )) + , m_rIncrement(std::move( aIncrement )) { //@todo: make sure that the scale is valid for the scaling @@ -105,7 +106,7 @@ EquidistantTickFactory::EquidistantTickFactory( m_fOuterMajorTickBorderMin_Scaled = m_fOuterMajorTickBorderMin; m_fOuterMajorTickBorderMax_Scaled = m_fOuterMajorTickBorderMax; - if(!(!m_rIncrement.PostEquidistant && m_xInverseScaling.is()) ) + if(m_rIncrement.PostEquidistant || !m_xInverseScaling.is()) return; m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin); @@ -150,6 +151,7 @@ void EquidistantTickFactory::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno:: return; uno::Sequence< double > aSubTicks(nMaxSubTickCount); + auto pSubTicks = aSubTicks.getArray(); sal_Int32 nRealSubTickCount = 0; sal_Int32 nIntervalCount = m_rIncrement.SubIncrements[nDepth-1].IntervalCount; @@ -163,13 +165,13 @@ void EquidistantTickFactory::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno:: if(!pValue) continue; - aSubTicks[nRealSubTickCount] = *pValue; + pSubTicks[nRealSubTickCount] = *pValue; nRealSubTickCount++; } } aSubTicks.realloc(nRealSubTickCount); - rParentTicks[nDepth] = aSubTicks; + rParentTicks.getArray()[nDepth] = aSubTicks; if(static_cast<sal_Int32>(m_rIncrement.SubIncrements.size())>nDepth) addSubTicks( nDepth+1, rParentTicks ); } @@ -317,7 +319,9 @@ void EquidistantTickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos ) co return; uno::Sequence< uno::Sequence< double > > aAllTicks(nDepthCount); - aAllTicks[0].realloc(nMaxMajorTickCount); + auto pAllTicks = aAllTicks.getArray(); + pAllTicks[0].realloc(nMaxMajorTickCount); + auto pAllTicks0 = pAllTicks[0].getArray(); sal_Int32 nRealMajorTickCount = 0; for( sal_Int32 nMajorTick=0; nMajorTick<nMaxMajorTickCount; nMajorTick++ ) @@ -325,12 +329,12 @@ void EquidistantTickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos ) co double* pValue = getMajorTick( nMajorTick ); if(!pValue) continue; - aAllTicks[0][nRealMajorTickCount] = *pValue; + pAllTicks0[nRealMajorTickCount] = *pValue; nRealMajorTickCount++; } if(!nRealMajorTickCount) return; - aAllTicks[0].realloc(nRealMajorTickCount); + pAllTicks[0].realloc(nRealMajorTickCount); addSubTicks(1, aAllTicks); @@ -350,7 +354,7 @@ void EquidistantTickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos ) co if( m_rIncrement.SubIncrements[nN].IntervalCount>1 ) nCheckCount *= m_rIncrement.SubIncrements[nN].IntervalCount; } - uno::Sequence< double >& rTicks = aAllTicks[nDepth]; + uno::Sequence< double >& rTicks = pAllTicks[nDepth]; sal_Int32 nCount = rTicks.getLength(); //check lower border for( nTick=0; nTick<nCheckCount && nTick<nCount; nTick++) @@ -377,8 +381,9 @@ void EquidistantTickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos ) co uno::Sequence< double > aOldTicks(rTicks); rTicks.realloc(nNewCount); + auto pTicks = rTicks.getArray(); for(nTick = 0; nTick<nNewCount; nTick++) - rTicks[nTick] = aOldTicks[nInvisibleAtLowerBorder+nTick]; + pTicks[nTick] = aOldTicks[nInvisibleAtLowerBorder+nTick]; } } diff --git a/chart2/source/view/axes/Tickmarks_Equidistant.hxx b/chart2/source/view/axes/Tickmarks_Equidistant.hxx index 55263c05ba28..6068903cb6e7 100644 --- a/chart2/source/view/axes/Tickmarks_Equidistant.hxx +++ b/chart2/source/view/axes/Tickmarks_Equidistant.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_EQUIDISTANT_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_TICKMARKS_EQUIDISTANT_HXX +#pragma once #include "Tickmarks.hxx" #include <memory> @@ -102,8 +101,8 @@ class EquidistantTickFactory { public: EquidistantTickFactory( - const ExplicitScaleData& rScale - , const ExplicitIncrementData& rIncrement ); + ExplicitScaleData aScale + , ExplicitIncrementData aIncrement ); ~EquidistantTickFactory(); void getAllTicks( TickInfoArraysType& rAllTickInfos ) const; @@ -143,6 +142,5 @@ private: //member }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VAxisBase.cxx b/chart2/source/view/axes/VAxisBase.cxx index 6e6f40b65684..30aead187dcb 100644 --- a/chart2/source/view/axes/VAxisBase.cxx +++ b/chart2/source/view/axes/VAxisBase.cxx @@ -21,11 +21,10 @@ #include <ShapeFactory.hxx> #include <ExplicitCategoriesProvider.hxx> #include "Tickmarks.hxx" -#include <com/sun/star/drawing/XShapes.hpp> +#include <Axis.hxx> +#include <VSeriesPlotter.hxx> #include <com/sun/star/chart2/AxisType.hpp> -#include <com/sun/star/chart2/XAxis.hpp> #include <com/sun/star/chart2/data/XTextualDataSequence.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> #include <osl/diagnose.h> @@ -85,10 +84,10 @@ void VAxisBase::initAxisLabelProperties( const css::awt::Size& rFontReferenceSiz m_bUseTextLabels = true; } - m_aAxisLabelProperties.nNumberFormatKey = m_aAxisProperties.m_nNumberFormatKey; + m_aAxisLabelProperties.m_nNumberFormatKey = m_aAxisProperties.m_nNumberFormatKey; m_aAxisLabelProperties.init(m_aAxisProperties.m_xAxisModel); if( m_aAxisProperties.m_bComplexCategories && m_aAxisProperties.m_nAxisType == AxisType::CATEGORY ) - m_aAxisLabelProperties.eStaggering = AxisLabelStaggering::SideBySide; + m_aAxisLabelProperties.m_eStaggering = AxisLabelStaggering::SideBySide; } bool VAxisBase::isDateAxis() const @@ -100,9 +99,9 @@ bool VAxisBase::isComplexCategoryAxis() const return m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels; } -void VAxisBase::recordMaximumTextSize( const Reference< drawing::XShape >& xShape, double fRotationAngleDegree ) +void VAxisBase::recordMaximumTextSize( SvxShape& xShape, double fRotationAngleDegree ) { - if( m_bRecordMaximumTextSize && xShape.is() ) + if( m_bRecordMaximumTextSize ) { awt::Size aSize( ShapeFactory::getSizeAfterRotation( xShape, fRotationAngleDegree ) ); @@ -132,15 +131,14 @@ bool VAxisBase::isAnythingToDraw() if( !m_aAxisProperties.m_xAxisModel.is() ) return false; - OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized"); - if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized"); + if(!(m_xLogicTarget.is()&&m_xFinalTarget.is())) return false; - uno::Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY ); - if( xProps.is() ) + if( m_aAxisProperties.m_xAxisModel.is() ) { bool bShow = false; - xProps->getPropertyValue( "Show" ) >>= bShow; + m_aAxisProperties.m_xAxisModel->getPropertyValue( "Show" ) >>= bShow; if( !bShow ) return false; } @@ -159,7 +157,7 @@ void VAxisBase::setExplicitScaleAndIncrement( void VAxisBase::createAllTickInfos( TickInfoArraysType& rAllTickInfos ) { std::unique_ptr< TickFactory > apTickFactory( createTickFactory() ); - if( m_aScale.ShiftedCategoryPosition ) + if( m_aScale.m_bShiftedCategoryPosition ) apTickFactory->getAllTicksShifted( rAllTickInfos ); else apTickFactory->getAllTicks( rAllTickInfos ); @@ -186,8 +184,10 @@ bool VAxisBase::prepareShapeCreation() //create named group shape m_xGroupShape_Shapes = createGroupShape( m_xLogicTarget, m_nDimension==2 ? m_aCID : ""); - if( m_aAxisProperties.m_bDisplayLabels ) - m_xTextTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget, m_aCID ); + if (m_aAxisProperties.m_bDisplayLabels) + m_xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget, m_aCID ); + if (m_aAxisProperties.m_bDisplayDataTable) + m_xDataTableTarget = ShapeFactory::createGroup2D(m_xFinalTarget); return true; } @@ -242,6 +242,13 @@ void VAxisBase::updateUnscaledValuesAtTicks( TickIter& rIter ) } } +void VAxisBase::createDataTableView(std::vector<std::unique_ptr<VSeriesPlotter>>& /*rSeriesPlotterList*/, + uno::Reference<util::XNumberFormatsSupplier> const& /*xNumberFormatsSupplier*/, + rtl::Reference<::chart::ChartModel> const& /*xChartDoc*/, + css::uno::Reference<css::uno::XComponentContext> const& /*rComponentContext*/) +{ +} + } //namespace chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VAxisBase.hxx b/chart2/source/view/axes/VAxisBase.hxx index bddba67f9e5c..4ee4f5e288ae 100644 --- a/chart2/source/view/axes/VAxisBase.hxx +++ b/chart2/source/view/axes/VAxisBase.hxx @@ -16,18 +16,23 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISBASE_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISBASE_HXX +#pragma once #include "VAxisOrGridBase.hxx" #include "VAxisProperties.hxx" #include "Tickmarks.hxx" namespace com::sun::star::util { class XNumberFormatsSupplier; } +namespace com::sun::star::uno { class XComponentContext; } namespace chart { +class VSeriesPlotter; +class DataTableView; +class ChartModel; +class LegendEntryProvider; + class VAxisBase : public VAxisOrGridBase { public: @@ -60,14 +65,20 @@ public: void setExtraLinePositionAtOtherAxis( double fCrossingAt ); + virtual void createDataTableView(std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList, + css::uno::Reference<css::util::XNumberFormatsSupplier> const& xNumberFormatsSupplier, + rtl::Reference<::chart::ChartModel> const& xChartDoc, + css::uno::Reference<css::uno::XComponentContext> const& rComponentContext); + + std::shared_ptr<DataTableView> getDataTableView() { return m_pDataTableView; } + protected: //methods static size_t getIndexOfLongestLabel( const css::uno::Sequence<OUString>& rLabels ); void removeTextShapesFromTicks(); void updateUnscaledValuesAtTicks( TickIter& rIter ); virtual bool prepareShapeCreation(); - void recordMaximumTextSize( const css::uno::Reference< css::drawing::XShape >& xShape - , double fRotationAngleDegree ); + void recordMaximumTextSize( SvxShape& xShape, double fRotationAngleDegree ); bool isDateAxis() const; bool isComplexCategoryAxis() const; @@ -79,8 +90,11 @@ protected: //member css::uno::Sequence< OUString > m_aTextLabels; bool m_bUseTextLabels; - css::uno::Reference< css::drawing::XShapes > m_xGroupShape_Shapes; - css::uno::Reference< css::drawing::XShapes > m_xTextTarget; + rtl::Reference< SvxShapeGroupAnyD > m_xGroupShape_Shapes; + rtl::Reference< SvxShapeGroupAnyD > m_xTextTarget; + rtl::Reference< SvxShapeGroupAnyD > m_xDataTableTarget; + + std::shared_ptr<DataTableView> m_pDataTableView; /** * This typically consists of 2 TickInfo vectors (i.e. the outer vector @@ -100,6 +114,5 @@ protected: //member }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VAxisOrGridBase.hxx b/chart2/source/view/axes/VAxisOrGridBase.hxx index 8bcaf898c3eb..1defc154a809 100644 --- a/chart2/source/view/axes/VAxisOrGridBase.hxx +++ b/chart2/source/view/axes/VAxisOrGridBase.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISORGRIDBASE_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISORGRIDBASE_HXX +#pragma once #include <PlotterBase.hxx> #include <ThreeDHelper.hxx> @@ -60,6 +59,5 @@ protected: //member }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx index 27a4950a886b..a69508cec77a 100644 --- a/chart2/source/view/axes/VAxisProperties.cxx +++ b/chart2/source/view/axes/VAxisProperties.cxx @@ -19,17 +19,17 @@ #include "VAxisProperties.hxx" #include <ViewDefines.hxx> +#include <Axis.hxx> #include <AxisHelper.hxx> #include <ChartModelHelper.hxx> #include <ExplicitCategoriesProvider.hxx> -#include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp> #include <com/sun/star/chart2/AxisType.hpp> -#include <com/sun/star/chart2/XAxis.hpp> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <rtl/math.hxx> +#include <utility> using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; @@ -152,9 +152,10 @@ TickmarkProperties AxisProperties::getBiggestTickmarkProperties() return aTickmarkProperties; } -AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel - , ExplicitCategoriesProvider* pExplicitCategoriesProvider ) - : m_xAxisModel(xAxisModel) +AxisProperties::AxisProperties(rtl::Reference<::chart::Axis> xAxisModel, + ExplicitCategoriesProvider* pExplicitCategoriesProvider, + rtl::Reference<::chart::DataTable> const& xDataTableModel) + : m_xAxisModel(std::move(xAxisModel)) , m_nDimensionIndex(0) , m_bIsMainAxis(true) , m_bSwapXAndY(false) @@ -163,18 +164,18 @@ AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel , m_eTickmarkPos( css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS ) , m_bCrossingAxisHasReverseDirection(false) , m_bCrossingAxisIsCategoryAxes(false) + , m_bDisplayDataTable(false) + , m_bDataTableAlignAxisValuesWithColumns(false) , m_bDisplayLabels( true ) , m_bTryStaggeringFirst( false ) , m_nNumberFormatKey(0) , m_nMajorTickmarks(1) , m_nMinorTickmarks(1) - , m_aTickmarkPropertiesList() - , m_aLineProperties() - //for category axes , m_nAxisType(AxisType::REALNUMBER) , m_bComplexCategories(false) , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider) , m_bLimitSpaceForLabels(false) + , m_xDataTableModel(xDataTableModel) { } @@ -243,13 +244,11 @@ void AxisProperties::initAxisPositioning( const uno::Reference< beans::XProperty void AxisProperties::init( bool bCartesian ) { - uno::Reference< beans::XPropertySet > xProp = - uno::Reference<beans::XPropertySet>::query( m_xAxisModel ); - if( !xProp.is() ) + if( !m_xAxisModel.is() ) return; if( m_nDimensionIndex<2 ) - initAxisPositioning( xProp ); + initAxisPositioning( m_xAxisModel ); ScaleData aScaleData = m_xAxisModel->getScaleData(); if( m_nDimensionIndex==0 ) @@ -258,6 +257,11 @@ void AxisProperties::init( bool bCartesian ) if( bCartesian ) { + if ((!m_bSwapXAndY && m_nDimensionIndex == 0) || (m_bSwapXAndY && m_nDimensionIndex == 1)) + { + m_bDisplayDataTable = m_xDataTableModel.is(); + } + if( m_nDimensionIndex == 0 && m_nAxisType == AxisType::CATEGORY && m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() ) m_bComplexCategories = true; @@ -286,10 +290,9 @@ void AxisProperties::init( bool bCartesian ) { maLabelAlignment.mfLabelDirection *= -1.0; maLabelAlignment.mfInnerTickDirection *= -1.0; - } - if( bIsYAxisPosition ) maLabelAlignment.meAlignment = lcl_getLabelAlignmentForYAxis(*this); + } else maLabelAlignment.meAlignment = lcl_getLabelAlignmentForXAxis(*this); } @@ -298,19 +301,19 @@ void AxisProperties::init( bool bCartesian ) try { //init LineProperties - m_aLineProperties.initFromPropertySet( xProp ); + m_aLineProperties.initFromPropertySet( m_xAxisModel ); //init display labels - xProp->getPropertyValue( "DisplayLabels" ) >>= m_bDisplayLabels; + m_xAxisModel->getPropertyValue( "DisplayLabels" ) >>= m_bDisplayLabels; // Init layout strategy hint for axis labels. // Compatibility option: starting from LibreOffice 5.1 the rotated // layout is preferred to staggering for axis labels. - xProp->getPropertyValue( "TryStaggeringFirst" ) >>= m_bTryStaggeringFirst; + m_xAxisModel->getPropertyValue( "TryStaggeringFirst" ) >>= m_bTryStaggeringFirst; //init TickmarkProperties - xProp->getPropertyValue( "MajorTickmarks" ) >>= m_nMajorTickmarks; - xProp->getPropertyValue( "MinorTickmarks" ) >>= m_nMinorTickmarks; + m_xAxisModel->getPropertyValue( "MajorTickmarks" ) >>= m_nMajorTickmarks; + m_xAxisModel->getPropertyValue( "MinorTickmarks" ) >>= m_nMinorTickmarks; sal_Int32 nMaxDepth = 0; if(m_nMinorTickmarks!=0) @@ -329,51 +332,60 @@ void AxisProperties::init( bool bCartesian ) { TOOLS_WARN_EXCEPTION("chart2", "" ); } + + if (m_bDisplayDataTable) + { + m_bDataTableAlignAxisValuesWithColumns = (m_nDimensionIndex == 0); + + if (m_nDimensionIndex == 0) + { + m_bDisplayLabels = false; + } + + } } AxisLabelProperties::AxisLabelProperties() : m_aFontReferenceSize( ChartModelHelper::getDefaultPageSize() ) , m_aMaximumSpaceForLabels( 0 , 0, m_aFontReferenceSize.Width, m_aFontReferenceSize.Height ) - , nNumberFormatKey(0) - , eStaggering( AxisLabelStaggering::SideBySide ) - , bLineBreakAllowed( false ) - , bOverlapAllowed( false ) - , bStackCharacters( false ) - , fRotationAngleDegree( 0.0 ) - , nRhythm( 1 ) + , m_nNumberFormatKey(0) + , m_eStaggering( AxisLabelStaggering::SideBySide ) + , m_bLineBreakAllowed( false ) + , m_bOverlapAllowed( false ) + , m_bStackCharacters( false ) + , m_fRotationAngleDegree( 0.0 ) + , m_nRhythm( 1 ) { } -void AxisLabelProperties::init( const uno::Reference< XAxis >& xAxisModel ) +void AxisLabelProperties::init( const rtl::Reference< Axis >& xAxisModel ) { - uno::Reference< beans::XPropertySet > xProp = - uno::Reference<beans::XPropertySet>::query( xAxisModel ); - if(!xProp.is()) + if(!xAxisModel.is()) return; try { - xProp->getPropertyValue( "TextBreak" ) >>= bLineBreakAllowed; - xProp->getPropertyValue( "TextOverlap" ) >>= bOverlapAllowed; - xProp->getPropertyValue( "StackCharacters" ) >>= bStackCharacters; - xProp->getPropertyValue( "TextRotation" ) >>= fRotationAngleDegree; + xAxisModel->getPropertyValue( "TextBreak" ) >>= m_bLineBreakAllowed; + xAxisModel->getPropertyValue( "TextOverlap" ) >>= m_bOverlapAllowed; + xAxisModel->getPropertyValue( "StackCharacters" ) >>= m_bStackCharacters; + xAxisModel->getPropertyValue( "TextRotation" ) >>= m_fRotationAngleDegree; css::chart::ChartAxisArrangeOrderType eArrangeOrder; - xProp->getPropertyValue( "ArrangeOrder" ) >>= eArrangeOrder; + xAxisModel->getPropertyValue( "ArrangeOrder" ) >>= eArrangeOrder; switch(eArrangeOrder) { case css::chart::ChartAxisArrangeOrderType_SIDE_BY_SIDE: - eStaggering = AxisLabelStaggering::SideBySide; + m_eStaggering = AxisLabelStaggering::SideBySide; break; case css::chart::ChartAxisArrangeOrderType_STAGGER_EVEN: - eStaggering = AxisLabelStaggering::StaggerEven; + m_eStaggering = AxisLabelStaggering::StaggerEven; break; case css::chart::ChartAxisArrangeOrderType_STAGGER_ODD: - eStaggering = AxisLabelStaggering::StaggerOdd; + m_eStaggering = AxisLabelStaggering::StaggerOdd; break; default: - eStaggering = AxisLabelStaggering::StaggerAuto; + m_eStaggering = AxisLabelStaggering::StaggerAuto; break; } } @@ -385,14 +397,14 @@ void AxisLabelProperties::init( const uno::Reference< XAxis >& xAxisModel ) bool AxisLabelProperties::isStaggered() const { - return ( eStaggering == AxisLabelStaggering::StaggerOdd || eStaggering == AxisLabelStaggering::StaggerEven ); + return ( m_eStaggering == AxisLabelStaggering::StaggerOdd || m_eStaggering == AxisLabelStaggering::StaggerEven ); } void AxisLabelProperties::autoRotate45() { - fRotationAngleDegree = 45; - bLineBreakAllowed = false; - eStaggering = AxisLabelStaggering::SideBySide; + m_fRotationAngleDegree = 45; + m_bLineBreakAllowed = false; + m_eStaggering = AxisLabelStaggering::SideBySide; } } //namespace chart diff --git a/chart2/source/view/axes/VAxisProperties.hxx b/chart2/source/view/axes/VAxisProperties.hxx index d087e5064e37..0cc23602b541 100644 --- a/chart2/source/view/axes/VAxisProperties.hxx +++ b/chart2/source/view/axes/VAxisProperties.hxx @@ -16,11 +16,12 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISPROPERTIES_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VAXISPROPERTIES_HXX +#pragma once #include "TickmarkProperties.hxx" +#include <Axis.hxx> #include <LabelAlignment.hxx> +#include <DataTable.hxx> #include <com/sun/star/chart/ChartAxisLabelPosition.hpp> #include <com/sun/star/chart/ChartAxisMarkPosition.hpp> @@ -28,6 +29,7 @@ #include <com/sun/star/awt/Rectangle.hpp> #include <com/sun/star/awt/Size.hpp> #include <com/sun/star/uno/Any.hxx> +#include <rtl/ref.hxx> #include <vector> #include <optional> @@ -59,20 +61,20 @@ struct AxisLabelProperties final css::awt::Size m_aFontReferenceSize;//reference size to calculate the font height css::awt::Rectangle m_aMaximumSpaceForLabels;//Labels need to be clipped in order to fit into this rectangle - sal_Int32 nNumberFormatKey; + sal_Int32 m_nNumberFormatKey; - AxisLabelStaggering eStaggering; + AxisLabelStaggering m_eStaggering; - bool bLineBreakAllowed; - bool bOverlapAllowed; + bool m_bLineBreakAllowed; + bool m_bOverlapAllowed; - bool bStackCharacters; - double fRotationAngleDegree; + bool m_bStackCharacters; + double m_fRotationAngleDegree; - sal_Int32 nRhythm; //show only each nth label with n==nRhythm + sal_Int32 m_nRhythm; //show only each nth label with n==nRhythm //methods: - void init( const css::uno::Reference< css::chart2::XAxis >& xAxisModel ); + void init( const rtl::Reference< ::chart::Axis >& xAxisModel ); bool isStaggered() const; @@ -91,7 +93,7 @@ struct AxisLabelAlignment struct AxisProperties final { - css::uno::Reference<css::chart2::XAxis> m_xAxisModel; + rtl::Reference<::chart::Axis> m_xAxisModel; sal_Int32 m_nDimensionIndex; bool m_bIsMainAxis;//not secondary axis @@ -109,7 +111,11 @@ struct AxisProperties final AxisLabelAlignment maLabelAlignment; - bool m_bDisplayLabels; + // Data table + bool m_bDisplayDataTable; + bool m_bDataTableAlignAxisValuesWithColumns; + + bool m_bDisplayLabels; // Compatibility option: starting from LibreOffice 5.1 the rotated // layout is preferred to staggering for axis labels. @@ -137,10 +143,13 @@ struct AxisProperties final bool m_bLimitSpaceForLabels; + rtl::Reference<::chart::DataTable> m_xDataTableModel; + //methods: - AxisProperties( const css::uno::Reference< css::chart2::XAxis >& xAxisModel - , ExplicitCategoriesProvider* pExplicitCategoriesProvider ); + AxisProperties(rtl::Reference<::chart::Axis> xAxisModel, + ExplicitCategoriesProvider* pExplicitCategoriesProvider, + rtl::Reference<::chart::DataTable> const& xDataTableModel); void init(bool bCartesian=false);//init from model data (m_xAxisModel) @@ -159,6 +168,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx index 1c62bfb93903..3b40602660f1 100644 --- a/chart2/source/view/axes/VCartesianAxis.cxx +++ b/chart2/source/view/axes/VCartesianAxis.cxx @@ -23,18 +23,23 @@ #include <PropertyMapper.hxx> #include <NumberFormatterWrapper.hxx> #include <LabelPositionHelper.hxx> -#include <TrueGuard.hxx> #include <BaseGFXHelper.hxx> +#include <Axis.hxx> #include <AxisHelper.hxx> #include "Tickmarks_Equidistant.hxx" #include <ExplicitCategoriesProvider.hxx> #include <com/sun/star/chart2/AxisType.hpp> -#include <com/sun/star/chart2/XAxis.hpp> +#include <o3tl/safeint.hxx> #include <rtl/math.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <tools/color.hxx> #include <svx/unoshape.hxx> #include <svx/unoshtxt.hxx> +#include <VSeriesPlotter.hxx> +#include <DataTableView.hxx> +#include <ChartModel.hxx> + +#include <comphelper/scopeguard.hxx> #include <basegfx/polygon/b2dpolygon.hxx> #include <basegfx/polygon/b2dpolypolygon.hxx> @@ -44,6 +49,7 @@ #include <basegfx/numeric/ftools.hxx> #include <algorithm> +#include <limits> #include <memory> using namespace ::com::sun::star; @@ -72,57 +78,52 @@ VCartesianAxis::~VCartesianAxis() m_pPosHelper = nullptr; } -static void lcl_ResizeTextShapeToFitAvailableSpace( Reference< drawing::XShape > const & xShape2DText, +static void lcl_ResizeTextShapeToFitAvailableSpace( SvxShapeText& rShape2DText, const AxisLabelProperties& rAxisLabelProperties, - const OUString& rLabel, + std::u16string_view rLabel, const tNameSequence& rPropNames, const tAnySequence& rPropValues, const bool bIsHorizontalAxis ) { - uno::Reference< text::XTextRange > xTextRange( xShape2DText, uno::UNO_QUERY ); + bool bTextHorizontal = rAxisLabelProperties.m_fRotationAngleDegree != 0.0; + bool bIsDirectionVertical = bIsHorizontalAxis && bTextHorizontal; + const sal_Int32 nFullSize = bIsDirectionVertical ? rAxisLabelProperties.m_aFontReferenceSize.Height : rAxisLabelProperties.m_aFontReferenceSize.Width; - if( !xTextRange.is() ) + if( !nFullSize || rLabel.empty() ) return; - const sal_Int32 nFullSize = bIsHorizontalAxis ? rAxisLabelProperties.m_aFontReferenceSize.Height : rAxisLabelProperties.m_aFontReferenceSize.Width; + const sal_Int32 nAvgCharWidth = rShape2DText.getSize().Width / rLabel.size(); - if( !nFullSize || !rLabel.getLength() ) - return; + sal_Int32 nMaxLabelsSize = bIsDirectionVertical ? rAxisLabelProperties.m_aMaximumSpaceForLabels.Height : rAxisLabelProperties.m_aMaximumSpaceForLabels.Width; - sal_Int32 nMaxLabelsSize = bIsHorizontalAxis ? rAxisLabelProperties.m_aMaximumSpaceForLabels.Height : rAxisLabelProperties.m_aMaximumSpaceForLabels.Width; - const sal_Int32 nAvgCharWidth = xShape2DText->getSize().Width / rLabel.getLength(); - const sal_Int32 nTextSize = bIsHorizontalAxis ? ShapeFactory::getSizeAfterRotation(xShape2DText, rAxisLabelProperties.fRotationAngleDegree).Height : - ShapeFactory::getSizeAfterRotation(xShape2DText, rAxisLabelProperties.fRotationAngleDegree).Width; + awt::Size aSizeAfterRotation = ShapeFactory::getSizeAfterRotation(rShape2DText, rAxisLabelProperties.m_fRotationAngleDegree); + + const sal_Int32 nTextSize = bIsDirectionVertical ? aSizeAfterRotation.Height : aSizeAfterRotation.Width; if( !nAvgCharWidth ) return; - const OUString sDots = "..."; + static constexpr OUString sDots = u"..."_ustr; const sal_Int32 nCharsToRemove = ( nTextSize - nMaxLabelsSize ) / nAvgCharWidth + 1; - sal_Int32 nNewLen = rLabel.getLength() - nCharsToRemove - sDots.getLength(); + sal_Int32 nNewLen = rLabel.size() - nCharsToRemove - sDots.getLength(); // Prevent from showing only dots if (nNewLen < 0) - nNewLen = ( rLabel.getLength() >= sDots.getLength() ) ? sDots.getLength() : rLabel.getLength(); + nNewLen = ( sal_Int32(rLabel.size()) >= sDots.getLength() ) ? sDots.getLength() : rLabel.size(); bool bCrop = nCharsToRemove > 0; if( !bCrop ) return; - OUString aNewLabel = rLabel.copy( 0, nNewLen ); + OUString aNewLabel( rLabel.substr( 0, nNewLen ) ); if( nNewLen > sDots.getLength() ) aNewLabel += sDots; - xTextRange->setString( aNewLabel ); + rShape2DText.setString( aNewLabel ); - uno::Reference< beans::XPropertySet > xProp( xTextRange, uno::UNO_QUERY ); - if( xProp.is() ) - { - PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); - } + PropertyMapper::setMultiProperties( rPropNames, rPropValues, rShape2DText ); } -static Reference< drawing::XShape > createSingleLabel( - const Reference< lang::XMultiServiceFactory>& xShapeFactory - , const Reference< drawing::XShapes >& xTarget +static rtl::Reference<SvxShapeText> createSingleLabel( + const rtl::Reference< SvxShapeGroupAnyD >& xTarget , const awt::Point& rAnchorScreenPosition2D , const OUString& rLabel , const AxisLabelProperties& rAxisLabelProperties @@ -136,30 +137,27 @@ static Reference< drawing::XShape > createSingleLabel( return nullptr; // #i78696# use mathematically correct rotation now - const double fRotationAnglePi(-basegfx::deg2rad(rAxisLabelProperties.fRotationAngleDegree)); + const double fRotationAnglePi(-basegfx::deg2rad(rAxisLabelProperties.m_fRotationAngleDegree)); uno::Any aATransformation = ShapeFactory::makeTransformation( rAnchorScreenPosition2D, fRotationAnglePi ); - OUString aLabel = ShapeFactory::getStackedString( rLabel, rAxisLabelProperties.bStackCharacters ); + OUString aLabel = ShapeFactory::getStackedString( rLabel, rAxisLabelProperties.m_bStackCharacters ); - Reference< drawing::XShape > xShape2DText = ShapeFactory::getOrCreateShapeFactory(xShapeFactory) - ->createText( xTarget, aLabel, rPropNames, rPropValues, aATransformation ); + rtl::Reference<SvxShapeText> xShape2DText = + ShapeFactory::createText( xTarget, aLabel, rPropNames, rPropValues, aATransformation ); if( rAxisProperties.m_bLimitSpaceForLabels ) - lcl_ResizeTextShapeToFitAvailableSpace(xShape2DText, rAxisLabelProperties, aLabel, rPropNames, rPropValues, bIsHorizontalAxis); + lcl_ResizeTextShapeToFitAvailableSpace(*xShape2DText, rAxisLabelProperties, aLabel, rPropNames, rPropValues, bIsHorizontalAxis); LabelPositionHelper::correctPositionForRotation( xShape2DText - , rAxisProperties.maLabelAlignment.meAlignment, rAxisLabelProperties.fRotationAngleDegree, rAxisProperties.m_bComplexCategories ); + , rAxisProperties.maLabelAlignment.meAlignment, rAxisLabelProperties.m_fRotationAngleDegree, rAxisProperties.m_bComplexCategories ); return xShape2DText; } -static bool lcl_doesShapeOverlapWithTickmark( const Reference< drawing::XShape >& xShape +static bool lcl_doesShapeOverlapWithTickmark( SvxShape& rShape , double fRotationAngleDegree , const basegfx::B2DVector& rTickScreenPosition ) { - if(!xShape.is()) - return false; - - ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(xShape->getPosition(), ShapeFactory::getSizeAfterRotation( xShape, fRotationAngleDegree )); + ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(rShape.getPosition(), ShapeFactory::getSizeAfterRotation( rShape, fRotationAngleDegree )); basegfx::B2IVector aPosition( static_cast<sal_Int32>( rTickScreenPosition.getX() ) @@ -187,8 +185,8 @@ static void lcl_getRotatedPolygon( B2DPolygon &aPoly, const ::basegfx::B2DRectan aPoly.transform( aMatrix ); } -static bool doesOverlap( const Reference< drawing::XShape >& xShape1 - , const Reference< drawing::XShape >& xShape2 +static bool doesOverlap( const rtl::Reference<SvxShapeText>& xShape1 + , const rtl::Reference<SvxShapeText>& xShape2 , double fRotationAngleDegree ) { if( !xShape1.is() || !xShape2.is() ) @@ -213,7 +211,7 @@ static bool doesOverlap( const Reference< drawing::XShape >& xShape1 static void removeShapesAtWrongRhythm( TickIter& rIter , sal_Int32 nCorrectRhythm , sal_Int32 nMaxTickToCheck - , const Reference< drawing::XShapes >& xTarget ) + , const rtl::Reference< SvxShapeGroupAnyD >& xTarget ) { sal_Int32 nTick = 0; for( TickInfo* pTickInfo = rIter.firstInfo() @@ -326,7 +324,7 @@ static B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDista aStaggerDirection.normalize(); sal_Int32 nDistance=0; - Reference< drawing::XShape > xShape2DText; + rtl::Reference< SvxShapeText > xShape2DText; for( TickInfo* pTickInfo = rIter.firstInfo() ; pTickInfo ; pTickInfo = rIter.nextInfo() ) @@ -334,7 +332,7 @@ static B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDista xShape2DText = pTickInfo->xTextShape; if( xShape2DText.is() ) { - awt::Size aSize = ShapeFactory::getSizeAfterRotation( xShape2DText, fRotationAngleDegree ); + awt::Size aSize = ShapeFactory::getSizeAfterRotation( *xShape2DText, fRotationAngleDegree ); if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY())) nDistance = std::max(nDistance,aSize.Width); else @@ -355,12 +353,11 @@ static void lcl_shiftLabels( TickIter& rIter, const B2DVector& rStaggerDistance { if(rStaggerDistance.getLength()==0.0) return; - Reference< drawing::XShape > xShape2DText; for( TickInfo* pTickInfo = rIter.firstInfo() ; pTickInfo ; pTickInfo = rIter.nextInfo() ) { - xShape2DText = pTickInfo->xTextShape; + const rtl::Reference<SvxShapeText>& xShape2DText = pTickInfo->xTextShape; if( xShape2DText.is() ) { awt::Point aPos = xShape2DText->getPosition(); @@ -371,17 +368,12 @@ static void lcl_shiftLabels( TickIter& rIter, const B2DVector& rStaggerDistance } } -static bool lcl_hasWordBreak( const Reference<drawing::XShape>& xShape ) +static bool lcl_hasWordBreak( const rtl::Reference<SvxShapeText>& xShape ) { if (!xShape.is()) return false; - SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>(xShape); - SvxShapeText* pShapeText = dynamic_cast<SvxShapeText*>(pShape); - if (!pShapeText) - return false; - - SvxTextEditSource* pTextEditSource = dynamic_cast<SvxTextEditSource*>(pShapeText->GetEditSource()); + SvxTextEditSource* pTextEditSource = dynamic_cast<SvxTextEditSource*>(xShape->GetEditSource()); if (!pTextEditSource) return false; @@ -442,7 +434,7 @@ static void getAxisLabelProperties( const AxisLabelProperties& rAxisLabelProp, sal_Int32 nLimitedSpaceForText, bool bLimitedHeight ) { - Reference<beans::XPropertySet> xProps(rAxisProp.m_xAxisModel, uno::UNO_QUERY); + Reference<beans::XPropertySet> xProps(rAxisProp.m_xAxisModel); PropertyMapper::getTextLabelMultiPropertyLists( xProps, rPropNames, rPropValues, false, nLimitedSpaceForText, bLimitedHeight, false); @@ -525,16 +517,16 @@ bool VCartesianAxis::isBreakOfLabelsAllowed( { if( m_aTextLabels.getLength() > 100 ) return false; - if( !rAxisLabelProperties.bLineBreakAllowed ) + if( !rAxisLabelProperties.m_bLineBreakAllowed ) return false; - if( rAxisLabelProperties.bStackCharacters ) + if( rAxisLabelProperties.m_bStackCharacters ) return false; //no break for value axis if( !m_bUseTextLabels ) return false; - if( !( rAxisLabelProperties.fRotationAngleDegree == 0.0 || - rAxisLabelProperties.fRotationAngleDegree == 90.0 || - rAxisLabelProperties.fRotationAngleDegree == 270.0 ) ) + if( !( rAxisLabelProperties.m_fRotationAngleDegree == 0.0 || + rAxisLabelProperties.m_fRotationAngleDegree == 90.0 || + rAxisLabelProperties.m_fRotationAngleDegree == 270.0 ) ) return false; //no break for complex vertical category axis if( !m_aAxisProperties.m_bSwapXAndY ) @@ -550,26 +542,26 @@ bool canAutoAdjustLabelPlacement( const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis, bool bIsVerticalAxis) { // joined prerequisite checks for auto rotate and auto stagger - if( rAxisLabelProperties.bOverlapAllowed ) + if( rAxisLabelProperties.m_bOverlapAllowed ) return false; - if( rAxisLabelProperties.bLineBreakAllowed ) // auto line break may conflict with... + if( rAxisLabelProperties.m_bLineBreakAllowed ) // auto line break may conflict with... return false; - if( rAxisLabelProperties.fRotationAngleDegree != 0.0 ) + if( rAxisLabelProperties.m_fRotationAngleDegree != 0.0 ) return false; // automatic adjusting labels only works for // horizontal axis with horizontal text // or vertical axis with vertical text if( bIsHorizontalAxis ) - return !rAxisLabelProperties.bStackCharacters; + return !rAxisLabelProperties.m_bStackCharacters; if( bIsVerticalAxis ) - return rAxisLabelProperties.bStackCharacters; + return rAxisLabelProperties.m_bStackCharacters; return false; } bool isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis, bool bIsVerticalAxis ) { - if( rAxisLabelProperties.eStaggering != AxisLabelStaggering::StaggerAuto ) + if( rAxisLabelProperties.m_eStaggering != AxisLabelStaggering::StaggerAuto ) return false; return canAutoAdjustLabelPlacement(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis); } @@ -674,7 +666,7 @@ void VCartesianAxis::createAllTickInfos( TickInfoArraysType& rAllTickInfos ) TickIter* VCartesianAxis::createLabelTickIterator( sal_Int32 nTextLevel ) { - if( nTextLevel>=0 && nTextLevel < static_cast< sal_Int32 >(m_aAllTickInfos.size()) ) + if( nTextLevel>=0 && o3tl::make_unsigned(nTextLevel) < m_aAllTickInfos.size() ) return new PureTickIter( m_aAllTickInfos[nTextLevel] ); return nullptr; } @@ -711,7 +703,7 @@ sal_Int32 VCartesianAxis::getTextLevelCount() const } bool VCartesianAxis::createTextShapes( - const Reference<drawing::XShapes>& xTarget, TickIter& rTickIter, + const rtl::Reference< SvxShapeGroupAnyD >& xTarget, TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties, TickFactory2D const * pTickFactory, sal_Int32 nScreenDistanceBetweenTicks ) { @@ -733,21 +725,31 @@ bool VCartesianAxis::createTextShapes( } } - if (!isBreakOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) && + bool bIsBreakOfLabelsAllowed = isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ); + if (!bIsBreakOfLabelsAllowed && !isAutoStaggeringOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) && !rAxisLabelProperties.isStaggered()) + { return createTextShapesSimple(xTarget, rTickIter, rAxisLabelProperties, pTickFactory); + } FixedNumberFormatter aFixedNumberFormatter( - m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); + m_xNumberFormatsSupplier, rAxisLabelProperties.m_nNumberFormatKey ); bool bIsStaggered = rAxisLabelProperties.isStaggered(); B2DVector aTextToTickDistance = pTickFactory->getDistanceAxisTickToText(m_aAxisProperties, true); sal_Int32 nLimitedSpaceForText = -1; - if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) ) + if (bIsBreakOfLabelsAllowed) { - nLimitedSpaceForText = nScreenDistanceBetweenTicks; + if (!m_aAxisProperties.m_bLimitSpaceForLabels) + { + basegfx::B2DVector nDeltaVector = pTickFactory->getXaxisEndPos() - pTickFactory->getXaxisStartPos(); + nLimitedSpaceForText = nDeltaVector.getX(); + } + if (nScreenDistanceBetweenTicks > 0) + nLimitedSpaceForText = nScreenDistanceBetweenTicks; + if( bIsStaggered ) nLimitedSpaceForText *= 2; @@ -760,14 +762,14 @@ bool VCartesianAxis::createTextShapes( } // recalculate the nLimitedSpaceForText in case of 90 and 270 degree if the text break is true - if ( rAxisLabelProperties.fRotationAngleDegree == 90.0 || rAxisLabelProperties.fRotationAngleDegree == 270.0 ) + if ( rAxisLabelProperties.m_fRotationAngleDegree == 90.0 || rAxisLabelProperties.m_fRotationAngleDegree == 270.0 ) { nLimitedSpaceForText = rAxisLabelProperties.m_aMaximumSpaceForLabels.Height; m_aAxisProperties.m_bLimitSpaceForLabels = false; } // recalculate the nLimitedSpaceForText in case of vertical category axis if the text break is true - if ( m_aAxisProperties.m_bSwapXAndY && bIsVerticalAxis && rAxisLabelProperties.fRotationAngleDegree == 0.0 ) + if ( m_aAxisProperties.m_bSwapXAndY && bIsVerticalAxis && rAxisLabelProperties.m_fRotationAngleDegree == 0.0 ) { nLimitedSpaceForText = pTickFactory->getXaxisStartPos().getX(); m_aAxisProperties.m_bLimitSpaceForLabels = false; @@ -790,7 +792,7 @@ bool VCartesianAxis::createTextShapes( tAnySequence aPropValues; getAxisLabelProperties(aPropNames, aPropValues, m_aAxisProperties, rAxisLabelProperties, nLimitedSpaceForText, bLimitedHeight); - uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,"CharColor"); + uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,u"CharColor"); Color nColor = COL_AUTO; if(pColorAny) *pColorAny >>= nColor; @@ -808,21 +810,21 @@ bool VCartesianAxis::createTextShapes( pPREPreviousVisibleTickInfo : pPreviousVisibleTickInfo; //don't create labels which does not fit into the rhythm - if( nTick%rAxisLabelProperties.nRhythm != 0 ) + if( nTick%rAxisLabelProperties.m_nRhythm != 0 ) continue; //don't create labels for invisible ticks if( !pTickInfo->bPaintIt ) continue; - if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed ) + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.m_bOverlapAllowed ) { // Overlapping is not allowed. If the label overlaps with its // neighboring label, try increasing the tick interval (or rhythm // as it's called) and start over. - if( lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape - , rAxisLabelProperties.fRotationAngleDegree + if( lcl_doesShapeOverlapWithTickmark( *pLastVisibleNeighbourTickInfo->xTextShape + , rAxisLabelProperties.m_fRotationAngleDegree , pTickInfo->aTickScreenPosition ) ) { // This tick overlaps with its neighbor. Try to stagger (if @@ -832,11 +834,11 @@ bool VCartesianAxis::createTextShapes( if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) ) { bIsStaggered = true; - rAxisLabelProperties.eStaggering = AxisLabelStaggering::StaggerEven; + rAxisLabelProperties.m_eStaggering = AxisLabelStaggering::StaggerEven; pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo; if( !pLastVisibleNeighbourTickInfo || - !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape - , rAxisLabelProperties.fRotationAngleDegree + !lcl_doesShapeOverlapWithTickmark( *pLastVisibleNeighbourTickInfo->xTextShape + , rAxisLabelProperties.m_fRotationAngleDegree , pTickInfo->aTickScreenPosition ) ) bOverlapsAfterAutoStagger = false; } @@ -847,8 +849,8 @@ bool VCartesianAxis::createTextShapes( // Increment the visible tick intervals (if that's // allowed) and start over. - rAxisLabelProperties.nRhythm++; - removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + rAxisLabelProperties.m_nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.m_nRhythm, nTick, xTarget ); return false; } } @@ -874,37 +876,41 @@ bool VCartesianAxis::createTextShapes( //create single label if(!pTickInfo->xTextShape.is()) - pTickInfo->xTextShape = createSingleLabel( m_xShapeFactory, xTarget + { + pTickInfo->xTextShape = createSingleLabel( xTarget , aAnchorScreenPosition2D, aLabel , rAxisLabelProperties, m_aAxisProperties , aPropNames, aPropValues, bIsHorizontalAxis ); + } if(!pTickInfo->xTextShape.is()) continue; - recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ); + recordMaximumTextSize( *pTickInfo->xTextShape, rAxisLabelProperties.m_fRotationAngleDegree ); // Label has multiple lines and the words are broken - if( nLimitedSpaceForText>0 && !rAxisLabelProperties.bOverlapAllowed - && rAxisLabelProperties.fRotationAngleDegree == 0.0 - && lcl_hasWordBreak( pTickInfo->xTextShape ) ) + if (nLimitedSpaceForText > 0 + && !rAxisLabelProperties.m_bOverlapAllowed + && rAxisLabelProperties.m_fRotationAngleDegree == 0.0 + && nTick > 0 + && lcl_hasWordBreak(pTickInfo->xTextShape)) { // Label has multiple lines and belongs to a complex category // axis. Rotate 90 degrees to try to avoid overlaps. if ( m_aAxisProperties.m_bComplexCategories ) { - rAxisLabelProperties.fRotationAngleDegree = 90; + rAxisLabelProperties.m_fRotationAngleDegree = 90; } - rAxisLabelProperties.bLineBreakAllowed = false; - m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; + rAxisLabelProperties.m_bLineBreakAllowed = false; + m_aAxisLabelProperties.m_fRotationAngleDegree = rAxisLabelProperties.m_fRotationAngleDegree; removeTextShapesFromTicks(); return false; } //if NO OVERLAP -> remove overlapping shapes - if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed ) + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.m_bOverlapAllowed ) { // Check if the label still overlaps with its neighbor. - if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ) ) + if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.m_fRotationAngleDegree ) ) { // It overlaps. Check if staggering helps. bool bOverlapsAfterAutoStagger = true; @@ -916,11 +922,11 @@ bool VCartesianAxis::createTextShapes( || m_aAxisProperties.m_bTryStaggeringFirst ) { bIsStaggered = true; - rAxisLabelProperties.eStaggering = AxisLabelStaggering::StaggerEven; + rAxisLabelProperties.m_eStaggering = AxisLabelStaggering::StaggerEven; pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo; if( !pLastVisibleNeighbourTickInfo || - !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape - , rAxisLabelProperties.fRotationAngleDegree + !lcl_doesShapeOverlapWithTickmark( *pLastVisibleNeighbourTickInfo->xTextShape + , rAxisLabelProperties.m_fRotationAngleDegree , pTickInfo->aTickScreenPosition ) ) bOverlapsAfterAutoStagger = false; } @@ -937,15 +943,15 @@ bool VCartesianAxis::createTextShapes( // The nRhythm parameter is reset to 1 since the layout // used for text labels is changed. rAxisLabelProperties.autoRotate45(); - m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; // Store it for future runs. + m_aAxisLabelProperties.m_fRotationAngleDegree = rAxisLabelProperties.m_fRotationAngleDegree; // Store it for future runs. removeTextShapesFromTicks(); - rAxisLabelProperties.nRhythm = 1; + rAxisLabelProperties.m_nRhythm = 1; return false; } // Try incrementing the tick interval and start over. - rAxisLabelProperties.nRhythm++; - removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + rAxisLabelProperties.m_nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.m_nRhythm, nTick, xTarget ); return false; } } @@ -958,11 +964,11 @@ bool VCartesianAxis::createTextShapes( } bool VCartesianAxis::createTextShapesSimple( - const Reference<drawing::XShapes>& xTarget, TickIter& rTickIter, + const rtl::Reference< SvxShapeGroupAnyD >& xTarget, TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties, TickFactory2D const * pTickFactory ) { FixedNumberFormatter aFixedNumberFormatter( - m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); + m_xNumberFormatsSupplier, rAxisLabelProperties.m_nNumberFormatKey ); const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis(); const bool bIsVerticalAxis = pTickFactory->isVerticalAxis(); @@ -981,7 +987,7 @@ bool VCartesianAxis::createTextShapesSimple( tAnySequence aPropValues; getAxisLabelProperties(aPropNames, aPropValues, m_aAxisProperties, rAxisLabelProperties, -1, bLimitedHeight); - uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,"CharColor"); + uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,u"CharColor"); Color nColor = COL_AUTO; if(pColorAny) *pColorAny >>= nColor; @@ -997,28 +1003,28 @@ bool VCartesianAxis::createTextShapesSimple( const TickInfo* pLastVisibleNeighbourTickInfo = pPreviousVisibleTickInfo; //don't create labels which does not fit into the rhythm - if( nTick%rAxisLabelProperties.nRhythm != 0 ) + if( nTick%rAxisLabelProperties.m_nRhythm != 0 ) continue; //don't create labels for invisible ticks if( !pTickInfo->bPaintIt ) continue; - if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed ) + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.m_bOverlapAllowed ) { // Overlapping is not allowed. If the label overlaps with its // neighboring label, try increasing the tick interval (or rhythm // as it's called) and start over. - if( lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape - , rAxisLabelProperties.fRotationAngleDegree + if( lcl_doesShapeOverlapWithTickmark( *pLastVisibleNeighbourTickInfo->xTextShape + , rAxisLabelProperties.m_fRotationAngleDegree , pTickInfo->aTickScreenPosition ) ) { // This tick overlaps with its neighbor. Increment the visible // tick intervals (if that's allowed) and start over. - rAxisLabelProperties.nRhythm++; - removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + rAxisLabelProperties.m_nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.m_nRhythm, nTick, xTarget ); return false; } } @@ -1043,20 +1049,20 @@ bool VCartesianAxis::createTextShapesSimple( //create single label if(!pTickInfo->xTextShape.is()) - pTickInfo->xTextShape = createSingleLabel( m_xShapeFactory, xTarget + pTickInfo->xTextShape = createSingleLabel( xTarget , aAnchorScreenPosition2D, aLabel , rAxisLabelProperties, m_aAxisProperties , aPropNames, aPropValues, bIsHorizontalAxis ); if(!pTickInfo->xTextShape.is()) continue; - recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ); + recordMaximumTextSize( *pTickInfo->xTextShape, rAxisLabelProperties.m_fRotationAngleDegree ); //if NO OVERLAP -> remove overlapping shapes - if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed ) + if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.m_bOverlapAllowed ) { // Check if the label still overlaps with its neighbor. - if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ) ) + if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.m_fRotationAngleDegree ) ) { // It overlaps. if( isAutoRotatingOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) ) @@ -1067,15 +1073,15 @@ bool VCartesianAxis::createTextShapesSimple( // The nRhythm parameter is reset to 1 since the layout // used for text labels is changed. rAxisLabelProperties.autoRotate45(); - m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; // Store it for future runs. + m_aAxisLabelProperties.m_fRotationAngleDegree = rAxisLabelProperties.m_fRotationAngleDegree; // Store it for future runs. removeTextShapesFromTicks(); - rAxisLabelProperties.nRhythm = 1; + rAxisLabelProperties.m_nRhythm = 1; return false; } // Try incrementing the tick interval and start over. - rAxisLabelProperties.nRhythm++; - removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget ); + rAxisLabelProperties.m_nRhythm++; + removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.m_nRhythm, nTick, xTarget ); return false; } } @@ -1109,18 +1115,15 @@ double VCartesianAxis::getLabelLineIntersectionValue() const double VCartesianAxis::getExtraLineIntersectionValue() const { - double fNan; - rtl::math::setNan(&fNan); - if( !m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis ) - return fNan; + return std::numeric_limits<double>::quiet_NaN(); double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY(); double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY(); if( *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis <= fMin || *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis >= fMax ) - return fNan; + return std::numeric_limits<double>::quiet_NaN(); return *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis; } @@ -1134,10 +1137,10 @@ B2DVector VCartesianAxis::getScreenPosition( double fLogicX, double fLogicY, dou drawing::Position3D aScenePos = m_pPosHelper->transformLogicToScene( fLogicX, fLogicY, fLogicZ, true ); if(m_nDimension==3) { - if (m_xLogicTarget.is() && m_pShapeFactory) + if (m_xLogicTarget.is()) { tPropertyNameMap aDummyPropertyNameMap; - Reference< drawing::XShape > xShape3DAnchor = m_pShapeFactory->createCube( m_xLogicTarget + rtl::Reference<Svx3DExtrudeObject> xShape3DAnchor = ShapeFactory::createCube( m_xLogicTarget , aScenePos,drawing::Direction3D(1,1,1), 0, nullptr, aDummyPropertyNameMap); awt::Point a2DPos = xShape3DAnchor->getPosition(); //get 2D position from xShape3DAnchor m_xLogicTarget->remove(xShape3DAnchor); @@ -1275,9 +1278,7 @@ void VCartesianAxis::get2DAxisMainLine( double fDeltaY = rEnd.getY() - rStart.getY(); //only those points are candidates which are lying on exactly one wall as these are outer edges - tScreenPosAndLogicPosList aPosList; - aPosList.push_back( getScreenPosAndLogicPos( fMinX, fYOnYPlane, fZOther ) ); - aPosList.push_back( getScreenPosAndLogicPos( fMinX, fYOther, fZOnZPlane ) ); + tScreenPosAndLogicPosList aPosList { getScreenPosAndLogicPos( fMinX, fYOnYPlane, fZOther ), getScreenPosAndLogicPos( fMinX, fYOther, fZOnZPlane ) }; if( fabs(fDeltaY) > fabs(fDeltaX) ) { @@ -1329,9 +1330,7 @@ void VCartesianAxis::get2DAxisMainLine( double fDeltaY = rEnd.getY() - rStart.getY(); //only those points are candidates which are lying on exactly one wall as these are outer edges - tScreenPosAndLogicPosList aPosList; - aPosList.push_back( getScreenPosAndLogicPos( fXOnXPlane, fMinY, fZOther ) ); - aPosList.push_back( getScreenPosAndLogicPos( fXOther, fMinY, fZOnZPlane ) ); + tScreenPosAndLogicPosList aPosList { getScreenPosAndLogicPos( fXOnXPlane, fMinY, fZOther ), getScreenPosAndLogicPos( fXOther, fMinY, fZOnZPlane ) }; if( fabs(fDeltaY) > fabs(fDeltaX) ) { @@ -1408,9 +1407,7 @@ void VCartesianAxis::get2DAxisMainLine( double fDeltaX = rEnd.getX() - rStart.getX(); //only those points are candidates which are lying on exactly one wall as these are outer edges - tScreenPosAndLogicPosList aPosList; - aPosList.push_back( getScreenPosAndLogicPos( fXOther, fYOnYPlane, fMinZ ) ); - aPosList.push_back( getScreenPosAndLogicPos( fXOnXPlane, fYOther, fMinZ ) ); + tScreenPosAndLogicPosList aPosList { getScreenPosAndLogicPos( fXOther, fYOnYPlane, fMinZ ), getScreenPosAndLogicPos( fXOnXPlane, fYOther, fMinZ ) }; std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() ); ScreenPosAndLogicPos aBestPos( aPosList[0] ); @@ -1583,14 +1580,14 @@ sal_Int32 VCartesianAxis::estimateMaximumAutoMainIncrementCount() // tdf#48041: do not duplicate the value labels because of rounding if (m_aAxisProperties.m_nAxisType != css::chart2::AxisType::DATE) { - FixedNumberFormatter aFixedNumberFormatterTest(m_xNumberFormatsSupplier, m_aAxisLabelProperties.nNumberFormatKey); + FixedNumberFormatter aFixedNumberFormatterTest(m_xNumberFormatsSupplier, m_aAxisLabelProperties.m_nNumberFormatKey); OUString sPreviousValueLabel; sal_Int32 nSameLabel = 0; - for (sal_Int32 nLabel = 0; nLabel < static_cast<sal_Int32>(m_aAllTickInfos[0].size()); ++nLabel) + for (auto const & nLabel: m_aAllTickInfos[0]) { Color nColor = COL_AUTO; bool bHasColor = false; - OUString sValueLabel = aFixedNumberFormatterTest.getFormattedString(m_aAllTickInfos[0][nLabel].fScaledTickValue, nColor, bHasColor); + OUString sValueLabel = aFixedNumberFormatterTest.getFormattedString(nLabel.fScaledTickValue, nColor, bHasColor); if (sValueLabel == sPreviousValueLabel) { nSameLabel++; @@ -1631,23 +1628,23 @@ void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabel if( isComplexCategoryAxis() ) { sal_Int32 nTextLevelCount = getTextLevelCount(); - B2DVector aCummulatedLabelsDistance(0,0); + B2DVector aCumulatedLabelsDistance(0,0); for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) { std::unique_ptr<TickIter> apTickIter(createLabelTickIterator(nTextLevel)); if (apTickIter) { - double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree; + double fRotationAngleDegree = m_aAxisLabelProperties.m_fRotationAngleDegree; if( nTextLevel>0 ) { - lcl_shiftLabels(*apTickIter, aCummulatedLabelsDistance); + lcl_shiftLabels(*apTickIter, aCumulatedLabelsDistance); //multilevel labels: 0 or 90 by default if( m_aAxisProperties.m_bSwapXAndY ) fRotationAngleDegree = 90.0; else fRotationAngleDegree = 0.0; } - aCummulatedLabelsDistance += lcl_getLabelsDistance( + aCumulatedLabelsDistance += lcl_getLabelsDistance( *apTickIter, pTickFactory2D->getDistanceAxisTickToText(m_aAxisProperties), fRotationAngleDegree); } @@ -1657,8 +1654,8 @@ void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabel { if( !m_aAllTickInfos.empty() ) { - LabelIterator aInnerIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, true ); - LabelIterator aOuterIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, false ); + LabelIterator aInnerIter( m_aAllTickInfos[0], rAxisLabelProperties.m_eStaggering, true ); + LabelIterator aOuterIter( m_aAllTickInfos[0], rAxisLabelProperties.m_eStaggering, false ); lcl_shiftLabels( aOuterIter , lcl_getLabelsDistance( aInnerIter @@ -1667,16 +1664,55 @@ void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabel } } +void VCartesianAxis::createDataTableShape(std::unique_ptr<TickFactory2D> const& rpTickFactory2D) +{ + // Check if we can create the data table shape + // Data table view and m_bDisplayDataTable must be true + if (!m_pDataTableView || !m_aAxisProperties.m_bDisplayDataTable) + return; + + m_pDataTableView->initializeShapes(m_xDataTableTarget); + basegfx::B2DVector aStart = rpTickFactory2D->getXaxisStartPos(); + basegfx::B2DVector aEnd = rpTickFactory2D->getXaxisEndPos(); + + rpTickFactory2D->updateScreenValues(m_aAllTickInfos); + + sal_Int32 nDistance = -1; + + std::unique_ptr<TickIter> apTickIter(createLabelTickIterator(0)); + if (apTickIter) + { + nDistance = TickFactory2D::getTickScreenDistance(*apTickIter); + if (getTextLevelCount() > 1) + nDistance *= 2; + } + + if (nDistance <= 0) + { + // we only have one data series so we have no TickMarks, therefore calculate and use the table size + auto rDelta = aEnd - aStart; + nDistance = basegfx::fround(rDelta.getX()); + } + + if (nDistance > 0) + { + m_pDataTableView->createShapes(aStart, aEnd, nDistance); + } +} + void VCartesianAxis::createLabels() { if( !prepareShapeCreation() ) return; + std::unique_ptr<TickFactory2D> apTickFactory2D(createTickFactory2D()); // throws on failure + + createDataTableShape(apTickFactory2D); + //create labels if (!m_aAxisProperties.m_bDisplayLabels) return; - std::unique_ptr<TickFactory2D> apTickFactory2D(createTickFactory2D()); // throws on failure TickFactory2D* pTickFactory2D = apTickFactory2D.get(); //get the transformed screen values for all tickmarks in aAllTickInfos @@ -1704,15 +1740,15 @@ void VCartesianAxis::createLabels() AxisLabelProperties aComplexProps(m_aAxisLabelProperties); if( m_aAxisProperties.m_bComplexCategories ) { - aComplexProps.bLineBreakAllowed = true; - aComplexProps.bOverlapAllowed = aComplexProps.fRotationAngleDegree != 0.0; + aComplexProps.m_bLineBreakAllowed = true; + aComplexProps.m_bOverlapAllowed = aComplexProps.m_fRotationAngleDegree != 0.0; if( nTextLevel > 0 ) { //multilevel labels: 0 or 90 by default if( m_aAxisProperties.m_bSwapXAndY ) - aComplexProps.fRotationAngleDegree = 90.0; + aComplexProps.m_fRotationAngleDegree = 90.0; else - aComplexProps.fRotationAngleDegree = 0.0; + aComplexProps.m_fRotationAngleDegree = 0.0; } } AxisLabelProperties& rAxisLabelProperties = m_aAxisProperties.m_bComplexCategories ? aComplexProps : m_aAxisLabelProperties; @@ -1723,11 +1759,20 @@ void VCartesianAxis::createLabels() } } doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D ); + + if (m_pDataTableView) + { + sal_Int32 x = m_xTextTarget->getPosition().X; + sal_Int32 y = m_xTextTarget->getPosition().Y; + sal_Int32 height = m_xTextTarget->getSize().Height; + m_pDataTableView->changePosition(x, y + height); + } } void VCartesianAxis::createMaximumLabels() { - TrueGuard aRecordMaximumTextSize(m_bRecordMaximumTextSize); + m_bRecordMaximumTextSize = true; + const comphelper::ScopeGuard aGuard([this]() { m_bRecordMaximumTextSize = false; }); if( !prepareShapeCreation() ) return; @@ -1747,10 +1792,10 @@ void VCartesianAxis::createMaximumLabels() AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties ); if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickFactory2D->isHorizontalAxis(), pTickFactory2D->isVerticalAxis() ) ) - aAxisLabelProperties.eStaggering = AxisLabelStaggering::StaggerEven; + aAxisLabelProperties.m_eStaggering = AxisLabelStaggering::StaggerEven; - aAxisLabelProperties.bOverlapAllowed = true; - aAxisLabelProperties.bLineBreakAllowed = false; + aAxisLabelProperties.m_bOverlapAllowed = true; + aAxisLabelProperties.m_bLineBreakAllowed = false; sal_Int32 nTextLevelCount = getTextLevelCount(); for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ ) { @@ -1783,7 +1828,7 @@ void VCartesianAxis::updatePositions() { for (auto const& tickInfo : tickInfos) { - Reference< drawing::XShape > xShape2DText(tickInfo.xTextShape); + const rtl::Reference<SvxShapeText> & xShape2DText(tickInfo.xTextShape); if( xShape2DText.is() ) { B2DVector aTextToTickDistance( pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, true ) ); @@ -1793,7 +1838,7 @@ void VCartesianAxis::updatePositions() static_cast<sal_Int32>(aTickScreenPos2D.getX()) ,static_cast<sal_Int32>(aTickScreenPos2D.getY())); - double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree; + double fRotationAngleDegree = m_aAxisLabelProperties.m_fRotationAngleDegree; if( nDepth > 0 ) { //multilevel labels: 0 or 90 by default @@ -1808,17 +1853,13 @@ void VCartesianAxis::updatePositions() uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi); //set new position - uno::Reference< beans::XPropertySet > xProp( xShape2DText, uno::UNO_QUERY ); - if( xProp.is() ) + try { - try - { - xProp->setPropertyValue( "Transformation", aATransformation ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + xShape2DText->SvxShape::setPropertyValue( "Transformation", aATransformation ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } //correctPositionForRotation @@ -1857,7 +1898,7 @@ void VCartesianAxis::createTickMarkLineShapes( TickInfoArrayType& rTickInfos, co , m_aAxisProperties.maLabelAlignment.mfInnerTickDirection, rTickmarkProperties, !bTicksAtLabels ); } aPoints.realloc(nN); - m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints + ShapeFactory::createLine2D( m_xGroupShape_Shapes, aPoints , &rTickmarkProperties.aLineProperties ); } @@ -1866,12 +1907,12 @@ void VCartesianAxis::createShapes() if( !prepareShapeCreation() ) return; - std::unique_ptr<TickFactory2D> apTickFactory2D(createTickFactory2D()); // throws on failure - TickFactory2D* pTickFactory2D = apTickFactory2D.get(); - //create line shapes if(m_nDimension==2) { + std::unique_ptr<TickFactory2D> apTickFactory2D(createTickFactory2D()); // throws on failure + TickFactory2D* pTickFactory2D = apTickFactory2D.get(); + //create extra long ticks to separate complex categories (create them only there where the labels are) if( isComplexCategoryAxis() ) { @@ -1889,7 +1930,7 @@ void VCartesianAxis::createShapes() std::unique_ptr< TickIter > apTickIter(createLabelTickIterator( nTextLevel )); if( apTickIter ) { - double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree; + double fRotationAngleDegree = m_aAxisLabelProperties.m_fRotationAngleDegree; if( nTextLevel > 0 ) { //Multi-level Labels: default to 0 or 90 @@ -1920,13 +1961,13 @@ void VCartesianAxis::createShapes() //create normal ticks for major and minor intervals { TickInfoArraysType aUnshiftedTickInfos; - if( m_aScale.ShiftedCategoryPosition )// if ShiftedCategoryPosition==true the tickmarks in m_aAllTickInfos are shifted + if( m_aScale.m_bShiftedCategoryPosition )// if m_bShiftedCategoryPosition==true the tickmarks in m_aAllTickInfos are shifted { pTickFactory2D->getAllTicks( aUnshiftedTickInfos ); pTickFactory2D->updateScreenValues( aUnshiftedTickInfos ); hideIdenticalScreenValues( aUnshiftedTickInfos ); } - TickInfoArraysType& rAllTickInfos = m_aScale.ShiftedCategoryPosition ? aUnshiftedTickInfos : m_aAllTickInfos; + TickInfoArraysType& rAllTickInfos = m_aScale.m_bShiftedCategoryPosition ? aUnshiftedTickInfos : m_aAllTickInfos; if (rAllTickInfos.empty()) return; @@ -1947,7 +1988,7 @@ void VCartesianAxis::createShapes() { drawing::PointSequenceSequence aPoints(1); apTickFactory2D->createPointSequenceForAxisMainLine( aPoints ); - Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( + rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D( m_xGroupShape_Shapes, aPoints , &m_aAxisProperties.m_aLineProperties ); //because of this name this line will be used for marking the axis @@ -1966,7 +2007,7 @@ void VCartesianAxis::createShapes() drawing::PointSequenceSequence aPoints{{ {static_cast<sal_Int32>(aStart.getX()), static_cast<sal_Int32>(aStart.getY())}, {static_cast<sal_Int32>(aEnd.getX()), static_cast<sal_Int32>(aEnd.getY())} }}; - m_pShapeFactory->createLine2D( + ShapeFactory::createLine2D( m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties ); } } @@ -1975,6 +2016,20 @@ void VCartesianAxis::createShapes() createLabels(); } +void VCartesianAxis::createDataTableView(std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList, + Reference<util::XNumberFormatsSupplier> const& xNumberFormatsSupplier, + rtl::Reference<::chart::ChartModel> const& xChartDoc, + css::uno::Reference<css::uno::XComponentContext> const& rComponentContext) +{ + if (!m_aAxisProperties.m_bDisplayDataTable) + return; + + m_pDataTableView.reset(new DataTableView(xChartDoc, m_aAxisProperties.m_xDataTableModel, rComponentContext, m_aAxisProperties.m_bDataTableAlignAxisValuesWithColumns)); + m_pDataTableView->initializeValues(rSeriesPlotterList); + m_xNumberFormatsSupplier = xNumberFormatsSupplier; +} + + } //namespace chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx index 1c020bc4174c..210f36dd4802 100644 --- a/chart2/source/view/axes/VCartesianAxis.hxx +++ b/chart2/source/view/axes/VCartesianAxis.hxx @@ -16,15 +16,13 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANAXIS_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANAXIS_HXX +#pragma once #include "VAxisBase.hxx" #include <basegfx/vector/b2dvector.hxx> namespace chart { - class VCartesianAxis : public VAxisBase { // public methods @@ -100,6 +98,10 @@ public: ::basegfx::B2DVector aScreenPos; }; + void createDataTableView(std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList, + css::uno::Reference<css::util::XNumberFormatsSupplier> const& xNumberFormatsSupplier, + rtl::Reference<::chart::ChartModel> const& xChartDoc, + css::uno::Reference<css::uno::XComponentContext> const& rComponentContext) override; private: //methods /** * Go through all tick label positions and decide which labels to display @@ -118,7 +120,7 @@ private: //methods * method once again to get the text shapes created. */ bool createTextShapes( - const css::uno::Reference<css::drawing::XShapes >& xTarget, + const rtl::Reference< SvxShapeGroupAnyD >& xTarget, TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties, TickFactory2D const * pTickFactory, sal_Int32 nScreenDistanceBetweenTicks ); @@ -128,7 +130,7 @@ private: //methods * are to be resolved only by adjusting the label tick interval. */ bool createTextShapesSimple( - const css::uno::Reference<css::drawing::XShapes >& xTarget, + const rtl::Reference< SvxShapeGroupAnyD >& xTarget, TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties, TickFactory2D const * pTickFactory ); @@ -154,9 +156,10 @@ private: //methods ::basegfx::B2DVector getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const; ScreenPosAndLogicPos getScreenPosAndLogicPos( double fLogicX, double fLogicY, double fLogicZ ) const; + + void createDataTableShape(std::unique_ptr<TickFactory2D> const& rTickFactory2D); }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx index e7fe42a87124..81fa369c2f60 100644 --- a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx +++ b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx @@ -20,11 +20,15 @@ #include "VCartesianCoordinateSystem.hxx" #include "VCartesianGrid.hxx" #include "VCartesianAxis.hxx" +#include <BaseCoordinateSystem.hxx> #include <AxisIndexDefines.hxx> +#include <Axis.hxx> +#include <DataTable.hxx> +#include <Diagram.hxx> #include <AxisHelper.hxx> #include <cppuhelper/implbase.hxx> #include <ChartModel.hxx> -#include <com/sun/star/chart2/XCoordinateSystem.hpp> +#include <GridProperties.hxx> #include <com/sun/star/chart2/data/XTextualDataSequence.hpp> #include <com/sun/star/chart2/AxisType.hpp> @@ -58,7 +62,7 @@ private: //member } -VCartesianCoordinateSystem::VCartesianCoordinateSystem( const Reference< XCoordinateSystem >& xCooSys ) +VCartesianCoordinateSystem::VCartesianCoordinateSystem( const rtl::Reference< BaseCoordinateSystem >& xCooSys ) : VCoordinateSystem(xCooSys) { } @@ -78,7 +82,7 @@ void VCartesianCoordinateSystem::createGridShapes() for( sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++) { sal_Int32 nAxisIndex = MAIN_AXIS_INDEX; - Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, m_xCooSysModel ) ); + rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, nAxisIndex, m_xCooSysModel ); if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel )) continue; @@ -87,7 +91,7 @@ void VCartesianCoordinateSystem::createGridShapes() , getExplicitIncrement(nDimensionIndex,nAxisIndex) ); aGrid.set3DWallPositions( m_eLeftWallPos, m_eBackWallPos, m_eBottomPos ); - aGrid.initPlotter(m_xLogicTargetForGrids,m_xFinalTarget,m_xShapeFactory + aGrid.initPlotter(m_xLogicTargetForGrids,m_xFinalTarget , createCIDForGrid( nDimensionIndex,nAxisIndex ) ); if(nDimensionCount==2) aGrid.setTransformationSceneToScreen( m_aMatrixSceneToScreen ); @@ -97,16 +101,17 @@ void VCartesianCoordinateSystem::createGridShapes() } void VCartesianCoordinateSystem::createVAxisList( - const uno::Reference<chart2::XChartDocument> & xChartDoc - , const awt::Size& rFontReferenceSize - , const awt::Rectangle& rMaximumSpaceForLabels - , bool bLimitSpaceForLabels - ) + const rtl::Reference<::chart::ChartModel> & xChartDoc, + const awt::Size& rFontReferenceSize, + const awt::Rectangle& rMaximumSpaceForLabels, + bool bLimitSpaceForLabels, + std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList, + uno::Reference<uno::XComponentContext> const& rComponentContext) { // note: using xChartDoc itself as XNumberFormatsSupplier would cause // a leak from VCartesianAxis due to cyclic reference uno::Reference<util::XNumberFormatsSupplier> const xNumberFormatsSupplier( - dynamic_cast<ChartModel&>(*xChartDoc).getNumberFormatsSupplier()); + xChartDoc->getNumberFormatsSupplier()); m_aAxisMap.clear(); @@ -125,16 +130,17 @@ void VCartesianCoordinateSystem::createVAxisList( sal_Int32 nMaxAxisIndex = m_xCooSysModel->getMaximumAxisIndexByDimension(nDimensionIndex); for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ ) { - Reference< XAxis > xAxis = getAxisByDimension(nDimensionIndex,nAxisIndex); + rtl::Reference< Axis > xAxis = getAxisByDimension(nDimensionIndex,nAxisIndex); if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel )) continue; - AxisProperties aAxisProperties(xAxis,getExplicitCategoriesProvider()); + rtl::Reference<Diagram> xDiagram(xChartDoc->getFirstChartDiagram()); + AxisProperties aAxisProperties(xAxis, getExplicitCategoriesProvider(), xDiagram->getDataTableRef()); aAxisProperties.m_nDimensionIndex = nDimensionIndex; aAxisProperties.m_bSwapXAndY = bSwapXAndY; aAxisProperties.m_bIsMainAxis = (nAxisIndex==0); aAxisProperties.m_bLimitSpaceForLabels = bLimitSpaceForLabels; - Reference< XAxis > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, m_xCooSysModel ) ); + rtl::Reference< Axis > xCrossingMainAxis = AxisHelper::getCrossingMainAxis( xAxis, m_xCooSysModel ); if( xCrossingMainAxis.is() ) { ScaleData aCrossingScale( xCrossingMainAxis->getScaleData() ); @@ -149,8 +155,8 @@ void VCartesianCoordinateSystem::createVAxisList( aAxisProperties.m_xAxisTextProvider = new TextualDataProvider( m_aSeriesNamesForZAxis ); //for the z axis copy the positioning properties from the x axis (or from the y axis for swapped coordinate systems) - Reference< XAxis > xSisterAxis( AxisHelper::getCrossingMainAxis( xCrossingMainAxis, m_xCooSysModel ) ); - aAxisProperties.initAxisPositioning( Reference< beans::XPropertySet >( xSisterAxis, uno::UNO_QUERY) ); + rtl::Reference< Axis > xSisterAxis = AxisHelper::getCrossingMainAxis( xCrossingMainAxis, m_xCooSysModel ); + aAxisProperties.initAxisPositioning( xSisterAxis ); } aAxisProperties.init(true); if(aAxisProperties.m_bDisplayLabels) @@ -162,6 +168,7 @@ void VCartesianCoordinateSystem::createVAxisList( apVAxis->set3DWallPositions( m_eLeftWallPos, m_eBackWallPos, m_eBottomPos ); apVAxis->initAxisLabelProperties(rFontReferenceSize,rMaximumSpaceForLabels); + apVAxis->createDataTableView(rSeriesPlotterList, xNumberFormatsSupplier, xChartDoc, rComponentContext); } } } @@ -174,16 +181,13 @@ void VCartesianCoordinateSystem::initVAxisInList() sal_Int32 nDimensionCount = m_xCooSysModel->getDimension(); bool bSwapXAndY = getPropertySwapXAndYAxis(); - for (auto const& elem : m_aAxisMap) + for (auto const& [nIndexPair, pVAxis] : m_aAxisMap) { - VAxisBase* pVAxis = elem.second.get(); - if( pVAxis ) + if (pVAxis) { - sal_Int32 nDimensionIndex = elem.first.first; - sal_Int32 nAxisIndex = elem.first.second; + auto [nDimensionIndex, nAxisIndex] = nIndexPair; pVAxis->setExplicitScaleAndIncrement( getExplicitScale( nDimensionIndex, nAxisIndex ), getExplicitIncrement( nDimensionIndex, nAxisIndex ) ); - pVAxis->initPlotter(m_xLogicTargetForAxes,m_xFinalTarget,m_xShapeFactory - , createCIDForAxis( nDimensionIndex, nAxisIndex ) ); + pVAxis->initPlotter(m_xLogicTargetForAxes, m_xFinalTarget, createCIDForAxis( nDimensionIndex, nAxisIndex ) ); if(nDimensionCount==2) pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); pVAxis->setScales( getExplicitScales(nDimensionIndex,nAxisIndex), bSwapXAndY ); @@ -199,13 +203,12 @@ void VCartesianCoordinateSystem::updateScalesAndIncrementsOnAxes() sal_Int32 nDimensionCount = m_xCooSysModel->getDimension(); bool bSwapXAndY = getPropertySwapXAndYAxis(); - for (auto const& elem : m_aAxisMap) + for (auto const& [nIndexPair, pVAxis] : m_aAxisMap) { - VAxisBase* pVAxis = elem.second.get(); - if( pVAxis ) + if (pVAxis) { - sal_Int32 nDimensionIndex = elem.first.first; - sal_Int32 nAxisIndex = elem.first.second; + auto [nDimensionIndex, nAxisIndex] = nIndexPair; + pVAxis->setExplicitScaleAndIncrement( getExplicitScale( nDimensionIndex, nAxisIndex ), getExplicitIncrement( nDimensionIndex, nAxisIndex ) ); if(nDimensionCount==2) pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); diff --git a/chart2/source/view/axes/VCartesianCoordinateSystem.hxx b/chart2/source/view/axes/VCartesianCoordinateSystem.hxx index e959dbc5d5ef..968d97a21099 100644 --- a/chart2/source/view/axes/VCartesianCoordinateSystem.hxx +++ b/chart2/source/view/axes/VCartesianCoordinateSystem.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANCOORDINATESYSTEM_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANCOORDINATESYSTEM_HXX +#pragma once #include <VCoordinateSystem.hxx> @@ -28,14 +27,16 @@ class VCartesianCoordinateSystem : public VCoordinateSystem { public: VCartesianCoordinateSystem() = delete; - explicit VCartesianCoordinateSystem( const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys ); + explicit VCartesianCoordinateSystem( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys ); virtual ~VCartesianCoordinateSystem() override; virtual void createVAxisList( - const css::uno::Reference< css::chart2::XChartDocument> &ChartDoc - , const css::awt::Size& rFontReferenceSize - , const css::awt::Rectangle& rMaximumSpaceForLabels - , bool bLimitSpaceForLabels ) override; + const rtl::Reference<::chart::ChartModel> &ChartDoc, + const css::awt::Size& rFontReferenceSize, + const css::awt::Rectangle& rMaximumSpaceForLabels, + bool bLimitSpaceForLabels, + std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList, + css::uno::Reference<css::uno::XComponentContext> const& rComponentContext) override; virtual void initVAxisInList() override; virtual void updateScalesAndIncrementsOnAxes() override; @@ -44,6 +45,5 @@ public: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VCartesianGrid.cxx b/chart2/source/view/axes/VCartesianGrid.cxx index eda61d9b8e6c..9916ebac0be4 100644 --- a/chart2/source/view/axes/VCartesianGrid.cxx +++ b/chart2/source/view/axes/VCartesianGrid.cxx @@ -25,9 +25,9 @@ #include <CommonConverters.hxx> #include <AxisHelper.hxx> #include <VLineProperties.hxx> +#include <GridProperties.hxx> #include <com/sun/star/drawing/PointSequenceSequence.hpp> #include <com/sun/star/drawing/LineStyle.hpp> -#include <com/sun/star/chart2/XTransformation.hpp> #include <memory> #include <vector> @@ -62,10 +62,7 @@ GridLinePoints::GridLinePoints( const PlottingPositionHelper* pPosHelper, sal_In , CuboidPlanePosition eLeftWallPos , CuboidPlanePosition eBackWallPos , CuboidPlanePosition eBottomPos ) - : P0(3) - , P1(3) - , P2(3) - , m_nDimensionIndex(nDimensionIndex) + : m_nDimensionIndex(nDimensionIndex) { double MinX = pPosHelper->getLogicMinX(); double MinY = pPosHelper->getLogicMinY(); @@ -78,51 +75,40 @@ GridLinePoints::GridLinePoints( const PlottingPositionHelper* pPosHelper, sal_In pPosHelper->doLogicScaling( &MaxX,&MaxY,&MaxZ ); if(!pPosHelper->isMathematicalOrientationX()) - { - double fHelp = MinX; - MinX = MaxX; - MaxX = fHelp; - } + std::swap( MinX, MaxX ); if(!pPosHelper->isMathematicalOrientationY()) - { - double fHelp = MinY; - MinY = MaxY; - MaxY = fHelp; - } + std::swap( MinY, MaxY ); if(pPosHelper->isMathematicalOrientationZ())//z axis in draw is reverse to mathematical - { - double fHelp = MinZ; - MinZ = MaxZ; - MaxZ = fHelp; - } + std::swap( MinZ, MaxZ ); bool bSwapXY = pPosHelper->isSwapXAndY(); //P0: point on 'back' wall, not on 'left' wall //P1: point on both walls //P2: point on 'left' wall not on 'back' wall - P0[0]=P1[0]=P2[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MinX : MaxX; - P0[1]=P1[1]=P2[1]= (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MinY : MaxY; - P0[2]=P1[2]=P2[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MinZ : MaxZ; + const double v0 = (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MinX : MaxX; + const double v1 = (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MinY : MaxY; + const double v2 = (eBackWallPos == CuboidPlanePosition_Back) ? MinZ : MaxZ; + P0 = P1 = P2 = { v0, v1, v2 }; if(m_nDimensionIndex==0) { - P0[1]= (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MaxY : MinY; - P2[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MaxZ : MinZ; + P0.getArray()[1] = (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MaxY : MinY; + P2.getArray()[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MaxZ : MinZ; if( eBottomPos != CuboidPlanePosition_Bottom && !bSwapXY ) P2=P1; } else if(m_nDimensionIndex==1) { - P0[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MaxX : MinX; - P2[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MaxZ : MinZ; + P0.getArray()[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MaxX : MinX; + P2.getArray()[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MaxZ : MinZ; if( eBottomPos != CuboidPlanePosition_Bottom && bSwapXY ) P2=P1; } else if(m_nDimensionIndex==2) { - P0[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MaxX : MinX; - P2[1]= (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MaxY : MinY; + P0.getArray()[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MaxX : MinX; + P2.getArray()[1]= (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MaxY : MinY; if( eBottomPos != CuboidPlanePosition_Bottom ) { if( !bSwapXY ) @@ -135,40 +121,38 @@ GridLinePoints::GridLinePoints( const PlottingPositionHelper* pPosHelper, sal_In void GridLinePoints::update( double fScaledTickValue ) { - P0[m_nDimensionIndex] = P1[m_nDimensionIndex] = P2[m_nDimensionIndex] = fScaledTickValue; + P0.getArray()[m_nDimensionIndex] = P1.getArray()[m_nDimensionIndex] = P2.getArray()[m_nDimensionIndex] = fScaledTickValue; } static void addLine2D( drawing::PointSequenceSequence& rPoints, sal_Int32 nIndex , const GridLinePoints& rScaledLogicPoints - , const Reference< XTransformation > & xTransformation + , const XTransformation2& rTransformation ) { - drawing::Position3D aPA = SequenceToPosition3D( xTransformation->transform( rScaledLogicPoints.P0 ) ); - drawing::Position3D aPB = SequenceToPosition3D( xTransformation->transform( rScaledLogicPoints.P1 ) ); - - rPoints[nIndex].realloc(2); - rPoints[nIndex][0].X = static_cast<sal_Int32>(aPA.PositionX); - rPoints[nIndex][0].Y = static_cast<sal_Int32>(aPA.PositionY); - rPoints[nIndex][1].X = static_cast<sal_Int32>(aPB.PositionX); - rPoints[nIndex][1].Y = static_cast<sal_Int32>(aPB.PositionY); + drawing::Position3D aPA = rTransformation.transform( SequenceToPosition3D(rScaledLogicPoints.P0) ); + drawing::Position3D aPB = rTransformation.transform( SequenceToPosition3D(rScaledLogicPoints.P1) ); + + rPoints.getArray()[nIndex] + = { { static_cast<sal_Int32>(aPA.PositionX), static_cast<sal_Int32>(aPA.PositionY) }, + { static_cast<sal_Int32>(aPB.PositionX), static_cast<sal_Int32>(aPB.PositionY) } }; } -static void addLine3D( drawing::PolyPolygonShape3D& rPoints, sal_Int32 nIndex +static void addLine3D( std::vector<std::vector<css::drawing::Position3D>>& rPoints, sal_Int32 nIndex , const GridLinePoints& rBasePoints - , const Reference< XTransformation > & xTransformation ) + , const XTransformation2 & rTransformation ) { - drawing::Position3D aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P0 ) ); + drawing::Position3D aPoint =rTransformation.transform( rBasePoints.P0 ); AddPointToPoly( rPoints, aPoint, nIndex ); - aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P1 ) ); + aPoint = rTransformation.transform( rBasePoints.P1 ); AddPointToPoly( rPoints, aPoint, nIndex ); - aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P2 ) ); + aPoint = rTransformation.transform( rBasePoints.P2 ); AddPointToPoly( rPoints, aPoint, nIndex ); } VCartesianGrid::VCartesianGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount - , const Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList ) + , std::vector< rtl::Reference< ::chart::GridProperties > > aGridPropertiesList ) : VAxisOrGridBase( nDimensionIndex, nDimensionCount ) - , m_aGridPropertiesList( rGridPropertiesList ) + , m_aGridPropertiesList( std::move(aGridPropertiesList) ) { m_pPosHelper = new PlottingPositionHelper(); } @@ -180,10 +164,10 @@ VCartesianGrid::~VCartesianGrid() } void VCartesianGrid::fillLinePropertiesFromGridModel( std::vector<VLineProperties>& rLinePropertiesList - , const Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList ) + , const std::vector< rtl::Reference< ::chart::GridProperties > > & rGridPropertiesList ) { rLinePropertiesList.clear(); - if( !rGridPropertiesList.hasElements() ) + if( rGridPropertiesList.empty() ) return; VLineProperties aLineProperties; @@ -199,12 +183,12 @@ void VCartesianGrid::fillLinePropertiesFromGridModel( std::vector<VLinePropertie void VCartesianGrid::createShapes() { - if(!m_aGridPropertiesList.hasElements()) + if(m_aGridPropertiesList.empty()) return; //somehow equal to axis tickmarks //create named group shape - Reference< drawing::XShapes > xGroupShape_Shapes( + rtl::Reference< SvxShapeGroupAnyD > xGroupShape_Shapes( createGroupShape( m_xLogicTarget, m_aCID ) ); if(!xGroupShape_Shapes.is()) @@ -235,14 +219,14 @@ void VCartesianGrid::createShapes() if( !aLinePropertiesList[nDepth].isLineVisible() ) continue; - Reference< drawing::XShapes > xTarget( xGroupShape_Shapes ); + rtl::Reference< SvxShapeGroupAnyD > xTarget( xGroupShape_Shapes ); if( nDepth > 0 ) { - xTarget.set( createGroupShape( m_xLogicTarget + xTarget = createGroupShape( m_xLogicTarget , ObjectIdentifier::addChildParticle( m_aCID, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_SUBGRID, nDepth-1 ) ) - ) ); + ); if(!xTarget.is()) - xTarget.set( xGroupShape_Shapes ); + xTarget = xGroupShape_Shapes; } if(m_nDimension==2) @@ -259,24 +243,25 @@ void VCartesianGrid::createShapes() if( !tick.bPaintIt ) continue; aGridLinePoints.update( tick.fScaledTickValue ); - addLine2D( aPoints, nRealPointCount, aGridLinePoints, m_pPosHelper->getTransformationScaledLogicToScene() ); + addLine2D( aPoints, nRealPointCount, aGridLinePoints, *m_pPosHelper->getTransformationScaledLogicToScene() ); nRealPointCount++; } aPoints.realloc(nRealPointCount); - m_pShapeFactory->createLine2D( xTarget, aPoints, &aLinePropertiesList[nDepth] ); + ShapeFactory::createLine2D( xTarget, aPoints, &aLinePropertiesList[nDepth] ); //prepare polygon for handle shape: drawing::PointSequenceSequence aHandlesPoints(1); - sal_Int32 nOldHandleCount = aHandlesPoints[0].getLength(); - aHandlesPoints[0].realloc(nOldHandleCount+nRealPointCount); + auto pHandlesPoints = aHandlesPoints.getArray(); + pHandlesPoints[0].realloc(nRealPointCount); + auto pHandlesPoints0 = pHandlesPoints[0].getArray(); for( sal_Int32 nN = 0; nN<nRealPointCount; nN++) - aHandlesPoints[0][nOldHandleCount+nN] = aPoints[nN][1]; + pHandlesPoints0[nN] = aPoints[nN][1]; //create handle shape: VLineProperties aHandleLineProperties; aHandleLineProperties.LineStyle <<= drawing::LineStyle_NONE; - Reference< drawing::XShape > xHandleShape = - m_pShapeFactory->createLine2D( xTarget, aHandlesPoints, &aHandleLineProperties ); + rtl::Reference<SvxShapePolyPolygon> xHandleShape = + ShapeFactory::createLine2D( xTarget, aHandlesPoints, &aHandleLineProperties ); ::chart::ShapeFactory::setShapeName( xHandleShape, "HandlesOnly" ); } else //if(2!=m_nDimension) @@ -284,10 +269,8 @@ void VCartesianGrid::createShapes() GridLinePoints aGridLinePoints( m_pPosHelper, m_nDimensionIndex, m_eLeftWallPos, m_eBackWallPos, m_eBottomPos ); sal_Int32 nPointCount = (*aDepthIter).size(); - drawing::PolyPolygonShape3D aPoints; - aPoints.SequenceX.realloc(nPointCount); - aPoints.SequenceY.realloc(nPointCount); - aPoints.SequenceZ.realloc(nPointCount); + std::vector<std::vector<css::drawing::Position3D>> aPoints; + aPoints.resize(nPointCount); sal_Int32 nRealPointCount = 0; sal_Int32 nPolyIndex = 0; @@ -300,14 +283,12 @@ void VCartesianGrid::createShapes() } aGridLinePoints.update( tick.fScaledTickValue ); - addLine3D( aPoints, nPolyIndex, aGridLinePoints, m_pPosHelper->getTransformationScaledLogicToScene() ); + addLine3D( aPoints, nPolyIndex, aGridLinePoints, *m_pPosHelper->getTransformationScaledLogicToScene() ); nRealPointCount+=3; ++nPolyIndex; } - aPoints.SequenceX.realloc(nRealPointCount); - aPoints.SequenceY.realloc(nRealPointCount); - aPoints.SequenceZ.realloc(nRealPointCount); - m_pShapeFactory->createLine3D( xTarget, aPoints, aLinePropertiesList[nDepth] ); + aPoints.resize(nRealPointCount); + ShapeFactory::createLine3D( xTarget, aPoints, aLinePropertiesList[nDepth] ); } } } diff --git a/chart2/source/view/axes/VCartesianGrid.hxx b/chart2/source/view/axes/VCartesianGrid.hxx index d655e0e87142..d41bcc4d466f 100644 --- a/chart2/source/view/axes/VCartesianGrid.hxx +++ b/chart2/source/view/axes/VCartesianGrid.hxx @@ -16,39 +16,37 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANGRID_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VCARTESIANGRID_HXX +#pragma once #include "VAxisOrGridBase.hxx" #include <com/sun/star/beans/XPropertySet.hpp> -namespace chart { struct VLineProperties; } - namespace chart { +class GridProperties; +struct VLineProperties; class VCartesianGrid : public VAxisOrGridBase { // public methods public: VCartesianGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount - , const css::uno::Sequence< - css::uno::Reference< css::beans::XPropertySet > >& rGridPropertiesList //main grid, subgrid, subsubgrid etc + , std::vector< + rtl::Reference< ::chart::GridProperties > > aGridPropertiesList //main grid, subgrid, subsubgrid etc ); virtual ~VCartesianGrid() override; virtual void createShapes() override; static void fillLinePropertiesFromGridModel( std::vector<VLineProperties>& rLinePropertiesList - , const css::uno::Sequence< - css::uno::Reference< css::beans::XPropertySet > >& rGridPropertiesList ); + , const std::vector< + rtl::Reference< ::chart::GridProperties > >& rGridPropertiesList ); private: - css::uno::Sequence< - css::uno::Reference< css::beans::XPropertySet > > m_aGridPropertiesList; //main grid, subgrid, subsubgrid etc + std::vector< + rtl::Reference< ::chart::GridProperties > > m_aGridPropertiesList; //main grid, subgrid, subsubgrid etc }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VCoordinateSystem.cxx b/chart2/source/view/axes/VCoordinateSystem.cxx index 1c900b392233..41ec23d307f3 100644 --- a/chart2/source/view/axes/VCoordinateSystem.cxx +++ b/chart2/source/view/axes/VCoordinateSystem.cxx @@ -18,24 +18,30 @@ */ #include <BaseGFXHelper.hxx> +#include <DateHelper.hxx> #include <VCoordinateSystem.hxx> #include "VCartesianCoordinateSystem.hxx" #include "VPolarCoordinateSystem.hxx" +#include <BaseCoordinateSystem.hxx> +#include <GridProperties.hxx> +#include <ChartModel.hxx> #include <ScaleAutomatism.hxx> #include <ShapeFactory.hxx> #include <servicenames_coosystems.hxx> #include <ObjectIdentifier.hxx> #include <ExplicitCategoriesProvider.hxx> +#include <Axis.hxx> #include "VAxisBase.hxx" #include <defines.hxx> #include <chartview/ExplicitValueProvider.hxx> #include <com/sun/star/chart/TimeUnit.hpp> #include <com/sun/star/chart2/AxisType.hpp> -#include <com/sun/star/chart2/XCoordinateSystem.hpp> -#include <comphelper/sequence.hxx> -#include <tools/diagnose_ex.h> -#include <algorithm> #include <rtl/math.hxx> +#include <comphelper/diagnose_ex.hxx> + +#include <algorithm> +#include <limits> +#include <utility> namespace chart { @@ -45,7 +51,7 @@ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; std::unique_ptr<VCoordinateSystem> VCoordinateSystem::createCoordinateSystem( - const Reference< XCoordinateSystem >& xCooSysModel ) + const rtl::Reference< BaseCoordinateSystem >& xCooSysModel ) { if( !xCooSysModel.is() ) return nullptr; @@ -63,13 +69,11 @@ std::unique_ptr<VCoordinateSystem> VCoordinateSystem::createCoordinateSystem( return pRet; } -VCoordinateSystem::VCoordinateSystem( const Reference< XCoordinateSystem >& xCooSys ) - : m_xCooSysModel(xCooSys) - , m_aMatrixSceneToScreen() +VCoordinateSystem::VCoordinateSystem( rtl::Reference< BaseCoordinateSystem > xCooSys ) + : m_xCooSysModel(std::move(xCooSys)) , m_eLeftWallPos(CuboidPlanePosition_Left) , m_eBackWallPos(CuboidPlanePosition_Back) , m_eBottomPos(CuboidPlanePosition_Bottom) - , m_aMergedMinMaxSupplier() , m_aExplicitScales(3) , m_aExplicitIncrements(3) { @@ -84,33 +88,30 @@ VCoordinateSystem::~VCoordinateSystem() { } -void VCoordinateSystem::initPlottingTargets( const Reference< drawing::XShapes >& xLogicTarget - , const Reference< drawing::XShapes >& xFinalTarget - , const Reference< lang::XMultiServiceFactory >& xShapeFactory - , Reference< drawing::XShapes >& xLogicTargetForSeriesBehindAxis ) +void VCoordinateSystem::initPlottingTargets( const rtl::Reference< SvxShapeGroupAnyD >& xLogicTarget + , const rtl::Reference< SvxShapeGroupAnyD >& xFinalTarget + , rtl::Reference<SvxShapeGroupAnyD>& xLogicTargetForSeriesBehindAxis ) { - OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is()&&xShapeFactory.is(),"no proper initialization parameters"); + OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is(),"no proper initialization parameters"); //is only allowed to be called once sal_Int32 nDimensionCount = m_xCooSysModel->getDimension(); //create group shape for grids first thus axes are always painted above grids - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); if(nDimensionCount==2) { //create and add to target - m_xLogicTargetForGrids = pShapeFactory->createGroup2D( xLogicTarget ); - xLogicTargetForSeriesBehindAxis = pShapeFactory->createGroup2D( xLogicTarget ); - m_xLogicTargetForAxes = pShapeFactory->createGroup2D( xLogicTarget ); + m_xLogicTargetForGrids = ShapeFactory::createGroup2D( xLogicTarget ); + xLogicTargetForSeriesBehindAxis = ShapeFactory::createGroup2D( xLogicTarget ); + m_xLogicTargetForAxes = ShapeFactory::createGroup2D( xLogicTarget ); } else { //create and added to target - m_xLogicTargetForGrids = pShapeFactory->createGroup3D( xLogicTarget ); - xLogicTargetForSeriesBehindAxis = pShapeFactory->createGroup3D( xLogicTarget ); - m_xLogicTargetForAxes = pShapeFactory->createGroup3D( xLogicTarget ); + m_xLogicTargetForGrids = ShapeFactory::createGroup3D( xLogicTarget ); + xLogicTargetForSeriesBehindAxis = ShapeFactory::createGroup3D( xLogicTarget ); + m_xLogicTargetForAxes = ShapeFactory::createGroup3D( xLogicTarget ); } m_xFinalTarget = xFinalTarget; - m_xShapeFactory = xShapeFactory; } void VCoordinateSystem::setParticle( const OUString& rCooSysParticle ) @@ -141,8 +142,8 @@ uno::Sequence< sal_Int32 > VCoordinateSystem::getCoordinateSystemResolution( { uno::Sequence<sal_Int32> aResolution( std::max<sal_Int32>(m_xCooSysModel->getDimension(), 2)); - - for( auto& i : aResolution ) + auto aResolutionRange = asNonConstRange(aResolution); + for( auto& i : aResolutionRange ) i = 1000; ::basegfx::B3DTuple aScale( BaseGFXHelper::GetScaleFromMatrix( @@ -170,48 +171,45 @@ uno::Sequence< sal_Int32 > VCoordinateSystem::getCoordinateSystemResolution( //2D if( aResolution.getLength() == 2 ) { - aResolution[0]=nXResolution; - aResolution[1]=nYResolution; + aResolutionRange[0]=nXResolution; + aResolutionRange[1]=nYResolution; } else { //this maybe can be optimized further ... sal_Int32 nMaxResolution = std::max( nXResolution, nYResolution ); nMaxResolution*=2; - for( auto& i : aResolution ) + for( auto& i : asNonConstRange(aResolution) ) i = nMaxResolution; } return aResolution; } -Reference< XAxis > VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const +rtl::Reference< Axis > VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const { if( m_xCooSysModel.is() ) - return m_xCooSysModel->getAxisByDimension( nDimensionIndex, nAxisIndex ); + return m_xCooSysModel->getAxisByDimension2( nDimensionIndex, nAxisIndex ); return nullptr; } -Sequence< Reference< beans::XPropertySet > > VCoordinateSystem::getGridListFromAxis( const Reference< XAxis >& xAxis ) +std::vector< rtl::Reference< ::chart::GridProperties > > VCoordinateSystem::getGridListFromAxis( const rtl::Reference< Axis >& xAxis ) { - std::vector< Reference< beans::XPropertySet > > aRet; + std::vector< rtl::Reference< ::chart::GridProperties > > aRet; if( xAxis.is() ) { - aRet.push_back( xAxis->getGridProperties() ); - auto aSubGrids( comphelper::sequenceToContainer<std::vector< Reference< beans::XPropertySet > > >( xAxis->getSubGridProperties() ) ); + aRet.push_back( xAxis->getGridProperties2() ); + std::vector<rtl::Reference<::chart::GridProperties>> aSubGrids = xAxis->getSubGridProperties2(); aRet.insert( aRet.end(), aSubGrids.begin(), aSubGrids.end() ); } - return comphelper::containerToSequence( aRet ); + return aRet; } void VCoordinateSystem::impl_adjustDimension( sal_Int32& rDimensionIndex ) { - if( rDimensionIndex<0 ) - rDimensionIndex=0; - if( rDimensionIndex>2 ) - rDimensionIndex=2; + rDimensionIndex = std::clamp<sal_Int32>(rDimensionIndex, 0, 2); } void VCoordinateSystem::impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const @@ -325,11 +323,12 @@ sal_Int32 VCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensio } void VCoordinateSystem::createVAxisList( - const uno::Reference<chart2::XChartDocument> & /* xChartDoc */ - , const awt::Size& /* rFontReferenceSize */ - , const awt::Rectangle& /* rMaximumSpaceForLabels */ - , bool /* bLimitSpaceForLabels */ - ) + const rtl::Reference<::chart::ChartModel> & /* xChartDoc */, + const awt::Size& /* rFontReferenceSize */, + const awt::Rectangle& /* rMaximumSpaceForLabels */, + bool /* bLimitSpaceForLabels */, + std::vector<std::unique_ptr<VSeriesPlotter>>& /*rSeriesPlotterList*/, + uno::Reference<uno::XComponentContext> const& /*rComponentContext*/) { } @@ -342,7 +341,8 @@ void VCoordinateSystem::updateScalesAndIncrementsOnAxes() void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) { - if( rScaleAutomatism.getScale().AxisType==AxisType::DATE && nDimIndex==0 ) + bool bDateAxisX = (rScaleAutomatism.getScale().AxisType == AxisType::DATE) && (nDimIndex == 0); + if( bDateAxisX ) { // This is a date X dimension. Determine proper time resolution. sal_Int32 nTimeResolution = css::chart::TimeUnit::MONTH; @@ -354,10 +354,8 @@ void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAuto m_aMergedMinMaxSupplier.setTimeResolutionOnXAxis( nTimeResolution, rScaleAutomatism.getNullDate() ); } - double fMin = 0.0; - double fMax = 0.0; - ::rtl::math::setInf(&fMin, false); - ::rtl::math::setInf(&fMax, true); + double fMin = std::numeric_limits<double>::infinity(); + double fMax = -std::numeric_limits<double>::infinity(); if( nDimIndex == 0 ) { // x dimension @@ -368,8 +366,26 @@ void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAuto { // y dimension ExplicitScaleData aScale = getExplicitScale( 0, 0 ); + double fMaximum = aScale.Maximum; + if (!aScale.m_bShiftedCategoryPosition && aScale.AxisType == AxisType::DATE) + { + // tdf#146066 Increase maximum date value by one month/year, + // because the automatic scaling of the Y axis was incorrect when the last Y value was the highest value. + Date aMaxDate(aScale.NullDate); + aMaxDate.AddDays(::rtl::math::approxFloor(fMaximum)); + switch (aScale.TimeResolution) + { + case css::chart::TimeUnit::MONTH: + aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate, 1); + break; + case css::chart::TimeUnit::YEAR: + aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate, 1); + break; + } + fMaximum = aMaxDate - aScale.NullDate; + } fMin = m_aMergedMinMaxSupplier.getMinimumYInRange(aScale.Minimum,aScale.Maximum, nAxisIndex); - fMax = m_aMergedMinMaxSupplier.getMaximumYInRange(aScale.Minimum,aScale.Maximum, nAxisIndex); + fMax = m_aMergedMinMaxSupplier.getMaximumYInRange(aScale.Minimum, fMaximum, nAxisIndex); } else if( nDimIndex == 2 ) { @@ -387,6 +403,9 @@ void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAuto m_aMergedMinMaxSupplier.isExpandWideValuesToZero( nDimIndex ), m_aMergedMinMaxSupplier.isExpandNarrowValuesTowardZero( nDimIndex ) ); + if (bDateAxisX) + return; + VAxisBase* pVAxis = getVAxis(nDimIndex, nAxisIndex); if( pVAxis ) rScaleAutomatism.setMaximumAutoMainIncrementCount( pVAxis->estimateMaximumAutoMainIncrementCount() ); @@ -399,7 +418,7 @@ VAxisBase* VCoordinateSystem::getVAxis( sal_Int32 nDimensionIndex, sal_Int32 nAx tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex ); tVAxisMap::const_iterator aIt = m_aAxisMap.find( aFullAxisIndex ); - if( aIt != m_aAxisMap.end() ) + if (aIt != m_aAxisMap.cend()) pRet = aIt->second.get(); return pRet; @@ -435,26 +454,26 @@ void VCoordinateSystem::set3DWallPositions( CuboidPlanePosition eLeftWallPos, Cu void VCoordinateSystem::createMaximumAxesLabels() { - for (auto const& elem : m_aAxisMap) + for (auto const&[unused, pVAxis] : m_aAxisMap) { - VAxisBase* pVAxis = elem.second.get(); - if( pVAxis ) + (void)unused; + if (pVAxis) { - if(pVAxis->getDimensionCount()==2) - pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); + if (pVAxis->getDimensionCount() == 2) + pVAxis->setTransformationSceneToScreen(m_aMatrixSceneToScreen); pVAxis->createMaximumLabels(); } } } void VCoordinateSystem::createAxesLabels() { - for (auto const& elem : m_aAxisMap) + for (auto const&[unused, pVAxis] : m_aAxisMap) { - VAxisBase* pVAxis = elem.second.get(); - if( pVAxis ) + (void)unused; + if (pVAxis) { - if(pVAxis->getDimensionCount()==2) - pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); + if (pVAxis->getDimensionCount() == 2) + pVAxis->setTransformationSceneToScreen(m_aMatrixSceneToScreen); pVAxis->createLabels(); } } @@ -462,12 +481,12 @@ void VCoordinateSystem::createAxesLabels() void VCoordinateSystem::updatePositions() { - for (auto const& elem : m_aAxisMap) + for (auto const&[unused, pVAxis] : m_aAxisMap) { - VAxisBase* pVAxis = elem.second.get(); - if( pVAxis ) + (void)unused; + if (pVAxis) { - if(pVAxis->getDimensionCount()==2) + if (pVAxis->getDimensionCount() == 2) pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); pVAxis->updatePositions(); } @@ -476,24 +495,24 @@ void VCoordinateSystem::updatePositions() void VCoordinateSystem::createAxesShapes() { - for (auto const& elem : m_aAxisMap) + for (auto const&[aFullAxisIndex, pVAxis] : m_aAxisMap) { - VAxisBase* pVAxis = elem.second.get(); - if( pVAxis ) + if (pVAxis) { - if(pVAxis->getDimensionCount()==2) + auto const&[nDimensionIndex, nAxisIndex] = aFullAxisIndex; + + if (pVAxis->getDimensionCount() == 2) pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen ); - tFullAxisIndex aFullAxisIndex = elem.first; - if( aFullAxisIndex.second == 0 ) + if (nAxisIndex == 0) { - if( aFullAxisIndex.first == 0 ) + if (nDimensionIndex == 0) { if( m_aExplicitScales[1].AxisType!=AxisType::CATEGORY ) pVAxis->setExtraLinePositionAtOtherAxis( m_aExplicitScales[1].Origin ); } - else if( aFullAxisIndex.first == 1 ) + else if (nDimensionIndex == 1) { if( m_aExplicitScales[0].AxisType!=AxisType::CATEGORY ) pVAxis->setExtraLinePositionAtOtherAxis( @@ -525,11 +544,10 @@ void VCoordinateSystem::clearMinimumAndMaximumSupplierList() bool VCoordinateSystem::getPropertySwapXAndYAxis() const { - Reference<beans::XPropertySet> xProp(m_xCooSysModel, uno::UNO_QUERY ); bool bSwapXAndY = false; - if( xProp.is()) try + if( m_xCooSysModel.is()) try { - xProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY; + m_xCooSysModel->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY; } catch( const uno::Exception& ) { @@ -548,8 +566,8 @@ void VCoordinateSystem::setSeriesNamesForAxis( const Sequence< OUString >& rSeri } sal_Int32 VCoordinateSystem::getNumberFormatKeyForAxis( - const Reference< chart2::XAxis >& xAxis - , const Reference<chart2::XChartDocument>& xChartDoc) + const rtl::Reference< Axis >& xAxis + , const rtl::Reference<::chart::ChartModel>& xChartDoc) { return ExplicitValueProvider::getExplicitNumberFormatKeyForAxis( xAxis, m_xCooSysModel, xChartDoc); diff --git a/chart2/source/view/axes/VPolarAngleAxis.cxx b/chart2/source/view/axes/VPolarAngleAxis.cxx index 1a93888b7428..6c3f0790a573 100644 --- a/chart2/source/view/axes/VPolarAngleAxis.cxx +++ b/chart2/source/view/axes/VPolarAngleAxis.cxx @@ -22,10 +22,10 @@ #include "VPolarAngleAxis.hxx" #include "VPolarGrid.hxx" #include <ShapeFactory.hxx> +#include <Axis.hxx> #include <NumberFormatterWrapper.hxx> #include <PolarLabelPositionHelper.hxx> #include <PlottingPositionHelper.hxx> -#include <com/sun/star/chart2/XAxis.hpp> #include <tools/color.hxx> #include <memory> @@ -33,8 +33,6 @@ namespace chart { using namespace ::com::sun::star; -using namespace ::com::sun::star::chart2; -using namespace ::rtl::math; VPolarAngleAxis::VPolarAngleAxis( const AxisProperties& rAxisProperties , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier @@ -48,27 +46,25 @@ VPolarAngleAxis::~VPolarAngleAxis() } void VPolarAngleAxis::createTextShapes_ForAngleAxis( - const uno::Reference< drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , EquidistantTickIter& rTickIter , AxisLabelProperties const & rAxisLabelProperties , double fLogicRadius , double fLogicZ ) { - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); - FixedNumberFormatter aFixedNumberFormatter( - m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey ); + m_xNumberFormatsSupplier, rAxisLabelProperties.m_nNumberFormatKey ); //prepare text properties for multipropertyset-interface of shape tNameSequence aPropNames; tAnySequence aPropValues; - uno::Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel ); PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false, -1, false, false ); LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps , rAxisLabelProperties.m_aFontReferenceSize ); - uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,"CharColor"); + uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,u"CharColor"); Color nColor = COL_AUTO; if(pColorAny) *pColorAny >>= nColor; @@ -83,7 +79,7 @@ void VPolarAngleAxis::createTextShapes_ForAngleAxis( ; pTickInfo = rTickIter.nextInfo(), nTick++ ) { //don't create labels which does not fit into the rhythm - if( nTick%rAxisLabelProperties.nRhythm != 0) + if( nTick%rAxisLabelProperties.m_nRhythm != 0) continue; //don't create labels for invisible ticks @@ -116,19 +112,19 @@ void VPolarAngleAxis::createTextShapes_ForAngleAxis( double fLogicAngle = pTickInfo->getUnscaledTickValue(); LabelAlignment eLabelAlignment(LABEL_ALIGN_CENTER); - PolarLabelPositionHelper aPolarLabelPositionHelper(m_pPosHelper.get(), 2/*nDimensionCount*/, xTarget, pShapeFactory); + PolarLabelPositionHelper aPolarLabelPositionHelper(&m_aPosHelper, 2/*nDimensionCount*/, xTarget); sal_Int32 nScreenValueOffsetInRadiusDirection = m_aAxisLabelProperties.m_aMaximumSpaceForLabels.Height/15; awt::Point aAnchorScreenPosition2D( aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues( eLabelAlignment, fLogicAngle, fLogicRadius, fLogicZ, nScreenValueOffsetInRadiusDirection )); LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, eLabelAlignment ); // #i78696# use mathematically correct rotation now - const double fRotationAnglePi(-basegfx::deg2rad(rAxisLabelProperties.fRotationAngleDegree)); + const double fRotationAnglePi(-basegfx::deg2rad(rAxisLabelProperties.m_fRotationAngleDegree)); uno::Any aATransformation = ShapeFactory::makeTransformation( aAnchorScreenPosition2D, fRotationAnglePi ); - OUString aStackedLabel = ShapeFactory::getStackedString( aLabel, rAxisLabelProperties.bStackCharacters ); + OUString aStackedLabel = ShapeFactory::getStackedString( aLabel, rAxisLabelProperties.m_bStackCharacters ); - pTickInfo->xTextShape = pShapeFactory->createText( xTarget, aStackedLabel, aPropNames, aPropValues, aATransformation ); + pTickInfo->xTextShape = ShapeFactory::createText( xTarget, aStackedLabel, aPropNames, aPropValues, aATransformation ); } //if NO OVERLAP -> remove overlapping shapes @@ -159,7 +155,7 @@ void VPolarAngleAxis::createLabels() if( !prepareShapeCreation() ) return; - double fLogicRadius = m_pPosHelper->getOuterLogicRadius(); + double fLogicRadius = m_aPosHelper.getOuterLogicRadius(); if( !m_aAxisProperties.m_bDisplayLabels ) return; @@ -173,7 +169,7 @@ void VPolarAngleAxis::createLabels() removeTextShapesFromTicks(); AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties ); - aAxisLabelProperties.bOverlapAllowed = true; + aAxisLabelProperties.m_bOverlapAllowed = true; double const fLogicZ = 1.0;//as defined createTextShapes_ForAngleAxis( m_xTextTarget, aTickIter , aAxisLabelProperties @@ -188,13 +184,13 @@ void VPolarAngleAxis::createShapes() if( !prepareShapeCreation() ) return; - double fLogicRadius = m_pPosHelper->getOuterLogicRadius(); + double fLogicRadius = m_aPosHelper.getOuterLogicRadius(); double const fLogicZ = 1.0;//as defined //create axis main lines drawing::PointSequenceSequence aPoints(1); - VPolarGrid::createLinePointSequence_ForAngleAxis( aPoints, m_aAllTickInfos, m_aIncrement, m_aScale, m_pPosHelper.get(), fLogicRadius, fLogicZ ); - uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( + VPolarGrid::createLinePointSequence_ForAngleAxis( aPoints, m_aAllTickInfos, m_aIncrement, m_aScale, &m_aPosHelper, fLogicRadius, fLogicZ ); + rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D( m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties ); //because of this name this line will be used for marking the axis ::chart::ShapeFactory::setShapeName( xShape, "MarkHandles" ); diff --git a/chart2/source/view/axes/VPolarAngleAxis.hxx b/chart2/source/view/axes/VPolarAngleAxis.hxx index 3ee9e7e15837..0e0774e9ebc5 100644 --- a/chart2/source/view/axes/VPolarAngleAxis.hxx +++ b/chart2/source/view/axes/VPolarAngleAxis.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARANGLEAXIS_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARANGLEAXIS_HXX +#pragma once #include "VPolarAxis.hxx" #include "Tickmarks_Equidistant.hxx" @@ -41,13 +40,12 @@ public: private: //methods void createTextShapes_ForAngleAxis( - const css::uno::Reference< css::drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , EquidistantTickIter& rTickIter , AxisLabelProperties const & rAxisLabelProperties , double fLogicRadius, double fLogicZ ); }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VPolarAxis.cxx b/chart2/source/view/axes/VPolarAxis.cxx index 9e41857c29d4..89f65fee3745 100644 --- a/chart2/source/view/axes/VPolarAxis.cxx +++ b/chart2/source/view/axes/VPolarAxis.cxx @@ -25,7 +25,6 @@ namespace chart { using namespace ::com::sun::star; -using namespace ::com::sun::star::chart2; std::shared_ptr<VPolarAxis> VPolarAxis::createAxis( const AxisProperties& rAxisProperties , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier @@ -40,19 +39,17 @@ VPolarAxis::VPolarAxis( const AxisProperties& rAxisProperties , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount ) : VAxisBase( nDimensionIndex, nDimensionCount, rAxisProperties, xNumberFormatsSupplier ) - , m_pPosHelper( new PolarPlottingPositionHelper() ) - , m_aIncrements() { - PlotterBase::m_pPosHelper = m_pPosHelper.get(); + PlotterBase::m_pPosHelper = &m_aPosHelper; } VPolarAxis::~VPolarAxis() { } -void VPolarAxis::setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ) +void VPolarAxis::setIncrements( std::vector< ExplicitIncrementData >&& rIncrements ) { - m_aIncrements = rIncrements; + m_aIncrements = std::move(rIncrements); } bool VPolarAxis::isAnythingToDraw() diff --git a/chart2/source/view/axes/VPolarAxis.hxx b/chart2/source/view/axes/VPolarAxis.hxx index 0a7056be72aa..dc6233a71e02 100644 --- a/chart2/source/view/axes/VPolarAxis.hxx +++ b/chart2/source/view/axes/VPolarAxis.hxx @@ -16,17 +16,15 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARAXIS_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARAXIS_HXX +#pragma once #include "VAxisBase.hxx" +#include <PlottingPositionHelper.hxx> #include <memory> namespace chart { -class PolarPlottingPositionHelper; - class VPolarAxis : public VAxisBase { public: @@ -34,7 +32,7 @@ public: , const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount ); - void setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ); + void setIncrements( std::vector< ExplicitIncrementData >&& rIncrements ); virtual bool isAnythingToDraw() override; @@ -46,11 +44,10 @@ protected: , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount ); protected: //member - std::unique_ptr<PolarPlottingPositionHelper> m_pPosHelper; + PolarPlottingPositionHelper m_aPosHelper; std::vector< ExplicitIncrementData > m_aIncrements; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VPolarCoordinateSystem.cxx b/chart2/source/view/axes/VPolarCoordinateSystem.cxx index 1fee84175444..ab7e603009ba 100644 --- a/chart2/source/view/axes/VPolarCoordinateSystem.cxx +++ b/chart2/source/view/axes/VPolarCoordinateSystem.cxx @@ -20,18 +20,21 @@ #include "VPolarCoordinateSystem.hxx" #include "VPolarGrid.hxx" #include "VPolarAxis.hxx" +#include <BaseCoordinateSystem.hxx> #include <AxisIndexDefines.hxx> +#include <Axis.hxx> #include <AxisHelper.hxx> +#include <Diagram.hxx> +#include <DataTable.hxx> #include <ChartModel.hxx> -#include <com/sun/star/chart2/XCoordinateSystem.hpp> +#include <GridProperties.hxx> namespace chart { using namespace ::com::sun::star; -using namespace ::com::sun::star::chart2; using ::com::sun::star::uno::Reference; -VPolarCoordinateSystem::VPolarCoordinateSystem( const Reference< XCoordinateSystem >& xCooSys ) +VPolarCoordinateSystem::VPolarCoordinateSystem( const rtl::Reference< BaseCoordinateSystem >& xCooSys ) : VCoordinateSystem(xCooSys) { } @@ -48,15 +51,16 @@ uno::Sequence< sal_Int32 > VPolarCoordinateSystem::getCoordinateSystemResolution if( aResolution.getLength() >= 2 ) { + auto pResolution = aResolution.getArray(); if( getPropertySwapXAndYAxis() ) { - aResolution[0]/=2;//radius - aResolution[1]*=4;//outer circle resolution + pResolution[0]/=2;//radius + pResolution[1]*=4;//outer circle resolution } else { - aResolution[0]*=4;//outer circle resolution - aResolution[1]/=2;//radius + pResolution[0]*=4;//outer circle resolution + pResolution[1]/=2;//radius } } @@ -64,16 +68,17 @@ uno::Sequence< sal_Int32 > VPolarCoordinateSystem::getCoordinateSystemResolution } void VPolarCoordinateSystem::createVAxisList( - const uno::Reference<chart2::XChartDocument> & xChartDoc - , const awt::Size& rFontReferenceSize - , const awt::Rectangle& rMaximumSpaceForLabels - , bool //bLimitSpaceForLabels - ) + const rtl::Reference<::chart::ChartModel> & xChartDoc, + const awt::Size& rFontReferenceSize, + const awt::Rectangle& rMaximumSpaceForLabels, + bool /*bLimitSpaceForLabels*/, + std::vector<std::unique_ptr<VSeriesPlotter>>& /*rSeriesPlotterList*/, + css::uno::Reference<css::uno::XComponentContext> const& /*rComponentContext*/) { // note: using xChartDoc itself as XNumberFormatsSupplier would cause // a leak from VPolarAxis due to cyclic reference uno::Reference<util::XNumberFormatsSupplier> const xNumberFormatsSupplier( - dynamic_cast<ChartModel&>(*xChartDoc).getNumberFormatsSupplier()); + xChartDoc->getNumberFormatsSupplier()); m_aAxisMap.clear(); sal_Int32 nDimensionCount = m_xCooSysModel->getDimension(); @@ -85,10 +90,12 @@ void VPolarCoordinateSystem::createVAxisList( sal_Int32 nMaxAxisIndex = m_xCooSysModel->getMaximumAxisIndexByDimension(nDimensionIndex); for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ ) { - Reference< XAxis > xAxis( getAxisByDimension(nDimensionIndex,nAxisIndex) ); + rtl::Reference< Axis > xAxis = getAxisByDimension(nDimensionIndex,nAxisIndex); if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel )) continue; - AxisProperties aAxisProperties(xAxis,getExplicitCategoriesProvider()); + + rtl::Reference<Diagram> xDiagram(xChartDoc->getFirstChartDiagram()); + AxisProperties aAxisProperties(xAxis,getExplicitCategoriesProvider(), xDiagram->getDataTableRef()); aAxisProperties.init(); if(aAxisProperties.m_bDisplayLabels) aAxisProperties.m_nNumberFormatKey = getNumberFormatKeyForAxis(xAxis, xChartDoc); @@ -118,7 +125,7 @@ void VPolarCoordinateSystem::initVAxisInList() sal_Int32 nDimensionIndex = elem.first.first; sal_Int32 nAxisIndex = elem.first.second; pVAxis->setExplicitScaleAndIncrement( getExplicitScale( nDimensionIndex, nAxisIndex ), getExplicitIncrement(nDimensionIndex, nAxisIndex) ); - pVAxis->initPlotter(m_xLogicTargetForAxes,m_xFinalTarget,m_xShapeFactory + pVAxis->initPlotter(m_xLogicTargetForAxes,m_xFinalTarget , createCIDForAxis( nDimensionIndex, nAxisIndex ) ); VPolarAxis* pVPolarAxis = dynamic_cast< VPolarAxis* >( pVAxis ); if( pVPolarAxis ) @@ -168,13 +175,13 @@ void VPolarCoordinateSystem::createGridShapes() { sal_Int32 nAxisIndex = MAIN_AXIS_INDEX; - Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, m_xCooSysModel ) ); + rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, nAxisIndex, m_xCooSysModel ); if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel )) continue; VPolarGrid aGrid(nDimensionIndex,nDimensionCount,getGridListFromAxis( xAxis )); aGrid.setIncrements( getExplicitIncrements( nDimensionIndex, nAxisIndex ) ); - aGrid.initPlotter(m_xLogicTargetForGrids,m_xFinalTarget,m_xShapeFactory + aGrid.initPlotter(m_xLogicTargetForGrids,m_xFinalTarget , createCIDForGrid( nDimensionIndex, nAxisIndex ) ); if(nDimensionCount==2) aGrid.setTransformationSceneToScreen( m_aMatrixSceneToScreen ); diff --git a/chart2/source/view/axes/VPolarCoordinateSystem.hxx b/chart2/source/view/axes/VPolarCoordinateSystem.hxx index 4976672963c8..a2ea0220f8bc 100644 --- a/chart2/source/view/axes/VPolarCoordinateSystem.hxx +++ b/chart2/source/view/axes/VPolarCoordinateSystem.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARCOORDINATESYSTEM_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARCOORDINATESYSTEM_HXX +#pragma once #include <VCoordinateSystem.hxx> @@ -28,7 +27,7 @@ class VPolarCoordinateSystem : public VCoordinateSystem { public: VPolarCoordinateSystem() = delete; - explicit VPolarCoordinateSystem( const css::uno::Reference< css::chart2::XCoordinateSystem >& xCooSys ); + explicit VPolarCoordinateSystem( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys ); virtual ~VPolarCoordinateSystem() override; //better performance for big data @@ -36,10 +35,12 @@ public: , const css::awt::Size& rPageResolution ) override; virtual void createVAxisList( - const css::uno::Reference< css::chart2::XChartDocument> & xChartDoc - , const css::awt::Size& rFontReferenceSize - , const css::awt::Rectangle& rMaximumSpaceForLabels - , bool bLimitSpaceForLabels ) override; + const rtl::Reference<::chart::ChartModel> &ChartDoc, + const css::awt::Size& rFontReferenceSize, + const css::awt::Rectangle& rMaximumSpaceForLabels, + bool bLimitSpaceForLabels, + std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList, + css::uno::Reference<css::uno::XComponentContext> const& rComponentContext) override; virtual void initVAxisInList() override; virtual void updateScalesAndIncrementsOnAxes() override; @@ -48,6 +49,5 @@ public: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VPolarGrid.cxx b/chart2/source/view/axes/VPolarGrid.cxx index 46d176b6d91b..7c49842640a7 100644 --- a/chart2/source/view/axes/VPolarGrid.cxx +++ b/chart2/source/view/axes/VPolarGrid.cxx @@ -20,6 +20,7 @@ #include "VPolarGrid.hxx" #include "VCartesianGrid.hxx" #include "Tickmarks.hxx" +#include <GridProperties.hxx> #include <PlottingPositionHelper.hxx> #include <ShapeFactory.hxx> #include <ObjectIdentifier.hxx> @@ -38,22 +39,20 @@ using namespace ::com::sun::star::chart2; using ::com::sun::star::uno::Reference; VPolarGrid::VPolarGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount - , const uno::Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList ) + , std::vector< rtl::Reference< ::chart::GridProperties > > aGridPropertiesList ) : VAxisOrGridBase( nDimensionIndex, nDimensionCount ) - , m_aGridPropertiesList( rGridPropertiesList ) - , m_pPosHelper( new PolarPlottingPositionHelper() ) - , m_aIncrements() + , m_aGridPropertiesList( std::move(aGridPropertiesList) ) { - PlotterBase::m_pPosHelper = m_pPosHelper.get(); + PlotterBase::m_pPosHelper = &m_aPosHelper; } VPolarGrid::~VPolarGrid() { } -void VPolarGrid::setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ) +void VPolarGrid::setIncrements( std::vector< ExplicitIncrementData >&& rIncrements ) { - m_aIncrements = rIncrements; + m_aIncrements = std::move(rIncrements); } void VPolarGrid::getAllTickInfos( sal_Int32 nDimensionIndex, TickInfoArraysType& rAllTickInfos ) const @@ -77,28 +76,31 @@ void VPolarGrid::createLinePointSequence_ForAngleAxis( sal_Int32 nTick = 0; EquidistantTickIter aIter( rAllTickInfos, rIncrement, 0 ); + auto pPoints = rPoints.getArray(); for( TickInfo* pTickInfo = aIter.firstInfo() ; pTickInfo ; pTickInfo = aIter.nextInfo(), nTick++ ) { if(nTick>=rPoints[0].getLength()) - rPoints[0].realloc(rPoints[0].getLength()+30); + pPoints[0].realloc(rPoints[0].getLength()+30); + auto pPoints0 = pPoints[0].getArray(); //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling ); double fLogicAngle = pTickInfo->getUnscaledTickValue(); drawing::Position3D aScenePosition3D( pPosHelper->transformAngleRadiusToScene( fLogicAngle, fLogicRadius, fLogicZ ) ); - rPoints[0][nTick].X = static_cast<sal_Int32>(aScenePosition3D.PositionX); - rPoints[0][nTick].Y = static_cast<sal_Int32>(aScenePosition3D.PositionY); + pPoints0[nTick].X = static_cast<sal_Int32>(aScenePosition3D.PositionX); + pPoints0[nTick].Y = static_cast<sal_Int32>(aScenePosition3D.PositionY); } if(rPoints[0].getLength()>1) { - rPoints[0].realloc(nTick+1); - rPoints[0][nTick].X = rPoints[0][0].X; - rPoints[0][nTick].Y = rPoints[0][0].Y; + pPoints[0].realloc(nTick+1); + auto pPoints0 = pPoints[0].getArray(); + pPoints0[nTick].X = rPoints[0][0].X; + pPoints0[nTick].Y = rPoints[0][0].Y; } else - rPoints[0].realloc(0); + pPoints[0].realloc(0); } #ifdef NOTYET void VPolarGrid::create2DAngleGrid( const Reference< drawing::XShapes >& xLogicTarget @@ -144,7 +146,7 @@ void VPolarGrid::create2DAngleGrid( const Reference< drawing::XShapes >& xLogicT appendPointSequence( aAllPoints, aPoints ); } - Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( + rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D( xMainTarget, aAllPoints, &rLinePropertiesList[nDepth] ); //because of this name this line will be used for marking m_pShapeFactory->setShapeName( xShape, "MarkHandles" ); @@ -152,13 +154,13 @@ void VPolarGrid::create2DAngleGrid( const Reference< drawing::XShapes >& xLogicT } #endif -void VPolarGrid::create2DRadiusGrid( const Reference< drawing::XShapes >& xLogicTarget +void VPolarGrid::create2DRadiusGrid( const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget , TickInfoArraysType& rRadiusTickInfos , TickInfoArraysType& rAngleTickInfos , const std::vector<VLineProperties>& rLinePropertiesList ) { - Reference< drawing::XShapes > xMainTarget( - createGroupShape( xLogicTarget, m_aCID ) ); + rtl::Reference<SvxShapeGroupAnyD> xMainTarget = + createGroupShape( xLogicTarget, m_aCID ); const std::vector<ExplicitScaleData>& rScales = m_pPosHelper->getScales(); const ExplicitScaleData& rRadiusScale = rScales[1]; @@ -178,14 +180,14 @@ void VPolarGrid::create2DRadiusGrid( const Reference< drawing::XShapes >& xLogic if( !rLinePropertiesList[nDepth].isLineVisible() ) continue; - Reference< drawing::XShapes > xTarget( xMainTarget ); + rtl::Reference<SvxShapeGroupAnyD> xTarget( xMainTarget ); if( nDepth > 0 ) { - xTarget.set( createGroupShape( xLogicTarget + xTarget = createGroupShape( xLogicTarget , ObjectIdentifier::addChildParticle( m_aCID, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_SUBGRID, nDepth-1 ) ) - ) ); + ); if(!xTarget.is()) - xTarget.set( xMainTarget ); + xTarget = xMainTarget; } //create axis main lines @@ -201,12 +203,12 @@ void VPolarGrid::create2DRadiusGrid( const Reference< drawing::XShapes >& xLogic drawing::PointSequenceSequence aPoints(1); VPolarGrid::createLinePointSequence_ForAngleAxis( aPoints, rAngleTickInfos - , rAngleIncrement, rAngleScale, m_pPosHelper.get(), fLogicRadius, fLogicZ ); + , rAngleIncrement, rAngleScale, &m_aPosHelper, fLogicRadius, fLogicZ ); if(aPoints[0].getLength()) appendPointSequence( aAllPoints, aPoints ); } - Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( + rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D( xTarget, aAllPoints, &rLinePropertiesList[nDepth] ); //because of this name this line will be used for marking ::chart::ShapeFactory::setShapeName( xShape, "MarkHandles" ); @@ -215,10 +217,10 @@ void VPolarGrid::create2DRadiusGrid( const Reference< drawing::XShapes >& xLogic void VPolarGrid::createShapes() { - OSL_PRECOND(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized"); - if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + OSL_PRECOND(m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized"); + if(!(m_xLogicTarget.is()&&m_xFinalTarget.is())) return; - if(!m_aGridPropertiesList.hasElements()) + if(m_aGridPropertiesList.empty()) return; //create all scaled tickmark values diff --git a/chart2/source/view/axes/VPolarGrid.hxx b/chart2/source/view/axes/VPolarGrid.hxx index 29fa8b27065a..5c0a21bb4733 100644 --- a/chart2/source/view/axes/VPolarGrid.hxx +++ b/chart2/source/view/axes/VPolarGrid.hxx @@ -16,11 +16,11 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARGRID_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARGRID_HXX +#pragma once #include "VAxisOrGridBase.hxx" #include "Tickmarks.hxx" +#include <PlottingPositionHelper.hxx> #include <com/sun/star/drawing/PointSequenceSequence.hpp> #include <memory> @@ -28,22 +28,21 @@ namespace chart { struct VLineProperties; } namespace chart { - -class PolarPlottingPositionHelper; +class GridProperties; class VPolarGrid : public VAxisOrGridBase { // public methods public: VPolarGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount - , const css::uno::Sequence< - css::uno::Reference< css::beans::XPropertySet > > & rGridPropertiesList //main grid, subgrid, subsubgrid etc + , std::vector< + rtl::Reference< ::chart::GridProperties > > aGridPropertiesList //main grid, subgrid, subsubgrid etc ); virtual ~VPolarGrid() override; virtual void createShapes() override; - void setIncrements( const std::vector< ExplicitIncrementData >& rIncrements ); + void setIncrements( std::vector< ExplicitIncrementData >&& rIncrements ); static void createLinePointSequence_ForAngleAxis( css::drawing::PointSequenceSequence& rPoints @@ -54,20 +53,19 @@ public: , double fLogicRadius, double fLogicZ ); private: //member - css::uno::Sequence< - css::uno::Reference< css::beans::XPropertySet > > m_aGridPropertiesList;//main grid, subgrid, subsubgrid etc - std::unique_ptr<PolarPlottingPositionHelper> m_pPosHelper; + std::vector< + rtl::Reference< ::chart::GridProperties > > m_aGridPropertiesList;//main grid, subgrid, subsubgrid etc + PolarPlottingPositionHelper m_aPosHelper; std::vector< ExplicitIncrementData > m_aIncrements; void getAllTickInfos( sal_Int32 nDimensionIndex, TickInfoArraysType& rAllTickInfos ) const; - void create2DRadiusGrid( const css::uno::Reference<css::drawing::XShapes>& xLogicTarget + void create2DRadiusGrid( const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget , TickInfoArraysType& rRadiusTickInfos , TickInfoArraysType& rAngleTickInfos , const std::vector<VLineProperties>& rLinePropertiesList ); }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/axes/VPolarRadiusAxis.cxx b/chart2/source/view/axes/VPolarRadiusAxis.cxx index 6bf0b0f47d3b..f93315410e96 100644 --- a/chart2/source/view/axes/VPolarRadiusAxis.cxx +++ b/chart2/source/view/axes/VPolarRadiusAxis.cxx @@ -20,6 +20,7 @@ #include "VPolarRadiusAxis.hxx" #include "VCartesianAxis.hxx" #include <PlottingPositionHelper.hxx> +#include <Axis.hxx> #include <CommonConverters.hxx> #include "Tickmarks_Equidistant.hxx" @@ -27,7 +28,6 @@ namespace chart { using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; -using namespace ::rtl::math; VPolarRadiusAxis::VPolarRadiusAxis( const AxisProperties& rAxisProperties , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier @@ -63,19 +63,18 @@ void VPolarRadiusAxis::setExplicitScaleAndIncrement( m_apAxisWithLabels->setExplicitScaleAndIncrement( rScale, rIncrement ); } -void VPolarRadiusAxis::initPlotter( const uno::Reference< drawing::XShapes >& xLogicTarget - , const uno::Reference< drawing::XShapes >& xFinalTarget - , const uno::Reference< lang::XMultiServiceFactory >& xShapeFactory +void VPolarRadiusAxis::initPlotter( const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget + , const rtl::Reference<SvxShapeGroupAnyD>& xFinalTarget , const OUString& rCID ) { - VPolarAxis::initPlotter( xLogicTarget, xFinalTarget, xShapeFactory, rCID ); - m_apAxisWithLabels->initPlotter( xLogicTarget, xFinalTarget, xShapeFactory, rCID ); + VPolarAxis::initPlotter( xLogicTarget, xFinalTarget, rCID ); + m_apAxisWithLabels->initPlotter( xLogicTarget, xFinalTarget, rCID ); } -void VPolarRadiusAxis::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) +void VPolarRadiusAxis::setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) { - VPolarAxis::setScales( rScales, bSwapXAndYAxis ); - m_apAxisWithLabels->setScales( rScales, bSwapXAndYAxis ); + VPolarAxis::setScales( std::vector(rScales), bSwapXAndYAxis ); + m_apAxisWithLabels->setScales( std::move(rScales), bSwapXAndYAxis ); } void VPolarRadiusAxis::initAxisLabelProperties( const css::awt::Size& rFontReferenceSize @@ -153,9 +152,9 @@ void VPolarRadiusAxis::createShapes() VCartesianAxis aAxis(aAxisProperties,m_xNumberFormatsSupplier ,1,2,new PolarPlottingPositionHelper()); aAxis.setExplicitScaleAndIncrement( m_aScale, m_aIncrement ); - aAxis.initPlotter(m_xLogicTarget,m_xFinalTarget,m_xShapeFactory, m_aCID ); + aAxis.initPlotter(m_xLogicTarget,m_xFinalTarget, m_aCID ); aAxis.setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( m_aMatrixScreenToScene ) ); - aAxis.setScales( m_pPosHelper->getScales(), false ); + aAxis.setScales( std::vector(m_pPosHelper->getScales()), false ); aAxis.initAxisLabelProperties(m_aAxisLabelProperties.m_aFontReferenceSize,m_aAxisLabelProperties.m_aMaximumSpaceForLabels); aAxis.createShapes(); } diff --git a/chart2/source/view/axes/VPolarRadiusAxis.hxx b/chart2/source/view/axes/VPolarRadiusAxis.hxx index 38ebd7b299a6..b2450e236268 100644 --- a/chart2/source/view/axes/VPolarRadiusAxis.hxx +++ b/chart2/source/view/axes/VPolarRadiusAxis.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARRADIUSAXIS_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_AXES_VPOLARRADIUSAXIS_HXX +#pragma once #include "VPolarAxis.hxx" #include <memory> @@ -36,15 +35,14 @@ public: virtual ~VPolarRadiusAxis() override; virtual void initPlotter( - const css::uno::Reference< css::drawing::XShapes >& xLogicTarget - , const css::uno::Reference< css::drawing::XShapes >& xFinalTarget - , const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory + const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget + , const rtl::Reference<SvxShapeGroupAnyD>& xFinalTarget , const OUString& rCID ) override; virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix ) override; - virtual void setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) override; + virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) override; virtual void setExplicitScaleAndIncrement( const ExplicitScaleData& rScale @@ -70,6 +68,5 @@ private: //member }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/AreaChart.cxx b/chart2/source/view/charttypes/AreaChart.cxx index a658a26d04a6..3bab48585148 100644 --- a/chart2/source/view/charttypes/AreaChart.cxx +++ b/chart2/source/view/charttypes/AreaChart.cxx @@ -24,40 +24,39 @@ #include <ExplicitCategoriesProvider.hxx> #include <ObjectIdentifier.hxx> #include "Splines.hxx" +#include <ChartType.hxx> #include <ChartTypeHelper.hxx> #include <LabelPositionHelper.hxx> #include <Clipping.hxx> #include <Stripe.hxx> #include <DateHelper.hxx> #include <unonames.hxx> -#include <ConfigAccess.hxx> #include <com/sun/star/chart2/Symbol.hpp> #include <com/sun/star/chart/DataLabelPlacement.hpp> #include <com/sun/star/chart/MissingValueTreatment.hpp> -#include <rtl/math.hxx> #include <sal/log.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> -#include <com/sun/star/drawing/DoubleSequence.hpp> -#include <com/sun/star/drawing/XShapes.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <officecfg/Office/Compatibility.hxx> +#include <officecfg/Office/Chart.hxx> + +#include <limits> namespace chart { using namespace ::com::sun::star; -using namespace ::rtl::math; using namespace ::com::sun::star::chart2; -AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel +AreaChart::AreaChart( const rtl::Reference<ChartType>& xChartTypeModel , sal_Int32 nDimensionCount , bool bCategoryXAxis , bool bNoArea ) : VSeriesPlotter( xChartTypeModel, nDimensionCount, bCategoryXAxis ) - , m_pMainPosHelper(new PlottingPositionHelper()) , m_bArea(!bNoArea) , m_bLine(bNoArea) , m_bSymbol( ChartTypeHelper::isSupportingSymbolProperties(xChartTypeModel,nDimensionCount) ) @@ -65,19 +64,19 @@ AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel , m_nCurveResolution(20) , m_nSplineOrder(3) { + PlotterBase::m_pPosHelper = &m_aMainPosHelper; + VSeriesPlotter::m_pMainPosHelper = &m_aMainPosHelper; + m_pMainPosHelper->AllowShiftXAxisPos(true); m_pMainPosHelper->AllowShiftZAxisPos(true); - PlotterBase::m_pPosHelper = m_pMainPosHelper.get(); - VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper.get(); - try { - if( m_xChartTypeModelProps.is() ) + if( m_xChartTypeModel.is() ) { - m_xChartTypeModelProps->getPropertyValue(CHART_UNONAME_CURVE_STYLE) >>= m_eCurveStyle; - m_xChartTypeModelProps->getPropertyValue(CHART_UNONAME_CURVE_RESOLUTION) >>= m_nCurveResolution; - m_xChartTypeModelProps->getPropertyValue(CHART_UNONAME_SPLINE_ORDER) >>= m_nSplineOrder; + m_xChartTypeModel->getPropertyValue(CHART_UNONAME_CURVE_STYLE) >>= m_eCurveStyle; + m_xChartTypeModel->getPropertyValue(CHART_UNONAME_CURVE_RESOLUTION) >>= m_nCurveResolution; + m_xChartTypeModel->getPropertyValue(CHART_UNONAME_SPLINE_ORDER) >>= m_nSplineOrder; } } catch( uno::Exception& e ) @@ -154,122 +153,95 @@ void AreaChart::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot VSeriesPlotter::addSeries( std::move(pSeries), zSlot, xSlot, ySlot ); } -static void lcl_removeDuplicatePoints( drawing::PolyPolygonShape3D& rPolyPoly, PlottingPositionHelper& rPosHelper ) +static void lcl_removeDuplicatePoints( std::vector<std::vector<css::drawing::Position3D>>& rPolyPoly, PlottingPositionHelper& rPosHelper ) { - sal_Int32 nPolyCount = rPolyPoly.SequenceX.getLength(); + sal_Int32 nPolyCount = rPolyPoly.size(); if(!nPolyCount) return; - drawing::PolyPolygonShape3D aTmp; - aTmp.SequenceX.realloc(nPolyCount); - aTmp.SequenceY.realloc(nPolyCount); - aTmp.SequenceZ.realloc(nPolyCount); + // TODO we could do with without a temporary array + std::vector<std::vector<css::drawing::Position3D>> aTmp; + aTmp.resize(nPolyCount); for( sal_Int32 nPolygonIndex = 0; nPolygonIndex<nPolyCount; nPolygonIndex++ ) { - drawing::DoubleSequence* pOuterSourceX = &rPolyPoly.SequenceX.getArray()[nPolygonIndex]; - drawing::DoubleSequence* pOuterSourceY = &rPolyPoly.SequenceY.getArray()[nPolygonIndex]; - drawing::DoubleSequence* pOuterSourceZ = &rPolyPoly.SequenceZ.getArray()[nPolygonIndex]; + std::vector<css::drawing::Position3D>* pOuterSource = &rPolyPoly[nPolygonIndex]; + std::vector<css::drawing::Position3D>* pOuterTarget = &aTmp[nPolygonIndex]; - drawing::DoubleSequence* pOuterTargetX = &aTmp.SequenceX.getArray()[nPolygonIndex]; - drawing::DoubleSequence* pOuterTargetY = &aTmp.SequenceY.getArray()[nPolygonIndex]; - drawing::DoubleSequence* pOuterTargetZ = &aTmp.SequenceZ.getArray()[nPolygonIndex]; - - sal_Int32 nPointCount = pOuterSourceX->getLength(); + sal_Int32 nPointCount = pOuterSource->size(); if( !nPointCount ) continue; - pOuterTargetX->realloc(nPointCount); - pOuterTargetY->realloc(nPointCount); - pOuterTargetZ->realloc(nPointCount); - - double* pSourceX = pOuterSourceX->getArray(); - double* pSourceY = pOuterSourceY->getArray(); - double* pSourceZ = pOuterSourceZ->getArray(); + pOuterTarget->resize(nPointCount); - double* pTargetX = pOuterTargetX->getArray(); - double* pTargetY = pOuterTargetY->getArray(); - double* pTargetZ = pOuterTargetZ->getArray(); + css::drawing::Position3D* pSource = pOuterSource->data(); + css::drawing::Position3D* pTarget = pOuterTarget->data(); //copy first point - *pTargetX=*pSourceX++; - *pTargetY=*pSourceY++; - *pTargetZ=*pSourceZ++; + *pTarget=*pSource++; sal_Int32 nTargetPointCount=1; for( sal_Int32 nSource=1; nSource<nPointCount; nSource++ ) { - if( !rPosHelper.isSameForGivenResolution( *pTargetX, *pTargetY, *pTargetZ - , *pSourceX, *pSourceY, *pSourceZ ) ) + if( !rPosHelper.isSameForGivenResolution( pTarget->PositionX, pTarget->PositionY, pTarget->PositionZ + , pSource->PositionX, pSource->PositionY, pSource->PositionZ ) ) { - pTargetX++; pTargetY++; pTargetZ++; - *pTargetX=*pSourceX; - *pTargetY=*pSourceY; - *pTargetZ=*pSourceZ; + pTarget++; + *pTarget=*pSource; nTargetPointCount++; } - pSourceX++; pSourceY++; pSourceZ++; + pSource++; } //free unused space if( nTargetPointCount<nPointCount ) { - pOuterTargetX->realloc(nTargetPointCount); - pOuterTargetY->realloc(nTargetPointCount); - pOuterTargetZ->realloc(nTargetPointCount); + pOuterTarget->resize(nTargetPointCount); } - pOuterSourceX->realloc(0); - pOuterSourceY->realloc(0); - pOuterSourceZ->realloc(0); + pOuterSource->clear(); } //free space - rPolyPoly.SequenceX.realloc(nPolyCount); - rPolyPoly.SequenceY.realloc(nPolyCount); - rPolyPoly.SequenceZ.realloc(nPolyCount); + rPolyPoly.resize(nPolyCount); - rPolyPoly=aTmp; + rPolyPoly = std::move(aTmp); } -bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, chart2::CurveStyle eCurveStyle, PlottingPositionHelper const * pPosHelper, drawing::PolyPolygonShape3D &aPoly ) +bool AreaChart::create_stepped_line( + std::vector<std::vector<css::drawing::Position3D>> aStartPoly, + chart2::CurveStyle eCurveStyle, + PlottingPositionHelper const * pPosHelper, + std::vector<std::vector<css::drawing::Position3D>> &aPoly ) { - sal_uInt32 nOuterCount = aStartPoly.SequenceX.getLength(); + sal_uInt32 nOuterCount = aStartPoly.size(); if ( !nOuterCount ) return false; - drawing::PolyPolygonShape3D aSteppedPoly; - aSteppedPoly.SequenceX.realloc(nOuterCount); - aSteppedPoly.SequenceY.realloc(nOuterCount); - aSteppedPoly.SequenceZ.realloc(nOuterCount); + std::vector<std::vector<css::drawing::Position3D>> aSteppedPoly; + aSteppedPoly.resize(nOuterCount); + + auto pSequence = aSteppedPoly.data(); for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter ) { - if( aStartPoly.SequenceX[nOuter].getLength() <= 1 ) + if( aStartPoly[nOuter].size() <= 1 ) continue; //we need at least two points - sal_uInt32 nMaxIndexPoints = aStartPoly.SequenceX[nOuter].getLength()-1; // is >1 + sal_uInt32 nMaxIndexPoints = aStartPoly[nOuter].size()-1; // is >1 sal_uInt32 nNewIndexPoints = 0; if ( eCurveStyle==CurveStyle_STEP_START || eCurveStyle==CurveStyle_STEP_END) nNewIndexPoints = nMaxIndexPoints * 2 + 1; else nNewIndexPoints = nMaxIndexPoints * 3 + 1; - const double* pOldX = aStartPoly.SequenceX[nOuter].getConstArray(); - const double* pOldY = aStartPoly.SequenceY[nOuter].getConstArray(); - const double* pOldZ = aStartPoly.SequenceZ[nOuter].getConstArray(); + const css::drawing::Position3D* pOld = aStartPoly[nOuter].data(); - aSteppedPoly.SequenceX[nOuter].realloc( nNewIndexPoints ); - aSteppedPoly.SequenceY[nOuter].realloc( nNewIndexPoints ); - aSteppedPoly.SequenceZ[nOuter].realloc( nNewIndexPoints ); + pSequence[nOuter].resize( nNewIndexPoints ); - double* pNewX = aSteppedPoly.SequenceX[nOuter].getArray(); - double* pNewY = aSteppedPoly.SequenceY[nOuter].getArray(); - double* pNewZ = aSteppedPoly.SequenceZ[nOuter].getArray(); + css::drawing::Position3D* pNew = pSequence[nOuter].data(); - pNewX[0] = pOldX[0]; - pNewY[0] = pOldY[0]; - pNewZ[0] = pOldZ[0]; + pNew[0] = pOld[0]; for( sal_uInt32 oi = 0; oi < nMaxIndexPoints; oi++ ) { switch ( eCurveStyle ) @@ -282,13 +254,11 @@ bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, cha O-----+ */ // create the intermediate point - pNewX[1+oi*2] = pOldX[oi+1]; - pNewY[1+oi*2] = pOldY[oi]; - pNewZ[1+oi*2] = pOldZ[oi]; + pNew[1+oi*2].PositionX = pOld[oi+1].PositionX; + pNew[1+oi*2].PositionY = pOld[oi].PositionY; + pNew[1+oi*2].PositionZ = pOld[oi].PositionZ; // and now the normal one - pNewX[1+oi*2+1] = pOldX[oi+1]; - pNewY[1+oi*2+1] = pOldY[oi+1]; - pNewZ[1+oi*2+1] = pOldZ[oi+1]; + pNew[1+oi*2+1] = pOld[oi+1]; break; case CurveStyle_STEP_END: /** +------O @@ -298,13 +268,11 @@ bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, cha O */ // create the intermediate point - pNewX[1+oi*2] = pOldX[oi]; - pNewY[1+oi*2] = pOldY[oi+1]; - pNewZ[1+oi*2] = pOldZ[oi]; + pNew[1+oi*2].PositionX = pOld[oi].PositionX; + pNew[1+oi*2].PositionY = pOld[oi+1].PositionY; + pNew[1+oi*2].PositionZ = pOld[oi].PositionZ; // and now the normal one - pNewX[1+oi*2+1] = pOldX[oi+1]; - pNewY[1+oi*2+1] = pOldY[oi+1]; - pNewZ[1+oi*2+1] = pOldZ[oi+1]; + pNew[1+oi*2+1] = pOld[oi+1]; break; case CurveStyle_STEP_CENTER_X: /** +--O @@ -314,17 +282,15 @@ bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, cha O--+ */ // create the first intermediate point - pNewX[1+oi*3] = (pOldX[oi]+pOldX[oi+1])/2; - pNewY[1+oi*3] = pOldY[oi]; - pNewZ[1+oi*3] = pOldZ[oi]; + pNew[1+oi*3].PositionX = (pOld[oi].PositionX + pOld[oi+1].PositionX) / 2; + pNew[1+oi*3].PositionY = pOld[oi].PositionY; + pNew[1+oi*3].PositionZ = pOld[oi].PositionZ; // create the second intermediate point - pNewX[1+oi*3+1] = (pOldX[oi]+pOldX[oi+1])/2; - pNewY[1+oi*3+1] = pOldY[oi+1]; - pNewZ[1+oi*3+1] = pOldZ[oi]; + pNew[1+oi*3+1].PositionX = (pOld[oi].PositionX + pOld[oi+1].PositionX) / 2; + pNew[1+oi*3+1].PositionY = pOld[oi+1].PositionY; + pNew[1+oi*3+1].PositionZ = pOld[oi].PositionZ; // and now the normal one - pNewX[1+oi*3+2] = pOldX[oi+1]; - pNewY[1+oi*3+2] = pOldY[oi+1]; - pNewZ[1+oi*3+2] = pOldZ[oi+1]; + pNew[1+oi*3+2] = pOld[oi+1]; break; case CurveStyle_STEP_CENTER_Y: /** O @@ -334,17 +300,15 @@ bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, cha O */ // create the first intermediate point - pNewX[1+oi*3] = pOldX[oi]; - pNewY[1+oi*3] = (pOldY[oi]+pOldY[oi+1])/2; - pNewZ[1+oi*3] = pOldZ[oi]; + pNew[1+oi*3].PositionX = pOld[oi].PositionX; + pNew[1+oi*3].PositionY = (pOld[oi].PositionY + pOld[oi+1].PositionY) / 2; + pNew[1+oi*3].PositionZ = pOld[oi].PositionZ; // create the second intermediate point - pNewX[1+oi*3+1] = pOldX[oi+1]; - pNewY[1+oi*3+1] = (pOldY[oi]+pOldY[oi+1])/2; - pNewZ[1+oi*3+1] = pOldZ[oi]; + pNew[1+oi*3+1].PositionX = pOld[oi+1].PositionX; + pNew[1+oi*3+1].PositionY = (pOld[oi].PositionY + pOld[oi+1].PositionY) / 2; + pNew[1+oi*3+1].PositionZ = pOld[oi].PositionZ; // and now the normal one - pNewX[1+oi*3+2] = pOldX[oi+1]; - pNewY[1+oi*3+2] = pOldY[oi+1]; - pNewZ[1+oi*3+2] = pOldZ[oi+1]; + pNew[1+oi*3+2] = pOld[oi+1]; break; default: // this should never be executed @@ -358,23 +322,23 @@ bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, cha } bool AreaChart::impl_createLine( VDataSeries* pSeries - , drawing::PolyPolygonShape3D const * pSeriesPoly + , std::vector<std::vector<css::drawing::Position3D>> const * pSeriesPoly , PlottingPositionHelper* pPosHelper ) { //return true if a line was created successfully - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); - drawing::PolyPolygonShape3D aPoly; + std::vector<std::vector<css::drawing::Position3D>> aPoly; if(m_eCurveStyle==CurveStyle_CUBIC_SPLINES) { - drawing::PolyPolygonShape3D aSplinePoly; + std::vector<std::vector<css::drawing::Position3D>> aSplinePoly; SplineCalculater::CalculateCubicSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution ); lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper ); Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly ); } else if(m_eCurveStyle==CurveStyle_B_SPLINES) { - drawing::PolyPolygonShape3D aSplinePoly; + std::vector<std::vector<css::drawing::Position3D>> aSplinePoly; SplineCalculater::CalculateBSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution, m_nSplineOrder ); lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper ); Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly ); @@ -403,26 +367,21 @@ bool AreaChart::impl_createLine( VDataSeries* pSeries pPosHelper->transformScaledLogicToScene( aPoly ); //create line: - uno::Reference< drawing::XShape > xShape; + rtl::Reference< SvxShape > xShape; if(m_nDimension==3) { double fDepth = getTransformedDepth(); - sal_Int32 nPolyCount = aPoly.SequenceX.getLength(); + sal_Int32 nPolyCount = aPoly.size(); for(sal_Int32 nPoly=0;nPoly<nPolyCount;nPoly++) { - sal_Int32 nPointCount = aPoly.SequenceX[nPoly].getLength(); + sal_Int32 nPointCount = aPoly[nPoly].size(); for(sal_Int32 nPoint=0;nPoint<nPointCount-1;nPoint++) { drawing::Position3D aPoint1, aPoint2; - aPoint1.PositionX = aPoly.SequenceX[nPoly][nPoint+1]; - aPoint1.PositionY = aPoly.SequenceY[nPoly][nPoint+1]; - aPoint1.PositionZ = aPoly.SequenceZ[nPoly][nPoint+1]; + aPoint1 = aPoly[nPoly][nPoint+1]; + aPoint2 = aPoly[nPoly][nPoint]; - aPoint2.PositionX = aPoly.SequenceX[nPoly][nPoint]; - aPoint2.PositionY = aPoly.SequenceY[nPoly][nPoint]; - aPoint2.PositionZ = aPoly.SequenceZ[nPoly][nPoint]; - - m_pShapeFactory->createStripe(xSeriesGroupShape_Shapes + ShapeFactory::createStripe(xSeriesGroupShape_Shapes , Stripe( aPoint1, aPoint2, fDepth ) , pSeries->getPropertiesOfSeries(), PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), true, 1 ); } @@ -430,9 +389,8 @@ bool AreaChart::impl_createLine( VDataSeries* pSeries } else //m_nDimension!=3 { - xShape = m_pShapeFactory->createLine2D( xSeriesGroupShape_Shapes - , PolyToPointSequence( aPoly ) ); - setMappedProperties( xShape + xShape = ShapeFactory::createLine2D( xSeriesGroupShape_Shapes, aPoly ); + PropertyMapper::setMappedProperties( *xShape , pSeries->getPropertiesOfSeries() , PropertyMapper::getPropertyNameMapForLineSeriesProperties() ); //because of this name this line will be used for marking @@ -442,16 +400,16 @@ bool AreaChart::impl_createLine( VDataSeries* pSeries } bool AreaChart::impl_createArea( VDataSeries* pSeries - , drawing::PolyPolygonShape3D const * pSeriesPoly - , drawing::PolyPolygonShape3D const * pPreviousSeriesPoly + , std::vector<std::vector<css::drawing::Position3D>> const * pSeriesPoly + , std::vector<std::vector<css::drawing::Position3D>> const * pPreviousSeriesPoly , PlottingPositionHelper const * pPosHelper ) { //return true if an area was created successfully - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); double zValue = pSeries->m_fLogicZPos; - drawing::PolyPolygonShape3D aPoly( *pSeriesPoly ); + std::vector<std::vector<css::drawing::Position3D>> aPoly( *pSeriesPoly ); //add second part to the polygon (grounding points or previous series points) if(!pPreviousSeriesPoly) { @@ -484,7 +442,7 @@ bool AreaChart::impl_createArea( VDataSeries* pSeries //apply clipping { - drawing::PolyPolygonShape3D aClippedPoly; + std::vector<std::vector<css::drawing::Position3D>> aClippedPoly; Clipping::clipPolygonAtRectangle( aPoly, pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly, false ); ShapeFactory::closePolygon(aClippedPoly); //again necessary after clipping aPoly = aClippedPoly; @@ -497,18 +455,18 @@ bool AreaChart::impl_createArea( VDataSeries* pSeries pPosHelper->transformScaledLogicToScene( aPoly ); //create area: - uno::Reference< drawing::XShape > xShape; + rtl::Reference< SvxShape > xShape; if(m_nDimension==3) { - xShape = m_pShapeFactory->createArea3D( xSeriesGroupShape_Shapes + xShape = ShapeFactory::createArea3D( xSeriesGroupShape_Shapes , aPoly, getTransformedDepth() ); } else //m_nDimension!=3 { - xShape = m_pShapeFactory->createArea2D( xSeriesGroupShape_Shapes + xShape = ShapeFactory::createArea2D( xSeriesGroupShape_Shapes , aPoly ); } - setMappedProperties( xShape + PropertyMapper::setMappedProperties( *xShape , pSeries->getPropertiesOfSeries() , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); //because of this name this line will be used for marking @@ -525,8 +483,8 @@ void AreaChart::impl_createSeriesShapes() { for( auto const& rXSlot : rZSlot ) { - std::map< sal_Int32, drawing::PolyPolygonShape3D* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex - drawing::PolyPolygonShape3D* pSeriesPoly = nullptr; + std::map< sal_Int32, std::vector<std::vector<css::drawing::Position3D>>* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex + std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly = nullptr; //iterate through all series for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector ) @@ -589,10 +547,10 @@ struct FormerPoint : m_fX(fX), m_fY(fY), m_fZ(fZ) {} FormerPoint() + : m_fX(std::numeric_limits<double>::quiet_NaN()) + , m_fY(std::numeric_limits<double>::quiet_NaN()) + , m_fZ(std::numeric_limits<double>::quiet_NaN()) { - ::rtl::math::setNan( &m_fX ); - ::rtl::math::setNan( &m_fY ); - ::rtl::math::setNan( &m_fZ ); } double m_fX; @@ -611,8 +569,8 @@ void AreaChart::createShapes() if( officecfg::Office::Compatibility::View::ReverseSeriesOrderAreaAndNetChart::get() && m_nDimension == 2 && ( m_bArea || !m_bCategoryXAxis ) ) lcl_reorderSeries( m_aZSlots ); - OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"AreaChart is not proper initialized"); - if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"AreaChart is not proper initialized"); + if(!(m_xLogicTarget.is()&&m_xFinalTarget.is())) return; //the text labels should be always on top of the other series shapes @@ -625,8 +583,8 @@ void AreaChart::createShapes() m_xErrorBarTarget = createGroupShape( m_xLogicTarget ); else m_xErrorBarTarget = m_xSeriesTarget; - m_xTextTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget ); - m_xRegressionCurveEquationTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget ); + m_xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget ); + m_xRegressionCurveEquationTarget = ShapeFactory::createGroup2D( m_xFinalTarget ); //check necessary here that different Y axis can not be stacked in the same group? ... hm? @@ -664,8 +622,7 @@ void AreaChart::createShapes() { std::map< sal_Int32, double >& rLogicYSumMap = aLogicYSumMapByX[nIndex]; sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex(); - if( rLogicYSumMap.find(nAttachedAxisIndex)==rLogicYSumMap.end() ) - rLogicYSumMap[nAttachedAxisIndex]=0.0; + rLogicYSumMap.insert({nAttachedAxisIndex, 0.0}); m_pPosHelper = &getPlottingPositionHelper(nAttachedAxisIndex); @@ -677,6 +634,8 @@ void AreaChart::createShapes() } } + const bool bUseErrorRectangle = officecfg::Office::Chart::ErrorProperties::ErrorRectangle::get(); + sal_Int32 nZ=1; for( auto const& rZSlot : m_aZSlots ) { @@ -691,9 +650,11 @@ void AreaChart::createShapes() if(!pSeries) continue; - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(pSeries.get(), m_xSeriesTarget); + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(pSeries.get(), m_xSeriesTarget); sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex(); + double fXMin, fXMax; + pSeries->getMinMaxXValue(fXMin, fXMax); PlottingPositionHelper& rPosHelper = getPlottingPositionHelper(nAttachedAxisIndex); m_pPosHelper = &rPosHelper; @@ -714,7 +675,7 @@ void AreaChart::createShapes() double fLogicX = pSeries->getXValue(nIndex); if (bDateCategory) { - if (std::isnan(fLogicX)) + if (std::isnan(fLogicX) || (fLogicX < fXMin || fLogicX > fXMax)) continue; fLogicX = DateHelper::RasterizeDateValue( fLogicX, m_aNullDate, m_nTimeResolution ); @@ -737,11 +698,11 @@ void AreaChart::createShapes() { if( pSeries->getMissingValueTreatment() == css::chart::MissingValueTreatment::LEAVE_GAP ) { - drawing::PolyPolygonShape3D& rPolygon = pSeries->m_aPolyPolygonShape3D; + std::vector<std::vector<css::drawing::Position3D>>& rPolygon = pSeries->m_aPolyPolygonShape3D; sal_Int32& rIndex = pSeries->m_nPolygonIndex; - if( 0<= rIndex && rIndex < rPolygon.SequenceX.getLength() ) + if( 0<= rIndex && o3tl::make_unsigned(rIndex) < rPolygon.size() ) { - if( rPolygon.SequenceX[ rIndex ].hasElements() ) + if( !rPolygon[ rIndex ].empty() ) rIndex++; //start a new polygon for the next point if the current poly is not empty } } @@ -833,13 +794,6 @@ void AreaChart::createShapes() !bCreateXErrorBar && !pSeries->getDataPointLabelIfLabel(nIndex) ) continue; - //create a group shape for this point and add to the series shape: - OUString aPointCID = ObjectIdentifier::createPointCID( - pSeries->getPointCID_Stub(), nIndex ); - uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( - createGroupShape(xSeriesGroupShape_Shapes,aPointCID) ); - uno::Reference<drawing::XShape> xPointGroupShape_Shape( xPointGroupShape_Shapes, uno::UNO_QUERY ); - { nCreatedPoints++; @@ -849,6 +803,13 @@ void AreaChart::createShapes() { if(m_nDimension!=3) { + //create a group shape for this point and add to the series shape: + OUString aPointCID = ObjectIdentifier::createPointCID( + pSeries->getPointCID_Stub(), nIndex ); + rtl::Reference<SvxShapeGroupAnyD> xPointGroupShape_Shapes; + if (pSymbolProperties->Style == SymbolStyle_STANDARD || pSymbolProperties->Style == SymbolStyle_GRAPHIC) + xPointGroupShape_Shapes = createGroupShape(xSeriesGroupShape_Shapes,aPointCID); + if (pSymbolProperties->Style != SymbolStyle_NONE) { aSymbolSize.DirectionX = pSymbolProperties->Size.Width; @@ -858,14 +819,14 @@ void AreaChart::createShapes() if (pSymbolProperties->Style == SymbolStyle_STANDARD) { sal_Int32 nSymbol = pSymbolProperties->StandardSymbol; - m_pShapeFactory->createSymbol2D( + ShapeFactory::createSymbol2D( xPointGroupShape_Shapes, aScenePosition, aSymbolSize, nSymbol, pSymbolProperties->BorderColor, pSymbolProperties->FillColor); } else if (pSymbolProperties->Style == SymbolStyle_GRAPHIC) { - m_pShapeFactory->createGraphic2D(xPointGroupShape_Shapes, + ShapeFactory::createGraphic2D(xPointGroupShape_Shapes, aScenePosition, aSymbolSize, pSymbolProperties->Graphic); } @@ -873,7 +834,7 @@ void AreaChart::createShapes() } } //create error bars or rectangles, depending on configuration - if ( ConfigAccess::getUseErrorRectangle() ) + if ( bUseErrorRectangle ) { if ( bCreateXErrorBar || bCreateYErrorBar ) { @@ -948,7 +909,7 @@ void AreaChart::createShapes() { if(eAlignment==LABEL_ALIGN_CENTER || m_nDimension == 3 ) nOffset = 0; - aScreenPosition2D = LabelPositionHelper(m_nDimension,m_xLogicTarget,m_pShapeFactory) + aScreenPosition2D = LabelPositionHelper(m_nDimension,m_xLogicTarget) .transformSceneToScreenPosition( aScenePosition3D ); } @@ -957,10 +918,6 @@ void AreaChart::createShapes() , rLogicYSumMap[nAttachedAxisIndex], aScreenPosition2D, eAlignment, nOffset ); } } - - //remove PointGroupShape if empty - if(!xPointGroupShape_Shapes->getCount()) - xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape); } }//next series in x slot (next y slot) diff --git a/chart2/source/view/charttypes/AreaChart.hxx b/chart2/source/view/charttypes/AreaChart.hxx index 786fcba8310e..411b9d6642aa 100644 --- a/chart2/source/view/charttypes/AreaChart.hxx +++ b/chart2/source/view/charttypes/AreaChart.hxx @@ -17,11 +17,11 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_AREACHART_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_AREACHART_HXX +#pragma once #include <memory> #include <VSeriesPlotter.hxx> +#include <PlottingPositionHelper.hxx> #include <com/sun/star/chart2/CurveStyle.hpp> namespace chart @@ -33,7 +33,7 @@ class AreaChart : public VSeriesPlotter public: AreaChart() = delete; - AreaChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + AreaChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel , sal_Int32 nDimensionCount , bool bCategoryXAxis, bool bNoArea=false ); @@ -53,20 +53,19 @@ public: private: //methods void impl_createSeriesShapes(); bool impl_createArea( VDataSeries* pSeries - , css::drawing::PolyPolygonShape3D const * pSeriesPoly - , css::drawing::PolyPolygonShape3D const * pPreviousSeriesPoly + , std::vector<std::vector<css::drawing::Position3D>> const * pSeriesPoly + , std::vector<std::vector<css::drawing::Position3D>> const * pPreviousSeriesPoly , PlottingPositionHelper const * pPosHelper ); bool impl_createLine( VDataSeries* pSeries - , css::drawing::PolyPolygonShape3D const * pSeriesPoly + , std::vector<std::vector<css::drawing::Position3D>> const * pSeriesPoly , PlottingPositionHelper* pPosHelper ); - static bool create_stepped_line( css::drawing::PolyPolygonShape3D aStartPoly + static bool create_stepped_line( std::vector<std::vector<css::drawing::Position3D>> aStartPoly , css::chart2::CurveStyle eCurveStyle , PlottingPositionHelper const * pPosHelper - , css::drawing::PolyPolygonShape3D &aPoly ); + , std::vector<std::vector<css::drawing::Position3D>> &aPoly ); private: //member - std::unique_ptr<PlottingPositionHelper> - m_pMainPosHelper; + PlottingPositionHelper m_aMainPosHelper; bool m_bArea;//false -> line or symbol only bool m_bLine; @@ -77,12 +76,11 @@ private: //member sal_Int32 m_nCurveResolution; sal_Int32 m_nSplineOrder; - css::uno::Reference< css::drawing::XShapes > m_xSeriesTarget; - css::uno::Reference< css::drawing::XShapes > m_xErrorBarTarget; - css::uno::Reference< css::drawing::XShapes > m_xTextTarget; - css::uno::Reference< css::drawing::XShapes > m_xRegressionCurveEquationTarget; + rtl::Reference<SvxShapeGroupAnyD> m_xSeriesTarget; + rtl::Reference<SvxShapeGroupAnyD> m_xErrorBarTarget; + rtl::Reference<SvxShapeGroupAnyD> m_xTextTarget; + rtl::Reference<SvxShapeGroupAnyD> m_xRegressionCurveEquationTarget; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/BarChart.cxx b/chart2/source/view/charttypes/BarChart.cxx index 3641e67b4657..fcc969b898ad 100644 --- a/chart2/source/view/charttypes/BarChart.cxx +++ b/chart2/source/view/charttypes/BarChart.cxx @@ -20,6 +20,7 @@ #include "BarChart.hxx" #include "BarPositionHelper.hxx" +#include <ChartType.hxx> #include <ShapeFactory.hxx> #include <CommonConverters.hxx> #include <ObjectIdentifier.hxx> @@ -28,17 +29,13 @@ #include <Clipping.hxx> #include <DateHelper.hxx> #include <svx/scene3d.hxx> -#include <svx/unoshape.hxx> #include <comphelper/scopeguard.hxx> #include <com/sun/star/chart/DataLabelPlacement.hpp> -#include <com/sun/star/chart2/XTransformation.hpp> #include <com/sun/star/chart2/DataPointGeometry3D.hpp> #include <rtl/math.hxx> -#include <sal/log.hxx> -#include <tools/diagnose_ex.h> -#include <unordered_set> +#include <comphelper/diagnose_ex.hxx> namespace chart { @@ -46,20 +43,19 @@ using namespace ::com::sun::star; using namespace ::rtl::math; using namespace ::com::sun::star::chart2; -BarChart::BarChart( const uno::Reference<XChartType>& xChartTypeModel +BarChart::BarChart( const rtl::Reference<ChartType>& xChartTypeModel , sal_Int32 nDimensionCount ) : VSeriesPlotter( xChartTypeModel, nDimensionCount ) - , m_pMainPosHelper( new BarPositionHelper() ) { - PlotterBase::m_pPosHelper = m_pMainPosHelper.get(); - VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper.get(); + PlotterBase::m_pPosHelper = &m_aMainPosHelper; + VSeriesPlotter::m_pMainPosHelper = &m_aMainPosHelper; try { - if( m_xChartTypeModelProps.is() ) + if( m_xChartTypeModel.is() ) { - m_xChartTypeModelProps->getPropertyValue( "OverlapSequence" ) >>= m_aOverlapSequence; - m_xChartTypeModelProps->getPropertyValue( "GapwidthSequence" ) >>= m_aGapwidthSequence; + m_xChartTypeModel->getPropertyValue( "OverlapSequence" ) >>= m_aOverlapSequence; + m_xChartTypeModel->getPropertyValue( "GapwidthSequence" ) >>= m_aGapwidthSequence; } } catch( const uno::Exception& ) @@ -126,9 +122,7 @@ drawing::Direction3D BarChart::getPreferredDiagramAspectRatio() const } if( m_pMainPosHelper && m_pMainPosHelper->isSwapXAndY() ) { - double fTemp = aRet.DirectionX; - aRet.DirectionX = aRet.DirectionY; - aRet.DirectionY = fTemp; + std::swap(aRet.DirectionX, aRet.DirectionY); } } else @@ -292,12 +286,12 @@ awt::Point BarChart::getLabelScreenPositionAndAlignment( drawing::Position3D aScenePosition3D( pPosHelper-> transformScaledLogicToScene( fX, fY, fZ, true ) ); - return LabelPositionHelper(m_nDimension,m_xLogicTarget,m_pShapeFactory) + return LabelPositionHelper(m_nDimension,m_xLogicTarget) .transformSceneToScreenPosition( aScenePosition3D ); } -uno::Reference< drawing::XShape > BarChart::createDataPoint3D_Bar( - const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference< SvxShape > BarChart::createDataPoint3D_Bar( + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree , const uno::Reference< beans::XPropertySet >& xObjectProperties @@ -319,28 +313,28 @@ uno::Reference< drawing::XShape > BarChart::createDataPoint3D_Bar( TOOLS_WARN_EXCEPTION("chart2", "" ); } - uno::Reference< drawing::XShape > xShape; + rtl::Reference< SvxShape > xShape; switch( nGeometry3D ) { case DataPointGeometry3D::CYLINDER: - xShape = m_pShapeFactory->createCylinder( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree ); + xShape = ShapeFactory::createCylinder( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree ); break; case DataPointGeometry3D::CONE: - xShape = m_pShapeFactory->createCone( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree ); + xShape = ShapeFactory::createCone( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree ); break; case DataPointGeometry3D::PYRAMID: - xShape = m_pShapeFactory->createPyramid( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree>0 + xShape = ShapeFactory::createPyramid( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree>0 , xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); break; case DataPointGeometry3D::CUBOID: default: - xShape = m_pShapeFactory->createCube( xTarget, rPosition, rSize + xShape = ShapeFactory::createCube( xTarget, rPosition, rSize , nRotateZAngleHundredthDegree, xObjectProperties , PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), bRoundedEdges ); return xShape; } if( nGeometry3D != DataPointGeometry3D::PYRAMID ) - setMappedProperties( xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); + PropertyMapper::setMappedProperties( *xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); return xShape; } @@ -385,37 +379,13 @@ void BarChart::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, VSeriesPlotter::addSeries( std::move(pSeries), zSlot, xSlot, ySlot ); } -namespace { - -//better performance for big data -struct FormerBarPoint -{ - FormerBarPoint( double fX, double fUpperY, double fLowerY, double fZ ) - : m_fX(fX), m_fUpperY(fUpperY), m_fLowerY(fLowerY), m_fZ(fZ) - {} - FormerBarPoint() - { - ::rtl::math::setNan( &m_fX ); - ::rtl::math::setNan( &m_fUpperY ); - ::rtl::math::setNan( &m_fLowerY ); - ::rtl::math::setNan( &m_fZ ); - } - - double m_fX; - double m_fUpperY; - double m_fLowerY; - double m_fZ; -}; - -} - void BarChart::adaptOverlapAndGapwidthForGroupBarsPerAxis() { //adapt m_aOverlapSequence and m_aGapwidthSequence for the groupBarsPerAxis feature //thus the different series use the same settings VDataSeries* pFirstSeries = getFirstSeries(); - if(!(pFirstSeries && !pFirstSeries->getGroupBarsPerAxis()) ) + if(!pFirstSeries || pFirstSeries->getGroupBarsPerAxis()) return; sal_Int32 nAxisIndex = pFirstSeries->getAttachedAxisIndex(); @@ -423,33 +393,22 @@ void BarChart::adaptOverlapAndGapwidthForGroupBarsPerAxis() sal_Int32 nUseThisIndex = nAxisIndex; if( nUseThisIndex < 0 || nUseThisIndex >= m_aOverlapSequence.getLength() ) nUseThisIndex = 0; + auto aOverlapSequenceRange = asNonConstRange(m_aOverlapSequence); for( nN = 0; nN < m_aOverlapSequence.getLength(); nN++ ) { if(nN!=nUseThisIndex) - m_aOverlapSequence[nN] = m_aOverlapSequence[nUseThisIndex]; + aOverlapSequenceRange[nN] = m_aOverlapSequence[nUseThisIndex]; } nUseThisIndex = nAxisIndex; if( nUseThisIndex < 0 || nUseThisIndex >= m_aGapwidthSequence.getLength() ) nUseThisIndex = 0; + auto aGapwidthSequenceRange = asNonConstRange(m_aGapwidthSequence); for( nN = 0; nN < m_aGapwidthSequence.getLength(); nN++ ) { if(nN!=nUseThisIndex) - m_aGapwidthSequence[nN] = m_aGapwidthSequence[nUseThisIndex]; - } -} - -static E3dScene* lcl_getE3dScene(uno::Reference<uno::XInterface> const & xInterface) -{ - E3dScene* pScene = nullptr; - - SvxShape* pSvxShape = comphelper::getUnoTunnelImplementation<SvxShape>(xInterface); - if (pSvxShape) - { - SdrObject* pObject = pSvxShape->GetSdrObject(); - pScene = dynamic_cast<E3dScene*>(pObject); + aGapwidthSequenceRange[nN] = m_aGapwidthSequence[nUseThisIndex]; } - return pScene; } void BarChart::createShapes() @@ -457,8 +416,8 @@ void BarChart::createShapes() if( m_aZSlots.empty() ) //no series return; - OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"BarChart is not proper initialized"); - if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"BarChart is not proper initialized"); + if(!(m_xLogicTarget.is()&&m_xFinalTarget.is())) return; //the text labels should be always on top of the other series shapes @@ -468,33 +427,26 @@ void BarChart::createShapes() //the regression curves should always be on top of the bars but beneath the text labels //to achieve this the regression curve target is created after the series target and before the text target - uno::Reference< drawing::XShapes > xSeriesTarget( - createGroupShape( m_xLogicTarget )); - uno::Reference< drawing::XShapes > xRegressionCurveTarget( - createGroupShape( m_xLogicTarget )); - uno::Reference< drawing::XShapes > xTextTarget( - m_pShapeFactory->createGroup2D( m_xFinalTarget )); + rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget = createGroupShape( m_xLogicTarget ); + rtl::Reference<SvxShapeGroupAnyD> xRegressionCurveTarget = createGroupShape( m_xLogicTarget ); + rtl::Reference<SvxShapeGroupAnyD> xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget ); - uno::Reference< drawing::XShapes > xRegressionCurveEquationTarget( - m_pShapeFactory->createGroup2D( m_xFinalTarget )); + rtl::Reference<SvxShapeGroupAnyD> xRegressionCurveEquationTarget = + ShapeFactory::createGroup2D( m_xFinalTarget ); //check necessary here that different Y axis can not be stacked in the same group? ... hm? - double fLogicZ = 1.0;//as defined - bool bDrawConnectionLines = false; bool bDrawConnectionLinesInited = false; - bool bOnlyConnectionLinesForThisPoint = false; - std::unordered_set<uno::Reference<drawing::XShape>> aShapeSet; + std::unordered_set<rtl::Reference<SvxShape>> aShapeSet; const comphelper::ScopeGuard aGuard([aShapeSet]() { std::unordered_set<E3dScene*> aSceneSet; - for (uno::Reference<drawing::XShape> const & rShape : aShapeSet) + for (rtl::Reference<SvxShape> const & rShape : aShapeSet) { - E3dScene* pScene = lcl_getE3dScene(rShape); - if(nullptr != pScene) + if(E3dScene* pScene = DynCastE3dScene(rShape->GetSdrObject())) { aSceneSet.insert(pScene->getRootE3dSceneFromE3dObject()); } @@ -511,8 +463,6 @@ void BarChart::createShapes() //better performance for big data std::map< VDataSeries*, FormerBarPoint > aSeriesFormerPointMap; m_bPointsWereSkipped = false; - sal_Int32 nSkippedPoints = 0; - sal_Int32 nCreatedPoints = 0; sal_Int32 nStartIndex = 0; sal_Int32 nEndIndex = VSeriesPlotter::getPointCount(); @@ -526,8 +476,7 @@ void BarChart::createShapes() for( auto& rXSlot : rZSlot ) { sal_Int32 nAttachedAxisIndex = rXSlot.getAttachedAxisIndexForFirstSeries(); - if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() ) - aLogicYSumMap[nAttachedAxisIndex]=0.0; + aLogicYSumMap.insert({nAttachedAxisIndex, 0.0}); const sal_Int32 nSlotPoints = rXSlot.getPointCount(); if( nPointIndex >= nSlotPoints ) @@ -547,380 +496,9 @@ void BarChart::createShapes() sal_Int32 nZ=1; for( auto& rZSlot : m_aZSlots ) { - //iterate through all x slots in this category - double fSlotX=0; - for( auto& rXSlot : rZSlot ) - { - sal_Int32 nAttachedAxisIndex = rXSlot.getAttachedAxisIndexForFirstSeries(); - //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot - BarPositionHelper* pPosHelper = dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( nAttachedAxisIndex ) ) ); - if(!pPosHelper) - pPosHelper = m_pMainPosHelper.get(); - - PlotterBase::m_pPosHelper = pPosHelper; - - //update/create information for current group - pPosHelper->updateSeriesCount( rZSlot.size() ); - double fLogicBaseWidth = pPosHelper->getScaledSlotWidth(); - - // get distance from base value to maximum and minimum - - double fMinimumY = 0.0, fMaximumY = 0.0; - if( nPointIndex < rXSlot.getPointCount()) - rXSlot.calculateYMinAndMaxForCategory( nPointIndex - , isSeparateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex ); - - double fLogicPositiveYSum = 0.0; - if( !std::isnan( fMaximumY ) ) - fLogicPositiveYSum = fMaximumY; - - double fLogicNegativeYSum = 0.0; - if( !std::isnan( fMinimumY ) ) - fLogicNegativeYSum = fMinimumY; - - if( pPosHelper->isPercentY() ) - { - /* #i70395# fLogicPositiveYSum contains sum of all positive - values, if any, otherwise the highest negative value. - fLogicNegativeYSum contains sum of all negative values, - if any, otherwise the lowest positive value. - Afterwards, fLogicPositiveYSum will contain the maximum - (positive) value that is related to 100%. */ - - // do nothing if there are positive values only - if( fLogicNegativeYSum < 0.0 ) - { - // fLogicPositiveYSum<0 => negative values only, use absolute of negative sum - if( fLogicPositiveYSum < 0.0 ) - fLogicPositiveYSum = -fLogicNegativeYSum; - // otherwise there are positive and negative values, calculate total distance - else - fLogicPositiveYSum -= fLogicNegativeYSum; - } - fLogicNegativeYSum = 0.0; - } - - double fBaseValue = 0.0; - if( !pPosHelper->isPercentY() && rXSlot.m_aSeriesVector.size()<=1 ) - fBaseValue = pPosHelper->getBaseValueY(); - double fPositiveLogicYForNextSeries = fBaseValue; - double fNegativeLogicYForNextSeries = fBaseValue; - - //iterate through all series in this x slot - for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector ) - { - if(!pSeries) - continue; - - bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor"); - - bOnlyConnectionLinesForThisPoint = false; - - if(nPointIndex==nStartIndex)//do not create a regression line for each point - createRegressionCurvesShapes( *pSeries, xRegressionCurveTarget, xRegressionCurveEquationTarget, - m_pPosHelper->maySkipPointsInRegressionCalculation()); - - if( !bDrawConnectionLinesInited ) - { - bDrawConnectionLines = pSeries->getConnectBars(); - if( m_nDimension==3 ) - bDrawConnectionLines = false; - if( bDrawConnectionLines && rXSlot.m_aSeriesVector.size()==1 ) - { - //detect whether we have a stacked chart or not: - StackingDirection eDirection = pSeries->getStackingDirection(); - if( eDirection != StackingDirection_Y_STACKING ) - bDrawConnectionLines = false; - } - bDrawConnectionLinesInited = true; - } - - uno::Reference<drawing::XShapes> xSeriesGroupShape_Shapes(getSeriesGroupShape(pSeries.get(), xSeriesTarget)); - uno::Reference<drawing::XShape> xSeriesGroupShape(xSeriesGroupShape_Shapes, uno::UNO_QUERY); - // Suspend setting rects dirty for the duration of this call - aShapeSet.insert(xSeriesGroupShape); - E3dScene* pScene = lcl_getE3dScene(xSeriesGroupShape); - if (pScene) - pScene->SuspendReportingDirtyRects(); - - //collect data point information (logic coordinates, style ): - double fUnscaledLogicX = pSeries->getXValue( nPointIndex ); - fUnscaledLogicX = DateHelper::RasterizeDateValue( fUnscaledLogicX, m_aNullDate, m_nTimeResolution ); - if(std::isnan(fUnscaledLogicX)) - continue;//point not visible - if(fUnscaledLogicX<pPosHelper->getLogicMinX()) - continue;//point not visible - if(fUnscaledLogicX>pPosHelper->getLogicMaxX()) - continue;//point not visible - if(pPosHelper->isStrongLowerRequested(0) && fUnscaledLogicX==pPosHelper->getLogicMaxX()) - continue;//point not visible - double fLogicX = pPosHelper->getScaledSlotPos( fUnscaledLogicX, fSlotX ); - - double fLogicBarHeight = pSeries->getYValue( nPointIndex ); - if( std::isnan( fLogicBarHeight )) //no value at this category - continue; - - double fLogicValueForLabeDisplay = fLogicBarHeight; - fLogicBarHeight-=fBaseValue; - - if( pPosHelper->isPercentY() ) - { - if(fLogicPositiveYSum!=0.0) - fLogicBarHeight = fabs( fLogicBarHeight )/fLogicPositiveYSum; - else - fLogicBarHeight = 0.0; - } - - // tdf#114141 to draw the top of the zero height 3D bar - // we set a small positive value, here the smallest one for the type double (DBL_MIN) - if( fLogicBarHeight == 0.0 ) - fLogicBarHeight = DBL_MIN; - - //sort negative and positive values, to display them on different sides of the x axis - bool bPositive = fLogicBarHeight >= 0.0; - double fLowerYValue = bPositive ? fPositiveLogicYForNextSeries : fNegativeLogicYForNextSeries; - double fUpperYValue = fLowerYValue+fLogicBarHeight; - if( bPositive ) - fPositiveLogicYForNextSeries += fLogicBarHeight; - else - fNegativeLogicYForNextSeries += fLogicBarHeight; - - if(m_nDimension==3) - fLogicZ = nZ+0.5; - - drawing::Position3D aUnscaledLogicPosition( fUnscaledLogicX, fUpperYValue, fLogicZ ); - - //@todo ... start an iteration over the different breaks of the axis - //each subsystem may add an additional shape to form the whole point - //create a group shape for this point and add to the series shape: - // uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( createGroupShape(xSeriesGroupShape_Shapes) ); - // uno::Reference<drawing::XShape> xPointGroupShape_Shape = - // uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY ); - //as long as we do not iterate we do not need to create an additional group for each point - uno::Reference< beans::XPropertySet > xDataPointProperties( pSeries->getPropertiesOfPoint( nPointIndex ) ); - sal_Int32 nGeometry3D = DataPointGeometry3D::CUBOID; - if(m_nDimension==3) try - { - xDataPointProperties->getPropertyValue( "Geometry3D") >>= nGeometry3D; - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } - - //@todo iterate through all subsystems to create partial points - { - //@todo select a suitable PositionHelper for this subsystem - BarPositionHelper* pSubPosHelper = pPosHelper; - - double fUnclippedUpperYValue = fUpperYValue; - - //apply clipping to Y - if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) ) - { - if( bDrawConnectionLines ) - bOnlyConnectionLinesForThisPoint = true; - else - continue; - } - //@todo clipping of X and Z is not fully integrated so far, as there is a need to create different objects - - //apply scaling to Y before calculating width (necessary to maintain gradient in clipped objects) - pSubPosHelper->doLogicScaling(nullptr,&fLowerYValue,nullptr); - pSubPosHelper->doLogicScaling(nullptr,&fUpperYValue,nullptr); - //scaling of X and Z is not provided as the created objects should be symmetric in that dimensions - - pSubPosHelper->doLogicScaling(nullptr,&fUnclippedUpperYValue,nullptr); - - //calculate resulting width - double fCompleteHeight = bPositive ? fLogicPositiveYSum : fLogicNegativeYSum; - if( pPosHelper->isPercentY() ) - fCompleteHeight = 1.0; - double fLogicBarWidth = fLogicBaseWidth; - double fTopHeight=approxSub(fCompleteHeight,fUpperYValue); - if(!bPositive) - fTopHeight=approxSub(fCompleteHeight,fLowerYValue); - double fLogicYStart = bPositive ? fLowerYValue : fUpperYValue; - double fMiddleHeight = fUpperYValue-fLowerYValue; - if(!bPositive) - fMiddleHeight*=-1.0; - double fLogicBarDepth = 0.5; - if(m_nDimension==3) - { - if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 ) - { - double fHeight = fCompleteHeight-fLowerYValue; - if(!bPositive) - fHeight = fCompleteHeight-fUpperYValue; - fLogicBarWidth = fLogicBaseWidth*fHeight/fCompleteHeight; - if(fLogicBarWidth<=0.0) - fLogicBarWidth=fLogicBaseWidth; - fLogicBarDepth = fLogicBarDepth*fHeight/fCompleteHeight; - if(fLogicBarDepth<=0.0) - fLogicBarDepth*=-1.0; - } - } - - //better performance for big data - FormerBarPoint aFormerPoint( aSeriesFormerPointMap[pSeries.get()] ); - pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution ); - if( !pSeries->isAttributedDataPoint(nPointIndex) - && - pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fUpperY, aFormerPoint.m_fZ - , fLogicX, fUpperYValue, fLogicZ ) - && - pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fLowerY, aFormerPoint.m_fZ - , fLogicX, fLowerYValue, fLogicZ ) - ) - { - nSkippedPoints++; - m_bPointsWereSkipped = true; - continue; - } - aSeriesFormerPointMap[pSeries.get()] = FormerBarPoint(fLogicX,fUpperYValue,fLowerYValue,fLogicZ); - - if( bDrawConnectionLines ) - { - //store point information for connection lines - - drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ ); - drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ ); - - if( isValidPosition(aLeftUpperPoint) ) - AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aLeftUpperPoint ); - if( isValidPosition(aRightUpperPoint) ) - AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aRightUpperPoint ); - } - - if( bOnlyConnectionLinesForThisPoint ) - continue; - - //maybe additional possibility for performance improvement - //bool bCreateLineInsteadOfComplexGeometryDueToMissingSpace = false; - //pPosHelper->isSameForGivenResolution( fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ - // , fLogicX+fLogicBarWidth/2.0, fLowerYValue, fLogicZ ); - - nCreatedPoints++; - //create partial point - if( !approxEqual(fLowerYValue,fUpperYValue) ) - { - uno::Reference< drawing::XShape > xShape; - if( m_nDimension==3 ) - { - drawing::Position3D aLogicBottom (fLogicX,fLogicYStart,fLogicZ); - drawing::Position3D aLogicLeftBottomFront (fLogicX+fLogicBarWidth/2.0,fLogicYStart,fLogicZ-fLogicBarDepth/2.0); - drawing::Position3D aLogicRightDeepTop (fLogicX-fLogicBarWidth/2.0,fLogicYStart+fMiddleHeight,fLogicZ+fLogicBarDepth/2.0); - drawing::Position3D aLogicTopTop (fLogicX,fLogicYStart+fMiddleHeight+fTopHeight,fLogicZ); - - uno::Reference< XTransformation > xTransformation = pSubPosHelper->getTransformationScaledLogicToScene(); - - //transformation 3) -> 4) - drawing::Position3D aTransformedBottom ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicBottom) ) ) ); - drawing::Position3D aTransformedLeftBottomFront ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicLeftBottomFront) ) ) ); - drawing::Position3D aTransformedRightDeepTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicRightDeepTop) ) ) ); - drawing::Position3D aTransformedTopTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicTopTop) ) ) ); - - drawing::Direction3D aSize = aTransformedRightDeepTop - aTransformedLeftBottomFront; - drawing::Direction3D aTopSize( aTransformedTopTop - aTransformedRightDeepTop ); - fTopHeight = aTopSize.DirectionY; - - sal_Int32 nRotateZAngleHundredthDegree = 0; - if( pPosHelper->isSwapXAndY() ) - { - fTopHeight = aTopSize.DirectionX; - nRotateZAngleHundredthDegree = 90*100; - aSize = drawing::Direction3D(aSize.DirectionY,aSize.DirectionX,aSize.DirectionZ); - } - - if( aSize.DirectionX < 0 ) - aSize.DirectionX *= -1.0; - if( aSize.DirectionZ < 0 ) - aSize.DirectionZ *= -1.0; - if( fTopHeight < 0 ) - fTopHeight *= -1.0; - - xShape = createDataPoint3D_Bar( - xSeriesGroupShape_Shapes, aTransformedBottom, aSize, fTopHeight, nRotateZAngleHundredthDegree - , xDataPointProperties, nGeometry3D ); - } - else //m_nDimension!=3 - { - // performance improvement: alloc the sequence before the rendering - // otherwise we have 2 realloc calls - drawing::PolyPolygonShape3D aPoly; - aPoly.SequenceX.realloc(1); - aPoly.SequenceY.realloc(1); - aPoly.SequenceZ.realloc(1); - drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ ); - drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ ); - - AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) ); - AddPointToPoly( aPoly, drawing::Position3D( fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ) ); - AddPointToPoly( aPoly, aRightUpperPoint ); - AddPointToPoly( aPoly, aLeftUpperPoint ); - AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) ); - pPosHelper->transformScaledLogicToScene( aPoly ); - xShape = m_pShapeFactory->createArea2D( xSeriesGroupShape_Shapes, aPoly ); - setMappedProperties( xShape, xDataPointProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); - } - - if(bHasFillColorMapping) - { - double nPropVal = pSeries->getValueByProperty(nPointIndex, "FillColor"); - if(!std::isnan(nPropVal)) - { - uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW ); - xProps->setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>(nPropVal))); - } - } - //set name/classified ObjectID (CID) - ShapeFactory::setShapeName(xShape - , ObjectIdentifier::createPointCID( - pSeries->getPointCID_Stub(),nPointIndex) ); - } - - //create error bar - createErrorBar_Y( aUnscaledLogicPosition, *pSeries, nPointIndex, m_xLogicTarget, &fLogicX ); - - //create data point label - if( pSeries->getDataPointLabelIfLabel(nPointIndex) ) - { - double fLogicSum = aLogicYSumMap[nAttachedAxisIndex]; - - LabelAlignment eAlignment(LABEL_ALIGN_CENTER); - sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nPointIndex, m_xChartTypeModel, pPosHelper->isSwapXAndY() ); - - double fLowerBarDepth = fLogicBarDepth; - double fUpperBarDepth = fLogicBarDepth; - { - if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 ) - { - double fOuterBarDepth = fLogicBarDepth * fTopHeight/(fabs(fCompleteHeight)); - fLowerBarDepth = (fBaseValue < fUpperYValue) ? fabs(fLogicBarDepth) : fabs(fOuterBarDepth); - fUpperBarDepth = (fBaseValue < fUpperYValue) ? fabs(fOuterBarDepth) : fabs(fLogicBarDepth); - } - } - - awt::Point aScreenPosition2D = getLabelScreenPositionAndAlignment( - eAlignment, nLabelPlacement, fLogicX, fLowerYValue, fUpperYValue, fLogicZ, - fLowerBarDepth, fUpperBarDepth, fBaseValue, pPosHelper); - sal_Int32 nOffset = 0; - if(eAlignment!=LABEL_ALIGN_CENTER) - { - nOffset = 100;//add some spacing //@todo maybe get more intelligent values - if( m_nDimension == 3 ) - nOffset = 260; - } - createDataLabel( - xTextTarget, *pSeries, nPointIndex, - fLogicValueForLabeDisplay, fLogicSum, aScreenPosition2D, eAlignment, nOffset); - } - - }//end iteration through partial points - - }//next series in x slot (next y slot) - fSlotX+=1.0; - }//next x slot + doZSlot(bDrawConnectionLines, bDrawConnectionLinesInited, rZSlot, nZ, nPointIndex, nStartIndex, + xSeriesTarget, xRegressionCurveTarget, xRegressionCurveEquationTarget, xTextTarget, + aShapeSet, aSeriesFormerPointMap, aLogicYSumMap); ++nZ; }//next z slot }//next category @@ -928,14 +506,14 @@ void BarChart::createShapes() { for( auto const& rZSlot : m_aZSlots ) { - BarPositionHelper* pPosHelper = m_pMainPosHelper.get(); + BarPositionHelper* pPosHelper = &m_aMainPosHelper; if( !rZSlot.empty() ) { sal_Int32 nAttachedAxisIndex = rZSlot.front().getAttachedAxisIndexForFirstSeries(); //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot pPosHelper = dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( nAttachedAxisIndex ) ) ); if(!pPosHelper) - pPosHelper = m_pMainPosHelper.get(); + pPosHelper = &m_aMainPosHelper; } PlotterBase::m_pPosHelper = pPosHelper; @@ -947,11 +525,11 @@ void BarChart::createShapes() { if(!pSeries) continue; - drawing::PolyPolygonShape3D* pSeriesPoly = &pSeries->m_aPolyPolygonShape3D; + std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly = &pSeries->m_aPolyPolygonShape3D; if(!ShapeFactory::hasPolygonAnyLines(*pSeriesPoly)) continue; - drawing::PolyPolygonShape3D aPoly; + std::vector<std::vector<css::drawing::Position3D>> aPoly; Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly ); if(!ShapeFactory::hasPolygonAnyLines(aPoly)) @@ -960,12 +538,10 @@ void BarChart::createShapes() //transformation 3) -> 4) pPosHelper->transformScaledLogicToScene( aPoly ); - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes( + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes( getSeriesGroupShape(pSeries.get(), xSeriesTarget) ); - uno::Reference< drawing::XShape > xShape( m_pShapeFactory->createLine2D( - xSeriesGroupShape_Shapes, PolyToPointSequence( aPoly ) ) ); - setMappedProperties( xShape, pSeries->getPropertiesOfSeries() - , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); + rtl::Reference<SvxShapePolyPolygon> xShape( ShapeFactory::createLine2D( + xSeriesGroupShape_Shapes, aPoly ) ); } } } @@ -973,11 +549,420 @@ void BarChart::createShapes() /* @todo remove series shapes if empty */ +} + +void BarChart::doZSlot( + bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited, + const std::vector< VDataSeriesGroup >& rZSlot, + const sal_Int32 nZ, const sal_Int32 nPointIndex, const sal_Int32 nStartIndex, + const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, + std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet, + std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap, + std::map< sal_Int32, double >& aLogicYSumMap) +{ + //iterate through all x slots in this category + double fSlotX=0; + for( auto& rXSlot : rZSlot ) + { + sal_Int32 nAttachedAxisIndex = rXSlot.getAttachedAxisIndexForFirstSeries(); + //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot + BarPositionHelper* pPosHelper = dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( nAttachedAxisIndex ) ) ); + if(!pPosHelper) + pPosHelper = &m_aMainPosHelper; + + PlotterBase::m_pPosHelper = pPosHelper; + + //update/create information for current group + pPosHelper->updateSeriesCount( rZSlot.size() ); + double fLogicBaseWidth = pPosHelper->getScaledSlotWidth(); + + // get distance from base value to maximum and minimum + + double fMinimumY = 0.0, fMaximumY = 0.0; + if( nPointIndex < rXSlot.getPointCount()) + rXSlot.calculateYMinAndMaxForCategory( nPointIndex + , isSeparateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex ); + + double fLogicPositiveYSum = 0.0; + if( !std::isnan( fMaximumY ) ) + fLogicPositiveYSum = fMaximumY; + + double fLogicNegativeYSum = 0.0; + if( !std::isnan( fMinimumY ) ) + fLogicNegativeYSum = fMinimumY; + + if( pPosHelper->isPercentY() ) + { + /* #i70395# fLogicPositiveYSum contains sum of all positive + values, if any, otherwise the highest negative value. + fLogicNegativeYSum contains sum of all negative values, + if any, otherwise the lowest positive value. + Afterwards, fLogicPositiveYSum will contain the maximum + (positive) value that is related to 100%. */ + + // do nothing if there are positive values only + if( fLogicNegativeYSum < 0.0 ) + { + // fLogicPositiveYSum<0 => negative values only, use absolute of negative sum + if( fLogicPositiveYSum < 0.0 ) + fLogicPositiveYSum = -fLogicNegativeYSum; + // otherwise there are positive and negative values, calculate total distance + else + fLogicPositiveYSum -= fLogicNegativeYSum; + } + fLogicNegativeYSum = 0.0; + } + + doXSlot(rXSlot, bDrawConnectionLines, bDrawConnectionLinesInited, nZ, nPointIndex, nStartIndex, + xSeriesTarget, xRegressionCurveTarget, xRegressionCurveEquationTarget, xTextTarget, + aShapeSet, aSeriesFormerPointMap, aLogicYSumMap, + fLogicBaseWidth, fSlotX, pPosHelper, fLogicPositiveYSum, fLogicNegativeYSum, nAttachedAxisIndex); + + fSlotX+=1.0; + }//next x slot +} + + +void BarChart::doXSlot( + const VDataSeriesGroup& rXSlot, + bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited, + const sal_Int32 nZ, const sal_Int32 nPointIndex, const sal_Int32 nStartIndex, + const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, + std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet, + std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap, + std::map< sal_Int32, double >& aLogicYSumMap, + const double fLogicBaseWidth, const double fSlotX, + BarPositionHelper* const pPosHelper, + const double fLogicPositiveYSum, const double fLogicNegativeYSum, + const sal_Int32 nAttachedAxisIndex) +{ + double fBaseValue = 0.0; + if( !pPosHelper->isPercentY() && rXSlot.m_aSeriesVector.size()<=1 ) + fBaseValue = pPosHelper->getBaseValueY(); + double fPositiveLogicYForNextSeries = fBaseValue; + double fNegativeLogicYForNextSeries = fBaseValue; + + //iterate through all series in this x slot + for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector ) + { + if(!pSeries) + continue; + + bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor"); + + bool bOnlyConnectionLinesForThisPoint = false; + + if(nPointIndex==nStartIndex)//do not create a regression line for each point + createRegressionCurvesShapes( *pSeries, xRegressionCurveTarget, xRegressionCurveEquationTarget, + m_pPosHelper->maySkipPointsInRegressionCalculation()); + + if( !bDrawConnectionLinesInited ) + { + bDrawConnectionLines = pSeries->getConnectBars(); + if( m_nDimension==3 ) + bDrawConnectionLines = false; + if( bDrawConnectionLines && rXSlot.m_aSeriesVector.size()==1 ) + { + //detect whether we have a stacked chart or not: + StackingDirection eDirection = pSeries->getStackingDirection(); + if( eDirection != StackingDirection_Y_STACKING ) + bDrawConnectionLines = false; + } + bDrawConnectionLinesInited = true; + } + + // Use another XShapes for background, so we can avoid needing to set the Z-order on all of them, + // which is expensive in bulk. + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes(getSeriesGroupShape(pSeries.get(), xSeriesTarget)); + rtl::Reference<SvxShapeGroupAnyD> xSeriesBackgroundShape_Shapes(getSeriesGroupShape(pSeries.get(), xSeriesTarget)); + aShapeSet.insert(xSeriesGroupShape_Shapes); + aShapeSet.insert(xSeriesBackgroundShape_Shapes); + // Suspend setting rects dirty for the duration of this call + E3dScene* pScene = DynCastE3dScene(xSeriesGroupShape_Shapes->GetSdrObject()); + if (pScene) + pScene->SuspendReportingDirtyRects(); + pScene = DynCastE3dScene(xSeriesBackgroundShape_Shapes->GetSdrObject()); + if (pScene) + pScene->SuspendReportingDirtyRects(); + + //collect data point information (logic coordinates, style ): + double fUnscaledLogicX = pSeries->getXValue( nPointIndex ); + fUnscaledLogicX = DateHelper::RasterizeDateValue( fUnscaledLogicX, m_aNullDate, m_nTimeResolution ); + if(std::isnan(fUnscaledLogicX)) + continue;//point not visible + if(fUnscaledLogicX<pPosHelper->getLogicMinX()) + continue;//point not visible + if(fUnscaledLogicX>pPosHelper->getLogicMaxX()) + continue;//point not visible + if(pPosHelper->isStrongLowerRequested(0) && fUnscaledLogicX==pPosHelper->getLogicMaxX()) + continue;//point not visible + double fLogicX = pPosHelper->getScaledSlotPos( fUnscaledLogicX, fSlotX ); + + double fLogicBarHeight = pSeries->getYValue( nPointIndex ); + if( std::isnan( fLogicBarHeight )) //no value at this category + continue; + + double fLogicValueForLabeDisplay = fLogicBarHeight; + fLogicBarHeight-=fBaseValue; + + if( pPosHelper->isPercentY() ) + { + if(fLogicPositiveYSum!=0.0) + fLogicBarHeight = fabs( fLogicBarHeight )/fLogicPositiveYSum; + else + fLogicBarHeight = 0.0; + } + + // tdf#114141 to draw the top of the zero height 3D bar + // we set a small positive value, here the smallest one for the type double (DBL_MIN) + if( fLogicBarHeight == 0.0 ) + fLogicBarHeight = DBL_MIN; + + //sort negative and positive values, to display them on different sides of the x axis + bool bPositive = fLogicBarHeight >= 0.0; + double fLowerYValue = bPositive ? fPositiveLogicYForNextSeries : fNegativeLogicYForNextSeries; + double fUpperYValue = fLowerYValue+fLogicBarHeight; + if( bPositive ) + fPositiveLogicYForNextSeries += fLogicBarHeight; + else + fNegativeLogicYForNextSeries += fLogicBarHeight; + + double fLogicZ = 1.0;//as defined + if(m_nDimension==3) + fLogicZ = nZ+0.5; + + drawing::Position3D aUnscaledLogicPosition( fUnscaledLogicX, fUpperYValue, fLogicZ ); + + //@todo ... start an iteration over the different breaks of the axis + //each subsystem may add an additional shape to form the whole point + //create a group shape for this point and add to the series shape: +// uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( createGroupShape(xSeriesGroupShape_Shapes) ); +// uno::Reference<drawing::XShape> xPointGroupShape_Shape = +// uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY ); + //as long as we do not iterate we do not need to create an additional group for each point + uno::Reference< beans::XPropertySet > xDataPointProperties( pSeries->getPropertiesOfPoint( nPointIndex ) ); + sal_Int32 nGeometry3D = DataPointGeometry3D::CUBOID; + if(m_nDimension==3) try + { + xDataPointProperties->getPropertyValue( "Geometry3D") >>= nGeometry3D; + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + + //@todo iterate through all subsystems to create partial points + { + //@todo select a suitable PositionHelper for this subsystem + BarPositionHelper* pSubPosHelper = pPosHelper; + + double fUnclippedUpperYValue = fUpperYValue; + + //apply clipping to Y + if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) ) + { + if( bDrawConnectionLines ) + bOnlyConnectionLinesForThisPoint = true; + else + continue; + } + //@todo clipping of X and Z is not fully integrated so far, as there is a need to create different objects + + //apply scaling to Y before calculating width (necessary to maintain gradient in clipped objects) + pSubPosHelper->doLogicScaling(nullptr,&fLowerYValue,nullptr); + pSubPosHelper->doLogicScaling(nullptr,&fUpperYValue,nullptr); + //scaling of X and Z is not provided as the created objects should be symmetric in that dimensions + + pSubPosHelper->doLogicScaling(nullptr,&fUnclippedUpperYValue,nullptr); + + //calculate resulting width + double fCompleteHeight = bPositive ? fLogicPositiveYSum : fLogicNegativeYSum; + if( pPosHelper->isPercentY() ) + fCompleteHeight = 1.0; + double fLogicBarWidth = fLogicBaseWidth; + double fTopHeight=approxSub(fCompleteHeight,fUpperYValue); + if(!bPositive) + fTopHeight=approxSub(fCompleteHeight,fLowerYValue); + double fLogicYStart = bPositive ? fLowerYValue : fUpperYValue; + double fMiddleHeight = fUpperYValue-fLowerYValue; + if(!bPositive) + fMiddleHeight*=-1.0; + double fLogicBarDepth = 0.5; + if(m_nDimension==3) + { + if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 ) + { + double fHeight = fCompleteHeight-fLowerYValue; + if(!bPositive) + fHeight = fCompleteHeight-fUpperYValue; + fLogicBarWidth = fLogicBaseWidth*fHeight/fCompleteHeight; + if(fLogicBarWidth<=0.0) + fLogicBarWidth=fLogicBaseWidth; + fLogicBarDepth = fLogicBarDepth*fHeight/fCompleteHeight; + if(fLogicBarDepth<=0.0) + fLogicBarDepth*=-1.0; + } + } + + //better performance for big data + FormerBarPoint aFormerPoint( aSeriesFormerPointMap[pSeries.get()] ); + pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution ); + if( !pSeries->isAttributedDataPoint(nPointIndex) + && + pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fUpperY, aFormerPoint.m_fZ + , fLogicX, fUpperYValue, fLogicZ ) + && + pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fLowerY, aFormerPoint.m_fZ + , fLogicX, fLowerYValue, fLogicZ ) + ) + { + m_bPointsWereSkipped = true; + continue; + } + aSeriesFormerPointMap[pSeries.get()] = FormerBarPoint(fLogicX,fUpperYValue,fLowerYValue,fLogicZ); + + if( bDrawConnectionLines ) + { + //store point information for connection lines + + drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ ); + drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ ); + + if( isValidPosition(aLeftUpperPoint) ) + AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aLeftUpperPoint ); + if( isValidPosition(aRightUpperPoint) ) + AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aRightUpperPoint ); + } + + if( bOnlyConnectionLinesForThisPoint ) + continue; + + //maybe additional possibility for performance improvement + //bool bCreateLineInsteadOfComplexGeometryDueToMissingSpace = false; + //pPosHelper->isSameForGivenResolution( fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ + // , fLogicX+fLogicBarWidth/2.0, fLowerYValue, fLogicZ ); + + //create partial point + if( !approxEqual(fLowerYValue,fUpperYValue) ) + { + rtl::Reference< SvxShape > xShape; + if( m_nDimension==3 ) + { + drawing::Position3D aLogicBottom (fLogicX,fLogicYStart,fLogicZ); + drawing::Position3D aLogicLeftBottomFront (fLogicX+fLogicBarWidth/2.0,fLogicYStart,fLogicZ-fLogicBarDepth/2.0); + drawing::Position3D aLogicRightDeepTop (fLogicX-fLogicBarWidth/2.0,fLogicYStart+fMiddleHeight,fLogicZ+fLogicBarDepth/2.0); + drawing::Position3D aLogicTopTop (fLogicX,fLogicYStart+fMiddleHeight+fTopHeight,fLogicZ); + + ::chart::XTransformation2* pTransformation = pSubPosHelper->getTransformationScaledLogicToScene(); + + //transformation 3) -> 4) + drawing::Position3D aTransformedBottom ( pTransformation->transform( aLogicBottom ) ); + drawing::Position3D aTransformedLeftBottomFront ( pTransformation->transform( aLogicLeftBottomFront ) ); + drawing::Position3D aTransformedRightDeepTop ( pTransformation->transform( aLogicRightDeepTop ) ); + drawing::Position3D aTransformedTopTop ( pTransformation->transform( aLogicTopTop ) ); + + drawing::Direction3D aSize = aTransformedRightDeepTop - aTransformedLeftBottomFront; + drawing::Direction3D aTopSize( aTransformedTopTop - aTransformedRightDeepTop ); + fTopHeight = aTopSize.DirectionY; + + sal_Int32 nRotateZAngleHundredthDegree = 0; + if( pPosHelper->isSwapXAndY() ) + { + fTopHeight = aTopSize.DirectionX; + nRotateZAngleHundredthDegree = 90*100; + aSize = drawing::Direction3D(aSize.DirectionY,aSize.DirectionX,aSize.DirectionZ); + } + + if( aSize.DirectionX < 0 ) + aSize.DirectionX *= -1.0; + if( aSize.DirectionZ < 0 ) + aSize.DirectionZ *= -1.0; + if( fTopHeight < 0 ) + fTopHeight *= -1.0; + + xShape = createDataPoint3D_Bar( + xSeriesGroupShape_Shapes, aTransformedBottom, aSize, fTopHeight, nRotateZAngleHundredthDegree + , xDataPointProperties, nGeometry3D ); + } + else //m_nDimension!=3 + { + drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ ); + drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ ); + std::vector<std::vector<css::drawing::Position3D>> aPoly + { + { // inner vector + drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ), + drawing::Position3D( fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ), + aRightUpperPoint, + aLeftUpperPoint, + drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) + } + }; + pPosHelper->transformScaledLogicToScene( aPoly ); + xShape = ShapeFactory::createArea2D( xSeriesGroupShape_Shapes, aPoly ); + PropertyMapper::setMappedProperties( *xShape, xDataPointProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); + } + + if(bHasFillColorMapping) + { + double nPropVal = pSeries->getValueByProperty(nPointIndex, "FillColor"); + if(!std::isnan(nPropVal)) + { + xShape->setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>(nPropVal))); + } + } + //set name/classified ObjectID (CID) + ShapeFactory::setShapeName(xShape + , ObjectIdentifier::createPointCID( + pSeries->getPointCID_Stub(),nPointIndex) ); + } + + //create error bar + createErrorBar_Y( aUnscaledLogicPosition, *pSeries, nPointIndex, m_xLogicTarget, &fLogicX ); + + //create data point label + if( pSeries->getDataPointLabelIfLabel(nPointIndex) ) + { + double fLogicSum = aLogicYSumMap[nAttachedAxisIndex]; + + LabelAlignment eAlignment(LABEL_ALIGN_CENTER); + sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nPointIndex, m_xChartTypeModel, pPosHelper->isSwapXAndY() ); + + double fLowerBarDepth = fLogicBarDepth; + double fUpperBarDepth = fLogicBarDepth; + { + if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 ) + { + double fOuterBarDepth = fLogicBarDepth * fTopHeight/(fabs(fCompleteHeight)); + fLowerBarDepth = (fBaseValue < fUpperYValue) ? fabs(fLogicBarDepth) : fabs(fOuterBarDepth); + fUpperBarDepth = (fBaseValue < fUpperYValue) ? fabs(fOuterBarDepth) : fabs(fLogicBarDepth); + } + } + + awt::Point aScreenPosition2D = getLabelScreenPositionAndAlignment( + eAlignment, nLabelPlacement, fLogicX, fLowerYValue, fUpperYValue, fLogicZ, + fLowerBarDepth, fUpperBarDepth, fBaseValue, pPosHelper); + sal_Int32 nOffset = 0; + if(eAlignment!=LABEL_ALIGN_CENTER) + { + nOffset = 100;//add some spacing //@todo maybe get more intelligent values + if( m_nDimension == 3 ) + nOffset = 260; + } + createDataLabel( + xTextTarget, *pSeries, nPointIndex, + fLogicValueForLabeDisplay, fLogicSum, aScreenPosition2D, eAlignment, nOffset); + } + + }//end iteration through partial points - SAL_INFO( - "chart2", - "skipped points: " << nSkippedPoints << " created points: " - << nCreatedPoints); + }//next series in x slot (next y slot) } } //namespace chart diff --git a/chart2/source/view/charttypes/BarChart.hxx b/chart2/source/view/charttypes/BarChart.hxx index ed4457affb71..ff46786afcbb 100644 --- a/chart2/source/view/charttypes/BarChart.hxx +++ b/chart2/source/view/charttypes/BarChart.hxx @@ -17,15 +17,14 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BARCHART_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BARCHART_HXX +#pragma once #include <memory> #include <VSeriesPlotter.hxx> +#include "BarPositionHelper.hxx" namespace chart { -class BarPositionHelper; class BarChart : public VSeriesPlotter { @@ -33,7 +32,7 @@ class BarChart : public VSeriesPlotter public: BarChart() = delete; - BarChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + BarChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel , sal_Int32 nDimensionCount ); virtual ~BarChart() override; @@ -43,9 +42,9 @@ public: virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override; private: //methods - css::uno::Reference< css::drawing::XShape > + static rtl::Reference< SvxShape > createDataPoint3D_Bar( - const css::uno::Reference< css::drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPosition , const css::drawing::Direction3D& rSize , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree @@ -62,12 +61,58 @@ private: //methods void adaptOverlapAndGapwidthForGroupBarsPerAxis(); + //better performance for big data + struct FormerBarPoint + { + FormerBarPoint( double fX, double fUpperY, double fLowerY, double fZ ) + : m_fX(fX), m_fUpperY(fUpperY), m_fLowerY(fLowerY), m_fZ(fZ) + {} + FormerBarPoint() + : m_fX(std::numeric_limits<double>::quiet_NaN()) + , m_fUpperY(std::numeric_limits<double>::quiet_NaN()) + , m_fLowerY(std::numeric_limits<double>::quiet_NaN()) + , m_fZ(std::numeric_limits<double>::quiet_NaN()) + { + } + + double m_fX; + double m_fUpperY; + double m_fLowerY; + double m_fZ; + }; + + void doZSlot( + bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited, const std::vector< VDataSeriesGroup >& rZSlot, + sal_Int32 nZ, sal_Int32 nPointIndex, sal_Int32 nStartIndex, + const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, + std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet, + std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap, + std::map< sal_Int32, double >& aLogicYSumMap); + + void doXSlot( + const VDataSeriesGroup& rXSlot, + bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited, + sal_Int32 nZ, sal_Int32 nPointIndex, sal_Int32 nStartIndex, + const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, + std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet, + std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap, + std::map< sal_Int32, double >& aLogicYSumMap, + double fLogicBaseWidth, double fSlotX, + BarPositionHelper* const pPosHelper, + double fLogicPositiveYSum, double fLogicNegativeYSum, + sal_Int32 nAttachedAxisIndex); + private: //member - std::unique_ptr<BarPositionHelper> m_pMainPosHelper; + BarPositionHelper m_aMainPosHelper; css::uno::Sequence< sal_Int32 > m_aOverlapSequence; css::uno::Sequence< sal_Int32 > m_aGapwidthSequence; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/BarPositionHelper.cxx b/chart2/source/view/charttypes/BarPositionHelper.cxx index f8ac3e7d62ef..279d998a02e4 100644 --- a/chart2/source/view/charttypes/BarPositionHelper.cxx +++ b/chart2/source/view/charttypes/BarPositionHelper.cxx @@ -23,7 +23,6 @@ namespace chart { using namespace ::com::sun::star; -using namespace ::com::sun::star::chart2; BarPositionHelper::BarPositionHelper() : CategoryPositionHelper( 1 ) diff --git a/chart2/source/view/charttypes/BarPositionHelper.hxx b/chart2/source/view/charttypes/BarPositionHelper.hxx index e63fa883708e..961ea988f604 100644 --- a/chart2/source/view/charttypes/BarPositionHelper.hxx +++ b/chart2/source/view/charttypes/BarPositionHelper.hxx @@ -17,31 +17,28 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BARPOSITIONHELPER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BARPOSITIONHELPER_HXX +#pragma once #include <PlottingPositionHelper.hxx> #include "CategoryPositionHelper.hxx" namespace chart { - class BarPositionHelper : public CategoryPositionHelper, public PlottingPositionHelper { public: explicit BarPositionHelper(); - BarPositionHelper( const BarPositionHelper& rSource ); + BarPositionHelper(const BarPositionHelper& rSource); virtual ~BarPositionHelper() override; virtual std::unique_ptr<PlottingPositionHelper> clone() const override; - void updateSeriesCount( double fSeriesCount ); /*only enter the size of x stacked series*/ + void updateSeriesCount(double fSeriesCount); /*only enter the size of x stacked series*/ - virtual double getScaledSlotPos( double fCategoryX, double fSeriesNumber ) const override; - virtual void setScaledCategoryWidth( double fScaledCategoryWidth ) override; + virtual double getScaledSlotPos(double fCategoryX, double fSeriesNumber) const override; + virtual void setScaledCategoryWidth(double fScaledCategoryWidth) override; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/BubbleChart.cxx b/chart2/source/view/charttypes/BubbleChart.cxx index 9ad349b9f455..d5bd2c3a16fc 100644 --- a/chart2/source/view/charttypes/BubbleChart.cxx +++ b/chart2/source/view/charttypes/BubbleChart.cxx @@ -22,21 +22,19 @@ #include <ShapeFactory.hxx> #include <ObjectIdentifier.hxx> #include <LabelPositionHelper.hxx> +#include <ChartType.hxx> #include <com/sun/star/chart/DataLabelPlacement.hpp> -#include <rtl/math.hxx> #include <sal/log.hxx> #include <osl/diagnose.h> -#include <com/sun/star/drawing/XShapes.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> + +#include <limits> namespace chart { using namespace ::com::sun::star; -using namespace ::rtl::math; -using namespace ::com::sun::star::chart2; -BubbleChart::BubbleChart( const uno::Reference<XChartType>& xChartTypeModel +BubbleChart::BubbleChart( const rtl::Reference<ChartType>& xChartTypeModel , sal_Int32 nDimensionCount ) : VSeriesPlotter( xChartTypeModel, nDimensionCount, false ) , m_fMaxLogicBubbleSize( 0.0 ) @@ -88,8 +86,8 @@ void BubbleChart::calculateBubbleSizeScalingFactor() drawing::Position3D aSceneMinPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMinX(),m_pMainPosHelper->getLogicMinY(),fLogicZ, false ) ); drawing::Position3D aSceneMaxPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMaxX(),m_pMainPosHelper->getLogicMaxY(),fLogicZ, false ) ); - awt::Point aScreenMinPos( LabelPositionHelper(m_nDimension,m_xLogicTarget,m_pShapeFactory).transformSceneToScreenPosition( aSceneMinPos ) ); - awt::Point aScreenMaxPos( LabelPositionHelper(m_nDimension,m_xLogicTarget,m_pShapeFactory).transformSceneToScreenPosition( aSceneMaxPos ) ); + awt::Point aScreenMinPos( LabelPositionHelper(m_nDimension,m_xLogicTarget).transformSceneToScreenPosition( aSceneMinPos ) ); + awt::Point aScreenMaxPos( LabelPositionHelper(m_nDimension,m_xLogicTarget).transformSceneToScreenPosition( aSceneMaxPos ) ); sal_Int32 nWidth = abs( aScreenMaxPos.X - aScreenMinPos.X ); sal_Int32 nHeight = abs( aScreenMaxPos.Y - aScreenMinPos.Y ); @@ -107,8 +105,8 @@ drawing::Direction3D BubbleChart::transformToScreenBubbleSize( double fLogicSize double fMaxSize = m_fMaxLogicBubbleSize; - double fMaxRadius = sqrt( fMaxSize / F_PI ); - double fRadius = sqrt( fLogicSize / F_PI ); + double fMaxRadius = sqrt( fMaxSize / M_PI ); + double fRadius = sqrt( fLogicSize / M_PI ); aRet.DirectionX = m_fBubbleSizeFactorToScreen * fRadius / fMaxRadius; aRet.DirectionY = aRet.DirectionX; @@ -145,10 +143,10 @@ struct FormerPoint : m_fX(fX), m_fY(fY), m_fZ(fZ) {} FormerPoint() + : m_fX(std::numeric_limits<double>::quiet_NaN()) + , m_fY(std::numeric_limits<double>::quiet_NaN()) + , m_fZ(std::numeric_limits<double>::quiet_NaN()) { - ::rtl::math::setNan( &m_fX ); - ::rtl::math::setNan( &m_fY ); - ::rtl::math::setNan( &m_fZ ); } double m_fX; @@ -163,16 +161,14 @@ void BubbleChart::createShapes() if( m_aZSlots.empty() ) //no series return; - OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"BubbleChart is not proper initialized"); - if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"BubbleChart is not proper initialized"); + if(!(m_xLogicTarget.is()&&m_xFinalTarget.is())) return; //therefore create an own group for the texts and the error bars to move them to front //(because the text group is created after the series group the texts are displayed on top) - uno::Reference< drawing::XShapes > xSeriesTarget( - createGroupShape( m_xLogicTarget )); - uno::Reference< drawing::XShapes > xTextTarget( - m_pShapeFactory->createGroup2D( m_xFinalTarget )); + rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget = createGroupShape( m_xLogicTarget ); + rtl::Reference< SvxShapeGroup > xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget ); //update/create information for current group double fLogicZ = 1.0;//as defined @@ -209,7 +205,7 @@ void BubbleChart::createShapes() bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor"); bool bHasBorderColorMapping = pSeries->hasPropertyMapping("LineColor"); - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries.get(), xSeriesTarget); + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries.get(), xSeriesTarget); sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex(); PlottingPositionHelper& rPosHelper @@ -263,19 +259,18 @@ void BubbleChart::createShapes() //create a group shape for this point and add to the series shape: OUString aPointCID = ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), nIndex ); - uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( + rtl::Reference<SvxShapeGroupAnyD> xPointGroupShape_Shapes( createGroupShape(xSeriesGroupShape_Shapes,aPointCID) ); - uno::Reference<drawing::XShape> xPointGroupShape_Shape( xPointGroupShape_Shapes, uno::UNO_QUERY ); { nCreatedPoints++; //create data point drawing::Direction3D aSymbolSize = transformToScreenBubbleSize( fBubbleSize ); - uno::Reference<drawing::XShape> xShape = m_pShapeFactory->createCircle2D( xPointGroupShape_Shapes + rtl::Reference<SvxShapeCircle> xShape = ShapeFactory::createCircle2D( xPointGroupShape_Shapes , aScenePosition, aSymbolSize ); - setMappedProperties( xShape + PropertyMapper::setMappedProperties( *xShape , pSeries->getPropertiesOfPoint( nIndex ) , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); @@ -284,8 +279,7 @@ void BubbleChart::createShapes() double nPropVal = pSeries->getValueByProperty(nIndex, "FillColor"); if(!std::isnan(nPropVal)) { - uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW ); - xProps->setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>(nPropVal))); + xShape->SvxShape::setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>(nPropVal))); } } if(bHasBorderColorMapping) @@ -293,8 +287,7 @@ void BubbleChart::createShapes() double nPropVal = pSeries->getValueByProperty(nIndex, "LineColor"); if(!std::isnan(nPropVal)) { - uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW ); - xProps->setPropertyValue("LineColor", uno::Any(static_cast<sal_Int32>(nPropVal))); + xShape->SvxShape::setPropertyValue("LineColor", uno::Any(static_cast<sal_Int32>(nPropVal))); } } @@ -339,7 +332,7 @@ void BubbleChart::createShapes() break; } - awt::Point aScreenPosition2D( LabelPositionHelper(m_nDimension,m_xLogicTarget,m_pShapeFactory) + awt::Point aScreenPosition2D( LabelPositionHelper(m_nDimension,m_xLogicTarget) .transformSceneToScreenPosition( aScenePosition3D ) ); sal_Int32 nOffset = 0; if(eAlignment!=LABEL_ALIGN_CENTER) @@ -351,7 +344,7 @@ void BubbleChart::createShapes() //remove PointGroupShape if empty if(!xPointGroupShape_Shapes->getCount()) - xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape); + xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shapes); }//next series in x slot (next y slot) }//next x slot diff --git a/chart2/source/view/charttypes/BubbleChart.hxx b/chart2/source/view/charttypes/BubbleChart.hxx index a4e9f7a75621..c25e5b6345bf 100644 --- a/chart2/source/view/charttypes/BubbleChart.hxx +++ b/chart2/source/view/charttypes/BubbleChart.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BUBBLECHART_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_BUBBLECHART_HXX +#pragma once #include <VSeriesPlotter.hxx> #include <com/sun/star/drawing/Direction3D.hpp> @@ -31,7 +30,7 @@ class BubbleChart : public VSeriesPlotter public: BubbleChart() = delete; - BubbleChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + BubbleChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel , sal_Int32 nDimensionCount ); virtual ~BubbleChart() override; @@ -57,6 +56,5 @@ private: //member double m_fBubbleSizeFactorToScreen;//calculated values }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/CandleStickChart.cxx b/chart2/source/view/charttypes/CandleStickChart.cxx index a82c8896592b..5f3a19582e12 100644 --- a/chart2/source/view/charttypes/CandleStickChart.cxx +++ b/chart2/source/view/charttypes/CandleStickChart.cxx @@ -18,6 +18,7 @@ */ #include "CandleStickChart.hxx" +#include <ChartType.hxx> #include <ShapeFactory.hxx> #include <CommonConverters.hxx> #include <ExplicitCategoriesProvider.hxx> @@ -25,23 +26,19 @@ #include "BarPositionHelper.hxx" #include <DateHelper.hxx> #include <com/sun/star/beans/XPropertySet.hpp> -#include <com/sun/star/drawing/XShape.hpp> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <osl/diagnose.h> namespace chart { using namespace ::com::sun::star; -using namespace ::rtl::math; -using namespace ::com::sun::star::chart2; -CandleStickChart::CandleStickChart( const uno::Reference<XChartType>& xChartTypeModel +CandleStickChart::CandleStickChart( const rtl::Reference<ChartType>& xChartTypeModel , sal_Int32 nDimensionCount ) : VSeriesPlotter( xChartTypeModel, nDimensionCount ) - , m_pMainPosHelper( new BarPositionHelper() ) { - PlotterBase::m_pPosHelper = m_pMainPosHelper.get(); - VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper.get(); + PlotterBase::m_pPosHelper = &m_aMainPosHelper; + VSeriesPlotter::m_pMainPosHelper = &m_aMainPosHelper; } CandleStickChart::~CandleStickChart() @@ -79,24 +76,24 @@ void CandleStickChart::createShapes() if( m_nDimension!=2 ) return; - OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"CandleStickChart is not proper initialized"); - if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"CandleStickChart is not proper initialized"); + if(!(m_xLogicTarget.is()&&m_xFinalTarget.is())) return; //the text labels should be always on top of the other series shapes //therefore create an own group for the texts to move them to front //(because the text group is created after the series group the texts are displayed on top) - uno::Reference< drawing::XShapes > xSeriesTarget( - createGroupShape( m_xLogicTarget )); - uno::Reference< drawing::XShapes > xLossTarget( + rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget = + createGroupShape( m_xLogicTarget ); + rtl::Reference<SvxShapeGroupAnyD> xLossTarget = createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier( - OBJECTTYPE_DATA_STOCK_LOSS, OUString() ))); - uno::Reference< drawing::XShapes > xGainTarget( + OBJECTTYPE_DATA_STOCK_LOSS, u"" )); + rtl::Reference<SvxShapeGroupAnyD> xGainTarget = createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier( - OBJECTTYPE_DATA_STOCK_GAIN, OUString() ))); - uno::Reference< drawing::XShapes > xTextTarget( - m_pShapeFactory->createGroup2D( m_xFinalTarget )); + OBJECTTYPE_DATA_STOCK_GAIN, u"" )); + rtl::Reference< SvxShapeGroup > xTextTarget = + ShapeFactory::createGroup2D( m_xFinalTarget ); //check necessary here that different Y axis can not be stacked in the same group? ... hm? @@ -106,15 +103,15 @@ void CandleStickChart::createShapes() tAnySequence aWhiteBox_Values, aBlackBox_Values; try { - if( m_xChartTypeModelProps.is() ) + if( m_xChartTypeModel.is() ) { - m_xChartTypeModelProps->getPropertyValue( "ShowFirst" ) >>= bShowFirst; + m_xChartTypeModel->getPropertyValue( "ShowFirst" ) >>= bShowFirst; uno::Reference< beans::XPropertySet > xWhiteDayProps; uno::Reference< beans::XPropertySet > xBlackDayProps; - m_xChartTypeModelProps->getPropertyValue( "Japanese" ) >>= bJapaneseStyle; - m_xChartTypeModelProps->getPropertyValue( "WhiteDay" ) >>= xWhiteDayProps; - m_xChartTypeModelProps->getPropertyValue( "BlackDay" ) >>= xBlackDayProps; + m_xChartTypeModel->getPropertyValue( "Japanese" ) >>= bJapaneseStyle; + m_xChartTypeModel->getPropertyValue( "WhiteDay" ) >>= xWhiteDayProps; + m_xChartTypeModel->getPropertyValue( "BlackDay" ) >>= xBlackDayProps; tPropertyNameValueMap aWhiteBox_Map; PropertyMapper::getValueMap( aWhiteBox_Map, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xWhiteDayProps ); @@ -138,15 +135,14 @@ void CandleStickChart::createShapes() { for( auto const& rZSlot : m_aZSlots ) { - sal_Int32 nAttachedAxisIndex = 0; - BarPositionHelper* pPosHelper = m_pMainPosHelper.get(); + BarPositionHelper* pPosHelper = &m_aMainPosHelper; if( !rZSlot.empty() ) { - nAttachedAxisIndex = rZSlot.front().getAttachedAxisIndexForFirstSeries(); + sal_Int32 nAttachedAxisIndex = rZSlot.front().getAttachedAxisIndexForFirstSeries(); //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot pPosHelper = dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( nAttachedAxisIndex ) ) ); if(!pPosHelper) - pPosHelper = m_pMainPosHelper.get(); + pPosHelper = &m_aMainPosHelper; } PlotterBase::m_pPosHelper = pPosHelper; @@ -203,30 +199,27 @@ void CandleStickChart::createShapes() drawing::Position3D aPosMiddleMinimum( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_Min ,0 ,true ) ); drawing::Position3D aPosMiddleMaximum( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_Max ,0 ,true ) ); - uno::Reference< drawing::XShapes > xLossGainTarget( xGainTarget ); - if(bBlack) - xLossGainTarget = xLossTarget; + rtl::Reference<SvxShapeGroupAnyD> xLossGainTarget(bBlack ? xLossTarget : xGainTarget); uno::Reference< beans::XPropertySet > xPointProp( pSeries->getPropertiesOfPoint( nIndex )); - uno::Reference< drawing::XShapes > xPointGroupShape_Shapes; + rtl::Reference<SvxShapeGroupAnyD> xPointGroupShape_Shapes; { OUString aPointCID = ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), nIndex ); - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes( getSeriesGroupShape(pSeries.get(), xSeriesTarget) ); + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes( getSeriesGroupShape(pSeries.get(), xSeriesTarget) ); xPointGroupShape_Shapes = createGroupShape(xSeriesGroupShape_Shapes,aPointCID); } //create min-max line if( isValidPosition(aPosMiddleMinimum) && isValidPosition(aPosMiddleMaximum) ) { - drawing::PolyPolygonShape3D aPoly; - sal_Int32 nLineIndex =0; - AddPointToPoly( aPoly, aPosMiddleMinimum, nLineIndex); - AddPointToPoly( aPoly, aPosMiddleMaximum, nLineIndex); - - uno::Reference< drawing::XShape > xShape = - m_pShapeFactory->createLine2D( xPointGroupShape_Shapes, - PolyToPointSequence(aPoly)); - setMappedProperties( xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() ); + std::vector<std::vector<css::drawing::Position3D>> aPoly + { + { aPosMiddleMinimum, aPosMiddleMaximum } + }; + + rtl::Reference<SvxShapePolyPolygon> xShape = + ShapeFactory::createLine2D( xPointGroupShape_Shapes, aPoly); + PropertyMapper::setMappedProperties( *xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() ); } //create first-last shape @@ -241,23 +234,19 @@ void CandleStickChart::createShapes() tNameSequence aNames; tAnySequence aValues; - uno::Reference< drawing::XShape > xShape = - m_pShapeFactory->createRectangle( xLossGainTarget, + rtl::Reference<SvxShapeRect> xShape = + ShapeFactory::createRectangle( xLossGainTarget, aAWTSize, Position3DToAWTPoint( aPosLeftFirst ), aNames, aValues); - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - if(xProp.is()) - { - if(bBlack) - PropertyMapper::setMultiProperties( aBlackBox_Names, aBlackBox_Values, xProp ); - else - PropertyMapper::setMultiProperties( aWhiteBox_Names, aWhiteBox_Values, xProp ); - } + if(bBlack) + PropertyMapper::setMultiProperties( aBlackBox_Names, aBlackBox_Values, *xShape ); + else + PropertyMapper::setMultiProperties( aWhiteBox_Names, aWhiteBox_Values, *xShape ); } else { - drawing::PolyPolygonShape3D aPoly; + std::vector<std::vector<css::drawing::Position3D>> aPoly; sal_Int32 nLineIndex = 0; if( bShowFirst && pPosHelper->isLogicVisible( fUnscaledX, fUnscaledY_First ,fLogicZ ) @@ -273,16 +262,11 @@ void CandleStickChart::createShapes() AddPointToPoly( aPoly, aPosRightLast, nLineIndex ); } - if( aPoly.SequenceX.hasElements() ) + if( !aPoly.empty() ) { - uno::Reference< drawing::XShape > xShape = - m_pShapeFactory->createLine2D( xPointGroupShape_Shapes, - PolyToPointSequence(aPoly) ); - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - if(xProp.is()) - { - setMappedProperties( xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() ); - } + rtl::Reference<SvxShapePolyPolygon> xShape = + ShapeFactory::createLine2D( xPointGroupShape_Shapes, aPoly ); + PropertyMapper::setMappedProperties( *xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() ); } } diff --git a/chart2/source/view/charttypes/CandleStickChart.hxx b/chart2/source/view/charttypes/CandleStickChart.hxx index 2d289131827a..3202cf0d7eaf 100644 --- a/chart2/source/view/charttypes/CandleStickChart.hxx +++ b/chart2/source/view/charttypes/CandleStickChart.hxx @@ -17,15 +17,14 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_CANDLESTICKCHART_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_CANDLESTICKCHART_HXX +#pragma once #include <memory> +#include "BarPositionHelper.hxx" #include <VSeriesPlotter.hxx> namespace chart { -class BarPositionHelper; class CandleStickChart : public VSeriesPlotter { @@ -33,7 +32,7 @@ class CandleStickChart : public VSeriesPlotter public: CandleStickChart() = delete; - CandleStickChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + CandleStickChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel , sal_Int32 nDimensionCount ); virtual ~CandleStickChart() override; @@ -48,9 +47,8 @@ public: virtual LegendSymbolStyle getLegendSymbolStyle() override; private: //member - std::unique_ptr<BarPositionHelper> m_pMainPosHelper; + BarPositionHelper m_aMainPosHelper; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/CategoryPositionHelper.hxx b/chart2/source/view/charttypes/CategoryPositionHelper.hxx index 2fd0d3d0aaaa..ebc784ef66cc 100644 --- a/chart2/source/view/charttypes/CategoryPositionHelper.hxx +++ b/chart2/source/view/charttypes/CategoryPositionHelper.hxx @@ -17,43 +17,41 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_CATEGORYPOSITIONHELPER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_CATEGORYPOSITIONHELPER_HXX +#pragma once namespace chart { - class CategoryPositionHelper { public: - CategoryPositionHelper( double fSeriesCount, double CategoryWidth = 1.0); + CategoryPositionHelper(double fSeriesCount, double CategoryWidth = 1.0); virtual ~CategoryPositionHelper(); - CategoryPositionHelper(CategoryPositionHelper const &) = default; - CategoryPositionHelper(CategoryPositionHelper &&) = default; - CategoryPositionHelper & operator =(CategoryPositionHelper const &) = default; - CategoryPositionHelper & operator =(CategoryPositionHelper &&) = default; + CategoryPositionHelper(CategoryPositionHelper const&) = default; + CategoryPositionHelper(CategoryPositionHelper&&) = default; + CategoryPositionHelper& operator=(CategoryPositionHelper const&) = default; + CategoryPositionHelper& operator=(CategoryPositionHelper&&) = default; double getScaledSlotWidth() const; - virtual double getScaledSlotPos( double fCategoryX, double fSeriesNumber ) const; - void setCategoryWidth( double fCategoryWidth ); + virtual double getScaledSlotPos(double fCategoryX, double fSeriesNumber) const; + void setCategoryWidth(double fCategoryWidth); //Distance between two neighboring bars in same category, seen relative to width of the bar - void setInnerDistance( double fInnerDistance ); + void setInnerDistance(double fInnerDistance); //Distance between two neighboring bars in different category, seen relative to width of the bar: - void setOuterDistance( double fOuterDistance ); + void setOuterDistance(double fOuterDistance); protected: double m_fSeriesCount; double m_fCategoryWidth; //Distance between two neighboring bars in same category, seen relative to width of the bar: - double m_fInnerDistance; //[-1,1] m_fInnerDistance=1 --> distance == width; m_fInnerDistance=-1-->all rects are painted on the same position + double + m_fInnerDistance; //[-1,1] m_fInnerDistance=1 --> distance == width; m_fInnerDistance=-1-->all rects are painted on the same position //Distance between two neighboring bars in different category, seen relative to width of the bar: double m_fOuterDistance; //>=0 m_fOuterDistance=1 --> distance == width }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/ConfigAccess.cxx b/chart2/source/view/charttypes/ConfigAccess.cxx deleted file mode 100644 index 964e58ce43f7..000000000000 --- a/chart2/source/view/charttypes/ConfigAccess.cxx +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * 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 . - */ - -#include <ConfigAccess.hxx> - -#include <unotools/configitem.hxx> -#include <o3tl/any.hxx> -#include <rtl/instance.hxx> -#include <com/sun/star/uno/Sequence.hxx> - -namespace chart -{ -using namespace ::com::sun::star; - -namespace -{ -class ChartConfigItem : public ::utl::ConfigItem -{ -private: - virtual void ImplCommit() override; - -public: - ChartConfigItem(); - - bool getUseErrorRectangle(); - virtual void Notify(const uno::Sequence<OUString>& aPropertyNames) override; -}; -} - -ChartConfigItem::ChartConfigItem() - : ConfigItem("Office.Chart/ErrorProperties") -{ -} - -void ChartConfigItem::ImplCommit() {} -void ChartConfigItem::Notify(const uno::Sequence<OUString>&) {} - -bool ChartConfigItem::getUseErrorRectangle() -{ - uno::Sequence<OUString> aNames(1); - aNames[0] = "ErrorRectangle"; - - auto b = o3tl::tryAccess<bool>(GetProperties(aNames)[0]); - return b && *b; -} - -namespace -{ -//a ChartConfigItem Singleton -struct theChartConfigItem : public rtl::Static<ChartConfigItem, theChartConfigItem> -{ -}; -} - -namespace ConfigAccess -{ -bool getUseErrorRectangle() -{ - bool bResult(theChartConfigItem::get().getUseErrorRectangle()); - return bResult; -} -} //namespace ConfigAccess - -} //namespace chart - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/NetChart.cxx b/chart2/source/view/charttypes/NetChart.cxx index a8a0f776dd24..5b8f1db34be5 100644 --- a/chart2/source/view/charttypes/NetChart.cxx +++ b/chart2/source/view/charttypes/NetChart.cxx @@ -27,24 +27,25 @@ #include <Clipping.hxx> #include <PolarLabelPositionHelper.hxx> #include <DateHelper.hxx> +#include <ChartType.hxx> #include <com/sun/star/chart2/Symbol.hpp> #include <com/sun/star/chart/DataLabelPlacement.hpp> #include <com/sun/star/chart/MissingValueTreatment.hpp> -#include <rtl/math.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> -#include <com/sun/star/drawing/XShapes.hpp> #include <officecfg/Office/Compatibility.hxx> +#include <limits> + namespace chart { using namespace ::com::sun::star; -using namespace ::rtl::math; using namespace ::com::sun::star::chart2; -NetChart::NetChart( const uno::Reference<XChartType>& xChartTypeModel +NetChart::NetChart( const rtl::Reference<ChartType>& xChartTypeModel , sal_Int32 nDimensionCount , bool bNoArea , std::unique_ptr<PlottingPositionHelper> pPlottingPositionHelper @@ -111,13 +112,13 @@ drawing::Direction3D NetChart::getPreferredDiagramAspectRatio() const } bool NetChart::impl_createLine( VDataSeries* pSeries - , drawing::PolyPolygonShape3D* pSeriesPoly + , const std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly , PlottingPositionHelper const * pPosHelper ) { //return true if a line was created successfully - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); - drawing::PolyPolygonShape3D aPoly; + std::vector<std::vector<css::drawing::Position3D>> aPoly; { bool bIsClipped = false; if( !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) ) @@ -130,10 +131,10 @@ bool NetChart::impl_createLine( VDataSeries* pSeries { // connect last point in last polygon with first point in first polygon ::basegfx::B2DRectangle aScaledLogicClipDoubleRect( pPosHelper->getScaledLogicClipDoubleRect() ); - drawing::PolyPolygonShape3D aTmpPoly(*pSeriesPoly); - drawing::Position3D aLast(aScaledLogicClipDoubleRect.getMaxX(),aTmpPoly.SequenceY[0][0],aTmpPoly.SequenceZ[0][0]); + std::vector<std::vector<css::drawing::Position3D>> aTmpPoly(*pSeriesPoly); + drawing::Position3D aLast(aScaledLogicClipDoubleRect.getMaxX(),aTmpPoly[0][0].PositionY,aTmpPoly[0][0].PositionZ); // add connector line to last polygon - AddPointToPoly( aTmpPoly, aLast, pSeriesPoly->SequenceX.getLength() - 1 ); + AddPointToPoly( aTmpPoly, aLast, pSeriesPoly->size() - 1 ); Clipping::clipPolygonAtRectangle( aTmpPoly, aScaledLogicClipDoubleRect, aPoly ); bIsClipped = true; } @@ -150,11 +151,10 @@ bool NetChart::impl_createLine( VDataSeries* pSeries pPosHelper->transformScaledLogicToScene( aPoly ); //create line: - uno::Reference< drawing::XShape > xShape; + rtl::Reference<SvxShapePolyPolygon> xShape; { - xShape = m_pShapeFactory->createLine2D( xSeriesGroupShape_Shapes - , PolyToPointSequence( aPoly ) ); - setMappedProperties( xShape + xShape = ShapeFactory::createLine2D( xSeriesGroupShape_Shapes, aPoly ); + PropertyMapper::setMappedProperties( *xShape , pSeries->getPropertiesOfSeries() , PropertyMapper::getPropertyNameMapForLineSeriesProperties() ); //because of this name this line will be used for marking @@ -164,16 +164,16 @@ bool NetChart::impl_createLine( VDataSeries* pSeries } bool NetChart::impl_createArea( VDataSeries* pSeries - , drawing::PolyPolygonShape3D* pSeriesPoly - , drawing::PolyPolygonShape3D const * pPreviousSeriesPoly + , const std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly + , std::vector<std::vector<css::drawing::Position3D>> const * pPreviousSeriesPoly , PlottingPositionHelper const * pPosHelper ) { //return true if an area was created successfully - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget); double zValue = pSeries->m_fLogicZPos; - drawing::PolyPolygonShape3D aPoly( *pSeriesPoly ); + std::vector<std::vector<css::drawing::Position3D>> aPoly( *pSeriesPoly ); //add second part to the polygon (grounding points or previous series points) if( !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) ) { @@ -209,7 +209,7 @@ bool NetChart::impl_createArea( VDataSeries* pSeries //apply clipping { - drawing::PolyPolygonShape3D aClippedPoly; + std::vector<std::vector<css::drawing::Position3D>> aClippedPoly; Clipping::clipPolygonAtRectangle( aPoly, pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly, false ); ShapeFactory::closePolygon(aClippedPoly); //again necessary after clipping aPoly = aClippedPoly; @@ -222,10 +222,10 @@ bool NetChart::impl_createArea( VDataSeries* pSeries pPosHelper->transformScaledLogicToScene( aPoly ); //create area: - uno::Reference< drawing::XShape > - xShape = m_pShapeFactory->createArea2D( xSeriesGroupShape_Shapes + rtl::Reference<SvxShapePolyPolygon> + xShape = ShapeFactory::createArea2D( xSeriesGroupShape_Shapes , aPoly ); - setMappedProperties( xShape + PropertyMapper::setMappedProperties( *xShape , pSeries->getPropertiesOfSeries() , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); //because of this name this line will be used for marking @@ -242,8 +242,8 @@ void NetChart::impl_createSeriesShapes() { for( auto const& rXSlot : rZSlot ) { - std::map< sal_Int32, drawing::PolyPolygonShape3D* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex - drawing::PolyPolygonShape3D* pSeriesPoly = nullptr; + std::map< sal_Int32, std::vector<std::vector<css::drawing::Position3D>>* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex + std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly = nullptr; //iterate through all series for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector ) @@ -301,10 +301,11 @@ struct FormerPoint : m_fX(fX), m_fY(fY), m_fZ(fZ) {} FormerPoint() + : m_fX(std::numeric_limits<double>::quiet_NaN()) + , m_fY(std::numeric_limits<double>::quiet_NaN()) + , m_fZ(std::numeric_limits<double>::quiet_NaN()) + { - ::rtl::math::setNan( &m_fX ); - ::rtl::math::setNan( &m_fY ); - ::rtl::math::setNan( &m_fZ ); } double m_fX; @@ -323,8 +324,8 @@ void NetChart::createShapes() if (officecfg::Office::Compatibility::View::ReverseSeriesOrderAreaAndNetChart::get() && m_bArea) lcl_reorderSeries( m_aZSlots ); - OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"NetChart is not proper initialized"); - if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"NetChart is not proper initialized"); + if(!(m_xLogicTarget.is()&&m_xFinalTarget.is())) return; //the text labels should be always on top of the other series shapes @@ -333,7 +334,7 @@ void NetChart::createShapes() //therefore create an own group for the texts and the error bars to move them to front //(because the text group is created after the series group the texts are displayed on top) m_xSeriesTarget = createGroupShape( m_xLogicTarget ); - m_xTextTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget ); + m_xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget ); //check necessary here that different Y axis can not be stacked in the same group? ... hm? @@ -369,8 +370,7 @@ void NetChart::createShapes() pSeries->doSortByXValues(); sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex(); - if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() ) - aLogicYSumMap[nAttachedAxisIndex]=0.0; + aLogicYSumMap.insert({nAttachedAxisIndex, 0.0}); m_pPosHelper = &getPlottingPositionHelper(nAttachedAxisIndex); @@ -400,7 +400,7 @@ void NetChart::createShapes() if( m_bArea && (rXSlot.m_aSeriesVector.size() == 1) && (nIndex >= pSeries->getTotalPointCount()) ) continue; - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(pSeries.get(), m_xSeriesTarget); + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(pSeries.get(), m_xSeriesTarget); sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex(); m_pPosHelper = &getPlottingPositionHelper(nAttachedAxisIndex); @@ -439,11 +439,11 @@ void NetChart::createShapes() { if( pSeries->getMissingValueTreatment() == css::chart::MissingValueTreatment::LEAVE_GAP ) { - drawing::PolyPolygonShape3D& rPolygon = pSeries->m_aPolyPolygonShape3D; + std::vector<std::vector<css::drawing::Position3D>>& rPolygon = pSeries->m_aPolyPolygonShape3D; sal_Int32& rIndex = pSeries->m_nPolygonIndex; - if( 0<= rIndex && rIndex < rPolygon.SequenceX.getLength() ) + if( 0<= rIndex && o3tl::make_unsigned(rIndex) < rPolygon.size() ) { - if( rPolygon.SequenceX[ rIndex ].hasElements() ) + if( !rPolygon[ rIndex ].empty() ) rIndex++; //start a new polygon for the next point if the current poly is not empty } } @@ -527,9 +527,8 @@ void NetChart::createShapes() //create a group shape for this point and add to the series shape: OUString aPointCID = ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), nIndex ); - uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( + rtl::Reference<SvxShapeGroupAnyD> xPointGroupShape_Shapes( createGroupShape(xSeriesGroupShape_Shapes,aPointCID) ); - uno::Reference<drawing::XShape> xPointGroupShape_Shape( xPointGroupShape_Shapes, uno::UNO_QUERY ); { //create data point @@ -545,13 +544,13 @@ void NetChart::createShapes() if (pSymbolProperties->Style == SymbolStyle_STANDARD) { sal_Int32 nSymbol = pSymbolProperties->StandardSymbol; - m_pShapeFactory->createSymbol2D( + ShapeFactory::createSymbol2D( xPointGroupShape_Shapes, aScenePosition, aSymbolSize, nSymbol, pSymbolProperties->BorderColor, pSymbolProperties->FillColor); } else if (pSymbolProperties->Style == SymbolStyle_GRAPHIC) { - m_pShapeFactory->createGraphic2D(xPointGroupShape_Shapes, + ShapeFactory::createGraphic2D(xPointGroupShape_Shapes, aScenePosition, aSymbolSize, pSymbolProperties->Graphic); } @@ -606,7 +605,7 @@ void NetChart::createShapes() = dynamic_cast<PolarPlottingPositionHelper*>(m_pPosHelper); if( pPolarPosHelper ) { - PolarLabelPositionHelper aPolarLabelPositionHelper(pPolarPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory); + PolarLabelPositionHelper aPolarLabelPositionHelper(pPolarPosHelper,m_nDimension,m_xLogicTarget); aScreenPosition2D = aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues( eAlignment, fLogicX, fLogicY, fLogicZ, nOffset ); } @@ -615,7 +614,7 @@ void NetChart::createShapes() { if(eAlignment==LABEL_ALIGN_CENTER ) nOffset = 0; - aScreenPosition2D = LabelPositionHelper(m_nDimension,m_xLogicTarget,m_pShapeFactory) + aScreenPosition2D = LabelPositionHelper(m_nDimension,m_xLogicTarget) .transformSceneToScreenPosition( aScenePosition3D ); } @@ -627,7 +626,7 @@ void NetChart::createShapes() //remove PointGroupShape if empty if(!xPointGroupShape_Shapes->getCount()) - xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape); + xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shapes); }//next series in x slot (next y slot) }//next x slot diff --git a/chart2/source/view/charttypes/NetChart.hxx b/chart2/source/view/charttypes/NetChart.hxx index 2d948d2e2138..a536daf15fd2 100644 --- a/chart2/source/view/charttypes/NetChart.hxx +++ b/chart2/source/view/charttypes/NetChart.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_NETCHART_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_NETCHART_HXX +#pragma once #include <memory> #include <VSeriesPlotter.hxx> @@ -32,7 +31,7 @@ class NetChart : public VSeriesPlotter public: NetChart() = delete; - NetChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + NetChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel , sal_Int32 nDimensionCount , bool bNoArea , std::unique_ptr<PlottingPositionHelper> pPlottingPositionHelper //takes ownership @@ -54,11 +53,11 @@ public: private: //methods void impl_createSeriesShapes(); bool impl_createArea( VDataSeries* pSeries - , css::drawing::PolyPolygonShape3D* pSeriesPoly - , css::drawing::PolyPolygonShape3D const * pPreviousSeriesPoly + , const std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly + , std::vector<std::vector<css::drawing::Position3D>> const * pPreviousSeriesPoly , PlottingPositionHelper const * pPosHelper ); bool impl_createLine( VDataSeries* pSeries - , css::drawing::PolyPolygonShape3D* pSeriesPoly + , const std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly , PlottingPositionHelper const * pPosHelper ); private: //member @@ -67,10 +66,9 @@ private: //member bool m_bArea;//false -> line or symbol only bool m_bLine; - css::uno::Reference< css::drawing::XShapes > m_xSeriesTarget; - css::uno::Reference< css::drawing::XShapes > m_xTextTarget; + rtl::Reference<SvxShapeGroupAnyD> m_xSeriesTarget; + rtl::Reference<SvxShapeGroupAnyD> m_xTextTarget; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx index 5ab60729cf93..ff8cf62f133a 100644 --- a/chart2/source/view/charttypes/PieChart.cxx +++ b/chart2/source/view/charttypes/PieChart.cxx @@ -20,29 +20,29 @@ #include <BaseGFXHelper.hxx> #include <VLineProperties.hxx> #include "PieChart.hxx" -#include <PlottingPositionHelper.hxx> #include <ShapeFactory.hxx> #include <PolarLabelPositionHelper.hxx> #include <CommonConverters.hxx> #include <ObjectIdentifier.hxx> +#include <ChartType.hxx> +#include <DataSeries.hxx> +#include <DataSeriesProperties.hxx> #include <com/sun/star/chart/DataLabelPlacement.hpp> -#include <com/sun/star/chart2/XChartType.hpp> #include <com/sun/star/chart2/XColorScheme.hpp> -#include <com/sun/star/container/XChild.hpp> -#include <com/sun/star/drawing/XShape.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> -#include <rtl/math.hxx> +#include <com/sun/star/drawing/XShapes.hpp> #include <sal/log.hxx> #include <osl/diagnose.h> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <tools/helpers.hxx> +#include <limits> #include <memory> using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; +using namespace ::chart::DataSeriesProperties; namespace chart { @@ -101,17 +101,28 @@ struct PieChart::ShapeParam mfDepth(0.0) {} }; -class PiePositionHelper : public PolarPlottingPositionHelper +namespace +{ +::basegfx::B2IRectangle lcl_getRect(const rtl::Reference<SvxShape>& xShape) { -public: - PiePositionHelper( double fAngleDegreeOffset ); + ::basegfx::B2IRectangle aRect; + if (xShape.is()) + aRect = BaseGFXHelper::makeRectangle(xShape->getPosition(), xShape->getSize()); + return aRect; +} - bool getInnerAndOuterRadius( double fCategoryX, double& fLogicInnerRadius, double& fLogicOuterRadius, bool bUseRings, double fMaxOffset ) const; +bool lcl_isInsidePage(const awt::Point& rPos, const awt::Size& rSize, const awt::Size& rPageSize) +{ + if (rPos.X < 0 || rPos.Y < 0) + return false; + if ((rPos.X + rSize.Width) > rPageSize.Width) + return false; + if ((rPos.Y + rSize.Height) > rPageSize.Height) + return false; + return true; +} -public: - //Distance between different category rings, seen relative to width of a ring: - double m_fRingDistance; //>=0 m_fRingDistance=1 --> distance == width -}; +} //end anonymous namespace PiePositionHelper::PiePositionHelper( double fAngleDegreeOffset ) : m_fRingDistance(0.0) @@ -167,49 +178,64 @@ bool PiePositionHelper::getInnerAndOuterRadius( double fCategoryX return true; } -PieChart::PieChart( const uno::Reference<XChartType>& xChartTypeModel + +bool PiePositionHelper::clockwiseWedges() const +{ + const ExplicitScaleData& rAngleScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[0]; + return rAngleScale.Orientation == AxisOrientation_REVERSE; +} + + +PieChart::PieChart( const rtl::Reference<ChartType>& xChartTypeModel , sal_Int32 nDimensionCount , bool bExcludingPositioning ) : VSeriesPlotter( xChartTypeModel, nDimensionCount ) - , m_pPosHelper( new PiePositionHelper( (m_nDimension==3) ? 0.0 : 90.0 ) ) + , m_aPosHelper( (m_nDimension==3) ? 0.0 : 90.0 ) , m_bUseRings(false) , m_bSizeExcludesLabelsAndExplodedSegments(bExcludingPositioning) + , m_eSubType(PieChartSubType_NONE) + , m_fMaxOffset(std::numeric_limits<double>::quiet_NaN()) { - ::rtl::math::setNan(&m_fMaxOffset); + PlotterBase::m_pPosHelper = &m_aPosHelper; + VSeriesPlotter::m_pMainPosHelper = &m_aPosHelper; + m_aPosHelper.m_fRadiusOffset = 0.0; + m_aPosHelper.m_fRingDistance = 0.0; - PlotterBase::m_pPosHelper = m_pPosHelper.get(); - VSeriesPlotter::m_pMainPosHelper = m_pPosHelper.get(); - m_pPosHelper->m_fRadiusOffset = 0.0; - m_pPosHelper->m_fRingDistance = 0.0; - - uno::Reference< beans::XPropertySet > xChartTypeProps( xChartTypeModel, uno::UNO_QUERY ); - if( !xChartTypeProps.is() ) + if( !xChartTypeModel.is() ) return; try { - xChartTypeProps->getPropertyValue( "UseRings") >>= m_bUseRings; + xChartTypeModel->getFastPropertyValue(PROP_PIECHARTTYPE_USE_RINGS) >>= m_bUseRings; // "UseRings" if( m_bUseRings ) { - m_pPosHelper->m_fRadiusOffset = 1.0; + m_aPosHelper.m_fRadiusOffset = 1.0; if( nDimensionCount==3 ) - m_pPosHelper->m_fRingDistance = 0.1; + m_aPosHelper.m_fRingDistance = 0.1; } } catch( const uno::Exception& ) { TOOLS_WARN_EXCEPTION("chart2", "" ); } + try + { + xChartTypeModel->getFastPropertyValue(PROP_PIECHARTTYPE_SUBTYPE) >>= m_eSubType; // "SubType" + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } } PieChart::~PieChart() { } -void PieChart::setScales( const std::vector< ExplicitScaleData >& rScales, bool /* bSwapXAndYAxis */ ) +void PieChart::setScales( std::vector< ExplicitScaleData >&& rScales, bool /* bSwapXAndYAxis */ ) { OSL_ENSURE(m_nDimension<=static_cast<sal_Int32>(rScales.size()),"Dimension of Plotter does not fit two dimension of given scale sequence"); - m_pPosHelper->setScales( rScales, true ); + m_aPosHelper.setScales( std::move(rScales), true ); } drawing::Direction3D PieChart::getPreferredDiagramAspectRatio() const @@ -224,46 +250,143 @@ bool PieChart::shouldSnapRectToUsedArea() return true; } -uno::Reference< drawing::XShape > PieChart::createDataPoint( - const uno::Reference<drawing::XShapes>& xTarget, +rtl::Reference<SvxShape> PieChart::createDataPoint( + const SubPieType e_subType, + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const uno::Reference<beans::XPropertySet>& xObjectProperties, - tPropertyNameValueMap const * pOverwritePropertiesMap, - const ShapeParam& rParam ) + const ShapeParam& rParam, + const sal_Int32 nPointCount, + const bool bConcentricExplosion) { //transform position: drawing::Direction3D aOffset; - if (rParam.mfExplodePercentage != 0.0) - { - double fAngle = rParam.mfUnitCircleStartAngleDegree + rParam.mfUnitCircleWidthAngleDegree/2.0; - double fRadius = (rParam.mfUnitCircleOuterRadius-rParam.mfUnitCircleInnerRadius)*rParam.mfExplodePercentage; - drawing::Position3D aOrigin = m_pPosHelper->transformUnitCircleToScene(0, 0, rParam.mfLogicZ); - drawing::Position3D aNewOrigin = m_pPosHelper->transformUnitCircleToScene(fAngle, fRadius, rParam.mfLogicZ); - aOffset = aNewOrigin - aOrigin; + double fExplodedInnerRadius = rParam.mfUnitCircleInnerRadius; + double fExplodedOuterRadius = rParam.mfUnitCircleOuterRadius; + double fStartAngle = rParam.mfUnitCircleStartAngleDegree; + double fWidthAngle = rParam.mfUnitCircleWidthAngleDegree; + + if (rParam.mfExplodePercentage != 0.0) { + double fRadius = (fExplodedOuterRadius-fExplodedInnerRadius)*rParam.mfExplodePercentage; + + if (bConcentricExplosion) { + + // For concentric explosion, increase the radius but retain the original + // arc length of all ring segments together. This results in a gap + // that's evenly divided among all segments, assuming they all have + // the same explosion percentage + assert(fExplodedInnerRadius >= 0 && fExplodedOuterRadius > 0); + double fAngleRatio = (fExplodedInnerRadius + fExplodedOuterRadius) / + (fExplodedInnerRadius + fExplodedOuterRadius + 2 * fRadius); + + assert(nPointCount > 0); + double fAngleGap = 360 * (1.0 - fAngleRatio) / nPointCount; + fStartAngle += fAngleGap / 2; + fWidthAngle -= fAngleGap; + + fExplodedInnerRadius += fRadius; + fExplodedOuterRadius += fRadius; + + } else { + // For the non-concentric explosion case, keep the original radius + // but shift the circle origin + double fAngle = fStartAngle + fWidthAngle/2.0; + + drawing::Position3D aOrigin = m_aPosHelper.transformUnitCircleToScene(0, 0, rParam.mfLogicZ); + drawing::Position3D aNewOrigin = m_aPosHelper.transformUnitCircleToScene(fAngle, fRadius, rParam.mfLogicZ); + aOffset = aNewOrigin - aOrigin; + } + } else { + drawing::Position3D aOrigin, aNewOrigin; + switch (e_subType) { + case SubPieType::LEFT: + // Draw the main pie for bar-of-pie/pie-of-pie smaller and to the left + aOrigin = m_aPosHelper.transformUnitCircleToScene(0, 0, rParam.mfLogicZ); + aNewOrigin = m_aPosHelper.transformUnitCircleToScene(180, 0.75, rParam.mfLogicZ); + aOffset = aNewOrigin - aOrigin; + fExplodedOuterRadius *= 2.0/3; + break; + case SubPieType::RIGHT: + // Draw the sub-pie for pie-of-pie much smaller and to the right + aOrigin = m_aPosHelper.transformUnitCircleToScene(0, 0, rParam.mfLogicZ); + aNewOrigin = m_aPosHelper.transformUnitCircleToScene(0, 0.75, rParam.mfLogicZ); + aOffset = aNewOrigin - aOrigin; + fExplodedOuterRadius *= 1.0/3; + break; + case SubPieType::NONE: + default: + // no change + break; + } } + //create point - uno::Reference< drawing::XShape > xShape; + rtl::Reference<SvxShape> xShape; if(m_nDimension==3) { - xShape = m_pShapeFactory->createPieSegment( xTarget - , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree - , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius - , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() ) + xShape = ShapeFactory::createPieSegment( xTarget + , fStartAngle, fWidthAngle + , fExplodedInnerRadius, fExplodedOuterRadius + , aOffset, B3DHomMatrixToHomogenMatrix( m_aPosHelper.getUnitCartesianToScene() ) , rParam.mfDepth ); } else { - xShape = m_pShapeFactory->createPieSegment2D( xTarget - , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree - , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius - , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() ) ); + xShape = ShapeFactory::createPieSegment2D( xTarget + , fStartAngle, fWidthAngle + , fExplodedInnerRadius, fExplodedOuterRadius + , aOffset, B3DHomMatrixToHomogenMatrix( m_aPosHelper.getUnitCartesianToScene() ) ); } - setMappedProperties( xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), pOverwritePropertiesMap ); + PropertyMapper::setMappedProperties( *xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); + return xShape; +} + +rtl::Reference<SvxShape> PieChart::createBarDataPoint( + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, + const uno::Reference<beans::XPropertySet>& xObjectProperties, + const ShapeParam& rParam, + double fBarSegBottom, double fBarSegTop) +{ + drawing::Position3D aP0, aP1; + + // Draw the bar for bar-of-pie small and to the right. Width and + // position are hard-coded for now. + +#if 0 + aP0 = cartesianPosHelper.transformLogicToScene(0.75, fBarSegBottom, + rParam.mfLogicZ, false); + aP1 = cartesianPosHelper.transformLogicToScene(1.25, fBarSegTop, + rParam.mfLogicZ, false); +#else + double x0 = m_aPosHelper.transformUnitCircleToScene(0, 0.75, 0).PositionX; + double x1 = m_aPosHelper.transformUnitCircleToScene(0, 1.25, 0).PositionX; + double y0 = m_aPosHelper.transformUnitCircleToScene( + 90, fBarSegBottom, 0).PositionY; + double y1 = m_aPosHelper.transformUnitCircleToScene( + 90, fBarSegTop, 0).PositionY; + + aP0 = drawing::Position3D(x0, y0, rParam.mfLogicZ); + aP1 = drawing::Position3D(x1, y1, rParam.mfLogicZ); +#endif + + const css::awt::Point aPos(aP0.PositionX, aP1.PositionY); + const css::awt::Size aSz(fabs(aP0.PositionX - aP1.PositionX), + fabs(aP0.PositionY - aP1.PositionY)); + + const tNameSequence emptyNameSeq; + const tAnySequence emptyValSeq; + //create point + rtl::Reference<SvxShape> xShape = ShapeFactory::createRectangle( + xTarget, + aSz, aPos, + emptyNameSeq, emptyValSeq); + + PropertyMapper::setMappedProperties( *xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); return xShape; } void PieChart::createTextLabelShape( - const uno::Reference<drawing::XShapes>& xTextTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, VDataSeries& rSeries, sal_Int32 nPointIndex, ShapeParam& rParam ) { if (!rSeries.getDataPointLabelIfLabel(nPointIndex)) @@ -284,7 +407,12 @@ void PieChart::createTextLabelShape( ///get the required label placement type. Available placements are ///`AVOID_OVERLAP`, `CENTER`, `OUTSIDE` and `INSIDE`; sal_Int32 nLabelPlacement = rSeries.getLabelPlacement( - nPointIndex, m_xChartTypeModel, m_pPosHelper->isSwapXAndY()); + nPointIndex, m_xChartTypeModel, m_aPosHelper.isSwapXAndY()); + + // has an X/Y offset (relative to the OUTSIDE label default position) been provided? + const bool bHasCustomLabelPlacement = nLabelPlacement == css::chart::DataLabelPlacement::CUSTOM; + if (bHasCustomLabelPlacement) + nLabelPlacement = css::chart::DataLabelPlacement::OUTSIDE; ///when the placement is of `AVOID_OVERLAP` type a later rearrangement of ///the label position is allowed; the `createTextLabelShape` treats the @@ -292,7 +420,7 @@ void PieChart::createTextLabelShape( double nVal = rSeries.getYValue(nPointIndex); //AVOID_OVERLAP is in fact "Best fit" in the UI. - bool bMovementAllowed = ( nLabelPlacement == css::chart::DataLabelPlacement::AVOID_OVERLAP ); + bool bMovementAllowed = nLabelPlacement == css::chart::DataLabelPlacement::AVOID_OVERLAP; if( bMovementAllowed ) nLabelPlacement = css::chart::DataLabelPlacement::CENTER; @@ -314,7 +442,7 @@ void PieChart::createTextLabelShape( ///the scene position of the label anchor point is calculated (see notes for ///`PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues`), ///and immediately transformed into the screen position. - PolarLabelPositionHelper aPolarPosHelper(m_pPosHelper.get(),m_nDimension,m_xLogicTarget,m_pShapeFactory); + PolarLabelPositionHelper aPolarPosHelper(&m_aPosHelper,m_nDimension,m_xLogicTarget); awt::Point aScreenPosition2D( aPolarPosHelper.getLabelScreenPositionAndAlignmentForUnitCircleValues(eAlignment, nLabelPlacement , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree @@ -323,7 +451,7 @@ void PieChart::createTextLabelShape( ///the screen position of the pie/donut center is calculated. PieLabelInfo aPieLabelInfo; aPieLabelInfo.aFirstPosition = basegfx::B2IVector( aScreenPosition2D.X, aScreenPosition2D.Y ); - awt::Point aOrigin( aPolarPosHelper.transformSceneToScreenPosition( m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, rParam.mfLogicZ+1.0 ) ) ); + awt::Point aOrigin( aPolarPosHelper.transformSceneToScreenPosition( m_aPosHelper.transformUnitCircleToScene( 0.0, 0.0, rParam.mfLogicZ+1.0 ) ) ); aPieLabelInfo.aOrigin = basegfx::B2IVector( aOrigin.X, aOrigin.Y ); ///add a scaling independent Offset if requested @@ -337,19 +465,81 @@ void PieChart::createTextLabelShape( // compute outer pie radius awt::Point aOuterCirclePoint = PlottingPositionHelper::transformSceneToScreenPosition( - m_pPosHelper->transformUnitCircleToScene( + m_aPosHelper.transformUnitCircleToScene( 0, rParam.mfUnitCircleOuterRadius, 0 ), - m_xLogicTarget, m_pShapeFactory, m_nDimension ); + m_xLogicTarget, m_nDimension ); basegfx::B2IVector aRadiusVector( aOuterCirclePoint.X - aPieLabelInfo.aOrigin.getX(), aOuterCirclePoint.Y - aPieLabelInfo.aOrigin.getY() ); double fSquaredPieRadius = aRadiusVector.scalar(aRadiusVector); double fPieRadius = sqrt( fSquaredPieRadius ); + const double fHalfWidthAngleDegree = rParam.mfUnitCircleWidthAngleDegree / 2.0; + // fAngleDegree: the angle through the center of the slice / the bisecting ray + const double fAngleDegree + = NormAngle360(rParam.mfUnitCircleStartAngleDegree + fHalfWidthAngleDegree); + + // aOuterPosition: slice midpoint on the circumference, + // which is where an outside/custom label would be connected + awt::Point aOuterPosition = PlottingPositionHelper::transformSceneToScreenPosition( + m_aPosHelper.transformUnitCircleToScene(fAngleDegree, rParam.mfUnitCircleOuterRadius, 0), + m_xLogicTarget, m_nDimension); + aPieLabelInfo.aOuterPosition = basegfx::B2IVector(aOuterPosition.X, aOuterPosition.Y); + + /* There are basically three places where a label could be placed in a pie chart + * 1.) outside the slice + * -typically used for long labels or charts with many, thin slices + * 2.) inside the slice (center or edge) + * -typically used for charts with 5 or less slices + * 3.) in a custom location + * -typically set (by auto-positioning I presume) when labels overlap + * + * Selecting a good width for the text is critical to achieving good-looking labels. + * Our bestFit algorithm completely depends on a good starting guess. + * Lots of room for improvement here... + * Warning: complication due to 3D ovals (so can't use normal circle functions), + * donuts(m_bUseRings), auto re-scaling of the pie chart, etc. + * + * Based on observation, Microsoft uses 1/5 of the chart space as its text limit, + * although it will reduce the width (as long as it is not a custom position) + * if doing so means that the now-taller-text will fit inside the slice, + * so best if we do the same for our charts. + */ - // set the maximum text width to be used when text wrapping is enabled + // set the maximum text width to be used when text wrapping is enabled (default text wrap is on) + /* A reasonable start for bestFitting a 90deg slice oriented on an Axis is 80% of the radius */ double fTextMaximumFrameWidth = 0.8 * fPieRadius; + const double fCompatMaxTextLen = m_aAvailableOuterRect.getWidth() / 5.0; + if (m_aAvailableOuterRect.getWidth()) + { + if (bHasCustomLabelPlacement) + { + // if a custom width has been provided, then use that of course, + // otherwise use the interoperability-compliant 1/5 of the chart space as max width + const awt::Size aCustomSize = rSeries.getLabelCustomSize(nPointIndex); + if (aCustomSize.Width > 0) + fTextMaximumFrameWidth = aCustomSize.Width; + else + fTextMaximumFrameWidth = fCompatMaxTextLen; + } + else if (nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE) + { + // use up to 80% of the available space from the slice edge to the edge of the chart + const sal_Int32 nOuterX = aPieLabelInfo.aOuterPosition.getX(); + if (fAngleDegree < 90 || fAngleDegree > 270) // label is placed on the right side + fTextMaximumFrameWidth = 0.8 * abs(m_aAvailableOuterRect.getWidth() - nOuterX); + else // label is placed on the left side + fTextMaximumFrameWidth = 0.8 * nOuterX; + + // limited of course to the 1/5 maximum allowed for compatibility + fTextMaximumFrameWidth = std::min(fTextMaximumFrameWidth, fCompatMaxTextLen); + } + } + /* TODO: better guesses for INSIDE: does the slice better handle wide text or tall/wrapped text? + * * wide: center near X-axis, shorter text content, slice > 90degree wide + * * tall: center near Y-axis, longer text content, many categories shown + */ sal_Int32 nTextMaximumFrameWidth = ceil(fTextMaximumFrameWidth); ///the text shape for the label is created @@ -359,24 +549,163 @@ void PieChart::createTextLabelShape( ///a new `PieLabelInfo` instance is initialized with all the info related to ///the current label in order to simplify later label position rearrangement; - uno::Reference< container::XChild > xChild( aPieLabelInfo.xTextShape, uno::UNO_QUERY ); + rtl::Reference< SvxShape > xChild = aPieLabelInfo.xTextShape; ///text shape could be empty; in that case there is no need to add label info if( !xChild.is() ) return; - aPieLabelInfo.xLabelGroupShape.set( xChild->getParent(), uno::UNO_QUERY ); + aPieLabelInfo.xLabelGroupShape = dynamic_cast<SvxShapeGroupAnyD*>(xChild->getParent().get()); - aPieLabelInfo.fValue = nVal; - aPieLabelInfo.bMovementAllowed = bMovementAllowed; - aPieLabelInfo.bMoved= false; - aPieLabelInfo.xTextTarget = xTextTarget; + if (bMovementAllowed && !m_bUseRings) + { + /** Handle the placement of the label in the best fit case. + * First off the routine try to place the label inside the related pie slice, + * if this is not possible the label is placed outside. + */ + + /* Note: bestFit surprisingly does not adjust the width of the label, + * so having an optimal width already set when createDataLabel ran earlier + * is crucial (and currently lacking)! + * TODO: * change bestFit to treat the width as a max width, and reduce if beneficial + */ + if (!performLabelBestFitInnerPlacement(rParam, aPieLabelInfo)) + { + if (m_aAvailableOuterRect.getWidth()) + { + /* This tried to bestFit, but it didn't fit. So how best to handle this? + * + * Two possible cases relating to compatibility + * 1.) It did fit for Microsoft, but our bestFit wasn't able to do the same + * * In that case, the best response is to be as small as possible + * (the distance from the chart edge to where the label attaches to the slice) + * to avoid scaling the diagram with too long outside labels, + * and to encourage fixing the bestFit algorithm. + * 2.) It didn't fit for Microsoft either (possible, but less likely situation) + * * In that case, the compatible max length would be best + * * can expect the chart space has been properly sized to handle the max length + * + * In the native LO case, it is also best to be as small as possible, + * so that the user creating the diagram is annoyed and makes the chart area larger. + * + * Therefore, handle this by making the label as small as possible. + * + * Complication (tdf122765.pptx): it is possible for the aOuterPosition + * to be outside of the available outer rectangle (somehow), + * so in that bizarre case just try the positive value of the result... + */ + const sal_Int32 nOuterX = aPieLabelInfo.aOuterPosition.getX(); + if (fAngleDegree < 90 || fAngleDegree > 270) // label is placed on the right side + fTextMaximumFrameWidth = 0.8 * abs(m_aAvailableOuterRect.getWidth() - nOuterX); + else // label is placed on the left side + fTextMaximumFrameWidth = 0.8 * nOuterX; + + nTextMaximumFrameWidth = ceil(std::min(fTextMaximumFrameWidth, fCompatMaxTextLen)); + } - if (bMovementAllowed) + // find the position to connect an Outside label to + nScreenValueOffsetInRadiusDirection = (m_nDimension != 3) ? 150 : 0; + aScreenPosition2D + = aPolarPosHelper.getLabelScreenPositionAndAlignmentForUnitCircleValues( + eAlignment, css::chart::DataLabelPlacement::OUTSIDE, + rParam.mfUnitCircleStartAngleDegree, + rParam.mfUnitCircleWidthAngleDegree, rParam.mfUnitCircleInnerRadius, + rParam.mfUnitCircleOuterRadius, rParam.mfLogicZ + 0.5, 0); + aPieLabelInfo.aFirstPosition + = basegfx::B2IVector(aScreenPosition2D.X, aScreenPosition2D.Y); + + //add a scaling independent Offset if requested + if (nScreenValueOffsetInRadiusDirection != 0) + { + basegfx::B2IVector aDirection(aScreenPosition2D.X - aOrigin.X, + aScreenPosition2D.Y - aOrigin.Y); + aDirection.setLength(nScreenValueOffsetInRadiusDirection); + aScreenPosition2D.X += aDirection.getX(); + aScreenPosition2D.Y += aDirection.getY(); + } + + uno::Reference<drawing::XShapes> xShapes(xChild->getParent(), uno::UNO_QUERY); + /* question: why remove and rebuild? Can't the existing one just be changed? */ + xShapes->remove(aPieLabelInfo.xTextShape); + aPieLabelInfo.xTextShape + = createDataLabel(xTextTarget, rSeries, nPointIndex, nVal, rParam.mfLogicYSum, + aScreenPosition2D, eAlignment, 0, nTextMaximumFrameWidth); + xChild = aPieLabelInfo.xTextShape; + if (!xChild.is()) + return; + + aPieLabelInfo.xLabelGroupShape = dynamic_cast<SvxShapeGroupAnyD*>(xChild->getParent().get()); + } + } + + bool bShowLeaderLine = rSeries.getModel() + ->getFastPropertyValue(PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES) // "ShowCustomLeaderLines" + .get<sal_Bool>(); + if (m_bPieLabelsAllowToMove) { - performLabelBestFit(rParam, aPieLabelInfo); + ::basegfx::B2IRectangle aRect(lcl_getRect(aPieLabelInfo.xLabelGroupShape)); + sal_Int32 nPageWidth = m_aPageReferenceSize.Width; + sal_Int32 nPageHeight = m_aPageReferenceSize.Height; + + // the data label should be inside the chart area + awt::Point aShapePos = aPieLabelInfo.xLabelGroupShape->getPosition(); + if (aRect.getMinX() < 0) + aPieLabelInfo.xLabelGroupShape->setPosition( + awt::Point(aShapePos.X - aRect.getMinX(), aShapePos.Y)); + if (aRect.getMinY() < 0) + aPieLabelInfo.xLabelGroupShape->setPosition( + awt::Point(aShapePos.X, aShapePos.Y - aRect.getMinY())); + if (aRect.getMaxX() > nPageWidth) + aPieLabelInfo.xLabelGroupShape->setPosition( + awt::Point(aShapePos.X - (aRect.getMaxX() - nPageWidth), aShapePos.Y)); + if (aRect.getMaxY() > nPageHeight) + aPieLabelInfo.xLabelGroupShape->setPosition( + awt::Point(aShapePos.X, aShapePos.Y - (aRect.getMaxY() - nPageHeight))); + + if (rSeries.isLabelCustomPos(nPointIndex) && bShowLeaderLine) + { + sal_Int32 nX1 = aPieLabelInfo.aOuterPosition.getX(); + sal_Int32 nY1 = aPieLabelInfo.aOuterPosition.getY(); + const sal_Int32 nX2 = std::clamp(nX1, aRect.getMinX(), aRect.getMaxX()); + const sal_Int32 nY2 = std::clamp(nY1, aRect.getMinY(), aRect.getMaxY()); + + const sal_Int32 nLabelSquaredDistanceFromOrigin + = (nX2 - aOrigin.X) * (nX2 - aOrigin.X) + (nY2 - aOrigin.Y) * (nY2 - aOrigin.Y); + // can't use fSquaredPieRadius for 3D charts, since no longer a true circle + const sal_Int32 nPieEdgeSquaredDistanceFromOrigin + = (nX1 - aOrigin.X) * (nX1 - aOrigin.X) + (nY1 - aOrigin.Y) * (nY1 - aOrigin.Y); + + // tdf#138018 Don't show leader line when custom positioned data label is inside pie chart + if (nLabelSquaredDistanceFromOrigin > nPieEdgeSquaredDistanceFromOrigin) + { + //when the line is very short compared to the page size don't create one + ::basegfx::B2DVector aLength(nX1 - nX2, nY1 - nY2); + double fPageDiagonaleLength = std::hypot(nPageWidth, nPageHeight); + if ((aLength.getLength() / fPageDiagonaleLength) >= 0.01) + { + drawing::PointSequenceSequence aPoints{ { {nX1, nY1}, {nX2, nY2} } }; + + VLineProperties aVLineProperties; + if (aPieLabelInfo.xTextShape.is()) + { + sal_Int32 nColor = 0; + aPieLabelInfo.xTextShape->SvxShape::getPropertyValue("CharColor") >>= nColor; + //automatic font color does not work for lines -> fallback to black + if (nColor != -1) + aVLineProperties.Color <<= nColor; + } + ShapeFactory::createLine2D(xTextTarget, aPoints, &aVLineProperties); + } + } + } } + aPieLabelInfo.fValue = nVal; + aPieLabelInfo.bMovementAllowed = bMovementAllowed; + aPieLabelInfo.bMoved = false; + aPieLabelInfo.xTextTarget = xTextTarget; + aPieLabelInfo.bShowLeaderLine = bShowLeaderLine && !rSeries.isLabelCustomPos(nPointIndex); + m_aLabelInfoList.push_back(aPieLabelInfo); } @@ -406,19 +735,20 @@ double PieChart::getMaxOffset() return m_fMaxOffset; VDataSeries* pSeries = rSeriesList.front().get(); - uno::Reference< beans::XPropertySet > xSeriesProp( pSeries->getPropertiesOfSeries() ); - if( !xSeriesProp.is() ) + rtl::Reference< DataSeries > xSeries( pSeries->getModel() ); + if( !xSeries.is() ) return m_fMaxOffset; double fExplodePercentage=0.0; - xSeriesProp->getPropertyValue( "Offset") >>= fExplodePercentage; + xSeries->getPropertyValue( "Offset") >>= fExplodePercentage; if(fExplodePercentage>m_fMaxOffset) m_fMaxOffset=fExplodePercentage; if(!m_bSizeExcludesLabelsAndExplodedSegments) { uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; - if( xSeriesProp->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList ) + // "AttributedDataPoints" + if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList ) { for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;) { @@ -498,18 +828,16 @@ void PieChart::createShapes() ///( a member of a VDiagram object); this initialization occurs in ///`ChartView::impl_createDiagramAndContent`. - OSL_ENSURE(m_pShapeFactory && m_xLogicTarget.is() && m_xFinalTarget.is(), "PieChart is not properly initialized."); - if (!m_pShapeFactory || !m_xLogicTarget.is() || !m_xFinalTarget.is()) + OSL_ENSURE(m_xLogicTarget.is() && m_xFinalTarget.is(), "PieChart is not properly initialized."); + if (!m_xLogicTarget.is() || !m_xFinalTarget.is()) return; ///the text labels should be always on top of the other series shapes ///therefore create an own group for the texts to move them to front ///(because the text group is created after the series group the texts are ///displayed on top) - uno::Reference< drawing::XShapes > xSeriesTarget( - createGroupShape( m_xLogicTarget )); - uno::Reference< drawing::XShapes > xTextTarget( - m_pShapeFactory->createGroup2D( m_xFinalTarget )); + rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget = createGroupShape( m_xLogicTarget ); + rtl::Reference<SvxShapeGroup> xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget ); //check necessary here that different Y axis can not be stacked in the same group? ... hm? ///pay attention that the `m_bSwapXAndY` parameter used by the polar @@ -531,22 +859,14 @@ void PieChart::createShapes() ///the angle axis scale range is [0, 1]. The max_offset parameter is used ///for exploded pie chart and its value is 0.5. - ///the `explodeable` ring is the first one except when the radius axis - ///orientation is reversed (always!?) and we are dealing with a donut: in - ///such a case the `explodeable` ring is the last one. - std::vector< VDataSeriesGroup >::size_type nExplodeableSlot = 0; - if( m_pPosHelper->isMathematicalOrientationRadius() && m_bUseRings ) - nExplodeableSlot = m_aZSlots.front().size()-1; - m_aLabelInfoList.clear(); - ::rtl::math::setNan(&m_fMaxOffset); + m_fMaxOffset = std::numeric_limits<double>::quiet_NaN(); sal_Int32 n3DRelativeHeight = 100; - uno::Reference< beans::XPropertySet > xPropertySet( m_xChartTypeModel, uno::UNO_QUERY ); - if ( (m_nDimension==3) && xPropertySet.is()) + if ( (m_nDimension==3) && m_xChartTypeModel.is()) { try { - uno::Any aAny = xPropertySet->getPropertyValue( "3DRelativeHeight" ); + uno::Any aAny = m_xChartTypeModel->getFastPropertyValue( PROP_PIECHARTTYPE_3DRELATIVEHEIGHT ); // "3DRelativeHeight" aAny >>= n3DRelativeHeight; } catch (const uno::Exception&) { } @@ -557,8 +877,6 @@ void PieChart::createShapes() ///(m_bUseRings||fSlotX<0.5) for( double fSlotX=0; aXSlotIter != aXSlotEnd && (m_bUseRings||fSlotX<0.5 ); ++aXSlotIter, fSlotX+=1.0 ) { - ShapeParam aParam; - std::vector< std::unique_ptr<VDataSeries> >* pSeriesList = &(aXSlotIter->m_aSeriesVector); if(pSeriesList->empty())//there should be only one series in each x slot continue; @@ -566,17 +884,17 @@ void PieChart::createShapes() if(!pSeries) continue; - bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor"); - /// The angle degree offset is set by the same property of the /// data series. /// Counter-clockwise offset from the 3 o'clock position. - m_pPosHelper->m_fAngleDegreeOffset = pSeries->getStartingAngle(); + m_aPosHelper.m_fAngleDegreeOffset = pSeries->getStartingAngle(); ///iterate through all points to get the sum of all entries of ///the current data series sal_Int32 nPointIndex=0; sal_Int32 nPointCount=pSeries->getTotalPointCount(); + ShapeParam aParam; + for( nPointIndex = 0; nPointIndex < nPointCount; nPointIndex++ ) { double fY = pSeries->getYValue( nPointIndex ); @@ -589,165 +907,464 @@ void PieChart::createShapes() aParam.mfLogicYSum += fabs(fY); } - if (aParam.mfLogicYSum == 0.0) + if (aParam.mfLogicYSum == 0.0) { // Total sum of all Y values in this series is zero. Skip the whole series. continue; + } - double fLogicYForNextPoint = 0.0; - ///iterate through all points to create shapes - for( nPointIndex = 0; nPointIndex < nPointCount; nPointIndex++ ) + PieDataSrcBase *pDataSrc = nullptr; + PieDataSrc normalPieSrc; + OfPieDataSrc ofPieSrc; + + // Default to regular pie if too few points for of-pie + ::css::chart2::PieChartSubType eSubType = + nPointCount >= OfPieDataSrc::minPoints ? + m_eSubType : + PieChartSubType_NONE; + + switch (eSubType) { + case PieChartSubType_NONE: + pDataSrc = &normalPieSrc; + createOneRing(SubPieType::NONE, fSlotX, aParam, xSeriesTarget, + xTextTarget, pSeries, pDataSrc, n3DRelativeHeight); + break; + case PieChartSubType_BAR: { - double fLogicInnerRadius, fLogicOuterRadius; - - ///compute the maximum relative distance offset of the current slice - ///from the pie center - ///it is worth noting that after the first invocation the maximum - ///offset value is cached, so it is evaluated only once per each - ///call to `createShapes` - double fOffset = getMaxOffset(); - - ///compute the outer and the inner radius for the current ring slice - bool bIsVisible = m_pPosHelper->getInnerAndOuterRadius( fSlotX+1.0, fLogicInnerRadius, fLogicOuterRadius, m_bUseRings, fOffset ); - if( !bIsVisible ) - continue; + pDataSrc = &ofPieSrc; + createOneRing(SubPieType::LEFT, 0, aParam, xSeriesTarget, + xTextTarget, pSeries, pDataSrc, n3DRelativeHeight); + createOneBar(SubPieType::RIGHT, aParam, xSeriesTarget, + xTextTarget, pSeries, pDataSrc, n3DRelativeHeight); + + // + // Draw connecting lines + // + double xl0, xl1, yl0, yl1, x0, y0, x1, y1, y2, y3; + + // Get coordinates of "corners" of left composite wedge + sal_Int32 nEnd = pDataSrc->getNPoints(pSeries, SubPieType::LEFT); + double compFrac = pDataSrc->getData(pSeries, nEnd - 1, + SubPieType::LEFT) / aParam.mfLogicYSum; + if (compFrac < 0.5) { + xl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale * + cos(compFrac * M_PI) + m_fLeftShift; + yl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale * + sin(compFrac * M_PI); + } else { + xl0 = m_fLeftShift; + yl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale; + } - aParam.mfDepth = getTransformedDepth() * (n3DRelativeHeight / 100.0); + // Coordinates of bar top left corner + xl1 = m_fBarLeft; + yl1 = m_fFullBarHeight / 2; - uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries, xSeriesTarget); - ///collect data point information (logic coordinates, style ): - double fLogicYValue = fabs(pSeries->getYValue( nPointIndex )); - if( std::isnan(fLogicYValue) ) - continue; - if(fLogicYValue==0.0)//@todo: continue also if the resolution is too small - continue; - double fLogicYPos = fLogicYForNextPoint; - fLogicYForNextPoint += fLogicYValue; + x0 = m_aPosHelper.transformUnitCircleToScene(0, xl0, 0).PositionX; + y0 = m_aPosHelper.transformUnitCircleToScene(90, yl0, 0).PositionY; + x1 = m_aPosHelper.transformUnitCircleToScene(0, xl1, 0).PositionX; + y1 = m_aPosHelper.transformUnitCircleToScene(90, yl1, 0).PositionY; + y2 = m_aPosHelper.transformUnitCircleToScene(90, -yl0, 0).PositionY; + y3 = m_aPosHelper.transformUnitCircleToScene(90, -yl1, 0).PositionY; - uno::Reference< beans::XPropertySet > xPointProperties = pSeries->getPropertiesOfPoint( nPointIndex ); - - //iterate through all subsystems to create partial points - { - //logic values on angle axis: - double fLogicStartAngleValue = fLogicYPos / aParam.mfLogicYSum; - double fLogicEndAngleValue = (fLogicYPos+fLogicYValue) / aParam.mfLogicYSum; - - ///note that the explode percentage is set to the `Offset` - ///property of the current data series entry only for slices - ///belonging to the outer ring - aParam.mfExplodePercentage = 0.0; - bool bDoExplode = ( nExplodeableSlot == static_cast< std::vector< VDataSeriesGroup >::size_type >(fSlotX) ); - if(bDoExplode) try - { - xPointProperties->getPropertyValue( "Offset") >>= aParam.mfExplodePercentage; - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + std::vector<std::vector<css::drawing::Position3D>> linePts; + linePts.resize(2); + linePts[0].push_back(css::drawing::Position3D(x0, y0, aParam.mfLogicZ)); + linePts[0].push_back(css::drawing::Position3D(x1, y1, aParam.mfLogicZ)); + linePts[1].push_back(css::drawing::Position3D(x0, y2, aParam.mfLogicZ)); + linePts[1].push_back(css::drawing::Position3D(x1, y3, aParam.mfLogicZ)); - ///see notes for `PolarPlottingPositionHelper` methods - ///transform to unit circle: - aParam.mfUnitCircleWidthAngleDegree = m_pPosHelper->getWidthAngleDegree( fLogicStartAngleValue, fLogicEndAngleValue ); - aParam.mfUnitCircleStartAngleDegree = m_pPosHelper->transformToAngleDegree( fLogicStartAngleValue ); - aParam.mfUnitCircleInnerRadius = m_pPosHelper->transformToRadius( fLogicInnerRadius ); - aParam.mfUnitCircleOuterRadius = m_pPosHelper->transformToRadius( fLogicOuterRadius ); + VLineProperties aVLineProperties; // default black - ///point color: - std::unique_ptr< tPropertyNameValueMap > apOverwritePropertiesMap; - if (!pSeries->hasPointOwnColor(nPointIndex) && m_xColorScheme.is()) - { - apOverwritePropertiesMap.reset( new tPropertyNameValueMap ); - (*apOverwritePropertiesMap)["FillColor"] <<= - m_xColorScheme->getColorByIndex( nPointIndex ); - } + //create line + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = + getSeriesGroupShape(pSeries, xSeriesTarget); + rtl::Reference<SvxShape> xShape = ShapeFactory::createLine2D( + xSeriesGroupShape_Shapes, linePts, &aVLineProperties); - ///create data point - aParam.mfLogicZ = -1.0; // For 3D pie chart label position - uno::Reference<drawing::XShape> xPointShape = - createDataPoint( - xSeriesGroupShape_Shapes, xPointProperties, apOverwritePropertiesMap.get(), aParam); + // need to set properties? + //PropertyMapper::setMappedProperties( *xShape, xObjectProperties, + // PropertyMapper::getPropertyNameMapForLineSeriesProperties() ); - if(bHasFillColorMapping) - { - double nPropVal = pSeries->getValueByProperty(nPointIndex, "FillColor"); - if(!std::isnan(nPropVal)) - { - uno::Reference< beans::XPropertySet > xProps( xPointShape, uno::UNO_QUERY_THROW ); - xProps->setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>( nPropVal))); - } - } + break; + } + case PieChartSubType_PIE: + { + pDataSrc = &ofPieSrc; + createOneRing(SubPieType::LEFT, 0, aParam, xSeriesTarget, + xTextTarget, pSeries, pDataSrc, n3DRelativeHeight); + createOneRing(SubPieType::RIGHT, 0, aParam, xSeriesTarget, + xTextTarget, pSeries, pDataSrc, n3DRelativeHeight); + + // + // Draw connecting lines + // + double xl0, xl1, yl0, yl1, x0, y0, x1, y1, y2, y3; + + // Get coordinates of "corners" of left composite wedge + sal_Int32 nEnd = pDataSrc->getNPoints(pSeries, SubPieType::LEFT); + double compFrac = pDataSrc->getData(pSeries, nEnd - 1, + SubPieType::LEFT) / aParam.mfLogicYSum; + // The following isn't quite right. The tangent points on the left + // pie are only at pi/2 and -pi/2 for composite wedges over 1/2 the + // total if left and right pies are the same diameter. And the + // threshold of 1/2 isn't quite right either. So there + // really should be a more sophisticated approach here. TODO + if (compFrac < 0.5) { + // Translated, per below + xl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale * + cos(compFrac * M_PI) + m_fLeftShift - m_fRightShift; + yl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale * + sin(compFrac * M_PI); + } else { + // Translated, per below + xl0 = m_fLeftShift - m_fRightShift; + yl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale; + } - ///create label - createTextLabelShape(xTextTarget, *pSeries, nPointIndex, aParam); + // Compute tangent point on the right-hand circle of the line + // through (xl0, yl0). If we translate things so the right-hand + // circle is centered on the origin, then this point (x,y) + // satisfies these two equations, where r is the radius of the + // right-hand circle: + // (1) x^2 + y^2 = r^2 + // (2) (y - yl0) / (x - xl0) = -x / y + const double r = aParam.mfUnitCircleOuterRadius * m_fRightScale; + + xl1 = (r*r * xl0 + yl0 * r * sqrt(xl0*xl0 + yl0*yl0 - r*r)) / + (xl0*xl0 + yl0*yl0); + yl1 = sqrt(r*r - xl1*xl1); + + // Now translate back to the coordinates we use + xl0 += m_fRightShift; + xl1 += m_fRightShift; + + x0 = m_aPosHelper.transformUnitCircleToScene(0, xl0, 0).PositionX; + y0 = m_aPosHelper.transformUnitCircleToScene(90, yl0, 0).PositionY; + x1 = m_aPosHelper.transformUnitCircleToScene(0, xl1, 0).PositionX; + y1 = m_aPosHelper.transformUnitCircleToScene(90, yl1, 0).PositionY; + y2 = m_aPosHelper.transformUnitCircleToScene(90, -yl0, 0).PositionY; + y3 = m_aPosHelper.transformUnitCircleToScene(90, -yl1, 0).PositionY; + + std::vector<std::vector<css::drawing::Position3D>> linePts; + linePts.resize(2); + linePts[0].push_back(css::drawing::Position3D(x0, y0, aParam.mfLogicZ)); + linePts[0].push_back(css::drawing::Position3D(x1, y1, aParam.mfLogicZ)); + linePts[1].push_back(css::drawing::Position3D(x0, y2, aParam.mfLogicZ)); + linePts[1].push_back(css::drawing::Position3D(x1, y3, aParam.mfLogicZ)); + + VLineProperties aVLineProperties; // default black + + //create line + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = + getSeriesGroupShape(pSeries, xSeriesTarget); + rtl::Reference<SvxShape> xShape = ShapeFactory::createLine2D( + xSeriesGroupShape_Shapes, linePts, &aVLineProperties); - if(!bDoExplode) - { - ShapeFactory::setShapeName( xPointShape - , ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), nPointIndex ) ); - } - else try - { - ///enable dragging of outer segments - - double fAngle = aParam.mfUnitCircleStartAngleDegree + aParam.mfUnitCircleWidthAngleDegree/2.0; - double fMaxDeltaRadius = aParam.mfUnitCircleOuterRadius-aParam.mfUnitCircleInnerRadius; - drawing::Position3D aOrigin = m_pPosHelper->transformUnitCircleToScene( fAngle, aParam.mfUnitCircleOuterRadius, aParam.mfLogicZ ); - drawing::Position3D aNewOrigin = m_pPosHelper->transformUnitCircleToScene( fAngle, aParam.mfUnitCircleOuterRadius + fMaxDeltaRadius, aParam.mfLogicZ ); - - sal_Int32 nOffsetPercent( static_cast<sal_Int32>(aParam.mfExplodePercentage * 100.0) ); - - awt::Point aMinimumPosition( PlottingPositionHelper::transformSceneToScreenPosition( - aOrigin, m_xLogicTarget, m_pShapeFactory, m_nDimension ) ); - awt::Point aMaximumPosition( PlottingPositionHelper::transformSceneToScreenPosition( - aNewOrigin, m_xLogicTarget, m_pShapeFactory, m_nDimension ) ); - - //enable dragging of piesegments - OUString aPointCIDStub( ObjectIdentifier::createSeriesSubObjectStub( OBJECTTYPE_DATA_POINT - , pSeries->getSeriesParticle() - , ObjectIdentifier::getPieSegmentDragMethodServiceName() - , ObjectIdentifier::createPieSegmentDragParameterString( - nOffsetPercent, aMinimumPosition, aMaximumPosition ) - ) ); - - ShapeFactory::setShapeName( xPointShape - , ObjectIdentifier::createPointCID( aPointCIDStub, nPointIndex ) ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } - }//next series in x slot (next y slot) - }//next category + break; + } + default: + assert(false); // this shouldn't happen + } }//next x slot } -namespace +static sal_Int32 propIndex( + sal_Int32 nPointIndex, + enum SubPieType eType, + const PieDataSrcBase *pDataSrc, + VDataSeries* pSeries) { -::basegfx::B2IRectangle lcl_getRect( const uno::Reference< drawing::XShape >& xShape ) -{ - ::basegfx::B2IRectangle aRect; - if( xShape.is() ) - aRect = BaseGFXHelper::makeRectangle(xShape->getPosition(),xShape->getSize() ); - return aRect; + switch (eType) { + case SubPieType::LEFT: + if (nPointIndex == pDataSrc->getNPoints(pSeries, + SubPieType::LEFT) - 1) { + return pSeries->getTotalPointCount(); + } else { + return nPointIndex; + } + break; + case SubPieType::RIGHT: + return pDataSrc->getNPoints(pSeries, SubPieType::LEFT) + + nPointIndex - 1; + break; + case SubPieType::NONE: + return nPointIndex; + break; + default: // shouldn't happen + assert(false); + return 0; // suppress compile warning + } } -bool lcl_isInsidePage( const awt::Point& rPos, const awt::Size& rSize, const awt::Size& rPageSize ) + +void PieChart::createOneRing( + enum SubPieType eType, + double fSlotX, + ShapeParam& aParam, + const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget, + const rtl::Reference<SvxShapeGroup>& xTextTarget, + VDataSeries* pSeries, + const PieDataSrcBase *pDataSrc, + sal_Int32 n3DRelativeHeight) { - if( rPos.X < 0 || rPos.Y < 0 ) - return false; - if( (rPos.X + rSize.Width) > rPageSize.Width ) - return false; - if( (rPos.Y + rSize.Height) > rPageSize.Height ) - return false; - return true; + bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor"); + + sal_Int32 nRingPtCnt = pDataSrc->getNPoints(pSeries, eType); + + // Find sum of entries for this ring or sub-pie + double ringSum = 0; + for (sal_Int32 nPointIndex = 0; nPointIndex < nRingPtCnt; nPointIndex++ ) { + double fY = pDataSrc->getData(pSeries, nPointIndex, eType); + if (!std::isnan(fY) ) ringSum += fY; + } + + // determine the starting angle around the ring + auto sAngle = [&]() + { + if (eType == SubPieType::LEFT) { + // Left of-pie has the "composite" wedge (the one expanded in the right + // subgraph) facing to the right in the chart, to allow the expansion + // lines to meet it + const double compositeVal = pDataSrc->getData(pSeries, nRingPtCnt - 1, eType); + const double degAng = compositeVal * 360 / (ringSum * 2); + return m_aPosHelper.clockwiseWedges() ? 360 - degAng : degAng; + } else { + /// The angle degree offset is set by the same property of the + /// data series. + /// Counter-clockwise offset from the 3 o'clock position. + return static_cast<double>(pSeries->getStartingAngle()); + } + }; + + m_aPosHelper.m_fAngleDegreeOffset = sAngle(); + + ///the `explodeable` ring is the first one except when the radius axis + ///orientation is reversed (always!?) and we are dealing with a donut: in + ///such a case the `explodeable` ring is the last one. + std::vector< VDataSeriesGroup >::size_type nExplodeableSlot = 0; + if( m_aPosHelper.isMathematicalOrientationRadius() && m_bUseRings ) + nExplodeableSlot = m_aZSlots.front().size()-1; + + double fLogicYForNextPoint = 0.0; + ///iterate through all points to create shapes + for(sal_Int32 nPointIndex = 0; nPointIndex < nRingPtCnt; nPointIndex++ ) + { + double fLogicInnerRadius, fLogicOuterRadius; + + ///compute the maximum relative distance offset of the current slice + ///from the pie center + ///it is worth noting that after the first invocation the maximum + ///offset value is cached, so it is evaluated only once per each + ///call to `createShapes` + double fOffset = getMaxOffset(); + + ///compute the outer and the inner radius for the current ring slice + bool bIsVisible = m_aPosHelper.getInnerAndOuterRadius( fSlotX+1.0, fLogicInnerRadius, fLogicOuterRadius, m_bUseRings, fOffset ); + if( !bIsVisible ) + continue; + + aParam.mfDepth = getTransformedDepth() * (n3DRelativeHeight / 100.0); + + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries, xSeriesTarget); + + ///collect data point information (logic coordinates, style ): + double fLogicYValue = pDataSrc->getData(pSeries, nPointIndex, eType); + if( std::isnan(fLogicYValue) ) + continue; + if(fLogicYValue==0.0)//@todo: continue also if the resolution is too small + continue; + double fLogicYPos = fLogicYForNextPoint; + fLogicYForNextPoint += fLogicYValue; + + uno::Reference< beans::XPropertySet > xPointProperties = + pDataSrc->getProps(pSeries, nPointIndex, eType); + + //iterate through all subsystems to create partial points + { + //logic values on angle axis: + double fLogicStartAngleValue = fLogicYPos / ringSum; + double fLogicEndAngleValue = (fLogicYPos+fLogicYValue) / ringSum; + + ///note that the explode percentage is set to the `Offset` + ///property of the current data series entry only for slices + ///belonging to the outer ring + aParam.mfExplodePercentage = 0.0; + bool bDoExplode = ( nExplodeableSlot == static_cast< std::vector< VDataSeriesGroup >::size_type >(fSlotX) ); + if(bDoExplode) try + { + xPointProperties->getPropertyValue( "Offset") >>= aParam.mfExplodePercentage; + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + + ///see notes for `PolarPlottingPositionHelper` methods + ///transform to unit circle: + aParam.mfUnitCircleWidthAngleDegree = m_aPosHelper.getWidthAngleDegree( fLogicStartAngleValue, fLogicEndAngleValue ); + aParam.mfUnitCircleStartAngleDegree = m_aPosHelper.transformToAngleDegree( fLogicStartAngleValue ); + aParam.mfUnitCircleInnerRadius = m_aPosHelper.transformToRadius( fLogicInnerRadius ); + aParam.mfUnitCircleOuterRadius = m_aPosHelper.transformToRadius( fLogicOuterRadius ); + + ///create data point + aParam.mfLogicZ = -1.0; // For 3D pie chart label position + + // Do concentric explosion if it's a donut chart with more than one series + const bool bConcentricExplosion = m_bUseRings && (m_aZSlots.front().size() > 1); + rtl::Reference<SvxShape> xPointShape = + createDataPoint(eType, xSeriesGroupShape_Shapes, + xPointProperties, aParam, nRingPtCnt, + bConcentricExplosion); + + // Handle coloring of the composite wedge + sal_Int32 nPropIdx = propIndex(nPointIndex, eType, pDataSrc, + pSeries); + + ///point color: + if (!pSeries->hasPointOwnColor(nPropIdx) && m_xColorScheme.is()) + { + xPointShape->setPropertyValue("FillColor", + uno::Any(m_xColorScheme->getColorByIndex( nPropIdx ))); + } + + + if(bHasFillColorMapping) + { + double nPropVal = pSeries->getValueByProperty(nPropIdx, "FillColor"); + if(!std::isnan(nPropVal)) + { + xPointShape->setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>( nPropVal))); + } + } + + ///create label + createTextLabelShape(xTextTarget, *pSeries, nPropIdx, aParam); + + if(!bDoExplode) + { + ShapeFactory::setShapeName( xPointShape + , ObjectIdentifier::createPointCID( + pSeries->getPointCID_Stub(), nPropIdx ) ); + } + else try + { + ///enable dragging of outer segments + + double fAngle = aParam.mfUnitCircleStartAngleDegree + aParam.mfUnitCircleWidthAngleDegree/2.0; + double fMaxDeltaRadius = aParam.mfUnitCircleOuterRadius-aParam.mfUnitCircleInnerRadius; + drawing::Position3D aOrigin = m_aPosHelper.transformUnitCircleToScene( fAngle, aParam.mfUnitCircleOuterRadius, aParam.mfLogicZ ); + drawing::Position3D aNewOrigin = m_aPosHelper.transformUnitCircleToScene( fAngle, aParam.mfUnitCircleOuterRadius + fMaxDeltaRadius, aParam.mfLogicZ ); + + sal_Int32 nOffsetPercent( static_cast<sal_Int32>(aParam.mfExplodePercentage * 100.0) ); + + awt::Point aMinimumPosition( PlottingPositionHelper::transformSceneToScreenPosition( + aOrigin, m_xLogicTarget, m_nDimension ) ); + awt::Point aMaximumPosition( PlottingPositionHelper::transformSceneToScreenPosition( + aNewOrigin, m_xLogicTarget, m_nDimension ) ); + + //enable dragging of piesegments + OUString aPointCIDStub( ObjectIdentifier::createSeriesSubObjectStub( OBJECTTYPE_DATA_POINT + , pSeries->getSeriesParticle() + , ObjectIdentifier::getPieSegmentDragMethodServiceName() + , ObjectIdentifier::createPieSegmentDragParameterString( + nOffsetPercent, aMinimumPosition, aMaximumPosition ) + ) ); + + ShapeFactory::setShapeName( xPointShape + , ObjectIdentifier::createPointCID( aPointCIDStub, + nPropIdx ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + }//next series in x slot (next y slot) + }//next category } -}//end anonymous namespace +void PieChart::createOneBar( + enum SubPieType eType, + ShapeParam& aParam, + const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget, + const rtl::Reference<SvxShapeGroup>& xTextTarget, + VDataSeries* pSeries, + const PieDataSrcBase *pDataSrc, + sal_Int32 n3DRelativeHeight) +{ + bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor"); + + sal_Int32 nBarPtCnt = pDataSrc->getNPoints(pSeries, eType); + + // Find sum of entries for this bar chart + double barSum = 0; + for (sal_Int32 nPointIndex = 0; nPointIndex < nBarPtCnt; nPointIndex++ ) { + double fY = pDataSrc->getData(pSeries, nPointIndex, eType); + if (!std::isnan(fY) ) barSum += fY; + } + + double fBarBottom = 0.0; + double fBarTop = -0.5; // make the bar go from -0.5 to 0.5 + ///iterate through all points to create shapes + for(sal_Int32 nPointIndex = 0; nPointIndex < nBarPtCnt; nPointIndex++ ) + { + aParam.mfDepth = getTransformedDepth() * (n3DRelativeHeight / 100.0); + + rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries, xSeriesTarget); + + ///collect data point information (logic coordinates, style ): + double fY = pDataSrc->getData(pSeries, nPointIndex, eType) / barSum; + if( std::isnan(fY) ) + continue; + if(fY==0.0)//@todo: continue also if the resolution is too small + continue; + fBarBottom = fBarTop; + fBarTop += fY; + + uno::Reference< beans::XPropertySet > xPointProperties = + pDataSrc->getProps(pSeries, nPointIndex, eType); + + ///create data point + aParam.mfLogicZ = -1.0; // For 3D pie chart label position + + rtl::Reference<SvxShape> xPointShape = + createBarDataPoint(xSeriesGroupShape_Shapes, + xPointProperties, aParam, + fBarBottom, fBarTop); + + sal_Int32 nPropIdx = propIndex(nPointIndex, eType, pDataSrc, pSeries); + + ///point color: + if (!pSeries->hasPointOwnColor(nPropIdx) && m_xColorScheme.is()) + { + xPointShape->setPropertyValue("FillColor", + uno::Any(m_xColorScheme->getColorByIndex( nPropIdx ))); + } + + + if(bHasFillColorMapping) + { + double nPropVal = pSeries->getValueByProperty(nPropIdx, "FillColor"); + if(!std::isnan(nPropVal)) + { + xPointShape->setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>( nPropVal))); + } + } + + ///create label + createTextLabelShape(xTextTarget, *pSeries, nPropIdx, aParam); + + ShapeFactory::setShapeName( xPointShape, + ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), + nPropIdx ) ); + }//next category +} PieChart::PieLabelInfo::PieLabelInfo() - : aFirstPosition(), aOrigin(), fValue(0.0) - , bMovementAllowed(false), bMoved(false), pPrevious(nullptr),pNext(nullptr) + : fValue(0.0) + , bMovementAllowed(false), bMoved(false) + , bShowLeaderLine(false), pPrevious(nullptr) + , pNext(nullptr) { } @@ -770,48 +1387,49 @@ bool PieChart::PieLabelInfo::moveAwayFrom( const PieChart::PieLabelInfo* pFix, c ///boxes (`aOverlap`). ::basegfx::B2IRectangle aOverlap( lcl_getRect( xLabelGroupShape ) ); aOverlap.intersect( lcl_getRect( pFix->xLabelGroupShape ) ); - if( !aOverlap.isEmpty() ) - { - //TODO: alternative move direction - - ///the label is shifted along the direction orthogonal to the vector - ///starting at the pie/donut center and ending at this label anchor - ///point; - - ///named `aTangentialDirection` the unit vector related to such a - ///direction, the magnitude of the shift along such a direction is - ///calculated in this way: if the horizontal component of - ///`aTangentialDirection` is greater than the vertical component, - ///the magnitude of the shift is equal to `aOverlap.Width` else to - ///`aOverlap.Height`; - basegfx::B2IVector aRadiusDirection = aFirstPosition - aOrigin; - aRadiusDirection.setLength(1.0); - basegfx::B2IVector aTangentialDirection( -aRadiusDirection.getY(), aRadiusDirection.getX() ); - bool bShiftHorizontal = abs(aTangentialDirection.getX()) > abs(aTangentialDirection.getY()); - sal_Int32 nShift = bShiftHorizontal ? static_cast<sal_Int32>(aOverlap.getWidth()) : static_cast<sal_Int32>(aOverlap.getHeight()); - ///the magnitude of the shift is also increased by 1/50-th of the width - ///or the height of the document page; - nShift += (bShiftHorizontal ? nLabelDistanceX : nLabelDistanceY); - ///in case the `bMoveHalfWay` parameter is true the magnitude of - ///the shift is halved. - if( bMoveHalfWay ) - nShift/=2; - ///in case the `bMoveClockwise` parameter is false the direction of - ///`aTangentialDirection` is reversed; - if(!bMoveClockwise) - nShift*=-1; - awt::Point aOldPos( xLabelGroupShape->getPosition() ); - basegfx::B2IVector aNewPos = basegfx::B2IVector( aOldPos.X, aOldPos.Y ) + nShift*aTangentialDirection; - - ///a final check is performed in order to be sure that the moved label - ///is still inside the page document; - awt::Point aNewAWTPos( aNewPos.getX(), aNewPos.getY() ); - if( !lcl_isInsidePage( aNewAWTPos, xLabelGroupShape->getSize(), rPageSize ) ) - return false; + if( aOverlap.isEmpty() ) + return true; + + //TODO: alternative move direction + + ///the label is shifted along the direction orthogonal to the vector + ///starting at the pie/donut center and ending at this label anchor + ///point; + + ///named `aTangentialDirection` the unit vector related to such a + ///direction, the magnitude of the shift along such a direction is + ///calculated in this way: if the horizontal component of + ///`aTangentialDirection` is greater than the vertical component, + ///the magnitude of the shift is equal to `aOverlap.Width` else to + ///`aOverlap.Height`; + basegfx::B2IVector aRadiusDirection = aFirstPosition - aOrigin; + aRadiusDirection.setLength(1.0); + basegfx::B2IVector aTangentialDirection( -aRadiusDirection.getY(), aRadiusDirection.getX() ); + bool bShiftHorizontal = abs(aTangentialDirection.getX()) > abs(aTangentialDirection.getY()); + sal_Int32 nShift = bShiftHorizontal ? static_cast<sal_Int32>(aOverlap.getWidth()) : static_cast<sal_Int32>(aOverlap.getHeight()); + ///the magnitude of the shift is also increased by 1/50-th of the width + ///or the height of the document page; + nShift += (bShiftHorizontal ? nLabelDistanceX : nLabelDistanceY); + ///in case the `bMoveHalfWay` parameter is true the magnitude of + ///the shift is halved. + if( bMoveHalfWay ) + nShift/=2; + ///in case the `bMoveClockwise` parameter is false the direction of + ///`aTangentialDirection` is reversed; + if(!bMoveClockwise) + nShift*=-1; + awt::Point aOldPos( xLabelGroupShape->getPosition() ); + basegfx::B2IVector aNewPos = basegfx::B2IVector( aOldPos.X, aOldPos.Y ) + nShift*aTangentialDirection; + + ///a final check is performed in order to be sure that the moved label + ///is still inside the page document; + awt::Point aNewAWTPos( aNewPos.getX(), aNewPos.getY() ); + if( !lcl_isInsidePage( aNewAWTPos, xLabelGroupShape->getSize(), rPageSize ) ) + return false; + + xLabelGroupShape->setPosition( aNewAWTPos ); + bMoved = true; - xLabelGroupShape->setPosition( aNewAWTPos ); - bMoved = true; - } return true; ///note that no further test is performed in order to check that the @@ -989,7 +1607,7 @@ bool PieChart::tryMoveLabels( PieLabelInfo const * pFirstBorder, PieLabelInfo co PieLabelInfo* p2 = pCenter->pNext; //return true when successful - bool bLabelOrderIsAntiClockWise = m_pPosHelper->isMathematicalOrientationAngle(); + bool bLabelOrderIsAntiClockWise = m_aPosHelper.isMathematicalOrientationAngle(); ///two loops are performed simultaneously: the outer loop iterates on ///`PieLabelInfo` objects in the list starting from the central element @@ -1099,7 +1717,7 @@ void PieChart::rearrangeLabelToAvoidOverlapIfRequested( const awt::Size& rPageSi if(!bMoveableFound) return; - double fPageDiagonaleLength = sqrt( double(rPageSize.Width)*double(rPageSize.Width) + double(rPageSize.Height)*double(rPageSize.Height) ); + double fPageDiagonaleLength = std::hypot(rPageSize.Width, rPageSize.Height); if( fPageDiagonaleLength == 0.0 ) return; @@ -1127,44 +1745,29 @@ void PieChart::rearrangeLabelToAvoidOverlapIfRequested( const awt::Size& rPageSi VLineProperties aVLineProperties; for (auto const& labelInfo : m_aLabelInfoList) { - if( labelInfo.bMoved ) + if( labelInfo.bMoved && labelInfo.bShowLeaderLine ) { - sal_Int32 nX1 = labelInfo.aFirstPosition.getX(); - sal_Int32 nY1 = labelInfo.aFirstPosition.getY(); - sal_Int32 nX2 = nX1; - sal_Int32 nY2 = nY1; - ::basegfx::B2IRectangle aRect( lcl_getRect( labelInfo.xLabelGroupShape ) ); - if( nX1 < aRect.getMinX() ) - nX2 = aRect.getMinX(); - else if( nX1 > aRect.getMaxX() ) - nX2 = aRect.getMaxX(); - - if( nY1 < aRect.getMinY() ) - nY2 = aRect.getMinY(); - else if( nY1 > aRect.getMaxY() ) - nY2 = aRect.getMaxY(); + const basegfx::B2IRectangle aRect(lcl_getRect(labelInfo.xLabelGroupShape)); + sal_Int32 nX1 = labelInfo.aOuterPosition.getX(); + sal_Int32 nY1 = labelInfo.aOuterPosition.getY(); + const sal_Int32 nX2 = std::clamp(nX1, aRect.getMinX(), aRect.getMaxX()); + const sal_Int32 nY2 = std::clamp(nY1, aRect.getMinY(), aRect.getMaxY()); //when the line is very short compared to the page size don't create one ::basegfx::B2DVector aLength(nX1-nX2, nY1-nY2); if( (aLength.getLength()/fPageDiagonaleLength) < 0.01 ) continue; - drawing::PointSequenceSequence aPoints(1); - aPoints[0].realloc(2); - aPoints[0][0].X = nX1; - aPoints[0][0].Y = nY1; - aPoints[0][1].X = nX2; - aPoints[0][1].Y = nY2; + drawing::PointSequenceSequence aPoints{ { {nX1, nY1}, {nX2, nY2} } }; - uno::Reference< beans::XPropertySet > xProp( labelInfo.xTextShape, uno::UNO_QUERY); - if( xProp.is() ) + if( labelInfo.xTextShape.is() ) { sal_Int32 nColor = 0; - xProp->getPropertyValue("CharColor") >>= nColor; + labelInfo.xTextShape->SvxShape::getPropertyValue("CharColor") >>= nColor; if( nColor != -1 )//automatic font color does not work for lines -> fallback to black aVLineProperties.Color <<= nColor; } - m_pShapeFactory->createLine2D( labelInfo.xTextTarget, aPoints, &aVLineProperties ); + ShapeFactory::createLine2D( labelInfo.xTextTarget, aPoints, &aVLineProperties ); } } } @@ -1259,11 +1862,11 @@ bool PieChart::performLabelBestFitInnerPlacement(ShapeParam& rShapeParam, PieLab // get the middle point of the arc representing the pie slice border double fLogicZ = rShapeParam.mfLogicZ + 1.0; awt::Point aMiddleArcPoint = PlottingPositionHelper::transformSceneToScreenPosition( - m_pPosHelper->transformUnitCircleToScene( + m_aPosHelper.transformUnitCircleToScene( fBisectingRayAngleDeg, rShapeParam.mfUnitCircleOuterRadius, fLogicZ ), - m_xLogicTarget, m_pShapeFactory, m_nDimension ); + m_xLogicTarget, m_nDimension ); // compute the pie radius basegfx::B2IVector aPieCenter = rPieLabelInfo.aOrigin; @@ -1345,8 +1948,7 @@ bool PieChart::performLabelBestFitInnerPlacement(ShapeParam& rShapeParam, PieLab // compute the length of the diagonal vector d, // that is the distance between P and F - double fSquaredDistancePF = fDistancePM * fDistancePM + fOrthogonalEdgeLength * fOrthogonalEdgeLength; - double fDistancePF = sqrt( fSquaredDistancePF ); + double fDistancePF = std::hypot(fDistancePM, fOrthogonalEdgeLength); SAL_INFO( "chart2.pie.label.bestfit.inside", " width = " << fLabelWidth ); @@ -1556,64 +2158,90 @@ bool PieChart::performLabelBestFitInnerPlacement(ShapeParam& rShapeParam, PieLab return true; } -/** Handle the placement of the label in the best fit case. - * First off the routine try to place the label inside the related pie slice, - * if this is not possible the label is placed outside. - */ -void PieChart::performLabelBestFit(ShapeParam& rShapeParam, PieLabelInfo const & rPieLabelInfo) +//======================= +// class PieDataSrc +//======================= +double PieDataSrc::getData(const VDataSeries* pSeries, sal_Int32 nPtIdx, + [[maybe_unused]] enum SubPieType eType) const { - if( m_bUseRings ) - return; + return fabs(pSeries->getYValue( nPtIdx )); +} - if( performLabelBestFitInnerPlacement(rShapeParam, rPieLabelInfo) ) - return; +sal_Int32 PieDataSrc::getNPoints(const VDataSeries* pSeries, + [[maybe_unused]] enum SubPieType eType) const +{ + assert(eType == SubPieType::NONE); + return pSeries->getTotalPointCount(); +} - // If it does not fit inside, let's put it outside - awt::Point aOldPos(rPieLabelInfo.xLabelGroupShape->getPosition()); - basegfx::B2IVector aTranslationVector = rPieLabelInfo.aFirstPosition - rPieLabelInfo.aOrigin; - awt::Point aScreenPosition2D(aOldPos.X + aTranslationVector.getX(), - aOldPos.Y + aTranslationVector.getY()); +uno::Reference< beans::XPropertySet > PieDataSrc::getProps( + const VDataSeries* pSeries, sal_Int32 nPtIdx, + [[maybe_unused]] enum SubPieType eType) const +{ + assert(eType == SubPieType::NONE); + return pSeries->getPropertiesOfPoint(nPtIdx); +} - double fAngleDegree = rShapeParam.mfUnitCircleStartAngleDegree + rShapeParam.mfUnitCircleWidthAngleDegree / 2.0; - ::basegfx::B2IRectangle aBb(lcl_getRect(rPieLabelInfo.xLabelGroupShape)); - double fLabelWidth = aBb.getWidth(); - double fLabelHeight = aBb.getHeight(); - while (fAngleDegree > 360.0) - fAngleDegree -= 360.0; - while (fAngleDegree < 0.0) - fAngleDegree += 360.0; +//======================= +// class OfPieDataSrc +//======================= - if (fAngleDegree <= 22.5 || fAngleDegree >= 337.5) - aScreenPosition2D.X += fLabelWidth / 2; - else if (fAngleDegree < 67.5) - { - aScreenPosition2D.X += fLabelWidth / 2; - aScreenPosition2D.Y -= fLabelHeight / 2; - } - else if (fAngleDegree < 112.5) - aScreenPosition2D.Y -= fLabelHeight / 2; - else if (fAngleDegree <= 157.5) - { - aScreenPosition2D.X -= fLabelWidth / 2; - aScreenPosition2D.Y -= fLabelHeight / 2; - } - else if (fAngleDegree <= 202.5) - aScreenPosition2D.X -= fLabelWidth / 2; - else if (fAngleDegree < 247.5) - { - aScreenPosition2D.X -= fLabelWidth / 2; - aScreenPosition2D.Y += fLabelHeight / 2; +// For now, just implement the default Excel behavior, which is that the +// right pie consists of the last three entries in the series. Other +// behaviors should be supported later. +// TODO + +sal_Int32 OfPieDataSrc::getNPoints(const VDataSeries* pSeries, + enum SubPieType eType) const +{ + if (eType == SubPieType::LEFT) { + return pSeries->getTotalPointCount() - 2; + } else { + assert(eType == SubPieType::RIGHT); + return 3; } - else if (fAngleDegree < 292.5) - aScreenPosition2D.Y += fLabelHeight / 2; - else - { - aScreenPosition2D.X += fLabelWidth / 2; - aScreenPosition2D.Y += fLabelHeight / 2; +} + +double OfPieDataSrc::getData(const VDataSeries* pSeries, sal_Int32 nPtIdx, + enum SubPieType eType) const +{ + const sal_Int32 n = pSeries->getTotalPointCount() - 3; + if (eType == SubPieType::LEFT) { + // nPtIdx should be in [0, n] + if (nPtIdx < n) { + return fabs(pSeries->getYValue( nPtIdx )); + } else { + assert(nPtIdx == n); + return fabs(pSeries->getYValue(n)) + + fabs(pSeries->getYValue(n+1)) + + fabs(pSeries->getYValue(n+2)); + } + } else { + assert(eType == SubPieType::RIGHT); + return fabs(pSeries->getYValue(nPtIdx + n)); } +} - rPieLabelInfo.xLabelGroupShape->setPosition(aScreenPosition2D); +uno::Reference< beans::XPropertySet > OfPieDataSrc::getProps( + const VDataSeries* pSeries, sal_Int32 nPtIdx, + enum SubPieType eType) const +{ + const sal_Int32 nPts = pSeries->getTotalPointCount(); + const sal_Int32 n = nPts - 3; + if (eType == SubPieType::LEFT) { + // nPtIdx should be in [0, n] + if (nPtIdx < n) { + return pSeries->getPropertiesOfPoint( nPtIdx ); + } else { + // The aggregated wedge + assert(nPtIdx == n); + return pSeries->getPropertiesOfPoint(nPts); + } + } else { + assert(eType == SubPieType::RIGHT); + return pSeries->getPropertiesOfPoint(nPtIdx + n); + } } } //namespace chart diff --git a/chart2/source/view/charttypes/PieChart.hxx b/chart2/source/view/charttypes/PieChart.hxx index a176adaaf44a..ccbe9cb94d94 100644 --- a/chart2/source/view/charttypes/PieChart.hxx +++ b/chart2/source/view/charttypes/PieChart.hxx @@ -17,18 +17,107 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_PIECHART_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_PIECHART_HXX +#pragma once #include <memory> #include <VSeriesPlotter.hxx> +#include <PlottingPositionHelper.hxx> #include <basegfx/vector/b2ivector.hxx> #include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/chart2/PieChartSubType.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; namespace chart { -class PiePositionHelper; +class PiePositionHelper : public PolarPlottingPositionHelper +{ +public: + PiePositionHelper( double fAngleDegreeOffset ); + + bool getInnerAndOuterRadius( double fCategoryX, double& fLogicInnerRadius, double& fLogicOuterRadius, bool bUseRings, double fMaxOffset ) const; + + // Determine if the pie wedges are ordered clockwise (returns true) or + // counterclockwise (returns false) + bool clockwiseWedges() const; + +public: + //Distance between different category rings, seen relative to width of a ring: + double m_fRingDistance; //>=0 m_fRingDistance=1 --> distance == width +}; + +enum class SubPieType { + NONE, // solo pie or donut + LEFT, // left pie in pie-of-pie + RIGHT // right pie in pie-of-pie +}; + + +//======================= +// class PieDataSrcBase +//======================= +class PieDataSrcBase +{ +public: + PieDataSrcBase() = default; + virtual ~PieDataSrcBase() = default; + + // Number of data points for given pie subtype + virtual sal_Int32 getNPoints(const VDataSeries* pSeries, + enum SubPieType eType) const = 0; + + // Get the value for the given pie wedge, for the given subtype + virtual double getData(const VDataSeries* pSeries, sal_Int32 nPtIdx, + enum SubPieType eType) const = 0; + + // Get the properties for the wedge and subtype + virtual uno::Reference< beans::XPropertySet > getProps( + const VDataSeries* pSeries, sal_Int32 nPtIdx, + enum SubPieType eType) const = 0; +}; + +//======================= +// class PieDataSrc +//======================= +class PieDataSrc : public PieDataSrcBase +{ +public: + sal_Int32 getNPoints(const VDataSeries* pSeries, + enum SubPieType eType) const; + + double getData(const VDataSeries* pSeries, sal_Int32 nPtIdx, + [[maybe_unused]]enum SubPieType eType) const; + + virtual uno::Reference< beans::XPropertySet > getProps( + const VDataSeries* pSeries, sal_Int32 nPtIdx, + enum SubPieType eType) const; +}; + +//======================= +// class OfPieDataSrc +//======================= +class OfPieDataSrc : public PieDataSrcBase +{ +public: + // Minimum sensible number of data points + static constexpr sal_Int32 minPoints = 4; + + sal_Int32 getNPoints(const VDataSeries* pSeries, + enum SubPieType eType) const; + + double getData(const VDataSeries* pSeries, sal_Int32 nPtIdx, + enum SubPieType eType) const; + + virtual uno::Reference< beans::XPropertySet > getProps( + const VDataSeries* pSeries, sal_Int32 nPtIdx, + enum SubPieType eType) const; +}; + +//======================= +// class PieChart +//======================= class PieChart : public VSeriesPlotter { struct ShapeParam; @@ -36,7 +125,7 @@ class PieChart : public VSeriesPlotter public: PieChart() = delete; - PieChart( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + PieChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel , sal_Int32 nDimensionCount, bool bExcludingPositioning ); virtual ~PieChart() override; @@ -45,7 +134,7 @@ public: virtual void createShapes() override; virtual void rearrangeLabelToAvoidOverlapIfRequested( const css::awt::Size& rPageSize ) override; - virtual void setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) override; + virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) override; virtual void addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot ) override; virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override; @@ -64,13 +153,20 @@ public: virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override; private: //methods - css::uno::Reference<css::drawing::XShape> + rtl::Reference<SvxShape> createDataPoint( - const css::uno::Reference<css::drawing::XShapes>& xTarget, + enum SubPieType eType, + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const css::uno::Reference<css::beans::XPropertySet>& xObjectProperties, - tPropertyNameValueMap const * pOverWritePropertiesMap, - const ShapeParam& rParam ); + const ShapeParam& rParam, + const sal_Int32 nPointCount, + const bool bConcentricExplosion); + rtl::Reference<SvxShape> createBarDataPoint( + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, + const uno::Reference<beans::XPropertySet>& xObjectProperties, + const ShapeParam& rParam, + double fBarSegBottom, double fBarSegTop); /** This method creates a text shape for a label of a data point. * * @param xTextTarget @@ -83,7 +179,7 @@ private: //methods * ShapeParam object. */ void createTextLabelShape( - const css::uno::Reference<css::drawing::XShapes>& xTextTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, VDataSeries& rSeries, sal_Int32 nPointIndex, ShapeParam& rParam ); /** This method sets `m_fMaxOffset` to the maximum `Offset` property and @@ -106,14 +202,51 @@ struct PieLabelInfo; , PieLabelInfo* pCenter, bool bSingleCenter, bool& rbAlternativeMoveDirection , const css::awt::Size& rPageSize ); - bool performLabelBestFitInnerPlacement(ShapeParam& rShapeParam, PieLabelInfo const & rPieLabelInfo); - void performLabelBestFit(ShapeParam& rShapeParam, PieLabelInfo const & rPieLabelInfo); + bool performLabelBestFitInnerPlacement( ShapeParam& rShapeParam + , PieLabelInfo const & rPieLabelInfo ); + + // A standalone pie, one pie in a pie-of-pie, or one ring of a donut + void createOneRing([[maybe_unused]]enum SubPieType eType + , double fSlotX + , ShapeParam& aParam + , const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget + , const rtl::Reference<SvxShapeGroup>& xTextTarget + , VDataSeries* pSeries + , const PieDataSrcBase *pDataSrc + , sal_Int32 n3DRelativeHeight); + + // A bar chart in a bar-of-pie + void createOneBar( + enum SubPieType eType, + ShapeParam& aParam, + const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget, + const rtl::Reference<SvxShapeGroup>& xTextTarget, + VDataSeries* pSeries, + const PieDataSrcBase *pDataSrc, + sal_Int32 n3DRelativeHeight); private: //member - std::unique_ptr<PiePositionHelper> - m_pPosHelper; + // Constants for of-pie charts. Some of these will want to become + // user-selectable values. TODO + + // Radius scalings for left and right of-pie subcharts + static constexpr double m_fLeftScale = 2.0/3; + static constexpr double m_fRightScale = 1.0/3; + // Shifts left/right for of-pie subcharts + static constexpr double m_fLeftShift = -0.75; + static constexpr double m_fRightShift = 0.75; + // Height of bar-of-pie bar + static constexpr double m_fFullBarHeight = 1.0; + // Bar-of-pie bar left side position + static constexpr double m_fBarLeft = 0.75; + // Bar-of-pie bar right side position + static constexpr double m_fBarRight = 1.25; + + PiePositionHelper m_aPosHelper; + bool m_bUseRings; bool m_bSizeExcludesLabelsAndExplodedSegments; + ::css::chart2::PieChartSubType m_eSubType; struct PieLabelInfo { @@ -121,14 +254,16 @@ private: //member bool moveAwayFrom( const PieLabelInfo* pFix, const css::awt::Size& rPageSize , bool bMoveHalfWay, bool bMoveClockwise ); - css::uno::Reference< css::drawing::XShape > xTextShape; - css::uno::Reference< css::drawing::XShape > xLabelGroupShape; + rtl::Reference< SvxShapeText > xTextShape; + rtl::Reference< SvxShapeGroupAnyD > xLabelGroupShape; ::basegfx::B2IVector aFirstPosition; + ::basegfx::B2IVector aOuterPosition; ::basegfx::B2IVector aOrigin; double fValue; bool bMovementAllowed; bool bMoved; - css::uno::Reference< css::drawing::XShapes > xTextTarget; + bool bShowLeaderLine; + rtl::Reference<SvxShapeGroupAnyD> xTextTarget; PieLabelInfo* pPrevious; PieLabelInfo* pNext; css::awt::Point aPreviousPosition; @@ -138,7 +273,7 @@ private: //member double m_fMaxOffset; /// cached max offset value (init'ed to NaN) }; + } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/Splines.cxx b/chart2/source/view/charttypes/Splines.cxx index 774d5fc1d7ac..15980b638bc8 100644 --- a/chart2/source/view/charttypes/Splines.cxx +++ b/chart2/source/view/charttypes/Splines.cxx @@ -18,13 +18,14 @@ */ #include "Splines.hxx" -#include <rtl/math.hxx> #include <osl/diagnose.h> -#include <com/sun/star/drawing/PolyPolygonShape3D.hpp> +#include <com/sun/star/drawing/Position3D.hpp> #include <vector> #include <algorithm> -#include <memory> +#include <optional> +#include <cmath> +#include <limits> namespace chart { @@ -51,7 +52,7 @@ public: derivation equal to this value at the x-value of the last point of rSortedPoints */ - lcl_SplineCalculation( const tPointVecType & rSortedPoints, + lcl_SplineCalculation( tPointVecType && rSortedPoints, double fY1FirstDerivation, double fYnFirstDerivation ); @@ -61,7 +62,7 @@ public: @param rSortedPoints the points for which splines shall be calculated, they need to be sorted in x values. First and last y value must be equal */ - explicit lcl_SplineCalculation( const tPointVecType & rSortedPoints); + explicit lcl_SplineCalculation( tPointVecType && rSortedPoints); /** @descr this function corresponds to the function splint in [1]. @@ -112,30 +113,28 @@ private: }; lcl_SplineCalculation::lcl_SplineCalculation( - const tPointVecType & rSortedPoints, + tPointVecType && rSortedPoints, double fY1FirstDerivation, double fYnFirstDerivation ) - : m_aPoints( rSortedPoints ), + : m_aPoints( std::move(rSortedPoints) ), m_fYp1( fY1FirstDerivation ), m_fYpN( fYnFirstDerivation ), m_nKLow( 0 ), - m_nKHigh( rSortedPoints.size() - 1 ), - m_fLastInterpolatedValue(0.0) + m_nKHigh( m_aPoints.size() - 1 ), + m_fLastInterpolatedValue(std::numeric_limits<double>::infinity()) { - ::rtl::math::setInf( &m_fLastInterpolatedValue, false ); Calculate(); } lcl_SplineCalculation::lcl_SplineCalculation( - const tPointVecType & rSortedPoints) - : m_aPoints( rSortedPoints ), + tPointVecType && rSortedPoints) + : m_aPoints( std::move(rSortedPoints) ), m_fYp1( 0.0 ), /*dummy*/ m_fYpN( 0.0 ), /*dummy*/ m_nKLow( 0 ), - m_nKHigh( rSortedPoints.size() - 1 ), - m_fLastInterpolatedValue(0.0) + m_nKHigh( m_aPoints.size() - 1 ), + m_fLastInterpolatedValue(std::numeric_limits<double>::infinity()) { - ::rtl::math::setInf( &m_fLastInterpolatedValue, false ); CalculatePeriodic(); } @@ -198,7 +197,7 @@ void lcl_SplineCalculation::Calculate() ( m_fYpN - ( m_aPoints[ n ].second - m_aPoints[ n - 1 ].second ) / xDiff ); } - m_aSecDerivY[ n ] = ( un - qn * u[ n - 1 ] ) * ( qn * m_aSecDerivY[ n - 1 ] + 1.0 ); + m_aSecDerivY[ n ] = ( un - qn * u[ n - 1 ] ) / ( qn * m_aSecDerivY[ n - 1 ] + 1.0 ); // note: the algorithm in [1] iterates from n-1 to 0, but as size_type // may be (usually is) an unsigned type, we can not write k >= 0, as this @@ -411,26 +410,19 @@ bool createParameterT(const tPointVecType& rUniquePoints, double* t) bool bIsSuccessful = true; const lcl_tSizeType n = rUniquePoints.size() - 1; t[0]=0.0; - double dx = 0.0; - double dy = 0.0; - double fDiffMax = 1.0; //dummy values double fDenominator = 0.0; // initialized for summing up for (lcl_tSizeType i=1; i<=n ; ++i) { // 4th root(dx^2+dy^2) - dx = rUniquePoints[i].first - rUniquePoints[i-1].first; - dy = rUniquePoints[i].second - rUniquePoints[i-1].second; - // scaling to avoid underflow or overflow - fDiffMax = std::max(fabs(dx), fabs(dy)); - if (fDiffMax == 0.0) + double dx = rUniquePoints[i].first - rUniquePoints[i-1].first; + double dy = rUniquePoints[i].second - rUniquePoints[i-1].second; + if (dx == 0 && dy == 0) { bIsSuccessful = false; break; } else { - dx /= fDiffMax; - dy /= fDiffMax; - fDenominator += sqrt(sqrt(dx * dx + dy * dy)) * sqrt(fDiffMax); + fDenominator += sqrt(std::hypot(dx, dy)); } } if (fDenominator == 0.0) @@ -444,13 +436,9 @@ bool createParameterT(const tPointVecType& rUniquePoints, double* t) double fNumerator = 0.0; for (lcl_tSizeType i=1; i<=j ; ++i) { - dx = rUniquePoints[i].first - rUniquePoints[i-1].first; - dy = rUniquePoints[i].second - rUniquePoints[i-1].second; - fDiffMax = std::max(fabs(dx), fabs(dy)); - // same as above, so should not be zero - dx /= fDiffMax; - dy /= fDiffMax; - fNumerator += sqrt(sqrt(dx * dx + dy * dy)) * sqrt(fDiffMax); + double dx = rUniquePoints[i].first - rUniquePoints[i-1].first; + double dy = rUniquePoints[i].second - rUniquePoints[i-1].second; + fNumerator += sqrt(std::hypot(dx, dy)); } t[j] = fNumerator / fDenominator; @@ -532,30 +520,28 @@ void applyNtoParameterT(const lcl_tSizeType i,const double tk,const sal_uInt32 p // Calculates uniform parametric splines with subinterval length 1, // according ODF1.2 part 1, chapter 'chart interpolation'. void SplineCalculater::CalculateCubicSplines( - const drawing::PolyPolygonShape3D& rInput - , drawing::PolyPolygonShape3D& rResult + const std::vector<std::vector<css::drawing::Position3D>>& rInput + , std::vector<std::vector<css::drawing::Position3D>>& rResult , sal_uInt32 nGranularity ) { OSL_PRECOND( nGranularity > 0, "Granularity is invalid" ); - sal_uInt32 nOuterCount = rInput.SequenceX.getLength(); + sal_uInt32 nOuterCount = rInput.size(); - rResult.SequenceX.realloc(nOuterCount); - rResult.SequenceY.realloc(nOuterCount); - rResult.SequenceZ.realloc(nOuterCount); + rResult.resize(nOuterCount); + + auto pSequence = rResult.data(); if( !nOuterCount ) return; for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter ) { - if( rInput.SequenceX[nOuter].getLength() <= 1 ) + if( rInput[nOuter].size() <= 1 ) continue; //we need at least two points - sal_uInt32 nMaxIndexPoints = rInput.SequenceX[nOuter].getLength()-1; // is >=1 - const double* pOldX = rInput.SequenceX[nOuter].getConstArray(); - const double* pOldY = rInput.SequenceY[nOuter].getConstArray(); - const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray(); + sal_uInt32 nMaxIndexPoints = rInput[nOuter].size()-1; // is >=1 + const css::drawing::Position3D* pOld = rInput[nOuter].data(); std::vector < double > aParameter(nMaxIndexPoints+1); aParameter[0]=0.0; @@ -574,57 +560,50 @@ void SplineCalculater::CalculateCubicSplines( for (sal_uInt32 nN=0;nN<=nMaxIndexPoints; nN++ ) { aInputX[ nN ].first=aParameter[nN]; - aInputX[ nN ].second=pOldX[ nN ]; + aInputX[ nN ].second=pOld[ nN ].PositionX; aInputY[ nN ].first=aParameter[nN]; - aInputY[ nN ].second=pOldY[ nN ]; + aInputY[ nN ].second=pOld[ nN ].PositionY; aInputZ[ nN ].first=aParameter[nN]; - aInputZ[ nN ].second=pOldZ[ nN ]; + aInputZ[ nN ].second=pOld[ nN ].PositionZ; } // generate a spline for each coordinate. It holds the complete // information to calculate each point of the curve - std::unique_ptr<lcl_SplineCalculation> aSplineX; - std::unique_ptr<lcl_SplineCalculation> aSplineY; + std::optional<lcl_SplineCalculation> aSplineX; + std::optional<lcl_SplineCalculation> aSplineY; // lcl_SplineCalculation* aSplineZ; the z-coordinates of all points in // a data series are equal. No spline calculation needed, but copy // coordinate to output - if( pOldX[ 0 ] == pOldX[nMaxIndexPoints] && - pOldY[ 0 ] == pOldY[nMaxIndexPoints] && - pOldZ[ 0 ] == pOldZ[nMaxIndexPoints] && + if( pOld[ 0 ].PositionX == pOld[nMaxIndexPoints].PositionX && + pOld[ 0 ].PositionY == pOld[nMaxIndexPoints].PositionY && + pOld[ 0 ].PositionZ == pOld[nMaxIndexPoints].PositionZ && nMaxIndexPoints >=2 ) { // periodic spline - aSplineX.reset(new lcl_SplineCalculation( aInputX)); - aSplineY.reset(new lcl_SplineCalculation( aInputY)); - // aSplineZ = new lcl_SplineCalculation( aInputZ) ; + aSplineX.emplace(std::move(aInputX)); + aSplineY.emplace(std::move(aInputY)); } else // generate the kind "natural spline" { - double fInfty; - ::rtl::math::setInf( &fInfty, false ); - double fXDerivation = fInfty; - double fYDerivation = fInfty; - aSplineX.reset(new lcl_SplineCalculation( aInputX, fXDerivation, fXDerivation )); - aSplineY.reset(new lcl_SplineCalculation( aInputY, fYDerivation, fYDerivation )); + double fXDerivation = std::numeric_limits<double>::infinity(); + double fYDerivation = std::numeric_limits<double>::infinity(); + aSplineX.emplace(std::move(aInputX), fXDerivation, fXDerivation); + aSplineY.emplace(std::move(aInputY), fYDerivation, fYDerivation); } // fill result polygon with calculated values - rResult.SequenceX[nOuter].realloc( nMaxIndexPoints*nGranularity + 1); - rResult.SequenceY[nOuter].realloc( nMaxIndexPoints*nGranularity + 1); - rResult.SequenceZ[nOuter].realloc( nMaxIndexPoints*nGranularity + 1); + pSequence[nOuter].resize( nMaxIndexPoints*nGranularity + 1); - double* pNewX = rResult.SequenceX[nOuter].getArray(); - double* pNewY = rResult.SequenceY[nOuter].getArray(); - double* pNewZ = rResult.SequenceZ[nOuter].getArray(); + css::drawing::Position3D* pNew = pSequence[nOuter].data(); sal_uInt32 nNewPointIndex = 0; // Index in result points for( sal_uInt32 ni = 0; ni < nMaxIndexPoints; ni++ ) { // given point is surely a curve point - pNewX[nNewPointIndex] = pOldX[ni]; - pNewY[nNewPointIndex] = pOldY[ni]; - pNewZ[nNewPointIndex] = pOldZ[ni]; + pNew[nNewPointIndex].PositionX = pOld[ni].PositionX; + pNew[nNewPointIndex].PositionY = pOld[ni].PositionY; + pNew[nNewPointIndex].PositionZ = pOld[ni].PositionZ; nNewPointIndex++; // calculate intermediate points @@ -633,31 +612,21 @@ void SplineCalculater::CalculateCubicSplines( { double fParam = aParameter[ni] + ( fInc * static_cast< double >( nj ) ); - pNewX[nNewPointIndex]=aSplineX->GetInterpolatedValue( fParam ); - pNewY[nNewPointIndex]=aSplineY->GetInterpolatedValue( fParam ); + pNew[nNewPointIndex].PositionX = aSplineX->GetInterpolatedValue( fParam ); + pNew[nNewPointIndex].PositionY = aSplineY->GetInterpolatedValue( fParam ); // pNewZ[nNewPointIndex]=aSplineZ->GetInterpolatedValue( fParam ); - pNewZ[nNewPointIndex] = pOldZ[ni]; + pNew[nNewPointIndex].PositionZ = pOld[ni].PositionZ; nNewPointIndex++; } } // add last point - pNewX[nNewPointIndex] = pOldX[nMaxIndexPoints]; - pNewY[nNewPointIndex] = pOldY[nMaxIndexPoints]; - pNewZ[nNewPointIndex] = pOldZ[nMaxIndexPoints]; + pNew[nNewPointIndex] = pOld[nMaxIndexPoints]; } } -// The implementation follows closely ODF1.2 spec, chapter chart:interpolation -// using the same names as in spec as far as possible, without prefix. -// More details can be found on -// Dr. C.-K. Shene: CS3621 Introduction to Computing with Geometry Notes -// Unit 9: Interpolation and Approximation/Curve Global Interpolation -// Department of Computer Science, Michigan Technological University -// http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/ -// [last called 2011-05-20] void SplineCalculater::CalculateBSplines( - const css::drawing::PolyPolygonShape3D& rInput - , css::drawing::PolyPolygonShape3D& rResult + const std::vector<std::vector<css::drawing::Position3D>>& rInput + , std::vector<std::vector<css::drawing::Position3D>>& rResult , sal_uInt32 nResolution , sal_uInt32 nDegree ) { @@ -671,34 +640,32 @@ void SplineCalculater::CalculateBSplines( // limit the b-spline degree at 15 to prevent insanely large sets of points sal_uInt32 p = std::min<sal_uInt32>(nDegree, 15); - sal_Int32 nOuterCount = rInput.SequenceX.getLength(); + sal_Int32 nOuterCount = rInput.size(); + + rResult.resize(nOuterCount); - rResult.SequenceX.realloc(nOuterCount); - rResult.SequenceY.realloc(nOuterCount); - rResult.SequenceZ.realloc(nOuterCount); + auto pSequence = rResult.data(); if( !nOuterCount ) return; // no input for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter ) { - if( rInput.SequenceX[nOuter].getLength() <= 1 ) + if( rInput[nOuter].size() <= 1 ) continue; // need at least 2 points, next piece of the series // Copy input to vector of points and remove adjacent double points. The // Z-coordinate is equal for all points in a series and holds the depth // in 3D mode, simple copying is enough. - lcl_tSizeType nMaxIndexPoints = rInput.SequenceX[nOuter].getLength()-1; // is >=1 - const double* pOldX = rInput.SequenceX[nOuter].getConstArray(); - const double* pOldY = rInput.SequenceY[nOuter].getConstArray(); - const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray(); - double fZCoordinate = pOldZ[0]; + lcl_tSizeType nMaxIndexPoints = rInput[nOuter].size()-1; // is >=1 + const css::drawing::Position3D* pOld = rInput[nOuter].data(); + double fZCoordinate = pOld[0].PositionZ; tPointVecType aPointsIn; aPointsIn.resize(nMaxIndexPoints+1); for (lcl_tSizeType i = 0; i <= nMaxIndexPoints; ++i ) { - aPointsIn[ i ].first = pOldX[i]; - aPointsIn[ i ].second = pOldY[i]; + aPointsIn[ i ].first = pOld[i].PositionX; + aPointsIn[ i ].second = pOld[i].PositionY; } aPointsIn.erase( std::unique( aPointsIn.begin(), aPointsIn.end()), aPointsIn.end() ); @@ -710,29 +677,23 @@ void SplineCalculater::CalculateBSplines( continue; // need at least 2 points, degree p needs at least n+1 points // next piece of series - std::unique_ptr<double[]> t(new double [n+1]); - if (!createParameterT(aPointsIn, t.get())) + std::vector<double> t(n + 1); + if (!createParameterT(aPointsIn, t.data())) { continue; // next piece of series } lcl_tSizeType m = n + p + 1; - std::unique_ptr<double[]> u(new double [m+1]); - createKnotVector(n, p, t.get(), u.get()); + std::vector<double> u(m + 1); + createKnotVector(n, p, t.data(), u.data()); // The matrix N contains the B-spline basis functions applied to parameters. // In each row only p+1 adjacent elements are non-zero. The starting // column in a higher row is equal or greater than in the lower row. // To store this matrix the non-zero elements are shifted to column 0 // and the amount of shifting is remembered in an array. - std::unique_ptr<double*[]> aMatN(new double*[n+1]); - for (lcl_tSizeType row = 0; row <=n; ++row) - { - aMatN[row] = new double[p+1]; - for (sal_uInt32 col = 0; col <= p; ++col) - aMatN[row][col] = 0.0; - } - std::unique_ptr<lcl_tSizeType[]> aShift(new lcl_tSizeType[n+1]); + std::vector<std::vector<double>> aMatN(n + 1, std::vector<double>(p + 1)); + std::vector<lcl_tSizeType> aShift(n + 1); aMatN[0][0] = 1.0; //all others are zero aShift[0] = 0; aMatN[n][0] = 1.0; @@ -752,7 +713,7 @@ void SplineCalculater::CalculateBSplines( // index in reduced matrix aMatN = (index in full matrix N) - (i-p) aShift[k] = i - p; - applyNtoParameterT(i, t[k], p, u.get(), aMatN[k]); + applyNtoParameterT(i, t[k], p, u.data(), aMatN[k].data()); } // next row k // Get matrix C of control points from the matrix equation aMatN * C = aPointsIn @@ -762,9 +723,6 @@ void SplineCalculater::CalculateBSplines( lcl_tSizeType c = 0; // true column index double fDivisor = 1.0; // used for diagonal element double fEliminate = 1.0; // used for the element, that will become zero - double fHelp; - tPointType aHelp; - lcl_tSizeType nHelp; // used in triangle change bool bIsSuccessful = true; for (c = 0 ; c <= n && bIsSuccessful; ++c) { @@ -784,18 +742,9 @@ void SplineCalculater::CalculateBSplines( // exchange total row r with total row c if necessary if (r != c) { - for ( sal_uInt32 i = 0; i <= p ; ++i) - { - fHelp = aMatN[r][i]; - aMatN[r][i] = aMatN[c][i]; - aMatN[c][i] = fHelp; - } - aHelp = aPointsIn[r]; - aPointsIn[r] = aPointsIn[c]; - aPointsIn[c] = aHelp; - nHelp = aShift[r]; - aShift[r] = aShift[c]; - aShift[c] = nHelp; + std::swap( aMatN[r], aMatN[c] ); + std::swap( aPointsIn[r], aPointsIn[c] ); + std::swap( aShift[r], aShift[c] ); } // divide row c, so that element(c,c) becomes 1 @@ -855,19 +804,15 @@ void SplineCalculater::CalculateBSplines( // calculate the intermediate points according given resolution // using deBoor-Cox algorithm lcl_tSizeType nNewSize = nResolution * n + 1; - rResult.SequenceX[nOuter].realloc(nNewSize); - rResult.SequenceY[nOuter].realloc(nNewSize); - rResult.SequenceZ[nOuter].realloc(nNewSize); - double* pNewX = rResult.SequenceX[nOuter].getArray(); - double* pNewY = rResult.SequenceY[nOuter].getArray(); - double* pNewZ = rResult.SequenceZ[nOuter].getArray(); - pNewX[0] = aPointsIn[0].first; - pNewY[0] = aPointsIn[0].second; - pNewZ[0] = fZCoordinate; // Precondition: z-coordinates of all points of a series are equal - pNewX[nNewSize -1 ] = aPointsIn[n].first; - pNewY[nNewSize -1 ] = aPointsIn[n].second; - pNewZ[nNewSize -1 ] = fZCoordinate; - std::unique_ptr<double[]> aP(new double[m+1]); + pSequence[nOuter].resize(nNewSize); + css::drawing::Position3D* pNew = pSequence[nOuter].data(); + pNew[0].PositionX = aPointsIn[0].first; + pNew[0].PositionY = aPointsIn[0].second; + pNew[0].PositionZ = fZCoordinate; // Precondition: z-coordinates of all points of a series are equal + pNew[nNewSize -1 ].PositionX = aPointsIn[n].first; + pNew[nNewSize -1 ].PositionY = aPointsIn[n].second; + pNew[nNewSize -1 ].PositionZ = fZCoordinate; + std::vector<double> aP(m + 1); lcl_tSizeType nLow = 0; for ( lcl_tSizeType nTIndex = 0; nTIndex <= n-1; ++nTIndex) { @@ -899,7 +844,7 @@ void SplineCalculater::CalculateBSplines( aP[i] = (1 - fFactor)* aP[i-1] + fFactor * aP[i]; } } - pNewX[nNewIndex] = aP[nLow]; + pNew[nNewIndex].PositionX = aP[nLow]; // y-coordinate for (lcl_tSizeType i = nLow - p; i <= nLow; ++i) @@ -914,15 +859,11 @@ void SplineCalculater::CalculateBSplines( aP[i] = (1 - fFactor)* aP[i-1] + fFactor * aP[i]; } } - pNewY[nNewIndex] = aP[nLow]; - pNewZ[nNewIndex] = fZCoordinate; + pNew[nNewIndex].PositionY = aP[nLow]; + pNew[nNewIndex].PositionZ = fZCoordinate; } } } - for (lcl_tSizeType row = 0; row <=n; ++row) - { - delete[] aMatN[row]; - } } // next piece of the series } diff --git a/chart2/source/view/charttypes/Splines.hxx b/chart2/source/view/charttypes/Splines.hxx index af0d82ea7ce4..b83c13931b47 100644 --- a/chart2/source/view/charttypes/Splines.hxx +++ b/chart2/source/view/charttypes/Splines.hxx @@ -17,12 +17,13 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_SPLINES_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_CHARTTYPES_SPLINES_HXX +#pragma once #include <sal/types.h> +#include <vector> namespace com::sun::star::drawing { struct PolyPolygonShape3D; } +namespace com::sun::star::drawing { struct Position3D; } namespace chart { @@ -31,18 +32,17 @@ class SplineCalculater { public: static void CalculateCubicSplines( - const css::drawing::PolyPolygonShape3D& rPoints - , css::drawing::PolyPolygonShape3D& rResult + const std::vector<std::vector<css::drawing::Position3D>>& rPoints + , std::vector<std::vector<css::drawing::Position3D>>& rResult , sal_uInt32 nGranularity ); static void CalculateBSplines( - const css::drawing::PolyPolygonShape3D& rPoints - , css::drawing::PolyPolygonShape3D& rResult + const std::vector<std::vector<css::drawing::Position3D>>& rPoints + , std::vector<std::vector<css::drawing::Position3D>>& rResult , sal_uInt32 nGranularity , sal_uInt32 nSplineDepth ); }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index bbc1788ec148..b9773494d785 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -17,23 +17,32 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <cstddef> +#include <limits> #include <memory> #include <VSeriesPlotter.hxx> #include <BaseGFXHelper.hxx> #include <VLineProperties.hxx> #include <ShapeFactory.hxx> +#include <Diagram.hxx> +#include <BaseCoordinateSystem.hxx> +#include <DataSeries.hxx> +#include <DataSeriesProperties.hxx> #include <CommonConverters.hxx> #include <ExplicitCategoriesProvider.hxx> +#include <FormattedString.hxx> #include <ObjectIdentifier.hxx> #include <StatisticsHelper.hxx> #include <PlottingPositionHelper.hxx> #include <LabelPositionHelper.hxx> +#include <ChartType.hxx> #include <ChartTypeHelper.hxx> #include <Clipping.hxx> #include <servicenames_charttypes.hxx> #include <NumberFormatterWrapper.hxx> #include <DataSeriesHelper.hxx> +#include <RegressionCurveModel.hxx> #include <RegressionCurveHelper.hxx> #include <VLegendSymbolFactory.hxx> #include <FormattedStringHelper.hxx> @@ -56,27 +65,25 @@ #include <com/sun/star/chart2/DataPointLabel.hpp> #include <com/sun/star/chart/ErrorBarStyle.hpp> #include <com/sun/star/chart/TimeUnit.hpp> +#include <com/sun/star/chart2/MovingAverageType.hpp> #include <com/sun/star/chart2/XDataPointCustomLabelField.hpp> -#include <com/sun/star/chart2/XRegressionCurveContainer.hpp> #include <com/sun/star/container/XChild.hpp> #include <com/sun/star/chart2/RelativePosition.hpp> -#include <editeng/unoprnms.hxx> +#include <o3tl/safeint.hxx> #include <tools/color.hxx> +#include <tools/UnitConversion.hxx> #include <rtl/ustrbuf.hxx> #include <rtl/math.hxx> #include <basegfx/vector/b2dvector.hxx> #include <com/sun/star/drawing/LineStyle.hpp> #include <com/sun/star/util/XCloneable.hpp> -#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> - -#include <com/sun/star/style/ParagraphAdjust.hpp> -#include <com/sun/star/drawing/XShapes.hpp> #include <unotools/localedatawrapper.hxx> #include <comphelper/sequence.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <vcl/settings.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <sal/log.hxx> #include <functional> @@ -89,6 +96,7 @@ namespace chart { using namespace ::com::sun::star; using namespace ::com::sun::star::chart; using namespace ::com::sun::star::chart2; +using namespace ::chart::DataSeriesProperties; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; @@ -103,7 +111,6 @@ VDataSeriesGroup::VDataSeriesGroup( std::unique_ptr<VDataSeries> pSeries ) : m_aSeriesVector(1) , m_bMaxPointCountDirty(true) , m_nMaxPointCount(0) - , m_aListOfCachedYValues() { m_aSeriesVector[0] = std::move(pSeries); } @@ -137,20 +144,18 @@ sal_Int32 VDataSeriesGroup::getSeriesCount() const return m_aSeriesVector.size(); } -VSeriesPlotter::VSeriesPlotter( const uno::Reference<XChartType>& xChartTypeModel +VSeriesPlotter::VSeriesPlotter( rtl::Reference<ChartType> xChartTypeModel , sal_Int32 nDimensionCount, bool bCategoryXAxis ) : PlotterBase( nDimensionCount ) , m_pMainPosHelper( nullptr ) - , m_xChartTypeModel(xChartTypeModel) - , m_xChartTypeModelProps( uno::Reference< beans::XPropertySet >::query( xChartTypeModel )) - , m_aZSlots() + , m_xChartTypeModel(std::move(xChartTypeModel)) , m_bCategoryXAxis(bCategoryXAxis) , m_nTimeResolution(css::chart::TimeUnit::DAY) , m_aNullDate(30,12,1899) - , m_xColorScheme() , m_pExplicitCategoriesProvider(nullptr) , m_bPointsWereSkipped(false) , m_bPieLabelsAllowToMove(false) + , m_aAvailableOuterRect(0, 0, 0, 0) { SAL_WARN_IF(!m_xChartTypeModel.is(),"chart2","no XChartType available in view, fallback to default values may be wrong"); } @@ -194,7 +199,7 @@ void VSeriesPlotter::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 pSeries->setXValuesIfNone( m_pExplicitCategoriesProvider->getOriginalCategories() ); } - if(zSlot<0 || zSlot>=static_cast<sal_Int32>(m_aZSlots.size())) + if(zSlot<0 || o3tl::make_unsigned(zSlot)>=m_aZSlots.size()) { //new z slot std::vector< VDataSeriesGroup > aZSlot; @@ -206,7 +211,7 @@ void VSeriesPlotter::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 //existing zslot std::vector< VDataSeriesGroup >& rXSlots = m_aZSlots[zSlot]; - if(xSlot<0 || xSlot>=static_cast<sal_Int32>(rXSlots.size())) + if(xSlot<0 || o3tl::make_unsigned(xSlot)>=rXSlots.size()) { //append the series to already existing x series rXSlots.emplace_back( std::move(pSeries) ); @@ -272,81 +277,68 @@ void VSeriesPlotter::releaseShapes() } } -uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShape( VDataSeries* pDataSeries - , const uno::Reference< drawing::XShapes >& xTarget ) +rtl::Reference<SvxShapeGroupAnyD> VSeriesPlotter::getSeriesGroupShape( VDataSeries* pDataSeries + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ) { - uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xGroupShape ); - if( !xShapes.is() ) - { + if( !pDataSeries->m_xGroupShape ) //create a group shape for this series and add to logic target: - xShapes = createGroupShape( xTarget,pDataSeries->getCID() ); - pDataSeries->m_xGroupShape = xShapes; - } - return xShapes; + pDataSeries->m_xGroupShape = createGroupShape( xTarget,pDataSeries->getCID() ); + return pDataSeries->m_xGroupShape; } -uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries - , const uno::Reference< drawing::XShapes >& xTarget ) +rtl::Reference<SvxShapeGroupAnyD> VSeriesPlotter::getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ) { - uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xFrontSubGroupShape ); - if(!xShapes.is()) + if(!pDataSeries->m_xFrontSubGroupShape) { //ensure that the series group shape is already created - uno::Reference< drawing::XShapes > xSeriesShapes( getSeriesGroupShape( pDataSeries, xTarget ) ); + rtl::Reference<SvxShapeGroupAnyD> xSeriesShapes( getSeriesGroupShape( pDataSeries, xTarget ) ); //ensure that the back child is created first getSeriesGroupShapeBackChild( pDataSeries, xTarget ); //use series group shape as parent for the new created front group shape - xShapes = createGroupShape( xSeriesShapes ); - pDataSeries->m_xFrontSubGroupShape = xShapes; + pDataSeries->m_xFrontSubGroupShape = createGroupShape( xSeriesShapes ); } - return xShapes; + return pDataSeries->m_xFrontSubGroupShape; } -uno::Reference< drawing::XShapes > VSeriesPlotter::getSeriesGroupShapeBackChild( VDataSeries* pDataSeries - , const uno::Reference< drawing::XShapes >& xTarget ) +rtl::Reference<SvxShapeGroupAnyD> VSeriesPlotter::getSeriesGroupShapeBackChild( VDataSeries* pDataSeries + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ) { - uno::Reference< drawing::XShapes > xShapes( pDataSeries->m_xBackSubGroupShape ); - if(!xShapes.is()) + if(!pDataSeries->m_xBackSubGroupShape) { //ensure that the series group shape is already created - uno::Reference< drawing::XShapes > xSeriesShapes( getSeriesGroupShape( pDataSeries, xTarget ) ); + rtl::Reference<SvxShapeGroupAnyD> xSeriesShapes( getSeriesGroupShape( pDataSeries, xTarget ) ); //use series group shape as parent for the new created back group shape - xShapes = createGroupShape( xSeriesShapes ); - pDataSeries->m_xBackSubGroupShape = xShapes; + pDataSeries->m_xBackSubGroupShape = createGroupShape( xSeriesShapes ); } - return xShapes; + return pDataSeries->m_xBackSubGroupShape; } -uno::Reference< drawing::XShapes > VSeriesPlotter::getLabelsGroupShape( VDataSeries& rDataSeries - , const uno::Reference< drawing::XShapes >& xTextTarget ) +rtl::Reference<SvxShapeGroup> VSeriesPlotter::getLabelsGroupShape( VDataSeries& rDataSeries + , const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget ) { //xTextTarget needs to be a 2D shape container always! - - uno::Reference< drawing::XShapes > xShapes( rDataSeries.m_xLabelsGroupShape ); - if(!xShapes.is()) + if(!rDataSeries.m_xLabelsGroupShape) { //create a 2D group shape for texts of this series and add to text target: - xShapes = m_pShapeFactory->createGroup2D( xTextTarget, rDataSeries.getLabelsCID() ); - rDataSeries.m_xLabelsGroupShape = xShapes; + rDataSeries.m_xLabelsGroupShape = ShapeFactory::createGroup2D( xTextTarget, rDataSeries.getLabelsCID() ); } - return xShapes; + return rDataSeries.m_xLabelsGroupShape; } -uno::Reference< drawing::XShapes > VSeriesPlotter::getErrorBarsGroupShape( VDataSeries& rDataSeries - , const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference<SvxShapeGroupAnyD> VSeriesPlotter::getErrorBarsGroupShape( VDataSeries& rDataSeries + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget , bool bYError ) { - uno::Reference< css::drawing::XShapes > &rShapeGroup = + rtl::Reference<SvxShapeGroupAnyD> &rShapeGroup = bYError ? rDataSeries.m_xErrorYBarsGroupShape : rDataSeries.m_xErrorXBarsGroupShape; - uno::Reference< drawing::XShapes > xShapes( rShapeGroup ); - if(!xShapes.is()) + if(!rShapeGroup) { //create a group shape for this series and add to logic target: - xShapes = createGroupShape( xTarget,rDataSeries.getErrorBarsCID(bYError) ); - rShapeGroup = xShapes; + rShapeGroup = createGroupShape( xTarget,rDataSeries.getErrorBarsCID(bYError) ); } - return xShapes; + return rShapeGroup; } @@ -393,7 +385,7 @@ OUString VSeriesPlotter::getLabelTextForValue( VDataSeries const & rDataSeries return aNumber; } -uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference<SvxShapeText> VSeriesPlotter::createDataLabel( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , VDataSeries& rDataSeries , sal_Int32 nPointIndex , double fValue @@ -403,7 +395,7 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re , sal_Int32 nOffset , sal_Int32 nTextWidth ) { - uno::Reference< drawing::XShape > xTextShape; + rtl::Reference<SvxShapeText> xTextShape; Sequence<uno::Reference<XDataPointCustomLabelField>> aCustomLabels; try @@ -429,8 +421,8 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re else if(eAlignment==LABEL_ALIGN_BOTTOM) aScreenPosition2D.Y += nOffset; - uno::Reference< drawing::XShapes > xTarget_ = - m_pShapeFactory->createGroup2D( + rtl::Reference<SvxShapeGroup> xTarget_ = + ShapeFactory::createGroup2D( getLabelsGroupShape(rDataSeries, xTarget), ObjectIdentifier::createPointCID( rDataSeries.getLabelCID_Stub(), nPointIndex)); @@ -452,13 +444,12 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re uno::Reference< beans::XPropertySet > xProps( rDataSeries.getPropertiesOfPoint( nPointIndex ) ); if( xProps.is() ) xProps->getPropertyValue( "CharHeight") >>= fViewFontSize; - // pt -> 1/100th mm - fViewFontSize *= (2540.0f / 72.0f); + fViewFontSize = convertPointToMm100(fViewFontSize); } // the font height is used for computing the size of an optional legend // symbol to be prepended to the text label. - Reference< drawing::XShape > xSymbol; + rtl::Reference< SvxShapeGroup > xSymbol; if(pLabel->ShowLegendSymbol) { sal_Int32 nSymbolHeight = static_cast< sal_Int32 >( fViewFontSize * 0.6 ); @@ -471,9 +462,9 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re awt::Size aMaxSymbolExtent( nSymbolWidth, nSymbolHeight ); if( rDataSeries.isVaryColorsByPoint() ) - xSymbol.set( VSeriesPlotter::createLegendSymbolForPoint( aMaxSymbolExtent, rDataSeries, nPointIndex, xTarget_, m_xShapeFactory ) ); + xSymbol = VSeriesPlotter::createLegendSymbolForPoint( aMaxSymbolExtent, rDataSeries, nPointIndex, xTarget_ ); else - xSymbol.set( VSeriesPlotter::createLegendSymbolForSeries( aMaxSymbolExtent, rDataSeries, xTarget_, m_xShapeFactory ) ); + xSymbol = VSeriesPlotter::createLegendSymbolForSeries( aMaxSymbolExtent, rDataSeries, xTarget_ ); } //prepare text @@ -498,7 +489,7 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re } sal_Int32 nLineCountForSymbolsize = 0; - sal_uInt32 nTextListLength = 3; + sal_uInt32 nTextListLength = 4; sal_uInt32 nCustomLabelsCount = aCustomLabels.getLength(); Sequence< OUString > aTextList( nTextListLength ); @@ -508,18 +499,19 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re nTextListLength = ( nCustomLabelsCount > 3 ) ? nCustomLabelsCount : 3; aSeparator = ""; aTextList = Sequence< OUString >( nTextListLength ); + auto pTextList = aTextList.getArray(); for( sal_uInt32 i = 0; i < nCustomLabelsCount; ++i ) { switch( aCustomLabels[i]->getFieldType() ) { case DataPointCustomLabelFieldType_VALUE: { - aTextList[i] = getLabelTextForValue( rDataSeries, nPointIndex, fValue, false ); + pTextList[i] = getLabelTextForValue( rDataSeries, nPointIndex, fValue, false ); break; } case DataPointCustomLabelFieldType_CATEGORYNAME: { - aTextList[i] = getCategoryName( nPointIndex ); + pTextList[i] = getCategoryName( nPointIndex ); break; } case DataPointCustomLabelFieldType_SERIESNAME: @@ -527,29 +519,43 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re OUString aRole; if ( m_xChartTypeModel ) aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel(); - const uno::Reference< XDataSeries >& xSeries( rDataSeries.getModel() ); - aTextList[i] = DataSeriesHelper::getDataSeriesLabel( xSeries, aRole ); + const rtl::Reference< DataSeries >& xSeries( rDataSeries.getModel() ); + pTextList[i] = xSeries->getLabelForRole( aRole ); break; } case DataPointCustomLabelFieldType_PERCENTAGE: { - aTextList[i] = getLabelTextForValue( rDataSeries, nPointIndex, fValue, true ); + if(fSumValue == 0.0) + fSumValue = 1.0; + fValue /= fSumValue; + if(fValue < 0) + fValue *= -1.0; + + pTextList[i] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true); + break; + } + case DataPointCustomLabelFieldType_CELLRANGE: + { + if (aCustomLabels[i]->getDataLabelsRange()) + pTextList[i] = aCustomLabels[i]->getString(); + else + pTextList[i] = OUString(); break; } case DataPointCustomLabelFieldType_CELLREF: { // TODO: for now doesn't show placeholder - aTextList[i] = OUString(); + pTextList[i] = OUString(); break; } case DataPointCustomLabelFieldType_TEXT: { - aTextList[i] = aCustomLabels[i]->getString(); + pTextList[i] = aCustomLabels[i]->getString(); break; } case DataPointCustomLabelFieldType_NEWLINE: { - aTextList[i] = "\n"; + pTextList[i] = "\n"; break; } default: @@ -560,14 +566,24 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re } else { + auto pTextList = aTextList.getArray(); if( pLabel->ShowCategoryName ) { - aTextList[0] = getCategoryName( nPointIndex ); + pTextList[0] = getCategoryName( nPointIndex ); + } + + if( pLabel->ShowSeriesName ) + { + OUString aRole; + if ( m_xChartTypeModel ) + aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel(); + const rtl::Reference< DataSeries >& xSeries( rDataSeries.getModel() ); + pTextList[1] = xSeries->getLabelForRole( aRole ); } if( pLabel->ShowNumber ) { - aTextList[1] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, false); + pTextList[2] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, false); } if( pLabel->ShowNumberInPercent ) @@ -578,11 +594,11 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re if( fValue < 0 ) fValue*=-1.0; - aTextList[2] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true); + pTextList[3] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true); } } - for( auto const & line : std::as_const(aTextList) ) + for (auto const& line : aTextList) { if( !line.isEmpty() ) { @@ -607,46 +623,14 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re if( bUseCustomLabel ) { - Sequence< uno::Reference< XFormattedString > > aFormattedLabels( aCustomLabels.getLength() ); - for( int i = 0; i < aFormattedLabels.getLength(); i++ ) - { - aFormattedLabels[i] = aCustomLabels[i]; - } - - // center the text - sal_uInt32 nProperties = pPropNames->getLength(); - pPropNames->realloc( nProperties + 1 ); - pPropValues->realloc( nProperties + 1 ); - (*pPropNames)[ nProperties ] = UNO_NAME_EDIT_PARA_ADJUST; - (*pPropValues)[ nProperties ] <<= style::ParagraphAdjust_CENTER; + Sequence< uno::Reference< XFormattedString > > aFormattedLabels( + comphelper::containerToSequence<uno::Reference<XFormattedString>>(aCustomLabels)); // create text shape - xTextShape = ShapeFactory::getOrCreateShapeFactory( m_xShapeFactory )-> + xTextShape = ShapeFactory:: createText( xTarget_, aFormattedLabels, *pPropNames, *pPropValues, ShapeFactory::makeTransformation( aScreenPosition2D ) ); } - else if( bMultiLineLabel ) - { - // prepare properties for each paragraph - // we want to have the value and percent value centered respect - // with the category name - Sequence< tNameSequence > aParaPropNames(3); - aParaPropNames[1].realloc(1); - aParaPropNames[1][0] = "ParaAdjust"; - aParaPropNames[2].realloc(1); - aParaPropNames[2][0] = "ParaAdjust"; - - Sequence< tAnySequence > aParaPropValues(3); - aParaPropValues[1].realloc(1); - aParaPropValues[1][0] <<= style::ParagraphAdjust_CENTER; - aParaPropValues[2].realloc(1); - aParaPropValues[2][0] <<= style::ParagraphAdjust_CENTER; - - //create text shape - xTextShape = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory)-> - createText( xTarget_, aTextList, aParaPropNames, aParaPropValues - , *pPropNames, *pPropValues, ShapeFactory::makeTransformation( aScreenPosition2D ) ); - } else { // join text list elements @@ -664,9 +648,9 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re } //create text shape - xTextShape = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory)-> - createText( xTarget_, aText.makeStringAndClear() - , *pPropNames, *pPropValues, ShapeFactory::makeTransformation( aScreenPosition2D ) ); + xTextShape = ShapeFactory:: + createText( xTarget_, aText.makeStringAndClear(), *pPropNames, *pPropValues, + ShapeFactory::makeTransformation( aScreenPosition2D ) ); } if( !xTextShape.is() ) @@ -686,25 +670,21 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re // for the text shape if( nTextWidth != 0 && bTextWrap ) { - uno::Reference< beans::XPropertySet > xProp( xTextShape, uno::UNO_QUERY ); - if( xProp.is() ) + // compute the height of a line of text + if( !bMultiLineLabel || nLineCountForSymbolsize <= 0 ) { - // compute the height of a line of text - if( !bMultiLineLabel || nLineCountForSymbolsize <= 0 ) - { - nLineCountForSymbolsize = 1; - } - awt::Size aTextSize = xTextShape->getSize(); - sal_Int32 aTextLineHeight = aTextSize.Height / nLineCountForSymbolsize; + nLineCountForSymbolsize = 1; + } + awt::Size aTextSize = xTextShape->getSize(); + sal_Int32 aTextLineHeight = aTextSize.Height / nLineCountForSymbolsize; - // set maximum text width - uno::Any aTextMaximumFrameWidth( nTextWidth ); - xProp->setPropertyValue( "TextMaximumFrameWidth", aTextMaximumFrameWidth ); + // set maximum text width + uno::Any aTextMaximumFrameWidth( nTextWidth ); + xTextShape->SvxShape::setPropertyValue( "TextMaximumFrameWidth", aTextMaximumFrameWidth ); - // compute the total lines of text - aTextSize = xTextShape->getSize(); - nLineCountForSymbolsize = aTextSize.Height / aTextLineHeight; - } + // compute the total lines of text + aTextSize = xTextShape->getSize(); + nLineCountForSymbolsize = aTextSize.Height / aTextLineHeight; } // in case text is rotated, the transformation property of the text @@ -712,9 +692,7 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re if( fRotationDegrees != 0.0 ) { const double fDegreesPi( -basegfx::deg2rad(fRotationDegrees) ); - uno::Reference< beans::XPropertySet > xProp( xTextShape, uno::UNO_QUERY ); - if( xProp.is() ) - xProp->setPropertyValue( "Transformation", ShapeFactory::makeTransformation( aScreenPosition2D, fDegreesPi ) ); + xTextShape->SvxShape::setPropertyValue( "Transformation", ShapeFactory::makeTransformation( aScreenPosition2D, fDegreesPi ) ); LabelPositionHelper::correctPositionForRotation( xTextShape, eAlignment, fRotationDegrees, true /*bRotateAroundCenter*/ ); } @@ -725,37 +703,27 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re if( aRelPos.X != -1 ) { xTextShape->setPosition(aRelPos); - if( !m_xChartTypeModel->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) + if( !m_xChartTypeModel->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) && + // "ShowCustomLeaderLines" + rDataSeries.getModel()->getFastPropertyValue( PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES ).get<sal_Bool>()) { + const basegfx::B2IRectangle aRect( + BaseGFXHelper::makeRectangle(aRelPos, xTextShape->getSize())); sal_Int32 nX1 = rScreenPosition2D.X; sal_Int32 nY1 = rScreenPosition2D.Y; - sal_Int32 nX2 = nX1; - sal_Int32 nY2 = nY1; - ::basegfx::B2IRectangle aRect(BaseGFXHelper::makeRectangle(aRelPos, xTextShape->getSize())); - if (nX1 < aRelPos.X) - nX2 = aRelPos.X; - else if (nX1 > aRect.getMaxX()) - nX2 = aRect.getMaxX(); - - if (nY1 < aRect.getMinY()) - nY2 = aRect.getMinY(); - else if (nY1 > aRect.getMaxY()) - nY2 = aRect.getMaxY(); + const sal_Int32 nX2 = std::clamp(nX1, aRelPos.X, aRect.getMaxX()); + const sal_Int32 nY2 = std::clamp(nY1, aRect.getMinY(), aRect.getMaxY()); //when the line is very short compared to the page size don't create one ::basegfx::B2DVector aLength(nX1 - nX2, nY1 - nY2); - double fPageDiagonaleLength = sqrt(double(m_aPageReferenceSize.Width)*double(m_aPageReferenceSize.Width) + double(m_aPageReferenceSize.Height)*double(m_aPageReferenceSize.Height)); + double fPageDiagonaleLength + = std::hypot(m_aPageReferenceSize.Width, m_aPageReferenceSize.Height); if ((aLength.getLength() / fPageDiagonaleLength) >= 0.01) { - drawing::PointSequenceSequence aPoints(1); - aPoints[0].realloc(2); - aPoints[0][0].X = nX1; - aPoints[0][0].Y = nY1; - aPoints[0][1].X = nX2; - aPoints[0][1].Y = nY2; + drawing::PointSequenceSequence aPoints{ { {nX1, nY1}, {nX2, nY2} } }; VLineProperties aVLineProperties; - m_pShapeFactory->createLine2D(xTarget, aPoints, &aVLineProperties); + ShapeFactory::createLine2D(xTarget, aPoints, &aVLineProperties); } } } @@ -763,13 +731,11 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re // in case legend symbol has to be displayed, text shape position is // slightly changed. - const awt::Point aUnrotatedTextPos(xTextShape->getPosition()); if( xSymbol.is() ) { - const awt::Point aOldTextPos( xTextShape->getPosition() ); - awt::Point aNewTextPos( aOldTextPos ); + awt::Point aNewTextPos(xTextShape->getPosition()); - awt::Point aSymbolPosition( aUnrotatedTextPos ); + awt::Point aSymbolPosition(aNewTextPos); awt::Size aSymbolSize( xSymbol->getSize() ); awt::Size aTextSize = xTextShape->getSize(); @@ -820,8 +786,7 @@ double lcl_getErrorBarLogicLength( bool bPositive, bool bYError ) { - double fResult; - ::rtl::math::setNan( & fResult ); + double fResult = std::numeric_limits<double>::quiet_NaN(); try { switch( nErrorBarStyle ) @@ -863,8 +828,7 @@ double lcl_getErrorBarLogicLength( ? OUString("PositiveError") : OUString("NegativeError") ) >>= fPercent ) { - double fMaxValue; - ::rtl::math::setInf(&fMaxValue, true); + double fMaxValue = -std::numeric_limits<double>::infinity(); for(double d : rData) { if(fMaxValue < d) @@ -900,7 +864,7 @@ double lcl_getErrorBarLogicLength( } void lcl_AddErrorBottomLine( const drawing::Position3D& rPosition, ::basegfx::B2DVector aMainDirection - , drawing::PolyPolygonShape3D& rPoly, sal_Int32 nSequenceIndex ) + , std::vector<std::vector<css::drawing::Position3D>>& rPoly, sal_Int32 nSequenceIndex ) { double fFixedWidth = 200.0; @@ -973,7 +937,7 @@ drawing::Position3D lcl_transformMixedToScene( PlottingPositionHelper const * pP } // anonymous namespace void VSeriesPlotter::createErrorBar( - const uno::Reference< drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rUnscaledLogicPosition , const uno::Reference< beans::XPropertySet > & xErrorBarProperties , const VDataSeries& rVDataSeries @@ -1075,7 +1039,21 @@ void VSeriesPlotter::createErrorBar( fLocalX-=fLength; aNegative = m_pPosHelper->transformLogicToScene( fLocalX, fLocalY, fZ, true ); } - bCreateNegativeBorder = m_pPosHelper->isLogicVisible( fLocalX, fLocalY, fZ); + if (std::isfinite(aNegative.PositionX) && + std::isfinite(aNegative.PositionY) && + std::isfinite(aNegative.PositionZ)) { + bCreateNegativeBorder = m_pPosHelper->isLogicVisible( fLocalX, fLocalY, fZ); + } else { + // If error bars result in a numerical problem (e.g., an + // error bar on a logarithmic chart that results in a point + // <= 0) then just turn off the error bar. + // + // TODO: This perhaps should display a warning, so the user + // knows why a bar is not appearing. + // TODO: This test could also be added to the positive case, + // though a numerical overflow there is less likely. + bShowNegative = false; + } } else bShowNegative = false; @@ -1084,7 +1062,7 @@ void VSeriesPlotter::createErrorBar( if(!bShowPositive && !bShowNegative) return; - drawing::PolyPolygonShape3D aPoly; + std::vector<std::vector<css::drawing::Position3D>> aPoly; sal_Int32 nSequenceIndex=0; if( bShowNegative ) @@ -1106,8 +1084,8 @@ void VSeriesPlotter::createErrorBar( lcl_AddErrorBottomLine( aPositive, aMainDirection, aPoly, nSequenceIndex ); } - uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( xTarget, PolyToPointSequence( aPoly) ); - setMappedProperties( xShape, xErrorBarProperties, PropertyMapper::getPropertyNameMapForLineProperties() ); + rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D( xTarget, aPoly ); + PropertyMapper::setMappedProperties( *xShape, xErrorBarProperties, PropertyMapper::getPropertyNameMapForLineProperties() ); } catch( const uno::Exception & ) { @@ -1119,16 +1097,13 @@ void VSeriesPlotter::createErrorBar( void VSeriesPlotter::addErrorBorder( const drawing::Position3D& rPos0 ,const drawing::Position3D& rPos1 - ,const uno::Reference< drawing::XShapes >& rTarget + ,const rtl::Reference<SvxShapeGroupAnyD>& rTarget ,const uno::Reference< beans::XPropertySet >& rErrorBorderProp ) { - drawing::PolyPolygonShape3D aPoly; - sal_Int32 nSequenceIndex = 0; - AddPointToPoly( aPoly, rPos0, nSequenceIndex ); - AddPointToPoly( aPoly, rPos1, nSequenceIndex ); - uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( - rTarget, PolyToPointSequence( aPoly) ); - setMappedProperties( xShape, rErrorBorderProp, + std::vector<std::vector<css::drawing::Position3D>> aPoly { { rPos0, rPos1} }; + rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D( + rTarget, aPoly ); + PropertyMapper::setMappedProperties( *xShape, rErrorBorderProp, PropertyMapper::getPropertyNameMapForLineProperties() ); } @@ -1136,7 +1111,7 @@ void VSeriesPlotter::createErrorRectangle( const drawing::Position3D& rUnscaledLogicPosition ,VDataSeries& rVDataSeries ,sal_Int32 nIndex - ,const uno::Reference< drawing::XShapes >& rTarget + ,const rtl::Reference<SvxShapeGroupAnyD>& rTarget ,bool bUseXErrorData ,bool bUseYErrorData ) { @@ -1151,8 +1126,8 @@ void VSeriesPlotter::createErrorRectangle( if ( !xErrorBorderPropX.is() ) return; } - uno::Reference< drawing::XShapes > xErrorBorder_ShapesX( - getErrorBarsGroupShape( rVDataSeries, rTarget, false ) ); + rtl::Reference<SvxShapeGroupAnyD> xErrorBorder_ShapesX = + getErrorBarsGroupShape( rVDataSeries, rTarget, false ); if ( bUseYErrorData ) { @@ -1160,8 +1135,8 @@ void VSeriesPlotter::createErrorRectangle( if ( !xErrorBorderPropY.is() ) return; } - uno::Reference< drawing::XShapes > xErrorBorder_ShapesY( - getErrorBarsGroupShape( rVDataSeries, rTarget, true ) ); + rtl::Reference<SvxShapeGroupAnyD> xErrorBorder_ShapesY = + getErrorBarsGroupShape( rVDataSeries, rTarget, true ); if( !ChartTypeHelper::isSupportingStatisticProperties( m_xChartTypeModel, m_nDimension ) ) return; @@ -1279,7 +1254,7 @@ void VSeriesPlotter::createErrorRectangle( void VSeriesPlotter::createErrorBar_X( const drawing::Position3D& rUnscaledLogicPosition , VDataSeries& rVDataSeries, sal_Int32 nPointIndex - , const uno::Reference< drawing::XShapes >& xTarget ) + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ) { if(m_nDimension!=2) return; @@ -1287,8 +1262,8 @@ void VSeriesPlotter::createErrorBar_X( const drawing::Position3D& rUnscaledLogic uno::Reference< beans::XPropertySet > xErrorBarProp(rVDataSeries.getXErrorBarProperties(nPointIndex)); if( xErrorBarProp.is()) { - uno::Reference< drawing::XShapes > xErrorBarsGroup_Shapes( - getErrorBarsGroupShape(rVDataSeries, xTarget, false) ); + rtl::Reference<SvxShapeGroupAnyD> xErrorBarsGroup_Shapes = + getErrorBarsGroupShape(rVDataSeries, xTarget, false); createErrorBar( xErrorBarsGroup_Shapes , rUnscaledLogicPosition, xErrorBarProp @@ -1300,7 +1275,7 @@ void VSeriesPlotter::createErrorBar_X( const drawing::Position3D& rUnscaledLogic void VSeriesPlotter::createErrorBar_Y( const drawing::Position3D& rUnscaledLogicPosition , VDataSeries& rVDataSeries, sal_Int32 nPointIndex - , const uno::Reference< drawing::XShapes >& xTarget + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget , double const * pfScaledLogicX ) { if(m_nDimension!=2) @@ -1309,8 +1284,8 @@ void VSeriesPlotter::createErrorBar_Y( const drawing::Position3D& rUnscaledLogic uno::Reference< beans::XPropertySet > xErrorBarProp(rVDataSeries.getYErrorBarProperties(nPointIndex)); if( xErrorBarProp.is()) { - uno::Reference< drawing::XShapes > xErrorBarsGroup_Shapes( - getErrorBarsGroupShape(rVDataSeries, xTarget, true) ); + rtl::Reference<SvxShapeGroupAnyD> xErrorBarsGroup_Shapes = + getErrorBarsGroupShape(rVDataSeries, xTarget, true); createErrorBar( xErrorBarsGroup_Shapes , rUnscaledLogicPosition, xErrorBarProp @@ -1321,47 +1296,48 @@ void VSeriesPlotter::createErrorBar_Y( const drawing::Position3D& rUnscaledLogic } void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries const & rVDataSeries, - const uno::Reference< drawing::XShapes >& xTarget, - const uno::Reference< drawing::XShapes >& xEquationTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xEquationTarget, bool bMaySkipPoints ) { if(m_nDimension!=2) return; - uno::Reference< XRegressionCurveContainer > xContainer( rVDataSeries.getModel(), uno::UNO_QUERY ); + rtl::Reference< DataSeries > xContainer( rVDataSeries.getModel() ); if(!xContainer.is()) return; if (!m_pPosHelper) return; - uno::Sequence< uno::Reference< XRegressionCurve > > aCurveList = xContainer->getRegressionCurves(); + const std::vector< rtl::Reference< ::chart::RegressionCurveModel > > & aCurveList = xContainer->getRegressionCurves2(); - for(sal_Int32 nN=0; nN<aCurveList.getLength(); nN++) + for(std::size_t nN=0; nN<aCurveList.size(); nN++) { - uno::Reference< XRegressionCurveCalculator > xCalculator( aCurveList[nN]->getCalculator() ); + const auto & rCurve = aCurveList[nN]; + uno::Reference< XRegressionCurveCalculator > xCalculator( rCurve->getCalculator() ); if( !xCalculator.is()) continue; - uno::Reference< beans::XPropertySet > xProperties( aCurveList[nN], uno::UNO_QUERY ); - - bool bAverageLine = RegressionCurveHelper::isMeanValueLine( aCurveList[nN] ); + bool bAverageLine = RegressionCurveHelper::isMeanValueLine( rCurve ); sal_Int32 aDegree = 2; sal_Int32 aPeriod = 2; + sal_Int32 aMovingAverageType = css::chart2::MovingAverageType::Prior; double aExtrapolateForward = 0.0; double aExtrapolateBackward = 0.0; bool bForceIntercept = false; double aInterceptValue = 0.0; - if ( xProperties.is() && !bAverageLine ) + if ( !bAverageLine ) { - xProperties->getPropertyValue( "PolynomialDegree") >>= aDegree; - xProperties->getPropertyValue( "MovingAveragePeriod") >>= aPeriod; - xProperties->getPropertyValue( "ExtrapolateForward") >>= aExtrapolateForward; - xProperties->getPropertyValue( "ExtrapolateBackward") >>= aExtrapolateBackward; - xProperties->getPropertyValue( "ForceIntercept") >>= bForceIntercept; + rCurve->getPropertyValue( "PolynomialDegree") >>= aDegree; + rCurve->getPropertyValue( "MovingAveragePeriod") >>= aPeriod; + rCurve->getPropertyValue( "MovingAverageType") >>= aMovingAverageType; + rCurve->getPropertyValue( "ExtrapolateForward") >>= aExtrapolateForward; + rCurve->getPropertyValue( "ExtrapolateBackward") >>= aExtrapolateBackward; + rCurve->getPropertyValue( "ForceIntercept") >>= bForceIntercept; if (bForceIntercept) - xProperties->getPropertyValue( "InterceptValue") >>= aInterceptValue; + rCurve->getPropertyValue( "InterceptValue") >>= aInterceptValue; } double fChartMinX = m_pPosHelper->getLogicMinX(); @@ -1383,8 +1359,9 @@ void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries const & rVDataSer fPointScale = std::min(fPointScale, 1000.0); } - xCalculator->setRegressionProperties(aDegree, bForceIntercept, aInterceptValue, aPeriod); - xCalculator->recalculateRegression( rVDataSeries.getAllX(), rVDataSeries.getAllY() ); + xCalculator->setRegressionProperties(aDegree, bForceIntercept, aInterceptValue, aPeriod, + aMovingAverageType); + xCalculator->recalculateRegression(rVDataSeries.getAllX(), rVDataSeries.getAllY()); sal_Int32 nPointCount = 100 * fPointScale; if ( nPointCount < 2 ) @@ -1410,9 +1387,13 @@ void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries const & rVDataSer aRegressionPoly.SequenceX.realloc(1); aRegressionPoly.SequenceY.realloc(1); aRegressionPoly.SequenceZ.realloc(1); - aRegressionPoly.SequenceX[0].realloc(nPointCount); - aRegressionPoly.SequenceY[0].realloc(nPointCount); - aRegressionPoly.SequenceZ[0].realloc(nPointCount); + auto pSequenceX = aRegressionPoly.SequenceX.getArray(); + auto pSequenceY = aRegressionPoly.SequenceY.getArray(); + auto pSequenceZ = aRegressionPoly.SequenceZ.getArray(); + pSequenceX[0].realloc(nPointCount); + pSequenceY[0].realloc(nPointCount); + auto pSequenceX0 = pSequenceX[0].getArray(); + auto pSequenceY0 = pSequenceY[0].getArray(); sal_Int32 nRealPointCount = 0; @@ -1430,14 +1411,14 @@ void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries const & rVDataSer !std::isnan(fLogicY) && !std::isinf(fLogicY) && !std::isnan(fLogicZ) && !std::isinf(fLogicZ) ) { - aRegressionPoly.SequenceX[0][nRealPointCount] = fLogicX; - aRegressionPoly.SequenceY[0][nRealPointCount] = fLogicY; + pSequenceX0[nRealPointCount] = fLogicX; + pSequenceY0[nRealPointCount] = fLogicY; nRealPointCount++; } } - aRegressionPoly.SequenceX[0].realloc(nRealPointCount); - aRegressionPoly.SequenceY[0].realloc(nRealPointCount); - aRegressionPoly.SequenceZ[0].realloc(nRealPointCount); + pSequenceX[0].realloc(nRealPointCount); + pSequenceY[0].realloc(nRealPointCount); + pSequenceZ[0].realloc(nRealPointCount); drawing::PolyPolygonShape3D aClippedPoly; Clipping::clipPolygonAtRectangle( aRegressionPoly, m_pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly ); @@ -1448,19 +1429,19 @@ void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries const & rVDataSer if( aRegressionPoly.SequenceX.hasElements() && aRegressionPoly.SequenceX[0].hasElements() ) { VLineProperties aVLineProperties; - aVLineProperties.initFromPropertySet( xProperties ); + aVLineProperties.initFromPropertySet( rCurve ); //create an extra group shape for each curve for selection handling - uno::Reference< drawing::XShapes > xRegressionGroupShapes = + rtl::Reference<SvxShapeGroupAnyD> xRegressionGroupShapes = createGroupShape( xTarget, rVDataSeries.getDataCurveCID( nN, bAverageLine ) ); - uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D( + rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D( xRegressionGroupShapes, PolyToPointSequence( aRegressionPoly ), &aVLineProperties ); ShapeFactory::setShapeName( xShape, "MarkHandles" ); aDefaultPos = xShape->getPosition(); } // curve equation and correlation coefficient - uno::Reference< beans::XPropertySet > xEquationProperties( aCurveList[nN]->getEquationProperties()); + uno::Reference< beans::XPropertySet > xEquationProperties( rCurve->getEquationProperties()); if( xEquationProperties.is()) { createRegressionCurveEquationShapes( @@ -1493,7 +1474,7 @@ static sal_Int32 lcl_getOUStringMaxLineLength ( OUStringBuffer const & aString ) void VSeriesPlotter::createRegressionCurveEquationShapes( const OUString & rEquationCID, const uno::Reference< beans::XPropertySet > & xEquationProperties, - const uno::Reference< drawing::XShapes >& xEquationTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xEquationTarget, const uno::Reference< chart2::XRegressionCurveCalculator > & xRegressionCurveCalculator, awt::Point aDefaultPos ) { @@ -1551,7 +1532,7 @@ void VSeriesPlotter::createRegressionCurveEquationShapes( } if( bShowCorrCoeff ) { - aFormula.append( "R" ).append( OUStringChar( aSuperscriptFigures[2] ) ).append( " = " ); + aFormula.append( "R" + OUStringChar( aSuperscriptFigures[2] ) + " = " ); double fR( xRegressionCurveCalculator->getCorrelationCoefficient()); if (m_apNumberFormatterWrapper) { @@ -1592,65 +1573,51 @@ void VSeriesPlotter::createRegressionCurveEquationShapes( tAnySequence aValues; PropertyMapper::getPreparedTextShapePropertyLists( xEquationProperties, aNames, aValues ); - uno::Reference< drawing::XShape > xTextShape = m_pShapeFactory->createText( + rtl::Reference<SvxShapeText> xTextShape = ShapeFactory::createText( xEquationTarget, aFormula.makeStringAndClear(), aNames, aValues, ShapeFactory::makeTransformation( aScreenPosition2D )); - OSL_ASSERT( xTextShape.is()); - if( xTextShape.is()) + ShapeFactory::setShapeName( xTextShape, rEquationCID ); + awt::Size aSize( xTextShape->getSize() ); + awt::Point aPos( RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( + aScreenPosition2D, aSize, aRelativePosition.Anchor ) ); + //ensure that the equation is fully placed within the page (if possible) + if( (aPos.X + aSize.Width) > m_aPageReferenceSize.Width ) + aPos.X = m_aPageReferenceSize.Width - aSize.Width; + if( aPos.X < 0 ) { - ShapeFactory::setShapeName( xTextShape, rEquationCID ); - awt::Size aSize( xTextShape->getSize() ); - awt::Point aPos( RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( - aScreenPosition2D, aSize, aRelativePosition.Anchor ) ); - //ensure that the equation is fully placed within the page (if possible) - if( (aPos.X + aSize.Width) > m_aPageReferenceSize.Width ) - aPos.X = m_aPageReferenceSize.Width - aSize.Width; - if( aPos.X < 0 ) + aPos.X = 0; + if ( nFormulaWidth > 0 ) { - aPos.X = 0; - if ( nFormulaWidth > 0 ) - { - bResizeEquation = true; - if ( nCountIteration < nMaxIteration-1 ) - xEquationTarget->remove( xTextShape ); // remove equation - nFormulaWidth *= m_aPageReferenceSize.Width / static_cast< double >(aSize.Width); - nFormulaWidth -= nCountIteration; - if ( nFormulaWidth < 0 ) - nFormulaWidth = 0; - } + bResizeEquation = true; + if ( nCountIteration < nMaxIteration-1 ) + xEquationTarget->remove( xTextShape ); // remove equation + nFormulaWidth *= m_aPageReferenceSize.Width / static_cast< double >(aSize.Width); + nFormulaWidth -= nCountIteration; + if ( nFormulaWidth < 0 ) + nFormulaWidth = 0; } - if( (aPos.Y + aSize.Height) > m_aPageReferenceSize.Height ) - aPos.Y = m_aPageReferenceSize.Height - aSize.Height; - if( aPos.Y < 0 ) - aPos.Y = 0; - if ( !bResizeEquation || nCountIteration == nMaxIteration-1 ) - xTextShape->setPosition(aPos); // if equation was not removed } + if( (aPos.Y + aSize.Height) > m_aPageReferenceSize.Height ) + aPos.Y = m_aPageReferenceSize.Height - aSize.Height; + if( aPos.Y < 0 ) + aPos.Y = 0; + if ( !bResizeEquation || nCountIteration == nMaxIteration-1 ) + xTextShape->setPosition(aPos); // if equation was not removed } } } -void VSeriesPlotter::setMappedProperties( - const uno::Reference< drawing::XShape >& xTargetShape - , const uno::Reference< beans::XPropertySet >& xSource - , const tPropertyNameMap& rMap - , tPropertyNameValueMap const * pOverwriteMap ) -{ - uno::Reference< beans::XPropertySet > xTargetProp( xTargetShape, uno::UNO_QUERY ); - PropertyMapper::setMappedProperties(xTargetProp,xSource,rMap,pOverwriteMap); -} - -void VSeriesPlotter::setTimeResolutionOnXAxis( long TimeResolution, const Date& rNullDate ) +void VSeriesPlotter::setTimeResolutionOnXAxis( tools::Long TimeResolution, const Date& rNullDate ) { m_nTimeResolution = TimeResolution; m_aNullDate = rNullDate; } // MinimumAndMaximumSupplier -long VSeriesPlotter::calculateTimeResolutionOnXAxis() +tools::Long VSeriesPlotter::calculateTimeResolutionOnXAxis() { - long nRet = css::chart::TimeUnit::YEAR; + tools::Long nRet = css::chart::TimeUnit::YEAR; if (!m_pExplicitCategoriesProvider) return nRet; @@ -1696,13 +1663,13 @@ long VSeriesPlotter::calculateTimeResolutionOnXAxis() double VSeriesPlotter::getMinimumX() { double fMinimum, fMaximum; - getMinimumAndMaximiumX( fMinimum, fMaximum ); + getMinimumAndMaximumX( fMinimum, fMaximum ); return fMinimum; } double VSeriesPlotter::getMaximumX() { double fMinimum, fMaximum; - getMinimumAndMaximiumX( fMinimum, fMaximum ); + getMinimumAndMaximumX( fMinimum, fMaximum ); return fMaximum; } @@ -1711,13 +1678,12 @@ double VSeriesPlotter::getMinimumYInRange( double fMinimumX, double fMaximumX, s if( !m_bCategoryXAxis || ( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() ) ) { double fMinY, fMaxY; - getMinimumAndMaximiumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex ); + getMinimumAndMaximumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex ); return fMinY; } - double fMinimum, fMaximum; - ::rtl::math::setInf(&fMinimum, false); - ::rtl::math::setInf(&fMaximum, true); + double fMinimum = std::numeric_limits<double>::infinity(); + double fMaximum = -std::numeric_limits<double>::infinity(); for(std::vector<VDataSeriesGroup> & rXSlots : m_aZSlots) { for(VDataSeriesGroup & rXSlot : rXSlots) @@ -1735,7 +1701,7 @@ double VSeriesPlotter::getMinimumYInRange( double fMinimumX, double fMaximumX, s } } if(std::isinf(fMinimum)) - ::rtl::math::setNan(&fMinimum); + return std::numeric_limits<double>::quiet_NaN(); return fMinimum; } @@ -1744,13 +1710,12 @@ double VSeriesPlotter::getMaximumYInRange( double fMinimumX, double fMaximumX, s if( !m_bCategoryXAxis || ( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() ) ) { double fMinY, fMaxY; - getMinimumAndMaximiumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex ); + getMinimumAndMaximumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex ); return fMaxY; } - double fMinimum, fMaximum; - ::rtl::math::setInf(&fMinimum, false); - ::rtl::math::setInf(&fMaximum, true); + double fMinimum = std::numeric_limits<double>::infinity(); + double fMaximum = -std::numeric_limits<double>::infinity(); for( std::vector< VDataSeriesGroup > & rXSlots : m_aZSlots) { for(VDataSeriesGroup & rXSlot : rXSlots) @@ -1768,7 +1733,7 @@ double VSeriesPlotter::getMaximumYInRange( double fMinimumX, double fMaximumX, s } } if(std::isinf(fMaximum)) - ::rtl::math::setNan(&fMaximum); + return std::numeric_limits<double>::quiet_NaN(); return fMaximum; } @@ -1824,17 +1789,17 @@ bool VSeriesPlotter::isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIn return nDimensionIndex == 1; } -void VSeriesPlotter::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const +void VSeriesPlotter::getMinimumAndMaximumX( double& rfMinimum, double& rfMaximum ) const { - ::rtl::math::setInf(&rfMinimum, false); - ::rtl::math::setInf(&rfMaximum, true); + rfMinimum = std::numeric_limits<double>::infinity(); + rfMaximum = -std::numeric_limits<double>::infinity(); for (auto const& ZSlot : m_aZSlots) { for (auto const& XSlot : ZSlot) { double fLocalMinimum, fLocalMaximum; - XSlot.getMinimumAndMaximiumX( fLocalMinimum, fLocalMaximum ); + XSlot.getMinimumAndMaximumX( fLocalMinimum, fLocalMaximum ); if( !std::isnan(fLocalMinimum) && fLocalMinimum< rfMinimum ) rfMinimum = fLocalMinimum; if( !std::isnan(fLocalMaximum) && fLocalMaximum> rfMaximum ) @@ -1842,22 +1807,22 @@ void VSeriesPlotter::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximu } } if(std::isinf(rfMinimum)) - ::rtl::math::setNan(&rfMinimum); + rfMinimum = std::numeric_limits<double>::quiet_NaN(); if(std::isinf(rfMaximum)) - ::rtl::math::setNan(&rfMaximum); + rfMaximum = std::numeric_limits<double>::quiet_NaN(); } -void VSeriesPlotter::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const +void VSeriesPlotter::getMinimumAndMaximumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const { - ::rtl::math::setInf(&rfMinY, false); - ::rtl::math::setInf(&rfMaxY, true); + rfMinY = std::numeric_limits<double>::infinity(); + rfMaxY = -std::numeric_limits<double>::infinity(); for (auto const& ZSlot : m_aZSlots) { for (auto const& XSlot : ZSlot) { double fLocalMinimum, fLocalMaximum; - XSlot.getMinimumAndMaximiumYInContinuousXRange( fLocalMinimum, fLocalMaximum, fMinX, fMaxX, nAxisIndex ); + XSlot.getMinimumAndMaximumYInContinuousXRange( fLocalMinimum, fLocalMaximum, fMinX, fMaxX, nAxisIndex ); if( !std::isnan(fLocalMinimum) && fLocalMinimum< rfMinY ) rfMinY = fLocalMinimum; if( !std::isnan(fLocalMaximum) && fLocalMaximum> rfMaxY ) @@ -1865,9 +1830,9 @@ void VSeriesPlotter::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, d } } if(std::isinf(rfMinY)) - ::rtl::math::setNan(&rfMinY); + rfMinY = std::numeric_limits<double>::quiet_NaN(); if(std::isinf(rfMaxY)) - ::rtl::math::setNan(&rfMaxY); + rfMaxY = std::numeric_limits<double>::quiet_NaN(); } sal_Int32 VSeriesPlotter::getPointCount() const @@ -1932,11 +1897,11 @@ sal_Int32 VDataSeriesGroup::getAttachedAxisIndexForFirstSeries() const return nRet; } -void VDataSeriesGroup::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const +void VDataSeriesGroup::getMinimumAndMaximumX( double& rfMinimum, double& rfMaximum ) const { - ::rtl::math::setInf(&rfMinimum, false); - ::rtl::math::setInf(&rfMaximum, true); + rfMinimum = std::numeric_limits<double>::infinity(); + rfMaximum = -std::numeric_limits<double>::infinity(); for (std::unique_ptr<VDataSeries> const & pSeries : m_aSeriesVector) { @@ -1953,9 +1918,9 @@ void VDataSeriesGroup::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaxi } } if(std::isinf(rfMinimum)) - ::rtl::math::setNan(&rfMinimum); + rfMinimum = std::numeric_limits<double>::quiet_NaN(); if(std::isinf(rfMaximum)) - ::rtl::math::setNan(&rfMaximum); + rfMaximum = std::numeric_limits<double>::quiet_NaN(); } namespace { @@ -1978,7 +1943,7 @@ class PerXMinMaxCalculator { typedef std::pair<double, double> MinMaxType; typedef std::map<size_t, MinMaxType> SeriesMinMaxType; - typedef std::map<double, std::unique_ptr<SeriesMinMaxType>> GroupMinMaxType; + typedef std::map<double, SeriesMinMaxType> GroupMinMaxType; typedef std::unordered_map<double, MinMaxType> TotalStoreType; GroupMinMaxType m_SeriesGroup; size_t mnCurSeries; @@ -2016,14 +1981,15 @@ public: void getTotalRange(double& rfMin, double& rfMax) const { - rtl::math::setNan(&rfMin); - rtl::math::setNan(&rfMax); - TotalStoreType aStore; getTotalStore(aStore); if (aStore.empty()) + { + rfMin = std::numeric_limits<double>::quiet_NaN(); + rfMax = std::numeric_limits<double>::quiet_NaN(); return; + } TotalStoreType::const_iterator it = aStore.begin(), itEnd = aStore.end(); rfMin = it->second.first; @@ -2049,7 +2015,7 @@ private: { double fX = it.first; - const SeriesMinMaxType& rSeries = *it.second; + const SeriesMinMaxType& rSeries = it.second; for (auto const& series : rSeries) { double fYMin = series.second.first, fYMax = series.second.second; @@ -2076,7 +2042,7 @@ private: if (it == m_SeriesGroup.end()) { std::pair<GroupMinMaxType::iterator,bool> r = - m_SeriesGroup.insert(std::make_pair(fX, std::make_unique<SeriesMinMaxType>())); + m_SeriesGroup.insert(std::make_pair(fX, SeriesMinMaxType{})); if (!r.second) // insertion failed. @@ -2085,17 +2051,17 @@ private: it = r.first; } - return it->second.get(); + return &it->second; } }; } -void VDataSeriesGroup::getMinimumAndMaximiumYInContinuousXRange( +void VDataSeriesGroup::getMinimumAndMaximumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const { - ::rtl::math::setNan(&rfMinY); - ::rtl::math::setNan(&rfMaxY); + rfMinY = std::numeric_limits<double>::quiet_NaN(); + rfMaxY = std::numeric_limits<double>::quiet_NaN(); if (m_aSeriesVector.empty()) // No data series. Bail out. @@ -2134,13 +2100,13 @@ void VDataSeriesGroup::getMinimumAndMaximiumYInContinuousXRange( void VDataSeriesGroup::calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex , bool bSeparateStackingForDifferentSigns - , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ) + , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ) const { assert(nCategoryIndex >= 0); assert(nCategoryIndex < getPointCount()); - ::rtl::math::setInf(&rfMinimumY, false); - ::rtl::math::setInf(&rfMaximumY, true); + rfMinimumY = std::numeric_limits<double>::infinity(); + rfMaximumY = -std::numeric_limits<double>::infinity(); if(m_aSeriesVector.empty()) return; @@ -2154,12 +2120,11 @@ void VDataSeriesGroup::calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex return; } - double fTotalSum, fPositiveSum, fNegativeSum, fFirstPositiveY, fFirstNegativeY; - ::rtl::math::setNan( &fTotalSum ); - ::rtl::math::setNan( &fPositiveSum ); - ::rtl::math::setNan( &fNegativeSum ); - ::rtl::math::setNan( &fFirstPositiveY ); - ::rtl::math::setNan( &fFirstNegativeY ); + double fTotalSum = std::numeric_limits<double>::quiet_NaN(); + double fPositiveSum = std::numeric_limits<double>::quiet_NaN(); + double fNegativeSum = std::numeric_limits<double>::quiet_NaN(); + double fFirstPositiveY = std::numeric_limits<double>::quiet_NaN(); + double fFirstNegativeY = std::numeric_limits<double>::quiet_NaN(); if( bSeparateStackingForDifferentSigns ) { @@ -2227,8 +2192,8 @@ void VDataSeriesGroup::calculateYMinAndMaxForCategoryRange( , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ) { //@todo maybe cache these values - ::rtl::math::setInf(&rfMinimumY, false); - ::rtl::math::setInf(&rfMaximumY, true); + rfMinimumY = std::numeric_limits<double>::infinity(); + rfMaximumY = -std::numeric_limits<double>::infinity(); //iterate through the given categories if(nStartCategoryIndex<0) @@ -2242,8 +2207,8 @@ void VDataSeriesGroup::calculateYMinAndMaxForCategoryRange( nEndCategoryIndex=0; for( sal_Int32 nCatIndex = nStartCategoryIndex; nCatIndex <= nEndCategoryIndex; nCatIndex++ ) { - double fMinimumY; ::rtl::math::setNan(&fMinimumY); - double fMaximumY; ::rtl::math::setNan(&fMaximumY); + double fMinimumY = std::numeric_limits<double>::quiet_NaN(); + double fMaximumY = std::numeric_limits<double>::quiet_NaN(); calculateYMinAndMaxForCategory( nCatIndex , bSeparateStackingForDifferentSigns, fMinimumY, fMaximumY, nAxisIndex ); @@ -2294,8 +2259,7 @@ PlottingPositionHelper& VSeriesPlotter::getPlottingPositionHelper( sal_Int32 nAx } if( !pRet ) pRet = m_pMainPosHelper; - if(pRet) - pRet->setTimeResolution( m_nTimeResolution, m_aNullDate ); + pRet->setTimeResolution( m_nTimeResolution, m_aNullDate ); return *pRet; } @@ -2333,12 +2297,83 @@ OUString VSeriesPlotter::getCategoryName( sal_Int32 nPointIndex ) const return OUString(); } -uno::Sequence< OUString > VSeriesPlotter::getSeriesNames() const +namespace { +// The following it to support rendering order for combo charts. A chart type +// with a lower rendering order is rendered before (i.e., behind) a chart with a +// higher rendering order. The rendering orders are based on rough guesses about +// how much one chart (type) will obscure another chart (type). The intent is to +// minimize obscuring of data, by putting charts that generally cover more +// pixels (e.g., area charts) behind ones that generally cover fewer (e.g., line +// charts). +struct ROrderPair +{ + ROrderPair(OUString n, sal_Int32 r) : chartName(n), renderOrder(r) {} + + OUString chartName; + sal_Int32 renderOrder; +}; + +const ROrderPair pairList[] = { + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_AREA, 0), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_BAR, 6), // bar & column are same + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN, 6), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_LINE, 8), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER, 5), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_PIE, 1), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_NET, 3), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET, 2), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK, 7), + ROrderPair(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE, 4) +}; +} // unnamed + +sal_Int32 VSeriesPlotter::getRenderOrder() const +{ + OUString aChartType = m_xChartTypeModel->getChartType(); + for (const auto& elem : pairList) { + if (aChartType.equalsIgnoreAsciiCase(elem.chartName)) { + return elem.renderOrder; + } + } + SAL_WARN("chart2", "Unsupported chart type in getRenderOrder()"); + return 0; +} + +std::vector<VDataSeries const*> VSeriesPlotter::getAllSeries() const +{ + std::vector<VDataSeries const*> aAllSeries; + for (std::vector<VDataSeriesGroup> const & rXSlot : m_aZSlots) + { + for(VDataSeriesGroup const & rGroup : rXSlot) + { + for (std::unique_ptr<VDataSeries> const & p : rGroup.m_aSeriesVector) + aAllSeries.push_back(p.get()); + } + } + return aAllSeries; +} + + +std::vector<VDataSeries*> VSeriesPlotter::getAllSeries() +{ + std::vector<VDataSeries*> aAllSeries; + for (std::vector<VDataSeriesGroup> const & rXSlot : m_aZSlots) + { + for(VDataSeriesGroup const & rGroup : rXSlot) + { + for (std::unique_ptr<VDataSeries> const & p : rGroup.m_aSeriesVector) + aAllSeries.push_back(p.get()); + } + } + return aAllSeries; +} + +uno::Sequence<OUString> VSeriesPlotter::getSeriesNames() const { std::vector<OUString> aRetVector; OUString aRole; - if( m_xChartTypeModel.is() ) + if (m_xChartTypeModel.is()) aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel(); for (auto const& rGroup : m_aZSlots) @@ -2349,10 +2384,10 @@ uno::Sequence< OUString > VSeriesPlotter::getSeriesNames() const if (!rSeriesGroup.m_aSeriesVector.empty()) { VDataSeries const * pSeries = rSeriesGroup.m_aSeriesVector[0].get(); - uno::Reference< XDataSeries > xSeries( pSeries ? pSeries->getModel() : nullptr ); + rtl::Reference< DataSeries > xSeries( pSeries ? pSeries->getModel() : nullptr ); if( xSeries.is() ) { - OUString aSeriesName( DataSeriesHelper::getDataSeriesLabel( xSeries, aRole ) ); + OUString aSeriesName( xSeries->getLabelForRole( aRole ) ); aRetVector.push_back( aSeriesName ); } } @@ -2361,6 +2396,25 @@ uno::Sequence< OUString > VSeriesPlotter::getSeriesNames() const return comphelper::containerToSequence( aRetVector ); } +uno::Sequence<OUString> VSeriesPlotter::getAllSeriesNames() const +{ + std::vector<OUString> aRetVector; + + OUString aRole; + if (m_xChartTypeModel.is()) + aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel(); + + for (VDataSeries const* pSeries : getAllSeries()) + { + if (pSeries) + { + OUString aSeriesName(pSeries->getModel()->getLabelForRole(aRole)); + aRetVector.push_back(aSeriesName); + } + } + return comphelper::containerToSequence(aRetVector); +} + void VSeriesPlotter::setPageReferenceSize( const css::awt::Size & rPageRefSize ) { m_aPageReferenceSize = rPageRefSize; @@ -2397,8 +2451,7 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntries( const awt::Size& rEntryKeyAspectRatio , LegendPosition eLegendPosition , const Reference< beans::XPropertySet >& xTextProperties - , const Reference< drawing::XShapes >& xTarget - , const Reference< lang::XMultiServiceFactory >& xShapeFactory + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const Reference< uno::XComponentContext >& xContext , ChartModel& rModel ) @@ -2407,14 +2460,13 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntries( if( xTarget.is() ) { - uno::Reference< XCoordinateSystemContainer > xCooSysCnt( rModel.getFirstDiagram(), uno::UNO_QUERY ); - Reference< chart2::XCoordinateSystem > xCooSys(xCooSysCnt->getCoordinateSystems()[0]); - Reference< beans::XPropertySet > xProp( xCooSys, uno::UNO_QUERY ); + rtl::Reference< Diagram > xDiagram = rModel.getFirstChartDiagram(); + rtl::Reference< BaseCoordinateSystem > xCooSys(xDiagram->getBaseCoordinateSystems()[0]); bool bSwapXAndY = false; - if( xProp.is()) try + try { - xProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY; + xCooSys->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY; } catch( const uno::Exception& ) { @@ -2434,7 +2486,8 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntries( if (!pSeries) continue; - if (!pSeries->getPropertiesOfSeries()->getPropertyValue("ShowLegendEntry").get<sal_Bool>()) + // "ShowLegendEntry" + if (!pSeries->getModel()->getFastPropertyValue(PROP_DATASERIES_SHOW_LEGEND_ENTRY).get<sal_Bool>()) { continue; } @@ -2442,7 +2495,7 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntries( std::vector<ViewLegendEntry> aSeriesEntries( createLegendEntriesForSeries( rEntryKeyAspectRatio, *pSeries, xTextProperties, - xTarget, xShapeFactory, xContext)); + xTarget, xContext)); //add series entries to the result now @@ -2480,18 +2533,45 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntries( return aResult; } -std::vector<VDataSeries*> VSeriesPlotter::getAllSeries() +std::vector<ViewLegendSymbol> VSeriesPlotter::createSymbols(const awt::Size& rEntryKeyAspectRatio + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const Reference<uno::XComponentContext>& xContext) { - std::vector<VDataSeries*> aAllSeries; - for (std::vector<VDataSeriesGroup> const & rXSlot : m_aZSlots) + std::vector<ViewLegendSymbol> aResult; + + if( xTarget.is() ) { - for(VDataSeriesGroup const & rGroup : rXSlot) + bool bBreak = false; + bool bFirstSeries = true; + + for (std::vector<VDataSeriesGroup> const & rGroupVector : m_aZSlots) { - for (std::unique_ptr<VDataSeries> const & p : rGroup.m_aSeriesVector) - aAllSeries.push_back(p.get()); + for (VDataSeriesGroup const & rGroup : rGroupVector) + { + for (std::unique_ptr<VDataSeries> const & pSeries : rGroup.m_aSeriesVector) + { + if (!pSeries) + continue; + + std::vector<ViewLegendSymbol> aSeriesSymbols = createSymbolsForSeries(rEntryKeyAspectRatio, *pSeries, xTarget, xContext); + + //add series entries to the result now + + // use only the first series if VaryColorsByPoint is set for the first series + if (bFirstSeries && pSeries->isVaryColorsByPoint()) + bBreak = true; + + bFirstSeries = false; + + aResult.insert(aResult.end(), aSeriesSymbols.begin(), aSeriesSymbols.end()); + } + if (bBreak) + return aResult; + } } } - return aAllSeries; + + return aResult; } namespace @@ -2514,19 +2594,11 @@ bool lcl_HasVisibleLine( const uno::Reference< beans::XPropertySet >& xProps, bo bool lcl_HasRegressionCurves( const VDataSeries& rSeries, bool& rbHasDashedLine ) { bool bHasRegressionCurves = false; - Reference< XRegressionCurveContainer > xRegrCont( rSeries.getModel(), uno::UNO_QUERY ); - if( xRegrCont.is()) + rtl::Reference< DataSeries > xRegrCont( rSeries.getModel() ); + for( const rtl::Reference< RegressionCurveModel > & rCurve : xRegrCont->getRegressionCurves2() ) { - Sequence< Reference< XRegressionCurve > > aCurves( xRegrCont->getRegressionCurves() ); - sal_Int32 i = 0, nCount = aCurves.getLength(); - for( i=0; i<nCount; ++i ) - { - if( aCurves[i].is() ) - { - bHasRegressionCurves = true; - lcl_HasVisibleLine( uno::Reference< beans::XPropertySet >( aCurves[i], uno::UNO_QUERY ), rbHasDashedLine ); - } - } + bHasRegressionCurves = true; + lcl_HasVisibleLine( rCurve, rbHasDashedLine ); } return bHasRegressionCurves; } @@ -2587,11 +2659,10 @@ uno::Any VSeriesPlotter::getExplicitSymbol( const VDataSeries& /*rSeries*/, sal_ return uno::Any(); } -Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForSeries( +rtl::Reference<SvxShapeGroup> VSeriesPlotter::createLegendSymbolForSeries( const awt::Size& rEntryKeyAspectRatio , const VDataSeries& rSeries - , const Reference< drawing::XShapes >& xTarget - , const Reference< lang::XMultiServiceFactory >& xShapeFactory ) + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ) { LegendSymbolStyle eLegendSymbolStyle = getLegendSymbolStyle(); @@ -2610,19 +2681,18 @@ Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForSeries( default: break; } - Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio, - xTarget, eLegendSymbolStyle, xShapeFactory - , rSeries.getPropertiesOfSeries(), ePropType, aExplicitSymbol )); + rtl::Reference<SvxShapeGroup> xShape = VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio, + xTarget, eLegendSymbolStyle, + rSeries.getPropertiesOfSeries(), ePropType, aExplicitSymbol ); return xShape; } -Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForPoint( +rtl::Reference< SvxShapeGroup > VSeriesPlotter::createLegendSymbolForPoint( const awt::Size& rEntryKeyAspectRatio , const VDataSeries& rSeries , sal_Int32 nPointIndex - , const Reference< drawing::XShapes >& xTarget - , const Reference< lang::XMultiServiceFactory >& xShapeFactory ) + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ) { LegendSymbolStyle eLegendSymbolStyle = getLegendSymbolStyle(); @@ -2666,8 +2736,8 @@ Reference< drawing::XShape > VSeriesPlotter::createLegendSymbolForPoint( } } - Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio, - xTarget, eLegendSymbolStyle, xShapeFactory, xPointSet, ePropType, aExplicitSymbol )); + rtl::Reference< SvxShapeGroup > xShape = VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio, + xTarget, eLegendSymbolStyle, xPointSet, ePropType, aExplicitSymbol ); return xShape; } @@ -2676,14 +2746,13 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( const awt::Size& rEntryKeyAspectRatio , const VDataSeries& rSeries , const Reference< beans::XPropertySet >& xTextProperties - , const Reference< drawing::XShapes >& xTarget - , const Reference< lang::XMultiServiceFactory >& xShapeFactory + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const Reference< uno::XComponentContext >& xContext ) { std::vector< ViewLegendEntry > aResult; - if( ! ( xShapeFactory.is() && xTarget.is() && xContext.is() ) ) + if( ! ( xTarget.is() && xContext.is() ) ) return aResult; try @@ -2691,7 +2760,23 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( ViewLegendEntry aEntry; OUString aLabelText; bool bVaryColorsByPoint = rSeries.isVaryColorsByPoint(); - if( bVaryColorsByPoint ) + bool bIsPie = m_xChartTypeModel->getChartType().equalsIgnoreAsciiCase( + CHART2_SERVICE_NAME_CHARTTYPE_PIE); + try + { + if (bIsPie) + { + bool bDonut = false; + // "UseRings" + if ((m_xChartTypeModel->getFastPropertyValue(PROP_PIECHARTTYPE_USE_RINGS) >>= bDonut) && bDonut) + bIsPie = false; + } + } + catch (const uno::Exception&) + { + } + + if (bVaryColorsByPoint || bIsPie) { Sequence< OUString > aCategoryNames; if( m_pExplicitCategoriesProvider ) @@ -2699,7 +2784,8 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( Sequence<sal_Int32> deletedLegendEntries; try { - rSeries.getPropertiesOfSeries()->getPropertyValue("DeletedLegendEntries") >>= deletedLegendEntries; + // "DeletedLegendEntries" + rSeries.getModel()->getFastPropertyValue(PROP_DATASERIES_DELETED_LEGEND_ENTRIES) >>= deletedLegendEntries; } catch (const uno::Exception&) { @@ -2707,7 +2793,7 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( for( sal_Int32 nIdx=0; nIdx<aCategoryNames.getLength(); ++nIdx ) { bool deletedLegendEntry = false; - for (auto& deletedLegendEntryIdx : deletedLegendEntries) + for (const auto& deletedLegendEntryIdx : deletedLegendEntries) { if (nIdx == deletedLegendEntryIdx) { @@ -2719,16 +2805,16 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( continue; // symbol - uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory::getOrCreateShapeFactory(xShapeFactory)->createGroup2D( xTarget )); + rtl::Reference< SvxShapeGroup > xSymbolGroup(ShapeFactory::createGroup2D( xTarget )); // create the symbol - Reference< drawing::XShape > xShape( createLegendSymbolForPoint( rEntryKeyAspectRatio, - rSeries, nIdx, xSymbolGroup, xShapeFactory ) ); + rtl::Reference< SvxShapeGroup > xShape = createLegendSymbolForPoint( rEntryKeyAspectRatio, + rSeries, nIdx, xSymbolGroup ); // set CID to symbol for selection if( xShape.is() ) { - aEntry.aSymbol.set( xSymbolGroup, uno::UNO_QUERY ); + aEntry.xSymbol = xSymbolGroup; OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_DATA_POINT, nIdx ) ); aChildParticle = ObjectIdentifier::addChildParticle( aChildParticle, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) ); @@ -2740,7 +2826,7 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( aLabelText = aCategoryNames[nIdx]; if( xShape.is() || !aLabelText.isEmpty() ) { - aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aLabelText, xTextProperties ); + aEntry.xLabel = FormattedStringHelper::createFormattedString( aLabelText, xTextProperties ); aResult.push_back(aEntry); } } @@ -2748,16 +2834,16 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( else { // symbol - uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory::getOrCreateShapeFactory(xShapeFactory)->createGroup2D( xTarget )); + rtl::Reference< SvxShapeGroup > xSymbolGroup(ShapeFactory::createGroup2D( xTarget )); // create the symbol - Reference< drawing::XShape > xShape( createLegendSymbolForSeries( - rEntryKeyAspectRatio, rSeries, xSymbolGroup, xShapeFactory ) ); + rtl::Reference<SvxShapeGroup> xShape = createLegendSymbolForSeries( + rEntryKeyAspectRatio, rSeries, xSymbolGroup ); // set CID to symbol for selection if( xShape.is()) { - aEntry.aSymbol.set( xSymbolGroup, uno::UNO_QUERY ); + aEntry.xSymbol = xSymbolGroup; OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) ); OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle ); @@ -2765,8 +2851,8 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( } // label - aLabelText = DataSeriesHelper::getDataSeriesLabel( rSeries.getModel(), m_xChartTypeModel.is() ? m_xChartTypeModel->getRoleOfSequenceForSeriesLabel() : "values-y"); - aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aLabelText, xTextProperties ); + aLabelText = rSeries.getModel()->getLabelForRole( m_xChartTypeModel.is() ? m_xChartTypeModel->getRoleOfSequenceForSeriesLabel() : "values-y"); + aEntry.xLabel = FormattedStringHelper::createFormattedString( aLabelText, xTextProperties ); aResult.push_back(aEntry); } @@ -2776,44 +2862,41 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( if (!ChartTypeHelper::isSupportingStatisticProperties( m_xChartTypeModel, m_nDimension )) return aResult; - Reference< XRegressionCurveContainer > xRegrCont( rSeries.getModel(), uno::UNO_QUERY ); + rtl::Reference< DataSeries > xRegrCont = rSeries.getModel(); if( xRegrCont.is()) { - Sequence< Reference< XRegressionCurve > > aCurves( xRegrCont->getRegressionCurves()); - sal_Int32 i = 0, nCount = aCurves.getLength(); + const std::vector< rtl::Reference< RegressionCurveModel > > & aCurves = xRegrCont->getRegressionCurves2(); + sal_Int32 i = 0, nCount = aCurves.size(); for( i=0; i<nCount; ++i ) { - if( aCurves[i].is() ) + //label + OUString aResStr( RegressionCurveHelper::getUINameForRegressionCurve( aCurves[i] ) ); + replaceParamterInString( aResStr, u"%SERIESNAME", aLabelText ); + aEntry.xLabel = FormattedStringHelper::createFormattedString( aResStr, xTextProperties ); + + // symbol + rtl::Reference<SvxShapeGroup> xSymbolGroup(ShapeFactory::createGroup2D( xTarget )); + + // create the symbol + rtl::Reference<SvxShapeGroup> xShape = VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio, + xSymbolGroup, LegendSymbolStyle::Line, + aCurves[i], + VLegendSymbolFactory::PropertyType::Line, uno::Any() ); + + // set CID to symbol for selection + if( xShape.is()) { - //label - OUString aResStr( RegressionCurveHelper::getUINameForRegressionCurve( aCurves[i] ) ); - replaceParamterInString( aResStr, "%SERIESNAME", aLabelText ); - aEntry.aLabel = FormattedStringHelper::createFormattedStringSequence( xContext, aResStr, xTextProperties ); - - // symbol - uno::Reference< drawing::XShapes > xSymbolGroup( ShapeFactory::getOrCreateShapeFactory(xShapeFactory)->createGroup2D( xTarget )); - - // create the symbol - Reference< drawing::XShape > xShape( VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio, - xSymbolGroup, LegendSymbolStyle::Line, xShapeFactory, - Reference< beans::XPropertySet >( aCurves[i], uno::UNO_QUERY ), - VLegendSymbolFactory::PropertyType::Line, uno::Any() )); - - // set CID to symbol for selection - if( xShape.is()) - { - aEntry.aSymbol.set( xSymbolGroup, uno::UNO_QUERY ); - - bool bAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[i] ); - ObjectType eObjectType = bAverageLine ? OBJECTTYPE_DATA_AVERAGE_LINE : OBJECTTYPE_DATA_CURVE; - OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( eObjectType, i ) ); - aChildParticle = ObjectIdentifier::addChildParticle( aChildParticle, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) ); - OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle ); - ShapeFactory::setShapeName( xShape, aCID ); - } + aEntry.xSymbol = xSymbolGroup; - aResult.push_back(aEntry); + bool bAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[i] ); + ObjectType eObjectType = bAverageLine ? OBJECTTYPE_DATA_AVERAGE_LINE : OBJECTTYPE_DATA_CURVE; + OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( eObjectType, i ) ); + aChildParticle = ObjectIdentifier::addChildParticle( aChildParticle, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) ); + OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle ); + ShapeFactory::setShapeName( xShape, aCID ); } + + aResult.push_back(aEntry); } } } @@ -2824,8 +2907,42 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( return aResult; } +std::vector<ViewLegendSymbol> VSeriesPlotter::createSymbolsForSeries( + const awt::Size& rEntryKeyAspectRatio + , const VDataSeries& rSeries + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const Reference<uno::XComponentContext>& xContext) +{ + std::vector<ViewLegendSymbol> aResult; + + if (!(xTarget.is() && xContext.is())) + return aResult; + + try + { + ViewLegendSymbol aEntry; + // symbol + rtl::Reference<SvxShapeGroup> xSymbolGroup(ShapeFactory::createGroup2D(xTarget)); + + // create the symbol + rtl::Reference<SvxShapeGroup> xShape = createLegendSymbolForSeries(rEntryKeyAspectRatio, rSeries, xSymbolGroup ); + + // set CID to symbol for selection + if (xShape.is()) + { + aEntry.xSymbol = xSymbolGroup; + aResult.push_back(aEntry); + } + } + catch (const uno::Exception &) + { + DBG_UNHANDLED_EXCEPTION("chart2" ); + } + return aResult; +} + VSeriesPlotter* VSeriesPlotter::createSeriesPlotter( - const uno::Reference<XChartType>& xChartTypeModel + const rtl::Reference<ChartType>& xChartTypeModel , sal_Int32 nDimensionCount , bool bExcludingPositioning ) { diff --git a/chart2/source/view/diagram/VDiagram.cxx b/chart2/source/view/diagram/VDiagram.cxx index bf9b9b70d343..ff660a485d04 100644 --- a/chart2/source/view/diagram/VDiagram.cxx +++ b/chart2/source/view/diagram/VDiagram.cxx @@ -19,21 +19,21 @@ #include <ShapeFactory.hxx> #include <VDiagram.hxx> +#include <Diagram.hxx> #include <PropertyMapper.hxx> #include <ViewDefines.hxx> #include <Stripe.hxx> #include <ObjectIdentifier.hxx> #include <DiagramHelper.hxx> +#include <ChartType.hxx> #include <BaseGFXHelper.hxx> #include <ChartTypeHelper.hxx> #include <ThreeDHelper.hxx> #include <defines.hxx> #include <editeng/unoprnms.hxx> -#include <com/sun/star/lang/XTypeProvider.hpp> -#include <svx/unoshape.hxx> #include <svx/scene3d.hxx> #include <svx/e3dsceneupdater.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> namespace chart { @@ -41,13 +41,11 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; VDiagram::VDiagram( - const uno::Reference<XDiagram> & xDiagram, const drawing::Direction3D& rPreferredAspectRatio, + const rtl::Reference<Diagram> & xDiagram, const drawing::Direction3D& rPreferredAspectRatio, sal_Int32 nDimension ) - : m_pShapeFactory(nullptr) - , m_nDimensionCount(nDimension) + : m_nDimensionCount(nDimension) , m_xDiagram(xDiagram) , m_aPreferredAspectRatio(rPreferredAspectRatio) - , m_xAspectRatio3D() , m_fXAnglePi(0) , m_fYAnglePi(0) , m_fZAnglePi(0) @@ -56,13 +54,12 @@ VDiagram::VDiagram( if( m_nDimensionCount != 3) return; - uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY ); - ThreeDHelper::getRotationAngleFromDiagram( xSourceProp, m_fXAnglePi, m_fYAnglePi, m_fZAnglePi ); + xDiagram->getRotationAngle( m_fXAnglePi, m_fYAnglePi, m_fZAnglePi ); if( ChartTypeHelper::isSupportingRightAngledAxes( - DiagramHelper::getChartTypeByIndex( m_xDiagram, 0 ) ) ) + m_xDiagram->getChartTypeByIndex( 0 ) ) ) { - if(xSourceProp.is()) - xSourceProp->getPropertyValue("RightAngledAxes") >>= m_bRightAngledAxes; + if(xDiagram.is()) + xDiagram->getPropertyValue("RightAngledAxes") >>= m_bRightAngledAxes; if( m_bRightAngledAxes ) { ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi ); @@ -75,14 +72,9 @@ VDiagram::~VDiagram() { } -void VDiagram::init( - const uno::Reference< drawing::XShapes >& xTarget, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +void VDiagram::init( const rtl::Reference<SvxShapeGroupAnyD>& xTarget ) { - OSL_PRECOND(xFactory.is(), "no proper initialization parameters"); - m_xTarget = xTarget; - m_xShapeFactory = xFactory; - m_pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xFactory); } void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize ) @@ -138,81 +130,60 @@ void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize ) void VDiagram::createShapes_2d() { - OSL_PRECOND(m_pShapeFactory && m_xTarget.is() && m_xShapeFactory.is(), "is not proper initialized"); - if (!m_pShapeFactory || !m_xTarget.is() || !m_xShapeFactory.is()) + OSL_PRECOND(m_xTarget.is(), "is not proper initialized"); + if (!m_xTarget.is()) return; //create group shape - uno::Reference< drawing::XShapes > xOuterGroup_Shapes = m_pShapeFactory->createGroup2D(m_xTarget); - m_xOuterGroupShape.set( xOuterGroup_Shapes, uno::UNO_QUERY ); + rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = ShapeFactory::createGroup2D(m_xTarget); + m_xOuterGroupShape = xOuterGroup_Shapes; - uno::Reference< drawing::XShapes > xGroupForWall( m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,"PlotAreaExcludingAxes") ); + rtl::Reference<SvxShapeGroupAnyD> xGroupForWall( ShapeFactory::createGroup2D(xOuterGroup_Shapes,"PlotAreaExcludingAxes") ); //create independent group shape as container for datapoints and such things - { - uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID"); - m_xCoordinateRegionShape.set( xShapes, uno::UNO_QUERY ); - } + m_xCoordinateRegionShape = ShapeFactory::createGroup2D(xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID"); - bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram ); + bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall(); //add back wall { - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); - m_xWall2D = pShapeFactory->createRectangle( - xGroupForWall ); + m_xWall2D = ShapeFactory::createRectangle( xGroupForWall ); - uno::Reference< beans::XPropertySet > xProp( m_xWall2D, uno::UNO_QUERY ); - if( xProp.is()) + try { - try + OSL_ENSURE( m_xDiagram.is(), "Invalid Diagram model" ); + if( m_xDiagram.is() ) { - OSL_ENSURE( m_xDiagram.is(), "Invalid Diagram model" ); - if( m_xDiagram.is() ) - { - uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall()); - if( xWallProp.is()) - PropertyMapper::setMappedProperties( xProp, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() ); - } - if( !bAddFloorAndWall ) - { - //we always need this object as dummy object for correct scene dimensions - //but it should not be visible in this case: - ShapeFactory::makeShapeInvisible( m_xWall2D ); - } - else - { - //CID for selection handling - OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) );//@todo read CID from model - xProp->setPropertyValue( UNO_NAME_MISC_OBJ_NAME, uno::Any( aWallCID ) ); - } + uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall()); + if( xWallProp.is()) + PropertyMapper::setMappedProperties( *m_xWall2D, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() ); + } + if( !bAddFloorAndWall ) + { + //we always need this object as dummy object for correct scene dimensions + //but it should not be visible in this case: + ShapeFactory::makeShapeInvisible( m_xWall2D ); } - catch( const uno::Exception& ) + else { - TOOLS_WARN_EXCEPTION("chart2", "" ); + //CID for selection handling + OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model + m_xWall2D->SvxShape::setPropertyValue( UNO_NAME_MISC_OBJ_NAME, uno::Any( aWallCID ) ); } } - + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } } //position and size for diagram adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes ); } -static E3dScene* lcl_getE3dScene( const uno::Reference< drawing::XShape >& xShape ) +static E3dScene* lcl_getE3dScene( const rtl::Reference<SvxShapeGroupAnyD>& xShape ) { - E3dScene* pRet=nullptr; - uno::Reference< lang::XTypeProvider > xTypeProvider( xShape, uno::UNO_QUERY ); - if(xTypeProvider.is()) - { - SvxShape* pSvxShape = comphelper::getUnoTunnelImplementation<SvxShape>(xShape); - if(pSvxShape) - { - SdrObject* pObj = pSvxShape->GetSdrObject(); - pRet = dynamic_cast< E3dScene* >(pObj); - } - } - return pRet; + return DynCastE3dScene(xShape->GetSdrObject()); } static void lcl_setLightSources( @@ -456,21 +427,22 @@ void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize ) void VDiagram::createShapes_3d() { - OSL_PRECOND(m_pShapeFactory && m_xTarget.is() && m_xShapeFactory.is(), "is not proper initialized"); - if (!m_pShapeFactory || !m_xTarget.is() || !m_xShapeFactory.is()) + OSL_PRECOND(m_xTarget.is(), "is not proper initialized"); + if (!m_xTarget.is()) return; //create shape - m_xOuterGroupShape.set( m_pShapeFactory->createGroup3D( m_xTarget, "PlotAreaExcludingAxes" ), uno::UNO_QUERY); + rtl::Reference<Svx3DSceneObject> xShapes = ShapeFactory::createGroup3D( m_xTarget, "PlotAreaExcludingAxes" ); + m_xOuterGroupShape = xShapes; - uno::Reference< drawing::XShapes > xOuterGroup_Shapes( m_xOuterGroupShape, uno::UNO_QUERY ); + rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = m_xOuterGroupShape; //create additional group to manipulate the aspect ratio of the whole diagram: - xOuterGroup_Shapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes ); + xOuterGroup_Shapes = ShapeFactory::createGroup3D( xOuterGroup_Shapes ); - m_xAspectRatio3D.set( xOuterGroup_Shapes, uno::UNO_QUERY ); + m_xAspectRatio3D = xOuterGroup_Shapes; - bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram ); + bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall(); const bool bDoubleSided = false; @@ -480,13 +452,13 @@ void VDiagram::createShapes_3d() if( m_xDiagram.is() ) xWallProp.set( m_xDiagram->getWall() ); - OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) );//@todo read CID from model + OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model if( !bAddFloorAndWall ) aWallCID.clear(); - uno::Reference< drawing::XShapes > xWallGroup_Shapes( m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, aWallCID ) ); + rtl::Reference<Svx3DSceneObject> xWallGroup_Shapes = ShapeFactory::createGroup3D( xOuterGroup_Shapes, aWallCID ); - CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); - CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); + CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( m_xDiagram ) ); + CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( m_xDiagram ) ); //add left wall { @@ -506,8 +478,8 @@ void VDiagram::createShapes_3d() } aStripe.InvertNormal(true); - uno::Reference< drawing::XShape > xShape = - m_pShapeFactory->createStripe( xWallGroup_Shapes, aStripe + rtl::Reference<Svx3DPolygonObject> xShape = + ShapeFactory::createStripe( xWallGroup_Shapes, aStripe , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture ); if( !bAddFloorAndWall ) { @@ -534,8 +506,8 @@ void VDiagram::createShapes_3d() } aStripe.InvertNormal(true); - uno::Reference< drawing::XShape > xShape = - m_pShapeFactory->createStripe(xWallGroup_Shapes, aStripe + rtl::Reference<Svx3DPolygonObject> xShape = + ShapeFactory::createStripe(xWallGroup_Shapes, aStripe , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture ); if( !bAddFloorAndWall ) { @@ -548,28 +520,25 @@ void VDiagram::createShapes_3d() try { - uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY_THROW ); - uno::Reference< beans::XPropertySet > xDestProp( m_xOuterGroupShape, uno::UNO_QUERY_THROW ); - //perspective { //ignore distance and focal length from file format and model completely //use vrp only to indicate the distance of the camera and thus influence the perspective - xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_DISTANCE, uno::Any( - static_cast<sal_Int32>(ThreeDHelper::getCameraDistance( xSourceProp )))); - xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE, - xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE)); + m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_DISTANCE, uno::Any( + static_cast<sal_Int32>(m_xDiagram->getCameraDistance()))); + m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE, + m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE)); } //light { - xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE, - xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE)); - xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR, - xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR)); - xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING, - xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING)); - lcl_setLightSources( xSourceProp, xDestProp ); + m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE, + m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE)); + m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR, + m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR)); + m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING, + m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING)); + lcl_setLightSources( m_xDiagram, m_xOuterGroupShape ); } //rotation @@ -589,7 +558,7 @@ void VDiagram::createShapes_3d() //#i98497# 3D charts are rendered with wrong size E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape)); - xDestProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX, + m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX, uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTransformation ) ) ); } } @@ -609,11 +578,11 @@ void VDiagram::createShapes_3d() , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) ); aStripe.InvertNormal(true); - uno::Reference< drawing::XShape > xShape = - m_pShapeFactory->createStripe(xOuterGroup_Shapes, aStripe + rtl::Reference<Svx3DPolygonObject> xShape = + ShapeFactory::createStripe(xOuterGroup_Shapes, aStripe , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided ); - CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); + CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( m_xDiagram ) ); if( !bAddFloorAndWall || (eBottomPos!=CuboidPlanePosition_Bottom) ) { //we always need this object as dummy object for correct scene dimensions @@ -622,38 +591,33 @@ void VDiagram::createShapes_3d() } else { - OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, OUString() ) );//@todo read CID from model + OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, u"" ) );//@todo read CID from model ShapeFactory::setShapeName( xShape, aFloorCID ); } } //create an additional scene for the smaller inner coordinate region: { - uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID" ); - m_xCoordinateRegionShape.set( xShapes, uno::UNO_QUERY ); + rtl::Reference<Svx3DSceneObject> xShapes2 = ShapeFactory::createGroup3D( xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID" ); + m_xCoordinateRegionShape = xShapes2; - uno::Reference< beans::XPropertySet > xShapeProp( m_xCoordinateRegionShape, uno::UNO_QUERY ); - OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet"); - if( xShapeProp.is()) + try { - try - { - double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME; - double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME; - double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME; + double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME; + double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME; + double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME; - ::basegfx::B3DHomMatrix aM; - aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale); - aM.scale( fXScale, fYScale, fZScale ); - E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape)); + ::basegfx::B3DHomMatrix aM; + aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale); + aM.scale( fXScale, fYScale, fZScale ); + E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape)); - xShapeProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX - , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + xShapes2->SvxShape::setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX + , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } } @@ -667,7 +631,7 @@ basegfx::B2IRectangle VDiagram::getCurrentRectangle() const return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes); } -void VDiagram::reduceToMimimumSize() +void VDiagram::reduceToMinimumSize() { if( !m_xOuterGroupShape.is() ) return; @@ -675,8 +639,8 @@ void VDiagram::reduceToMimimumSize() awt::Size aMaxSize( m_aAvailableSizeIncludingAxes ); awt::Point aMaxPos( m_aAvailablePosIncludingAxes ); - sal_Int32 nNewWidth = aMaxSize.Width/3; - sal_Int32 nNewHeight = aMaxSize.Height/3; + sal_Int32 nNewWidth = std::round(aMaxSize.Width/2.2); + sal_Int32 nNewHeight = std::round(aMaxSize.Height/2.2); awt::Size aNewSize( nNewWidth, nNewHeight ); awt::Point aNewPos( aMaxPos ); aNewPos.X += nNewWidth; diff --git a/chart2/source/view/inc/Clipping.hxx b/chart2/source/view/inc/Clipping.hxx index 4f9a33adb55d..e816e7aa79b1 100644 --- a/chart2/source/view/inc/Clipping.hxx +++ b/chart2/source/view/inc/Clipping.hxx @@ -17,12 +17,12 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_CLIPPING_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_CLIPPING_HXX +#pragma once #include <basegfx/range/b2drectangle.hxx> namespace com::sun::star::drawing { struct PolyPolygonShape3D; } +namespace com::sun::star::drawing { struct Position3D; } namespace chart { @@ -49,9 +49,13 @@ public: , const ::basegfx::B2DRectangle& rRectangle , css::drawing::PolyPolygonShape3D& aResult , bool bSplitPiecesToDifferentPolygons = true ); + static void clipPolygonAtRectangle( + const std::vector<std::vector<css::drawing::Position3D>>& rPolygon + , const ::basegfx::B2DRectangle& rRectangle + , std::vector<std::vector<css::drawing::Position3D>>& aResult + , bool bSplitPiecesToDifferentPolygons = true ); }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/ConfigAccess.hxx b/chart2/source/view/inc/ConfigAccess.hxx deleted file mode 100644 index 556b371f1d81..000000000000 --- a/chart2/source/view/inc/ConfigAccess.hxx +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * 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 . - */ - -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_CONFIGACCESS_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_CONFIGACCESS_HXX - -namespace chart -{ -namespace ConfigAccess -{ -/** @descr Retrieve the setting for showing errors in charts from the registry - settings of the Calc application. - - If this setting is not found, it is set to false (the default setting). - - @return boolean UseErrorRectangle. - */ -bool getUseErrorRectangle(); -} - -} //namespace chart -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/DataTableView.hxx b/chart2/source/view/inc/DataTableView.hxx new file mode 100644 index 000000000000..0bccaaddde31 --- /dev/null +++ b/chart2/source/view/inc/DataTableView.hxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ +#pragma once + +#include <svx/unoshape.hxx> +#include <svx/unodraw/SvxTableShape.hxx> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/table/XTable.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <DataTable.hxx> +#include "VLineProperties.hxx" + +namespace chart +{ +class VSeriesPlotter; +class ChartModel; +class LegendEntryProvider; + +/** + * DataTableView is responsible to create the table object, set the cell + * properties accordingly to the model and fill it with the chart series + * data. + */ +class DataTableView final +{ +private: + rtl::Reference<::chart::ChartModel> m_xChartModel; + // the target shape + rtl::Reference<SvxShapeGroupAnyD> m_xTarget; + // the data table shape + rtl::Reference<SvxTableShape> m_xTableShape; + // the data table model + rtl::Reference<DataTable> m_xDataTableModel; + css::uno::Reference<css::uno::XComponentContext> m_xComponentContext; + css::uno::Reference<css::table::XTable> m_xTable; + VLineProperties m_aLineProperties; + std::vector<VSeriesPlotter*> m_pSeriesPlotterList; + + // data series names + std::vector<OUString> m_aDataSeriesNames; + // X axis names + std::vector<OUString> m_aXValues; + // list of data series values + std::vector<std::vector<OUString>> m_pDataSeriesValues; + + // if the header vales should be aligned with the x-axis vales + bool m_bAlignAxisValuesWithColumns; + + /** Set the char and paragraph properties for the input (value) cell */ + void + setCellCharAndParagraphProperties(css::uno::Reference<css::beans::XPropertySet>& xPropertySet); + + /** Set the common cell properties (for all cells in the data table, + * including headers) + */ + void setCellProperties(css::uno::Reference<css::beans::XPropertySet>& xPropertySet, bool bLeft, + bool bTop, bool bRight, bool bBottom); + +public: + DataTableView(rtl::Reference<::chart::ChartModel> const& xChartDoc, + rtl::Reference<DataTable> const& rDataTableModel, + css::uno::Reference<css::uno::XComponentContext> const& rComponentContext, + bool bAlignAxisValuesWithColumns); + + /** Initializes and prepares the target and data table shape */ + void initializeShapes(const rtl::Reference<SvxShapeGroupAnyD>& xTarget); + + /** Prepares the values of the chart, which will be shown it the data table */ + void initializeValues(std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList); + + /** Creates the data table and fills the values */ + void createShapes(basegfx::B2DVector const& rStart, basegfx::B2DVector const& rEnd, + sal_Int32 nAxisStepWidth); + + /** Repositions the data table shape */ + void changePosition(sal_Int32 x, sal_Int32 y); +}; + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/DateHelper.hxx b/chart2/source/view/inc/DateHelper.hxx index bfd549b22142..8c37851b7de3 100644 --- a/chart2/source/view/inc/DateHelper.hxx +++ b/chart2/source/view/inc/DateHelper.hxx @@ -16,10 +16,10 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_DATEHELPER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_DATEHELPER_HXX +#pragma once #include <tools/date.hxx> +#include <tools/long.hxx> namespace chart { @@ -35,10 +35,9 @@ public: static bool IsLessThanOneMonthAway( const Date& rD1, const Date& rD2 ); static bool IsLessThanOneYearAway( const Date& rD1, const Date& rD2 ); - static double RasterizeDateValue( double fValue, const Date& rNullDate, long TimeResolution ); + static double RasterizeDateValue( double fValue, const Date& rNullDate, tools::Long TimeResolution ); }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/LabelAlignment.hxx b/chart2/source/view/inc/LabelAlignment.hxx index 7d2eff4a699d..425f5c6c3eaa 100644 --- a/chart2/source/view/inc/LabelAlignment.hxx +++ b/chart2/source/view/inc/LabelAlignment.hxx @@ -17,12 +17,12 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_LABELALIGNMENT_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_LABELALIGNMENT_HXX +#pragma once -namespace chart { - -enum LabelAlignment { +namespace chart +{ +enum LabelAlignment +{ LABEL_ALIGN_CENTER, LABEL_ALIGN_LEFT, LABEL_ALIGN_TOP, @@ -33,9 +33,6 @@ enum LabelAlignment { LABEL_ALIGN_RIGHT_TOP, LABEL_ALIGN_RIGHT_BOTTOM }; - } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/LabelPositionHelper.hxx b/chart2/source/view/inc/LabelPositionHelper.hxx index 92b12d8d35f0..4f2f3ba2797a 100644 --- a/chart2/source/view/inc/LabelPositionHelper.hxx +++ b/chart2/source/view/inc/LabelPositionHelper.hxx @@ -17,12 +17,13 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_LABELPOSITIONHELPER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_LABELPOSITIONHELPER_HXX +#pragma once #include "LabelAlignment.hxx" #include "PropertyMapper.hxx" #include <com/sun/star/awt/Point.hpp> +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> namespace com::sun::star::drawing { struct Position3D; } namespace com::sun::star::drawing { class XShapes; } @@ -32,16 +33,13 @@ namespace com::sun::star::drawing { class XShape; } namespace chart { -class ShapeFactory; - class LabelPositionHelper { public: LabelPositionHelper() = delete; LabelPositionHelper( sal_Int32 nDimensionCount - , const css::uno::Reference< css::drawing::XShapes >& xLogicTarget - , ShapeFactory* pShapeFactory ); + , rtl::Reference<SvxShapeGroupAnyD> xLogicTarget ); virtual ~LabelPositionHelper(); css::awt::Point transformSceneToScreenPosition( @@ -52,7 +50,7 @@ public: , const css::uno::Reference< css::beans::XPropertySet >& xAxisModelProps , const css::awt::Size& rNewReferenceSize ); - static void correctPositionForRotation( const css::uno::Reference< css::drawing::XShape >& xShape2DText + static void correctPositionForRotation( const rtl::Reference<SvxShapeText>& xShape2DText , LabelAlignment eLabelAlignment, const double fRotationAngle, bool bRotateAroundCenter ); protected: @@ -60,11 +58,9 @@ protected: private: //these members are only necessary for transformation from 3D to 2D - css::uno::Reference< css::drawing::XShapes > m_xLogicTarget; - ShapeFactory* m_pShapeFactory; + rtl::Reference<SvxShapeGroupAnyD> m_xLogicTarget; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/LegendEntryProvider.hxx b/chart2/source/view/inc/LegendEntryProvider.hxx index 8c7ae00fafab..ce7722b0edfd 100644 --- a/chart2/source/view/inc/LegendEntryProvider.hxx +++ b/chart2/source/view/inc/LegendEntryProvider.hxx @@ -16,18 +16,19 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_LEGENDENTRYPROVIDER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_LEGENDENTRYPROVIDER_HXX +#pragma once #include <com/sun/star/chart2/LegendPosition.hpp> +#include <com/sun/star/chart2/XFormattedString2.hpp> #include <com/sun/star/awt/Size.hpp> #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> #include <vector> namespace chart { class ChartModel; } namespace com::sun::star::beans { class XPropertySet; } -namespace com::sun::star::chart2 { class XFormattedString2; } namespace com::sun::star::drawing { class XShape; } namespace com::sun::star::drawing { class XShapes; } namespace com::sun::star::lang { class XMultiServiceFactory; } @@ -35,6 +36,7 @@ namespace com::sun::star::uno { class XComponentContext; } namespace chart { +class FormattedString; enum class LegendSymbolStyle { @@ -57,12 +59,20 @@ struct ViewLegendEntry /** The legend symbol that represents a data series or other information contained in the legend */ - css::uno::Reference< css::drawing::XShape > aSymbol; + rtl::Reference< SvxShapeGroup > xSymbol; /** The descriptive text for a legend entry. */ - css::uno::Sequence< - css::uno::Reference< css::chart2::XFormattedString2 > > aLabel; + rtl::Reference< ::chart::FormattedString > xLabel; +}; + + +struct ViewLegendSymbol +{ + /** The legend symbol that represents a data series or other + information contained in the legend + */ + rtl::Reference<SvxShapeGroup> xSymbol; }; class LegendEntryProvider @@ -74,8 +84,7 @@ public: const css::awt::Size& rEntryKeyAspectRatio, css::chart2::LegendPosition eLegendPosition, const css::uno::Reference< css::beans::XPropertySet >& xTextProperties, - const css::uno::Reference< css::drawing::XShapes >& xTarget, - const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory, + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const css::uno::Reference< css::uno::XComponentContext >& xContext, ChartModel& rModel ) = 0; @@ -86,7 +95,4 @@ protected: } // namespace chart -// INCLUDED_CHART2_SOURCE_VIEW_INC_LEGENDENTRYPROVIDER_HXX -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/Linear3DTransformation.hxx b/chart2/source/view/inc/Linear3DTransformation.hxx index 3572caab7a7c..456f6e4c4b26 100644 --- a/chart2/source/view/inc/Linear3DTransformation.hxx +++ b/chart2/source/view/inc/Linear3DTransformation.hxx @@ -16,32 +16,25 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_LINEAR3DTRANSFORMATION_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_LINEAR3DTRANSFORMATION_HXX +#pragma once -#include <cppuhelper/implbase.hxx> -#include <com/sun/star/chart2/XTransformation.hpp> +#include "PlottingPositionHelper.hxx" #include <com/sun/star/drawing/HomogenMatrix.hpp> namespace chart { -class Linear3DTransformation : public ::cppu::WeakImplHelper< - css::chart2::XTransformation - > +class Linear3DTransformation final : public XTransformation2 { public: Linear3DTransformation( const css::drawing::HomogenMatrix& rHomMatrix, bool bSwapXAndY ); virtual ~Linear3DTransformation() override; - // ____ XTransformation ____ - /// @see css::chart2::XTransformation - virtual css::uno::Sequence< double > SAL_CALL transform( - const css::uno::Sequence< double >& rSourceValues ) override; - /// @see css::chart2::XTransformation - virtual sal_Int32 SAL_CALL getSourceDimension() override; - /// @see css::chart2::XTransformation - virtual sal_Int32 SAL_CALL getTargetDimension() override; + // ____ XTransformation2 ____ + virtual css::drawing::Position3D transform( + const css::drawing::Position3D& rSourceValues ) const override; + virtual css::drawing::Position3D transform( + const css::uno::Sequence< double >& rSourceValues ) const override; private: css::drawing::HomogenMatrix m_Matrix; @@ -50,7 +43,4 @@ private: } // namespace chart -// INCLUDED_CHART2_SOURCE_VIEW_INC_LINEAR3DTRANSFORMATION_HXX -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx b/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx index b256f1b919fd..cbb5e55ba74a 100644 --- a/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx +++ b/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx @@ -17,11 +17,11 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_MINIMUMANDMAXIMUMSUPPLIER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_MINIMUMANDMAXIMUMSUPPLIER_HXX +#pragma once #include <sal/types.h> #include <tools/date.hxx> +#include <tools/long.hxx> #include <set> namespace chart @@ -48,14 +48,14 @@ public: virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) = 0; //return a constant out of css::chart::TimeUnit that allows to display the smallest distance between occurring dates - virtual long calculateTimeResolutionOnXAxis() = 0; - virtual void setTimeResolutionOnXAxis( long nTimeResolution, const Date& rNullDate ) = 0; + virtual tools::Long calculateTimeResolutionOnXAxis() = 0; + virtual void setTimeResolutionOnXAxis( tools::Long nTimeResolution, const Date& rNullDate ) = 0; protected: ~MinimumAndMaximumSupplier() {} }; -class MergedMinimumAndMaximumSupplier : public MinimumAndMaximumSupplier +class MergedMinimumAndMaximumSupplier final : public MinimumAndMaximumSupplier { public: MergedMinimumAndMaximumSupplier(); @@ -79,8 +79,8 @@ public: virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex ) override; virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override; - virtual long calculateTimeResolutionOnXAxis() override; - virtual void setTimeResolutionOnXAxis( long nTimeResolution, const Date& rNullDate ) override; + virtual tools::Long calculateTimeResolutionOnXAxis() override; + virtual void setTimeResolutionOnXAxis( tools::Long nTimeResolution, const Date& rNullDate ) override; private: typedef std::set< MinimumAndMaximumSupplier* > MinimumAndMaximumSupplierSet; @@ -88,6 +88,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/PlotterBase.hxx b/chart2/source/view/inc/PlotterBase.hxx index 7fe205578b21..73695507fd48 100644 --- a/chart2/source/view/inc/PlotterBase.hxx +++ b/chart2/source/view/inc/PlotterBase.hxx @@ -16,11 +16,10 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTERBASE_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTERBASE_HXX +#pragma once -#include <com/sun/star/uno/Reference.h> #include <rtl/ustring.hxx> +#include <svx/unoshape.hxx> #include <vector> namespace com::sun::star::drawing { struct HomogenMatrix; } @@ -48,13 +47,12 @@ public: /// @throws css::uno::RuntimeException virtual void initPlotter( - const css::uno::Reference< css::drawing::XShapes >& xLogicTarget - , const css::uno::Reference< css::drawing::XShapes >& xFinalTarget - , const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory + const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget + , const rtl::Reference<SvxShapeGroupAnyD>& xFinalTarget , const OUString& rCID ); - virtual void setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ); + virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ); virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix ); @@ -63,16 +61,13 @@ public: static bool isValidPosition( const css::drawing::Position3D& rPos ); protected: //methods - css::uno::Reference< css::drawing::XShapes > - createGroupShape( const css::uno::Reference< - css::drawing::XShapes >& xTarget + rtl::Reference< SvxShapeGroupAnyD > + createGroupShape( const rtl::Reference< SvxShapeGroupAnyD >& xTarget , const OUString& rName=OUString() ); protected: //member - css::uno::Reference< css::drawing::XShapes > m_xLogicTarget; - css::uno::Reference< css::drawing::XShapes > m_xFinalTarget; - css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; - ShapeFactory* m_pShapeFactory; + rtl::Reference< SvxShapeGroupAnyD > m_xLogicTarget; + rtl::Reference< SvxShapeGroupAnyD > m_xFinalTarget; OUString m_aCID; const sal_Int32 m_nDimension; @@ -80,6 +75,5 @@ protected: //member PlottingPositionHelper* m_pPosHelper; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/PlottingPositionHelper.hxx b/chart2/source/view/inc/PlottingPositionHelper.hxx index 198941330b12..916668dd6c14 100644 --- a/chart2/source/view/inc/PlottingPositionHelper.hxx +++ b/chart2/source/view/inc/PlottingPositionHelper.hxx @@ -16,20 +16,24 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTINGPOSITIONHELPER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTINGPOSITIONHELPER_HXX +#pragma once + +#include <sal/config.h> + +#include <memory> #include <chartview/ExplicitScaleValues.hxx> #include <basegfx/range/b2drectangle.hxx> -#include <rtl/math.hxx> +#include <tools/long.hxx> #include <com/sun/star/drawing/Direction3D.hpp> #include <com/sun/star/drawing/Position3D.hpp> #include <basegfx/matrix/b3dhommatrix.hxx> #include <com/sun/star/awt/Point.hpp> #include <com/sun/star/uno/Sequence.hxx> +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> -namespace com::sun::star::chart2 { class XTransformation; } namespace com::sun::star::drawing { class XShapes; } namespace com::sun::star::drawing { struct HomogenMatrix; } namespace com::sun::star::drawing { struct PolyPolygonShape3D; } @@ -39,6 +43,45 @@ namespace chart class ShapeFactory; +/** allows the transformation of numeric values from one + coordinate-system into another. Values may be transformed using + any mapping. + This is a non-UNO variant of the css::chart2::XTransformation interface, + but using more efficient calling and returning types. + */ +class XTransformation2 +{ +public: + virtual ~XTransformation2(); + /** transforms the given input data tuple, given in the source + coordinate system, according to the internal transformation + rules, into a tuple of transformed coordinates in the + destination coordinate system. + + <p>Note that both coordinate systems may have different + dimensions, e.g., if a transformation does simply a projection + into a lower-dimensional space.</p> + + @param aValues a source tuple of data that is to be + transformed. The length of this sequence must be + equivalent to the dimension of the source coordinate + system. + + @return the transformed data tuple. The length of this + sequence is equal to the dimension of the output + coordinate system. + + @throws ::com::sun::star::lang::IllegalArgumentException + if the dimension of the input vector is not equal to the + dimension given in getSourceDimension(). + */ + virtual css::drawing::Position3D transform( + const css::drawing::Position3D& rSourceValues ) const = 0; + virtual css::drawing::Position3D transform( + const css::uno::Sequence< double >& rSourceValues ) const = 0; +}; + + class PlottingPositionHelper { public: @@ -51,7 +94,7 @@ public: virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix); - virtual void setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ); + virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ); const std::vector< ExplicitScaleData >& getScales() const { return m_aScales;} //better performance for big data @@ -69,7 +112,7 @@ public: inline void doLogicScaling( css::drawing::Position3D& rPos ) const; - virtual css::uno::Reference< css::chart2::XTransformation > + virtual ::chart::XTransformation2* getTransformationScaledLogicToScene() const; virtual css::drawing::Position3D @@ -79,11 +122,12 @@ public: transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const; void transformScaledLogicToScene( css::drawing::PolyPolygonShape3D& rPoly ) const; + void transformScaledLogicToScene( std::vector<std::vector<css::drawing::Position3D>>& rPoly ) const; static css::awt::Point transformSceneToScreenPosition( const css::drawing::Position3D& rScenePosition3D - , const css::uno::Reference< css::drawing::XShapes >& xSceneTarget - , ShapeFactory* pShapeFactory, sal_Int32 nDimensionCount ); + , const rtl::Reference<SvxShapeGroupAnyD>& xSceneTarget + , sal_Int32 nDimensionCount ); inline double getLogicMinX() const; inline double getLogicMinY() const; @@ -107,7 +151,7 @@ public: inline bool maySkipPointsInRegressionCalculation() const; - void setTimeResolution( long nTimeResolution, const Date& rNullDate ); + void setTimeResolution( tools::Long nTimeResolution, const Date& rNullDate ); virtual void setScaledCategoryWidth( double fScaledCategoryWidth ); void AllowShiftXAxisPos( bool bAllowShift ); void AllowShiftZAxisPos( bool bAllowShift ); @@ -117,7 +161,7 @@ protected: //member ::basegfx::B3DHomMatrix m_aMatrixScreenToScene; //this is calculated based on m_aScales and m_aMatrixScreenToScene - mutable css::uno::Reference< css::chart2::XTransformation > m_xTransformationLogicToScene; + mutable std::unique_ptr< ::chart::XTransformation2 > m_xTransformationLogicToScene; bool m_bSwapXAndY;//e.g. true for bar chart and false for column chart @@ -128,7 +172,7 @@ protected: //member bool m_bMaySkipPointsInRegressionCalculation; bool m_bDateAxis; - long m_nTimeResolution; + tools::Long m_nTimeResolution; Date m_aNullDate; double m_fScaledCategoryWidth; @@ -146,11 +190,11 @@ public: virtual std::unique_ptr<PlottingPositionHelper> clone() const override; virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix) override; - virtual void setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) override; + virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) override; const ::basegfx::B3DHomMatrix& getUnitCartesianToScene() const { return m_aUnitCartesianToScene;} - virtual css::uno::Reference< css::chart2::XTransformation > + virtual ::chart::XTransformation2* getTransformationScaledLogicToScene() const override; //the resulting values provided by the following 3 methods should be used @@ -278,9 +322,9 @@ bool PlottingPositionHelper::isStrongLowerRequested( sal_Int32 nDimensionIndex ) if( m_aScales.empty() ) return false; if( 0==nDimensionIndex ) - return m_bAllowShiftXAxisPos && m_aScales[nDimensionIndex].ShiftedCategoryPosition; + return m_bAllowShiftXAxisPos && m_aScales[nDimensionIndex].m_bShiftedCategoryPosition; else if( 2==nDimensionIndex ) - return m_bAllowShiftZAxisPos && m_aScales[nDimensionIndex].ShiftedCategoryPosition; + return m_bAllowShiftZAxisPos && m_aScales[nDimensionIndex].m_bShiftedCategoryPosition; return false; } @@ -298,7 +342,7 @@ void PlottingPositionHelper::doLogicScaling( double* pX, double* pY, double* pZ { if( m_aScales[0].Scaling.is()) *pX = m_aScales[0].Scaling->doScaling(*pX); - if( m_bAllowShiftXAxisPos && m_aScales[0].ShiftedCategoryPosition ) + if( m_bAllowShiftXAxisPos && m_aScales[0].m_bShiftedCategoryPosition ) (*pX) += m_fScaledCategoryWidth/2.0; } if(pY && m_aScales[1].Scaling.is()) @@ -307,7 +351,7 @@ void PlottingPositionHelper::doLogicScaling( double* pX, double* pY, double* pZ { if( m_aScales[2].Scaling.is()) *pZ = m_aScales[2].Scaling->doScaling(*pZ); - if( m_bAllowShiftZAxisPos && m_aScales[2].ShiftedCategoryPosition) + if( m_bAllowShiftZAxisPos && m_aScales[2].m_bShiftedCategoryPosition) (*pZ) += 0.5; } } @@ -356,11 +400,7 @@ inline bool PlottingPositionHelper::clipYRange( double& rMin, double& rMax ) con { //returns true if something remains if( rMin > rMax ) - { - double fHelp = rMin; - rMin = rMax; - rMax = fHelp; - } + std::swap( rMin, rMax ); if( rMin > getLogicMaxY() ) return false; if( rMax < getLogicMinY() ) @@ -419,6 +459,5 @@ inline bool PlottingPositionHelper::maySkipPointsInRegressionCalculation() const } } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/PolarLabelPositionHelper.hxx b/chart2/source/view/inc/PolarLabelPositionHelper.hxx index 2c6ed3a93795..84f4ff1dc83c 100644 --- a/chart2/source/view/inc/PolarLabelPositionHelper.hxx +++ b/chart2/source/view/inc/PolarLabelPositionHelper.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_POLARLABELPOSITIONHELPER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_POLARLABELPOSITIONHELPER_HXX +#pragma once #include "LabelPositionHelper.hxx" #include <com/sun/star/awt/Point.hpp> @@ -28,14 +27,13 @@ namespace chart class PolarPlottingPositionHelper; -class PolarLabelPositionHelper : public LabelPositionHelper +class PolarLabelPositionHelper final : public LabelPositionHelper { public: PolarLabelPositionHelper( PolarPlottingPositionHelper* pPosHelper , sal_Int32 nDimensionCount - , const css::uno::Reference< css::drawing::XShapes >& xLogicTarget - , ShapeFactory* pShapeFactory ); + , const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget ); virtual ~PolarLabelPositionHelper() override; css::awt::Point getLabelScreenPositionAndAlignmentForLogicValues( @@ -68,6 +66,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/PropertyMapper.hxx b/chart2/source/view/inc/PropertyMapper.hxx index 5da914074e1c..c4d9a1fa2577 100644 --- a/chart2/source/view/inc/PropertyMapper.hxx +++ b/chart2/source/view/inc/PropertyMapper.hxx @@ -16,23 +16,23 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_PROPERTYMAPPER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_PROPERTYMAPPER_HXX +#pragma once #include <sal/config.h> -#include <map> +#include <unordered_map> #include <com/sun/star/uno/Sequence.h> #include <com/sun/star/uno/Reference.h> namespace com::sun::star::beans { class XPropertySet; } +class SvxShape; namespace chart { -typedef std::map< OUString, OUString > tPropertyNameMap; -typedef std::map< OUString, css::uno::Any > tPropertyNameValueMap; +typedef std::unordered_map<OUString, OUString> tPropertyNameMap; +typedef std::unordered_map<OUString, css::uno::Any> tPropertyNameValueMap; typedef css::uno::Sequence< OUString > tNameSequence; typedef css::uno::Sequence< css::uno::Any > tAnySequence; @@ -48,8 +48,12 @@ public: static void setMappedProperties( const css::uno::Reference< css::beans::XPropertySet >& xTarget , const css::uno::Reference< css::beans::XPropertySet >& xSource - , const tPropertyNameMap& rMap - , tPropertyNameValueMap const * pOverwriteMap=nullptr ); + , const tPropertyNameMap& rMap ); + + static void setMappedProperties( + SvxShape& xTarget + , const css::uno::Reference< css::beans::XPropertySet >& xSource + , const tPropertyNameMap& rMap ); /** * Fetch property values from the source object and map it to the @@ -67,13 +71,6 @@ public: , const css::uno::Reference< css::beans::XPropertySet >& xSourceProp ); - static void getMultiPropertyLists( - tNameSequence& rNames - , tAnySequence& rValues - , const css::uno::Reference< css::beans::XPropertySet >& xProp - , const tPropertyNameMap& rMap - ); - static void getMultiPropertyListsFromValueMap( tNameSequence& rNames , tAnySequence& rValues @@ -83,7 +80,7 @@ public: static css::uno::Any* getValuePointer( tAnySequence& rPropValues , const tNameSequence& rPropNames - , const OUString& rPropName ); + , std::u16string_view rPropName ); static css::uno::Any* getValuePointerForLimitedSpace( tAnySequence& rPropValues @@ -93,7 +90,7 @@ public: static void setMultiProperties( const tNameSequence& rNames , const tAnySequence& rValues - , const css::uno::Reference< css::beans::XPropertySet >& xTarget ); + , SvxShape& xTarget ); static const tPropertyNameMap& getPropertyNameMapForCharacterProperties(); static const tPropertyNameMap& getPropertyNameMapForParagraphProperties(); @@ -124,6 +121,5 @@ public: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/ScaleAutomatism.hxx b/chart2/source/view/inc/ScaleAutomatism.hxx index df2e203bc0d6..1141c9e87cd4 100644 --- a/chart2/source/view/inc/ScaleAutomatism.hxx +++ b/chart2/source/view/inc/ScaleAutomatism.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_SCALEAUTOMATISM_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_SCALEAUTOMATISM_HXX +#pragma once #include <com/sun/star/chart2/ScaleData.hpp> @@ -141,6 +140,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/ShapeFactory.hxx b/chart2/source/view/inc/ShapeFactory.hxx index 7a698e4b9d87..b44612e74a4f 100644 --- a/chart2/source/view/inc/ShapeFactory.hxx +++ b/chart2/source/view/inc/ShapeFactory.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_SHAPEFACTORY_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_SHAPEFACTORY_HXX +#pragma once #include "PropertyMapper.hxx" #include <basegfx/range/b2irectangle.hxx> @@ -25,12 +24,15 @@ #include <com/sun/star/awt/Point.hpp> #include <com/sun/star/drawing/PointSequenceSequence.hpp> +#include <rtl/ref.hxx> #include <rtl/ustring.hxx> +#include <svx/unoshape.hxx> +#include <svx/unodraw/SvxTableShape.hxx> +#include <svx/unopage.hxx> namespace chart { struct VLineProperties; } namespace com::sun::star::beans { class XPropertySet; } namespace com::sun::star::chart2 { class XFormattedString; } -namespace com::sun::star::drawing { class XDrawPage; } namespace com::sun::star::drawing { class XShape; } namespace com::sun::star::drawing { class XShapes; } namespace com::sun::star::drawing { struct HomogenMatrix; } @@ -40,7 +42,6 @@ namespace com::sun::star::graphic { class XGraphic; } namespace com::sun::star::lang { class XMultiServiceFactory; } namespace com::sun::star::drawing { struct Direction3D; } - namespace chart { class Stripe; @@ -68,29 +69,28 @@ enum SymbolEnum { Symbol_Square=0 class ShapeFactory { - css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; - - ShapeFactory(css::uno::Reference< css::lang::XMultiServiceFactory> const & xFactory) - {m_xShapeFactory = xFactory;} - public: enum class StackPosition { Top, Bottom }; - static ShapeFactory* getOrCreateShapeFactory(const css::uno::Reference< css::lang::XMultiServiceFactory>& xFactory); - ShapeFactory() = delete; - css::uno::Reference< css::drawing::XShapes > + + static rtl::Reference< SvxShapeGroup > createGroup2D( - const css::uno::Reference< css::drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const OUString& aName = OUString() ); - css::uno::Reference< css::drawing::XShapes > + static rtl::Reference< SvxShapeGroup > + createGroup2D( + const rtl::Reference<SvxDrawPage>& xTarget + , const OUString& aName = OUString() ); + + static rtl::Reference<Svx3DSceneObject> createGroup3D( - const css::uno::Reference< css::drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const OUString& aName = OUString() ); - css::uno::Reference< css::drawing::XShape > - createCube( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<Svx3DExtrudeObject> + createCube( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPosition , const css::drawing::Direction3D& rSize , sal_Int32 nRotateZAngleHundredthDegree @@ -98,14 +98,14 @@ public: , const tPropertyNameMap& rPropertyNameMap , bool bRounded = false); - css::uno::Reference< css::drawing::XShape > - createCylinder( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<Svx3DLatheObject> + createCylinder( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPosition , const css::drawing::Direction3D& rSize , sal_Int32 nRotateZAngleHundredthDegree ); - css::uno::Reference< css::drawing::XShape > - createPyramid( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<Svx3DSceneObject> + createPyramid( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPosition , const css::drawing::Direction3D& rSize , double fTopHeight @@ -113,29 +113,29 @@ public: , const css::uno::Reference< css::beans::XPropertySet >& xSourceProp , const tPropertyNameMap& rPropertyNameMap); - css::uno::Reference< css::drawing::XShape > - createCone( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<Svx3DLatheObject> + createCone( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPosition , const css::drawing::Direction3D& rSize , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree ); - css::uno::Reference< css::drawing::XShape > - createPieSegment2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<SvxShapePolyPolygon> + createPieSegment2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius , const css::drawing::Direction3D& rOffset , const css::drawing::HomogenMatrix& rUnitCircleToScene ); - css::uno::Reference< css::drawing::XShape > - createPieSegment( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<Svx3DExtrudeObject> + createPieSegment( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius , const css::drawing::Direction3D& rOffset , const css::drawing::HomogenMatrix& rUnitCircleToScene , double fDepth ); - css::uno::Reference< css::drawing::XShape > - createStripe( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<Svx3DPolygonObject> + createStripe( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const Stripe& rStripe , const css::uno::Reference< css::beans::XPropertySet >& xSourceProp , const tPropertyNameMap& rPropertyNameMap @@ -143,143 +143,112 @@ public: , short nRotatedTexture = 0 //0 to 7 are the different possibilities , bool bFlatNormals=true ); - css::uno::Reference< css::drawing::XShape > - createArea3D( const css::uno::Reference< css::drawing::XShapes >& xTarget - , const css::drawing::PolyPolygonShape3D& rPolyPolygon + static rtl::Reference<Svx3DExtrudeObject> + createArea3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon , double fDepth); - css::uno::Reference< css::drawing::XShape > - createArea2D( const css::uno::Reference< css::drawing::XShapes >& xTarget - , const css::drawing::PolyPolygonShape3D& rPolyPolygon); + static rtl::Reference<SvxShapePolyPolygon> + createArea2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon); - css::uno::Reference< css::drawing::XShape > - createSymbol2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<SvxShapePolyPolygon> + createSymbol2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPos , const css::drawing::Direction3D& rSize , sal_Int32 nStandardSymbol , sal_Int32 nBorderColor , sal_Int32 nFillColor ); - css::uno::Reference< css::drawing::XShape > - createGraphic2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<SvxGraphicObject> + createGraphic2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPos , const css::drawing::Direction3D& rSize , const css::uno::Reference< css::graphic::XGraphic >& xGraphic ); - css::uno::Reference< css::drawing::XShape > - createLine2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<SvxShapePolyPolygon> + createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::PointSequenceSequence& rPoints , const VLineProperties* pLineProperties = nullptr ); + static rtl::Reference<SvxShapePolyPolygon> + createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const std::vector<std::vector<css::drawing::Position3D>>& rPoints + , const VLineProperties* pLineProperties = nullptr ); - css::uno::Reference< css::drawing::XShape > - createLine ( const css::uno::Reference< css::drawing::XShapes >& xTarget, + static rtl::Reference<SvxShapePolyPolygon> + createLine ( const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const css::awt::Size& rSize, const css::awt::Point& rPosition ); - css::uno::Reference< css::drawing::XShape > - createLine3D( const css::uno::Reference< css::drawing::XShapes >& xTarget - , const css::drawing::PolyPolygonShape3D& rPoints + static rtl::Reference<Svx3DPolygonObject> + createLine3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const std::vector<std::vector<css::drawing::Position3D>>& rPoints , const VLineProperties& rLineProperties ); - css::uno::Reference< css::drawing::XShape > - createCircle2D( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<SvxShapeCircle> + createCircle2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPos , const css::drawing::Direction3D& rSize ); - css::uno::Reference< css::drawing::XShape > - createCircle( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<SvxShapeCircle> + createCircle( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::awt::Size& rSize , const css::awt::Point& rPosition ); - css::uno::Reference< css::drawing::XShape > - createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D + static rtl::Reference<SvxShapeText> + createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget2D , const OUString& rText , const tNameSequence& rPropNames , const tAnySequence& rPropValues , const css::uno::Any& rATransformation ); - /** This method creates a text shape made up by a set of paragraphs. - * For each paragraph the related text style is passed to the method. - * - * @param xTarget - * where to append the new created text shape. - * - * @param rTextParagraphs - * the set of paragraphs which made up the text shape. - * - * @param rParaPropNames - * a collection of lists of text property names: - * there must be a list of text property names for each paragraph. - * - * @param rParaPropValues - * a collection of lists of text property values: - * there must be a list of text property values for each paragraph. - * - * @param rPropNames - * a list of text property names to be applied to the whole text shape. - * - * @param rPropValues - * a list of text property values to be applied to the whole text shape. - * - * @param rATransformation - * a transformation to be applied to the text shape as final step. - * - */ - css::uno::Reference< css::drawing::XShape > - createText( const css::uno::Reference< css::drawing::XShapes >& xTarget - , const css::uno::Sequence< OUString >& rTextParagraphs - , const css::uno::Sequence< tNameSequence >& rParaPropNames - , const css::uno::Sequence< tAnySequence >& rParaPropValues - , const tNameSequence& rPropNames - , const tAnySequence& rPropValues - , const css::uno::Any& rATransformation ); - - css::uno::Reference< css::drawing::XShape > - createText(const css::uno::Reference< css::drawing::XShapes >& xTarget - , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString + static rtl::Reference<SvxShapeText> + createText(const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString , const tNameSequence& rPropNames , const tAnySequence& rPropValues , const css::uno::Any& rATransformation); - css::uno::Reference< css::drawing::XShape > - createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D, + static rtl::Reference<SvxShapeText> + createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget2D, const css::awt::Size& rSize, const css::awt::Point& rPosition, css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString, const css::uno::Reference< css::beans::XPropertySet > & xTextProperties, double nRotation, const OUString& aName, sal_Int32 nTextMaxWidth ); - css::uno::Reference< css::drawing::XShape > + static rtl::Reference<SvxTableShape> createTable(rtl::Reference<SvxShapeGroupAnyD> const& xTarget, OUString const& rName = OUString()); + + static rtl::Reference<SvxShapeRect> createInvisibleRectangle( - const css::uno::Reference< css::drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::awt::Size& rSize ); - css::uno::Reference< css::drawing::XShape > + static rtl::Reference<SvxShapeRect> createRectangle( - const css::uno::Reference< css::drawing::XShapes >& xTarget, + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const css::awt::Size& rSize, const css::awt::Point& rPosition, const tNameSequence& rPropNames, const tAnySequence& rPropValues, StackPosition ePos = StackPosition::Top ); - css::uno::Reference< css::drawing::XShape > + static rtl::Reference<SvxShapeRect> createRectangle( - const css::uno::Reference< css::drawing::XShapes >& xTarget ); + const rtl::Reference<SvxShapeGroupAnyD>& xTarget ); - css::uno::Reference< css::drawing::XShapes > - getOrCreateChartRootShape( const css::uno::Reference< - css::drawing::XDrawPage>& xPage ); + static rtl::Reference<SvxShapeGroupAnyD> + getOrCreateChartRootShape( const rtl::Reference<SvxDrawPage>& xPage ); - static void setPageSize(const css::uno::Reference<css::drawing::XShapes>& xChartShapes, + static void setPageSize(const rtl::Reference<SvxShapeGroupAnyD>& xChartShapes, const css::awt::Size& rSize); - static css::uno::Reference< css::drawing::XShapes > - getChartRootShape( const css::uno::Reference< css::drawing::XDrawPage>& xPage ); + static rtl::Reference<SvxShapeGroupAnyD> + getChartRootShape( const rtl::Reference<SvxDrawPage>& xPage ); - static void makeShapeInvisible( const css::uno::Reference< css::drawing::XShape >& xShape ); + static void makeShapeInvisible( const rtl::Reference< SvxShape >& rShape ); - static void setShapeName( const css::uno::Reference< css::drawing::XShape >& xShape + static void setShapeName( const rtl::Reference< SvxShape >& xShape , const OUString& rName ); static OUString getShapeName( const css::uno::Reference< css::drawing::XShape >& xShape ); @@ -288,9 +257,11 @@ public: static OUString getStackedString( const OUString& rString, bool bStacked ); - static bool hasPolygonAnyLines( css::drawing::PolyPolygonShape3D& rPoly ); - static bool isPolygonEmptyOrSinglePoint( css::drawing::PolyPolygonShape3D& rPoly ); + static bool hasPolygonAnyLines( const std::vector<std::vector<css::drawing::Position3D>>& rPoly ); + static bool isPolygonEmptyOrSinglePoint( const css::drawing::PolyPolygonShape3D& rPoly ); + static bool isPolygonEmptyOrSinglePoint( const std::vector<std::vector<css::drawing::Position3D>>& rPoly ); static void closePolygon( css::drawing::PolyPolygonShape3D& rPoly ); + static void closePolygon( std::vector<std::vector<css::drawing::Position3D>>& rPoly ); static css::awt::Size calculateNewSizeRespectingAspectRatio( const css::awt::Size& rTargetSize @@ -301,25 +272,24 @@ public: , const css::awt::Size& rTargetAreaSize , const css::awt::Size& rObjectSize ); - static ::basegfx::B2IRectangle getRectangleOfShape( - const css::uno::Reference< css::drawing::XShape >& xShape ); + static ::basegfx::B2IRectangle getRectangleOfShape( SvxShape& rShape ); static css::awt::Size getSizeAfterRotation( - const css::uno::Reference< css::drawing::XShape >& xShape, double fRotationAngleDegree ); + SvxShape& rShape, double fRotationAngleDegree ); - static void removeSubShapes( const css::uno::Reference< css::drawing::XShapes >& xShapes ); + static void removeSubShapes( const rtl::Reference<SvxShapeGroupAnyD>& xShapes ); static sal_Int32 getSymbolCount() { return Symbol_COUNT; } private: - css::uno::Reference< css::drawing::XShape > - impl_createCube( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<Svx3DExtrudeObject> + impl_createCube( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPosition , const css::drawing::Direction3D& rSize, sal_Int32 nRotateZAngleHundredthDegree , bool bRounded ); - css::uno::Reference< css::drawing::XShape > - impl_createConeOrCylinder( const css::uno::Reference< css::drawing::XShapes >& xTarget + static rtl::Reference<Svx3DLatheObject> + impl_createConeOrCylinder( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D& rPosition , const css::drawing::Direction3D& rSize , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree @@ -327,6 +297,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/Stripe.hxx b/chart2/source/view/inc/Stripe.hxx index 4c25af12a2ac..0da5e0b5dcc5 100644 --- a/chart2/source/view/inc/Stripe.hxx +++ b/chart2/source/view/inc/Stripe.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_STRIPE_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_STRIPE_HXX +#pragma once #include <com/sun/star/drawing/Position3D.hpp> #include <com/sun/star/drawing/Direction3D.hpp> @@ -68,6 +67,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/VCoordinateSystem.hxx b/chart2/source/view/inc/VCoordinateSystem.hxx index 48f3f4aed0a6..61dda842d02b 100644 --- a/chart2/source/view/inc/VCoordinateSystem.hxx +++ b/chart2/source/view/inc/VCoordinateSystem.hxx @@ -16,21 +16,21 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VCOORDINATESYSTEM_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_VCOORDINATESYSTEM_HXX +#pragma once #include "MinimumAndMaximumSupplier.hxx" #include <ThreeDHelper.hxx> +#include "VSeriesPlotter.hxx" #include <chartview/ExplicitScaleValues.hxx> #include <com/sun/star/drawing/HomogenMatrix.hpp> #include <com/sun/star/uno/Sequence.h> +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> #include <map> #include <memory> #include <vector> -namespace chart { class ExplicitCategoriesProvider; } -namespace chart { class ScaleAutomatism; } namespace com::sun::star::awt { struct Rectangle; } namespace com::sun::star::awt { struct Size; } namespace com::sun::star::beans { class XPropertySet; } @@ -39,11 +39,16 @@ namespace com::sun::star::chart2 { class XChartDocument; } namespace com::sun::star::chart2 { class XCoordinateSystem; } namespace com::sun::star::drawing { class XShapes; } namespace com::sun::star::lang { class XMultiServiceFactory; } - +namespace com::sun::star::uno { class XComponentContext; } namespace chart { - +class ExplicitCategoriesProvider; +class ScaleAutomatism; +class ChartModel; +class Axis; +class BaseCoordinateSystem; +class GridProperties; class VAxisBase; class VCoordinateSystem @@ -51,15 +56,14 @@ class VCoordinateSystem public: virtual ~VCoordinateSystem(); - static std::unique_ptr<VCoordinateSystem> createCoordinateSystem( const css::uno::Reference< - css::chart2::XCoordinateSystem >& xCooSysModel ); + static std::unique_ptr<VCoordinateSystem> createCoordinateSystem( const rtl::Reference< + ::chart::BaseCoordinateSystem >& xCooSysModel ); /// @throws css::uno::RuntimeException void initPlottingTargets( - const css::uno::Reference< css::drawing::XShapes >& xLogicTarget - , const css::uno::Reference< css::drawing::XShapes >& xFinalTarget - , const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory - , css::uno::Reference< css::drawing::XShapes >& xLogicTargetForSeriesBehindAxis ); + const rtl::Reference< SvxShapeGroupAnyD >& xLogicTarget + , const rtl::Reference< SvxShapeGroupAnyD >& xFinalTarget + , rtl::Reference<SvxShapeGroupAnyD>& xLogicTargetForSeriesBehindAxis ); void setParticle( const OUString& rCooSysParticle ); @@ -107,17 +111,19 @@ public: void set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos ); - const css::uno::Reference< css::chart2::XCoordinateSystem >& + const rtl::Reference< ::chart::BaseCoordinateSystem >& getModel() const { return m_xCooSysModel;} /** - * Create "view" axis obejcts 'VAxis' from the coordinate system model. + * Create "view" axis objects 'VAxis' from the coordinate system model. */ virtual void createVAxisList( - const css::uno::Reference< css::chart2::XChartDocument> & xChartDoc - , const css::awt::Size& rFontReferenceSize - , const css::awt::Rectangle& rMaximumSpaceForLabels - , bool bLimitSpaceForLabels ); + const rtl::Reference<::chart::ChartModel> & xChartDoc, + const css::awt::Size& rFontReferenceSize, + const css::awt::Rectangle& rMaximumSpaceForLabels, + bool bLimitSpaceForLabels, + std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList, + css::uno::Reference<css::uno::XComponentContext> const& rComponentContext); virtual void initVAxisInList(); virtual void updateScalesAndIncrementsOnAxes(); @@ -137,39 +143,35 @@ public: void setSeriesNamesForAxis( const css::uno::Sequence< OUString >& rSeriesNames ); protected: //methods - VCoordinateSystem( const css::uno::Reference< - css::chart2::XCoordinateSystem >& xCooSys ); + VCoordinateSystem( rtl::Reference< ::chart::BaseCoordinateSystem > xCooSys ); - css::uno::Reference< css::chart2::XAxis > + rtl::Reference< ::chart::Axis > getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const; - static css::uno::Sequence< css::uno::Reference< css::beans::XPropertySet > > - getGridListFromAxis( const css::uno::Reference< css::chart2::XAxis >& xAxis ); + static std::vector< rtl::Reference< ::chart::GridProperties > > + getGridListFromAxis( const rtl::Reference< ::chart::Axis >& xAxis ); VAxisBase* getVAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ); OUString createCIDForAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ); OUString createCIDForGrid( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ); - sal_Int32 getNumberFormatKeyForAxis( const css::uno::Reference< - css::chart2::XAxis >& xAxis - , const css::uno::Reference< - css::chart2::XChartDocument>& xChartDoc); + sal_Int32 getNumberFormatKeyForAxis( const rtl::Reference< ::chart::Axis >& xAxis + , const rtl::Reference<::chart::ChartModel>& xChartDoc); private: //methods static void impl_adjustDimension( sal_Int32& rDimensionIndex ); void impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const; protected: //member - css::uno::Reference< css::chart2::XCoordinateSystem > m_xCooSysModel; + rtl::Reference< ::chart::BaseCoordinateSystem > m_xCooSysModel; OUString m_aCooSysParticle; typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex; //first index is the dimension, second index is the axis index that indicates whether this is a main or secondary axis - css::uno::Reference< css::drawing::XShapes > m_xLogicTargetForGrids; - css::uno::Reference< css::drawing::XShapes > m_xLogicTargetForAxes; - css::uno::Reference< css::drawing::XShapes > m_xFinalTarget; - css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; + rtl::Reference<SvxShapeGroupAnyD> m_xLogicTargetForGrids; + rtl::Reference<SvxShapeGroupAnyD> m_xLogicTargetForAxes; + rtl::Reference<SvxShapeGroupAnyD> m_xFinalTarget; css::drawing::HomogenMatrix m_aMatrixSceneToScreen; CuboidPlanePosition m_eLeftWallPos; @@ -203,6 +205,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/VDataSeries.hxx b/chart2/source/view/inc/VDataSeries.hxx index 287415c27280..dd5054d26bd8 100644 --- a/chart2/source/view/inc/VDataSeries.hxx +++ b/chart2/source/view/inc/VDataSeries.hxx @@ -16,15 +16,19 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VDATASERIES_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_VDATASERIES_HXX +#pragma once #include "PropertyMapper.hxx" +#include <com/sun/star/chart2/DataPointLabel.hpp> #include <com/sun/star/chart2/StackingDirection.hpp> -#include <com/sun/star/drawing/PolyPolygonShape3D.hpp> +#include <com/sun/star/chart2/Symbol.hpp> +#include <com/sun/star/drawing/Position3D.hpp> #include <com/sun/star/awt/Size.hpp> #include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/chart2/PieChartSubType.hpp> +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> #include <memory> #include <map> @@ -33,12 +37,12 @@ namespace com::sun::star::beans { class XPropertySet; } namespace com::sun::star::chart2 { class XChartType; } namespace com::sun::star::chart2 { class XDataSeries; } namespace com::sun::star::chart2::data { class XDataSequence; } -namespace com::sun::star::chart2 { struct DataPointLabel; } -namespace com::sun::star::chart2 { struct Symbol; } namespace com::sun::star::drawing { class XShapes; } namespace chart { +class ChartType; +class DataSeries; class VDataSequence { @@ -50,22 +54,21 @@ public: sal_Int32 detectNumberFormatKey( sal_Int32 index ) const; sal_Int32 getLength() const; - css::uno::Reference<css::chart2::data::XDataSequence> Model; - - mutable css::uno::Sequence<double> Doubles; + css::uno::Reference<css::chart2::data::XDataSequence> m_xModel; + mutable css::uno::Sequence<double> m_aValues; }; class VDataSeries final { public: - VDataSeries( const css::uno::Reference<css::chart2::XDataSeries>& xDataSeries ); + VDataSeries( const rtl::Reference<::chart::DataSeries>& xDataSeries ); ~VDataSeries(); VDataSeries(const VDataSeries&) = delete; const VDataSeries& operator=(const VDataSeries&) = delete; - const css::uno::Reference<css::chart2::XDataSeries>& getModel() const; + const rtl::Reference<::chart::DataSeries>& getModel() const; void setCategoryXAxis(); void setXValues( const css::uno::Reference<css::chart2::data::XDataSequence>& xValues ); @@ -105,15 +108,16 @@ public: sal_Int32 detectNumberFormatKey( sal_Int32 nPointIndex ) const; sal_Int32 getLabelPlacement( - sal_Int32 nPointIndex, const css::uno::Reference<css::chart2::XChartType>& xChartType, + sal_Int32 nPointIndex, const rtl::Reference<::chart::ChartType>& xChartType, bool bSwapXAndY ) const; css::awt::Point getLabelPosition( css::awt::Point aTextShapePos, sal_Int32 nPointIndex ) const; bool isLabelCustomPos( sal_Int32 nPointIndex ) const; + css::awt::Size getLabelCustomSize(sal_Int32 nPointIndex) const; css::uno::Reference<css::beans::XPropertySet> getPropertiesOfPoint( sal_Int32 index ) const; - css::uno::Reference<css::beans::XPropertySet> getPropertiesOfSeries() const; + const css::uno::Reference<css::beans::XPropertySet> & getPropertiesOfSeries() const; css::chart2::Symbol* getSymbolProperties( sal_Int32 index ) const; @@ -138,10 +142,10 @@ public: void setStartingAngle( sal_Int32 nStartingAngle ); sal_Int32 getStartingAngle() const; - void setRoleOfSequenceForDataLabelNumberFormatDetection( const OUString& rRole ); + void setRoleOfSequenceForDataLabelNumberFormatDetection( std::u16string_view rRole ); //this is only temporarily here for area chart: - css::drawing::PolyPolygonShape3D m_aPolyPolygonShape3D; + std::vector<std::vector<css::drawing::Position3D>> m_aPolyPolygonShape3D; sal_Int32 m_nPolygonIndex; double m_fLogicMinX; double m_fLogicMaxX; @@ -181,18 +185,19 @@ private: //methods VDataSeries(); public: //member - css::uno::Reference<css::drawing::XShapes> m_xGroupShape; - css::uno::Reference<css::drawing::XShapes> m_xLabelsGroupShape; - css::uno::Reference<css::drawing::XShapes> m_xErrorXBarsGroupShape; - css::uno::Reference<css::drawing::XShapes> m_xErrorYBarsGroupShape; + rtl::Reference<SvxShapeGroupAnyD> m_xGroupShape; + rtl::Reference<SvxShapeGroup> m_xLabelsGroupShape; + rtl::Reference<SvxShapeGroupAnyD> m_xErrorXBarsGroupShape; + rtl::Reference<SvxShapeGroupAnyD> m_xErrorYBarsGroupShape; //the following group shapes will be created as children of m_xGroupShape on demand //they can be used to assure that some parts of a series shape are always in front of others (e.g. symbols in front of lines) - css::uno::Reference<css::drawing::XShapes> m_xFrontSubGroupShape; - css::uno::Reference<css::drawing::XShapes> m_xBackSubGroupShape; + rtl::Reference<SvxShapeGroupAnyD> m_xFrontSubGroupShape; + rtl::Reference<SvxShapeGroupAnyD> m_xBackSubGroupShape; private: //member - css::uno::Reference<css::chart2::XDataSeries> m_xDataSeries; + rtl::Reference<::chart::DataSeries> m_xDataSeries; + css::uno::Reference<css::beans::XPropertySet> m_xDataSeriesProps; // cached //all points given by the model data (here are not only the visible points meant) sal_Int32 m_nPointCount; @@ -235,20 +240,19 @@ private: //member sal_Int32 m_nGlobalSeriesIndex; //some cached values for data labels as they are very expensive - mutable std::unique_ptr<css::chart2::DataPointLabel> - m_apLabel_Series; - mutable std::unique_ptr<tNameSequence> m_apLabelPropNames_Series; - mutable std::unique_ptr<tAnySequence> m_apLabelPropValues_Series; - mutable std::unique_ptr<css::chart2::Symbol> m_apSymbolProperties_Series; - - mutable std::unique_ptr<css::chart2::DataPointLabel> - m_apLabel_AttributedPoint; - mutable std::unique_ptr<tNameSequence> m_apLabelPropNames_AttributedPoint; - mutable std::unique_ptr<tAnySequence> m_apLabelPropValues_AttributedPoint; - mutable std::unique_ptr<css::chart2::Symbol> m_apSymbolProperties_AttributedPoint; - mutable std::unique_ptr<css::chart2::Symbol> - m_apSymbolProperties_InvisibleSymbolForSelection; - mutable sal_Int32 m_nCurrentAttributedPoint; + mutable std::optional<css::chart2::DataPointLabel> + m_oLabel_Series; + mutable std::optional<tNameSequence> m_oLabelPropNames_Series; + mutable std::optional<tAnySequence> m_oLabelPropValues_Series; + mutable std::optional<css::chart2::Symbol> m_oSymbolProperties_Series; + + mutable std::optional<css::chart2::DataPointLabel> + m_oLabel_AttributedPoint; + mutable std::optional<tNameSequence> m_oLabelPropNames_AttributedPoint; + mutable std::optional<tAnySequence> m_oLabelPropValues_AttributedPoint; + mutable std::optional<css::chart2::Symbol> m_oSymbolProperties_AttributedPoint; + mutable std::optional<css::chart2::Symbol> m_oSymbolProperties_InvisibleSymbolForSelection; + mutable sal_Int32 m_nCurrentAttributedPoint; css::awt::Size m_aReferenceSize; sal_Int32 m_nMissingValueTreatment; @@ -260,6 +264,5 @@ private: //member }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/VDiagram.hxx b/chart2/source/view/inc/VDiagram.hxx index 15ea26434531..ab391f7bc0d3 100644 --- a/chart2/source/view/inc/VDiagram.hxx +++ b/chart2/source/view/inc/VDiagram.hxx @@ -16,14 +16,14 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VDIAGRAM_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_VDIAGRAM_HXX +#pragma once -#include <com/sun/star/drawing/XShapes.hpp> #include <basegfx/range/b2irectangle.hxx> #include <com/sun/star/drawing/Direction3D.hpp> #include <com/sun/star/awt/Size.hpp> #include <com/sun/star/awt/Point.hpp> +#include <svx/unoshape.hxx> +#include <rtl/ref.hxx> namespace com::sun::star::beans { class XPropertySet; } namespace com::sun::star::chart2 { class XDiagram; } @@ -33,7 +33,7 @@ namespace com::sun::star::drawing { class XShape; } namespace chart { - +class Diagram; class ShapeFactory; /** The VDiagram is responsible to generate the visible parts of the Diagram @@ -45,27 +45,26 @@ diagram. class VDiagram final { public: //methods - VDiagram( const css::uno::Reference<css::chart2::XDiagram>& xDiagram, + VDiagram( const rtl::Reference<::chart::Diagram>& xDiagram, const css::drawing::Direction3D& rPreferredAspectRatio, sal_Int32 nDimension ); ~VDiagram(); void init( - const css::uno::Reference<css::drawing::XShapes>& xTarget, - const css::uno::Reference<css::lang::XMultiServiceFactory>& xFactory ); + const rtl::Reference<SvxShapeGroupAnyD>& xTarget ); void createShapes( const css::awt::Point& rPos , const css::awt::Size& rSize ); - css::uno::Reference< css::drawing::XShapes > - getCoordinateRegion() const { return css::uno::Reference<css::drawing::XShapes>( m_xCoordinateRegionShape, css::uno::UNO_QUERY );} + const rtl::Reference<SvxShapeGroupAnyD> & + getCoordinateRegion() const { return m_xCoordinateRegionShape; } /** * Get current bounding rectangle for the diagram without axes. */ basegfx::B2IRectangle getCurrentRectangle() const; - void reduceToMimimumSize(); + void reduceToMinimumSize(); ::basegfx::B2IRectangle adjustPosAndSize( const css::awt::Point& rPos , const css::awt::Size& rAvailableSize ); @@ -86,18 +85,16 @@ private: //methods private: //members VDiagram(const VDiagram& rD) = delete; - css::uno::Reference< css::drawing::XShapes > m_xTarget; - css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; - ShapeFactory* m_pShapeFactory; + rtl::Reference<SvxShapeGroupAnyD> m_xTarget; // this is the surrounding shape which contains floor, wall and coordinate - css::uno::Reference< css::drawing::XShape > m_xOuterGroupShape; + rtl::Reference<SvxShapeGroupAnyD> m_xOuterGroupShape; // this is an additional inner shape that represents the coordinate region - that is - where to place data points - css::uno::Reference< css::drawing::XShape > m_xCoordinateRegionShape; - css::uno::Reference< css::drawing::XShape > m_xWall2D; + rtl::Reference<SvxShapeGroupAnyD> m_xCoordinateRegionShape; + rtl::Reference<SvxShapeRect> m_xWall2D; - sal_Int32 m_nDimensionCount; - css::uno::Reference< css::chart2::XDiagram > m_xDiagram; + sal_Int32 m_nDimensionCount; + rtl::Reference< ::chart::Diagram > m_xDiagram; css::drawing::Direction3D m_aPreferredAspectRatio; css::uno::Reference< css::beans::XPropertySet > m_xAspectRatio3D; @@ -116,6 +113,5 @@ private: //members }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/VLegendSymbolFactory.hxx b/chart2/source/view/inc/VLegendSymbolFactory.hxx index 96eb58782ec9..f637a5894912 100644 --- a/chart2/source/view/inc/VLegendSymbolFactory.hxx +++ b/chart2/source/view/inc/VLegendSymbolFactory.hxx @@ -16,11 +16,12 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VLEGENDSYMBOLFACTORY_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_VLEGENDSYMBOLFACTORY_HXX +#pragma once #include "LegendEntryProvider.hxx" #include <com/sun/star/uno/Reference.h> +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> namespace com::sun::star::awt { struct Size; } namespace com::sun::star::beans { class XPropertySet; } @@ -29,10 +30,7 @@ namespace com::sun::star::drawing { class XShapes; } namespace com::sun::star::lang { class XMultiServiceFactory; } namespace com::sun::star::uno { class Any; } -namespace chart -{ - -namespace VLegendSymbolFactory +namespace chart::VLegendSymbolFactory { enum class PropertyType { @@ -41,20 +39,15 @@ namespace VLegendSymbolFactory Line, }; - css::uno::Reference< css::drawing::XShape > + rtl::Reference< SvxShapeGroup > createSymbol( const css::awt::Size& rEntryKeyAspectRatio, - const css::uno::Reference< css::drawing::XShapes >& rSymbolContainer, + const rtl::Reference<SvxShapeGroupAnyD>& rSymbolContainer, LegendSymbolStyle eStyle, - const css::uno::Reference< css::lang::XMultiServiceFactory > & xShapeFactory, const css::uno::Reference< css::beans::XPropertySet > & xLegendEntryProperties, PropertyType ePropertyType, const css::uno::Any& rExplicitSymbol /*should contain a css::chart2::Symbol without automatic symbol if the charttype does support symbols else empty*/); -} } // namespace chart -// INCLUDED_CHART2_SOURCE_VIEW_INC_VLEGENDSYMBOLFACTORY_HXX -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/VLineProperties.hxx b/chart2/source/view/inc/VLineProperties.hxx index a255499fd088..aa1c88ce74f2 100644 --- a/chart2/source/view/inc/VLineProperties.hxx +++ b/chart2/source/view/inc/VLineProperties.hxx @@ -17,32 +17,33 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VLINEPROPERTIES_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_VLINEPROPERTIES_HXX +#pragma once #include <com/sun/star/uno/Any.h> #include <com/sun/star/uno/Reference.h> -namespace com::sun::star::beans { class XPropertySet; } +namespace com::sun::star::beans +{ +class XPropertySet; +} namespace chart { - struct VLineProperties { css::uno::Any Color; //type sal_Int32 UNO_NAME_LINECOLOR css::uno::Any LineStyle; //type drawing::LineStyle for property UNO_NAME_LINESTYLE - css::uno::Any Transparence;//type sal_Int16 for property UNO_NAME_LINETRANSPARENCE - css::uno::Any Width;//type sal_Int32 for property UNO_NAME_LINEWIDTH - css::uno::Any DashName;//type OUString for property "LineDashName" + css::uno::Any Transparence; //type sal_Int16 for property UNO_NAME_LINETRANSPARENCE + css::uno::Any Width; //type sal_Int32 for property UNO_NAME_LINEWIDTH + css::uno::Any DashName; //type OUString for property "LineDashName" + css::uno::Any LineCap; //type drawing::LineCap for property UNO_NAME_LINECAP VLineProperties(); - void initFromPropertySet( const css::uno::Reference< css::beans::XPropertySet >& xProp ); + void initFromPropertySet(const css::uno::Reference<css::beans::XPropertySet>& xProp); bool isLineVisible() const; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/VPolarTransformation.hxx b/chart2/source/view/inc/VPolarTransformation.hxx index af9404ffc1d5..23f3c3b71875 100644 --- a/chart2/source/view/inc/VPolarTransformation.hxx +++ b/chart2/source/view/inc/VPolarTransformation.hxx @@ -16,32 +16,24 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VPOLARTRANSFORMATION_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_VPOLARTRANSFORMATION_HXX +#pragma once #include "PlottingPositionHelper.hxx" -#include <cppuhelper/implbase.hxx> -#include <com/sun/star/chart2/XTransformation.hpp> namespace chart { -class VPolarTransformation : public ::cppu::WeakImplHelper< - css::chart2::XTransformation - > +class VPolarTransformation final : public XTransformation2 { public: VPolarTransformation( const PolarPlottingPositionHelper& rPositionHelper ); virtual ~VPolarTransformation() override; - // ____ XTransformation ____ - /// @see css::chart2::XTransformation - virtual css::uno::Sequence< double > SAL_CALL transform( - const css::uno::Sequence< double >& rSourceValues ) override; - /// @see css::chart2::XTransformation - virtual sal_Int32 SAL_CALL getSourceDimension() override; - /// @see css::chart2::XTransformation - virtual sal_Int32 SAL_CALL getTargetDimension() override; + // ____ XTransformation2 ____ + virtual css::drawing::Position3D transform( + const css::uno::Sequence< double >& rSourceValues ) const override; + virtual css::drawing::Position3D transform( + const css::drawing::Position3D& rSourceValues ) const override; private: PolarPlottingPositionHelper m_aPositionHelper; @@ -50,7 +42,4 @@ private: } // namespace chart -// INCLUDED_CHART2_SOURCE_VIEW_INC_VPOLARTRANSFORMATION_HXX -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx b/chart2/source/view/inc/VSeriesPlotter.hxx index 17215faae4b5..45676830b538 100644 --- a/chart2/source/view/inc/VSeriesPlotter.hxx +++ b/chart2/source/view/inc/VSeriesPlotter.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VSERIESPLOTTER_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_VSERIESPLOTTER_HXX +#pragma once #include <memory> #include "PlotterBase.hxx" @@ -25,7 +24,10 @@ #include "LabelAlignment.hxx" #include "MinimumAndMaximumSupplier.hxx" #include "LegendEntryProvider.hxx" +#include <basegfx/range/b2irectangle.hxx> #include <com/sun/star/drawing/Direction3D.hpp> +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> namespace com::sun::star::awt { struct Point; } namespace com::sun::star::chart2 { class XChartType; } @@ -47,6 +49,7 @@ namespace com::sun::star { namespace chart { +class ChartType; class NumberFormatterWrapper; class AxesNumberFormats @@ -83,12 +86,12 @@ public: sal_Int32 getPointCount() const; sal_Int32 getAttachedAxisIndexForFirstSeries() const; - void getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const; - void getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const; + void getMinimumAndMaximumX( double& rfMinimum, double& rfMaximum ) const; + void getMinimumAndMaximumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const; void calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex , bool bSeparateStackingForDifferentSigns - , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ); + , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ) const; void calculateYMinAndMaxForCategoryRange( sal_Int32 nStartCategoryIndex, sal_Int32 nEndCategoryIndex , bool bSeparateStackingForDifferentSigns , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ); @@ -171,11 +174,11 @@ public: virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex ) override; virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override; - virtual long calculateTimeResolutionOnXAxis() override; - virtual void setTimeResolutionOnXAxis( long nTimeResolution, const Date& rNullDate ) override; + virtual tools::Long calculateTimeResolutionOnXAxis() override; + virtual void setTimeResolutionOnXAxis( tools::Long nTimeResolution, const Date& rNullDate ) override; - void getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const; - void getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const; + void getMinimumAndMaximumX( double& rfMinimum, double& rfMaximum ) const; + void getMinimumAndMaximumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const; // Methods for handling legends and legend entries. @@ -184,8 +187,7 @@ public: const css::awt::Size& rEntryKeyAspectRatio, css::chart2::LegendPosition eLegendPosition, const css::uno::Reference< css::beans::XPropertySet >& xTextProperties, - const css::uno::Reference< css::drawing::XShapes >& xTarget, - const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory, + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const css::uno::Reference< css::uno::XComponentContext >& xContext, ChartModel& rModel ) override; @@ -195,32 +197,41 @@ public: virtual css::uno::Any getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex/*-1 for series symbol*/ ); - css::uno::Reference< css::drawing::XShape > createLegendSymbolForSeries( + rtl::Reference<SvxShapeGroup> createLegendSymbolForSeries( const css::awt::Size& rEntryKeyAspectRatio , const VDataSeries& rSeries - , const css::uno::Reference< css::drawing::XShapes >& xTarget - , const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory ); + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ); - css::uno::Reference< css::drawing::XShape > createLegendSymbolForPoint( + rtl::Reference< SvxShapeGroup > createLegendSymbolForPoint( const css::awt::Size& rEntryKeyAspectRatio , const VDataSeries& rSeries , sal_Int32 nPointIndex - , const css::uno::Reference< css::drawing::XShapes >& xTarget - , const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory ); + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ); std::vector< ViewLegendEntry > createLegendEntriesForSeries( const css::awt::Size& rEntryKeyAspectRatio, const VDataSeries& rSeries, const css::uno::Reference< css::beans::XPropertySet >& xTextProperties, - const css::uno::Reference< css::drawing::XShapes >& xTarget, - const css::uno::Reference< css::lang::XMultiServiceFactory >& xShapeFactory, + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const css::uno::Reference< css::uno::XComponentContext >& xContext ); - std::vector< VDataSeries* > getAllSeries(); + std::vector<ViewLegendSymbol> createSymbols( + const css::awt::Size& rEntryKeyAspectRatio + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const css::uno::Reference<css::uno::XComponentContext>& xContext); + + std::vector<ViewLegendSymbol> createSymbolsForSeries( + const css::awt::Size& rEntryKeyAspectRatio + , const VDataSeries& rSeries + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const css::uno::Reference<css::uno::XComponentContext>& xContext); + + std::vector<VDataSeries*> getAllSeries(); + std::vector<VDataSeries const*> getAllSeries() const; // This method creates a series plotter of the requested type; e.g. : return new PieChart... - static VSeriesPlotter* createSeriesPlotter( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + static VSeriesPlotter* createSeriesPlotter( const rtl::Reference< ::chart::ChartType >& xChartTypeModel , sal_Int32 nDimensionCount , bool bExcludingPositioning /*for pie and donut charts labels and exploded segments are excluded from the given size*/); @@ -234,14 +245,20 @@ public: void setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider ); + ExplicitCategoriesProvider* getExplicitCategoriesProvider() { return m_pExplicitCategoriesProvider; } + //get series names for the z axis labels - css::uno::Sequence< OUString > getSeriesNames() const; + css::uno::Sequence<OUString> getSeriesNames() const; + + //get all series names + css::uno::Sequence<OUString> getAllSeriesNames() const; void setPageReferenceSize( const css::awt::Size & rPageRefSize ); //better performance for big data void setCoordinateSystemResolution( const css::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution ); bool PointsWereSkipped() const { return m_bPointsWereSkipped;} void setPieLabelsAllowToMove( bool bIsPieOrDonut ) { m_bPieLabelsAllowToMove = bIsPieOrDonut; }; + void setAvailableOuterRect( const basegfx::B2IRectangle& aAvailableOuterRect ) { m_aAvailableOuterRect = aAvailableOuterRect; }; //return the depth for a logic 1 double getTransformedDepth() const; @@ -253,37 +270,44 @@ public: bool WantToPlotInFrontOfAxisLine(); virtual bool shouldSnapRectToUsedArea(); + /// This method returns a text string representation of the passed numeric + /// value by exploiting a NumberFormatterWrapper object. + OUString getLabelTextForValue(VDataSeries const & rDataSeries, sal_Int32 nPointIndex, + double fValue, bool bAsPercentage); + + sal_Int32 getRenderOrder() const; + protected: - VSeriesPlotter( const css::uno::Reference< css::chart2::XChartType >& xChartTypeModel + VSeriesPlotter( rtl::Reference< ::chart::ChartType > xChartTypeModel , sal_Int32 nDimensionCount , bool bCategoryXAxis=true ); // Methods for group shapes. - css::uno::Reference< css::drawing::XShapes > + rtl::Reference<SvxShapeGroupAnyD> getSeriesGroupShape( VDataSeries* pDataSeries - , const css:: uno::Reference< css::drawing::XShapes >& xTarget ); + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ); //the following group shapes will be created as children of SeriesGroupShape on demand //they can be used to assure that some parts of a series shape are always in front of others (e.g. symbols in front of lines) //parameter xTarget will be used as parent for the series group shape - css::uno::Reference< css::drawing::XShapes > + rtl::Reference<SvxShapeGroupAnyD> getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries - , const css:: uno::Reference< css::drawing::XShapes >& xTarget ); - css::uno::Reference< css::drawing::XShapes > + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ); + rtl::Reference<SvxShapeGroupAnyD> getSeriesGroupShapeBackChild( VDataSeries* pDataSeries - , const css:: uno::Reference< css::drawing::XShapes >& xTarget ); + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ); /// This method creates a 2D group shape for containing all text shapes /// needed for this series; the group is added to the text target; - css::uno::Reference< css::drawing::XShapes > + static rtl::Reference<SvxShapeGroup> getLabelsGroupShape( VDataSeries& rDataSeries - , const css:: uno::Reference< css::drawing::XShapes >& xTarget ); + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ); - css::uno::Reference< css::drawing::XShapes > + rtl::Reference<SvxShapeGroupAnyD> getErrorBarsGroupShape( VDataSeries& rDataSeries - , const css:: uno::Reference< css::drawing::XShapes >& xTarget, bool bYError ); + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget, bool bYError ); /** This method creates a text shape for a label related to a data point * and append it to the root text shape group (xTarget). @@ -310,8 +334,8 @@ protected: * @return * a reference to the created text shape. */ - css::uno::Reference< css::drawing::XShape > - createDataLabel( const css::uno::Reference< css::drawing::XShapes >& xTarget + rtl::Reference<SvxShapeText> + createDataLabel( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , VDataSeries& rDataSeries , sal_Int32 nPointIndex , double fValue @@ -321,13 +345,6 @@ protected: , sal_Int32 nOffset=0 , sal_Int32 nTextWidth = 0 ); - /// This method returns a text string representation of the passed numeric - /// value by exploiting a NumberFormatterWrapper object. - OUString getLabelTextForValue( VDataSeries const & rDataSeries - , sal_Int32 nPointIndex - , double fValue - , bool bAsPercentage ); - /** creates two T-shaped error bars in both directions (up/down or left/right depending on the bVertical parameter) @@ -346,7 +363,7 @@ protected: for y-error bars this is true, for x-error-bars it is false. */ void createErrorBar( - const css::uno::Reference< css::drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const css::drawing::Position3D & rPos , const css::uno::Reference< css::beans::XPropertySet > & xErrorBarProperties , const VDataSeries& rVDataSeries @@ -359,43 +376,37 @@ protected: const css::drawing::Position3D& rUnscaledLogicPosition , VDataSeries& rVDataSeries , sal_Int32 nIndex - , const css::uno::Reference< css::drawing::XShapes >& rTarget + , const rtl::Reference<SvxShapeGroupAnyD>& rTarget , bool bUseXErrorData , bool bUseYErrorData ); - void addErrorBorder( + static void addErrorBorder( const css::drawing::Position3D& rPos0 , const css::drawing::Position3D& rPos1 - , const css::uno::Reference< css::drawing::XShapes >& rTarget + , const rtl::Reference<SvxShapeGroupAnyD>& rTarget , const css::uno::Reference< css::beans::XPropertySet >& rErrorBorderProp ); void createErrorBar_X( const css::drawing::Position3D& rUnscaledLogicPosition , VDataSeries& rVDataSeries, sal_Int32 nPointIndex - , const css::uno::Reference< css::drawing::XShapes >& xTarget ); + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ); void createErrorBar_Y( const css::drawing::Position3D& rUnscaledLogicPosition , VDataSeries& rVDataSeries, sal_Int32 nPointIndex - , const css::uno::Reference< css::drawing::XShapes >& xTarget + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget , double const * pfScaledLogicX ); void createRegressionCurvesShapes( VDataSeries const & rVDataSeries - , const css::uno::Reference< css::drawing::XShapes >& xTarget - , const css::uno::Reference< css::drawing::XShapes >& xEquationTarget + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const rtl::Reference<SvxShapeGroupAnyD>& xEquationTarget , bool bMaySkipPointsInRegressionCalculation ); void createRegressionCurveEquationShapes( const OUString & rEquationCID , const css::uno::Reference< css::beans::XPropertySet > & xEquationProperties - , const css::uno::Reference< css::drawing::XShapes >& xEquationTarget + , const rtl::Reference<SvxShapeGroupAnyD>& xEquationTarget , const css::uno::Reference< css::chart2::XRegressionCurveCalculator > & xRegressionCurveCalculator , css::awt::Point aDefaultPos ); - static void setMappedProperties( - const css::uno::Reference< css::drawing::XShape >& xTarget - , const css::uno::Reference< css::beans::XPropertySet >& xSource - , const tPropertyNameMap& rMap - , tPropertyNameValueMap const * pOverwriteMap=nullptr ); - virtual PlottingPositionHelper& getPlottingPositionHelper( sal_Int32 nAxisIndex ) const;//nAxisIndex indicates whether the position belongs to the main axis ( nAxisIndex==0 ) or secondary axis ( nAxisIndex==1 ) VDataSeries* getFirstSeries() const; @@ -405,13 +416,12 @@ protected: protected: PlottingPositionHelper* m_pMainPosHelper; - css::uno::Reference< css::chart2::XChartType > m_xChartTypeModel; - css::uno::Reference< css::beans::XPropertySet > m_xChartTypeModelProps; + rtl::Reference< ::chart::ChartType > m_xChartTypeModel; std::vector< std::vector< VDataSeriesGroup > > m_aZSlots; bool m_bCategoryXAxis;//true->xvalues are indices (this would not be necessary if series for category chart wouldn't have x-values) - long m_nTimeResolution; + tools::Long m_nTimeResolution; Date m_aNullDate; std::unique_ptr< NumberFormatterWrapper > m_apNumberFormatterWrapper; @@ -424,6 +434,8 @@ protected: css::uno::Sequence< sal_Int32 > m_aCoordinateSystemResolution; bool m_bPointsWereSkipped; bool m_bPieLabelsAllowToMove; + basegfx::B2IRectangle m_aAvailableOuterRect; + css::awt::Size m_aPageReferenceSize; private: typedef std::map< sal_Int32 , ExplicitScaleData > tSecondaryValueScales; @@ -431,10 +443,8 @@ private: typedef std::map< sal_Int32 , std::unique_ptr<PlottingPositionHelper> > tSecondaryPosHelperMap; mutable tSecondaryPosHelperMap m_aSecondaryPosHelperMap; - css::awt::Size m_aPageReferenceSize; }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/inc/ViewDefines.hxx b/chart2/source/view/inc/ViewDefines.hxx index d191efe484f9..b8b82be956c5 100644 --- a/chart2/source/view/inc/ViewDefines.hxx +++ b/chart2/source/view/inc/ViewDefines.hxx @@ -16,23 +16,20 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_VIEWDEFINES_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_INC_VIEWDEFINES_HXX +#pragma once #include <sal/types.h> namespace chart { - #define CHART_3DOBJECT_SEGMENTCOUNT (sal_Int32(32)) //There needs to be a little distance between grid lines and walls in 3D, otherwise the lines are partly hidden by the walls #define GRID_TO_WALL_DISTANCE (1.0) -const double ZDIRECTION = 1.0; -const sal_Int32 AXIS2D_TICKLENGTH = 150;//value like in old chart -const sal_Int32 AXIS2D_TICKLABELSPACING = 100;//value like in old chart +const double ZDIRECTION = 1.0; +const sal_Int32 AXIS2D_TICKLENGTH = 150; //value like in old chart +const sal_Int32 AXIS2D_TICKLABELSPACING = 100; //value like in old chart -}//end namespace chart -#endif +} //end namespace chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/AxisUsage.hxx b/chart2/source/view/main/AxisUsage.hxx new file mode 100644 index 000000000000..51a32a59b0e1 --- /dev/null +++ b/chart2/source/view/main/AxisUsage.hxx @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#pragma once + +#include <sal/types.h> +#include <memory> +#include <map> + +#include <VCoordinateSystem.hxx> +#include <AxisHelper.hxx> +#include <ScaleAutomatism.hxx> + +namespace chart +{ +//first index is the dimension, second index is the axis index that indicates whether this is a main or secondary axis +typedef std::pair<sal_Int32, sal_Int32> tFullAxisIndex; +typedef std::map<VCoordinateSystem*, tFullAxisIndex> tCoordinateSystemMap; + +/** This class handles a collection of coordinate systems and is used for + * executing some action on all coordinate systems such as + * "prepareAutomaticAxisScaling" and "setExplicitScaleAndIncrement". + * Moreover it contains the "aAutoScaling" object that is an instance of + * the "ScaleAutomatism" class. The initialization of "aAutoScaling" is + * performed in the "SeriesPlotterContainer::initAxisUsageList" method and is + * used in the "SeriesPlotterContainer::doAutoScaling" for calculating explicit + * scale and increment objects (see "SeriesPlotterContainer::doAutoScaling"). + */ +class AxisUsage +{ +public: + AxisUsage() + : aAutoScaling(AxisHelper::createDefaultScale(), Date(Date::SYSTEM)) + { + } + + void addCoordinateSystem(VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, + sal_Int32 nAxisIndex) + { + if (!pCooSys) + return; + + tFullAxisIndex aFullAxisIndex(nDimensionIndex, nAxisIndex); + tCoordinateSystemMap::const_iterator aFound(aCoordinateSystems.find(pCooSys)); + + //use one scale only once for each coordinate system + //main axis are preferred over secondary axis + //value scales are preferred + if (aFound != aCoordinateSystems.end()) + { + sal_Int32 nFoundAxisIndex = aFound->second.second; + if (nFoundAxisIndex < nAxisIndex) + return; + sal_Int32 nFoundDimension = aFound->second.first; + if (nFoundDimension == 1) + return; + if (nFoundDimension < nDimensionIndex) + return; + } + aCoordinateSystems[pCooSys] = std::move(aFullAxisIndex); + + //set maximum scale index + auto aIter = aMaxIndexPerDimension.find(nDimensionIndex); + if (aIter != aMaxIndexPerDimension.end()) + { + sal_Int32 nCurrentMaxIndex = aIter->second; + if (nCurrentMaxIndex < nAxisIndex) + aMaxIndexPerDimension[nDimensionIndex] = nAxisIndex; + } + else + aMaxIndexPerDimension[nDimensionIndex] = nAxisIndex; + } + + std::vector<VCoordinateSystem*> getCoordinateSystems(sal_Int32 nDimensionIndex, + sal_Int32 nAxisIndex) + { + std::vector<VCoordinateSystem*> aRet; + + for (auto const& coordinateSystem : aCoordinateSystems) + { + if (coordinateSystem.second.first != nDimensionIndex) + continue; + if (coordinateSystem.second.second != nAxisIndex) + continue; + aRet.push_back(coordinateSystem.first); + } + + return aRet; + } + + sal_Int32 getMaxAxisIndexForDimension(sal_Int32 nDimensionIndex) + { + sal_Int32 nRet = -1; + auto aIter = aMaxIndexPerDimension.find(nDimensionIndex); + if (aIter != aMaxIndexPerDimension.end()) + nRet = aIter->second; + return nRet; + } + + void prepareAutomaticAxisScaling(ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, + sal_Int32 nAxisIndex) + { + std::vector<VCoordinateSystem*> aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex); + for (VCoordinateSystem* pVCoordinateSystem : aVCooSysList) + pVCoordinateSystem->prepareAutomaticAxisScaling(rScaleAutomatism, nDimIndex, + nAxisIndex); + } + + void setExplicitScaleAndIncrement(sal_Int32 nDimIndex, sal_Int32 nAxisIndex, + const ExplicitScaleData& rScale, + const ExplicitIncrementData& rInc) + { + std::vector<VCoordinateSystem*> aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex); + for (VCoordinateSystem* pVCoordinateSystem : aVCooSysList) + pVCoordinateSystem->setExplicitScaleAndIncrement(nDimIndex, nAxisIndex, rScale, rInc); + } + + ScaleAutomatism aAutoScaling; + +private: + tCoordinateSystemMap aCoordinateSystems; + std::map<sal_Int32, sal_Int32> aMaxIndexPerDimension; +}; + +} //end chart2 namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/ChartItemPool.cxx b/chart2/source/view/main/ChartItemPool.cxx index 7e428942f0db..e28bb97f81db 100644 --- a/chart2/source/view/main/ChartItemPool.cxx +++ b/chart2/source/view/main/ChartItemPool.cxx @@ -19,182 +19,199 @@ #include "ChartItemPool.hxx" #include <chartview/ChartSfxItemIds.hxx> +#include <DataSeries.hxx> +#include <FormattedString.hxx> +#include <Legend.hxx> +#include <Axis.hxx> #include <svx/chrtitem.hxx> +#include <svx/sdangitm.hxx> +#include <svx/svdpool.hxx> +#include <svx/svx3ditems.hxx> #include <svl/intitem.hxx> +#include <editeng/editeng.hxx> #include <editeng/brushitem.hxx> +#include <editeng/eeitem.hxx> #include <editeng/sizeitem.hxx> #include <svl/stritem.hxx> #include <svl/ilstitem.hxx> +#include <comphelper/processfactory.hxx> #include <editeng/editids.hrc> #include <svx/svxids.hrc> #include <vector> #include <com/sun/star/chart2/LegendPosition.hpp> +#include <com/sun/star/chart2/MovingAverageType.hpp> +#include <com/sun/star/frame/XTerminateListener.hpp> +#include <com/sun/star/frame/Desktop.hpp> namespace chart { -ChartItemPool::ChartItemPool(): - SfxItemPool( "ChartItemPool" , SCHATTR_START, SCHATTR_END, nullptr, nullptr ), - pItemInfos(new SfxItemInfo[SCHATTR_END - SCHATTR_START + 1]) +static ItemInfoPackage& getItemInfoPackageChart() { - /************************************************************************** - * PoolDefaults - **************************************************************************/ - std::vector<SfxPoolItem*>* ppPoolDefaults = new std::vector<SfxPoolItem*>(SCHATTR_END - SCHATTR_START + 1); - std::vector<SfxPoolItem*>& rPoolDefaults = *ppPoolDefaults; - rPoolDefaults[SCHATTR_DATADESCR_SHOW_NUMBER - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_NUMBER); - rPoolDefaults[SCHATTR_DATADESCR_SHOW_PERCENTAGE- SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_PERCENTAGE); - rPoolDefaults[SCHATTR_DATADESCR_SHOW_CATEGORY - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_CATEGORY); - rPoolDefaults[SCHATTR_DATADESCR_SHOW_SYMBOL - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_SYMBOL); - rPoolDefaults[SCHATTR_DATADESCR_WRAP_TEXT - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_WRAP_TEXT); - rPoolDefaults[SCHATTR_DATADESCR_SEPARATOR - SCHATTR_START] = new SfxStringItem(SCHATTR_DATADESCR_SEPARATOR," "); - rPoolDefaults[SCHATTR_DATADESCR_PLACEMENT - SCHATTR_START] = new SfxInt32Item(SCHATTR_DATADESCR_PLACEMENT,0); - rPoolDefaults[SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS - SCHATTR_START] = new SfxIntegerListItem(SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, std::vector < sal_Int32 >() ); - rPoolDefaults[SCHATTR_DATADESCR_NO_PERCENTVALUE - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_NO_PERCENTVALUE); - rPoolDefaults[SCHATTR_PERCENT_NUMBERFORMAT_VALUE - SCHATTR_START] = new SfxUInt32Item(SCHATTR_PERCENT_NUMBERFORMAT_VALUE, 0); - rPoolDefaults[SCHATTR_PERCENT_NUMBERFORMAT_SOURCE - SCHATTR_START] = new SfxBoolItem(SCHATTR_PERCENT_NUMBERFORMAT_SOURCE); - - //legend - rPoolDefaults[SCHATTR_LEGEND_POS - SCHATTR_START] = new SfxInt32Item(SCHATTR_LEGEND_POS, sal_Int32(css::chart2::LegendPosition_LINE_END) ); - rPoolDefaults[SCHATTR_LEGEND_SHOW - SCHATTR_START] = new SfxBoolItem(SCHATTR_LEGEND_SHOW, true); - rPoolDefaults[SCHATTR_LEGEND_NO_OVERLAY - SCHATTR_START] = new SfxBoolItem(SCHATTR_LEGEND_NO_OVERLAY, true); - - //text - rPoolDefaults[SCHATTR_TEXT_DEGREES - SCHATTR_START] = new SfxInt32Item(SCHATTR_TEXT_DEGREES, 0); - rPoolDefaults[SCHATTR_TEXT_STACKED - SCHATTR_START] = new SfxBoolItem(SCHATTR_TEXT_STACKED,false); - - //statistic - rPoolDefaults[SCHATTR_STAT_AVERAGE - SCHATTR_START] = new SfxBoolItem (SCHATTR_STAT_AVERAGE); - rPoolDefaults[SCHATTR_STAT_KIND_ERROR - SCHATTR_START] = new SvxChartKindErrorItem (SvxChartKindError::NONE, SCHATTR_STAT_KIND_ERROR); - rPoolDefaults[SCHATTR_STAT_PERCENT - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_PERCENT); - rPoolDefaults[SCHATTR_STAT_BIGERROR - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_BIGERROR); - rPoolDefaults[SCHATTR_STAT_CONSTPLUS - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_CONSTPLUS); - rPoolDefaults[SCHATTR_STAT_CONSTMINUS - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_CONSTMINUS); - rPoolDefaults[SCHATTR_STAT_INDICATE - SCHATTR_START] = new SvxChartIndicateItem (SvxChartIndicate::NONE, SCHATTR_STAT_INDICATE); - rPoolDefaults[SCHATTR_STAT_RANGE_POS - SCHATTR_START] = new SfxStringItem (SCHATTR_STAT_RANGE_POS, OUString()); - rPoolDefaults[SCHATTR_STAT_RANGE_NEG - SCHATTR_START] = new SfxStringItem (SCHATTR_STAT_RANGE_NEG, OUString()); - rPoolDefaults[SCHATTR_STAT_ERRORBAR_TYPE - SCHATTR_START] = new SfxBoolItem(SCHATTR_STAT_ERRORBAR_TYPE, true); - - rPoolDefaults[SCHATTR_STYLE_DEEP - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_DEEP, false); - rPoolDefaults[SCHATTR_STYLE_3D - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_3D, false); - rPoolDefaults[SCHATTR_STYLE_VERTICAL - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_VERTICAL, false); - rPoolDefaults[SCHATTR_STYLE_BASETYPE - SCHATTR_START] = new SfxInt32Item(SCHATTR_STYLE_BASETYPE, 0); - rPoolDefaults[SCHATTR_STYLE_LINES - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_LINES, false); - rPoolDefaults[SCHATTR_STYLE_PERCENT - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_PERCENT, false); - rPoolDefaults[SCHATTR_STYLE_STACKED - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_STACKED, false); - rPoolDefaults[SCHATTR_STYLE_SPLINES - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SPLINES, 0); //Bug: was Bool! test ->Fileformat (touches only 5's) - rPoolDefaults[SCHATTR_STYLE_SYMBOL - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SYMBOL, 0); - rPoolDefaults[SCHATTR_STYLE_SHAPE - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SHAPE, 0); - - rPoolDefaults[SCHATTR_AXIS - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS,2); //2 = Y-Axis!!! - - //axis scale - rPoolDefaults[SCHATTR_AXISTYPE - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXISTYPE, CHART_AXIS_REALNUMBER); - rPoolDefaults[SCHATTR_AXIS_REVERSE - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_REVERSE,false); - rPoolDefaults[SCHATTR_AXIS_AUTO_MIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_MIN); - rPoolDefaults[SCHATTR_AXIS_MIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_MIN); - rPoolDefaults[SCHATTR_AXIS_AUTO_MAX - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_MAX); - rPoolDefaults[SCHATTR_AXIS_MAX - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_MAX); - rPoolDefaults[SCHATTR_AXIS_AUTO_STEP_MAIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_MAIN); - rPoolDefaults[SCHATTR_AXIS_STEP_MAIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_STEP_MAIN); - rPoolDefaults[SCHATTR_AXIS_MAIN_TIME_UNIT - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_MAIN_TIME_UNIT,2); - rPoolDefaults[SCHATTR_AXIS_AUTO_STEP_HELP - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_HELP); - rPoolDefaults[SCHATTR_AXIS_STEP_HELP - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_STEP_HELP,0); - rPoolDefaults[SCHATTR_AXIS_HELP_TIME_UNIT - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_HELP_TIME_UNIT,2); - rPoolDefaults[SCHATTR_AXIS_AUTO_TIME_RESOLUTION - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_TIME_RESOLUTION); - rPoolDefaults[SCHATTR_AXIS_TIME_RESOLUTION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_TIME_RESOLUTION,2); - rPoolDefaults[SCHATTR_AXIS_LOGARITHM - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_LOGARITHM); - rPoolDefaults[SCHATTR_AXIS_AUTO_DATEAXIS - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_DATEAXIS); - rPoolDefaults[SCHATTR_AXIS_ALLOW_DATEAXIS - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_ALLOW_DATEAXIS); - rPoolDefaults[SCHATTR_AXIS_AUTO_ORIGIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_ORIGIN); - rPoolDefaults[SCHATTR_AXIS_ORIGIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_ORIGIN); - - //axis position - rPoolDefaults[SCHATTR_AXIS_TICKS - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_TICKS,CHAXIS_MARK_OUTER); - rPoolDefaults[SCHATTR_AXIS_HELPTICKS - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_HELPTICKS,0); - rPoolDefaults[SCHATTR_AXIS_POSITION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_POSITION,0); - rPoolDefaults[SCHATTR_AXIS_POSITION_VALUE - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_POSITION_VALUE); - rPoolDefaults[SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT - SCHATTR_START] = new SfxUInt32Item(SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT,0); - rPoolDefaults[SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION,false); - rPoolDefaults[SCHATTR_AXIS_LABEL_POSITION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_LABEL_POSITION,0); - rPoolDefaults[SCHATTR_AXIS_MARK_POSITION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_MARK_POSITION,0); - - //axis label - rPoolDefaults[SCHATTR_AXIS_SHOWDESCR - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_SHOWDESCR,false); - rPoolDefaults[SCHATTR_AXIS_LABEL_ORDER - SCHATTR_START] = new SvxChartTextOrderItem(SvxChartTextOrder::SideBySide, SCHATTR_AXIS_LABEL_ORDER); - rPoolDefaults[SCHATTR_AXIS_LABEL_OVERLAP - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_LABEL_OVERLAP,false); - rPoolDefaults[SCHATTR_AXIS_LABEL_BREAK - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_LABEL_BREAK, false ); - - rPoolDefaults[SCHATTR_SYMBOL_BRUSH - SCHATTR_START] = new SvxBrushItem(SCHATTR_SYMBOL_BRUSH); - rPoolDefaults[SCHATTR_STOCK_VOLUME - SCHATTR_START] = new SfxBoolItem(SCHATTR_STOCK_VOLUME,false); - rPoolDefaults[SCHATTR_STOCK_UPDOWN - SCHATTR_START] = new SfxBoolItem(SCHATTR_STOCK_UPDOWN,false); - rPoolDefaults[SCHATTR_SYMBOL_SIZE - SCHATTR_START] = new SvxSizeItem(SCHATTR_SYMBOL_SIZE,Size(0,0)); - rPoolDefaults[SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY - SCHATTR_START] = new SfxBoolItem(SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, false); - - // new for New Chart - rPoolDefaults[SCHATTR_BAR_OVERLAP - SCHATTR_START] = new SfxInt32Item(SCHATTR_BAR_OVERLAP,0); - rPoolDefaults[SCHATTR_BAR_GAPWIDTH - SCHATTR_START] = new SfxInt32Item(SCHATTR_BAR_GAPWIDTH,0); - rPoolDefaults[SCHATTR_BAR_CONNECT - SCHATTR_START] = new SfxBoolItem(SCHATTR_BAR_CONNECT, false); - rPoolDefaults[SCHATTR_NUM_OF_LINES_FOR_BAR - SCHATTR_START] = new SfxInt32Item( SCHATTR_NUM_OF_LINES_FOR_BAR, 0 ); - rPoolDefaults[SCHATTR_SPLINE_ORDER - SCHATTR_START] = new SfxInt32Item( SCHATTR_SPLINE_ORDER, 3 ); - rPoolDefaults[SCHATTR_SPLINE_RESOLUTION - SCHATTR_START] = new SfxInt32Item( SCHATTR_SPLINE_RESOLUTION, 20 ); - rPoolDefaults[SCHATTR_GROUP_BARS_PER_AXIS - SCHATTR_START] = new SfxBoolItem(SCHATTR_GROUP_BARS_PER_AXIS, false); - rPoolDefaults[SCHATTR_STARTING_ANGLE - SCHATTR_START] = new SfxInt32Item( SCHATTR_STARTING_ANGLE, 90 ); - rPoolDefaults[SCHATTR_CLOCKWISE - SCHATTR_START] = new SfxBoolItem( SCHATTR_CLOCKWISE, false ); - - rPoolDefaults[SCHATTR_MISSING_VALUE_TREATMENT - SCHATTR_START] = new SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT, 0); - rPoolDefaults[SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS - SCHATTR_START] = new SfxIntegerListItem(SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS, std::vector < sal_Int32 >() ); - rPoolDefaults[SCHATTR_INCLUDE_HIDDEN_CELLS - SCHATTR_START] = new SfxBoolItem(SCHATTR_INCLUDE_HIDDEN_CELLS, true); - rPoolDefaults[SCHATTR_HIDE_LEGEND_ENTRY - SCHATTR_START] = new SfxBoolItem(SCHATTR_HIDE_LEGEND_ENTRY, false); - - rPoolDefaults[SCHATTR_AXIS_FOR_ALL_SERIES - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_FOR_ALL_SERIES, 0); - - rPoolDefaults[SCHATTR_REGRESSION_TYPE - SCHATTR_START] = new SvxChartRegressItem (SvxChartRegress::NONE, SCHATTR_REGRESSION_TYPE); - rPoolDefaults[SCHATTR_REGRESSION_SHOW_EQUATION - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SHOW_EQUATION, false); - rPoolDefaults[SCHATTR_REGRESSION_SHOW_COEFF - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SHOW_COEFF, false); - rPoolDefaults[SCHATTR_REGRESSION_DEGREE - SCHATTR_START] = new SfxInt32Item(SCHATTR_REGRESSION_DEGREE, 2); - rPoolDefaults[SCHATTR_REGRESSION_PERIOD - SCHATTR_START] = new SfxInt32Item(SCHATTR_REGRESSION_PERIOD, 2); - rPoolDefaults[SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD); - rPoolDefaults[SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD); - rPoolDefaults[SCHATTR_REGRESSION_SET_INTERCEPT - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SET_INTERCEPT, false); - rPoolDefaults[SCHATTR_REGRESSION_INTERCEPT_VALUE - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_REGRESSION_INTERCEPT_VALUE); - rPoolDefaults[SCHATTR_REGRESSION_CURVE_NAME - SCHATTR_START] = new SfxStringItem(SCHATTR_REGRESSION_CURVE_NAME, OUString()); - rPoolDefaults[SCHATTR_REGRESSION_XNAME - SCHATTR_START] = new SfxStringItem(SCHATTR_REGRESSION_XNAME, "x"); - rPoolDefaults[SCHATTR_REGRESSION_YNAME - SCHATTR_START] = new SfxStringItem(SCHATTR_REGRESSION_YNAME, "f(x)"); - - /************************************************************************** - * ItemInfos - **************************************************************************/ - const sal_uInt16 nMax = SCHATTR_END - SCHATTR_START + 1; - for( sal_uInt16 i = 0; i < nMax; i++ ) + class ItemInfoPackageChart : public ItemInfoPackage { - pItemInfos[i]._nSID = 0; - pItemInfos[i]._bPoolable = true; - } - - // slot ids differing from which ids - pItemInfos[SCHATTR_SYMBOL_BRUSH - SCHATTR_START]._nSID = SID_ATTR_BRUSH; - pItemInfos[SCHATTR_STYLE_SYMBOL - SCHATTR_START]._nSID = SID_ATTR_SYMBOLTYPE; - pItemInfos[SCHATTR_SYMBOL_SIZE - SCHATTR_START]._nSID = SID_ATTR_SYMBOLSIZE; + typedef std::array<ItemInfoStatic, SCHATTR_END - SCHATTR_START + 1> ItemInfoArrayChart; + ItemInfoArrayChart maItemInfos {{ + // m_nWhich, m_pItem, m_nSlotID, m_nItemInfoFlags + { SCHATTR_DATADESCR_SHOW_NUMBER, new SfxBoolItem(SCHATTR_DATADESCR_SHOW_NUMBER), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_SHOW_PERCENTAGE, new SfxBoolItem(SCHATTR_DATADESCR_SHOW_PERCENTAGE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_SHOW_CATEGORY, new SfxBoolItem(SCHATTR_DATADESCR_SHOW_CATEGORY), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_SHOW_SYMBOL, new SfxBoolItem(SCHATTR_DATADESCR_SHOW_SYMBOL), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_WRAP_TEXT, new SfxBoolItem(SCHATTR_DATADESCR_WRAP_TEXT), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_SEPARATOR, new SfxStringItem(SCHATTR_DATADESCR_SEPARATOR," "), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_PLACEMENT, new SfxInt32Item(SCHATTR_DATADESCR_PLACEMENT,0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, new SfxIntegerListItem(SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, std::vector < sal_Int32 >() ), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_NO_PERCENTVALUE, new SfxBoolItem(SCHATTR_DATADESCR_NO_PERCENTVALUE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_CUSTOM_LEADER_LINES, new SfxBoolItem(SCHATTR_DATADESCR_CUSTOM_LEADER_LINES, true), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_PERCENT_NUMBERFORMAT_VALUE, new SfxUInt32Item(SCHATTR_PERCENT_NUMBERFORMAT_VALUE, 0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, new SfxBoolItem(SCHATTR_PERCENT_NUMBERFORMAT_SOURCE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME, new SfxBoolItem(SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME), 0, SFX_ITEMINFOFLAG_NONE }, + + //legend + { SCHATTR_LEGEND_POS, new SfxInt32Item(SCHATTR_LEGEND_POS, sal_Int32(css::chart2::LegendPosition_LINE_END) ), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_LEGEND_SHOW, new SfxBoolItem(SCHATTR_LEGEND_SHOW, true), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_LEGEND_NO_OVERLAY, new SfxBoolItem(SCHATTR_LEGEND_NO_OVERLAY, true), 0, SFX_ITEMINFOFLAG_NONE }, + + //text + { SCHATTR_TEXT_DEGREES, new SdrAngleItem(SCHATTR_TEXT_DEGREES, 0_deg100), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_TEXT_STACKED, new SfxBoolItem(SCHATTR_TEXT_STACKED,false), 0, SFX_ITEMINFOFLAG_NONE }, + + //statistic + { SCHATTR_STAT_AVERAGE, new SfxBoolItem (SCHATTR_STAT_AVERAGE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STAT_KIND_ERROR, new SvxChartKindErrorItem (SvxChartKindError::NONE, SCHATTR_STAT_KIND_ERROR), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STAT_PERCENT, new SvxDoubleItem (0.0, SCHATTR_STAT_PERCENT), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STAT_BIGERROR, new SvxDoubleItem (0.0, SCHATTR_STAT_BIGERROR), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STAT_CONSTPLUS, new SvxDoubleItem (0.0, SCHATTR_STAT_CONSTPLUS), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STAT_CONSTMINUS, new SvxDoubleItem (0.0, SCHATTR_STAT_CONSTMINUS), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STAT_INDICATE, new SvxChartIndicateItem (SvxChartIndicate::NONE, SCHATTR_STAT_INDICATE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STAT_RANGE_POS, new SfxStringItem (SCHATTR_STAT_RANGE_POS, OUString()), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STAT_RANGE_NEG, new SfxStringItem (SCHATTR_STAT_RANGE_NEG, OUString()), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STAT_ERRORBAR_TYPE, new SfxBoolItem(SCHATTR_STAT_ERRORBAR_TYPE, true), 0, SFX_ITEMINFOFLAG_NONE }, + + { SCHATTR_STYLE_DEEP, new SfxBoolItem (SCHATTR_STYLE_DEEP, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STYLE_3D, new SfxBoolItem (SCHATTR_STYLE_3D, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STYLE_VERTICAL, new SfxBoolItem (SCHATTR_STYLE_VERTICAL, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STYLE_BASETYPE, new SfxInt32Item(SCHATTR_STYLE_BASETYPE, 0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STYLE_LINES, new SfxBoolItem (SCHATTR_STYLE_LINES, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STYLE_PERCENT, new SfxBoolItem (SCHATTR_STYLE_PERCENT, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STYLE_STACKED, new SfxBoolItem (SCHATTR_STYLE_STACKED, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STYLE_SPLINES, new SfxInt32Item (SCHATTR_STYLE_SPLINES, 0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STYLE_SYMBOL, new SfxInt32Item (SCHATTR_STYLE_SYMBOL, 0), SID_ATTR_SYMBOLTYPE, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STYLE_SHAPE, new SfxInt32Item (SCHATTR_STYLE_SHAPE, 0), 0, SFX_ITEMINFOFLAG_NONE }, + + { SCHATTR_AXIS, new SfxInt32Item(SCHATTR_AXIS,2), 0, SFX_ITEMINFOFLAG_NONE }, + + //axis scale + { SCHATTR_AXISTYPE, new SfxInt32Item(SCHATTR_AXISTYPE, CHART_AXIS_REALNUMBER), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_REVERSE, new SfxBoolItem(SCHATTR_AXIS_REVERSE,false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_AUTO_MIN, new SfxBoolItem(SCHATTR_AXIS_AUTO_MIN), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_MIN, new SvxDoubleItem(0.0, SCHATTR_AXIS_MIN), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_AUTO_MAX, new SfxBoolItem(SCHATTR_AXIS_AUTO_MAX), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_MAX, new SvxDoubleItem(0.0, SCHATTR_AXIS_MAX), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_AUTO_STEP_MAIN, new SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_MAIN), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_STEP_MAIN, new SvxDoubleItem(0.0, SCHATTR_AXIS_STEP_MAIN), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_MAIN_TIME_UNIT, new SfxInt32Item(SCHATTR_AXIS_MAIN_TIME_UNIT,2), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_AUTO_STEP_HELP, new SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_HELP), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_STEP_HELP, new SfxInt32Item(SCHATTR_AXIS_STEP_HELP,0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_HELP_TIME_UNIT, new SfxInt32Item(SCHATTR_AXIS_HELP_TIME_UNIT,2), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_AUTO_TIME_RESOLUTION, new SfxBoolItem(SCHATTR_AXIS_AUTO_TIME_RESOLUTION), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_TIME_RESOLUTION, new SfxInt32Item(SCHATTR_AXIS_TIME_RESOLUTION,2), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_LOGARITHM, new SfxBoolItem(SCHATTR_AXIS_LOGARITHM), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_AUTO_DATEAXIS, new SfxBoolItem(SCHATTR_AXIS_AUTO_DATEAXIS), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_ALLOW_DATEAXIS, new SfxBoolItem(SCHATTR_AXIS_ALLOW_DATEAXIS), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_AUTO_ORIGIN, new SfxBoolItem(SCHATTR_AXIS_AUTO_ORIGIN), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_ORIGIN, new SvxDoubleItem(0.0, SCHATTR_AXIS_ORIGIN), 0, SFX_ITEMINFOFLAG_NONE }, + + //axis position + { SCHATTR_AXIS_TICKS, new SfxInt32Item(SCHATTR_AXIS_TICKS,CHAXIS_MARK_OUTER), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_HELPTICKS, new SfxInt32Item(SCHATTR_AXIS_HELPTICKS,0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_POSITION, new SfxInt32Item(SCHATTR_AXIS_POSITION,0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_POSITION_VALUE, new SvxDoubleItem(0.0, SCHATTR_AXIS_POSITION_VALUE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT, new SfxUInt32Item(SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT,0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION, new SfxBoolItem(SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION,false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_LABEL_POSITION, new SfxInt32Item(SCHATTR_AXIS_LABEL_POSITION,0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_MARK_POSITION, new SfxInt32Item(SCHATTR_AXIS_MARK_POSITION,0), 0, SFX_ITEMINFOFLAG_NONE }, + + //axis label + { SCHATTR_AXIS_SHOWDESCR, new SfxBoolItem(SCHATTR_AXIS_SHOWDESCR,false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_LABEL_ORDER, new SvxChartTextOrderItem(SvxChartTextOrder::SideBySide, SCHATTR_AXIS_LABEL_ORDER), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_LABEL_OVERLAP, new SfxBoolItem(SCHATTR_AXIS_LABEL_OVERLAP,false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AXIS_LABEL_BREAK, new SfxBoolItem(SCHATTR_AXIS_LABEL_BREAK, false ), 0, SFX_ITEMINFOFLAG_NONE }, + + { SCHATTR_SYMBOL_BRUSH, new SvxBrushItem(SCHATTR_SYMBOL_BRUSH), SID_ATTR_BRUSH, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STOCK_VOLUME, new SfxBoolItem(SCHATTR_STOCK_VOLUME,false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STOCK_UPDOWN, new SfxBoolItem(SCHATTR_STOCK_UPDOWN,false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_SYMBOL_SIZE, new SvxSizeItem(SCHATTR_SYMBOL_SIZE,Size(0,0)), SID_ATTR_SYMBOLSIZE, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, new SfxBoolItem(SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, false), 0, SFX_ITEMINFOFLAG_NONE }, + + // new for New Chart + { SCHATTR_BAR_OVERLAP, new SfxInt32Item(SCHATTR_BAR_OVERLAP,0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_BAR_GAPWIDTH, new SfxInt32Item(SCHATTR_BAR_GAPWIDTH,0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_BAR_CONNECT, new SfxBoolItem(SCHATTR_BAR_CONNECT, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_NUM_OF_LINES_FOR_BAR, new SfxInt32Item( SCHATTR_NUM_OF_LINES_FOR_BAR, 0 ), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_SPLINE_ORDER, new SfxInt32Item( SCHATTR_SPLINE_ORDER, 3 ), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_SPLINE_RESOLUTION, new SfxInt32Item( SCHATTR_SPLINE_RESOLUTION, 20 ), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_GROUP_BARS_PER_AXIS, new SfxBoolItem(SCHATTR_GROUP_BARS_PER_AXIS, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_STARTING_ANGLE, new SdrAngleItem( SCHATTR_STARTING_ANGLE, 9000_deg100 ), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_CLOCKWISE, new SfxBoolItem( SCHATTR_CLOCKWISE, false ), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_MISSING_VALUE_TREATMENT, new SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT, 0), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS, new SfxIntegerListItem(SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS, std::vector < sal_Int32 >() ), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_INCLUDE_HIDDEN_CELLS, new SfxBoolItem(SCHATTR_INCLUDE_HIDDEN_CELLS, true), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_HIDE_LEGEND_ENTRY, new SfxBoolItem(SCHATTR_HIDE_LEGEND_ENTRY, false), 0, SFX_ITEMINFOFLAG_NONE }, + + { SCHATTR_AXIS_FOR_ALL_SERIES, new SfxInt32Item(SCHATTR_AXIS_FOR_ALL_SERIES, 0), 0, SFX_ITEMINFOFLAG_NONE }, + + { SCHATTR_REGRESSION_TYPE, new SvxChartRegressItem (SvxChartRegress::NONE, SCHATTR_REGRESSION_TYPE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_SHOW_EQUATION, new SfxBoolItem(SCHATTR_REGRESSION_SHOW_EQUATION, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_SHOW_COEFF, new SfxBoolItem(SCHATTR_REGRESSION_SHOW_COEFF, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_DEGREE, new SfxInt32Item(SCHATTR_REGRESSION_DEGREE, 2), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_PERIOD, new SfxInt32Item(SCHATTR_REGRESSION_PERIOD, 2), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD, new SvxDoubleItem(0.0, SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD, new SvxDoubleItem(0.0, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_SET_INTERCEPT, new SfxBoolItem(SCHATTR_REGRESSION_SET_INTERCEPT, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_INTERCEPT_VALUE, new SvxDoubleItem(0.0, SCHATTR_REGRESSION_INTERCEPT_VALUE), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_CURVE_NAME, new SfxStringItem(SCHATTR_REGRESSION_CURVE_NAME, OUString()), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_XNAME, new SfxStringItem(SCHATTR_REGRESSION_XNAME, "x"), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_YNAME, new SfxStringItem(SCHATTR_REGRESSION_YNAME, "f(x)"), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_REGRESSION_MOVING_TYPE, new SfxInt32Item(SCHATTR_REGRESSION_MOVING_TYPE, css::chart2::MovingAverageType::Prior), 0, SFX_ITEMINFOFLAG_NONE }, + + { SCHATTR_DATA_TABLE_HORIZONTAL_BORDER, new SfxBoolItem(SCHATTR_DATA_TABLE_HORIZONTAL_BORDER, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATA_TABLE_VERTICAL_BORDER, new SfxBoolItem(SCHATTR_DATA_TABLE_VERTICAL_BORDER, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATA_TABLE_OUTLINE, new SfxBoolItem(SCHATTR_DATA_TABLE_OUTLINE, false), 0, SFX_ITEMINFOFLAG_NONE }, + { SCHATTR_DATA_TABLE_KEYS, new SfxBoolItem(SCHATTR_DATA_TABLE_KEYS, false), 0, SFX_ITEMINFOFLAG_NONE } + }}; + + virtual const ItemInfoStatic& getItemInfoStatic(size_t nIndex) const override { return maItemInfos[nIndex]; } + + public: + virtual size_t size() const override { return maItemInfos.size(); } + virtual const ItemInfo& getItemInfo(size_t nIndex, SfxItemPool& /*rPool*/) override { return maItemInfos[nIndex]; } + }; + + static std::unique_ptr<ItemInfoPackageChart> g_aItemInfoPackageChart; + if (!g_aItemInfoPackageChart) + g_aItemInfoPackageChart.reset(new ItemInfoPackageChart); + return *g_aItemInfoPackageChart; +} - SetDefaults(ppPoolDefaults); - SetItemInfos(pItemInfos.get()); +ChartItemPool::ChartItemPool() +: SfxItemPool("ChartItemPool") +{ + registerItemInfoPackage(getItemInfoPackageChart()); } -ChartItemPool::ChartItemPool(const ChartItemPool& rPool): - SfxItemPool(rPool) +ChartItemPool::ChartItemPool(const ChartItemPool& rPool) +: SfxItemPool(rPool) { } ChartItemPool::~ChartItemPool() { - Delete(); - // release and delete static pool default items - ReleaseDefaults(true); + sendShutdownHint(); } -SfxItemPool* ChartItemPool::Clone() const +rtl::Reference<SfxItemPool> ChartItemPool::Clone() const { return new ChartItemPool(*this); } @@ -204,8 +221,21 @@ MapUnit ChartItemPool::GetMetric(sal_uInt16 /* nWhich */) const return MapUnit::Map100thMM; } -SfxItemPool* ChartItemPool::CreateChartItemPool() +rtl::Reference<SfxItemPool> ChartItemPool::CreateChartItemPool() { + // There are various default values which want to call + // OutputDevice::GetDefaultFont. Unfortunately, when processing + // UNO methods which may get called from out of process, this + // happens on a thread that does not take the SolarMutex, which + // causes trouble in ImplFontCache. + // Trying to take the SolarMutex when initialising these default + // leads to ABBA deadlocks. + // So rather just trigger the initialisation of these things here. + StaticDataSeriesDefaults(); + StaticAxisDefaults(); + StaticLegendDefaults(); + StaticFormattedStringDefaults(); + return new ChartItemPool(); } diff --git a/chart2/source/view/main/ChartItemPool.hxx b/chart2/source/view/main/ChartItemPool.hxx index b311b3050aa7..558ab3c6e2fc 100644 --- a/chart2/source/view/main/ChartItemPool.hxx +++ b/chart2/source/view/main/ChartItemPool.hxx @@ -16,8 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_MAIN_CHARTITEMPOOL_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_MAIN_CHARTITEMPOOL_HXX +#pragma once #include <tools/mapunit.hxx> #include <svl/itempool.hxx> @@ -27,26 +26,20 @@ namespace chart { class ChartItemPool : public SfxItemPool { -private: - std::unique_ptr<SfxItemInfo[]> pItemInfos; - public: ChartItemPool(); ChartItemPool(const ChartItemPool& rPool); -protected: virtual ~ChartItemPool() override; -public: - virtual SfxItemPool* Clone() const override; - MapUnit GetMetric( sal_uInt16 nWhich ) const override; + virtual rtl::Reference<SfxItemPool> Clone() const override; + MapUnit GetMetric(sal_uInt16 nWhich) const override; /// creates a pure chart item pool - static SfxItemPool* CreateChartItemPool(); + static rtl::Reference<SfxItemPool> CreateChartItemPool(); }; } // namespace chart -#endif // INCLUDED_CHART2_SOURCE_VIEW_MAIN_CHARTITEMPOOL_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx index a70738adb906..dc09a83f810a 100644 --- a/chart2/source/view/main/ChartView.cxx +++ b/chart2/source/view/main/ChartView.cxx @@ -19,17 +19,24 @@ #include <config_feature_desktop.h> +#include "SeriesPlotterContainer.hxx" + #include <ChartView.hxx> #include <chartview/DrawModelWrapper.hxx> +#include <Diagram.hxx> +#include <ChartType.hxx> +#include <DataSeries.hxx> #include <NumberFormatterWrapper.hxx> #include <VDiagram.hxx> #include "VTitle.hxx" #include "VButton.hxx" #include <ShapeFactory.hxx> +#include <BaseCoordinateSystem.hxx> #include <VCoordinateSystem.hxx> #include <VSeriesPlotter.hxx> #include <CommonConverters.hxx> #include <TitleHelper.hxx> +#include <Legend.hxx> #include <LegendHelper.hxx> #include "VLegend.hxx" #include <PropertyMapper.hxx> @@ -40,17 +47,22 @@ #include <DiagramHelper.hxx> #include <RelativePositionHelper.hxx> #include <servicenames.hxx> +#include <Axis.hxx> #include <AxisHelper.hxx> +#include "AxisUsage.hxx" #include <AxisIndexDefines.hxx> #include <BaseGFXHelper.hxx> #include <DataSeriesHelper.hxx> #include <DateHelper.hxx> #include <ExplicitCategoriesProvider.hxx> #include <defines.hxx> +#include <comphelper/dumpxmltostring.hxx> #include <unonames.hxx> #include <editeng/frmdiritem.hxx> +#include <editeng/eeitem.hxx> #include <tools/globname.hxx> #include <comphelper/fileformat.h> +#include <comphelper/propertyvalue.hxx> #include <comphelper/scopeguard.hxx> #include <comphelper/servicehelper.hxx> #include <cppuhelper/supportsservice.hxx> @@ -58,29 +70,25 @@ #include <unotools/streamwrap.hxx> #include <svx/svdpage.hxx> #include <svx/unopage.hxx> -#include <svx/unoshape.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <osl/mutex.hxx> #include <svx/unofill.hxx> #include <drawinglayer/XShapeDumper.hxx> +#include <sfx2/objsh.hxx> #include <time.h> -#include <com/sun/star/awt/Size.hpp> #include <com/sun/star/awt/Point.hpp> #include <com/sun/star/chart/ChartAxisPosition.hpp> #include <com/sun/star/chart/TimeUnit.hpp> #include <com/sun/star/chart2/AxisType.hpp> #include <com/sun/star/chart2/StackingDirection.hpp> -#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> -#include <com/sun/star/chart2/XChartTypeContainer.hpp> -#include <com/sun/star/chart2/XDataSeriesContainer.hpp> #include <com/sun/star/chart2/RelativePosition.hpp> #include <com/sun/star/chart2/RelativeSize.hpp> #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp> #include <com/sun/star/chart2/data/PivotTableFieldEntry.hpp> #include <com/sun/star/drawing/GraphicExportFilter.hpp> -#include <com/sun/star/drawing/XShapeGroup.hpp> #include <com/sun/star/embed/Aspects.hpp> #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> @@ -92,910 +100,26 @@ #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp> #include <com/sun/star/view/XSelectionSupplier.hpp> #include <svl/itempool.hxx> -#include <svl/languageoptions.hxx> +#include <svl/ctloptions.hxx> #include <comphelper/classids.hxx> #include <servicenames_charttypes.hxx> #include <rtl/ustring.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <tools/stream.hxx> #include <memory> #include <libxml/xmlwriter.h> -namespace com::sun::star::chart2 { class XChartDocument; } namespace chart { using namespace ::com::sun::star; -using namespace ::com::sun::star::chart2; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Any; -namespace { - -class theExplicitValueProviderUnoTunnelId : public rtl::Static<UnoTunnelIdInit, theExplicitValueProviderUnoTunnelId> {}; - -typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex; //first index is the dimension, second index is the axis index that indicates whether this is a main or secondary axis -typedef std::map< VCoordinateSystem*, tFullAxisIndex > tCoordinateSystemMap; - -/** This class handles a collection of coordinate systems and is used for - * executing some action on all coordinate systems such as - * `prepareAutomaticAxisScaling` and `setExplicitScaleAndIncrement`. - * Moreover it contains the `aAutoScaling` object that is an instance of - * the `ScaleAutomatism` class. The initialization of `aAutoScaling` is - * performed in the `SeriesPlotterContainer::initAxisUsageList` method and is - * used in the `SeriesPlotterContainer::doAutoScaling` for calculating explicit - * scale and increment objects (see `SeriesPlotterContainer::doAutoScaling`). - */ -struct AxisUsage -{ - AxisUsage(); - ~AxisUsage(); - - void addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ); - std::vector< VCoordinateSystem* > getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ); - sal_Int32 getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex ); - - void prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex ); - void setExplicitScaleAndIncrement( sal_Int32 nDimIndex, sal_Int32 nAxisIndex, const ExplicitScaleData& rScale, const ExplicitIncrementData& rInc ); - - ScaleAutomatism aAutoScaling; - -private: - tCoordinateSystemMap aCoordinateSystems; - std::map< sal_Int32, sal_Int32 > aMaxIndexPerDimension; -}; - -AxisUsage::AxisUsage() - : aAutoScaling(AxisHelper::createDefaultScale(), Date(Date::SYSTEM)) -{ -} - -AxisUsage::~AxisUsage() -{ - aCoordinateSystems.clear(); -} - -void AxisUsage::addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) -{ - if(!pCooSys) - return; - - tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex ); - tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) ); - - //use one scale only once for each coordinate system - //main axis are preferred over secondary axis - //value scales are preferred - if(aFound!=aCoordinateSystems.end()) - { - sal_Int32 nFoundAxisIndex = aFound->second.second; - if( nFoundAxisIndex < nAxisIndex ) - return; - sal_Int32 nFoundDimension = aFound->second.first; - if( nFoundDimension ==1 ) - return; - if( nFoundDimension < nDimensionIndex ) - return; - } - aCoordinateSystems[pCooSys] = aFullAxisIndex; - - //set maximum scale index - std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex); - if( aIter != aMaxIndexPerDimension.end() ) - { - sal_Int32 nCurrentMaxIndex = aIter->second; - if( nCurrentMaxIndex < nAxisIndex ) - aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex; - } - else - aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex; -} - -std::vector< VCoordinateSystem* > AxisUsage::getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) -{ - std::vector< VCoordinateSystem* > aRet; - - for (auto const& coordinateSystem : aCoordinateSystems) - { - if( coordinateSystem.second.first != nDimensionIndex ) - continue; - if( coordinateSystem.second.second != nAxisIndex ) - continue; - aRet.push_back( coordinateSystem.first ); - } - - return aRet; -} - -sal_Int32 AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex ) -{ - sal_Int32 nRet = -1; - std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex); - if( aIter != aMaxIndexPerDimension.end() ) - nRet = aIter->second; - return nRet; -} - -void AxisUsage::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex ) -{ - std::vector<VCoordinateSystem*> aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex); - for (VCoordinateSystem * i : aVCooSysList) - i->prepareAutomaticAxisScaling(rScaleAutomatism, nDimIndex, nAxisIndex); -} - -void AxisUsage::setExplicitScaleAndIncrement( - sal_Int32 nDimIndex, sal_Int32 nAxisIndex, const ExplicitScaleData& rScale, const ExplicitIncrementData& rInc ) -{ - std::vector<VCoordinateSystem*> aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex); - for (VCoordinateSystem* i : aVCooSysList) - i->setExplicitScaleAndIncrement(nDimIndex, nAxisIndex, rScale, rInc); -} - -typedef std::vector<std::unique_ptr<VSeriesPlotter> > SeriesPlottersType; - -/** This class is a container of `SeriesPlotter` objects (such as `PieChart` - * instances). It is used for initializing coordinate systems, axes and scales - * of all series plotters which belongs to the container. - */ -class SeriesPlotterContainer -{ -public: - explicit SeriesPlotterContainer( std::vector< std::unique_ptr<VCoordinateSystem> >& rVCooSysList ); - ~SeriesPlotterContainer(); - - /** It is used to set coordinate systems (`m_rVCooSysList`), this method - * is invoked by `ChartView::createShapes2D` before of - * `ChartView::impl_createDiagramAndContent`. - * Coordinate systems are retrieved through the `XCoordinateSystemContainer` - * interface implemented by a diagram object which is provided by the - * `ChartModel` object passed to the method (`rChartModel.getFirstDiagram()`). - * - * It is used for creating series plotters and appending them - * to `m_aSeriesPlotterList`. The created series plotters are initialized - * through data (number formats supplier, color scheme, data series), - * extracted from the chart model or the diagram objects. An exception is - * the explicit category provider that is retrieved through the - * `VCoordinateSystem` object used by the series plotter. - * - * It sets the minimum-maximum supplier for a coordinate system: - * this supplier is the series plotter itself which utilizes the given - * coordinate system. In fact `VSeriesPlotter` has `MinimumMaximumSupplier` - * as one of its base classes. - * Hence, for instance, a `PieChart`, which is a series plotter, is - * a `MinimumMaximumSupplier`, too. - */ - void initializeCooSysAndSeriesPlotter( ChartModel& rModel ); - - /** This method is invoked by `ChartView::impl_createDiagramAndContent`. - * It iterates on every axis of every coordinate systems, and if the axis - * is not yet present in `m_aAxisUsageList` it creates a new `AxisUsage` - * object and initialize its `aAutoScaling` member to the `ScaleData` - * object of the current axis. - */ - void initAxisUsageList(const Date& rNullDate); - - /** - * Perform automatic axis scaling and determine the amount and spacing of - * increments. It assumes that the caller has determined the size of the - * largest axis label text object prior to calling this method. - * - * The new axis scaling data will be stored in the VCoordinateSystem - * objects. The label alignment direction for each axis will also get - * determined during this process, and stored in VAxis. - * - * This method is invoked by `ChartView::impl_createDiagramAndContent` - * soon after `initAxisUsageList`. - * It initializes explicit scale and increment objects for all coordinate - * systems in `m_rVCooSysList`. - * This action is achieved by iterating on the `m_aAxisUsageList` container, - * and performing 3 steps: - * 1- call `VCoordinateSystem::prepareAutomaticAxisScaling` for setting - * scaling parameters of the `aAutoScaling` member (a `ScaleAutomatism` - * object) for the current `AxisUsage` instance - * (see `VCoordinateSystem::prepareAutomaticAxisScaling`); - * 2- calculate the explicit scale and increment objects - * (see ScaleAutomatism::calculateExplicitScaleAndIncrement); - * 3- set the explicit scale and increment objects for each coordinate - * system. - */ - void doAutoScaling( ChartModel& rModel ); - - /** - * After auto-scaling is performed, call this method to set the explicit - * scaling and increment data to all relevant VAxis objects. - */ - void updateScalesAndIncrementsOnAxes(); - - /** - * After auto-scaling is performed, call this method to set the explicit - * scaling data to all the plotters. - */ - void setScalesFromCooSysToPlotter(); - - void setNumberFormatsFromAxes(); - drawing::Direction3D getPreferredAspectRatio(); - - SeriesPlottersType& getSeriesPlotterList() { return m_aSeriesPlotterList; } - std::vector< std::unique_ptr<VCoordinateSystem> >& getCooSysList() { return m_rVCooSysList; } - std::vector< LegendEntryProvider* > getLegendEntryProviderList(); - - void AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel& rModel ); - - static bool isCategoryPositionShifted( - const chart2::ScaleData& rSourceScale, bool bHasComplexCategories ); - -private: - /** A vector of series plotters. - */ - SeriesPlottersType m_aSeriesPlotterList; - - /** A vector of coordinate systems. - */ - std::vector< std::unique_ptr<VCoordinateSystem> >& m_rVCooSysList; - - /** A map whose key is a `XAxis` interface and the related value is - * an object of `AxisUsage` type. - */ - std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList; - - /** - * Max axis index of all dimensions. Currently this can be either 0 or 1 - * since we only support primary and secondary axes per dimension. The - * value of 0 means all dimensions have only primary axis, while 1 means - * at least one dimension has a secondary axis. - */ - sal_Int32 m_nMaxAxisIndex; - - sal_Int32 m_nDefaultDateNumberFormat; -}; - -SeriesPlotterContainer::SeriesPlotterContainer( std::vector< std::unique_ptr<VCoordinateSystem> >& rVCooSysList ) - : m_rVCooSysList( rVCooSysList ) - , m_nMaxAxisIndex(0) - , m_nDefaultDateNumberFormat(0) -{ -} - -SeriesPlotterContainer::~SeriesPlotterContainer() -{ - // - remove plotter from coordinatesystems - for(auto & nC : m_rVCooSysList) - nC->clearMinimumAndMaximumSupplierList(); -} - -std::vector< LegendEntryProvider* > SeriesPlotterContainer::getLegendEntryProviderList() -{ - std::vector< LegendEntryProvider* > aRet( m_aSeriesPlotterList.size() ); - sal_Int32 nN = 0; - for( const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList) - aRet[nN++] = aPlotter.get(); - return aRet; -} - -VCoordinateSystem* findInCooSysList( const std::vector< std::unique_ptr<VCoordinateSystem> >& rVCooSysList - , const uno::Reference< XCoordinateSystem >& xCooSys ) -{ - for(auto & pVCooSys : rVCooSysList) - { - if(pVCooSys->getModel()==xCooSys) - return pVCooSys.get(); - } - return nullptr; -} - -VCoordinateSystem* lcl_getCooSysForPlotter( const std::vector< std::unique_ptr<VCoordinateSystem> >& rVCooSysList, MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier ) -{ - if(!pMinimumAndMaximumSupplier) - return nullptr; - for(auto & pVCooSys : rVCooSysList) - { - if(pVCooSys->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier )) - return pVCooSys.get(); - } - return nullptr; -} - -VCoordinateSystem* addCooSysToList( std::vector< std::unique_ptr<VCoordinateSystem> >& rVCooSysList - , const uno::Reference< XCoordinateSystem >& xCooSys - , ChartModel& rChartModel ) -{ - VCoordinateSystem* pExistingVCooSys = findInCooSysList( rVCooSysList, xCooSys ); - if( pExistingVCooSys ) - return pExistingVCooSys; - - std::unique_ptr<VCoordinateSystem> pVCooSys = VCoordinateSystem::createCoordinateSystem(xCooSys ); - if(!pVCooSys) - return nullptr; - - OUString aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys, rChartModel ) ); - pVCooSys->setParticle(aCooSysParticle); - - pVCooSys->setExplicitCategoriesProvider( new ExplicitCategoriesProvider(xCooSys, rChartModel) ); - rVCooSysList.push_back( std::move(pVCooSys) ); - return rVCooSysList.back().get(); -} - -void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter( - ChartModel& rChartModel ) -{ - uno::Reference< XDiagram > xDiagram( rChartModel.getFirstDiagram() ); - if( !xDiagram.is()) - return; - - uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( static_cast< ::cppu::OWeakObject* >( &rChartModel ), uno::UNO_QUERY ); - if( rChartModel.hasInternalDataProvider() && DiagramHelper::isSupportingDateAxis( xDiagram ) ) - m_nDefaultDateNumberFormat=DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier ); - - sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); - if(!nDimensionCount) - { - //@todo handle mixed dimension - nDimensionCount = 2; - } - - bool bSortByXValues = false; - bool bConnectBars = false; - bool bGroupBarsPerAxis = true; - bool bIncludeHiddenCells = true; - bool bSecondaryYaxisVisible = true; - sal_Int32 nStartingAngle = 90; - sal_Int32 n3DRelativeHeight = 100; - try - { - uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW ); - xDiaProp->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= bSortByXValues; - xDiaProp->getPropertyValue( "ConnectBars" ) >>= bConnectBars; - xDiaProp->getPropertyValue( "GroupBarsPerAxis" ) >>= bGroupBarsPerAxis; - xDiaProp->getPropertyValue( "IncludeHiddenCells" ) >>= bIncludeHiddenCells; - xDiaProp->getPropertyValue( "StartingAngle" ) >>= nStartingAngle; - - if (nDimensionCount == 3) - { - xDiaProp->getPropertyValue( "3DRelativeHeight" ) >>= n3DRelativeHeight; - } - } - catch( const uno::Exception & ) - { - DBG_UNHANDLED_EXCEPTION("chart2" ); - } - - //prepare for autoscaling and shape creation - // - create plotter for charttypes (for each first scale group at each plotter, as they are independent) - // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling) - // - add plotter to coordinate systems - - //iterate through all coordinate systems - uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); - OSL_ASSERT( xCooSysContainer.is()); - if( !xCooSysContainer.is()) - return; - uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); - uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); - sal_Int32 nGlobalSeriesIndex = 0;//for automatic symbols - for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) - { - uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] ); - VCoordinateSystem* pVCooSys = addCooSysToList(m_rVCooSysList,xCooSys,rChartModel); - // Let's check whether the secondary Y axis is visible - try - { - if (xCooSys->getMaximumAxisIndexByDimension(1) > 0) - { - Reference< beans::XPropertySet > xAxisProp(xCooSys->getAxisByDimension(1, 1), uno::UNO_QUERY); - xAxisProp->getPropertyValue("Show") >>= bSecondaryYaxisVisible; - } - } - catch (const lang::IndexOutOfBoundsException&) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } - //iterate through all chart types in the current coordinate system - uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); - OSL_ASSERT( xChartTypeContainer.is()); - if( !xChartTypeContainer.is() ) - continue; - uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); - for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) - { - uno::Reference< XChartType > xChartType( aChartTypeList[nT] ); - if(nDimensionCount == 3 && xChartType->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE)) - { - uno::Reference< beans::XPropertySet > xPropertySet( xChartType, uno::UNO_QUERY ); - if (xPropertySet.is()) - { - try - { - sal_Int32 n3DRelativeHeightOldValue(100); - uno::Any aAny = xPropertySet->getPropertyValue( "3DRelativeHeight" ); - aAny >>= n3DRelativeHeightOldValue; - if (n3DRelativeHeightOldValue != n3DRelativeHeight) - xPropertySet->setPropertyValue( "3DRelativeHeight", uno::Any(n3DRelativeHeight) ); - } - catch (const uno::Exception&) { } - } - } - - bool bExcludingPositioning = DiagramHelper::getDiagramPositioningMode( xDiagram ) == DiagramPositioningMode_EXCLUDING; - VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount, bExcludingPositioning ); - if( !pPlotter ) - continue; - - m_aSeriesPlotterList.push_back( std::unique_ptr<VSeriesPlotter>(pPlotter) ); - pPlotter->setNumberFormatsSupplier( xNumberFormatsSupplier ); - pPlotter->setColorScheme( xColorScheme ); - if(pVCooSys) - pPlotter->setExplicitCategoriesProvider( pVCooSys->getExplicitCategoriesProvider() ); - sal_Int32 nMissingValueTreatment = DiagramHelper::getCorrectedMissingValueTreatment( xDiagram, xChartType ); - - if(pVCooSys) - pVCooSys->addMinimumAndMaximumSupplier(pPlotter); - - uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY ); - OSL_ASSERT( xDataSeriesContainer.is()); - if( !xDataSeriesContainer.is() ) - continue; - - sal_Int32 zSlot=-1; - sal_Int32 xSlot=-1; - sal_Int32 ySlot=-1; - uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); - for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS ) - { - uno::Reference< XDataSeries > const & xDataSeries = aSeriesList[nS]; - if(!xDataSeries.is()) - continue; - if( !bIncludeHiddenCells && !DataSeriesHelper::hasUnhiddenData(xDataSeries) ) - continue; - - std::unique_ptr<VDataSeries> pSeries(new VDataSeries( xDataSeries )); - - pSeries->setGlobalSeriesIndex(nGlobalSeriesIndex); - nGlobalSeriesIndex++; - - if( bSortByXValues ) - pSeries->doSortByXValues(); - - pSeries->setConnectBars( bConnectBars ); - pSeries->setGroupBarsPerAxis( bGroupBarsPerAxis ); - pSeries->setStartingAngle( nStartingAngle ); - - pSeries->setMissingValueTreatment( nMissingValueTreatment ); - - OUString aSeriesParticle( ObjectIdentifier::createParticleForSeries( 0, nCS, nT, nS ) ); - pSeries->setParticle(aSeriesParticle); - - OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) ); - pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole); - - //ignore secondary axis for charttypes that do not support them - if( pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX && - ( !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount ) || - !bSecondaryYaxisVisible ) ) - { - pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX); - } - - StackingDirection eDirection = pSeries->getStackingDirection(); - switch(eDirection) - { - case StackingDirection_NO_STACKING: - xSlot++; ySlot=-1; - if(zSlot<0) - zSlot=0; - break; - case StackingDirection_Y_STACKING: - ySlot++; - if(xSlot<0) - xSlot=0; - if(zSlot<0) - zSlot=0; - break; - case StackingDirection_Z_STACKING: - zSlot++; xSlot=-1; ySlot=-1; - break; - default: - // UNO enums have one additional auto-generated case - break; - } - pPlotter->addSeries( std::move(pSeries), zSlot, xSlot, ySlot ); - } - } - } - - //transport seriesnames to the coordinatesystems if needed - if( m_aSeriesPlotterList.empty() ) - return; - - uno::Sequence< OUString > aSeriesNames; - bool bSeriesNamesInitialized = false; - for(auto & pVCooSys : m_rVCooSysList) - { - if( pVCooSys->needSeriesNamesForAxis() ) - { - if(!bSeriesNamesInitialized) - { - aSeriesNames = m_aSeriesPlotterList[0]->getSeriesNames(); - bSeriesNamesInitialized = true; - } - pVCooSys->setSeriesNamesForAxis( aSeriesNames ); - } - } -} - -bool SeriesPlotterContainer::isCategoryPositionShifted( - const chart2::ScaleData& rSourceScale, bool bHasComplexCategories ) -{ - if (rSourceScale.AxisType == AxisType::CATEGORY) - return bHasComplexCategories || rSourceScale.ShiftedCategoryPosition; - - if (rSourceScale.AxisType == AxisType::DATE) - return rSourceScale.ShiftedCategoryPosition; - - return rSourceScale.AxisType == AxisType::SERIES; -} - -void SeriesPlotterContainer::initAxisUsageList(const Date& rNullDate) -{ - m_aAxisUsageList.clear(); - - // Loop through coordinate systems in the diagram (though for now - // there should only be one coordinate system per diagram). - for (auto & pVCooSys : m_rVCooSysList) - { - uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel(); - sal_Int32 nDimCount = xCooSys->getDimension(); - bool bComplexCategoryAllowed = ChartTypeHelper::isSupportingComplexCategory(AxisHelper::getChartTypeByIndex(xCooSys, 0)); - - for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex) - { - bool bDateAxisAllowed = ChartTypeHelper::isSupportingDateAxis( - AxisHelper::getChartTypeByIndex(xCooSys, 0), nDimIndex); - - // Each dimension may have primary and secondary axes. - const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex); - for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; ++nAxisIndex) - { - uno::Reference<XAxis> xAxis = xCooSys->getAxisByDimension(nDimIndex, nAxisIndex); - - if (!xAxis.is()) - continue; - - if (m_aAxisUsageList.find(xAxis) == m_aAxisUsageList.end()) - { - // Create axis usage object for this axis. - - chart2::ScaleData aSourceScale = xAxis->getScaleData(); - ExplicitCategoriesProvider* pCatProvider = pVCooSys->getExplicitCategoriesProvider(); - if (nDimIndex == 0) - AxisHelper::checkDateAxis( aSourceScale, pCatProvider, bDateAxisAllowed ); - - bool bHasComplexCat = pCatProvider && pCatProvider->hasComplexCategories() && bComplexCategoryAllowed; - aSourceScale.ShiftedCategoryPosition = isCategoryPositionShifted(aSourceScale, bHasComplexCat); - - m_aAxisUsageList[xAxis].aAutoScaling = ScaleAutomatism(aSourceScale, rNullDate); - } - - AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis]; - rAxisUsage.addCoordinateSystem(pVCooSys.get(), nDimIndex, nAxisIndex); - } - } - } - - // Determine the highest axis index of all dimensions. - m_nMaxAxisIndex = 0; - for (const auto & pVCooSys : m_rVCooSysList) - { - uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel(); - sal_Int32 nDimCount = xCooSys->getDimension(); - - for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex) - { - for (auto & axisUsage : m_aAxisUsageList) - { - sal_Int32 nLocalMax = axisUsage.second.getMaxAxisIndexForDimension(nDimIndex); - if (m_nMaxAxisIndex < nLocalMax) - m_nMaxAxisIndex = nLocalMax; - } - } - } -} - -void SeriesPlotterContainer::setScalesFromCooSysToPlotter() -{ - //set scales to plotter to enable them to provide the preferred scene AspectRatio - for( const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList ) - { - VSeriesPlotter* pSeriesPlotter = aPlotter.get(); - VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter ); - if(pVCooSys) - { - pSeriesPlotter->setScales( pVCooSys->getExplicitScales(0,0), pVCooSys->getPropertySwapXAndYAxis() ); - sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension(1);//only additional value axis are relevant for series plotter - for( sal_Int32 nI=1; nI<=nMaxAxisIndex; nI++ ) - pSeriesPlotter->addSecondaryValueScale( pVCooSys->getExplicitScale(1,nI), nI ); - } - } -} - -void SeriesPlotterContainer::setNumberFormatsFromAxes() -{ - //set numberformats to plotter to enable them to display the data labels in the numberformat of the axis - for( const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList ) - { - VSeriesPlotter* pSeriesPlotter = aPlotter.get(); - VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter ); - if(pVCooSys) - { - AxesNumberFormats aAxesNumberFormats; - const uno::Reference< XCoordinateSystem >& xCooSys = pVCooSys->getModel(); - sal_Int32 nDimensionCount = xCooSys->getDimension(); - for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nDimensionCount; ++nDimensionIndex) - { - const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex); - for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex) - { - try - { - Reference< beans::XPropertySet > xAxisProp( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY ); - if( xAxisProp.is()) - { - sal_Int32 nNumberFormatKey(0); - if( xAxisProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormatKey ) - { - aAxesNumberFormats.setFormat( nNumberFormatKey, nDimensionIndex, nAxisIndex ); - } - else if( nDimensionIndex==0 ) - { - //provide a default date format for date axis with own data - aAxesNumberFormats.setFormat( m_nDefaultDateNumberFormat, nDimensionIndex, nAxisIndex ); - } - } - } - catch( const lang::IndexOutOfBoundsException& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } - } - } - } - } -} - -void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes() -{ - for(auto & nC : m_rVCooSysList) - nC->updateScalesAndIncrementsOnAxes(); -} - -void SeriesPlotterContainer::doAutoScaling( ChartModel& rChartModel ) -{ - if (m_aSeriesPlotterList.empty() || m_aAxisUsageList.empty()) - // We need these two containers populated to do auto-scaling. Bail out. - return; - - //iterate over the main scales first than secondary axis - for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; ++nAxisIndex) - { - // - first do autoscale for all x and z scales (because they are treated independent) - for (auto & axisUsage : m_aAxisUsageList) - { - AxisUsage& rAxisUsage = axisUsage.second; - - rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 0, nAxisIndex); - rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 2, nAxisIndex); - - ExplicitScaleData aExplicitScale; - ExplicitIncrementData aExplicitIncrement; - rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement ); - - rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale, aExplicitIncrement); - rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale, aExplicitIncrement); - } - - // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already ) - for (auto & axisUsage : m_aAxisUsageList) - { - AxisUsage& rAxisUsage = axisUsage.second; - - rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, nAxisIndex); - - ExplicitScaleData aExplicitScale; - ExplicitIncrementData aExplicitIncrement; - rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement ); - - rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale, aExplicitIncrement); - rAxisUsage.setExplicitScaleAndIncrement(1, nAxisIndex, aExplicitScale, aExplicitIncrement); - rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale, aExplicitIncrement); - } - } - AdaptScaleOfYAxisWithoutAttachedSeries( rChartModel ); -} - -void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel& rModel ) -{ - //issue #i80518# - for( sal_Int32 nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ ) - { - for (auto & axisUsage : m_aAxisUsageList) - { - AxisUsage& rAxisUsage = axisUsage.second; - std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems( 1, nAxisIndex ); - if( aVCooSysList_Y.empty() ) - continue; - - uno::Reference< XDiagram > xDiagram( rModel.getFirstDiagram() ); - if (!xDiagram.is()) - continue; - - bool bSeriesAttachedToThisAxis = false; - sal_Int32 nAttachedAxisIndex = -1; - { - std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); - for (auto const& series : aSeriesVector) - { - sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex(series); - if( nAxisIndex == nCurrentIndex ) - { - bSeriesAttachedToThisAxis = true; - break; - } - else if( nAttachedAxisIndex<0 || nAttachedAxisIndex>nCurrentIndex ) - nAttachedAxisIndex=nCurrentIndex; - } - } - - if (bSeriesAttachedToThisAxis || nAttachedAxisIndex < 0) - continue; - - for(VCoordinateSystem* nC : aVCooSysList_Y) - { - nC->prepareAutomaticAxisScaling( rAxisUsage.aAutoScaling, 1, nAttachedAxisIndex ); - - ExplicitScaleData aExplicitScaleSource = nC->getExplicitScale( 1,nAttachedAxisIndex ); - ExplicitIncrementData aExplicitIncrementSource = nC->getExplicitIncrement( 1,nAttachedAxisIndex ); - - ExplicitScaleData aExplicitScaleDest = nC->getExplicitScale( 1,nAxisIndex ); - ExplicitIncrementData aExplicitIncrementDest = nC->getExplicitIncrement( 1,nAxisIndex ); - - aExplicitScaleDest.Orientation = aExplicitScaleSource.Orientation; - aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling; - aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType; - - aExplicitIncrementDest.BaseValue = aExplicitIncrementSource.BaseValue; - - ScaleData aScale( rAxisUsage.aAutoScaling.getScale() ); - if( !aScale.Minimum.hasValue() ) - { - bool bNewMinOK = true; - double fMax=0.0; - if( aScale.Maximum >>= fMax ) - bNewMinOK = (aExplicitScaleSource.Minimum <= fMax); - if( bNewMinOK ) - aExplicitScaleDest.Minimum = aExplicitScaleSource.Minimum; - } - else - aExplicitIncrementDest.BaseValue = aExplicitScaleDest.Minimum; - - if( !aScale.Maximum.hasValue() ) - { - bool bNewMaxOK = true; - double fMin=0.0; - if( aScale.Minimum >>= fMin ) - bNewMaxOK = (fMin <= aExplicitScaleSource.Maximum); - if( bNewMaxOK ) - aExplicitScaleDest.Maximum = aExplicitScaleSource.Maximum; - } - if( !aScale.Origin.hasValue() ) - aExplicitScaleDest.Origin = aExplicitScaleSource.Origin; - - if( !aScale.IncrementData.Distance.hasValue() ) - aExplicitIncrementDest.Distance = aExplicitIncrementSource.Distance; - - bool bAutoMinorInterval = true; - if( aScale.IncrementData.SubIncrements.hasElements() ) - bAutoMinorInterval = !( aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue() ); - if( bAutoMinorInterval ) - { - if( !aExplicitIncrementDest.SubIncrements.empty() && !aExplicitIncrementSource.SubIncrements.empty() ) - aExplicitIncrementDest.SubIncrements[0].IntervalCount = - aExplicitIncrementSource.SubIncrements[0].IntervalCount; - } - - nC->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScaleDest, aExplicitIncrementDest ); - } - } - } - - if( !AxisHelper::isAxisPositioningEnabled() ) - return; - - //correct origin for y main axis (the origin is where the other main axis crosses) - sal_Int32 nAxisIndex=0; - sal_Int32 nDimensionIndex=1; - for (auto & axisUsage : m_aAxisUsageList) - { - AxisUsage& rAxisUsage = axisUsage.second; - std::vector< VCoordinateSystem* > aVCooSysList = rAxisUsage.getCoordinateSystems(nDimensionIndex,nAxisIndex); - size_t nC; - for( nC=0; nC < aVCooSysList.size(); nC++) - { - ExplicitScaleData aExplicitScale( aVCooSysList[nC]->getExplicitScale( nDimensionIndex, nAxisIndex ) ); - ExplicitIncrementData aExplicitIncrement( aVCooSysList[nC]->getExplicitIncrement( nDimensionIndex, nAxisIndex ) ); - - Reference< chart2::XCoordinateSystem > xCooSys( aVCooSysList[nC]->getModel() ); - Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) ); - Reference< beans::XPropertySet > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, xCooSys ), uno::UNO_QUERY ); - - css::chart::ChartAxisPosition eCrossingMainAxisPos( css::chart::ChartAxisPosition_ZERO ); - if( xCrossingMainAxis.is() ) - { - xCrossingMainAxis->getPropertyValue("CrossoverPosition") >>= eCrossingMainAxisPos; - if( eCrossingMainAxisPos == css::chart::ChartAxisPosition_VALUE ) - { - double fValue = 0.0; - xCrossingMainAxis->getPropertyValue("CrossoverValue") >>= fValue; - aExplicitScale.Origin = fValue; - } - else if( eCrossingMainAxisPos == css::chart::ChartAxisPosition_ZERO ) - aExplicitScale.Origin = 0.0; - else if( eCrossingMainAxisPos == css::chart::ChartAxisPosition_START ) - aExplicitScale.Origin = aExplicitScale.Minimum; - else if( eCrossingMainAxisPos == css::chart::ChartAxisPosition_END ) - aExplicitScale.Origin = aExplicitScale.Maximum; - } - - aVCooSysList[nC]->setExplicitScaleAndIncrement( nDimensionIndex, nAxisIndex, aExplicitScale, aExplicitIncrement ); - } - } -} - -drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio() -{ - drawing::Direction3D aPreferredAspectRatio(1.0,1.0,1.0); - - //get a list of all preferred aspect ratios and combine them - //first with special demands wins (less or equal zero <-> arbitrary) - double fx, fy, fz; - fx = fy = fz = -1.0; - for( const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList ) - { - drawing::Direction3D aSingleRatio( aPlotter->getPreferredDiagramAspectRatio() ); - if( fx<0 && aSingleRatio.DirectionX>0 ) - fx = aSingleRatio.DirectionX; - - if( fy<0 && aSingleRatio.DirectionY>0 ) - { - if( fx>0 && aSingleRatio.DirectionX>0 ) - fy = fx*aSingleRatio.DirectionY/aSingleRatio.DirectionX; - else if( fz>0 && aSingleRatio.DirectionZ>0 ) - fy = fz*aSingleRatio.DirectionY/aSingleRatio.DirectionZ; - else - fy = aSingleRatio.DirectionY; - } - - if( fz<0 && aSingleRatio.DirectionZ>0 ) - { - if( fx>0 && aSingleRatio.DirectionX>0 ) - fz = fx*aSingleRatio.DirectionZ/aSingleRatio.DirectionX; - else if( fy>0 && aSingleRatio.DirectionY>0 ) - fz = fy*aSingleRatio.DirectionZ/aSingleRatio.DirectionY; - else - fz = aSingleRatio.DirectionZ; - } - - if( fx>0 && fy>0 && fz>0 ) - break; - } - aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz); - return aPreferredAspectRatio; -} - -} - struct CreateShapeParam2D { css::awt::Rectangle maRemainingSpace; @@ -1009,10 +133,10 @@ struct CreateShapeParam2D std::shared_ptr<VTitle> mpVTitleSecondX; std::shared_ptr<VTitle> mpVTitleSecondY; - css::uno::Reference<css::drawing::XShape> mxMarkHandles; - css::uno::Reference<css::drawing::XShape> mxPlotAreaWithAxes; + rtl::Reference<SvxShapeRect> mxMarkHandles; + rtl::Reference<SvxShapeRect> mxPlotAreaWithAxes; - css::uno::Reference<css::drawing::XShapes> mxDiagramWithAxesShapes; + rtl::Reference<SvxShapeGroup> mxDiagramWithAxesShapes; bool mbAutoPosTitleX; bool mbAutoPosTitleY; @@ -1032,21 +156,13 @@ struct CreateShapeParam2D mbUseFixedInnerSize(false) {} }; -const uno::Sequence<sal_Int8>& ExplicitValueProvider::getUnoTunnelId() -{ - return theExplicitValueProviderUnoTunnelId::get().getSeq(); -} + ChartView::ChartView( - uno::Reference<uno::XComponentContext> const & xContext, + uno::Reference<uno::XComponentContext> xContext, ChartModel& rModel) - : m_aMutex() - , m_xCC(xContext) + : m_xCC(std::move(xContext)) , mrChartModel(rModel) - , m_xShapeFactory() - , m_xDrawPage() - , m_pDrawModelWrapper() - , m_aListenerContainer( m_aMutex ) , m_bViewDirty(true) , m_bInViewUpdate(false) , m_bViewUpdatePending(false) @@ -1108,10 +224,10 @@ void ChartView::impl_deleteCoordinateSystems() // datatransfer::XTransferable namespace { -const OUString lcl_aGDIMetaFileMIMEType( - "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" ); -const OUString lcl_aGDIMetaFileMIMETypeHighContrast( - "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ); +constexpr OUString lcl_aGDIMetaFileMIMEType( + u"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""_ustr ); +constexpr OUString lcl_aGDIMetaFileMIMETypeHighContrast( + u"application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""_ustr ); } // anonymous namespace void ChartView::getMetaFile( const uno::Reference< io::XOutputStream >& xOutStream @@ -1123,41 +239,25 @@ void ChartView::getMetaFile( const uno::Reference< io::XOutputStream >& xOutStre // creating the graphic exporter uno::Reference< drawing::XGraphicExportFilter > xExporter = drawing::GraphicExportFilter::create( m_xCC ); - uno::Sequence< beans::PropertyValue > aProps(3); - aProps[0].Name = "FilterName"; - aProps[0].Value <<= OUString("SVM"); - - aProps[1].Name = "OutputStream"; - aProps[1].Value <<= xOutStream; - - uno::Sequence< beans::PropertyValue > aFilterData(8); - aFilterData[0].Name = "ExportOnlyBackground"; - aFilterData[0].Value <<= false; - aFilterData[1].Name = "HighContrast"; - aFilterData[1].Value <<= bUseHighContrast; - - aFilterData[2].Name = "Version"; - const sal_Int32 nVersion = SOFFICE_FILEFORMAT_50; - aFilterData[2].Value <<= nVersion; - - aFilterData[3].Name = "CurrentPage"; - aFilterData[3].Value <<= uno::Reference< uno::XInterface >( m_xDrawPage, uno::UNO_QUERY ); - - //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100% - aFilterData[4].Name = "ScaleXNumerator"; - aFilterData[4].Value <<= m_nScaleXNumerator; - aFilterData[5].Name = "ScaleXDenominator"; - aFilterData[5].Value <<= m_nScaleXDenominator; - aFilterData[6].Name = "ScaleYNumerator"; - aFilterData[6].Value <<= m_nScaleYNumerator; - aFilterData[7].Name = "ScaleYDenominator"; - aFilterData[7].Value <<= m_nScaleYDenominator; - - - aProps[2].Name = "FilterData"; - aProps[2].Value <<= aFilterData; - - xExporter->setSourceDocument( uno::Reference< lang::XComponent >( m_xDrawPage, uno::UNO_QUERY) ); + uno::Sequence< beans::PropertyValue > aFilterData{ + comphelper::makePropertyValue("ExportOnlyBackground", false), + comphelper::makePropertyValue("HighContrast", bUseHighContrast), + comphelper::makePropertyValue("Version", sal_Int32(SOFFICE_FILEFORMAT_50)), + comphelper::makePropertyValue("CurrentPage", uno::Reference< uno::XInterface >( static_cast<cppu::OWeakObject*>(m_xDrawPage.get()), uno::UNO_QUERY )), + //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100% + comphelper::makePropertyValue("ScaleXNumerator", m_nScaleXNumerator), + comphelper::makePropertyValue("ScaleXDenominator", m_nScaleXDenominator), + comphelper::makePropertyValue("ScaleYNumerator", m_nScaleYNumerator), + comphelper::makePropertyValue("ScaleYDenominator", m_nScaleYDenominator) + }; + + uno::Sequence< beans::PropertyValue > aProps{ + comphelper::makePropertyValue("FilterName", OUString("SVM")), + comphelper::makePropertyValue("OutputStream", xOutStream), + comphelper::makePropertyValue("FilterData", aFilterData) + }; + + xExporter->setSourceDocument( m_xDrawPage ); if( xExporter->filter( aProps ) ) { xOutStream->flush(); @@ -1178,41 +278,26 @@ uno::Any SAL_CALL ChartView::getTransferData( const datatransfer::DataFlavor& aF update(); SvMemoryStream aStream( 1024, 1024 ); - utl::OStreamWrapper* pStreamWrapper = new utl::OStreamWrapper( aStream ); + rtl::Reference<utl::OStreamWrapper> pStreamWrapper = new utl::OStreamWrapper( aStream ); - uno::Reference< io::XOutputStream > xOutStream( pStreamWrapper ); - uno::Reference< io::XInputStream > xInStream( pStreamWrapper ); - uno::Reference< io::XSeekable > xSeekable( pStreamWrapper ); + this->getMetaFile( pStreamWrapper, bHighContrastMetaFile ); - if( xOutStream.is() ) - { - this->getMetaFile( xOutStream, bHighContrastMetaFile ); - - if( xInStream.is() && xSeekable.is() ) - { - xSeekable->seek(0); - sal_Int32 nBytesToRead = xInStream->available(); - uno::Sequence< sal_Int8 > aSeq( nBytesToRead ); - xInStream->readBytes( aSeq, nBytesToRead); - aRet <<= aSeq; - xInStream->closeInput(); - } - } + pStreamWrapper->seek(0); + sal_Int32 nBytesToRead = pStreamWrapper->available(); + uno::Sequence< sal_Int8 > aSeq( nBytesToRead ); + pStreamWrapper->readBytes( aSeq, nBytesToRead); + aRet <<= aSeq; + pStreamWrapper->closeInput(); return aRet; } uno::Sequence< datatransfer::DataFlavor > SAL_CALL ChartView::getTransferDataFlavors() { - uno::Sequence< datatransfer::DataFlavor > aRet(2); - - aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType, - "GDIMetaFile", - cppu::UnoType<uno::Sequence< sal_Int8 >>::get() ); - aRet[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast, - "GDIMetaFile", - cppu::UnoType<uno::Sequence< sal_Int8 >>::get() ); - - return aRet; + return + { + { lcl_aGDIMetaFileMIMEType, "GDIMetaFile", cppu::UnoType<uno::Sequence< sal_Int8 >>::get() }, + { lcl_aGDIMetaFileMIMETypeHighContrast, "GDIMetaFile", cppu::UnoType<uno::Sequence< sal_Int8 >>::get() } + }; } sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor ) { @@ -1220,17 +305,6 @@ sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlav aFlavor.MimeType == lcl_aGDIMetaFileMIMETypeHighContrast ); } -// ____ XUnoTunnel ___ -::sal_Int64 SAL_CALL ChartView::getSomething( const uno::Sequence< ::sal_Int8 >& aIdentifier ) -{ - if( isUnoTunnelId<ExplicitValueProvider>(aIdentifier) ) - { - ExplicitValueProvider* pProvider = this; - return reinterpret_cast<sal_Int64>(pProvider); - } - return 0; -} - // lang::XServiceInfo OUString SAL_CALL ChartView::getImplementationName() @@ -1262,19 +336,19 @@ static ::basegfx::B3DHomMatrix createTransformationSceneToScreen( namespace { -bool lcl_IsPieOrDonut( const uno::Reference< XDiagram >& xDiagram ) +bool lcl_IsPieOrDonut( const rtl::Reference< Diagram >& xDiagram ) { //special treatment for pie charts //the size is checked after complete creation to get the datalabels into the given space //todo: this is just a workaround at the moment for pie and donut labels - return DiagramHelper::isPieOrDonutChart( xDiagram ); + return xDiagram->isPieOrDonutChart(); } void lcl_setDefaultWritingMode( const std::shared_ptr< DrawModelWrapper >& pDrawModelWrapper, ChartModel& rModel) { //get writing mode from parent document: - if( !SvtLanguageOptions().IsCTLFontEnabled() ) + if( !SvtCTLOptions::IsCTLFontEnabled() ) return; try @@ -1397,7 +471,7 @@ void lcl_setDefaultWritingMode( const std::shared_ptr< DrawModelWrapper >& pDraw if( nWritingMode != -1 && nWritingMode != text::WritingMode2::PAGE ) { if( pDrawModelWrapper ) - pDrawModelWrapper->GetItemPool().SetPoolDefaultItem(SvxFrameDirectionItem(static_cast<SvxFrameDirection>(nWritingMode), EE_PARA_WRITINGDIR) ); + pDrawModelWrapper->GetItemPool().SetUserDefaultItem(SvxFrameDirectionItem(static_cast<SvxFrameDirection>(nWritingMode), EE_PARA_WRITINGDIR) ); } } catch( const uno::Exception& ) @@ -1412,7 +486,7 @@ sal_Int16 lcl_getDefaultWritingModeFromPool( const std::shared_ptr<DrawModelWrap if(!pDrawModelWrapper) return nWritingMode; - const SfxPoolItem& rItem = pDrawModelWrapper->GetItemPool().GetDefaultItem(EE_PARA_WRITINGDIR); + const SfxPoolItem& rItem = pDrawModelWrapper->GetItemPool().GetUserOrPoolDefaultItem(EE_PARA_WRITINGDIR); nWritingMode = static_cast<sal_Int16>(static_cast<const SvxFrameDirectionItem&>(rItem).GetValue()); return nWritingMode; @@ -1425,11 +499,11 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D //return the used rectangle awt::Rectangle aUsedOuterRect(rParam.maRemainingSpace.X, rParam.maRemainingSpace.Y, 0, 0); - uno::Reference< XDiagram > xDiagram( mrChartModel.getFirstDiagram() ); + rtl::Reference< Diagram > xDiagram( mrChartModel.getFirstChartDiagram() ); if( !xDiagram.is()) return aUsedOuterRect; - sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + sal_Int32 nDimensionCount = xDiagram->getDimension(); if(!nDimensionCount) { //@todo handle mixed dimension @@ -1439,26 +513,23 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D basegfx::B2IRectangle aAvailableOuterRect = BaseGFXHelper::makeRectangle(rParam.maRemainingSpace); const std::vector< std::unique_ptr<VCoordinateSystem> >& rVCooSysList( rParam.mpSeriesPlotterContainer->getCooSysList() ); - SeriesPlottersType& rSeriesPlotterList = rParam.mpSeriesPlotterContainer->getSeriesPlotterList(); + auto& rSeriesPlotterList = rParam.mpSeriesPlotterContainer->getSeriesPlotterList(); //create VAxis, so they can give necessary information for automatic scaling - uno::Reference<chart2::XChartDocument> const xChartDoc(&mrChartModel); uno::Reference<util::XNumberFormatsSupplier> const xNumberFormatsSupplier( mrChartModel.getNumberFormatsSupplier()); - size_t nC = 0; - for( nC=0; nC < rVCooSysList.size(); nC++) + + for (auto& rpVCooSys : rVCooSysList) { - VCoordinateSystem* pVCooSys = rVCooSysList[nC].get(); - if(nDimensionCount==3) + if (nDimensionCount == 3) { - uno::Reference<beans::XPropertySet> xSceneProperties( xDiagram, uno::UNO_QUERY ); - CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xSceneProperties ) ); - CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xSceneProperties ) ); - CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xSceneProperties ) ); - pVCooSys->set3DWallPositions( eLeftWallPos, eBackWallPos, eBottomPos ); + CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xDiagram ) ); + CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xDiagram ) ); + CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xDiagram ) ); + rpVCooSys->set3DWallPositions( eLeftWallPos, eBackWallPos, eBottomPos ); } - - pVCooSys->createVAxisList(xChartDoc, rPageSize, rParam.maRemainingSpace, rParam.mbUseFixedInnerSize); + rpVCooSys->createVAxisList(&mrChartModel, rPageSize, rParam.maRemainingSpace, + rParam.mbUseFixedInnerSize, rSeriesPlotterList, getComponentContext()); } // - prepare list of all axis and how they are used @@ -1474,11 +545,11 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D drawing::Direction3D aPreferredAspectRatio = rParam.mpSeriesPlotterContainer->getPreferredAspectRatio(); - uno::Reference< drawing::XShapes > xSeriesTargetInFrontOfAxis; - uno::Reference< drawing::XShapes > xSeriesTargetBehindAxis; + rtl::Reference<SvxShapeGroupAnyD> xSeriesTargetInFrontOfAxis; + rtl::Reference<SvxShapeGroupAnyD> xSeriesTargetBehindAxis; VDiagram aVDiagram(xDiagram, aPreferredAspectRatio, nDimensionCount); {//create diagram - aVDiagram.init(rParam.mxDiagramWithAxesShapes, m_xShapeFactory); + aVDiagram.init(rParam.mxDiagramWithAxesShapes); aVDiagram.createShapes( awt::Point(rParam.maRemainingSpace.X, rParam.maRemainingSpace.Y), awt::Size(rParam.maRemainingSpace.Width, rParam.maRemainingSpace.Height)); @@ -1486,29 +557,28 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D xSeriesTargetInFrontOfAxis = aVDiagram.getCoordinateRegion(); // It is preferable to use full size than minimum for pie charts if (!rParam.mbUseFixedInnerSize) - aVDiagram.reduceToMimimumSize(); + aVDiagram.reduceToMinimumSize(); } - uno::Reference< drawing::XShapes > xTextTargetShapes = - ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory)->createGroup2D(rParam.mxDiagramWithAxesShapes); + rtl::Reference<SvxShapeGroup> xTextTargetShapes = + ShapeFactory::createGroup2D(rParam.mxDiagramWithAxesShapes); // - create axis and grids for all coordinate systems //init all coordinate systems - for( nC=0; nC < rVCooSysList.size(); nC++) + for (auto& rpVCooSys : rVCooSysList) { - VCoordinateSystem* pVCooSys = rVCooSysList[nC].get(); - pVCooSys->initPlottingTargets(xSeriesTargetInFrontOfAxis,xTextTargetShapes,m_xShapeFactory,xSeriesTargetBehindAxis); + rpVCooSys->initPlottingTargets(xSeriesTargetInFrontOfAxis, xTextTargetShapes, xSeriesTargetBehindAxis); - pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + rpVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) )); - pVCooSys->initVAxisInList(); + rpVCooSys->initVAxisInList(); } //calculate resulting size respecting axis label layout and fontscaling - uno::Reference< drawing::XShape > xBoundingShape(rParam.mxDiagramWithAxesShapes, uno::UNO_QUERY); + rtl::Reference<SvxShapeGroup> xBoundingShape(rParam.mxDiagramWithAxesShapes); ::basegfx::B2IRectangle aConsumedOuterRect; //use first coosys only so far; todo: calculate for more than one coosys if we have more in future @@ -1519,7 +589,7 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D VCoordinateSystem* pVCooSys = rVCooSysList[0].get(); pVCooSys->createMaximumAxesLabels(); - aConsumedOuterRect = ShapeFactory::getRectangleOfShape(xBoundingShape); + aConsumedOuterRect = ShapeFactory::getRectangleOfShape(*xBoundingShape); ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() ); if (!rParam.mbUseFixedInnerSize) aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect ); @@ -1536,12 +606,14 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D bool bLessSpaceConsumedThanExpected = false; { - aConsumedOuterRect = ShapeFactory::getRectangleOfShape(xBoundingShape); + aConsumedOuterRect = ShapeFactory::getRectangleOfShape(*xBoundingShape); if( aConsumedOuterRect.getMinX() > aAvailableOuterRect.getMinX() || aConsumedOuterRect.getMaxX() < aAvailableOuterRect.getMaxX() || aConsumedOuterRect.getMinY() > aAvailableOuterRect.getMinY() || aConsumedOuterRect.getMinY() < aAvailableOuterRect.getMaxY() ) + { bLessSpaceConsumedThanExpected = true; + } } if (bLessSpaceConsumedThanExpected && !rParam.mbUseFixedInnerSize) @@ -1549,20 +621,28 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D aVDiagram.adjustInnerSize( aConsumedOuterRect ); pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) )); + + // Need to re-adjust again if the labels have changed height because of + // text can break. Ideally this shouldn't be needed, but the chart height + // isn't readjusted otherwise. + pVCooSys->createAxesLabels(); + aConsumedOuterRect = ShapeFactory::getRectangleOfShape(*xBoundingShape); + aVDiagram.adjustInnerSize(aConsumedOuterRect); + pVCooSys->setTransformationSceneToScreen(B3DHomMatrixToHomogenMatrix( + createTransformationSceneToScreen(aVDiagram.getCurrentRectangle()))); + } pVCooSys->updatePositions();//todo: logically this belongs to the condition above, but it seems also to be necessary to give the axes group shapes the right bounding rects for hit test - probably caused by bug i106183 -> check again if fixed } //create axes and grids for the final size - for( nC=0; nC < rVCooSysList.size(); nC++) + for (auto& rpVCooSys : rVCooSysList) { - VCoordinateSystem* pVCooSys = rVCooSysList[nC].get(); - - pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + rpVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) )); - pVCooSys->createAxesShapes(); - pVCooSys->createGridShapes(); + rpVCooSys->createAxesShapes(); + rpVCooSys->createGridShapes(); } // - create data series for all charttypes @@ -1570,7 +650,7 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D for( const std::unique_ptr<VSeriesPlotter>& aPlotter : rSeriesPlotterList ) { VSeriesPlotter* pSeriesPlotter = aPlotter.get(); - uno::Reference< drawing::XShapes > xSeriesTarget; + rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget; if( pSeriesPlotter->WantToPlotInFrontOfAxisLine() ) xSeriesTarget = xSeriesTargetInFrontOfAxis; else @@ -1578,9 +658,9 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D xSeriesTarget = xSeriesTargetBehindAxis; OSL_ENSURE( !bIsPieOrDonut, "not implemented yet! - during a complete recreation this shape is destroyed so no series can be created anymore" ); } - pSeriesPlotter->initPlotter( xSeriesTarget,xTextTargetShapes,m_xShapeFactory,OUString() ); + pSeriesPlotter->initPlotter( xSeriesTarget,xTextTargetShapes,OUString() ); pSeriesPlotter->setPageReferenceSize( rPageSize ); - VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter ); + VCoordinateSystem* pVCooSys = SeriesPlotterContainer::getCooSysForPlotter( rVCooSysList, pSeriesPlotter ); if(nDimensionCount==2) pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() ); //better performance for big data @@ -1591,6 +671,11 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D } // Do not allow to move data labels in case of pie or donut chart, yet! pSeriesPlotter->setPieLabelsAllowToMove(!bIsPieOrDonut); + // use the pagesize as remaining space if we have a fixed inner size + if( rParam.mbUseFixedInnerSize ) + aAvailableOuterRect = BaseGFXHelper::makeRectangle(awt::Rectangle(0, 0, rPageSize.Width, rPageSize.Height)); + // set the available space for data labels to avoid moving out from chart area + pSeriesPlotter->setAvailableOuterRect(aAvailableOuterRect); pSeriesPlotter->createShapes(); m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped(); } @@ -1600,7 +685,7 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D { m_bPointsWereSkipped = false; - aConsumedOuterRect = ShapeFactory::getRectangleOfShape(xBoundingShape); + aConsumedOuterRect = ShapeFactory::getRectangleOfShape(*xBoundingShape); ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() ); if (!rParam.mbUseFixedInnerSize) aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect ); @@ -1616,17 +701,16 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D ShapeFactory::removeSubShapes( xTextTargetShapes ); //set new transformation - for( nC=0; nC < rVCooSysList.size(); nC++) + for (auto& rpVCooSys : rVCooSysList) { - VCoordinateSystem* pVCooSys = rVCooSysList[nC].get(); - pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( - createTransformationSceneToScreen( aNewInnerRect ) )); + auto aMatrix = createTransformationSceneToScreen(aNewInnerRect); + rpVCooSys->setTransformationSceneToScreen(B3DHomMatrixToHomogenMatrix(aMatrix)); } // - create data series for all charttypes for( std::unique_ptr<VSeriesPlotter>& aPlotter : rSeriesPlotterList ) { - VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, aPlotter.get() ); + VCoordinateSystem* pVCooSys = SeriesPlotterContainer::getCooSysForPlotter( rVCooSysList, aPlotter.get() ); if(nDimensionCount==2) aPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() ); // Now we can move data labels in case of pie or donut chart! @@ -1660,7 +744,7 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D else { ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle(); - m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() ); + m_aResultingDiagramRectangleExcludingAxes = BaseGFXHelper::toAwtRectangle(aConsumedInnerRect); } } else @@ -1670,7 +754,7 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D else { ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle(); - m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() ); + m_aResultingDiagramRectangleExcludingAxes = BaseGFXHelper::toAwtRectangle(aConsumedInnerRect); } } @@ -1680,8 +764,7 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D awt::Size aSize(rParam.maRemainingSpace.Width, rParam.maRemainingSpace.Height); bool bPosSizeExcludeAxesProperty = true; - uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY_THROW ); - xDiaProps->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxesProperty; + xDiagram->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxesProperty; if (rParam.mbUseFixedInnerSize || bPosSizeExcludeAxesProperty) { aPos = awt::Point( m_aResultingDiagramRectangleExcludingAxes.X, m_aResultingDiagramRectangleExcludingAxes.Y ); @@ -1695,7 +778,7 @@ awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D } bool ChartView::getExplicitValuesForAxis( - uno::Reference< XAxis > xAxis + rtl::Reference< Axis > xAxis , ExplicitScaleData& rExplicitScale , ExplicitIncrementData& rExplicitIncrement ) { @@ -1706,64 +789,66 @@ bool ChartView::getExplicitValuesForAxis( if(!xAxis.is()) return false; - uno::Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis, mrChartModel.getFirstDiagram() ) ); - const VCoordinateSystem* pVCooSys = findInCooSysList(m_aVCooSysList,xCooSys); + rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemOfAxis(xAxis, mrChartModel.getFirstChartDiagram() ); + const VCoordinateSystem* pVCooSys = SeriesPlotterContainer::findInCooSysList(m_aVCooSysList, xCooSys); if(!pVCooSys) return false; sal_Int32 nDimensionIndex=-1; sal_Int32 nAxisIndex=-1; - if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) ) + if( !AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) ) + return false; + + rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex); + rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex); + if( !rExplicitScale.m_bShiftedCategoryPosition ) + return true; + + //remove 'one' from max + if( rExplicitScale.AxisType == css::chart2::AxisType::DATE ) { - rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex); - rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex); - if( rExplicitScale.ShiftedCategoryPosition ) + Date aMaxDate(rExplicitScale.NullDate); aMaxDate.AddDays(::rtl::math::approxFloor(rExplicitScale.Maximum)); + //for explicit scales with shifted categories we need one interval more + switch( rExplicitScale.TimeResolution ) { - //remove 'one' from max - if( rExplicitScale.AxisType == css::chart2::AxisType::DATE ) - { - Date aMaxDate(rExplicitScale.NullDate); aMaxDate.AddDays(::rtl::math::approxFloor(rExplicitScale.Maximum)); - //for explicit scales with shifted categories we need one interval more - switch( rExplicitScale.TimeResolution ) - { - case css::chart::TimeUnit::DAY: - --aMaxDate; - break; - case css::chart::TimeUnit::MONTH: - aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,-1); - break; - case css::chart::TimeUnit::YEAR: - aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate,-1); - break; - } - rExplicitScale.Maximum = aMaxDate - rExplicitScale.NullDate; - } - else if( rExplicitScale.AxisType == css::chart2::AxisType::CATEGORY ) - rExplicitScale.Maximum -= 1.0; - else if( rExplicitScale.AxisType == css::chart2::AxisType::SERIES ) - rExplicitScale.Maximum -= 1.0; + case css::chart::TimeUnit::DAY: + --aMaxDate; + break; + case css::chart::TimeUnit::MONTH: + aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,-1); + break; + case css::chart::TimeUnit::YEAR: + aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate,-1); + break; } - return true; + rExplicitScale.Maximum = aMaxDate - rExplicitScale.NullDate; } - return false; + else if( rExplicitScale.AxisType == css::chart2::AxisType::CATEGORY ) + rExplicitScale.Maximum -= 1.0; + else if( rExplicitScale.AxisType == css::chart2::AxisType::SERIES ) + rExplicitScale.Maximum -= 1.0; + return true; } SdrPage* ChartView::getSdrPage() { - auto pSvxDrawPage = comphelper::getUnoTunnelImplementation<SvxDrawPage>(m_xDrawPage); - if(pSvxDrawPage) - return pSvxDrawPage->GetSdrPage(); + if(m_xDrawPage) + return m_xDrawPage->GetSdrPage(); return nullptr; } -uno::Reference< drawing::XShape > ChartView::getShapeForCID( const OUString& rObjectCID ) +rtl::Reference< SvxShape > ChartView::getShapeForCID( const OUString& rObjectCID ) { SolarMutexGuard aSolarGuard; SdrObject* pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, this->getSdrPage() ); - if( pObj ) - return uno::Reference< drawing::XShape >( pObj->getUnoShape(), uno::UNO_QUERY); - return nullptr; + if( !pObj ) + return nullptr; + + uno::Reference< drawing::XShape > xShape = pObj->getUnoShape(); + rtl::Reference<SvxShape> xShape2 = dynamic_cast<SvxShape*>(xShape.get()); + assert(xShape2 || !xShape); + return xShape2; } awt::Rectangle ChartView::getDiagramRectangleExcludingAxes() @@ -1777,7 +862,7 @@ awt::Rectangle ChartView::getRectangleOfObject( const OUString& rObjectCID, bool impl_updateView(); awt::Rectangle aRet; - uno::Reference< drawing::XShape > xShape( getShapeForCID(rObjectCID) ); + rtl::Reference< SvxShape > xShape = getShapeForCID(rObjectCID); if(xShape.is()) { //special handling for axis for old api: @@ -1786,21 +871,20 @@ awt::Rectangle ChartView::getRectangleOfObject( const OUString& rObjectCID, bool if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_DIAGRAM ) { SolarMutexGuard aSolarGuard; - SvxShape* pRoot = comphelper::getUnoTunnelImplementation<SvxShape>( xShape ); - if( pRoot ) + SdrObject* pRootSdrObject = xShape->GetSdrObject(); + if( pRootSdrObject ) { - SdrObject* pRootSdrObject = pRoot->GetSdrObject(); - if( pRootSdrObject ) + SdrObjList* pRootList = pRootSdrObject->GetSubList(); + if( pRootList ) { - SdrObjList* pRootList = pRootSdrObject->GetSubList(); - if( pRootList ) + OUString aShapeName = "MarkHandles"; + if( eObjectType == OBJECTTYPE_DIAGRAM ) + aShapeName = "PlotAreaIncludingAxes"; + SdrObject* pShape = DrawModelWrapper::getNamedSdrObject( aShapeName, pRootList ); + if( pShape ) { - OUString aShapeName = "MarkHandles"; - if( eObjectType == OBJECTTYPE_DIAGRAM ) - aShapeName = "PlotAreaIncludingAxes"; - SdrObject* pShape = DrawModelWrapper::getNamedSdrObject( aShapeName, pRootList ); - if( pShape ) - xShape.set( pShape->getUnoShape(), uno::UNO_QUERY); + xShape = dynamic_cast<SvxShape*>(pShape->getUnoShape().get()); + assert(xShape); } } } @@ -1812,15 +896,11 @@ awt::Rectangle ChartView::getRectangleOfObject( const OUString& rObjectCID, bool if( bSnapRect ) { //for rotated objects the shape size and position differs from the visible rectangle - SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( xShape ); - if( pShape ) + SdrObject* pSdrObject = xShape->GetSdrObject(); + if( pSdrObject ) { - SdrObject* pSdrObject = pShape->GetSdrObject(); - if( pSdrObject ) - { - tools::Rectangle aSnapRect( pSdrObject->GetSnapRect() ); - aRet = awt::Rectangle(aSnapRect.Left(),aSnapRect.Top(),aSnapRect.GetWidth(),aSnapRect.GetHeight()); - } + tools::Rectangle aSnapRect( pSdrObject->GetSnapRect() ); + aRet = awt::Rectangle(aSnapRect.Left(),aSnapRect.Top(),aSnapRect.GetWidth(),aSnapRect.GetHeight()); } } } @@ -1834,170 +914,31 @@ std::shared_ptr< DrawModelWrapper > ChartView::getDrawModelWrapper() namespace { -sal_Int32 lcl_getDiagramTitleSpace() -{ - return 200; //=0,2 cm spacing -} -bool lcl_getPropertySwapXAndYAxis( const uno::Reference< XDiagram >& xDiagram ) -{ - bool bSwapXAndY = false; - - uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); - if( xCooSysContainer.is() ) - { - uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); - if( aCooSysList.hasElements() ) - { - uno::Reference<beans::XPropertySet> xProp(aCooSysList[0], uno::UNO_QUERY ); - if( xProp.is()) try - { - xProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY; - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } - } - } - return bSwapXAndY; -} - -} -sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis( - const Reference< chart2::XAxis >& xAxis - , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem - , const Reference<chart2::XChartDocument>& xChartDoc) -{ - return AxisHelper::getExplicitNumberFormatKeyForAxis( xAxis, xCorrespondingCoordinateSystem, xChartDoc - , true /*bSearchForParallelAxisIfNothingIsFound*/ ); -} +constexpr double constPageLayoutDistancePercentage = 0.02; +constexpr sal_Int32 constPageLayoutFixedDistance = 350; -sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp ) +bool getAvailablePosAndSizeForDiagram( + CreateShapeParam2D& rParam, const awt::Size & rPageSize, rtl::Reference<Diagram> const& xDiagram) { - sal_Int32 nFormat=0; - if( !xSeriesOrPointProp.is() ) - return nFormat; - - try - { - xSeriesOrPointProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nFormat; - } - catch (const beans::UnknownPropertyException&) {} - - if(nFormat<0) - nFormat=0; - return nFormat; -} + uno::Reference<beans::XPropertySet> const& xProp(xDiagram); + rParam.mbUseFixedInnerSize = false; -sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel( - const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp, - const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier ) -{ - sal_Int32 nFormat=0; - if( !xSeriesOrPointProp.is() ) - return nFormat; - if( !(xSeriesOrPointProp->getPropertyValue("PercentageNumberFormat") >>= nFormat) ) - { - nFormat = DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier ); - } - if(nFormat<0) - nFormat=0; - return nFormat; -} + //@todo: we need a size dependent on the axis labels + rtl::Reference<ChartType> xChartType; + if (xDiagram) + xChartType = xDiagram->getChartTypeByIndex(0); -awt::Rectangle ExplicitValueProvider::AddSubtractAxisTitleSizes( - ChartModel& rModel - , const Reference< uno::XInterface >& xChartView - , const awt::Rectangle& rPositionAndSize, bool bSubtract ) -{ - awt::Rectangle aRet(rPositionAndSize); + sal_Int32 nXDistance = sal_Int32(rPageSize.Width * constPageLayoutDistancePercentage); + sal_Int32 nYDistance = sal_Int32(rPageSize.Height * constPageLayoutDistancePercentage); - //add axis title sizes to the diagram size - uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, rModel ) ); - uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, rModel ) ); - uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, rModel ) ); - uno::Reference< chart2::XTitle > xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, rModel ) ); - if( xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() || xSecondTitle_Width.is() ) + // Only pie chart uses fixed size margins + if (xChartType.is() && xChartType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_PIE) { - ExplicitValueProvider* pExplicitValueProvider = comphelper::getUnoTunnelImplementation<ExplicitValueProvider>(xChartView); - if( pExplicitValueProvider ) - { - //detect whether x axis points into x direction or not - if( lcl_getPropertySwapXAndYAxis( rModel.getFirstDiagram() ) ) - { - std::swap( xTitle_Height, xTitle_Width ); - std::swap( xSecondTitle_Height, xSecondTitle_Width ); - } - - sal_Int32 nTitleSpaceWidth = 0; - sal_Int32 nTitleSpaceHeight = 0; - sal_Int32 nSecondTitleSpaceWidth = 0; - sal_Int32 nSecondTitleSpaceHeight = 0; - - if( xTitle_Height.is() ) - { - OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, rModel ) ); - nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height; - if( nTitleSpaceHeight ) - nTitleSpaceHeight+=lcl_getDiagramTitleSpace(); - } - if( xTitle_Width.is() ) - { - OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, rModel ) ); - nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width; - if(nTitleSpaceWidth) - nTitleSpaceWidth+=lcl_getDiagramTitleSpace(); - } - if( xSecondTitle_Height.is() ) - { - OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, rModel ) ); - nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height; - if( nSecondTitleSpaceHeight ) - nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace(); - } - if( xSecondTitle_Width.is() ) - { - OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, rModel ) ); - nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width; - if( nSecondTitleSpaceWidth ) - nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace(); - } - if( bSubtract ) - { - aRet.X += nTitleSpaceWidth; - aRet.Y += nSecondTitleSpaceHeight; - aRet.Width -= (nTitleSpaceWidth + nSecondTitleSpaceWidth); - aRet.Height -= (nTitleSpaceHeight + nSecondTitleSpaceHeight); - } - else - { - - aRet.X -= nTitleSpaceWidth; - aRet.Y -= nSecondTitleSpaceHeight; - aRet.Width += nTitleSpaceWidth + nSecondTitleSpaceWidth; - aRet.Height += nTitleSpaceHeight + nSecondTitleSpaceHeight; - } - } + nXDistance = constPageLayoutFixedDistance; + nYDistance = constPageLayoutFixedDistance; } - return aRet; -} - -namespace { -double lcl_getPageLayoutDistancePercentage() -{ - return 0.02; -} - -bool getAvailablePosAndSizeForDiagram( - CreateShapeParam2D& rParam, const awt::Size & rPageSize, const uno::Reference< beans::XPropertySet >& xProp) -{ - rParam.mbUseFixedInnerSize = false; - - //@todo: we need a size dependent on the axis labels - sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage()); - sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage()); rParam.maRemainingSpace.X += nXDistance; rParam.maRemainingSpace.Width -= 2*nXDistance; rParam.maRemainingSpace.Y += nYDistance; @@ -2050,7 +991,7 @@ bool getAvailablePosAndSizeForDiagram( return true; } -enum TitleAlignment { ALIGN_LEFT, ALIGN_TOP, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_Z }; +enum class TitleAlignment { ALIGN_LEFT, ALIGN_TOP, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_Z }; void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment , awt::Rectangle const & rDiagramPlusAxesRect, const awt::Size & rPageSize ) @@ -2060,32 +1001,30 @@ void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment awt::Point aNewPosition(0,0); awt::Size aTitleSize = pVTitle->getFinalSize(); - sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage()); - sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage()); - switch( eAlignment ) + sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height * constPageLayoutDistancePercentage); + sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width * constPageLayoutDistancePercentage); + switch (eAlignment) { - case ALIGN_TOP: + case TitleAlignment::ALIGN_TOP: aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2 , rDiagramPlusAxesRect.Y - aTitleSize.Height/2 - nYDistance ); break; - case ALIGN_BOTTOM: + case TitleAlignment::ALIGN_BOTTOM: aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2 , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height + aTitleSize.Height/2 + nYDistance ); break; - case ALIGN_LEFT: + case TitleAlignment::ALIGN_LEFT: aNewPosition = awt::Point( rDiagramPlusAxesRect.X - aTitleSize.Width/2 - nXDistance , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 ); break; - case ALIGN_RIGHT: + case TitleAlignment::ALIGN_RIGHT: aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 ); break; - case ALIGN_Z: + case TitleAlignment::ALIGN_Z: aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height - aTitleSize.Height/2 ); break; - default: - break; } sal_Int32 nMaxY = rPageSize.Height - aTitleSize.Height/2; @@ -2105,8 +1044,7 @@ void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment } std::shared_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType - , const uno::Reference< drawing::XShapes>& xPageShapes - , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory + , const rtl::Reference<SvxShapeGroupAnyD>& xPageShapes , ChartModel& rModel , awt::Rectangle& rRemainingSpace , const awt::Size & rPageSize @@ -2116,7 +1054,7 @@ std::shared_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType std::shared_ptr<VTitle> apVTitle; // #i109336# Improve auto positioning in chart - double fPercentage = lcl_getPageLayoutDistancePercentage(); + double fPercentage = constPageLayoutDistancePercentage; sal_Int32 nXDistance = static_cast< sal_Int32 >( rPageSize.Width * fPercentage ); sal_Int32 nYDistance = static_cast< sal_Int32 >( rPageSize.Height * fPercentage ); if ( eType == TitleHelper::MAIN_TITLE ) @@ -2132,9 +1070,9 @@ std::shared_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType nXDistance = 450; // 1/100 mm } - uno::Reference< XTitle > xTitle( TitleHelper::getTitle( eType, rModel ) ); + rtl::Reference< Title > xTitle( TitleHelper::getTitle( eType, rModel ) ); OUString aCompleteString = TitleHelper::getCompleteString(xTitle); - if (aCompleteString.isEmpty()) + if (aCompleteString.isEmpty() || !VTitle::isVisible(xTitle)) return apVTitle; //create title @@ -2159,8 +1097,8 @@ std::shared_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType bYAxisTitle = true; } apVTitle = std::make_shared<VTitle>(xTitle); - OUString aCID = ObjectIdentifier::createClassifiedIdentifierForObject(xTitle, rModel); - apVTitle->init(xPageShapes, xShapeFactory, aCID); + OUString aCID = ObjectIdentifier::createClassifiedIdentifierForObject(xTitle, &rModel); + apVTitle->init(xPageShapes, aCID); apVTitle->createShapes(awt::Point(0, 0), rPageSize, aTextMaxWidth, bYAxisTitle); awt::Size aTitleUnrotatedSize = apVTitle->getUnrotatedSize(); awt::Size aTitleSize = apVTitle->getFinalSize(); @@ -2169,8 +1107,7 @@ std::shared_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType rbAutoPosition = true; awt::Point aNewPosition(0,0); chart2::RelativePosition aRelativePosition; - uno::Reference<beans::XPropertySet> xProp(xTitle, uno::UNO_QUERY); - if (xProp.is() && (xProp->getPropertyValue("RelativePosition") >>= aRelativePosition)) + if (xTitle.is() && (xTitle->getPropertyValue("RelativePosition") >>= aRelativePosition)) { rbAutoPosition = false; @@ -2187,23 +1124,23 @@ std::shared_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType { switch( eAlignment ) { - case ALIGN_TOP: + case TitleAlignment::ALIGN_TOP: aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2 , rRemainingSpace.Y + aTitleSize.Height/2 + nYDistance ); break; - case ALIGN_BOTTOM: + case TitleAlignment::ALIGN_BOTTOM: aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2 , rRemainingSpace.Y + rRemainingSpace.Height - aTitleSize.Height/2 - nYDistance ); break; - case ALIGN_LEFT: + case TitleAlignment::ALIGN_LEFT: aNewPosition = awt::Point( rRemainingSpace.X + aTitleSize.Width/2 + nXDistance , rRemainingSpace.Y + rRemainingSpace.Height/2 ); break; - case ALIGN_RIGHT: + case TitleAlignment::ALIGN_RIGHT: aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width - aTitleSize.Width/2 - nXDistance , rRemainingSpace.Y + rRemainingSpace.Height/2 ); break; - default: + case TitleAlignment::ALIGN_Z: break; } @@ -2213,47 +1150,46 @@ std::shared_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType //remaining space switch( eAlignment ) { - case ALIGN_TOP: + case TitleAlignment::ALIGN_TOP: // Push the remaining space down from top. rRemainingSpace.Y += ( aTitleSize.Height + nYDistance ); rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance ); break; - case ALIGN_BOTTOM: + case TitleAlignment::ALIGN_BOTTOM: // Push the remaining space up from bottom. rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance ); break; - case ALIGN_LEFT: + case TitleAlignment::ALIGN_LEFT: // Push the remaining space to the right from left edge. rRemainingSpace.X += ( aTitleSize.Width + nXDistance ); rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance ); break; - case ALIGN_RIGHT: + case TitleAlignment::ALIGN_RIGHT: // Push the remaining space to the left from right edge. rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance ); break; - default: + case TitleAlignment::ALIGN_Z: break; } return apVTitle; } -bool lcl_createLegend( const uno::Reference< XLegend > & xLegend - , const uno::Reference< drawing::XShapes>& xPageShapes - , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory +bool lcl_createLegend( const rtl::Reference< Legend > & xLegend + , const rtl::Reference<SvxShapeGroupAnyD>& xPageShapes , const uno::Reference< uno::XComponentContext > & xContext , awt::Rectangle & rRemainingSpace , const awt::Size & rPageSize , ChartModel& rModel - , const std::vector< LegendEntryProvider* >& rLegendEntryProviderList + , std::vector< LegendEntryProvider* >&& rLegendEntryProviderList , sal_Int16 nDefaultWritingMode ) { if (!VLegend::isVisible(xLegend)) return false; awt::Size rDefaultLegendSize; - VLegend aVLegend( xLegend, xContext, rLegendEntryProviderList, - xPageShapes, xShapeFactory, rModel); + VLegend aVLegend( xLegend, xContext, std::move(rLegendEntryProviderList), + xPageShapes, rModel); aVLegend.setDefaultWritingMode( nDefaultWritingMode ); aVLegend.createShapes( awt::Size( rRemainingSpace.Width, rRemainingSpace.Height ), rPageSize, rDefaultLegendSize ); @@ -2261,8 +1197,7 @@ bool lcl_createLegend( const uno::Reference< XLegend > & xLegend return true; } -void lcl_createButtons(const uno::Reference<drawing::XShapes>& xPageShapes, - const uno::Reference<lang::XMultiServiceFactory>& xShapeFactory, +void lcl_createButtons(const rtl::Reference<SvxShapeGroupAnyD>& xPageShapes, ChartModel& rModel, awt::Rectangle& rRemainingSpace) { @@ -2274,7 +1209,7 @@ void lcl_createButtons(const uno::Reference<drawing::XShapes>& xPageShapes, awt::Size aSize(4000, 700); // size of the button - long x = 0; + tools::Long x = 0; if (xPivotTableDataProvider->getPageFields().hasElements()) { @@ -2283,19 +1218,19 @@ void lcl_createButtons(const uno::Reference<drawing::XShapes>& xPageShapes, const css::uno::Sequence<chart2::data::PivotTableFieldEntry> aPivotFieldEntries = xPivotTableDataProvider->getPageFields(); for (css::chart2::data::PivotTableFieldEntry const & rPageFieldEntry : aPivotFieldEntries) { - std::unique_ptr<VButton> pButton(new VButton); - pButton->init(xPageShapes, xShapeFactory); + VButton aButton; + aButton.init(xPageShapes); awt::Point aNewPosition(rRemainingSpace.X + x + 100, rRemainingSpace.Y + 100); sal_Int32 nDimensionIndex = rPageFieldEntry.DimensionIndex; OUString aFieldOutputDescription = xPivotTableDataProvider->getFieldOutputDescription(nDimensionIndex); - pButton->setLabel(rPageFieldEntry.Name + " | " + aFieldOutputDescription); - pButton->setCID("FieldButton.Page." + OUString::number(nDimensionIndex)); - pButton->setPosition(aNewPosition); - pButton->setSize(aSize); + aButton.setLabel(rPageFieldEntry.Name + " | " + aFieldOutputDescription); + aButton.setCID("FieldButton.Page." + OUString::number(nDimensionIndex)); + aButton.setPosition(aNewPosition); + aButton.setSize(aSize); if (rPageFieldEntry.HasHiddenMembers) - pButton->setArrowColor(Color(0x0000FF)); + aButton.setArrowColor(Color(0x0000FF)); - pButton->createShapes(xModelPage); + aButton.createShapes(xModelPage); x += aSize.Width + 100; } rRemainingSpace.Y += (aSize.Height + 100 + 100); @@ -2311,23 +1246,22 @@ void lcl_createButtons(const uno::Reference<drawing::XShapes>& xPageShapes, const css::uno::Sequence<chart2::data::PivotTableFieldEntry> aPivotFieldEntries = xPivotTableDataProvider->getRowFields(); for (css::chart2::data::PivotTableFieldEntry const & rRowFieldEntry : aPivotFieldEntries) { - - std::unique_ptr<VButton> pButton(new VButton); - pButton->init(xPageShapes, xShapeFactory); + VButton aButton; + aButton.init(xPageShapes); awt::Point aNewPosition(rRemainingSpace.X + x + 100, rRemainingSpace.Y + rRemainingSpace.Height - aSize.Height - 100); - pButton->setLabel(rRowFieldEntry.Name); - pButton->setCID("FieldButton.Row." + OUString::number(rRowFieldEntry.DimensionIndex)); - pButton->setPosition(aNewPosition); - pButton->setSize(aSize); + aButton.setLabel(rRowFieldEntry.Name); + aButton.setCID("FieldButton.Row." + OUString::number(rRowFieldEntry.DimensionIndex)); + aButton.setPosition(aNewPosition); + aButton.setSize(aSize); if ( rRowFieldEntry.Name == "Data" ) { - pButton->setBGColor( Color(0x00F6F6F6) ); - pButton->showArrow( false ); + aButton.setBGColor( Color(0x00F6F6F6) ); + aButton.showArrow( false ); } else if (rRowFieldEntry.HasHiddenMembers) - pButton->setArrowColor(Color(0x0000FF)); - pButton->createShapes(xModelPage); + aButton.setArrowColor(Color(0x0000FF)); + aButton.createShapes(xModelPage); x += aSize.Width + 100; } rRemainingSpace.Height -= (aSize.Height + 100 + 100); @@ -2336,8 +1270,7 @@ void lcl_createButtons(const uno::Reference<drawing::XShapes>& xPageShapes, void formatPage( ChartModel& rChartModel , const awt::Size& rPageSize - , const uno::Reference< drawing::XShapes >& xTarget - , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory + , const rtl::Reference<SvxShapeGroupAnyD>& xTarget ) { try @@ -2346,22 +1279,18 @@ void formatPage( if( ! xModelPage.is()) return; - if( !xShapeFactory.is() ) - return; - //format page tPropertyNameValueMap aNameValueMap; PropertyMapper::getValueMap( aNameValueMap, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage ); - OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ); + OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) ); aNameValueMap.emplace( "Name", uno::Any( aCID ) ); //CID OUString tNameSequence aNames; tAnySequence aValues; PropertyMapper::getMultiPropertyListsFromValueMap( aNames, aValues, aNameValueMap ); - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); - pShapeFactory->createRectangle( + ShapeFactory::createRectangle( xTarget, rPageSize, awt::Point(0, 0), aNames, aValues); } catch( const uno::Exception & ) @@ -2370,33 +1299,26 @@ void formatPage( } } -void lcl_removeEmptyGroupShapes( const Reference< drawing::XShapes>& xParent ) +void lcl_removeEmptyGroupShapes( const SdrObject& rParent ) { - if(!xParent.is()) + SdrObjList* pObjList = rParent.getChildrenOfSdrObject(); + if (!pObjList || pObjList->GetObjCount() == 0) return; - Reference< drawing::XShapeGroup > xParentGroup( xParent, uno::UNO_QUERY ); - if( !xParentGroup.is() ) - { - Reference< drawing::XDrawPage > xPage( xParent, uno::UNO_QUERY ); - if( !xPage.is() ) - return; - } //iterate from back! - for( sal_Int32 nN = xParent->getCount(); nN--; ) + for(auto nIdx = static_cast<sal_Int32>(pObjList->GetObjCount() - 1); nIdx >= 0; --nIdx) { - uno::Any aAny = xParent->getByIndex( nN ); - Reference< drawing::XShapes> xShapes; - if( aAny >>= xShapes ) - lcl_removeEmptyGroupShapes( xShapes ); - if( xShapes.is() && xShapes->getCount()==0 ) + SdrObject* pChildSdrObject = pObjList->GetObj(nIdx); + SdrObjList* pChildObjList = pChildSdrObject->getChildrenOfSdrObject(); + if (!pChildObjList) + continue; + if (pChildObjList->GetObjCount() == 0) { //remove empty group shape - Reference< drawing::XShapeGroup > xGroup( xShapes, uno::UNO_QUERY ); - Reference< drawing::XShape > xShape( xShapes, uno::UNO_QUERY ); - if( xGroup.is() ) - xParent->remove( xShape ); + pObjList->NbcRemoveObject(nIdx); } + else + lcl_removeEmptyGroupShapes(*pChildSdrObject); } } @@ -2429,13 +1351,11 @@ void ChartView::impl_refreshAddIn() } } -static const char* envChartDummyFactory = getenv("CHART_DUMMY_FACTORY"); - void ChartView::createShapes() { SolarMutexGuard aSolarGuard; - osl::MutexGuard aTimedGuard(maTimeMutex); + std::unique_lock aTimedGuard(maTimeMutex); if(mrChartModel.isTimeBased()) { maTimeBased.bTimeBased = true; @@ -2457,13 +1377,15 @@ void ChartView::createShapes() awt::Size aPageSize = mrChartModel.getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); if(!mxRootShape.is()) - mxRootShape = pShapeFactory->getOrCreateChartRootShape( m_xDrawPage ); + mxRootShape = ShapeFactory::getOrCreateChartRootShape( m_xDrawPage ); - SdrPage* pPage = ChartView::getSdrPage(); - if(pPage) //it is necessary to use the implementation here as the uno page does not provide a propertyset + SdrPage* pPage = getSdrPage(); + + if (pPage) //it is necessary to use the implementation here as the uno page does not provide a propertyset + { pPage->SetSize(Size(aPageSize.Width,aPageSize.Height)); + } else { OSL_FAIL("could not set page size correctly"); @@ -2489,6 +1411,35 @@ void SAL_CALL ChartView::disposing( const lang::EventObject& /* rSource */ ) { } +namespace +{ +// Disables setting the chart's modified state, as well as its parent's (if exists). +// Painting a chart must not set these states. +struct ChartModelDisableSetModified +{ + ChartModel& mrChartModel; + SfxObjectShell* mpParentShell; + bool mbWasUnmodified; + ChartModelDisableSetModified(ChartModel& rChartModel) + : mrChartModel(rChartModel) + , mpParentShell(SfxObjectShell::GetShellFromComponent(rChartModel.getParent())) + , mbWasUnmodified(!rChartModel.isModified()) + { + if (mpParentShell && mpParentShell->IsEnableSetModified()) + mpParentShell->EnableSetModified(false); + else + mpParentShell = nullptr; + } + ~ChartModelDisableSetModified() + { + if (mbWasUnmodified && mrChartModel.isModified()) + mrChartModel.setModified(false); + if (mpParentShell) + mpParentShell->EnableSetModified(true); + } +}; +} + void ChartView::impl_updateView( bool bCheckLockedCtrler ) { if( !m_pDrawModelWrapper ) @@ -2503,7 +1454,7 @@ void ChartView::impl_updateView( bool bCheckLockedCtrler ) if (bCheckLockedCtrler && mrChartModel.hasControllersLocked()) return; - if( !(m_bViewDirty && !m_bInViewUpdate) ) + if( !m_bViewDirty || m_bInViewUpdate ) return; m_bInViewUpdate = true; @@ -2519,6 +1470,9 @@ void ChartView::impl_updateView( bool bCheckLockedCtrler ) m_pDrawModelWrapper->lockControllers(); } + // Rendering the chart must not set its (or its parent) modified status + ChartModelDisableSetModified dontSetModified(mrChartModel); + //create chart view { m_bViewDirty = false; @@ -2635,18 +1589,11 @@ void ChartView::impl_notifyModeChangeListener( const OUString& rNewMode ) { try { - ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer - .getContainer( cppu::UnoType<util::XModeChangeListener>::get()); - if( pIC ) + std::unique_lock g(m_aMutex); + if( m_aModeChangeListeners.getLength(g) ) { util::ModeChangeEvent aEvent( static_cast< uno::XWeak* >( this ), rNewMode ); - ::cppu::OInterfaceIteratorHelper aIt( *pIC ); - while( aIt.hasMoreElements() ) - { - uno::Reference< util::XModeChangeListener > xListener( aIt.next(), uno::UNO_QUERY ); - if( xListener.is() ) - xListener->modeChanged( aEvent ); - } + m_aModeChangeListeners.notifyEach( g, &css::util::XModeChangeListener::modeChanged, aEvent); } } catch( const uno::Exception& ) @@ -2659,13 +1606,13 @@ void ChartView::impl_notifyModeChangeListener( const OUString& rNewMode ) void SAL_CALL ChartView::addModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener ) { - m_aListenerContainer.addInterface( - cppu::UnoType<util::XModeChangeListener>::get(), xListener ); + std::unique_lock g(m_aMutex); + m_aModeChangeListeners.addInterface(g, xListener ); } void SAL_CALL ChartView::removeModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener ) { - m_aListenerContainer.removeInterface( - cppu::UnoType<util::XModeChangeListener>::get(), xListener ); + std::unique_lock g(m_aMutex); + m_aModeChangeListeners.removeInterface(g, xListener ); } void SAL_CALL ChartView::addModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ ) { @@ -2734,20 +1681,16 @@ void SAL_CALL ChartView::setPropertyValue( const OUString& rPropertyName if( ! (rValue >>= aZoomFactors) ) throw lang::IllegalArgumentException( "Property 'ZoomFactors' requires value of type Sequence< PropertyValue >", nullptr, 0 ); - sal_Int32 nFilterArgs = aZoomFactors.getLength(); - beans::PropertyValue* pDataValues = aZoomFactors.getArray(); - while( nFilterArgs-- ) + for (auto& propval : aZoomFactors) { - if ( pDataValues->Name == "ScaleXNumerator" ) - pDataValues->Value >>= m_nScaleXNumerator; - else if ( pDataValues->Name == "ScaleXDenominator" ) - pDataValues->Value >>= m_nScaleXDenominator; - else if ( pDataValues->Name == "ScaleYNumerator" ) - pDataValues->Value >>= m_nScaleYNumerator; - else if ( pDataValues->Name == "ScaleYDenominator" ) - pDataValues->Value >>= m_nScaleYDenominator; - - pDataValues++; + if (propval.Name == "ScaleXNumerator") + propval.Value >>= m_nScaleXNumerator; + else if (propval.Name == "ScaleXDenominator") + propval.Value >>= m_nScaleXDenominator; + else if (propval.Name == "ScaleYNumerator") + propval.Value >>= m_nScaleYNumerator; + else if (propval.Name == "ScaleYDenominator") + propval.Value >>= m_nScaleYDenominator; } } else if( rPropertyName == "SdrViewIsInEditMode" ) @@ -2859,38 +1802,40 @@ Reference< uno::XInterface > ChartView::createInstanceWithArguments( const OUStr uno::Sequence< OUString > ChartView::getAvailableServiceNames() { - uno::Sequence< OUString > aServiceNames( 6 ); - - aServiceNames[0] = "com.sun.star.drawing.DashTable"; - aServiceNames[1] = "com.sun.star.drawing.GradientTable"; - aServiceNames[2] = "com.sun.star.drawing.HatchTable"; - aServiceNames[3] = "com.sun.star.drawing.BitmapTable"; - aServiceNames[4] = "com.sun.star.drawing.TransparencyGradientTable"; - aServiceNames[5] = "com.sun.star.drawing.MarkerTable"; + uno::Sequence< OUString > aServiceNames{ "com.sun.star.drawing.DashTable", + "com.sun.star.drawing.GradientTable", + "com.sun.star.drawing.HatchTable", + "com.sun.star.drawing.BitmapTable", + "com.sun.star.drawing.TransparencyGradientTable", + "com.sun.star.drawing.MarkerTable" }; return aServiceNames; } -OUString ChartView::dump() +OUString ChartView::dump(OUString const & kind) { + if (kind.isEmpty()) { + return comphelper::dumpXmlToString([this](auto writer) { return dumpAsXml(writer); }); + } + + // kind == "shapes": #if HAVE_FEATURE_DESKTOP // Used for unit tests and in chartcontroller only, no need to drag in this when cross-compiling // for non-desktop impl_updateView(); - uno::Reference< drawing::XShapes > xShapes( m_xDrawPage, uno::UNO_QUERY_THROW ); - sal_Int32 n = xShapes->getCount(); + sal_Int32 n = m_xDrawPage->getCount(); OUStringBuffer aBuffer; for(sal_Int32 i = 0; i < n; ++i) { - uno::Reference< drawing::XShapes > xShape(xShapes->getByIndex(i), uno::UNO_QUERY); + uno::Reference< drawing::XShapes > xShape(m_xDrawPage->getByIndex(i), uno::UNO_QUERY); if(xShape.is()) { - OUString aString = XShapeDumper::dump(mxRootShape); + OUString aString = XShapeDumper::dump(uno::Reference<drawing::XShapes>(mxRootShape)); aBuffer.append(aString); } else { - uno::Reference< drawing::XShape > xSingleShape(xShapes->getByIndex(i), uno::UNO_QUERY); + uno::Reference< drawing::XShape > xSingleShape(m_xDrawPage->getByIndex(i), uno::UNO_QUERY); if(!xSingleShape.is()) continue; OUString aString = XShapeDumper::dump(xSingleShape); @@ -2907,20 +1852,20 @@ OUString ChartView::dump() void ChartView::dumpAsXml(xmlTextWriterPtr pWriter) const { - xmlTextWriterStartElement(pWriter, BAD_CAST("ChartView")); - xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ChartView")); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); if (m_pDrawModelWrapper) { m_pDrawModelWrapper->dumpAsXml(pWriter); } - xmlTextWriterEndElement(pWriter); + (void)xmlTextWriterEndElement(pWriter); } void ChartView::setViewDirty() { - osl::MutexGuard aGuard(maTimeMutex); + std::unique_lock aGuard(maTimeMutex); m_bViewDirty = true; } @@ -2932,11 +1877,9 @@ IMPL_LINK_NOARG(ChartView, UpdateTimeBased, Timer *, void) void ChartView::createShapes2D( const awt::Size& rPageSize ) { - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); - // todo: it would be nicer to just pass the page m_xDrawPage and format it, // but the draw page does not support XPropertySet - formatPage( mrChartModel, rPageSize, mxRootShape, m_xShapeFactory ); + formatPage( mrChartModel, rPageSize, mxRootShape ); CreateShapeParam2D aParam; aParam.maRemainingSpace.X = 0; @@ -2945,40 +1888,39 @@ void ChartView::createShapes2D( const awt::Size& rPageSize ) aParam.maRemainingSpace.Height = rPageSize.Height; //create the group shape for diagram and axes first to have title and legends on top of it - uno::Reference< XDiagram > xDiagram( mrChartModel.getFirstDiagram() ); - uno::Reference< beans::XPropertySet > xProp(xDiagram, uno::UNO_QUERY); + rtl::Reference< Diagram > xDiagram( mrChartModel.getFirstChartDiagram() ); bool bHasRelativeSize = false; - if( xProp.is() && xProp->getPropertyValue("RelativeSize").hasValue() ) + if( xDiagram.is() && xDiagram->getPropertyValue("RelativeSize").hasValue() ) bHasRelativeSize = true; OUString aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) ) );//todo: other index if more than one diagram is possible - uno::Reference< drawing::XShapes > xDiagramPlusAxesPlusMarkHandlesGroup_Shapes( - pShapeFactory->createGroup2D(mxRootShape,aDiagramCID) ); + rtl::Reference<SvxShapeGroup> xDiagramPlusAxesPlusMarkHandlesGroup_Shapes = + ShapeFactory::createGroup2D(mxRootShape,aDiagramCID); - aParam.mxMarkHandles = pShapeFactory->createInvisibleRectangle( + aParam.mxMarkHandles = ShapeFactory::createInvisibleRectangle( xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0)); ShapeFactory::setShapeName(aParam.mxMarkHandles, "MarkHandles"); - aParam.mxPlotAreaWithAxes = pShapeFactory->createInvisibleRectangle( + aParam.mxPlotAreaWithAxes = ShapeFactory::createInvisibleRectangle( xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0, 0)); ShapeFactory::setShapeName(aParam.mxPlotAreaWithAxes, "PlotAreaIncludingAxes"); - aParam.mxDiagramWithAxesShapes = pShapeFactory->createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes); + aParam.mxDiagramWithAxesShapes = ShapeFactory::createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes); bool bAutoPositionDummy = true; // create buttons - lcl_createButtons(mxRootShape, m_xShapeFactory, mrChartModel, aParam.maRemainingSpace); + lcl_createButtons(mxRootShape, mrChartModel, aParam.maRemainingSpace); lcl_createTitle( - TitleHelper::MAIN_TITLE, mxRootShape, m_xShapeFactory, mrChartModel, - aParam.maRemainingSpace, rPageSize, ALIGN_TOP, bAutoPositionDummy); + TitleHelper::MAIN_TITLE, mxRootShape, mrChartModel, + aParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_TOP, bAutoPositionDummy); if (!bHasRelativeSize && (aParam.maRemainingSpace.Width <= 0 || aParam.maRemainingSpace.Height <= 0)) return; lcl_createTitle( - TitleHelper::SUB_TITLE, mxRootShape, m_xShapeFactory, mrChartModel, - aParam.maRemainingSpace, rPageSize, ALIGN_TOP, bAutoPositionDummy ); + TitleHelper::SUB_TITLE, mxRootShape, mrChartModel, + aParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_TOP, bAutoPositionDummy ); if (!bHasRelativeSize && (aParam.maRemainingSpace.Width <= 0 || aParam.maRemainingSpace.Height <= 0)) return; @@ -2986,7 +1928,7 @@ void ChartView::createShapes2D( const awt::Size& rPageSize ) aParam.mpSeriesPlotterContainer->initializeCooSysAndSeriesPlotter( mrChartModel ); if(maTimeBased.bTimeBased && maTimeBased.nFrame != 0) { - SeriesPlottersType& rSeriesPlotter = aParam.mpSeriesPlotterContainer->getSeriesPlotterList(); + auto& rSeriesPlotter = aParam.mpSeriesPlotterContainer->getSeriesPlotterList(); size_t n = rSeriesPlotter.size(); for(size_t i = 0; i < n; ++i) { @@ -3003,7 +1945,7 @@ void ChartView::createShapes2D( const awt::Size& rPageSize ) } lcl_createLegend( - LegendHelper::getLegend( mrChartModel ), mxRootShape, m_xShapeFactory, m_xCC, + LegendHelper::getLegend( mrChartModel ), mxRootShape, getComponentContext(), aParam.maRemainingSpace, rPageSize, mrChartModel, aParam.mpSeriesPlotterContainer->getLegendEntryProviderList(), lcl_getDefaultWritingModeFromPool( m_pDrawModelWrapper ) ); @@ -3014,9 +1956,9 @@ void ChartView::createShapes2D( const awt::Size& rPageSize ) return; bool bDummy = false; - bool bIsVertical = DiagramHelper::getVertical(xDiagram, bDummy, bDummy); + bool bIsVertical = xDiagram && xDiagram->getVertical(bDummy, bDummy); - if (getAvailablePosAndSizeForDiagram(aParam, rPageSize, xProp)) + if (getAvailablePosAndSizeForDiagram(aParam, rPageSize, xDiagram)) { awt::Rectangle aUsedOuterRect = impl_createDiagramAndContent(aParam, rPageSize); @@ -3029,24 +1971,24 @@ void ChartView::createShapes2D( const awt::Size& rPageSize ) //correct axis title position awt::Rectangle aDiagramPlusAxesRect( aUsedOuterRect ); if (aParam.mbAutoPosTitleX) - changePositionOfAxisTitle(aParam.mpVTitleX.get(), ALIGN_BOTTOM, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleX.get(), TitleAlignment::ALIGN_BOTTOM, aDiagramPlusAxesRect, rPageSize); if (aParam.mbAutoPosTitleY) - changePositionOfAxisTitle(aParam.mpVTitleY.get(), ALIGN_LEFT, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleY.get(), TitleAlignment::ALIGN_LEFT, aDiagramPlusAxesRect, rPageSize); if (aParam.mbAutoPosTitleZ) - changePositionOfAxisTitle(aParam.mpVTitleZ.get(), ALIGN_Z, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleZ.get(), TitleAlignment::ALIGN_Z, aDiagramPlusAxesRect, rPageSize); if (aParam.mbAutoPosSecondTitleX) - changePositionOfAxisTitle(aParam.mpVTitleSecondX.get(), bIsVertical? ALIGN_RIGHT : ALIGN_TOP, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleSecondX.get(), bIsVertical? TitleAlignment::ALIGN_RIGHT : TitleAlignment::ALIGN_TOP, aDiagramPlusAxesRect, rPageSize); if (aParam.mbAutoPosSecondTitleY) - changePositionOfAxisTitle(aParam.mpVTitleSecondY.get(), bIsVertical? ALIGN_TOP : ALIGN_RIGHT, aDiagramPlusAxesRect, rPageSize); + changePositionOfAxisTitle(aParam.mpVTitleSecondY.get(), bIsVertical? TitleAlignment::ALIGN_TOP : TitleAlignment::ALIGN_RIGHT, aDiagramPlusAxesRect, rPageSize); } //cleanup: remove all empty group shapes to avoid grey border lines: - lcl_removeEmptyGroupShapes( mxRootShape ); + lcl_removeEmptyGroupShapes( *mxRootShape->GetSdrObject() ); if(maTimeBased.bTimeBased && maTimeBased.nFrame % 60 == 0) { // create copy of the data for next frame - SeriesPlottersType& rSeriesPlotter = aParam.mpSeriesPlotterContainer->getSeriesPlotterList(); + auto& rSeriesPlotter = aParam.mpSeriesPlotterContainer->getSeriesPlotterList(); size_t n = rSeriesPlotter.size(); maTimeBased.m_aDataSeriesList.clear(); maTimeBased.m_aDataSeriesList.resize(n); @@ -3075,41 +2017,46 @@ void ChartView::createShapes2D( const awt::Size& rPageSize ) bool ChartView::createAxisTitleShapes2D( CreateShapeParam2D& rParam, const css::awt::Size& rPageSize, bool bHasRelativeSize ) { - uno::Reference<XDiagram> xDiagram = mrChartModel.getFirstDiagram(); + rtl::Reference<Diagram> xDiagram = mrChartModel.getFirstChartDiagram(); - Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); - sal_Int32 nDimension = DiagramHelper::getDimension( xDiagram ); + rtl::Reference< ChartType > xChartType; + sal_Int32 nDimension = 0; + if (xDiagram) + { + xChartType = xDiagram->getChartTypeByIndex( 0 ); + nDimension = xDiagram->getDimension(); + } if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 0 ) ) - rParam.mpVTitleX = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, mxRootShape, m_xShapeFactory, mrChartModel - , rParam.maRemainingSpace, rPageSize, ALIGN_BOTTOM, rParam.mbAutoPosTitleX ); + rParam.mpVTitleX = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, mxRootShape, mrChartModel + , rParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_BOTTOM, rParam.mbAutoPosTitleX ); if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)) return false; if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 1 ) ) - rParam.mpVTitleY = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, mxRootShape, m_xShapeFactory, mrChartModel - , rParam.maRemainingSpace, rPageSize, ALIGN_LEFT, rParam.mbAutoPosTitleY ); + rParam.mpVTitleY = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, mxRootShape, mrChartModel + , rParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_LEFT, rParam.mbAutoPosTitleY ); if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)) return false; if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 2 ) ) - rParam.mpVTitleZ = lcl_createTitle( TitleHelper::Z_AXIS_TITLE, mxRootShape, m_xShapeFactory, mrChartModel - , rParam.maRemainingSpace, rPageSize, ALIGN_RIGHT, rParam.mbAutoPosTitleZ ); + rParam.mpVTitleZ = lcl_createTitle( TitleHelper::Z_AXIS_TITLE, mxRootShape, mrChartModel + , rParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_RIGHT, rParam.mbAutoPosTitleZ ); if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)) return false; bool bDummy = false; - bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy ); + bool bIsVertical = xDiagram && xDiagram->getVertical( bDummy, bDummy ); if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension ) ) - rParam.mpVTitleSecondX = lcl_createTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, mxRootShape, m_xShapeFactory, mrChartModel - , rParam.maRemainingSpace, rPageSize, bIsVertical? ALIGN_RIGHT : ALIGN_TOP, rParam.mbAutoPosSecondTitleX ); + rParam.mpVTitleSecondX = lcl_createTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, mxRootShape, mrChartModel + , rParam.maRemainingSpace, rPageSize, bIsVertical? TitleAlignment::ALIGN_RIGHT : TitleAlignment::ALIGN_TOP, rParam.mbAutoPosSecondTitleX ); if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)) return false; if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension ) ) - rParam.mpVTitleSecondY = lcl_createTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, mxRootShape, m_xShapeFactory, mrChartModel - , rParam.maRemainingSpace, rPageSize, bIsVertical? ALIGN_TOP : ALIGN_RIGHT, rParam.mbAutoPosSecondTitleY ); + rParam.mpVTitleSecondY = lcl_createTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, mxRootShape, mrChartModel + , rParam.maRemainingSpace, rPageSize, bIsVertical? TitleAlignment::ALIGN_TOP : TitleAlignment::ALIGN_RIGHT, rParam.mbAutoPosSecondTitleY ); if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)) return false; @@ -3122,7 +2069,7 @@ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_chart2_ChartView_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence<css::uno::Any> const &) { - ::chart::ChartModel *pChartModel = new ::chart::ChartModel(context); + rtl::Reference<::chart::ChartModel> pChartModel = new ::chart::ChartModel(context); return cppu::acquire(new ::chart::ChartView(context, *pChartModel)); } diff --git a/chart2/source/view/main/Clipping.cxx b/chart2/source/view/main/Clipping.cxx index 463b74975a91..713e88c26bd0 100644 --- a/chart2/source/view/main/Clipping.cxx +++ b/chart2/source/view/main/Clipping.cxx @@ -21,6 +21,7 @@ #include <CommonConverters.hxx> #include <BaseGFXHelper.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <com/sun/star/drawing/Position3D.hpp> @@ -204,6 +205,47 @@ void lcl_addPointToPoly( drawing::PolyPolygonShape3D& rPoly rResultPointCount[nPolygonIndex]=nNewResultPointCount; } +void lcl_addPointToPoly( std::vector<std::vector<css::drawing::Position3D>>& rPoly + , const drawing::Position3D& rPos + , sal_Int32 nPolygonIndex + , std::vector< sal_Int32 >& rResultPointCount + , sal_Int32 nReservePointCount ) +{ + if(nPolygonIndex<0) + { + OSL_FAIL( "The polygon index needs to be > 0"); + nPolygonIndex=0; + } + + //make sure that we have enough polygons + if(o3tl::make_unsigned(nPolygonIndex) >= rPoly.size() ) + { + rPoly.resize(nPolygonIndex+1); + rResultPointCount.resize(nPolygonIndex+1,0); + } + + std::vector<css::drawing::Position3D>* pOuterSequence = &rPoly[nPolygonIndex]; + + sal_Int32 nNewResultPointCount = rResultPointCount[nPolygonIndex]+1; + sal_Int32 nSeqLength = pOuterSequence->size(); + + if( nSeqLength <= nNewResultPointCount ) + { + sal_Int32 nReallocLength = nReservePointCount > SAL_MAX_INT16 ? round_up_nearest_pow2(nNewResultPointCount) * 2 : nReservePointCount; + if( nNewResultPointCount > nReallocLength ) + { + nReallocLength = nNewResultPointCount; + OSL_FAIL("this should not be the case to avoid performance problems"); + } + pOuterSequence->resize(nReallocLength); + } + + css::drawing::Position3D* pInnerSequence = pOuterSequence->data(); + + pInnerSequence[nNewResultPointCount-1] = rPos; + rResultPointCount[nPolygonIndex]=nNewResultPointCount; +} + }//end anonymous namespace void Clipping::clipPolygonAtRectangle( const drawing::PolyPolygonShape3D& rPolygon @@ -295,6 +337,89 @@ void Clipping::clipPolygonAtRectangle( const drawing::PolyPolygonShape3D& rPolyg } } +void Clipping::clipPolygonAtRectangle( const std::vector<std::vector<css::drawing::Position3D>>& rPolygon + , const B2DRectangle& rRectangle + , std::vector<std::vector<css::drawing::Position3D>>& aResult + , bool bSplitPiecesToDifferentPolygons ) +{ + aResult.clear(); + + if(rPolygon.empty()) + return; + + //need clipping?: + { + ::basegfx::B3DRange a3DRange( BaseGFXHelper::getBoundVolume( rPolygon ) ); + ::basegfx::B2DRange a2DRange( a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY() ); + if( rRectangle.isInside( a2DRange ) ) + { + aResult = rPolygon; + return; + } + else + { + a2DRange.intersect( rRectangle ); + if( a2DRange.isEmpty() ) + return; + } + } + + std::vector< sal_Int32 > aResultPointCount;//per polygon index + + //apply clipping: + drawing::Position3D aFrom; + drawing::Position3D aTo; + + sal_Int32 nNewPolyIndex = 0; + sal_Int32 nOldPolyCount = rPolygon.size(); + for(sal_Int32 nOldPolyIndex=0; nOldPolyIndex<nOldPolyCount; nOldPolyIndex++, nNewPolyIndex++ ) + { + sal_Int32 nOldPointCount = rPolygon[nOldPolyIndex].size(); + + // set last point to a position outside the rectangle, such that the first + // time lcl_clip2d returns true, the comparison to last will always yield false + drawing::Position3D aLast(rRectangle.getMinX()-1.0,rRectangle.getMinY()-1.0, 0.0 ); + + for(sal_Int32 nOldPoint=1; nOldPoint<nOldPointCount; nOldPoint++) + { + aFrom = getPointFromPoly(rPolygon,nOldPoint-1,nOldPolyIndex); + aTo = getPointFromPoly(rPolygon,nOldPoint,nOldPolyIndex); + if( lcl_clip2d_(aFrom, aTo, rRectangle) ) + { + // compose a Polygon of as many consecutive points as possible + if(aFrom == aLast) + { + if( aTo != aFrom ) + { + lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount ); + } + } + else + { + if( bSplitPiecesToDifferentPolygons && nOldPoint!=1 ) + { + if( nNewPolyIndex < static_cast<sal_Int32>(aResult.size()) + && aResultPointCount[nNewPolyIndex]>0 ) + nNewPolyIndex++; + } + lcl_addPointToPoly( aResult, aFrom, nNewPolyIndex, aResultPointCount, nOldPointCount ); + if( aTo != aFrom ) + lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount ); + } + aLast = aTo; + } + } + } + //free unused space + for( sal_Int32 nPolygonIndex = aResultPointCount.size(); nPolygonIndex--; ) + { + std::vector<css::drawing::Position3D>* pOuterSequence = &aResult[nPolygonIndex]; + + sal_Int32 nUsedPointCount = aResultPointCount[nPolygonIndex]; + pOuterSequence->resize(nUsedPointCount); + } +} + } //namespace chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/DataPointSymbolSupplier.cxx b/chart2/source/view/main/DataPointSymbolSupplier.cxx index 7f446139ac22..ff7f8370ac32 100644 --- a/chart2/source/view/main/DataPointSymbolSupplier.cxx +++ b/chart2/source/view/main/DataPointSymbolSupplier.cxx @@ -25,19 +25,16 @@ namespace chart { using namespace ::com::sun::star; -uno::Reference< drawing::XShapes > DataPointSymbolSupplier::create2DSymbolList( - const uno::Reference< lang::XMultiServiceFactory >& xShapeFactory - , const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference< SvxShapeGroup > DataPointSymbolSupplier::create2DSymbolList( + const rtl::Reference<SvxDrawPage>& xTarget , const drawing::Direction3D& rSize ) { - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); - uno::Reference< drawing::XShapes > xGroupShapes = - pShapeFactory->createGroup2D( xTarget ); + rtl::Reference< SvxShapeGroup > xGroupShapes = ShapeFactory::createGroup2D( xTarget ); drawing::Position3D aPos(0,0,0); for(sal_Int32 nS=0;nS<ShapeFactory::getSymbolCount();nS++) { - pShapeFactory->createSymbol2D( xGroupShapes, aPos, rSize, nS, 0, 0 ); + ShapeFactory::createSymbol2D( xGroupShapes, aPos, rSize, nS, 0, 0 ); } return xGroupShapes; } diff --git a/chart2/source/view/main/DataTableView.cxx b/chart2/source/view/main/DataTableView.cxx new file mode 100644 index 000000000000..eacd91a6a651 --- /dev/null +++ b/chart2/source/view/main/DataTableView.cxx @@ -0,0 +1,559 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <DataTableView.hxx> +#include <VSeriesPlotter.hxx> +#include <ShapeFactory.hxx> +#include <ExplicitCategoriesProvider.hxx> +#include <ChartModel.hxx> +#include <ObjectIdentifier.hxx> + +#include <svx/svdotable.hxx> + +#include <com/sun/star/table/BorderLine.hpp> +#include <com/sun/star/table/BorderLine2.hpp> +#include <com/sun/star/table/TableBorder.hpp> +#include <com/sun/star/table/BorderLineStyle.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> +#include <com/sun/star/drawing/TextHorizontalAdjust.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/util/XBroadcaster.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <o3tl/unit_conversion.hxx> + +using namespace css; + +namespace chart +{ +namespace +{ +void setTopCell(uno::Reference<beans::XPropertySet>& xPropertySet) +{ + xPropertySet->setPropertyValue("FillColor", uno::Any(Color(0xFFFFFF))); + xPropertySet->setPropertyValue("TextVerticalAdjust", uno::Any(drawing::TextVerticalAdjust_TOP)); + xPropertySet->setPropertyValue("ParaAdjust", uno::Any(style::ParagraphAdjust_CENTER)); + + table::BorderLine2 aBorderLine; + aBorderLine.LineWidth = 0; + aBorderLine.Color = 0x000000; + + xPropertySet->setPropertyValue("TopBorder", uno::Any(aBorderLine)); + xPropertySet->setPropertyValue("LeftBorder", uno::Any(aBorderLine)); +} + +void copyProperty(uno::Reference<beans::XPropertySet>& xOut, + uno::Reference<beans::XPropertySet>& xIn, OUString const& sPropertyName) +{ + xOut->setPropertyValue(sPropertyName, xIn->getPropertyValue(sPropertyName)); +} + +uno::Reference<text::XTextRange> getFirstParagraph(uno::Reference<text::XText> const& xText) +{ + uno::Reference<text::XTextRange> xParagraph; + uno::Reference<container::XEnumerationAccess> xEnumAccess(xText, uno::UNO_QUERY); + if (!xEnumAccess.is()) + return xParagraph; + uno::Reference<container::XEnumeration> xEnumeration(xEnumAccess->createEnumeration()); + xParagraph.set(xEnumeration->nextElement(), uno::UNO_QUERY); + return xParagraph; +} + +uno::Reference<beans::XPropertySet> +getFirstParagraphProperties(uno::Reference<text::XText> const& xText) +{ + uno::Reference<beans::XPropertySet> xPropertySet; + auto xParagraph = getFirstParagraph(xText); + if (!xParagraph.is()) + return xPropertySet; + xPropertySet.set(xParagraph, uno::UNO_QUERY); + return xPropertySet; +} + +} // end anonymous namespace + +DataTableView::DataTableView( + rtl::Reference<::chart::ChartModel> const& xChartModel, + rtl::Reference<DataTable> const& rDataTableModel, + css::uno::Reference<css::uno::XComponentContext> const& rComponentContext, + bool bAlignAxisValuesWithColumns) + : m_xChartModel(xChartModel) + , m_xDataTableModel(rDataTableModel) + , m_xComponentContext(rComponentContext) + , m_bAlignAxisValuesWithColumns(bAlignAxisValuesWithColumns) +{ + uno::Reference<beans::XPropertySet> xPropertySet(m_xDataTableModel); + m_aLineProperties.initFromPropertySet(xPropertySet); +} + +void DataTableView::setCellCharAndParagraphProperties( + uno::Reference<beans::XPropertySet>& xPropertySet) +{ + uno::Reference<beans::XPropertySet> xDataTableProperties(m_xDataTableModel); + + copyProperty(xPropertySet, xDataTableProperties, "CharColor"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontFamily"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontFamilyAsian"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontFamilyComplex"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontCharSet"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontCharSetAsian"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontCharSetComplex"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontName"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontNameAsian"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontNameComplex"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontPitch"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontPitchAsian"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontPitchComplex"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontStyleName"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontStyleNameAsian"); + copyProperty(xPropertySet, xDataTableProperties, "CharFontStyleNameComplex"); + + copyProperty(xPropertySet, xDataTableProperties, "CharHeight"); + copyProperty(xPropertySet, xDataTableProperties, "CharHeightAsian"); + copyProperty(xPropertySet, xDataTableProperties, "CharHeightComplex"); + copyProperty(xPropertySet, xDataTableProperties, "CharKerning"); + copyProperty(xPropertySet, xDataTableProperties, "CharLocale"); + copyProperty(xPropertySet, xDataTableProperties, "CharLocaleAsian"); + copyProperty(xPropertySet, xDataTableProperties, "CharLocaleComplex"); + copyProperty(xPropertySet, xDataTableProperties, "CharPosture"); + copyProperty(xPropertySet, xDataTableProperties, "CharPostureAsian"); + copyProperty(xPropertySet, xDataTableProperties, "CharPostureComplex"); + copyProperty(xPropertySet, xDataTableProperties, "CharRelief"); + copyProperty(xPropertySet, xDataTableProperties, "CharShadowed"); + copyProperty(xPropertySet, xDataTableProperties, "CharStrikeout"); + copyProperty(xPropertySet, xDataTableProperties, "CharUnderline"); + copyProperty(xPropertySet, xDataTableProperties, "CharUnderlineColor"); + copyProperty(xPropertySet, xDataTableProperties, "CharUnderlineHasColor"); + copyProperty(xPropertySet, xDataTableProperties, "CharOverline"); + copyProperty(xPropertySet, xDataTableProperties, "CharOverlineColor"); + copyProperty(xPropertySet, xDataTableProperties, "CharOverlineHasColor"); + copyProperty(xPropertySet, xDataTableProperties, "CharWeight"); + copyProperty(xPropertySet, xDataTableProperties, "CharWeightAsian"); + copyProperty(xPropertySet, xDataTableProperties, "CharWeightComplex"); + copyProperty(xPropertySet, xDataTableProperties, "CharWordMode"); + + drawing::FillStyle eFillStyle = drawing::FillStyle_NONE; + xDataTableProperties->getPropertyValue("FillStyle") >>= eFillStyle; + if (eFillStyle == drawing::FillStyle_SOLID) + { + sal_Int32 aColor = 0; + if (xDataTableProperties->getPropertyValue("FillColor") >>= aColor) + xPropertySet->setPropertyValue("CharBackColor", uno::Any(aColor)); + } + + xPropertySet->setPropertyValue("ParaAdjust", uno::Any(style::ParagraphAdjust_CENTER)); +} + +void DataTableView::setCellProperties(css::uno::Reference<beans::XPropertySet>& xPropertySet, + bool bLeft, bool bTop, bool bRight, bool bBottom) +{ + xPropertySet->setPropertyValue("FillColor", uno::Any(Color(0xFFFFFF))); + + uno::Reference<beans::XPropertySet> xDataTableProperties(m_xDataTableModel); + float fFontHeight = 0.0; + xDataTableProperties->getPropertyValue("CharHeight") >>= fFontHeight; + fFontHeight = o3tl::convert(fFontHeight, o3tl::Length::pt, o3tl::Length::mm100); + sal_Int32 nXDistance = std::round(fFontHeight * 0.18f); + sal_Int32 nYDistance = std::round(fFontHeight * 0.30f); + + xPropertySet->setPropertyValue("TextLeftDistance", uno::Any(nXDistance)); + xPropertySet->setPropertyValue("TextRightDistance", uno::Any(nXDistance)); + xPropertySet->setPropertyValue("TextUpperDistance", uno::Any(nYDistance)); + xPropertySet->setPropertyValue("TextLowerDistance", uno::Any(nYDistance)); + + xPropertySet->setPropertyValue("TextVerticalAdjust", uno::Any(drawing::TextVerticalAdjust_TOP)); + + drawing::LineStyle eStyle = drawing::LineStyle_NONE; + m_aLineProperties.LineStyle >>= eStyle; + + if (eStyle != drawing::LineStyle_NONE) + { + table::BorderLine2 aBorderLine; + + sal_Int32 nWidth = 0; + m_aLineProperties.Width >>= nWidth; + aBorderLine.LineWidth = o3tl::convert(nWidth, o3tl::Length::mm100, o3tl::Length::twip); + + sal_Int32 nColor = 0; + m_aLineProperties.Color >>= nColor; + aBorderLine.Color = nColor; + + aBorderLine.LineStyle = table::BorderLineStyle::SOLID; + + if (eStyle == drawing::LineStyle_DASH) + { + OUString aDashName; + m_aLineProperties.DashName >>= aDashName; + if (!aDashName.isEmpty() && m_xChartModel.is()) + { + uno::Reference<container::XNameContainer> xDashTable( + m_xChartModel->createInstance("com.sun.star.drawing.DashTable"), + uno::UNO_QUERY); + if (xDashTable.is() && xDashTable->hasByName(aDashName)) + { + drawing::LineDash aLineDash; + xDashTable->getByName(aDashName) >>= aLineDash; + + if (aLineDash.Dots == 0 && aLineDash.Dashes == 0) + aBorderLine.LineStyle = table::BorderLineStyle::SOLID; + else if (aLineDash.Dots == 1 && aLineDash.Dashes == 0) + aBorderLine.LineStyle = table::BorderLineStyle::DOTTED; + else if (aLineDash.Dots == 0 && aLineDash.Dashes == 1) + aBorderLine.LineStyle = table::BorderLineStyle::DASHED; + else if (aLineDash.Dots == 1 && aLineDash.Dashes == 1) + aBorderLine.LineStyle = table::BorderLineStyle::DASH_DOT; + else if (aLineDash.Dots == 2 && aLineDash.Dashes == 1) + aBorderLine.LineStyle = table::BorderLineStyle::DASH_DOT_DOT; + else + aBorderLine.LineStyle = table::BorderLineStyle::DASHED; + } + } + } + + if (bLeft) + xPropertySet->setPropertyValue("LeftBorder", uno::Any(aBorderLine)); + if (bTop) + xPropertySet->setPropertyValue("TopBorder", uno::Any(aBorderLine)); + if (bRight) + xPropertySet->setPropertyValue("RightBorder", uno::Any(aBorderLine)); + if (bBottom) + xPropertySet->setPropertyValue("BottomBorder", uno::Any(aBorderLine)); + } +} + +void DataTableView::createShapes(basegfx::B2DVector const& rStart, basegfx::B2DVector const& rEnd, + sal_Int32 nAxisStepWidth) +{ + if (!m_xTarget.is()) + return; + + // Remove shapes first before we add the new ones + ShapeFactory::removeSubShapes(m_xTarget); + auto sParticle = ObjectIdentifier::createParticleForDataTable(m_xChartModel); + auto sCID = ObjectIdentifier::createClassifiedIdentifierForParticle(sParticle); + m_xTableShape = ShapeFactory::createTable(m_xTarget, sCID); + + // calculate the table size + auto rDelta = rEnd - rStart; + sal_Int32 nTableSize = basegfx::fround(rDelta.getX()); + m_xTableShape->setSize({ nTableSize, 0 }); + + try + { + m_xTableShape->getPropertyValue("Model") >>= m_xTable; + } + catch (const uno::Exception&) + { + return; + } + + if (!m_xTable.is()) + return; + + uno::Reference<util::XBroadcaster> xBroadcaster(m_xTable, uno::UNO_QUERY); + + if (!xBroadcaster.is()) + return; + + xBroadcaster->lockBroadcasts(); + + auto* pTableObject = static_cast<sdr::table::SdrTableObj*>(m_xTableShape->GetSdrObject()); + + // get the data table properties from the model + bool bHBorder = false; + bool bVBorder = false; + bool bOutline = false; + bool bKeys = false; + + std::vector<ViewLegendSymbol> aSymbols; + + m_xDataTableModel->getPropertyValue("HBorder") >>= bHBorder; + m_xDataTableModel->getPropertyValue("VBorder") >>= bVBorder; + m_xDataTableModel->getPropertyValue("Outline") >>= bOutline; + m_xDataTableModel->getPropertyValue("Keys") >>= bKeys; + + // set the data table row and column size + sal_Int32 nColumnCount = m_aXValues.size(); + uno::Reference<table::XTableColumns> xTableColumns = m_xTable->getColumns(); + xTableColumns->insertByIndex(0, nColumnCount); + + sal_Int32 nRowCount = m_aDataSeriesNames.size(); + uno::Reference<table::XTableRows> xTableRows = m_xTable->getRows(); + xTableRows->insertByIndex(0, nRowCount); + + sal_Int32 nColumnWidth = 0.0; + + // If we don't align, we have to calculate the column width ourselves, + // otherwise the column width is taken from the x-axis width + if (m_bAlignAxisValuesWithColumns) + nColumnWidth = nAxisStepWidth; + else + nColumnWidth = double(nTableSize) / nColumnCount; + + // Setup empty top-left cell + { + uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(0, 0); + uno::Reference<beans::XPropertySet> xPropertySet(xCell, uno::UNO_QUERY); + if (xPropertySet.is()) + { + setTopCell(xPropertySet); + } + } + + sal_Int32 nColumn; + sal_Int32 nRow; + + // COLUMN HEADER + + nColumn = 1; + for (auto const& rString : m_aXValues) + { + uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(nColumn, 0); + uno::Reference<beans::XPropertySet> xPropertySet(xCell, uno::UNO_QUERY); + uno::Reference<text::XTextRange> xCellTextRange(xCell, uno::UNO_QUERY); + if (xCellTextRange.is()) + { + auto xText = xCellTextRange->getText(); + xText->insertString(xText->getStart(), rString, false); + auto xTextPropertySet = getFirstParagraphProperties(xText); + if (!xTextPropertySet.is()) + continue; + + bool bLeft + = (bOutline && nColumn == 1) || (bVBorder && nColumn > 1 && nColumn < nColumnCount); + bool bRight = (bOutline && nColumn == nColumnCount) + || (bVBorder && nColumn > 1 && nColumn < nColumnCount); + setCellCharAndParagraphProperties(xTextPropertySet); + setCellProperties(xPropertySet, bLeft, bOutline, bRight, bOutline); + } + nColumn++; + } + + // ROW HEADER + // Prepare keys (symbols) + sal_Int32 nMaxSymbolWidth = 0; + constexpr const sal_Int32 constSymbolMargin = 100; // 1mm + if (bKeys) + { + uno::Reference<beans::XPropertySet> xDataTableProperties(m_xDataTableModel); + float fFontHeight = 0.0; + xDataTableProperties->getPropertyValue("CharHeight") >>= fFontHeight; + fFontHeight = o3tl::convert(fFontHeight, o3tl::Length::pt, o3tl::Length::mm100); + + sal_Int32 nSymbolHeight = sal_Int32(fFontHeight * 0.6); + sal_Int32 nSymbolWidth = nSymbolHeight; + + for (VSeriesPlotter* pSeriesPlotter : m_pSeriesPlotterList) + { + if (pSeriesPlotter) + { + awt::Size aCurrentRatio = pSeriesPlotter->getPreferredLegendKeyAspectRatio(); + sal_Int32 nCurrentWidth = aCurrentRatio.Width; + if (aCurrentRatio.Height > 0) + nCurrentWidth = nSymbolHeight * aCurrentRatio.Width / aCurrentRatio.Height; + nSymbolWidth = std::max(nSymbolWidth, nCurrentWidth); + } + } + nMaxSymbolWidth = nSymbolWidth; + + for (VSeriesPlotter* pSeriesPlotter : m_pSeriesPlotterList) + { + if (pSeriesPlotter) + { + awt::Size aSize(nSymbolWidth, nSymbolHeight); + std::vector<ViewLegendSymbol> aNewEntries + = pSeriesPlotter->createSymbols(aSize, m_xTarget, m_xComponentContext); + + for (auto const& rSymbol : aNewEntries) + aSymbols.push_back(rSymbol); + } + } + } + + nRow = 1; + for (auto const& rSeriesName : m_aDataSeriesNames) + { + uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(0, nRow); + uno::Reference<beans::XPropertySet> xCellPropertySet(xCell, uno::UNO_QUERY); + uno::Reference<text::XTextRange> xCellTextRange(xCell, uno::UNO_QUERY); + if (xCellTextRange.is()) + { + bool bTop = (bOutline && nRow == 1) || (bHBorder && nRow > 1 && nRow < nRowCount); + bool bBottom + = (bOutline && nRow == nRowCount) || (bHBorder && nRow > 1 && nRow < nRowCount); + + auto xText = xCellTextRange->getText(); + xText->insertString(xText->getStart(), rSeriesName, false); + auto xTextPropertySet = getFirstParagraphProperties(xText); + if (!xTextPropertySet.is()) + continue; + setCellCharAndParagraphProperties(xTextPropertySet); + setCellProperties(xCellPropertySet, bOutline, bTop, bOutline, bBottom); + + xCellPropertySet->setPropertyValue("ParaAdjust", uno::Any(style::ParagraphAdjust_LEFT)); + if (bKeys) + { + xCellPropertySet->setPropertyValue( + "ParaLeftMargin", uno::Any(nMaxSymbolWidth + sal_Int32(2 * constSymbolMargin))); + } + } + nRow++; + } + + // TABLE + nRow = 1; + for (auto const& rSeries : m_pDataSeriesValues) + { + nColumn = 1; + for (auto const& rValue : rSeries) + { + uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(nColumn, nRow); + uno::Reference<beans::XPropertySet> xCellPropertySet(xCell, uno::UNO_QUERY); + uno::Reference<text::XTextRange> xCellTextRange(xCell, uno::UNO_QUERY); + if (xCellTextRange.is()) + { + auto xText = xCellTextRange->getText(); + xText->insertString(xText->getStart(), rValue, false); + auto xTextPropertySet = getFirstParagraphProperties(xText); + if (!xTextPropertySet.is()) + continue; + + bool bLeft = false; + bool bTop = false; + bool bRight = false; + bool bBottom = false; + + if (nColumn > 1 && bVBorder) + bLeft = true; + + if (nRow > 1 && bHBorder) + bTop = true; + + if (nRow == nRowCount && bOutline) + bBottom = true; + + if (nColumn == nColumnCount && bOutline) + bRight = true; + + setCellCharAndParagraphProperties(xTextPropertySet); + setCellProperties(xCellPropertySet, bLeft, bTop, bRight, bBottom); + } + nColumn++; + } + nRow++; + } + + // force recalculation of column widths in the table shape + xBroadcaster->unlockBroadcasts(); + pTableObject->DistributeColumns(0, nColumnCount, true, true); + + xBroadcaster->lockBroadcasts(); + + // reposition the data table + changePosition(basegfx::fround(rStart.getX()), basegfx::fround(rStart.getY())); + + sal_Int32 nTableX = m_xTableShape->getPosition().X; + sal_Int32 nTableY = m_xTableShape->getPosition().Y; + + uno::Reference<beans::XPropertySet> xPropertySet(xTableColumns->getByIndex(0), uno::UNO_QUERY); + + for (sal_Int32 i = 1; i < xTableColumns->getCount(); ++i) + { + xPropertySet.set(xTableColumns->getByIndex(i), uno::UNO_QUERY); + xPropertySet->setPropertyValue("Width", uno::Any(nColumnWidth)); + } + + // force recalculation of row heights in the table shape + xBroadcaster->unlockBroadcasts(); + pTableObject->DistributeRows(0, nRowCount, true, true); + + if (bKeys) + { + sal_Int32 nTotalHeight = 0; + for (sal_Int32 i = 0; i < xTableRows->getCount(); i++) + { + sal_Int32 nSymbolIndex = i - 1; + if (nSymbolIndex < sal_Int32(aSymbols.size())) + { + xPropertySet.set(xTableRows->getByIndex(i), uno::UNO_QUERY); + sal_Int32 nHeight = 0; + xPropertySet->getPropertyValue("Height") >>= nHeight; + if (i > 0) + { + auto& rSymbol = aSymbols[nSymbolIndex].xSymbol; + sal_Int32 nSymbolHeight = rSymbol->getSize().Height; + sal_Int32 nSymbolY + = basegfx::fround(double(nHeight) / 2.0 - double(nSymbolHeight) / 2.0); + rSymbol->setPosition( + { nTableX + constSymbolMargin, nTableY + nTotalHeight + nSymbolY }); + } + nTotalHeight += nHeight; + } + } + } +} + +void DataTableView::changePosition(sal_Int32 x, sal_Int32 y) +{ + if (!m_xTable.is()) + return; + + uno::Reference<table::XTableColumns> xTableColumns = m_xTable->getColumns(); + uno::Reference<beans::XPropertySet> xPropertySet(xTableColumns->getByIndex(0), uno::UNO_QUERY); + + sal_Int32 nWidth = 0; + xPropertySet->getPropertyValue("Width") >>= nWidth; + + m_xTarget->setPosition({ x - nWidth, y }); +} + +void DataTableView::initializeShapes(const rtl::Reference<SvxShapeGroupAnyD>& xTarget) +{ + m_xTarget = xTarget; +} + +void DataTableView::initializeValues( + std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList) +{ + for (auto& rSeriesPlotter : rSeriesPlotterList) + { + m_pSeriesPlotterList.push_back(rSeriesPlotter.get()); + + for (auto const& rCategory : + rSeriesPlotter->getExplicitCategoriesProvider()->getSimpleCategories()) + { + m_aXValues.push_back(rCategory); + } + + for (auto const& rString : rSeriesPlotter->getAllSeriesNames()) + { + m_aDataSeriesNames.push_back(rString); + } + + for (VDataSeries* pSeries : rSeriesPlotter->getAllSeries()) + { + auto& rValues = m_pDataSeriesValues.emplace_back(); + for (int i = 0; i < pSeries->getTotalPointCount(); i++) + { + double nValue = pSeries->getYValue(i); + rValues.push_back(rSeriesPlotter->getLabelTextForValue(*pSeries, i, nValue, false)); + } + } + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/DrawModelWrapper.cxx b/chart2/source/view/main/DrawModelWrapper.cxx index 1d9bc2914ce2..71cd8d699cf7 100644 --- a/chart2/source/view/main/DrawModelWrapper.cxx +++ b/chart2/source/view/main/DrawModelWrapper.cxx @@ -23,19 +23,16 @@ #include <ObjectIdentifier.hxx> #include <svx/unomodel.hxx> #include <svl/itempool.hxx> -#include <svl/eitem.hxx> -#include <editeng/eeitem.hxx> -#include <svx/svx3ditems.hxx> #include <svx/objfac3d.hxx> #include <svx/svdpage.hxx> +#include <svx/svx3ditems.hxx> #include <svx/xtable.hxx> #include <svx/svdoutl.hxx> #include <editeng/unolingu.hxx> #include <vcl/svapp.hxx> #include <vcl/virdev.hxx> #include <libxml/xmlwriter.h> - -#include <com/sun/star/container/XChild.hpp> +#include <osl/diagnose.h> namespace com::sun::star::linguistic2 { class XHyphenator; } namespace com::sun::star::linguistic2 { class XSpellChecker1; } @@ -48,31 +45,19 @@ namespace chart DrawModelWrapper::DrawModelWrapper() : SdrModel() - , m_pChartItemPool(nullptr) { - m_pChartItemPool = ChartItemPool::CreateChartItemPool(); + m_xChartItemPool = ChartItemPool::CreateChartItemPool(); - SetScaleUnit(MapUnit::Map100thMM); - SetScaleFraction(Fraction(1, 1)); SetDefaultFontHeight(423); // 12pt SfxItemPool* pMasterPool = &GetItemPool(); pMasterPool->SetDefaultMetric(MapUnit::Map100thMM); - pMasterPool->SetPoolDefaultItem(SfxBoolItem(EE_PARA_HYPHENATE, true) ); - pMasterPool->SetPoolDefaultItem(makeSvx3DPercentDiagonalItem (5)); + pMasterPool->SetUserDefaultItem(SfxBoolItem(EE_PARA_HYPHENATE, true) ); + pMasterPool->SetUserDefaultItem(makeSvx3DPercentDiagonalItem (5)); - SfxItemPool* pPool = pMasterPool; // append chart pool to end of pool chain - for (;;) - { - SfxItemPool* pSecondary = pPool->GetSecondaryPool(); - if (!pSecondary) - break; - - pPool = pSecondary; - } - pPool->SetSecondaryPool(m_pChartItemPool); - pMasterPool->FreezeIdRanges(); + pMasterPool->GetLastPoolInChain()->SetSecondaryPool(m_xChartItemPool.get()); + SetTextDefaults(); //this factory needs to be created before first use of 3D scenes once upon an office runtime //@todo in future this should be done by drawing engine itself on demand @@ -115,35 +100,36 @@ DrawModelWrapper::DrawModelWrapper() DrawModelWrapper::~DrawModelWrapper() { + // normally call from ~SdrModel, but do it here explicitly before we clear m_xChartItemPool + implDtorClearModel(); + //remove m_pChartItemPool from pool chain - if(m_pChartItemPool) + if (m_xChartItemPool) { SfxItemPool* pPool = &GetItemPool(); for (;;) { SfxItemPool* pSecondary = pPool->GetSecondaryPool(); - if(pSecondary == m_pChartItemPool) + if(pSecondary == m_xChartItemPool.get()) { pPool->SetSecondaryPool (nullptr); break; } pPool = pSecondary; } - SfxItemPool::Free(m_pChartItemPool); + m_xChartItemPool.clear(); } m_pRefDevice.disposeAndClear(); } -uno::Reference< uno::XInterface > DrawModelWrapper::createUnoModel() +uno::Reference< frame::XModel > DrawModelWrapper::createUnoModel() { - uno::Reference< lang::XComponent > xComponent = new SvxUnoDrawingModel( this ); //tell Andreas Schluens if SvxUnoDrawingModel is not needed anymore -> remove export from svx to avoid link problems in writer - return uno::Reference< uno::XInterface >::query( xComponent ); + return new SvxUnoDrawingModel( this ); //tell Andreas Schluens if SvxUnoDrawingModel is not needed anymore -> remove export from svx to avoid link problems in writer } uno::Reference< frame::XModel > DrawModelWrapper::getUnoModel() { - uno::Reference< uno::XInterface > xI = SdrModel::getUnoModel(); - return uno::Reference<frame::XModel>::query( xI ); + return SdrModel::getUnoModel(); } SdrModel& DrawModelWrapper::getSdrModel() @@ -157,7 +143,7 @@ uno::Reference< lang::XMultiServiceFactory > DrawModelWrapper::getShapeFactory() return xShapeFactory; } -uno::Reference< drawing::XDrawPage > const & DrawModelWrapper::getMainDrawPage() +const rtl::Reference<SvxDrawPage> & DrawModelWrapper::getMainDrawPage() { if (m_xMainDrawPage.is()) return m_xMainDrawPage; @@ -172,12 +158,16 @@ uno::Reference< drawing::XDrawPage > const & DrawModelWrapper::getMainDrawPage() { // Take the first page in case of multiple pages. uno::Any aPage = xDrawPages->getByIndex(0); - aPage >>= m_xMainDrawPage; + uno::Reference<drawing::XDrawPage> xTmp; + aPage >>= xTmp; + m_xMainDrawPage = dynamic_cast<SvxDrawPage*>(xTmp.get()); + assert(m_xMainDrawPage); } if (!m_xMainDrawPage.is()) { - m_xMainDrawPage = xDrawPages->insertNewByIndex(0); + m_xMainDrawPage = dynamic_cast<SvxDrawPage*>(xDrawPages->insertNewByIndex(0).get()); + assert(m_xMainDrawPage); } //ensure that additional shapes are in front of the chart objects so create the chart root before @@ -186,7 +176,8 @@ uno::Reference< drawing::XDrawPage > const & DrawModelWrapper::getMainDrawPage() // ShapeFactory::getOrCreateShapeFactory(getShapeFactory())->getOrCreateChartRootShape( m_xMainDrawPage ); return m_xMainDrawPage; } -uno::Reference< drawing::XDrawPage > const & DrawModelWrapper::getHiddenDrawPage() + +const rtl::Reference<SvxDrawPage> & DrawModelWrapper::getHiddenDrawPage() { if( !m_xHiddenDrawPage.is() ) { @@ -197,14 +188,21 @@ uno::Reference< drawing::XDrawPage > const & DrawModelWrapper::getHiddenDrawPage if( xDrawPages->getCount()>1 ) { uno::Any aPage = xDrawPages->getByIndex( 1 ) ; - aPage >>= m_xHiddenDrawPage; + uno::Reference<drawing::XDrawPage> xTmp; + aPage >>= xTmp; + m_xHiddenDrawPage = dynamic_cast<SvxDrawPage*>(xTmp.get()); + assert(m_xHiddenDrawPage); } if(!m_xHiddenDrawPage.is()) { if( xDrawPages->getCount()==0 ) - m_xMainDrawPage = xDrawPages->insertNewByIndex( 0 ); - m_xHiddenDrawPage = xDrawPages->insertNewByIndex( 1 ); + { + m_xMainDrawPage = dynamic_cast<SvxDrawPage*>(xDrawPages->insertNewByIndex( 0 ).get()); + assert(m_xMainDrawPage); + } + m_xHiddenDrawPage = dynamic_cast<SvxDrawPage*>(xDrawPages->insertNewByIndex( 1 ).get()); + assert(m_xHiddenDrawPage); } } } @@ -213,7 +211,7 @@ uno::Reference< drawing::XDrawPage > const & DrawModelWrapper::getHiddenDrawPage void DrawModelWrapper::clearMainDrawPage() { //uno::Reference<drawing::XShapes> xChartRoot( m_xMainDrawPage, uno::UNO_QUERY ); - uno::Reference<drawing::XShapes> xChartRoot( ShapeFactory::getChartRootShape( m_xMainDrawPage ) ); + rtl::Reference<SvxShapeGroupAnyD> xChartRoot( ShapeFactory::getChartRootShape( m_xMainDrawPage ) ); if( xChartRoot.is() ) { sal_Int32 nSubCount = xChartRoot->getCount(); @@ -226,8 +224,7 @@ void DrawModelWrapper::clearMainDrawPage() } } -uno::Reference< drawing::XShapes > DrawModelWrapper::getChartRootShape( - const uno::Reference< drawing::XDrawPage>& xDrawPage ) +rtl::Reference<SvxShapeGroupAnyD> DrawModelWrapper::getChartRootShape( const rtl::Reference<SvxDrawPage>& xDrawPage ) { return ShapeFactory::getChartRootShape( xDrawPage ); } @@ -295,44 +292,36 @@ SdrObject* DrawModelWrapper::getNamedSdrObject( const OUString& rObjectCID, SdrO { if(!pSearchList || rObjectCID.isEmpty()) return nullptr; - const size_t nCount = pSearchList->GetObjCount(); - for( size_t nN=0; nN<nCount; ++nN ) + for (const rtl::Reference<SdrObject>& pObj : *pSearchList) { - SdrObject* pObj = pSearchList->GetObj(nN); - if(!pObj) - continue; if( ObjectIdentifier::areIdenticalObjects( rObjectCID, pObj->GetName() ) ) - return pObj; - pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, pObj->GetSubList() ); - if(pObj) - return pObj; + return pObj.get(); + SdrObject* pNamedObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, pObj->GetSubList() ); + if(pNamedObj) + return pNamedObj; } return nullptr; } -bool DrawModelWrapper::removeShape( const uno::Reference< drawing::XShape >& xShape ) +bool DrawModelWrapper::removeShape( const rtl::Reference<SvxShape>& xShape ) { - uno::Reference< container::XChild > xChild( xShape, uno::UNO_QUERY ); - if( xChild.is() ) + uno::Reference<drawing::XShapes> xShapes( xShape->getParent(), uno::UNO_QUERY ); + if( xShapes.is() ) { - uno::Reference<drawing::XShapes> xShapes( xChild->getParent(), uno::UNO_QUERY ); - if( xShapes.is() ) - { - xShapes->remove(xShape); - return true; - } + xShapes->remove(xShape); + return true; } return false; } void DrawModelWrapper::dumpAsXml(xmlTextWriterPtr pWriter) const { - xmlTextWriterStartElement(pWriter, BAD_CAST("DrawModelWrapper")); - xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("DrawModelWrapper")); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); SdrModel::dumpAsXml(pWriter); - xmlTextWriterEndElement(pWriter); + (void)xmlTextWriterEndElement(pWriter); } } //namespace chart diff --git a/chart2/source/view/main/ExplicitValueProvider.cxx b/chart2/source/view/main/ExplicitValueProvider.cxx new file mode 100644 index 000000000000..52f259d341c9 --- /dev/null +++ b/chart2/source/view/main/ExplicitValueProvider.cxx @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <chartview/ExplicitValueProvider.hxx> +#include <AxisHelper.hxx> +#include <ChartModel.hxx> +#include <Diagram.hxx> +#include <DiagramHelper.hxx> +#include <unonames.hxx> +#include <BaseCoordinateSystem.hxx> +#include <TitleHelper.hxx> +#include <ObjectIdentifier.hxx> + +#include <comphelper/servicehelper.hxx> +#include <comphelper/diagnose_ex.hxx> + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; + +namespace +{ +constexpr sal_Int32 constDiagramTitleSpace = 200; //=0,2 cm spacing + +bool lcl_getPropertySwapXAndYAxis(const rtl::Reference<Diagram>& xDiagram) +{ + bool bSwapXAndY = false; + + if (xDiagram.is()) + { + const std::vector<rtl::Reference<BaseCoordinateSystem>>& aCooSysList( + xDiagram->getBaseCoordinateSystems()); + if (!aCooSysList.empty()) + { + try + { + aCooSysList[0]->getPropertyValue("SwapXAndYAxis") >>= bSwapXAndY; + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } + } + } + return bSwapXAndY; +} + +} // end anonymous namespace + +sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis( + const rtl::Reference<::chart::Axis>& xAxis, + const rtl::Reference<::chart::BaseCoordinateSystem>& xCorrespondingCoordinateSystem, + const rtl::Reference<::chart::ChartModel>& xChartDoc) +{ + return AxisHelper::getExplicitNumberFormatKeyForAxis( + xAxis, xCorrespondingCoordinateSystem, xChartDoc, + true /*bSearchForParallelAxisIfNothingIsFound*/); +} + +sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( + const uno::Reference<beans::XPropertySet>& xSeriesOrPointProp) +{ + sal_Int32 nFormat = 0; + if (!xSeriesOrPointProp.is()) + return nFormat; + + try + { + xSeriesOrPointProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nFormat; + } + catch (const beans::UnknownPropertyException&) + { + } + + if (nFormat < 0) + nFormat = 0; + return nFormat; +} + +sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel( + const uno::Reference<beans::XPropertySet>& xSeriesOrPointProp, + const uno::Reference<util::XNumberFormatsSupplier>& xNumberFormatsSupplier) +{ + sal_Int32 nFormat = 0; + if (!xSeriesOrPointProp.is()) + return nFormat; + if (!(xSeriesOrPointProp->getPropertyValue("PercentageNumberFormat") >>= nFormat)) + { + nFormat = DiagramHelper::getPercentNumberFormat(xNumberFormatsSupplier); + } + if (nFormat < 0) + nFormat = 0; + return nFormat; +} + +awt::Rectangle ExplicitValueProvider::AddSubtractAxisTitleSizes( + ChartModel& rModel, ExplicitValueProvider* pChartView, const awt::Rectangle& rPositionAndSize, + bool bSubtract) +{ + awt::Rectangle aRet(rPositionAndSize); + + //add axis title sizes to the diagram size + rtl::Reference<::chart::Title> xTitle_Height( + TitleHelper::getTitle(TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, rModel)); + rtl::Reference<::chart::Title> xTitle_Width( + TitleHelper::getTitle(TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, rModel)); + rtl::Reference<::chart::Title> xSecondTitle_Height( + TitleHelper::getTitle(TitleHelper::SECONDARY_X_AXIS_TITLE, rModel)); + rtl::Reference<::chart::Title> xSecondTitle_Width( + TitleHelper::getTitle(TitleHelper::SECONDARY_Y_AXIS_TITLE, rModel)); + if (xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() + || xSecondTitle_Width.is()) + { + ExplicitValueProvider* pExplicitValueProvider = pChartView; + if (pExplicitValueProvider) + { + //detect whether x axis points into x direction or not + if (lcl_getPropertySwapXAndYAxis(rModel.getFirstChartDiagram())) + { + std::swap(xTitle_Height, xTitle_Width); + std::swap(xSecondTitle_Height, xSecondTitle_Width); + } + + sal_Int32 nTitleSpaceWidth = 0; + sal_Int32 nTitleSpaceHeight = 0; + sal_Int32 nSecondTitleSpaceWidth = 0; + sal_Int32 nSecondTitleSpaceHeight = 0; + + if (xTitle_Height.is()) + { + OUString aCID_X( + ObjectIdentifier::createClassifiedIdentifierForObject(xTitle_Height, &rModel)); + nTitleSpaceHeight + = pExplicitValueProvider->getRectangleOfObject(aCID_X, true).Height; + if (nTitleSpaceHeight) + nTitleSpaceHeight += constDiagramTitleSpace; + } + if (xTitle_Width.is()) + { + OUString aCID_Y( + ObjectIdentifier::createClassifiedIdentifierForObject(xTitle_Width, &rModel)); + nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject(aCID_Y, true).Width; + if (nTitleSpaceWidth) + nTitleSpaceWidth += constDiagramTitleSpace; + } + if (xSecondTitle_Height.is()) + { + OUString aCID_X(ObjectIdentifier::createClassifiedIdentifierForObject( + xSecondTitle_Height, &rModel)); + nSecondTitleSpaceHeight + = pExplicitValueProvider->getRectangleOfObject(aCID_X, true).Height; + if (nSecondTitleSpaceHeight) + nSecondTitleSpaceHeight += constDiagramTitleSpace; + } + if (xSecondTitle_Width.is()) + { + OUString aCID_Y(ObjectIdentifier::createClassifiedIdentifierForObject( + xSecondTitle_Width, &rModel)); + nSecondTitleSpaceWidth + += pExplicitValueProvider->getRectangleOfObject(aCID_Y, true).Width; + if (nSecondTitleSpaceWidth) + nSecondTitleSpaceWidth += constDiagramTitleSpace; + } + if (bSubtract) + { + aRet.X += nTitleSpaceWidth; + aRet.Y += nSecondTitleSpaceHeight; + aRet.Width -= (nTitleSpaceWidth + nSecondTitleSpaceWidth); + aRet.Height -= (nTitleSpaceHeight + nSecondTitleSpaceHeight); + } + else + { + aRet.X -= nTitleSpaceWidth; + aRet.Y -= nSecondTitleSpaceHeight; + aRet.Width += nTitleSpaceWidth + nSecondTitleSpaceWidth; + aRet.Height += nTitleSpaceHeight + nSecondTitleSpaceHeight; + } + } + } + return aRet; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/LabelPositionHelper.cxx b/chart2/source/view/main/LabelPositionHelper.cxx index 811bf7ad148b..3112c591243d 100644 --- a/chart2/source/view/main/LabelPositionHelper.cxx +++ b/chart2/source/view/main/LabelPositionHelper.cxx @@ -24,20 +24,19 @@ #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/drawing/TextVerticalAdjust.hpp> #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> -#include <com/sun/star/drawing/XShape.hpp> + +#include <cmath> +#include <utility> namespace chart { using namespace ::com::sun::star; -using namespace ::com::sun::star::chart2; LabelPositionHelper::LabelPositionHelper( sal_Int32 nDimensionCount - , const uno::Reference< drawing::XShapes >& xLogicTarget - , ShapeFactory* pShapeFactory ) + , rtl::Reference<SvxShapeGroupAnyD> xLogicTarget) : m_nDimensionCount(nDimensionCount) - , m_xLogicTarget(xLogicTarget) - , m_pShapeFactory(pShapeFactory) + , m_xLogicTarget(std::move(xLogicTarget)) { } @@ -48,33 +47,33 @@ LabelPositionHelper::~LabelPositionHelper() awt::Point LabelPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D ) const { return PlottingPositionHelper::transformSceneToScreenPosition( - rScenePosition3D, m_xLogicTarget, m_pShapeFactory, m_nDimensionCount ); + rScenePosition3D, m_xLogicTarget, m_nDimensionCount ); } void LabelPositionHelper::changeTextAdjustment( tAnySequence& rPropValues, const tNameSequence& rPropNames, LabelAlignment eAlignment) { - //HorizontalAdjustment + uno::Any* pHorizontalAdjustAny + = PropertyMapper::getValuePointer(rPropValues, rPropNames, u"TextHorizontalAdjust"); + if (pHorizontalAdjustAny) { drawing::TextHorizontalAdjust eHorizontalAdjust = drawing::TextHorizontalAdjust_CENTER; if( eAlignment==LABEL_ALIGN_RIGHT || eAlignment==LABEL_ALIGN_RIGHT_TOP || eAlignment==LABEL_ALIGN_RIGHT_BOTTOM ) eHorizontalAdjust = drawing::TextHorizontalAdjust_LEFT; else if( eAlignment==LABEL_ALIGN_LEFT || eAlignment==LABEL_ALIGN_LEFT_TOP || eAlignment==LABEL_ALIGN_LEFT_BOTTOM ) eHorizontalAdjust = drawing::TextHorizontalAdjust_RIGHT; - uno::Any* pHorizontalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,"TextHorizontalAdjust"); - if(pHorizontalAdjustAny) - *pHorizontalAdjustAny <<= eHorizontalAdjust; + *pHorizontalAdjustAny <<= eHorizontalAdjust; } - //VerticalAdjustment + uno::Any* pVerticalAdjustAny + = PropertyMapper::getValuePointer(rPropValues, rPropNames, u"TextVerticalAdjust"); + if (pVerticalAdjustAny) { drawing::TextVerticalAdjust eVerticalAdjust = drawing::TextVerticalAdjust_CENTER; if( eAlignment==LABEL_ALIGN_TOP || eAlignment==LABEL_ALIGN_RIGHT_TOP || eAlignment==LABEL_ALIGN_LEFT_TOP ) eVerticalAdjust = drawing::TextVerticalAdjust_BOTTOM; else if( eAlignment==LABEL_ALIGN_BOTTOM || eAlignment==LABEL_ALIGN_RIGHT_BOTTOM || eAlignment==LABEL_ALIGN_LEFT_BOTTOM ) eVerticalAdjust = drawing::TextVerticalAdjust_TOP; - uno::Any* pVerticalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,"TextVerticalAdjust"); - if(pVerticalAdjustAny) - *pVerticalAdjustAny <<= eVerticalAdjust; + *pVerticalAdjustAny <<= eVerticalAdjust; } } @@ -100,11 +99,11 @@ void LabelPositionHelper::doDynamicFontResize( tAnySequence& rPropValues awt::Size aOldReferenceSize; if( xAxisModelProps->getPropertyValue( "ReferencePageSize") >>= aOldReferenceSize ) { - uno::Any* pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, "CharHeight" ); + uno::Any* pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, u"CharHeight" ); lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize ); - pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, "CharHeightAsian" ); + pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, u"CharHeightAsian" ); lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize ); - pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, "CharHeightComplex" ); + pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, u"CharHeightComplex" ); lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize ); } } @@ -122,36 +121,36 @@ void lcl_correctRotation_Left( double& rfXCorrection, double& rfYCorrection } else if( fAnglePositiveDegree<= 90.0 ) { - rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi )/2.0; + rfXCorrection = -aSize.Height*std::sin( fAnglePi )/2.0; if( bRotateAroundCenter ) - rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi )/2.0; + rfYCorrection = -aSize.Width*std::sin( fAnglePi )/2.0; } else if( fAnglePositiveDegree<= 180.0 ) { - double beta = fAnglePi-F_PI2; - rfXCorrection = -aSize.Width *rtl::math::sin( beta ) - -aSize.Height *rtl::math::cos( beta )/2.0; + double beta = fAnglePi-M_PI_2; + rfXCorrection = -aSize.Width *std::sin( beta ) + -aSize.Height *std::cos( beta )/2.0; if( bRotateAroundCenter ) - rfYCorrection = -aSize.Width *rtl::math::cos( beta )/2.0; + rfYCorrection = -aSize.Width *std::cos( beta )/2.0; else - rfYCorrection = -aSize.Width *rtl::math::cos( beta ); + rfYCorrection = -aSize.Width *std::cos( beta ); } else if( fAnglePositiveDegree<= 270.0 ) { - double beta = fAnglePi - F_PI; - rfXCorrection = -aSize.Width *rtl::math::cos( beta ) - -aSize.Height*rtl::math::sin( beta )/2.0; + double beta = fAnglePi - M_PI; + rfXCorrection = -aSize.Width *std::cos( beta ) + -aSize.Height*std::sin( beta )/2.0; if( bRotateAroundCenter ) - rfYCorrection = aSize.Width *rtl::math::sin( beta )/2.0; + rfYCorrection = aSize.Width *std::sin( beta )/2.0; else - rfYCorrection = aSize.Width *rtl::math::sin( beta ); + rfYCorrection = aSize.Width *std::sin( beta ); } else { - double beta = 2*F_PI - fAnglePi; - rfXCorrection = -aSize.Height*rtl::math::sin( beta )/2.0; + double beta = 2*M_PI - fAnglePi; + rfXCorrection = -aSize.Height*std::sin( beta )/2.0; if( bRotateAroundCenter ) - rfYCorrection = aSize.Width*rtl::math::sin( beta )/2.0; + rfYCorrection = aSize.Width*std::sin( beta )/2.0; } } @@ -165,35 +164,35 @@ void lcl_correctRotation_Right( double& rfXCorrection, double& rfYCorrection } else if( fAnglePositiveDegree<= 90.0 ) { - rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0; + rfXCorrection = aSize.Height*std::sin( fAnglePi )/2.0; if( bRotateAroundCenter ) - rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0; + rfYCorrection = aSize.Width*std::sin( fAnglePi )/2.0; } else if( fAnglePositiveDegree<= 180.0 ) { - double beta = F_PI - fAnglePi; - rfXCorrection = aSize.Width *rtl::math::cos( beta ) - + aSize.Height*rtl::math::sin( beta )/2.0; + double beta = M_PI - fAnglePi; + rfXCorrection = aSize.Width *std::cos( beta ) + + aSize.Height*std::sin( beta )/2.0; if( bRotateAroundCenter ) - rfYCorrection = aSize.Width *rtl::math::sin( beta )/2.0; + rfYCorrection = aSize.Width *std::sin( beta )/2.0; else - rfYCorrection = aSize.Width *rtl::math::sin( beta ); + rfYCorrection = aSize.Width *std::sin( beta ); } else if( fAnglePositiveDegree<= 270.0 ) { - double beta = 3*F_PI2 - fAnglePi; - rfXCorrection = aSize.Width *rtl::math::sin( beta ) - +aSize.Height*rtl::math::cos( beta )/2.0; + double beta = 3*M_PI_2 - fAnglePi; + rfXCorrection = aSize.Width *std::sin( beta ) + +aSize.Height*std::cos( beta )/2.0; if( bRotateAroundCenter ) - rfYCorrection = -aSize.Width *rtl::math::cos( beta )/2.0; + rfYCorrection = -aSize.Width *std::cos( beta )/2.0; else - rfYCorrection = -aSize.Width *rtl::math::cos( beta ); + rfYCorrection = -aSize.Width *std::cos( beta ); } else { - rfXCorrection = aSize.Height*rtl::math::sin( 2*F_PI - fAnglePi )/2.0; + rfXCorrection = aSize.Height*std::sin( 2*M_PI - fAnglePi )/2.0; if( bRotateAroundCenter ) - rfYCorrection = -aSize.Width*rtl::math::sin( 2*F_PI - fAnglePi )/2.0; + rfYCorrection = -aSize.Width*std::sin( 2*M_PI - fAnglePi )/2.0; } } @@ -207,35 +206,35 @@ void lcl_correctRotation_Top( double& rfXCorrection, double& rfYCorrection } else if( fAnglePositiveDegree<= 90.0 ) { - rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0; + rfXCorrection = aSize.Height*std::sin( fAnglePi )/2.0; if( !bRotateAroundCenter ) - rfXCorrection += aSize.Width*rtl::math::cos( fAnglePi )/2.0; - rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi )/2.0; + rfXCorrection += aSize.Width*std::cos( fAnglePi )/2.0; + rfYCorrection = -aSize.Width*std::sin( fAnglePi )/2.0; } else if( fAnglePositiveDegree<= 180.0 ) { - double beta = fAnglePi - F_PI2; - rfXCorrection = aSize.Height*rtl::math::cos( beta )/2.0; + double beta = fAnglePi - M_PI_2; + rfXCorrection = aSize.Height*std::cos( beta )/2.0; if( !bRotateAroundCenter ) - rfXCorrection -= aSize.Width*rtl::math::sin( beta )/2.0; - rfYCorrection = -aSize.Width*rtl::math::cos( beta )/2.0 - - aSize.Height*rtl::math::sin( beta ); + rfXCorrection -= aSize.Width*std::sin( beta )/2.0; + rfYCorrection = -aSize.Width*std::cos( beta )/2.0 + - aSize.Height*std::sin( beta ); } else if( fAnglePositiveDegree<= 270.0 ) { - double beta = fAnglePi - F_PI; - rfXCorrection = -aSize.Height *rtl::math::sin( beta )/2.0; + double beta = fAnglePi - M_PI; + rfXCorrection = -aSize.Height *std::sin( beta )/2.0; if( !bRotateAroundCenter ) - rfXCorrection += aSize.Width *rtl::math::cos( beta )/2.0; - rfYCorrection = -aSize.Width *rtl::math::sin( beta )/2.0 - -aSize.Height *rtl::math::cos( beta ); + rfXCorrection += aSize.Width *std::cos( beta )/2.0; + rfYCorrection = -aSize.Width *std::sin( beta )/2.0 + -aSize.Height *std::cos( beta ); } else { - rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi )/2.0; + rfXCorrection = aSize.Height*std::sin( fAnglePi )/2.0; if( !bRotateAroundCenter ) - rfXCorrection -= aSize.Width*rtl::math::cos( fAnglePi )/2.0; - rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0; + rfXCorrection -= aSize.Width*std::cos( fAnglePi )/2.0; + rfYCorrection = aSize.Width*std::sin( fAnglePi )/2.0; } } @@ -249,36 +248,36 @@ void lcl_correctRotation_Bottom( double& rfXCorrection, double& rfYCorrection } else if( fAnglePositiveDegree<= 90.0 ) { - rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi )/2.0; + rfXCorrection = -aSize.Height*std::sin( fAnglePi )/2.0; if( !bRotateAroundCenter ) - rfXCorrection -= aSize.Width *rtl::math::cos( fAnglePi )/2.0; - rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi )/2.0; + rfXCorrection -= aSize.Width *std::cos( fAnglePi )/2.0; + rfYCorrection = aSize.Width*std::sin( fAnglePi )/2.0; } else if( fAnglePositiveDegree<= 180.0 ) { - double beta = fAnglePi-F_PI2; - rfXCorrection = -aSize.Height*rtl::math::cos( beta )/2.0; + double beta = fAnglePi-M_PI_2; + rfXCorrection = -aSize.Height*std::cos( beta )/2.0; if( !bRotateAroundCenter ) - rfXCorrection += aSize.Width *rtl::math::sin( beta )/2.0; - rfYCorrection = aSize.Width *rtl::math::cos( beta )/2.0 - +aSize.Height*rtl::math::sin( beta ); + rfXCorrection += aSize.Width *std::sin( beta )/2.0; + rfYCorrection = aSize.Width *std::cos( beta )/2.0 + +aSize.Height*std::sin( beta ); } else if( fAnglePositiveDegree<= 270.0 ) { - double beta = 3*F_PI2 - fAnglePi; - rfXCorrection = aSize.Height*rtl::math::cos( beta )/2.0; + double beta = 3*M_PI_2 - fAnglePi; + rfXCorrection = aSize.Height*std::cos( beta )/2.0; if( !bRotateAroundCenter ) - rfXCorrection -= aSize.Width *rtl::math::sin( beta )/2.0; - rfYCorrection = aSize.Height*rtl::math::sin( beta ) - +aSize.Width*rtl::math::cos( beta )/2.0; + rfXCorrection -= aSize.Width *std::sin( beta )/2.0; + rfYCorrection = aSize.Height*std::sin( beta ) + +aSize.Width*std::cos( beta )/2.0; } else { - double beta = 2*F_PI - fAnglePi; - rfXCorrection = aSize.Height*rtl::math::sin( beta )/2.0; + double beta = 2*M_PI - fAnglePi; + rfXCorrection = aSize.Height*std::sin( beta )/2.0; if( !bRotateAroundCenter ) - rfXCorrection += aSize.Width*rtl::math::cos( beta )/2.0; - rfYCorrection = aSize.Width*rtl::math::sin( beta )/2.0; + rfXCorrection += aSize.Width*std::cos( beta )/2.0; + rfYCorrection = aSize.Width*std::sin( beta )/2.0; } } @@ -292,25 +291,25 @@ void lcl_correctRotation_Left_Top( double& rfXCorrection, double& rfYCorrection } else if( fAnglePositiveDegree<= 90.0 ) { - rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi ); + rfYCorrection = -aSize.Width*std::sin( fAnglePi ); } else if( fAnglePositiveDegree<= 180.0 ) { - double beta = fAnglePi-F_PI2; - rfXCorrection = -aSize.Width*rtl::math::sin( beta ); - rfYCorrection = -aSize.Height*rtl::math::sin( beta ) - -aSize.Width*rtl::math::cos( beta ); + double beta = fAnglePi-M_PI_2; + rfXCorrection = -aSize.Width*std::sin( beta ); + rfYCorrection = -aSize.Height*std::sin( beta ) + -aSize.Width*std::cos( beta ); } else if( fAnglePositiveDegree<= 270.0 ) { - double beta = 3*F_PI2 - fAnglePi; - rfXCorrection = -aSize.Height*rtl::math::cos( beta ) - -aSize.Width*rtl::math::sin( beta ); - rfYCorrection = -aSize.Height*rtl::math::sin( beta ); + double beta = 3*M_PI_2 - fAnglePi; + rfXCorrection = -aSize.Height*std::cos( beta ) + -aSize.Width*std::sin( beta ); + rfYCorrection = -aSize.Height*std::sin( beta ); } else { - rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi ); + rfXCorrection = aSize.Height*std::sin( fAnglePi ); } } @@ -324,25 +323,25 @@ void lcl_correctRotation_Left_Bottom( double& rfXCorrection, double& rfYCorrecti } else if( fAnglePositiveDegree<= 90.0 ) { - rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi ); + rfXCorrection = -aSize.Height*std::sin( fAnglePi ); } else if( fAnglePositiveDegree<= 180.0 ) { - double beta = fAnglePi-F_PI2; - rfXCorrection = -aSize.Width*rtl::math::sin( beta ) - -aSize.Height*rtl::math::cos( beta ); - rfYCorrection = aSize.Height*rtl::math::sin( beta ); + double beta = fAnglePi-M_PI_2; + rfXCorrection = -aSize.Width*std::sin( beta ) + -aSize.Height*std::cos( beta ); + rfYCorrection = aSize.Height*std::sin( beta ); } else if( fAnglePositiveDegree<= 270.0 ) { - double beta = 3*F_PI2 - fAnglePi; - rfXCorrection = -aSize.Width*rtl::math::sin( beta ); - rfYCorrection = aSize.Width*rtl::math::cos( beta ) - +aSize.Height*rtl::math::sin( beta ); + double beta = 3*M_PI_2 - fAnglePi; + rfXCorrection = -aSize.Width*std::sin( beta ); + rfYCorrection = aSize.Width*std::cos( beta ) + +aSize.Height*std::sin( beta ); } else { - rfYCorrection = -aSize.Width*rtl::math::sin( fAnglePi ); + rfYCorrection = -aSize.Width*std::sin( fAnglePi ); } } @@ -356,25 +355,25 @@ void lcl_correctRotation_Right_Top( double& rfXCorrection, double& rfYCorrection } else if( fAnglePositiveDegree<= 90.0 ) { - rfXCorrection = aSize.Height*rtl::math::sin( fAnglePi ); + rfXCorrection = aSize.Height*std::sin( fAnglePi ); } else if( fAnglePositiveDegree<= 180.0 ) { - double beta = fAnglePi-F_PI2; - rfXCorrection = aSize.Width*rtl::math::sin( beta ) - +aSize.Height*rtl::math::cos( beta ); - rfYCorrection = -aSize.Height*rtl::math::sin( beta ); + double beta = fAnglePi-M_PI_2; + rfXCorrection = aSize.Width*std::sin( beta ) + +aSize.Height*std::cos( beta ); + rfYCorrection = -aSize.Height*std::sin( beta ); } else if( fAnglePositiveDegree<= 270.0 ) { - double beta = 3*F_PI2 - fAnglePi; - rfXCorrection = aSize.Width*rtl::math::sin( beta ); - rfYCorrection = -aSize.Width*rtl::math::cos( beta ) - -aSize.Height*rtl::math::sin( beta ); + double beta = 3*M_PI_2 - fAnglePi; + rfXCorrection = aSize.Width*std::sin( beta ); + rfYCorrection = -aSize.Width*std::cos( beta ) + -aSize.Height*std::sin( beta ); } else { - rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi ); + rfYCorrection = aSize.Width*std::sin( fAnglePi ); } } @@ -388,31 +387,31 @@ void lcl_correctRotation_Right_Bottom( double& rfXCorrection, double& rfYCorrect } else if( fAnglePositiveDegree<= 90.0 ) { - rfYCorrection = aSize.Width*rtl::math::sin( fAnglePi ); + rfYCorrection = aSize.Width*std::sin( fAnglePi ); } else if( fAnglePositiveDegree<= 180.0 ) { - double beta = fAnglePi-F_PI2; - rfXCorrection = aSize.Width*rtl::math::sin( beta ); - rfYCorrection = aSize.Height*rtl::math::sin( beta ) - +aSize.Width*rtl::math::cos( beta ); + double beta = fAnglePi-M_PI_2; + rfXCorrection = aSize.Width*std::sin( beta ); + rfYCorrection = aSize.Height*std::sin( beta ) + +aSize.Width*std::cos( beta ); } else if( fAnglePositiveDegree<= 270.0 ) { - double beta = 3*F_PI2 - fAnglePi; - rfXCorrection = aSize.Height*rtl::math::cos( beta ) - +aSize.Width*rtl::math::sin( beta ); - rfYCorrection = aSize.Height*rtl::math::sin( beta ); + double beta = 3*M_PI_2 - fAnglePi; + rfXCorrection = aSize.Height*std::cos( beta ) + +aSize.Width*std::sin( beta ); + rfYCorrection = aSize.Height*std::sin( beta ); } else { - rfXCorrection = -aSize.Height*rtl::math::sin( fAnglePi ); + rfXCorrection = -aSize.Height*std::sin( fAnglePi ); } } }//end anonymous namespace -void LabelPositionHelper::correctPositionForRotation( const uno::Reference< drawing::XShape >& xShape2DText +void LabelPositionHelper::correctPositionForRotation( const rtl::Reference<SvxShapeText>& xShape2DText , LabelAlignment eLabelAlignment, const double fRotationAngle, bool bRotateAroundCenter ) { if( !xShape2DText.is() ) diff --git a/chart2/source/view/main/Linear3DTransformation.cxx b/chart2/source/view/main/Linear3DTransformation.cxx index c27ffa3168a5..0d723ef3454f 100644 --- a/chart2/source/view/main/Linear3DTransformation.cxx +++ b/chart2/source/view/main/Linear3DTransformation.cxx @@ -34,35 +34,35 @@ namespace chart Linear3DTransformation::~Linear3DTransformation() {} -// ____ XTransformation ____ -Sequence< double > SAL_CALL Linear3DTransformation::transform( - const Sequence< double >& rSourceValues ) +// ____ XTransformation2 ____ +css::drawing::Position3D Linear3DTransformation::transform( + const Sequence< double >& rSourceValues ) const { double fX = rSourceValues[0]; double fY = rSourceValues[1]; double fZ = rSourceValues[2]; if(m_bSwapXAndY) std::swap(fX,fY); - Sequence< double > aNewVec(3); + css::drawing::Position3D aNewVec; double fZwi; fZwi = m_Matrix.Line1.Column1 * fX + m_Matrix.Line1.Column2 * fY + m_Matrix.Line1.Column3 * fZ + m_Matrix.Line1.Column4; - aNewVec[0] = fZwi; + aNewVec.PositionX = fZwi; fZwi = m_Matrix.Line2.Column1 * fX + m_Matrix.Line2.Column2 * fY + m_Matrix.Line2.Column3 * fZ + m_Matrix.Line2.Column4; - aNewVec[1] = fZwi; + aNewVec.PositionY = fZwi; fZwi = m_Matrix.Line3.Column1 * fX + m_Matrix.Line3.Column2 * fY + m_Matrix.Line3.Column3 * fZ + m_Matrix.Line3.Column4; - aNewVec[2] = fZwi; + aNewVec.PositionZ = fZwi; fZwi = m_Matrix.Line4.Column1 * fX + m_Matrix.Line4.Column2 * fY @@ -70,21 +70,53 @@ Sequence< double > SAL_CALL Linear3DTransformation::transform( + m_Matrix.Line4.Column4; if(fZwi != 1.0 && fZwi != 0.0) { - aNewVec[0] /= fZwi; - aNewVec[1] /= fZwi; - aNewVec[2] /= fZwi; + aNewVec.PositionX /= fZwi; + aNewVec.PositionY /= fZwi; + aNewVec.PositionZ /= fZwi; } return aNewVec; } -sal_Int32 SAL_CALL Linear3DTransformation::getSourceDimension() +css::drawing::Position3D Linear3DTransformation::transform( + const css::drawing::Position3D& rSourceValues ) const { - return 3; -} + double fX = rSourceValues.PositionX; + double fY = rSourceValues.PositionY; + double fZ = rSourceValues.PositionZ; + if(m_bSwapXAndY) + std::swap(fX,fY); + css::drawing::Position3D aNewVec; + double fZwi; -sal_Int32 SAL_CALL Linear3DTransformation::getTargetDimension() -{ - return 3; + fZwi = m_Matrix.Line1.Column1 * fX + + m_Matrix.Line1.Column2 * fY + + m_Matrix.Line1.Column3 * fZ + + m_Matrix.Line1.Column4; + aNewVec.PositionX = fZwi; + + fZwi = m_Matrix.Line2.Column1 * fX + + m_Matrix.Line2.Column2 * fY + + m_Matrix.Line2.Column3 * fZ + + m_Matrix.Line2.Column4; + aNewVec.PositionY = fZwi; + + fZwi = m_Matrix.Line3.Column1 * fX + + m_Matrix.Line3.Column2 * fY + + m_Matrix.Line3.Column3 * fZ + + m_Matrix.Line3.Column4; + aNewVec.PositionZ = fZwi; + + fZwi = m_Matrix.Line4.Column1 * fX + + m_Matrix.Line4.Column2 * fY + + m_Matrix.Line4.Column3 * fZ + + m_Matrix.Line4.Column4; + if(fZwi != 1.0 && fZwi != 0.0) + { + aNewVec.PositionX /= fZwi; + aNewVec.PositionY /= fZwi; + aNewVec.PositionZ /= fZwi; + } + return aNewVec; } } // namespace chart diff --git a/chart2/source/view/main/PlotterBase.cxx b/chart2/source/view/main/PlotterBase.cxx index 6479668c67ef..d09bba64aeef 100644 --- a/chart2/source/view/main/PlotterBase.cxx +++ b/chart2/source/view/main/PlotterBase.cxx @@ -20,33 +20,26 @@ #include <PlotterBase.hxx> #include <PlottingPositionHelper.hxx> #include <ShapeFactory.hxx> -#include <rtl/math.hxx> #include <osl/diagnose.h> namespace chart { using namespace ::com::sun::star; -using namespace ::com::sun::star::chart2; PlotterBase::PlotterBase( sal_Int32 nDimensionCount ) - : m_pShapeFactory(nullptr) - , m_aCID() - , m_nDimension(nDimensionCount) + : m_nDimension(nDimensionCount) , m_pPosHelper(nullptr) { } -void PlotterBase::initPlotter( const uno::Reference< drawing::XShapes >& xLogicTarget - , const uno::Reference< drawing::XShapes >& xFinalTarget - , const uno::Reference< lang::XMultiServiceFactory >& xShapeFactory +void PlotterBase::initPlotter( const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget + , const rtl::Reference<SvxShapeGroupAnyD>& xFinalTarget , const OUString& rCID ) { - OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is()&&xShapeFactory.is(),"no proper initialization parameters"); + OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is(),"no proper initialization parameters"); //is only allowed to be called once m_xLogicTarget = xLogicTarget; m_xFinalTarget = xFinalTarget; - m_xShapeFactory = xShapeFactory; - m_pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); m_aCID = rCID; } @@ -54,13 +47,13 @@ PlotterBase::~PlotterBase() { } -void PlotterBase::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) +void PlotterBase::setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) { if (!m_pPosHelper) return; OSL_PRECOND(m_nDimension<=static_cast<sal_Int32>(rScales.size()),"Dimension of Plotter does not fit two dimension of given scale sequence"); - m_pPosHelper->setScales( rScales, bSwapXAndYAxis ); + m_pPosHelper->setScales( std::move(rScales), bSwapXAndYAxis ); } void PlotterBase::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix) @@ -74,22 +67,19 @@ void PlotterBase::setTransformationSceneToScreen( const drawing::HomogenMatrix& m_pPosHelper->setTransformationSceneToScreen( rMatrix ); } -uno::Reference< drawing::XShapes > PlotterBase::createGroupShape( - const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference<SvxShapeGroupAnyD> PlotterBase::createGroupShape( + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const OUString& rName ) { - if(!m_xShapeFactory.is()) - return nullptr; - if(m_nDimension==2) { //create and add to target - return m_pShapeFactory->createGroup2D( xTarget, rName ); + return ShapeFactory::createGroup2D( xTarget, rName ); } else { //create and added to target - return m_pShapeFactory->createGroup3D( xTarget, rName ); + return ShapeFactory::createGroup3D( xTarget, rName ); } } diff --git a/chart2/source/view/main/PlottingPositionHelper.cxx b/chart2/source/view/main/PlottingPositionHelper.cxx index d26e9331ba44..dfbf38bbd90e 100644 --- a/chart2/source/view/main/PlottingPositionHelper.cxx +++ b/chart2/source/view/main/PlottingPositionHelper.cxx @@ -27,9 +27,7 @@ #include <com/sun/star/chart/TimeUnit.hpp> #include <com/sun/star/chart2/AxisType.hpp> -#include <com/sun/star/drawing/DoubleSequence.hpp> #include <com/sun/star/drawing/Position3D.hpp> -#include <com/sun/star/drawing/XShapes.hpp> #include <rtl/math.hxx> @@ -38,10 +36,10 @@ namespace chart using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; +XTransformation2::~XTransformation2() {} + PlottingPositionHelper::PlottingPositionHelper() - : m_aScales() - , m_aMatrixScreenToScene() - , m_bSwapXAndY( false ) + : m_bSwapXAndY( false ) , m_nXResolution( 1000 ) , m_nYResolution( 1000 ) , m_nZResolution( 1000 ) @@ -95,14 +93,14 @@ void PlottingPositionHelper::setTransformationSceneToScreen( const drawing::Homo m_xTransformationLogicToScene = nullptr; } -void PlottingPositionHelper::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) +void PlottingPositionHelper::setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) { - m_aScales = rScales; + m_aScales = std::move(rScales); m_bSwapXAndY = bSwapXAndYAxis; m_xTransformationLogicToScene = nullptr; } -uno::Reference< XTransformation > PlottingPositionHelper::getTransformationScaledLogicToScene() const +::chart::XTransformation2* PlottingPositionHelper::getTransformationScaledLogicToScene() const { //this is a standard transformation for a cartesian coordinate system @@ -110,7 +108,7 @@ uno::Reference< XTransformation > PlottingPositionHelper::getTransformationScale //we need to apply this transformation to each geometric object because of a bug/problem //of the old drawing layer (the UNO_NAME_3D_EXTRUDE_DEPTH is an integer value instead of a double ) - if(!m_xTransformationLogicToScene.is()) + if(!m_xTransformationLogicToScene) { ::basegfx::B3DHomMatrix aMatrix; double MinX = getLogicMinX(); @@ -164,9 +162,9 @@ uno::Reference< XTransformation > PlottingPositionHelper::getTransformationScale aMatrix = m_aMatrixScreenToScene*aMatrix; - m_xTransformationLogicToScene = new Linear3DTransformation(B3DHomMatrixToHomogenMatrix( aMatrix ),m_bSwapXAndY); + m_xTransformationLogicToScene.reset(new Linear3DTransformation(B3DHomMatrixToHomogenMatrix( aMatrix ), m_bSwapXAndY)); } - return m_xTransformationLogicToScene; + return m_xTransformationLogicToScene.get(); } drawing::Position3D PlottingPositionHelper::transformLogicToScene( @@ -187,16 +185,13 @@ drawing::Position3D PlottingPositionHelper::transformScaledLogicToScene( drawing::Position3D aPos( fX, fY, fZ); - uno::Reference< XTransformation > xTransformation = + ::chart::XTransformation2* pTransformation = getTransformationScaledLogicToScene(); - uno::Sequence< double > aSeq = - xTransformation->transform( Position3DToSequence(aPos) ); - return SequenceToPosition3D(aSeq); + return pTransformation->transform( aPos ); } awt::Point PlottingPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D - , const uno::Reference< drawing::XShapes >& xSceneTarget - , ShapeFactory* pShapeFactory + , const rtl::Reference<SvxShapeGroupAnyD>& xSceneTarget , sal_Int32 nDimensionCount ) { //@todo would like to have a cheaper method to do this transformation @@ -207,7 +202,7 @@ awt::Point PlottingPositionHelper::transformSceneToScreenPosition( const drawing { //create 3D anchor shape tPropertyNameMap aDummyPropertyNameMap; - uno::Reference< drawing::XShape > xShape3DAnchor = pShapeFactory->createCube( xSceneTarget + rtl::Reference<Svx3DExtrudeObject> xShape3DAnchor = ShapeFactory::createCube( xSceneTarget , rScenePosition3D,drawing::Direction3D(1,1,1) , 0, nullptr, aDummyPropertyNameMap); //get 2D position from xShape3DAnchor @@ -220,16 +215,38 @@ awt::Point PlottingPositionHelper::transformSceneToScreenPosition( const drawing void PlottingPositionHelper::transformScaledLogicToScene( drawing::PolyPolygonShape3D& rPolygon ) const { drawing::Position3D aScenePosition; + auto SequenceXRange = asNonConstRange(rPolygon.SequenceX); + auto SequenceYRange = asNonConstRange(rPolygon.SequenceY); + auto SequenceZRange = asNonConstRange(rPolygon.SequenceZ); for( sal_Int32 nS = rPolygon.SequenceX.getLength(); nS--;) { - drawing::DoubleSequence& xValues = rPolygon.SequenceX[nS]; - drawing::DoubleSequence& yValues = rPolygon.SequenceY[nS]; - drawing::DoubleSequence& zValues = rPolygon.SequenceZ[nS]; - for( sal_Int32 nP = xValues.getLength(); nP--; ) + auto xValuesRange = asNonConstRange(SequenceXRange[nS]); + auto yValuesRange = asNonConstRange(SequenceYRange[nS]); + auto zValuesRange = asNonConstRange(SequenceZRange[nS]); + for( sal_Int32 nP = SequenceXRange[nS].getLength(); nP--; ) { - double& fX = xValues[nP]; - double& fY = yValues[nP]; - double& fZ = zValues[nP]; + double& fX = xValuesRange[nP]; + double& fY = yValuesRange[nP]; + double& fZ = zValuesRange[nP]; + aScenePosition = transformScaledLogicToScene( fX,fY,fZ,true ); + fX = aScenePosition.PositionX; + fY = aScenePosition.PositionY; + fZ = aScenePosition.PositionZ; + } + } +} + +void PlottingPositionHelper::transformScaledLogicToScene( std::vector<std::vector<css::drawing::Position3D>>& rPolygon ) const +{ + drawing::Position3D aScenePosition; + for( sal_Int32 nS = static_cast<sal_Int32>(rPolygon.size()); nS--;) + { + auto valuesRange = rPolygon[nS].data(); + for( sal_Int32 nP = rPolygon[nS].size(); nP--; ) + { + double& fX = valuesRange[nP].PositionX; + double& fY = valuesRange[nP].PositionY; + double& fZ = valuesRange[nP].PositionZ; aScenePosition = transformScaledLogicToScene( fX,fY,fZ,true ); fX = aScenePosition.PositionX; fY = aScenePosition.PositionY; @@ -316,7 +333,6 @@ drawing::Direction3D PlottingPositionHelper::getScaledLogicWidth() const PolarPlottingPositionHelper::PolarPlottingPositionHelper() : m_fRadiusOffset(0.0) , m_fAngleDegreeOffset(90.0) - , m_aUnitCartesianToScene() { m_bMaySkipPointsInRegressionCalculation = false; } @@ -343,9 +359,9 @@ void PolarPlottingPositionHelper::setTransformationSceneToScreen( const drawing: PlottingPositionHelper::setTransformationSceneToScreen( rMatrix); m_aUnitCartesianToScene =impl_calculateMatrixUnitCartesianToScene( m_aMatrixScreenToScene ); } -void PolarPlottingPositionHelper::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ) +void PolarPlottingPositionHelper::setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) { - PlottingPositionHelper::setScales( rScales, bSwapXAndYAxis ); + PlottingPositionHelper::setScales( std::move(rScales), bSwapXAndYAxis ); m_aUnitCartesianToScene =impl_calculateMatrixUnitCartesianToScene( m_aMatrixScreenToScene ); } @@ -391,22 +407,18 @@ void PolarPlottingPositionHelper::setScales( const std::vector< ExplicitScaleDat return aRet; } -uno::Reference< XTransformation > PolarPlottingPositionHelper::getTransformationScaledLogicToScene() const +::chart::XTransformation2* PolarPlottingPositionHelper::getTransformationScaledLogicToScene() const { - if( !m_xTransformationLogicToScene.is() ) - m_xTransformationLogicToScene = new VPolarTransformation(*this); - return m_xTransformationLogicToScene; + if( !m_xTransformationLogicToScene ) + m_xTransformationLogicToScene.reset(new VPolarTransformation(*this)); + return m_xTransformationLogicToScene.get(); } double PolarPlottingPositionHelper::getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const { const ExplicitScaleData& rAngleScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[0]; if( rAngleScale.Orientation != AxisOrientation_MATHEMATICAL ) - { - double fHelp = fEndLogicValueOnAngleAxis; - fEndLogicValueOnAngleAxis = fStartLogicValueOnAngleAxis; - fStartLogicValueOnAngleAxis = fHelp; - } + std::swap( fStartLogicValueOnAngleAxis, fEndLogicValueOnAngleAxis ); double fStartAngleDegree = transformToAngleDegree( fStartLogicValueOnAngleAxis ); double fEndAngleDegree = transformToAngleDegree( fEndLogicValueOnAngleAxis ); @@ -615,8 +627,8 @@ drawing::Position3D PolarPlottingPositionHelper::transformUnitCircleToScene( dou { double fAnglePi = basegfx::deg2rad(fUnitAngleDegree); - double fX=fUnitRadius*rtl::math::cos(fAnglePi); - double fY=fUnitRadius*rtl::math::sin(fAnglePi); + double fX=fUnitRadius*std::cos(fAnglePi); + double fY=fUnitRadius*std::sin(fAnglePi); double fZ=fLogicZ; //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector @@ -652,7 +664,7 @@ double PlottingPositionHelper::getBaseValueY() const return m_aScales[1].Origin; } -void PlottingPositionHelper::setTimeResolution( long nTimeResolution, const Date& rNullDate ) +void PlottingPositionHelper::setTimeResolution( tools::Long nTimeResolution, const Date& rNullDate ) { m_nTimeResolution = nTimeResolution; m_aNullDate = rNullDate; diff --git a/chart2/source/view/main/PolarLabelPositionHelper.cxx b/chart2/source/view/main/PolarLabelPositionHelper.cxx index a3e9a7cd9778..44070603c75a 100644 --- a/chart2/source/view/main/PolarLabelPositionHelper.cxx +++ b/chart2/source/view/main/PolarLabelPositionHelper.cxx @@ -27,14 +27,12 @@ namespace chart { using namespace ::com::sun::star; -using namespace ::com::sun::star::chart2; PolarLabelPositionHelper::PolarLabelPositionHelper( PolarPlottingPositionHelper* pPosHelper , sal_Int32 nDimensionCount - , const uno::Reference< drawing::XShapes >& xLogicTarget - , ShapeFactory* pShapeFactory ) - : LabelPositionHelper( nDimensionCount, xLogicTarget, pShapeFactory ) + , const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget ) + : LabelPositionHelper( nDimensionCount, xLogicTarget ) , m_pPosHelper(pPosHelper) { } @@ -104,19 +102,8 @@ awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCi double fDX = aRet.X-aP0.X; double fDY = aRet.Y-aP0.Y; fDY*=-1.0;//drawing layer has inverse y values - if( fDX != 0.0 ) - { - fAngleDegree = basegfx::rad2deg(atan(fDY/fDX)); - if(fDX<0.0) - fAngleDegree+=180.0; - } - else - { - if(fDY>0.0) - fAngleDegree = 90.0; - else - fAngleDegree = 270.0; - } + + fAngleDegree = basegfx::rad2deg(atan2(fDY,fDX)); } //set LabelAlignment if( !bCenter ) @@ -129,26 +116,22 @@ awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCi bool bOutside = nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE; - if(fAngleDegree==0.0) - rAlignment = LABEL_ALIGN_CENTER; - else if(fAngleDegree<=22.5) + if (fAngleDegree <= 5 || fAngleDegree >= 355) rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT; - else if(fAngleDegree<67.5) + else if (fAngleDegree < 85) rAlignment = bOutside ? LABEL_ALIGN_RIGHT_TOP : LABEL_ALIGN_LEFT_BOTTOM; - else if(fAngleDegree<112.5) + else if (fAngleDegree <= 95) rAlignment = bOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM; - else if(fAngleDegree<=157.5) + else if (fAngleDegree < 175) rAlignment = bOutside ? LABEL_ALIGN_LEFT_TOP : LABEL_ALIGN_RIGHT_BOTTOM; - else if(fAngleDegree<=202.5) + else if (fAngleDegree <= 185) rAlignment = bOutside ? LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT; - else if(fAngleDegree<247.5) + else if (fAngleDegree < 265) rAlignment = bOutside ? LABEL_ALIGN_LEFT_BOTTOM : LABEL_ALIGN_RIGHT_TOP; - else if(fAngleDegree<292.5) + else if (fAngleDegree <= 275) rAlignment = bOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP; - else if(fAngleDegree<337.5) - rAlignment = bOutside ? LABEL_ALIGN_RIGHT_BOTTOM : LABEL_ALIGN_LEFT_TOP; else - rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT; + rAlignment = bOutside ? LABEL_ALIGN_RIGHT_BOTTOM : LABEL_ALIGN_LEFT_TOP; } else { diff --git a/chart2/source/view/main/PropertyMapper.cxx b/chart2/source/view/main/PropertyMapper.cxx index 0550cdd5ce11..79206624f436 100644 --- a/chart2/source/view/main/PropertyMapper.cxx +++ b/chart2/source/view/main/PropertyMapper.cxx @@ -26,48 +26,139 @@ #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> #include <com/sun/star/drawing/LineJoint.hpp> #include <com/sun/star/style/ParagraphAdjust.hpp> -#include <comphelper/sequence.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> +#include <svx/unoshape.hxx> namespace chart { using namespace ::com::sun::star; -namespace +void PropertyMapper::setMappedProperties( + SvxShape& xTarget + , const uno::Reference< beans::XPropertySet >& xSource + , const tPropertyNameMap& rMap ) { + if( !xSource.is() ) + return; -void lcl_overwriteOrAppendValues( - tPropertyNameValueMap &rMap, const tPropertyNameValueMap& rOverwriteMap ) -{ - for (auto const& elem : rOverwriteMap) - rMap[ elem.first ] = elem.second; -} + sal_Int32 nPropertyCount = rMap.size(); + tNameSequence aNames(nPropertyCount); + tAnySequence aValues(nPropertyCount); + auto pNames = aNames.getArray(); + auto pValues = aValues.getArray(); + sal_Int32 nN=0; + + for (auto const& elem : rMap) + { + const OUString & rTarget = elem.first; + const OUString & rSource = elem.second; + try + { + uno::Any aAny( xSource->getPropertyValue(rSource) ); + if( aAny.hasValue() ) + { + //do not set empty anys because of performance (otherwise SdrAttrObj::ItemChange will take much longer) + pNames[nN] = rTarget; + pValues[nN] = std::move(aAny); + ++nN; + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + if (nN == 0) + return; + //reduce to real property count + aNames.realloc(nN); + aValues.realloc(nN); -} // anonymous namespace + uno::Reference< beans::XMultiPropertySet > xShapeMultiProp( xTarget, uno::UNO_QUERY_THROW ); + try + { + xShapeMultiProp->setPropertyValues( aNames, aValues ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); //if this occurs more often think of removing the XMultiPropertySet completely for better performance + } +} void PropertyMapper::setMappedProperties( const uno::Reference< beans::XPropertySet >& xTarget , const uno::Reference< beans::XPropertySet >& xSource - , const tPropertyNameMap& rMap - , tPropertyNameValueMap const * pOverwriteMap ) + , const tPropertyNameMap& rMap ) { if( !xTarget.is() || !xSource.is() ) return; tNameSequence aNames; tAnySequence aValues; - getMultiPropertyLists(aNames, aValues, xSource, rMap ); - if(pOverwriteMap && (aNames.getLength() == aValues.getLength())) + sal_Int32 nN=0; + sal_Int32 nPropertyCount = rMap.size(); + aNames.realloc(nPropertyCount); + auto pNames = aNames.getArray(); + aValues.realloc(nPropertyCount); + auto pValues = aValues.getArray(); + + for (auto const& elem : rMap) { - tPropertyNameValueMap aNewMap; - for( sal_Int32 nI=0; nI<aNames.getLength(); ++nI ) - aNewMap[ aNames[nI] ] = aValues[nI]; - lcl_overwriteOrAppendValues( aNewMap, *pOverwriteMap ); - aNames = comphelper::mapKeysToSequence( aNewMap ); - aValues = comphelper::mapValuesToSequence( aNewMap ); + const OUString & rTarget = elem.first; + const OUString & rSource = elem.second; + try + { + uno::Any aAny( xSource->getPropertyValue(rSource) ); + if( aAny.hasValue() ) + { + //do not set empty anys because of performance (otherwise SdrAttrObj::ItemChange will take much longer) + pNames[nN] = rTarget; + pValues[nN] = aAny; + ++nN; + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "exception mapping property from " << rSource << " to " << rTarget); + } } + if (nN == 0) + return; + + uno::Reference< beans::XMultiPropertySet > xShapeMultiProp( xTarget, uno::UNO_QUERY ); + if (xShapeMultiProp) + try + { + //reduce to real property count + aNames.realloc(nN); + aValues.realloc(nN); + xShapeMultiProp->setPropertyValues( aNames, aValues ); + return; // successful + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); //if this occurs more often think of removing the XMultiPropertySet completely for better performance + } - PropertyMapper::setMultiProperties( aNames, aValues, xTarget ); + // fall back to one at a time + try + { + for( sal_Int32 i = 0; i < nN; i++ ) + { + try + { + xTarget->setPropertyValue( aNames[i], aValues[i] ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } } void PropertyMapper::getValueMap( @@ -80,12 +171,14 @@ void PropertyMapper::getValueMap( if((false) && xMultiPropSet.is()) { uno::Sequence< OUString > aPropSourceNames(rNameMap.size()); + auto aPropSourceNamesRange = asNonConstRange(aPropSourceNames); uno::Sequence< OUString > aPropTargetNames(rNameMap.size()); + auto aPropTargetNamesRange = asNonConstRange(aPropTargetNames); sal_Int32 i = 0; for (auto const& elem : rNameMap) { - aPropTargetNames[i] = elem.first; - aPropSourceNames[i] = elem.second; + aPropTargetNamesRange[i] = elem.first; + aPropSourceNamesRange[i] = elem.second; ++i; } @@ -101,13 +194,13 @@ void PropertyMapper::getValueMap( { for (auto const& elem : rNameMap) { - OUString aTarget = elem.first; - OUString aSource = elem.second; + const OUString & rTarget = elem.first; + const OUString & rSource = elem.second; try { - uno::Any aAny( xSourceProp->getPropertyValue(aSource) ); + uno::Any aAny( xSourceProp->getPropertyValue(rSource) ); if( aAny.hasValue() ) - rValueMap.emplace( aTarget, aAny ); + rValueMap.emplace( rTarget, aAny ); } catch( const uno::Exception& ) { @@ -117,18 +210,6 @@ void PropertyMapper::getValueMap( } } -void PropertyMapper::getMultiPropertyLists( - tNameSequence& rNames - , tAnySequence& rValues - , const uno::Reference< beans::XPropertySet >& xSourceProp - , const tPropertyNameMap& rNameMap - ) -{ - tPropertyNameValueMap aValueMap; - getValueMap( aValueMap, rNameMap, xSourceProp ); - getMultiPropertyListsFromValueMap( rNames, rValues, aValueMap ); -} - void PropertyMapper::getMultiPropertyListsFromValueMap( tNameSequence& rNames , tAnySequence& rValues @@ -137,7 +218,9 @@ void PropertyMapper::getMultiPropertyListsFromValueMap( { sal_Int32 nPropertyCount = rValueMap.size(); rNames.realloc(nPropertyCount); + auto pNames = rNames.getArray(); rValues.realloc(nPropertyCount); + auto pValues = rValues.getArray(); //fill sequences sal_Int32 nN=0; @@ -147,8 +230,8 @@ void PropertyMapper::getMultiPropertyListsFromValueMap( if( rAny.hasValue() ) { //do not set empty anys because of performance (otherwise SdrAttrObj::ItemChange will take much longer) - rNames[nN] = elem.first; - rValues[nN] = rAny; + pNames[nN] = elem.first; + pValues[nN] = rAny; ++nN; } } @@ -159,13 +242,13 @@ void PropertyMapper::getMultiPropertyListsFromValueMap( uno::Any* PropertyMapper::getValuePointer( tAnySequence& rPropValues , const tNameSequence& rPropNames - , const OUString& rPropName ) + , std::u16string_view rPropName ) { sal_Int32 nCount = rPropNames.getLength(); for( sal_Int32 nN = 0; nN < nCount; nN++ ) { if(rPropNames[nN] == rPropName) - return &rPropValues[nN]; + return &rPropValues.getArray()[nN]; } return nullptr; } @@ -185,7 +268,8 @@ const tPropertyNameMap& PropertyMapper::getPropertyNameMapForCharacterProperties {"CharColor", "CharColor"}, {"CharContoured", "CharContoured"}, {"CharEmphasis", "CharEmphasis"},//the service style::CharacterProperties describes a property called 'CharEmphasize' which is nowhere implemented - + {"CharEscapement", "CharEscapement"}, + {"CharEscapementHeight", "CharEscapementHeight"}, {"CharFontFamily", "CharFontFamily"}, {"CharFontFamilyAsian", "CharFontFamilyAsian"}, {"CharFontFamilyComplex", "CharFontFamilyComplex"}, @@ -282,7 +366,8 @@ const tPropertyNameMap& PropertyMapper::getPropertyNameMapForLineProperties() {"LineJoint", "LineJoint"}, {"LineStyle", "LineStyle"}, {"LineTransparence", "LineTransparence"}, - {"LineWidth", "LineWidth"}}; + {"LineWidth", "LineWidth"}, + {"LineCap", "LineCap"}}; return s_aShapePropertyMapForLineProperties; } @@ -329,7 +414,8 @@ const tPropertyNameMap& PropertyMapper::getPropertyNameMapForLineSeriesPropertie {"LineDashName", "LineDashName"}, {"LineStyle", "LineStyle"}, {"LineTransparence", "Transparency"}, - {"LineWidth", "LineWidth"}}; + {"LineWidth", "LineWidth"}, + {"LineCap", "LineCap"}}; return s_aShapePropertyMapForLineSeriesProperties; } @@ -385,58 +471,24 @@ const tPropertyNameMap& PropertyMapper::getPropertyNameMapForFilledSeriesPropert {"LineDashName", "BorderDashName"}, {"LineStyle", "BorderStyle"}, {"LineTransparence", "BorderTransparency"}, - {"LineWidth", "BorderWidth"}}; + {"LineWidth", "BorderWidth"}, + {"LineCap", "LineCap"}}; return s_aShapePropertyMapForFilledSeriesProperties; } void PropertyMapper::setMultiProperties( const tNameSequence& rNames , const tAnySequence& rValues - , const css::uno::Reference< - css::beans::XPropertySet >& xTarget ) + , SvxShape& xTarget ) { - bool bSuccess = false; try { - uno::Reference< beans::XMultiPropertySet > xShapeMultiProp( xTarget, uno::UNO_QUERY ); - if( xShapeMultiProp.is() ) - { - xShapeMultiProp->setPropertyValues( rNames, rValues ); - bSuccess = true; - } + xTarget.setPropertyValues( rNames, rValues ); } catch( const uno::Exception& ) { TOOLS_WARN_EXCEPTION("chart2", "" ); //if this occurs more often think of removing the XMultiPropertySet completely for better performance } - - if(bSuccess) - return; - - try - { - sal_Int32 nCount = std::max( rNames.getLength(), rValues.getLength() ); - OUString aPropName; - uno::Any aValue; - for( sal_Int32 nN = 0; nN < nCount; nN++ ) - { - aPropName = rNames[nN]; - aValue = rValues[nN]; - - try - { - xTarget->setPropertyValue( aPropName, aValue ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } - } - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } } void PropertyMapper::getTextLabelMultiPropertyLists( diff --git a/chart2/source/view/main/SeriesPlotterContainer.cxx b/chart2/source/view/main/SeriesPlotterContainer.cxx new file mode 100644 index 000000000000..afca7efbc463 --- /dev/null +++ b/chart2/source/view/main/SeriesPlotterContainer.cxx @@ -0,0 +1,759 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/config.h> + +#include <cstddef> + +#include "SeriesPlotterContainer.hxx" + +#include <ChartView.hxx> +#include <Diagram.hxx> +#include <ChartType.hxx> +#include <DataSeries.hxx> +#include <ChartModel.hxx> +#include <ChartTypeHelper.hxx> +#include <ObjectIdentifier.hxx> +#include <DiagramHelper.hxx> +#include <Axis.hxx> +#include <AxisIndexDefines.hxx> +#include <DataSeriesHelper.hxx> +#include <ExplicitCategoriesProvider.hxx> +#include <unonames.hxx> + +#include <com/sun/star/chart/ChartAxisPosition.hpp> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/PieChartSubType.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> + +#include <comphelper/classids.hxx> +#include <servicenames_charttypes.hxx> +#include <comphelper/diagnose_ex.hxx> + +namespace chart +{ +using namespace ::css; +using namespace ::css::chart2; + +using ::css::uno::Reference; +using ::css::uno::Sequence; +using ::css::uno::Any; + +SeriesPlotterContainer::SeriesPlotterContainer( + std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList) + : m_rVCooSysList(rVCooSysList) + , m_nMaxAxisIndex(0) + , m_bChartTypeUsesShiftedCategoryPositionPerDefault(false) + , m_nDefaultDateNumberFormat(0) +{ +} + +SeriesPlotterContainer::~SeriesPlotterContainer() +{ + // - remove plotter from coordinatesystems + for (auto& nC : m_rVCooSysList) + nC->clearMinimumAndMaximumSupplierList(); +} + +std::vector<LegendEntryProvider*> SeriesPlotterContainer::getLegendEntryProviderList() +{ + std::vector<LegendEntryProvider*> aRet(m_aSeriesPlotterList.size()); + sal_Int32 nN = 0; + for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList) + aRet[nN++] = aPlotter.get(); + return aRet; +} + +VCoordinateSystem* SeriesPlotterContainer::findInCooSysList( + const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList, + const rtl::Reference<BaseCoordinateSystem>& xCooSys) +{ + for (auto& pVCooSys : rVCooSysList) + { + if (pVCooSys->getModel() == xCooSys) + return pVCooSys.get(); + } + return nullptr; +} + +VCoordinateSystem* SeriesPlotterContainer::getCooSysForPlotter( + const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList, + MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier) +{ + if (!pMinimumAndMaximumSupplier) + return nullptr; + for (auto& pVCooSys : rVCooSysList) + { + if (pVCooSys->hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier)) + return pVCooSys.get(); + } + return nullptr; +} + +VCoordinateSystem* SeriesPlotterContainer::addCooSysToList( + std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList, + const rtl::Reference<BaseCoordinateSystem>& xCooSys, ChartModel& rChartModel) +{ + VCoordinateSystem* pExistingVCooSys + = SeriesPlotterContainer::findInCooSysList(rVCooSysList, xCooSys); + if (pExistingVCooSys) + return pExistingVCooSys; + + std::unique_ptr<VCoordinateSystem> pVCooSys + = VCoordinateSystem::createCoordinateSystem(xCooSys); + if (!pVCooSys) + return nullptr; + + OUString aCooSysParticle( + ObjectIdentifier::createParticleForCoordinateSystem(xCooSys, &rChartModel)); + pVCooSys->setParticle(aCooSysParticle); + + pVCooSys->setExplicitCategoriesProvider(new ExplicitCategoriesProvider(xCooSys, rChartModel)); + rVCooSysList.push_back(std::move(pVCooSys)); + return rVCooSysList.back().get(); +} + +void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(ChartModel& rChartModel) +{ + rtl::Reference<Diagram> xDiagram = rChartModel.getFirstChartDiagram(); + if (!xDiagram.is()) + return; + + uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(&rChartModel); + if (rChartModel.hasInternalDataProvider() && xDiagram->isSupportingDateAxis()) + m_nDefaultDateNumberFormat = DiagramHelper::getDateNumberFormat(xNumberFormatsSupplier); + + sal_Int32 nDimensionCount = xDiagram->getDimension(); + if (!nDimensionCount) + { + //@todo handle mixed dimension + nDimensionCount = 2; + } + + bool bSortByXValues = false; + bool bConnectBars = false; + bool bGroupBarsPerAxis = true; + bool bIncludeHiddenCells = true; + bool bSecondaryYaxisVisible = true; + sal_Int32 nStartingAngle = 90; + sal_Int32 n3DRelativeHeight = 100; + PieChartSubType ePieChartSubType = PieChartSubType_NONE; + try + { + xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= bSortByXValues; + xDiagram->getPropertyValue("ConnectBars") >>= bConnectBars; + xDiagram->getPropertyValue("GroupBarsPerAxis") >>= bGroupBarsPerAxis; + xDiagram->getPropertyValue("IncludeHiddenCells") >>= bIncludeHiddenCells; + xDiagram->getPropertyValue("StartingAngle") >>= nStartingAngle; + + if (nDimensionCount == 3) + { + xDiagram->getPropertyValue("3DRelativeHeight") >>= n3DRelativeHeight; + } + xDiagram->getPropertyValue("SubPieType") >>= ePieChartSubType; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + if (xDiagram->getDataTable().is()) + m_bTableShiftPosition = true; + + //prepare for autoscaling and shape creation + // - create plotter for charttypes (for each first scale group at each plotter, as they are independent) + // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling) + // - add plotter to coordinate systems + + //iterate through all coordinate systems + uno::Reference<XColorScheme> xColorScheme(xDiagram->getDefaultColorScheme()); + auto aCooSysList = xDiagram->getBaseCoordinateSystems(); + sal_Int32 nGlobalSeriesIndex = 0; //for automatic symbols + for (std::size_t nCS = 0; nCS < aCooSysList.size(); ++nCS) + { + rtl::Reference<BaseCoordinateSystem> xCooSys(aCooSysList[nCS]); + VCoordinateSystem* pVCooSys + = SeriesPlotterContainer::addCooSysToList(m_rVCooSysList, xCooSys, rChartModel); + // Let's check whether the secondary Y axis is visible + try + { + if (xCooSys->getMaximumAxisIndexByDimension(1) > 0) + { + rtl::Reference<Axis> xAxisProp = xCooSys->getAxisByDimension2(1, 1); + xAxisProp->getPropertyValue("Show") >>= bSecondaryYaxisVisible; + } + } + catch (const lang::IndexOutOfBoundsException&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } + //iterate through all chart types in the current coordinate system + std::vector<rtl::Reference<ChartType>> aChartTypeList(xCooSys->getChartTypes2()); + for (std::size_t nT = 0; nT < aChartTypeList.size(); ++nT) + { + rtl::Reference<ChartType> xChartType(aChartTypeList[nT]); + if (nDimensionCount == 3 + && xChartType->getChartType().equalsIgnoreAsciiCase( + CHART2_SERVICE_NAME_CHARTTYPE_PIE)) + { + try + { + sal_Int32 n3DRelativeHeightOldValue(100); + uno::Any aAny = xChartType->getFastPropertyValue( + PROP_PIECHARTTYPE_3DRELATIVEHEIGHT); // "3DRelativeHeight" + aAny >>= n3DRelativeHeightOldValue; + if (n3DRelativeHeightOldValue != n3DRelativeHeight) + xChartType->setFastPropertyValue( + PROP_PIECHARTTYPE_3DRELATIVEHEIGHT, // "3DRelativeHeight" + uno::Any(n3DRelativeHeight)); + } + catch (const uno::Exception&) + { + } + } + + if (ePieChartSubType != PieChartSubType_NONE) + { + xChartType->setFastPropertyValue(PROP_PIECHARTTYPE_SUBTYPE, + uno::Any(ePieChartSubType)); + } + + if (nT == 0) + m_bChartTypeUsesShiftedCategoryPositionPerDefault + = ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault(xChartType); + + bool bExcludingPositioning + = xDiagram->getDiagramPositioningMode() == DiagramPositioningMode::Excluding; + VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( + xChartType, nDimensionCount, bExcludingPositioning); + if (!pPlotter) + continue; + + m_aSeriesPlotterList.push_back(std::unique_ptr<VSeriesPlotter>(pPlotter)); + pPlotter->setNumberFormatsSupplier(xNumberFormatsSupplier); + pPlotter->setColorScheme(xColorScheme); + if (pVCooSys) + pPlotter->setExplicitCategoriesProvider(pVCooSys->getExplicitCategoriesProvider()); + sal_Int32 nMissingValueTreatment + = xDiagram->getCorrectedMissingValueTreatment(xChartType); + + if (pVCooSys) + pVCooSys->addMinimumAndMaximumSupplier(pPlotter); + + sal_Int32 zSlot = -1; + sal_Int32 xSlot = -1; + sal_Int32 ySlot = -1; + const std::vector<rtl::Reference<DataSeries>>& aSeriesList + = xChartType->getDataSeries2(); + for (std::size_t nS = 0; nS < aSeriesList.size(); ++nS) + { + rtl::Reference<DataSeries> const& xDataSeries = aSeriesList[nS]; + if (!bIncludeHiddenCells && !xDataSeries->hasUnhiddenData()) + continue; + + std::unique_ptr<VDataSeries> pSeries(new VDataSeries(xDataSeries)); + + pSeries->setGlobalSeriesIndex(nGlobalSeriesIndex); + nGlobalSeriesIndex++; + + if (bSortByXValues) + pSeries->doSortByXValues(); + + pSeries->setConnectBars(bConnectBars); + pSeries->setGroupBarsPerAxis(bGroupBarsPerAxis); + pSeries->setStartingAngle(nStartingAngle); + + pSeries->setMissingValueTreatment(nMissingValueTreatment); + + OUString aSeriesParticle(ObjectIdentifier::createParticleForSeries(0, nCS, nT, nS)); + pSeries->setParticle(aSeriesParticle); + + OUString aRole(ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( + xChartType)); + pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole); + + //ignore secondary axis for charttypes that do not support them + if (pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX + && (!ChartTypeHelper::isSupportingSecondaryAxis(xChartType, nDimensionCount) + || !bSecondaryYaxisVisible)) + { + pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX); + } + + StackingDirection eDirection = pSeries->getStackingDirection(); + switch (eDirection) + { + case StackingDirection_NO_STACKING: + xSlot++; + ySlot = -1; + if (zSlot < 0) + zSlot = 0; + break; + case StackingDirection_Y_STACKING: + ySlot++; + if (xSlot < 0) + xSlot = 0; + if (zSlot < 0) + zSlot = 0; + break; + case StackingDirection_Z_STACKING: + zSlot++; + xSlot = -1; + ySlot = -1; + break; + default: + // UNO enums have one additional auto-generated case + break; + } + pPlotter->addSeries(std::move(pSeries), zSlot, xSlot, ySlot); + } + } + } + + auto order + = [](const std::unique_ptr<VSeriesPlotter>& a, const std::unique_ptr<VSeriesPlotter>& b) { + return a->getRenderOrder() < b->getRenderOrder(); + }; + + std::stable_sort(m_aSeriesPlotterList.begin(), m_aSeriesPlotterList.end(), order); + + //transport seriesnames to the coordinatesystems if needed + if (m_aSeriesPlotterList.empty()) + return; + + uno::Sequence<OUString> aSeriesNames; + bool bSeriesNamesInitialized = false; + for (auto& pVCooSys : m_rVCooSysList) + { + if (pVCooSys->needSeriesNamesForAxis()) + { + if (!bSeriesNamesInitialized) + { + aSeriesNames = m_aSeriesPlotterList[0]->getSeriesNames(); + bSeriesNamesInitialized = true; + } + pVCooSys->setSeriesNamesForAxis(aSeriesNames); + } + } +} + +bool SeriesPlotterContainer::isCategoryPositionShifted(const chart2::ScaleData& rSourceScale, + bool bHasComplexCategories) +{ + if (rSourceScale.AxisType == AxisType::CATEGORY) + return bHasComplexCategories || rSourceScale.ShiftedCategoryPosition + || m_bTableShiftPosition || m_bChartTypeUsesShiftedCategoryPositionPerDefault; + + if (rSourceScale.AxisType == AxisType::DATE) + return rSourceScale.ShiftedCategoryPosition; + + return rSourceScale.AxisType == AxisType::SERIES; +} + +void SeriesPlotterContainer::initAxisUsageList(const Date& rNullDate) +{ + m_aAxisUsageList.clear(); + + // Loop through coordinate systems in the diagram (though for now + // there should only be one coordinate system per diagram). + for (auto& pVCooSys : m_rVCooSysList) + { + rtl::Reference<BaseCoordinateSystem> xCooSys = pVCooSys->getModel(); + sal_Int32 nDimCount = xCooSys->getDimension(); + bool bComplexCategoryAllowed = ChartTypeHelper::isSupportingComplexCategory( + AxisHelper::getChartTypeByIndex(xCooSys, 0)); + + for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex) + { + bool bDateAxisAllowed = ChartTypeHelper::isSupportingDateAxis( + AxisHelper::getChartTypeByIndex(xCooSys, 0), nDimIndex); + + // Each dimension may have primary and secondary axes. + const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex); + for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; ++nAxisIndex) + { + rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(nDimIndex, nAxisIndex); + + if (!xAxis.is()) + continue; + + if (m_aAxisUsageList.find(xAxis) == m_aAxisUsageList.end()) + { + // Create axis usage object for this axis. + + chart2::ScaleData aSourceScale = xAxis->getScaleData(); + ExplicitCategoriesProvider* pCatProvider + = pVCooSys->getExplicitCategoriesProvider(); + if (nDimIndex == 0) + AxisHelper::checkDateAxis(aSourceScale, pCatProvider, bDateAxisAllowed); + + bool bHasComplexCat = pCatProvider && pCatProvider->hasComplexCategories() + && bComplexCategoryAllowed; + aSourceScale.ShiftedCategoryPosition + = isCategoryPositionShifted(aSourceScale, bHasComplexCat); + + m_aAxisUsageList[xAxis].aAutoScaling = ScaleAutomatism(aSourceScale, rNullDate); + } + + AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis]; + rAxisUsage.addCoordinateSystem(pVCooSys.get(), nDimIndex, nAxisIndex); + } + } + } + + // Determine the highest axis index of all dimensions. + m_nMaxAxisIndex = 0; + for (const auto& pVCooSys : m_rVCooSysList) + { + uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel(); + sal_Int32 nDimCount = xCooSys->getDimension(); + + for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex) + { + for (auto& axisUsage : m_aAxisUsageList) + { + sal_Int32 nLocalMax = axisUsage.second.getMaxAxisIndexForDimension(nDimIndex); + if (m_nMaxAxisIndex < nLocalMax) + m_nMaxAxisIndex = nLocalMax; + } + } + } +} + +void SeriesPlotterContainer::setScalesFromCooSysToPlotter() +{ + //set scales to plotter to enable them to provide the preferred scene AspectRatio + for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList) + { + VSeriesPlotter* pSeriesPlotter = aPlotter.get(); + VCoordinateSystem* pVCooSys + = SeriesPlotterContainer::getCooSysForPlotter(m_rVCooSysList, pSeriesPlotter); + if (pVCooSys) + { + pSeriesPlotter->setScales(pVCooSys->getExplicitScales(0, 0), + pVCooSys->getPropertySwapXAndYAxis()); + sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension( + 1); //only additional value axis are relevant for series plotter + for (sal_Int32 nI = 1; nI <= nMaxAxisIndex; nI++) + pSeriesPlotter->addSecondaryValueScale(pVCooSys->getExplicitScale(1, nI), nI); + } + } +} + +void SeriesPlotterContainer::setNumberFormatsFromAxes() +{ + //set numberformats to plotter to enable them to display the data labels in the numberformat of the axis + for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList) + { + VSeriesPlotter* pSeriesPlotter = aPlotter.get(); + VCoordinateSystem* pVCooSys + = SeriesPlotterContainer::getCooSysForPlotter(m_rVCooSysList, pSeriesPlotter); + if (pVCooSys) + { + AxesNumberFormats aAxesNumberFormats; + const rtl::Reference<BaseCoordinateSystem>& xCooSys = pVCooSys->getModel(); + sal_Int32 nDimensionCount = xCooSys->getDimension(); + for (sal_Int32 nDimensionIndex = 0; nDimensionIndex < nDimensionCount; + ++nDimensionIndex) + { + const sal_Int32 nMaximumAxisIndex + = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex); + for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaximumAxisIndex; ++nAxisIndex) + { + try + { + rtl::Reference<Axis> xAxisProp + = xCooSys->getAxisByDimension2(nDimensionIndex, nAxisIndex); + if (xAxisProp.is()) + { + sal_Int32 nNumberFormatKey(0); + if (xAxisProp->getPropertyValue(CHART_UNONAME_NUMFMT) + >>= nNumberFormatKey) + { + aAxesNumberFormats.setFormat(nNumberFormatKey, nDimensionIndex, + nAxisIndex); + } + else if (nDimensionIndex == 0) + { + //provide a default date format for date axis with own data + aAxesNumberFormats.setFormat(m_nDefaultDateNumberFormat, + nDimensionIndex, nAxisIndex); + } + } + } + catch (const lang::IndexOutOfBoundsException&) + { + TOOLS_WARN_EXCEPTION("chart2", ""); + } + } + } + } + } +} + +void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes() +{ + for (auto& nC : m_rVCooSysList) + nC->updateScalesAndIncrementsOnAxes(); +} + +void SeriesPlotterContainer::doAutoScaling(ChartModel& rChartModel) +{ + if (m_aSeriesPlotterList.empty() || m_aAxisUsageList.empty()) + // We need these two containers populated to do auto-scaling. Bail out. + return; + + //iterate over the main scales first than secondary axis + for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; ++nAxisIndex) + { + // - first do autoscale for all x and z scales (because they are treated independent) + for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList) + { + (void)rAxis; + rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 0, nAxisIndex); + rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 2, nAxisIndex); + + ExplicitScaleData aExplicitScale; + ExplicitIncrementData aExplicitIncrement; + rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement(aExplicitScale, + aExplicitIncrement); + + rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale, + aExplicitIncrement); + rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale, + aExplicitIncrement); + } + + // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already ) + for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList) + { + (void)rAxis; + rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, nAxisIndex); + + ExplicitScaleData aExplicitScale; + ExplicitIncrementData aExplicitIncrement; + rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement(aExplicitScale, + aExplicitIncrement); + + rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale, + aExplicitIncrement); + rAxisUsage.setExplicitScaleAndIncrement(1, nAxisIndex, aExplicitScale, + aExplicitIncrement); + rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale, + aExplicitIncrement); + } + } + AdaptScaleOfYAxisWithoutAttachedSeries(rChartModel); +} + +void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries(ChartModel& rModel) +{ + //issue #i80518# + for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; nAxisIndex++) + { + for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList) + { + (void)rAxis; + std::vector<VCoordinateSystem*> aVCooSysList_Y + = rAxisUsage.getCoordinateSystems(1, nAxisIndex); + if (aVCooSysList_Y.empty()) + continue; + + rtl::Reference<Diagram> xDiagram(rModel.getFirstChartDiagram()); + if (!xDiagram.is()) + continue; + + bool bSeriesAttachedToThisAxis = false; + sal_Int32 nAttachedAxisIndex = -1; + { + std::vector<rtl::Reference<DataSeries>> aSeriesVector = xDiagram->getDataSeries(); + for (auto const& series : aSeriesVector) + { + sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex(series); + if (nAxisIndex == nCurrentIndex) + { + bSeriesAttachedToThisAxis = true; + break; + } + else if (nAttachedAxisIndex < 0 || nAttachedAxisIndex > nCurrentIndex) + nAttachedAxisIndex = nCurrentIndex; + } + } + + if (bSeriesAttachedToThisAxis || nAttachedAxisIndex < 0) + continue; + + for (VCoordinateSystem* nC : aVCooSysList_Y) + { + nC->prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, nAttachedAxisIndex); + + ExplicitScaleData aExplicitScaleSource + = nC->getExplicitScale(1, nAttachedAxisIndex); + ExplicitIncrementData aExplicitIncrementSource + = nC->getExplicitIncrement(1, nAttachedAxisIndex); + + ExplicitScaleData aExplicitScaleDest = nC->getExplicitScale(1, nAxisIndex); + ExplicitIncrementData aExplicitIncrementDest + = nC->getExplicitIncrement(1, nAxisIndex); + + aExplicitScaleDest.Orientation = aExplicitScaleSource.Orientation; + aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling; + aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType; + + aExplicitIncrementDest.BaseValue = aExplicitIncrementSource.BaseValue; + + ScaleData aScale(rAxisUsage.aAutoScaling.getScale()); + if (!aScale.Minimum.hasValue()) + { + bool bNewMinOK = true; + double fMax = 0.0; + if (aScale.Maximum >>= fMax) + bNewMinOK = (aExplicitScaleSource.Minimum <= fMax); + if (bNewMinOK) + aExplicitScaleDest.Minimum = aExplicitScaleSource.Minimum; + } + else + aExplicitIncrementDest.BaseValue = aExplicitScaleDest.Minimum; + + if (!aScale.Maximum.hasValue()) + { + bool bNewMaxOK = true; + double fMin = 0.0; + if (aScale.Minimum >>= fMin) + bNewMaxOK = (fMin <= aExplicitScaleSource.Maximum); + if (bNewMaxOK) + aExplicitScaleDest.Maximum = aExplicitScaleSource.Maximum; + } + if (!aScale.Origin.hasValue()) + aExplicitScaleDest.Origin = aExplicitScaleSource.Origin; + + if (!aScale.IncrementData.Distance.hasValue()) + aExplicitIncrementDest.Distance = aExplicitIncrementSource.Distance; + + bool bAutoMinorInterval = true; + if (aScale.IncrementData.SubIncrements.hasElements()) + bAutoMinorInterval + = !(aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue()); + if (bAutoMinorInterval) + { + if (!aExplicitIncrementDest.SubIncrements.empty() + && !aExplicitIncrementSource.SubIncrements.empty()) + aExplicitIncrementDest.SubIncrements[0].IntervalCount + = aExplicitIncrementSource.SubIncrements[0].IntervalCount; + } + + nC->setExplicitScaleAndIncrement(1, nAxisIndex, aExplicitScaleDest, + aExplicitIncrementDest); + } + } + } + + if (!AxisHelper::isAxisPositioningEnabled()) + return; + + //correct origin for y main axis (the origin is where the other main axis crosses) + sal_Int32 nAxisIndex = 0; + sal_Int32 nDimensionIndex = 1; + for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList) + { + (void)rAxis; + std::vector<VCoordinateSystem*> aVCooSysList + = rAxisUsage.getCoordinateSystems(nDimensionIndex, nAxisIndex); + size_t nC; + for (nC = 0; nC < aVCooSysList.size(); nC++) + { + ExplicitScaleData aExplicitScale( + aVCooSysList[nC]->getExplicitScale(nDimensionIndex, nAxisIndex)); + ExplicitIncrementData aExplicitIncrement( + aVCooSysList[nC]->getExplicitIncrement(nDimensionIndex, nAxisIndex)); + + rtl::Reference<BaseCoordinateSystem> xCooSys(aVCooSysList[nC]->getModel()); + rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(nDimensionIndex, nAxisIndex); + rtl::Reference<Axis> xCrossingMainAxis + = AxisHelper::getCrossingMainAxis(xAxis, xCooSys); + + if (xCrossingMainAxis.is()) + { + css::chart::ChartAxisPosition eCrossingMainAxisPos( + css::chart::ChartAxisPosition_ZERO); + xCrossingMainAxis->getPropertyValue("CrossoverPosition") >>= eCrossingMainAxisPos; + if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_VALUE) + { + double fValue = 0.0; + xCrossingMainAxis->getPropertyValue("CrossoverValue") >>= fValue; + aExplicitScale.Origin = fValue; + } + else if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_ZERO) + aExplicitScale.Origin = 0.0; + else if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_START) + aExplicitScale.Origin = aExplicitScale.Minimum; + else if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_END) + aExplicitScale.Origin = aExplicitScale.Maximum; + } + + aVCooSysList[nC]->setExplicitScaleAndIncrement(nDimensionIndex, nAxisIndex, + aExplicitScale, aExplicitIncrement); + } + } +} + +drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio() +{ + drawing::Direction3D aPreferredAspectRatio(1.0, 1.0, 1.0); + + //get a list of all preferred aspect ratios and combine them + //first with special demands wins (less or equal zero <-> arbitrary) + double fx, fy, fz; + fx = fy = fz = -1.0; + for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList) + { + drawing::Direction3D aSingleRatio(aPlotter->getPreferredDiagramAspectRatio()); + if (fx < 0 && aSingleRatio.DirectionX > 0) + fx = aSingleRatio.DirectionX; + + if (fy < 0 && aSingleRatio.DirectionY > 0) + { + if (fx > 0 && aSingleRatio.DirectionX > 0) + fy = fx * aSingleRatio.DirectionY / aSingleRatio.DirectionX; + else if (fz > 0 && aSingleRatio.DirectionZ > 0) + fy = fz * aSingleRatio.DirectionY / aSingleRatio.DirectionZ; + else + fy = aSingleRatio.DirectionY; + } + + if (fz < 0 && aSingleRatio.DirectionZ > 0) + { + if (fx > 0 && aSingleRatio.DirectionX > 0) + fz = fx * aSingleRatio.DirectionZ / aSingleRatio.DirectionX; + else if (fy > 0 && aSingleRatio.DirectionY > 0) + fz = fy * aSingleRatio.DirectionZ / aSingleRatio.DirectionY; + else + fz = aSingleRatio.DirectionZ; + } + + if (fx > 0 && fy > 0 && fz > 0) + break; + } + aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz); + return aPreferredAspectRatio; +} + +} //end chart2 namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/SeriesPlotterContainer.hxx b/chart2/source/view/main/SeriesPlotterContainer.hxx new file mode 100644 index 000000000000..38f3c8b909c8 --- /dev/null +++ b/chart2/source/view/main/SeriesPlotterContainer.hxx @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <config_feature_desktop.h> +#include <VSeriesPlotter.hxx> +#include <BaseCoordinateSystem.hxx> +#include "AxisUsage.hxx" + +namespace chart +{ +/** This class is a container of `SeriesPlotter` objects (such as `PieChart` + * instances). It is used for initializing coordinate systems, axes and scales + * of all series plotters which belongs to the container. + */ +class SeriesPlotterContainer +{ +public: + explicit SeriesPlotterContainer(std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList); + ~SeriesPlotterContainer(); + + /** It is used to set coordinate systems (`m_rVCooSysList`), this method + * is invoked by `ChartView::createShapes2D` before of + * `ChartView::impl_createDiagramAndContent`. + * Coordinate systems are retrieved through the `XCoordinateSystemContainer` + * interface implemented by a diagram object which is provided by the + * `ChartModel` object passed to the method (`rChartModel.getFirstDiagram()`). + * + * It is used for creating series plotters and appending them + * to `m_aSeriesPlotterList`. The created series plotters are initialized + * through data (number formats supplier, color scheme, data series), + * extracted from the chart model or the diagram objects. An exception is + * the explicit category provider that is retrieved through the + * `VCoordinateSystem` object used by the series plotter. + * + * It sets the minimum-maximum supplier for a coordinate system: + * this supplier is the series plotter itself which utilizes the given + * coordinate system. In fact `VSeriesPlotter` has `MinimumMaximumSupplier` + * as one of its base classes. + * Hence, for instance, a `PieChart`, which is a series plotter, is + * a `MinimumMaximumSupplier`, too. + */ + void initializeCooSysAndSeriesPlotter(ChartModel& rModel); + + /** This method is invoked by `ChartView::impl_createDiagramAndContent`. + * It iterates on every axis of every coordinate systems, and if the axis + * is not yet present in `m_aAxisUsageList` it creates a new `AxisUsage` + * object and initialize its `aAutoScaling` member to the `ScaleData` + * object of the current axis. + */ + void initAxisUsageList(const Date& rNullDate); + + /** + * Perform automatic axis scaling and determine the amount and spacing of + * increments. It assumes that the caller has determined the size of the + * largest axis label text object prior to calling this method. + * + * The new axis scaling data will be stored in the VCoordinateSystem + * objects. The label alignment direction for each axis will also get + * determined during this process, and stored in VAxis. + * + * This method is invoked by `ChartView::impl_createDiagramAndContent` + * soon after `initAxisUsageList`. + * It initializes explicit scale and increment objects for all coordinate + * systems in `m_rVCooSysList`. + * This action is achieved by iterating on the `m_aAxisUsageList` container, + * and performing 3 steps: + * 1- call `VCoordinateSystem::prepareAutomaticAxisScaling` for setting + * scaling parameters of the `aAutoScaling` member (a `ScaleAutomatism` + * object) for the current `AxisUsage` instance + * (see `VCoordinateSystem::prepareAutomaticAxisScaling`); + * 2- calculate the explicit scale and increment objects + * (see ScaleAutomatism::calculateExplicitScaleAndIncrement); + * 3- set the explicit scale and increment objects for each coordinate + * system. + */ + void doAutoScaling(ChartModel& rModel); + + /** + * After auto-scaling is performed, call this method to set the explicit + * scaling and increment data to all relevant VAxis objects. + */ + void updateScalesAndIncrementsOnAxes(); + + /** + * After auto-scaling is performed, call this method to set the explicit + * scaling data to all the plotters. + */ + void setScalesFromCooSysToPlotter(); + + void setNumberFormatsFromAxes(); + css::drawing::Direction3D getPreferredAspectRatio(); + + std::vector<std::unique_ptr<VSeriesPlotter>>& getSeriesPlotterList() + { + return m_aSeriesPlotterList; + } + std::vector<std::unique_ptr<VCoordinateSystem>>& getCooSysList() { return m_rVCooSysList; } + std::vector<LegendEntryProvider*> getLegendEntryProviderList(); + + void AdaptScaleOfYAxisWithoutAttachedSeries(ChartModel& rModel); + + bool isCategoryPositionShifted(const css::chart2::ScaleData& rSourceScale, + bool bHasComplexCategories); + + static VCoordinateSystem* + getCooSysForPlotter(const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList, + MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier); + static VCoordinateSystem* + addCooSysToList(std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList, + const rtl::Reference<BaseCoordinateSystem>& xCooSys, ChartModel& rChartModel); + static VCoordinateSystem* + findInCooSysList(const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList, + const rtl::Reference<BaseCoordinateSystem>& xCooSys); + +private: + /** A vector of series plotters. + */ + std::vector<std::unique_ptr<VSeriesPlotter>> m_aSeriesPlotterList; + + /** A vector of coordinate systems. + */ + std::vector<std::unique_ptr<VCoordinateSystem>>& m_rVCooSysList; + + /** A map whose key is a `XAxis` interface and the related value is + * an object of `AxisUsage` type. + */ + std::map<rtl::Reference<Axis>, AxisUsage> m_aAxisUsageList; + + /** + * Max axis index of all dimensions. Currently this can be either 0 or 1 + * since we only support primary and secondary axes per dimension. The + * value of 0 means all dimensions have only primary axis, while 1 means + * at least one dimension has a secondary axis. + */ + sal_Int32 m_nMaxAxisIndex; + + bool m_bChartTypeUsesShiftedCategoryPositionPerDefault; + bool m_bTableShiftPosition = false; + sal_Int32 m_nDefaultDateNumberFormat; +}; + +} //end chart2 namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx index b2e19781c8ef..c681c581a7b3 100644 --- a/chart2/source/view/main/ShapeFactory.cxx +++ b/chart2/source/view/main/ShapeFactory.cxx @@ -26,7 +26,6 @@ #include <PropertyMapper.hxx> #include <VLineProperties.hxx> #include <com/sun/star/beans/XPropertySet.hpp> -#include <com/sun/star/beans/XMultiPropertySet.hpp> #include <com/sun/star/chart2/XFormattedString.hpp> #include <com/sun/star/drawing/CircleKind.hpp> #include <com/sun/star/drawing/DoubleSequence.hpp> @@ -39,13 +38,10 @@ #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> #include <com/sun/star/drawing/TextureProjectionMode.hpp> #include <com/sun/star/drawing/TextVerticalAdjust.hpp> -#include <com/sun/star/drawing/XDrawPage.hpp> #include <com/sun/star/drawing/XShapes2.hpp> #include <com/sun/star/graphic/XGraphic.hpp> #include <com/sun/star/drawing/XShapes.hpp> -#include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/style/ParagraphAdjust.hpp> -#include <com/sun/star/text/XText.hpp> #include <com/sun/star/uno/Sequence.hxx> #include <com/sun/star/uno/Any.hxx> @@ -54,11 +50,16 @@ #include <basegfx/point/b2dpoint.hxx> #include <basegfx/matrix/b3dhommatrix.hxx> -#include <tools/diagnose_ex.h> +#include <svx/svdpage.hxx> +#include <svx/svdopath.hxx> +#include <comphelper/diagnose_ex.hxx> #include <tools/helpers.hxx> +#include <tools/UnitConversion.hxx> #include <sal/log.hxx> #include <algorithm> +#include <cmath> +#include <cstddef> using namespace ::com::sun::star; using ::com::sun::star::uno::Reference; @@ -73,36 +74,63 @@ void lcl_addProperty(uno::Sequence<OUString> & rPropertyNames, uno::Sequence<uno OUString const & rName, uno::Any const & rAny) { rPropertyNames.realloc(rPropertyNames.getLength() + 1); - rPropertyNames[rPropertyNames.getLength() - 1] = rName; + rPropertyNames.getArray()[rPropertyNames.getLength() - 1] = rName; rPropertyValues.realloc(rPropertyValues.getLength() + 1); - rPropertyValues[rPropertyValues.getLength() - 1] = rAny; + rPropertyValues.getArray()[rPropertyValues.getLength() - 1] = rAny; +} + +css::drawing::PolyPolygonShape3D toPolyPolygonShape3D(const std::vector<std::vector<css::drawing::Position3D>>& rPoints) +{ + css::drawing::PolyPolygonShape3D aUnoPoly; + aUnoPoly.SequenceX.realloc(rPoints.size()); + aUnoPoly.SequenceY.realloc(rPoints.size()); + aUnoPoly.SequenceZ.realloc(rPoints.size()); + for (std::size_t nPolygonIndex=0; nPolygonIndex<rPoints.size(); ++nPolygonIndex) + { + drawing::DoubleSequence* pOuterSequenceX = &aUnoPoly.SequenceX.getArray()[nPolygonIndex]; + drawing::DoubleSequence* pOuterSequenceY = &aUnoPoly.SequenceY.getArray()[nPolygonIndex]; + drawing::DoubleSequence* pOuterSequenceZ = &aUnoPoly.SequenceZ.getArray()[nPolygonIndex]; + pOuterSequenceX->realloc(rPoints[nPolygonIndex].size()); + pOuterSequenceY->realloc(rPoints[nPolygonIndex].size()); + pOuterSequenceZ->realloc(rPoints[nPolygonIndex].size()); + double* pInnerSequenceX = pOuterSequenceX->getArray(); + double* pInnerSequenceY = pOuterSequenceY->getArray(); + double* pInnerSequenceZ = pOuterSequenceZ->getArray(); + for (std::size_t nPointIndex=0; nPointIndex<rPoints[nPolygonIndex].size(); ++nPointIndex) + { + auto& rPos = rPoints[nPolygonIndex][nPointIndex]; + pInnerSequenceX[nPointIndex] = rPos.PositionX; + pInnerSequenceY[nPointIndex] = rPos.PositionY; + pInnerSequenceZ[nPointIndex] = rPos.PositionZ; + } + } + return aUnoPoly; } } // end anonymous namespace -uno::Reference< drawing::XShapes > ShapeFactory::getOrCreateChartRootShape( - const uno::Reference< drawing::XDrawPage>& xDrawPage ) +rtl::Reference<SvxShapeGroupAnyD> ShapeFactory::getOrCreateChartRootShape( + const rtl::Reference<SvxDrawPage>& xDrawPage ) { - uno::Reference<drawing::XShapes> xRet = ShapeFactory::getChartRootShape(xDrawPage); + rtl::Reference<SvxShapeGroupAnyD> xRet = ShapeFactory::getChartRootShape(xDrawPage); if (xRet.is()) return xRet; // Create a new root shape and set it to the bottom of the page. The root // shape is identified by having the name com.sun.star.chart2.shapes. - uno::Reference<drawing::XShape> xShape( - m_xShapeFactory->createInstance("com.sun.star.drawing.GroupShape"), uno::UNO_QUERY); - uno::Reference<drawing::XShapes2> xShapes2(xDrawPage, uno::UNO_QUERY_THROW); - xShapes2->addBottom(xShape); + rtl::Reference<SvxShapeGroup> xShapeGroup = new SvxShapeGroup(nullptr, nullptr); + xShapeGroup->setShapeKind(SdrObjKind::Group); + // cast to resolve ambiguity in converting to XShape + xDrawPage->addBottom(static_cast<SvxShape*>(xShapeGroup.get())); - setShapeName(xShape, "com.sun.star.chart2.shapes"); - xShape->setSize(awt::Size(0,0)); + setShapeName(xShapeGroup, "com.sun.star.chart2.shapes"); + xShapeGroup->setSize(awt::Size(0,0)); - xRet.set(xShape, uno::UNO_QUERY); - return xRet; + return xShapeGroup; } -void ShapeFactory::setPageSize(const uno::Reference<drawing::XShapes>&, const awt::Size&) {} +void ShapeFactory::setPageSize(const rtl::Reference<SvxShapeGroupAnyD>&, const awt::Size&) {} // diverse tools::PolyPolygon create methods @@ -356,9 +384,9 @@ static uno::Any createPolyPolygon_Cone( double fHeight, double fRadius, double f // methods for 3D shape creation -uno::Reference<drawing::XShape> +rtl::Reference<Svx3DExtrudeObject> ShapeFactory::createCube( - const uno::Reference<drawing::XShapes>& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize , sal_Int32 nRotateZAngleHundredthDegree , const uno::Reference< beans::XPropertySet >& xSourceProp @@ -384,16 +412,15 @@ uno::Reference<drawing::XShape> TOOLS_WARN_EXCEPTION("chart2", "" ); } } - uno::Reference<drawing::XShape> xShape = impl_createCube( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree, bRounded ); - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + rtl::Reference<Svx3DExtrudeObject> xShape = impl_createCube( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree, bRounded ); if( xSourceProp.is()) - PropertyMapper::setMappedProperties( xProp, xSourceProp, rPropertyNameMap ); + PropertyMapper::setMappedProperties( *xShape, xSourceProp, rPropertyNameMap ); return xShape; } -uno::Reference<drawing::XShape> +rtl::Reference<Svx3DExtrudeObject> ShapeFactory::impl_createCube( - const uno::Reference<drawing::XShapes>& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize , sal_Int32 nRotateZAngleHundredthDegree , bool bRounded ) @@ -402,60 +429,54 @@ uno::Reference<drawing::XShape> return nullptr; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<Svx3DExtrudeObject> xShape = new Svx3DExtrudeObject(nullptr); + xShape->setShapeKind(SdrObjKind::E3D_Extrusion); + xTarget->addShape(*xShape); //set properties - uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY); - OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); - if (xMultiPropertySet.is()) + try { - try - { - //depth - double fDepth = rSize.DirectionZ; - if (fDepth<0) - fDepth*=-1.0; - - //PercentDiagonal - sal_Int16 nPercentDiagonal = bRounded ? 3 : 0; - - //Matrix for position - basegfx::B3DHomMatrix aHomMatrix; - if (nRotateZAngleHundredthDegree != 0) - aHomMatrix.rotate(0.0, 0.0, -nRotateZAngleHundredthDegree / 18000.00 * F_PI); - aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY, - rPosition.PositionZ - (fDepth / 2.0)); - - uno::Sequence<OUString> aPropertyNames { - UNO_NAME_3D_EXTRUDE_DEPTH, - UNO_NAME_3D_PERCENT_DIAGONAL, - UNO_NAME_3D_POLYPOLYGON3D, - UNO_NAME_3D_TRANSFORM_MATRIX, - }; - - uno::Sequence<uno::Any> aPropertyValues { - uno::Any(sal_Int32(fDepth)), // Depth - uno::Any(nPercentDiagonal), // PercentDiagonal - createPolyPolygon_Cube(rSize, double(nPercentDiagonal) / 200.0, bRounded), - uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix)) - }; - - xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + //depth + double fDepth = rSize.DirectionZ; + if (fDepth<0) + fDepth*=-1.0; + + //PercentDiagonal + sal_Int16 nPercentDiagonal = bRounded ? 3 : 0; + + //Matrix for position + basegfx::B3DHomMatrix aHomMatrix; + if (nRotateZAngleHundredthDegree != 0) + aHomMatrix.rotate(0.0, 0.0, -basegfx::deg2rad<100>(nRotateZAngleHundredthDegree)); + aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY, + rPosition.PositionZ - (fDepth / 2.0)); + + uno::Sequence<OUString> aPropertyNames { + UNO_NAME_3D_EXTRUDE_DEPTH, + UNO_NAME_3D_PERCENT_DIAGONAL, + UNO_NAME_3D_POLYPOLYGON3D, + UNO_NAME_3D_TRANSFORM_MATRIX, + }; + + uno::Sequence<uno::Any> aPropertyValues { + uno::Any(sal_Int32(fDepth)), // Depth + uno::Any(nPercentDiagonal), // PercentDiagonal + createPolyPolygon_Cube(rSize, double(nPercentDiagonal) / 200.0, bRounded), + uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix)) + }; + + xShape->setPropertyValues(aPropertyNames, aPropertyValues); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } -uno::Reference<drawing::XShape> +rtl::Reference<Svx3DLatheObject> ShapeFactory::createCylinder( - const uno::Reference<drawing::XShapes>& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize , sal_Int32 nRotateZAngleHundredthDegree ) { @@ -463,9 +484,9 @@ uno::Reference<drawing::XShape> xTarget, rPosition, rSize, 0.0, nRotateZAngleHundredthDegree, true ); } -uno::Reference<drawing::XShape> +rtl::Reference<Svx3DSceneObject> ShapeFactory::createPyramid( - const uno::Reference<drawing::XShapes>& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize , double fTopHeight, bool bRotateZ , const uno::Reference< beans::XPropertySet >& xSourceProp @@ -474,7 +495,7 @@ uno::Reference<drawing::XShape> if( !xTarget.is() ) return nullptr; - Reference< drawing::XShapes > xGroup( ShapeFactory::createGroup3D( xTarget ) ); + rtl::Reference<Svx3DSceneObject> xGroup( ShapeFactory::createGroup3D( xTarget ) ); bool bDoubleSided = false; short nRotatedTexture = 0; @@ -620,21 +641,21 @@ uno::Reference<drawing::XShape> ShapeFactory::createStripe( xGroup, aStripe4, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals ); ShapeFactory::createStripe( xGroup, aStripeBottom, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals ); - return Reference< drawing::XShape >( xGroup, uno::UNO_QUERY ); + return xGroup; } -uno::Reference<drawing::XShape> +rtl::Reference<Svx3DLatheObject> ShapeFactory::createCone( - const uno::Reference<drawing::XShapes>& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree ) { return impl_createConeOrCylinder( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree, false ); } -uno::Reference<drawing::XShape> +rtl::Reference<Svx3DLatheObject> ShapeFactory::impl_createConeOrCylinder( - const uno::Reference<drawing::XShapes>& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree , bool bCylinder ) @@ -643,60 +664,54 @@ uno::Reference<drawing::XShape> return nullptr; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.Shape3DLatheObject" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<Svx3DLatheObject> xShape = new Svx3DLatheObject(nullptr); + xShape->setShapeKind(SdrObjKind::E3D_Lathe); + xTarget->addShape(*xShape); double fWidth = rSize.DirectionX/2.0; //The depth will be corrected within Matrix double fRadius = fWidth; //!!!!!!!! problem in drawing layer: rotation object calculates wrong needed size -> wrong camera (it's a problem with bounding boxes) double fHeight = rSize.DirectionY; //set properties - uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY); - OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); - if (xMultiPropertySet.is()) + try { - try - { - //Polygon - sal_Int32 nVerticalSegmentCount = 0; - uno::Any aPPolygon = bCylinder - ? createPolyPolygon_Cylinder(fHeight, fRadius, nVerticalSegmentCount) - : createPolyPolygon_Cone(fHeight, fRadius, fTopHeight, nVerticalSegmentCount); - - //Matrix for position - basegfx::B3DHomMatrix aHomMatrix; - if (nRotateZAngleHundredthDegree != 0) - aHomMatrix.rotate(0.0,0.0,-nRotateZAngleHundredthDegree/18000.00*F_PI); - //stretch the symmetric objects to given depth - aHomMatrix.scale(1.0,1.0,rSize.DirectionZ/rSize.DirectionX); - aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ); - - uno::Sequence<OUString> aPropertyNames{ - UNO_NAME_3D_PERCENT_DIAGONAL, - UNO_NAME_3D_POLYPOLYGON3D, - UNO_NAME_3D_TRANSFORM_MATRIX, - UNO_NAME_3D_HORZ_SEGS, - UNO_NAME_3D_VERT_SEGS, - UNO_NAME_3D_REDUCED_LINE_GEOMETRY - }; - - uno::Sequence<uno::Any> aPropertyValues { - uno::Any(sal_Int16(5)), // PercentDiagonal - aPPolygon, // Polygon - uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix)), // Matrix - uno::Any(CHART_3DOBJECT_SEGMENTCOUNT), // Horizontal Segments - uno::Any(nVerticalSegmentCount), // Vertical Segments - uno::Any(true) // Reduced lines - }; - - xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + //Polygon + sal_Int32 nVerticalSegmentCount = 0; + uno::Any aPPolygon = bCylinder + ? createPolyPolygon_Cylinder(fHeight, fRadius, nVerticalSegmentCount) + : createPolyPolygon_Cone(fHeight, fRadius, fTopHeight, nVerticalSegmentCount); + + //Matrix for position + basegfx::B3DHomMatrix aHomMatrix; + if (nRotateZAngleHundredthDegree != 0) + aHomMatrix.rotate(0.0,0.0,-basegfx::deg2rad<100>(nRotateZAngleHundredthDegree)); + //stretch the symmetric objects to given depth + aHomMatrix.scale(1.0,1.0,rSize.DirectionZ/rSize.DirectionX); + aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ); + + uno::Sequence<OUString> aPropertyNames{ + UNO_NAME_3D_PERCENT_DIAGONAL, + UNO_NAME_3D_POLYPOLYGON3D, + UNO_NAME_3D_TRANSFORM_MATRIX, + UNO_NAME_3D_HORZ_SEGS, + UNO_NAME_3D_VERT_SEGS, + UNO_NAME_3D_REDUCED_LINE_GEOMETRY + }; + + uno::Sequence<uno::Any> aPropertyValues { + uno::Any(sal_Int16(5)), // PercentDiagonal + aPPolygon, // Polygon + uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix)), // Matrix + uno::Any(CHART_3DOBJECT_SEGMENTCOUNT), // Horizontal Segments + uno::Any(nVerticalSegmentCount), // Vertical Segments + uno::Any(true) // Reduced lines + }; + + xShape->setPropertyValues(aPropertyNames, aPropertyValues); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } @@ -711,19 +726,23 @@ static void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rRetur sal_Int32 nOldCount = rReturn.Coordinates[0].getLength(); - rReturn.Coordinates[0].realloc(nOldCount+nAddCount+1); - rReturn.Flags[0].realloc(nOldCount+nAddCount+1); + auto pCoordinates = rReturn.Coordinates.getArray(); + pCoordinates[0].realloc(nOldCount + nAddCount + 1); + auto pCoordinates0 = pCoordinates[0].getArray(); + auto pFlags = rReturn.Flags.getArray(); + pFlags[0].realloc(nOldCount+nAddCount+1); + auto pFlags0 = pFlags[0].getArray(); for(sal_Int32 nN=0;nN<nAddCount; nN++ ) { sal_Int32 nAdd = bAppendInverse ? (nAddCount-1-nN) : nN; - rReturn.Coordinates[0][nOldCount+nN] = rAdd.Coordinates[0][nAdd]; - rReturn.Flags[0][nOldCount+nN] = rAdd.Flags[0][nAdd]; + pCoordinates0[nOldCount+nN] = rAdd.Coordinates[0][nAdd]; + pFlags0[nOldCount+nN] = rAdd.Flags[0][nAdd]; } //close - rReturn.Coordinates[0][nOldCount+nAddCount] = rReturn.Coordinates[0][0]; - rReturn.Flags[0][nOldCount+nAddCount] = rReturn.Flags[0][0]; + pCoordinates0[nOldCount+nAddCount] = rReturn.Coordinates[0][0]; + pFlags0[nOldCount+nAddCount] = rReturn.Flags[0][0]; } static drawing::PolyPolygonBezierCoords getCircularArcBezierCoords( @@ -748,9 +767,9 @@ static drawing::PolyPolygonBezierCoords getCircularArcBezierCoords( } else { - double fFirstAngleOnSubDevision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian; - if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDevision ) ) - fFirstSegmentAngle = fFirstAngleOnSubDevision-fStartAngleRadian; + double fFirstAngleOnSubDivision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian; + if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDivision ) ) + fFirstSegmentAngle = fFirstAngleOnSubDivision-fStartAngleRadian; if(nSegmentCount>1) { @@ -767,11 +786,10 @@ static drawing::PolyPolygonBezierCoords getCircularArcBezierCoords( sal_Int32 nPointCount = 1 + 3*nSegmentCount; //first point of next segment equals last point of former segment - aReturn.Coordinates = drawing::PointSequenceSequence(1); - aReturn.Flags = drawing::FlagSequenceSequence(1); - drawing::PointSequence aPoints(nPointCount); + auto pPoints = aPoints.getArray(); drawing::FlagSequence aFlags(nPointCount); + auto pFlags = aFlags.getArray(); //!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector ::basegfx::B2DPoint P0,P1,P2,P3; @@ -781,7 +799,7 @@ static drawing::PolyPolygonBezierCoords getCircularArcBezierCoords( for(sal_Int32 nSegment=0; nSegment<nSegmentCount; nSegment++) { double fCurrentSegmentAngle = fAngleSubdivisionRadian; - if(nSegment==0)//first segment gets only a smaller peace until the next subdevision + if(nSegment==0)//first segment gets only a smaller peace until the next subdivision fCurrentSegmentAngle = fFirstSegmentAngle; else if(nSegment==(nSegmentCount-1)) //the last segment gets the rest angle that does not fit into equal pieces fCurrentSegmentAngle = fLastSegmentAngle; @@ -811,28 +829,28 @@ static drawing::PolyPolygonBezierCoords getCircularArcBezierCoords( P2 = rTransformationFromUnitCircle*(aStart*P2); P3 = rTransformationFromUnitCircle*(aStart*P3); - aPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX()); - aPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY()); - aFlags [nPoint++] = drawing::PolygonFlags_NORMAL; + pPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX()); + pPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY()); + pFlags [nPoint++] = drawing::PolygonFlags_NORMAL; - aPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX()); - aPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY()); - aFlags[nPoint++] = drawing::PolygonFlags_CONTROL; + pPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX()); + pPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY()); + pFlags[nPoint++] = drawing::PolygonFlags_CONTROL; - aPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX()); - aPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY()); - aFlags [nPoint++] = drawing::PolygonFlags_CONTROL; + pPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX()); + pPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY()); + pFlags [nPoint++] = drawing::PolygonFlags_CONTROL; if(nSegment==(nSegmentCount-1)) { - aPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX()); - aPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY()); - aFlags [nPoint++] = drawing::PolygonFlags_NORMAL; + pPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX()); + pPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY()); + pFlags [nPoint++] = drawing::PolygonFlags_NORMAL; } } - aReturn.Coordinates[0] = aPoints; - aReturn.Flags[0] = aFlags; + aReturn.Coordinates = { aPoints }; + aReturn.Flags = { aFlags }; return aReturn; } @@ -846,13 +864,10 @@ static drawing::PolyPolygonBezierCoords getRingBezierCoords( { drawing::PolyPolygonBezierCoords aReturn; - aReturn.Coordinates = drawing::PointSequenceSequence(1); - aReturn.Flags = drawing::FlagSequenceSequence(1); - drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords( fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian ); - aReturn.Coordinates[0] = aOuterArc.Coordinates[0]; - aReturn.Flags[0] = aOuterArc.Flags[0]; + aReturn.Coordinates = { aOuterArc.Coordinates[0] }; + aReturn.Flags = { aOuterArc.Flags[0] }; drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords( fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian ); @@ -861,9 +876,9 @@ static drawing::PolyPolygonBezierCoords getRingBezierCoords( return aReturn; } -uno::Reference< drawing::XShape > +rtl::Reference<SvxShapePolyPolygon> ShapeFactory::createPieSegment2D( - const uno::Reference< drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius , const drawing::Direction3D& rOffset @@ -879,43 +894,43 @@ uno::Reference< drawing::XShape > fUnitCircleWidthAngleDegree += 360.0; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.ClosedBezierShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); //need to add the shape before setting of properties + rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr); + xShape->setShapeKind(SdrObjKind::PathFill); // aka ClosedBezierShape + xTarget->addShape(*xShape); //need to add the shape before setting of properties + + if (std::isnan(fUnitCircleWidthAngleDegree)) + { + SAL_WARN("chart2", "fUnitCircleWidthAngleDegree isNaN"); + return xShape; + } //set properties - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); - if( xProp.is()) + try { - try - { - ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) ); - aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY); + ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) ); + aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY); - const double fAngleSubdivisionRadian = F_PI/10.0; + const double fAngleSubdivisionRadian = M_PI/10.0; - drawing::PolyPolygonBezierCoords aCoords - = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius, - basegfx::deg2rad(fUnitCircleStartAngleDegree), - basegfx::deg2rad(fUnitCircleWidthAngleDegree), - aTransformationFromUnitCircle, fAngleSubdivisionRadian); + drawing::PolyPolygonBezierCoords aCoords + = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius, + basegfx::deg2rad(fUnitCircleStartAngleDegree), + basegfx::deg2rad(fUnitCircleWidthAngleDegree), + aTransformationFromUnitCircle, fAngleSubdivisionRadian); - xProp->setPropertyValue( "PolyPolygonBezier", uno::Any( aCoords ) ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + xShape->SvxShape::setPropertyValue( "PolyPolygonBezier", uno::Any( aCoords ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } -uno::Reference< drawing::XShape > +rtl::Reference<Svx3DExtrudeObject> ShapeFactory::createPieSegment( - const uno::Reference< drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius , const drawing::Direction3D& rOffset @@ -932,71 +947,65 @@ uno::Reference< drawing::XShape > fUnitCircleWidthAngleDegree += 360.0; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY ); - xTarget->add(xShape); //need to add the shape before setting of properties + rtl::Reference<Svx3DExtrudeObject> xShape = new Svx3DExtrudeObject(nullptr); + xShape->setShapeKind(SdrObjKind::E3D_Extrusion); + xTarget->addShape(*xShape); //need to add the shape before setting of properties //set properties - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); - if( xProp.is()) + try { - try - { - ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) ); - aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY); - - const double fAngleSubdivisionRadian = F_PI/32.0; - - drawing::PolyPolygonBezierCoords aCoords - = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius, - basegfx::deg2rad(fUnitCircleStartAngleDegree), - basegfx::deg2rad(fUnitCircleWidthAngleDegree), - aTransformationFromUnitCircle, fAngleSubdivisionRadian); - - //depth - xProp->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH - , uno::Any(static_cast<sal_Int32>(fDepth)) ); - - //PercentDiagonal - xProp->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL - , uno::Any( sal_Int16(0) ) ); - - //Polygon - drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) ); - ShapeFactory::closePolygon( aPoly ); - xProp->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D - , uno::Any( aPoly ) ); - - //DoubleSided - xProp->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED - , uno::Any( true ) ); - - //Reduced lines - xProp->setPropertyValue( UNO_NAME_3D_REDUCED_LINE_GEOMETRY - , uno::Any( true ) ); - - //TextureProjectionMode - xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y - , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) ); - - //TextureProjectionMode - xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_X - , uno::Any( drawing::TextureProjectionMode_PARALLEL ) ); - xProp->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y - , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) ); + aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY); + + const double fAngleSubdivisionRadian = M_PI/32.0; + + drawing::PolyPolygonBezierCoords aCoords + = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius, + basegfx::deg2rad(fUnitCircleStartAngleDegree), + basegfx::deg2rad(fUnitCircleWidthAngleDegree), + aTransformationFromUnitCircle, fAngleSubdivisionRadian); + + //depth + xShape->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH + , uno::Any(static_cast<sal_Int32>(fDepth)) ); + + //PercentDiagonal + xShape->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL + , uno::Any( sal_Int16(0) ) ); + + //Polygon + drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) ); + ShapeFactory::closePolygon( aPoly ); + xShape->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D + , uno::Any( aPoly ) ); + + //DoubleSided + xShape->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED + , uno::Any( true ) ); + + //Reduced lines + xShape->setPropertyValue( UNO_NAME_3D_REDUCED_LINE_GEOMETRY + , uno::Any( true ) ); + + //TextureProjectionMode + xShape->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y + , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) ); + + //TextureProjectionMode + xShape->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_X + , uno::Any( drawing::TextureProjectionMode_PARALLEL ) ); + xShape->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y + , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createStripe( const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference<Svx3DPolygonObject> + ShapeFactory::createStripe( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const Stripe& rStripe , const uno::Reference< beans::XPropertySet >& xSourceProp , const tPropertyNameMap& rPropertyNameMap @@ -1008,155 +1017,131 @@ uno::Reference< drawing::XShape > return nullptr; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<Svx3DPolygonObject> xShape = new Svx3DPolygonObject(nullptr); + xShape->setShapeKind(SdrObjKind::E3D_Polygon); + xTarget->addShape(*xShape); //set properties - uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY); - OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); - if (xMultiPropertySet.is()) + try { - try - { - uno::Sequence<OUString> aPropertyNames{ - UNO_NAME_3D_POLYPOLYGON3D, - UNO_NAME_3D_TEXTUREPOLYGON3D, - UNO_NAME_3D_NORMALSPOLYGON3D, - UNO_NAME_3D_LINEONLY, - UNO_NAME_3D_DOUBLE_SIDED - }; - - uno::Sequence<uno::Any> aPropertyValues { - rStripe.getPolyPolygonShape3D(), // Polygon - Stripe::getTexturePolygon(nRotatedTexture), // TexturePolygon - rStripe.getNormalsPolygon(), // Normals Polygon - uno::Any(false), // LineOnly - uno::Any(bDoubleSided) // DoubleSided - }; - - //NormalsKind - if (bFlatNormals) - lcl_addProperty(aPropertyNames, aPropertyValues, - UNO_NAME_3D_NORMALS_KIND, uno::Any(drawing::NormalsKind_FLAT)); - - xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues); - - uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY); - if (xSourceProp.is() && xPropertySet.is()) - { - PropertyMapper::setMappedProperties(xPropertySet, xSourceProp, rPropertyNameMap); - } - } - catch( const uno::Exception& ) + uno::Sequence<OUString> aPropertyNames{ + UNO_NAME_3D_POLYPOLYGON3D, + UNO_NAME_3D_TEXTUREPOLYGON3D, + UNO_NAME_3D_NORMALSPOLYGON3D, + UNO_NAME_3D_LINEONLY, + UNO_NAME_3D_DOUBLE_SIDED + }; + + uno::Sequence<uno::Any> aPropertyValues { + rStripe.getPolyPolygonShape3D(), // Polygon + Stripe::getTexturePolygon(nRotatedTexture), // TexturePolygon + rStripe.getNormalsPolygon(), // Normals Polygon + uno::Any(false), // LineOnly + uno::Any(bDoubleSided) // DoubleSided + }; + + //NormalsKind + if (bFlatNormals) + lcl_addProperty(aPropertyNames, aPropertyValues, + UNO_NAME_3D_NORMALS_KIND, uno::Any(drawing::NormalsKind_FLAT)); + + xShape->setPropertyValues(aPropertyNames, aPropertyValues); + + if (xSourceProp) { - TOOLS_WARN_EXCEPTION("chart2", "" ); + PropertyMapper::setMappedProperties(*xShape, xSourceProp, rPropertyNameMap); } } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createArea3D( const uno::Reference< drawing::XShapes >& xTarget - , const drawing::PolyPolygonShape3D& rPolyPolygon +rtl::Reference<Svx3DExtrudeObject> + ShapeFactory::createArea3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon , double fDepth ) { if( !xTarget.is() ) return nullptr; - if( !rPolyPolygon.SequenceX.hasElements()) + if( rPolyPolygon.empty() ) return nullptr; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.Shape3DExtrudeObject" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<Svx3DExtrudeObject> xShape = new Svx3DExtrudeObject(nullptr); + xShape->setShapeKind(SdrObjKind::E3D_Extrusion); + xTarget->addShape(*xShape); + + css::drawing::PolyPolygonShape3D aUnoPolyPolygon = toPolyPolygonShape3D(rPolyPolygon); //set properties - uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY); - OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); - if (xMultiPropertySet.is()) + try { - try - { - uno::Sequence<OUString> aPropertyNames{ - UNO_NAME_3D_EXTRUDE_DEPTH, - UNO_NAME_3D_PERCENT_DIAGONAL, - UNO_NAME_3D_POLYPOLYGON3D, - UNO_NAME_3D_DOUBLE_SIDED, - }; - - uno::Sequence<uno::Any> aPropertyValues { - uno::Any(sal_Int32(fDepth)), // depth - uno::Any(sal_Int16(0)), // PercentDiagonal - uno::Any(rPolyPolygon), // Polygon - uno::Any(true) // DoubleSided - }; - - //the z component of the polygon is now ignored by the drawing layer, - //so we need to translate the object via transformation matrix - - //Matrix for position - if (rPolyPolygon.SequenceZ.hasElements()&& rPolyPolygon.SequenceZ[0].hasElements()) - { - basegfx::B3DHomMatrix aM; - aM.translate(0, 0, rPolyPolygon.SequenceZ[0][0]); - drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM); - lcl_addProperty(aPropertyNames, aPropertyValues, UNO_NAME_3D_TRANSFORM_MATRIX, uno::Any(aHM)); - } - xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + uno::Sequence<OUString> aPropertyNames{ + UNO_NAME_3D_EXTRUDE_DEPTH, + UNO_NAME_3D_PERCENT_DIAGONAL, + UNO_NAME_3D_POLYPOLYGON3D, + UNO_NAME_3D_DOUBLE_SIDED, + }; + + uno::Sequence<uno::Any> aPropertyValues { + uno::Any(sal_Int32(fDepth)), // depth + uno::Any(sal_Int16(0)), // PercentDiagonal + uno::Any(aUnoPolyPolygon), // Polygon + uno::Any(true) // DoubleSided + }; + + //the z component of the polygon is now ignored by the drawing layer, + //so we need to translate the object via transformation matrix + + //Matrix for position + if (!rPolyPolygon.empty() && !rPolyPolygon[0].empty()) + { + basegfx::B3DHomMatrix aM; + aM.translate(0, 0, rPolyPolygon[0][0].PositionZ); + drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM); + lcl_addProperty(aPropertyNames, aPropertyValues, UNO_NAME_3D_TRANSFORM_MATRIX, uno::Any(aHM)); + } + xShape->setPropertyValues(aPropertyNames, aPropertyValues); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createArea2D( const uno::Reference< drawing::XShapes >& xTarget - , const drawing::PolyPolygonShape3D& rPolyPolygon ) +rtl::Reference<SvxShapePolyPolygon> + ShapeFactory::createArea2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon ) { if( !xTarget.is() ) return nullptr; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SdrPathObj> pPath = new SdrPathObj(xTarget->GetSdrObject()->getSdrModelFromSdrObject(), SdrObjKind::Polygon); + xTarget->GetSdrObject()->GetSubList()->InsertObject(pPath.get()); //set properties - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); - if( xProp.is()) + try { - try - { - //UNO_NAME_POLYGON "Polygon" drawing::PointSequence* - drawing::PointSequenceSequence aPoints( PolyToPointSequence(rPolyPolygon) ); - - //Polygon - xProp->setPropertyValue( UNO_NAME_POLYPOLYGON - , uno::Any( aPoints ) ); - - //ZOrder - //an area should always be behind other shapes - xProp->setPropertyValue( UNO_NAME_MISC_OBJ_ZORDER - , uno::Any( sal_Int32(0) ) ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + // Polygon + basegfx::B2DPolyPolygon aNewPolyPolygon( PolyToB2DPolyPolygon(rPolyPolygon) ); + // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm + pPath->ForceMetricToItemPoolMetric(aNewPolyPolygon); + pPath->SetPathPoly(aNewPolyPolygon); } - return xShape; + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return static_cast<SvxShapePolyPolygon*>(pPath->getUnoShape().get()); } -static drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Position3D& rPos +static drawing::PointSequenceSequence createPolyPolygon_Symbol( const drawing::Position3D& rPos , const drawing::Direction3D& rSize , sal_Int32 nStandardSymbol ) { @@ -1203,267 +1188,196 @@ static drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Posi break; } - drawing::PolyPolygonShape3D aPP; - - aPP.SequenceX.realloc(1); - aPP.SequenceY.realloc(1); - aPP.SequenceZ.realloc(1); + drawing::PointSequenceSequence aPP; - drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray(); - drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray(); - drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray(); + aPP.realloc(1); - pOuterSequenceX->realloc(nPointCount); - pOuterSequenceY->realloc(nPointCount); - pOuterSequenceZ->realloc(nPointCount); + uno::Sequence<awt::Point>* pOuterSequence = aPP.getArray(); - double* pInnerSequenceX = pOuterSequenceX->getArray(); - double* pInnerSequenceY = pOuterSequenceY->getArray(); - double* pInnerSequenceZ = pOuterSequenceZ->getArray(); + pOuterSequence->realloc(nPointCount); - for(sal_Int32 nN = nPointCount; nN--;) - *pInnerSequenceZ++ = 0.0; + awt::Point* pInnerSequence = pOuterSequence->getArray(); + auto toPoint = [](double x, double y) -> awt::Point + { + return { static_cast<sal_Int32>(x), static_cast<sal_Int32>(y) }; + }; switch(eSymbolType) { case Symbol_Square: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); break; } case Symbol_UpArrow: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH ); break; } case Symbol_DownArrow: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); break; } case Symbol_RightArrow: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX+fWidthH, fY ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); break; } case Symbol_LeftArrow: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX-fWidthH, fY ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX-fWidthH, fY ); break; } case Symbol_Bowtie: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); break; } case Symbol_Sandglass: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH ); break; } case Symbol_Diamond: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX-fWidthH, fY ); - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX+fWidthH, fY ); - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX-fWidthH, fY ); break; } case Symbol_HorizontalBar: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-0.2*fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-0.2*fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY-0.2*fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY-0.2*fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY+0.2*fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY+0.2*fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+0.2*fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+0.2*fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-0.2*fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-0.2*fHeightH ); break; } case Symbol_VerticalBar: { - *pInnerSequenceX++ = fX-0.2*fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX+0.2*fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX+0.2*fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX-0.2*fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX-0.2*fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY-fHeightH ); break; } case Symbol_Circle: { - double fOmega = 1.5707963267948966192 / (nQuarterCount + 1.0); + double fOmega = M_PI_2 / (nQuarterCount + 1.0); // one point in the middle of each edge to get full size bounding rectangle - *pInnerSequenceX++ = fX + fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX + fWidthH, fY ); // 0 to PI/2 for (sal_Int32 i = 1; i <= nQuarterCount; ++i) { - *pInnerSequenceX++ = fX + fWidthH * cos( i * fOmega ); - *pInnerSequenceY++ = fY - fHeightH * sin( i * fOmega ); + *pInnerSequence++ = toPoint( fX + fWidthH * cos( i * fOmega ), fY - fHeightH * sin( i * fOmega ) ); } // PI/2 to PI - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY - fHeightH; + *pInnerSequence++ = toPoint( fX, fY - fHeightH ); for (sal_Int32 i = 1; i <= nQuarterCount; ++i) { - *pInnerSequenceX++ = fX - fWidthH * sin( i * fOmega); - *pInnerSequenceY++ = fY - fHeightH * cos( i * fOmega); + *pInnerSequence++ = toPoint( fX - fWidthH * sin( i * fOmega), fY - fHeightH * cos( i * fOmega) ); } // PI to 3/2*PI - *pInnerSequenceX++ = fX - fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX - fWidthH, fY ); for (sal_Int32 i = 1; i <= nQuarterCount; ++i) { - *pInnerSequenceX++ = fX - fWidthH * cos( i * fOmega); - *pInnerSequenceY++ = fY + fHeightH * sin( i * fOmega); + *pInnerSequence++ = toPoint( fX - fWidthH * cos( i * fOmega), fY + fHeightH * sin( i * fOmega) ); } // 3/2*PI to 2*PI - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY + fHeightH; + *pInnerSequence++ = toPoint( fX, fY + fHeightH ); for (sal_Int32 i = 1; i <= nQuarterCount; ++i) { - *pInnerSequenceX++ = fX + fWidthH * sin(i * fOmega); - *pInnerSequenceY++ = fY + fHeightH * cos(i * fOmega); + *pInnerSequence++ = toPoint( fX + fWidthH * sin(i * fOmega), fY + fHeightH * cos(i * fOmega) ); } // close polygon - *pInnerSequenceX++ = fX + fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX + fWidthH, fY ); break; } case Symbol_Star: { - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX, fY-fHeightH ); - *pInnerSequenceX++ = fX+0.2*fWidthH; - *pInnerSequenceY++ = fY-0.2*fHeightH; + *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY-0.2*fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX+fWidthH, fY ); - *pInnerSequenceX++ = fX+0.2*fWidthH; - *pInnerSequenceY++ = fY+0.2*fHeightH; + *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY+0.2*fHeightH ); - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX, fY+fHeightH ); - *pInnerSequenceX++ = fX-0.2*fWidthH; - *pInnerSequenceY++ = fY+0.2*fHeightH; + *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY+0.2*fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX-fWidthH, fY ); - *pInnerSequenceX++ = fX-0.2*fWidthH; - *pInnerSequenceY++ = fY-0.2*fHeightH; + *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY-0.2*fHeightH ); - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX, fY-fHeightH ); break; } case Symbol_X: @@ -1473,44 +1387,31 @@ static drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Posi const double fSmall = sqrt(200.0); const double fLarge = 128.0 - fSmall; - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY - fScaleY * fSmall; + *pInnerSequence++ = toPoint( fX, fY - fScaleY * fSmall ); - *pInnerSequenceX++ = fX - fScaleX * fLarge; - *pInnerSequenceY++ = fY - fHeightH; + *pInnerSequence++ = toPoint( fX - fScaleX * fLarge, fY - fHeightH ); - *pInnerSequenceX++ = fX - fWidthH; - *pInnerSequenceY++ = fY - fScaleY * fLarge; + *pInnerSequence++ = toPoint( fX - fWidthH, fY - fScaleY * fLarge ); - *pInnerSequenceX++ = fX - fScaleX * fSmall; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX - fScaleX * fSmall, fY ); - *pInnerSequenceX++ = fX - fWidthH; - *pInnerSequenceY++ = fY + fScaleY * fLarge; + *pInnerSequence++ = toPoint( fX - fWidthH, fY + fScaleY * fLarge ); - *pInnerSequenceX++ = fX - fScaleX * fLarge; - *pInnerSequenceY++ = fY + fHeightH; + *pInnerSequence++ = toPoint( fX - fScaleX * fLarge, fY + fHeightH ); - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY + fScaleY * fSmall; + *pInnerSequence++ = toPoint( fX, fY + fScaleY * fSmall ); - *pInnerSequenceX++ = fX + fScaleX * fLarge; - *pInnerSequenceY++ = fY + fHeightH; + *pInnerSequence++ = toPoint( fX + fScaleX * fLarge, fY + fHeightH ); - *pInnerSequenceX++ = fX + fWidthH; - *pInnerSequenceY++ = fY + fScaleY * fLarge; + *pInnerSequence++ = toPoint( fX + fWidthH, fY + fScaleY * fLarge ); - *pInnerSequenceX++ = fX + fScaleX * fSmall; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX + fScaleX * fSmall, fY ); - *pInnerSequenceX++ = fX + fWidthH; - *pInnerSequenceY++ = fY - fScaleY * fLarge; + *pInnerSequence++ = toPoint( fX + fWidthH, fY - fScaleY * fLarge ); - *pInnerSequenceX++ = fX + fScaleX * fLarge; - *pInnerSequenceY++ = fY - fHeightH; + *pInnerSequence++ = toPoint( fX + fScaleX * fLarge, fY - fHeightH ); - *pInnerSequenceX++ = fX; - *pInnerSequenceY++ = fY - fScaleY * fSmall; + *pInnerSequence++ = toPoint( fX, fY - fScaleY * fSmall ); break; } @@ -1522,44 +1423,31 @@ static drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Posi const double fdX = fScaleX * fHalf; const double fdY = fScaleY * fHalf; - *pInnerSequenceX++ = fX-fdX; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fdX, fY-fHeightH ); - *pInnerSequenceX++ = fX-fdX; - *pInnerSequenceY++ = fY-fdY; + *pInnerSequence++ = toPoint( fX-fdX, fY-fdY ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fdY; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fdY ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fdY; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fdY ); - *pInnerSequenceX++ = fX-fdX; - *pInnerSequenceY++ = fY+fdY; + *pInnerSequence++ = toPoint( fX-fdX, fY+fdY ); - *pInnerSequenceX++ = fX-fdX; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fdX, fY+fHeightH ); - *pInnerSequenceX++ = fX+fdX; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX+fdX, fY+fHeightH ); - *pInnerSequenceX++ = fX+fdX; - *pInnerSequenceY++ = fY+fdY; + *pInnerSequence++ = toPoint( fX+fdX, fY+fdY ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY+fdY; + *pInnerSequence++ = toPoint( fX+fWidthH, fY+fdY ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY-fdY; + *pInnerSequence++ = toPoint( fX+fWidthH, fY-fdY ); - *pInnerSequenceX++ = fX+fdX; - *pInnerSequenceY++ = fY-fdY; + *pInnerSequence++ = toPoint( fX+fdX, fY-fdY ); - *pInnerSequenceX++ = fX+fdY; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX+fdY, fY-fHeightH ); - *pInnerSequenceX++ = fX-fdX; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fdX, fY-fHeightH ); break; } @@ -1576,80 +1464,56 @@ static drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Posi const double fScaleY = fHeightH / 128.0; //1 - *pInnerSequenceX++ = fX-fScaleX * fHalf; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY-fHeightH ); //2 - *pInnerSequenceX++ = fX-fScaleX * fHalf; - *pInnerSequenceY++ = fY-fScaleY * fTwoY; + *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY-fScaleY * fTwoY ); //3 - *pInnerSequenceX++ = fX-fScaleX * fThreeX; - *pInnerSequenceY++ = fY-fScaleY * fThreeY; + *pInnerSequence++ = toPoint( fX-fScaleX * fThreeX, fY-fScaleY * fThreeY ); //4 - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fScaleY * fFourY; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fScaleY * fFourY ); //5 - *pInnerSequenceX++ = fX-fScaleX * fFiveX; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX-fScaleX * fFiveX, fY ); //6 as 4 - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fScaleY * fFourY; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fScaleY * fFourY ); //7 as 3 - *pInnerSequenceX++ = fX-fScaleX * fThreeX; - *pInnerSequenceY++ = fY+fScaleY * fThreeY; + *pInnerSequence++ = toPoint( fX-fScaleX * fThreeX, fY+fScaleY * fThreeY ); //8 as 2 - *pInnerSequenceX++ = fX-fScaleX * fHalf; - *pInnerSequenceY++ = fY+fScaleY * fTwoY; + *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY+fScaleY * fTwoY ); //9 as 1 - *pInnerSequenceX++ = fX-fScaleX * fHalf; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY+fHeightH ); //10 as 1 - *pInnerSequenceX++ = fX+fScaleX * fHalf; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY+fHeightH ); //11 as 2 - *pInnerSequenceX++ = fX+fScaleX * fHalf; - *pInnerSequenceY++ = fY+fScaleY * fTwoY; + *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY+fScaleY * fTwoY ); //12 as 3 - *pInnerSequenceX++ = fX+fScaleX * fThreeX; - *pInnerSequenceY++ = fY+fScaleY * fThreeY; + *pInnerSequence++ = toPoint( fX+fScaleX * fThreeX, fY+fScaleY * fThreeY ); //13 as 4 - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY+fScaleY * fFourY; + *pInnerSequence++ = toPoint( fX+fWidthH, fY+fScaleY * fFourY ); //14 as 5 - *pInnerSequenceX++ = fX+fScaleX * fFiveX; - *pInnerSequenceY++ = fY; + *pInnerSequence++ = toPoint( fX+fScaleX * fFiveX, fY ); //15 as 4 - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY-fScaleY * fFourY; + *pInnerSequence++ = toPoint( fX+fWidthH, fY-fScaleY * fFourY ); //16 as 3 - *pInnerSequenceX++ = fX+fScaleX * fThreeX; - *pInnerSequenceY++ = fY-fScaleY * fThreeY; + *pInnerSequence++ = toPoint( fX+fScaleX * fThreeX, fY-fScaleY * fThreeY ); //17 as 2 - *pInnerSequenceX++ = fX+fScaleX * fHalf; - *pInnerSequenceY++ = fY-fScaleY * fTwoY; + *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY-fScaleY * fTwoY ); // 18 as 1 - *pInnerSequenceX++ = fX+fScaleX * fHalf; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY-fHeightH ); // 19 = 1, closing - *pInnerSequenceX++ = fX-fScaleX * fHalf; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY-fHeightH ); break; } default: //case Symbol_Square: { - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY+fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH ); - *pInnerSequenceX++ = fX+fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH ); - *pInnerSequenceX++ = fX-fWidthH; - *pInnerSequenceY++ = fY-fHeightH; + *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH ); break; } } @@ -1657,9 +1521,9 @@ static drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const drawing::Posi return aPP; } -uno::Reference< drawing::XShape > +rtl::Reference<SvxShapePolyPolygon> ShapeFactory::createSymbol2D( - const uno::Reference< drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition , const drawing::Direction3D& rSize , sal_Int32 nStandardSymbol @@ -1670,44 +1534,38 @@ uno::Reference< drawing::XShape > return nullptr; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.PolyPolygonShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr); + xShape->setShapeKind(SdrObjKind::Polygon); + xTarget->addShape(*xShape); //set properties - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); - if( xProp.is()) + try { - try - { - drawing::PointSequenceSequence aPoints( PolyToPointSequence( - createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol ) )); + drawing::PointSequenceSequence aPoints = + createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol ); - //Polygon - xProp->setPropertyValue( UNO_NAME_POLYPOLYGON - , uno::Any( aPoints ) ); + //Polygon + xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON + , uno::Any( aPoints ) ); - //LineColor - xProp->setPropertyValue( UNO_NAME_LINECOLOR - , uno::Any( nBorderColor ) ); + //LineColor + xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR + , uno::Any( nBorderColor ) ); - //FillColor - xProp->setPropertyValue( UNO_NAME_FILLCOLOR - , uno::Any( nFillColor ) ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + //FillColor + xShape->SvxShape::setPropertyValue( UNO_NAME_FILLCOLOR + , uno::Any( nFillColor ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } -uno::Reference< drawing::XShape > +rtl::Reference<SvxGraphicObject> ShapeFactory::createGraphic2D( - const uno::Reference< drawing::XShapes >& xTarget + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition , const drawing::Direction3D& rSize , const uno::Reference< graphic::XGraphic >& xGraphic ) @@ -1719,10 +1577,9 @@ uno::Reference< drawing::XShape > // performance reasons (ask AW, said CL) //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.GraphicObjectShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SvxGraphicObject> xShape = new SvxGraphicObject(nullptr); + xShape->setShapeKind(SdrObjKind::Graphic); + xTarget->addShape(*xShape); try { @@ -1738,24 +1595,19 @@ uno::Reference< drawing::XShape > { TOOLS_WARN_EXCEPTION("chart2", "" ); } - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); - if( xProp.is()) + try { - try - { - xProp->setPropertyValue( "Graphic", uno::Any( xGraphic )); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + xShape->SvxShape::setPropertyValue( "Graphic", uno::Any( xGraphic )); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } -uno::Reference< drawing::XShapes > - ShapeFactory::createGroup2D( const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference< SvxShapeGroup > + ShapeFactory::createGroup2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const OUString& aName ) { if( !xTarget.is() ) @@ -1763,23 +1615,21 @@ uno::Reference< drawing::XShapes > try { //create and add to target - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.GroupShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SvxShapeGroup> xShapeGroup = new SvxShapeGroup(nullptr, nullptr); + xShapeGroup->setShapeKind(SdrObjKind::Group); + // cast to resolve ambiguity in converting to XShape + xTarget->addShape(*xShapeGroup); //set name if(!aName.isEmpty()) - setShapeName( xShape , aName ); + setShapeName( xShapeGroup, aName ); {//workaround //need this null size as otherwise empty group shapes where painted with a gray border - xShape->setSize(awt::Size(0,0)); + xShapeGroup->setSize(awt::Size(0,0)); } - //return - uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY ); - return xShapes; + return xShapeGroup; } catch( const uno::Exception& ) { @@ -1788,41 +1638,64 @@ uno::Reference< drawing::XShapes > return nullptr; } -uno::Reference< drawing::XShapes > - ShapeFactory::createGroup3D( const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference< SvxShapeGroup > + ShapeFactory::createGroup2D( const rtl::Reference<SvxDrawPage>& xTarget , const OUString& aName ) { if( !xTarget.is() ) return nullptr; try { - //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.Shape3DSceneObject" ), uno::UNO_QUERY ); + //create and add to target + rtl::Reference<SvxShapeGroup> xShapeGroup = new SvxShapeGroup(nullptr, nullptr); + xShapeGroup->setShapeKind(SdrObjKind::Group); + // cast to resolve ambiguity in converting to XShape + xTarget->add(static_cast<SvxShape*>(xShapeGroup.get())); - xTarget->add(xShape); + //set name + if(!aName.isEmpty()) + setShapeName( xShapeGroup, aName ); + + {//workaround + //need this null size as otherwise empty group shapes where painted with a gray border + xShapeGroup->setSize(awt::Size(0,0)); + } + + return xShapeGroup; + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return nullptr; +} + +rtl::Reference<Svx3DSceneObject> + ShapeFactory::createGroup3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const OUString& aName ) +{ + if( !xTarget.is() ) + return nullptr; + try + { + //create shape + rtl::Reference<Svx3DSceneObject> xShape = new Svx3DSceneObject(nullptr, nullptr); + xShape->setShapeKind(SdrObjKind::E3D_Scene); + xTarget->addShape(*xShape); //it is necessary to set the transform matrix to initialize the scene properly //otherwise all objects which are placed into this Group will not be visible //the following should be unnecessary after the bug is fixed + //set properties + try { - //set properties - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); - if( xProp.is()) - { - try - { - ::basegfx::B3DHomMatrix aM; - xProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX - , uno::Any(B3DHomMatrixToHomogenMatrix(aM)) ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } - } + ::basegfx::B3DHomMatrix aM; + xShape->SvxShape::setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX + , uno::Any(B3DHomMatrixToHomogenMatrix(aM)) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } //set name @@ -1830,8 +1703,7 @@ uno::Reference< drawing::XShapes > setShapeName( xShape , aName ); //return - uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY ); - return xShapes; + return xShape; } catch( const uno::Exception& ) { @@ -1840,8 +1712,8 @@ uno::Reference< drawing::XShapes > return nullptr; } -uno::Reference< drawing::XShape > - ShapeFactory::createCircle2D( const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference<SvxShapeCircle> + ShapeFactory::createCircle2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::Position3D& rPosition , const drawing::Direction3D& rSize ) { @@ -1849,10 +1721,9 @@ uno::Reference< drawing::XShape > return nullptr; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SvxShapeCircle> xShape = new SvxShapeCircle(nullptr); + xShape->setShapeKind(SdrObjKind::CircleOrEllipse); + xTarget->addShape(*xShape); try { @@ -1869,114 +1740,104 @@ uno::Reference< drawing::XShape > } //set properties - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); - if( xProp.is()) + try { - try - { - xProp->setPropertyValue( UNO_NAME_CIRCKIND, uno::Any( drawing::CircleKind_FULL ) ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + xShape->SvxShape::setPropertyValue( UNO_NAME_CIRCKIND, uno::Any( drawing::CircleKind_FULL ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createCircle( const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference<SvxShapeCircle> + ShapeFactory::createCircle( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const awt::Size& rSize , const awt::Point& rPosition ) { - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.EllipseShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SvxShapeCircle> xShape = new SvxShapeCircle(nullptr); + xShape->setShapeKind(SdrObjKind::CircleOrEllipse); + xTarget->addShape(*xShape); xShape->setSize( rSize ); xShape->setPosition( rPosition ); return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createLine3D( const uno::Reference< drawing::XShapes >& xTarget - , const drawing::PolyPolygonShape3D& rPoints +rtl::Reference<Svx3DPolygonObject> + ShapeFactory::createLine3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const std::vector<std::vector<css::drawing::Position3D>>& rPoints , const VLineProperties& rLineProperties ) { if( !xTarget.is() ) return nullptr; - if(!rPoints.SequenceX.hasElements()) + if(rPoints.empty()) return nullptr; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.Shape3DPolygonObject" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<Svx3DPolygonObject> xShape = new Svx3DPolygonObject(nullptr); + xShape->setShapeKind(SdrObjKind::E3D_Polygon); + xTarget->addShape(*xShape); + + css::drawing::PolyPolygonShape3D aUnoPoly = toPolyPolygonShape3D(rPoints); //set properties - uno::Reference<beans::XMultiPropertySet> xMultiPropertySet(xShape, uno::UNO_QUERY); - OSL_ENSURE(xMultiPropertySet.is(), "created shape offers no XMultiPropertySet"); - if (xMultiPropertySet.is()) + try { - try - { - uno::Sequence<OUString> aPropertyNames { - UNO_NAME_3D_POLYPOLYGON3D, - UNO_NAME_3D_LINEONLY - }; + uno::Sequence<OUString> aPropertyNames { + UNO_NAME_3D_POLYPOLYGON3D, + UNO_NAME_3D_LINEONLY + }; - uno::Sequence<uno::Any> aPropertyValues { - uno::Any(rPoints), // Polygon - uno::Any(true) // LineOnly - }; + uno::Sequence<uno::Any> aPropertyValues { + uno::Any(aUnoPoly), // Polygon + uno::Any(true) // LineOnly + }; - //Transparency - if(rLineProperties.Transparence.hasValue()) - { - lcl_addProperty(aPropertyNames, aPropertyValues, - UNO_NAME_LINETRANSPARENCE, - rLineProperties.Transparence); - } - - //LineStyle - if(rLineProperties.LineStyle.hasValue()) - { - lcl_addProperty(aPropertyNames, aPropertyValues, - UNO_NAME_LINESTYLE, - rLineProperties.LineStyle); - } + //Transparency + if(rLineProperties.Transparence.hasValue()) + { + lcl_addProperty(aPropertyNames, aPropertyValues, + UNO_NAME_LINETRANSPARENCE, + rLineProperties.Transparence); + } - //LineWidth - if(rLineProperties.Width.hasValue()) - { - lcl_addProperty(aPropertyNames, aPropertyValues, - UNO_NAME_LINEWIDTH, - rLineProperties.Width); - } + //LineStyle + if(rLineProperties.LineStyle.hasValue()) + { + lcl_addProperty(aPropertyNames, aPropertyValues, + UNO_NAME_LINESTYLE, + rLineProperties.LineStyle); + } - //LineColor - if(rLineProperties.Color.hasValue()) - { - lcl_addProperty(aPropertyNames, aPropertyValues, - UNO_NAME_LINECOLOR, - rLineProperties.Color); - } - xMultiPropertySet->setPropertyValues(aPropertyNames, aPropertyValues); + //LineWidth + if(rLineProperties.Width.hasValue()) + { + lcl_addProperty(aPropertyNames, aPropertyValues, + UNO_NAME_LINEWIDTH, + rLineProperties.Width); } - catch( const uno::Exception& ) + + //LineColor + if(rLineProperties.Color.hasValue()) { - TOOLS_WARN_EXCEPTION("chart2", "" ); + lcl_addProperty(aPropertyNames, aPropertyValues, + UNO_NAME_LINECOLOR, + rLineProperties.Color); } + xShape->setPropertyValues(aPropertyNames, aPropertyValues); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createLine2D( const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference<SvxShapePolyPolygon> + ShapeFactory::createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const drawing::PointSequenceSequence& rPoints , const VLineProperties* pLineProperties ) { @@ -1987,75 +1848,138 @@ uno::Reference< drawing::XShape > return nullptr; //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.PolyLineShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr); + xShape->setShapeKind(SdrObjKind::PolyLine); + xTarget->addShape(*xShape); //set properties - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xProp.is(), "created shape offers no XPropertySet"); - if( xProp.is()) + try { - try + //Polygon + xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON + , uno::Any( rPoints ) ); + + if(pLineProperties) { - //Polygon - xProp->setPropertyValue( UNO_NAME_POLYPOLYGON - , uno::Any( rPoints ) ); + //Transparency + if(pLineProperties->Transparence.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINETRANSPARENCE + , pLineProperties->Transparence ); - if(pLineProperties) - { - //Transparency - if(pLineProperties->Transparence.hasValue()) - xProp->setPropertyValue( UNO_NAME_LINETRANSPARENCE - , pLineProperties->Transparence ); - - //LineStyle - if(pLineProperties->LineStyle.hasValue()) - xProp->setPropertyValue( UNO_NAME_LINESTYLE - , pLineProperties->LineStyle ); - - //LineWidth - if(pLineProperties->Width.hasValue()) - xProp->setPropertyValue( UNO_NAME_LINEWIDTH - , pLineProperties->Width ); - - //LineColor - if(pLineProperties->Color.hasValue()) - xProp->setPropertyValue( UNO_NAME_LINECOLOR - , pLineProperties->Color ); - - //LineDashName - if(pLineProperties->DashName.hasValue()) - xProp->setPropertyValue( "LineDashName" - , pLineProperties->DashName ); - } + //LineStyle + if(pLineProperties->LineStyle.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINESTYLE + , pLineProperties->LineStyle ); + + //LineWidth + if(pLineProperties->Width.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINEWIDTH + , pLineProperties->Width ); + + //LineColor + if(pLineProperties->Color.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR + , pLineProperties->Color ); + + //LineDashName + if(pLineProperties->DashName.hasValue()) + xShape->SvxShape::setPropertyValue( "LineDashName" + , pLineProperties->DashName ); + + //LineCap + if(pLineProperties->LineCap.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINECAP + , pLineProperties->LineCap ); } - catch( const uno::Exception& ) + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + return xShape; +} + +rtl::Reference<SvxShapePolyPolygon> + ShapeFactory::createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const std::vector<std::vector<css::drawing::Position3D>>& rPoints + , const VLineProperties* pLineProperties ) +{ + if( !xTarget.is() ) + return nullptr; + + if(rPoints.empty()) + return nullptr; + + //create shape + rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr); + xShape->setShapeKind(SdrObjKind::PolyLine); + xTarget->addShape(*xShape); + + drawing::PointSequenceSequence aAnyPoints = PolyToPointSequence(rPoints); + + //set properties + try + { + //Polygon + xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON + , uno::Any( aAnyPoints ) ); + + if(pLineProperties) { - TOOLS_WARN_EXCEPTION("chart2", "" ); + //Transparency + if(pLineProperties->Transparence.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINETRANSPARENCE + , pLineProperties->Transparence ); + + //LineStyle + if(pLineProperties->LineStyle.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINESTYLE + , pLineProperties->LineStyle ); + + //LineWidth + if(pLineProperties->Width.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINEWIDTH + , pLineProperties->Width ); + + //LineColor + if(pLineProperties->Color.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR + , pLineProperties->Color ); + + //LineDashName + if(pLineProperties->DashName.hasValue()) + xShape->SvxShape::setPropertyValue( "LineDashName" + , pLineProperties->DashName ); + + //LineCap + if(pLineProperties->LineCap.hasValue()) + xShape->SvxShape::setPropertyValue( UNO_NAME_LINECAP + , pLineProperties->LineCap ); } } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createLine ( const uno::Reference< drawing::XShapes >& xTarget, +rtl::Reference<SvxShapePolyPolygon> + ShapeFactory::createLine ( const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const awt::Size& rSize, const awt::Point& rPosition ) { //create shape - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.LineShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr); + xShape->setShapeKind(SdrObjKind::Line); + xTarget->addShape(*xShape); xShape->setSize( rSize ); xShape->setPosition( rPosition ); return xShape; } -uno::Reference< drawing::XShape > ShapeFactory::createInvisibleRectangle( - const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference<SvxShapeRect> ShapeFactory::createInvisibleRectangle( + const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const awt::Size& rSize ) { try @@ -2063,14 +1987,11 @@ uno::Reference< drawing::XShape > ShapeFactory::createInvisibleRectangle( if(!xTarget.is()) return nullptr; - uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance( - "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY ); - if( xShape.is()) - { - xTarget->add( xShape ); - ShapeFactory::makeShapeInvisible( xShape ); - xShape->setSize( rSize ); - } + rtl::Reference<SvxShapeRect> xShape = new SvxShapeRect(nullptr); + xShape->setShapeKind(SdrObjKind::Rectangle); + xTarget->addShape( *xShape ); + ShapeFactory::makeShapeInvisible( xShape ); + xShape->setSize( rSize ); return xShape; } catch( const uno::Exception & ) @@ -2080,50 +2001,46 @@ uno::Reference< drawing::XShape > ShapeFactory::createInvisibleRectangle( return nullptr; } -uno::Reference< drawing::XShape > ShapeFactory::createRectangle( - const uno::Reference< drawing::XShapes >& xTarget, +rtl::Reference<SvxShapeRect> ShapeFactory::createRectangle( + const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const awt::Size& rSize, const awt::Point& rPosition, const tNameSequence& rPropNames, const tAnySequence& rPropValues, StackPosition ePos ) { - uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance( - "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY ); - if( xShape.is()) + rtl::Reference<SvxShapeRect> xShape = new SvxShapeRect(nullptr); + xShape->setShapeKind(SdrObjKind::Rectangle); + if (ePos == StackPosition::Bottom) { - if (ePos == StackPosition::Bottom) - { - uno::Reference<drawing::XShapes2> xTarget2(xTarget, uno::UNO_QUERY); - if (xTarget2.is()) - xTarget2->addBottom(xShape); - } - else - xTarget->add(xShape); - - xShape->setPosition( rPosition ); - xShape->setSize( rSize ); - uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY_THROW ); - PropertyMapper::setMultiProperties( rPropNames, rPropValues, xPropSet ); + uno::Reference<drawing::XShapes2> xTarget2(static_cast<cppu::OWeakObject*>(xTarget.get()), uno::UNO_QUERY); + assert(xTarget2); + if (xTarget2.is()) + xTarget2->addBottom(xShape); } + else + xTarget->addShape(*xShape); + + xShape->setPosition( rPosition ); + xShape->setSize( rSize ); + PropertyMapper::setMultiProperties( rPropNames, rPropValues, *xShape ); return xShape; } -uno::Reference< drawing::XShape > +rtl::Reference<SvxShapeRect> ShapeFactory::createRectangle( - const uno::Reference< - drawing::XShapes >& xTarget ) + const rtl::Reference<SvxShapeGroupAnyD>& xTarget ) { - uno::Reference< drawing::XShape > xShape( m_xShapeFactory->createInstance( - "com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY ); - xTarget->add( xShape ); + rtl::Reference<SvxShapeRect> xShape = new SvxShapeRect(nullptr); + xShape->setShapeKind(SdrObjKind::Rectangle); + xTarget->addShape( *xShape ); return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget +rtl::Reference<SvxShapeText> + ShapeFactory::createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget , const OUString& rText , const tNameSequence& rPropNames , const tAnySequence& rPropValues @@ -2136,147 +2053,36 @@ uno::Reference< drawing::XShape > return nullptr; //create shape and add to page - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SvxShapeText> xShape = new SvxShapeText(nullptr); + xShape->setShapeKind(SdrObjKind::Text); + xTarget->addShape(*xShape); //set text - uno::Reference< text::XTextRange > xTextRange( xShape, uno::UNO_QUERY ); - if( xTextRange.is() ) - xTextRange->setString( rText ); - - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - if( xProp.is() ) - { - //set properties - PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); - - //set position matrix - //the matrix needs to be set at the end behind autogrow and such position influencing properties - try - { - if (rATransformation.hasValue()) - xProp->setPropertyValue( "Transformation", rATransformation ); - else - SAL_INFO("chart2", "No rATransformation value is given to ShapeFactory::createText()"); + xShape->setString( rText ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } - } - return xShape; -} - -uno::Reference< drawing::XShape > - ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget - , const uno::Sequence< OUString >& rTextParagraphs - , const uno::Sequence< tNameSequence >& rParaPropNames - , const uno::Sequence< tAnySequence >& rParaPropValues - , const tNameSequence& rPropNames - , const tAnySequence& rPropValues - , const uno::Any& rATransformation ) -{ - if( !xTarget.is() ) - return nullptr; - - if( !rTextParagraphs.hasElements() ) - return nullptr; - - sal_Int32 nNumberOfParagraphs = rTextParagraphs.getLength(); - - if( rParaPropNames.getLength() != nNumberOfParagraphs ) - return nullptr; - - if( rParaPropValues.getLength() != nNumberOfParagraphs ) - return nullptr; + //set properties + PropertyMapper::setMultiProperties( rPropNames, rPropValues, *xShape ); - bool bNotEmpty = false; - for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN ) + //set position matrix + //the matrix needs to be set at the end behind autogrow and such position influencing properties + try { - if( !rTextParagraphs[nN].isEmpty() ) - { - bNotEmpty = true; - break; - } - } - if( !bNotEmpty ) - return nullptr; - - //create shape and add to page - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + if (rATransformation.hasValue()) + xShape->SvxShape::setPropertyValue( "Transformation", rATransformation ); + else + SAL_INFO("chart2", "No rATransformation value is given to ShapeFactory::createText()"); - //set paragraph properties - bNotEmpty = false; - Reference< text::XText > xText( xShape, uno::UNO_QUERY ); - if( xText.is() ) - { - // the first cursor is used for appending the next paragraph, - // after a new string has been inserted the cursor is moved at the end - // of the inserted string - // the second cursor is used for selecting the paragraph and apply the - // passed text properties - Reference< text::XTextCursor > xInsertCursor = xText->createTextCursor(); - Reference< text::XTextCursor > xSelectionCursor = xText->createTextCursor(); - if( xInsertCursor.is() && xSelectionCursor.is() ) - { - uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY ); - if( xSelectionProp.is() ) - { - for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN ) - { - if( !rTextParagraphs[nN].isEmpty() ) - { - xInsertCursor->gotoEnd(false); - if( bNotEmpty ) - { - xText->insertString( xInsertCursor, "\n", false ); - } - xSelectionCursor->gotoEnd(false); - xText->insertString( xInsertCursor, rTextParagraphs[nN], false ); - bNotEmpty = true; - xSelectionCursor->gotoEnd(true); // select current paragraph - PropertyMapper::setMultiProperties( rParaPropNames[nN], rParaPropValues[nN], xSelectionProp ); - } - } - } - } } - - if( !bNotEmpty ) - return nullptr; - - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - if( xProp.is() ) + catch( const uno::Exception& ) { - //set whole text shape properties - PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); - - if (rATransformation.hasValue()) - { - //set position matrix - //the matrix needs to be set at the end behind autogrow and such position influencing properties - try - { - xProp->setPropertyValue( "Transformation", rATransformation ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } - } + TOOLS_WARN_EXCEPTION("chart2", "" ); } return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget - , uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString +rtl::Reference<SvxShapeText> + ShapeFactory::createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget + , const uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString , const tNameSequence& rPropNames , const tAnySequence& rPropValues , const uno::Any& rATransformation ) @@ -2302,41 +2108,36 @@ uno::Reference< drawing::XShape > return nullptr; //create shape and add to page - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); - xTarget->add(xShape); + rtl::Reference<SvxShapeText> xShape = new SvxShapeText(nullptr); + xShape->setShapeKind(SdrObjKind::Text); + xTarget->addShape(*xShape); //set paragraph properties bNotEmpty = false; - Reference< text::XText > xText( xShape, uno::UNO_QUERY ); - if( xText.is() ) - { - // the first cursor is used for appending the next paragraph, - // after a new string has been inserted the cursor is moved at the end - // of the inserted string - // the second cursor is used for selecting the paragraph and apply the - // passed text properties - Reference< text::XTextCursor > xInsertCursor = xText->createTextCursor(); - Reference< text::XTextCursor > xSelectionCursor = xText->createTextCursor(); - if( xInsertCursor.is() && xSelectionCursor.is() ) + // the first cursor is used for appending the next paragraph, + // after a new string has been inserted the cursor is moved at the end + // of the inserted string + // the second cursor is used for selecting the paragraph and apply the + // passed text properties + Reference< text::XTextCursor > xInsertCursor = xShape->createTextCursor(); + Reference< text::XTextCursor > xSelectionCursor = xShape->createTextCursor(); + if( xInsertCursor.is() && xSelectionCursor.is() ) + { + uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY ); + if( xSelectionProp.is() ) { - uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY ); - if( xSelectionProp.is() ) + for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN ) { - for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN ) + if( !xFormattedString[nN]->getString().isEmpty() ) { - if( !xFormattedString[nN]->getString().isEmpty() ) - { - xInsertCursor->gotoEnd( false ); - xSelectionCursor->gotoEnd( false ); - xText->insertString( xInsertCursor, xFormattedString[nN]->getString(), false ); - bNotEmpty = true; - xSelectionCursor->gotoEnd( true ); // select current paragraph - uno::Reference< beans::XPropertySet > xStringProperties( xFormattedString[nN], uno::UNO_QUERY ); - PropertyMapper::setMappedProperties( xSelectionProp, xStringProperties, - PropertyMapper::getPropertyNameMapForTextShapeProperties() ); - } + xInsertCursor->gotoEnd( false ); + xSelectionCursor->gotoEnd( false ); + xShape->insertString( xInsertCursor, xFormattedString[nN]->getString(), false ); + bNotEmpty = true; + xSelectionCursor->gotoEnd( true ); // select current paragraph + uno::Reference< beans::XPropertySet > xStringProperties( xFormattedString[nN], uno::UNO_QUERY ); + PropertyMapper::setMappedProperties( xSelectionProp, xStringProperties, + PropertyMapper::getPropertyNameMapForTextShapeProperties() ); } } } @@ -2345,31 +2146,27 @@ uno::Reference< drawing::XShape > if( !bNotEmpty ) return nullptr; - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - if( xProp.is() ) - { - //set whole text shape properties - PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp ); + //set whole text shape properties + PropertyMapper::setMultiProperties( rPropNames, rPropValues, *xShape ); - if( rATransformation.hasValue() ) + if( rATransformation.hasValue() ) + { + //set position matrix + //the matrix needs to be set at the end behind autogrow and such position influencing properties + try { - //set position matrix - //the matrix needs to be set at the end behind autogrow and such position influencing properties - try - { - xProp->setPropertyValue( "Transformation", rATransformation ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + xShape->SvxShape::setPropertyValue( "Transformation", rATransformation ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } } return xShape; } -uno::Reference< drawing::XShape > - ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget, +rtl::Reference<SvxShapeText> + ShapeFactory::createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const awt::Size& rSize, const awt::Point& rPos, uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString, @@ -2378,18 +2175,16 @@ uno::Reference< drawing::XShape > double nRotation, const OUString& aName, sal_Int32 nTextMaxWidth ) { //create shape and add to page - uno::Reference< drawing::XShape > xShape( - m_xShapeFactory->createInstance( - "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY ); + rtl::Reference<SvxShapeText> xShape = new SvxShapeText(nullptr); + xShape->setShapeKind(SdrObjKind::Text); try { - xTarget->add(xShape); + xTarget->addShape(*xShape); //set text and text properties - uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY ); - uno::Reference< text::XTextCursor > xTextCursor( xText->createTextCursor() ); - uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY ); - if( !xText.is() || !xTextCursor.is() || !xShapeProp.is() || !xTextProperties.is() ) + uno::Reference< text::XTextCursor > xTextCursor( xShape->createTextCursor() ); + uno::Reference< text::XTextCursor > xSelectionCursor( xShape->createTextCursor() ); + if( !xTextCursor.is() || !xSelectionCursor.is() ) return xShape; tPropertyNameValueMap aValueMap; @@ -2420,7 +2215,7 @@ uno::Reference< drawing::XShape > tNameSequence aPropNames; tAnySequence aPropValues; PropertyMapper::getMultiPropertyListsFromValueMap( aPropNames, aPropValues, aValueMap ); - PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp ); + PropertyMapper::setMultiProperties( aPropNames, aPropValues, *xShape ); } bool bStackCharacters(false); @@ -2438,65 +2233,88 @@ uno::Reference< drawing::XShape > //if the characters should be stacked we use only the first character properties for code simplicity if( xFormattedString.hasElements() ) { - OUString aLabel; - for( const auto & i : std::as_const(xFormattedString) ) - aLabel += i->getString(); - aLabel = ShapeFactory::getStackedString( aLabel, bStackCharacters ); - - xTextCursor->gotoEnd(false); - xText->insertString( xTextCursor, aLabel, false ); - xTextCursor->gotoEnd(true); - uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY ); - uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY ); - - PropertyMapper::setMappedProperties( xTargetProps, xSourceProps - , PropertyMapper::getPropertyNameMapForCharacterProperties() ); + size_t nLBreaks = xFormattedString.size() - 1; + uno::Reference< beans::XPropertySet > xSelectionProp(xSelectionCursor, uno::UNO_QUERY); + for (const uno::Reference<chart2::XFormattedString>& rxFS : xFormattedString) + { + if (!rxFS->getString().isEmpty()) + { + xTextCursor->gotoEnd(false); + xSelectionCursor->gotoEnd(false); + OUString aLabel = ShapeFactory::getStackedString(rxFS->getString(), bStackCharacters); + if (nLBreaks-- > 0) + aLabel += OUStringChar('\r'); + xShape->insertString(xTextCursor, aLabel, false); + xSelectionCursor->gotoEnd(true); // select current paragraph + uno::Reference< beans::XPropertySet > xSourceProps(rxFS, uno::UNO_QUERY); + if (xFormattedString.size() > 1 && xSelectionProp.is()) + { + PropertyMapper::setMappedProperties(xSelectionProp, xSourceProps, + PropertyMapper::getPropertyNameMapForTextShapeProperties()); + } + else + { + PropertyMapper::setMappedProperties(*xShape, xSourceProps, + PropertyMapper::getPropertyNameMapForTextShapeProperties()); + } + } + } // adapt font size according to page size awt::Size aOldRefSize; if( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize ) { - RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize ); + RelativeSizeHelper::adaptFontSizes( *xShape, aOldRefSize, rSize ); } } } else { - for( const uno::Reference< chart2::XFormattedString >& rxFS : std::as_const(xFormattedString) ) + uno::Reference< beans::XPropertySet > xSelectionProp(xSelectionCursor, uno::UNO_QUERY); + for (const uno::Reference<chart2::XFormattedString>& rxFS : xFormattedString) { - xTextCursor->gotoEnd(false); - xText->insertString( xTextCursor, rxFS->getString(), false ); - xTextCursor->gotoEnd(true); + if (!rxFS->getString().isEmpty()) + { + xTextCursor->gotoEnd(false); + xSelectionCursor->gotoEnd(false); + xShape->insertString(xTextCursor, rxFS->getString(), false); + xSelectionCursor->gotoEnd(true); // select current paragraph + uno::Reference< beans::XPropertySet > xSourceProps(rxFS, uno::UNO_QUERY); + if (xFormattedString.size() > 1 && xSelectionProp.is()) + { + PropertyMapper::setMappedProperties(xSelectionProp, xSourceProps, + PropertyMapper::getPropertyNameMapForTextShapeProperties()); + } + else + { + PropertyMapper::setMappedProperties(*xShape, xSourceProps, + PropertyMapper::getPropertyNameMapForTextShapeProperties()); + } + } } - awt::Size aOldRefSize; - bool bHasRefPageSize = - ( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize ); if( xFormattedString.hasElements() ) { - uno::Reference< beans::XPropertySet > xTargetProps( xShape, uno::UNO_QUERY ); - uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY ); - PropertyMapper::setMappedProperties( xTargetProps, xSourceProps, PropertyMapper::getPropertyNameMapForCharacterProperties() ); - // adapt font size according to page size - if( bHasRefPageSize ) + awt::Size aOldRefSize; + if( xTextProperties->getPropertyValue("ReferencePageSize") >>= aOldRefSize ) { - RelativeSizeHelper::adaptFontSizes( xTargetProps, aOldRefSize, rSize ); + RelativeSizeHelper::adaptFontSizes( *xShape, aOldRefSize, rSize ); } } } // #i109336# Improve auto positioning in chart float fFontHeight = 0.0; - if ( xShapeProp.is() && ( xShapeProp->getPropertyValue( "CharHeight" ) >>= fFontHeight ) ) + if ( xShape->SvxShape::getPropertyValue( "CharHeight" ) >>= fFontHeight ) { - fFontHeight *= ( 2540.0f / 72.0f ); // pt -> 1/100 mm + fFontHeight = convertPointToMm100(fFontHeight); sal_Int32 nXDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.18f ) ); sal_Int32 nYDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.30f ) ); - xShapeProp->setPropertyValue( "TextLeftDistance", uno::Any( nXDistance ) ); - xShapeProp->setPropertyValue( "TextRightDistance", uno::Any( nXDistance ) ); - xShapeProp->setPropertyValue( "TextUpperDistance", uno::Any( nYDistance ) ); - xShapeProp->setPropertyValue( "TextLowerDistance", uno::Any( nYDistance ) ); + xShape->SvxShape::setPropertyValue( "TextLeftDistance", uno::Any( nXDistance ) ); + xShape->SvxShape::setPropertyValue( "TextRightDistance", uno::Any( nXDistance ) ); + xShape->SvxShape::setPropertyValue( "TextUpperDistance", uno::Any( nYDistance ) ); + xShape->SvxShape::setPropertyValue( "TextLowerDistance", uno::Any( nYDistance ) ); } sal_Int32 nXPos = rPos.X; sal_Int32 nYPos = rPos.Y; @@ -2506,9 +2324,9 @@ uno::Reference< drawing::XShape > ::basegfx::B2DHomMatrix aM; aM.rotate( -basegfx::deg2rad(nRotation) );//#i78696#->#i80521# aM.translate( nXPos, nYPos ); - xShapeProp->setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) ); + xShape->SvxShape::setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) ); - xShapeProp->setPropertyValue( "ParaAdjust", uno::Any( style::ParagraphAdjust_CENTER ) ); + xShape->SvxShape::setPropertyValue( "ParaAdjust", uno::Any( style::ParagraphAdjust_CENTER ) ); } catch( const uno::Exception& ) { @@ -2517,16 +2335,10 @@ uno::Reference< drawing::XShape > return xShape; } -ShapeFactory* ShapeFactory::getOrCreateShapeFactory(const uno::Reference< lang::XMultiServiceFactory>& xFactory) -{ - static ShapeFactory* pShapeFactory = new ShapeFactory(xFactory); - return pShapeFactory; -} - -uno::Reference< drawing::XShapes > ShapeFactory::getChartRootShape( - const uno::Reference< drawing::XDrawPage>& xDrawPage ) +rtl::Reference<SvxShapeGroupAnyD> ShapeFactory::getChartRootShape( + const rtl::Reference<SvxDrawPage>& xDrawPage ) { - uno::Reference< drawing::XShapes > xRet; + rtl::Reference<SvxShapeGroupAnyD> xRet; const uno::Reference< drawing::XShapes > xShapes = xDrawPage; if( xShapes.is() ) { @@ -2538,7 +2350,8 @@ uno::Reference< drawing::XShapes > ShapeFactory::getChartRootShape( { if( ShapeFactory::getShapeName( xShape ) == "com.sun.star.chart2.shapes" ) { - xRet.set( xShape, uno::UNO_QUERY ); + xRet = dynamic_cast<SvxShapeGroupAnyD*>(xShape.get()); + assert(xRet); break; } } @@ -2547,44 +2360,34 @@ uno::Reference< drawing::XShapes > ShapeFactory::getChartRootShape( return xRet; } -void ShapeFactory::makeShapeInvisible( const uno::Reference< drawing::XShape >& xShape ) +void ShapeFactory::makeShapeInvisible( const rtl::Reference< SvxShape >& xShape ) { - uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet"); - if( xShapeProp.is()) + try { - try - { - xShapeProp->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE )); - xShapeProp->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_NONE )); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + xShape->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE )); + xShape->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_NONE )); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } } // set a name/CID at a shape (is used for selection handling) -void ShapeFactory::setShapeName( const uno::Reference< drawing::XShape >& xShape +void ShapeFactory::setShapeName( const rtl::Reference< SvxShape >& xShape , const OUString& rName ) { if(!xShape.is()) return; - uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); - OSL_ENSURE(xProp.is(), "shape offers no XPropertySet"); - if( xProp.is()) + try { - try - { - xProp->setPropertyValue( UNO_NAME_MISC_OBJ_NAME - , uno::Any( rName ) ); - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("chart2", "" ); - } + xShape->setPropertyValue( UNO_NAME_MISC_OBJ_NAME + , uno::Any( rName ) ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); } } @@ -2640,22 +2443,28 @@ OUString ShapeFactory::getStackedString( const OUString& rString, bool bStacked return aStackStr.makeStringAndClear(); } -bool ShapeFactory::hasPolygonAnyLines( drawing::PolyPolygonShape3D& rPoly) +bool ShapeFactory::hasPolygonAnyLines( const std::vector<std::vector<css::drawing::Position3D>>& rPoly) { // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true - for( auto const & i : std::as_const(rPoly.SequenceX) ) - if( i.getLength() > 1 ) + for( auto const & i : rPoly ) + if( i.size() > 1 ) return true; return false; } -bool ShapeFactory::isPolygonEmptyOrSinglePoint( drawing::PolyPolygonShape3D& rPoly) +bool ShapeFactory::isPolygonEmptyOrSinglePoint( const drawing::PolyPolygonShape3D& rPoly) { // true, if empty polypolygon or one polygon with one point return !rPoly.SequenceX.hasElements() || ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() <= 1)); } +bool ShapeFactory::isPolygonEmptyOrSinglePoint( const std::vector<std::vector<css::drawing::Position3D>>& rPoly) +{ + // true, if empty polypolygon or one polygon with one point + return rPoly.empty() || ((rPoly.size() == 1) && (rPoly[0].size() <= 1)); +} + void ShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly) { OSL_ENSURE( rPoly.SequenceX.getLength() <= 1, "ShapeFactory::closePolygon - single polygon expected" ); @@ -2666,6 +2475,16 @@ void ShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly) AddPointToPoly( rPoly, aFirst ); } +void ShapeFactory::closePolygon( std::vector<std::vector<css::drawing::Position3D>>& rPoly) +{ + OSL_ENSURE( rPoly.size() <= 1, "ShapeFactory::closePolygon - single polygon expected" ); + //add a last point == first point + if(isPolygonEmptyOrSinglePoint(rPoly)) + return; + drawing::Position3D aFirst(rPoly[0][0]); + AddPointToPoly( rPoly, aFirst ); +} + awt::Size ShapeFactory::calculateNewSizeRespectingAspectRatio( const awt::Size& rTargetSize , const awt::Size& rSourceSizeWithCorrectAspectRatio ) @@ -2692,55 +2511,48 @@ awt::Point ShapeFactory::calculateTopLeftPositionToCenterObject( return aNewPosition; } -::basegfx::B2IRectangle ShapeFactory::getRectangleOfShape( - const uno::Reference< drawing::XShape >& xShape ) +::basegfx::B2IRectangle ShapeFactory::getRectangleOfShape( SvxShape& rShape ) { ::basegfx::B2IRectangle aRet; - if( xShape.is() ) - { - awt::Point aPos = xShape->getPosition(); - awt::Size aSize = xShape->getSize(); - aRet = BaseGFXHelper::makeRectangle(aPos,aSize); - } - return aRet; + awt::Point aPos = rShape.getPosition(); + awt::Size aSize = rShape.getSize(); + aRet = BaseGFXHelper::makeRectangle(aPos,aSize); + return aRet; } awt::Size ShapeFactory::getSizeAfterRotation( - const uno::Reference< drawing::XShape >& xShape, double fRotationAngleDegree ) + SvxShape& rShape, double fRotationAngleDegree ) { awt::Size aRet(0,0); - if(xShape.is()) - { - const awt::Size aSize( xShape->getSize() ); + const awt::Size aSize( rShape.getSize() ); - if( fRotationAngleDegree == 0.0 ) - aRet = aSize; - else - { - fRotationAngleDegree = NormAngle360(fRotationAngleDegree); - if(fRotationAngleDegree>270.0) - fRotationAngleDegree=360.0-fRotationAngleDegree; - else if(fRotationAngleDegree>180.0) - fRotationAngleDegree=fRotationAngleDegree-180.0; - else if(fRotationAngleDegree>90.0) - fRotationAngleDegree=180.0-fRotationAngleDegree; - - const double fAnglePi = basegfx::deg2rad(fRotationAngleDegree); - - aRet.Height = static_cast<sal_Int32>( - aSize.Width*rtl::math::sin( fAnglePi ) - + aSize.Height*rtl::math::cos( fAnglePi )); - aRet.Width = static_cast<sal_Int32>( - aSize.Width*rtl::math::cos( fAnglePi ) - + aSize.Height*rtl::math::sin( fAnglePi )); - } + if( fRotationAngleDegree == 0.0 ) + aRet = aSize; + else + { + fRotationAngleDegree = NormAngle360(fRotationAngleDegree); + if(fRotationAngleDegree>270.0) + fRotationAngleDegree=360.0-fRotationAngleDegree; + else if(fRotationAngleDegree>180.0) + fRotationAngleDegree=fRotationAngleDegree-180.0; + else if(fRotationAngleDegree>90.0) + fRotationAngleDegree=180.0-fRotationAngleDegree; + + const double fAnglePi = basegfx::deg2rad(fRotationAngleDegree); + + aRet.Height = static_cast<sal_Int32>( + aSize.Width*std::sin( fAnglePi ) + + aSize.Height*std::cos( fAnglePi )); + aRet.Width = static_cast<sal_Int32>( + aSize.Width*std::cos( fAnglePi ) + + aSize.Height*std::sin( fAnglePi )); } return aRet; } -void ShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& xShapes ) +void ShapeFactory::removeSubShapes( const rtl::Reference<SvxShapeGroupAnyD>& xShapes ) { if( xShapes.is() ) { @@ -2754,6 +2566,21 @@ void ShapeFactory::removeSubShapes( const uno::Reference< drawing::XShapes >& xS } } +rtl::Reference<SvxTableShape> +ShapeFactory::createTable(rtl::Reference<SvxShapeGroupAnyD> const& xTarget, OUString const& rName) +{ + if (!xTarget.is()) + return nullptr; + + //create table shape + rtl::Reference<SvxTableShape> xShape = new SvxTableShape(nullptr); + xShape->setShapeKind(SdrObjKind::Table); + xTarget->addShape(*xShape); + if (!rName.isEmpty()) + setShapeName(xShape, rName); + return xShape; +} + } //namespace chart /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/VButton.cxx b/chart2/source/view/main/VButton.cxx index 088df5850416..25a770fb04bc 100644 --- a/chart2/source/view/main/VButton.cxx +++ b/chart2/source/view/main/VButton.cxx @@ -12,21 +12,15 @@ #include <ShapeFactory.hxx> #include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/drawing/LineStyle.hpp> -#include <com/sun/star/drawing/XShapes.hpp> #include <com/sun/star/style/ParagraphAdjust.hpp> #include <com/sun/star/drawing/TextVerticalAdjust.hpp> #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> -#include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> - -#include <memory> #include <CommonConverters.hxx> #include <editeng/unoprnms.hxx> namespace chart { - using namespace css; VButton::VButton() @@ -36,22 +30,15 @@ VButton::VButton() { } -void VButton::init(const uno::Reference<drawing::XShapes>& xTargetPage, - const uno::Reference<lang::XMultiServiceFactory>& xFactory) +void VButton::init(const rtl::Reference<SvxShapeGroupAnyD>& xTargetPage) { m_xTarget = xTargetPage; - m_xShapeFactory = xFactory; } -uno::Reference<drawing::XShape> VButton::createTriangle(awt::Size aSize) +rtl::Reference<SvxShapePolyPolygon> VButton::createTriangle(awt::Size aSize) { - uno::Reference<drawing::XShape> xShape; - xShape.set(m_xShapeFactory->createInstance("com.sun.star.drawing.PolyPolygonShape"), uno::UNO_QUERY); - - if (!xShape.is()) - return xShape; - - uno::Reference<beans::XPropertySet> xProperies(xShape, uno::UNO_QUERY); + rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr); + xShape->setShapeKind(SdrObjKind::Polygon); drawing::PolyPolygonShape3D aPolyPolygon; aPolyPolygon.SequenceX.realloc(1); @@ -82,30 +69,27 @@ uno::Reference<drawing::XShape> VButton::createTriangle(awt::Size aSize) pInnerSequenceY[2] = 0.0; pInnerSequenceZ[2] = 0.0; - xProperies->setPropertyValue("Name", uno::makeAny(m_sCID)); - xProperies->setPropertyValue(UNO_NAME_POLYPOLYGON, uno::Any(PolyToPointSequence(aPolyPolygon))); - xProperies->setPropertyValue("LineStyle", uno::makeAny(drawing::LineStyle_NONE)); - xProperies->setPropertyValue("FillColor", uno::makeAny(m_nArrowColor)); + xShape->SvxShape::setPropertyValue("Name", uno::Any(m_sCID)); + xShape->SvxShape::setPropertyValue(UNO_NAME_POLYPOLYGON, + uno::Any(PolyToPointSequence(aPolyPolygon))); + xShape->SvxShape::setPropertyValue("LineStyle", uno::Any(drawing::LineStyle_NONE)); + xShape->SvxShape::setPropertyValue("FillColor", uno::Any(m_nArrowColor)); return xShape; } void VButton::createShapes(const uno::Reference<beans::XPropertySet>& xTextProp) { - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); + tNameSequence aPropNames; + tAnySequence aPropValues; - std::unique_ptr<tNameSequence> pPropNames(new tNameSequence); - std::unique_ptr<tAnySequence> pPropValues(new tAnySequence); + PropertyMapper::getTextLabelMultiPropertyLists(xTextProp, aPropNames, aPropValues); - PropertyMapper::getTextLabelMultiPropertyLists(xTextProp, *pPropNames, *pPropValues); - - m_xShape.set(pShapeFactory->createGroup2D(m_xTarget, m_sCID), uno::UNO_QUERY); + m_xShape = ShapeFactory::createGroup2D(m_xTarget, m_sCID); m_xShape->setPosition(m_aPosition); m_xShape->setSize(m_aSize); - uno::Reference<drawing::XShapes> xContainer(m_xShape, uno::UNO_QUERY); - if (!xContainer.is()) - return; + rtl::Reference<SvxShapeGroupAnyD> xContainer = m_xShape; tPropertyNameValueMap aTextValueMap; aTextValueMap["CharHeight"] <<= 10.0f; @@ -123,10 +107,10 @@ void VButton::createShapes(const uno::Reference<beans::XPropertySet>& xTextProp) aTextValueMap["Name"] <<= m_sCID; //CID OUString - PropertyMapper::getMultiPropertyListsFromValueMap(*pPropNames, *pPropValues, aTextValueMap); + PropertyMapper::getMultiPropertyListsFromValueMap(aPropNames, aPropValues, aTextValueMap); - uno::Reference<drawing::XShape> xEntry = pShapeFactory->createText( - xContainer, m_sLabel, *pPropNames, *pPropValues, uno::Any()); + rtl::Reference<SvxShapeText> xEntry + = ShapeFactory::createText(xContainer, m_sLabel, aPropNames, aPropValues, uno::Any()); if (xEntry.is()) { @@ -137,16 +121,14 @@ void VButton::createShapes(const uno::Reference<beans::XPropertySet>& xTextProp) if (!m_bShowArrow) return; - awt::Size aPolySize {280, 180}; + awt::Size aPolySize{ 280, 180 }; - uno::Reference<drawing::XShape> xPoly = createTriangle(aPolySize); - if (xPoly.is()) - { - xPoly->setSize(aPolySize); - xPoly->setPosition({ sal_Int32(m_aPosition.X + m_aSize.Width - aPolySize.Width - 100), - sal_Int32(m_aPosition.Y + (m_aSize.Height / 2.0) - (aPolySize.Height / 2.0)) }); - xContainer->add(xPoly); - } + rtl::Reference<SvxShapePolyPolygon> xPoly = createTriangle(aPolySize); + xPoly->setSize(aPolySize); + xPoly->setPosition( + { sal_Int32(m_aPosition.X + m_aSize.Width - aPolySize.Width - 100), + sal_Int32(m_aPosition.Y + (m_aSize.Height / 2.0) - (aPolySize.Height / 2.0)) }); + xContainer->add(xPoly); } } //namespace chart diff --git a/chart2/source/view/main/VButton.hxx b/chart2/source/view/main/VButton.hxx index cb420332631a..87017f36901a 100644 --- a/chart2/source/view/main/VButton.hxx +++ b/chart2/source/view/main/VButton.hxx @@ -7,13 +7,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_MAIN_VBUTTON_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_MAIN_VBUTTON_HXX +#pragma once #include <tools/color.hxx> #include <com/sun/star/awt/Point.hpp> #include <com/sun/star/awt/Size.hpp> #include <com/sun/star/uno/Reference.hxx> +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> namespace com::sun::star::beans { class XPropertySet; } namespace com::sun::star::drawing { class XShape; } @@ -26,9 +27,8 @@ namespace chart class VButton final { private: - css::uno::Reference<css::lang::XMultiServiceFactory> m_xShapeFactory; - css::uno::Reference<css::drawing::XShapes> m_xTarget; - css::uno::Reference<css::drawing::XShape> m_xShape; + rtl::Reference<SvxShapeGroupAnyD> m_xTarget; + rtl::Reference<SvxShapeGroup> m_xShape; OUString m_sLabel; OUString m_sCID; css::awt::Point m_aPosition; @@ -37,14 +37,13 @@ private: Color m_nArrowColor; Color m_nBGColor; - css::uno::Reference<css::drawing::XShape> + rtl::Reference<SvxShapePolyPolygon> createTriangle(css::awt::Size aSize); public: VButton(); - void init(const css::uno::Reference<css::drawing::XShapes>& xTargetPage, - const css::uno::Reference<css::lang::XMultiServiceFactory>& xFactory); + void init(const rtl::Reference<SvxShapeGroupAnyD>& xTargetPage); void createShapes(const css::uno::Reference<css::beans::XPropertySet>& xTextProp); @@ -83,6 +82,5 @@ public: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/VDataSeries.cxx b/chart2/source/view/main/VDataSeries.cxx index 91388d1c2eda..4527d4368b2f 100644 --- a/chart2/source/view/main/VDataSeries.cxx +++ b/chart2/source/view/main/VDataSeries.cxx @@ -17,63 +17,62 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <limits> #include <memory> #include <VDataSeries.hxx> +#include <DataSeries.hxx> +#include <DataSeriesProperties.hxx> #include <ObjectIdentifier.hxx> #include <CommonConverters.hxx> #include <LabelPositionHelper.hxx> +#include <ChartType.hxx> #include <ChartTypeHelper.hxx> +#include <RegressionCurveCalculator.hxx> #include <RegressionCurveHelper.hxx> #include <unonames.hxx> -#include <com/sun/star/chart/DataLabelPlacement.hpp> #include <com/sun/star/chart/MissingValueTreatment.hpp> #include <com/sun/star/chart2/DataPointLabel.hpp> #include <com/sun/star/chart2/Symbol.hpp> -#include <com/sun/star/chart2/XDataSeries.hpp> #include <com/sun/star/chart2/XRegressionCurveCalculator.hpp> #include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/RelativeSize.hpp> -#include <rtl/math.hxx> +#include <o3tl/compare.hxx> #include <osl/diagnose.h> #include <tools/color.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/XPropertyState.hpp> -#include <com/sun/star/chart2/data/XDataSource.hpp> namespace chart { using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; using ::com::sun::star::uno::Reference; +using namespace ::chart::DataSeriesProperties; void VDataSequence::init( const uno::Reference< data::XDataSequence >& xModel ) { - Model = xModel; - Doubles = DataSequenceToDoubleSequence( xModel ); + m_xModel = xModel; + m_aValues = DataSequenceToDoubleSequence( xModel ); } bool VDataSequence::is() const { - return Model.is(); + return m_xModel.is(); } void VDataSequence::clear() { - Model = nullptr; - Doubles.realloc(0); + m_xModel = nullptr; + m_aValues.realloc(0); } double VDataSequence::getValue( sal_Int32 index ) const { - if( 0<=index && index<Doubles.getLength() ) - return Doubles[index]; - else - { - double fNan; - ::rtl::math::setNan( & fNan ); - return fNan; - } + if( 0<=index && index<m_aValues.getLength() ) + return m_aValues[index]; + return std::numeric_limits<double>::quiet_NaN(); } sal_Int32 VDataSequence::detectNumberFormatKey( sal_Int32 index ) const @@ -81,10 +80,9 @@ sal_Int32 VDataSequence::detectNumberFormatKey( sal_Int32 index ) const sal_Int32 nNumberFormatKey = -1; // -1 is allowed and means a key for the whole sequence - if( -1<=index && index<Doubles.getLength() && - Model.is()) + if( -1<=index && index<m_aValues.getLength() && m_xModel.is()) { - nNumberFormatKey = Model->getNumberFormatKeyByIndex( index ); + nNumberFormatKey = m_xModel->getNumberFormatKeyByIndex( index ); } return nNumberFormatKey; @@ -92,7 +90,7 @@ sal_Int32 VDataSequence::detectNumberFormatKey( sal_Int32 index ) const sal_Int32 VDataSequence::getLength() const { - return Doubles.getLength(); + return m_aValues.getLength(); } namespace @@ -104,7 +102,7 @@ struct lcl_LessXOfPoint { if( !first.empty() && !second.empty() ) { - return first[0]<second[0]; + return o3tl::strong_order(first[0], second[0]) < 0; } return false; } @@ -113,10 +111,10 @@ struct lcl_LessXOfPoint void lcl_clearIfNoValuesButTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence ) { //#i71686#, #i101968#, #i102428# - sal_Int32 nCount = rData.Doubles.getLength(); + sal_Int32 nCount = rData.m_aValues.getLength(); for( sal_Int32 i = 0; i < nCount; ++i ) { - if( !std::isnan( rData.Doubles[i] ) ) + if( !std::isnan( rData.m_aValues[i] ) ) return; } //no double value is contained @@ -143,48 +141,35 @@ void lcl_maybeReplaceNanWithZero( double& rfValue, sal_Int32 nMissingValueTreatm } -VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) +VDataSeries::VDataSeries( const rtl::Reference< DataSeries >& xDataSeries ) : m_nPolygonIndex(0) , m_fLogicMinX(0.0) , m_fLogicMaxX(0.0) , m_fLogicZPos(0.0) , m_xDataSeries(xDataSeries) , m_nPointCount(0) - , m_pValueSequenceForDataLabelNumberFormatDetection(&m_aValues_Y) - - , m_fXMeanValue(1.0) - , m_fYMeanValue(1.0) - - , m_aAttributedDataPointIndexList() - + , m_fXMeanValue(std::numeric_limits<double>::quiet_NaN()) + , m_fYMeanValue(std::numeric_limits<double>::quiet_NaN()) , m_eStackingDirection(StackingDirection_NO_STACKING) , m_nAxisIndex(0) , m_bConnectBars(false) , m_bGroupBarsPerAxis(true) , m_nStartingAngle(90) - , m_nGlobalSeriesIndex(0) - , m_nCurrentAttributedPoint(-1) , m_nMissingValueTreatment(css::chart::MissingValueTreatment::LEAVE_GAP) , m_bAllowPercentValueInDataLabel(false) , mpOldSeries(nullptr) , mnPercent(0.0) { - ::rtl::math::setNan( & m_fXMeanValue ); - ::rtl::math::setNan( & m_fYMeanValue ); + m_xDataSeriesProps = m_xDataSeries; - uno::Reference<data::XDataSource> xDataSource( xDataSeries, uno::UNO_QUERY ); + const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aDataSequences = + m_xDataSeries->getDataSequences2(); - uno::Sequence< uno::Reference< - chart2::data::XLabeledDataSequence > > aDataSequences = - xDataSource->getDataSequences(); - - for(sal_Int32 nN = aDataSequences.getLength();nN--;) + for(sal_Int32 nN = aDataSequences.size();nN--;) { - if(!aDataSequences[nN].is()) - continue; uno::Reference<data::XDataSequence> xDataSequence( aDataSequences[nN]->getValues()); uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY ); if( xProp.is()) @@ -241,18 +226,17 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) m_nPointCount = m_aValues_Y_Last.getLength(); } - uno::Reference<beans::XPropertySet> xProp(xDataSeries, uno::UNO_QUERY ); - if( !xProp.is()) + if( !xDataSeries.is()) return; try { - //get AttributedDataPoints - xProp->getPropertyValue("AttributedDataPoints") >>= m_aAttributedDataPointIndexList; + // "AttributedDataPoints" + xDataSeries->getFastPropertyValue(PROP_DATASERIES_ATTRIBUTED_DATA_POINTS) >>= m_aAttributedDataPointIndexList; - xProp->getPropertyValue("StackingDirection") >>= m_eStackingDirection; + xDataSeries->getFastPropertyValue(PROP_DATASERIES_STACKING_DIRECTION) >>= m_eStackingDirection; // "StackingDirection" - xProp->getPropertyValue("AttachedAxisIndex") >>= m_nAxisIndex; + xDataSeries->getFastPropertyValue(PROP_DATASERIES_ATTACHED_AXIS_INDEX) >>= m_nAxisIndex; // "AttachedAxisIndex" if(m_nAxisIndex<0) m_nAxisIndex=0; } @@ -268,52 +252,53 @@ VDataSeries::~VDataSeries() void VDataSeries::doSortByXValues() { - if( !(m_aValues_X.is() && m_aValues_X.Doubles.hasElements()) ) + if( !(m_aValues_X.is() && m_aValues_X.m_aValues.hasElements()) ) return; //prepare a vector for sorting std::vector< std::vector< double > > aTmp;//outer vector are points, inner vector are the different values of the point - double fNan; - ::rtl::math::setNan( & fNan ); sal_Int32 nPointIndex = 0; for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ ) { - std::vector< double > aSinglePoint; - aSinglePoint.push_back( (nPointIndex < m_aValues_X.Doubles.getLength()) ? m_aValues_X.Doubles[nPointIndex] : fNan ); - aSinglePoint.push_back( (nPointIndex < m_aValues_Y.Doubles.getLength()) ? m_aValues_Y.Doubles[nPointIndex] : fNan ); - aTmp.push_back( aSinglePoint ); + aTmp.push_back( + { ((nPointIndex < m_aValues_X.m_aValues.getLength()) ? m_aValues_X.m_aValues[nPointIndex] + : std::numeric_limits<double>::quiet_NaN()), + ((nPointIndex < m_aValues_Y.m_aValues.getLength()) ? m_aValues_Y.m_aValues[nPointIndex] + : std::numeric_limits<double>::quiet_NaN()) + } + ); } //do sort std::stable_sort( aTmp.begin(), aTmp.end(), lcl_LessXOfPoint() ); //fill the sorted points back to the members - m_aValues_X.Doubles.realloc( m_nPointCount ); - m_aValues_Y.Doubles.realloc( m_nPointCount ); + m_aValues_X.m_aValues.realloc( m_nPointCount ); + auto pDoublesX = m_aValues_X.m_aValues.getArray(); + m_aValues_Y.m_aValues.realloc( m_nPointCount ); + auto pDoublesY = m_aValues_Y.m_aValues.getArray(); for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ ) { - m_aValues_X.Doubles[nPointIndex]=aTmp[nPointIndex][0]; - m_aValues_Y.Doubles[nPointIndex]=aTmp[nPointIndex][1]; + pDoublesX[nPointIndex]=aTmp[nPointIndex][0]; + pDoublesY[nPointIndex]=aTmp[nPointIndex][1]; } } void VDataSeries::releaseShapes() { - m_xGroupShape.set(nullptr); - m_xLabelsGroupShape.set(nullptr); - m_xErrorXBarsGroupShape.set(nullptr); - m_xErrorYBarsGroupShape.set(nullptr); - m_xFrontSubGroupShape.set(nullptr); - m_xBackSubGroupShape.set(nullptr); + m_xGroupShape.clear(); + m_xLabelsGroupShape.clear(); + m_xErrorXBarsGroupShape.clear(); + m_xErrorYBarsGroupShape.clear(); + m_xFrontSubGroupShape.clear(); + m_xBackSubGroupShape.clear(); - m_aPolyPolygonShape3D.SequenceX.realloc(0); - m_aPolyPolygonShape3D.SequenceY.realloc(0); - m_aPolyPolygonShape3D.SequenceZ.realloc(0); + m_aPolyPolygonShape3D.clear(); m_nPolygonIndex = 0; } -const uno::Reference<css::chart2::XDataSeries>& VDataSeries::getModel() const +const rtl::Reference<::chart::DataSeries>& VDataSeries::getModel() const { return m_xDataSeries; } @@ -354,7 +339,7 @@ void VDataSeries::setParticle( const OUString& rSeriesParticle ) m_aPointCID_Stub = ObjectIdentifier::createSeriesSubObjectStub( OBJECTTYPE_DATA_POINT, m_aSeriesParticle ); m_aLabelCID_Stub = ObjectIdentifier::createClassifiedIdentifierWithParent( - OBJECTTYPE_DATA_LABEL, OUString(), getLabelsCID() ); + OBJECTTYPE_DATA_LABEL, u"", getLabelsCID() ); } OUString VDataSeries::getErrorBarsCID(bool bYError) const { @@ -435,28 +420,24 @@ void VDataSeries::setAttachedAxisIndex( sal_Int32 nAttachedAxisIndex ) double VDataSeries::getXValue( sal_Int32 index ) const { - double fRet = 0.0; + double fRet = std::numeric_limits<double>::quiet_NaN(); if(m_aValues_X.is()) { if( 0<=index && index<m_aValues_X.getLength() ) { - fRet = m_aValues_X.Doubles[index]; + fRet = m_aValues_X.m_aValues[index]; if(mpOldSeries && index < mpOldSeries->m_aValues_X.getLength()) { - double nOldVal = mpOldSeries->m_aValues_X.Doubles[index]; + double nOldVal = mpOldSeries->m_aValues_X.m_aValues[index]; fRet = nOldVal + (fRet - nOldVal) * mnPercent; } } - else - ::rtl::math::setNan( &fRet ); } else { // #i70133# always return correct X position - needed for short data series if( 0<=index /*&& index < m_nPointCount*/ ) fRet = index+1;//first category (index 0) matches with real number 1.0 - else - ::rtl::math::setNan( &fRet ); } lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() ); return fRet; @@ -464,28 +445,24 @@ double VDataSeries::getXValue( sal_Int32 index ) const double VDataSeries::getYValue( sal_Int32 index ) const { - double fRet = 0.0; + double fRet = std::numeric_limits<double>::quiet_NaN(); if(m_aValues_Y.is()) { if( 0<=index && index<m_aValues_Y.getLength() ) { - fRet = m_aValues_Y.Doubles[index]; + fRet = m_aValues_Y.m_aValues[index]; if(mpOldSeries && index < mpOldSeries->m_aValues_Y.getLength()) { - double nOldVal = mpOldSeries->m_aValues_Y.Doubles[index]; + double nOldVal = mpOldSeries->m_aValues_Y.m_aValues[index]; fRet = nOldVal + (fRet - nOldVal) * mnPercent; } } - else - ::rtl::math::setNan( &fRet ); } else { // #i70133# always return correct X position - needed for short data series if( 0<=index /*&& index < m_nPointCount*/ ) fRet = index+1;//first category (index 0) matches with real number 1.0 - else - ::rtl::math::setNan( &fRet ); } lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() ); return fRet; @@ -493,8 +470,8 @@ double VDataSeries::getYValue( sal_Int32 index ) const void VDataSeries::getMinMaxXValue(double& fMin, double& fMax) const { - rtl::math::setNan( &fMax ); - rtl::math::setNan( &fMin ); + fMax = std::numeric_limits<double>::quiet_NaN(); + fMin = std::numeric_limits<double>::quiet_NaN(); uno::Sequence< double > aValuesX = getAllX(); @@ -550,13 +527,13 @@ double VDataSeries::getBubble_Size( sal_Int32 index ) const bool VDataSeries::hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const { - OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : OUString(CHART_UNONAME_NUMFMT); + OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : CHART_UNONAME_NUMFMT; bool bHasNumberFormat = false; bool bLinkToSource = true; uno::Reference< beans::XPropertySet > xPointProp( getPropertiesOfPoint( nPointIndex )); - sal_Int32 nNumberFormat = -1; if( xPointProp.is() && (xPointProp->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource)) { + sal_Int32 nNumberFormat = -1; if( !bLinkToSource && (xPointProp->getPropertyValue(aPropName) >>= nNumberFormat)) bHasNumberFormat = true; } @@ -564,28 +541,28 @@ bool VDataSeries::hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPerce } sal_Int32 VDataSeries::getExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const { - OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : OUString(CHART_UNONAME_NUMFMT); + OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : CHART_UNONAME_NUMFMT; sal_Int32 nNumberFormat = -1; uno::Reference< beans::XPropertySet > xPointProp( getPropertiesOfPoint( nPointIndex )); if( xPointProp.is() ) xPointProp->getPropertyValue(aPropName) >>= nNumberFormat; return nNumberFormat; } -void VDataSeries::setRoleOfSequenceForDataLabelNumberFormatDetection( const OUString& rRole ) +void VDataSeries::setRoleOfSequenceForDataLabelNumberFormatDetection( std::u16string_view rRole ) { - if (rRole == "values-y") + if (rRole == u"values-y") m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y; - else if (rRole == "values-size") + else if (rRole == u"values-size") m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Bubble_Size; - else if (rRole == "values-min") + else if (rRole == u"values-min") m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Min; - else if (rRole == "values-max") + else if (rRole == u"values-max") m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Max; - else if (rRole == "values-first") + else if (rRole == u"values-first") m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_First; - else if (rRole == "values-last") + else if (rRole == u"values-last") m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Last; - else if (rRole == "values-x") + else if (rRole == u"values-x") m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_X; } sal_Int32 VDataSeries::detectNumberFormatKey( sal_Int32 index ) const @@ -596,7 +573,7 @@ sal_Int32 VDataSeries::detectNumberFormatKey( sal_Int32 index ) const return nRet; } -sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const uno::Reference< chart2::XChartType >& xChartType, bool bSwapXAndY ) const +sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const rtl::Reference< ChartType >& xChartType, bool bSwapXAndY ) const { sal_Int32 nLabelPlacement=0; try @@ -605,7 +582,7 @@ sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const uno::Refe if( xPointProps.is() ) xPointProps->getPropertyValue("LabelPlacement") >>= nLabelPlacement; - uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements( + const uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements( xChartType, bSwapXAndY, m_xDataSeries ) ); for( sal_Int32 n : aAvailablePlacements ) @@ -653,12 +630,12 @@ awt::Point VDataSeries::getLabelPosition( awt::Point aTextShapePos, sal_Int32 nP bool VDataSeries::isLabelCustomPos(sal_Int32 nPointIndex) const { bool bCustom = false; - RelativePosition aCustomLabelPosition; try { if( isAttributedDataPoint(nPointIndex) ) { uno::Reference< beans::XPropertySet > xPointProps(m_xDataSeries->getDataPointByIndex(nPointIndex)); + RelativePosition aCustomLabelPosition; if( xPointProps.is() && (xPointProps->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition) ) bCustom = true; } @@ -670,10 +647,29 @@ bool VDataSeries::isLabelCustomPos(sal_Int32 nPointIndex) const return bCustom; } +awt::Size VDataSeries::getLabelCustomSize(sal_Int32 nPointIndex) const +{ + awt::Size aSize(-1, -1); + try + { + RelativeSize aCustomLabelSize; + const uno::Reference<beans::XPropertySet> xPointProps(getPropertiesOfPoint(nPointIndex)); + if (xPointProps.is() && (xPointProps->getPropertyValue("CustomLabelSize") >>= aCustomLabelSize)) + { + aSize.Width = static_cast<sal_Int32>(aCustomLabelSize.Primary * m_aReferenceSize.Width); + aSize.Height = static_cast<sal_Int32>(aCustomLabelSize.Secondary * m_aReferenceSize.Height); + } + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return aSize; +} + double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const { - double fMin=0.0; - ::rtl::math::setInf(&fMin, false); + double fMin = std::numeric_limits<double>::infinity(); if( !m_aValues_Y.is() && (m_aValues_Y_Min.is() || m_aValues_Y_Max.is() @@ -701,15 +697,14 @@ double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const } if( std::isinf(fMin) ) - ::rtl::math::setNan(&fMin); + return std::numeric_limits<double>::quiet_NaN(); return fMin; } double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const { - double fMax=0.0; - ::rtl::math::setInf(&fMax, true); + double fMax = -std::numeric_limits<double>::infinity(); if( !m_aValues_Y.is() && (m_aValues_Y_Min.is() || m_aValues_Y_Max.is() @@ -737,7 +732,7 @@ double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const } if( std::isinf(fMax) ) - ::rtl::math::setNan(&fMax); + return std::numeric_limits<double>::quiet_NaN(); return fMax; } @@ -748,11 +743,12 @@ uno::Sequence< double > const & VDataSeries::getAllX() const { //init x values from category indexes //first category (index 0) matches with real number 1.0 - m_aValues_X.Doubles.realloc( m_nPointCount ); + m_aValues_X.m_aValues.realloc( m_nPointCount ); + auto pDoubles = m_aValues_X.m_aValues.getArray(); for(sal_Int32 nN=m_aValues_X.getLength();nN--;) - m_aValues_X.Doubles[nN] = nN+1; + pDoubles[nN] = nN+1; } - return m_aValues_X.Doubles; + return m_aValues_X.m_aValues; } uno::Sequence< double > const & VDataSeries::getAllY() const @@ -761,18 +757,19 @@ uno::Sequence< double > const & VDataSeries::getAllY() const { //init y values from indexes //first y-value (index 0) matches with real number 1.0 - m_aValues_Y.Doubles.realloc( m_nPointCount ); + m_aValues_Y.m_aValues.realloc( m_nPointCount ); + auto pDoubles = m_aValues_Y.m_aValues.getArray(); for(sal_Int32 nN=m_aValues_Y.getLength();nN--;) - m_aValues_Y.Doubles[nN] = nN+1; + pDoubles[nN] = nN+1; } - return m_aValues_Y.Doubles; + return m_aValues_Y.m_aValues; } double VDataSeries::getXMeanValue() const { if( std::isnan( m_fXMeanValue ) ) { - uno::Reference< XRegressionCurveCalculator > xCalculator( RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( "com.sun.star.chart2.MeanValueRegressionCurve" ) ); + rtl::Reference< RegressionCurveCalculator > xCalculator( RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( u"com.sun.star.chart2.MeanValueRegressionCurve" ) ); uno::Sequence< double > aXValuesDummy; xCalculator->recalculateRegression( aXValuesDummy, getAllX() ); m_fXMeanValue = xCalculator->getCurveValue( 1.0 ); @@ -784,8 +781,8 @@ double VDataSeries::getYMeanValue() const { if( std::isnan( m_fYMeanValue ) ) { - uno::Reference< XRegressionCurveCalculator > xCalculator( - RegressionCurveHelper::createRegressionCurveCalculatorByServiceName("com.sun.star.chart2.MeanValueRegressionCurve")); + rtl::Reference< RegressionCurveCalculator > xCalculator( + RegressionCurveHelper::createRegressionCurveCalculatorByServiceName(u"com.sun.star.chart2.MeanValueRegressionCurve")); uno::Sequence< double > aXValuesDummy; xCalculator->recalculateRegression( aXValuesDummy, getAllY() ); m_fYMeanValue = xCalculator->getCurveValue( 1.0 ); @@ -793,26 +790,26 @@ double VDataSeries::getYMeanValue() const return m_fYMeanValue; } -static std::unique_ptr<Symbol> getSymbolPropertiesFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp ) +static std::optional<Symbol> getSymbolPropertiesFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp ) { - std::unique_ptr< Symbol > apSymbolProps( new Symbol() ); + Symbol aSymbolProps; try { - if( xProp->getPropertyValue("Symbol") >>= *apSymbolProps ) + if( xProp->getPropertyValue("Symbol") >>= aSymbolProps ) { //use main color to fill symbols - xProp->getPropertyValue("Color") >>= apSymbolProps->FillColor; + xProp->getPropertyValue("Color") >>= aSymbolProps.FillColor; // border of symbols always same as fill color - apSymbolProps->BorderColor = apSymbolProps->FillColor; + aSymbolProps.BorderColor = aSymbolProps.FillColor; } else - apSymbolProps.reset(); + return std::nullopt; } catch(const uno::Exception &) { TOOLS_WARN_EXCEPTION("chart2", "" ); } - return apSymbolProps; + return aSymbolProps; } Symbol* VDataSeries::getSymbolProperties( sal_Int32 index ) const @@ -821,38 +818,38 @@ Symbol* VDataSeries::getSymbolProperties( sal_Int32 index ) const if( isAttributedDataPoint( index ) ) { adaptPointCache( index ); - if (!m_apSymbolProperties_AttributedPoint) - m_apSymbolProperties_AttributedPoint + if (!m_oSymbolProperties_AttributedPoint) + m_oSymbolProperties_AttributedPoint = getSymbolPropertiesFromPropertySet(getPropertiesOfPoint(index)); - pRet = m_apSymbolProperties_AttributedPoint.get(); + pRet = &*m_oSymbolProperties_AttributedPoint; //if a single data point does not have symbols but the dataseries itself has symbols //we create an invisible symbol shape to enable selection of that point if( !pRet || pRet->Style == SymbolStyle_NONE ) { - if (!m_apSymbolProperties_Series) - m_apSymbolProperties_Series + if (!m_oSymbolProperties_Series) + m_oSymbolProperties_Series = getSymbolPropertiesFromPropertySet(getPropertiesOfSeries()); - if( m_apSymbolProperties_Series && m_apSymbolProperties_Series->Style != SymbolStyle_NONE ) + if( m_oSymbolProperties_Series && m_oSymbolProperties_Series->Style != SymbolStyle_NONE ) { - if (!m_apSymbolProperties_InvisibleSymbolForSelection) + if (!m_oSymbolProperties_InvisibleSymbolForSelection) { - m_apSymbolProperties_InvisibleSymbolForSelection.reset(new Symbol); - m_apSymbolProperties_InvisibleSymbolForSelection->Style = SymbolStyle_STANDARD; - m_apSymbolProperties_InvisibleSymbolForSelection->StandardSymbol = 0;//square - m_apSymbolProperties_InvisibleSymbolForSelection->Size = com::sun::star::awt::Size(0, 0);//tdf#126033 - m_apSymbolProperties_InvisibleSymbolForSelection->BorderColor = 0xff000000;//invisible - m_apSymbolProperties_InvisibleSymbolForSelection->FillColor = 0xff000000;//invisible + m_oSymbolProperties_InvisibleSymbolForSelection.emplace(); + m_oSymbolProperties_InvisibleSymbolForSelection->Style = SymbolStyle_STANDARD; + m_oSymbolProperties_InvisibleSymbolForSelection->StandardSymbol = 0;//square + m_oSymbolProperties_InvisibleSymbolForSelection->Size = com::sun::star::awt::Size(0, 0);//tdf#126033 + m_oSymbolProperties_InvisibleSymbolForSelection->BorderColor = 0xff000000;//invisible + m_oSymbolProperties_InvisibleSymbolForSelection->FillColor = 0xff000000;//invisible } - pRet = m_apSymbolProperties_InvisibleSymbolForSelection.get(); + pRet = &*m_oSymbolProperties_InvisibleSymbolForSelection; } } } else { - if (!m_apSymbolProperties_Series) - m_apSymbolProperties_Series + if (!m_oSymbolProperties_Series) + m_oSymbolProperties_Series = getSymbolPropertiesFromPropertySet(getPropertiesOfSeries()); - pRet = m_apSymbolProperties_Series.get(); + pRet = &*m_oSymbolProperties_Series; } if( pRet && pRet->Style == SymbolStyle_AUTO ) @@ -921,9 +918,8 @@ bool VDataSeries::isAttributedDataPoint( sal_Int32 index ) const bool VDataSeries::isVaryColorsByPoint() const { bool bVaryColorsByPoint = false; - Reference< beans::XPropertySet > xSeriesProp( getPropertiesOfSeries() ); - if( xSeriesProp.is() ) - xSeriesProp->getPropertyValue("VaryColorsByPoint") >>= bVaryColorsByPoint; + if( m_xDataSeries ) + m_xDataSeries->getFastPropertyValue(PROP_DATASERIES_VARY_COLORS_BY_POINT) >>= bVaryColorsByPoint; // "VaryColorsByPoint" return bVaryColorsByPoint; } @@ -934,14 +930,14 @@ uno::Reference< beans::XPropertySet > VDataSeries::getPropertiesOfPoint( sal_Int return getPropertiesOfSeries(); } -uno::Reference<beans::XPropertySet> VDataSeries::getPropertiesOfSeries() const +const uno::Reference<beans::XPropertySet> & VDataSeries::getPropertiesOfSeries() const { - return uno::Reference<css::beans::XPropertySet>(m_xDataSeries, css::uno::UNO_QUERY); + return m_xDataSeriesProps; } -static std::unique_ptr<DataPointLabel> getDataPointLabelFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp ) +static std::optional<DataPointLabel> getDataPointLabelFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp ) { - std::unique_ptr< DataPointLabel > apLabel( new DataPointLabel() ); + std::optional< DataPointLabel > apLabel( std::in_place ); try { if( !(xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= *apLabel) ) @@ -958,10 +954,10 @@ void VDataSeries::adaptPointCache( sal_Int32 nNewPointIndex ) const { if( m_nCurrentAttributedPoint != nNewPointIndex ) { - m_apLabel_AttributedPoint.reset(); - m_apLabelPropNames_AttributedPoint.reset(); - m_apLabelPropValues_AttributedPoint.reset(); - m_apSymbolProperties_AttributedPoint.reset(); + m_oLabel_AttributedPoint.reset(); + m_oLabelPropNames_AttributedPoint.reset(); + m_oLabelPropValues_AttributedPoint.reset(); + m_oSymbolProperties_AttributedPoint.reset(); m_nCurrentAttributedPoint = nNewPointIndex; } } @@ -972,17 +968,19 @@ DataPointLabel* VDataSeries::getDataPointLabel( sal_Int32 index ) const if( isAttributedDataPoint( index ) ) { adaptPointCache( index ); - if (!m_apLabel_AttributedPoint) - m_apLabel_AttributedPoint + if (!m_oLabel_AttributedPoint) + m_oLabel_AttributedPoint = getDataPointLabelFromPropertySet(getPropertiesOfPoint(index)); - pRet = m_apLabel_AttributedPoint.get(); + if (m_oLabel_AttributedPoint) + pRet = &*m_oLabel_AttributedPoint; } else { - if (!m_apLabel_Series) - m_apLabel_Series + if (!m_oLabel_Series) + m_oLabel_Series = getDataPointLabelFromPropertySet(getPropertiesOfPoint(index)); - pRet = m_apLabel_Series.get(); + if (m_oLabel_Series) + pRet = &*m_oLabel_Series; } if( !m_bAllowPercentValueInDataLabel ) { @@ -996,7 +994,7 @@ DataPointLabel* VDataSeries::getDataPointLabelIfLabel( sal_Int32 index ) const { DataPointLabel* pLabel = getDataPointLabel( index ); if( !pLabel || (!pLabel->ShowNumber && !pLabel->ShowNumberInPercent - && !pLabel->ShowCategoryName ) ) + && !pLabel->ShowCategoryName && !pLabel->ShowCustomLabel && !pLabel->ShowSeriesName ) ) return nullptr; return pLabel; } @@ -1011,33 +1009,33 @@ bool VDataSeries::getTextLabelMultiPropertyLists( sal_Int32 index if( isAttributedDataPoint( index ) ) { adaptPointCache( index ); - if (!m_apLabelPropValues_AttributedPoint) + if (!m_oLabelPropValues_AttributedPoint) { // Cache these properties for this point. - m_apLabelPropNames_AttributedPoint.reset(new tNameSequence); - m_apLabelPropValues_AttributedPoint.reset(new tAnySequence); + m_oLabelPropNames_AttributedPoint.emplace(); + m_oLabelPropValues_AttributedPoint.emplace(); xTextProp.set( getPropertiesOfPoint( index )); PropertyMapper::getTextLabelMultiPropertyLists( - xTextProp, *m_apLabelPropNames_AttributedPoint, *m_apLabelPropValues_AttributedPoint); + xTextProp, *m_oLabelPropNames_AttributedPoint, *m_oLabelPropValues_AttributedPoint); bDoDynamicFontResize = true; } - pPropNames = m_apLabelPropNames_AttributedPoint.get(); - pPropValues = m_apLabelPropValues_AttributedPoint.get(); + pPropNames = &*m_oLabelPropNames_AttributedPoint; + pPropValues = &*m_oLabelPropValues_AttributedPoint; } else { - if (!m_apLabelPropValues_Series) + if (!m_oLabelPropValues_Series) { // Cache these properties for the whole series. - m_apLabelPropNames_Series.reset(new tNameSequence); - m_apLabelPropValues_Series.reset(new tAnySequence); + m_oLabelPropNames_Series.emplace(); + m_oLabelPropValues_Series.emplace(); xTextProp.set( getPropertiesOfPoint( index )); PropertyMapper::getTextLabelMultiPropertyLists( - xTextProp, *m_apLabelPropNames_Series, *m_apLabelPropValues_Series); + xTextProp, *m_oLabelPropNames_Series, *m_oLabelPropValues_Series); bDoDynamicFontResize = true; } - pPropNames = m_apLabelPropNames_Series.get(); - pPropValues = m_apLabelPropValues_Series.get(); + pPropNames = &*m_oLabelPropNames_Series; + pPropValues = &*m_oLabelPropValues_Series; } if( bDoDynamicFontResize && @@ -1112,11 +1110,7 @@ double VDataSeries::getValueByProperty( sal_Int32 nIndex, const OUString& rPropN { auto const itr = m_PropertyMap.find(rPropName); if (itr == m_PropertyMap.end()) - { - double fNan; - ::rtl::math::setNan( &fNan ); - return fNan; - } + return std::numeric_limits<double>::quiet_NaN(); const VDataSequence* pData = &itr->second; double fValue = pData->getValue(nIndex); @@ -1126,13 +1120,13 @@ double VDataSeries::getValueByProperty( sal_Int32 nIndex, const OUString& rPropN if(rPropName.endsWith("Color")) { //optimized interpolation for color values - Color aColor(static_cast<sal_uInt32>(fValue)); - Color aOldColor(static_cast<sal_uInt32>(fOldValue)); + Color aColor(ColorTransparency, static_cast<sal_uInt32>(fValue)); + Color aOldColor(ColorTransparency, static_cast<sal_uInt32>(fOldValue)); sal_uInt8 r = aOldColor.GetRed() + (aColor.GetRed() - aOldColor.GetRed()) * mnPercent; sal_uInt8 g = aOldColor.GetGreen() + (aColor.GetGreen() - aOldColor.GetGreen()) * mnPercent; sal_uInt8 b = aOldColor.GetBlue() + (aColor.GetBlue() - aOldColor.GetBlue()) * mnPercent; - sal_uInt8 t = aOldColor.GetTransparency() + (aColor.GetTransparency() - aOldColor.GetTransparency()) * mnPercent; - Color aRet(t, r, g, b); + sal_uInt8 a = aOldColor.GetAlpha() + (aColor.GetAlpha() - aOldColor.GetAlpha()) * mnPercent; + Color aRet(ColorAlpha, a, r, g, b); return sal_uInt32(aRet); } return fOldValue + (fValue - fOldValue) * mnPercent; @@ -1142,7 +1136,7 @@ double VDataSeries::getValueByProperty( sal_Int32 nIndex, const OUString& rPropN bool VDataSeries::hasPropertyMapping(const OUString& rPropName ) const { - return m_PropertyMap.find(rPropName) != m_PropertyMap.end(); + return m_PropertyMap.contains(rPropName); } } //namespace chart diff --git a/chart2/source/view/main/VLegend.cxx b/chart2/source/view/main/VLegend.cxx index d16495e426f3..72c0165a69f5 100644 --- a/chart2/source/view/main/VLegend.cxx +++ b/chart2/source/view/main/VLegend.cxx @@ -19,9 +19,11 @@ #include "VLegend.hxx" #include "VButton.hxx" +#include <Legend.hxx> #include <PropertyMapper.hxx> #include <ChartModel.hxx> #include <ObjectIdentifier.hxx> +#include <FormattedString.hxx> #include <RelativePositionHelper.hxx> #include <ShapeFactory.hxx> #include <RelativeSizeHelper.hxx> @@ -31,7 +33,6 @@ #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> #include <com/sun/star/drawing/LineJoint.hpp> -#include <com/sun/star/drawing/XShapes.hpp> #include <com/sun/star/chart/ChartLegendExpansion.hpp> #include <com/sun/star/chart2/LegendPosition.hpp> #include <com/sun/star/chart2/RelativePosition.hpp> @@ -40,9 +41,11 @@ #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp> #include <com/sun/star/chart2/data/PivotTableFieldEntry.hpp> #include <rtl/math.hxx> -#include <svl/languageoptions.hxx> -#include <tools/diagnose_ex.h> +#include <svl/ctloptions.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <tools/UnitConversion.hxx> +#include <utility> #include <vector> #include <algorithm> @@ -66,13 +69,13 @@ double lcl_CalcViewFontSize( { double fResult = 10.0; - awt::Size aPropRefSize; float fFontHeight( 0.0 ); if( xProp.is() && ( xProp->getPropertyValue( "CharHeight") >>= fFontHeight )) { fResult = fFontHeight; try { + awt::Size aPropRefSize; if( (xProp->getPropertyValue( "ReferencePageSize") >>= aPropRefSize) && (aPropRefSize.Height > 0)) { @@ -85,8 +88,7 @@ double lcl_CalcViewFontSize( } } - // pt -> 1/100th mm - return (fResult * (2540.0 / 72.0)); + return convertPointToMm100(fResult); } void lcl_getProperties( @@ -148,34 +150,35 @@ void lcl_getProperties( awt::Size lcl_createTextShapes( const std::vector<ViewLegendEntry> & rEntries, - const Reference< lang::XMultiServiceFactory > & xShapeFactory, - const Reference< drawing::XShapes > & xTarget, - std::vector< Reference< drawing::XShape > > & rOutTextShapes, + const rtl::Reference<SvxShapeGroupAnyD> & xTarget, + std::vector< rtl::Reference<SvxShapeText> > & rOutTextShapes, const tPropertyValues & rTextProperties ) { awt::Size aResult; - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); for (ViewLegendEntry const & rEntry : rEntries) { try { OUString aLabelString; - Sequence< Reference< XFormattedString2 > > aLabelSeq = rEntry.aLabel; - for( sal_Int32 i = 0; i < aLabelSeq.getLength(); ++i ) + if (rEntry.xLabel) { - // todo: support more than one text range - if( i == 1 ) - break; + // tdf#150034 limit legend label text + if (rEntry.xLabel->getString().getLength() > 520) + { + sal_Int32 nIndex = rEntry.xLabel->getString().indexOf(' ', 500); + rEntry.xLabel->setString( + rEntry.xLabel->getString().copy(0, nIndex > 500 ? nIndex : 500)); + } - aLabelString += aLabelSeq[i]->getString(); + aLabelString += rEntry.xLabel->getString(); // workaround for Issue #i67540# if( aLabelString.isEmpty()) aLabelString = " "; } - Reference< drawing::XShape > xEntry = - pShapeFactory->createText( xTarget, aLabelString, + rtl::Reference<SvxShapeText> xEntry = + ShapeFactory::createText( xTarget, aLabelString, rTextProperties.first, rTextProperties.second, uno::Any() ); // adapt max-extent @@ -195,7 +198,7 @@ awt::Size lcl_createTextShapes( } void lcl_collectColumnWidths( std::vector< sal_Int32 >& rColumnWidths, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns, - const std::vector< Reference< drawing::XShape > >& rTextShapes, sal_Int32 nSymbolPlusDistanceWidth ) + const std::vector< rtl::Reference<SvxShapeText> >& rTextShapes, sal_Int32 nSymbolPlusDistanceWidth ) { rColumnWidths.clear(); sal_Int32 nNumberOfEntries = rTextShapes.size(); @@ -218,7 +221,7 @@ void lcl_collectColumnWidths( std::vector< sal_Int32 >& rColumnWidths, const sal } void lcl_collectRowHeighs( std::vector< sal_Int32 >& rRowHeights, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns, - const std::vector< Reference< drawing::XShape > >& rTextShapes ) + const std::vector< rtl::Reference<SvxShapeText> >& rTextShapes ) { // calculate maximum height for each row // and collect column widths @@ -266,8 +269,7 @@ awt::Size lcl_placeLegendEntries( double fViewFontSize, const awt::Size& rMaxSymbolExtent, tPropertyValues & rTextProperties, - const Reference< drawing::XShapes > & xTarget, - const Reference< lang::XMultiServiceFactory > & xShapeFactory, + const rtl::Reference<SvxShapeGroupAnyD> & xTarget, const awt::Size& rRemainingSpace, sal_Int32 nYStartPosition, const awt::Size& rPageSize, @@ -291,7 +293,7 @@ awt::Size lcl_placeLegendEntries( const sal_Int32 nSymbolToTextDistance = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.22 ) );//minimum 1mm const sal_Int32 nSymbolPlusDistanceWidth = rMaxSymbolExtent.Width + nSymbolToTextDistance; sal_Int32 nMaxTextWidth = rRemainingSpace.Width - nSymbolPlusDistanceWidth; - uno::Any* pFrameWidthAny = PropertyMapper::getValuePointer( rTextProperties.second, rTextProperties.first, "TextMaximumFrameWidth"); + uno::Any* pFrameWidthAny = PropertyMapper::getValuePointer( rTextProperties.second, rTextProperties.first, u"TextMaximumFrameWidth"); if(pFrameWidthAny) { if( eExpansion == css::chart::ChartLegendExpansion_HIGH ) @@ -303,8 +305,8 @@ awt::Size lcl_placeLegendEntries( *pFrameWidthAny <<= nMaxTextWidth; } - std::vector< Reference< drawing::XShape > > aTextShapes; - awt::Size aMaxEntryExtent = lcl_createTextShapes( rEntries, xShapeFactory, xTarget, aTextShapes, rTextProperties ); + std::vector< rtl::Reference<SvxShapeText> > aTextShapes; + awt::Size aMaxEntryExtent = lcl_createTextShapes( rEntries, xTarget, aTextShapes, rTextProperties ); OSL_ASSERT( aTextShapes.size() == rEntries.size()); sal_Int32 nMaxEntryWidth = nXOffset + nSymbolPlusDistanceWidth + aMaxEntryExtent.Width; @@ -328,7 +330,7 @@ awt::Size lcl_placeLegendEntries( sal_Int32 nMaxColumnCount=-1; for( sal_Int32 nN=0; nN<static_cast<sal_Int32>(aTextShapes.size()); nN++ ) { - Reference< drawing::XShape > xShape( aTextShapes[nN] ); + rtl::Reference<SvxShapeText> xShape( aTextShapes[nN] ); if( !xShape.is() ) continue; awt::Size aSize( xShape->getSize() ); @@ -348,10 +350,9 @@ awt::Size lcl_placeLegendEntries( //all good proceed with next entry continue; } - } - if( nCurrentColumn < nCurrentColumnCount ) + aColumnWidths[nCurrentColumn] = std::max( nNewWidth, aColumnWidths[nCurrentColumn] ); - else + } else aColumnWidths.push_back(nNewWidth); //do the columns still fit into the given size? @@ -410,7 +411,7 @@ awt::Size lcl_placeLegendEntries( } if( nEntry < nNumberOfEntries && ( nEntry != 0 || nNumberOfColumns != 1 ) ) { - DrawModelWrapper::removeShape( rEntries[ nEntry ].aSymbol ); + DrawModelWrapper::removeShape( rEntries[ nEntry ].xSymbol ); rEntries.pop_back(); nNumberOfEntries--; } @@ -419,13 +420,12 @@ awt::Size lcl_placeLegendEntries( { try { - OUString aLabelString = rEntries[0].aLabel[0]->getString(); - const OUString sDots = "..."; - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); - for (sal_Int32 nNewLen = aLabelString.getLength() - sDots.getLength(); nNewLen > 0; nNewLen--) + OUString aLabelString = rEntries[0].xLabel->getString(); + static constexpr OUString sDots = u"..."_ustr; + for (sal_Int32 nNewLen = aLabelString.getLength() - sDots.getLength(); nNewLen > 0; ) { - OUString aNewLabel = aLabelString.copy(0, nNewLen) + sDots; - Reference<drawing::XShape> xEntry = pShapeFactory->createText( + OUString aNewLabel = aLabelString.subView(0, nNewLen) + sDots; + rtl::Reference<SvxShapeText> xEntry = ShapeFactory::createText( xTarget, aNewLabel, rTextProperties.first, rTextProperties.second, uno::Any()); nSumHeight = xEntry->getSize().Height; nRemainingSpace = rRemainingSpace.Height - nSumHeight; @@ -435,17 +435,23 @@ awt::Size lcl_placeLegendEntries( if (rRemainingSpace.Width - nWidth >= 0) { aTextShapes.push_back(xEntry); - rEntries[0].aLabel[0]->setString(aNewLabel); + rEntries[0].xLabel->setString(aNewLabel); aRowHeights[0] = nSumHeight; aColumnWidths[0] = nWidth; break; } } DrawModelWrapper::removeShape(xEntry); + // The intention here is to make pathological cases with extremely large labels + // converge a little faster + if (nNewLen > 10 && std::abs(nRemainingSpace) > nSumHeight / 10) + nNewLen -= nNewLen / 10; + else + --nNewLen; } - if (aTextShapes.size() == 0) + if (aTextShapes.empty()) { - DrawModelWrapper::removeShape(rEntries[0].aSymbol); + DrawModelWrapper::removeShape(rEntries[0].xSymbol); rEntries.pop_back(); nNumberOfEntries--; aRowHeights.pop_back(); @@ -580,7 +586,7 @@ awt::Size lcl_placeLegendEntries( break; // text shape - Reference< drawing::XShape > xTextShape( aTextShapes[nEntry] ); + rtl::Reference<SvxShapeText> xTextShape( aTextShapes[nEntry] ); if( xTextShape.is() ) { awt::Size aTextSize( xTextShape->getSize() ); @@ -591,7 +597,7 @@ awt::Size lcl_placeLegendEntries( } // symbol - Reference< drawing::XShape > xSymbol( rEntries[ nEntry ].aSymbol ); + rtl::Reference<SvxShapeGroup> & xSymbol( rEntries[ nEntry ].xSymbol ); if( xSymbol.is() ) { awt::Size aSymbolSize( rMaxSymbolExtent ); @@ -639,11 +645,11 @@ awt::Size lcl_placeLegendEntries( awt::Point aPos(0,0); for( sal_Int32 nEntry=0; nEntry<nNumberOfEntries; nEntry++ ) { - Reference< drawing::XShape > xSymbol( rEntries[ nEntry ].aSymbol ); + rtl::Reference<SvxShapeGroup> & xSymbol( rEntries[ nEntry ].xSymbol ); aPos = xSymbol->getPosition(); aPos.X += nLegendWidth; xSymbol->setPosition( aPos ); - Reference< drawing::XShape > xText( aTextShapes[ nEntry ] ); + rtl::Reference<SvxShapeText> & xText( aTextShapes[ nEntry ] ); aPos = xText->getPosition(); aPos.X += nLegendWidth; xText->setPosition( aPos ); @@ -801,7 +807,7 @@ bool lcl_shouldSymbolsBePlacedOnTheLeftSide( const Reference< beans::XPropertySe bool bSymbolsLeftSide = true; try { - if( SvtLanguageOptions().IsCTLFontEnabled() ) + if( SvtCTLOptions::IsCTLFontEnabled() ) { if(xLegendProp.is()) { @@ -824,9 +830,8 @@ bool lcl_shouldSymbolsBePlacedOnTheLeftSide( const Reference< beans::XPropertySe } std::vector<std::shared_ptr<VButton>> lcl_createButtons( - uno::Reference<drawing::XShapes> const & xLegendContainer, - uno::Reference<lang::XMultiServiceFactory> const & xShapeFactory, - ChartModel& rModel, bool bPlaceButtonsVertically, long & nUsedHeight) + rtl::Reference<SvxShapeGroupAnyD> const & xLegendContainer, + ChartModel& rModel, bool bPlaceButtonsVertically, tools::Long & nUsedHeight) { std::vector<std::shared_ptr<VButton>> aButtons; @@ -846,7 +851,7 @@ std::vector<std::shared_ptr<VButton>> lcl_createButtons( { auto pButton = std::make_shared<VButton>(); aButtons.push_back(pButton); - pButton->init(xLegendContainer, xShapeFactory); + pButton->init(xLegendContainer); awt::Point aNewPosition(x, y); pButton->setLabel(sColumnFieldEntry.Name); pButton->setCID("FieldButton.Column." + OUString::number(sColumnFieldEntry.DimensionIndex)); @@ -876,18 +881,16 @@ std::vector<std::shared_ptr<VButton>> lcl_createButtons( } // anonymous namespace VLegend::VLegend( - const Reference< XLegend > & xLegend, + rtl::Reference< Legend > xLegend, const Reference< uno::XComponentContext > & xContext, - const std::vector< LegendEntryProvider* >& rLegendEntryProviderList, - const Reference< drawing::XShapes >& xTargetPage, - const Reference< lang::XMultiServiceFactory >& xFactory, + std::vector< LegendEntryProvider* >&& rLegendEntryProviderList, + rtl::Reference<SvxShapeGroupAnyD> xTargetPage, ChartModel& rModel ) - : m_xTarget(xTargetPage) - , m_xShapeFactory(xFactory) - , m_xLegend(xLegend) + : m_xTarget(std::move(xTargetPage)) + , m_xLegend(std::move(xLegend)) , mrModel(rModel) , m_xContext(xContext) - , m_aLegendEntryProviderList(rLegendEntryProviderList) + , m_aLegendEntryProviderList(std::move(rLegendEntryProviderList)) , m_nDefaultWritingMode(text::WritingMode2::LR_TB) { } @@ -897,7 +900,7 @@ void VLegend::setDefaultWritingMode( sal_Int16 nDefaultWritingMode ) m_nDefaultWritingMode = nDefaultWritingMode; } -bool VLegend::isVisible( const Reference< XLegend > & xLegend ) +bool VLegend::isVisible( const rtl::Reference< Legend > & xLegend ) { if( ! xLegend.is()) return false; @@ -905,8 +908,7 @@ bool VLegend::isVisible( const Reference< XLegend > & xLegend ) bool bShow = false; try { - Reference< beans::XPropertySet > xLegendProp( xLegend, uno::UNO_QUERY_THROW ); - xLegendProp->getPropertyValue( "Show") >>= bShow; + xLegend->getPropertyValue( "Show") >>= bShow; } catch( const uno::Exception & ) { @@ -921,58 +923,50 @@ void VLegend::createShapes( const awt::Size & rPageSize, awt::Size & rDefaultLegendSize ) { - if(! (m_xLegend.is() && - m_xShapeFactory.is() && - m_xTarget.is())) + if(! (m_xLegend.is() && m_xTarget.is())) return; try { //create shape and add to page - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); - OUString aLegendParticle( ObjectIdentifier::createParticleForLegend( mrModel ) ); - m_xShape.set( pShapeFactory->createGroup2D( m_xTarget, - ObjectIdentifier::createClassifiedIdentifierForParticle( aLegendParticle )), - uno::UNO_QUERY); + OUString aLegendParticle( ObjectIdentifier::createParticleForLegend( &mrModel ) ); + m_xShape = ShapeFactory::createGroup2D( m_xTarget, + ObjectIdentifier::createClassifiedIdentifierForParticle( aLegendParticle ) ); // create and insert sub-shapes - Reference< drawing::XShapes > xLegendContainer( m_xShape, uno::UNO_QUERY ); - if( xLegendContainer.is()) + rtl::Reference<SvxShapeGroupAnyD> xLegendContainer = m_xShape; + if( xLegendContainer.is() ) { // for quickly setting properties tPropertyValues aLineFillProperties; tPropertyValues aTextProperties; - Reference< beans::XPropertySet > xLegendProp( m_xLegend, uno::UNO_QUERY ); css::chart::ChartLegendExpansion eExpansion = css::chart::ChartLegendExpansion_HIGH; awt::Size aLegendSize( rAvailableSpace ); bool bCustom = false; LegendPosition eLegendPosition = LegendPosition_LINE_END; - if (xLegendProp.is()) + // get Expansion property + m_xLegend->getPropertyValue("Expansion") >>= eExpansion; + if( eExpansion == css::chart::ChartLegendExpansion_CUSTOM ) { - // get Expansion property - xLegendProp->getPropertyValue("Expansion") >>= eExpansion; - if( eExpansion == css::chart::ChartLegendExpansion_CUSTOM ) + RelativeSize aRelativeSize; + if (m_xLegend->getPropertyValue("RelativeSize") >>= aRelativeSize) { - RelativeSize aRelativeSize; - if (xLegendProp->getPropertyValue("RelativeSize") >>= aRelativeSize) - { - aLegendSize.Width = static_cast<sal_Int32>(::rtl::math::approxCeil( aRelativeSize.Primary * rPageSize.Width )); - aLegendSize.Height = static_cast<sal_Int32>(::rtl::math::approxCeil( aRelativeSize.Secondary * rPageSize.Height )); - bCustom = true; - } - else - { - eExpansion = css::chart::ChartLegendExpansion_HIGH; - } + aLegendSize.Width = static_cast<sal_Int32>(::rtl::math::approxCeil( aRelativeSize.Primary * rPageSize.Width )); + aLegendSize.Height = static_cast<sal_Int32>(::rtl::math::approxCeil( aRelativeSize.Secondary * rPageSize.Height )); + bCustom = true; + } + else + { + eExpansion = css::chart::ChartLegendExpansion_HIGH; } - xLegendProp->getPropertyValue("AnchorPosition") >>= eLegendPosition; - lcl_getProperties( xLegendProp, aLineFillProperties, aTextProperties, rPageSize ); } + m_xLegend->getPropertyValue("AnchorPosition") >>= eLegendPosition; + lcl_getProperties( m_xLegend, aLineFillProperties, aTextProperties, rPageSize ); // create entries - double fViewFontSize = lcl_CalcViewFontSize( xLegendProp, rPageSize );//todo + double fViewFontSize = lcl_CalcViewFontSize( m_xLegend, rPageSize );//todo // #i109336# Improve auto positioning in chart sal_Int32 nSymbolHeight = static_cast< sal_Int32 >( fViewFontSize * 0.6 ); sal_Int32 nSymbolWidth = nSymbolHeight; @@ -998,15 +992,13 @@ void VLegend::createShapes( if (pLegendEntryProvider) { std::vector<ViewLegendEntry> aNewEntries = pLegendEntryProvider->createLegendEntries( - aMaxSymbolExtent, eLegendPosition, xLegendProp, - xLegendContainer, m_xShapeFactory, m_xContext, mrModel); - if (aNewEntries.size() == 0) - return; + aMaxSymbolExtent, eLegendPosition, m_xLegend, + xLegendContainer, m_xContext, mrModel); aViewEntries.insert( aViewEntries.end(), aNewEntries.begin(), aNewEntries.end() ); } } - bool bSymbolsLeftSide = lcl_shouldSymbolsBePlacedOnTheLeftSide( xLegendProp, m_nDefaultWritingMode ); + bool bSymbolsLeftSide = lcl_shouldSymbolsBePlacedOnTheLeftSide( m_xLegend, m_nDefaultWritingMode ); uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider( mrModel.getDataProvider(), uno::UNO_QUERY ); bool bIsPivotChart = xPivotTableDataProvider.is(); @@ -1014,12 +1006,12 @@ void VLegend::createShapes( if ( !aViewEntries.empty() || bIsPivotChart ) { // create buttons - long nUsedButtonHeight = 0; + tools::Long nUsedButtonHeight = 0; bool bPlaceButtonsVertically = (eLegendPosition != LegendPosition_PAGE_START && eLegendPosition != LegendPosition_PAGE_END && eExpansion != css::chart::ChartLegendExpansion_WIDE); - std::vector<std::shared_ptr<VButton>> aButtons = lcl_createButtons(xLegendContainer, m_xShapeFactory, mrModel, bPlaceButtonsVertically, nUsedButtonHeight); + std::vector<std::shared_ptr<VButton>> aButtons = lcl_createButtons(xLegendContainer, mrModel, bPlaceButtonsVertically, nUsedButtonHeight); // A custom size includes the size we used for buttons already, so we need to // subtract that from the size that is available for the legend @@ -1029,7 +1021,7 @@ void VLegend::createShapes( // place the legend entries aLegendSize = lcl_placeLegendEntries(aViewEntries, eExpansion, bSymbolsLeftSide, fViewFontSize, aMaxSymbolExtent, aTextProperties, xLegendContainer, - m_xShapeFactory, aLegendSize, nUsedButtonHeight, rPageSize, bIsPivotChart, rDefaultLegendSize); + aLegendSize, nUsedButtonHeight, rPageSize, bIsPivotChart, rDefaultLegendSize); uno::Reference<beans::XPropertySet> xModelPage(mrModel.getPageBackground()); @@ -1042,17 +1034,14 @@ void VLegend::createShapes( // create the buttons pButton->createShapes(xModelPage); } - } - Reference< drawing::XShape > xBorder = - pShapeFactory->createRectangle( xLegendContainer, - aLegendSize, - awt::Point(0,0), - aLineFillProperties.first, - aLineFillProperties.second, ShapeFactory::StackPosition::Bottom ); + rtl::Reference<SvxShapeRect> xBorder = ShapeFactory::createRectangle( + xLegendContainer, aLegendSize, awt::Point(0, 0), aLineFillProperties.first, + aLineFillProperties.second, ShapeFactory::StackPosition::Bottom); - //because of this name this border will be used for marking the legend - ShapeFactory::setShapeName( xBorder, "MarkHandles" ); + //because of this name this border will be used for marking the legend + ShapeFactory::setShapeName(xBorder, "MarkHandles"); + } } } catch( const uno::Exception & ) @@ -1073,18 +1062,17 @@ void VLegend::changePosition( { // determine position and alignment depending on default position awt::Size aLegendSize = m_xShape->getSize(); - Reference< beans::XPropertySet > xLegendProp( m_xLegend, uno::UNO_QUERY_THROW ); chart2::RelativePosition aRelativePosition; bool bDefaultLegendSize = rDefaultLegendSize.Width != 0 || rDefaultLegendSize.Height != 0; bool bAutoPosition = - ! (xLegendProp->getPropertyValue( "RelativePosition") >>= aRelativePosition); + ! (m_xLegend->getPropertyValue( "RelativePosition") >>= aRelativePosition); LegendPosition ePos = LegendPosition_LINE_END; - xLegendProp->getPropertyValue( "AnchorPosition") >>= ePos; + m_xLegend->getPropertyValue( "AnchorPosition") >>= ePos; bool bOverlay = false; - xLegendProp->getPropertyValue("Overlay") >>= bOverlay; + m_xLegend->getPropertyValue("Overlay") >>= bOverlay; //calculate position if( bAutoPosition ) { diff --git a/chart2/source/view/main/VLegend.hxx b/chart2/source/view/main/VLegend.hxx index 297a99129d4d..b6b6a0074e49 100644 --- a/chart2/source/view/main/VLegend.hxx +++ b/chart2/source/view/main/VLegend.hxx @@ -16,11 +16,13 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_MAIN_VLEGEND_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_MAIN_VLEGEND_HXX +#pragma once -#include <com/sun/star/uno/Reference.hxx> +#include <Legend.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <rtl/ref.hxx> +#include <svx/unoshape.hxx> #include <vector> namespace chart { class ChartModel; } @@ -35,16 +37,16 @@ namespace com::sun::star::uno { class XComponentContext; } namespace chart { +class Legend; class LegendEntryProvider; class VLegend { public: - VLegend( const css::uno::Reference< css::chart2::XLegend > & xLegend, + VLegend( rtl::Reference< ::chart::Legend > xLegend, const css::uno::Reference< css::uno::XComponentContext > & xContext, - const std::vector< LegendEntryProvider* >& rLegendEntryProviderList, - const css::uno::Reference< css::drawing::XShapes >& xTargetPage, - const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory, + std::vector< LegendEntryProvider* >&& rLegendEntryProviderList, + rtl::Reference<SvxShapeGroupAnyD> xTargetPage, ChartModel& rModel ); void setDefaultWritingMode( sal_Int16 nDefaultWritingMode ); @@ -68,13 +70,12 @@ public: const css::awt::Size & rDefaultLegendSize ); static bool isVisible( - const css::uno::Reference< css::chart2::XLegend > & xLegend ); + const rtl::Reference< ::chart::Legend > & xLegend ); private: - css::uno::Reference< css::drawing::XShapes > m_xTarget; - css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; - css::uno::Reference< css::chart2::XLegend > m_xLegend; - css::uno::Reference< css::drawing::XShape > m_xShape; + rtl::Reference<SvxShapeGroupAnyD> m_xTarget; + rtl::Reference<::chart::Legend> m_xLegend; + rtl::Reference< SvxShapeGroup > m_xShape; ChartModel& mrModel; @@ -86,6 +87,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/VLegendSymbolFactory.cxx b/chart2/source/view/main/VLegendSymbolFactory.cxx index 1ccc0de34324..0b230ed07f34 100644 --- a/chart2/source/view/main/VLegendSymbolFactory.cxx +++ b/chart2/source/view/main/VLegendSymbolFactory.cxx @@ -22,10 +22,8 @@ #include <ShapeFactory.hxx> #include <com/sun/star/drawing/Position3D.hpp> #include <com/sun/star/chart2/Symbol.hpp> -#include <com/sun/star/drawing/XShapes.hpp> #include <com/sun/star/drawing/Direction3D.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <sal/log.hxx> using namespace ::com::sun::star; @@ -60,7 +58,7 @@ void getPropNamesAndValues( const Reference< beans::XPropertySet >& xProp, ::chart::PropertyMapper::getMultiPropertyListsFromValueMap( rNames, rValues, aValueMap ); - uno::Any* pLineWidthAny = ::chart::PropertyMapper::getValuePointer(rValues,rNames,"LineWidth"); + uno::Any* pLineWidthAny = ::chart::PropertyMapper::getValuePointer(rValues,rNames,u"LineWidth"); sal_Int32 nLineWidth = 0; if( pLineWidthAny && (*pLineWidthAny>>=nLineWidth) ) { @@ -73,7 +71,7 @@ void getPropNamesAndValues( const Reference< beans::XPropertySet >& xProp, void lcl_setPropertiesToShape( const Reference< beans::XPropertySet > & xProp, - const Reference< drawing::XShape > & xShape, + const rtl::Reference< SvxShape > & xShape, ::chart::VLegendSymbolFactory::PropertyType ePropertyType, const awt::Size& aMaxSymbolExtent) { @@ -82,8 +80,7 @@ void lcl_setPropertiesToShape( getPropNamesAndValues( xProp, aPropNames, aPropValues, ePropertyType, aMaxSymbolExtent ); - Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY ); - ::chart::PropertyMapper::setMultiProperties( aPropNames, aPropValues, xShapeProp ); + ::chart::PropertyMapper::setMultiProperties( aPropNames, aPropValues, *xShape ); } } // anonymous namespace @@ -91,50 +88,43 @@ void lcl_setPropertiesToShape( namespace chart { -Reference< drawing::XShape > VLegendSymbolFactory::createSymbol( +rtl::Reference< SvxShapeGroup > VLegendSymbolFactory::createSymbol( const awt::Size& rEntryKeyAspectRatio, - const Reference< drawing::XShapes >& rSymbolContainer, + const rtl::Reference<SvxShapeGroupAnyD>& rSymbolContainer, LegendSymbolStyle eStyle, - const Reference< lang::XMultiServiceFactory > & xShapeFactory, const Reference< beans::XPropertySet > & xLegendEntryProperties, PropertyType ePropertyType, const uno::Any& rExplicitSymbol ) { - Reference< drawing::XShape > xResult; + rtl::Reference< SvxShapeGroup > xResult; - if( ! (rSymbolContainer.is() && xShapeFactory.is())) + if( !rSymbolContainer) return xResult; - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory); - xResult.set( pShapeFactory->createGroup2D( rSymbolContainer ), uno::UNO_QUERY ); - - Reference< drawing::XShapes > xResultGroup( xResult, uno::UNO_QUERY ); - if( ! xResultGroup.is()) + xResult = ShapeFactory::createGroup2D( rSymbolContainer ); + if( ! xResult) return xResult; + rtl::Reference<SvxShapeGroupAnyD> xResultGroup = xResult; + // add an invisible square box to maintain aspect ratio - pShapeFactory->createInvisibleRectangle( xResultGroup, rEntryKeyAspectRatio ); + ShapeFactory::createInvisibleRectangle( xResultGroup, rEntryKeyAspectRatio ); // create symbol try { if( eStyle == LegendSymbolStyle::Line ) { - Reference< drawing::XShape > xLine = - pShapeFactory->createLine( xResultGroup, awt::Size( rEntryKeyAspectRatio.Width, 0 ), + rtl::Reference<SvxShapePolyPolygon> xLine = + ShapeFactory::createLine( xResultGroup, awt::Size( rEntryKeyAspectRatio.Width, 0 ), awt::Point( 0, rEntryKeyAspectRatio.Height/2 )); - if( xLine.is()) - { - lcl_setPropertiesToShape( xLegendEntryProperties, xLine, ePropertyType, rEntryKeyAspectRatio ); - } + lcl_setPropertiesToShape( xLegendEntryProperties, xLine, ePropertyType, rEntryKeyAspectRatio ); - Reference< drawing::XShape > xSymbol; const sal_Int32 nSize = std::min(rEntryKeyAspectRatio.Width,rEntryKeyAspectRatio.Height); chart2::Symbol aSymbol; if( rExplicitSymbol >>= aSymbol ) { drawing::Direction3D aSymbolSize( nSize, nSize, 0 ); drawing::Position3D aPos( rEntryKeyAspectRatio.Width/2.0, rEntryKeyAspectRatio.Height/2.0, 0 ); - ShapeFactory* pFactory = ShapeFactory::getOrCreateShapeFactory( xShapeFactory ); if( aSymbol.Style == chart2::SymbolStyle_STANDARD ) { // take series color as fill color @@ -142,21 +132,21 @@ Reference< drawing::XShape > VLegendSymbolFactory::createSymbol( // border of symbols always same as fill color aSymbol.BorderColor = aSymbol.FillColor; - xSymbol.set( pFactory->createSymbol2D( + ShapeFactory::createSymbol2D( xResultGroup, aPos, aSymbolSize, aSymbol.StandardSymbol, aSymbol.BorderColor, - aSymbol.FillColor )); + aSymbol.FillColor ); } else if( aSymbol.Style == chart2::SymbolStyle_GRAPHIC ) { - xSymbol.set( pFactory->createGraphic2D( + ShapeFactory::createGraphic2D( xResultGroup, aPos, aSymbolSize, - aSymbol.Graphic )); + aSymbol.Graphic ); } else if( aSymbol.Style == chart2::SymbolStyle_AUTO ) { @@ -167,13 +157,10 @@ Reference< drawing::XShape > VLegendSymbolFactory::createSymbol( else if( eStyle == LegendSymbolStyle::Circle ) { sal_Int32 nSize = std::min( rEntryKeyAspectRatio.Width, rEntryKeyAspectRatio.Height ); - Reference< drawing::XShape > xShape = - pShapeFactory->createCircle( xResultGroup, awt::Size( nSize, nSize ), + rtl::Reference<SvxShapeCircle> xShape = + ShapeFactory::createCircle( xResultGroup, awt::Size( nSize, nSize ), awt::Point( rEntryKeyAspectRatio.Width/2-nSize/2, rEntryKeyAspectRatio.Height/2-nSize/2 )); - if( xShape.is() ) - { - lcl_setPropertiesToShape( xLegendEntryProperties, xShape, ePropertyType, awt::Size(0,0) ); // PropertyType::FilledSeries ); - } + lcl_setPropertiesToShape( xLegendEntryProperties, xShape, ePropertyType, awt::Size(0,0) ); // PropertyType::FilledSeries ); } else // eStyle == LegendSymbolStyle::Box { @@ -183,7 +170,7 @@ Reference< drawing::XShape > VLegendSymbolFactory::createSymbol( getPropNamesAndValues( xLegendEntryProperties, aPropNames, aPropValues, ePropertyType, awt::Size(0,0) );// PropertyType::FilledSeries - pShapeFactory->createRectangle( xResultGroup, + ShapeFactory::createRectangle( xResultGroup, rEntryKeyAspectRatio, awt::Point( 0, 0 ), aPropNames, aPropValues ); } diff --git a/chart2/source/view/main/VLineProperties.cxx b/chart2/source/view/main/VLineProperties.cxx index f1ca35e71730..81685337f704 100644 --- a/chart2/source/view/main/VLineProperties.cxx +++ b/chart2/source/view/main/VLineProperties.cxx @@ -19,8 +19,9 @@ #include <VLineProperties.hxx> #include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/LineCap.hpp> #include <com/sun/star/beans/XPropertySet.hpp> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> namespace chart { @@ -31,26 +32,29 @@ using namespace ::com::sun::star; VLineProperties::VLineProperties() { Color <<= sal_Int32(0x000000); //type sal_Int32 UNO_NAME_LINECOLOR - LineStyle <<= drawing::LineStyle_SOLID; //type drawing::LineStyle for property UNO_NAME_LINESTYLE - Transparence <<= sal_Int16(0);//type sal_Int16 for property UNO_NAME_LINETRANSPARENCE - Width <<= sal_Int32(0);//type sal_Int32 for property UNO_NAME_LINEWIDTH + LineStyle + <<= drawing::LineStyle_SOLID; //type drawing::LineStyle for property UNO_NAME_LINESTYLE + Transparence <<= sal_Int16(0); //type sal_Int16 for property UNO_NAME_LINETRANSPARENCE + Width <<= sal_Int32(0); //type sal_Int32 for property UNO_NAME_LINEWIDTH + LineCap <<= drawing::LineCap_BUTT; //type drawing::LineCap for property UNO_NAME_LINECAP } -void VLineProperties::initFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp ) +void VLineProperties::initFromPropertySet(const uno::Reference<beans::XPropertySet>& xProp) { - if(xProp.is()) + if (xProp.is()) { try { - Color = xProp->getPropertyValue( "LineColor" ); - LineStyle = xProp->getPropertyValue( "LineStyle" ); - Transparence = xProp->getPropertyValue( "LineTransparence" ); - Width = xProp->getPropertyValue( "LineWidth" ); - DashName = xProp->getPropertyValue( "LineDashName" ); + Color = xProp->getPropertyValue("LineColor"); + LineStyle = xProp->getPropertyValue("LineStyle"); + Transparence = xProp->getPropertyValue("LineTransparence"); + Width = xProp->getPropertyValue("LineWidth"); + DashName = xProp->getPropertyValue("LineDashName"); + LineCap = xProp->getPropertyValue("LineCap"); } - catch( const uno::Exception& ) + catch (const uno::Exception&) { - TOOLS_WARN_EXCEPTION("chart2", "" ); + TOOLS_WARN_EXCEPTION("chart2", ""); } } else @@ -63,11 +67,11 @@ bool VLineProperties::isLineVisible() const drawing::LineStyle aLineStyle(drawing::LineStyle_SOLID); LineStyle >>= aLineStyle; - if( aLineStyle != drawing::LineStyle_NONE ) + if (aLineStyle != drawing::LineStyle_NONE) { - sal_Int16 nLineTransparence=0; + sal_Int16 nLineTransparence = 0; Transparence >>= nLineTransparence; - if(nLineTransparence!=100) + if (nLineTransparence != 100) { bRet = true; } diff --git a/chart2/source/view/main/VPolarTransformation.cxx b/chart2/source/view/main/VPolarTransformation.cxx index 6d3ba587fc9c..9ec2eea3fc58 100644 --- a/chart2/source/view/main/VPolarTransformation.cxx +++ b/chart2/source/view/main/VPolarTransformation.cxx @@ -18,7 +18,6 @@ */ #include <VPolarTransformation.hxx> -#include <CommonConverters.hxx> using namespace ::com::sun::star; @@ -37,9 +36,9 @@ VPolarTransformation::~VPolarTransformation() { } -// ____ XTransformation ____ -Sequence< double > SAL_CALL VPolarTransformation::transform( - const Sequence< double >& rSourceValues ) +// ____ XTransformation2 ____ +css::drawing::Position3D VPolarTransformation::transform( + const Sequence< double >& rSourceValues ) const { double fScaledLogicAngle = rSourceValues[0]; double fScaledLogicRadius = rSourceValues[1]; @@ -58,17 +57,30 @@ Sequence< double > SAL_CALL VPolarTransformation::transform( //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector ::basegfx::B3DPoint aPoint(fX,fY,fZ); ::basegfx::B3DPoint aRet = m_aUnitCartesianToScene * aPoint; - return B3DPointToSequence(aRet); + return css::drawing::Position3D(aRet.getX(), aRet.getY(), aRet.getZ()); } -sal_Int32 SAL_CALL VPolarTransformation::getSourceDimension() +css::drawing::Position3D VPolarTransformation::transform( + const css::drawing::Position3D& rSourceValues ) const { - return 3; -} + double fScaledLogicAngle = rSourceValues.PositionX; + double fScaledLogicRadius = rSourceValues.PositionY; -sal_Int32 SAL_CALL VPolarTransformation::getTargetDimension() -{ - return 3; + if( m_aPositionHelper.isSwapXAndY() ) + std::swap(fScaledLogicAngle,fScaledLogicRadius); + + double fAngleDegree = m_aPositionHelper.transformToAngleDegree( fScaledLogicAngle, false ); + double fAnglePi = basegfx::deg2rad(fAngleDegree); + double fRadius = m_aPositionHelper.transformToRadius( fScaledLogicRadius, false); + + double fX=fRadius*cos(fAnglePi); + double fY=fRadius*sin(fAnglePi); + double fZ=rSourceValues.PositionZ; + + //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector + ::basegfx::B3DPoint aPoint(fX,fY,fZ); + ::basegfx::B3DPoint aRet = m_aUnitCartesianToScene * aPoint; + return css::drawing::Position3D(aRet.getX(), aRet.getY(), aRet.getZ()); } } // namespace chart diff --git a/chart2/source/view/main/VTitle.cxx b/chart2/source/view/main/VTitle.cxx index f0befe954659..e251fe95971c 100644 --- a/chart2/source/view/main/VTitle.cxx +++ b/chart2/source/view/main/VTitle.cxx @@ -20,19 +20,19 @@ #include "VTitle.hxx" #include <CommonConverters.hxx> #include <ShapeFactory.hxx> +#include <Title.hxx> #include <com/sun/star/chart2/XTitle.hpp> -#include <com/sun/star/drawing/XShape.hpp> #include <com/sun/star/beans/XPropertySet.hpp> -#include <tools/diagnose_ex.h> +#include <utility> +#include <comphelper/diagnose_ex.hxx> namespace chart { using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; -VTitle::VTitle( const uno::Reference< XTitle > & xTitle ) - : m_xTitle(xTitle) - , m_aCID() +VTitle::VTitle( uno::Reference< XTitle > xTitle ) + : m_xTitle(std::move(xTitle)) , m_fRotationAngleDegree(0.0) , m_nXPos(0) , m_nYPos(0) @@ -44,12 +44,10 @@ VTitle::~VTitle() } void VTitle::init( - const uno::Reference< drawing::XShapes >& xTargetPage - , const uno::Reference< lang::XMultiServiceFactory >& xFactory + const rtl::Reference<SvxShapeGroupAnyD>& xTargetPage , const OUString& rCID ) { m_xTarget = xTargetPage; - m_xShapeFactory = xFactory; m_aCID = rCID; } @@ -69,16 +67,13 @@ awt::Size VTitle::getUnrotatedSize() const //size before rotation awt::Size VTitle::getFinalSize() const //size after rotation { return ShapeFactory::getSizeAfterRotation( - m_xShape, m_fRotationAngleDegree ); + *m_xShape, m_fRotationAngleDegree ); } void VTitle::changePosition( const awt::Point& rPos ) { if(!m_xShape.is()) return; - uno::Reference< beans::XPropertySet > xShapeProp( m_xShape, uno::UNO_QUERY ); - if(!xShapeProp.is()) - return; try { m_nXPos = rPos.X; @@ -87,9 +82,9 @@ void VTitle::changePosition( const awt::Point& rPos ) //set position matrix //the matrix needs to be set at the end behind autogrow and such position influencing properties ::basegfx::B2DHomMatrix aM; - aM.rotate( -m_fRotationAngleDegree*F_PI/180.0 );//#i78696#->#i80521# + aM.rotate( basegfx::deg2rad(-m_fRotationAngleDegree) );//#i78696#->#i80521# aM.translate( m_nXPos, m_nYPos); - xShapeProp->setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) ); + m_xShape->SvxShape::setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) ); } catch( const uno::Exception& ) { @@ -97,6 +92,20 @@ void VTitle::changePosition( const awt::Point& rPos ) } } +bool VTitle::isVisible(const rtl::Reference< Title >& xTitle) { + if (!xTitle.is()) { + return false; + } + bool bShow = true; + try { + xTitle->getPropertyValue("Visible") >>= bShow; + } catch (const uno::Exception &) { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return bShow; +} + + void VTitle::createShapes( const awt::Point& rPos , const awt::Size& rReferenceSize @@ -141,8 +150,7 @@ void VTitle::createShapes( else nTextMaxWidth = rTextMaxWidth.Height; - ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory); - m_xShape =pShapeFactory->createText( m_xTarget, rReferenceSize, rPos, aStringList, xTitleProperties, + m_xShape = ShapeFactory::createText( m_xTarget, rReferenceSize, rPos, aStringList, xTitleProperties, m_fRotationAngleDegree, m_aCID, nTextMaxWidth ); } diff --git a/chart2/source/view/main/VTitle.hxx b/chart2/source/view/main/VTitle.hxx index 9fb0e905fa8a..792d7f6a0a5c 100644 --- a/chart2/source/view/main/VTitle.hxx +++ b/chart2/source/view/main/VTitle.hxx @@ -16,31 +16,33 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_CHART2_SOURCE_VIEW_MAIN_VTITLE_HXX -#define INCLUDED_CHART2_SOURCE_VIEW_MAIN_VTITLE_HXX +#pragma once #include <com/sun/star/awt/Size.hpp> #include <com/sun/star/uno/Reference.h> #include <rtl/ustring.hxx> +#include <rtl/ref.hxx> #include <sal/types.h> +#include <svx/unoshape.hxx> namespace com::sun::star::awt { struct Point; } namespace com::sun::star::chart2 { class XTitle; } namespace com::sun::star::drawing { class XShape; } namespace com::sun::star::drawing { class XShapes; } namespace com::sun::star::lang { class XMultiServiceFactory; } +class SvxShapeText; namespace chart { +class Title; class VTitle final { public: - explicit VTitle( const css::uno::Reference< css::chart2::XTitle > & xTitle ); + explicit VTitle( css::uno::Reference< css::chart2::XTitle > xTitle ); ~VTitle(); - void init( const css::uno::Reference< css::drawing::XShapes >& xTargetPage - , const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory + void init( const rtl::Reference<SvxShapeGroupAnyD>& xTargetPage , const OUString& rCID ); void createShapes( const css::awt::Point& rPos @@ -52,12 +54,13 @@ public: css::awt::Size getUnrotatedSize() const; css::awt::Size getFinalSize() const; void changePosition( const css::awt::Point& rPos ); + static bool isVisible( + const rtl::Reference< ::chart::Title > & xTitle); private: - css::uno::Reference< css::drawing::XShapes > m_xTarget; - css::uno::Reference< css::lang::XMultiServiceFactory> m_xShapeFactory; + rtl::Reference<SvxShapeGroupAnyD> m_xTarget; css::uno::Reference< css::chart2::XTitle > m_xTitle; - css::uno::Reference< css::drawing::XShape > m_xShape; + rtl::Reference<SvxShapeText> m_xShape; OUString m_aCID; double m_fRotationAngleDegree; @@ -66,6 +69,5 @@ private: }; } //namespace chart -#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |