1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "ErrorBarItemConverter.hxx"
27 #include "SchWhichPairs.hxx"
28 #include "macros.hxx"
29 #include "ItemPropertyMap.hxx"
30 #include "ErrorBar.hxx"
31 #include "PropertyHelper.hxx"
32 #include "ChartModelHelper.hxx"
33 #include "ChartTypeHelper.hxx"
34 #include "StatisticsHelper.hxx"
35
36 #include "GraphicPropertyItemConverter.hxx"
37
38 #include <svl/stritem.hxx>
39 #include <svx/chrtitem.hxx>
40 #include <svl/intitem.hxx>
41 #include <rtl/math.hxx>
42
43 #include <com/sun/star/chart2/DataPointLabel.hpp>
44 #include <com/sun/star/chart2/XInternalDataProvider.hpp>
45 #include <com/sun/star/chart/ErrorBarStyle.hpp>
46 #include <com/sun/star/lang/XServiceName.hpp>
47
48 #include <functional>
49 #include <algorithm>
50 #include <vector>
51
52 using namespace ::com::sun::star;
53
54 namespace
55 {
56
lcl_getErrorValues(const uno::Reference<beans::XPropertySet> & xErrorBarProp,double & rOutPosError,double & rOutNegError)57 void lcl_getErrorValues( const uno::Reference< beans::XPropertySet > & xErrorBarProp,
58 double & rOutPosError, double & rOutNegError )
59 {
60 if( ! xErrorBarProp.is())
61 return;
62
63 try
64 {
65 xErrorBarProp->getPropertyValue( C2U( "PositiveError" )) >>= rOutPosError;
66 xErrorBarProp->getPropertyValue( C2U( "NegativeError" )) >>= rOutNegError;
67 }
68 catch( uno::Exception & ex )
69 {
70 ASSERT_EXCEPTION( ex );
71 }
72 }
73
lcl_getErrorIndicatorValues(const uno::Reference<beans::XPropertySet> & xErrorBarProp,bool & rOutShowPosError,bool & rOutShowNegError)74 void lcl_getErrorIndicatorValues(
75 const uno::Reference< beans::XPropertySet > & xErrorBarProp,
76 bool & rOutShowPosError, bool & rOutShowNegError )
77 {
78 if( ! xErrorBarProp.is())
79 return;
80
81 try
82 {
83 xErrorBarProp->getPropertyValue( C2U( "ShowPositiveError" )) >>= rOutShowPosError;
84 xErrorBarProp->getPropertyValue( C2U( "ShowNegativeError" )) >>= rOutShowNegError;
85 }
86 catch( uno::Exception & ex )
87 {
88 ASSERT_EXCEPTION( ex );
89 }
90 }
91
92 } // anonymous namespace
93
94 namespace chart
95 {
96 namespace wrapper
97 {
98
ErrorBarItemConverter(const uno::Reference<frame::XModel> & xModel,const uno::Reference<beans::XPropertySet> & rPropertySet,SfxItemPool & rItemPool,SdrModel & rDrawModel,const uno::Reference<lang::XMultiServiceFactory> & xNamedPropertyContainerFactory)99 ErrorBarItemConverter::ErrorBarItemConverter(
100 const uno::Reference< frame::XModel > & xModel,
101 const uno::Reference< beans::XPropertySet > & rPropertySet,
102 SfxItemPool& rItemPool,
103 SdrModel& rDrawModel,
104 const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory ) :
105 ItemConverter( rPropertySet, rItemPool ),
106 m_spGraphicConverter( new GraphicPropertyItemConverter(
107 rPropertySet, rItemPool, rDrawModel,
108 xNamedPropertyContainerFactory,
109 GraphicPropertyItemConverter::LINE_PROPERTIES )),
110 m_xModel( xModel )
111 {}
112
~ErrorBarItemConverter()113 ErrorBarItemConverter::~ErrorBarItemConverter()
114 {}
115
FillItemSet(SfxItemSet & rOutItemSet) const116 void ErrorBarItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
117 {
118 m_spGraphicConverter->FillItemSet( rOutItemSet );
119
120 // own items
121 ItemConverter::FillItemSet( rOutItemSet );
122 }
123
ApplyItemSet(const SfxItemSet & rItemSet)124 bool ErrorBarItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
125 {
126 bool bResult = m_spGraphicConverter->ApplyItemSet( rItemSet );
127
128 // own items
129 return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
130 }
131
GetWhichPairs() const132 const sal_uInt16 * ErrorBarItemConverter::GetWhichPairs() const
133 {
134 // must span all used items!
135 return nErrorBarWhichPairs;
136 }
137
GetItemProperty(tWhichIdType,tPropertyNameWithMemberId &) const138 bool ErrorBarItemConverter::GetItemProperty(
139 tWhichIdType /* nWhichId */,
140 tPropertyNameWithMemberId & /* rOutProperty */ ) const
141 {
142 return false;
143 }
144
ApplySpecialItem(sal_uInt16 nWhichId,const SfxItemSet & rItemSet)145 bool ErrorBarItemConverter::ApplySpecialItem(
146 sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
147 throw( uno::Exception )
148 {
149 bool bChanged = false;
150 uno::Any aValue;
151
152 switch( nWhichId )
153 {
154 // Attention !!! This case must be passed before SCHATTR_STAT_PERCENT,
155 // SCHATTR_STAT_BIGERROR, SCHATTR_STAT_CONSTPLUS,
156 // SCHATTR_STAT_CONSTMINUS and SCHATTR_STAT_INDICATE
157 case SCHATTR_STAT_KIND_ERROR:
158 {
159 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
160
161 SvxChartKindError eErrorKind =
162 static_cast< const SvxChartKindErrorItem & >(
163 rItemSet.Get( nWhichId )).GetValue();
164
165 if( !xErrorBarProp.is() && eErrorKind == CHERROR_NONE)
166 {
167 //nothing to do
168 }
169 else
170 {
171 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
172
173 switch( eErrorKind )
174 {
175 case CHERROR_NONE:
176 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; break;
177 case CHERROR_VARIANT:
178 nStyle = ::com::sun::star::chart::ErrorBarStyle::VARIANCE; break;
179 case CHERROR_SIGMA:
180 nStyle = ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION; break;
181 case CHERROR_PERCENT:
182 nStyle = ::com::sun::star::chart::ErrorBarStyle::RELATIVE; break;
183 case CHERROR_BIGERROR:
184 nStyle = ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN; break;
185 case CHERROR_CONST:
186 nStyle = ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE; break;
187 case CHERROR_STDERROR:
188 nStyle = ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR; break;
189 case CHERROR_RANGE:
190 nStyle = ::com::sun::star::chart::ErrorBarStyle::FROM_DATA; break;
191 }
192
193 xErrorBarProp->setPropertyValue( C2U( "ErrorBarStyle" ),
194 uno::makeAny( nStyle ));
195 bChanged = true;
196 }
197 }
198 break;
199
200 case SCHATTR_STAT_PERCENT:
201 case SCHATTR_STAT_BIGERROR:
202 {
203 OSL_ENSURE( false, "Deprectaed item" );
204 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
205
206 double fValue =
207 static_cast< const SvxDoubleItem & >(
208 rItemSet.Get( nWhichId )).GetValue();
209 double fPos, fNeg;
210 lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
211
212 if( ! ( ::rtl::math::approxEqual( fPos, fValue ) &&
213 ::rtl::math::approxEqual( fNeg, fValue )))
214 {
215 xErrorBarProp->setPropertyValue( C2U( "PositiveError" ),
216 uno::makeAny( fValue ));
217 xErrorBarProp->setPropertyValue( C2U( "NegativeError" ),
218 uno::makeAny( fValue ));
219 bChanged = true;
220 }
221 }
222 break;
223
224 case SCHATTR_STAT_CONSTPLUS:
225 {
226 double fValue =
227 static_cast< const SvxDoubleItem & >(
228 rItemSet.Get( nWhichId )).GetValue();
229 double fPos, fNeg;
230 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
231
232 if( ! ::rtl::math::approxEqual( fPos, fValue ))
233 {
234 GetPropertySet()->setPropertyValue( C2U( "PositiveError" ), uno::makeAny( fValue ));
235 bChanged = true;
236 }
237 }
238 break;
239
240 case SCHATTR_STAT_CONSTMINUS:
241 {
242 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
243
244 double fValue =
245 static_cast< const SvxDoubleItem & >(
246 rItemSet.Get( nWhichId )).GetValue();
247 double fPos, fNeg;
248 lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
249
250 if( ! ::rtl::math::approxEqual( fNeg, fValue ))
251 {
252 xErrorBarProp->setPropertyValue( C2U( "NegativeError" ), uno::makeAny( fValue ));
253 bChanged = true;
254 }
255 }
256 break;
257
258 case SCHATTR_STAT_INDICATE:
259 {
260 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
261
262 SvxChartIndicate eIndicate =
263 static_cast< const SvxChartIndicateItem & >(
264 rItemSet.Get( nWhichId )).GetValue();
265
266 bool bNewIndPos = (eIndicate == CHINDICATE_BOTH || eIndicate == CHINDICATE_UP );
267 bool bNewIndNeg = (eIndicate == CHINDICATE_BOTH || eIndicate == CHINDICATE_DOWN );
268
269 bool bShowPos, bShowNeg;
270 lcl_getErrorIndicatorValues( xErrorBarProp, bShowPos, bShowNeg );
271
272 if( ( bShowPos != bNewIndPos ||
273 bShowNeg != bNewIndNeg ))
274 {
275 xErrorBarProp->setPropertyValue( C2U( "ShowPositiveError" ), uno::makeAny( bNewIndPos ));
276 xErrorBarProp->setPropertyValue( C2U( "ShowNegativeError" ), uno::makeAny( bNewIndNeg ));
277 bChanged = true;
278 }
279 }
280 break;
281
282 case SCHATTR_STAT_RANGE_POS:
283 case SCHATTR_STAT_RANGE_NEG:
284 {
285 // @todo: also be able to deal with x-error bars
286 const bool bYError = true;
287 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
288 uno::Reference< chart2::XChartDocument > xChartDoc( m_xModel, uno::UNO_QUERY );
289 uno::Reference< chart2::data::XDataProvider > xDataProvider;
290
291 if( xChartDoc.is())
292 xDataProvider.set( xChartDoc->getDataProvider());
293 if( xErrorBarSource.is() && xDataProvider.is())
294 {
295 ::rtl::OUString aNewRange( static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue());
296 bool bApplyNewRange = false;
297
298 bool bIsPositiveValue( nWhichId == SCHATTR_STAT_RANGE_POS );
299 if( xChartDoc->hasInternalDataProvider())
300 {
301 if( !aNewRange.isEmpty() )
302 {
303 uno::Reference< chart2::data::XDataSequence > xSeq(
304 StatisticsHelper::getErrorDataSequenceFromDataSource(
305 xErrorBarSource, bIsPositiveValue, bYError ));
306 if( ! xSeq.is())
307 {
308 // no data range for error bars yet => create
309 uno::Reference< chart2::XInternalDataProvider > xIntDataProvider( xDataProvider, uno::UNO_QUERY );
310 OSL_ASSERT( xIntDataProvider.is());
311 if( xIntDataProvider.is())
312 {
313 xIntDataProvider->appendSequence();
314 aNewRange = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("last"));
315 bApplyNewRange = true;
316 }
317 }
318 }
319 }
320 else
321 {
322 uno::Reference< chart2::data::XDataSequence > xSeq(
323 StatisticsHelper::getErrorDataSequenceFromDataSource(
324 xErrorBarSource, bIsPositiveValue, bYError ));
325 bApplyNewRange =
326 ! ( xSeq.is() && aNewRange.equals( xSeq->getSourceRangeRepresentation()));
327 }
328
329 if( bApplyNewRange )
330 StatisticsHelper::setErrorDataSequence(
331 xErrorBarSource, xDataProvider, aNewRange, bIsPositiveValue, bYError );
332 }
333 }
334 break;
335 }
336
337 return bChanged;
338 }
339
FillSpecialItem(sal_uInt16 nWhichId,SfxItemSet & rOutItemSet) const340 void ErrorBarItemConverter::FillSpecialItem(
341 sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
342 throw( uno::Exception )
343 {
344 switch( nWhichId )
345 {
346 case SCHATTR_STAT_KIND_ERROR:
347 {
348 SvxChartKindError eErrorKind = CHERROR_NONE;
349 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
350
351 sal_Int32 nStyle = 0;
352 if( xErrorBarProp->getPropertyValue( C2U( "ErrorBarStyle" )) >>= nStyle )
353 {
354 switch( nStyle )
355 {
356 case ::com::sun::star::chart::ErrorBarStyle::NONE:
357 break;
358 case ::com::sun::star::chart::ErrorBarStyle::VARIANCE:
359 eErrorKind = CHERROR_VARIANT; break;
360 case ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION:
361 eErrorKind = CHERROR_SIGMA; break;
362 case ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE:
363 eErrorKind = CHERROR_CONST; break;
364 case ::com::sun::star::chart::ErrorBarStyle::RELATIVE:
365 eErrorKind = CHERROR_PERCENT; break;
366 case ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN:
367 eErrorKind = CHERROR_BIGERROR; break;
368 case ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR:
369 eErrorKind = CHERROR_STDERROR; break;
370 case ::com::sun::star::chart::ErrorBarStyle::FROM_DATA:
371 eErrorKind = CHERROR_RANGE; break;
372 }
373 }
374 rOutItemSet.Put( SvxChartKindErrorItem( eErrorKind, SCHATTR_STAT_KIND_ERROR ));
375 }
376 break;
377
378 case SCHATTR_STAT_PERCENT:
379 {
380 double fPos, fNeg;
381 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
382 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, nWhichId ));
383 }
384 break;
385
386 case SCHATTR_STAT_BIGERROR:
387 {
388 double fPos, fNeg;
389 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
390 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, nWhichId ));
391 }
392 break;
393
394 case SCHATTR_STAT_CONSTPLUS:
395 {
396 double fPos, fNeg;
397 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
398 rOutItemSet.Put( SvxDoubleItem( fPos, nWhichId ));
399 }
400 break;
401
402 case SCHATTR_STAT_CONSTMINUS:
403 {
404 double fPos, fNeg;
405 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
406 rOutItemSet.Put( SvxDoubleItem( fNeg, nWhichId ));
407 }
408 break;
409
410 case SCHATTR_STAT_INDICATE:
411 {
412 SvxChartIndicate eIndicate = CHINDICATE_BOTH;
413 bool bShowPos, bShowNeg;
414 lcl_getErrorIndicatorValues( GetPropertySet(), bShowPos, bShowNeg );
415
416 if( bShowPos )
417 {
418 if( bShowNeg )
419 eIndicate = CHINDICATE_BOTH;
420 else
421 eIndicate = CHINDICATE_UP;
422 }
423 else
424 {
425 if( bShowNeg )
426 eIndicate = CHINDICATE_DOWN;
427 else
428 eIndicate = CHINDICATE_NONE;
429 }
430 rOutItemSet.Put( SvxChartIndicateItem( eIndicate, SCHATTR_STAT_INDICATE ));
431 }
432 break;
433
434 case SCHATTR_STAT_RANGE_POS:
435 case SCHATTR_STAT_RANGE_NEG:
436 {
437 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
438 if( xErrorBarSource.is())
439 {
440 uno::Reference< chart2::data::XDataSequence > xSeq(
441 StatisticsHelper::getErrorDataSequenceFromDataSource(
442 xErrorBarSource, (nWhichId == SCHATTR_STAT_RANGE_POS) /*, true */ /* y */ ));
443 if( xSeq.is())
444 rOutItemSet.Put( SfxStringItem( nWhichId, String( xSeq->getSourceRangeRepresentation())));
445 }
446 }
447 break;
448 }
449 }
450
451 } // namespace wrapper
452 } // namespace chart
453