Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/model/main/BaseCoordinateSystem.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 <BaseCoordinateSystem.hxx>
21
#include <PropertyHelper.hxx>
22
#include <UserDefinedProperties.hxx>
23
#include <CloneHelper.hxx>
24
#include <ModifyListenerHelper.hxx>
25
#include <Axis.hxx>
26
#include <ChartType.hxx>
27
#include <com/sun/star/chart2/AxisType.hpp>
28
#include <com/sun/star/container/NoSuchElementException.hpp>
29
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30
#include <o3tl/safeint.hxx>
31
#include <comphelper/diagnose_ex.hxx>
32
33
#include <algorithm>
34
35
#include <com/sun/star/beans/PropertyAttribute.hpp>
36
37
using namespace ::com::sun::star;
38
using ::com::sun::star::uno::Reference;
39
using ::com::sun::star::uno::Sequence;
40
using ::com::sun::star::beans::Property;
41
42
namespace
43
{
44
enum
45
{
46
    PROP_COORDINATESYSTEM_SWAPXANDYAXIS
47
};
48
49
void lcl_AddPropertiesToVector(
50
    std::vector< Property > & rOutProperties )
51
0
{
52
0
    rOutProperties.emplace_back( "SwapXAndYAxis",
53
0
                  PROP_COORDINATESYSTEM_SWAPXANDYAXIS,
54
0
                  cppu::UnoType<bool>::get(),
55
0
                  beans::PropertyAttribute::BOUND
56
0
                  | beans::PropertyAttribute::MAYBEVOID );
57
0
}
58
59
const ::chart::tPropertyValueMap & StaticCooSysDefaults()
60
0
{
61
0
    static ::chart::tPropertyValueMap aStaticDefaults = []()
62
0
    {
63
0
        ::chart::tPropertyValueMap aMap;
64
0
        ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_COORDINATESYSTEM_SWAPXANDYAXIS, false );
65
0
        return aMap;
66
0
    }();
67
0
    return aStaticDefaults;
68
0
};
69
70
::cppu::OPropertyArrayHelper& StaticCooSysInfoHelper()
71
0
{
72
0
    static ::cppu::OPropertyArrayHelper aPropHelper = []()
73
0
        {
74
0
            std::vector< css::beans::Property > aProperties;
75
0
            lcl_AddPropertiesToVector( aProperties );
76
0
            ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
77
78
0
            std::sort( aProperties.begin(), aProperties.end(),
79
0
                         ::chart::PropertyNameLess() );
80
81
0
            return comphelper::containerToSequence( aProperties );
82
0
        }();
83
0
    return aPropHelper;
84
0
};
85
86
} // anonymous namespace
87
88
namespace chart
89
{
90
91
BaseCoordinateSystem::BaseCoordinateSystem(
92
    sal_Int32 nDimensionCount /* = 2 */ ) :
93
0
        m_xModifyEventForwarder( new ModifyEventForwarder() ),
94
0
        m_nDimensionCount( nDimensionCount )
95
0
 {
96
0
    m_aAllAxis.resize( m_nDimensionCount );
97
0
    for( sal_Int32 nN=0; nN<m_nDimensionCount; nN++ )
98
0
    {
99
0
        m_aAllAxis[nN].resize( 1 );
100
0
        rtl::Reference< Axis > xAxis( new Axis );
101
0
        m_aAllAxis[nN][0] = xAxis;
102
103
0
        ModifyListenerHelper::addListenerToAllElements( m_aAllAxis[nN], m_xModifyEventForwarder );
104
0
        chart2::ScaleData aScaleData( xAxis->getScaleData() );
105
0
        if(nN==0)
106
0
        {
107
0
            aScaleData.AxisType = chart2::AxisType::CATEGORY;
108
0
        }
109
0
        else if( nN==1)
110
0
        {
111
0
            aScaleData.AxisType = chart2::AxisType::REALNUMBER;
112
0
        }
113
0
        else if( nN==2)
114
0
        {
115
0
            aScaleData.AxisType = chart2::AxisType::SERIES;
116
0
        }
117
0
        xAxis->setScaleData( aScaleData );
118
0
    }
119
120
0
    setFastPropertyValue_NoBroadcast( PROP_COORDINATESYSTEM_SWAPXANDYAXIS, uno::Any( false ));
121
0
}
122
123
// explicit
124
BaseCoordinateSystem::BaseCoordinateSystem(
125
    const BaseCoordinateSystem & rSource ) :
126
0
        impl::BaseCoordinateSystem_Base(rSource),
127
0
        ::property::OPropertySet( rSource ),
128
0
    m_xModifyEventForwarder( new ModifyEventForwarder() ),
129
0
    m_nDimensionCount( rSource.m_nDimensionCount )
130
0
{
131
0
    m_aAllAxis.resize(rSource.m_aAllAxis.size());
132
0
    tAxisVecVecType::size_type nN=0;
133
0
    for( nN=0; nN<m_aAllAxis.size(); nN++ )
134
0
        CloneHelper::CloneRefVector( rSource.m_aAllAxis[nN], m_aAllAxis[nN] );
135
0
    for (const auto & rxChartType : rSource.m_aChartTypes)
136
0
        m_aChartTypes.push_back(rxChartType->cloneChartType());
137
138
0
    for( nN=0; nN<m_aAllAxis.size(); nN++ )
139
0
        ModifyListenerHelper::addListenerToAllElements( m_aAllAxis[nN], m_xModifyEventForwarder );
140
0
    for (const auto & rxChartType : m_aChartTypes)
141
0
        rxChartType->addModifyListener( m_xModifyEventForwarder );
142
0
}
143
144
BaseCoordinateSystem::~BaseCoordinateSystem()
145
0
{
146
0
    try
147
0
    {
148
0
        for(const tAxisVecVecType::value_type & i : m_aAllAxis)
149
0
            ModifyListenerHelper::removeListenerFromAllElements( i, m_xModifyEventForwarder );
150
0
        for (const auto & rxChartType : m_aChartTypes)
151
0
            rxChartType->removeModifyListener( m_xModifyEventForwarder );
152
0
    }
153
0
    catch( const uno::Exception & )
154
0
    {
155
0
        DBG_UNHANDLED_EXCEPTION("chart2" );
156
0
    }
157
0
}
158
159
// ____ XCoordinateSystem ____
160
sal_Int32 SAL_CALL BaseCoordinateSystem::getDimension()
161
0
{
162
0
    return m_nDimensionCount;
163
0
}
164
165
void SAL_CALL BaseCoordinateSystem::setAxisByDimension(
166
    sal_Int32 nDimensionIndex,
167
    const Reference< chart2::XAxis >& xAxis,
168
    sal_Int32 nIndex )
169
0
{
170
0
    if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
171
0
        throw lang::IndexOutOfBoundsException();
172
173
0
    if( nIndex < 0 )
174
0
        throw lang::IndexOutOfBoundsException();
175
176
0
    assert(!xAxis || dynamic_cast<Axis*>(xAxis.get()));
177
178
0
    if( m_aAllAxis[ nDimensionIndex ].size() < o3tl::make_unsigned( nIndex+1 ))
179
0
    {
180
0
        m_aAllAxis[ nDimensionIndex ].resize( nIndex+1 );
181
0
        m_aAllAxis[ nDimensionIndex ][nIndex] = nullptr;
182
0
    }
183
184
0
    rtl::Reference< Axis > xOldAxis( m_aAllAxis[ nDimensionIndex ][nIndex] );
185
0
    if( xOldAxis.is())
186
0
        ModifyListenerHelper::removeListener( xOldAxis, m_xModifyEventForwarder );
187
0
    m_aAllAxis[ nDimensionIndex ][nIndex] = dynamic_cast<Axis*>(xAxis.get());
188
0
    if( xAxis.is())
189
0
        ModifyListenerHelper::addListener( xAxis, m_xModifyEventForwarder );
190
0
    fireModifyEvent();
191
0
}
192
193
void BaseCoordinateSystem::setAxisByDimension(
194
    sal_Int32 nDimensionIndex,
195
    const rtl::Reference< Axis >& xAxis,
196
    sal_Int32 nIndex )
197
0
{
198
0
    if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
199
0
        throw lang::IndexOutOfBoundsException();
200
201
0
    if( nIndex < 0 )
202
0
        throw lang::IndexOutOfBoundsException();
203
204
0
    if( m_aAllAxis[ nDimensionIndex ].size() < o3tl::make_unsigned( nIndex+1 ))
205
0
    {
206
0
        m_aAllAxis[ nDimensionIndex ].resize( nIndex+1 );
207
0
        m_aAllAxis[ nDimensionIndex ][nIndex] = nullptr;
208
0
    }
209
210
0
    rtl::Reference< Axis > xOldAxis( m_aAllAxis[ nDimensionIndex ][nIndex] );
211
0
    if( xOldAxis.is())
212
0
        ModifyListenerHelper::removeListener( xOldAxis, m_xModifyEventForwarder );
213
0
    m_aAllAxis[ nDimensionIndex ][nIndex] = xAxis;
214
0
    if( xAxis.is())
215
0
        ModifyListenerHelper::addListener( xAxis, m_xModifyEventForwarder );
216
0
    fireModifyEvent();
217
0
}
218
219
Reference< chart2::XAxis > SAL_CALL BaseCoordinateSystem::getAxisByDimension(
220
            sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
221
0
{
222
0
    if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
223
0
        throw lang::IndexOutOfBoundsException();
224
225
0
    OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( getDimension()));
226
227
0
    if( nAxisIndex < 0 || nAxisIndex > getMaximumAxisIndexByDimension(nDimensionIndex) )
228
0
        throw lang::IndexOutOfBoundsException();
229
230
0
    return m_aAllAxis[ nDimensionIndex ][nAxisIndex];
231
0
}
232
233
const rtl::Reference< Axis > & BaseCoordinateSystem::getAxisByDimension2(
234
            sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
235
0
{
236
0
    if( nDimensionIndex < 0 || nDimensionIndex >= m_nDimensionCount )
237
0
        throw lang::IndexOutOfBoundsException();
238
239
0
    OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( m_nDimensionCount));
240
241
0
    if( nAxisIndex < 0 || o3tl::make_unsigned(nAxisIndex) > m_aAllAxis[ nDimensionIndex ].size() )
242
0
        throw lang::IndexOutOfBoundsException();
243
244
0
    return m_aAllAxis[ nDimensionIndex ][nAxisIndex];
245
0
}
246
247
sal_Int32 SAL_CALL BaseCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex )
248
0
{
249
0
    if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
250
0
        throw lang::IndexOutOfBoundsException();
251
252
0
    OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( getDimension()));
253
254
0
    sal_Int32 nRet = m_aAllAxis[ nDimensionIndex ].size();
255
0
    if(nRet)
256
0
        nRet-=1;
257
258
0
    return nRet;
259
0
}
260
261
// ____ XChartTypeContainer ____
262
void SAL_CALL BaseCoordinateSystem::addChartType( const Reference< chart2::XChartType >& aChartType )
263
0
{
264
0
    auto pChartType = dynamic_cast<ChartType*>(aChartType.get());
265
0
    assert(pChartType);
266
267
0
    if( std::find( m_aChartTypes.begin(), m_aChartTypes.end(), pChartType )
268
0
        != m_aChartTypes.end())
269
0
        throw lang::IllegalArgumentException(u"type not found"_ustr, static_cast<cppu::OWeakObject*>(this), 1);
270
271
0
    m_aChartTypes.push_back( pChartType );
272
0
    ModifyListenerHelper::addListener( aChartType, m_xModifyEventForwarder );
273
0
    fireModifyEvent();
274
0
}
275
276
void SAL_CALL BaseCoordinateSystem::removeChartType( const Reference< chart2::XChartType >& aChartType )
277
0
{
278
0
    auto pChartType = dynamic_cast<ChartType*>(aChartType.get());
279
0
    assert(pChartType);
280
0
    auto aIt( std::find( m_aChartTypes.begin(), m_aChartTypes.end(), pChartType ));
281
0
    if( aIt == m_aChartTypes.end())
282
0
        throw container::NoSuchElementException(
283
0
            u"The given chart type is no element of the container"_ustr,
284
0
            static_cast< uno::XWeak * >( this ));
285
286
0
    m_aChartTypes.erase( aIt );
287
0
    ModifyListenerHelper::removeListener( aChartType, m_xModifyEventForwarder );
288
0
    fireModifyEvent();
289
0
}
290
291
Sequence< Reference< chart2::XChartType > > SAL_CALL BaseCoordinateSystem::getChartTypes()
292
0
{
293
0
    return comphelper::containerToSequence< Reference< chart2::XChartType > >( m_aChartTypes );
294
0
}
295
296
void SAL_CALL BaseCoordinateSystem::setChartTypes( const Sequence< Reference< chart2::XChartType > >& aChartTypes )
297
0
{
298
0
    for (auto const & aChartType : m_aChartTypes)
299
0
        aChartType->removeModifyListener( m_xModifyEventForwarder );
300
0
    m_aChartTypes.clear();
301
0
    for (auto const & aChartType : aChartTypes)
302
0
    {
303
0
        auto pChartType = dynamic_cast<ChartType*>(aChartType.get());
304
0
        assert(pChartType);
305
0
        m_aChartTypes.push_back(pChartType);
306
0
        pChartType->addModifyListener( m_xModifyEventForwarder );
307
0
    }
308
0
    fireModifyEvent();
309
0
}
310
311
void BaseCoordinateSystem::setChartTypes( const std::vector< rtl::Reference< ChartType > >& aChartTypes )
312
0
{
313
0
    for (auto const & aChartType : m_aChartTypes)
314
0
        aChartType->removeModifyListener( m_xModifyEventForwarder );
315
0
    m_aChartTypes = aChartTypes;
316
0
    for (auto const & aChartType : m_aChartTypes)
317
0
        aChartType->addModifyListener( m_xModifyEventForwarder );
318
0
    fireModifyEvent();
319
0
}
320
321
// ____ XModifyBroadcaster ____
322
void SAL_CALL BaseCoordinateSystem::addModifyListener( const Reference< util::XModifyListener >& aListener )
323
0
{
324
0
    m_xModifyEventForwarder->addModifyListener( aListener );
325
0
}
326
327
void SAL_CALL BaseCoordinateSystem::removeModifyListener( const Reference< util::XModifyListener >& aListener )
328
0
{
329
0
    m_xModifyEventForwarder->removeModifyListener( aListener );
330
0
}
331
332
// ____ XModifyListener ____
333
void SAL_CALL BaseCoordinateSystem::modified( const lang::EventObject& aEvent )
334
0
{
335
0
    m_xModifyEventForwarder->modified( aEvent );
336
0
}
337
338
// ____ XEventListener (base of XModifyListener) ____
339
void SAL_CALL BaseCoordinateSystem::disposing( const lang::EventObject& /* Source */ )
340
0
{
341
    // nothing
342
0
}
343
344
// ____ OPropertySet ____
345
void BaseCoordinateSystem::firePropertyChangeEvent()
346
0
{
347
0
    fireModifyEvent();
348
0
}
349
350
void BaseCoordinateSystem::fireModifyEvent()
351
0
{
352
0
    m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
353
0
}
354
355
// ____ OPropertySet ____
356
void BaseCoordinateSystem::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
357
0
{
358
0
    const tPropertyValueMap& rStaticDefaults = StaticCooSysDefaults();
359
0
    tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
360
0
    if( aFound == rStaticDefaults.end() )
361
0
        rAny.clear();
362
0
    else
363
0
        rAny = (*aFound).second;
364
0
}
365
366
// ____ OPropertySet ____
367
::cppu::IPropertyArrayHelper & SAL_CALL BaseCoordinateSystem::getInfoHelper()
368
0
{
369
0
    return StaticCooSysInfoHelper();
370
0
}
371
372
// ____ XPropertySet ____
373
Reference< beans::XPropertySetInfo > SAL_CALL BaseCoordinateSystem::getPropertySetInfo()
374
0
{
375
0
    static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
376
0
        ::cppu::OPropertySetHelper::createPropertySetInfo(StaticCooSysInfoHelper() ) );
377
0
    return xPropertySetInfo;
378
0
}
379
380
using impl::BaseCoordinateSystem_Base;
381
382
IMPLEMENT_FORWARD_XINTERFACE2( BaseCoordinateSystem, BaseCoordinateSystem_Base, ::property::OPropertySet )
383
IMPLEMENT_FORWARD_XTYPEPROVIDER2( BaseCoordinateSystem, BaseCoordinateSystem_Base, ::property::OPropertySet )
384
385
} //  namespace chart
386
387
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */