Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/controller/itemsetwrapper/ErrorBarItemConverter.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 <ErrorBarItemConverter.hxx>
21
#include "SchWhichPairs.hxx"
22
#include <StatisticsHelper.hxx>
23
24
#include <GraphicPropertyItemConverter.hxx>
25
#include <ChartModel.hxx>
26
27
#include <svl/stritem.hxx>
28
#include <svx/chrtitem.hxx>
29
#include <rtl/math.hxx>
30
31
#include <com/sun/star/chart2/XInternalDataProvider.hpp>
32
#include <com/sun/star/chart2/XChartDocument.hpp>
33
#include <com/sun/star/chart/ErrorBarStyle.hpp>
34
#include <comphelper/diagnose_ex.hxx>
35
36
using namespace ::com::sun::star;
37
38
namespace
39
{
40
41
void lcl_getErrorValues( const uno::Reference< beans::XPropertySet > & xErrorBarProp,
42
                    double & rOutPosError, double & rOutNegError )
43
0
{
44
0
    if( ! xErrorBarProp.is())
45
0
        return;
46
47
0
    try
48
0
    {
49
0
        xErrorBarProp->getPropertyValue( u"PositiveError"_ustr ) >>= rOutPosError;
50
0
        xErrorBarProp->getPropertyValue( u"NegativeError"_ustr ) >>= rOutNegError;
51
0
    }
52
0
    catch( const uno::Exception & )
53
0
    {
54
0
        DBG_UNHANDLED_EXCEPTION("chart2");
55
0
    }
56
0
}
57
58
void lcl_getErrorIndicatorValues(
59
    const uno::Reference< beans::XPropertySet > & xErrorBarProp,
60
    bool & rOutShowPosError, bool & rOutShowNegError )
61
0
{
62
0
    if( ! xErrorBarProp.is())
63
0
        return;
64
65
0
    try
66
0
    {
67
0
        xErrorBarProp->getPropertyValue( u"ShowPositiveError"_ustr ) >>= rOutShowPosError;
68
0
        xErrorBarProp->getPropertyValue( u"ShowNegativeError"_ustr ) >>= rOutShowNegError;
69
0
    }
70
0
    catch( const uno::Exception & )
71
0
    {
72
0
        DBG_UNHANDLED_EXCEPTION("chart2");
73
0
    }
74
0
}
75
76
} // anonymous namespace
77
78
namespace chart::wrapper
79
{
80
81
ErrorBarItemConverter::ErrorBarItemConverter(
82
    const rtl::Reference< ChartModel > & xChartModel,
83
    const uno::Reference< beans::XPropertySet > & rPropertySet,
84
    SfxItemPool& rItemPool,
85
    SdrModel& rDrawModel ) :
86
0
        ItemConverter( rPropertySet, rItemPool ),
87
0
        m_spGraphicConverter( std::make_shared<GraphicPropertyItemConverter>(
88
0
                                  rPropertySet, rItemPool, rDrawModel,
89
0
                                  xChartModel,
90
0
                                  GraphicObjectType::LineProperties )),
91
0
        m_xModel(xChartModel)
92
0
{}
93
94
ErrorBarItemConverter::~ErrorBarItemConverter()
95
0
{}
96
97
void ErrorBarItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
98
0
{
99
0
    m_spGraphicConverter->FillItemSet( rOutItemSet );
100
101
    // own items
102
0
    ItemConverter::FillItemSet( rOutItemSet );
103
0
}
104
105
bool ErrorBarItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
106
0
{
107
0
    bool bResult = m_spGraphicConverter->ApplyItemSet( rItemSet );
108
109
    // own items
110
0
    return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
111
0
}
112
113
const WhichRangesContainer& ErrorBarItemConverter::GetWhichPairs() const
114
0
{
115
    // must span all used items!
116
0
    return nErrorBarWhichPairs;
117
0
}
118
119
bool ErrorBarItemConverter::GetItemProperty(
120
    tWhichIdType /* nWhichId */,
121
    tPropertyNameWithMemberId & /* rOutProperty */ ) const
122
0
{
123
0
    return false;
124
0
}
125
126
bool ErrorBarItemConverter::ApplySpecialItem(
127
    sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
128
0
{
129
0
    bool bChanged = false;
130
131
0
    switch( nWhichId )
132
0
    {
133
        // Attention !!! This case must be passed before SCHATTR_STAT_PERCENT,
134
        // SCHATTR_STAT_BIGERROR, SCHATTR_STAT_CONSTPLUS,
135
        // SCHATTR_STAT_CONSTMINUS and SCHATTR_STAT_INDICATE
136
0
        case SCHATTR_STAT_KIND_ERROR:
137
0
        {
138
0
            uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
139
140
0
            SvxChartKindError eErrorKind =
141
0
                static_cast< const SvxChartKindErrorItem & >(
142
0
                    rItemSet.Get( nWhichId )).GetValue();
143
144
0
            if( !xErrorBarProp.is() && eErrorKind == SvxChartKindError::NONE)
145
0
            {
146
                //nothing to do
147
0
            }
148
0
            else
149
0
            {
150
0
                sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
151
152
0
                switch( eErrorKind )
153
0
                {
154
0
                    case SvxChartKindError::NONE:
155
0
                        nStyle = css::chart::ErrorBarStyle::NONE; break;
156
0
                    case SvxChartKindError::Variant:
157
0
                        nStyle = css::chart::ErrorBarStyle::VARIANCE; break;
158
0
                    case SvxChartKindError::Sigma:
159
0
                        nStyle = css::chart::ErrorBarStyle::STANDARD_DEVIATION; break;
160
0
                    case SvxChartKindError::Percent:
161
0
                        nStyle = css::chart::ErrorBarStyle::RELATIVE; break;
162
0
                    case SvxChartKindError::BigError:
163
0
                        nStyle = css::chart::ErrorBarStyle::ERROR_MARGIN; break;
164
0
                    case SvxChartKindError::Const:
165
0
                        nStyle = css::chart::ErrorBarStyle::ABSOLUTE; break;
166
0
                    case SvxChartKindError::StdError:
167
0
                        nStyle = css::chart::ErrorBarStyle::STANDARD_ERROR; break;
168
0
                    case SvxChartKindError::Range:
169
0
                        nStyle = css::chart::ErrorBarStyle::FROM_DATA; break;
170
0
                }
171
172
0
                xErrorBarProp->setPropertyValue( u"ErrorBarStyle"_ustr , uno::Any( nStyle ));
173
0
                bChanged = true;
174
0
            }
175
0
        }
176
0
        break;
177
178
0
        case SCHATTR_STAT_PERCENT:
179
0
        case SCHATTR_STAT_BIGERROR:
180
0
        {
181
0
            OSL_FAIL( "Deprecated item" );
182
0
            uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
183
184
0
            double fValue =
185
0
                static_cast< const SvxDoubleItem & >(
186
0
                    rItemSet.Get( nWhichId )).GetValue();
187
0
            double fPos(0.0), fNeg(0.0);
188
0
            lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
189
190
0
            if( ! ( ::rtl::math::approxEqual( fPos, fValue ) &&
191
0
                    ::rtl::math::approxEqual( fNeg, fValue )))
192
0
            {
193
0
                xErrorBarProp->setPropertyValue( u"PositiveError"_ustr , uno::Any( fValue ));
194
0
                xErrorBarProp->setPropertyValue( u"NegativeError"_ustr , uno::Any( fValue ));
195
0
                bChanged = true;
196
0
            }
197
0
        }
198
0
        break;
199
200
0
        case SCHATTR_STAT_CONSTPLUS:
201
0
        {
202
0
            double fValue =
203
0
                static_cast< const SvxDoubleItem & >(
204
0
                    rItemSet.Get( nWhichId )).GetValue();
205
0
            double fPos(0.0), fNeg(0.0);
206
0
            lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
207
208
0
            if( ! ::rtl::math::approxEqual( fPos, fValue ))
209
0
            {
210
0
                GetPropertySet()->setPropertyValue( u"PositiveError"_ustr , uno::Any( fValue ));
211
0
                bChanged = true;
212
0
            }
213
0
        }
214
0
        break;
215
216
0
        case SCHATTR_STAT_CONSTMINUS:
217
0
        {
218
0
            uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
219
220
0
            double fValue =
221
0
                static_cast< const SvxDoubleItem & >(
222
0
                    rItemSet.Get( nWhichId )).GetValue();
223
0
            double fPos(0.0), fNeg(0.0);
224
0
            lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
225
226
0
            if( ! ::rtl::math::approxEqual( fNeg, fValue ))
227
0
            {
228
0
                xErrorBarProp->setPropertyValue( u"NegativeError"_ustr , uno::Any( fValue ));
229
0
                bChanged = true;
230
0
            }
231
0
        }
232
0
        break;
233
234
0
        case SCHATTR_STAT_INDICATE:
235
0
        {
236
0
            uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
237
238
0
            SvxChartIndicate eIndicate =
239
0
                static_cast< const SvxChartIndicateItem & >(
240
0
                    rItemSet.Get( nWhichId )).GetValue();
241
242
0
            bool bNewIndPos = (eIndicate == SvxChartIndicate::Both || eIndicate == SvxChartIndicate::Up );
243
0
            bool bNewIndNeg = (eIndicate == SvxChartIndicate::Both || eIndicate == SvxChartIndicate::Down );
244
245
0
            bool bShowPos(false), bShowNeg(false);
246
0
            lcl_getErrorIndicatorValues( xErrorBarProp, bShowPos, bShowNeg );
247
248
0
            if( bShowPos != bNewIndPos ||
249
0
                bShowNeg != bNewIndNeg )
250
0
            {
251
0
                xErrorBarProp->setPropertyValue( u"ShowPositiveError"_ustr , uno::Any( bNewIndPos ));
252
0
                xErrorBarProp->setPropertyValue( u"ShowNegativeError"_ustr , uno::Any( bNewIndNeg ));
253
0
                bChanged = true;
254
0
            }
255
0
        }
256
0
        break;
257
258
0
        case SCHATTR_STAT_RANGE_POS:
259
0
        case SCHATTR_STAT_RANGE_NEG:
260
0
        {
261
            // @todo: also be able to deal with x-error bars
262
0
            const bool bYError =
263
0
                rItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
264
265
0
            uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
266
0
            uno::Reference< chart2::XChartDocument > xChartDoc( m_xModel, uno::UNO_QUERY );
267
0
            uno::Reference< chart2::data::XDataProvider > xDataProvider;
268
269
0
            if( xChartDoc.is())
270
0
                xDataProvider.set( xChartDoc->getDataProvider());
271
0
            if( xErrorBarSource.is() && xDataProvider.is())
272
0
            {
273
0
                OUString aNewRange( static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue());
274
0
                bool bApplyNewRange = false;
275
276
0
                bool bIsPositiveValue( nWhichId == SCHATTR_STAT_RANGE_POS );
277
0
                if( xChartDoc->hasInternalDataProvider())
278
0
                {
279
0
                    if( !aNewRange.isEmpty())
280
0
                    {
281
0
                        uno::Reference< chart2::data::XDataSequence > xSeq(
282
0
                            StatisticsHelper::getErrorDataSequenceFromDataSource(
283
0
                                xErrorBarSource, bIsPositiveValue, bYError ));
284
0
                        if( ! xSeq.is())
285
0
                        {
286
                            // no data range for error bars yet => create
287
0
                            uno::Reference< chart2::XInternalDataProvider > xIntDataProvider( xDataProvider, uno::UNO_QUERY );
288
0
                            OSL_ASSERT( xIntDataProvider.is());
289
0
                            if( xIntDataProvider.is())
290
0
                            {
291
0
                                xIntDataProvider->appendSequence();
292
0
                                aNewRange = "last";
293
0
                                bApplyNewRange = true;
294
0
                            }
295
0
                        }
296
0
                    }
297
0
                }
298
0
                else
299
0
                {
300
0
                    uno::Reference< chart2::data::XDataSequence > xSeq(
301
0
                        StatisticsHelper::getErrorDataSequenceFromDataSource(
302
0
                            xErrorBarSource, bIsPositiveValue, bYError ));
303
0
                    bApplyNewRange =
304
0
                        ! ( xSeq.is() && (aNewRange == xSeq->getSourceRangeRepresentation()));
305
0
                }
306
307
0
                if( bApplyNewRange )
308
0
                    StatisticsHelper::setErrorDataSequence(
309
0
                        xErrorBarSource, xDataProvider, aNewRange, bIsPositiveValue, bYError );
310
0
            }
311
0
        }
312
0
        break;
313
0
    }
314
315
0
    return bChanged;
316
0
}
317
318
void ErrorBarItemConverter::FillSpecialItem(
319
    sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
320
0
{
321
0
    switch( nWhichId )
322
0
    {
323
0
        case SCHATTR_STAT_KIND_ERROR:
324
0
        {
325
0
            SvxChartKindError eErrorKind = SvxChartKindError::NONE;
326
0
            uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
327
328
0
            sal_Int32 nStyle = 0;
329
0
            if( xErrorBarProp->getPropertyValue( u"ErrorBarStyle"_ustr ) >>= nStyle )
330
0
            {
331
0
                switch( nStyle )
332
0
                {
333
0
                    case css::chart::ErrorBarStyle::NONE:
334
0
                        break;
335
0
                    case css::chart::ErrorBarStyle::VARIANCE:
336
0
                        eErrorKind = SvxChartKindError::Variant; break;
337
0
                    case css::chart::ErrorBarStyle::STANDARD_DEVIATION:
338
0
                        eErrorKind = SvxChartKindError::Sigma; break;
339
0
                    case css::chart::ErrorBarStyle::ABSOLUTE:
340
0
                        eErrorKind = SvxChartKindError::Const; break;
341
0
                    case css::chart::ErrorBarStyle::RELATIVE:
342
0
                        eErrorKind = SvxChartKindError::Percent; break;
343
0
                    case css::chart::ErrorBarStyle::ERROR_MARGIN:
344
0
                        eErrorKind = SvxChartKindError::BigError; break;
345
0
                    case css::chart::ErrorBarStyle::STANDARD_ERROR:
346
0
                        eErrorKind = SvxChartKindError::StdError; break;
347
0
                    case css::chart::ErrorBarStyle::FROM_DATA:
348
0
                        eErrorKind = SvxChartKindError::Range; break;
349
0
                    default:
350
0
                        eErrorKind = SvxChartKindError::NONE; break;
351
0
                }
352
0
            }
353
0
            rOutItemSet.Put( SvxChartKindErrorItem( eErrorKind, SCHATTR_STAT_KIND_ERROR ));
354
0
        }
355
0
        break;
356
357
0
        case SCHATTR_STAT_PERCENT:
358
0
        {
359
0
            double fPos(0.0), fNeg(0.0);
360
0
            lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
361
0
            rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, SCHATTR_STAT_PERCENT ));
362
0
        }
363
0
        break;
364
365
0
        case SCHATTR_STAT_BIGERROR:
366
0
        {
367
0
            double fPos(0.0), fNeg(0.0);
368
0
            lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
369
0
            rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, SCHATTR_STAT_BIGERROR ));
370
0
        }
371
0
        break;
372
373
0
        case SCHATTR_STAT_CONSTPLUS:
374
0
        {
375
0
            double fPos(0.0), fNeg(0.0);
376
0
            lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
377
0
            rOutItemSet.Put( SvxDoubleItem( fPos, SCHATTR_STAT_CONSTPLUS ));
378
0
        }
379
0
        break;
380
381
0
        case SCHATTR_STAT_CONSTMINUS:
382
0
        {
383
0
            double fPos(0.0), fNeg(0.0);
384
0
            lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
385
0
            rOutItemSet.Put( SvxDoubleItem( fNeg, SCHATTR_STAT_CONSTMINUS ));
386
0
        }
387
0
        break;
388
389
0
        case SCHATTR_STAT_INDICATE:
390
0
        {
391
0
            SvxChartIndicate eIndicate = SvxChartIndicate::Both;
392
0
            bool bShowPos(false), bShowNeg(false);
393
0
            lcl_getErrorIndicatorValues( GetPropertySet(), bShowPos, bShowNeg );
394
395
0
            if( bShowPos )
396
0
            {
397
0
                if( bShowNeg )
398
0
                    eIndicate = SvxChartIndicate::Both;
399
0
                else
400
0
                    eIndicate = SvxChartIndicate::Up;
401
0
            }
402
0
            else
403
0
            {
404
0
                if( bShowNeg )
405
0
                    eIndicate = SvxChartIndicate::Down;
406
0
                else
407
0
                    eIndicate = SvxChartIndicate::NONE;
408
0
            }
409
0
            rOutItemSet.Put( SvxChartIndicateItem( eIndicate, SCHATTR_STAT_INDICATE ));
410
0
        }
411
0
        break;
412
413
0
        case SCHATTR_STAT_RANGE_POS:
414
0
        case SCHATTR_STAT_RANGE_NEG:
415
0
        {
416
0
            const bool bYError =
417
0
                rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
418
419
0
            uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
420
0
            if( xErrorBarSource.is())
421
0
            {
422
0
                uno::Reference< chart2::data::XDataSequence > xSeq(
423
0
                    StatisticsHelper::getErrorDataSequenceFromDataSource(
424
0
                        xErrorBarSource, (nWhichId == SCHATTR_STAT_RANGE_POS), bYError ));
425
0
                if( xSeq.is())
426
0
                    rOutItemSet.Put( SfxStringItem( nWhichId, xSeq->getSourceRangeRepresentation()));
427
0
            }
428
0
        }
429
0
        break;
430
0
   }
431
0
}
432
433
} //  namespace chart::wrapper
434
435
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */