Avoid potential negative array index access to cached text.
[LibreOffice.git] / chart2 / source / controller / itemsetwrapper / ErrorBarItemConverter.cxx
blob33e09062a9a75ce8f7a99ccc005444113504fcf4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <ErrorBarItemConverter.hxx>
21 #include "SchWhichPairs.hxx"
22 #include <StatisticsHelper.hxx>
24 #include <GraphicPropertyItemConverter.hxx>
26 #include <svl/stritem.hxx>
27 #include <svx/chrtitem.hxx>
28 #include <rtl/math.hxx>
30 #include <com/sun/star/chart2/XInternalDataProvider.hpp>
31 #include <com/sun/star/chart2/XChartDocument.hpp>
32 #include <com/sun/star/chart/ErrorBarStyle.hpp>
33 #include <utility>
34 #include <comphelper/diagnose_ex.hxx>
36 using namespace ::com::sun::star;
38 namespace
41 void lcl_getErrorValues( const uno::Reference< beans::XPropertySet > & xErrorBarProp,
42 double & rOutPosError, double & rOutNegError )
44 if( ! xErrorBarProp.is())
45 return;
47 try
49 xErrorBarProp->getPropertyValue( "PositiveError" ) >>= rOutPosError;
50 xErrorBarProp->getPropertyValue( "NegativeError" ) >>= rOutNegError;
52 catch( const uno::Exception & )
54 DBG_UNHANDLED_EXCEPTION("chart2");
58 void lcl_getErrorIndicatorValues(
59 const uno::Reference< beans::XPropertySet > & xErrorBarProp,
60 bool & rOutShowPosError, bool & rOutShowNegError )
62 if( ! xErrorBarProp.is())
63 return;
65 try
67 xErrorBarProp->getPropertyValue( "ShowPositiveError" ) >>= rOutShowPosError;
68 xErrorBarProp->getPropertyValue( "ShowNegativeError" ) >>= rOutShowNegError;
70 catch( const uno::Exception & )
72 DBG_UNHANDLED_EXCEPTION("chart2");
76 } // anonymous namespace
78 namespace chart::wrapper
81 ErrorBarItemConverter::ErrorBarItemConverter(
82 uno::Reference< frame::XModel > xModel,
83 const uno::Reference< beans::XPropertySet > & rPropertySet,
84 SfxItemPool& rItemPool,
85 SdrModel& rDrawModel,
86 const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory ) :
87 ItemConverter( rPropertySet, rItemPool ),
88 m_spGraphicConverter( std::make_shared<GraphicPropertyItemConverter>(
89 rPropertySet, rItemPool, rDrawModel,
90 xNamedPropertyContainerFactory,
91 GraphicObjectType::LineProperties )),
92 m_xModel(std::move( xModel ))
95 ErrorBarItemConverter::~ErrorBarItemConverter()
98 void ErrorBarItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
100 m_spGraphicConverter->FillItemSet( rOutItemSet );
102 // own items
103 ItemConverter::FillItemSet( rOutItemSet );
106 bool ErrorBarItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
108 bool bResult = m_spGraphicConverter->ApplyItemSet( rItemSet );
110 // own items
111 return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
114 const WhichRangesContainer& ErrorBarItemConverter::GetWhichPairs() const
116 // must span all used items!
117 return nErrorBarWhichPairs;
120 bool ErrorBarItemConverter::GetItemProperty(
121 tWhichIdType /* nWhichId */,
122 tPropertyNameWithMemberId & /* rOutProperty */ ) const
124 return false;
127 bool ErrorBarItemConverter::ApplySpecialItem(
128 sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
130 bool bChanged = false;
132 switch( nWhichId )
134 // Attention !!! This case must be passed before SCHATTR_STAT_PERCENT,
135 // SCHATTR_STAT_BIGERROR, SCHATTR_STAT_CONSTPLUS,
136 // SCHATTR_STAT_CONSTMINUS and SCHATTR_STAT_INDICATE
137 case SCHATTR_STAT_KIND_ERROR:
139 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
141 SvxChartKindError eErrorKind =
142 static_cast< const SvxChartKindErrorItem & >(
143 rItemSet.Get( nWhichId )).GetValue();
145 if( !xErrorBarProp.is() && eErrorKind == SvxChartKindError::NONE)
147 //nothing to do
149 else
151 sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
153 switch( eErrorKind )
155 case SvxChartKindError::NONE:
156 nStyle = css::chart::ErrorBarStyle::NONE; break;
157 case SvxChartKindError::Variant:
158 nStyle = css::chart::ErrorBarStyle::VARIANCE; break;
159 case SvxChartKindError::Sigma:
160 nStyle = css::chart::ErrorBarStyle::STANDARD_DEVIATION; break;
161 case SvxChartKindError::Percent:
162 nStyle = css::chart::ErrorBarStyle::RELATIVE; break;
163 case SvxChartKindError::BigError:
164 nStyle = css::chart::ErrorBarStyle::ERROR_MARGIN; break;
165 case SvxChartKindError::Const:
166 nStyle = css::chart::ErrorBarStyle::ABSOLUTE; break;
167 case SvxChartKindError::StdError:
168 nStyle = css::chart::ErrorBarStyle::STANDARD_ERROR; break;
169 case SvxChartKindError::Range:
170 nStyle = css::chart::ErrorBarStyle::FROM_DATA; break;
173 xErrorBarProp->setPropertyValue( "ErrorBarStyle" , uno::Any( nStyle ));
174 bChanged = true;
177 break;
179 case SCHATTR_STAT_PERCENT:
180 case SCHATTR_STAT_BIGERROR:
182 OSL_FAIL( "Deprecated item" );
183 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
185 double fValue =
186 static_cast< const SvxDoubleItem & >(
187 rItemSet.Get( nWhichId )).GetValue();
188 double fPos(0.0), fNeg(0.0);
189 lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
191 if( ! ( ::rtl::math::approxEqual( fPos, fValue ) &&
192 ::rtl::math::approxEqual( fNeg, fValue )))
194 xErrorBarProp->setPropertyValue( "PositiveError" , uno::Any( fValue ));
195 xErrorBarProp->setPropertyValue( "NegativeError" , uno::Any( fValue ));
196 bChanged = true;
199 break;
201 case SCHATTR_STAT_CONSTPLUS:
203 double fValue =
204 static_cast< const SvxDoubleItem & >(
205 rItemSet.Get( nWhichId )).GetValue();
206 double fPos(0.0), fNeg(0.0);
207 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
209 if( ! ::rtl::math::approxEqual( fPos, fValue ))
211 GetPropertySet()->setPropertyValue( "PositiveError" , uno::Any( fValue ));
212 bChanged = true;
215 break;
217 case SCHATTR_STAT_CONSTMINUS:
219 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
221 double fValue =
222 static_cast< const SvxDoubleItem & >(
223 rItemSet.Get( nWhichId )).GetValue();
224 double fPos(0.0), fNeg(0.0);
225 lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
227 if( ! ::rtl::math::approxEqual( fNeg, fValue ))
229 xErrorBarProp->setPropertyValue( "NegativeError" , uno::Any( fValue ));
230 bChanged = true;
233 break;
235 case SCHATTR_STAT_INDICATE:
237 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
239 SvxChartIndicate eIndicate =
240 static_cast< const SvxChartIndicateItem & >(
241 rItemSet.Get( nWhichId )).GetValue();
243 bool bNewIndPos = (eIndicate == SvxChartIndicate::Both || eIndicate == SvxChartIndicate::Up );
244 bool bNewIndNeg = (eIndicate == SvxChartIndicate::Both || eIndicate == SvxChartIndicate::Down );
246 bool bShowPos(false), bShowNeg(false);
247 lcl_getErrorIndicatorValues( xErrorBarProp, bShowPos, bShowNeg );
249 if( bShowPos != bNewIndPos ||
250 bShowNeg != bNewIndNeg )
252 xErrorBarProp->setPropertyValue( "ShowPositiveError" , uno::Any( bNewIndPos ));
253 xErrorBarProp->setPropertyValue( "ShowNegativeError" , uno::Any( bNewIndNeg ));
254 bChanged = true;
257 break;
259 case SCHATTR_STAT_RANGE_POS:
260 case SCHATTR_STAT_RANGE_NEG:
262 // @todo: also be able to deal with x-error bars
263 const bool bYError =
264 rItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
266 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
267 uno::Reference< chart2::XChartDocument > xChartDoc( m_xModel, uno::UNO_QUERY );
268 uno::Reference< chart2::data::XDataProvider > xDataProvider;
270 if( xChartDoc.is())
271 xDataProvider.set( xChartDoc->getDataProvider());
272 if( xErrorBarSource.is() && xDataProvider.is())
274 OUString aNewRange( static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue());
275 bool bApplyNewRange = false;
277 bool bIsPositiveValue( nWhichId == SCHATTR_STAT_RANGE_POS );
278 if( xChartDoc->hasInternalDataProvider())
280 if( !aNewRange.isEmpty())
282 uno::Reference< chart2::data::XDataSequence > xSeq(
283 StatisticsHelper::getErrorDataSequenceFromDataSource(
284 xErrorBarSource, bIsPositiveValue, bYError ));
285 if( ! xSeq.is())
287 // no data range for error bars yet => create
288 uno::Reference< chart2::XInternalDataProvider > xIntDataProvider( xDataProvider, uno::UNO_QUERY );
289 OSL_ASSERT( xIntDataProvider.is());
290 if( xIntDataProvider.is())
292 xIntDataProvider->appendSequence();
293 aNewRange = "last";
294 bApplyNewRange = true;
299 else
301 uno::Reference< chart2::data::XDataSequence > xSeq(
302 StatisticsHelper::getErrorDataSequenceFromDataSource(
303 xErrorBarSource, bIsPositiveValue, bYError ));
304 bApplyNewRange =
305 ! ( xSeq.is() && (aNewRange == xSeq->getSourceRangeRepresentation()));
308 if( bApplyNewRange )
309 StatisticsHelper::setErrorDataSequence(
310 xErrorBarSource, xDataProvider, aNewRange, bIsPositiveValue, bYError );
313 break;
316 return bChanged;
319 void ErrorBarItemConverter::FillSpecialItem(
320 sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
322 switch( nWhichId )
324 case SCHATTR_STAT_KIND_ERROR:
326 SvxChartKindError eErrorKind = SvxChartKindError::NONE;
327 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
329 sal_Int32 nStyle = 0;
330 if( xErrorBarProp->getPropertyValue( "ErrorBarStyle" ) >>= nStyle )
332 switch( nStyle )
334 case css::chart::ErrorBarStyle::NONE:
335 break;
336 case css::chart::ErrorBarStyle::VARIANCE:
337 eErrorKind = SvxChartKindError::Variant; break;
338 case css::chart::ErrorBarStyle::STANDARD_DEVIATION:
339 eErrorKind = SvxChartKindError::Sigma; break;
340 case css::chart::ErrorBarStyle::ABSOLUTE:
341 eErrorKind = SvxChartKindError::Const; break;
342 case css::chart::ErrorBarStyle::RELATIVE:
343 eErrorKind = SvxChartKindError::Percent; break;
344 case css::chart::ErrorBarStyle::ERROR_MARGIN:
345 eErrorKind = SvxChartKindError::BigError; break;
346 case css::chart::ErrorBarStyle::STANDARD_ERROR:
347 eErrorKind = SvxChartKindError::StdError; break;
348 case css::chart::ErrorBarStyle::FROM_DATA:
349 eErrorKind = SvxChartKindError::Range; break;
352 rOutItemSet.Put( SvxChartKindErrorItem( eErrorKind, SCHATTR_STAT_KIND_ERROR ));
354 break;
356 case SCHATTR_STAT_PERCENT:
358 double fPos(0.0), fNeg(0.0);
359 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
360 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, SCHATTR_STAT_PERCENT ));
362 break;
364 case SCHATTR_STAT_BIGERROR:
366 double fPos(0.0), fNeg(0.0);
367 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
368 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, SCHATTR_STAT_BIGERROR ));
370 break;
372 case SCHATTR_STAT_CONSTPLUS:
374 double fPos(0.0), fNeg(0.0);
375 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
376 rOutItemSet.Put( SvxDoubleItem( fPos, SCHATTR_STAT_CONSTPLUS ));
378 break;
380 case SCHATTR_STAT_CONSTMINUS:
382 double fPos(0.0), fNeg(0.0);
383 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
384 rOutItemSet.Put( SvxDoubleItem( fNeg, SCHATTR_STAT_CONSTMINUS ));
386 break;
388 case SCHATTR_STAT_INDICATE:
390 SvxChartIndicate eIndicate = SvxChartIndicate::Both;
391 bool bShowPos(false), bShowNeg(false);
392 lcl_getErrorIndicatorValues( GetPropertySet(), bShowPos, bShowNeg );
394 if( bShowPos )
396 if( bShowNeg )
397 eIndicate = SvxChartIndicate::Both;
398 else
399 eIndicate = SvxChartIndicate::Up;
401 else
403 if( bShowNeg )
404 eIndicate = SvxChartIndicate::Down;
405 else
406 eIndicate = SvxChartIndicate::NONE;
408 rOutItemSet.Put( SvxChartIndicateItem( eIndicate, SCHATTR_STAT_INDICATE ));
410 break;
412 case SCHATTR_STAT_RANGE_POS:
413 case SCHATTR_STAT_RANGE_NEG:
415 const bool bYError =
416 rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
418 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
419 if( xErrorBarSource.is())
421 uno::Reference< chart2::data::XDataSequence > xSeq(
422 StatisticsHelper::getErrorDataSequenceFromDataSource(
423 xErrorBarSource, (nWhichId == SCHATTR_STAT_RANGE_POS), bYError ));
424 if( xSeq.is())
425 rOutItemSet.Put( SfxStringItem( nWhichId, xSeq->getSourceRangeRepresentation()));
428 break;
432 } // namespace chart::wrapper
434 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */