Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/tools/ErrorBar.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 <ErrorBar.hxx>
21
#include <EventListenerHelper.hxx>
22
#include <CloneHelper.hxx>
23
#include <ModifyListenerHelper.hxx>
24
25
#include <comphelper/sequence.hxx>
26
#include <cppuhelper/supportsservice.hxx>
27
#include <svl/itemprop.hxx>
28
#include <vcl/svapp.hxx>
29
30
#include <com/sun/star/chart/ErrorBarStyle.hpp>
31
32
#include <com/sun/star/drawing/LineStyle.hpp>
33
#include <com/sun/star/util/Color.hpp>
34
#include <com/sun/star/drawing/LineJoint.hpp>
35
36
#include <comphelper/diagnose_ex.hxx>
37
#include <sal/log.hxx>
38
39
using namespace ::com::sun::star;
40
41
namespace
42
{
43
44
constexpr OUString lcl_aServiceName = u"com.sun.star.comp.chart2.ErrorBar"_ustr;
45
46
bool lcl_isInternalData( const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq )
47
0
{
48
0
    uno::Reference< lang::XServiceInfo > xServiceInfo( xLSeq, uno::UNO_QUERY );
49
0
    return ( xServiceInfo.is() && xServiceInfo->getImplementationName() == "com.sun.star.comp.chart2.LabeledDataSequence" );
50
0
}
51
52
const SfxItemPropertySet* GetErrorBarPropertySet()
53
0
{
54
0
    static const SfxItemPropertyMapEntry aErrorBarPropertyMap_Impl[] =
55
0
    {
56
0
        {u"ShowPositiveError"_ustr,0,cppu::UnoType<bool>::get(), 0, 0},
57
0
        {u"ShowNegativeError"_ustr,1,cppu::UnoType<bool>::get(), 0, 0},
58
0
        {u"PositiveError"_ustr,2,cppu::UnoType<double>::get(),0,0},
59
0
        {u"NegativeError"_ustr,3,cppu::UnoType<double>::get(), 0, 0},
60
0
        {u"PercentageError"_ustr,4,cppu::UnoType<double>::get(), 0, 0},
61
0
        {u"ErrorBarStyle"_ustr,5,cppu::UnoType<sal_Int32>::get(),0,0},
62
0
        {u"ErrorBarRangePositive"_ustr,6,cppu::UnoType<OUString>::get(),0,0}, // read-only for export
63
0
        {u"ErrorBarRangeNegative"_ustr,7,cppu::UnoType<OUString>::get(),0,0}, // read-only for export
64
0
        {u"Weight"_ustr,8,cppu::UnoType<double>::get(),0,0},
65
0
        {u"LineStyle"_ustr,9,cppu::UnoType<css::drawing::LineStyle>::get(),0,0},
66
0
        {u"LineDash"_ustr,10,cppu::UnoType<drawing::LineDash>::get(),0,0},
67
0
        {u"LineWidth"_ustr,11,cppu::UnoType<sal_Int32>::get(),0,0},
68
0
        {u"LineColor"_ustr,12,cppu::UnoType<css::util::Color>::get(),0,0},
69
0
        {u"LineTransparence"_ustr,13,cppu::UnoType<sal_Int16>::get(),0,0},
70
0
        {u"LineJoint"_ustr,14,cppu::UnoType<css::drawing::LineJoint>::get(),0,0},
71
0
    };
72
0
    static SfxItemPropertySet aPropSet( aErrorBarPropertyMap_Impl );
73
0
    return &aPropSet;
74
0
}
75
76
} // anonymous namespace
77
78
namespace chart
79
{
80
81
ErrorBar::ErrorBar() :
82
0
    mnLineWidth(0),
83
0
    meLineStyle(drawing::LineStyle_SOLID),
84
0
    maLineColor(0),
85
0
    mnLineTransparence(0),
86
0
    meLineJoint(drawing::LineJoint_ROUND),
87
0
    mbShowPositiveError(true),
88
0
    mbShowNegativeError(true),
89
0
    mfPositiveError(0),
90
0
    mfNegativeError(0),
91
0
    mfWeight(1),
92
0
    meStyle(css::chart::ErrorBarStyle::NONE),
93
0
    m_xModifyEventForwarder( new ModifyEventForwarder() )
94
0
{}
95
96
ErrorBar::ErrorBar( const ErrorBar & rOther ) :
97
0
    impl::ErrorBar_Base(rOther),
98
0
    maDashName(rOther.maDashName),
99
0
    maLineDash(rOther.maLineDash),
100
0
    mnLineWidth(rOther.mnLineWidth),
101
0
    meLineStyle(rOther.meLineStyle),
102
0
    maLineColor(rOther.maLineColor),
103
0
    mnLineTransparence(rOther.mnLineTransparence),
104
0
    meLineJoint(rOther.meLineJoint),
105
0
    mbShowPositiveError(rOther.mbShowPositiveError),
106
0
    mbShowNegativeError(rOther.mbShowNegativeError),
107
0
    mfPositiveError(rOther.mfPositiveError),
108
0
    mfNegativeError(rOther.mfNegativeError),
109
0
    mfWeight(rOther.mfWeight),
110
0
    meStyle(rOther.meStyle),
111
0
    m_xModifyEventForwarder( new ModifyEventForwarder() )
112
0
{
113
0
    if( ! rOther.m_aDataSequences.empty())
114
0
    {
115
0
        if( lcl_isInternalData( rOther.m_aDataSequences.front()))
116
0
            CloneHelper::CloneRefVector< css::chart2::data::XLabeledDataSequence >(
117
0
                rOther.m_aDataSequences, m_aDataSequences );
118
0
        else
119
0
            m_aDataSequences = rOther.m_aDataSequences;
120
0
        ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder );
121
0
    }
122
0
}
123
124
ErrorBar::~ErrorBar()
125
0
{}
126
127
uno::Reference< util::XCloneable > SAL_CALL ErrorBar::createClone()
128
0
{
129
0
    return uno::Reference< util::XCloneable >( new ErrorBar( *this ));
130
0
}
131
132
// ____ XPropertySet ____
133
uno::Reference< beans::XPropertySetInfo > SAL_CALL ErrorBar::getPropertySetInfo()
134
0
{
135
0
    static uno::Reference< beans::XPropertySetInfo > aRef (
136
0
            new SfxItemPropertySetInfo( GetErrorBarPropertySet()->getPropertyMap() ) );
137
0
    return aRef;
138
0
}
139
140
void ErrorBar::setPropertyValue( const OUString& rPropName, const uno::Any& rAny )
141
0
{
142
0
    SolarMutexGuard aGuard;
143
144
0
    if(rPropName == "ErrorBarStyle")
145
0
        rAny >>= meStyle;
146
0
    else if(rPropName == "PositiveError")
147
0
        rAny >>= mfPositiveError;
148
0
    else if(rPropName == "PercentageError")
149
0
    {
150
0
        rAny >>= mfPositiveError;
151
0
        rAny >>= mfNegativeError;
152
0
    }
153
0
    else if(rPropName == "Weight")
154
0
    {
155
0
        rAny >>= mfWeight;
156
0
    }
157
0
    else if(rPropName == "NegativeError")
158
0
        rAny >>= mfNegativeError;
159
0
    else if(rPropName == "ShowPositiveError")
160
0
        rAny >>= mbShowPositiveError;
161
0
    else if(rPropName == "ShowNegativeError")
162
0
        rAny >>= mbShowNegativeError;
163
0
    else if(rPropName == "ErrorBarRangePositive" || rPropName == "ErrorBarRangeNegative")
164
0
        throw beans::UnknownPropertyException(u"read-only property"_ustr, static_cast< uno::XWeak*>(this));
165
0
    else if(rPropName == "LineDashName")
166
0
        rAny >>= maDashName;
167
0
    else if(rPropName == "LineDash")
168
0
        rAny >>= maLineDash;
169
0
    else if(rPropName == "LineWidth")
170
0
        rAny >>= mnLineWidth;
171
0
    else if(rPropName == "LineStyle")
172
0
        rAny >>= meLineStyle;
173
0
    else if(rPropName == "LineColor")
174
0
        rAny >>= maLineColor;
175
0
    else if(rPropName == "LineTransparence")
176
0
        rAny >>= mnLineTransparence;
177
0
    else if(rPropName == "LineJoint")
178
0
        rAny >>= meLineJoint;
179
180
0
    m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
181
0
}
182
183
namespace {
184
185
OUString getSourceRangeStrFromLabeledSequences( const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > >& aSequences, bool bPositive )
186
0
{
187
0
    OUString aDirection;
188
0
    if(bPositive)
189
0
        aDirection = "positive";
190
0
    else
191
0
        aDirection = "negative";
192
193
0
    for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledData : aSequences )
194
0
    {
195
0
        try
196
0
        {
197
0
            if( labeledData.is())
198
0
            {
199
0
                uno::Reference< chart2::data::XDataSequence > xSequence( labeledData->getValues());
200
0
                uno::Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
201
0
                OUString aRole;
202
0
                if( ( xSeqProp->getPropertyValue( u"Role"_ustr ) >>= aRole ) &&
203
0
                        aRole.match( "error-bars" ) && aRole.indexOf(aDirection) >= 0 )
204
0
                {
205
0
                    return xSequence->getSourceRangeRepresentation();
206
0
                }
207
0
            }
208
0
        }
209
0
        catch (uno::Exception const &)
210
0
        {
211
            // we can't be sure that this is 100% safe and we don't want to kill the export
212
            // we should at least check why the exception is thrown
213
0
            TOOLS_WARN_EXCEPTION("chart2", "unexpected exception");
214
0
        }
215
0
        catch (...)
216
0
        {
217
            // we can't be sure that this is 100% safe and we don't want to kill the export
218
            // we should at least check why the exception is thrown
219
0
            SAL_WARN("chart2", "unexpected exception! ");
220
0
        }
221
0
    }
222
223
0
    return OUString();
224
0
}
225
226
}
227
228
uno::Any ErrorBar::getPropertyValue(const OUString& rPropName)
229
0
{
230
0
    SolarMutexGuard aGuard;
231
232
0
    uno::Any aRet;
233
0
    if(rPropName == "ErrorBarStyle")
234
0
        aRet <<= meStyle;
235
0
    else if(rPropName == "PositiveError")
236
0
        aRet <<= mfPositiveError;
237
0
    else if(rPropName == "NegativeError")
238
0
        aRet <<= mfNegativeError;
239
0
    else if(rPropName == "PercentageError")
240
0
        aRet <<= mfPositiveError;
241
0
    else if(rPropName == "ShowPositiveError")
242
0
        aRet <<= mbShowPositiveError;
243
0
    else if(rPropName == "ShowNegativeError")
244
0
        aRet <<= mbShowNegativeError;
245
0
    else if(rPropName == "Weight")
246
0
        aRet <<= mfWeight;
247
0
    else if(rPropName == "ErrorBarRangePositive")
248
0
    {
249
0
        OUString aRange;
250
0
        if(meStyle == css::chart::ErrorBarStyle::FROM_DATA)
251
0
        {
252
0
            uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences =
253
0
                getDataSequences();
254
255
0
            aRange = getSourceRangeStrFromLabeledSequences( aSequences, true );
256
0
        }
257
258
0
        aRet <<= aRange;
259
0
    }
260
0
    else if(rPropName == "ErrorBarRangeNegative")
261
0
    {
262
0
        OUString aRange;
263
0
        if(meStyle == css::chart::ErrorBarStyle::FROM_DATA)
264
0
        {
265
0
            uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences =
266
0
                getDataSequences();
267
268
0
            aRange = getSourceRangeStrFromLabeledSequences( aSequences, false );
269
0
        }
270
271
0
        aRet <<= aRange;
272
0
    }
273
0
    else if(rPropName == "LineDashName")
274
0
        aRet <<= maDashName;
275
0
    else if(rPropName == "LineDash")
276
0
        aRet <<= maLineDash;
277
0
    else if(rPropName == "LineWidth")
278
0
        aRet <<= mnLineWidth;
279
0
    else if(rPropName == "LineStyle")
280
0
        aRet <<= meLineStyle;
281
0
    else if(rPropName == "LineColor")
282
0
        aRet <<= maLineColor;
283
0
    else if(rPropName == "LineTransparence")
284
0
        aRet <<= mnLineTransparence;
285
0
    else if(rPropName == "LineJoint")
286
0
        aRet <<= meLineJoint;
287
288
0
    SAL_WARN_IF(!aRet.hasValue(), "chart2", "asked for property value: " << rPropName);
289
0
    return aRet;
290
0
}
291
292
beans::PropertyState ErrorBar::getPropertyState( const OUString& rPropName )
293
0
{
294
0
    if(rPropName == "ErrorBarStyle")
295
0
    {
296
0
        if(meStyle == css::chart::ErrorBarStyle::NONE)
297
0
            return beans::PropertyState_DEFAULT_VALUE;
298
0
        return beans::PropertyState_DIRECT_VALUE;
299
0
    }
300
0
    else if(rPropName == "PositiveError")
301
0
    {
302
0
        if(mbShowPositiveError)
303
0
        {
304
0
            switch(meStyle)
305
0
            {
306
0
                case css::chart::ErrorBarStyle::ABSOLUTE:
307
0
                case css::chart::ErrorBarStyle::ERROR_MARGIN:
308
0
                    return beans::PropertyState_DIRECT_VALUE;
309
0
                default:
310
0
                    break;
311
0
            }
312
0
        }
313
0
        return beans::PropertyState_DEFAULT_VALUE;
314
0
    }
315
0
    else if(rPropName == "NegativeError")
316
0
    {
317
0
        if(mbShowNegativeError)
318
0
        {
319
0
            switch(meStyle)
320
0
            {
321
0
                case css::chart::ErrorBarStyle::ABSOLUTE:
322
0
                case css::chart::ErrorBarStyle::ERROR_MARGIN:
323
0
                    return beans::PropertyState_DIRECT_VALUE;
324
0
                default:
325
0
                    break;
326
0
            }
327
0
        }
328
0
        return beans::PropertyState_DEFAULT_VALUE;
329
0
    }
330
0
    else if(rPropName == "PercentageError")
331
0
    {
332
0
        if(meStyle != css::chart::ErrorBarStyle::RELATIVE)
333
0
            return beans::PropertyState_DEFAULT_VALUE;
334
0
        return beans::PropertyState_DIRECT_VALUE;
335
0
    }
336
0
    else if(rPropName == "ShowPositiveError")
337
0
    {
338
        // this value should be never default
339
0
        return beans::PropertyState_DIRECT_VALUE;
340
0
    }
341
0
    else if(rPropName == "ShowNegativeError")
342
0
    {
343
        // this value should be never default
344
0
        return beans::PropertyState_DIRECT_VALUE;
345
0
    }
346
0
    else if(rPropName == "ErrorBarRangePositive")
347
0
    {
348
0
        if(meStyle == css::chart::ErrorBarStyle::FROM_DATA && mbShowPositiveError)
349
0
            return beans::PropertyState_DIRECT_VALUE;
350
0
        return beans::PropertyState_DEFAULT_VALUE;
351
0
    }
352
0
    else if(rPropName == "ErrorBarRangeNegative")
353
0
    {
354
0
        if(meStyle == css::chart::ErrorBarStyle::FROM_DATA && mbShowNegativeError)
355
0
            return beans::PropertyState_DIRECT_VALUE;
356
0
        return beans::PropertyState_DEFAULT_VALUE;
357
0
    }
358
0
    else
359
0
        return beans::PropertyState_DIRECT_VALUE;
360
0
}
361
362
uno::Sequence< beans::PropertyState > ErrorBar::getPropertyStates( const uno::Sequence< OUString >& rPropNames )
363
0
{
364
0
    uno::Sequence< beans::PropertyState > aRet( rPropNames.getLength() );
365
0
    auto aRetRange = asNonConstRange(aRet);
366
0
    for(sal_Int32 i = 0; i < rPropNames.getLength(); ++i)
367
0
    {
368
0
        aRetRange[i] = getPropertyState(rPropNames[i]);
369
0
    }
370
0
    return aRet;
371
0
}
372
373
void ErrorBar::setPropertyToDefault( const OUString& )
374
0
{
375
    //keep them unimplemented for now
376
0
}
377
378
uno::Any ErrorBar::getPropertyDefault( const OUString& )
379
0
{
380
    //keep them unimplemented for now
381
0
    return uno::Any();
382
0
}
383
384
void ErrorBar::addPropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& )
385
0
{
386
0
}
387
388
void ErrorBar::removePropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& )
389
0
{
390
0
}
391
392
void ErrorBar::addVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& )
393
0
{
394
0
}
395
396
void ErrorBar::removeVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& )
397
0
{
398
0
}
399
400
// ____ XModifyBroadcaster ____
401
void SAL_CALL ErrorBar::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
402
0
{
403
0
    m_xModifyEventForwarder->addModifyListener( aListener );
404
0
}
405
406
void SAL_CALL ErrorBar::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
407
0
{
408
0
    m_xModifyEventForwarder->removeModifyListener( aListener );
409
0
}
410
411
// ____ XModifyListener ____
412
void SAL_CALL ErrorBar::modified( const lang::EventObject& aEvent )
413
0
{
414
0
    m_xModifyEventForwarder->modified( aEvent );
415
0
}
416
417
// ____ XEventListener (base of XModifyListener) ____
418
void SAL_CALL ErrorBar::disposing( const lang::EventObject& /* Source */ )
419
0
{
420
    // nothing
421
0
}
422
423
// ____ XDataSink ____
424
void SAL_CALL ErrorBar::setData( const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > >& aData )
425
0
{
426
0
    ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences, m_xModifyEventForwarder );
427
0
    EventListenerHelper::removeListenerFromAllElements( m_aDataSequences, this );
428
0
    m_aDataSequences = comphelper::sequenceToContainer<tDataSequenceContainer>( aData );
429
0
    EventListenerHelper::addListenerToAllElements( m_aDataSequences, this );
430
0
    ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder );
431
0
}
432
433
// ____ XDataSource ____
434
uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > SAL_CALL ErrorBar::getDataSequences()
435
0
{
436
0
    return comphelper::containerToSequence( m_aDataSequences );
437
0
}
438
439
OUString SAL_CALL ErrorBar::getImplementationName()
440
0
{
441
0
    return lcl_aServiceName;
442
0
}
443
444
sal_Bool SAL_CALL ErrorBar::supportsService( const OUString& rServiceName )
445
0
{
446
0
    return cppu::supportsService(this, rServiceName);
447
0
}
448
449
css::uno::Sequence< OUString > SAL_CALL ErrorBar::getSupportedServiceNames()
450
0
{
451
0
    return {
452
0
        lcl_aServiceName,
453
0
        u"com.sun.star.chart2.ErrorBar"_ustr
454
0
    };
455
0
}
456
457
// needed by MSC compiler
458
using impl::ErrorBar_Base;
459
460
} //  namespace chart
461
462
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
463
com_sun_star_comp_chart2_ErrorBar_get_implementation(css::uno::XComponentContext *,
464
        css::uno::Sequence<css::uno::Any> const &)
465
0
{
466
0
    return cppu::acquire(new ::chart::ErrorBar);
467
0
}
468
469
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */