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