1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "DiagramHelper.hxx"
27 #include "LegendHelper.hxx"
28 #include "PropertyHelper.hxx"
29 #include "macros.hxx"
30 #include "DataSeriesHelper.hxx"
31 #include "AxisHelper.hxx"
32 #include "ContainerHelper.hxx"
33 #include "ChartTypeHelper.hxx"
34 #include "ChartModelHelper.hxx"
35 #include "CommonConverters.hxx"
36 #include "ExplicitCategoriesProvider.hxx"
37 #include "servicenames_charttypes.hxx"
38 #include "ChartModelHelper.hxx"
39 #include "RelativePositionHelper.hxx"
40 #include "ControllerLockGuard.hxx"
41 #include "NumberFormatterWrapper.hxx"
42
43 #include <com/sun/star/chart/MissingValueTreatment.hpp>
44 #include <com/sun/star/chart/XChartDocument.hpp>
45 #include <com/sun/star/chart/XDiagramPositioning.hpp>
46 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
47 #include <com/sun/star/chart2/XTitled.hpp>
48 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
49 #include <com/sun/star/chart2/XChartTypeTemplate.hpp>
50 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
51 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
52 #include <com/sun/star/chart2/InterpretedData.hpp>
53 #include <com/sun/star/chart2/AxisType.hpp>
54 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
55 #include <com/sun/star/chart2/RelativePosition.hpp>
56 #include <com/sun/star/chart2/RelativeSize.hpp>
57
58 #include <com/sun/star/util/NumberFormat.hpp>
59 #include <com/sun/star/util/XModifiable.hpp>
60 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
61
62 #include <unotools/saveopt.hxx>
63 #include <rtl/math.hxx>
64 #include <svl/zformat.hxx>
65 // header for class Application
66 #include <vcl/svapp.hxx>
67
68 using namespace ::com::sun::star;
69 using namespace ::com::sun::star::chart2;
70 using namespace ::std;
71
72 using ::com::sun::star::uno::Reference;
73 using ::com::sun::star::uno::Sequence;
74 using ::com::sun::star::uno::Any;
75 using ::rtl::OUString;
76 using ::com::sun::star::chart2::XAnyDescriptionAccess;
77
78 namespace chart
79 {
80
81 DiagramHelper::tTemplateWithServiceName
getTemplateForDiagram(const Reference<XDiagram> & xDiagram,const Reference<lang::XMultiServiceFactory> & xChartTypeManager,const OUString & rPreferredTemplateName)82 DiagramHelper::getTemplateForDiagram(
83 const Reference< XDiagram > & xDiagram,
84 const Reference< lang::XMultiServiceFactory > & xChartTypeManager,
85 const OUString & rPreferredTemplateName )
86 {
87 DiagramHelper::tTemplateWithServiceName aResult;
88
89 if( ! (xChartTypeManager.is() && xDiagram.is()))
90 return aResult;
91
92 Sequence< OUString > aServiceNames( xChartTypeManager->getAvailableServiceNames());
93 const sal_Int32 nLength = aServiceNames.getLength();
94
95 bool bHasPreferredTemplate = !rPreferredTemplateName.isEmpty();
96 bool bTemplateFound = false;
97
98 if( bHasPreferredTemplate )
99 {
100 Reference< XChartTypeTemplate > xTempl(
101 xChartTypeManager->createInstance( rPreferredTemplateName ), uno::UNO_QUERY );
102
103 if( xTempl.is() &&
104 xTempl->matchesTemplate( xDiagram, sal_True ))
105 {
106 aResult.first = xTempl;
107 aResult.second = rPreferredTemplateName;
108 bTemplateFound = true;
109 }
110 }
111
112 for( sal_Int32 i = 0; ! bTemplateFound && i < nLength; ++i )
113 {
114 try
115 {
116 if( ! bHasPreferredTemplate ||
117 ! rPreferredTemplateName.equals( aServiceNames[ i ] ))
118 {
119 Reference< XChartTypeTemplate > xTempl(
120 xChartTypeManager->createInstance( aServiceNames[ i ] ), uno::UNO_QUERY_THROW );
121
122 if( xTempl->matchesTemplate( xDiagram, sal_True ))
123 {
124 aResult.first = xTempl;
125 aResult.second = aServiceNames[ i ];
126 bTemplateFound = true;
127 }
128 }
129 }
130 catch( uno::Exception & ex )
131 {
132 ASSERT_EXCEPTION( ex );
133 }
134 }
135
136 return aResult;
137 }
138
setVertical(const Reference<XDiagram> & xDiagram,bool bVertical)139 void DiagramHelper::setVertical(
140 const Reference< XDiagram > & xDiagram,
141 bool bVertical /* = true */ )
142 {
143 try
144 {
145 Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY );
146 if( xCnt.is())
147 {
148 Sequence< Reference< XCoordinateSystem > > aCooSys(
149 xCnt->getCoordinateSystems());
150 uno::Any aValue;
151 aValue <<= bVertical;
152 for( sal_Int32 i=0; i<aCooSys.getLength(); ++i )
153 {
154 uno::Reference< XCoordinateSystem > xCooSys( aCooSys[i] );
155 Reference< beans::XPropertySet > xProp( xCooSys, uno::UNO_QUERY );
156 bool bChanged = false;
157 if( xProp.is() )
158 {
159 bool bOldSwap = sal_False;
160 if( !(xProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bOldSwap)
161 || bVertical != bOldSwap )
162 bChanged = true;
163
164 if( bChanged )
165 xProp->setPropertyValue( C2U("SwapXAndYAxis"), aValue );
166 }
167 if( xCooSys.is() )
168 {
169 const sal_Int32 nDimensionCount( xCooSys->getDimension() );
170 sal_Int32 nDimIndex = 0;
171 for(nDimIndex=0; nDimIndex<nDimensionCount; ++nDimIndex)
172 {
173 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
174 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
175 {
176 Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( nDimIndex,nI ));
177 if( xAxis.is() )
178 {
179 //adapt title rotation only when axis swapping has changed
180 if( bChanged )
181 {
182 Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY );
183 if( xTitled.is())
184 {
185 Reference< beans::XPropertySet > xTitleProps( xTitled->getTitleObject(), uno::UNO_QUERY );
186 if( !xTitleProps.is() )
187 continue;
188 double fAngleDegree = 0.0;
189 xTitleProps->getPropertyValue( C2U( "TextRotation" ) ) >>= fAngleDegree;
190 if( !::rtl::math::approxEqual( fAngleDegree, 0.0 )
191 && !::rtl::math::approxEqual( fAngleDegree, 90.0 ) )
192 continue;
193
194 double fNewAngleDegree = 0.0;
195 if( !bVertical && nDimIndex == 1 )
196 fNewAngleDegree = 90.0;
197 else if( bVertical && nDimIndex == 0 )
198 fNewAngleDegree = 90.0;
199
200 xTitleProps->setPropertyValue( C2U( "TextRotation" ), uno::makeAny( fNewAngleDegree ));
201 }
202 }
203 }
204 }
205 }
206 }
207 }
208 }
209 }
210 catch( uno::Exception & ex )
211 {
212 ASSERT_EXCEPTION( ex );
213 }
214 }
215
getVertical(const uno::Reference<chart2::XDiagram> & xDiagram,bool & rbFound,bool & rbAmbiguous)216 bool DiagramHelper::getVertical( const uno::Reference< chart2::XDiagram > & xDiagram,
217 bool& rbFound, bool& rbAmbiguous )
218 {
219 bool bValue = false;
220 rbFound = false;
221 rbAmbiguous = false;
222
223 Reference< XCoordinateSystemContainer > xCnt( xDiagram, uno::UNO_QUERY );
224 if( xCnt.is())
225 {
226 Sequence< Reference< XCoordinateSystem > > aCooSys(
227 xCnt->getCoordinateSystems());
228 for( sal_Int32 i=0; i<aCooSys.getLength(); ++i )
229 {
230 Reference< beans::XPropertySet > xProp( aCooSys[i], uno::UNO_QUERY );
231 if( xProp.is())
232 {
233 bool bCurrent = false;
234 if( xProp->getPropertyValue( C2U("SwapXAndYAxis") ) >>= bCurrent )
235 {
236 if( !rbFound )
237 {
238 bValue = bCurrent;
239 rbFound = true;
240 }
241 else if( bCurrent != bValue )
242 {
243 // ambiguous -> choose always first found
244 rbAmbiguous = true;
245 }
246 }
247 }
248 }
249 }
250 return bValue;
251 }
252
setStackMode(const Reference<XDiagram> & xDiagram,StackMode eStackMode,bool bOnlyAtFirstChartType)253 void DiagramHelper::setStackMode(
254 const Reference< XDiagram > & xDiagram,
255 StackMode eStackMode,
256 bool bOnlyAtFirstChartType /* = true */
257 )
258 {
259 try
260 {
261 if( eStackMode == StackMode_AMBIGUOUS )
262 return;
263
264 bool bValueFound = false;
265 bool bIsAmbiguous = false;
266 StackMode eOldStackMode = DiagramHelper::getStackMode( xDiagram, bValueFound, bIsAmbiguous );
267
268 if( eStackMode == eOldStackMode && !bIsAmbiguous )
269 return;
270
271 StackingDirection eNewDirection = StackingDirection_NO_STACKING;
272 if( eStackMode == StackMode_Y_STACKED || eStackMode == StackMode_Y_STACKED_PERCENT )
273 eNewDirection = StackingDirection_Y_STACKING;
274 else if( eStackMode == StackMode_Z_STACKED )
275 eNewDirection = StackingDirection_Z_STACKING;
276
277 uno::Any aNewDirection( uno::makeAny(eNewDirection) );
278
279 sal_Bool bPercent = sal_False;
280 if( eStackMode == StackMode_Y_STACKED_PERCENT )
281 bPercent = sal_True;
282
283 //iterate through all coordinate systems
284 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
285 if( !xCooSysContainer.is() )
286 return;
287 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
288 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
289 {
290 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
291 //set correct percent stacking
292 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(1);
293 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
294 {
295 Reference< chart2::XAxis > xAxis( xCooSys->getAxisByDimension( 1,nI ));
296 if( xAxis.is())
297 {
298 chart2::ScaleData aScaleData = xAxis->getScaleData();
299 if( (aScaleData.AxisType==AxisType::PERCENT) != bPercent )
300 {
301 if( bPercent )
302 aScaleData.AxisType = AxisType::PERCENT;
303 else
304 aScaleData.AxisType = AxisType::REALNUMBER;
305 xAxis->setScaleData( aScaleData );
306 }
307 }
308 }
309 //iterate through all chart types in the current coordinate system
310 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
311 if( !xChartTypeContainer.is() )
312 continue;
313 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
314 sal_Int32 nMax = aChartTypeList.getLength();
315 if( bOnlyAtFirstChartType
316 && nMax >= 1 )
317 nMax = 1;
318 for( sal_Int32 nT = 0; nT < nMax; ++nT )
319 {
320 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
321
322 //iterate through all series in this chart type
323 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
324 OSL_ASSERT( xDataSeriesContainer.is());
325 if( !xDataSeriesContainer.is() )
326 continue;
327
328 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
329 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
330 {
331 Reference< beans::XPropertySet > xProp( aSeriesList[nS], uno::UNO_QUERY );
332 if(xProp.is())
333 xProp->setPropertyValue( C2U( "StackingDirection" ), aNewDirection );
334 }
335 }
336 }
337 }
338 catch( uno::Exception & ex )
339 {
340 ASSERT_EXCEPTION( ex );
341 }
342 }
343
getStackMode(const Reference<XDiagram> & xDiagram,bool & rbFound,bool & rbAmbiguous)344 StackMode DiagramHelper::getStackMode( const Reference< XDiagram > & xDiagram, bool& rbFound, bool& rbAmbiguous )
345 {
346 rbFound=false;
347 rbAmbiguous=false;
348
349 StackMode eGlobalStackMode = StackMode_NONE;
350
351 //iterate through all coordinate systems
352 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
353 if( !xCooSysContainer.is() )
354 return eGlobalStackMode;
355 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
356 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
357 {
358 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
359
360 //iterate through all chart types in the current coordinate system
361 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
362 if( !xChartTypeContainer.is() )
363 continue;
364 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
365 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
366 {
367 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
368
369 StackMode eLocalStackMode = DiagramHelper::getStackModeFromChartType(
370 xChartType, rbFound, rbAmbiguous, xCooSys );
371
372 if( rbFound && eLocalStackMode != eGlobalStackMode && nT>0 )
373 {
374 rbAmbiguous = true;
375 return eGlobalStackMode;
376 }
377
378 eGlobalStackMode = eLocalStackMode;
379 }
380 }
381
382 return eGlobalStackMode;
383 }
384
getStackModeFromChartType(const Reference<XChartType> & xChartType,bool & rbFound,bool & rbAmbiguous,const Reference<XCoordinateSystem> & xCorrespondingCoordinateSystem)385 StackMode DiagramHelper::getStackModeFromChartType(
386 const Reference< XChartType > & xChartType,
387 bool& rbFound, bool& rbAmbiguous,
388 const Reference< XCoordinateSystem > & xCorrespondingCoordinateSystem )
389 {
390 StackMode eStackMode = StackMode_NONE;
391 rbFound = false;
392 rbAmbiguous = false;
393
394 try
395 {
396 Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW );
397 Sequence< Reference< chart2::XDataSeries > > aSeries( xDSCnt->getDataSeries());
398
399 chart2::StackingDirection eCommonDirection = chart2::StackingDirection_NO_STACKING;
400 bool bDirectionInitialized = false;
401
402 // first series is irrelvant for stacking, start with second, unless
403 // there is only one series
404 const sal_Int32 nSeriesCount = aSeries.getLength();
405 sal_Int32 i = (nSeriesCount == 1) ? 0: 1;
406 for( ; i<nSeriesCount; ++i )
407 {
408 rbFound = true;
409 Reference< beans::XPropertySet > xProp( aSeries[i], uno::UNO_QUERY_THROW );
410 chart2::StackingDirection eCurrentDirection = eCommonDirection;
411 // property is not MAYBEVOID
412 bool bSuccess = ( xProp->getPropertyValue( C2U("StackingDirection") ) >>= eCurrentDirection );
413 OSL_ASSERT( bSuccess );
414 (void)(bSuccess); // avoid warning in non-debug builds
415 if( ! bDirectionInitialized )
416 {
417 eCommonDirection = eCurrentDirection;
418 bDirectionInitialized = true;
419 }
420 else
421 {
422 if( eCommonDirection != eCurrentDirection )
423 {
424 rbAmbiguous = true;
425 break;
426 }
427 }
428 }
429
430 if( rbFound )
431 {
432 if( eCommonDirection == chart2::StackingDirection_Z_STACKING )
433 eStackMode = StackMode_Z_STACKED;
434 else if( eCommonDirection == chart2::StackingDirection_Y_STACKING )
435 {
436 eStackMode = StackMode_Y_STACKED;
437
438 // percent stacking
439 if( xCorrespondingCoordinateSystem.is() )
440 {
441 if( 1 < xCorrespondingCoordinateSystem->getDimension() )
442 {
443 sal_Int32 nAxisIndex = 0;
444 if( nSeriesCount )
445 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(aSeries[0]);
446
447 Reference< chart2::XAxis > xAxis(
448 xCorrespondingCoordinateSystem->getAxisByDimension( 1,nAxisIndex ));
449 if( xAxis.is())
450 {
451 chart2::ScaleData aScaleData = xAxis->getScaleData();
452 if( aScaleData.AxisType==chart2::AxisType::PERCENT )
453 eStackMode = StackMode_Y_STACKED_PERCENT;
454 }
455 }
456 }
457 }
458 }
459 }
460 catch( uno::Exception & ex )
461 {
462 ASSERT_EXCEPTION( ex );
463 }
464
465 return eStackMode;
466 }
467
getDimension(const Reference<XDiagram> & xDiagram)468 sal_Int32 DiagramHelper::getDimension( const Reference< XDiagram > & xDiagram )
469 {
470 // -1: not yet set
471 sal_Int32 nResult = -1;
472
473 try
474 {
475 Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY );
476 if( xCooSysCnt.is() )
477 {
478 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
479 xCooSysCnt->getCoordinateSystems());
480
481 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
482 {
483 Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] );
484 if(xCooSys.is())
485 {
486 nResult = xCooSys->getDimension();
487 break;
488 }
489 }
490 }
491 }
492 catch( uno::Exception & ex )
493 {
494 ASSERT_EXCEPTION( ex );
495 }
496
497 return nResult;
498 }
499
setDimension(const Reference<XDiagram> & xDiagram,sal_Int32 nNewDimensionCount)500 void DiagramHelper::setDimension(
501 const Reference< XDiagram > & xDiagram,
502 sal_Int32 nNewDimensionCount )
503 {
504 if( ! xDiagram.is())
505 return;
506
507 if( DiagramHelper::getDimension( xDiagram ) == nNewDimensionCount )
508 return;
509
510 try
511 {
512 bool rbFound = false;
513 bool rbAmbiguous = true;
514 StackMode eStackMode = DiagramHelper::getStackMode( xDiagram, rbFound, rbAmbiguous );
515 bool bIsSupportingOnlyDeepStackingFor3D=false;
516
517 //change all coordinate systems:
518 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY_THROW );
519 Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
520 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
521 {
522 Reference< XCoordinateSystem > xOldCooSys( aCooSysList[nCS], uno::UNO_QUERY );
523 Reference< XCoordinateSystem > xNewCooSys;
524
525 Reference< XChartTypeContainer > xChartTypeContainer( xOldCooSys, uno::UNO_QUERY );
526 if( !xChartTypeContainer.is() )
527 continue;
528
529 Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
530 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
531 {
532 Reference< XChartType > xChartType( aChartTypeList[nT], uno::UNO_QUERY );
533 bIsSupportingOnlyDeepStackingFor3D = ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType );
534 if(!xNewCooSys.is())
535 {
536 xNewCooSys = xChartType->createCoordinateSystem( nNewDimensionCount );
537 break;
538 }
539 //@todo make sure that all following charttypes are also capable of the new dimension
540 //otherwise separate them in a different group
541 //BM: might be done in replaceCoordinateSystem()
542 }
543
544 // replace the old coordinate system at all places where it was used
545 DiagramHelper::replaceCoordinateSystem( xDiagram, xOldCooSys, xNewCooSys );
546 }
547
548 //correct stack mode if necessary
549 if( nNewDimensionCount==3 && eStackMode != StackMode_Z_STACKED && bIsSupportingOnlyDeepStackingFor3D )
550 DiagramHelper::setStackMode( xDiagram, StackMode_Z_STACKED );
551 else if( nNewDimensionCount==2 && eStackMode == StackMode_Z_STACKED )
552 DiagramHelper::setStackMode( xDiagram, StackMode_NONE );
553 }
554 catch( uno::Exception & ex )
555 {
556 ASSERT_EXCEPTION( ex );
557 }
558 }
559
replaceCoordinateSystem(const Reference<XDiagram> & xDiagram,const Reference<XCoordinateSystem> & xCooSysToReplace,const Reference<XCoordinateSystem> & xReplacement)560 void DiagramHelper::replaceCoordinateSystem(
561 const Reference< XDiagram > & xDiagram,
562 const Reference< XCoordinateSystem > & xCooSysToReplace,
563 const Reference< XCoordinateSystem > & xReplacement )
564 {
565 OSL_ASSERT( xDiagram.is());
566 if( ! xDiagram.is())
567 return;
568
569 // update the coordinate-system container
570 Reference< XCoordinateSystemContainer > xCont( xDiagram, uno::UNO_QUERY );
571 if( xCont.is())
572 {
573 try
574 {
575 Reference< chart2::data::XLabeledDataSequence > xCategories = DiagramHelper::getCategoriesFromDiagram( xDiagram );
576
577 // move chart types of xCooSysToReplace to xReplacement
578 Reference< XChartTypeContainer > xCTCntCooSys( xCooSysToReplace, uno::UNO_QUERY_THROW );
579 Reference< XChartTypeContainer > xCTCntReplacement( xReplacement, uno::UNO_QUERY_THROW );
580 xCTCntReplacement->setChartTypes( xCTCntCooSys->getChartTypes());
581
582 xCont->removeCoordinateSystem( xCooSysToReplace );
583 xCont->addCoordinateSystem( xReplacement );
584
585 if( xCategories.is() )
586 DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram );
587 }
588 catch( uno::Exception & ex )
589 {
590 ASSERT_EXCEPTION( ex );
591 }
592 }
593 }
594
isSeriesAttachedToMainAxis(const uno::Reference<chart2::XDataSeries> & xDataSeries)595 bool DiagramHelper::isSeriesAttachedToMainAxis(
596 const uno::Reference< chart2::XDataSeries >& xDataSeries )
597 {
598 sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
599 return (nAxisIndex==0);
600 }
601
attachSeriesToAxis(bool bAttachToMainAxis,const uno::Reference<chart2::XDataSeries> & xDataSeries,const uno::Reference<chart2::XDiagram> & xDiagram,const uno::Reference<uno::XComponentContext> & xContext,bool bAdaptAxes)602 bool DiagramHelper::attachSeriesToAxis( bool bAttachToMainAxis
603 , const uno::Reference< chart2::XDataSeries >& xDataSeries
604 , const uno::Reference< chart2::XDiagram >& xDiagram
605 , const uno::Reference< uno::XComponentContext > & xContext
606 , bool bAdaptAxes )
607 {
608 bool bChanged = false;
609
610 //set property at axis
611 Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
612 if( !xProp.is() )
613 return bChanged;
614
615 sal_Int32 nNewAxisIndex = bAttachToMainAxis ? 0 : 1;
616 sal_Int32 nOldAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
617 uno::Reference< chart2::XAxis > xOldAxis( DiagramHelper::getAttachedAxis( xDataSeries, xDiagram ) );
618
619 if( nOldAxisIndex != nNewAxisIndex )
620 {
621 try
622 {
623 xProp->setPropertyValue( C2U("AttachedAxisIndex"), uno::makeAny( nNewAxisIndex ) );
624 bChanged = true;
625 }
626 catch( const uno::Exception & ex )
627 {
628 ASSERT_EXCEPTION( ex );
629 }
630 }
631
632 if( bChanged && xDiagram.is() )
633 {
634 uno::Reference< XAxis > xAxis( AxisHelper::getAxis( 1, bAttachToMainAxis, xDiagram ) );
635 if(!xAxis.is()) //create an axis if necessary
636 xAxis = AxisHelper::createAxis( 1, bAttachToMainAxis, xDiagram, xContext );
637 if( bAdaptAxes )
638 {
639 AxisHelper::makeAxisVisible( xAxis );
640 AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis, xDiagram );
641 }
642 }
643
644 return bChanged;
645 }
646
getAttachedAxis(const uno::Reference<XDataSeries> & xSeries,const uno::Reference<XDiagram> & xDiagram)647 uno::Reference< XAxis > DiagramHelper::getAttachedAxis(
648 const uno::Reference< XDataSeries >& xSeries,
649 const uno::Reference< XDiagram >& xDiagram )
650 {
651 return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries ), xDiagram );
652 }
653
getChartTypeOfSeries(const uno::Reference<chart2::XDiagram> & xDiagram,const uno::Reference<XDataSeries> & xGivenDataSeries)654 uno::Reference< XChartType > DiagramHelper::getChartTypeOfSeries(
655 const uno::Reference< chart2::XDiagram >& xDiagram
656 , const uno::Reference< XDataSeries >& xGivenDataSeries )
657 {
658 if( !xGivenDataSeries.is() )
659 return 0;
660 if(!xDiagram.is())
661 return 0;
662
663 //iterate through the model to find the given xSeries
664 //the found parent indicates the charttype
665
666 //iterate through all coordinate systems
667 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
668 if( !xCooSysContainer.is())
669 return 0;
670
671 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
672 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
673 {
674 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
675
676 //iterate through all chart types in the current coordinate system
677 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
678 OSL_ASSERT( xChartTypeContainer.is());
679 if( !xChartTypeContainer.is() )
680 continue;
681 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
682 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
683 {
684 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
685
686 //iterate through all series in this chart type
687 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
688 OSL_ASSERT( xDataSeriesContainer.is());
689 if( !xDataSeriesContainer.is() )
690 continue;
691
692 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
693 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
694 {
695 if( xGivenDataSeries==aSeriesList[nS] )
696 return xChartType;
697 }
698 }
699 }
700 return 0;
701 }
702
703 ::std::vector< Reference< XDataSeries > >
getDataSeriesFromDiagram(const Reference<XDiagram> & xDiagram)704 DiagramHelper::getDataSeriesFromDiagram(
705 const Reference< XDiagram > & xDiagram )
706 {
707 ::std::vector< Reference< XDataSeries > > aResult;
708
709 try
710 {
711 Reference< XCoordinateSystemContainer > xCooSysCnt(
712 xDiagram, uno::UNO_QUERY_THROW );
713 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
714 xCooSysCnt->getCoordinateSystems());
715 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
716 {
717 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
718 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
719 for( sal_Int32 j=0; j<aChartTypeSeq.getLength(); ++j )
720 {
721 Reference< XDataSeriesContainer > xDSCnt( aChartTypeSeq[j], uno::UNO_QUERY_THROW );
722 Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
723 ::std::copy( aSeriesSeq.getConstArray(), aSeriesSeq.getConstArray() + aSeriesSeq.getLength(),
724 ::std::back_inserter( aResult ));
725 }
726 }
727 }
728 catch( uno::Exception & ex )
729 {
730 ASSERT_EXCEPTION( ex );
731 }
732
733 return aResult;
734 }
735
736 Sequence< Sequence< Reference< XDataSeries > > >
getDataSeriesGroups(const Reference<XDiagram> & xDiagram)737 DiagramHelper::getDataSeriesGroups( const Reference< XDiagram > & xDiagram )
738 {
739 vector< Sequence< Reference< XDataSeries > > > aResult;
740
741 //iterate through all coordinate systems
742 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
743 if( xCooSysContainer.is() )
744 {
745 Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
746 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
747 {
748 //iterate through all chart types in the current coordinate system
749 Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY );
750 if( !xChartTypeContainer.is() )
751 continue;
752 Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
753 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
754 {
755 Reference< XDataSeriesContainer > xDataSeriesContainer( aChartTypeList[nT], uno::UNO_QUERY );
756 if( !xDataSeriesContainer.is() )
757 continue;
758 aResult.push_back( xDataSeriesContainer->getDataSeries() );
759 }
760 }
761 }
762 return ContainerHelper::ContainerToSequence( aResult );
763 }
764
765 Reference< XChartType >
getChartTypeByIndex(const Reference<XDiagram> & xDiagram,sal_Int32 nIndex)766 DiagramHelper::getChartTypeByIndex( const Reference< XDiagram >& xDiagram, sal_Int32 nIndex )
767 {
768 Reference< XChartType > xChartType;
769
770 //iterate through all coordinate systems
771 Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
772 if( ! xCooSysContainer.is())
773 return xChartType;
774
775 Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
776 sal_Int32 nTypesSoFar = 0;
777 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
778 {
779 Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY );
780 if( !xChartTypeContainer.is() )
781 continue;
782 Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
783 if( nIndex >= 0 && nIndex < (nTypesSoFar + aChartTypeList.getLength()) )
784 {
785 xChartType.set( aChartTypeList[nIndex - nTypesSoFar] );
786 break;
787 }
788 nTypesSoFar += aChartTypeList.getLength();
789 }
790
791 return xChartType;
792 }
793
794 namespace
795 {
796
lcl_getAxisHoldingCategoriesFromDiagram(const Reference<XDiagram> & xDiagram)797 std::vector< Reference< XAxis > > lcl_getAxisHoldingCategoriesFromDiagram(
798 const Reference< XDiagram > & xDiagram )
799 {
800 std::vector< Reference< XAxis > > aRet;
801
802 Reference< XAxis > xResult;
803 // return first x-axis as fall-back
804 Reference< XAxis > xFallBack;
805 try
806 {
807 Reference< XCoordinateSystemContainer > xCooSysCnt(
808 xDiagram, uno::UNO_QUERY_THROW );
809 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
810 xCooSysCnt->getCoordinateSystems());
811 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
812 {
813 Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] );
814 OSL_ASSERT( xCooSys.is());
815 for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
816 {
817 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
818 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
819 {
820 Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI );
821 OSL_ASSERT( xAxis.is());
822 if( xAxis.is())
823 {
824 ScaleData aScaleData = xAxis->getScaleData();
825 if( aScaleData.Categories.is() || (aScaleData.AxisType == AxisType::CATEGORY) )
826 {
827 aRet.push_back(xAxis);
828 }
829 if( (nN == 0) && !xFallBack.is())
830 xFallBack.set( xAxis );
831 }
832 }
833 }
834 }
835 }
836 catch( uno::Exception & ex )
837 {
838 ASSERT_EXCEPTION( ex );
839 }
840
841 if( aRet.empty() )
842 aRet.push_back(xFallBack);
843
844 return aRet;
845 }
846
847 } // anonymous namespace
848
isCategoryDiagram(const Reference<XDiagram> & xDiagram)849 bool DiagramHelper::isCategoryDiagram(
850 const Reference< XDiagram >& xDiagram )
851 {
852 try
853 {
854 Reference< XCoordinateSystemContainer > xCooSysCnt(
855 xDiagram, uno::UNO_QUERY_THROW );
856 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
857 xCooSysCnt->getCoordinateSystems());
858 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
859 {
860 Reference< XCoordinateSystem > xCooSys( aCooSysSeq[i] );
861 OSL_ASSERT( xCooSys.is());
862 for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
863 {
864 const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
865 for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
866 {
867 Reference< XAxis > xAxis = xCooSys->getAxisByDimension( nN,nI );
868 OSL_ASSERT( xAxis.is());
869 if( xAxis.is())
870 {
871 ScaleData aScaleData = xAxis->getScaleData();
872 if( aScaleData.AxisType == AxisType::CATEGORY || aScaleData.AxisType == AxisType::DATE )
873 return true;
874 }
875 }
876 }
877 }
878 }
879 catch( uno::Exception & ex )
880 {
881 ASSERT_EXCEPTION( ex );
882 }
883
884 return false;
885 }
886
setCategoriesToDiagram(const Reference<chart2::data::XLabeledDataSequence> & xCategories,const Reference<XDiagram> & xDiagram,bool bSetAxisType,bool bCategoryAxis)887 void DiagramHelper::setCategoriesToDiagram(
888 const Reference< chart2::data::XLabeledDataSequence >& xCategories,
889 const Reference< XDiagram >& xDiagram,
890 bool bSetAxisType /* = false */,
891 bool bCategoryAxis /* = true */ )
892 {
893 std::vector< Reference< chart2::XAxis > > aCatAxes(
894 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram ));
895
896 std::vector< Reference< chart2::XAxis > >::iterator aIt( aCatAxes.begin() );
897 std::vector< Reference< chart2::XAxis > >::const_iterator aEnd( aCatAxes.end() );
898
899 for( aIt = aCatAxes.begin(); aIt != aEnd; ++aIt )
900 {
901 Reference< chart2::XAxis > xCatAxis(*aIt);
902 if( xCatAxis.is())
903 {
904 ScaleData aScaleData( xCatAxis->getScaleData());
905 aScaleData.Categories = xCategories;
906 if( bSetAxisType )
907 {
908 if( bCategoryAxis )
909 aScaleData.AxisType = AxisType::CATEGORY;
910 else if( aScaleData.AxisType == AxisType::CATEGORY || aScaleData.AxisType == AxisType::DATE )
911 aScaleData.AxisType = AxisType::REALNUMBER;
912 }
913 xCatAxis->setScaleData( aScaleData );
914 }
915 }
916 }
917
918 Reference< data::XLabeledDataSequence >
getCategoriesFromDiagram(const Reference<XDiagram> & xDiagram)919 DiagramHelper::getCategoriesFromDiagram(
920 const Reference< XDiagram > & xDiagram )
921 {
922 Reference< data::XLabeledDataSequence > xResult;
923
924 try
925 {
926 std::vector< Reference< chart2::XAxis > > aCatAxes(
927 lcl_getAxisHoldingCategoriesFromDiagram( xDiagram ));
928 std::vector< Reference< chart2::XAxis > >::iterator aIt( aCatAxes.begin() );
929 std::vector< Reference< chart2::XAxis > >::const_iterator aEnd( aCatAxes.end() );
930 //search for first categories
931 if( aIt != aEnd )
932 {
933 Reference< chart2::XAxis > xCatAxis(*aIt);
934 if( xCatAxis.is())
935 {
936 ScaleData aScaleData( xCatAxis->getScaleData());
937 if( aScaleData.Categories.is() )
938 {
939 xResult.set( aScaleData.Categories );
940 uno::Reference<beans::XPropertySet> xProp(aScaleData.Categories->getValues(), uno::UNO_QUERY );
941 if( xProp.is() )
942 {
943 try
944 {
945 xProp->setPropertyValue( C2U( "Role" ), uno::makeAny( C2U("categories") ) );
946 }
947 catch( uno::Exception & ex )
948 {
949 ASSERT_EXCEPTION( ex );
950 }
951 }
952 }
953 }
954 }
955 }
956 catch( uno::Exception & ex )
957 {
958 ASSERT_EXCEPTION( ex );
959 }
960
961 return xResult;
962 }
963
lcl_generateAutomaticCategoriesFromChartType(Sequence<rtl::OUString> & rRet,const Reference<XChartType> & xChartType)964 void lcl_generateAutomaticCategoriesFromChartType(
965 Sequence< rtl::OUString >& rRet,
966 const Reference< XChartType >& xChartType )
967 {
968 if(!xChartType.is())
969 return;
970 rtl::OUString aMainSeq( xChartType->getRoleOfSequenceForSeriesLabel() );
971 Reference< XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY );
972 if( xSeriesCnt.is() )
973 {
974 Sequence< Reference< XDataSeries > > aSeriesSeq( xSeriesCnt->getDataSeries() );
975 for( sal_Int32 nS = 0; nS < aSeriesSeq.getLength(); nS++ )
976 {
977 Reference< data::XDataSource > xDataSource( aSeriesSeq[nS], uno::UNO_QUERY );
978 if( !xDataSource.is() )
979 continue;
980 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
981 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aMainSeq ));
982 if( !xLabeledSeq.is() )
983 continue;
984 Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
985 if( !xValueSeq.is() )
986 continue;
987 rRet = xValueSeq->generateLabel( chart2::data::LabelOrigin_LONG_SIDE );
988 if( rRet.getLength() )
989 return;
990 }
991 }
992 }
993
generateAutomaticCategoriesFromCooSys(const Reference<XCoordinateSystem> & xCooSys)994 Sequence< rtl::OUString > DiagramHelper::generateAutomaticCategoriesFromCooSys( const Reference< XCoordinateSystem > & xCooSys )
995 {
996 Sequence< rtl::OUString > aRet;
997
998 Reference< XChartTypeContainer > xTypeCntr( xCooSys, uno::UNO_QUERY );
999 if( xTypeCntr.is() )
1000 {
1001 Sequence< Reference< XChartType > > aChartTypes( xTypeCntr->getChartTypes() );
1002 for( sal_Int32 nN=0; nN<aChartTypes.getLength(); nN++ )
1003 {
1004 lcl_generateAutomaticCategoriesFromChartType( aRet, aChartTypes[nN] );
1005 if( aRet.getLength() )
1006 return aRet;
1007 }
1008 }
1009 return aRet;
1010 }
1011
getExplicitSimpleCategories(const Reference<XChartDocument> & xChartDoc)1012 Sequence< rtl::OUString > DiagramHelper::getExplicitSimpleCategories(
1013 const Reference< XChartDocument >& xChartDoc )
1014 {
1015 Sequence< rtl::OUString > aRet;
1016 uno::Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
1017 if(xChartModel.is())
1018 {
1019 uno::Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
1020 ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, xChartModel );
1021 aRet = aExplicitCategoriesProvider.getSimpleCategories();
1022 }
1023 return aRet;
1024 }
1025
1026 namespace
1027 {
lcl_switchToDateCategories(const Reference<XChartDocument> & xChartDoc,const Reference<XAxis> & xAxis)1028 void lcl_switchToDateCategories( const Reference< XChartDocument >& xChartDoc, const Reference< XAxis >& xAxis )
1029 {
1030 if( !xAxis.is() )
1031 return;
1032 if( !xChartDoc.is() )
1033 return;
1034
1035 ScaleData aScale( xAxis->getScaleData() );
1036 if( xChartDoc->hasInternalDataProvider() )
1037 {
1038 //remove all content the is not of type double and remove multiple level
1039 Reference< XAnyDescriptionAccess > xDataAccess( xChartDoc->getDataProvider(), uno::UNO_QUERY );
1040 if( xDataAccess.is() )
1041 {
1042 Sequence< Sequence< Any > > aAnyCategories( xDataAccess->getAnyRowDescriptions() );
1043 double fTest = 0.0;
1044 double fNan = 0.0;
1045 ::rtl::math::setNan( & fNan );
1046 sal_Int32 nN = aAnyCategories.getLength();
1047 for( ; nN--; )
1048 {
1049 Sequence< Any >& rCat = aAnyCategories[nN];
1050 if( rCat.getLength() > 1 )
1051 rCat.realloc(1);
1052 if( rCat.getLength() == 1 )
1053 {
1054 Any& rAny = rCat[0];
1055 if( !(rAny>>=fTest) )
1056 {
1057 rAny = uno::makeAny(fNan);
1058 }
1059 }
1060 }
1061 xDataAccess->setAnyRowDescriptions( aAnyCategories );
1062 }
1063 //check the numberformat at the axis
1064 Reference< beans::XPropertySet > xAxisProps( xAxis, uno::UNO_QUERY );
1065 Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartDoc, uno::UNO_QUERY );
1066 if( xAxisProps.is() && xNumberFormatsSupplier.is() )
1067 {
1068 sal_Int32 nNumberFormat = -1;
1069 xAxisProps->getPropertyValue( C2U("NumberFormat") ) >>= nNumberFormat;
1070
1071 Reference< util::XNumberFormats > xNumberFormats = Reference< util::XNumberFormats >( xNumberFormatsSupplier->getNumberFormats() );
1072 if( xNumberFormats.is() )
1073 {
1074 Reference< beans::XPropertySet > xKeyProps;
1075 try
1076 {
1077 xKeyProps = xNumberFormats->getByKey( nNumberFormat );
1078 }
1079 catch( uno::Exception & ex )
1080 {
1081 ASSERT_EXCEPTION( ex );
1082 }
1083 sal_Int32 nType = util::NumberFormat::UNDEFINED;
1084 if( xKeyProps.is() )
1085 xKeyProps->getPropertyValue( C2U("Type") ) >>= nType;
1086 if( !( nType & util::NumberFormat::DATE ) )
1087 {
1088 //set a date format to the axis
1089 sal_Bool bCreate = sal_True;
1090 const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
1091 Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::DATE, rLocaleDataWrapper.getLocale(), bCreate );
1092 if( aKeySeq.getLength() )
1093 {
1094 xAxisProps->setPropertyValue( C2U("NumberFormat"), uno::makeAny(aKeySeq[0]) );
1095 }
1096 }
1097 }
1098 }
1099 }
1100 if( aScale.AxisType != chart2::AxisType::DATE )
1101 AxisHelper::removeExplicitScaling( aScale );
1102 aScale.AxisType = chart2::AxisType::DATE;
1103 xAxis->setScaleData( aScale );
1104 }
1105
lcl_switchToTextCategories(const Reference<XChartDocument> & xChartDoc,const Reference<XAxis> & xAxis)1106 void lcl_switchToTextCategories( const Reference< XChartDocument >& xChartDoc, const Reference< XAxis >& xAxis )
1107 {
1108 if( !xAxis.is() )
1109 return;
1110 if( !xChartDoc.is() )
1111 return;
1112 ScaleData aScale( xAxis->getScaleData() );
1113 if( aScale.AxisType != chart2::AxisType::CATEGORY )
1114 AxisHelper::removeExplicitScaling( aScale );
1115 //todo migrate dates to text?
1116 aScale.AxisType = chart2::AxisType::CATEGORY;
1117 aScale.AutoDateAxis = false;
1118 xAxis->setScaleData( aScale );
1119 }
1120
1121 }
1122
switchToDateCategories(const Reference<XChartDocument> & xChartDoc)1123 void DiagramHelper::switchToDateCategories( const Reference< XChartDocument >& xChartDoc )
1124 {
1125 Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
1126 if(xChartModel.is())
1127 {
1128 ControllerLockGuard aCtrlLockGuard( xChartModel );
1129
1130 Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
1131 if( xCooSys.is() )
1132 {
1133 Reference< XAxis > xAxis( xCooSys->getAxisByDimension(0,0) );
1134 lcl_switchToDateCategories( xChartDoc, xAxis );
1135 }
1136 }
1137 }
1138
switchToTextCategories(const Reference<XChartDocument> & xChartDoc)1139 void DiagramHelper::switchToTextCategories( const Reference< XChartDocument >& xChartDoc )
1140 {
1141 Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
1142 if(xChartModel.is())
1143 {
1144 ControllerLockGuard aCtrlLockGuard( xChartModel );
1145
1146 Reference< chart2::XCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( xChartModel ) );
1147 if( xCooSys.is() )
1148 {
1149 Reference< XAxis > xAxis( xCooSys->getAxisByDimension(0,0) );
1150 lcl_switchToTextCategories( xChartDoc, xAxis );
1151 }
1152 }
1153 }
1154
isSupportingDateAxis(const Reference<chart2::XDiagram> & xDiagram)1155 bool DiagramHelper::isSupportingDateAxis( const Reference< chart2::XDiagram >& xDiagram )
1156 {
1157 return ::chart::ChartTypeHelper::isSupportingDateAxis(
1158 DiagramHelper::getChartTypeByIndex( xDiagram, 0 ), DiagramHelper::getDimension( xDiagram ), 0 );
1159 }
1160
isDateNumberFormat(sal_Int32 nNumberFormat,const Reference<util::XNumberFormats> & xNumberFormats)1161 bool DiagramHelper::isDateNumberFormat( sal_Int32 nNumberFormat, const Reference< util::XNumberFormats >& xNumberFormats )
1162 {
1163 bool bIsDate = false;
1164 if( !xNumberFormats.is() )
1165 return bIsDate;
1166
1167 Reference< beans::XPropertySet > xKeyProps = xNumberFormats->getByKey( nNumberFormat );
1168 if( xKeyProps.is() )
1169 {
1170 sal_Int32 nType = util::NumberFormat::UNDEFINED;
1171 xKeyProps->getPropertyValue( C2U("Type") ) >>= nType;
1172 bIsDate = nType & util::NumberFormat::DATE;
1173 }
1174 return bIsDate;
1175 }
1176
getDateNumberFormat(const Reference<util::XNumberFormatsSupplier> & xNumberFormatsSupplier)1177 sal_Int32 DiagramHelper::getDateNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
1178 {
1179 sal_Int32 nRet=-1;
1180 Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
1181 if( xNumberFormats.is() )
1182 {
1183 sal_Bool bCreate = sal_True;
1184 const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
1185 Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::DATE,
1186 rLocaleDataWrapper.getLocale(), bCreate );
1187 if( aKeySeq.getLength() )
1188 {
1189 nRet = aKeySeq[0];
1190 }
1191 }
1192
1193 //try to get a date format with full year display
1194 NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
1195 SvNumberFormatter* pNumFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
1196 if( pNumFormatter )
1197 {
1198 const SvNumberformat* pFormat = pNumFormatter->GetEntry( nRet );
1199 if( pFormat )
1200 nRet = pNumFormatter->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, pFormat->GetLanguage() );
1201 }
1202 return nRet;
1203 }
1204
getPercentNumberFormat(const Reference<util::XNumberFormatsSupplier> & xNumberFormatsSupplier)1205 sal_Int32 DiagramHelper::getPercentNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
1206 {
1207 sal_Int32 nRet=-1;
1208 Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
1209 if( xNumberFormats.is() )
1210 {
1211 sal_Bool bCreate = sal_True;
1212 const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
1213 Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::PERCENT,
1214 rLocaleDataWrapper.getLocale(), bCreate );
1215 if( aKeySeq.getLength() )
1216 {
1217 nRet = aKeySeq[0];
1218 }
1219 }
1220 return nRet;
1221 }
1222
1223 Sequence< Reference< XChartType > >
getChartTypesFromDiagram(const Reference<XDiagram> & xDiagram)1224 DiagramHelper::getChartTypesFromDiagram(
1225 const Reference< XDiagram > & xDiagram )
1226 {
1227 ::std::vector< Reference< XChartType > > aResult;
1228
1229 if(xDiagram.is())
1230 try
1231 {
1232 Reference< XCoordinateSystemContainer > xCooSysCnt(
1233 xDiagram, uno::UNO_QUERY_THROW );
1234 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
1235 xCooSysCnt->getCoordinateSystems());
1236 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
1237 {
1238 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
1239 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
1240 ::std::copy( aChartTypeSeq.getConstArray(), aChartTypeSeq.getConstArray() + aChartTypeSeq.getLength(),
1241 ::std::back_inserter( aResult ));
1242 }
1243 }
1244 catch( uno::Exception & ex )
1245 {
1246 ASSERT_EXCEPTION( ex );
1247 }
1248
1249 return ContainerHelper::ContainerToSequence( aResult );
1250 }
1251
areChartTypesCompatible(const Reference<::chart2::XChartType> & xFirstType,const Reference<::chart2::XChartType> & xSecondType)1252 bool DiagramHelper::areChartTypesCompatible( const Reference< ::chart2::XChartType >& xFirstType,
1253 const Reference< ::chart2::XChartType >& xSecondType )
1254 {
1255 if( !xFirstType.is() || !xSecondType.is() )
1256 return false;
1257
1258 ::std::vector< ::rtl::OUString > aFirstRoles( ContainerHelper::SequenceToVector( xFirstType->getSupportedMandatoryRoles() ) );
1259 ::std::vector< ::rtl::OUString > aSecondRoles( ContainerHelper::SequenceToVector( xSecondType->getSupportedMandatoryRoles() ) );
1260 ::std::sort( aFirstRoles.begin(), aFirstRoles.end() );
1261 ::std::sort( aSecondRoles.begin(), aSecondRoles.end() );
1262 return ( aFirstRoles == aSecondRoles );
1263 }
1264
1265 namespace
1266 {
1267 /**
1268 * This method implements the logic of checking if a series can be moved
1269 * forward/backward. Depending on the "bDoMove" parameter the series will
1270 * be moved (bDoMove = true) or the function just will test if the
1271 * series can be moved without doing the move (bDoMove = false).
1272 *
1273 * @param xDiagram
1274 * Reference to the diagram that contains the series.
1275 *
1276 * @param xGivenDataSeries
1277 * Reference to the series that should moved or tested for moving.
1278 *
1279 * @param bForward
1280 * Direction in which the series should be moved or tested for moving.
1281 *
1282 * @param bDoMove
1283 * Should this function really move the series (true) or just test if it is
1284 * possible (false).
1285 *
1286 *
1287 * @returns
1288 * in case of bDoMove == true
1289 * - True : if the move was done
1290 * - False : the move failed
1291 * in case of bDoMove == false
1292 * - True : the series can be moved
1293 * - False : the series can not be moved
1294 *
1295 */
1296
lcl_moveSeriesOrCheckIfMoveIsAllowed(const Reference<XDiagram> & xDiagram,const Reference<XDataSeries> & xGivenDataSeries,bool bForward,bool bDoMove)1297 bool lcl_moveSeriesOrCheckIfMoveIsAllowed(
1298 const Reference< XDiagram >& xDiagram,
1299 const Reference< XDataSeries >& xGivenDataSeries,
1300 bool bForward,
1301 bool bDoMove )
1302 {
1303 bool bMovedOrMoveAllowed = false;
1304
1305 try
1306 {
1307 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
1308
1309 //find position of series.
1310 bool bFound = false;
1311
1312 if( xGivenDataSeries.is() && xCooSysContainer.is() )
1313 {
1314 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
1315
1316 for( sal_Int32 nCS = 0; !bFound && nCS < aCooSysList.getLength(); ++nCS )
1317 {
1318 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
1319
1320 //iterate through all chart types in the current coordinate system
1321 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
1322 OSL_ASSERT( xChartTypeContainer.is());
1323 if( !xChartTypeContainer.is() )
1324 continue;
1325 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
1326 uno::Reference< XChartType > xFormerChartType;
1327
1328 for( sal_Int32 nT = 0; !bFound && nT < aChartTypeList.getLength(); ++nT )
1329 {
1330 uno::Reference< XChartType > xCurrentChartType( aChartTypeList[nT] );
1331
1332 //iterate through all series in this chart type
1333 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xCurrentChartType, uno::UNO_QUERY );
1334 OSL_ASSERT( xDataSeriesContainer.is());
1335 if( !xDataSeriesContainer.is() )
1336 continue;
1337
1338 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
1339
1340 for( sal_Int32 nS = 0; !bFound && nS < aSeriesList.getLength(); ++nS )
1341 {
1342
1343 // We found the series we are interrested in !
1344 if( xGivenDataSeries==aSeriesList[nS] )
1345 {
1346 sal_Int32 nOldSeriesIndex = nS;
1347 bFound = true;
1348
1349 try
1350 {
1351 sal_Int32 nNewSeriesIndex = nS;
1352
1353 if( bForward )
1354 nNewSeriesIndex--;
1355 else
1356 nNewSeriesIndex++;
1357
1358
1359 if( nNewSeriesIndex >= 0 && nNewSeriesIndex < aSeriesList.getLength() )
1360 {
1361 //move series in the same charttype
1362 bMovedOrMoveAllowed = true;
1363 if( bDoMove )
1364 {
1365 aSeriesList[ nOldSeriesIndex ] = aSeriesList[ nNewSeriesIndex ];
1366 aSeriesList[ nNewSeriesIndex ] = xGivenDataSeries;
1367 xDataSeriesContainer->setDataSeries( aSeriesList );
1368 }
1369 }
1370 else if( nNewSeriesIndex<0 )
1371 {
1372 //exchange series with former charttype
1373 if( xFormerChartType.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType, xCurrentChartType ) )
1374 {
1375 bMovedOrMoveAllowed = true;
1376 if( bDoMove )
1377 {
1378 uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xFormerChartType, uno::UNO_QUERY );
1379 if( xOtherDataSeriesContainer.is() )
1380 {
1381 uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() );
1382 sal_Int32 nOtherSeriesIndex = aOtherSeriesList.getLength()-1;
1383 if( nOtherSeriesIndex >= 0 && nOtherSeriesIndex < aOtherSeriesList.getLength() )
1384 {
1385 uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] );
1386 aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries;
1387 xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList);
1388
1389 aSeriesList[nOldSeriesIndex]=xExchangeSeries;
1390 xDataSeriesContainer->setDataSeries(aSeriesList);
1391 }
1392 }
1393 }
1394 }
1395 }
1396 else if( nT+1 < aChartTypeList.getLength() )
1397 {
1398 //exchange series with next charttype
1399 uno::Reference< XChartType > xOtherChartType( aChartTypeList[nT+1] );
1400 if( xOtherChartType.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType, xCurrentChartType ) )
1401 {
1402 bMovedOrMoveAllowed = true;
1403 if( bDoMove )
1404 {
1405 uno::Reference< XDataSeriesContainer > xOtherDataSeriesContainer( xOtherChartType, uno::UNO_QUERY );
1406 if( xOtherDataSeriesContainer.is() )
1407 {
1408 uno::Sequence< uno::Reference< XDataSeries > > aOtherSeriesList( xOtherDataSeriesContainer->getDataSeries() );
1409 sal_Int32 nOtherSeriesIndex = 0;
1410 if( nOtherSeriesIndex >= 0 && nOtherSeriesIndex < aOtherSeriesList.getLength() )
1411 {
1412 uno::Reference< XDataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] );
1413 aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries;
1414 xOtherDataSeriesContainer->setDataSeries(aOtherSeriesList);
1415
1416 aSeriesList[nOldSeriesIndex]=xExchangeSeries;
1417 xDataSeriesContainer->setDataSeries(aSeriesList);
1418 }
1419 }
1420 }
1421 }
1422 }
1423 }
1424 catch( util::CloseVetoException& )
1425 {
1426 }
1427 catch( uno::RuntimeException& )
1428 {
1429 }
1430 }
1431 }
1432 xFormerChartType = xCurrentChartType;
1433 }
1434 }
1435 }
1436 }
1437 catch( util::CloseVetoException& )
1438 {
1439 }
1440 catch( uno::RuntimeException& )
1441 {
1442 }
1443 return bMovedOrMoveAllowed;
1444 }
1445 } // anonymous namespace
1446
1447
isSeriesMoveable(const Reference<XDiagram> & xDiagram,const Reference<XDataSeries> & xGivenDataSeries,bool bForward)1448 bool DiagramHelper::isSeriesMoveable(
1449 const Reference< XDiagram >& xDiagram,
1450 const Reference< XDataSeries >& xGivenDataSeries,
1451 bool bForward )
1452 {
1453 bool bIsMoveable = false;
1454 const bool bDoMove = false;
1455
1456 bIsMoveable = lcl_moveSeriesOrCheckIfMoveIsAllowed(
1457 xDiagram, xGivenDataSeries, bForward, bDoMove );
1458
1459 return bIsMoveable;
1460 }
1461
1462
moveSeries(const Reference<XDiagram> & xDiagram,const Reference<XDataSeries> & xGivenDataSeries,bool bForward)1463 bool DiagramHelper::moveSeries( const Reference< XDiagram >& xDiagram, const Reference< XDataSeries >& xGivenDataSeries, bool bForward )
1464 {
1465 bool bMoved = false;
1466 const bool bDoMove = true;
1467
1468 bMoved = lcl_moveSeriesOrCheckIfMoveIsAllowed(
1469 xDiagram, xGivenDataSeries, bForward, bDoMove );
1470
1471 return bMoved;
1472 }
1473
isSupportingFloorAndWall(const Reference<chart2::XDiagram> & xDiagram)1474 bool DiagramHelper::isSupportingFloorAndWall( const Reference<
1475 chart2::XDiagram >& xDiagram )
1476 {
1477 //pies and donuts currently do not support this because of wrong files from older versions
1478 //todo: allow this in future again, if fileversion are available for ole objects (metastream)
1479 //thus the wrong bottom can be removed on import
1480
1481 Sequence< Reference< chart2::XChartType > > aTypes(
1482 ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ) );
1483 for( sal_Int32 nN = 0; nN < aTypes.getLength(); nN++ )
1484 {
1485 Reference< chart2::XChartType > xType( aTypes[nN] );
1486 if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
1487 return false;
1488 if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
1489 return false;
1490 if( xType.is() && xType->getChartType().match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
1491 return false;
1492 }
1493 return true;
1494 }
1495
isPieOrDonutChart(const::com::sun::star::uno::Reference<::com::sun::star::chart2::XDiagram> & xDiagram)1496 bool DiagramHelper::isPieOrDonutChart( const ::com::sun::star::uno::Reference<
1497 ::com::sun::star::chart2::XDiagram >& xDiagram )
1498 {
1499 uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex(
1500 xDiagram, 0 ) );
1501
1502 if( xChartType .is() )
1503 {
1504 rtl::OUString aChartType = xChartType->getChartType();
1505 if( aChartType.equals(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
1506 return true;
1507 }
1508 return false;
1509 }
1510
getGeometry3D(const uno::Reference<chart2::XDiagram> & xDiagram,bool & rbFound,bool & rbAmbiguous)1511 sal_Int32 DiagramHelper::getGeometry3D(
1512 const uno::Reference< chart2::XDiagram > & xDiagram,
1513 bool& rbFound, bool& rbAmbiguous )
1514 {
1515 sal_Int32 nCommonGeom( DataPointGeometry3D::CUBOID );
1516 rbFound = false;
1517 rbAmbiguous = false;
1518
1519 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVec(
1520 DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
1521
1522 if( aSeriesVec.empty())
1523 rbAmbiguous = true;
1524
1525 for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt =
1526 aSeriesVec.begin(); aIt != aSeriesVec.end(); ++aIt )
1527 {
1528 try
1529 {
1530 sal_Int32 nGeom = 0;
1531 Reference< beans::XPropertySet > xProp( *aIt, uno::UNO_QUERY_THROW );
1532 if( xProp->getPropertyValue( C2U( "Geometry3D" )) >>= nGeom )
1533 {
1534 if( ! rbFound )
1535 {
1536 // first series
1537 nCommonGeom = nGeom;
1538 rbFound = true;
1539 }
1540 // further series: compare for uniqueness
1541 else if( nCommonGeom != nGeom )
1542 {
1543 rbAmbiguous = true;
1544 break;
1545 }
1546 }
1547 }
1548 catch( uno::Exception & ex )
1549 {
1550 ASSERT_EXCEPTION( ex );
1551 }
1552 }
1553
1554 return nCommonGeom;
1555 }
1556
setGeometry3D(const Reference<chart2::XDiagram> & xDiagram,sal_Int32 nNewGeometry)1557 void DiagramHelper::setGeometry3D(
1558 const Reference< chart2::XDiagram > & xDiagram,
1559 sal_Int32 nNewGeometry )
1560 {
1561 ::std::vector< Reference< chart2::XDataSeries > > aSeriesVec(
1562 DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
1563
1564 for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt =
1565 aSeriesVec.begin(); aIt != aSeriesVec.end(); ++aIt )
1566 {
1567 DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(
1568 *aIt, C2U( "Geometry3D" ), uno::makeAny( nNewGeometry ));
1569 }
1570 }
1571
getCorrectedMissingValueTreatment(const Reference<chart2::XDiagram> & xDiagram,const Reference<chart2::XChartType> & xChartType)1572 sal_Int32 DiagramHelper::getCorrectedMissingValueTreatment(
1573 const Reference< chart2::XDiagram > & xDiagram,
1574 const Reference< chart2::XChartType >& xChartType )
1575 {
1576 sal_Int32 nResult = ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP;
1577 uno::Sequence < sal_Int32 > aAvailableMissingValueTreatments(
1578 ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) );
1579
1580 uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY );
1581 if( xDiaProp.is() && (xDiaProp->getPropertyValue( C2U( "MissingValueTreatment" ) ) >>= nResult) )
1582 {
1583 //ensure that the set value is supported by this charttype
1584 for( sal_Int32 nN = 0; nN < aAvailableMissingValueTreatments.getLength(); nN++ )
1585 if( aAvailableMissingValueTreatments[nN] == nResult )
1586 return nResult; //ok
1587 }
1588
1589 //otherwise use the first supported one
1590 if( aAvailableMissingValueTreatments.getLength() )
1591 {
1592 nResult = aAvailableMissingValueTreatments[0];
1593 return nResult;
1594 }
1595
1596 return nResult;
1597 }
1598
getDiagramPositioningMode(const uno::Reference<chart2::XDiagram> & xDiagram)1599 DiagramPositioningMode DiagramHelper::getDiagramPositioningMode( const uno::Reference<
1600 chart2::XDiagram > & xDiagram )
1601 {
1602 DiagramPositioningMode eMode = DiagramPositioningMode_AUTO;
1603 uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY );
1604 if( xDiaProps.is() )
1605 {
1606 RelativePosition aRelPos;
1607 RelativeSize aRelSize;
1608 if( (xDiaProps->getPropertyValue(C2U("RelativePosition")) >>= aRelPos ) &&
1609 (xDiaProps->getPropertyValue(C2U("RelativeSize")) >>= aRelSize ) )
1610 {
1611 bool bPosSizeExcludeAxes=false;
1612 xDiaProps->getPropertyValue(C2U("PosSizeExcludeAxes")) >>= bPosSizeExcludeAxes;
1613 if( bPosSizeExcludeAxes )
1614 eMode = DiagramPositioningMode_EXCLUDING;
1615 else
1616 eMode = DiagramPositioningMode_INCLUDING;
1617 }
1618 }
1619 return eMode;
1620 }
1621
lcl_ensureRange0to1(double & rValue)1622 void lcl_ensureRange0to1( double& rValue )
1623 {
1624 if(rValue<0.0)
1625 rValue=0.0;
1626 if(rValue>1.0)
1627 rValue=1.0;
1628 }
1629
setDiagramPositioning(const uno::Reference<frame::XModel> & xChartModel,const awt::Rectangle & rPosRect)1630 bool DiagramHelper::setDiagramPositioning( const uno::Reference< frame::XModel >& xChartModel,
1631 const awt::Rectangle& rPosRect /*100th mm*/ )
1632 {
1633 ControllerLockGuard aCtrlLockGuard( xChartModel );
1634
1635 bool bChanged = false;
1636 awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) );
1637 uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY );
1638 if( !xDiaProps.is() )
1639 return bChanged;
1640
1641 RelativePosition aOldPos;
1642 RelativeSize aOldSize;
1643 xDiaProps->getPropertyValue(C2U("RelativePosition") ) >>= aOldPos;
1644 xDiaProps->getPropertyValue(C2U("RelativeSize") ) >>= aOldSize;
1645
1646 RelativePosition aNewPos;
1647 aNewPos.Anchor = drawing::Alignment_TOP_LEFT;
1648 aNewPos.Primary = double(rPosRect.X)/double(aPageSize.Width);
1649 aNewPos.Secondary = double(rPosRect.Y)/double(aPageSize.Height);
1650
1651 chart2::RelativeSize aNewSize;
1652 aNewSize.Primary = double(rPosRect.Width)/double(aPageSize.Width);
1653 aNewSize.Secondary = double(rPosRect.Height)/double(aPageSize.Height);
1654
1655 lcl_ensureRange0to1( aNewPos.Primary );
1656 lcl_ensureRange0to1( aNewPos.Secondary );
1657 lcl_ensureRange0to1( aNewSize.Primary );
1658 lcl_ensureRange0to1( aNewSize.Secondary );
1659 if( (aNewPos.Primary + aNewSize.Primary) > 1.0 )
1660 aNewPos.Primary = 1.0 - aNewSize.Primary;
1661 if( (aNewPos.Secondary + aNewSize.Secondary) > 1.0 )
1662 aNewPos.Secondary = 1.0 - aNewSize.Secondary;
1663
1664 xDiaProps->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aNewPos) );
1665 xDiaProps->setPropertyValue( C2U( "RelativeSize" ), uno::makeAny(aNewSize) );
1666
1667 bChanged = (aOldPos.Anchor!=aNewPos.Anchor) ||
1668 (aOldPos.Primary!=aNewPos.Primary) ||
1669 (aOldPos.Secondary!=aNewPos.Secondary) ||
1670 (aOldSize.Primary!=aNewSize.Primary) ||
1671 (aOldSize.Secondary!=aNewSize.Secondary);
1672 return bChanged;
1673 }
1674
getDiagramRectangleFromModel(const uno::Reference<frame::XModel> & xChartModel)1675 awt::Rectangle DiagramHelper::getDiagramRectangleFromModel( const uno::Reference< frame::XModel >& xChartModel )
1676 {
1677 awt::Rectangle aRet(-1,-1,-1,-1);
1678
1679 uno::Reference< beans::XPropertySet > xDiaProps( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY );
1680 if( !xDiaProps.is() )
1681 return aRet;
1682
1683 awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) );
1684
1685 RelativePosition aRelPos;
1686 RelativeSize aRelSize;
1687 xDiaProps->getPropertyValue(C2U("RelativePosition") ) >>= aRelPos;
1688 xDiaProps->getPropertyValue(C2U("RelativeSize") ) >>= aRelSize;
1689
1690 awt::Size aAbsSize(
1691 static_cast< sal_Int32 >( aRelSize.Primary * aPageSize.Width ),
1692 static_cast< sal_Int32 >( aRelSize.Secondary * aPageSize.Height ));
1693
1694 awt::Point aAbsPos(
1695 static_cast< sal_Int32 >( aRelPos.Primary * aPageSize.Width ),
1696 static_cast< sal_Int32 >( aRelPos.Secondary * aPageSize.Height ));
1697
1698 awt::Point aAbsPosLeftTop = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( aAbsPos, aAbsSize, aRelPos.Anchor );
1699
1700 aRet = awt::Rectangle(aAbsPosLeftTop.X, aAbsPosLeftTop.Y, aAbsSize.Width, aAbsSize.Height );
1701
1702 return aRet;
1703 }
1704
switchDiagramPositioningToExcludingPositioning(const uno::Reference<frame::XModel> & xChartModel,bool bResetModifiedState,bool bConvertAlsoFromAutoPositioning)1705 bool DiagramHelper::switchDiagramPositioningToExcludingPositioning(
1706 const uno::Reference< frame::XModel >& xChartModel
1707 , bool bResetModifiedState, bool bConvertAlsoFromAutoPositioning )
1708 {
1709 //return true if something was changed
1710 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
1711 if( nCurrentODFVersion == SvtSaveOptions::ODFVER_LATEST )//#i100778# todo: change this dependent on fileformat evolution
1712 {
1713 uno::Reference< ::com::sun::star::chart::XChartDocument > xOldDoc( xChartModel, uno::UNO_QUERY ) ;
1714 if( xOldDoc.is() )
1715 {
1716 uno::Reference< ::com::sun::star::chart::XDiagramPositioning > xDiagramPositioning( xOldDoc->getDiagram(), uno::UNO_QUERY );
1717 if( xDiagramPositioning.is() && ( bConvertAlsoFromAutoPositioning || !xDiagramPositioning->isAutomaticDiagramPositioning() )
1718 && !xDiagramPositioning->isExcludingDiagramPositioning() )
1719 {
1720 ControllerLockGuard aCtrlLockGuard( xChartModel );
1721 uno::Reference< util::XModifiable > xModifiable( xChartModel, uno::UNO_QUERY );
1722 bool bModelWasModified = xModifiable.is() && xModifiable->isModified();
1723 xDiagramPositioning->setDiagramPositionExcludingAxes( xDiagramPositioning->calculateDiagramPositionExcludingAxes() );
1724 if(bResetModifiedState && !bModelWasModified && xModifiable.is() )
1725 xModifiable->setModified(sal_False);
1726 return true;
1727 }
1728 }
1729 }
1730 return false;
1731 }
1732
1733 } // namespace chart
1734