Update ooo320-m1
[ooovba.git] / chart2 / source / model / template / ChartTypeTemplate.cxx
blobfb0cff02afff579ea024be0c07c9cc80ab9d578b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ChartTypeTemplate.cxx,v $
10 * $Revision: 1.22 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "ChartTypeTemplate.hxx"
34 #include "PropertyHelper.hxx"
35 #include "macros.hxx"
36 #include "DataSeriesHelper.hxx"
37 #include "DataInterpreter.hxx"
38 #include "CommonConverters.hxx"
39 #include "ContainerHelper.hxx"
40 #include "ChartTypeHelper.hxx"
42 #include "CartesianCoordinateSystem.hxx"
43 #include "AxisHelper.hxx"
44 #include "LegendHelper.hxx"
45 #include "DiagramHelper.hxx"
46 #include "ChartDebugTrace.hxx"
47 #include "AxisIndexDefines.hxx"
48 #include <cppuhelper/component_context.hxx>
49 #include <com/sun/star/chart/ChartSolidType.hpp>
50 #include <com/sun/star/chart2/AxisType.hpp>
51 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
52 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
53 #include <com/sun/star/chart2/AxisType.hpp>
55 #include <algorithm>
56 #include <iterator>
58 using namespace ::com::sun::star;
59 using namespace ::com::sun::star::chart2;
61 using ::rtl::OUString;
62 using ::com::sun::star::uno::Sequence;
63 using ::com::sun::star::uno::Reference;
64 using ::com::sun::star::uno::Any;
65 using ::com::sun::star::uno::UNO_QUERY;
67 // ======================================================================
69 namespace
72 void lcl_applyDefaultStyle(
73 const Reference< XDataSeries > & xSeries,
74 sal_Int32 nIndex,
75 const Reference< XDiagram > & xDiagram )
77 // @deprecated: correct default color should be found by view without
78 // setting color as hard attribute
79 if( xSeries.is() && xDiagram.is())
81 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
82 Reference< chart2::XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
83 if( xSeriesProp.is() && xColorScheme.is() )
84 xSeriesProp->setPropertyValue(
85 C2U("Color"),
86 uno::makeAny( xColorScheme->getColorByIndex( nIndex )));
90 void lcl_ensureCorrectLabelPlacement( const Reference< beans::XPropertySet >& xProp, const uno::Sequence < sal_Int32 >& rAvailablePlacements )
92 sal_Int32 nLabelPlacement=0;
93 if( xProp->getPropertyValue( C2U( "LabelPlacement" ) ) >>= nLabelPlacement )
95 bool bValid = false;
96 for( sal_Int32 nN = 0; nN < rAvailablePlacements.getLength(); nN++ )
98 if( rAvailablePlacements[nN] == nLabelPlacement )
100 bValid = true;
101 break;
104 if( !bValid )
106 uno::Any aNewValue;
107 //otherwise use the first supported one
108 if( rAvailablePlacements.getLength() )
109 aNewValue <<=rAvailablePlacements[0];
110 xProp->setPropertyValue( C2U("LabelPlacement"), aNewValue );
115 void lcl_resetLabelPlacementIfDefault( const Reference< beans::XPropertySet >& xProp, sal_Int32 nDefaultPlacement )
118 sal_Int32 nLabelPlacement=0;
119 if( xProp->getPropertyValue( C2U( "LabelPlacement" ) ) >>= nLabelPlacement )
121 if( nDefaultPlacement == nLabelPlacement )
122 xProp->setPropertyValue( C2U("LabelPlacement"), uno::Any() );
126 void lcl_ensureCorrectMissingValueTreatment( const Reference< chart2::XDiagram >& xDiagram, const Reference< XChartType >& xChartType )
128 Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
129 if( xDiaProp.is() )
131 uno::Sequence < sal_Int32 > aAvailableMissingValueTreatment(
132 ::chart::ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) );
134 if( aAvailableMissingValueTreatment.getLength() )
135 xDiaProp->setPropertyValue( C2U( "MissingValueTreatment" ), uno::makeAny( aAvailableMissingValueTreatment[0] ) );
136 else
137 xDiaProp->setPropertyValue( C2U( "MissingValueTreatment" ), uno::Any() );
141 } // anonymous namespace
143 namespace chart
146 ChartTypeTemplate::ChartTypeTemplate(
147 Reference< uno::XComponentContext > const & xContext,
148 const ::rtl::OUString & rServiceName ) :
149 m_xContext( xContext ),
150 m_aServiceName( rServiceName )
154 ChartTypeTemplate::~ChartTypeTemplate()
157 // ____ XChartTypeTemplate ____
158 uno::Reference< XDiagram > SAL_CALL ChartTypeTemplate::createDiagramByDataSource(
159 const uno::Reference< data::XDataSource >& xDataSource,
160 const uno::Sequence< beans::PropertyValue >& aArguments )
161 throw (uno::RuntimeException)
163 Reference< XDiagram > xDia;
167 // create diagram
168 xDia.set(
169 GetComponentContext()->getServiceManager()->createInstanceWithContext(
170 C2U( "com.sun.star.chart2.Diagram" ),
171 GetComponentContext() ),
172 uno::UNO_QUERY_THROW );
174 // modify diagram
175 Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter());
176 chart2::InterpretedData aData(
177 xInterpreter->interpretDataSource(
178 xDataSource, aArguments, Sequence< Reference< XDataSeries > >() ));
180 Sequence< Sequence< Reference< XDataSeries > > > aSeries( aData.Series );
181 sal_Int32 i, j, nCount = 0;
182 for( i=0; i<aSeries.getLength(); ++i )
184 for( j=0; j<aSeries[i].getLength(); ++j, ++nCount )
185 lcl_applyDefaultStyle( aSeries[i][j], nCount, xDia );
188 Sequence< Reference< XChartType > > aOldChartTypesSeq;
189 FillDiagram( xDia, aData.Series, aData.Categories, aOldChartTypesSeq, true );
191 catch( uno::Exception & ex )
193 ASSERT_EXCEPTION( ex );
196 return xDia;
199 Sequence< OUString > SAL_CALL ChartTypeTemplate::getAvailableCreationParameterNames()
200 throw (uno::RuntimeException)
202 OUString aHasCat( C2U("HasCategories"));
203 return Sequence< OUString >( & aHasCat, 1 );
206 void SAL_CALL ChartTypeTemplate::changeDiagram( const uno::Reference< XDiagram >& xDiagram )
207 throw (uno::RuntimeException)
209 if( ! xDiagram.is())
210 return;
214 Sequence< Sequence< Reference< XDataSeries > > > aSeriesSeq(
215 DiagramHelper::getDataSeriesGroups( xDiagram ));
216 Sequence< Reference< XDataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq ));
217 const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.getLength();
219 // chart-type specific interpretation of existing data series
220 Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter());
221 chart2::InterpretedData aData;
222 aData.Series = aSeriesSeq;
223 aData.Categories = DiagramHelper::getCategoriesFromDiagram( xDiagram );
224 aData.UnusedData = xDiagram->getUnusedData();
226 if( (aData.UnusedData.getLength() == 0) &&
227 xInterpreter->isDataCompatible( aData ))
229 aData = xInterpreter->reinterpretDataSeries( aData );
231 else
233 Reference< data::XDataSource > xSource( xInterpreter->mergeInterpretedData( aData ));
234 // todo: get a "range-union" from the data provider by calling
235 // OUString aRange = getRangeRepresentationByData( xSource );
236 // xSource.set( getDataByRangeRepresentation( aRange, aParam ));
237 // where aParam == ??
238 Sequence< beans::PropertyValue > aParam;
239 if( aData.Categories.is())
241 aParam.realloc( 1 );
242 aParam[0] = beans::PropertyValue( C2U("HasCategories"), -1, uno::makeAny( true ),
243 beans::PropertyState_DIRECT_VALUE );
245 else if( aData.UnusedData.getLength())
247 for( sal_Int32 i=0; i<aData.UnusedData.getLength(); ++i )
250 Reference< beans::XPropertySet > xProp( aData.UnusedData[i]->getValues(), uno::UNO_QUERY_THROW );
251 OUString aRole;
252 if( (xProp->getPropertyValue(C2U("Role")) >>= aRole) &
253 aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) )
255 aData.Categories = aData.UnusedData[i];
256 for( ++i; i<aData.UnusedData.getLength(); ++i )
257 aData.UnusedData[i-1] = aData.UnusedData[i];
258 aData.UnusedData.realloc( aData.UnusedData.getLength() - 1 );
259 break;
262 catch( const uno::Exception & ex )
264 ASSERT_EXCEPTION( ex );
267 aData = xInterpreter->interpretDataSource( xSource, aParam, aFlatSeriesSeq );
269 aSeriesSeq = aData.Series;
270 xDiagram->setUnusedData( aData.UnusedData );
272 sal_Int32 i, j, nIndex = 0;
273 for( i=0; i<aSeriesSeq.getLength(); ++i )
274 for( j=0; j<aSeriesSeq[i].getLength(); ++j, ++nIndex )
276 if( nIndex >= nFormerSeriesCount )
277 lcl_applyDefaultStyle( aSeriesSeq[i][j], nIndex, xDiagram );
280 // remove charttype groups from all coordinate systems
281 Sequence< Reference< XChartType > > aOldChartTypesSeq(
282 DiagramHelper::getChartTypesFromDiagram(xDiagram) );
284 Reference< XCoordinateSystemContainer > xCoordSysCnt( xDiagram, uno::UNO_QUERY );
285 OSL_ASSERT( xCoordSysCnt.is());
286 if( xCoordSysCnt.is())
288 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
289 xCoordSysCnt->getCoordinateSystems());
290 for( sal_Int32 nCooSysIdx = 0; nCooSysIdx < aCooSysSeq.getLength(); ++nCooSysIdx )
292 Reference< XChartTypeContainer > xContainer( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
293 if( xContainer.is() )
294 xContainer->setChartTypes( Sequence< Reference< XChartType > >() );
298 FillDiagram( xDiagram, aSeriesSeq, aData.Categories, aOldChartTypesSeq, false );
300 catch( uno::Exception & ex )
302 ASSERT_EXCEPTION( ex );
306 void SAL_CALL ChartTypeTemplate::changeDiagramData(
307 const Reference< chart2::XDiagram >& xDiagram,
308 const Reference< chart2::data::XDataSource >& xDataSource,
309 const Sequence< beans::PropertyValue >& aArguments )
310 throw (uno::RuntimeException)
312 if( ! (xDiagram.is() &&
313 xDataSource.is()) )
314 return;
318 // interpret new data and re-use existing series
319 Sequence< Reference< XDataSeries > > aFlatSeriesSeq(
320 ::chart::ContainerHelper::ContainerToSequence( DiagramHelper::getDataSeriesFromDiagram( xDiagram )));
321 const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.getLength();
322 Reference< chart2::XDataInterpreter > xInterpreter( getDataInterpreter());
323 chart2::InterpretedData aData =
324 xInterpreter->interpretDataSource( xDataSource, aArguments, aFlatSeriesSeq );
326 // data series
327 Sequence< Sequence< Reference< XDataSeries > > > aSeriesSeq( aData.Series );
329 sal_Int32 i, j, nIndex = 0;
330 for( i=0; i<aSeriesSeq.getLength(); ++i )
331 for( j=0; j<aSeriesSeq[i].getLength(); ++j, ++nIndex )
333 if( nIndex >= nFormerSeriesCount )
335 lcl_applyDefaultStyle( aSeriesSeq[i][j], nIndex, xDiagram );
336 applyStyle( aSeriesSeq[i][j], i, j, aSeriesSeq[i].getLength() );
340 // categories
341 DiagramHelper::setCategoriesToDiagram( aData.Categories, xDiagram, true, supportsCategories() );
343 Sequence< Reference< XChartType > > aChartTypes(
344 DiagramHelper::getChartTypesFromDiagram( xDiagram ));
345 sal_Int32 nMax = ::std::min( aChartTypes.getLength(), aSeriesSeq.getLength());
346 for( i=0; i<nMax; ++i )
348 Reference< XDataSeriesContainer > xDSCnt( aChartTypes[i], uno::UNO_QUERY_THROW );
349 xDSCnt->setDataSeries( aSeriesSeq[i] );
351 #if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL
352 OSL_TRACE( "ChartTypeTemplate::changeDiagramData: Showing Diagram structure" );
353 OSL_TRACE( "---------------------------------------------------------------" );
354 debug::ChartDebugTraceDiagram( xDiagram );
355 #endif
357 catch( uno::Exception & ex )
359 ASSERT_EXCEPTION( ex );
363 sal_Bool SAL_CALL ChartTypeTemplate::matchesTemplate(
364 const Reference< chart2::XDiagram >& xDiagram,
365 sal_Bool /* bAdaptProperties */ )
366 throw (uno::RuntimeException)
368 sal_Bool bResult = sal_False;
370 if( ! xDiagram.is())
371 return bResult;
375 Reference< XCoordinateSystemContainer > xCooSysCnt(
376 xDiagram, uno::UNO_QUERY_THROW );
377 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
378 xCooSysCnt->getCoordinateSystems());
380 // need to have at least one coordinate system
381 bResult = (aCooSysSeq.getLength() > 0);
382 if( bResult )
384 Sequence< Reference< XChartType > > aFormerlyUsedChartTypes;
385 const OUString aChartTypeToMatch( getChartTypeForNewSeries(aFormerlyUsedChartTypes)->getChartType());
386 const sal_Int32 nDimensionToMatch = getDimension();
387 for( sal_Int32 nCooSysIdx=0; bResult && (nCooSysIdx < aCooSysSeq.getLength()); ++nCooSysIdx )
389 // match dimension
390 bResult = bResult && (aCooSysSeq[nCooSysIdx]->getDimension() == nDimensionToMatch);
392 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
393 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
394 for( sal_Int32 nCTIdx=0; bResult && (nCTIdx < aChartTypeSeq.getLength()); ++nCTIdx )
396 // match chart type
397 bResult = bResult && aChartTypeSeq[nCTIdx]->getChartType().equals( aChartTypeToMatch );
398 bool bFound=false;
399 bool bAmbiguous=false;
400 // match stacking mode
401 bResult = bResult &&
402 ( DiagramHelper::getStackModeFromChartType(
403 aChartTypeSeq[nCTIdx], bFound, bAmbiguous,
404 aCooSysSeq[nCooSysIdx] )
405 == getStackMode( nCTIdx ) );
410 catch( uno::Exception & ex )
412 ASSERT_EXCEPTION( ex );
415 return bResult;
418 Reference< chart2::XDataInterpreter > SAL_CALL ChartTypeTemplate::getDataInterpreter()
419 throw (uno::RuntimeException)
421 if( ! m_xDataInterpreter.is())
422 m_xDataInterpreter.set( new DataInterpreter( GetComponentContext() ) );
424 return m_xDataInterpreter;
427 void SAL_CALL ChartTypeTemplate::applyStyle(
428 const Reference< chart2::XDataSeries >& xSeries,
429 ::sal_Int32 nChartTypeIndex,
430 ::sal_Int32 /* nSeriesIndex */,
431 ::sal_Int32 /* nSeriesCount */ )
432 throw (uno::RuntimeException)
434 // sset stacking mode
435 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
436 if( xSeriesProp.is())
440 StackMode eStackMode = getStackMode( nChartTypeIndex );
441 const uno::Any aPropValue = uno::makeAny(
442 ( (eStackMode == StackMode_Y_STACKED) ||
443 (eStackMode == StackMode_Y_STACKED_PERCENT) )
444 ? chart2::StackingDirection_Y_STACKING
445 : (eStackMode == StackMode_Z_STACKED )
446 ? chart2::StackingDirection_Z_STACKING
447 : chart2::StackingDirection_NO_STACKING );
448 xSeriesProp->setPropertyValue( C2U("StackingDirection"), aPropValue );
450 //ensure valid label placement
452 uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
453 getChartTypeForIndex( nChartTypeIndex ), getDimension(), isSwapXAndY(), xSeries ) );
454 lcl_ensureCorrectLabelPlacement( xSeriesProp, aAvailablePlacements );
456 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
457 if( xSeriesProp->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
458 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
459 lcl_ensureCorrectLabelPlacement( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), aAvailablePlacements );
462 catch( const uno::Exception & ex )
464 ASSERT_EXCEPTION( ex );
469 void SAL_CALL ChartTypeTemplate::applyStyles( const Reference< chart2::XDiagram >& xDiagram )
470 throw (uno::RuntimeException)
472 // apply chart-type specific styles, like "symbols on" for example
473 Sequence< Sequence< Reference< XDataSeries > > > aNewSeriesSeq(
474 DiagramHelper::getDataSeriesGroups( xDiagram ));
475 for( sal_Int32 i=0; i<aNewSeriesSeq.getLength(); ++i )
477 const sal_Int32 nNumSeries = aNewSeriesSeq[i].getLength();
478 for( sal_Int32 j=0; j<nNumSeries; ++j )
479 applyStyle( aNewSeriesSeq[i][j], i, j, nNumSeries );
482 //ensure valid empty cell handling (for first chart type...)
483 lcl_ensureCorrectMissingValueTreatment( xDiagram, getChartTypeForIndex( 0 ) );
486 void SAL_CALL ChartTypeTemplate::resetStyles( const Reference< chart2::XDiagram >& xDiagram )
487 throw (uno::RuntimeException)
489 // reset number format if we had percent stacking on
490 sal_Bool bPercent = (getStackMode(0) == StackMode_Y_STACKED_PERCENT);
491 if( bPercent )
493 Sequence< Reference< chart2::XAxis > > aAxisSeq( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
494 for( sal_Int32 i=0; i<aAxisSeq.getLength(); ++i )
496 if( 1== AxisHelper::getDimensionIndexOfAxis( aAxisSeq[i], xDiagram ) )
498 Reference< beans::XPropertySet > xAxisProp( aAxisSeq[i], uno::UNO_QUERY );
499 if( xAxisProp.is())
501 // set number format to source format
502 uno::Any aValue( xAxisProp->getPropertyValue(C2U("NumberFormat")));
503 if( aValue.hasValue())
504 xAxisProp->setPropertyValue(C2U("NumberFormat"), uno::Any());
510 //reset label placement if default
512 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
513 if( xCooSysContainer.is() )
515 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
516 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
518 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
520 //iterate through all chart types in the current coordinate system
521 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
522 OSL_ASSERT( xChartTypeContainer.is());
523 if( !xChartTypeContainer.is() )
524 continue;
525 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
526 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
528 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
530 //iterate through all series in this chart type
531 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
532 OSL_ASSERT( xDataSeriesContainer.is());
533 if( !xDataSeriesContainer.is() )
534 continue;
536 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
537 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
539 Reference< XDataSeries > xSeries(aSeriesList[nS]);
540 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
541 if(!xSeries.is() || !xSeriesProp.is() )
542 continue;
544 uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
545 xChartType, getDimension(), isSwapXAndY(), xSeries ) );
546 if(!aAvailablePlacements.getLength())
547 continue;
549 sal_Int32 nDefaultPlacement = aAvailablePlacements[0];
551 lcl_resetLabelPlacementIfDefault( xSeriesProp, nDefaultPlacement );
553 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
554 if( xSeriesProp->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
555 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
556 lcl_resetLabelPlacementIfDefault( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), nDefaultPlacement );
563 return;
566 // ____ XServiceName ____
567 ::rtl::OUString SAL_CALL ChartTypeTemplate::getServiceName()
568 throw (uno::RuntimeException)
570 return m_aServiceName;
573 // ________________________________________
575 sal_Int32 ChartTypeTemplate::getDimension() const
577 return 2;
580 StackMode ChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
582 return StackMode_NONE;
585 bool ChartTypeTemplate::isSwapXAndY() const
587 return false;
590 bool ChartTypeTemplate::supportsCategories() const
592 return true;
595 // ________________________________________
597 void ChartTypeTemplate::createCoordinateSystems(
598 const Reference< chart2::XCoordinateSystemContainer > & xOutCooSysCnt )
600 if( ! xOutCooSysCnt.is())
601 return;
602 Sequence< Reference< XChartType > > aFormerlyUsedChartTypes;
603 Reference< XChartType > xChartType( getChartTypeForNewSeries(aFormerlyUsedChartTypes));
604 if( ! xChartType.is())
605 return;
606 Reference< XCoordinateSystem > xCooSys( xChartType->createCoordinateSystem( getDimension()));
607 if( ! xCooSys.is())
609 // chart type wants no coordinate systems
610 xOutCooSysCnt->setCoordinateSystems( Sequence< Reference< XCoordinateSystem > >());
611 return;
613 // #i69680# make grid of first y-axis visible (was in the CooSys CTOR before)
614 if( xCooSys->getDimension() >= 2 )
616 Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1, 0 ));
617 if( xAxis.is())
618 AxisHelper::makeGridVisible( xAxis->getGridProperties() );
621 Sequence< Reference< XCoordinateSystem > > aCoordinateSystems(
622 xOutCooSysCnt->getCoordinateSystems());
624 if( aCoordinateSystems.getLength())
626 bool bOk = true;
627 for( sal_Int32 i=0; bOk && i<aCoordinateSystems.getLength(); ++i )
628 bOk = bOk && ( xCooSys->getCoordinateSystemType().equals( aCoordinateSystems[i]->getCoordinateSystemType()) &&
629 (xCooSys->getDimension() == aCoordinateSystems[i]->getDimension()) );
630 // coordinate systems are ok
631 if( bOk )
632 return;
633 // there are coordinate systems but they do not fit. So overwrite them.
636 //copy as much info from former coordinate system as possible:
637 if( aCoordinateSystems.getLength() )
639 Reference< XCoordinateSystem > xOldCooSys( aCoordinateSystems[0] );
640 sal_Int32 nMaxDimensionCount = std::min( xCooSys->getDimension(), xOldCooSys->getDimension() );
642 for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nMaxDimensionCount; nDimensionIndex++)
644 const sal_Int32 nMaximumAxisIndex = xOldCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
645 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
647 uno::Reference< XAxis > xAxis( xOldCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
648 if( xAxis.is())
650 xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
656 // set new coordinate systems
657 aCoordinateSystems.realloc( 1 );
658 aCoordinateSystems[0] = xCooSys;
660 xOutCooSysCnt->setCoordinateSystems( aCoordinateSystems );
663 void ChartTypeTemplate::adaptScales(
664 const Sequence< Reference< chart2::XCoordinateSystem > > & aCooSysSeq,
665 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 )
668 bool bSupportsCategories( supportsCategories());
669 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
673 Reference< XCoordinateSystem > xCooSys( aCooSysSeq[nCooSysIdx] );
674 if( !xCooSys.is() )
675 continue;
677 // attach categories to first axis
678 sal_Int32 nDim( xCooSys->getDimension());
679 if( nDim > 0 )
681 const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(0);
682 for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
684 Reference< XAxis > xAxis( xCooSys->getAxisByDimension(0,nI) );
685 if( xAxis.is())
687 ScaleData aData( xAxis->getScaleData() );
688 aData.Categories = xCategories;
689 aData.AxisType = bSupportsCategories ? AxisType::CATEGORY : AxisType::REALNUMBER;
690 if( bSupportsCategories )
691 AxisHelper::removeExplicitScaling( aData );
692 xAxis->setScaleData( aData );
696 // set percent stacking mode at second axis
697 if( nDim > 1 )
699 const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(1);
700 for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
702 Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1,nI ));
703 if( xAxis.is())
705 sal_Bool bPercent = (getStackMode(0) == StackMode_Y_STACKED_PERCENT);
706 chart2::ScaleData aScaleData = xAxis->getScaleData();
708 if( bPercent != (aScaleData.AxisType==AxisType::PERCENT) )
710 if( bPercent )
711 aScaleData.AxisType = AxisType::PERCENT;
712 else
713 aScaleData.AxisType = AxisType::REALNUMBER;
714 xAxis->setScaleData( aScaleData );
720 catch( const uno::Exception & ex )
722 ASSERT_EXCEPTION( ex );
727 void ChartTypeTemplate::adaptDiagram( const Reference< XDiagram > & /* xDiagram */ )
729 return;
732 void ChartTypeTemplate::createAxes(
733 const Sequence< Reference< XCoordinateSystem > > & rCoordSys )
735 //create missing axes
736 if( rCoordSys.getLength() > 0 )
738 sal_Int32 nCooSysIdx = 0;
739 Reference< XCoordinateSystem > xCooSys( rCoordSys[nCooSysIdx] );
740 if(!xCooSys.is())
741 return;
743 //create main axis in first coordinate system
744 sal_Int32 nDimCount = xCooSys->getDimension();
745 sal_Int32 nDim=0;
746 for( nDim=0; nDim<nDimCount; ++nDim )
748 sal_Int32 nAxisCount = getAxisCountByDimension( nDim );
749 if( nDim == 1 &&
750 nAxisCount < 2 && AxisHelper::isSecondaryYAxisNeeded( xCooSys ))
751 nAxisCount = 2;
752 for( sal_Int32 nAxisIndex = 0; nAxisIndex < nAxisCount; ++nAxisIndex )
754 Reference< XAxis > xAxis = AxisHelper::getAxis( nDim, nAxisIndex, xCooSys );
755 if( !xAxis.is())
757 // create and add axis
758 xAxis.set( AxisHelper::createAxis(
759 nDim, nAxisIndex, xCooSys, GetComponentContext() ));
766 void ChartTypeTemplate::adaptAxes(
767 const Sequence< Reference< XCoordinateSystem > > & rCoordSys )
769 //adapt properties of exsisting axes and remove superfluous axes
771 if( rCoordSys.getLength() > 0 )
773 for( sal_Int32 nCooSysIdx=0; nCooSysIdx < rCoordSys.getLength(); ++nCooSysIdx )
775 Reference< XCoordinateSystem > xCooSys( rCoordSys[nCooSysIdx] );
776 if( !xCooSys.is() )
777 continue;
778 sal_Int32 nDimCount = xCooSys->getDimension();
779 for( sal_Int32 nDim=0; nDim<nDimCount; ++nDim )
781 sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension( nDim );
782 for( sal_Int32 nAxisIndex=0; nAxisIndex<=nMaxAxisIndex; nAxisIndex++ )
784 Reference< XAxis > xAxis( AxisHelper::getAxis( nDim, nAxisIndex, xCooSys ) );
785 if( !xAxis.is() )
786 continue;
788 if( nAxisIndex == MAIN_AXIS_INDEX || nAxisIndex == SECONDARY_AXIS_INDEX )
790 // adapt scales
791 sal_Bool bPercent = (getStackMode(0) == StackMode_Y_STACKED_PERCENT);
792 if( bPercent && nDim == 1 )
794 Reference< beans::XPropertySet > xAxisProp( xAxis, uno::UNO_QUERY );
795 if( xAxisProp.is())
797 // set number format to source format
798 uno::Any aValue( xAxisProp->getPropertyValue(C2U("NumberFormat")));
799 if( aValue.hasValue())
800 xAxisProp->setPropertyValue(C2U("NumberFormat"), uno::Any());
810 sal_Int32 ChartTypeTemplate::getAxisCountByDimension( sal_Int32 nDimension )
812 return (nDimension < getDimension()) ? 1 : 0;
815 void ChartTypeTemplate::FillDiagram(
816 const Reference< XDiagram >& xDiagram,
817 const Sequence< Sequence< Reference< XDataSeries > > >& aSeriesSeq,
818 Reference< data::XLabeledDataSequence > xCategories,
819 const Sequence< Reference< XChartType > >& aOldChartTypesSeq,
820 bool /* bCreate */ )
822 adaptDiagram( xDiagram );
826 // create coordinate systems and scales
827 Reference< XCoordinateSystemContainer > xCoordSysCnt( xDiagram, uno::UNO_QUERY_THROW );
828 createCoordinateSystems( xCoordSysCnt );
829 Sequence< Reference< XCoordinateSystem > > aCoordinateSystems( xCoordSysCnt->getCoordinateSystems());
830 createAxes( aCoordinateSystems );
831 adaptAxes( aCoordinateSystems );
832 adaptScales( aCoordinateSystems, xCategories );
834 // chart types
835 createChartTypes( aSeriesSeq, aCoordinateSystems, aOldChartTypesSeq );
836 applyStyles( xDiagram );
838 catch( const uno::Exception & ex )
840 ASSERT_EXCEPTION( ex );
843 #if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL
844 OSL_TRACE( "ChartTypeTemplate::FillDiagram: Showing Diagram structure" );
845 OSL_TRACE( "---------------------------------------------------------" );
846 debug::ChartDebugTraceDiagram( xDiagram );
847 #endif
850 void ChartTypeTemplate::createChartTypes(
851 const Sequence< Sequence< Reference< XDataSeries > > > & aSeriesSeq,
852 const Sequence< Reference< XCoordinateSystem > > & rCoordSys,
853 const Sequence< Reference< XChartType > >& aOldChartTypesSeq )
855 if( rCoordSys.getLength() == 0 ||
856 ! rCoordSys[0].is() )
857 return;
861 sal_Int32 nCooSysIdx=0;
862 Reference< XChartType > xCT;
863 if( aSeriesSeq.getLength() == 0 )
865 // we need a new chart type
866 xCT.set( getChartTypeForNewSeries( aOldChartTypesSeq ));
867 Reference< XChartTypeContainer > xCTCnt( rCoordSys[nCooSysIdx], uno::UNO_QUERY_THROW );
868 Sequence< Reference< XChartType > > aCTSeq( xCTCnt->getChartTypes());
869 aCTSeq.realloc( 1 );
870 aCTSeq[0] = xCT;
871 xCTCnt->setChartTypes( aCTSeq );
873 else
875 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
877 if( nSeriesIdx == nCooSysIdx )
879 // we need a new chart type
880 xCT.set( getChartTypeForNewSeries( aOldChartTypesSeq ));
881 Reference< XChartTypeContainer > xCTCnt( rCoordSys[nCooSysIdx], uno::UNO_QUERY_THROW );
882 Sequence< Reference< XChartType > > aCTSeq( xCTCnt->getChartTypes());
883 if( aCTSeq.getLength())
885 aCTSeq[0] = xCT;
886 xCTCnt->setChartTypes( aCTSeq );
888 else
889 xCTCnt->addChartType( xCT );
891 Reference< chart2::XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW );
892 xDSCnt->setDataSeries( aSeriesSeq[nSeriesIdx] );
894 else
896 // reuse existing chart type
897 OSL_ASSERT( xCT.is());
898 Reference< chart2::XDataSeriesContainer > xDSCnt( xCT, uno::UNO_QUERY_THROW );
899 Sequence< Reference< XDataSeries > > aNewSeriesSeq( xDSCnt->getDataSeries());
900 sal_Int32 nNewStartIndex = aNewSeriesSeq.getLength();
901 aNewSeriesSeq.realloc( nNewStartIndex + aSeriesSeq[nSeriesIdx].getLength() );
902 ::std::copy( aSeriesSeq[nSeriesIdx].getConstArray(),
903 aSeriesSeq[nSeriesIdx].getConstArray() + aSeriesSeq[nSeriesIdx].getLength(),
904 aNewSeriesSeq.getArray() + nNewStartIndex );
905 xDSCnt->setDataSeries( aNewSeriesSeq );
908 // spread the series over the available coordinate systems
909 if( rCoordSys.getLength() > (nCooSysIdx + 1) )
910 ++nCooSysIdx;
914 catch( uno::Exception & ex )
916 ASSERT_EXCEPTION( ex );
920 //static
921 void ChartTypeTemplate::copyPropertiesFromOldToNewCoordianteSystem(
922 const Sequence< Reference< XChartType > > & rOldChartTypesSeq,
923 const Reference< XChartType > & xNewChartType )
925 Reference< beans::XPropertySet > xDestination( xNewChartType, uno::UNO_QUERY );
926 if( !xDestination.is() )
927 return;
929 OUString aNewChartType( xNewChartType->getChartType() );
931 Reference< beans::XPropertySet > xSource;
932 sal_Int32 nN=0;
933 for( nN=0; nN<rOldChartTypesSeq.getLength();++nN)
935 Reference< XChartType > xOldType( rOldChartTypesSeq[nN] );
936 if( xOldType.is() && xOldType->getChartType().equals( aNewChartType ) )
938 xSource.set( Reference< beans::XPropertySet >(xOldType, uno::UNO_QUERY ) );
939 if( xSource.is() )
940 break;
943 if( xSource.is() )
944 comphelper::copyProperties( xSource, xDestination );
947 void ChartTypeTemplate::setStackModePropertiesToChartType(const Reference<XChartType>& xChartType)
949 Reference<beans::XPropertySet> xPropSet(xChartType, UNO_QUERY);
950 if (!xPropSet.is())
951 return;
953 bool bStacked = false;
954 bool bPercent = false;
955 switch (getStackMode(0))
957 case StackMode_Y_STACKED:
958 bStacked = true;
959 break;
960 case StackMode_Y_STACKED_PERCENT:
961 bStacked = true;
962 bPercent = true;
963 break;
964 case StackMode_Z_STACKED:
965 break;
966 default:
972 xPropSet->setPropertyValue(
973 C2U("Stacked"), uno::makeAny(static_cast<sal_Bool>(bStacked)));
975 catch (const beans::UnknownPropertyException&)
981 xPropSet->setPropertyValue(
982 C2U("Percent"), uno::makeAny(static_cast<sal_Bool>(bPercent)));
984 catch (const beans::UnknownPropertyException&)
989 // ________
991 Sequence< OUString > ChartTypeTemplate::getSupportedServiceNames_Static()
993 Sequence< OUString > aServices( 3 );
994 aServices[ 0 ] = C2U( "com.sun.star.chart2.ChartTypeTemplate" );
995 aServices[ 1 ] = C2U( "com.sun.star.layout.LayoutElement" );
996 aServices[ 2 ] = C2U( "com.sun.star.beans.PropertySet" );
997 return aServices;
1000 Reference< uno::XComponentContext > ChartTypeTemplate::GetComponentContext() const
1002 return m_xContext;
1005 // ================================================================================
1007 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
1008 APPHELPER_XSERVICEINFO_IMPL( ChartTypeTemplate,
1009 C2U( "com.sun.star.comp.chart.ChartTypeTemplate" ));
1010 } // namespace chart