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