Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/drawingml/chart/seriescontext.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 <drawingml/chart/seriescontext.hxx>
21
22
#include <drawingml/shapepropertiescontext.hxx>
23
#include <drawingml/textbodycontext.hxx>
24
#include <drawingml/chart/datasourcecontext.hxx>
25
#include <drawingml/chart/geographycontext.hxx>
26
#include <drawingml/chart/seriesmodel.hxx>
27
#include <drawingml/chart/titlecontext.hxx>
28
#include <oox/core/xmlfilterbase.hxx>
29
#include <oox/helper/attributelist.hxx>
30
#include <oox/token/namespaces.hxx>
31
#include <oox/token/tokens.hxx>
32
33
namespace oox::drawingml::chart {
34
35
using ::oox::core::ContextHandler2;
36
using ::oox::core::ContextHandler2Helper;
37
using ::oox::core::ContextHandlerRef;
38
39
namespace {
40
41
ContextHandlerRef lclDataLabelSharedCreateContext( ContextHandler2& rContext,
42
        sal_Int32 nElement, const AttributeList& rAttribs, DataLabelModelBase& orModel, bool bMSO2007 )
43
0
{
44
0
    if( rContext.isRootElement() ) switch( nElement )
45
0
    {
46
0
        case C_TOKEN( delete ):
47
0
            orModel.mbDeleted = rAttribs.getBool( XML_val, !bMSO2007 );
48
0
            return nullptr;
49
0
        case C_TOKEN( dLblPos ):
50
0
            orModel.monLabelPos = rAttribs.getToken( XML_val, XML_TOKEN_INVALID );
51
0
            return nullptr;
52
0
        case C_TOKEN( numFmt ):
53
0
        case CX_TOKEN( numFmt ):
54
0
            orModel.maNumberFormat.setAttributes( rAttribs );
55
0
            return nullptr;
56
0
        case C_TOKEN( showBubbleSize ):
57
0
            orModel.mobShowBubbleSize = rAttribs.getBool( XML_val );
58
0
            return nullptr;
59
0
        case C_TOKEN( showCatName ):
60
0
            orModel.mobShowCatName = rAttribs.getBool( XML_val );
61
0
            return nullptr;
62
0
        case C_TOKEN( showLegendKey ):
63
0
            orModel.mobShowLegendKey = rAttribs.getBool( XML_val );
64
0
            return nullptr;
65
0
        case C_TOKEN( showPercent ):
66
0
            orModel.mobShowPercent = rAttribs.getBool( XML_val );
67
0
            return nullptr;
68
0
        case C_TOKEN( showSerName ):
69
0
            orModel.mobShowSerName = rAttribs.getBool( XML_val );
70
0
            return nullptr;
71
0
        case C_TOKEN( showVal ):
72
0
            orModel.mobShowVal = rAttribs.getBool( XML_val );
73
0
            return nullptr;
74
0
        case C_TOKEN( separator ):
75
0
        case CX_TOKEN( separator ):
76
            // collect separator text in onCharacters()
77
0
            return &rContext;
78
0
        case C_TOKEN( spPr ):
79
0
        case CX_TOKEN( spPr ):
80
0
            return new ShapePropertiesContext( rContext, orModel.mxShapeProp.create() );
81
0
        case C_TOKEN( txPr ):
82
0
        case CX_TOKEN( txPr ):
83
0
            return new TextBodyContext( rContext, orModel.mxTextProp.create() );
84
0
        case CX_TOKEN( visibility ):
85
            // chartex has no legend key or percentage labels
86
0
            orModel.mobShowSerName = rAttribs.getBool( XML_seriesName, false );
87
0
            orModel.mobShowCatName = rAttribs.getBool( XML_categoryName, false );
88
0
            orModel.mobShowVal = rAttribs.getBool( XML_value, true );
89
0
            orModel.mobShowLegendKey = false;
90
0
            orModel.mobShowPercent = false;
91
0
            return nullptr;
92
0
    }
93
0
    return nullptr;
94
0
}
95
96
void lclDataLabelSharedCharacters( ContextHandler2 const & rContext, const OUString& rChars, DataLabelModelBase& orModel )
97
0
{
98
0
    if( rContext.isCurrentElement( C_TOKEN( separator ) ) ||
99
0
            rContext.isCurrentElement( CX_TOKEN( separator ) ) )
100
0
        orModel.moaSeparator = rChars;
101
0
}
102
103
} // namespace
104
105
DataLabelContext::DataLabelContext( ContextHandler2Helper& rParent, DataLabelModel& rModel ) :
106
0
    ContextBase< DataLabelModel >( rParent, rModel )
107
0
{
108
0
    mrModel.mbDeleted = false;
109
0
}
110
111
DataLabelContext::~DataLabelContext()
112
0
{
113
0
}
114
115
ContextHandlerRef DataLabelContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
116
0
{
117
0
    if( isRootElement() )
118
0
    {
119
0
        switch( nElement )
120
0
        {
121
0
            case C_TOKEN( idx ):
122
0
                mrModel.mnIndex = rAttribs.getInteger( XML_val, -1 );
123
0
                return nullptr;
124
0
            case C_TOKEN( layout ):
125
0
                return new LayoutContext( *this, mrModel.mxLayout.create() );
126
0
            case C_TOKEN( tx ):
127
0
                return new TextContext( *this, mrModel.mxText.create() );
128
0
            case C_TOKEN( extLst ):
129
0
                return this;
130
0
        }
131
0
    }
132
0
    else
133
0
    {
134
0
        switch( getCurrentElement() )
135
0
        {
136
0
            case C_TOKEN( extLst ):
137
0
                if ( nElement == C_TOKEN( ext ) )
138
0
                    return this;
139
0
            break;
140
0
            case C_TOKEN( ext ):
141
0
                if ( nElement == C15_TOKEN( showDataLabelsRange ) )
142
0
                {
143
0
                    mrModel.mobShowDataLabelsRange = rAttribs.getBool( XML_val );
144
0
                    return nullptr;
145
0
                }
146
0
                else if (nElement == C15_TOKEN(layout))
147
0
                    return new LayoutContext(*this, mrModel.mxLayout.getOrCreate());
148
0
            break;
149
            // Not sure how to handle <cx:extLst> and <cx:ext>. TODO
150
0
        }
151
0
    }
152
0
    bool bMSO2007 = getFilter().isMSO2007Document();
153
0
    return lclDataLabelSharedCreateContext( *this, nElement, rAttribs, mrModel, bMSO2007 );
154
0
}
155
156
void DataLabelContext::onCharacters( const OUString& rChars )
157
0
{
158
0
    lclDataLabelSharedCharacters( *this, rChars, mrModel );
159
0
}
160
161
DataLabelsContext::DataLabelsContext( ContextHandler2Helper& rParent, DataLabelsModel& rModel ) :
162
0
    ContextBase< DataLabelsModel >( rParent, rModel )
163
0
{
164
0
    mrModel.mbDeleted = false;
165
0
}
166
167
DataLabelsContext::~DataLabelsContext()
168
0
{
169
0
}
170
171
ContextHandlerRef DataLabelsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
172
0
{
173
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
174
0
    if( isRootElement() ) switch( nElement )
175
0
    {
176
0
        case C_TOKEN( dLbl ):
177
0
            return new DataLabelContext( *this, mrModel.maPointLabels.create(mrModel, bMSO2007Doc) );
178
0
        case CX_TOKEN( dataLabel ):
179
0
        {
180
0
            DataLabelModel& rLabel = mrModel.maPointLabels.create( mrModel, bMSO2007Doc );
181
0
            rLabel.mnIndex = rAttribs.getInteger( XML_idx, -1 );
182
0
            rLabel.monLabelPos = rAttribs.getToken( XML_pos );
183
            // set MSO defaults
184
0
            rLabel.mobShowSerName = false;
185
0
            rLabel.mobShowCatName = false;
186
0
            rLabel.mobShowVal = true;
187
0
            return new DataLabelContext( *this, rLabel );
188
0
        }
189
0
        case CX_TOKEN( dataLabelHidden ):
190
0
        {
191
0
            DataLabelModel& rLabel = mrModel.maPointLabels.create( mrModel, bMSO2007Doc );
192
0
            rLabel.mnIndex = rAttribs.getInteger( XML_idx, -1 );
193
0
            rLabel.mbDeleted = true;
194
0
            return nullptr;
195
0
        }
196
0
        case C_TOKEN( leaderLines ):
197
0
            return new ShapePrWrapperContext( *this, mrModel.mxLeaderLines.create() );
198
0
        case C_TOKEN( showLeaderLines ):
199
0
        case C15_TOKEN( showLeaderLines ):
200
0
            mrModel.mbShowLeaderLines = rAttribs.getBool( XML_val, true );
201
0
            return nullptr;
202
0
        case C_TOKEN( extLst ):
203
0
        case C_TOKEN( ext ):
204
0
            return new DataLabelsContext( *this, mrModel );
205
0
    }
206
0
    return lclDataLabelSharedCreateContext( *this, nElement, rAttribs, mrModel, bMSO2007Doc );
207
0
}
208
209
void DataLabelsContext::onCharacters( const OUString& rChars )
210
0
{
211
0
    lclDataLabelSharedCharacters( *this, rChars, mrModel );
212
0
}
213
214
PictureOptionsContext::PictureOptionsContext( ContextHandler2Helper& rParent, PictureOptionsModel& rModel ) :
215
0
    ContextBase< PictureOptionsModel >( rParent, rModel )
216
0
{
217
0
}
218
219
PictureOptionsContext::~PictureOptionsContext()
220
0
{
221
0
}
222
223
ContextHandlerRef PictureOptionsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
224
0
{
225
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
226
0
    if( isRootElement() ) switch( nElement )
227
0
    {
228
0
        case C_TOKEN( applyToEnd ):
229
0
            mrModel.mbApplyToEnd = rAttribs.getBool( XML_val, !bMSO2007Doc );
230
0
            return nullptr;
231
0
        case C_TOKEN( applyToFront ):
232
0
            mrModel.mbApplyToFront = rAttribs.getBool( XML_val, !bMSO2007Doc );
233
0
            return nullptr;
234
0
        case C_TOKEN( applyToSides ):
235
0
            mrModel.mbApplyToSides = rAttribs.getBool( XML_val, !bMSO2007Doc );
236
0
            return nullptr;
237
0
        case C_TOKEN( pictureFormat ):
238
0
            mrModel.mnPictureFormat = rAttribs.getToken( XML_val, XML_stretch );
239
0
            return nullptr;
240
0
        case C_TOKEN( pictureStackUnit ):
241
0
            mrModel.mfStackUnit = rAttribs.getDouble( XML_val, 1.0 );
242
0
            return nullptr;
243
0
    }
244
0
    return nullptr;
245
0
}
246
247
ErrorBarContext::ErrorBarContext( ContextHandler2Helper& rParent, ErrorBarModel& rModel ) :
248
0
    ContextBase< ErrorBarModel >( rParent, rModel )
249
0
{
250
0
}
251
252
ErrorBarContext::~ErrorBarContext()
253
0
{
254
0
}
255
256
ContextHandlerRef ErrorBarContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
257
0
{
258
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
259
0
    if( isRootElement() ) switch( nElement )
260
0
    {
261
0
        case C_TOKEN( errBarType ):
262
0
            mrModel.mnTypeId = rAttribs.getToken( XML_val, XML_both );
263
0
            return nullptr;
264
0
        case C_TOKEN( errDir ):
265
0
            mrModel.mnDirection = rAttribs.getToken( XML_val, XML_TOKEN_INVALID );
266
0
            return nullptr;
267
0
        case C_TOKEN( errValType ):
268
0
            mrModel.mnValueType = rAttribs.getToken( XML_val, XML_fixedVal );
269
0
            return nullptr;
270
0
        case C_TOKEN( minus ):
271
0
            return new DataSourceContext( *this, mrModel.maSources.create( ErrorBarModel::MINUS ) );
272
0
        case C_TOKEN( noEndCap ):
273
0
            mrModel.mbNoEndCap = rAttribs.getBool( XML_val, !bMSO2007Doc );
274
0
            return nullptr;
275
0
        case C_TOKEN( plus ):
276
0
            return new DataSourceContext( *this, mrModel.maSources.create( ErrorBarModel::PLUS ) );
277
0
        case C_TOKEN( spPr ):
278
0
            return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() );
279
0
        case C_TOKEN( val ):
280
0
            mrModel.mfValue = rAttribs.getDouble( XML_val, 0.0 );
281
0
            return nullptr;
282
0
    }
283
0
    return nullptr;
284
0
}
285
286
TrendlineLabelContext::TrendlineLabelContext( ContextHandler2Helper& rParent, TrendlineLabelModel& rModel ) :
287
0
    ContextBase< TrendlineLabelModel >( rParent, rModel )
288
0
{
289
0
}
290
291
TrendlineLabelContext::~TrendlineLabelContext()
292
0
{
293
0
}
294
295
ContextHandlerRef TrendlineLabelContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
296
0
{
297
0
    if( isRootElement() ) switch( nElement )
298
0
    {
299
0
        case C_TOKEN( layout ):
300
0
            return new LayoutContext( *this, mrModel.mxLayout.create() );
301
0
        case C_TOKEN( numFmt ):
302
0
            mrModel.maNumberFormat.setAttributes( rAttribs );
303
0
            return nullptr;
304
0
        case C_TOKEN( spPr ):
305
0
            return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() );
306
0
        case C_TOKEN( tx ):
307
0
            return new TextContext( *this, mrModel.mxText.create() );
308
0
        case C_TOKEN( txPr ):
309
0
            return new TextBodyContext( *this, mrModel.mxTextProp.create() );
310
0
    }
311
0
    return nullptr;
312
0
}
313
314
TrendlineContext::TrendlineContext( ContextHandler2Helper& rParent, TrendlineModel& rModel ) :
315
0
    ContextBase< TrendlineModel >( rParent, rModel )
316
0
{
317
0
}
318
319
TrendlineContext::~TrendlineContext()
320
0
{
321
0
}
322
323
ContextHandlerRef TrendlineContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
324
0
{
325
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
326
0
    if( isRootElement() ) switch( nElement )
327
0
    {
328
0
        case C_TOKEN( backward ):
329
0
            mrModel.mfBackward = rAttribs.getDouble( XML_val, 0.0 );
330
0
            return nullptr;
331
0
        case C_TOKEN( dispEq ):
332
0
            mrModel.mbDispEquation = rAttribs.getBool( XML_val, !bMSO2007Doc );
333
0
            return nullptr;
334
0
        case C_TOKEN( dispRSqr ):
335
0
            mrModel.mbDispRSquared = rAttribs.getBool( XML_val, !bMSO2007Doc );
336
0
            return nullptr;
337
0
        case C_TOKEN( forward ):
338
0
            mrModel.mfForward = rAttribs.getDouble( XML_val, 0.0 );
339
0
            return nullptr;
340
0
        case C_TOKEN( intercept ):
341
0
            mrModel.mfIntercept = rAttribs.getDouble( XML_val, 0.0 );
342
0
            return nullptr;
343
0
        case C_TOKEN( name ):
344
0
            return this;    // collect name in onCharacters()
345
0
        case C_TOKEN( order ):
346
0
            mrModel.mnOrder = rAttribs.getInteger( XML_val, 2 );
347
0
            return nullptr;
348
0
        case C_TOKEN( period ):
349
0
            mrModel.mnPeriod = rAttribs.getInteger( XML_val, 2 );
350
0
            return nullptr;
351
0
        case C_TOKEN( spPr ):
352
0
            return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() );
353
0
        case C_TOKEN( trendlineLbl ):
354
0
            return new TrendlineLabelContext( *this, mrModel.mxLabel.create() );
355
0
        case C_TOKEN( trendlineType ):
356
0
            mrModel.mnTypeId = rAttribs.getToken( XML_val, XML_linear );
357
0
            return nullptr;
358
0
    }
359
0
    return nullptr;
360
0
}
361
362
void TrendlineContext::onCharacters( const OUString& rChars )
363
0
{
364
0
    if( isCurrentElement( C_TOKEN( name ) ) )
365
0
        mrModel.maName = rChars;
366
0
}
367
368
DataPointContext::DataPointContext( ContextHandler2Helper& rParent, DataPointModel& rModel ) :
369
0
    ContextBase< DataPointModel >( rParent, rModel )
370
0
{
371
0
}
372
373
DataPointContext::~DataPointContext()
374
0
{
375
0
}
376
377
ContextHandlerRef DataPointContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
378
0
{
379
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
380
0
    switch( getCurrentElement() )
381
0
    {
382
0
        case C_TOKEN( dPt ):
383
0
            switch( nElement )
384
0
            {
385
0
                case C_TOKEN( bubble3D ):
386
0
                    mrModel.mobBubble3d = rAttribs.getBool( XML_val );
387
0
                    return nullptr;
388
0
                case C_TOKEN( explosion ):
389
                    // if the 'val' attribute is missing, series explosion remains unchanged
390
0
                    mrModel.monExplosion = rAttribs.getInteger( XML_val );
391
0
                    return nullptr;
392
0
                case C_TOKEN( idx ):
393
0
                    mrModel.mnIndex = rAttribs.getInteger( XML_val, -1 );
394
0
                    return nullptr;
395
0
                case C_TOKEN( invertIfNegative ):
396
0
                    mrModel.mbInvertNeg = rAttribs.getBool( XML_val, !bMSO2007Doc );
397
0
                    return nullptr;
398
0
                case C_TOKEN( marker ):
399
0
                    return this;
400
0
                case C_TOKEN( pictureOptions ):
401
0
                    return new PictureOptionsContext( *this, mrModel.mxPicOptions.create(bMSO2007Doc) );
402
0
                case C_TOKEN( spPr ):
403
0
                    return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() );
404
0
            }
405
0
        break;
406
407
0
        case C_TOKEN( marker ):
408
0
            switch( nElement )
409
0
            {
410
0
                case C_TOKEN( size ):
411
0
                    mrModel.monMarkerSize = rAttribs.getInteger( XML_val, 5 );
412
0
                    return nullptr;
413
0
                case C_TOKEN( spPr ):
414
0
                    return new ShapePropertiesContext( *this, mrModel.mxMarkerProp.create() );
415
0
                case C_TOKEN( symbol ):
416
0
                    mrModel.monMarkerSymbol = rAttribs.getToken( XML_val, XML_none );
417
0
                    return nullptr;
418
0
            }
419
0
        break;
420
0
    }
421
0
    return nullptr;
422
0
}
423
424
SeriesContextBase::SeriesContextBase( ContextHandler2Helper& rParent, SeriesModel& rModel ) :
425
0
    ContextBase< SeriesModel >( rParent, rModel )
426
0
{
427
0
}
428
429
SeriesContextBase::~SeriesContextBase()
430
0
{
431
0
}
432
433
ContextHandlerRef SeriesContextBase::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
434
0
{
435
0
    switch( getCurrentElement() )
436
0
    {
437
0
        case C_TOKEN( ser ):
438
0
        case CX_TOKEN( series ):
439
0
            switch( nElement )
440
0
            {
441
0
                case C_TOKEN( idx ):
442
0
                    mrModel.mnIndex = rAttribs.getInteger( XML_val, -1 );
443
0
                    return nullptr;
444
0
                case C_TOKEN( order ):
445
0
                    mrModel.mnOrder = rAttribs.getInteger( XML_val, -1 );
446
0
                    return nullptr;
447
0
                case C_TOKEN( spPr ):
448
0
                case CX_TOKEN( spPr ):
449
0
                    return new ShapePropertiesContext( *this,
450
0
                            mrModel.mxShapeProp.create(), true );
451
0
                case C_TOKEN( tx ):
452
0
                case CX_TOKEN( tx ):
453
0
                    return new TextContext( *this, mrModel.mxText.create() );
454
0
                case C_TOKEN( extLst ):
455
0
                case CX_TOKEN( extLst ):
456
0
                    return this;
457
0
            }
458
0
        break;
459
460
0
        case C_TOKEN( marker ):
461
0
            switch( nElement )
462
0
            {
463
0
                case C_TOKEN( size ):
464
0
                    mrModel.mnMarkerSize = rAttribs.getInteger( XML_val, 5 );
465
0
                    return nullptr;
466
0
                case C_TOKEN( spPr ):
467
0
                    return new ShapePropertiesContext( *this, mrModel.mxMarkerProp.create() );
468
0
                case C_TOKEN( symbol ):
469
0
                    mrModel.mnMarkerSymbol = rAttribs.getToken( XML_val, XML_none );
470
0
                    return nullptr;
471
0
            }
472
0
        break;
473
474
0
        case C_TOKEN( extLst ):
475
0
        case CX_TOKEN( extLst ):
476
0
            switch( nElement )
477
0
            {
478
0
                case C_TOKEN( ext ):
479
0
                case CX_TOKEN( ext ):
480
0
                    if (mrModel.maSources.has( DataSourceType::DATALABELS ))
481
0
                        break;
482
483
0
                    DataSourceModel& rLabelsSource = mrModel.maSources.create( DataSourceType::DATALABELS );
484
0
                    if (mrModel.mxLabels.is())
485
0
                        mrModel.mxLabels->mpLabelsSource = &rLabelsSource;
486
0
                    return new DataSourceContext( *this, rLabelsSource );
487
0
            }
488
0
            break;
489
0
    }
490
0
    return nullptr;
491
0
}
492
493
AreaSeriesContext::AreaSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) :
494
0
    SeriesContextBase( rParent, rModel )
495
0
{
496
0
}
497
498
AreaSeriesContext::~AreaSeriesContext()
499
{
500
}
501
502
ContextHandlerRef AreaSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
503
0
{
504
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
505
0
    switch( getCurrentElement() )
506
0
    {
507
0
        case C_TOKEN( ser ):
508
0
            switch( nElement )
509
0
            {
510
0
                case C_TOKEN( cat ):
511
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) );
512
0
                case C_TOKEN( errBars ):
513
0
                    return new ErrorBarContext( *this, mrModel.maErrorBars.create(bMSO2007Doc) );
514
0
                case C_TOKEN( dLbls ):
515
0
                    return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) );
516
0
                case C_TOKEN( dPt ):
517
0
                    return new DataPointContext( *this, mrModel.maPoints.create(bMSO2007Doc) );
518
0
                case C_TOKEN( trendline ):
519
0
                    return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) );
520
0
                case C_TOKEN( val ):
521
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) );
522
0
            }
523
0
        break;
524
0
    }
525
0
    return SeriesContextBase::onCreateContext( nElement, rAttribs );
526
0
}
527
528
BarSeriesContext::BarSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) :
529
0
    SeriesContextBase( rParent, rModel )
530
0
{
531
0
}
532
533
BarSeriesContext::~BarSeriesContext()
534
{
535
}
536
537
ContextHandlerRef BarSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
538
0
{
539
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
540
0
    switch( getCurrentElement() )
541
0
    {
542
0
        case C_TOKEN( ser ):
543
0
            switch( nElement )
544
0
            {
545
0
                case C_TOKEN( cat ):
546
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) );
547
0
                case C_TOKEN( dLbls ):
548
0
                    return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) );
549
0
                case C_TOKEN( dPt ):
550
0
                    return new DataPointContext( *this, mrModel.maPoints.create(bMSO2007Doc) );
551
0
                case C_TOKEN( errBars ):
552
0
                    return new ErrorBarContext( *this, mrModel.maErrorBars.create(bMSO2007Doc) );
553
0
                case C_TOKEN( invertIfNegative ):
554
0
                    mrModel.mbInvertNeg = rAttribs.getBool( XML_val, !bMSO2007Doc );
555
0
                    return nullptr;
556
0
                case C_TOKEN( pictureOptions ):
557
0
                    return new PictureOptionsContext( *this, mrModel.mxPicOptions.create(bMSO2007Doc) );
558
0
                case C_TOKEN( shape ):
559
0
                    mrModel.monShape = rAttribs.getToken(XML_val);
560
0
                    return nullptr;
561
0
                case C_TOKEN( trendline ):
562
0
                    return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) );
563
0
                case C_TOKEN( val ):
564
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) );
565
0
            }
566
0
        break;
567
0
    }
568
0
    return SeriesContextBase::onCreateContext( nElement, rAttribs );
569
0
}
570
571
BubbleSeriesContext::BubbleSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) :
572
0
    SeriesContextBase( rParent, rModel )
573
0
{
574
0
}
575
576
BubbleSeriesContext::~BubbleSeriesContext()
577
{
578
}
579
580
ContextHandlerRef BubbleSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
581
0
{
582
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
583
0
    switch( getCurrentElement() )
584
0
    {
585
0
        case C_TOKEN( ser ):
586
0
            switch( nElement )
587
0
            {
588
0
                case C_TOKEN( bubble3D ):
589
0
                    mrModel.mbBubble3d = rAttribs.getBool( XML_val, !bMSO2007Doc );
590
0
                    return nullptr;
591
0
                case C_TOKEN( bubbleSize ):
592
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::POINTS ) );
593
0
                case C_TOKEN( dLbls ):
594
0
                    return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) );
595
0
                case C_TOKEN( dPt ):
596
0
                    return new DataPointContext( *this, mrModel.maPoints.create(bMSO2007Doc) );
597
0
                case C_TOKEN( errBars ):
598
0
                    return new ErrorBarContext( *this, mrModel.maErrorBars.create(bMSO2007Doc) );
599
0
                case C_TOKEN( invertIfNegative ):
600
0
                    mrModel.mbInvertNeg = rAttribs.getBool( XML_val, !bMSO2007Doc );
601
0
                    return nullptr;
602
0
                case C_TOKEN( trendline ):
603
0
                    return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) );
604
0
                case C_TOKEN( xVal ):
605
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) );
606
0
                case C_TOKEN( yVal ):
607
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) );
608
0
            }
609
0
        break;
610
0
    }
611
0
    return SeriesContextBase::onCreateContext( nElement, rAttribs );
612
0
}
613
614
LineSeriesContext::LineSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) :
615
0
    SeriesContextBase( rParent, rModel )
616
0
{
617
0
}
618
619
LineSeriesContext::~LineSeriesContext()
620
{
621
}
622
623
ContextHandlerRef LineSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
624
0
{
625
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
626
0
    switch( getCurrentElement() )
627
0
    {
628
0
        case C_TOKEN( ser ):
629
0
            switch( nElement )
630
0
            {
631
0
                case C_TOKEN( cat ):
632
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) );
633
0
                case C_TOKEN( dLbls ):
634
0
                    return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) );
635
0
                case C_TOKEN( dPt ):
636
0
                    return new DataPointContext( *this, mrModel.maPoints.create(bMSO2007Doc) );
637
0
                case C_TOKEN( errBars ):
638
0
                    return new ErrorBarContext( *this, mrModel.maErrorBars.create(bMSO2007Doc) );
639
0
                case C_TOKEN( marker ):
640
0
                    return this;
641
0
                case C_TOKEN( smooth ):
642
0
                    mrModel.mbSmooth = rAttribs.getBool( XML_val, !bMSO2007Doc );
643
0
                    return nullptr;
644
0
                case C_TOKEN( trendline ):
645
0
                    return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) );
646
0
                case C_TOKEN( val ):
647
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) );
648
0
            }
649
0
        break;
650
0
    }
651
0
    return SeriesContextBase::onCreateContext( nElement, rAttribs );
652
0
}
653
654
PieSeriesContext::PieSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) :
655
0
    SeriesContextBase( rParent, rModel )
656
0
{
657
0
}
658
659
PieSeriesContext::~PieSeriesContext()
660
{
661
}
662
663
ContextHandlerRef PieSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
664
0
{
665
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
666
0
    switch( getCurrentElement() )
667
0
    {
668
0
        case C_TOKEN( ser ):
669
0
            switch( nElement )
670
0
            {
671
0
                case C_TOKEN( cat ):
672
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) );
673
0
                case C_TOKEN( dLbls ):
674
0
                    return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) );
675
0
                case C_TOKEN( dPt ):
676
0
                    return new DataPointContext( *this, mrModel.maPoints.create(bMSO2007Doc) );
677
0
                case C_TOKEN( explosion ):
678
0
                    mrModel.mnExplosion = rAttribs.getInteger( XML_val, 0 );
679
0
                    return nullptr;
680
0
                case C_TOKEN( val ):
681
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) );
682
0
            }
683
0
        break;
684
0
    }
685
0
    return SeriesContextBase::onCreateContext( nElement, rAttribs );
686
0
}
687
688
RadarSeriesContext::RadarSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) :
689
0
    SeriesContextBase( rParent, rModel )
690
0
{
691
0
}
692
693
RadarSeriesContext::~RadarSeriesContext()
694
{
695
}
696
697
ContextHandlerRef RadarSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
698
0
{
699
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
700
0
    switch( getCurrentElement() )
701
0
    {
702
0
        case C_TOKEN( ser ):
703
0
            switch( nElement )
704
0
            {
705
0
                case C_TOKEN( cat ):
706
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) );
707
0
                case C_TOKEN( dLbls ):
708
0
                    return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) );
709
0
                case C_TOKEN( dPt ):
710
0
                    return new DataPointContext( *this, mrModel.maPoints.create(bMSO2007Doc) );
711
0
                case C_TOKEN( marker ):
712
0
                    return this;
713
0
                case C_TOKEN( smooth ):
714
0
                    mrModel.mbSmooth = rAttribs.getBool( XML_val, bMSO2007Doc );
715
0
                    return nullptr;
716
0
                case C_TOKEN( val ):
717
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) );
718
0
            }
719
0
        break;
720
0
    }
721
0
    return SeriesContextBase::onCreateContext( nElement, rAttribs );
722
0
}
723
724
ScatterSeriesContext::ScatterSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) :
725
0
    SeriesContextBase( rParent, rModel )
726
0
{
727
0
}
728
729
ScatterSeriesContext::~ScatterSeriesContext()
730
{
731
}
732
733
ContextHandlerRef ScatterSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
734
0
{
735
0
    bool bMSO2007Doc = getFilter().isMSO2007Document();
736
0
    switch( getCurrentElement() )
737
0
    {
738
0
        case C_TOKEN( ser ):
739
0
            switch( nElement )
740
0
            {
741
0
                case C_TOKEN( dLbls ):
742
0
                    return new DataLabelsContext( *this, mrModel.mxLabels.create(bMSO2007Doc) );
743
0
                case C_TOKEN( dPt ):
744
0
                    return new DataPointContext( *this, mrModel.maPoints.create(bMSO2007Doc) );
745
0
                case C_TOKEN( errBars ):
746
0
                    return new ErrorBarContext( *this, mrModel.maErrorBars.create(bMSO2007Doc) );
747
0
                case C_TOKEN( marker ):
748
0
                    return this;
749
0
                case C_TOKEN( smooth ):
750
0
                    mrModel.mbSmooth = rAttribs.getBool( XML_val, !bMSO2007Doc );
751
0
                    return nullptr;
752
0
                case C_TOKEN( trendline ):
753
0
                    return new TrendlineContext( *this, mrModel.maTrendlines.create(bMSO2007Doc) );
754
0
                case C_TOKEN( xVal ):
755
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) );
756
0
                case C_TOKEN( yVal ):
757
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) );
758
0
            }
759
0
        break;
760
0
    }
761
0
    return SeriesContextBase::onCreateContext( nElement, rAttribs );
762
0
}
763
764
SurfaceSeriesContext::SurfaceSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) :
765
0
    SeriesContextBase( rParent, rModel )
766
0
{
767
0
}
768
769
SurfaceSeriesContext::~SurfaceSeriesContext()
770
{
771
}
772
773
ContextHandlerRef SurfaceSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
774
0
{
775
0
    switch( getCurrentElement() )
776
0
    {
777
0
        case C_TOKEN( ser ):
778
0
            switch( nElement )
779
0
            {
780
0
                case C_TOKEN( cat ):
781
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::STR_CAT ) );
782
0
                case C_TOKEN( val ):
783
0
                    return new DataSourceContext( *this, mrModel.maSources.create( DataSourceType::NUM_VAL ) );
784
0
            }
785
0
        break;
786
0
    }
787
0
    return SeriesContextBase::onCreateContext( nElement, rAttribs );
788
0
}
789
790
//======
791
// BinningContext
792
//======
793
BinningContext::BinningContext( ContextHandler2Helper& rParent, BinningModel& rModel ) :
794
0
    ContextBase( rParent, rModel )
795
0
{
796
0
}
797
798
BinningContext::~BinningContext()
799
0
{
800
0
}
801
802
void BinningContext::onCharacters( const OUString& rChars )
803
0
{
804
0
    switch (getCurrentElement())
805
0
    {
806
0
        case CX_TOKEN( binSize ) :
807
0
            mrModel.maBinSizeOrCount = rChars.toDouble();
808
0
            break;
809
0
        case CX_TOKEN(binCount) :
810
0
            mrModel.maBinSizeOrCount = rChars.toUInt32();
811
0
            break;
812
0
        default:
813
0
            assert(false);
814
0
    }
815
0
}
816
817
ContextHandlerRef BinningContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
818
0
{
819
0
    switch( getCurrentElement() )
820
0
    {
821
0
        case CX_TOKEN(binning):
822
0
            switch( nElement )
823
0
            {
824
0
                case CX_TOKEN( binSize ):
825
0
                    mrModel.maBinSizeOrCount = rAttribs.getDouble( XML_val, 0.0 );
826
0
                    return nullptr;
827
0
                case CX_TOKEN( binCount ):
828
0
                    mrModel.maBinSizeOrCount = std::variant<double, sal_uInt32>(
829
0
                            static_cast<sal_uInt32>(rAttribs.getInteger( XML_val, 0 )));
830
831
                    // TODO
832
0
                    return nullptr;
833
0
            }
834
0
            break;
835
0
    }
836
0
    return ContextBase::onCreateContext( nElement, rAttribs );
837
0
}
838
839
//======
840
// LayoutPropsContext
841
//======
842
LayoutPropsContext::LayoutPropsContext( ContextHandler2Helper& rParent, LayoutPropsModel& rModel ) :
843
0
    ContextBase( rParent, rModel )
844
0
{
845
0
}
846
847
LayoutPropsContext::~LayoutPropsContext()
848
0
{
849
0
}
850
851
ContextHandlerRef LayoutPropsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
852
0
{
853
0
    switch( getCurrentElement() )
854
0
    {
855
0
        case CX_TOKEN( layoutPr ):
856
0
            switch( nElement )
857
0
            {
858
0
                case CX_TOKEN( parentLabelLayout ):
859
0
                    mrModel.mosParentLabelLayout = rAttribs.getString( XML_val );
860
0
                    return nullptr;
861
0
                case CX_TOKEN( regionLabelLayout ):
862
0
                    mrModel.mosRegionLabelLayout = rAttribs.getString( XML_val );
863
0
                    return nullptr;
864
0
                case CX_TOKEN( visibility ):
865
0
                    mrModel.mobVisibilityConnectorLines = rAttribs.getBool( XML_connectorLines );
866
0
                    mrModel.mobVisibilityMeanLine = rAttribs.getBool( XML_meanLine );
867
0
                    mrModel.mobVisibilityMeanMarker = rAttribs.getBool( XML_meanMarker );
868
0
                    mrModel.mobVisibilityNonoutliers = rAttribs.getBool( XML_nonoutliers );
869
0
                    mrModel.mobVisibilityOutliers = rAttribs.getBool( XML_outliers );
870
0
                    return nullptr;
871
0
                case CX_TOKEN( aggregation ):
872
                    // The schema gives an empty definition for this type??
873
                    // TODO
874
0
                    return nullptr;
875
0
                case CX_TOKEN( binning ):
876
0
                {
877
0
                    BinningModel& rB = mrModel.mxBinning.create();
878
0
                    if (rAttribs.getString( XML_intervalClosed ) == "l")
879
0
                    {
880
0
                        rB.meIntervalClosed = BinningModel::ClosedSide::L;
881
0
                    }
882
0
                    else if (rAttribs.getString( XML_intervalClosed ) == "r")
883
0
                    {
884
0
                        rB.meIntervalClosed = BinningModel::ClosedSide::R;
885
0
                    }
886
                    // intervalClosed is optional in OOXML chartex
887
0
                    rB.mfUnderflow = rAttribs.getDouble(XML_underflow);
888
0
                    rB.mfOverflow = rAttribs.getDouble(XML_overflow);
889
0
                    return new BinningContext( *this, rB );
890
0
                }
891
0
                case CX_TOKEN( geography ):
892
0
                {
893
0
                    auto& rGeo = mrModel.mxGeography.emplace();
894
0
                    std::optional<OUString> sPT = rAttribs.getString( XML_projectionType );
895
0
                    if (sPT.has_value())
896
0
                        rGeo.moeProjectionType = geoProjectionTypeFromString( *sPT );
897
0
                    std::optional<OUString> sVR = rAttribs.getString( XML_viewedRegionType );
898
0
                    if (sVR.has_value())
899
0
                        rGeo.moeViewedRegionType = geoMappingLevelFromString( *sVR );
900
0
                    rGeo.mosCultureLanguage = rAttribs.getString( XML_cultureLanguage );
901
0
                    rGeo.mosCultureRegion = rAttribs.getString( XML_cultureRegion );
902
0
                    rGeo.mosAttribution = rAttribs.getString( XML_attribution );
903
0
                    return new GeographyContext( *this, *mrModel.mxGeography );
904
0
                }
905
0
                case CX_TOKEN( statistics ):
906
0
                    mrModel.mosQuartileMethod = rAttribs.getString( XML_quartileMethod );
907
0
                    return nullptr;
908
0
                case CX_TOKEN( subtotals ):
909
0
                    return this;
910
0
                case CX_TOKEN( extLst ):
911
                    // TODO
912
0
                    return nullptr;
913
0
            }
914
0
            break;
915
0
        case CX_TOKEN( subtotals ):
916
0
            switch( nElement )
917
0
            {
918
0
                case CX_TOKEN( idx ):
919
0
                {
920
0
                    sal_Int32 nVal = rAttribs.getInteger( XML_val, -1 );
921
0
                    if (nVal >= 0)
922
0
                        mrModel.maSubtotalIndices.push_back( nVal );
923
0
                    return nullptr;
924
0
                }
925
0
                default:
926
0
                    return nullptr;
927
0
            }
928
0
            break;
929
0
    }
930
0
    return ContextBase::onCreateContext( nElement, rAttribs );
931
0
}
932
933
//======
934
// ChartexSeriesContext
935
//======
936
ChartexSeriesContext::ChartexSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel, sal_Int32 nIndex ) :
937
0
    SeriesContextBase( rParent, rModel )
938
0
{
939
0
    rModel.mnIndex = nIndex;
940
0
}
941
942
ChartexSeriesContext::~ChartexSeriesContext()
943
{
944
}
945
946
ContextHandlerRef ChartexSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
947
0
{
948
0
    switch( getCurrentElement() )
949
0
    {
950
0
        case CX_TOKEN( series ):
951
0
            switch( nElement )
952
0
            {
953
0
                case CX_TOKEN( valueColors ):
954
                    // TODO
955
0
                    return nullptr;
956
0
                case CX_TOKEN( valueColorPositions ):
957
                    // TODO
958
0
                    return nullptr;
959
0
                case CX_TOKEN( dataPt ):
960
0
                    return new DataPointContext( *this, mrModel.maPoints.create(false) );
961
0
                case CX_TOKEN( dataLabels ):
962
0
                {
963
0
                    DataLabelsModel& rLabels = mrModel.mxLabels.create(false);
964
0
                    rLabels.monLabelPos = rAttribs.getToken( XML_pos );
965
                    // set MSO defaults
966
0
                    rLabels.mobShowSerName = false;
967
0
                    rLabels.mobShowCatName = false;
968
0
                    rLabels.mobShowVal = true;
969
0
                    return new DataLabelsContext( *this, rLabels );
970
0
                }
971
0
                case CX_TOKEN( dataId ):
972
0
                    mrModel.mnDataId = rAttribs.getInteger(XML_val, -1);
973
0
                    return nullptr;
974
0
                case CX_TOKEN( layoutPr ):
975
0
                    return new LayoutPropsContext( *this, mrModel.mxLayoutPr.create());
976
0
                case CX_TOKEN( axisId ):
977
0
                    mrModel.maAxisIds.push_back( rAttribs.getInteger( XML_val, -1 ) );
978
0
                    return nullptr;
979
0
            }
980
0
            break;
981
0
    }
982
0
    return SeriesContextBase::onCreateContext( nElement, rAttribs );
983
0
}
984
985
} // namespace oox
986
987
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */