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