Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/xmloff/source/chart/SchXMLPlotAreaContext.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include "SchXMLPlotAreaContext.hxx"
21
#include <SchXMLImport.hxx>
22
#include "SchXMLAxisContext.hxx"
23
#include "SchXMLSeries2Context.hxx"
24
#include "SchXMLTools.hxx"
25
26
#include <comphelper/processfactory.hxx>
27
#include <comphelper/sequence.hxx>
28
#include <sal/log.hxx>
29
#include <comphelper/diagnose_ex.hxx>
30
#include <utility>
31
#include <xmloff/xmlnamespace.hxx>
32
#include <xmloff/xmluconv.hxx>
33
#include <xmloff/prstylei.hxx>
34
#include <xmloff/xmlstyle.hxx>
35
36
#include <com/sun/star/awt/Point.hpp>
37
#include <com/sun/star/awt/Size.hpp>
38
#include <com/sun/star/chart/ErrorBarStyle.hpp>
39
#include <com/sun/star/chart/X3DDisplay.hpp>
40
#include <com/sun/star/chart/XStatisticDisplay.hpp>
41
#include <com/sun/star/chart/XDiagramPositioning.hpp>
42
#include <com/sun/star/chart/XChartDocument.hpp>
43
#include <com/sun/star/chart2/XChartDocument.hpp>
44
#include <com/sun/star/chart2/data/XDataSink.hpp>
45
#include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
46
#include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
47
#include <com/sun/star/drawing/CameraGeometry.hpp>
48
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
49
#include <com/sun/star/lang/XServiceInfo.hpp>
50
51
using namespace com::sun::star;
52
using namespace ::xmloff::token;
53
54
using com::sun::star::uno::Reference;
55
56
namespace
57
{
58
59
struct lcl_AxisHasCategories
60
{
61
    bool operator() ( const SchXMLAxis & rAxis )
62
0
    {
63
0
        return rAxis.bHasCategories;
64
0
    }
65
};
66
67
OUString lcl_ConvertRange( const OUString & rRange, const uno::Reference< chart2::XChartDocument > & xDoc )
68
0
{
69
0
    OUString aResult = rRange;
70
0
    if(!xDoc.is())
71
0
        return aResult;
72
0
    uno::Reference< chart2::data::XRangeXMLConversion > xConversion(
73
0
        xDoc->getDataProvider(), uno::UNO_QUERY );
74
0
    if( xConversion.is())
75
0
        aResult = xConversion->convertRangeFromXML( rRange );
76
0
    return aResult;
77
0
}
78
79
} // anonymous namespace
80
81
SchXML3DSceneAttributesHelper::SchXML3DSceneAttributesHelper( SvXMLImport& rImporter )
82
0
    : SdXML3DSceneAttributesHelper( rImporter )
83
0
{
84
0
}
85
86
void SchXML3DSceneAttributesHelper::getCameraDefaultFromDiagram( const uno::Reference< chart::XDiagram >& xDiagram )
87
0
{
88
    //different defaults for camera geometry necessary to workaround wrong behaviour in old chart
89
    //in future make this version dependent if we have versioning (metastream) for ole objects
90
91
0
    try
92
0
    {
93
0
        uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY );
94
0
        if( xProp.is() )
95
0
        {
96
0
            drawing::CameraGeometry aCamGeo;
97
0
            xProp->getPropertyValue(u"D3DCameraGeometry"_ustr) >>= aCamGeo;
98
0
            maVRP.setX( aCamGeo.vrp.PositionX );
99
0
            maVRP.setY( aCamGeo.vrp.PositionY );
100
0
            maVRP.setZ( aCamGeo.vrp.PositionZ );
101
0
            maVPN.setX( aCamGeo.vpn.DirectionX );
102
0
            maVPN.setY( aCamGeo.vpn.DirectionY );
103
0
            maVPN.setZ( aCamGeo.vpn.DirectionZ );
104
0
            maVUP.setX( aCamGeo.vup.DirectionX );
105
0
            maVUP.setY( aCamGeo.vup.DirectionY );
106
0
            maVUP.setZ( aCamGeo.vup.DirectionZ );
107
0
        }
108
0
    }
109
0
    catch( const uno::Exception & )
110
0
    {
111
0
        TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught for property NumberOfLines");
112
0
    }
113
0
}
114
115
SchXML3DSceneAttributesHelper::~SchXML3DSceneAttributesHelper()
116
0
{
117
0
}
118
119
SchXMLPlotAreaContext::SchXMLPlotAreaContext(
120
    SchXMLImportHelper& rImpHelper,
121
    SvXMLImport& rImport,
122
    const OUString& rXLinkHRefAttributeToIndicateDataProvider,
123
    OUString& rCategoriesAddress,
124
    OUString& rChartAddress,
125
    bool & rbHasRangeAtPlotArea,
126
    bool & rAllRangeAddressesAvailable,
127
    bool & rColHasLabels,
128
    bool & rRowHasLabels,
129
    chart::ChartDataRowSource & rDataRowSource,
130
    SeriesDefaultsAndStyles& rSeriesDefaultsAndStyles,
131
    OUString aChartTypeServiceName,
132
    tSchXMLLSequencesPerIndex & rLSequencesPerIndex,
133
    const awt::Size & rChartSize ) :
134
0
        SvXMLImportContext( rImport ),
135
0
        mrImportHelper( rImpHelper ),
136
0
        mrCategoriesAddress( rCategoriesAddress ),
137
0
        mrSeriesDefaultsAndStyles( rSeriesDefaultsAndStyles ),
138
0
        mnNumOfLinesProp( 0 ),
139
0
        mbStockHasVolume( false ),
140
0
        mnSeries( 0 ),
141
0
        m_aGlobalSeriesImportInfo( rAllRangeAddressesAvailable ),
142
0
        maSceneImportHelper( rImport ),
143
0
        m_aOuterPositioning( rImport ),
144
0
        m_aInnerPositioning( rImport ),
145
0
        mbPercentStacked(false),
146
0
        m_bAxisPositionAttributeImported(false),
147
0
        m_rXLinkHRefAttributeToIndicateDataProvider(rXLinkHRefAttributeToIndicateDataProvider),
148
0
        mrChartAddress( rChartAddress ),
149
0
        m_rbHasRangeAtPlotArea( rbHasRangeAtPlotArea ),
150
0
        mrColHasLabels( rColHasLabels ),
151
0
        mrRowHasLabels( rRowHasLabels ),
152
0
        mrDataRowSource( rDataRowSource ),
153
0
        maChartTypeServiceName(std::move( aChartTypeServiceName )),
154
0
        mrLSequencesPerIndex( rLSequencesPerIndex ),
155
0
        mbGlobalChartTypeUsedBySeries( false ),
156
0
        maChartSize( rChartSize )
157
0
{
158
0
    m_rbHasRangeAtPlotArea = false;
159
160
    // get Diagram
161
0
    const uno::Reference< chart::XChartDocument >& xDoc = rImpHelper.GetChartDocument();
162
0
    if( xDoc.is())
163
0
    {
164
0
        mxDiagram = xDoc->getDiagram();
165
0
        mxNewDoc.set( xDoc, uno::UNO_QUERY );
166
167
0
        maSceneImportHelper.getCameraDefaultFromDiagram( mxDiagram );
168
0
    }
169
0
    SAL_WARN_IF( !mxDiagram.is(),"xmloff.chart", "Couldn't get XDiagram" );
170
171
    // turn off all axes initially
172
0
    uno::Any aFalseBool;
173
0
    aFalseBool <<= false;
174
175
0
    uno::Reference< lang::XServiceInfo > xInfo( mxDiagram, uno::UNO_QUERY );
176
0
    uno::Reference< beans::XPropertySet > xProp( mxDiagram, uno::UNO_QUERY );
177
0
    if( !xInfo.is() || !xProp.is() )
178
0
        return;
179
180
0
    try
181
0
    {
182
0
        xProp->setPropertyValue(u"HasXAxis"_ustr, aFalseBool );
183
0
        xProp->setPropertyValue(u"HasXAxisGrid"_ustr, aFalseBool );
184
0
        xProp->setPropertyValue(u"HasXAxisDescription"_ustr, aFalseBool );
185
0
        xProp->setPropertyValue(u"HasSecondaryXAxis"_ustr, aFalseBool );
186
0
        xProp->setPropertyValue(u"HasSecondaryXAxisDescription"_ustr, aFalseBool );
187
188
0
        xProp->setPropertyValue(u"HasYAxis"_ustr, aFalseBool );
189
0
        xProp->setPropertyValue(u"HasYAxisGrid"_ustr, aFalseBool );
190
0
        xProp->setPropertyValue(u"HasYAxisDescription"_ustr, aFalseBool );
191
0
        xProp->setPropertyValue(u"HasSecondaryYAxis"_ustr, aFalseBool );
192
0
        xProp->setPropertyValue(u"HasSecondaryYAxisDescription"_ustr, aFalseBool );
193
194
0
        xProp->setPropertyValue(u"HasZAxis"_ustr, aFalseBool );
195
0
        xProp->setPropertyValue(u"HasZAxisDescription"_ustr, aFalseBool );
196
197
0
        xProp->setPropertyValue(u"DataRowSource"_ustr, uno::Any(chart::ChartDataRowSource_COLUMNS) );
198
0
    }
199
0
    catch( const beans::UnknownPropertyException & )
200
0
    {
201
0
        SAL_WARN("xmloff.chart", "Property required by service not supported" );
202
0
    }
203
0
}
204
205
SchXMLPlotAreaContext::~SchXMLPlotAreaContext()
206
0
{}
207
208
void SchXMLPlotAreaContext::startFastElement (sal_Int32 /*nElement*/,
209
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
210
0
{
211
    // parse attributes
212
0
    uno::Reference< chart2::XChartDocument > xNewDoc( GetImport().GetModel(), uno::UNO_QUERY );
213
214
0
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
215
0
    {
216
0
        switch( aIter.getToken() )
217
0
        {
218
0
            case XML_ELEMENT(SVG, XML_X):
219
0
            case XML_ELEMENT(SVG_COMPAT, XML_X):
220
0
            case XML_ELEMENT(SVG, XML_Y):
221
0
            case XML_ELEMENT(SVG_COMPAT, XML_Y):
222
0
            case XML_ELEMENT(SVG, XML_WIDTH):
223
0
            case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
224
0
            case XML_ELEMENT(SVG, XML_HEIGHT):
225
0
            case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
226
0
                m_aOuterPositioning.readPositioningAttribute( aIter.getToken(), aIter.toView() );
227
0
                break;
228
0
            case XML_ELEMENT(CHART, XML_STYLE_NAME):
229
0
                msAutoStyleName = aIter.toString();
230
0
                break;
231
0
            case XML_ELEMENT(TABLE, XML_CELL_RANGE_ADDRESS):
232
0
                mrChartAddress = lcl_ConvertRange( aIter.toString(), xNewDoc );
233
                // indicator for getting data from the outside
234
0
                m_rbHasRangeAtPlotArea = true;
235
0
                break;
236
0
            case XML_ELEMENT(CHART, XML_DATA_SOURCE_HAS_LABELS):
237
0
                {
238
0
                    if( IsXMLToken(aIter, XML_BOTH) )
239
0
                        mrColHasLabels = mrRowHasLabels = true;
240
0
                    else if( IsXMLToken(aIter, XML_ROW) )
241
0
                        mrRowHasLabels = true;
242
0
                    else if( IsXMLToken(aIter, XML_COLUMN) )
243
0
                        mrColHasLabels = true;
244
0
                }
245
0
                break;
246
0
            case XML_ELEMENT(DR3D, XML_TRANSFORM):
247
0
            case XML_ELEMENT(DR3D, XML_VRP):
248
0
            case XML_ELEMENT(DR3D, XML_VPN):
249
0
            case XML_ELEMENT(DR3D, XML_VUP):
250
0
            case XML_ELEMENT(DR3D, XML_PROJECTION):
251
0
            case XML_ELEMENT(DR3D, XML_DISTANCE):
252
0
            case XML_ELEMENT(DR3D, XML_FOCAL_LENGTH):
253
0
            case XML_ELEMENT(DR3D, XML_SHADOW_SLANT):
254
0
            case XML_ELEMENT(DR3D, XML_SHADE_MODE):
255
0
            case XML_ELEMENT(DR3D, XML_AMBIENT_COLOR):
256
0
            case XML_ELEMENT(DR3D, XML_LIGHTING_MODE):
257
0
                maSceneImportHelper.processSceneAttribute( aIter );
258
0
                break;
259
0
            default:
260
0
                XMLOFF_WARN_UNKNOWN("xmloff", aIter);
261
0
        }
262
0
    }
263
264
0
    if( ! mxNewDoc.is())
265
0
    {
266
0
        uno::Reference< beans::XPropertySet > xDocProp( mrImportHelper.GetChartDocument(), uno::UNO_QUERY );
267
0
        if( xDocProp.is())
268
0
        {
269
0
            try
270
0
            {
271
0
                xDocProp->setPropertyValue(u"DataSourceLabelsInFirstColumn"_ustr, uno::Any(mrColHasLabels) );
272
0
                xDocProp->setPropertyValue(u"DataSourceLabelsInFirstRow"_ustr, uno::Any(mrRowHasLabels) );
273
0
            }
274
0
            catch( const beans::UnknownPropertyException & )
275
0
            {
276
0
                SAL_WARN("xmloff.chart", "Properties missing" );
277
0
            }
278
0
        }
279
0
    }
280
281
    // set properties
282
0
    uno::Reference< beans::XPropertySet > xProp( mxDiagram, uno::UNO_QUERY );
283
0
    if( !msAutoStyleName.isEmpty())
284
0
    {
285
0
        if( xProp.is())
286
0
        {
287
0
            const SvXMLStylesContext* pStylesCtxt = mrImportHelper.GetAutoStylesContext();
288
0
            if( pStylesCtxt )
289
0
            {
290
0
                const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(
291
0
                    SchXMLImportHelper::GetChartFamilyID(), msAutoStyleName );
292
293
0
                XMLPropStyleContext* pPropStyleContext =
294
0
                    const_cast< XMLPropStyleContext * >(
295
0
                        dynamic_cast< const XMLPropStyleContext * >( pStyle ) );
296
0
                if( pPropStyleContext )
297
0
                {
298
0
                    pPropStyleContext->FillPropertySet( xProp );
299
300
                    // get the data row source that was set without having data
301
0
                    xProp->getPropertyValue(u"DataRowSource"_ustr)
302
0
                        >>= mrDataRowSource;
303
304
                    //lines on/off
305
                    //this old property is not supported fully anymore with the new chart, so we need to get the information a little bit different from similar properties
306
0
                    mrSeriesDefaultsAndStyles.maLinesOnProperty = SchXMLTools::getPropertyFromContext(
307
0
                        u"Lines", pPropStyleContext, pStylesCtxt );
308
309
                    //handle automatic position and size
310
0
                    m_aOuterPositioning.readAutomaticPositioningProperties( pPropStyleContext, pStylesCtxt );
311
312
                    //correct default starting angle for old 3D pies
313
0
                    if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan3_0( GetImport().GetModel() ) )
314
0
                    {
315
0
                        bool bIs3d = false;
316
0
                        if( xProp.is() && ( xProp->getPropertyValue(u"Dim3D"_ustr) >>= bIs3d ) &&
317
0
                            bIs3d )
318
0
                        {
319
0
                            if( maChartTypeServiceName == "com.sun.star.chart2.PieChartType" || maChartTypeServiceName == "com.sun.star.chart2.DonutChartType" )
320
0
                            {
321
0
                                OUString aPropName( u"StartingAngle"_ustr );
322
0
                                uno::Any aAStartingAngle( SchXMLTools::getPropertyFromContext( aPropName, pPropStyleContext, pStylesCtxt ) );
323
0
                                if( !aAStartingAngle.hasValue() )
324
0
                                    xProp->setPropertyValue( aPropName, uno::Any(sal_Int32(0)) ) ;
325
0
                            }
326
0
                        }
327
0
                    }
328
0
                }
329
0
            }
330
0
        }
331
0
    }
332
333
    //remember default values for dataseries
334
0
    if(xProp.is())
335
0
    {
336
0
        try
337
0
        {
338
0
            mrSeriesDefaultsAndStyles.maSymbolTypeDefault = xProp->getPropertyValue(u"SymbolType"_ustr);
339
0
            mrSeriesDefaultsAndStyles.maDataCaptionDefault = xProp->getPropertyValue(u"DataCaption"_ustr);
340
341
0
            mrSeriesDefaultsAndStyles.maMeanValueDefault = xProp->getPropertyValue(u"MeanValue"_ustr);
342
0
            mrSeriesDefaultsAndStyles.maRegressionCurvesDefault = xProp->getPropertyValue(u"RegressionCurves"_ustr);
343
344
0
            bool bStacked = false;
345
0
            mrSeriesDefaultsAndStyles.maStackedDefault = xProp->getPropertyValue(u"Stacked"_ustr);
346
0
            mrSeriesDefaultsAndStyles.maStackedDefault >>= bStacked;
347
0
            mrSeriesDefaultsAndStyles.maPercentDefault = xProp->getPropertyValue(u"Percent"_ustr);
348
0
            mrSeriesDefaultsAndStyles.maPercentDefault >>= mbPercentStacked;
349
0
            mrSeriesDefaultsAndStyles.maStackedBarsConnectedDefault = xProp->getPropertyValue(u"StackedBarsConnected"_ustr);
350
351
            // deep
352
0
            uno::Any aDeepProperty( xProp->getPropertyValue(u"Deep"_ustr));
353
            // #124488# old versions store a 3d area and 3D line deep chart with Deep==false => workaround for this
354
0
            if( ! (bStacked || mbPercentStacked ))
355
0
            {
356
0
                if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( GetImport().GetModel() ) )
357
0
                {
358
0
                    bool bIs3d = false;
359
0
                    if( ( xProp->getPropertyValue(u"Dim3D"_ustr) >>= bIs3d ) &&
360
0
                        bIs3d )
361
0
                    {
362
0
                        if( maChartTypeServiceName == "com.sun.star.chart2.AreaChartType" || maChartTypeServiceName == "com.sun.star.chart2.LineChartType" )
363
0
                        {
364
0
                            aDeepProperty <<= true;
365
0
                        }
366
0
                    }
367
0
                }
368
0
            }
369
0
            mrSeriesDefaultsAndStyles.maDeepDefault = std::move(aDeepProperty);
370
371
0
            xProp->getPropertyValue(u"NumberOfLines"_ustr) >>= mnNumOfLinesProp;
372
0
            xProp->getPropertyValue(u"Volume"_ustr) >>= mbStockHasVolume;
373
0
        }
374
0
        catch( const uno::Exception & )
375
0
        {
376
0
            TOOLS_INFO_EXCEPTION("xmloff.chart", "PlotAreaContext:EndElement(): Exception caught");
377
0
        }
378
0
    } // if
379
380
0
    bool bCreateInternalDataProvider = false;
381
0
    if( m_rXLinkHRefAttributeToIndicateDataProvider == "." ) //data comes from the chart itself
382
0
        bCreateInternalDataProvider = true;
383
0
    else if( m_rXLinkHRefAttributeToIndicateDataProvider == ".." ) //data comes from the parent application
384
0
        bCreateInternalDataProvider = false;
385
0
    else if( !m_rXLinkHRefAttributeToIndicateDataProvider.isEmpty() ) //not supported so far to get the data by sibling objects -> fall back to chart itself
386
0
        bCreateInternalDataProvider = true;
387
0
    else if( !m_rbHasRangeAtPlotArea )
388
0
        bCreateInternalDataProvider = true;
389
390
0
    if( bCreateInternalDataProvider && mxNewDoc.is() )
391
0
    {
392
        // we have no complete range => we have own data, so switch the data
393
        // provider to internal. Clone is not necessary, as we don't have any
394
        // data yet.
395
0
        mxNewDoc->createInternalDataProvider( false /* bCloneExistingData */ );
396
0
        if( xProp.is() && mrDataRowSource!=chart::ChartDataRowSource_COLUMNS )
397
0
            xProp->setPropertyValue(u"DataRowSource"_ustr, uno::Any(mrDataRowSource) );
398
0
    }
399
0
}
400
401
css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLPlotAreaContext::createFastChildContext(
402
    sal_Int32 nElement,
403
    const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
404
0
{
405
0
    SvXMLImportContext* pContext = nullptr;
406
407
0
    switch(nElement)
408
0
    {
409
0
        case XML_ELEMENT(CHART_EXT, XML_COORDINATE_REGION):
410
0
        case XML_ELEMENT(CHART, XML_COORDINATE_REGION):
411
0
        {
412
0
            pContext = new SchXMLCoordinateRegionContext( GetImport(), m_aInnerPositioning );
413
0
        }
414
0
        break;
415
416
0
        case XML_ELEMENT(CHART, XML_AXIS):
417
0
        {
418
0
            bool bAddMissingXAxisForNetCharts = false;
419
0
            bool bAdaptWrongPercentScaleValues = false;
420
0
            if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_3( GetImport().GetModel() ) )
421
0
            {
422
                //correct errors from older versions
423
424
                // for NetCharts there were no xAxis exported to older files
425
                // so we need to add the x axis here for those old NetChart files
426
0
                if ( maChartTypeServiceName == "com.sun.star.chart2.NetChartType" )
427
0
                    bAddMissingXAxisForNetCharts = true;
428
429
                //Issue 59288
430
0
                if( mbPercentStacked )
431
0
                    bAdaptWrongPercentScaleValues = true;
432
0
            }
433
434
0
            bool bAdaptXAxisOrientationForOld2DBarCharts = false;
435
0
            if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan2_4( GetImport().GetModel() ) )
436
0
            {
437
                //issue74660
438
0
                if ( maChartTypeServiceName == "com.sun.star.chart2.ColumnChartType" )
439
0
                    bAdaptXAxisOrientationForOld2DBarCharts = true;
440
0
            }
441
442
0
            pContext = new SchXMLAxisContext( mrImportHelper, GetImport(), mxDiagram, maAxes, mrCategoriesAddress,
443
0
                                              bAddMissingXAxisForNetCharts, bAdaptWrongPercentScaleValues, bAdaptXAxisOrientationForOld2DBarCharts, m_bAxisPositionAttributeImported );
444
0
        }
445
0
        break;
446
447
0
        case XML_ELEMENT(CHART, XML_SERIES):
448
0
            {
449
0
                if( mxNewDoc.is())
450
0
                {
451
0
                    pContext = new SchXMLSeries2Context(
452
0
                        mrImportHelper, GetImport(),
453
0
                        mxNewDoc, maAxes,
454
0
                        mrSeriesDefaultsAndStyles.maSeriesStyleVector,
455
0
                        mrSeriesDefaultsAndStyles.maRegressionStyleVector,
456
0
                        mnSeries,
457
0
                        mbStockHasVolume,
458
0
                        m_aGlobalSeriesImportInfo,
459
0
                        maChartTypeServiceName,
460
0
                        mrLSequencesPerIndex,
461
0
                        mbGlobalChartTypeUsedBySeries, maChartSize );
462
0
                }
463
0
                mnSeries++;
464
0
            }
465
0
            break;
466
467
0
        case XML_ELEMENT(CHART, XML_WALL):
468
0
            pContext = new SchXMLWallFloorContext( mrImportHelper, GetImport(), mxDiagram,
469
0
                                                   SchXMLWallFloorContext::CONTEXT_TYPE_WALL );
470
0
            break;
471
0
        case XML_ELEMENT(CHART, XML_FLOOR):
472
0
            pContext = new SchXMLWallFloorContext( mrImportHelper, GetImport(), mxDiagram,
473
0
                                                   SchXMLWallFloorContext::CONTEXT_TYPE_FLOOR );
474
0
            break;
475
476
0
        case XML_ELEMENT(DR3D, XML_LIGHT):
477
0
            pContext = maSceneImportHelper.create3DLightContext( xAttrList );
478
0
            break;
479
480
        // elements for stock charts
481
0
        case XML_ELEMENT(CHART, XML_STOCK_GAIN_MARKER):
482
0
            pContext = new SchXMLStockContext( mrImportHelper, GetImport(), mxDiagram,
483
0
                                               SchXMLStockContext::CONTEXT_TYPE_GAIN );
484
0
            break;
485
0
        case XML_ELEMENT(CHART, XML_STOCK_LOSS_MARKER):
486
0
            pContext = new SchXMLStockContext( mrImportHelper, GetImport(), mxDiagram,
487
0
                                               SchXMLStockContext::CONTEXT_TYPE_LOSS );
488
0
            break;
489
0
        case XML_ELEMENT(CHART, XML_STOCK_RANGE_LINE):
490
0
            pContext = new SchXMLStockContext( mrImportHelper, GetImport(), mxDiagram,
491
0
                                               SchXMLStockContext::CONTEXT_TYPE_RANGE );
492
0
            break;
493
0
        default:
494
0
            XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
495
0
    }
496
497
0
    return pContext;
498
0
}
499
500
void SchXMLPlotAreaContext::endFastElement(sal_Int32 )
501
0
{
502
    // set categories
503
0
    if( !mrCategoriesAddress.isEmpty() && mxNewDoc.is())
504
0
    {
505
0
        uno::Reference< chart2::data::XDataProvider > xDataProvider(
506
0
            mxNewDoc->getDataProvider()  );
507
        // @todo: correct coordinate system index
508
0
        sal_Int32 nDimension( 0 );
509
0
        ::std::vector< SchXMLAxis >::const_iterator aIt(
510
0
            ::std::find_if( maAxes.begin(), maAxes.end(), lcl_AxisHasCategories()));
511
0
        if( aIt != maAxes.end())
512
0
            nDimension = static_cast< sal_Int32 >( (*aIt).eDimension );
513
0
        SchXMLTools::CreateCategories(
514
0
            xDataProvider, mxNewDoc, mrCategoriesAddress,
515
0
            0 /* nCooSysIndex */,
516
0
            nDimension, &mrLSequencesPerIndex );
517
0
    }
518
519
0
    uno::Reference< beans::XPropertySet > xDiaProp( mxDiagram, uno::UNO_QUERY );
520
0
    if( xDiaProp.is())
521
0
    {
522
0
        bool bIsThreeDim = false;
523
0
        uno::Any aAny = xDiaProp->getPropertyValue(u"Dim3D"_ustr);
524
0
        aAny >>= bIsThreeDim;
525
526
        // set 3d scene attributes
527
0
        if( bIsThreeDim )
528
0
        {
529
            // set scene attributes at diagram
530
0
            maSceneImportHelper.setSceneAttributes( xDiaProp );
531
0
        }
532
533
        // set correct number of lines at series
534
0
        if( ! m_aGlobalSeriesImportInfo.rbAllRangeAddressesAvailable && mnNumOfLinesProp > 0 && maChartTypeServiceName == "com.sun.star.chart2.ColumnChartType" )
535
0
        {
536
0
            try
537
0
            {
538
0
                xDiaProp->setPropertyValue(u"NumberOfLines"_ustr,
539
0
                                            uno::Any( mnNumOfLinesProp ));
540
0
            }
541
0
            catch( const uno::Exception & )
542
0
            {
543
0
                TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught for property NumberOfLines");
544
0
            }
545
0
        }
546
547
        // #i32366# stock has volume
548
0
        if( mxDiagram->getDiagramType() == "com.sun.star.chart.StockDiagram" &&
549
0
            mbStockHasVolume )
550
0
        {
551
0
            try
552
0
            {
553
0
                xDiaProp->setPropertyValue(u"Volume"_ustr,
554
0
                                            uno::Any( true ));
555
0
            }
556
0
            catch( const uno::Exception & )
557
0
            {
558
0
                TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught for property Volume");
559
0
            }
560
0
        }
561
0
    }
562
563
    // set changed size and position after properties (esp. 3d)
564
565
0
    uno::Reference< chart::XDiagramPositioning > xDiaPos( mxDiagram, uno::UNO_QUERY );
566
0
    if( xDiaPos.is())
567
0
    {
568
0
        if( !m_aOuterPositioning.isAutomatic() )
569
0
        {
570
0
            if( m_aInnerPositioning.hasPosSize() )
571
0
                xDiaPos->setDiagramPositionExcludingAxes( m_aInnerPositioning.getRectangle() );
572
0
            else if( m_aOuterPositioning.hasPosSize() )
573
0
            {
574
0
                if( SchXMLTools::isDocumentGeneratedWithOpenOfficeOlderThan3_3( GetImport().GetModel() ) ) //old version of OOo did write a wrong rectangle for the diagram size
575
0
                    xDiaPos->setDiagramPositionIncludingAxesAndAxisTitles( m_aOuterPositioning.getRectangle() );
576
0
                else
577
0
                    xDiaPos->setDiagramPositionIncludingAxes( m_aOuterPositioning.getRectangle() );
578
0
            }
579
0
        }
580
0
    }
581
582
0
    SchXMLAxisContext::CorrectAxisPositions( uno::Reference< chart2::XChartDocument >( mrImportHelper.GetChartDocument(), uno::UNO_QUERY ), maChartTypeServiceName, GetImport().GetODFVersion(), m_bAxisPositionAttributeImported );
583
0
}
584
585
SchXMLDataLabelSpanContext::SchXMLDataLabelSpanContext( SvXMLImport& rImport, ::std::vector<OUString>& rLabels):
586
0
    SvXMLImportContext( rImport ),
587
0
    mrLabels(rLabels)
588
0
{
589
0
}
590
591
void SchXMLDataLabelSpanContext::characters(const OUString& rChars)
592
0
{
593
0
    maCharBuffer.append(rChars);
594
0
}
595
596
void SchXMLDataLabelSpanContext::endFastElement(sal_Int32 )
597
0
{
598
0
    mrLabels.push_back(maCharBuffer.makeStringAndClear());
599
0
}
600
601
SchXMLDataLabelParaContext::SchXMLDataLabelParaContext( SvXMLImport& rImport, ::std::vector<OUString>& rLabels):
602
0
    SvXMLImportContext( rImport ),
603
0
    mrLabels(rLabels)
604
0
{
605
0
}
606
607
css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataLabelParaContext::createFastChildContext(
608
    sal_Int32 nElement,
609
    const css::uno::Reference< css::xml::sax::XFastAttributeList >&  )
610
0
{
611
0
    if ( nElement == XML_ELEMENT(TEXT, XML_SPAN) )
612
0
        return new SchXMLDataLabelSpanContext(GetImport(), mrLabels);
613
0
    else
614
0
        XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
615
0
    return nullptr;
616
0
}
617
618
SchXMLDataLabelContext::SchXMLDataLabelContext(SvXMLImport& rImport,
619
                                               CustomLabelsInfo& rLabels,
620
                                               DataRowPointStyle& rDataLabelStyle)
621
0
    : SvXMLImportContext(rImport)
622
0
    , mrLabels(rLabels)
623
0
    , mrDataLabelStyle(rDataLabelStyle)
624
0
{
625
0
}
626
627
css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataLabelContext::createFastChildContext(
628
    sal_Int32 nElement,
629
    const css::uno::Reference< css::xml::sax::XFastAttributeList >&  )
630
0
{
631
0
    if ( nElement == XML_ELEMENT(TEXT, XML_P) )
632
0
        return new SchXMLDataLabelParaContext(GetImport(), mrLabels.mLabels);
633
0
    else
634
0
        XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
635
0
    return nullptr;
636
0
}
637
638
void SchXMLDataLabelContext::startFastElement(
639
    sal_Int32 /*nElement*/,
640
    const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
641
0
{
642
0
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
643
0
    {
644
0
        switch(aIter.getToken())
645
0
        {
646
0
            case XML_ELEMENT(SVG, XML_X):
647
0
            case XML_ELEMENT(SVG_COMPAT, XML_X):
648
0
            {
649
0
                sal_Int32 nResultValue;
650
0
                GetImport().GetMM100UnitConverter().convertMeasureToCore(nResultValue, aIter.toView());
651
0
                mrDataLabelStyle.mo_nLabelAbsolutePosX = nResultValue;
652
0
                break;
653
0
            }
654
0
            case XML_ELEMENT(SVG, XML_Y):
655
0
            case XML_ELEMENT(SVG_COMPAT, XML_Y):
656
0
            {
657
0
                sal_Int32 nResultValue;
658
0
                GetImport().GetMM100UnitConverter().convertMeasureToCore(nResultValue, aIter.toView());
659
0
                mrDataLabelStyle.mo_nLabelAbsolutePosY = nResultValue;
660
0
                break;
661
0
            }
662
0
            case XML_ELEMENT(CHART, XML_STYLE_NAME):
663
0
                mrDataLabelStyle.msStyleName = aIter.toString();
664
0
                break;
665
0
            case XML_ELEMENT(LO_EXT, XML_DATA_LABEL_GUID):
666
0
                mrLabels.msLabelGuid = aIter.toString();
667
0
                mrLabels.mbDataLabelsRange = true;
668
0
                break;
669
0
            case XML_ELEMENT(LO_EXT, XML_DATA_LABELS_CELL_RANGE):
670
0
                mrLabels.msLabelsCellRange = aIter.toString();
671
0
                mrLabels.mbDataLabelsRange = true;
672
0
                break;
673
0
            default:
674
0
                XMLOFF_WARN_UNKNOWN("xmloff", aIter);
675
0
        }
676
0
    }
677
0
}
678
679
680
SchXMLDataPointContext::SchXMLDataPointContext(  SvXMLImport& rImport,
681
                                                 ::std::vector< DataRowPointStyle >& rStyleVector,
682
                                                 const css::uno::Reference< css::chart2::XDataSeries >& xSeries,
683
                                                 sal_Int32& rIndex,
684
                                                 bool bSymbolSizeForSeriesIsMissingInFile ) :
685
0
        SvXMLImportContext( rImport ),
686
0
        mrStyleVector( rStyleVector ),
687
0
        mrIndex( rIndex ),
688
0
        mDataPoint(DataRowPointStyle::DATA_POINT, xSeries, rIndex, 1, OUString{}),
689
0
        mDataLabel(DataRowPointStyle::DATA_LABEL_POINT, xSeries, rIndex, 1, OUString{})
690
0
{
691
0
    mDataPoint.mbSymbolSizeForSeriesIsMissingInFile = bSymbolSizeForSeriesIsMissingInFile;
692
0
}
693
694
css::uno::Reference< css::xml::sax::XFastContextHandler > SchXMLDataPointContext::createFastChildContext(
695
    sal_Int32 nElement,
696
    const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
697
0
{
698
0
    SvXMLImportContext* pContext = nullptr;
699
0
    switch(nElement)
700
0
    {
701
0
        case XML_ELEMENT(CHART, XML_DATA_LABEL):
702
0
            mbHasLabelParagraph = true;
703
0
            pContext = new SchXMLDataLabelContext(GetImport(), mDataPoint.mCustomLabels,
704
0
                                                  mDataLabel);
705
0
            break;
706
0
        default:
707
0
            XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
708
0
    }
709
0
    return pContext;
710
0
}
711
712
SchXMLDataPointContext::~SchXMLDataPointContext()
713
0
{
714
0
}
715
716
void SchXMLDataPointContext::startFastElement (sal_Int32 /*Element*/,
717
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
718
0
{
719
0
    OUString sAutoStyleName;
720
0
    sal_Int32 nRepeat = 1;
721
0
    OUString sCustomLabelField;
722
723
0
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
724
0
    {
725
0
        switch (aIter.getToken())
726
0
        {
727
0
            case XML_ELEMENT(CHART, XML_STYLE_NAME):
728
0
            {
729
0
                sAutoStyleName = aIter.toString();
730
0
                mDataPoint.msStyleName = sAutoStyleName;
731
0
                mDataLabel.msStyleNameOfParent = sAutoStyleName;
732
0
                break;
733
0
            }
734
0
            case XML_ELEMENT(CHART, XML_REPEATED):
735
0
            {
736
0
                nRepeat = aIter.toInt32();
737
0
                mDataPoint.m_nPointRepeat = nRepeat;
738
0
                mDataLabel.m_nPointRepeat = nRepeat;
739
0
                break;
740
0
            }
741
            // Deprecated. New documents use the chart:data-label element
742
            // instead in order to store custom label text.
743
0
            case XML_ELEMENT(LO_EXT, XML_CUSTOM_LABEL_FIELD):
744
0
                if (!mbHasLabelParagraph)
745
0
                {
746
0
                    sCustomLabelField = aIter.toString();
747
0
                    mDataPoint.mCustomLabels.mLabels.push_back(sCustomLabelField);
748
0
                }
749
0
                break;
750
0
            case XML_ELEMENT(LO_EXT, XML_HIDE_LEGEND):
751
0
            {
752
0
                bool bHideLegend = aIter.toBoolean();
753
0
                if (bHideLegend)
754
0
                {
755
0
                    uno::Sequence<sal_Int32> deletedLegendEntriesSeq;
756
0
                    Reference<beans::XPropertySet> xSeriesProp(mDataPoint.m_xSeries, uno::UNO_QUERY);
757
0
                    xSeriesProp->getPropertyValue(u"DeletedLegendEntries"_ustr) >>= deletedLegendEntriesSeq;
758
0
                    std::vector<sal_Int32> deletedLegendEntries;
759
0
                    for (const auto& deletedLegendEntry : deletedLegendEntriesSeq)
760
0
                    {
761
0
                        deletedLegendEntries.push_back(deletedLegendEntry);
762
0
                    }
763
0
                    deletedLegendEntries.push_back(mDataPoint.m_nPointIndex);
764
0
                    xSeriesProp->setPropertyValue(u"DeletedLegendEntries"_ustr, uno::Any(comphelper::containerToSequence(deletedLegendEntries)));
765
0
                }
766
0
                break;
767
0
            }
768
0
            case XML_ELEMENT(LO_EXT, XML_CUSTOM_LABEL_POS_X):
769
0
            {
770
0
                mDataPoint.mCustomLabelPos[0] = aIter.toDouble();
771
0
                break;
772
0
            }
773
0
            case XML_ELEMENT(LO_EXT, XML_CUSTOM_LABEL_POS_Y):
774
0
            {
775
0
                mDataPoint.mCustomLabelPos[1] = aIter.toDouble();
776
0
                break;
777
0
            }
778
0
            default:
779
0
                XMLOFF_WARN_UNKNOWN("xmloff", aIter);
780
0
        }
781
0
    }
782
783
0
    mrIndex += nRepeat;
784
0
}
785
786
void SchXMLDataPointContext::endFastElement(sal_Int32 )
787
0
{
788
0
    if(!mDataPoint.msStyleName.isEmpty() || mDataPoint.mCustomLabels.mLabels.size() > 0)
789
0
    {
790
0
        mrStyleVector.push_back(mDataPoint);
791
0
    }
792
0
    if (!mDataLabel.msStyleName.isEmpty() || mDataLabel.mo_nLabelAbsolutePosX.has_value()
793
0
        || mDataLabel.mo_nLabelAbsolutePosY.has_value())
794
0
    {
795
0
        mrStyleVector.push_back(mDataLabel);
796
0
    }
797
0
}
798
799
SchXMLPositionAttributesHelper::SchXMLPositionAttributesHelper( SvXMLImport& rImporter )
800
0
    : m_rImport( rImporter )
801
0
    , m_aPosition(0,0)
802
0
    , m_aSize(0,0)
803
0
    , m_bHasSizeWidth( false )
804
0
    , m_bHasSizeHeight( false )
805
0
    , m_bHasPositionX( false )
806
0
    , m_bHasPositionY( false )
807
0
    , m_bAutoSize( false )
808
0
    , m_bAutoPosition( false )
809
0
{
810
0
}
811
812
bool SchXMLPositionAttributesHelper::hasPosSize() const
813
0
{
814
0
    return (m_bHasPositionX && m_bHasPositionY) && (m_bHasSizeWidth && m_bHasSizeHeight);
815
0
}
816
817
bool SchXMLPositionAttributesHelper::isAutomatic() const
818
0
{
819
0
    return m_bAutoSize || m_bAutoPosition;
820
0
}
821
822
void SchXMLPositionAttributesHelper::readPositioningAttribute( sal_Int32 nAttributeToken, std::string_view rValue )
823
0
{
824
0
    if( !IsTokenInNamespace(nAttributeToken, XML_NAMESPACE_SVG) && !IsTokenInNamespace(nAttributeToken, XML_NAMESPACE_SVG_COMPAT) )
825
0
        return;
826
827
0
    switch (nAttributeToken & TOKEN_MASK)
828
0
    {
829
0
        case XML_X:
830
0
        {
831
0
            m_rImport.GetMM100UnitConverter().convertMeasureToCore(
832
0
                    m_aPosition.X, rValue );
833
0
            m_bHasPositionX = true;
834
0
            break;
835
0
        }
836
0
        case XML_Y:
837
0
        {
838
0
            m_rImport.GetMM100UnitConverter().convertMeasureToCore(
839
0
                    m_aPosition.Y, rValue );
840
0
            m_bHasPositionY = true;
841
0
            break;
842
0
        }
843
0
        case XML_WIDTH:
844
0
        {
845
0
            m_rImport.GetMM100UnitConverter().convertMeasureToCore(
846
0
                    m_aSize.Width, rValue );
847
0
            m_bHasSizeWidth = true;
848
0
            break;
849
0
        }
850
0
        case XML_HEIGHT:
851
0
        {
852
0
            m_rImport.GetMM100UnitConverter().convertMeasureToCore(
853
0
                    m_aSize.Height, rValue );
854
0
            m_bHasSizeHeight = true;
855
0
            break;
856
0
        }
857
0
        default:
858
0
            XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttributeToken, OUString::fromUtf8(rValue));
859
0
    }
860
0
}
861
862
void SchXMLPositionAttributesHelper::readAutomaticPositioningProperties( XMLPropStyleContext const * pPropStyleContext, const SvXMLStylesContext* pStylesCtxt )
863
0
{
864
0
    if( pPropStyleContext && pStylesCtxt )
865
0
    {
866
        //handle automatic position and size
867
0
        SchXMLTools::getPropertyFromContext(
868
0
            u"AutomaticSize", pPropStyleContext, pStylesCtxt ) >>= m_bAutoSize;
869
0
        SchXMLTools::getPropertyFromContext(
870
0
            u"AutomaticPosition", pPropStyleContext, pStylesCtxt ) >>= m_bAutoPosition;
871
0
    }
872
0
}
873
874
SchXMLCoordinateRegionContext::SchXMLCoordinateRegionContext(
875
          SvXMLImport& rImport
876
        , SchXMLPositionAttributesHelper& rPositioning )
877
0
        : SvXMLImportContext( rImport )
878
0
        , m_rPositioning( rPositioning )
879
0
{
880
0
}
881
882
SchXMLCoordinateRegionContext::~SchXMLCoordinateRegionContext()
883
0
{
884
0
}
885
886
void SchXMLCoordinateRegionContext::startFastElement (sal_Int32 /*Element*/,
887
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
888
0
{
889
    // parse attributes
890
0
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
891
0
        m_rPositioning.readPositioningAttribute( aIter.getToken(), aIter.toView() );
892
0
}
893
894
SchXMLWallFloorContext::SchXMLWallFloorContext(
895
    SchXMLImportHelper& rImpHelper,
896
    SvXMLImport& rImport,
897
    uno::Reference< chart::XDiagram > const & xDiagram,
898
    ContextType eContextType ) :
899
0
        SvXMLImportContext( rImport ),
900
0
        mrImportHelper( rImpHelper ),
901
0
        mxWallFloorSupplier( xDiagram, uno::UNO_QUERY ),
902
0
        meContextType( eContextType )
903
0
{
904
0
}
905
906
SchXMLWallFloorContext::~SchXMLWallFloorContext()
907
0
{
908
0
}
909
910
void SchXMLWallFloorContext::startFastElement (sal_Int32 /*Element*/,
911
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
912
0
{
913
0
    if( !mxWallFloorSupplier.is())
914
0
        return;
915
916
0
    OUString sAutoStyleName;
917
918
0
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
919
0
    {
920
0
        if( aIter.getToken() == XML_ELEMENT(CHART, XML_STYLE_NAME) )
921
0
            sAutoStyleName = aIter.toString();
922
0
        else
923
0
            XMLOFF_WARN_UNKNOWN("xmloff", aIter);
924
0
    }
925
926
    // set properties
927
0
    uno::Reference< beans::XPropertySet > xProp = ( meContextType == CONTEXT_TYPE_WALL )
928
0
                                                 ? mxWallFloorSupplier->getWall()
929
0
                                                 : mxWallFloorSupplier->getFloor();
930
931
0
    if (!sAutoStyleName.isEmpty())
932
0
        mrImportHelper.FillAutoStyle(sAutoStyleName, xProp);
933
0
}
934
935
SchXMLStockContext::SchXMLStockContext(
936
    SchXMLImportHelper& rImpHelper,
937
    SvXMLImport& rImport,
938
    uno::Reference< chart::XDiagram > const & xDiagram,
939
    ContextType eContextType ) :
940
0
        SvXMLImportContext( rImport ),
941
0
        mrImportHelper( rImpHelper ),
942
0
        mxStockPropProvider( xDiagram, uno::UNO_QUERY ),
943
0
        meContextType( eContextType )
944
0
{
945
0
}
946
947
SchXMLStockContext::~SchXMLStockContext()
948
0
{
949
0
}
950
951
void SchXMLStockContext::startFastElement (sal_Int32 /*Element*/,
952
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
953
0
{
954
0
    if( !mxStockPropProvider.is())
955
0
        return;
956
957
0
    OUString sAutoStyleName;
958
959
0
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
960
0
    {
961
0
        if( aIter.getToken() == XML_ELEMENT(CHART, XML_STYLE_NAME) )
962
0
            sAutoStyleName = aIter.toString();
963
0
        else
964
0
            XMLOFF_WARN_UNKNOWN("xmloff", aIter);
965
0
    }
966
967
0
    if( sAutoStyleName.isEmpty())
968
0
        return;
969
970
    // set properties
971
0
    uno::Reference< beans::XPropertySet > xProp;
972
0
    switch( meContextType )
973
0
    {
974
0
        case CONTEXT_TYPE_GAIN:
975
0
            xProp = mxStockPropProvider->getUpBar();
976
0
            break;
977
0
        case CONTEXT_TYPE_LOSS:
978
0
            xProp = mxStockPropProvider->getDownBar();
979
0
            break;
980
0
        case CONTEXT_TYPE_RANGE:
981
0
            xProp = mxStockPropProvider->getMinMaxLine();
982
0
            break;
983
0
    }
984
985
0
    mrImportHelper.FillAutoStyle(sAutoStyleName, xProp);
986
0
}
987
988
static void lcl_setErrorBarSequence ( const uno::Reference< chart2::XChartDocument > &xDoc,
989
                               const uno::Reference< beans::XPropertySet > &xBarProp,
990
                               const OUString &aXMLRange,
991
                               bool bPositiveValue, bool bYError,
992
                               tSchXMLLSequencesPerIndex& rSequences)
993
0
{
994
0
    uno::Reference< css::chart2::data::XDataProvider > xDataProvider(xDoc->getDataProvider());
995
0
    uno::Reference< css::chart2::data::XDataSource > xDataSource( xBarProp, uno::UNO_QUERY );
996
0
    uno::Reference< css::chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
997
998
0
    assert( xDataSink.is() && xDataSource.is() && xDataProvider.is() );
999
1000
0
    OUString aRange(lcl_ConvertRange(aXMLRange,xDoc));
1001
1002
0
    uno::Reference< chart2::data::XDataSequence > xNewSequence(
1003
0
        xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
1004
1005
0
    if( !xNewSequence.is())
1006
0
        return;
1007
1008
0
    SchXMLTools::setXMLRangePropertyAtDataSequence(xNewSequence,aXMLRange);
1009
1010
0
    OUStringBuffer aRoleBuffer("error-bars-");
1011
0
    if( bYError )
1012
0
        aRoleBuffer.append( 'y' );
1013
0
    else
1014
0
        aRoleBuffer.append( 'x');
1015
1016
0
    aRoleBuffer.append( '-' );
1017
1018
0
    if( bPositiveValue )
1019
0
        aRoleBuffer = aRoleBuffer.append( "positive" );
1020
0
    else
1021
0
        aRoleBuffer = aRoleBuffer.append( "negative" );
1022
1023
0
    OUString aRole = aRoleBuffer.makeStringAndClear();
1024
1025
0
    Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
1026
1027
0
    xSeqProp->setPropertyValue(u"Role"_ustr, uno::Any( aRole ));
1028
1029
0
    const Reference< uno::XComponentContext >& xContext = comphelper::getProcessComponentContext();
1030
1031
0
    Reference< chart2::data::XLabeledDataSequence > xLabelSeq( chart2::data::LabeledDataSequence::create(xContext),
1032
0
        uno::UNO_QUERY_THROW );
1033
1034
0
    rSequences.emplace( tSchXMLIndexWithPart( -2, SCH_XML_PART_ERROR_BARS ), xLabelSeq );
1035
1036
0
    xLabelSeq->setValues( xNewSequence );
1037
1038
0
    uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
1039
0
        xDataSource->getDataSequences());
1040
1041
0
    aSequences.realloc( aSequences.getLength() + 1 );
1042
0
    aSequences.getArray()[ aSequences.getLength() - 1 ] = std::move(xLabelSeq);
1043
0
    xDataSink->setData( aSequences );
1044
1045
0
}
1046
1047
SchXMLStatisticsObjectContext::SchXMLStatisticsObjectContext(
1048
    SchXMLImportHelper& rImpHelper,
1049
    SvXMLImport& rImport,
1050
    OUString sSeriesStyleName,
1051
    ::std::vector< DataRowPointStyle >& rStyleVector,
1052
    css::uno::Reference< css::chart2::XDataSeries > xSeries,
1053
    ContextType eContextType,
1054
    tSchXMLLSequencesPerIndex & rLSequencesPerIndex) :
1055
1056
0
        SvXMLImportContext( rImport ),
1057
0
        mrImportHelper( rImpHelper ),
1058
0
        mrStyleVector( rStyleVector ),
1059
0
        m_xSeries(std::move( xSeries )),
1060
0
        meContextType( eContextType ),
1061
0
        maSeriesStyleName(std::move( sSeriesStyleName)),
1062
0
        mrLSequencesPerIndex(rLSequencesPerIndex)
1063
0
{}
1064
1065
SchXMLStatisticsObjectContext::~SchXMLStatisticsObjectContext()
1066
0
{
1067
0
}
1068
1069
namespace {
1070
1071
void SetErrorBarStyleProperties( const OUString& rStyleName, const uno::Reference< beans::XPropertySet >& xBarProp,
1072
                                 SchXMLImportHelper const & rImportHelper )
1073
0
{
1074
0
    const SvXMLStylesContext* pStylesCtxt = rImportHelper.GetAutoStylesContext();
1075
0
    const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(SchXMLImportHelper::GetChartFamilyID(),
1076
0
            rStyleName);
1077
1078
0
    XMLPropStyleContext &rSeriesStyleContext =
1079
0
        const_cast< XMLPropStyleContext& >( dynamic_cast< const XMLPropStyleContext& >( *pStyle ));
1080
1081
0
    rSeriesStyleContext.FillPropertySet( xBarProp );
1082
0
}
1083
1084
void SetErrorBarPropertiesFromStyleName( const OUString& aStyleName, const uno::Reference< beans::XPropertySet>& xBarProp,
1085
                                         SchXMLImportHelper const & rImportHelper, OUString& aPosRange, OUString& aNegRange)
1086
0
{
1087
0
    const SvXMLStylesContext* pStylesCtxt = rImportHelper.GetAutoStylesContext();
1088
0
    const SvXMLStyleContext* pStyle = pStylesCtxt->FindStyleChildContext(SchXMLImportHelper::GetChartFamilyID(),
1089
0
            aStyleName);
1090
1091
0
    XMLPropStyleContext * pSeriesStyleContext =
1092
0
        const_cast< XMLPropStyleContext * >( dynamic_cast< const XMLPropStyleContext * >( pStyle ));
1093
1094
0
    uno::Any aAny = SchXMLTools::getPropertyFromContext(u"ErrorBarStyle",
1095
0
            pSeriesStyleContext,pStylesCtxt);
1096
1097
0
    if ( !aAny.hasValue() )
1098
0
        return;
1099
1100
0
    sal_Int32 aBarStyle = css::chart::ErrorBarStyle::NONE;
1101
0
    aAny >>= aBarStyle;
1102
0
    xBarProp->setPropertyValue(u"ErrorBarStyle"_ustr, aAny);
1103
1104
0
    aAny = SchXMLTools::getPropertyFromContext(u"ShowPositiveError",
1105
0
            pSeriesStyleContext,pStylesCtxt);
1106
1107
0
    if(aAny.hasValue())
1108
0
        xBarProp->setPropertyValue(u"ShowPositiveError"_ustr,aAny);
1109
1110
0
    aAny = SchXMLTools::getPropertyFromContext(u"ShowNegativeError",
1111
0
            pSeriesStyleContext,pStylesCtxt);
1112
1113
0
    if(aAny.hasValue())
1114
0
        xBarProp->setPropertyValue(u"ShowNegativeError"_ustr,aAny);
1115
1116
0
    aAny = SchXMLTools::getPropertyFromContext(u"PositiveError",
1117
0
            pSeriesStyleContext, pStylesCtxt);
1118
1119
0
    if(aAny.hasValue())
1120
0
        xBarProp->setPropertyValue(u"PositiveError"_ustr, aAny);
1121
0
    else
1122
0
    {
1123
0
        aAny = SchXMLTools::getPropertyFromContext(u"ConstantErrorHigh",
1124
0
                pSeriesStyleContext, pStylesCtxt);
1125
1126
0
        if(aAny.hasValue())
1127
0
            xBarProp->setPropertyValue(u"PositiveError"_ustr, aAny);
1128
0
    }
1129
1130
0
    aAny = SchXMLTools::getPropertyFromContext(u"NegativeError",
1131
0
            pSeriesStyleContext, pStylesCtxt);
1132
1133
0
    if(aAny.hasValue())
1134
0
        xBarProp->setPropertyValue(u"NegativeError"_ustr, aAny);
1135
0
    else
1136
0
    {
1137
0
        aAny = SchXMLTools::getPropertyFromContext(u"ConstantErrorLow",
1138
0
                pSeriesStyleContext, pStylesCtxt);
1139
1140
0
        if(aAny.hasValue())
1141
0
            xBarProp->setPropertyValue(u"NegativeError"_ustr, aAny);
1142
0
    }
1143
1144
0
    aAny = SchXMLTools::getPropertyFromContext(u"ErrorBarRangePositive",
1145
0
            pSeriesStyleContext, pStylesCtxt);
1146
0
    if( aAny.hasValue() )
1147
0
    {
1148
0
        aAny >>= aPosRange;
1149
0
    }
1150
1151
0
    aAny = SchXMLTools::getPropertyFromContext(u"ErrorBarRangeNegative",
1152
0
            pSeriesStyleContext, pStylesCtxt);
1153
0
    if( aAny.hasValue() )
1154
0
    {
1155
0
        aAny >>= aNegRange;
1156
0
    }
1157
1158
0
    aAny = SchXMLTools::getPropertyFromContext(u"Weight",
1159
0
            pSeriesStyleContext, pStylesCtxt);
1160
0
    if( aAny.hasValue() )
1161
0
    {
1162
0
        xBarProp->setPropertyValue(u"Weight"_ustr, aAny);
1163
0
    }
1164
1165
0
    aAny = SchXMLTools::getPropertyFromContext(u"PercentageError",
1166
0
            pSeriesStyleContext, pStylesCtxt);
1167
0
    if( aAny.hasValue() && aBarStyle == css::chart::ErrorBarStyle::RELATIVE )
1168
0
    {
1169
0
        xBarProp->setPropertyValue(u"PositiveError"_ustr, aAny);
1170
0
        xBarProp->setPropertyValue(u"NegativeError"_ustr, aAny);
1171
0
    }
1172
1173
0
    switch(aBarStyle)
1174
0
    {
1175
0
        case css::chart::ErrorBarStyle::ERROR_MARGIN:
1176
0
            {
1177
0
                aAny = SchXMLTools::getPropertyFromContext(u"NegativeError",
1178
0
                        pSeriesStyleContext,pStylesCtxt);
1179
1180
0
                xBarProp->setPropertyValue(u"NegativeError"_ustr,aAny);
1181
1182
0
                aAny = SchXMLTools::getPropertyFromContext(u"PositiveError",
1183
0
                        pSeriesStyleContext,pStylesCtxt);
1184
1185
0
                xBarProp->setPropertyValue(u"PositiveError"_ustr,aAny);
1186
0
            }
1187
0
            break;
1188
0
        default:
1189
0
            break;
1190
0
    }
1191
1192
0
}
1193
1194
}
1195
1196
void SchXMLStatisticsObjectContext::startFastElement (sal_Int32 /*Element*/,
1197
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
1198
0
{
1199
0
    OUString sAutoStyleName;
1200
0
    OUString aPosRange;
1201
0
    OUString aNegRange;
1202
0
    bool bYError = true;    /// Default errorbar, to be backward compatible with older files!
1203
1204
0
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1205
0
    {
1206
0
        switch (aIter.getToken())
1207
0
        {
1208
0
            case XML_ELEMENT(CHART, XML_STYLE_NAME):
1209
0
                sAutoStyleName = aIter.toString();
1210
0
                break;
1211
0
            case XML_ELEMENT(CHART, XML_DIMENSION):
1212
0
                bYError = aIter.toView() == "y";
1213
0
                break;
1214
0
            case XML_ELEMENT(CHART, XML_ERROR_UPPER_RANGE):
1215
0
                aPosRange = aIter.toString();
1216
0
                break;
1217
0
            case XML_ELEMENT(CHART, XML_ERROR_LOWER_RANGE):
1218
0
                aNegRange = aIter.toString();
1219
0
                break;
1220
0
        }
1221
0
    }
1222
1223
0
    if( sAutoStyleName.isEmpty() )
1224
0
        return;
1225
1226
0
    DataRowPointStyle aStyle( DataRowPointStyle::MEAN_VALUE, m_xSeries, -1, 1, sAutoStyleName );
1227
1228
0
    switch( meContextType )
1229
0
    {
1230
0
        case CONTEXT_TYPE_MEAN_VALUE_LINE:
1231
0
            aStyle.meType = DataRowPointStyle::MEAN_VALUE;
1232
0
            break;
1233
0
        case CONTEXT_TYPE_ERROR_INDICATOR:
1234
0
            {
1235
0
                aStyle.meType = DataRowPointStyle::ERROR_INDICATOR;
1236
1237
0
                uno::Reference< lang::XMultiServiceFactory > xFact = comphelper::getProcessServiceFactory();
1238
1239
0
                uno::Reference< beans::XPropertySet > xBarProp( xFact->createInstance(u"com.sun.star.chart2.ErrorBar"_ustr ),
1240
0
                                                                uno::UNO_QUERY );
1241
1242
0
                xBarProp->setPropertyValue(u"ErrorBarStyle"_ustr,uno::Any(css::chart::ErrorBarStyle::NONE));
1243
0
                xBarProp->setPropertyValue(u"PositiveError"_ustr,uno::Any(0.0));
1244
0
                xBarProp->setPropertyValue(u"NegativeError"_ustr,uno::Any(0.0));
1245
0
                xBarProp->setPropertyValue(u"Weight"_ustr,uno::Any(1.0));
1246
0
                xBarProp->setPropertyValue(u"ShowPositiveError"_ustr,uno::Any(true));
1247
0
                xBarProp->setPropertyValue(u"ShowNegativeError"_ustr,uno::Any(true));
1248
1249
                // first import defaults from parent style
1250
0
                SetErrorBarStyleProperties( maSeriesStyleName, xBarProp, mrImportHelper );
1251
0
                SetErrorBarStyleProperties( sAutoStyleName, xBarProp, mrImportHelper );
1252
0
                SetErrorBarPropertiesFromStyleName( maSeriesStyleName, xBarProp, mrImportHelper, aPosRange, aNegRange );
1253
0
                SetErrorBarPropertiesFromStyleName( sAutoStyleName, xBarProp, mrImportHelper, aPosRange, aNegRange );
1254
1255
0
                uno::Reference< chart2::XChartDocument > xDoc(GetImport().GetModel(),uno::UNO_QUERY);
1256
1257
0
                if (!aPosRange.isEmpty())
1258
0
                    lcl_setErrorBarSequence(xDoc,xBarProp,aPosRange,true,bYError, mrLSequencesPerIndex);
1259
1260
0
                if (!aNegRange.isEmpty())
1261
0
                    lcl_setErrorBarSequence(xDoc,xBarProp,aNegRange,false,bYError, mrLSequencesPerIndex);
1262
1263
0
                if ( !bYError )
1264
0
                {
1265
0
                    aStyle.m_xErrorXProperties.set( xBarProp );
1266
0
                }
1267
0
                else
1268
0
                {
1269
0
                    aStyle.m_xErrorYProperties.set( xBarProp );
1270
0
                }
1271
0
            }
1272
0
            break;
1273
0
    }
1274
1275
0
    mrStyleVector.push_back(std::move(aStyle));
1276
0
}
1277
1278
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */