diff options
Diffstat (limited to 'chart2/source/view/charttypes/VSeriesPlotter.cxx')
-rw-r--r-- | chart2/source/view/charttypes/VSeriesPlotter.cxx | 852 |
1 files changed, 488 insertions, 364 deletions
diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index f405396e113c..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,25 +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 <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/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> @@ -87,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; @@ -101,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); } @@ -135,17 +144,14 @@ 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) @@ -193,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; @@ -205,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) ); @@ -271,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; } @@ -392,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 @@ -402,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 @@ -428,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)); @@ -451,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 ); @@ -470,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 @@ -497,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 ); @@ -507,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: @@ -526,8 +519,8 @@ 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: @@ -538,24 +531,31 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re if(fValue < 0) fValue *= -1.0; - aTextList[i] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true); + pTextList[i] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true); break; } - case DataPointCustomLabelFieldType_CELLREF: 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: @@ -566,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 ) @@ -584,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() ) { @@ -613,14 +623,11 @@ 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]; - } + 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 ) ); } @@ -641,7 +648,7 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re } //create text shape - xTextShape = ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory)-> + xTextShape = ShapeFactory:: createText( xTarget_, aText.makeStringAndClear(), *pPropNames, *pPropValues, ShapeFactory::makeTransformation( aScreenPosition2D ) ); } @@ -663,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 @@ -689,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*/ ); } @@ -703,37 +704,26 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re { xTextShape->setPosition(aRelPos); if( !m_xChartTypeModel->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) && - rDataSeries.getPropertiesOfSeries()->getPropertyValue( "ShowCustomLeaderLines" ).get<sal_Bool>()) + // "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); } } } @@ -741,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(); @@ -798,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 ) @@ -841,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) @@ -878,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; @@ -951,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 @@ -1053,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; @@ -1062,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 ) @@ -1084,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 & ) { @@ -1097,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() ); } @@ -1114,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 ) { @@ -1129,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 ) { @@ -1138,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; @@ -1257,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; @@ -1265,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 @@ -1278,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) @@ -1287,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 @@ -1299,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(); @@ -1361,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 ) @@ -1388,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; @@ -1408,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 ); @@ -1426,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( @@ -1471,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 ) { @@ -1529,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) { @@ -1570,55 +1573,41 @@ 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( tools::Long TimeResolution, const Date& rNullDate ) { m_nTimeResolution = TimeResolution; @@ -1693,9 +1682,8 @@ double VSeriesPlotter::getMinimumYInRange( double fMinimumX, double fMaximumX, s 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) @@ -1713,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; } @@ -1726,9 +1714,8 @@ double VSeriesPlotter::getMaximumYInRange( double fMinimumX, double fMaximumX, s 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) @@ -1746,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; } @@ -1804,8 +1791,8 @@ bool VSeriesPlotter::isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIn 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) { @@ -1820,15 +1807,15 @@ void VSeriesPlotter::getMinimumAndMaximumX( double& rfMinimum, double& rfMaximum } } 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::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) { @@ -1843,9 +1830,9 @@ void VSeriesPlotter::getMinimumAndMaximumYInContinuousXRange( double& rfMinY, do } } 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 @@ -1913,8 +1900,8 @@ sal_Int32 VDataSeriesGroup::getAttachedAxisIndexForFirstSeries() 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) { @@ -1931,9 +1918,9 @@ void VDataSeriesGroup::getMinimumAndMaximumX( double& rfMinimum, double& rfMaxim } } 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 { @@ -1956,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; @@ -1994,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; @@ -2027,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; @@ -2054,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. @@ -2063,7 +2051,7 @@ private: it = r.first; } - return it->second.get(); + return &it->second; } }; @@ -2072,8 +2060,8 @@ private: 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. @@ -2112,13 +2100,13 @@ void VDataSeriesGroup::getMinimumAndMaximumYInContinuousXRange( 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; @@ -2132,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 ) { @@ -2205,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) @@ -2220,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 ); @@ -2272,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; } @@ -2311,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) @@ -2327,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 ); } } @@ -2339,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; @@ -2375,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 ) @@ -2385,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& ) { @@ -2412,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; } @@ -2420,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 @@ -2458,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 @@ -2492,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; } @@ -2565,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(); @@ -2588,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(); @@ -2644,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; } @@ -2654,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 @@ -2673,10 +2764,11 @@ std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries( CHART2_SERVICE_NAME_CHARTTYPE_PIE); try { - if (bIsPie && m_xChartTypeModelProps.is()) + if (bIsPie) { bool bDonut = false; - if ((m_xChartTypeModelProps->getPropertyValue("UseRings") >>= bDonut) && bDonut) + // "UseRings" + if ((m_xChartTypeModel->getFastPropertyValue(PROP_PIECHARTTYPE_USE_RINGS) >>= bDonut) && bDonut) bIsPie = false; } } @@ -2692,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&) { @@ -2700,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) { @@ -2712,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 ) ); @@ -2733,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); } } @@ -2741,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 ); @@ -2758,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); } @@ -2769,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); } } } @@ -2817,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 ) { |