Avoid potential negative array index access to cached text.
[LibreOffice.git] / chart2 / source / tools / ErrorBar.cxx
blob3d049a44527f5f03565a97d18373688599276eb7
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 <ErrorBar.hxx>
21 #include <EventListenerHelper.hxx>
22 #include <CloneHelper.hxx>
23 #include <ModifyListenerHelper.hxx>
25 #include <comphelper/sequence.hxx>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <svl/itemprop.hxx>
28 #include <vcl/svapp.hxx>
30 #include <com/sun/star/chart/ErrorBarStyle.hpp>
32 #include <com/sun/star/drawing/LineStyle.hpp>
33 #include <com/sun/star/util/Color.hpp>
34 #include <com/sun/star/drawing/LineJoint.hpp>
36 #include <comphelper/diagnose_ex.hxx>
37 #include <sal/log.hxx>
39 using namespace ::com::sun::star;
41 namespace
44 constexpr OUString lcl_aServiceName = u"com.sun.star.comp.chart2.ErrorBar"_ustr;
46 bool lcl_isInternalData( const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq )
48 uno::Reference< lang::XServiceInfo > xServiceInfo( xLSeq, uno::UNO_QUERY );
49 return ( xServiceInfo.is() && xServiceInfo->getImplementationName() == "com.sun.star.comp.chart2.LabeledDataSequence" );
52 const SfxItemPropertySet* GetErrorBarPropertySet()
54 static const SfxItemPropertyMapEntry aErrorBarPropertyMap_Impl[] =
56 {u"ShowPositiveError"_ustr,0,cppu::UnoType<bool>::get(), 0, 0},
57 {u"ShowNegativeError"_ustr,1,cppu::UnoType<bool>::get(), 0, 0},
58 {u"PositiveError"_ustr,2,cppu::UnoType<double>::get(),0,0},
59 {u"NegativeError"_ustr,3,cppu::UnoType<double>::get(), 0, 0},
60 {u"PercentageError"_ustr,4,cppu::UnoType<double>::get(), 0, 0},
61 {u"ErrorBarStyle"_ustr,5,cppu::UnoType<sal_Int32>::get(),0,0},
62 {u"ErrorBarRangePositive"_ustr,6,cppu::UnoType<OUString>::get(),0,0}, // read-only for export
63 {u"ErrorBarRangeNegative"_ustr,7,cppu::UnoType<OUString>::get(),0,0}, // read-only for export
64 {u"Weight"_ustr,8,cppu::UnoType<double>::get(),0,0},
65 {u"LineStyle"_ustr,9,cppu::UnoType<css::drawing::LineStyle>::get(),0,0},
66 {u"LineDash"_ustr,10,cppu::UnoType<drawing::LineDash>::get(),0,0},
67 {u"LineWidth"_ustr,11,cppu::UnoType<sal_Int32>::get(),0,0},
68 {u"LineColor"_ustr,12,cppu::UnoType<css::util::Color>::get(),0,0},
69 {u"LineTransparence"_ustr,13,cppu::UnoType<sal_Int16>::get(),0,0},
70 {u"LineJoint"_ustr,14,cppu::UnoType<css::drawing::LineJoint>::get(),0,0},
72 static SfxItemPropertySet aPropSet( aErrorBarPropertyMap_Impl );
73 return &aPropSet;
76 } // anonymous namespace
78 namespace chart
81 ErrorBar::ErrorBar() :
82 mnLineWidth(0),
83 meLineStyle(drawing::LineStyle_SOLID),
84 maLineColor(0),
85 mnLineTransparence(0),
86 meLineJoint(drawing::LineJoint_ROUND),
87 mbShowPositiveError(true),
88 mbShowNegativeError(true),
89 mfPositiveError(0),
90 mfNegativeError(0),
91 mfWeight(1),
92 meStyle(css::chart::ErrorBarStyle::NONE),
93 m_xModifyEventForwarder( new ModifyEventForwarder() )
96 ErrorBar::ErrorBar( const ErrorBar & rOther ) :
97 impl::ErrorBar_Base(rOther),
98 maDashName(rOther.maDashName),
99 maLineDash(rOther.maLineDash),
100 mnLineWidth(rOther.mnLineWidth),
101 meLineStyle(rOther.meLineStyle),
102 maLineColor(rOther.maLineColor),
103 mnLineTransparence(rOther.mnLineTransparence),
104 meLineJoint(rOther.meLineJoint),
105 mbShowPositiveError(rOther.mbShowPositiveError),
106 mbShowNegativeError(rOther.mbShowNegativeError),
107 mfPositiveError(rOther.mfPositiveError),
108 mfNegativeError(rOther.mfNegativeError),
109 mfWeight(rOther.mfWeight),
110 meStyle(rOther.meStyle),
111 m_xModifyEventForwarder( new ModifyEventForwarder() )
113 if( ! rOther.m_aDataSequences.empty())
115 if( lcl_isInternalData( rOther.m_aDataSequences.front()))
116 CloneHelper::CloneRefVector< css::chart2::data::XLabeledDataSequence >(
117 rOther.m_aDataSequences, m_aDataSequences );
118 else
119 m_aDataSequences = rOther.m_aDataSequences;
120 ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder );
124 ErrorBar::~ErrorBar()
127 uno::Reference< util::XCloneable > SAL_CALL ErrorBar::createClone()
129 return uno::Reference< util::XCloneable >( new ErrorBar( *this ));
132 // ____ XPropertySet ____
133 uno::Reference< beans::XPropertySetInfo > SAL_CALL ErrorBar::getPropertySetInfo()
135 static uno::Reference< beans::XPropertySetInfo > aRef (
136 new SfxItemPropertySetInfo( GetErrorBarPropertySet()->getPropertyMap() ) );
137 return aRef;
140 void ErrorBar::setPropertyValue( const OUString& rPropName, const uno::Any& rAny )
142 SolarMutexGuard aGuard;
144 if(rPropName == "ErrorBarStyle")
145 rAny >>= meStyle;
146 else if(rPropName == "PositiveError")
147 rAny >>= mfPositiveError;
148 else if(rPropName == "PercentageError")
150 rAny >>= mfPositiveError;
151 rAny >>= mfNegativeError;
153 else if(rPropName == "Weight")
155 rAny >>= mfWeight;
157 else if(rPropName == "NegativeError")
158 rAny >>= mfNegativeError;
159 else if(rPropName == "ShowPositiveError")
160 rAny >>= mbShowPositiveError;
161 else if(rPropName == "ShowNegativeError")
162 rAny >>= mbShowNegativeError;
163 else if(rPropName == "ErrorBarRangePositive" || rPropName == "ErrorBarRangeNegative")
164 throw beans::UnknownPropertyException("read-only property", static_cast< uno::XWeak*>(this));
165 else if(rPropName == "LineDashName")
166 rAny >>= maDashName;
167 else if(rPropName == "LineDash")
168 rAny >>= maLineDash;
169 else if(rPropName == "LineWidth")
170 rAny >>= mnLineWidth;
171 else if(rPropName == "LineStyle")
172 rAny >>= meLineStyle;
173 else if(rPropName == "LineColor")
174 rAny >>= maLineColor;
175 else if(rPropName == "LineTransparence")
176 rAny >>= mnLineTransparence;
177 else if(rPropName == "LineJoint")
178 rAny >>= meLineJoint;
180 m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
183 namespace {
185 OUString getSourceRangeStrFromLabeledSequences( const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > >& aSequences, bool bPositive )
187 OUString aDirection;
188 if(bPositive)
189 aDirection = "positive";
190 else
191 aDirection = "negative";
193 for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledData : aSequences )
197 if( labeledData.is())
199 uno::Reference< chart2::data::XDataSequence > xSequence( labeledData->getValues());
200 uno::Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
201 OUString aRole;
202 if( ( xSeqProp->getPropertyValue( "Role" ) >>= aRole ) &&
203 aRole.match( "error-bars" ) && aRole.indexOf(aDirection) >= 0 )
205 return xSequence->getSourceRangeRepresentation();
209 catch (uno::Exception const &)
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 TOOLS_WARN_EXCEPTION("chart2", "unexpected exception");
215 catch (...)
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 SAL_WARN("chart2", "unexpected exception! ");
223 return OUString();
228 uno::Any ErrorBar::getPropertyValue(const OUString& rPropName)
230 SolarMutexGuard aGuard;
232 uno::Any aRet;
233 if(rPropName == "ErrorBarStyle")
234 aRet <<= meStyle;
235 else if(rPropName == "PositiveError")
236 aRet <<= mfPositiveError;
237 else if(rPropName == "NegativeError")
238 aRet <<= mfNegativeError;
239 else if(rPropName == "PercentageError")
240 aRet <<= mfPositiveError;
241 else if(rPropName == "ShowPositiveError")
242 aRet <<= mbShowPositiveError;
243 else if(rPropName == "ShowNegativeError")
244 aRet <<= mbShowNegativeError;
245 else if(rPropName == "Weight")
246 aRet <<= mfWeight;
247 else if(rPropName == "ErrorBarRangePositive")
249 OUString aRange;
250 if(meStyle == css::chart::ErrorBarStyle::FROM_DATA)
252 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences =
253 getDataSequences();
255 aRange = getSourceRangeStrFromLabeledSequences( aSequences, true );
258 aRet <<= aRange;
260 else if(rPropName == "ErrorBarRangeNegative")
262 OUString aRange;
263 if(meStyle == css::chart::ErrorBarStyle::FROM_DATA)
265 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences =
266 getDataSequences();
268 aRange = getSourceRangeStrFromLabeledSequences( aSequences, false );
271 aRet <<= aRange;
273 else if(rPropName == "LineDashName")
274 aRet <<= maDashName;
275 else if(rPropName == "LineDash")
276 aRet <<= maLineDash;
277 else if(rPropName == "LineWidth")
278 aRet <<= mnLineWidth;
279 else if(rPropName == "LineStyle")
280 aRet <<= meLineStyle;
281 else if(rPropName == "LineColor")
282 aRet <<= maLineColor;
283 else if(rPropName == "LineTransparence")
284 aRet <<= mnLineTransparence;
285 else if(rPropName == "LineJoint")
286 aRet <<= meLineJoint;
288 SAL_WARN_IF(!aRet.hasValue(), "chart2", "asked for property value: " << rPropName);
289 return aRet;
292 beans::PropertyState ErrorBar::getPropertyState( const OUString& rPropName )
294 if(rPropName == "ErrorBarStyle")
296 if(meStyle == css::chart::ErrorBarStyle::NONE)
297 return beans::PropertyState_DEFAULT_VALUE;
298 return beans::PropertyState_DIRECT_VALUE;
300 else if(rPropName == "PositiveError")
302 if(mbShowPositiveError)
304 switch(meStyle)
306 case css::chart::ErrorBarStyle::ABSOLUTE:
307 case css::chart::ErrorBarStyle::ERROR_MARGIN:
308 return beans::PropertyState_DIRECT_VALUE;
309 default:
310 break;
313 return beans::PropertyState_DEFAULT_VALUE;
315 else if(rPropName == "NegativeError")
317 if(mbShowNegativeError)
319 switch(meStyle)
321 case css::chart::ErrorBarStyle::ABSOLUTE:
322 case css::chart::ErrorBarStyle::ERROR_MARGIN:
323 return beans::PropertyState_DIRECT_VALUE;
324 default:
325 break;
328 return beans::PropertyState_DEFAULT_VALUE;
330 else if(rPropName == "PercentageError")
332 if(meStyle != css::chart::ErrorBarStyle::RELATIVE)
333 return beans::PropertyState_DEFAULT_VALUE;
334 return beans::PropertyState_DIRECT_VALUE;
336 else if(rPropName == "ShowPositiveError")
338 // this value should be never default
339 return beans::PropertyState_DIRECT_VALUE;
341 else if(rPropName == "ShowNegativeError")
343 // this value should be never default
344 return beans::PropertyState_DIRECT_VALUE;
346 else if(rPropName == "ErrorBarRangePositive")
348 if(meStyle == css::chart::ErrorBarStyle::FROM_DATA && mbShowPositiveError)
349 return beans::PropertyState_DIRECT_VALUE;
350 return beans::PropertyState_DEFAULT_VALUE;
352 else if(rPropName == "ErrorBarRangeNegative")
354 if(meStyle == css::chart::ErrorBarStyle::FROM_DATA && mbShowNegativeError)
355 return beans::PropertyState_DIRECT_VALUE;
356 return beans::PropertyState_DEFAULT_VALUE;
358 else
359 return beans::PropertyState_DIRECT_VALUE;
362 uno::Sequence< beans::PropertyState > ErrorBar::getPropertyStates( const uno::Sequence< OUString >& rPropNames )
364 uno::Sequence< beans::PropertyState > aRet( rPropNames.getLength() );
365 auto aRetRange = asNonConstRange(aRet);
366 for(sal_Int32 i = 0; i < rPropNames.getLength(); ++i)
368 aRetRange[i] = getPropertyState(rPropNames[i]);
370 return aRet;
373 void ErrorBar::setPropertyToDefault( const OUString& )
375 //keep them unimplemented for now
378 uno::Any ErrorBar::getPropertyDefault( const OUString& )
380 //keep them unimplemented for now
381 return uno::Any();
384 void ErrorBar::addPropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& )
388 void ErrorBar::removePropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& )
392 void ErrorBar::addVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& )
396 void ErrorBar::removeVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& )
400 // ____ XModifyBroadcaster ____
401 void SAL_CALL ErrorBar::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
403 m_xModifyEventForwarder->addModifyListener( aListener );
406 void SAL_CALL ErrorBar::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
408 m_xModifyEventForwarder->removeModifyListener( aListener );
411 // ____ XModifyListener ____
412 void SAL_CALL ErrorBar::modified( const lang::EventObject& aEvent )
414 m_xModifyEventForwarder->modified( aEvent );
417 // ____ XEventListener (base of XModifyListener) ____
418 void SAL_CALL ErrorBar::disposing( const lang::EventObject& /* Source */ )
420 // nothing
423 // ____ XDataSink ____
424 void SAL_CALL ErrorBar::setData( const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > >& aData )
426 ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences, m_xModifyEventForwarder );
427 EventListenerHelper::removeListenerFromAllElements( m_aDataSequences, this );
428 m_aDataSequences = comphelper::sequenceToContainer<tDataSequenceContainer>( aData );
429 EventListenerHelper::addListenerToAllElements( m_aDataSequences, this );
430 ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder );
433 // ____ XDataSource ____
434 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > SAL_CALL ErrorBar::getDataSequences()
436 return comphelper::containerToSequence( m_aDataSequences );
439 OUString SAL_CALL ErrorBar::getImplementationName()
441 return lcl_aServiceName;
444 sal_Bool SAL_CALL ErrorBar::supportsService( const OUString& rServiceName )
446 return cppu::supportsService(this, rServiceName);
449 css::uno::Sequence< OUString > SAL_CALL ErrorBar::getSupportedServiceNames()
451 return {
452 lcl_aServiceName,
453 "com.sun.star.chart2.ErrorBar"
457 // needed by MSC compiler
458 using impl::ErrorBar_Base;
460 } // namespace chart
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 &)
466 return cppu::acquire(new ::chart::ErrorBar);
469 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */