/* -*- 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 .
*/
/* Excel 2007 does not change the series setting for a single data point, if none of some specific elements occur. But only one existing element in a data point will reset most other of these elements from the series (e.g.: series has <c:showVal>, data point has <c:showCatName>, this will reset <c:showVal> for this point, unless <c:showVal> is repeated in the data point). The elements <c:layout>, <c:numberFormat>,
<c:spPr>, <c:tx>, and <c:txPr> are not affected at all. */ bool bHasAnyElement = true; if (bMSO2007Doc)
{
bHasAnyElement = rDataLabel.moaSeparator.has_value() || rDataLabel.monLabelPos.has_value() ||
rDataLabel.mobShowCatName.has_value() || rDataLabel.mobShowLegendKey.has_value() ||
rDataLabel.mobShowPercent.has_value() || rDataLabel.mobShowSerName.has_value() ||
rDataLabel.mobShowVal.has_value();
}
// tdf#132174, tdf#136650: the inner data table has no own cell number format. if( bHasInternalData && bShowValue && !bShowPercent )
rDataLabel.maNumberFormat.mbSourceLinked = false;
// data label number format (percentage format wins over value format)
rFormatter.convertNumberFormat( rPropSet, rDataLabel.maNumberFormat, false, bShowPercent );
// data label text formatting (frame formatting not supported by Chart2) if( bDataSeriesLabel || (rDataLabel.mxTextProp.is() && !rDataLabel.mxTextProp->getParagraphs().empty()) )
convertTextProperty(rPropSet, rFormatter, rDataLabel.mxTextProp);
// data label separator (do not overwrite series separator, if no explicit point separator is present) // Set the data label separator to "new line" if the value is shown as percentage with a category name, // just like in MS-Office. In any other case the default separator will be a semicolon. if( bShowPercent && !bShowValue && ( bDataSeriesLabel || rDataLabel.moaSeparator.has_value() ) )
rPropSet.setProperty( PROP_LabelSeparator, rDataLabel.moaSeparator.value_or( "\n" ) ); elseif( bDataSeriesLabel || rDataLabel.moaSeparator.has_value() )
rPropSet.setProperty( PROP_LabelSeparator, rDataLabel.moaSeparator.value_or( "; " ) );
// data label placement (do not overwrite series placement, if no explicit point placement is present) if( !(bDataSeriesLabel || rDataLabel.monLabelPos.has_value()) ) return;
namespace csscd = css::chart::DataLabelPlacement;
sal_Int32 nPlacement = -1; switch( rDataLabel.monLabelPos.value_or( XML_TOKEN_INVALID ) )
{ case XML_outEnd: nPlacement = csscd::OUTSIDE; break; case XML_inEnd: nPlacement = csscd::INSIDE; break; case XML_ctr: nPlacement = csscd::CENTER; break; case XML_inBase: nPlacement = csscd::NEAR_ORIGIN; break; case XML_t: nPlacement = csscd::TOP; break; case XML_b: nPlacement = csscd::BOTTOM; break; case XML_l: nPlacement = csscd::LEFT; break; case XML_r: nPlacement = csscd::RIGHT; break; case XML_bestFit: nPlacement = csscd::AVOID_OVERLAP; break;
}
void importBorderProperties( PropertySet& rPropSet, Shape& rShape, const GraphicHelper& rGraphicHelper )
{
LineProperties& rLP = rShape.getLineProperties(); // no fill has the same effect as no border so skip it if (rLP.maLineFill.moFillType.has_value() && rLP.maLineFill.moFillType.value() == XML_noFill) return;
void lcl_ImportLeaderLineProperties(PropertySet& rPropSet, Shape& rShape, const GraphicHelper& rGraphicHelper)
{
LineProperties& rLP = rShape.getLineProperties(); // no fill has the same effect as no line so skip it if (rLP.maLineFill.moFillType.has_value() && rLP.maLineFill.moFillType.value() == XML_noFill) return;
if (rLP.moLineWidth.has_value())
{
sal_Int32 nWidth = convertEmuToHmm(rLP.moLineWidth.value());
rPropSet.setProperty(PROP_LineWidth, uno::Any(nWidth));
}
namespace
{ /// Inherit <c:dLbl> text props (if not set) from <c:dLbls> text props (if set). void InheritFromDataLabelsTextProps(const DataLabelsModel& rLabels, const DataLabelModel& rLabel)
{ // See if <c:dLbls> contains text properties to inherit. if (!rLabels.mxTextProp.is() || rLabels.mxTextProp->getParagraphs().empty())
{ return;
}
if (mrModel.mxShapeProp)
{ // Import baseline border properties for these data labels.
importBorderProperties(aPropSet, *mrModel.mxShapeProp, getFilter().getGraphicHelper());
uno::Reference<lang::XMultiServiceFactory> xFactory(getChartDocument(), uno::UNO_QUERY);
ModelObjectHelper& rHelper = getFilter().getModelObjectHelperForModel(xFactory);
importFillProperties(aPropSet, *mrModel.mxShapeProp, getFilter().getGraphicHelper(),
rHelper);
}
} // import leaderline of data labels if( !mrModel.mbShowLeaderLines )
aPropSet.setProperty( PROP_ShowCustomLeaderLines, false );
if (mrModel.mxLeaderLines)
{ // Import leaderline properties (SolidFill color, and width)
lcl_ImportLeaderLineProperties(aPropSet, *mrModel.mxLeaderLines,
getFilter().getGraphicHelper());
}
// data point label settings for (autoconst& pointLabel : mrModel.maPointLabels)
{ if (pointLabel->maNumberFormat.maFormatCode.isEmpty())
pointLabel->maNumberFormat = mrModel.maNumberFormat;
InheritFromDataLabelsTextProps(mrModel, *pointLabel);
// data point markers
rTypeGroup.convertMarker( aSeriesProp, mrModel.mnMarkerSymbol, mrModel.mnMarkerSize, mrModel.mxMarkerProp ); #if OOX_CHART_SMOOTHED_PER_SERIES // #i66858# smoothed series lines
rTypeGroup.convertLineSmooth( aSeriesProp, mrModel.mbSmooth ); #endif // 3D bar style (not possible to set at chart type -> set at all series)
rTypeGroup.convertBarGeometry( aSeriesProp, mrModel.monShape.value_or( rTypeGroup.getModel().mnShape ) ); // pie explosion (restricted to [0%,100%] in Chart2)
rTypeGroup.convertPieExplosion( aSeriesProp, mrModel.mnExplosion ); // invert if negative
aSeriesProp.setProperty(PROP_InvertNegative, mrModel.mbInvertNeg);
// set the (unused) property default value used by the Chart2 templates (true for pie/doughnut charts) bool bIsPie = rTypeInfo.meTypeCategory == TYPECATEGORY_PIE;
aSeriesProp.setProperty( PROP_VaryColorsByPoint, bVaryColorsByPoint );
// own area formatting for every data point (TODO: varying line color not supported) // #i91271# always set area formatting for every point in pie/doughnut charts to override their automatic point formatting if( bIsPie || (bVaryColorsByPoint && rTypeGroup.isSeriesFrameFormat() && ObjectFormatter::isAutomaticFill( mrModel.mxShapeProp )) )
{ /* Set the series point number as color cycle size at the object formatter to get correct start-shade/end-tint. TODO: in doughnut charts, the sizes of the series may vary, need to use the maximum
point count of all series. */
sal_Int32 nOldMax = rFormatter.getMaxSeriesIndex(); if( bVaryColorsByPoint )
rFormatter.setMaxSeriesIndex( nDataPointCount - 1 ); for( sal_Int32 nIndex = 0; nIndex < nDataPointCount; ++nIndex )
{ try
{
PropertySet aPointProp( xDataSeries->getDataPointByIndex( nIndex ) );
rFormatter.convertAutomaticFill( aPointProp, eObjType, bVaryColorsByPoint ? nIndex : mrModel.mnIndex );
} catch( Exception& )
{
}
}
rFormatter.setMaxSeriesIndex( nOldMax );
}
// data point settings for (autoconst& point : mrModel.maPoints)
{
DataPointConverter aPointConv(*this, *point);
aPointConv.convertFromModel( xDataSeries, rTypeGroup, mrModel );
}
/* Series data label settings. If and only if the series does not contain a c:dLbls element, then the c:dLbls element of the parent chart type is used (data label settings of the parent chart type are *not* merged
into own existing data label settings). */
ModelRef< DataLabelsModel > xLabels = mrModel.mxLabels.is() ? mrModel.mxLabels : rTypeGroup.getModel().mxLabels; if( xLabels.is() )
{ if( xLabels->maNumberFormat.maFormatCode.isEmpty() )
{ // Use number format code from Value series
DataSourceModel* pValues = mrModel.maSources.get( SeriesModel::VALUES ).get(); if( pValues )
xLabels->maNumberFormat.maFormatCode = pValues->mxDataSeq->maFormatCode;
}
DataLabelsConverter aLabelsConv( *this, *xLabels );
aLabelsConv.convertFromModel( xDataSeries, rTypeGroup );
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.