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