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 "ChartTypeTemplate.hxx"
21 : #include "PropertyHelper.hxx"
22 : #include "macros.hxx"
23 : #include "DataSeriesHelper.hxx"
24 : #include "DataInterpreter.hxx"
25 : #include "CommonConverters.hxx"
26 : #include "ContainerHelper.hxx"
27 : #include "ChartTypeHelper.hxx"
28 :
29 : #include "CartesianCoordinateSystem.hxx"
30 : #include "AxisHelper.hxx"
31 : #include "LegendHelper.hxx"
32 : #include "DiagramHelper.hxx"
33 : #include "ChartDebugTrace.hxx"
34 : #include "AxisIndexDefines.hxx"
35 : #include <cppuhelper/component_context.hxx>
36 : #include <com/sun/star/chart/ChartSolidType.hpp>
37 : #include <com/sun/star/chart2/AxisType.hpp>
38 : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
39 : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
40 :
41 : #include <algorithm>
42 : #include <iterator>
43 :
44 : using namespace ::com::sun::star;
45 : using namespace ::com::sun::star::chart2;
46 :
47 : using ::com::sun::star::uno::Sequence;
48 : using ::com::sun::star::uno::Reference;
49 : using ::com::sun::star::uno::Any;
50 :
51 : namespace
52 : {
53 :
54 479 : void lcl_applyDefaultStyle(
55 : const Reference< XDataSeries > & xSeries,
56 : sal_Int32 nIndex,
57 : const Reference< XDiagram > & xDiagram )
58 : {
59 : // @deprecated: correct default color should be found by view without
60 : // setting color as hard attribute
61 479 : if( xSeries.is() && xDiagram.is())
62 : {
63 479 : Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
64 958 : Reference< chart2::XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
65 479 : if( xSeriesProp.is() && xColorScheme.is() )
66 479 : xSeriesProp->setPropertyValue(
67 : "Color",
68 958 : uno::makeAny( xColorScheme->getColorByIndex( nIndex )));
69 : }
70 479 : }
71 :
72 566 : void lcl_ensureCorrectLabelPlacement( const Reference< beans::XPropertySet >& xProp, const uno::Sequence < sal_Int32 >& rAvailablePlacements )
73 : {
74 566 : sal_Int32 nLabelPlacement=0;
75 566 : if( xProp.is() && (xProp->getPropertyValue( "LabelPlacement" ) >>= nLabelPlacement) )
76 : {
77 0 : bool bValid = false;
78 0 : for( sal_Int32 nN = 0; nN < rAvailablePlacements.getLength(); nN++ )
79 : {
80 0 : if( rAvailablePlacements[nN] == nLabelPlacement )
81 : {
82 0 : bValid = true;
83 0 : break;
84 : }
85 : }
86 0 : if( !bValid )
87 : {
88 0 : uno::Any aNewValue;
89 : //otherwise use the first supported one
90 0 : if( rAvailablePlacements.getLength() )
91 0 : aNewValue <<=rAvailablePlacements[0];
92 0 : xProp->setPropertyValue( "LabelPlacement", aNewValue );
93 : }
94 : }
95 566 : }
96 :
97 103 : void lcl_resetLabelPlacementIfDefault( const Reference< beans::XPropertySet >& xProp, sal_Int32 nDefaultPlacement )
98 : {
99 :
100 103 : sal_Int32 nLabelPlacement=0;
101 103 : if( xProp.is() && (xProp->getPropertyValue( "LabelPlacement" ) >>= nLabelPlacement) )
102 : {
103 0 : if( nDefaultPlacement == nLabelPlacement )
104 0 : xProp->setPropertyValue( "LabelPlacement", uno::Any() );
105 : }
106 103 : }
107 :
108 232 : void lcl_ensureCorrectMissingValueTreatment( const Reference< chart2::XDiagram >& xDiagram, const Reference< XChartType >& xChartType )
109 : {
110 232 : Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
111 232 : if( xDiaProp.is() )
112 : {
113 : uno::Sequence < sal_Int32 > aAvailableMissingValueTreatment(
114 232 : ::chart::ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) );
115 :
116 232 : if( aAvailableMissingValueTreatment.getLength() )
117 215 : xDiaProp->setPropertyValue( "MissingValueTreatment", uno::makeAny( aAvailableMissingValueTreatment[0] ) );
118 : else
119 17 : xDiaProp->setPropertyValue( "MissingValueTreatment", uno::Any() );
120 232 : }
121 232 : }
122 :
123 : } // anonymous namespace
124 :
125 : namespace chart
126 : {
127 :
128 61237 : ChartTypeTemplate::ChartTypeTemplate(
129 : Reference< uno::XComponentContext > const & xContext,
130 : const OUString & rServiceName ) :
131 : m_xContext( xContext ),
132 61237 : m_aServiceName( rServiceName )
133 : {
134 61237 : }
135 :
136 61237 : ChartTypeTemplate::~ChartTypeTemplate()
137 61237 : {}
138 :
139 : // ____ XChartTypeTemplate ____
140 217 : uno::Reference< XDiagram > SAL_CALL ChartTypeTemplate::createDiagramByDataSource(
141 : const uno::Reference< data::XDataSource >& xDataSource,
142 : const uno::Sequence< beans::PropertyValue >& aArguments )
143 : throw (uno::RuntimeException, std::exception)
144 : {
145 217 : Reference< XDiagram > xDia;
146 :
147 : try
148 : {
149 : // create diagram
150 : xDia.set(
151 434 : GetComponentContext()->getServiceManager()->createInstanceWithContext(
152 : "com.sun.star.chart2.Diagram",
153 217 : GetComponentContext() ),
154 217 : uno::UNO_QUERY_THROW );
155 :
156 : // modify diagram
157 217 : Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter());
158 : chart2::InterpretedData aData(
159 217 : xInterpreter->interpretDataSource(
160 434 : xDataSource, aArguments, Sequence< Reference< XDataSeries > >() ));
161 :
162 434 : Sequence< Sequence< Reference< XDataSeries > > > aSeries( aData.Series );
163 217 : sal_Int32 i, j, nCount = 0;
164 351 : for( i=0; i<aSeries.getLength(); ++i )
165 : {
166 536 : for( j=0; j<aSeries[i].getLength(); ++j, ++nCount )
167 402 : lcl_applyDefaultStyle( aSeries[i][j], nCount, xDia );
168 : }
169 :
170 434 : Sequence< Reference< XChartType > > aOldChartTypesSeq;
171 434 : FillDiagram( xDia, aData.Series, aData.Categories, aOldChartTypesSeq, true );
172 : }
173 0 : catch( const uno::Exception & ex )
174 : {
175 : ASSERT_EXCEPTION( ex );
176 : }
177 :
178 217 : return xDia;
179 : }
180 :
181 373 : sal_Bool SAL_CALL ChartTypeTemplate::supportsCategories()
182 : throw (::css::uno::RuntimeException, ::std::exception)
183 : {
184 373 : return sal_True;
185 : }
186 :
187 15 : void SAL_CALL ChartTypeTemplate::changeDiagram( const uno::Reference< XDiagram >& xDiagram )
188 : throw (uno::RuntimeException, std::exception)
189 : {
190 15 : if( ! xDiagram.is())
191 15 : return;
192 :
193 : try
194 : {
195 : Sequence< Sequence< Reference< XDataSeries > > > aSeriesSeq(
196 15 : DiagramHelper::getDataSeriesGroups( xDiagram ));
197 30 : Sequence< Reference< XDataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq ));
198 15 : const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.getLength();
199 :
200 : // chart-type specific interpretation of existing data series
201 30 : Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter());
202 30 : chart2::InterpretedData aData;
203 15 : aData.Series = aSeriesSeq;
204 15 : aData.Categories = DiagramHelper::getCategoriesFromDiagram( xDiagram );
205 :
206 15 : if( xInterpreter->isDataCompatible( aData ) )
207 : {
208 6 : aData = xInterpreter->reinterpretDataSeries( aData );
209 : }
210 : else
211 : {
212 9 : Reference< data::XDataSource > xSource( xInterpreter->mergeInterpretedData( aData ));
213 : // todo: get a "range-union" from the data provider by calling
214 : // OUString aRange = getRangeRepresentationByData( xSource );
215 : // xSource.set( getDataByRangeRepresentation( aRange, aParam ));
216 : // where aParam == ??
217 18 : Sequence< beans::PropertyValue > aParam;
218 9 : if( aData.Categories.is())
219 : {
220 7 : aParam.realloc( 1 );
221 14 : aParam[0] = beans::PropertyValue( "HasCategories", -1, uno::makeAny( true ),
222 7 : beans::PropertyState_DIRECT_VALUE );
223 : }
224 18 : aData = xInterpreter->interpretDataSource( xSource, aParam, aFlatSeriesSeq );
225 : }
226 15 : aSeriesSeq = aData.Series;
227 :
228 15 : sal_Int32 i, j, nIndex = 0;
229 30 : for( i=0; i<aSeriesSeq.getLength(); ++i )
230 118 : for( j=0; j<aSeriesSeq[i].getLength(); ++j, ++nIndex )
231 : {
232 103 : if( nIndex >= nFormerSeriesCount )
233 16 : lcl_applyDefaultStyle( aSeriesSeq[i][j], nIndex, xDiagram );
234 : }
235 :
236 : // remove charttype groups from all coordinate systems
237 : Sequence< Reference< XChartType > > aOldChartTypesSeq(
238 30 : DiagramHelper::getChartTypesFromDiagram(xDiagram) );
239 :
240 30 : Reference< XCoordinateSystemContainer > xCoordSysCnt( xDiagram, uno::UNO_QUERY );
241 : OSL_ASSERT( xCoordSysCnt.is());
242 15 : if( xCoordSysCnt.is())
243 : {
244 : Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
245 15 : xCoordSysCnt->getCoordinateSystems());
246 30 : for( sal_Int32 nCooSysIdx = 0; nCooSysIdx < aCooSysSeq.getLength(); ++nCooSysIdx )
247 : {
248 15 : Reference< XChartTypeContainer > xContainer( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
249 15 : if( xContainer.is() )
250 15 : xContainer->setChartTypes( Sequence< Reference< XChartType > >() );
251 30 : }
252 : }
253 :
254 30 : FillDiagram( xDiagram, aSeriesSeq, aData.Categories, aOldChartTypesSeq, false );
255 : }
256 0 : catch( const uno::Exception & ex )
257 : {
258 : ASSERT_EXCEPTION( ex );
259 : }
260 : }
261 :
262 27 : void SAL_CALL ChartTypeTemplate::changeDiagramData(
263 : const Reference< chart2::XDiagram >& xDiagram,
264 : const Reference< chart2::data::XDataSource >& xDataSource,
265 : const Sequence< beans::PropertyValue >& aArguments )
266 : throw (uno::RuntimeException, std::exception)
267 : {
268 54 : if( ! (xDiagram.is() &&
269 27 : xDataSource.is()) )
270 27 : return;
271 :
272 : try
273 : {
274 : // interpret new data and re-use existing series
275 : Sequence< Reference< XDataSeries > > aFlatSeriesSeq(
276 27 : ::chart::ContainerHelper::ContainerToSequence( DiagramHelper::getDataSeriesFromDiagram( xDiagram )));
277 27 : const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.getLength();
278 54 : Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter());
279 : chart2::InterpretedData aData =
280 54 : xInterpreter->interpretDataSource( xDataSource, aArguments, aFlatSeriesSeq );
281 :
282 : // data series
283 54 : Sequence< Sequence< Reference< XDataSeries > > > aSeriesSeq( aData.Series );
284 :
285 27 : sal_Int32 i, j, nIndex = 0;
286 56 : for( i=0; i<aSeriesSeq.getLength(); ++i )
287 223 : for( j=0; j<aSeriesSeq[i].getLength(); ++j, ++nIndex )
288 : {
289 194 : if( nIndex >= nFormerSeriesCount )
290 : {
291 61 : lcl_applyDefaultStyle( aSeriesSeq[i][j], nIndex, xDiagram );
292 61 : applyStyle( aSeriesSeq[i][j], i, j, aSeriesSeq[i].getLength() );
293 : }
294 : }
295 :
296 : // categories
297 27 : DiagramHelper::setCategoriesToDiagram( aData.Categories, xDiagram, true, supportsCategories() );
298 :
299 : Sequence< Reference< XChartType > > aChartTypes(
300 54 : DiagramHelper::getChartTypesFromDiagram( xDiagram ));
301 27 : sal_Int32 nMax = ::std::min( aChartTypes.getLength(), aSeriesSeq.getLength());
302 56 : for( i=0; i<nMax; ++i )
303 : {
304 29 : Reference< XDataSeriesContainer > xDSCnt( aChartTypes[i], uno::UNO_QUERY_THROW );
305 29 : xDSCnt->setDataSeries( aSeriesSeq[i] );
306 56 : }
307 : #if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL
308 : OSL_TRACE( "ChartTypeTemplate::changeDiagramData: Showing Diagram structure" );
309 : ::chart::debug::ChartDebugTraceDiagram( xDiagram );
310 : #endif
311 : }
312 0 : catch( const uno::Exception & ex )
313 : {
314 : ASSERT_EXCEPTION( ex );
315 : }
316 : }
317 :
318 56318 : sal_Bool SAL_CALL ChartTypeTemplate::matchesTemplate(
319 : const Reference< chart2::XDiagram >& xDiagram,
320 : sal_Bool /* bAdaptProperties */ )
321 : throw (uno::RuntimeException, std::exception)
322 : {
323 56318 : sal_Bool bResult = sal_False;
324 :
325 56318 : if( ! xDiagram.is())
326 0 : return bResult;
327 :
328 : try
329 : {
330 : Reference< XCoordinateSystemContainer > xCooSysCnt(
331 56318 : xDiagram, uno::UNO_QUERY_THROW );
332 : Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
333 112636 : xCooSysCnt->getCoordinateSystems());
334 :
335 : // need to have at least one coordinate system
336 56318 : bResult = (aCooSysSeq.getLength() > 0);
337 56318 : if( bResult )
338 : {
339 56318 : Sequence< Reference< XChartType > > aFormerlyUsedChartTypes;
340 112636 : Reference<XChartType> xOldCT = getChartTypeForNewSeries(aFormerlyUsedChartTypes);
341 56318 : if (!xOldCT.is())
342 0 : return false;
343 :
344 112636 : const OUString aChartTypeToMatch = xOldCT->getChartType();
345 56318 : const sal_Int32 nDimensionToMatch = getDimension();
346 112636 : for( sal_Int32 nCooSysIdx=0; bResult && (nCooSysIdx < aCooSysSeq.getLength()); ++nCooSysIdx )
347 : {
348 : // match dimension
349 56318 : bResult = bResult && (aCooSysSeq[nCooSysIdx]->getDimension() == nDimensionToMatch);
350 :
351 56318 : Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
352 112636 : Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
353 79815 : for( sal_Int32 nCTIdx=0; bResult && (nCTIdx < aChartTypeSeq.getLength()); ++nCTIdx )
354 : {
355 23497 : if (!aChartTypeSeq[nCTIdx].is())
356 0 : return false;
357 :
358 : // match chart type
359 23497 : bResult = bResult && aChartTypeSeq[nCTIdx]->getChartType().equals( aChartTypeToMatch );
360 23497 : bool bFound=false;
361 23497 : bool bAmbiguous=false;
362 : // match stacking mode
363 29850 : bResult = bResult &&
364 : ( DiagramHelper::getStackModeFromChartType(
365 6353 : aChartTypeSeq[nCTIdx], bFound, bAmbiguous,
366 12706 : aCooSysSeq[nCooSysIdx] )
367 29850 : == getStackMode( nCTIdx ) );
368 : }
369 112636 : }
370 56318 : }
371 : }
372 0 : catch( const uno::Exception & ex )
373 : {
374 : ASSERT_EXCEPTION( ex );
375 : }
376 :
377 56318 : return bResult;
378 : }
379 :
380 231 : Reference< chart2::XDataInterpreter > SAL_CALL ChartTypeTemplate::getDataInterpreter()
381 : throw (uno::RuntimeException, std::exception)
382 : {
383 231 : if( ! m_xDataInterpreter.is())
384 231 : m_xDataInterpreter.set( new DataInterpreter( GetComponentContext() ) );
385 :
386 231 : return m_xDataInterpreter;
387 : }
388 :
389 566 : void SAL_CALL ChartTypeTemplate::applyStyle(
390 : const Reference< chart2::XDataSeries >& xSeries,
391 : ::sal_Int32 nChartTypeIndex,
392 : ::sal_Int32 /* nSeriesIndex */,
393 : ::sal_Int32 /* nSeriesCount */ )
394 : throw (uno::RuntimeException, std::exception)
395 : {
396 : // sset stacking mode
397 566 : Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
398 566 : if( xSeriesProp.is())
399 : {
400 : try
401 : {
402 566 : StackMode eStackMode = getStackMode( nChartTypeIndex );
403 : const uno::Any aPropValue = uno::makeAny(
404 566 : ( (eStackMode == StackMode_Y_STACKED) ||
405 : (eStackMode == StackMode_Y_STACKED_PERCENT) )
406 : ? chart2::StackingDirection_Y_STACKING
407 : : (eStackMode == StackMode_Z_STACKED )
408 : ? chart2::StackingDirection_Z_STACKING
409 1132 : : chart2::StackingDirection_NO_STACKING );
410 566 : xSeriesProp->setPropertyValue( "StackingDirection", aPropValue );
411 :
412 : //ensure valid label placement
413 : {
414 : uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
415 566 : getChartTypeForIndex( nChartTypeIndex ), getDimension(), isSwapXAndY(), xSeries ) );
416 566 : lcl_ensureCorrectLabelPlacement( xSeriesProp, aAvailablePlacements );
417 :
418 1132 : uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
419 566 : if( xSeriesProp->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
420 1132 : for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
421 566 : lcl_ensureCorrectLabelPlacement( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), aAvailablePlacements );
422 566 : }
423 : }
424 0 : catch( const uno::Exception & ex )
425 : {
426 : ASSERT_EXCEPTION( ex );
427 : }
428 566 : }
429 566 : }
430 :
431 232 : void SAL_CALL ChartTypeTemplate::applyStyles( const Reference< chart2::XDiagram >& xDiagram )
432 : throw (uno::RuntimeException)
433 : {
434 : // apply chart-type specific styles, like "symbols on" for example
435 : Sequence< Sequence< Reference< XDataSeries > > > aNewSeriesSeq(
436 232 : DiagramHelper::getDataSeriesGroups( xDiagram ));
437 464 : for( sal_Int32 i=0; i<aNewSeriesSeq.getLength(); ++i )
438 : {
439 232 : const sal_Int32 nNumSeries = aNewSeriesSeq[i].getLength();
440 737 : for( sal_Int32 j=0; j<nNumSeries; ++j )
441 505 : applyStyle( aNewSeriesSeq[i][j], i, j, nNumSeries );
442 : }
443 :
444 : //ensure valid empty cell handling (for first chart type...)
445 232 : lcl_ensureCorrectMissingValueTreatment( xDiagram, getChartTypeForIndex( 0 ) );
446 232 : }
447 :
448 13 : void SAL_CALL ChartTypeTemplate::resetStyles( const Reference< chart2::XDiagram >& xDiagram )
449 : throw (uno::RuntimeException, std::exception)
450 : {
451 : // reset number format if we had percent stacking on
452 13 : sal_Bool bPercent = (getStackMode(0) == StackMode_Y_STACKED_PERCENT);
453 13 : if( bPercent )
454 : {
455 0 : Sequence< Reference< chart2::XAxis > > aAxisSeq( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
456 0 : for( sal_Int32 i=0; i<aAxisSeq.getLength(); ++i )
457 : {
458 0 : if( 1== AxisHelper::getDimensionIndexOfAxis( aAxisSeq[i], xDiagram ) )
459 : {
460 0 : Reference< beans::XPropertySet > xAxisProp( aAxisSeq[i], uno::UNO_QUERY );
461 0 : if( xAxisProp.is())
462 : {
463 : // set number format to source format
464 0 : uno::Any aValue( xAxisProp->getPropertyValue("NumberFormat"));
465 0 : if( aValue.hasValue())
466 0 : xAxisProp->setPropertyValue("NumberFormat", uno::Any());
467 0 : }
468 : }
469 0 : }
470 : }
471 :
472 : //reset label placement if default
473 : {
474 13 : uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
475 13 : if( xCooSysContainer.is() )
476 : {
477 13 : uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
478 26 : for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
479 : {
480 13 : uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
481 :
482 : //iterate through all chart types in the current coordinate system
483 26 : uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
484 : OSL_ASSERT( xChartTypeContainer.is());
485 13 : if( !xChartTypeContainer.is() )
486 0 : continue;
487 26 : uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
488 26 : for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
489 : {
490 13 : uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
491 :
492 : //iterate through all series in this chart type
493 26 : uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
494 : OSL_ASSERT( xDataSeriesContainer.is());
495 13 : if( !xDataSeriesContainer.is() )
496 0 : continue;
497 :
498 26 : uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
499 116 : for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
500 : {
501 103 : Reference< XDataSeries > xSeries(aSeriesList[nS]);
502 206 : Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
503 103 : if(!xSeries.is() || !xSeriesProp.is() )
504 0 : continue;
505 :
506 : uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
507 206 : xChartType, getDimension(), isSwapXAndY(), xSeries ) );
508 103 : if(!aAvailablePlacements.getLength())
509 0 : continue;
510 :
511 103 : sal_Int32 nDefaultPlacement = aAvailablePlacements[0];
512 :
513 103 : lcl_resetLabelPlacementIfDefault( xSeriesProp, nDefaultPlacement );
514 :
515 206 : uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
516 103 : if( xSeriesProp->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
517 206 : for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
518 0 : lcl_resetLabelPlacementIfDefault( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), nDefaultPlacement );
519 103 : }
520 13 : }
521 26 : }
522 13 : }
523 : }
524 :
525 13 : return;
526 : }
527 :
528 : // ____ XServiceName ____
529 0 : OUString SAL_CALL ChartTypeTemplate::getServiceName()
530 : throw (uno::RuntimeException, std::exception)
531 : {
532 0 : return m_aServiceName;
533 : }
534 :
535 15745 : sal_Int32 ChartTypeTemplate::getDimension() const
536 : {
537 15745 : return 2;
538 : }
539 :
540 1071 : StackMode ChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
541 : {
542 1071 : return StackMode_NONE;
543 : }
544 :
545 113 : bool ChartTypeTemplate::isSwapXAndY() const
546 : {
547 113 : return false;
548 : }
549 :
550 232 : void ChartTypeTemplate::createCoordinateSystems(
551 : const Reference< chart2::XCoordinateSystemContainer > & xOutCooSysCnt )
552 : {
553 232 : if( ! xOutCooSysCnt.is())
554 13 : return;
555 232 : Sequence< Reference< XChartType > > aFormerlyUsedChartTypes;
556 451 : Reference< XChartType > xChartType( getChartTypeForNewSeries(aFormerlyUsedChartTypes));
557 232 : if( ! xChartType.is())
558 0 : return;
559 451 : Reference< XCoordinateSystem > xCooSys( xChartType->createCoordinateSystem( getDimension()));
560 232 : if( ! xCooSys.is())
561 : {
562 : // chart type wants no coordinate systems
563 0 : xOutCooSysCnt->setCoordinateSystems( Sequence< Reference< XCoordinateSystem > >());
564 0 : return;
565 : }
566 : // #i69680# make grid of first y-axis visible (was in the CooSys CTOR before)
567 232 : if( xCooSys->getDimension() >= 2 )
568 : {
569 232 : Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1, 0 ));
570 232 : if( xAxis.is())
571 232 : AxisHelper::makeGridVisible( xAxis->getGridProperties() );
572 : }
573 :
574 : Sequence< Reference< XCoordinateSystem > > aCoordinateSystems(
575 451 : xOutCooSysCnt->getCoordinateSystems());
576 :
577 232 : if( aCoordinateSystems.getLength())
578 : {
579 15 : bool bOk = true;
580 30 : for( sal_Int32 i=0; bOk && i<aCoordinateSystems.getLength(); ++i )
581 58 : bOk = bOk && ( xCooSys->getCoordinateSystemType().equals( aCoordinateSystems[i]->getCoordinateSystemType()) &&
582 28 : (xCooSys->getDimension() == aCoordinateSystems[i]->getDimension()) );
583 : // coordinate systems are ok
584 15 : if( bOk )
585 13 : return;
586 : // there are coordinate systems but they do not fit. So overwrite them.
587 : }
588 :
589 : //copy as much info from former coordinate system as possible:
590 219 : if( aCoordinateSystems.getLength() )
591 : {
592 2 : Reference< XCoordinateSystem > xOldCooSys( aCoordinateSystems[0] );
593 2 : sal_Int32 nMaxDimensionCount = std::min( xCooSys->getDimension(), xOldCooSys->getDimension() );
594 :
595 6 : for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nMaxDimensionCount; nDimensionIndex++)
596 : {
597 4 : const sal_Int32 nMaximumAxisIndex = xOldCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
598 8 : for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
599 : {
600 4 : uno::Reference< XAxis > xAxis( xOldCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
601 4 : if( xAxis.is())
602 : {
603 4 : xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
604 : }
605 4 : }
606 2 : }
607 : }
608 :
609 : // set new coordinate systems
610 219 : aCoordinateSystems.realloc( 1 );
611 219 : aCoordinateSystems[0] = xCooSys;
612 :
613 438 : xOutCooSysCnt->setCoordinateSystems( aCoordinateSystems );
614 : }
615 :
616 232 : void ChartTypeTemplate::adaptScales(
617 : const Sequence< Reference< chart2::XCoordinateSystem > > & aCooSysSeq,
618 : const Reference< data::XLabeledDataSequence > & xCategories //@todo: in future there may be more than one sequence of categories (e.g. charttype with categories at x and y axis )
619 : )
620 : {
621 232 : bool bSupportsCategories( supportsCategories() );
622 464 : for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
623 : {
624 : try
625 : {
626 232 : Reference< XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIdx] );
627 232 : if( !xCooSys.is() )
628 0 : continue;
629 :
630 : // attach categories to first axis
631 232 : sal_Int32 nDim( xCooSys->getDimension());
632 232 : if( nDim > 0 )
633 : {
634 232 : const sal_Int32 nDimensionX = 0;
635 232 : const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionX);
636 464 : for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
637 : {
638 232 : Reference< XAxis > xAxis( xCooSys->getAxisByDimension(nDimensionX,nI) );
639 232 : if( xAxis.is())
640 : {
641 232 : ScaleData aData( xAxis->getScaleData() );
642 232 : aData.Categories = xCategories;
643 232 : if(bSupportsCategories)
644 : {
645 :
646 212 : Reference< XChartType > xChartType( getChartTypeForNewSeries(Sequence< Reference< XChartType > >() ));
647 212 : bool bSupportsDates = ::chart::ChartTypeHelper::isSupportingDateAxis( xChartType, 2, nDimensionX );
648 212 : if( aData.AxisType != AxisType::CATEGORY && ( aData.AxisType != AxisType::DATE || !bSupportsDates) )
649 : {
650 12 : aData.AxisType = AxisType::CATEGORY;
651 12 : aData.AutoDateAxis = true;
652 12 : AxisHelper::removeExplicitScaling( aData );
653 212 : }
654 : }
655 : else
656 20 : aData.AxisType = AxisType::REALNUMBER;
657 :
658 232 : xAxis->setScaleData( aData );
659 : }
660 232 : }
661 : }
662 : // set percent stacking mode at second axis
663 232 : if( nDim > 1 )
664 : {
665 232 : const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(1);
666 464 : for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
667 : {
668 232 : Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1,nI ));
669 232 : if( xAxis.is())
670 : {
671 232 : bool bPercent = (getStackMode(0) == StackMode_Y_STACKED_PERCENT);
672 232 : chart2::ScaleData aScaleData = xAxis->getScaleData();
673 :
674 232 : if( bPercent != (aScaleData.AxisType==AxisType::PERCENT) )
675 : {
676 0 : if( bPercent )
677 0 : aScaleData.AxisType = AxisType::PERCENT;
678 : else
679 0 : aScaleData.AxisType = AxisType::REALNUMBER;
680 0 : xAxis->setScaleData( aScaleData );
681 232 : }
682 : }
683 232 : }
684 232 : }
685 : }
686 0 : catch( const uno::Exception & ex )
687 : {
688 : ASSERT_EXCEPTION( ex );
689 : }
690 : }
691 232 : }
692 :
693 221 : void ChartTypeTemplate::adaptDiagram( const Reference< XDiagram > & /* xDiagram */ )
694 : {
695 221 : return;
696 : }
697 :
698 232 : void ChartTypeTemplate::createAxes(
699 : const Sequence< Reference< XCoordinateSystem > > & rCoordSys )
700 : {
701 : //create missing axes
702 232 : if( rCoordSys.getLength() > 0 )
703 : {
704 232 : sal_Int32 nCooSysIdx = 0;
705 232 : Reference< XCoordinateSystem > xCooSys( rCoordSys[nCooSysIdx] );
706 232 : if(!xCooSys.is())
707 232 : return;
708 :
709 : //create main axis in first coordinate system
710 232 : sal_Int32 nDimCount = xCooSys->getDimension();
711 232 : sal_Int32 nDim=0;
712 696 : for( nDim=0; nDim<nDimCount; ++nDim )
713 : {
714 464 : sal_Int32 nAxisCount = getAxisCountByDimension( nDim );
715 696 : if( nDim == 1 &&
716 696 : nAxisCount < 2 && AxisHelper::isSecondaryYAxisNeeded( xCooSys ))
717 0 : nAxisCount = 2;
718 906 : for( sal_Int32 nAxisIndex = 0; nAxisIndex < nAxisCount; ++nAxisIndex )
719 : {
720 442 : Reference< XAxis > xAxis = AxisHelper::getAxis( nDim, nAxisIndex, xCooSys );
721 442 : if( !xAxis.is())
722 : {
723 : // create and add axis
724 : xAxis.set( AxisHelper::createAxis(
725 0 : nDim, nAxisIndex, xCooSys, GetComponentContext() ));
726 : }
727 442 : }
728 232 : }
729 : }
730 : }
731 :
732 221 : void ChartTypeTemplate::adaptAxes(
733 : const Sequence< Reference< XCoordinateSystem > > & rCoordSys )
734 : {
735 : //adapt properties of exsisting axes and remove superfluous axes
736 :
737 221 : if( rCoordSys.getLength() > 0 )
738 : {
739 442 : for( sal_Int32 nCooSysIdx=0; nCooSysIdx < rCoordSys.getLength(); ++nCooSysIdx )
740 : {
741 221 : Reference< XCoordinateSystem > xCooSys( rCoordSys[nCooSysIdx] );
742 221 : if( !xCooSys.is() )
743 0 : continue;
744 221 : sal_Int32 nDimCount = xCooSys->getDimension();
745 663 : for( sal_Int32 nDim=0; nDim<nDimCount; ++nDim )
746 : {
747 442 : sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension( nDim );
748 884 : for( sal_Int32 nAxisIndex=0; nAxisIndex<=nMaxAxisIndex; nAxisIndex++ )
749 : {
750 442 : Reference< XAxis > xAxis( AxisHelper::getAxis( nDim, nAxisIndex, xCooSys ) );
751 442 : if( !xAxis.is() )
752 0 : continue;
753 :
754 442 : if( nAxisIndex == MAIN_AXIS_INDEX || nAxisIndex == SECONDARY_AXIS_INDEX )
755 : {
756 : // adapt scales
757 442 : sal_Bool bPercent = (getStackMode(0) == StackMode_Y_STACKED_PERCENT);
758 442 : if( bPercent && nDim == 1 )
759 : {
760 0 : Reference< beans::XPropertySet > xAxisProp( xAxis, uno::UNO_QUERY );
761 0 : if( xAxisProp.is())
762 : {
763 : // set number format to source format
764 0 : uno::Any aValue( xAxisProp->getPropertyValue("NumberFormat"));
765 0 : if( aValue.hasValue())
766 0 : xAxisProp->setPropertyValue("NumberFormat", uno::Any());
767 0 : }
768 : }
769 : }
770 442 : }
771 : }
772 221 : }
773 : }
774 221 : }
775 :
776 430 : sal_Int32 ChartTypeTemplate::getAxisCountByDimension( sal_Int32 nDimension )
777 : {
778 430 : return (nDimension < getDimension()) ? 1 : 0;
779 : }
780 :
781 232 : void ChartTypeTemplate::FillDiagram(
782 : const Reference< XDiagram >& xDiagram,
783 : const Sequence< Sequence< Reference< XDataSeries > > >& aSeriesSeq,
784 : Reference< data::XLabeledDataSequence > xCategories,
785 : const Sequence< Reference< XChartType > >& aOldChartTypesSeq,
786 : bool /* bCreate */ )
787 : {
788 232 : adaptDiagram( xDiagram );
789 :
790 : try
791 : {
792 : // create coordinate systems and scales
793 232 : Reference< XCoordinateSystemContainer > xCoordSysCnt( xDiagram, uno::UNO_QUERY_THROW );
794 232 : createCoordinateSystems( xCoordSysCnt );
795 464 : Sequence< Reference< XCoordinateSystem > > aCoordinateSystems( xCoordSysCnt->getCoordinateSystems());
796 232 : createAxes( aCoordinateSystems );
797 232 : adaptAxes( aCoordinateSystems );
798 232 : adaptScales( aCoordinateSystems, xCategories );
799 :
800 : // chart types
801 232 : createChartTypes( aSeriesSeq, aCoordinateSystems, aOldChartTypesSeq );
802 464 : applyStyles( xDiagram );
803 : }
804 0 : catch( const uno::Exception & ex )
805 : {
806 : ASSERT_EXCEPTION( ex );
807 : }
808 :
809 : #if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL
810 : OSL_TRACE( "ChartTypeTemplate::FillDiagram: Showing Diagram structure" );
811 : ::chart::debug::ChartDebugTraceDiagram( xDiagram );
812 : #endif
813 232 : }
814 :
815 215 : void ChartTypeTemplate::createChartTypes(
816 : const Sequence< Sequence< Reference< XDataSeries > > > & aSeriesSeq,
817 : const Sequence< Reference< XCoordinateSystem > > & rCoordSys,
818 : const Sequence< Reference< XChartType > >& aOldChartTypesSeq )
819 : {
820 430 : if( rCoordSys.getLength() == 0 ||
821 215 : ! rCoordSys[0].is() )
822 215 : return;
823 :
824 : try
825 : {
826 215 : sal_Int32 nCooSysIdx=0;
827 215 : Reference< XChartType > xCT;
828 215 : if( aSeriesSeq.getLength() == 0 )
829 : {
830 : // we need a new chart type
831 72 : xCT.set( getChartTypeForNewSeries( aOldChartTypesSeq ));
832 72 : Reference< XChartTypeContainer > xCTCnt( rCoordSys[nCooSysIdx], uno::UNO_QUERY_THROW );
833 144 : Sequence< Reference< XChartType > > aCTSeq( xCTCnt->getChartTypes());
834 72 : aCTSeq.realloc( 1 );
835 72 : aCTSeq[0] = xCT;
836 144 : xCTCnt->setChartTypes( aCTSeq );
837 : }
838 : else
839 : {
840 286 : for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
841 : {
842 143 : if( nSeriesIdx == nCooSysIdx )
843 : {
844 : // we need a new chart type
845 143 : xCT.set( getChartTypeForNewSeries( aOldChartTypesSeq ));
846 143 : Reference< XChartTypeContainer > xCTCnt( rCoordSys[nCooSysIdx], uno::UNO_QUERY_THROW );
847 286 : Sequence< Reference< XChartType > > aCTSeq( xCTCnt->getChartTypes());
848 143 : if( aCTSeq.getLength())
849 : {
850 0 : aCTSeq[0] = xCT;
851 0 : xCTCnt->setChartTypes( aCTSeq );
852 : }
853 : else
854 143 : xCTCnt->addChartType( xCT );
855 :
856 286 : Reference< chart2::XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW );
857 286 : xDSCnt->setDataSeries( aSeriesSeq[nSeriesIdx] );
858 : }
859 : else
860 : {
861 : // reuse existing chart type
862 : OSL_ASSERT( xCT.is());
863 0 : Reference< chart2::XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW );
864 0 : Sequence< Reference< XDataSeries > > aNewSeriesSeq( xDSCnt->getDataSeries());
865 0 : sal_Int32 nNewStartIndex = aNewSeriesSeq.getLength();
866 0 : aNewSeriesSeq.realloc( nNewStartIndex + aSeriesSeq[nSeriesIdx].getLength() );
867 0 : ::std::copy( aSeriesSeq[nSeriesIdx].getConstArray(),
868 0 : aSeriesSeq[nSeriesIdx].getConstArray() + aSeriesSeq[nSeriesIdx].getLength(),
869 0 : aNewSeriesSeq.getArray() + nNewStartIndex );
870 0 : xDSCnt->setDataSeries( aNewSeriesSeq );
871 : }
872 :
873 : // spread the series over the available coordinate systems
874 143 : if( rCoordSys.getLength() > (nCooSysIdx + 1) )
875 0 : ++nCooSysIdx;
876 : }
877 215 : }
878 : }
879 0 : catch( const uno::Exception & ex )
880 : {
881 : ASSERT_EXCEPTION( ex );
882 : }
883 : }
884 :
885 54443 : void ChartTypeTemplate::copyPropertiesFromOldToNewCoordianteSystem(
886 : const Sequence< Reference< XChartType > > & rOldChartTypesSeq,
887 : const Reference< XChartType > & xNewChartType )
888 : {
889 54443 : Reference< beans::XPropertySet > xDestination( xNewChartType, uno::UNO_QUERY );
890 54443 : if( !xDestination.is() )
891 54443 : return;
892 :
893 108886 : OUString aNewChartType( xNewChartType->getChartType() );
894 :
895 108886 : Reference< beans::XPropertySet > xSource;
896 54443 : sal_Int32 nN=0;
897 54452 : for( nN=0; nN<rOldChartTypesSeq.getLength();++nN)
898 : {
899 9 : Reference< XChartType > xOldType( rOldChartTypesSeq[nN] );
900 9 : if( xOldType.is() && xOldType->getChartType().equals( aNewChartType ) )
901 : {
902 0 : xSource.set( Reference< beans::XPropertySet >(xOldType, uno::UNO_QUERY ) );
903 0 : if( xSource.is() )
904 0 : break;
905 : }
906 9 : }
907 54443 : if( xSource.is() )
908 54443 : comphelper::copyProperties( xSource, xDestination );
909 : }
910 :
911 58485 : Reference< uno::XComponentContext > ChartTypeTemplate::GetComponentContext() const
912 : {
913 58485 : return m_xContext;
914 : }
915 :
916 : } // namespace chart
917 :
918 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|