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 "DataSeriesHelper.hxx"
21 : #include "DiagramHelper.hxx"
22 : #include "DataSource.hxx"
23 : #include "macros.hxx"
24 : #include "ContainerHelper.hxx"
25 : #include <unonames.hxx>
26 :
27 : #include <com/sun/star/beans/XPropertySet.hpp>
28 : #include <com/sun/star/chart2/DataPointLabel.hpp>
29 : #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
30 : #include <com/sun/star/chart2/StackingDirection.hpp>
31 : #include <com/sun/star/chart2/data/LabelOrigin.hpp>
32 : #include <com/sun/star/chart2/AxisType.hpp>
33 : #include <com/sun/star/chart2/SymbolStyle.hpp>
34 : #include <com/sun/star/chart2/Symbol.hpp>
35 : #include <com/sun/star/drawing/LineStyle.hpp>
36 :
37 : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
38 : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
39 : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
40 : #include <rtl/ustrbuf.hxx>
41 :
42 : #include <functional>
43 : #include <algorithm>
44 : #include <iterator>
45 : #include <vector>
46 : #include <set>
47 :
48 : using namespace ::com::sun::star;
49 : using namespace ::com::sun::star::chart2;
50 :
51 : using ::com::sun::star::uno::Reference;
52 : using ::com::sun::star::uno::Sequence;
53 :
54 : namespace
55 : {
56 :
57 379308 : class lcl_MatchesRole : public ::std::unary_function< Reference< chart2::data::XLabeledDataSequence >, bool >
58 : {
59 : public:
60 126436 : explicit lcl_MatchesRole( const OUString & aRole, bool bMatchPrefix ) :
61 : m_aRole( aRole ),
62 126436 : m_bMatchPrefix( bMatchPrefix )
63 126436 : {}
64 :
65 152463 : bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
66 : {
67 152463 : if(!xSeq.is())
68 0 : return false;
69 152463 : Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
70 304926 : OUString aRole;
71 :
72 152463 : if( m_bMatchPrefix )
73 416799 : return ( xProp.is() &&
74 833598 : (xProp->getPropertyValue( "Role" ) >>= aRole ) &&
75 277866 : aRole.match( m_aRole ));
76 :
77 40590 : return ( xProp.is() &&
78 81180 : (xProp->getPropertyValue( "Role" ) >>= aRole ) &&
79 179523 : m_aRole.equals( aRole ));
80 : }
81 :
82 : private:
83 : OUString m_aRole;
84 : bool m_bMatchPrefix;
85 : };
86 :
87 3 : Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
88 : const Reference< chart2::data::XDataSource > & xDataSource )
89 : {
90 3 : Reference< chart2::data::XLabeledDataSequence > xResult;
91 6 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
92 :
93 6 : for( sal_Int32 i=0; i<aSequences.getLength(); ++i )
94 : {
95 : OSL_ENSURE( aSequences[i].is(), "empty LabeledDataSequence" );
96 : // no values are set but a label exists
97 12 : if( aSequences[i].is() &&
98 12 : ( ! aSequences[i]->getValues().is() &&
99 3 : aSequences[i]->getLabel().is()))
100 : {
101 0 : xResult.set( aSequences[i] );
102 0 : break;
103 : }
104 : }
105 :
106 6 : return xResult;
107 : }
108 :
109 208 : void lcl_getCooSysAndChartTypeOfSeries(
110 : const Reference< chart2::XDataSeries > & xSeries,
111 : const Reference< chart2::XDiagram > & xDiagram,
112 : Reference< chart2::XCoordinateSystem > & xOutCooSys,
113 : Reference< chart2::XChartType > & xOutChartType )
114 : {
115 208 : Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
116 208 : if( xCooSysCnt.is())
117 : {
118 208 : Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
119 416 : for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
120 : {
121 208 : Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
122 416 : Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
123 428 : for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
124 : {
125 220 : Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY );
126 220 : if( xSeriesCnt.is())
127 : {
128 220 : Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries());
129 1304 : for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx )
130 : {
131 1084 : if( aSeries[nSeriesIdx] == xSeries )
132 : {
133 208 : xOutCooSys.set( aCooSysSeq[nCooSysIdx] );
134 208 : xOutChartType.set( aChartTypes[nCTIdx] );
135 : }
136 220 : }
137 : }
138 220 : }
139 416 : }
140 208 : }
141 208 : }
142 :
143 0 : void lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries, bool bInsert )
144 : {
145 : try
146 : {
147 0 : Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
148 0 : if( xSeriesProperties.is() )
149 : {
150 0 : DataPointLabel aLabelAtSeries;
151 0 : xSeriesProperties->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabelAtSeries;
152 0 : aLabelAtSeries.ShowNumber = bInsert;
153 0 : if( !bInsert )
154 : {
155 0 : aLabelAtSeries.ShowNumberInPercent = false;
156 0 : aLabelAtSeries.ShowCategoryName = false;
157 : }
158 0 : xSeriesProperties->setPropertyValue(CHART_UNONAME_LABEL, uno::makeAny(aLabelAtSeries));
159 0 : uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
160 0 : if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
161 : {
162 0 : for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
163 : {
164 0 : Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
165 0 : if( xPointProp.is() )
166 : {
167 0 : DataPointLabel aLabel;
168 0 : xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
169 0 : aLabel.ShowNumber = bInsert;
170 0 : if( !bInsert )
171 : {
172 0 : aLabel.ShowNumberInPercent = false;
173 0 : aLabel.ShowCategoryName = false;
174 : }
175 0 : xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::makeAny(aLabel));
176 : }
177 0 : }
178 0 : }
179 0 : }
180 : }
181 0 : catch(const uno::Exception &e)
182 : {
183 : ASSERT_EXCEPTION( e );
184 : }
185 0 : }
186 :
187 : } // anonymous namespace
188 :
189 : namespace chart
190 : {
191 :
192 : namespace DataSeriesHelper
193 : {
194 :
195 3957 : OUString getRole( const uno::Reference< chart2::data::XLabeledDataSequence >& xLabeledDataSequence )
196 : {
197 3957 : OUString aRet;
198 3957 : if( xLabeledDataSequence.is() )
199 : {
200 3957 : Reference< beans::XPropertySet > xProp( xLabeledDataSequence->getValues(), uno::UNO_QUERY );
201 3957 : if( xProp.is() )
202 3957 : xProp->getPropertyValue( "Role" ) >>= aRet;
203 : }
204 3957 : return aRet;
205 : }
206 :
207 : Reference< chart2::data::XLabeledDataSequence >
208 11350 : getDataSequenceByRole(
209 : const Reference< chart2::data::XDataSource > & xSource,
210 : const OUString& aRole,
211 : bool bMatchPrefix /* = false */ )
212 : {
213 11350 : Reference< chart2::data::XLabeledDataSequence > aNoResult;
214 11350 : if( ! xSource.is())
215 0 : return aNoResult;
216 22700 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences());
217 :
218 11350 : const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
219 11350 : const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
220 : const Reference< chart2::data::XLabeledDataSequence > * pMatch =
221 11350 : ::std::find_if( pBegin, pEnd, lcl_MatchesRole( aRole, bMatchPrefix ));
222 :
223 11350 : if( pMatch != pEnd )
224 8916 : return *pMatch;
225 :
226 13784 : return aNoResult;
227 : }
228 :
229 : ::std::vector< Reference< chart2::data::XLabeledDataSequence > >
230 115086 : getAllDataSequencesByRole( const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aDataSequences,
231 : const OUString& aRole, bool bMatchPrefix /* = false */ )
232 : {
233 115086 : ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVec;
234 115086 : ::std::remove_copy_if( aDataSequences.getConstArray(), aDataSequences.getConstArray() + aDataSequences.getLength(),
235 : ::std::back_inserter( aResultVec ),
236 230172 : ::std::not1( lcl_MatchesRole( aRole, bMatchPrefix )));
237 115086 : return aResultVec;
238 : }
239 :
240 : std::vector<Reference<css::chart2::data::XLabeledDataSequence> >
241 1720 : getAllDataSequences( const uno::Sequence<uno::Reference<chart2::XDataSeries> >& aSeries )
242 : {
243 1720 : ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVec;
244 :
245 5348 : for( sal_Int32 i = 0; i < aSeries.getLength(); ++i )
246 : {
247 3628 : Reference< chart2::data::XDataSource > xSource( aSeries[ i ], uno::UNO_QUERY );
248 3628 : if( xSource.is())
249 : {
250 3628 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
251 : ::std::copy( aSeq.begin(), aSeq.end(),
252 3628 : ::std::back_inserter( aSeqVec ));
253 : }
254 3628 : }
255 :
256 1720 : return aSeqVec;
257 : }
258 :
259 : Reference< chart2::data::XDataSource >
260 1720 : getDataSource( const Sequence< Reference< chart2::XDataSeries > > & aSeries )
261 : {
262 : return Reference< chart2::data::XDataSource >(
263 1720 : new DataSource(ContainerHelper::ContainerToSequence(getAllDataSequences(aSeries))));
264 : }
265 :
266 : namespace
267 : {
268 5007 : OUString lcl_getDataSequenceLabel( const Reference< chart2::data::XDataSequence > & xSequence )
269 : {
270 5007 : OUString aResult;
271 :
272 10014 : Reference< chart2::data::XTextualDataSequence > xTextSeq( xSequence, uno::UNO_QUERY );
273 5007 : if( xTextSeq.is())
274 : {
275 5007 : Sequence< OUString > aSeq( xTextSeq->getTextualData());
276 :
277 5007 : const sal_Int32 nMax = aSeq.getLength() - 1;
278 10014 : OUStringBuffer aBuf;
279 :
280 10014 : for( sal_Int32 i = 0; i <= nMax; ++i )
281 : {
282 5007 : aBuf.append( aSeq[i] );
283 5007 : if( i < nMax )
284 0 : aBuf.append( ' ');
285 : }
286 10014 : aResult = aBuf.makeStringAndClear();
287 : }
288 0 : else if( xSequence.is())
289 : {
290 0 : Sequence< uno::Any > aSeq( xSequence->getData());
291 :
292 0 : const sal_Int32 nMax = aSeq.getLength() - 1;
293 0 : OUString aVal;
294 0 : OUStringBuffer aBuf;
295 0 : double fNum = 0;
296 :
297 0 : for( sal_Int32 i = 0; i <= nMax; ++i )
298 : {
299 0 : if( aSeq[i] >>= aVal )
300 : {
301 0 : aBuf.append( aVal );
302 0 : if( i < nMax )
303 0 : aBuf.append( ' ');
304 : }
305 0 : else if( aSeq[ i ] >>= fNum )
306 : {
307 0 : aBuf.append( fNum );
308 0 : if( i < nMax )
309 0 : aBuf.append( ' ');
310 : }
311 : }
312 0 : aResult = aBuf.makeStringAndClear();
313 : }
314 :
315 10014 : return aResult;
316 : }
317 : }
318 :
319 5021 : OUString getLabelForLabeledDataSequence(
320 : const Reference< chart2::data::XLabeledDataSequence > & xLabeledSeq )
321 : {
322 5021 : OUString aResult;
323 5021 : if( xLabeledSeq.is())
324 : {
325 5021 : Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
326 5021 : if( xSeq.is() )
327 5001 : aResult = lcl_getDataSequenceLabel( xSeq );
328 5021 : if( !xSeq.is() || aResult.isEmpty() )
329 : {
330 : // no label set or label content is empty -> use auto-generated one
331 20 : Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
332 20 : if( xValueSeq.is() )
333 : {
334 20 : Sequence< OUString > aLabels( xValueSeq->generateLabel(
335 20 : chart2::data::LabelOrigin_SHORT_SIDE ) );
336 : // no labels returned is interpreted as: auto-generation not
337 : // supported by sequence
338 20 : if( aLabels.getLength() )
339 14 : aResult=aLabels[0];
340 : else
341 : {
342 : //todo?: maybe use the index of the series as name
343 : //but as the index may change it would be better to have such a name persistent
344 : //what is not possible at the moment
345 : //--> maybe use the identifier as part of the name ...
346 6 : aResult = lcl_getDataSequenceLabel( xValueSeq );
347 20 : }
348 20 : }
349 5021 : }
350 : }
351 5021 : return aResult;
352 : }
353 :
354 5024 : OUString getDataSeriesLabel(
355 : const Reference< chart2::XDataSeries > & xSeries,
356 : const OUString & rLabelSequenceRole )
357 : {
358 5024 : OUString aResult;
359 :
360 10048 : Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
361 5024 : if( xSource.is())
362 : {
363 : Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
364 5024 : ::chart::DataSeriesHelper::getDataSequenceByRole( xSource, rLabelSequenceRole ));
365 5024 : if( xLabeledSeq.is())
366 5021 : aResult = getLabelForLabeledDataSequence( xLabeledSeq );
367 : else
368 : {
369 : // special case: labeled data series with only a label and no values may
370 : // serve as label
371 3 : xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
372 3 : if( xLabeledSeq.is())
373 : {
374 0 : Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
375 0 : if( xSeq.is())
376 0 : aResult = lcl_getDataSequenceLabel( xSeq );
377 : }
378 5024 : }
379 :
380 : }
381 :
382 10048 : return aResult;
383 : }
384 :
385 2 : void setStackModeAtSeries(
386 : const Sequence< Reference< chart2::XDataSeries > > & aSeries,
387 : const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem,
388 : StackMode eStackMode )
389 : {
390 2 : if( eStackMode == StackMode_AMBIGUOUS )
391 2 : return;
392 :
393 2 : const OUString aPropName( "StackingDirection" );
394 : const uno::Any aPropValue = uno::makeAny(
395 2 : ( (eStackMode == StackMode_Y_STACKED) ||
396 : (eStackMode == StackMode_Y_STACKED_PERCENT) )
397 : ? chart2::StackingDirection_Y_STACKING
398 : : (eStackMode == StackMode_Z_STACKED )
399 : ? chart2::StackingDirection_Z_STACKING
400 6 : : chart2::StackingDirection_NO_STACKING );
401 :
402 4 : std::set< sal_Int32 > aAxisIndexSet;
403 8 : for( sal_Int32 i=0; i<aSeries.getLength(); ++i )
404 : {
405 : try
406 : {
407 6 : Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY );
408 6 : if( xProp.is() )
409 : {
410 6 : xProp->setPropertyValue( aPropName, aPropValue );
411 :
412 : sal_Int32 nAxisIndex;
413 6 : xProp->getPropertyValue( "AttachedAxisIndex" ) >>= nAxisIndex;
414 6 : aAxisIndexSet.insert(nAxisIndex);
415 6 : }
416 : }
417 0 : catch( const uno::Exception & ex )
418 : {
419 : ASSERT_EXCEPTION( ex );
420 : }
421 : }
422 :
423 4 : if( xCorrespondingCoordinateSystem.is() &&
424 2 : 1 < xCorrespondingCoordinateSystem->getDimension() )
425 : {
426 2 : sal_Int32 nAxisIndexCount = aAxisIndexSet.size();
427 2 : if( !nAxisIndexCount )
428 : {
429 0 : aAxisIndexSet.insert(0);
430 0 : nAxisIndexCount = aAxisIndexSet.size();
431 : }
432 :
433 12 : for( ::std::set< sal_Int32 >::const_iterator aIt = aAxisIndexSet.begin();
434 8 : aIt != aAxisIndexSet.end(); ++aIt )
435 : {
436 2 : sal_Int32 nAxisIndex = *aIt;
437 : Reference< chart2::XAxis > xAxis(
438 2 : xCorrespondingCoordinateSystem->getAxisByDimension( 1, nAxisIndex ));
439 2 : if( xAxis.is())
440 : {
441 2 : bool bPercent = (eStackMode == StackMode_Y_STACKED_PERCENT);
442 2 : chart2::ScaleData aScaleData = xAxis->getScaleData();
443 :
444 2 : if( bPercent != (aScaleData.AxisType==chart2::AxisType::PERCENT) )
445 : {
446 0 : if( bPercent )
447 0 : aScaleData.AxisType = chart2::AxisType::PERCENT;
448 : else
449 0 : aScaleData.AxisType = chart2::AxisType::REALNUMBER;
450 0 : xAxis->setScaleData( aScaleData );
451 2 : }
452 : }
453 2 : }
454 2 : }
455 : }
456 :
457 7693 : sal_Int32 getAttachedAxisIndex( const Reference< chart2::XDataSeries > & xSeries )
458 : {
459 7693 : sal_Int32 nRet = 0;
460 : try
461 : {
462 7693 : Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
463 7693 : if( xProp.is() )
464 : {
465 7693 : xProp->getPropertyValue( "AttachedAxisIndex" ) >>= nRet;
466 7693 : }
467 : }
468 0 : catch( const uno::Exception & ex )
469 : {
470 : ASSERT_EXCEPTION( ex );
471 : }
472 7693 : return nRet;
473 : }
474 :
475 0 : sal_Int32 getNumberFormatKeyFromAxis(
476 : const Reference< chart2::XDataSeries > & xSeries,
477 : const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem,
478 : sal_Int32 nDimensionIndex,
479 : sal_Int32 nAxisIndex /* = -1 */ )
480 : {
481 0 : sal_Int32 nResult = 0;
482 0 : if( nAxisIndex == -1 )
483 0 : nAxisIndex = getAttachedAxisIndex( xSeries );
484 : try
485 : {
486 : Reference< beans::XPropertySet > xAxisProp(
487 0 : xCorrespondingCoordinateSystem->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY );
488 0 : if( xAxisProp.is())
489 0 : xAxisProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nResult;
490 : }
491 0 : catch( const uno::Exception & ex )
492 : {
493 : ASSERT_EXCEPTION( ex );
494 : }
495 :
496 0 : return nResult;
497 : }
498 :
499 0 : Reference< chart2::XCoordinateSystem > getCoordinateSystemOfSeries(
500 : const Reference< chart2::XDataSeries > & xSeries,
501 : const Reference< chart2::XDiagram > & xDiagram )
502 : {
503 0 : Reference< chart2::XCoordinateSystem > xResult;
504 0 : Reference< chart2::XChartType > xDummy;
505 0 : lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xResult, xDummy );
506 :
507 0 : return xResult;
508 : }
509 :
510 208 : Reference< chart2::XChartType > getChartTypeOfSeries(
511 : const Reference< chart2::XDataSeries > & xSeries,
512 : const Reference< chart2::XDiagram > & xDiagram )
513 : {
514 208 : Reference< chart2::XChartType > xResult;
515 416 : Reference< chart2::XCoordinateSystem > xDummy;
516 208 : lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xDummy, xResult );
517 :
518 416 : return xResult;
519 : }
520 :
521 0 : void deleteSeries(
522 : const Reference< chart2::XDataSeries > & xSeries,
523 : const Reference< chart2::XChartType > & xChartType )
524 : {
525 : try
526 : {
527 0 : Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW );
528 : ::std::vector< Reference< chart2::XDataSeries > > aSeries(
529 0 : ContainerHelper::SequenceToVector( xSeriesCnt->getDataSeries()));
530 : ::std::vector< Reference< chart2::XDataSeries > >::iterator aIt =
531 0 : ::std::find( aSeries.begin(), aSeries.end(), xSeries );
532 0 : if( aIt != aSeries.end())
533 : {
534 0 : aSeries.erase( aIt );
535 0 : xSeriesCnt->setDataSeries( ContainerHelper::ContainerToSequence( aSeries ));
536 0 : }
537 : }
538 0 : catch( const uno::Exception & ex )
539 : {
540 : ASSERT_EXCEPTION( ex );
541 : }
542 0 : }
543 :
544 58 : void switchSymbolsOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties,
545 : bool bSymbolsOn, sal_Int32 nSeriesIndex )
546 : {
547 58 : if( !xSeriesProperties.is() )
548 58 : return;
549 :
550 58 : chart2::Symbol aSymbProp;
551 58 : if( (xSeriesProperties->getPropertyValue( "Symbol") >>= aSymbProp ) )
552 : {
553 58 : if( !bSymbolsOn )
554 29 : aSymbProp.Style = chart2::SymbolStyle_NONE;
555 29 : else if( aSymbProp.Style == chart2::SymbolStyle_NONE )
556 : {
557 29 : aSymbProp.Style = chart2::SymbolStyle_STANDARD;
558 29 : aSymbProp.StandardSymbol = nSeriesIndex;
559 : }
560 58 : xSeriesProperties->setPropertyValue( "Symbol", uno::makeAny( aSymbProp ));
561 58 : }
562 : //todo: check attributed data points
563 : }
564 :
565 58 : void switchLinesOnOrOff( const Reference< beans::XPropertySet > & xSeriesProperties, bool bLinesOn )
566 : {
567 58 : if( !xSeriesProperties.is() )
568 58 : return;
569 :
570 58 : if( bLinesOn )
571 : {
572 : // keep line-styles that are not NONE
573 : drawing::LineStyle eLineStyle;
574 116 : if( (xSeriesProperties->getPropertyValue( "LineStyle") >>= eLineStyle ) &&
575 58 : eLineStyle == drawing::LineStyle_NONE )
576 : {
577 0 : xSeriesProperties->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_SOLID ) );
578 : }
579 : }
580 : else
581 0 : xSeriesProperties->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_NONE ) );
582 : }
583 :
584 58 : void makeLinesThickOrThin( const Reference< beans::XPropertySet > & xSeriesProperties, bool bThick )
585 : {
586 58 : if( !xSeriesProperties.is() )
587 58 : return;
588 :
589 58 : sal_Int32 nNewValue = bThick ? 80 : 0;
590 58 : sal_Int32 nOldValue = 0;
591 116 : if( (xSeriesProperties->getPropertyValue( "LineWidth") >>= nOldValue ) &&
592 58 : nOldValue != nNewValue )
593 : {
594 32 : if( !(bThick && nOldValue>0))
595 32 : xSeriesProperties->setPropertyValue( "LineWidth", uno::makeAny( nNewValue ) );
596 : }
597 : }
598 :
599 261 : void setPropertyAlsoToAllAttributedDataPoints( const Reference< chart2::XDataSeries >& xSeries,
600 : const OUString& rPropertyName, const uno::Any& rPropertyValue )
601 : {
602 261 : Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
603 261 : if( !xSeriesProperties.is() )
604 261 : return;
605 :
606 261 : xSeriesProperties->setPropertyValue( rPropertyName, rPropertyValue );
607 522 : uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
608 261 : if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
609 : {
610 522 : for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
611 : {
612 0 : Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
613 0 : if(!xPointProp.is())
614 0 : continue;
615 0 : xPointProp->setPropertyValue( rPropertyName, rPropertyValue );
616 0 : }
617 261 : }
618 : }
619 :
620 206 : bool hasAttributedDataPointDifferentValue( const Reference< chart2::XDataSeries >& xSeries,
621 : const OUString& rPropertyName, const uno::Any& rPropertyValue )
622 : {
623 206 : Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
624 206 : if( !xSeriesProperties.is() )
625 0 : return false;
626 :
627 412 : uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
628 206 : if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
629 : {
630 412 : for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
631 : {
632 0 : Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
633 0 : if(!xPointProp.is())
634 0 : continue;
635 0 : uno::Any aPointValue( xPointProp->getPropertyValue( rPropertyName ) );
636 0 : if( !( rPropertyValue==aPointValue ) )
637 0 : return true;
638 0 : }
639 : }
640 412 : return false;
641 : }
642 :
643 0 : bool areAllSeriesAttachedToSameAxis( const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 & rOutAxisIndex )
644 : {
645 : try
646 : {
647 0 : uno::Reference< chart2::XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY_THROW );
648 0 : uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDataSeriesContainer->getDataSeries());
649 :
650 0 : const sal_Int32 nSeriesCount( aSeriesSeq.getLength());
651 : // AxisIndex can only be 0 or 1
652 0 : sal_Int32 nSeriesAtFirstAxis = 0;
653 0 : sal_Int32 nSeriesAtSecondAxis = 0;
654 :
655 0 : for( sal_Int32 nI = 0; nI < nSeriesCount; ++nI )
656 : {
657 0 : uno::Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nI], uno::UNO_QUERY );
658 0 : sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex( xSeries );
659 0 : if( nAxisIndex == 0 )
660 0 : ++nSeriesAtFirstAxis;
661 0 : else if( nAxisIndex == 1 )
662 0 : ++nSeriesAtSecondAxis;
663 0 : }
664 : OSL_ENSURE( nSeriesAtFirstAxis + nSeriesAtSecondAxis == nSeriesCount, "Invalid axis index found" );
665 :
666 0 : if( nSeriesAtFirstAxis == nSeriesCount )
667 0 : rOutAxisIndex = 0;
668 0 : else if( nSeriesAtSecondAxis == nSeriesCount )
669 0 : rOutAxisIndex = 1;
670 :
671 0 : return ( nSeriesAtFirstAxis == nSeriesCount ||
672 0 : nSeriesAtSecondAxis == nSeriesCount );
673 : }
674 0 : catch( const uno::Exception & ex )
675 : {
676 : ASSERT_EXCEPTION( ex );
677 0 : return false;
678 : }
679 : }
680 :
681 : namespace
682 : {
683 :
684 1881 : bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
685 : {
686 1881 : if( !xDataSequence.is() )
687 0 : return false;
688 1881 : uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
689 1881 : if( xProp.is() )
690 : {
691 1881 : uno::Sequence< sal_Int32 > aHiddenValues;
692 : try
693 : {
694 1881 : xProp->getPropertyValue( "HiddenValues" ) >>= aHiddenValues;
695 188 : if( !aHiddenValues.getLength() )
696 186 : return true;
697 : }
698 3386 : catch( const uno::Exception& )
699 : {
700 1693 : return true;
701 2 : }
702 : }
703 2 : if( xDataSequence->getData().getLength() )
704 2 : return true;
705 0 : return false;
706 : }
707 :
708 : }
709 :
710 1885 : bool hasUnhiddenData( const uno::Reference< chart2::XDataSeries >& xSeries )
711 : {
712 : uno::Reference< chart2::data::XDataSource > xDataSource =
713 1885 : uno::Reference< chart2::data::XDataSource >( xSeries, uno::UNO_QUERY );
714 :
715 3770 : uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDataSequences = xDataSource->getDataSequences();
716 :
717 3770 : for(sal_Int32 nN = aDataSequences.getLength();nN--;)
718 : {
719 1881 : if( !aDataSequences[nN].is() )
720 0 : continue;
721 1881 : if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getValues() ) )
722 1881 : return true;
723 0 : if( lcl_SequenceHasUnhiddenData( aDataSequences[nN]->getLabel() ) )
724 0 : return true;
725 : }
726 1889 : return false;
727 : }
728 :
729 : struct lcl_LessIndex
730 : {
731 0 : inline bool operator() ( const sal_Int32& first, const sal_Int32& second ) const
732 : {
733 0 : return ( first < second );
734 : }
735 : };
736 :
737 0 : sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nIndex, const Reference< chart2::data::XDataSequence >& xDataSequence, bool bTranslate )
738 : {
739 0 : if( !bTranslate )
740 0 : return nIndex;
741 :
742 : try
743 : {
744 0 : uno::Reference<beans::XPropertySet> xProp( xDataSequence, uno::UNO_QUERY );
745 0 : if( xProp.is())
746 : {
747 0 : Sequence<sal_Int32> aHiddenIndicesSeq;
748 0 : xProp->getPropertyValue( "HiddenValues" ) >>= aHiddenIndicesSeq;
749 0 : if( aHiddenIndicesSeq.getLength() )
750 : {
751 0 : ::std::vector< sal_Int32 > aHiddenIndices( ContainerHelper::SequenceToVector( aHiddenIndicesSeq ) );
752 0 : ::std::sort( aHiddenIndices.begin(), aHiddenIndices.end(), lcl_LessIndex() );
753 :
754 0 : sal_Int32 nHiddenCount = static_cast<sal_Int32>(aHiddenIndices.size());
755 0 : for( sal_Int32 nN = 0; nN < nHiddenCount; ++nN)
756 : {
757 0 : if( aHiddenIndices[nN] <= nIndex )
758 0 : nIndex += 1;
759 : else
760 0 : break;
761 0 : }
762 0 : }
763 0 : }
764 : }
765 0 : catch (const beans::UnknownPropertyException&)
766 : {
767 : }
768 0 : return nIndex;
769 : }
770 :
771 2378 : bool hasDataLabelsAtSeries( const Reference< chart2::XDataSeries >& xSeries )
772 : {
773 2378 : bool bRet = false;
774 : try
775 : {
776 2378 : Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
777 2378 : if( xProp.is() )
778 : {
779 2378 : DataPointLabel aLabel;
780 2378 : if( (xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel) )
781 2378 : bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName;
782 2378 : }
783 : }
784 0 : catch(const uno::Exception &e)
785 : {
786 : ASSERT_EXCEPTION( e );
787 : }
788 2378 : return bRet;
789 : }
790 :
791 0 : bool hasDataLabelsAtPoints( const Reference< chart2::XDataSeries >& xSeries )
792 : {
793 0 : bool bRet = false;
794 : try
795 : {
796 0 : Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
797 0 : if( xSeriesProperties.is() )
798 : {
799 0 : uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
800 0 : if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
801 : {
802 0 : for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
803 : {
804 0 : Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
805 0 : if( xPointProp.is() )
806 : {
807 0 : DataPointLabel aLabel;
808 0 : if( (xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel) )
809 0 : bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName;
810 0 : if( bRet )
811 0 : break;
812 : }
813 0 : }
814 0 : }
815 0 : }
816 : }
817 0 : catch(const uno::Exception &e)
818 : {
819 : ASSERT_EXCEPTION( e );
820 : }
821 0 : return bRet;
822 : }
823 :
824 0 : bool hasDataLabelAtPoint( const Reference< chart2::XDataSeries >& xSeries, sal_Int32 nPointIndex )
825 : {
826 0 : bool bRet = false;
827 : try
828 : {
829 0 : Reference< beans::XPropertySet > xProp;
830 0 : Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
831 0 : if( xSeriesProperties.is() )
832 : {
833 0 : uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
834 0 : if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
835 : {
836 0 : ::std::vector< sal_Int32 > aIndices( ContainerHelper::SequenceToVector( aAttributedDataPointIndexList ) );
837 0 : ::std::vector< sal_Int32 >::iterator aIt = ::std::find( aIndices.begin(), aIndices.end(), nPointIndex );
838 0 : if( aIt != aIndices.end())
839 0 : xProp = xSeries->getDataPointByIndex(nPointIndex);
840 : else
841 0 : xProp = xSeriesProperties;
842 : }
843 0 : if( xProp.is() )
844 : {
845 0 : DataPointLabel aLabel;
846 0 : if( (xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel) )
847 0 : bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName;
848 0 : }
849 0 : }
850 : }
851 0 : catch(const uno::Exception &e)
852 : {
853 : ASSERT_EXCEPTION( e );
854 : }
855 0 : return bRet;
856 : }
857 :
858 0 : void insertDataLabelsToSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries )
859 : {
860 0 : lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, true /*bInsert*/ );
861 0 : }
862 :
863 0 : void deleteDataLabelsFromSeriesAndAllPoints( const Reference< chart2::XDataSeries >& xSeries )
864 : {
865 0 : lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, false /*bInsert*/ );
866 0 : }
867 :
868 0 : void insertDataLabelToPoint( const Reference< beans::XPropertySet >& xPointProp )
869 : {
870 : try
871 : {
872 0 : if( xPointProp.is() )
873 : {
874 0 : DataPointLabel aLabel;
875 0 : xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
876 0 : aLabel.ShowNumber = true;
877 0 : xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::makeAny(aLabel));
878 : }
879 : }
880 0 : catch(const uno::Exception &e)
881 : {
882 : ASSERT_EXCEPTION( e );
883 : }
884 0 : }
885 :
886 0 : void deleteDataLabelsFromPoint( const Reference< beans::XPropertySet >& xPointProp )
887 : {
888 : try
889 : {
890 0 : if( xPointProp.is() )
891 : {
892 0 : DataPointLabel aLabel;
893 0 : xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
894 0 : aLabel.ShowNumber = false;
895 0 : aLabel.ShowNumberInPercent = false;
896 0 : aLabel.ShowCategoryName = false;
897 0 : xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::makeAny(aLabel));
898 : }
899 : }
900 0 : catch(const uno::Exception &e)
901 : {
902 : ASSERT_EXCEPTION( e );
903 : }
904 0 : }
905 :
906 : } // namespace DataSeriesHelper
907 : } // namespace chart
908 :
909 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|