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_chartcontroller.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 {
148 bool bChanged = false;
149 uno::Any aValue;
150
151 switch( nWhichId )
152 {
153 // Attention !!! This case must be passed before SCHATTR_STAT_PERCENT,
154 // SCHATTR_STAT_BIGERROR, SCHATTR_STAT_CONSTPLUS,
155 // SCHATTR_STAT_CONSTMINUS and SCHATTR_STAT_INDICATE
156 case SCHATTR_STAT_KIND_ERROR:
157 {
158 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
159
160 SvxChartKindError eErrorKind =
161 static_cast< const SvxChartKindErrorItem & >(
162 rItemSet.Get( nWhichId )).GetValue();
163
164 if( !xErrorBarProp.is() && eErrorKind == CHERROR_NONE)
165 {
166 //nothing to do
167 }
168 else
169 {
170 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
171
172 switch( eErrorKind )
173 {
174 case CHERROR_NONE:
175 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; break;
176 case CHERROR_VARIANT:
177 nStyle = ::com::sun::star::chart::ErrorBarStyle::VARIANCE; break;
178 case CHERROR_SIGMA:
179 nStyle = ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION; break;
180 case CHERROR_PERCENT:
181 nStyle = ::com::sun::star::chart::ErrorBarStyle::RELATIVE; break;
182 case CHERROR_BIGERROR:
183 nStyle = ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN; break;
184 case CHERROR_CONST:
185 nStyle = ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE; break;
186 case CHERROR_STDERROR:
187 nStyle = ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR; break;
188 case CHERROR_RANGE:
189 nStyle = ::com::sun::star::chart::ErrorBarStyle::FROM_DATA; break;
190 }
191
192 xErrorBarProp->setPropertyValue( C2U( "ErrorBarStyle" ),
193 uno::makeAny( nStyle ));
194 bChanged = true;
195 }
196 }
197 break;
198
199 case SCHATTR_STAT_PERCENT:
200 case SCHATTR_STAT_BIGERROR:
201 {
202 OSL_ENSURE( false, "Deprecated item" );
203 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
204
205 double fValue =
206 static_cast< const SvxDoubleItem & >(
207 rItemSet.Get( nWhichId )).GetValue();
208 double fPos, fNeg;
209 lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
210
211 if( ! ( ::rtl::math::approxEqual( fPos, fValue ) &&
212 ::rtl::math::approxEqual( fNeg, fValue )))
213 {
214 xErrorBarProp->setPropertyValue( C2U( "PositiveError" ),
215 uno::makeAny( fValue ));
216 xErrorBarProp->setPropertyValue( C2U( "NegativeError" ),
217 uno::makeAny( fValue ));
218 bChanged = true;
219 }
220 }
221 break;
222
223 case SCHATTR_STAT_CONSTPLUS:
224 {
225 double fValue =
226 static_cast< const SvxDoubleItem & >(
227 rItemSet.Get( nWhichId )).GetValue();
228 double fPos, fNeg;
229 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
230
231 if( ! ::rtl::math::approxEqual( fPos, fValue ))
232 {
233 GetPropertySet()->setPropertyValue( C2U( "PositiveError" ), uno::makeAny( fValue ));
234 bChanged = true;
235 }
236 }
237 break;
238
239 case SCHATTR_STAT_CONSTMINUS:
240 {
241 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
242
243 double fValue =
244 static_cast< const SvxDoubleItem & >(
245 rItemSet.Get( nWhichId )).GetValue();
246 double fPos, fNeg;
247 lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
248
249 if( ! ::rtl::math::approxEqual( fNeg, fValue ))
250 {
251 xErrorBarProp->setPropertyValue( C2U( "NegativeError" ), uno::makeAny( fValue ));
252 bChanged = true;
253 }
254 }
255 break;
256
257 case SCHATTR_STAT_INDICATE:
258 {
259 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
260
261 SvxChartIndicate eIndicate =
262 static_cast< const SvxChartIndicateItem & >(
263 rItemSet.Get( nWhichId )).GetValue();
264
265 bool bNewIndPos = (eIndicate == CHINDICATE_BOTH || eIndicate == CHINDICATE_UP );
266 bool bNewIndNeg = (eIndicate == CHINDICATE_BOTH || eIndicate == CHINDICATE_DOWN );
267
268 bool bShowPos, bShowNeg;
269 lcl_getErrorIndicatorValues( xErrorBarProp, bShowPos, bShowNeg );
270
271 if( ( bShowPos != bNewIndPos ||
272 bShowNeg != bNewIndNeg ))
273 {
274 xErrorBarProp->setPropertyValue( C2U( "ShowPositiveError" ), uno::makeAny( bNewIndPos ));
275 xErrorBarProp->setPropertyValue( C2U( "ShowNegativeError" ), uno::makeAny( bNewIndNeg ));
276 bChanged = true;
277 }
278 }
279 break;
280
281 case SCHATTR_STAT_RANGE_POS:
282 case SCHATTR_STAT_RANGE_NEG:
283 {
284 // @todo: also be able to deal with x-error bars
285 const bool bYError = true;
286 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
287 uno::Reference< chart2::XChartDocument > xChartDoc( m_xModel, uno::UNO_QUERY );
288 uno::Reference< chart2::data::XDataProvider > xDataProvider;
289
290 if( xChartDoc.is())
291 xDataProvider.set( xChartDoc->getDataProvider());
292 if( xErrorBarSource.is() && xDataProvider.is())
293 {
294 ::rtl::OUString aNewRange( static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue());
295 bool bApplyNewRange = false;
296
297 bool bIsPositiveValue( nWhichId == SCHATTR_STAT_RANGE_POS );
298 if( xChartDoc->hasInternalDataProvider())
299 {
300 if( !aNewRange.isEmpty() )
301 {
302 uno::Reference< chart2::data::XDataSequence > xSeq(
303 StatisticsHelper::getErrorDataSequenceFromDataSource(
304 xErrorBarSource, bIsPositiveValue, bYError ));
305 if( ! xSeq.is())
306 {
307 // no data range for error bars yet => create
308 uno::Reference< chart2::XInternalDataProvider > xIntDataProvider( xDataProvider, uno::UNO_QUERY );
309 OSL_ASSERT( xIntDataProvider.is());
310 if( xIntDataProvider.is())
311 {
312 xIntDataProvider->appendSequence();
313 aNewRange = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("last"));
314 bApplyNewRange = true;
315 }
316 }
317 }
318 }
319 else
320 {
321 uno::Reference< chart2::data::XDataSequence > xSeq(
322 StatisticsHelper::getErrorDataSequenceFromDataSource(
323 xErrorBarSource, bIsPositiveValue, bYError ));
324 bApplyNewRange =
325 ! ( xSeq.is() && aNewRange.equals( xSeq->getSourceRangeRepresentation()));
326 }
327
328 if( bApplyNewRange )
329 StatisticsHelper::setErrorDataSequence(
330 xErrorBarSource, xDataProvider, aNewRange, bIsPositiveValue, bYError );
331 }
332 }
333 break;
334 }
335
336 return bChanged;
337 }
338
FillSpecialItem(sal_uInt16 nWhichId,SfxItemSet & rOutItemSet) const339 void ErrorBarItemConverter::FillSpecialItem(
340 sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
341 {
342 switch( nWhichId )
343 {
344 case SCHATTR_STAT_KIND_ERROR:
345 {
346 SvxChartKindError eErrorKind = CHERROR_NONE;
347 uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
348
349 sal_Int32 nStyle = 0;
350 if( xErrorBarProp->getPropertyValue( C2U( "ErrorBarStyle" )) >>= nStyle )
351 {
352 switch( nStyle )
353 {
354 case ::com::sun::star::chart::ErrorBarStyle::NONE:
355 break;
356 case ::com::sun::star::chart::ErrorBarStyle::VARIANCE:
357 eErrorKind = CHERROR_VARIANT; break;
358 case ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION:
359 eErrorKind = CHERROR_SIGMA; break;
360 case ::com::sun::star::chart::ErrorBarStyle::ABSOLUTE:
361 eErrorKind = CHERROR_CONST; break;
362 case ::com::sun::star::chart::ErrorBarStyle::RELATIVE:
363 eErrorKind = CHERROR_PERCENT; break;
364 case ::com::sun::star::chart::ErrorBarStyle::ERROR_MARGIN:
365 eErrorKind = CHERROR_BIGERROR; break;
366 case ::com::sun::star::chart::ErrorBarStyle::STANDARD_ERROR:
367 eErrorKind = CHERROR_STDERROR; break;
368 case ::com::sun::star::chart::ErrorBarStyle::FROM_DATA:
369 eErrorKind = CHERROR_RANGE; break;
370 }
371 }
372 rOutItemSet.Put( SvxChartKindErrorItem( eErrorKind, SCHATTR_STAT_KIND_ERROR ));
373 }
374 break;
375
376 case SCHATTR_STAT_PERCENT:
377 {
378 double fPos, fNeg;
379 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
380 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, nWhichId ));
381 }
382 break;
383
384 case SCHATTR_STAT_BIGERROR:
385 {
386 double fPos, fNeg;
387 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
388 rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, nWhichId ));
389 }
390 break;
391
392 case SCHATTR_STAT_CONSTPLUS:
393 {
394 double fPos, fNeg;
395 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
396 rOutItemSet.Put( SvxDoubleItem( fPos, nWhichId ));
397 }
398 break;
399
400 case SCHATTR_STAT_CONSTMINUS:
401 {
402 double fPos, fNeg;
403 lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
404 rOutItemSet.Put( SvxDoubleItem( fNeg, nWhichId ));
405 }
406 break;
407
408 case SCHATTR_STAT_INDICATE:
409 {
410 SvxChartIndicate eIndicate = CHINDICATE_BOTH;
411 bool bShowPos, bShowNeg;
412 lcl_getErrorIndicatorValues( GetPropertySet(), bShowPos, bShowNeg );
413
414 if( bShowPos )
415 {
416 if( bShowNeg )
417 eIndicate = CHINDICATE_BOTH;
418 else
419 eIndicate = CHINDICATE_UP;
420 }
421 else
422 {
423 if( bShowNeg )
424 eIndicate = CHINDICATE_DOWN;
425 else
426 eIndicate = CHINDICATE_NONE;
427 }
428 rOutItemSet.Put( SvxChartIndicateItem( eIndicate, SCHATTR_STAT_INDICATE ));
429 }
430 break;
431
432 case SCHATTR_STAT_RANGE_POS:
433 case SCHATTR_STAT_RANGE_NEG:
434 {
435 uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
436 if( xErrorBarSource.is())
437 {
438 uno::Reference< chart2::data::XDataSequence > xSeq(
439 StatisticsHelper::getErrorDataSequenceFromDataSource(
440 xErrorBarSource, (nWhichId == SCHATTR_STAT_RANGE_POS) /*, true */ /* y */ ));
441 if( xSeq.is())
442 rOutItemSet.Put( SfxStringItem( nWhichId, String( xSeq->getSourceRangeRepresentation())));
443 }
444 }
445 break;
446 }
447 }
448
449 } // namespace wrapper
450 } // namespace chart
451