merged tag ooo/OOO330_m14
[LibreOffice.git] / chart2 / source / model / template / ChartTypeTemplate.cxx
blobe3943e9eb45fcb8589f0659df807af8725f54c1f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 #include "ChartTypeTemplate.hxx"
31 #include "PropertyHelper.hxx"
32 #include "macros.hxx"
33 #include "DataSeriesHelper.hxx"
34 #include "DataInterpreter.hxx"
35 #include "CommonConverters.hxx"
36 #include "ContainerHelper.hxx"
37 #include "ChartTypeHelper.hxx"
39 #include "CartesianCoordinateSystem.hxx"
40 #include "AxisHelper.hxx"
41 #include "LegendHelper.hxx"
42 #include "DiagramHelper.hxx"
43 #include "ChartDebugTrace.hxx"
44 #include "AxisIndexDefines.hxx"
45 #include <cppuhelper/component_context.hxx>
46 #include <com/sun/star/chart/ChartSolidType.hpp>
47 #include <com/sun/star/chart2/AxisType.hpp>
48 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
49 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
50 #include <com/sun/star/chart2/AxisType.hpp>
52 #include <algorithm>
53 #include <iterator>
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::chart2;
58 using ::rtl::OUString;
59 using ::com::sun::star::uno::Sequence;
60 using ::com::sun::star::uno::Reference;
61 using ::com::sun::star::uno::Any;
63 // ======================================================================
65 namespace
68 void lcl_applyDefaultStyle(
69 const Reference< XDataSeries > & xSeries,
70 sal_Int32 nIndex,
71 const Reference< XDiagram > & xDiagram )
73 // @deprecated: correct default color should be found by view without
74 // setting color as hard attribute
75 if( xSeries.is() && xDiagram.is())
77 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
78 Reference< chart2::XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
79 if( xSeriesProp.is() && xColorScheme.is() )
80 xSeriesProp->setPropertyValue(
81 C2U("Color"),
82 uno::makeAny( xColorScheme->getColorByIndex( nIndex )));
86 void lcl_ensureCorrectLabelPlacement( const Reference< beans::XPropertySet >& xProp, const uno::Sequence < sal_Int32 >& rAvailablePlacements )
88 sal_Int32 nLabelPlacement=0;
89 if( xProp.is() && (xProp->getPropertyValue( C2U( "LabelPlacement" ) ) >>= nLabelPlacement) )
91 bool bValid = false;
92 for( sal_Int32 nN = 0; nN < rAvailablePlacements.getLength(); nN++ )
94 if( rAvailablePlacements[nN] == nLabelPlacement )
96 bValid = true;
97 break;
100 if( !bValid )
102 uno::Any aNewValue;
103 //otherwise use the first supported one
104 if( rAvailablePlacements.getLength() )
105 aNewValue <<=rAvailablePlacements[0];
106 xProp->setPropertyValue( C2U("LabelPlacement"), aNewValue );
111 void lcl_resetLabelPlacementIfDefault( const Reference< beans::XPropertySet >& xProp, sal_Int32 nDefaultPlacement )
114 sal_Int32 nLabelPlacement=0;
115 if( xProp.is() && (xProp->getPropertyValue( C2U( "LabelPlacement" ) ) >>= nLabelPlacement) )
117 if( nDefaultPlacement == nLabelPlacement )
118 xProp->setPropertyValue( C2U("LabelPlacement"), uno::Any() );
122 void lcl_ensureCorrectMissingValueTreatment( const Reference< chart2::XDiagram >& xDiagram, const Reference< XChartType >& xChartType )
124 Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
125 if( xDiaProp.is() )
127 uno::Sequence < sal_Int32 > aAvailableMissingValueTreatment(
128 ::chart::ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) );
130 if( aAvailableMissingValueTreatment.getLength() )
131 xDiaProp->setPropertyValue( C2U( "MissingValueTreatment" ), uno::makeAny( aAvailableMissingValueTreatment[0] ) );
132 else
133 xDiaProp->setPropertyValue( C2U( "MissingValueTreatment" ), uno::Any() );
137 } // anonymous namespace
139 namespace chart
142 ChartTypeTemplate::ChartTypeTemplate(
143 Reference< uno::XComponentContext > const & xContext,
144 const ::rtl::OUString & rServiceName ) :
145 m_xContext( xContext ),
146 m_aServiceName( rServiceName )
150 ChartTypeTemplate::~ChartTypeTemplate()
153 // ____ XChartTypeTemplate ____
154 uno::Reference< XDiagram > SAL_CALL ChartTypeTemplate::createDiagramByDataSource(
155 const uno::Reference< data::XDataSource >& xDataSource,
156 const uno::Sequence< beans::PropertyValue >& aArguments )
157 throw (uno::RuntimeException)
159 Reference< XDiagram > xDia;
163 // create diagram
164 xDia.set(
165 GetComponentContext()->getServiceManager()->createInstanceWithContext(
166 C2U( "com.sun.star.chart2.Diagram" ),
167 GetComponentContext() ),
168 uno::UNO_QUERY_THROW );
170 // modify diagram
171 Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter());
172 chart2::InterpretedData aData(
173 xInterpreter->interpretDataSource(
174 xDataSource, aArguments, Sequence< Reference< XDataSeries > >() ));
176 Sequence< Sequence< Reference< XDataSeries > > > aSeries( aData.Series );
177 sal_Int32 i, j, nCount = 0;
178 for( i=0; i<aSeries.getLength(); ++i )
180 for( j=0; j<aSeries[i].getLength(); ++j, ++nCount )
181 lcl_applyDefaultStyle( aSeries[i][j], nCount, xDia );
184 Sequence< Reference< XChartType > > aOldChartTypesSeq;
185 FillDiagram( xDia, aData.Series, aData.Categories, aOldChartTypesSeq, true );
187 catch( uno::Exception & ex )
189 ASSERT_EXCEPTION( ex );
192 return xDia;
195 sal_Bool SAL_CALL ChartTypeTemplate::supportsCategories()
196 throw (uno::RuntimeException)
198 return sal_True;
201 void SAL_CALL ChartTypeTemplate::changeDiagram( const uno::Reference< XDiagram >& xDiagram )
202 throw (uno::RuntimeException)
204 if( ! xDiagram.is())
205 return;
209 Sequence< Sequence< Reference< XDataSeries > > > aSeriesSeq(
210 DiagramHelper::getDataSeriesGroups( xDiagram ));
211 Sequence< Reference< XDataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq ));
212 const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.getLength();
214 // chart-type specific interpretation of existing data series
215 Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter());
216 chart2::InterpretedData aData;
217 aData.Series = aSeriesSeq;
218 aData.Categories = DiagramHelper::getCategoriesFromDiagram( xDiagram );
220 if( xInterpreter->isDataCompatible( aData ) )
222 aData = xInterpreter->reinterpretDataSeries( aData );
224 else
226 Reference< data::XDataSource > xSource( xInterpreter->mergeInterpretedData( aData ));
227 // todo: get a "range-union" from the data provider by calling
228 // OUString aRange = getRangeRepresentationByData( xSource );
229 // xSource.set( getDataByRangeRepresentation( aRange, aParam ));
230 // where aParam == ??
231 Sequence< beans::PropertyValue > aParam;
232 if( aData.Categories.is())
234 aParam.realloc( 1 );
235 aParam[0] = beans::PropertyValue( C2U("HasCategories"), -1, uno::makeAny( true ),
236 beans::PropertyState_DIRECT_VALUE );
238 aData = xInterpreter->interpretDataSource( xSource, aParam, aFlatSeriesSeq );
240 aSeriesSeq = aData.Series;
242 sal_Int32 i, j, nIndex = 0;
243 for( i=0; i<aSeriesSeq.getLength(); ++i )
244 for( j=0; j<aSeriesSeq[i].getLength(); ++j, ++nIndex )
246 if( nIndex >= nFormerSeriesCount )
247 lcl_applyDefaultStyle( aSeriesSeq[i][j], nIndex, xDiagram );
250 // remove charttype groups from all coordinate systems
251 Sequence< Reference< XChartType > > aOldChartTypesSeq(
252 DiagramHelper::getChartTypesFromDiagram(xDiagram) );
254 Reference< XCoordinateSystemContainer > xCoordSysCnt( xDiagram, uno::UNO_QUERY );
255 OSL_ASSERT( xCoordSysCnt.is());
256 if( xCoordSysCnt.is())
258 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
259 xCoordSysCnt->getCoordinateSystems());
260 for( sal_Int32 nCooSysIdx = 0; nCooSysIdx < aCooSysSeq.getLength(); ++nCooSysIdx )
262 Reference< XChartTypeContainer > xContainer( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
263 if( xContainer.is() )
264 xContainer->setChartTypes( Sequence< Reference< XChartType > >() );
268 FillDiagram( xDiagram, aSeriesSeq, aData.Categories, aOldChartTypesSeq, false );
270 catch( uno::Exception & ex )
272 ASSERT_EXCEPTION( ex );
276 void SAL_CALL ChartTypeTemplate::changeDiagramData(
277 const Reference< chart2::XDiagram >& xDiagram,
278 const Reference< chart2::data::XDataSource >& xDataSource,
279 const Sequence< beans::PropertyValue >& aArguments )
280 throw (uno::RuntimeException)
282 if( ! (xDiagram.is() &&
283 xDataSource.is()) )
284 return;
288 // interpret new data and re-use existing series
289 Sequence< Reference< XDataSeries > > aFlatSeriesSeq(
290 ::chart::ContainerHelper::ContainerToSequence( DiagramHelper::getDataSeriesFromDiagram( xDiagram )));
291 const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.getLength();
292 Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter());
293 chart2::InterpretedData aData =
294 xInterpreter->interpretDataSource( xDataSource, aArguments, aFlatSeriesSeq );
296 // data series
297 Sequence< Sequence< Reference< XDataSeries > > > aSeriesSeq( aData.Series );
299 sal_Int32 i, j, nIndex = 0;
300 for( i=0; i<aSeriesSeq.getLength(); ++i )
301 for( j=0; j<aSeriesSeq[i].getLength(); ++j, ++nIndex )
303 if( nIndex >= nFormerSeriesCount )
305 lcl_applyDefaultStyle( aSeriesSeq[i][j], nIndex, xDiagram );
306 applyStyle( aSeriesSeq[i][j], i, j, aSeriesSeq[i].getLength() );
310 // categories
311 DiagramHelper::setCategoriesToDiagram( aData.Categories, xDiagram, true, supportsCategories() );
313 Sequence< Reference< XChartType > > aChartTypes(
314 DiagramHelper::getChartTypesFromDiagram( xDiagram ));
315 sal_Int32 nMax = ::std::min( aChartTypes.getLength(), aSeriesSeq.getLength());
316 for( i=0; i<nMax; ++i )
318 Reference< XDataSeriesContainer > xDSCnt( aChartTypes[i], uno::UNO_QUERY_THROW );
319 xDSCnt->setDataSeries( aSeriesSeq[i] );
321 #if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL
322 OSL_TRACE( "ChartTypeTemplate::changeDiagramData: Showing Diagram structure" );
323 OSL_TRACE( "---------------------------------------------------------------" );
324 debug::ChartDebugTraceDiagram( xDiagram );
325 #endif
327 catch( uno::Exception & ex )
329 ASSERT_EXCEPTION( ex );
333 sal_Bool SAL_CALL ChartTypeTemplate::matchesTemplate(
334 const Reference< chart2::XDiagram >& xDiagram,
335 sal_Bool /* bAdaptProperties */ )
336 throw (uno::RuntimeException)
338 sal_Bool bResult = sal_False;
340 if( ! xDiagram.is())
341 return bResult;
345 Reference< XCoordinateSystemContainer > xCooSysCnt(
346 xDiagram, uno::UNO_QUERY_THROW );
347 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
348 xCooSysCnt->getCoordinateSystems());
350 // need to have at least one coordinate system
351 bResult = (aCooSysSeq.getLength() > 0);
352 if( bResult )
354 Sequence< Reference< XChartType > > aFormerlyUsedChartTypes;
355 const OUString aChartTypeToMatch( getChartTypeForNewSeries(aFormerlyUsedChartTypes)->getChartType());
356 const sal_Int32 nDimensionToMatch = getDimension();
357 for( sal_Int32 nCooSysIdx=0; bResult && (nCooSysIdx < aCooSysSeq.getLength()); ++nCooSysIdx )
359 // match dimension
360 bResult = bResult && (aCooSysSeq[nCooSysIdx]->getDimension() == nDimensionToMatch);
362 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
363 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
364 for( sal_Int32 nCTIdx=0; bResult && (nCTIdx < aChartTypeSeq.getLength()); ++nCTIdx )
366 // match chart type
367 bResult = bResult && aChartTypeSeq[nCTIdx]->getChartType().equals( aChartTypeToMatch );
368 bool bFound=false;
369 bool bAmbiguous=false;
370 // match stacking mode
371 bResult = bResult &&
372 ( DiagramHelper::getStackModeFromChartType(
373 aChartTypeSeq[nCTIdx], bFound, bAmbiguous,
374 aCooSysSeq[nCooSysIdx] )
375 == getStackMode( nCTIdx ) );
380 catch( uno::Exception & ex )
382 ASSERT_EXCEPTION( ex );
385 return bResult;
388 Reference< chart2::XDataInterpreter > SAL_CALL ChartTypeTemplate::getDataInterpreter()
389 throw (uno::RuntimeException)
391 if( ! m_xDataInterpreter.is())
392 m_xDataInterpreter.set( new DataInterpreter( GetComponentContext() ) );
394 return m_xDataInterpreter;
397 void SAL_CALL ChartTypeTemplate::applyStyle(
398 const Reference< chart2::XDataSeries >& xSeries,
399 ::sal_Int32 nChartTypeIndex,
400 ::sal_Int32 /* nSeriesIndex */,
401 ::sal_Int32 /* nSeriesCount */ )
402 throw (uno::RuntimeException)
404 // sset stacking mode
405 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
406 if( xSeriesProp.is())
410 StackMode eStackMode = getStackMode( nChartTypeIndex );
411 const uno::Any aPropValue = uno::makeAny(
412 ( (eStackMode == StackMode_Y_STACKED) ||
413 (eStackMode == StackMode_Y_STACKED_PERCENT) )
414 ? chart2::StackingDirection_Y_STACKING
415 : (eStackMode == StackMode_Z_STACKED )
416 ? chart2::StackingDirection_Z_STACKING
417 : chart2::StackingDirection_NO_STACKING );
418 xSeriesProp->setPropertyValue( C2U("StackingDirection"), aPropValue );
420 //ensure valid label placement
422 uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
423 getChartTypeForIndex( nChartTypeIndex ), getDimension(), isSwapXAndY(), xSeries ) );
424 lcl_ensureCorrectLabelPlacement( xSeriesProp, aAvailablePlacements );
426 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
427 if( xSeriesProp->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
428 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
429 lcl_ensureCorrectLabelPlacement( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), aAvailablePlacements );
432 catch( const uno::Exception & ex )
434 ASSERT_EXCEPTION( ex );
439 void SAL_CALL ChartTypeTemplate::applyStyles( const Reference< chart2::XDiagram >& xDiagram )
440 throw (uno::RuntimeException)
442 // apply chart-type specific styles, like "symbols on" for example
443 Sequence< Sequence< Reference< XDataSeries > > > aNewSeriesSeq(
444 DiagramHelper::getDataSeriesGroups( xDiagram ));
445 for( sal_Int32 i=0; i<aNewSeriesSeq.getLength(); ++i )
447 const sal_Int32 nNumSeries = aNewSeriesSeq[i].getLength();
448 for( sal_Int32 j=0; j<nNumSeries; ++j )
449 applyStyle( aNewSeriesSeq[i][j], i, j, nNumSeries );
452 //ensure valid empty cell handling (for first chart type...)
453 lcl_ensureCorrectMissingValueTreatment( xDiagram, getChartTypeForIndex( 0 ) );
456 void SAL_CALL ChartTypeTemplate::resetStyles( const Reference< chart2::XDiagram >& xDiagram )
457 throw (uno::RuntimeException)
459 // reset number format if we had percent stacking on
460 sal_Bool bPercent = (getStackMode(0) == StackMode_Y_STACKED_PERCENT);
461 if( bPercent )
463 Sequence< Reference< chart2::XAxis > > aAxisSeq( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
464 for( sal_Int32 i=0; i<aAxisSeq.getLength(); ++i )
466 if( 1== AxisHelper::getDimensionIndexOfAxis( aAxisSeq[i], xDiagram ) )
468 Reference< beans::XPropertySet > xAxisProp( aAxisSeq[i], uno::UNO_QUERY );
469 if( xAxisProp.is())
471 // set number format to source format
472 uno::Any aValue( xAxisProp->getPropertyValue(C2U("NumberFormat")));
473 if( aValue.hasValue())
474 xAxisProp->setPropertyValue(C2U("NumberFormat"), uno::Any());
480 //reset label placement if default
482 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
483 if( xCooSysContainer.is() )
485 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
486 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
488 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
490 //iterate through all chart types in the current coordinate system
491 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
492 OSL_ASSERT( xChartTypeContainer.is());
493 if( !xChartTypeContainer.is() )
494 continue;
495 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
496 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
498 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
500 //iterate through all series in this chart type
501 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
502 OSL_ASSERT( xDataSeriesContainer.is());
503 if( !xDataSeriesContainer.is() )
504 continue;
506 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
507 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
509 Reference< XDataSeries > xSeries(aSeriesList[nS]);
510 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
511 if(!xSeries.is() || !xSeriesProp.is() )
512 continue;
514 uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
515 xChartType, getDimension(), isSwapXAndY(), xSeries ) );
516 if(!aAvailablePlacements.getLength())
517 continue;
519 sal_Int32 nDefaultPlacement = aAvailablePlacements[0];
521 lcl_resetLabelPlacementIfDefault( xSeriesProp, nDefaultPlacement );
523 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
524 if( xSeriesProp->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
525 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
526 lcl_resetLabelPlacementIfDefault( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), nDefaultPlacement );
533 return;
536 // ____ XServiceName ____
537 ::rtl::OUString SAL_CALL ChartTypeTemplate::getServiceName()
538 throw (uno::RuntimeException)
540 return m_aServiceName;
543 // ________________________________________
545 sal_Int32 ChartTypeTemplate::getDimension() const
547 return 2;
550 StackMode ChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
552 return StackMode_NONE;
555 bool ChartTypeTemplate::isSwapXAndY() const
557 return false;
560 // ________________________________________
562 void ChartTypeTemplate::createCoordinateSystems(
563 const Reference< chart2::XCoordinateSystemContainer > & xOutCooSysCnt )
565 if( ! xOutCooSysCnt.is())
566 return;
567 Sequence< Reference< XChartType > > aFormerlyUsedChartTypes;
568 Reference< XChartType > xChartType( getChartTypeForNewSeries(aFormerlyUsedChartTypes));
569 if( ! xChartType.is())
570 return;
571 Reference< XCoordinateSystem > xCooSys( xChartType->createCoordinateSystem( getDimension()));
572 if( ! xCooSys.is())
574 // chart type wants no coordinate systems
575 xOutCooSysCnt->setCoordinateSystems( Sequence< Reference< XCoordinateSystem > >());
576 return;
578 // #i69680# make grid of first y-axis visible (was in the CooSys CTOR before)
579 if( xCooSys->getDimension() >= 2 )
581 Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1, 0 ));
582 if( xAxis.is())
583 AxisHelper::makeGridVisible( xAxis->getGridProperties() );
586 Sequence< Reference< XCoordinateSystem > > aCoordinateSystems(
587 xOutCooSysCnt->getCoordinateSystems());
589 if( aCoordinateSystems.getLength())
591 bool bOk = true;
592 for( sal_Int32 i=0; bOk && i<aCoordinateSystems.getLength(); ++i )
593 bOk = bOk && ( xCooSys->getCoordinateSystemType().equals( aCoordinateSystems[i]->getCoordinateSystemType()) &&
594 (xCooSys->getDimension() == aCoordinateSystems[i]->getDimension()) );
595 // coordinate systems are ok
596 if( bOk )
597 return;
598 // there are coordinate systems but they do not fit. So overwrite them.
601 //copy as much info from former coordinate system as possible:
602 if( aCoordinateSystems.getLength() )
604 Reference< XCoordinateSystem > xOldCooSys( aCoordinateSystems[0] );
605 sal_Int32 nMaxDimensionCount = std::min( xCooSys->getDimension(), xOldCooSys->getDimension() );
607 for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nMaxDimensionCount; nDimensionIndex++)
609 const sal_Int32 nMaximumAxisIndex = xOldCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
610 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
612 uno::Reference< XAxis > xAxis( xOldCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
613 if( xAxis.is())
615 xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
621 // set new coordinate systems
622 aCoordinateSystems.realloc( 1 );
623 aCoordinateSystems[0] = xCooSys;
625 xOutCooSysCnt->setCoordinateSystems( aCoordinateSystems );
628 void ChartTypeTemplate::adaptScales(
629 const Sequence< Reference< chart2::XCoordinateSystem > > & aCooSysSeq,
630 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 )
633 bool bSupportsCategories( supportsCategories() );
634 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
638 Reference< XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIdx] );
639 if( !xCooSys.is() )
640 continue;
642 // attach categories to first axis
643 sal_Int32 nDim( xCooSys->getDimension());
644 if( nDim > 0 )
646 const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(0);
647 for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
649 Reference< XAxis > xAxis( xCooSys->getAxisByDimension(0,nI) );
650 if( xAxis.is())
652 ScaleData aData( xAxis->getScaleData() );
653 aData.Categories = xCategories;
654 aData.AxisType = bSupportsCategories ? AxisType::CATEGORY : AxisType::REALNUMBER;
655 if( bSupportsCategories )
656 AxisHelper::removeExplicitScaling( aData );
657 xAxis->setScaleData( aData );
661 // set percent stacking mode at second axis
662 if( nDim > 1 )
664 const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(1);
665 for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
667 Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1,nI ));
668 if( xAxis.is())
670 sal_Bool bPercent = (getStackMode(0) == StackMode_Y_STACKED_PERCENT);
671 chart2::ScaleData aScaleData = xAxis->getScaleData();
673 if( bPercent != (aScaleData.AxisType==AxisType::PERCENT) )
675 if( bPercent )
676 aScaleData.AxisType = AxisType::PERCENT;
677 else
678 aScaleData.AxisType = AxisType::REALNUMBER;
679 xAxis->setScaleData( aScaleData );
685 catch( const uno::Exception & ex )
687 ASSERT_EXCEPTION( ex );
692 void ChartTypeTemplate::adaptDiagram( const Reference< XDiagram > & /* xDiagram */ )
694 return;
697 void ChartTypeTemplate::createAxes(
698 const Sequence< Reference< XCoordinateSystem > > & rCoordSys )
700 //create missing axes
701 if( rCoordSys.getLength() > 0 )
703 sal_Int32 nCooSysIdx = 0;
704 Reference< XCoordinateSystem > xCooSys( rCoordSys[nCooSysIdx] );
705 if(!xCooSys.is())
706 return;
708 //create main axis in first coordinate system
709 sal_Int32 nDimCount = xCooSys->getDimension();
710 sal_Int32 nDim=0;
711 for( nDim=0; nDim<nDimCount; ++nDim )
713 sal_Int32 nAxisCount = getAxisCountByDimension( nDim );
714 if( nDim == 1 &&
715 nAxisCount < 2 && AxisHelper::isSecondaryYAxisNeeded( xCooSys ))
716 nAxisCount = 2;
717 for( sal_Int32 nAxisIndex = 0; nAxisIndex < nAxisCount; ++nAxisIndex )
719 Reference< XAxis > xAxis = AxisHelper::getAxis( nDim, nAxisIndex, xCooSys );
720 if( !xAxis.is())
722 // create and add axis
723 xAxis.set( AxisHelper::createAxis(
724 nDim, nAxisIndex, xCooSys, GetComponentContext() ));
731 void ChartTypeTemplate::adaptAxes(
732 const Sequence< Reference< XCoordinateSystem > > & rCoordSys )
734 //adapt properties of exsisting axes and remove superfluous axes
736 if( rCoordSys.getLength() > 0 )
738 for( sal_Int32 nCooSysIdx=0; nCooSysIdx < rCoordSys.getLength(); ++nCooSysIdx )
740 Reference< XCoordinateSystem > xCooSys( rCoordSys[nCooSysIdx] );
741 if( !xCooSys.is() )
742 continue;
743 sal_Int32 nDimCount = xCooSys->getDimension();
744 for( sal_Int32 nDim=0; nDim<nDimCount; ++nDim )
746 sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension( nDim );
747 for( sal_Int32 nAxisIndex=0; nAxisIndex<=nMaxAxisIndex; nAxisIndex++ )
749 Reference< XAxis > xAxis( AxisHelper::getAxis( nDim, nAxisIndex, xCooSys ) );
750 if( !xAxis.is() )
751 continue;
753 if( nAxisIndex == MAIN_AXIS_INDEX || nAxisIndex == SECONDARY_AXIS_INDEX )
755 // adapt scales
756 sal_Bool bPercent = (getStackMode(0) == StackMode_Y_STACKED_PERCENT);
757 if( bPercent && nDim == 1 )
759 Reference< beans::XPropertySet > xAxisProp( xAxis, uno::UNO_QUERY );
760 if( xAxisProp.is())
762 // set number format to source format
763 uno::Any aValue( xAxisProp->getPropertyValue(C2U("NumberFormat")));
764 if( aValue.hasValue())
765 xAxisProp->setPropertyValue(C2U("NumberFormat"), uno::Any());
775 sal_Int32 ChartTypeTemplate::getAxisCountByDimension( sal_Int32 nDimension )
777 return (nDimension < getDimension()) ? 1 : 0;
780 void ChartTypeTemplate::FillDiagram(
781 const Reference< XDiagram >& xDiagram,
782 const Sequence< Sequence< Reference< XDataSeries > > >& aSeriesSeq,
783 Reference< data::XLabeledDataSequence > xCategories,
784 const Sequence< Reference< XChartType > >& aOldChartTypesSeq,
785 bool /* bCreate */ )
787 adaptDiagram( xDiagram );
791 // create coordinate systems and scales
792 Reference< XCoordinateSystemContainer > xCoordSysCnt( xDiagram, uno::UNO_QUERY_THROW );
793 createCoordinateSystems( xCoordSysCnt );
794 Sequence< Reference< XCoordinateSystem > > aCoordinateSystems( xCoordSysCnt->getCoordinateSystems());
795 createAxes( aCoordinateSystems );
796 adaptAxes( aCoordinateSystems );
797 adaptScales( aCoordinateSystems, xCategories );
799 // chart types
800 createChartTypes( aSeriesSeq, aCoordinateSystems, aOldChartTypesSeq );
801 applyStyles( xDiagram );
803 catch( const uno::Exception & ex )
805 ASSERT_EXCEPTION( ex );
808 #if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL
809 OSL_TRACE( "ChartTypeTemplate::FillDiagram: Showing Diagram structure" );
810 OSL_TRACE( "---------------------------------------------------------" );
811 debug::ChartDebugTraceDiagram( xDiagram );
812 #endif
815 void ChartTypeTemplate::createChartTypes(
816 const Sequence< Sequence< Reference< XDataSeries > > > & aSeriesSeq,
817 const Sequence< Reference< XCoordinateSystem > > & rCoordSys,
818 const Sequence< Reference< XChartType > >& aOldChartTypesSeq )
820 if( rCoordSys.getLength() == 0 ||
821 ! rCoordSys[0].is() )
822 return;
826 sal_Int32 nCooSysIdx=0;
827 Reference< XChartType > xCT;
828 if( aSeriesSeq.getLength() == 0 )
830 // we need a new chart type
831 xCT.set( getChartTypeForNewSeries( aOldChartTypesSeq ));
832 Reference< XChartTypeContainer > xCTCnt( rCoordSys[nCooSysIdx], uno::UNO_QUERY_THROW );
833 Sequence< Reference< XChartType > > aCTSeq( xCTCnt->getChartTypes());
834 aCTSeq.realloc( 1 );
835 aCTSeq[0] = xCT;
836 xCTCnt->setChartTypes( aCTSeq );
838 else
840 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
842 if( nSeriesIdx == nCooSysIdx )
844 // we need a new chart type
845 xCT.set( getChartTypeForNewSeries( aOldChartTypesSeq ));
846 Reference< XChartTypeContainer > xCTCnt( rCoordSys[nCooSysIdx], uno::UNO_QUERY_THROW );
847 Sequence< Reference< XChartType > > aCTSeq( xCTCnt->getChartTypes());
848 if( aCTSeq.getLength())
850 aCTSeq[0] = xCT;
851 xCTCnt->setChartTypes( aCTSeq );
853 else
854 xCTCnt->addChartType( xCT );
856 Reference< chart2::XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW );
857 xDSCnt->setDataSeries( aSeriesSeq[nSeriesIdx] );
859 else
861 // reuse existing chart type
862 OSL_ASSERT( xCT.is());
863 Reference< chart2::XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW );
864 Sequence< Reference< XDataSeries > > aNewSeriesSeq( xDSCnt->getDataSeries());
865 sal_Int32 nNewStartIndex = aNewSeriesSeq.getLength();
866 aNewSeriesSeq.realloc( nNewStartIndex + aSeriesSeq[nSeriesIdx].getLength() );
867 ::std::copy( aSeriesSeq[nSeriesIdx].getConstArray(),
868 aSeriesSeq[nSeriesIdx].getConstArray() + aSeriesSeq[nSeriesIdx].getLength(),
869 aNewSeriesSeq.getArray() + nNewStartIndex );
870 xDSCnt->setDataSeries( aNewSeriesSeq );
873 // spread the series over the available coordinate systems
874 if( rCoordSys.getLength() > (nCooSysIdx + 1) )
875 ++nCooSysIdx;
879 catch( uno::Exception & ex )
881 ASSERT_EXCEPTION( ex );
885 //static
886 void ChartTypeTemplate::copyPropertiesFromOldToNewCoordianteSystem(
887 const Sequence< Reference< XChartType > > & rOldChartTypesSeq,
888 const Reference< XChartType > & xNewChartType )
890 Reference< beans::XPropertySet > xDestination( xNewChartType, uno::UNO_QUERY );
891 if( !xDestination.is() )
892 return;
894 OUString aNewChartType( xNewChartType->getChartType() );
896 Reference< beans::XPropertySet > xSource;
897 sal_Int32 nN=0;
898 for( nN=0; nN<rOldChartTypesSeq.getLength();++nN)
900 Reference< XChartType > xOldType( rOldChartTypesSeq[nN] );
901 if( xOldType.is() && xOldType->getChartType().equals( aNewChartType ) )
903 xSource.set( Reference< beans::XPropertySet >(xOldType, uno::UNO_QUERY ) );
904 if( xSource.is() )
905 break;
908 if( xSource.is() )
909 comphelper::copyProperties( xSource, xDestination );
912 // ________
914 Sequence< OUString > ChartTypeTemplate::getSupportedServiceNames_Static()
916 Sequence< OUString > aServices( 3 );
917 aServices[ 0 ] = C2U( "com.sun.star.chart2.ChartTypeTemplate" );
918 aServices[ 1 ] = C2U( "com.sun.star.layout.LayoutElement" );
919 aServices[ 2 ] = C2U( "com.sun.star.beans.PropertySet" );
920 return aServices;
923 Reference< uno::XComponentContext > ChartTypeTemplate::GetComponentContext() const
925 return m_xContext;
928 // ================================================================================
930 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
931 APPHELPER_XSERVICEINFO_IMPL( ChartTypeTemplate,
932 C2U( "com.sun.star.comp.chart.ChartTypeTemplate" ));
933 } // namespace chart