fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / chart2 / source / view / main / ChartView.cxx
blob3510549abcf9d6946c22586d3d3b183916716dc1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include "ChartView.hxx"
23 #include "chartview/DrawModelWrapper.hxx"
24 #include "NumberFormatterWrapper.hxx"
25 #include "ViewDefines.hxx"
26 #include "VDiagram.hxx"
27 #include "VTitle.hxx"
28 #include "AbstractShapeFactory.hxx"
29 #include "VCoordinateSystem.hxx"
30 #include "VSeriesPlotter.hxx"
31 #include "CommonConverters.hxx"
32 #include "macros.hxx"
33 #include "TitleHelper.hxx"
34 #include "LegendHelper.hxx"
35 #include "VLegend.hxx"
36 #include "PropertyMapper.hxx"
37 #include "ChartModelHelper.hxx"
38 #include "ChartTypeHelper.hxx"
39 #include "ScaleAutomatism.hxx"
40 #include "MinimumAndMaximumSupplier.hxx"
41 #include "ObjectIdentifier.hxx"
42 #include "DiagramHelper.hxx"
43 #include "RelativePositionHelper.hxx"
44 #include "servicenames.hxx"
45 #include "AxisHelper.hxx"
46 #include "AxisIndexDefines.hxx"
47 #include "ControllerLockGuard.hxx"
48 #include "BaseGFXHelper.hxx"
49 #include "DataSeriesHelper.hxx"
50 #include "DateHelper.hxx"
51 #include "defines.hxx"
52 #include <unonames.hxx>
53 #include <GL3DBarChart.hxx>
55 #include <editeng/frmdiritem.hxx>
56 #include <rtl/uuid.h>
57 #include <tools/globname.hxx>
58 #include <comphelper/scopeguard.hxx>
59 #include <comphelper/servicehelper.hxx>
60 #include <cppuhelper/supportsservice.hxx>
61 #include <boost/bind.hpp>
62 #include <unotools/streamwrap.hxx>
63 #include <unotools/localedatawrapper.hxx>
64 #include <svx/charthelper.hxx>
65 #include <svx/svdpage.hxx>
66 #include <svx/unopage.hxx>
67 #include <svx/unoshape.hxx>
68 #include <vcl/svapp.hxx>
69 #include <osl/mutex.hxx>
70 #include <svx/unofill.hxx>
71 #include <vcl/openglwin.hxx>
72 #include <vcl/opengl/OpenGLContext.hxx>
74 #include <drawinglayer/XShapeDumper.hxx>
76 #include <time.h>
78 #include <com/sun/star/awt/Size.hpp>
79 #include <com/sun/star/awt/Point.hpp>
80 #include <com/sun/star/chart/ChartAxisPosition.hpp>
81 #include <com/sun/star/chart/DataLabelPlacement.hpp>
82 #include <com/sun/star/chart/MissingValueTreatment.hpp>
83 #include <com/sun/star/chart2/StackingDirection.hpp>
84 #include <com/sun/star/chart2/XChartDocument.hpp>
85 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
86 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
87 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
88 #include <com/sun/star/chart2/XTitled.hpp>
89 #include <com/sun/star/chart2/RelativePosition.hpp>
90 #include <com/sun/star/chart2/RelativeSize.hpp>
91 #include <com/sun/star/drawing/FillStyle.hpp>
92 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
93 #include <com/sun/star/drawing/LineStyle.hpp>
94 #include <com/sun/star/drawing/XShapeGroup.hpp>
95 #include <com/sun/star/drawing/XShapeDescriptor.hpp>
96 #include <com/sun/star/document/XExporter.hpp>
97 #include <com/sun/star/document/XFilter.hpp>
98 #include <com/sun/star/embed/Aspects.hpp>
99 #include <com/sun/star/io/XSeekable.hpp>
100 #include <com/sun/star/util/XModifiable.hpp>
101 #include <com/sun/star/util/XRefreshable.hpp>
102 #include <com/sun/star/util/NumberFormat.hpp>
103 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
104 #include <com/sun/star/text/XText.hpp>
105 #include <com/sun/star/text/XTextDocument.hpp>
106 #include <com/sun/star/text/WritingMode2.hpp>
107 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
108 #include <com/sun/star/view/XSelectionSupplier.hpp>
109 #include <svl/languageoptions.hxx>
110 #include <comphelper/classids.hxx>
111 #include "servicenames_charttypes.hxx"
113 #include <rtl/strbuf.hxx>
114 #include <rtl/ustring.hxx>
116 #include <osl/conditn.hxx>
117 #include <osl/time.h>
119 #include <boost/shared_ptr.hpp>
120 #include <boost/ptr_container/ptr_vector.hpp>
122 namespace chart {
124 using namespace ::com::sun::star;
125 using namespace ::com::sun::star::chart2;
126 using ::com::sun::star::uno::Reference;
127 using ::com::sun::star::uno::Sequence;
128 using ::com::sun::star::uno::Any;
130 namespace {
132 class theExplicitValueProviderUnoTunnelId : public rtl::Static<UnoTunnelIdInit, theExplicitValueProviderUnoTunnelId> {};
134 typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex; //first index is the dimension, second index is the axis index that indicates whether this is a main or secondary axis
135 typedef std::map< VCoordinateSystem*, tFullAxisIndex > tCoordinateSystemMap;
137 /** This class handles a collection of coordinate systems and is used for
138 * executing some action on all coordinate systems such as
139 * `prepareAutomaticAxisScaling` and `setExplicitScaleAndIncrement`.
140 * Moreover it contains the `aAutoScaling` object that is an instance of
141 * the `ScaleAutomatism` class. The initialization of `aAutoScaling` is
142 * performed in the `SeriesPlotterContainer::initAxisUsageList` method and is
143 * used in the `SeriesPlotterContainer::doAutoScaling` for calculating explicit
144 * scale and increment objects (see `SeriesPlotterContainer::doAutoScaling`).
146 struct AxisUsage
148 AxisUsage();
149 ~AxisUsage();
151 void addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
152 ::std::vector< VCoordinateSystem* > getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
153 sal_Int32 getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex );
155 void prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex );
156 void setExplicitScaleAndIncrement( sal_Int32 nDimIndex, sal_Int32 nAxisIndex, const ExplicitScaleData& rScale, const ExplicitIncrementData& rInc );
158 ScaleAutomatism aAutoScaling;
160 private:
161 tCoordinateSystemMap aCoordinateSystems;
162 std::map< sal_Int32, sal_Int32 > aMaxIndexPerDimension;
165 AxisUsage::AxisUsage()
166 : aAutoScaling(AxisHelper::createDefaultScale(), Date(Date::SYSTEM))
170 AxisUsage::~AxisUsage()
172 aCoordinateSystems.clear();
175 void AxisUsage::addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
177 if(!pCooSys)
178 return;
180 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
181 tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) );
183 //use one scale only once for each coordinate system
184 //main axis are preferred over secondary axis
185 //value scales are preferred
186 if(aFound!=aCoordinateSystems.end())
188 sal_Int32 nFoundAxisIndex = aFound->second.second;
189 if( nFoundAxisIndex < nAxisIndex )
190 return;
191 sal_Int32 nFoundDimension = aFound->second.first;
192 if( nFoundDimension ==1 )
193 return;
194 if( nFoundDimension < nDimensionIndex )
195 return;
197 aCoordinateSystems[pCooSys] = aFullAxisIndex;
199 //set maximum scale index
200 std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
201 if( aIter != aMaxIndexPerDimension.end() )
203 sal_Int32 nCurrentMaxIndex = aIter->second;
204 if( nCurrentMaxIndex < nAxisIndex )
205 aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
207 else
208 aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
211 ::std::vector< VCoordinateSystem* > AxisUsage::getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
213 ::std::vector< VCoordinateSystem* > aRet;
215 tCoordinateSystemMap::const_iterator aIter;
216 for( aIter = aCoordinateSystems.begin(); aIter!=aCoordinateSystems.end();++aIter )
218 if( aIter->second.first != nDimensionIndex )
219 continue;
220 if( aIter->second.second != nAxisIndex )
221 continue;
222 aRet.push_back( aIter->first );
225 return aRet;
228 sal_Int32 AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex )
230 sal_Int32 nRet = -1;
231 std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
232 if( aIter != aMaxIndexPerDimension.end() )
233 nRet = aIter->second;
234 return nRet;
237 void AxisUsage::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex )
239 std::vector<VCoordinateSystem*> aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex);
240 for (size_t i = 0, n = aVCooSysList.size(); i < n; ++i)
241 aVCooSysList[i]->prepareAutomaticAxisScaling(rScaleAutomatism, nDimIndex, nAxisIndex);
244 void AxisUsage::setExplicitScaleAndIncrement(
245 sal_Int32 nDimIndex, sal_Int32 nAxisIndex, const ExplicitScaleData& rScale, const ExplicitIncrementData& rInc )
247 std::vector<VCoordinateSystem*> aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex);
248 for (size_t i = 0, n = aVCooSysList.size(); i < n; ++i)
249 aVCooSysList[i]->setExplicitScaleAndIncrement(nDimIndex, nAxisIndex, rScale, rInc);
252 typedef boost::ptr_vector<VSeriesPlotter> SeriesPlottersType;
254 /** This class is a container of `SeriesPlotter` objects (such as `PieChart`
255 * instances). It is used for initializing coordinate systems, axes and scales
256 * of all series plotters which belongs to the container.
258 class SeriesPlotterContainer
260 public:
261 SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList );
262 ~SeriesPlotterContainer();
264 /** It is used to set coordinate systems (`m_rVCooSysList`), this method
265 * is invoked by `ChartView::createShapes2D` before of
266 * `ChartView::impl_createDiagramAndContent`.
267 * Coordinate systems are retrieved through the `XCoordinateSystemContainer`
268 * interface implemented by a diagram object which is provided by the
269 * `ChartModel` object passed to the method (`rChartModel.getFirstDiagram()`).
271 * It is used for creating series plotters and appending them
272 * to `m_aSeriesPlotterList`. The created series plotters are initialized
273 * through data (number formats supplier, color scheme, data series),
274 * extracted from the chart model or the diagram objects. An exception is
275 * the explicit category provider that is retrieved through the
276 * `VCoordinateSystem` object used by the series plotter.
278 * It sets the minimum-maximum supplier for a coordinate system:
279 * this supplier is the series plotter itself which utilizes the given
280 * coordinate system. In fact `VSeriesPlotter` has `MinimumMaximumSupplier`
281 * as one of its base classes.
282 * Hence, for instance, a `PieChart`, which is a series plotter, is
283 * a `MinimumMaximumSupplier`, too.
285 void initializeCooSysAndSeriesPlotter( ChartModel& rModel );
287 /** This method is invoked by `ChartView::impl_createDiagramAndContent`.
288 * It iterates on every axis of every coordinate systems, and if the axis
289 * is not yet present in `m_aAxisUsageList` it creates a new `AxisUsage`
290 * object and initialize its `aAutoScaling` member to the `ScaleData`
291 * object of the current axis.
293 void initAxisUsageList(const Date& rNullDate);
296 * Perform automatic axis scaling and determine the amount and spacing of
297 * increments. It assumes that the caller has determined the size of the
298 * largest axis label text object prior to calling this method.
300 * The new axis scaling data will be stored in the VCoordinateSystem
301 * objects. The label alignment direction for each axis will also get
302 * determined during this process, and stored in VAxis.
304 * This method is invoked by `ChartView::impl_createDiagramAndContent`
305 * soon after `initAxisUsageList`.
306 * It initializes explicit scale and increment objects for all coordinate
307 * systems in `m_rVCooSysList`.
308 * This action is achieved by iterating on the `m_aAxisUsageList` container,
309 * and performing 3 steps:
310 * 1- call `VCoordinateSystem::prepareAutomaticAxisScaling` for setting
311 * scaling parameters of the `aAutoScaling` member (a `ScaleAutomatism`
312 * object) for the current `AxisUsage` instance
313 * (see `VCoordinateSystem::prepareAutomaticAxisScaling`);
314 * 2- calculate the explicit scale and increment objects
315 * (see ScaleAutomatism::calculateExplicitScaleAndIncrement);
316 * 3- set the explicit scale and increment objects for each coordinate
317 * system.
319 void doAutoScaling( ChartModel& rModel );
322 * After auto-scaling is performed, call this method to set the explicit
323 * scaling and increment data to all relevant VAxis objects.
325 void updateScalesAndIncrementsOnAxes();
328 * After auto-scaling is performed, call this method to set the explicit
329 * scaling data to all the plotters.
331 void setScalesFromCooSysToPlotter();
333 void setNumberFormatsFromAxes();
334 drawing::Direction3D getPreferredAspectRatio();
336 SeriesPlottersType& getSeriesPlotterList() { return m_aSeriesPlotterList; }
337 std::vector< VCoordinateSystem* >& getCooSysList() { return m_rVCooSysList; }
338 std::vector< LegendEntryProvider* > getLegendEntryProviderList();
340 void AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel& rModel );
342 bool isCategoryPositionShifted(
343 const chart2::ScaleData& rSourceScale, bool bHasComplexCategories ) const;
345 private:
346 /** A vector of series plotters.
348 SeriesPlottersType m_aSeriesPlotterList;
350 /** A vector of coordinate systems.
352 std::vector< VCoordinateSystem* >& m_rVCooSysList;
354 /** A map whose key is a `XAxis` interface and the related value is
355 * an object of `AxisUsage` type.
357 ::std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList;
360 * Max axis index of all dimensions. Currently this can be either 0 or 1
361 * since we only support primary and secondary axes per dimension. The
362 * value of 0 means all dimensions have only primary axis, while 1 means
363 * at least one dimension has a secondary axis.
365 sal_Int32 m_nMaxAxisIndex;
367 bool m_bChartTypeUsesShiftedCategoryPositionPerDefault;
368 sal_Int32 m_nDefaultDateNumberFormat;
371 SeriesPlotterContainer::SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList )
372 : m_rVCooSysList( rVCooSysList )
373 , m_nMaxAxisIndex(0)
374 , m_bChartTypeUsesShiftedCategoryPositionPerDefault(false)
375 , m_nDefaultDateNumberFormat(0)
379 SeriesPlotterContainer::~SeriesPlotterContainer()
381 // - remove plotter from coordinatesystems
382 for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
383 m_rVCooSysList[nC]->clearMinimumAndMaximumSupplierList();
386 std::vector< LegendEntryProvider* > SeriesPlotterContainer::getLegendEntryProviderList()
388 std::vector< LegendEntryProvider* > aRet( m_aSeriesPlotterList.size() );
389 SeriesPlottersType::iterator aPlotterIter = m_aSeriesPlotterList.begin();
390 const SeriesPlottersType::iterator aPlotterEnd = m_aSeriesPlotterList.end();
391 sal_Int32 nN = 0;
392 for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter, nN++ )
393 aRet[nN] = &(*aPlotterIter);
394 return aRet;
397 VCoordinateSystem* findInCooSysList( const std::vector< VCoordinateSystem* >& rVCooSysList
398 , const uno::Reference< XCoordinateSystem >& xCooSys )
400 for( size_t nC=0; nC < rVCooSysList.size(); nC++)
402 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
403 if(pVCooSys->getModel()==xCooSys)
404 return pVCooSys;
406 return NULL;
409 VCoordinateSystem* lcl_getCooSysForPlotter( const std::vector< VCoordinateSystem* >& rVCooSysList, MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
411 if(!pMinimumAndMaximumSupplier)
412 return 0;
413 for( size_t nC=0; nC < rVCooSysList.size(); nC++)
415 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
416 if(pVCooSys->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier ))
417 return pVCooSys;
419 return 0;
422 VCoordinateSystem* addCooSysToList( std::vector< VCoordinateSystem* >& rVCooSysList
423 , const uno::Reference< XCoordinateSystem >& xCooSys
424 , ChartModel& rChartModel )
426 VCoordinateSystem* pVCooSys = findInCooSysList( rVCooSysList, xCooSys );
427 if( !pVCooSys )
429 pVCooSys = VCoordinateSystem::createCoordinateSystem(xCooSys );
430 if(pVCooSys)
432 OUString aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys, rChartModel ) );
433 pVCooSys->setParticle(aCooSysParticle);
435 pVCooSys->setExplicitCategoriesProvider( new ExplicitCategoriesProvider(xCooSys, rChartModel) );
437 rVCooSysList.push_back( pVCooSys );
440 return pVCooSys;
443 void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(
444 ChartModel& rChartModel )
446 sal_Int32 nDiagramIndex = 0;//todo if more than one diagram is supported
447 uno::Reference< XDiagram > xDiagram( rChartModel.getFirstDiagram() );
448 if( !xDiagram.is())
449 return;
451 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( static_cast< ::cppu::OWeakObject* >( &rChartModel ), uno::UNO_QUERY );
452 if( rChartModel.hasInternalDataProvider() && DiagramHelper::isSupportingDateAxis( xDiagram ) )
453 m_nDefaultDateNumberFormat=DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
455 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
456 if(!nDimensionCount)
458 //@todo handle mixed dimension
459 nDimensionCount = 2;
462 bool bSortByXValues = false;
463 bool bConnectBars = false;
464 bool bGroupBarsPerAxis = true;
465 bool bIncludeHiddenCells = true;
466 sal_Int32 nStartingAngle = 90;
467 sal_Int32 n3DRelativeHeight = 100;
470 uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW );
471 xDiaProp->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= bSortByXValues;
472 xDiaProp->getPropertyValue( "ConnectBars" ) >>= bConnectBars;
473 xDiaProp->getPropertyValue( "GroupBarsPerAxis" ) >>= bGroupBarsPerAxis;
474 xDiaProp->getPropertyValue( "IncludeHiddenCells" ) >>= bIncludeHiddenCells;
475 xDiaProp->getPropertyValue( "StartingAngle" ) >>= nStartingAngle;
477 if (nDimensionCount == 3)
479 xDiaProp->getPropertyValue( "3DRelativeHeight" ) >>= n3DRelativeHeight;
482 catch( const uno::Exception & ex )
484 ASSERT_EXCEPTION( ex );
487 //prepare for autoscaling and shape creation
488 // - create plotter for charttypes (for each first scale group at each plotter, as they are independent)
489 // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling)
490 // - add plotter to coordinate systems
492 //iterate through all coordinate systems
493 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
494 OSL_ASSERT( xCooSysContainer.is());
495 if( !xCooSysContainer.is())
496 return;
497 uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
498 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
499 sal_Int32 nGlobalSeriesIndex = 0;//for automatic symbols
500 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
502 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
503 VCoordinateSystem* pVCooSys = addCooSysToList(m_rVCooSysList,xCooSys,rChartModel);
505 //iterate through all chart types in the current coordinate system
506 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
507 OSL_ASSERT( xChartTypeContainer.is());
508 if( !xChartTypeContainer.is() )
509 continue;
510 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
511 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
513 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
514 if(3 == nDimensionCount && xChartType->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE))
516 uno::Reference< beans::XPropertySet > xPropertySet( xChartType, uno::UNO_QUERY );
517 if (xPropertySet.is())
521 sal_Int32 n3DRelativeHeightOldValue(100);
522 uno::Any aAny = xPropertySet->getPropertyValue( "3DRelativeHeight" );
523 aAny >>= n3DRelativeHeightOldValue;
524 if (n3DRelativeHeightOldValue != n3DRelativeHeight)
525 xPropertySet->setPropertyValue( "3DRelativeHeight", uno::makeAny(n3DRelativeHeight) );
527 catch (const uno::Exception&) { }
531 if(nT==0)
532 m_bChartTypeUsesShiftedCategoryPositionPerDefault = ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault( xChartType );
534 bool bExcludingPositioning = DiagramPositioningMode_EXCLUDING == DiagramHelper::getDiagramPositioningMode( xDiagram );
535 VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount, bExcludingPositioning );
536 if( !pPlotter )
537 continue;
539 m_aSeriesPlotterList.push_back( pPlotter );
540 pPlotter->setNumberFormatsSupplier( xNumberFormatsSupplier );
541 pPlotter->setColorScheme( xColorScheme );
542 if(pVCooSys)
543 pPlotter->setExplicitCategoriesProvider( pVCooSys->getExplicitCategoriesProvider() );
544 sal_Int32 nMissingValueTreatment = DiagramHelper::getCorrectedMissingValueTreatment( xDiagram, xChartType );
546 if(pVCooSys)
547 pVCooSys->addMinimumAndMaximumSupplier(pPlotter);
549 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
550 OSL_ASSERT( xDataSeriesContainer.is());
551 if( !xDataSeriesContainer.is() )
552 continue;
554 sal_Int32 zSlot=-1;
555 sal_Int32 xSlot=-1;
556 sal_Int32 ySlot=-1;
557 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
558 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
560 uno::Reference< XDataSeries > xDataSeries( aSeriesList[nS], uno::UNO_QUERY );
561 if(!xDataSeries.is())
562 continue;
563 if( !bIncludeHiddenCells && !DataSeriesHelper::hasUnhiddenData(xDataSeries) )
564 continue;
566 VDataSeries* pSeries = new VDataSeries( xDataSeries );
568 pSeries->setGlobalSeriesIndex(nGlobalSeriesIndex);
569 nGlobalSeriesIndex++;
571 if( bSortByXValues )
572 pSeries->doSortByXValues();
574 pSeries->setConnectBars( bConnectBars );
575 pSeries->setGroupBarsPerAxis( bGroupBarsPerAxis );
576 pSeries->setStartingAngle( nStartingAngle );
578 pSeries->setMissingValueTreatment( nMissingValueTreatment );
580 OUString aSeriesParticle( ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCS, nT, nS ) );
581 pSeries->setParticle(aSeriesParticle);
583 OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
584 pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole);
586 //ignore secondary axis for charttypes that do not suppoert them
587 if( pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX &&
588 !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, 1 ) )
590 pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX);
593 StackingDirection eDirection = pSeries->getStackingDirection();
594 switch(eDirection)
596 case StackingDirection_NO_STACKING:
597 xSlot++; ySlot=-1;
598 if(zSlot<0)
599 zSlot=0;
600 break;
601 case StackingDirection_Y_STACKING:
602 ySlot++;
603 if(xSlot<0)
604 xSlot=0;
605 if(zSlot<0)
606 zSlot=0;
607 break;
608 case StackingDirection_Z_STACKING:
609 zSlot++; xSlot=-1; ySlot=-1;
610 break;
611 default:
612 // UNO enums have one additional auto-generated case
613 break;
615 pPlotter->addSeries( pSeries, zSlot, xSlot, ySlot );
620 //transport seriesnames to the coordinatesystems if needed
621 if( !m_aSeriesPlotterList.empty() )
623 uno::Sequence< OUString > aSeriesNames;
624 bool bSeriesNamesInitialized = false;
625 for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
627 VCoordinateSystem* pVCooSys = m_rVCooSysList[nC];
628 if(!pVCooSys)
629 continue;
630 if( pVCooSys->needSeriesNamesForAxis() )
632 if(!bSeriesNamesInitialized)
634 VSeriesPlotter* pSeriesPlotter = &m_aSeriesPlotterList[0];
635 if( pSeriesPlotter )
636 aSeriesNames = pSeriesPlotter->getSeriesNames();
637 bSeriesNamesInitialized = true;
639 pVCooSys->setSeriesNamesForAxis( aSeriesNames );
645 bool SeriesPlotterContainer::isCategoryPositionShifted(
646 const chart2::ScaleData& rSourceScale, bool bHasComplexCategories ) const
648 if (rSourceScale.AxisType == AxisType::CATEGORY && m_bChartTypeUsesShiftedCategoryPositionPerDefault)
649 return true;
651 if (rSourceScale.AxisType==AxisType::CATEGORY && bHasComplexCategories)
652 return true;
654 if (rSourceScale.AxisType == AxisType::DATE)
655 return true;
657 if (rSourceScale.AxisType == AxisType::SERIES)
658 return true;
660 return false;
663 void SeriesPlotterContainer::initAxisUsageList(const Date& rNullDate)
665 m_aAxisUsageList.clear();
667 // Loop through coordinate systems in the diagram (though for now
668 // there should only be one coordinate system per diagram).
669 for (size_t i = 0, n = m_rVCooSysList.size(); i < n; ++i)
671 VCoordinateSystem* pVCooSys = m_rVCooSysList[i];
672 uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel();
673 sal_Int32 nDimCount = xCooSys->getDimension();
675 for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
677 bool bDateAxisAllowed = ChartTypeHelper::isSupportingDateAxis(
678 AxisHelper::getChartTypeByIndex(xCooSys, 0), nDimCount, nDimIndex);
680 // Each dimension may have primary and secondary axes.
681 const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
682 for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; ++nAxisIndex)
684 uno::Reference<XAxis> xAxis = xCooSys->getAxisByDimension(nDimIndex, nAxisIndex);
686 if (!xAxis.is())
687 continue;
689 if (m_aAxisUsageList.find(xAxis) == m_aAxisUsageList.end())
691 // Create axis usage object for this axis.
693 chart2::ScaleData aSourceScale = xAxis->getScaleData();
694 ExplicitCategoriesProvider* pCatProvider = pVCooSys->getExplicitCategoriesProvider();
695 if (nDimIndex == 0)
696 AxisHelper::checkDateAxis( aSourceScale, pCatProvider, bDateAxisAllowed );
698 bool bHasComplexCat = pCatProvider && pCatProvider->hasComplexCategories();
699 aSourceScale.ShiftedCategoryPosition = isCategoryPositionShifted(aSourceScale, bHasComplexCat);
701 m_aAxisUsageList[xAxis].aAutoScaling = ScaleAutomatism(aSourceScale, rNullDate);
704 AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis];
705 rAxisUsage.addCoordinateSystem(pVCooSys, nDimIndex, nAxisIndex);
710 // Determine the highest axis index of all dimensions.
711 ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
712 const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
713 m_nMaxAxisIndex = 0;
714 for (size_t i = 0, n = m_rVCooSysList.size(); i < n; ++i)
716 VCoordinateSystem* pVCooSys = m_rVCooSysList[i];
717 uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel();
718 sal_Int32 nDimCount = xCooSys->getDimension();
720 for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
722 for (aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; ++aAxisIter)
724 sal_Int32 nLocalMax = aAxisIter->second.getMaxAxisIndexForDimension(nDimIndex);
725 if (m_nMaxAxisIndex < nLocalMax)
726 m_nMaxAxisIndex = nLocalMax;
732 void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
734 //set scales to plotter to enable them to provide the preferred scene AspectRatio
735 SeriesPlottersType::iterator aPlotterIter = m_aSeriesPlotterList.begin();
736 const SeriesPlottersType::iterator aPlotterEnd = m_aSeriesPlotterList.end();
737 for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter )
739 VSeriesPlotter* pSeriesPlotter = &(*aPlotterIter);
740 VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
741 if(pVCooSys)
743 pSeriesPlotter->setScales( pVCooSys->getExplicitScales(0,0), pVCooSys->getPropertySwapXAndYAxis() );
744 sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension(1);//only additional value axis are relevant for series plotter
745 for( sal_Int32 nI=1; nI<=nMaxAxisIndex; nI++ )
746 pSeriesPlotter->addSecondaryValueScale( pVCooSys->getExplicitScale(1,nI), nI );
751 void SeriesPlotterContainer::setNumberFormatsFromAxes()
753 //set numberformats to plotter to enable them to display the data labels in the numberformat of the axis
754 SeriesPlottersType::iterator aPlotterIter = m_aSeriesPlotterList.begin();
755 const SeriesPlottersType::iterator aPlotterEnd = m_aSeriesPlotterList.end();
756 for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter )
758 VSeriesPlotter* pSeriesPlotter = &(*aPlotterIter);
759 VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
760 if(pVCooSys)
762 AxesNumberFormats aAxesNumberFormats;
763 uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel();
764 sal_Int32 nDimensionCount = xCooSys->getDimension();
765 for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nDimensionCount; ++nDimensionIndex)
767 const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
768 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
772 Reference< beans::XPropertySet > xAxisProp( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY );
773 if( xAxisProp.is())
775 sal_Int32 nNumberFormatKey(0);
776 if( xAxisProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormatKey )
778 aAxesNumberFormats.setFormat( nNumberFormatKey, nDimensionIndex, nAxisIndex );
780 else if( nDimensionIndex==0 )
782 //provide a default date format for date axis with own data
783 aAxesNumberFormats.setFormat( m_nDefaultDateNumberFormat, nDimensionIndex, nAxisIndex );
787 catch( const lang::IndexOutOfBoundsException& e )
789 ASSERT_EXCEPTION( e );
793 pSeriesPlotter->setAxesNumberFormats( aAxesNumberFormats );
798 void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
800 for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
801 m_rVCooSysList[nC]->updateScalesAndIncrementsOnAxes();
804 void SeriesPlotterContainer::doAutoScaling( ChartModel& rChartModel )
806 if (m_aSeriesPlotterList.empty() || m_aAxisUsageList.empty())
807 // We need these two containers populated to do auto-scaling. Bail out.
808 return;
810 ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
811 const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
813 //iterate over the main scales first than secondary axis
814 for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; ++nAxisIndex)
816 // - first do autoscale for all x and z scales (because they are treated independent)
817 for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; ++aAxisIter )
819 AxisUsage& rAxisUsage = (*aAxisIter).second;
821 rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 0, nAxisIndex);
822 rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 2, nAxisIndex);
824 ExplicitScaleData aExplicitScale;
825 ExplicitIncrementData aExplicitIncrement;
826 rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
828 rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale, aExplicitIncrement);
829 rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale, aExplicitIncrement);
832 // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already )
833 for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; ++aAxisIter )
835 AxisUsage& rAxisUsage = (*aAxisIter).second;
837 rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, nAxisIndex);
839 ExplicitScaleData aExplicitScale;
840 ExplicitIncrementData aExplicitIncrement;
841 rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
843 rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale, aExplicitIncrement);
844 rAxisUsage.setExplicitScaleAndIncrement(1, nAxisIndex, aExplicitScale, aExplicitIncrement);
845 rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale, aExplicitIncrement);
848 AdaptScaleOfYAxisWithoutAttachedSeries( rChartModel );
851 void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel& rModel )
853 //issue #i80518#
855 ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
856 const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
858 for( sal_Int32 nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
860 for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; ++aAxisIter )
862 AxisUsage& rAxisUsage = (*aAxisIter).second;
863 ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems( 1, nAxisIndex );
864 if( !aVCooSysList_Y.size() )
865 continue;
867 uno::Reference< XDiagram > xDiagram( rModel.getFirstDiagram() );
868 if (!xDiagram.is())
869 continue;
871 bool bSeriesAttachedToThisAxis = false;
872 sal_Int32 nAttachedAxisIndex = -1;
874 ::std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
875 ::std::vector< Reference< XDataSeries > >::const_iterator aIter = aSeriesVector.begin();
876 for( ; aIter != aSeriesVector.end(); ++aIter )
878 sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex( *aIter );
879 if( nAxisIndex == nCurrentIndex )
881 bSeriesAttachedToThisAxis = true;
882 break;
884 else if( nAttachedAxisIndex<0 || nAttachedAxisIndex>nCurrentIndex )
885 nAttachedAxisIndex=nCurrentIndex;
889 if (bSeriesAttachedToThisAxis || nAttachedAxisIndex < 0)
890 continue;
892 for( size_t nC = 0; nC < aVCooSysList_Y.size(); ++nC )
894 aVCooSysList_Y[nC]->prepareAutomaticAxisScaling( rAxisUsage.aAutoScaling, 1, nAttachedAxisIndex );
896 ExplicitScaleData aExplicitScaleSource = aVCooSysList_Y[nC]->getExplicitScale( 1,nAttachedAxisIndex );
897 ExplicitIncrementData aExplicitIncrementSource = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAttachedAxisIndex );
899 ExplicitScaleData aExplicitScaleDest = aVCooSysList_Y[nC]->getExplicitScale( 1,nAxisIndex );;
900 ExplicitIncrementData aExplicitIncrementDest = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAxisIndex );;
902 aExplicitScaleDest.Orientation = aExplicitScaleSource.Orientation;
903 aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling;
904 aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType;
906 aExplicitIncrementDest.BaseValue = aExplicitIncrementSource.BaseValue;
908 ScaleData aScale( rAxisUsage.aAutoScaling.getScale() );
909 if( !aScale.Minimum.hasValue() )
911 bool bNewMinOK = true;
912 double fMax=0.0;
913 if( aScale.Maximum >>= fMax )
914 bNewMinOK = (aExplicitScaleSource.Minimum <= fMax);
915 if( bNewMinOK )
916 aExplicitScaleDest.Minimum = aExplicitScaleSource.Minimum;
918 else
919 aExplicitIncrementDest.BaseValue = aExplicitScaleDest.Minimum;
921 if( !aScale.Maximum.hasValue() )
923 bool bNewMaxOK = true;
924 double fMin=0.0;
925 if( aScale.Minimum >>= fMin )
926 bNewMaxOK = (fMin <= aExplicitScaleSource.Maximum);
927 if( bNewMaxOK )
928 aExplicitScaleDest.Maximum = aExplicitScaleSource.Maximum;
930 if( !aScale.Origin.hasValue() )
931 aExplicitScaleDest.Origin = aExplicitScaleSource.Origin;
933 if( !aScale.IncrementData.Distance.hasValue() )
934 aExplicitIncrementDest.Distance = aExplicitIncrementSource.Distance;
936 bool bAutoMinorInterval = true;
937 if( aScale.IncrementData.SubIncrements.getLength() )
938 bAutoMinorInterval = !( aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue() );
939 if( bAutoMinorInterval )
941 if( !aExplicitIncrementDest.SubIncrements.empty() && !aExplicitIncrementSource.SubIncrements.empty() )
942 aExplicitIncrementDest.SubIncrements[0].IntervalCount =
943 aExplicitIncrementSource.SubIncrements[0].IntervalCount;
946 aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScaleDest, aExplicitIncrementDest );
951 if( AxisHelper::isAxisPositioningEnabled() )
953 //correct origin for y main axis (the origin is where the other main axis crosses)
954 sal_Int32 nAxisIndex=0;
955 sal_Int32 nDimensionIndex=1;
956 for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; ++aAxisIter )
958 AxisUsage& rAxisUsage = (*aAxisIter).second;
959 ::std::vector< VCoordinateSystem* > aVCooSysList = rAxisUsage.getCoordinateSystems(nDimensionIndex,nAxisIndex);
960 size_t nC;
961 for( nC=0; nC < aVCooSysList.size(); nC++)
963 ExplicitScaleData aExplicitScale( aVCooSysList[nC]->getExplicitScale( nDimensionIndex, nAxisIndex ) );
964 ExplicitIncrementData aExplicitIncrement( aVCooSysList[nC]->getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
966 Reference< chart2::XCoordinateSystem > xCooSys( aVCooSysList[nC]->getModel() );
967 Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
968 Reference< beans::XPropertySet > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, xCooSys ), uno::UNO_QUERY );
970 ::com::sun::star::chart::ChartAxisPosition eCrossingMainAxisPos( ::com::sun::star::chart::ChartAxisPosition_ZERO );
971 if( xCrossingMainAxis.is() )
973 xCrossingMainAxis->getPropertyValue("CrossoverPosition") >>= eCrossingMainAxisPos;
974 if( ::com::sun::star::chart::ChartAxisPosition_VALUE == eCrossingMainAxisPos )
976 double fValue = 0.0;
977 xCrossingMainAxis->getPropertyValue("CrossoverValue") >>= fValue;
978 aExplicitScale.Origin = fValue;
980 else if( ::com::sun::star::chart::ChartAxisPosition_ZERO == eCrossingMainAxisPos )
981 aExplicitScale.Origin = 0.0;
982 else if( ::com::sun::star::chart::ChartAxisPosition_START == eCrossingMainAxisPos )
983 aExplicitScale.Origin = aExplicitScale.Minimum;
984 else if( ::com::sun::star::chart::ChartAxisPosition_END == eCrossingMainAxisPos )
985 aExplicitScale.Origin = aExplicitScale.Maximum;
988 aVCooSysList[nC]->setExplicitScaleAndIncrement( nDimensionIndex, nAxisIndex, aExplicitScale, aExplicitIncrement );
994 drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio()
996 drawing::Direction3D aPreferredAspectRatio(1.0,1.0,1.0);
998 sal_Int32 nPlotterCount=0;
999 //get a list of all preferred aspect ratios and combine them
1000 //first with special demands wins (less or equal zero <-> arbitrary)
1001 double fx, fy, fz;
1002 fx = fy = fz = -1.0;
1003 SeriesPlottersType::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
1004 const SeriesPlottersType::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
1005 for( aPlotterIter = m_aSeriesPlotterList.begin(), nPlotterCount=0
1006 ; aPlotterIter != aPlotterEnd; ++aPlotterIter, ++nPlotterCount )
1008 drawing::Direction3D aSingleRatio( aPlotterIter->getPreferredDiagramAspectRatio() );
1009 if( fx<0 && aSingleRatio.DirectionX>0 )
1010 fx = aSingleRatio.DirectionX;
1012 if( fy<0 && aSingleRatio.DirectionY>0 )
1014 if( fx>0 && aSingleRatio.DirectionX>0 )
1015 fy = fx*aSingleRatio.DirectionY/aSingleRatio.DirectionX;
1016 else if( fz>0 && aSingleRatio.DirectionZ>0 )
1017 fy = fz*aSingleRatio.DirectionY/aSingleRatio.DirectionZ;
1018 else
1019 fy = aSingleRatio.DirectionY;
1022 if( fz<0 && aSingleRatio.DirectionZ>0 )
1024 if( fx>0 && aSingleRatio.DirectionX>0 )
1025 fz = fx*aSingleRatio.DirectionZ/aSingleRatio.DirectionX;
1026 else if( fy>0 && aSingleRatio.DirectionY>0 )
1027 fz = fy*aSingleRatio.DirectionZ/aSingleRatio.DirectionY;
1028 else
1029 fz = aSingleRatio.DirectionZ;
1032 if( fx>0 && fy>0 && fz>0 )
1033 break;
1035 aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz);
1036 return aPreferredAspectRatio;
1041 struct CreateShapeParam2D
1043 css::awt::Rectangle maRemainingSpace;
1045 boost::shared_ptr<SeriesPlotterContainer> mpSeriesPlotterContainer;
1047 boost::shared_ptr<VTitle> mpVTitleX;
1048 boost::shared_ptr<VTitle> mpVTitleY;
1049 boost::shared_ptr<VTitle> mpVTitleZ;
1051 boost::shared_ptr<VTitle> mpVTitleSecondX;
1052 boost::shared_ptr<VTitle> mpVTitleSecondY;
1054 css::uno::Reference<css::drawing::XShape> mxMarkHandles;
1055 css::uno::Reference<css::drawing::XShape> mxPlotAreaWithAxes;
1057 css::uno::Reference<css::drawing::XShapes> mxDiagramWithAxesShapes;
1059 bool mbAutoPosTitleX;
1060 bool mbAutoPosTitleY;
1061 bool mbAutoPosTitleZ;
1063 bool mbAutoPosSecondTitleX;
1064 bool mbAutoPosSecondTitleY;
1066 bool mbUseFixedInnerSize;
1068 CreateShapeParam2D() :
1069 mbAutoPosTitleX(true),
1070 mbAutoPosTitleY(true),
1071 mbAutoPosTitleZ(true),
1072 mbAutoPosSecondTitleX(true),
1073 mbAutoPosSecondTitleY(true),
1074 mbUseFixedInnerSize(false) {}
1077 class GL2DRenderer : public IRenderer
1079 public:
1080 GL2DRenderer(ChartView* pView);
1081 virtual ~GL2DRenderer();
1083 virtual void update() SAL_OVERRIDE;
1084 virtual void clickedAt(const Point& rPos, sal_uInt16 nButton) SAL_OVERRIDE;
1085 virtual void mouseDragMove(const Point& rBegin, const Point& rEnd, sal_uInt16 nButton) SAL_OVERRIDE;
1086 virtual void scroll(long nDelta) SAL_OVERRIDE;
1087 virtual void contextDestroyed() SAL_OVERRIDE;
1089 const OpenGLWindow* getOpenGLWindow() const;
1090 void updateOpenGLWindow();
1091 private:
1092 ChartView* mpView;
1093 bool mbContextDestroyed;
1094 VclPtr<OpenGLWindow> mpWindow;
1097 GL2DRenderer::GL2DRenderer(ChartView* pView):
1098 mpView(pView),
1099 mbContextDestroyed(false),
1100 mpWindow(mpView->mrChartModel.getOpenGLWindow())
1104 GL2DRenderer::~GL2DRenderer()
1106 SolarMutexGuard g;
1107 if(!mbContextDestroyed && mpWindow)
1108 mpWindow->setRenderer(NULL);
1109 mpWindow.reset();
1112 void GL2DRenderer::update()
1114 mpView->update();
1115 mpView->render();
1118 void GL2DRenderer::clickedAt(const Point&, sal_uInt16 )
1122 void GL2DRenderer::mouseDragMove(const Point& , const Point& , sal_uInt16 )
1126 void GL2DRenderer::scroll(long )
1130 void GL2DRenderer::contextDestroyed()
1132 mbContextDestroyed = true;
1135 const OpenGLWindow* GL2DRenderer::getOpenGLWindow() const
1137 return mpWindow;
1140 void GL2DRenderer::updateOpenGLWindow()
1142 if(mbContextDestroyed)
1143 return;
1145 OpenGLWindow* pWindow = mpView->mrChartModel.getOpenGLWindow();
1146 if(pWindow != mpWindow)
1148 if(mpWindow)
1150 mpWindow->setRenderer(NULL);
1153 if(pWindow)
1155 pWindow->setRenderer(this);
1158 mpWindow = pWindow;
1161 const uno::Sequence<sal_Int8>& ExplicitValueProvider::getUnoTunnelId()
1163 return theExplicitValueProviderUnoTunnelId::get().getSeq();
1166 ExplicitValueProvider* ExplicitValueProvider::getExplicitValueProvider(
1167 const Reference< uno::XInterface >& xChartView )
1169 ExplicitValueProvider* pExplicitValueProvider=0;
1171 Reference< lang::XUnoTunnel > xTunnel( xChartView, uno::UNO_QUERY );
1172 if( xTunnel.is() )
1174 pExplicitValueProvider = reinterpret_cast<ExplicitValueProvider*>(xTunnel->getSomething(
1175 ExplicitValueProvider::getUnoTunnelId() ));
1177 return pExplicitValueProvider;
1180 ChartView::ChartView(
1181 uno::Reference<uno::XComponentContext> const & xContext,
1182 ChartModel& rModel)
1183 : m_aMutex()
1184 , m_xCC(xContext)
1185 , mrChartModel(rModel)
1186 , m_xShapeFactory()
1187 , m_xDrawPage()
1188 , m_pDrawModelWrapper()
1189 , m_aListenerContainer( m_aMutex )
1190 , m_bViewDirty(true)
1191 , m_bInViewUpdate(false)
1192 , m_bViewUpdatePending(false)
1193 , m_bRefreshAddIn(true)
1194 , m_aPageResolution(1000,1000)
1195 , m_bPointsWereSkipped(false)
1196 , m_nScaleXNumerator(1)
1197 , m_nScaleXDenominator(1)
1198 , m_nScaleYNumerator(1)
1199 , m_nScaleYDenominator(1)
1200 , m_bSdrViewIsInEditMode(false)
1201 , m_aResultingDiagramRectangleExcludingAxes(0,0,0,0)
1202 , mp2DRenderer(new GL2DRenderer(this))
1204 init();
1207 void ChartView::init()
1209 if( !m_pDrawModelWrapper.get() )
1211 SolarMutexGuard aSolarGuard;
1212 m_pDrawModelWrapper = ::boost::shared_ptr< DrawModelWrapper >( new DrawModelWrapper( m_xCC ) );
1213 m_xShapeFactory = m_pDrawModelWrapper->getShapeFactory();
1214 m_xDrawPage = m_pDrawModelWrapper->getMainDrawPage();
1215 StartListening( m_pDrawModelWrapper->getSdrModel(), false /*bPreventDups*/ );
1219 void SAL_CALL ChartView::initialize( const uno::Sequence< uno::Any >& )
1220 throw ( uno::Exception, uno::RuntimeException, std::exception)
1222 init();
1225 ChartView::~ChartView()
1227 maTimeBased.maTimer.Stop();
1228 // #i120831#. In ChartView::initialize(), m_xShapeFactory is created from SdrModel::getUnoModel() and indirectly
1229 // from SfxBaseModel, it needs call dispose() to make sure SfxBaseModel object is freed correctly.
1230 uno::Reference< lang::XComponent > xComp( m_xShapeFactory, uno::UNO_QUERY);
1231 if ( xComp.is() )
1232 xComp->dispose();
1234 if( m_pDrawModelWrapper.get() )
1236 SolarMutexGuard aSolarGuard;
1237 EndListening( m_pDrawModelWrapper->getSdrModel(), false /*bAllDups*/ );
1238 m_pDrawModelWrapper.reset();
1240 m_xDrawPage = NULL;
1241 impl_deleteCoordinateSystems();
1244 void ChartView::impl_deleteCoordinateSystems()
1246 //delete all coordinate systems
1247 ::std::vector< VCoordinateSystem* > aVectorToDeleteObjects;
1248 ::std::swap( aVectorToDeleteObjects, m_aVCooSysList );//#i109770#
1249 ::std::vector< VCoordinateSystem* >::const_iterator aIter = aVectorToDeleteObjects.begin();
1250 const ::std::vector< VCoordinateSystem* >::const_iterator aEnd = aVectorToDeleteObjects.end();
1251 for( ; aIter != aEnd; ++aIter )
1253 delete *aIter;
1255 aVectorToDeleteObjects.clear();
1258 // datatransfer::XTransferable
1259 namespace
1261 const OUString lcl_aGDIMetaFileMIMEType(
1262 "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" );
1263 const OUString lcl_aGDIMetaFileMIMETypeHighContrast(
1264 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" );
1265 } // anonymous namespace
1267 void ChartView::getMetaFile( const uno::Reference< io::XOutputStream >& xOutStream
1268 , bool bUseHighContrast )
1270 if( !m_xDrawPage.is() )
1271 return;
1273 // creating the graphic exporter
1274 uno::Reference< drawing::XGraphicExportFilter > xExporter = drawing::GraphicExportFilter::create( m_xCC );
1276 uno::Sequence< beans::PropertyValue > aProps(3);
1277 aProps[0].Name = "FilterName";
1278 aProps[0].Value <<= OUString("SVM");
1280 aProps[1].Name = "OutputStream";
1281 aProps[1].Value <<= xOutStream;
1283 uno::Sequence< beans::PropertyValue > aFilterData(4);
1284 aFilterData[0].Name = "ExportOnlyBackground";
1285 aFilterData[0].Value <<= sal_False;
1286 aFilterData[1].Name = "HighContrast";
1287 aFilterData[1].Value <<= bUseHighContrast;
1289 aFilterData[2].Name = "Version";
1290 const sal_Int32 nVersion = SOFFICE_FILEFORMAT_50;
1291 aFilterData[2].Value <<= nVersion;
1293 aFilterData[3].Name = "CurrentPage";
1294 aFilterData[3].Value <<= uno::Reference< uno::XInterface >( m_xDrawPage, uno::UNO_QUERY );
1296 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
1298 aFilterData.realloc( aFilterData.getLength()+4 );
1299 aFilterData[4].Name = "ScaleXNumerator";
1300 aFilterData[4].Value = uno::makeAny( m_nScaleXNumerator );
1301 aFilterData[5].Name = "ScaleXDenominator";
1302 aFilterData[5].Value = uno::makeAny( m_nScaleXDenominator );
1303 aFilterData[6].Name = "ScaleYNumerator";
1304 aFilterData[6].Value = uno::makeAny( m_nScaleYNumerator );
1305 aFilterData[7].Name = "ScaleYDenominator";
1306 aFilterData[7].Value = uno::makeAny( m_nScaleYDenominator );
1309 aProps[2].Name = "FilterData";
1310 aProps[2].Value <<= aFilterData;
1312 xExporter->setSourceDocument( uno::Reference< lang::XComponent >( m_xDrawPage, uno::UNO_QUERY) );
1313 if( xExporter->filter( aProps ) )
1315 xOutStream->flush();
1316 xOutStream->closeOutput();
1317 uno::Reference< io::XSeekable > xSeekable( xOutStream, uno::UNO_QUERY );
1318 if( xSeekable.is() )
1319 xSeekable->seek(0);
1323 uno::Any SAL_CALL ChartView::getTransferData( const datatransfer::DataFlavor& aFlavor )
1324 throw (datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException, std::exception)
1326 bool bHighContrastMetaFile( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast));
1327 uno::Any aRet;
1328 if( ! (bHighContrastMetaFile || aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType)) )
1329 return aRet;
1331 update();
1333 SvMemoryStream aStream( 1024, 1024 );
1334 utl::OStreamWrapper* pStreamWrapper = new utl::OStreamWrapper( aStream );
1336 uno::Reference< io::XOutputStream > xOutStream( pStreamWrapper );
1337 uno::Reference< io::XInputStream > xInStream( pStreamWrapper );
1338 uno::Reference< io::XSeekable > xSeekable( pStreamWrapper );
1340 if( xOutStream.is() )
1342 this->getMetaFile( xOutStream, bHighContrastMetaFile );
1344 if( xInStream.is() && xSeekable.is() )
1346 xSeekable->seek(0);
1347 sal_Int32 nBytesToRead = xInStream->available();
1348 uno::Sequence< sal_Int8 > aSeq( nBytesToRead );
1349 xInStream->readBytes( aSeq, nBytesToRead);
1350 aRet <<= aSeq;
1351 xInStream->closeInput();
1355 return aRet;
1357 uno::Sequence< datatransfer::DataFlavor > SAL_CALL ChartView::getTransferDataFlavors()
1358 throw (uno::RuntimeException, std::exception)
1360 uno::Sequence< datatransfer::DataFlavor > aRet(2);
1362 aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType,
1363 "GDIMetaFile",
1364 cppu::UnoType<uno::Sequence< sal_Int8 >>::get() );
1365 aRet[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast,
1366 "GDIMetaFile",
1367 cppu::UnoType<uno::Sequence< sal_Int8 >>::get() );
1369 return aRet;
1371 sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
1372 throw (uno::RuntimeException, std::exception)
1374 return ( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType) ||
1375 aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast) );
1378 // ____ XUnoTunnel ___
1379 ::sal_Int64 SAL_CALL ChartView::getSomething( const uno::Sequence< ::sal_Int8 >& aIdentifier )
1380 throw( uno::RuntimeException, std::exception)
1382 if( aIdentifier.getLength() == 16 && 0 == memcmp( ExplicitValueProvider::getUnoTunnelId().getConstArray(),
1383 aIdentifier.getConstArray(), 16 ) )
1385 ExplicitValueProvider* pProvider = this;
1386 return reinterpret_cast<sal_Int64>(pProvider);
1388 return 0;
1391 // lang::XServiceInfo
1393 OUString SAL_CALL ChartView::getImplementationName()
1394 throw( css::uno::RuntimeException, std::exception )
1396 return getImplementationName_Static();
1399 OUString ChartView::getImplementationName_Static()
1401 return OUString(CHART_VIEW_SERVICE_IMPLEMENTATION_NAME);
1404 sal_Bool SAL_CALL ChartView::supportsService( const OUString& rServiceName )
1405 throw( css::uno::RuntimeException, std::exception )
1407 return cppu::supportsService(this, rServiceName);
1410 css::uno::Sequence< OUString > SAL_CALL ChartView::getSupportedServiceNames()
1411 throw( css::uno::RuntimeException, std::exception )
1413 return getSupportedServiceNames_Static();
1416 uno::Sequence< OUString > ChartView::getSupportedServiceNames_Static()
1418 uno::Sequence< OUString > aSNS( 1 );
1419 aSNS.getArray()[ 0 ] = CHART_VIEW_SERVICE_NAME;
1420 return aSNS;
1423 ::basegfx::B3DHomMatrix createTransformationSceneToScreen(
1424 const ::basegfx::B2IRectangle& rDiagramRectangleWithoutAxes )
1426 ::basegfx::B3DHomMatrix aM;
1427 aM.scale(double(rDiagramRectangleWithoutAxes.getWidth())/FIXED_SIZE_FOR_3D_CHART_VOLUME
1428 , -double(rDiagramRectangleWithoutAxes.getHeight())/FIXED_SIZE_FOR_3D_CHART_VOLUME, 1.0 );
1429 aM.translate(double(rDiagramRectangleWithoutAxes.getMinX())
1430 , double(rDiagramRectangleWithoutAxes.getMinY()+rDiagramRectangleWithoutAxes.getHeight()-1), 0);
1431 return aM;
1434 namespace
1437 bool lcl_IsPieOrDonut( const uno::Reference< XDiagram >& xDiagram )
1439 //special treatment for pie charts
1440 //the size is checked after complete creation to get the datalabels into the given space
1442 //todo: this is just a workaround at the moment for pie and donut labels
1443 return DiagramHelper::isPieOrDonutChart( xDiagram );
1446 void lcl_setDefaultWritingMode( ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper, ChartModel& rModel)
1448 //get writing mode from parent document:
1449 if( SvtLanguageOptions().IsCTLFontEnabled() )
1453 sal_Int16 nWritingMode=-1;
1454 uno::Reference< beans::XPropertySet > xParentProps( rModel.getParent(), uno::UNO_QUERY );
1455 uno::Reference< style::XStyleFamiliesSupplier > xStyleFamiliesSupplier( xParentProps, uno::UNO_QUERY );
1456 if( xStyleFamiliesSupplier.is() )
1458 uno::Reference< container::XNameAccess > xStylesFamilies( xStyleFamiliesSupplier->getStyleFamilies() );
1459 if( xStylesFamilies.is() )
1461 if( !xStylesFamilies->hasByName( "PageStyles" ) )
1463 //draw/impress is parent document
1464 uno::Reference< lang::XMultiServiceFactory > xFatcory( xParentProps, uno::UNO_QUERY );
1465 if( xFatcory.is() )
1467 uno::Reference< beans::XPropertySet > xDrawDefaults( xFatcory->createInstance( "com.sun.star.drawing.Defaults" ), uno::UNO_QUERY );
1468 if( xDrawDefaults.is() )
1469 xDrawDefaults->getPropertyValue( "WritingMode" ) >>= nWritingMode;
1472 else
1474 uno::Reference< container::XNameAccess > xPageStyles( xStylesFamilies->getByName( "PageStyles" ), uno::UNO_QUERY );
1475 if( xPageStyles.is() )
1477 OUString aPageStyle;
1479 uno::Reference< text::XTextDocument > xTextDocument( xParentProps, uno::UNO_QUERY );
1480 if( xTextDocument.is() )
1482 //writer is parent document
1483 //retrieve the current page style from the text cursor property PageStyleName
1485 uno::Reference< text::XTextEmbeddedObjectsSupplier > xTextEmbeddedObjectsSupplier( xTextDocument, uno::UNO_QUERY );
1486 if( xTextEmbeddedObjectsSupplier.is() )
1488 uno::Reference< container::XNameAccess > xEmbeddedObjects( xTextEmbeddedObjectsSupplier->getEmbeddedObjects() );
1489 if( xEmbeddedObjects.is() )
1491 uno::Sequence< OUString > aNames( xEmbeddedObjects->getElementNames() );
1493 sal_Int32 nCount = aNames.getLength();
1494 for( sal_Int32 nN=0; nN<nCount; nN++ )
1496 uno::Reference< beans::XPropertySet > xEmbeddedProps( xEmbeddedObjects->getByName( aNames[nN] ), uno::UNO_QUERY );
1497 if( xEmbeddedProps.is() )
1499 static OUString aChartCLSID = OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName());
1500 OUString aCLSID;
1501 xEmbeddedProps->getPropertyValue( "CLSID" ) >>= aCLSID;
1502 if( aCLSID.equals(aChartCLSID) )
1504 uno::Reference< text::XTextContent > xEmbeddedObject( xEmbeddedProps, uno::UNO_QUERY );
1505 if( xEmbeddedObject.is() )
1507 uno::Reference< text::XTextRange > xAnchor( xEmbeddedObject->getAnchor() );
1508 if( xAnchor.is() )
1510 uno::Reference< beans::XPropertySet > xAnchorProps( xAnchor, uno::UNO_QUERY );
1511 if( xAnchorProps.is() )
1513 xAnchorProps->getPropertyValue( "WritingMode" ) >>= nWritingMode;
1515 uno::Reference< text::XText > xText( xAnchor->getText() );
1516 if( xText.is() )
1518 uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
1519 if( xTextCursorProps.is() )
1520 xTextCursorProps->getPropertyValue( "PageStyleName" ) >>= aPageStyle;
1524 break;
1530 if( aPageStyle.isEmpty() )
1532 uno::Reference< text::XText > xText( xTextDocument->getText() );
1533 if( xText.is() )
1535 uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
1536 if( xTextCursorProps.is() )
1537 xTextCursorProps->getPropertyValue( "PageStyleName" ) >>= aPageStyle;
1541 else
1543 //Calc is parent document
1544 xParentProps->getPropertyValue( "PageStyle" ) >>= aPageStyle;
1545 if(aPageStyle.isEmpty())
1546 aPageStyle = "Default";
1548 if( nWritingMode == -1 || nWritingMode == text::WritingMode2::PAGE )
1550 uno::Reference< beans::XPropertySet > xPageStyle( xPageStyles->getByName( aPageStyle ), uno::UNO_QUERY );
1551 if( xPageStyle.is() )
1552 xPageStyle->getPropertyValue( "WritingMode" ) >>= nWritingMode;
1558 if( nWritingMode != -1 && nWritingMode != text::WritingMode2::PAGE )
1560 if( pDrawModelWrapper.get() )
1561 pDrawModelWrapper->GetItemPool().SetPoolDefaultItem(SvxFrameDirectionItem(static_cast<SvxFrameDirection>(nWritingMode), EE_PARA_WRITINGDIR) );
1564 catch( const uno::Exception& ex )
1566 ASSERT_EXCEPTION( ex );
1571 sal_Int16 lcl_getDefaultWritingModeFromPool( const boost::shared_ptr<DrawModelWrapper>& pDrawModelWrapper )
1573 sal_Int16 nWritingMode = text::WritingMode2::LR_TB;
1574 if(!pDrawModelWrapper)
1575 return nWritingMode;
1577 const SfxPoolItem* pItem = &(pDrawModelWrapper->GetItemPool().GetDefaultItem( EE_PARA_WRITINGDIR ));
1578 if( pItem )
1579 nWritingMode = static_cast< sal_Int16 >((static_cast< const SvxFrameDirectionItem * >( pItem ))->GetValue());
1580 return nWritingMode;
1583 } //end anonymous namespace
1585 awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D& rParam, const awt::Size& rPageSize )
1587 //return the used rectangle
1588 awt::Rectangle aUsedOuterRect(rParam.maRemainingSpace.X, rParam.maRemainingSpace.Y, 0, 0);
1590 uno::Reference< XDiagram > xDiagram( mrChartModel.getFirstDiagram() );
1591 if( !xDiagram.is())
1592 return aUsedOuterRect;
1594 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
1595 if(!nDimensionCount)
1597 //@todo handle mixed dimension
1598 nDimensionCount = 2;
1601 basegfx::B2IRectangle aAvailableOuterRect = BaseGFXHelper::makeRectangle(rParam.maRemainingSpace);
1603 const std::vector< VCoordinateSystem* >& rVCooSysList( rParam.mpSeriesPlotterContainer->getCooSysList() );
1604 SeriesPlottersType& rSeriesPlotterList = rParam.mpSeriesPlotterContainer->getSeriesPlotterList();
1606 //create VAxis, so they can give necessary information for automatic scaling
1607 uno::Reference<chart2::XChartDocument> const xChartDoc(&mrChartModel);
1608 uno::Reference<util::XNumberFormatsSupplier> const xNumberFormatsSupplier(
1609 mrChartModel.getNumberFormatsSupplier());
1610 size_t nC = 0;
1611 for( nC=0; nC < rVCooSysList.size(); nC++)
1613 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1614 if(3==nDimensionCount)
1616 uno::Reference<beans::XPropertySet> xSceneProperties( xDiagram, uno::UNO_QUERY );
1617 CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xSceneProperties ) );
1618 CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xSceneProperties ) );
1619 CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xSceneProperties ) );
1620 pVCooSys->set3DWallPositions( eLeftWallPos, eBackWallPos, eBottomPos );
1623 pVCooSys->createVAxisList(xChartDoc, rPageSize, rParam.maRemainingSpace);
1626 // - prepare list of all axis and how they are used
1627 Date aNullDate = NumberFormatterWrapper( xNumberFormatsSupplier ).getNullDate();
1628 rParam.mpSeriesPlotterContainer->initAxisUsageList(aNullDate);
1629 rParam.mpSeriesPlotterContainer->doAutoScaling( mrChartModel );
1630 rParam.mpSeriesPlotterContainer->setScalesFromCooSysToPlotter();
1631 rParam.mpSeriesPlotterContainer->setNumberFormatsFromAxes();
1633 //create shapes
1635 //aspect ratio
1636 drawing::Direction3D aPreferredAspectRatio =
1637 rParam.mpSeriesPlotterContainer->getPreferredAspectRatio();
1639 uno::Reference< drawing::XShapes > xSeriesTargetInFrontOfAxis(0);
1640 uno::Reference< drawing::XShapes > xSeriesTargetBehindAxis(0);
1641 VDiagram aVDiagram(xDiagram, aPreferredAspectRatio, nDimensionCount);
1642 bool bIsPieOrDonut = lcl_IsPieOrDonut(xDiagram);
1643 {//create diagram
1644 aVDiagram.init(rParam.mxDiagramWithAxesShapes, m_xShapeFactory);
1645 aVDiagram.createShapes(
1646 awt::Point(rParam.maRemainingSpace.X, rParam.maRemainingSpace.Y),
1647 awt::Size(rParam.maRemainingSpace.Width, rParam.maRemainingSpace.Height));
1649 xSeriesTargetInFrontOfAxis = aVDiagram.getCoordinateRegion();
1650 // It is preferrable to use full size than minimum for pie charts
1651 if (!bIsPieOrDonut && !rParam.mbUseFixedInnerSize)
1652 aVDiagram.reduceToMimimumSize();
1655 uno::Reference< drawing::XShapes > xTextTargetShapes =
1656 AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory)->createGroup2D(rParam.mxDiagramWithAxesShapes);
1658 // - create axis and grids for all coordinate systems
1660 //init all coordinate systems
1661 for( nC=0; nC < rVCooSysList.size(); nC++)
1663 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1664 pVCooSys->initPlottingTargets(xSeriesTargetInFrontOfAxis,xTextTargetShapes,m_xShapeFactory,xSeriesTargetBehindAxis);
1666 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1667 createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
1669 pVCooSys->initVAxisInList();
1672 //calculate resulting size respecting axis label layout and fontscaling
1674 uno::Reference< drawing::XShape > xBoundingShape(rParam.mxDiagramWithAxesShapes, uno::UNO_QUERY);
1675 ::basegfx::B2IRectangle aConsumedOuterRect;
1677 //use first coosys only so far; todo: calculate for more than one coosys if we have more in future
1678 //todo: this is just a workaround at the moment for pie and donut labels
1679 if( !bIsPieOrDonut && (!rVCooSysList.empty()) )
1681 VCoordinateSystem* pVCooSys = rVCooSysList[0];
1682 pVCooSys->createMaximumAxesLabels();
1684 aConsumedOuterRect = AbstractShapeFactory::getRectangleOfShape(xBoundingShape);
1685 ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() );
1686 if (!rParam.mbUseFixedInnerSize)
1687 aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect );
1689 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1690 createTransformationSceneToScreen( aNewInnerRect ) ));
1692 //redo autoscaling to get size and text dependent automatic main increment count
1693 rParam.mpSeriesPlotterContainer->doAutoScaling( mrChartModel );
1694 rParam.mpSeriesPlotterContainer->updateScalesAndIncrementsOnAxes();
1695 rParam.mpSeriesPlotterContainer->setScalesFromCooSysToPlotter();
1697 pVCooSys->createAxesLabels();
1699 bool bLessSpaceConsumedThanExpected = false;
1701 aConsumedOuterRect = AbstractShapeFactory::getRectangleOfShape(xBoundingShape);
1702 if( aConsumedOuterRect.getMinX() > aAvailableOuterRect.getMinX()
1703 || aConsumedOuterRect.getMaxX() < aAvailableOuterRect.getMaxX()
1704 || aConsumedOuterRect.getMinY() > aAvailableOuterRect.getMinY()
1705 || aConsumedOuterRect.getMinY() < aAvailableOuterRect.getMaxY() )
1706 bLessSpaceConsumedThanExpected = true;
1709 if (bLessSpaceConsumedThanExpected && !rParam.mbUseFixedInnerSize)
1711 aVDiagram.adjustInnerSize( aConsumedOuterRect );
1712 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1713 createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
1715 pVCooSys->updatePositions();//todo: logically this belongs to the condition above, but it seems also to be necessary to give the axes group shapes the right bounding rects for hit test - probably caused by bug i106183 -> check again if fixed
1718 //create axes and grids for the final size
1719 for( nC=0; nC < rVCooSysList.size(); nC++)
1721 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1723 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1724 createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
1726 pVCooSys->createAxesShapes();
1727 pVCooSys->createGridShapes();
1730 // - create data series for all charttypes
1731 m_bPointsWereSkipped = false;
1732 SeriesPlottersType::iterator aPlotterIter = rSeriesPlotterList.begin();
1733 const SeriesPlottersType::iterator aPlotterEnd = rSeriesPlotterList.end();
1734 for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter )
1736 VSeriesPlotter* pSeriesPlotter = &(*aPlotterIter);
1737 OUString aCID; //III
1738 uno::Reference< drawing::XShapes > xSeriesTarget(0);
1739 if( pSeriesPlotter->WantToPlotInFrontOfAxisLine() )
1740 xSeriesTarget = xSeriesTargetInFrontOfAxis;
1741 else
1743 xSeriesTarget = xSeriesTargetBehindAxis;
1744 OSL_ENSURE( !bIsPieOrDonut, "not implemented yet! - during a complete recreation this shape is destroyed so no series can be created anymore" );
1746 pSeriesPlotter->initPlotter( xSeriesTarget,xTextTargetShapes,m_xShapeFactory,aCID );
1747 pSeriesPlotter->setPageReferenceSize( rPageSize );
1748 VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
1749 if(2==nDimensionCount)
1750 pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
1751 //better performance for big data
1752 awt::Size aCoordinateRegionResolution(1000,1000);
1754 //calculate resolution for coordinate system
1755 Sequence<sal_Int32> aCoordinateSystemResolution = pVCooSys->getCoordinateSystemResolution( rPageSize, m_aPageResolution );
1756 pSeriesPlotter->setCoordinateSystemResolution( aCoordinateSystemResolution );
1759 pSeriesPlotter->createShapes();
1760 m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
1763 //recreate all with corrected sizes if requested
1764 if( bIsPieOrDonut )
1766 m_bPointsWereSkipped = false;
1768 aConsumedOuterRect = ::basegfx::B2IRectangle( AbstractShapeFactory::getRectangleOfShape(xBoundingShape) );
1769 ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() );
1770 if (!rParam.mbUseFixedInnerSize)
1771 aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect );
1773 for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter )
1775 VSeriesPlotter* pSeriesPlotter = &(*aPlotterIter);
1776 pSeriesPlotter->releaseShapes();
1779 //clear and recreate
1780 AbstractShapeFactory::removeSubShapes( xSeriesTargetInFrontOfAxis ); //xSeriesTargetBehindAxis is a sub shape of xSeriesTargetInFrontOfAxis and will be removed here
1781 xSeriesTargetBehindAxis.clear();
1782 AbstractShapeFactory::removeSubShapes( xTextTargetShapes );
1784 //set new transformation
1785 for( nC=0; nC < rVCooSysList.size(); nC++)
1787 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1788 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1789 createTransformationSceneToScreen( aNewInnerRect ) ));
1792 // - create data series for all charttypes
1793 for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter )
1795 VSeriesPlotter* pSeriesPlotter = &(*aPlotterIter);
1796 VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
1797 if(2==nDimensionCount)
1798 pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
1799 pSeriesPlotter->createShapes();
1800 m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
1803 for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter )
1804 aPlotterIter->rearrangeLabelToAvoidOverlapIfRequested(rPageSize);
1807 if (rParam.mbUseFixedInnerSize)
1809 aUsedOuterRect = awt::Rectangle( aConsumedOuterRect.getMinX(), aConsumedOuterRect.getMinY(), aConsumedOuterRect.getWidth(), aConsumedOuterRect.getHeight() );
1811 else
1812 aUsedOuterRect = rParam.maRemainingSpace;
1814 bool bSnapRectToUsedArea = false;
1815 for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter )
1817 bSnapRectToUsedArea = aPlotterIter->shouldSnapRectToUsedArea();
1818 if(bSnapRectToUsedArea)
1819 break;
1821 if(bSnapRectToUsedArea)
1823 if (rParam.mbUseFixedInnerSize)
1824 m_aResultingDiagramRectangleExcludingAxes = getRectangleOfObject( "PlotAreaExcludingAxes" );
1825 else
1827 ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle();
1828 m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() );
1831 else
1833 if (rParam.mbUseFixedInnerSize)
1834 m_aResultingDiagramRectangleExcludingAxes = rParam.maRemainingSpace;
1835 else
1837 ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle();
1838 m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() );
1842 if (rParam.mxMarkHandles.is())
1844 awt::Point aPos(rParam.maRemainingSpace.X, rParam.maRemainingSpace.Y);
1845 awt::Size aSize(rParam.maRemainingSpace.Width, rParam.maRemainingSpace.Height);
1847 bool bPosSizeExcludeAxesProperty = true;
1848 uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY_THROW );
1849 if( xDiaProps.is() )
1850 xDiaProps->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxesProperty;
1851 if (rParam.mbUseFixedInnerSize || bPosSizeExcludeAxesProperty)
1853 aPos = awt::Point( m_aResultingDiagramRectangleExcludingAxes.X, m_aResultingDiagramRectangleExcludingAxes.Y );
1854 aSize = awt::Size( m_aResultingDiagramRectangleExcludingAxes.Width, m_aResultingDiagramRectangleExcludingAxes.Height );
1856 rParam.mxMarkHandles->setPosition(aPos);
1857 rParam.mxMarkHandles->setSize(aSize);
1860 return aUsedOuterRect;
1863 bool ChartView::getExplicitValuesForAxis(
1864 uno::Reference< XAxis > xAxis
1865 , ExplicitScaleData& rExplicitScale
1866 , ExplicitIncrementData& rExplicitIncrement )
1868 impl_updateView();
1870 if(!xAxis.is())
1871 return false;
1873 uno::Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis, mrChartModel.getFirstDiagram() ) );
1874 const VCoordinateSystem* pVCooSys = findInCooSysList(m_aVCooSysList,xCooSys);
1875 if(!pVCooSys)
1876 return false;
1878 sal_Int32 nDimensionIndex=-1;
1879 sal_Int32 nAxisIndex=-1;
1880 if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
1882 rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex);
1883 rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex);
1884 if( rExplicitScale.ShiftedCategoryPosition )
1886 //remove 'one' from max
1887 if( rExplicitScale.AxisType == ::com::sun::star::chart2::AxisType::DATE )
1889 Date aMaxDate(rExplicitScale.NullDate); aMaxDate += static_cast<long>(::rtl::math::approxFloor(rExplicitScale.Maximum));
1890 //for explicit scales with shifted categories we need one interval more
1891 switch( rExplicitScale.TimeResolution )
1893 case ::com::sun::star::chart::TimeUnit::DAY:
1894 --aMaxDate;
1895 break;
1896 case ::com::sun::star::chart::TimeUnit::MONTH:
1897 aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,-1);
1898 break;
1899 case ::com::sun::star::chart::TimeUnit::YEAR:
1900 aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate,-1);
1901 break;
1903 rExplicitScale.Maximum = aMaxDate - rExplicitScale.NullDate;
1905 else if( rExplicitScale.AxisType == ::com::sun::star::chart2::AxisType::CATEGORY )
1906 rExplicitScale.Maximum -= 1.0;
1907 else if( rExplicitScale.AxisType == ::com::sun::star::chart2::AxisType::SERIES )
1908 rExplicitScale.Maximum -= 1.0;
1910 return true;
1912 return false;
1915 SdrPage* ChartView::getSdrPage()
1917 SdrPage* pPage=0;
1918 Reference< lang::XUnoTunnel> xUnoTunnel(m_xDrawPage,uno::UNO_QUERY);
1919 if(xUnoTunnel.is())
1921 SvxDrawPage* pSvxDrawPage = reinterpret_cast<SvxDrawPage*>(xUnoTunnel->getSomething(
1922 SvxDrawPage::getUnoTunnelId() ));
1923 if(pSvxDrawPage)
1925 pPage = pSvxDrawPage->GetSdrPage();
1928 return pPage;
1931 uno::Reference< drawing::XShape > ChartView::getShapeForCID( const OUString& rObjectCID )
1933 SolarMutexGuard aSolarGuard;
1934 SdrObject* pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, this->getSdrPage() );
1935 if( pObj )
1936 return uno::Reference< drawing::XShape >( pObj->getUnoShape(), uno::UNO_QUERY);
1937 return 0;
1940 awt::Rectangle ChartView::getDiagramRectangleExcludingAxes()
1942 impl_updateView();
1943 return m_aResultingDiagramRectangleExcludingAxes;
1946 awt::Rectangle ChartView::getRectangleOfObject( const OUString& rObjectCID, bool bSnapRect )
1948 impl_updateView();
1950 awt::Rectangle aRet;
1951 uno::Reference< drawing::XShape > xShape( getShapeForCID(rObjectCID) );
1952 if(xShape.is())
1954 //special handling for axis for old api:
1955 //same special handling for diagram
1956 ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) );
1957 if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_DIAGRAM )
1959 SolarMutexGuard aSolarGuard;
1960 SvxShape* pRoot = SvxShape::getImplementation( xShape );
1961 if( pRoot )
1963 SdrObject* pRootSdrObject = pRoot->GetSdrObject();
1964 if( pRootSdrObject )
1966 SdrObjList* pRootList = pRootSdrObject->GetSubList();
1967 if( pRootList )
1969 OUString aShapeName = "MarkHandles";
1970 if( eObjectType == OBJECTTYPE_DIAGRAM )
1971 aShapeName = "PlotAreaIncludingAxes";
1972 SdrObject* pShape = DrawModelWrapper::getNamedSdrObject( aShapeName, pRootList );
1973 if( pShape )
1974 xShape = uno::Reference< drawing::XShape >( pShape->getUnoShape(), uno::UNO_QUERY);
1980 awt::Size aSize( xShape->getSize() );
1981 awt::Point aPoint( xShape->getPosition() );
1982 aRet = awt::Rectangle( aPoint.X, aPoint.Y, aSize.Width, aSize.Height );
1983 if( bSnapRect )
1985 //for rotated objects the shape size and position differs from the visible rectangle
1986 SvxShape* pShape = SvxShape::getImplementation( xShape );
1987 if( pShape )
1989 SdrObject* pSdrObject = pShape->GetSdrObject();
1990 if( pSdrObject )
1992 Rectangle aSnapRect( pSdrObject->GetSnapRect() );
1993 aRet = awt::Rectangle(aSnapRect.Left(),aSnapRect.Top(),aSnapRect.GetWidth(),aSnapRect.GetHeight());
1998 return aRet;
2001 ::boost::shared_ptr< DrawModelWrapper > ChartView::getDrawModelWrapper()
2003 return m_pDrawModelWrapper;
2006 namespace
2008 inline sal_Int32 lcl_getDiagramTitleSpace()
2010 return 200; //=0,2 cm spacing
2012 bool lcl_getPropertySwapXAndYAxis( const uno::Reference< XDiagram >& xDiagram )
2014 bool bSwapXAndY = false;
2016 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
2017 if( xCooSysContainer.is() )
2019 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
2020 if( aCooSysList.getLength() )
2022 uno::Reference<beans::XPropertySet> xProp(aCooSysList[0], uno::UNO_QUERY );
2023 if( xProp.is()) try
2025 xProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY;
2027 catch( const uno::Exception& e )
2029 ASSERT_EXCEPTION( e );
2033 return bSwapXAndY;
2038 sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
2039 const Reference< chart2::XAxis >& xAxis
2040 , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
2041 , const Reference<chart2::XChartDocument>& xChartDoc)
2043 return AxisHelper::getExplicitNumberFormatKeyForAxis( xAxis, xCorrespondingCoordinateSystem, xChartDoc
2044 , true /*bSearchForParallelAxisIfNothingIsFound*/ );
2047 sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
2048 const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
2049 const uno::Reference< XDataSeries >& xSeries,
2050 sal_Int32 nPointIndex /*-1 for whole series*/,
2051 const uno::Reference< XDiagram >& xDiagram
2054 sal_Int32 nFormat=0;
2055 if( !xSeriesOrPointProp.is() )
2056 return nFormat;
2058 bool bLinkToSource = true;
2061 xSeriesOrPointProp->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource;
2063 catch ( const beans::UnknownPropertyException& ) {}
2065 xSeriesOrPointProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nFormat;
2066 sal_Int32 nOldFormat = nFormat;
2067 if (bLinkToSource)
2069 uno::Reference< chart2::XChartType > xChartType( DataSeriesHelper::getChartTypeOfSeries( xSeries, xDiagram ) );
2071 bool bFormatFound = false;
2072 if( ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( xChartType ) )
2074 uno::Reference< beans::XPropertySet > xAttachedAxisProps( DiagramHelper::getAttachedAxis( xSeries, xDiagram ), uno::UNO_QUERY );
2075 if (xAttachedAxisProps.is() && (xAttachedAxisProps->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nFormat))
2076 bFormatFound = true;
2078 if( !bFormatFound )
2080 Reference< chart2::data::XDataSource > xSeriesSource( xSeries, uno::UNO_QUERY );
2081 OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
2083 Reference< data::XLabeledDataSequence > xLabeledSequence(
2084 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, aRole, false ));
2085 if( xLabeledSequence.is() )
2087 Reference< data::XDataSequence > xValues( xLabeledSequence->getValues() );
2088 if( xValues.is() )
2089 nFormat = xValues->getNumberFormatKeyByIndex( nPointIndex );
2093 if (nFormat >= 0 && nOldFormat != nFormat)
2094 xSeriesOrPointProp->setPropertyValue(CHART_UNONAME_NUMFMT, uno::makeAny(nFormat));
2097 if(nFormat<0)
2098 nFormat=0;
2099 return nFormat;
2102 sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
2103 const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
2104 const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
2106 sal_Int32 nFormat=0;
2107 if( !xSeriesOrPointProp.is() )
2108 return nFormat;
2109 if( !(xSeriesOrPointProp->getPropertyValue("PercentageNumberFormat") >>= nFormat) )
2111 nFormat = DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier );
2113 if(nFormat<0)
2114 nFormat=0;
2115 return nFormat;
2118 awt::Rectangle ExplicitValueProvider::addAxisTitleSizes(
2119 ChartModel& rModel
2120 , const Reference< uno::XInterface >& xChartView
2121 , const awt::Rectangle& rExcludingPositionAndSize )
2123 awt::Rectangle aRet(rExcludingPositionAndSize);
2125 //add axis title sizes to the diagram size
2126 uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, rModel ) );
2127 uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, rModel ) );
2128 uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, rModel ) );
2129 uno::Reference< chart2::XTitle > xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, rModel ) );
2130 if( xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() || xSecondTitle_Width.is() )
2132 ExplicitValueProvider* pExplicitValueProvider = ExplicitValueProvider::getExplicitValueProvider(xChartView);
2133 if( pExplicitValueProvider )
2135 //detect whether x axis points into x direction or not
2136 if( lcl_getPropertySwapXAndYAxis( rModel.getFirstDiagram() ) )
2138 std::swap( xTitle_Height, xTitle_Width );
2139 std::swap( xSecondTitle_Height, xSecondTitle_Width );
2142 sal_Int32 nTitleSpaceWidth = 0;
2143 sal_Int32 nTitleSpaceHeight = 0;
2144 sal_Int32 nSecondTitleSpaceWidth = 0;
2145 sal_Int32 nSecondTitleSpaceHeight = 0;
2147 if( xTitle_Height.is() )
2149 OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, rModel ) );
2150 nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
2151 if( nTitleSpaceHeight )
2152 nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
2154 if( xTitle_Width.is() )
2156 OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, rModel ) );
2157 nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
2158 if(nTitleSpaceWidth)
2159 nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
2161 if( xSecondTitle_Height.is() )
2163 OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, rModel ) );
2164 nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
2165 if( nSecondTitleSpaceHeight )
2166 nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
2168 if( xSecondTitle_Width.is() )
2170 OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, rModel ) );
2171 nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
2172 if( nSecondTitleSpaceWidth )
2173 nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
2176 aRet.X -= nTitleSpaceWidth;
2177 aRet.Y -= nSecondTitleSpaceHeight;
2178 aRet.Width += nTitleSpaceWidth + nSecondTitleSpaceWidth;
2179 aRet.Height += nTitleSpaceHeight + nSecondTitleSpaceHeight;
2182 return aRet;
2185 awt::Rectangle ExplicitValueProvider::substractAxisTitleSizes(
2186 ChartModel& rModel
2187 , const Reference< uno::XInterface >& xChartView
2188 , const awt::Rectangle& rPositionAndSizeIncludingTitles )
2190 awt::Rectangle aRet(rPositionAndSizeIncludingTitles);
2192 //add axis title sizes to the diagram size
2193 uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, rModel ) );
2194 uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, rModel ) );
2195 uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, rModel ) );
2196 uno::Reference< chart2::XTitle > xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, rModel ) );
2197 if( xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() || xSecondTitle_Width.is() )
2199 ExplicitValueProvider* pExplicitValueProvider = ExplicitValueProvider::getExplicitValueProvider(xChartView);
2200 if( pExplicitValueProvider )
2202 //detect whether x axis points into x direction or not
2203 if( lcl_getPropertySwapXAndYAxis( rModel.getFirstDiagram() ) )
2205 std::swap( xTitle_Height, xTitle_Width );
2206 std::swap( xSecondTitle_Height, xSecondTitle_Width );
2209 sal_Int32 nTitleSpaceWidth = 0;
2210 sal_Int32 nTitleSpaceHeight = 0;
2211 sal_Int32 nSecondTitleSpaceWidth = 0;
2212 sal_Int32 nSecondTitleSpaceHeight = 0;
2214 if( xTitle_Height.is() )
2216 OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, rModel ) );
2217 nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
2218 if( nTitleSpaceHeight )
2219 nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
2221 if( xTitle_Width.is() )
2223 OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, rModel ) );
2224 nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
2225 if(nTitleSpaceWidth)
2226 nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
2228 if( xSecondTitle_Height.is() )
2230 OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, rModel ) );
2231 nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
2232 if( nSecondTitleSpaceHeight )
2233 nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
2235 if( xSecondTitle_Width.is() )
2237 OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, rModel ) );
2238 nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
2239 if( nSecondTitleSpaceWidth )
2240 nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
2243 aRet.X += nTitleSpaceWidth;
2244 aRet.Y += nSecondTitleSpaceHeight;
2245 aRet.Width -= (nTitleSpaceWidth + nSecondTitleSpaceWidth);
2246 aRet.Height -= (nTitleSpaceHeight + nSecondTitleSpaceHeight);
2249 return aRet;
2252 namespace {
2254 inline double lcl_getPageLayoutDistancePercentage()
2256 return 0.02;
2259 bool getAvailablePosAndSizeForDiagram(
2260 CreateShapeParam2D& rParam, const awt::Size & rPageSize, const uno::Reference<XDiagram>& xDiagram )
2262 rParam.mbUseFixedInnerSize = false;
2264 //@todo: we need a size dependent on the axis labels
2265 sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
2266 sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
2267 rParam.maRemainingSpace.X += nXDistance;
2268 rParam.maRemainingSpace.Width -= 2*nXDistance;
2269 rParam.maRemainingSpace.Y += nYDistance;
2270 rParam.maRemainingSpace.Height -= 2*nYDistance;
2272 if (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)
2273 return false;
2275 uno::Reference< beans::XPropertySet > xProp(xDiagram, uno::UNO_QUERY);
2277 bool bPosSizeExcludeAxes = false;
2278 if( xProp.is() )
2279 xProp->getPropertyValue( "PosSizeExcludeAxes" ) >>= bPosSizeExcludeAxes;
2281 //size:
2282 ::com::sun::star::chart2::RelativeSize aRelativeSize;
2283 if( xProp.is() && (xProp->getPropertyValue( "RelativeSize" )>>=aRelativeSize) )
2285 rParam.maRemainingSpace.Height = static_cast<sal_Int32>(aRelativeSize.Secondary*rPageSize.Height);
2286 rParam.maRemainingSpace.Width = static_cast<sal_Int32>(aRelativeSize.Primary*rPageSize.Width);
2287 rParam.mbUseFixedInnerSize = bPosSizeExcludeAxes;
2290 //position:
2291 chart2::RelativePosition aRelativePosition;
2292 if( xProp.is() && (xProp->getPropertyValue( "RelativePosition" )>>=aRelativePosition) )
2294 //@todo decide whether x is primary or secondary
2296 //the coordinates re relative to the page
2297 double fX = aRelativePosition.Primary*rPageSize.Width;
2298 double fY = aRelativePosition.Secondary*rPageSize.Height;
2300 awt::Point aPos = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
2301 awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY)),
2302 awt::Size(rParam.maRemainingSpace.Width, rParam.maRemainingSpace.Height),
2303 aRelativePosition.Anchor);
2305 rParam.maRemainingSpace.X = aPos.X;
2306 rParam.maRemainingSpace.Y = aPos.Y;
2308 rParam.mbUseFixedInnerSize = bPosSizeExcludeAxes;
2311 //ensure that the diagram does not lap out right side or out of bottom
2312 if (rParam.maRemainingSpace.Y + rParam.maRemainingSpace.Height > rPageSize.Height)
2313 rParam.maRemainingSpace.Height = rPageSize.Height - rParam.maRemainingSpace.Y;
2315 if (rParam.maRemainingSpace.X + rParam.maRemainingSpace.Width > rPageSize.Width)
2316 rParam.maRemainingSpace.Width = rPageSize.Width - rParam.maRemainingSpace.X;
2318 return true;
2321 enum TitleAlignment { ALIGN_LEFT, ALIGN_TOP, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_Z };
2323 void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment
2324 , awt::Rectangle& rDiagramPlusAxesRect, const awt::Size & rPageSize )
2326 if(!pVTitle)
2327 return;
2329 awt::Point aNewPosition(0,0);
2330 awt::Size aTitleSize = pVTitle->getFinalSize();
2331 sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
2332 sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
2333 switch( eAlignment )
2335 case ALIGN_TOP:
2336 aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
2337 , rDiagramPlusAxesRect.Y - aTitleSize.Height/2 - nYDistance );
2338 break;
2339 case ALIGN_BOTTOM:
2340 aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
2341 , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height + aTitleSize.Height/2 + nYDistance );
2342 break;
2343 case ALIGN_LEFT:
2344 aNewPosition = awt::Point( rDiagramPlusAxesRect.X - aTitleSize.Width/2 - nXDistance
2345 , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
2346 break;
2347 case ALIGN_RIGHT:
2348 aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
2349 , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
2350 break;
2351 case ALIGN_Z:
2352 aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
2353 , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height - aTitleSize.Height/2 );
2354 break;
2355 default:
2356 break;
2359 sal_Int32 nMaxY = rPageSize.Height - aTitleSize.Height/2;
2360 sal_Int32 nMaxX = rPageSize.Width - aTitleSize.Width/2;
2361 sal_Int32 nMinX = aTitleSize.Width/2;
2362 sal_Int32 nMinY = aTitleSize.Height/2;
2363 if( aNewPosition.Y > nMaxY )
2364 aNewPosition.Y = nMaxY;
2365 if( aNewPosition.X > nMaxX )
2366 aNewPosition.X = nMaxX;
2367 if( aNewPosition.Y < nMinY )
2368 aNewPosition.Y = nMinY;
2369 if( aNewPosition.X < nMinX )
2370 aNewPosition.X = nMinX;
2372 pVTitle->changePosition( aNewPosition );
2375 boost::shared_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType
2376 , const uno::Reference< drawing::XShapes>& xPageShapes
2377 , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
2378 , ChartModel& rModel
2379 , awt::Rectangle& rRemainingSpace
2380 , const awt::Size & rPageSize
2381 , TitleAlignment eAlignment
2382 , bool& rbAutoPosition )
2384 boost::shared_ptr<VTitle> apVTitle;
2386 // #i109336# Improve auto positioning in chart
2387 double fPercentage = lcl_getPageLayoutDistancePercentage();
2388 sal_Int32 nXDistance = static_cast< sal_Int32 >( rPageSize.Width * fPercentage );
2389 sal_Int32 nYDistance = static_cast< sal_Int32 >( rPageSize.Height * fPercentage );
2390 if ( eType == TitleHelper::MAIN_TITLE )
2392 sal_Int32 nYOffset = 135; // 1/100 mm
2393 nYDistance += nYOffset;
2395 else if ( eType == TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION )
2397 sal_Int32 nYOffset = 420; // 1/100 mm
2398 nYDistance = nYOffset;
2400 else if ( eType == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION )
2402 sal_Int32 nXOffset = 450; // 1/100 mm
2403 nXDistance = nXOffset;
2406 uno::Reference< XTitle > xTitle( TitleHelper::getTitle( eType, rModel ) );
2407 OUString aCompleteString = TitleHelper::getCompleteString(xTitle);
2408 if (aCompleteString.isEmpty())
2409 return apVTitle;
2411 //create title
2412 apVTitle.reset(new VTitle(xTitle));
2413 OUString aCID = ObjectIdentifier::createClassifiedIdentifierForObject(xTitle, rModel);
2414 apVTitle->init(xPageShapes, xShapeFactory, aCID);
2415 apVTitle->createShapes(awt::Point(0,0), rPageSize);
2416 awt::Size aTitleUnrotatedSize = apVTitle->getUnrotatedSize();
2417 awt::Size aTitleSize = apVTitle->getFinalSize();
2419 //position
2420 rbAutoPosition = true;
2421 awt::Point aNewPosition(0,0);
2422 chart2::RelativePosition aRelativePosition;
2423 uno::Reference<beans::XPropertySet> xProp(xTitle, uno::UNO_QUERY);
2424 if (xProp.is() && (xProp->getPropertyValue("RelativePosition") >>= aRelativePosition))
2426 rbAutoPosition = false;
2428 //@todo decide whether x is primary or secondary
2429 double fX = aRelativePosition.Primary*rPageSize.Width;
2430 double fY = aRelativePosition.Secondary*rPageSize.Height;
2432 double fAnglePi = apVTitle->getRotationAnglePi();
2433 aNewPosition = RelativePositionHelper::getCenterOfAnchoredObject(
2434 awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
2435 , aTitleUnrotatedSize, aRelativePosition.Anchor, fAnglePi );
2437 else //auto position
2439 switch( eAlignment )
2441 case ALIGN_TOP:
2442 aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
2443 , rRemainingSpace.Y + aTitleSize.Height/2 + nYDistance );
2444 break;
2445 case ALIGN_BOTTOM:
2446 aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
2447 , rRemainingSpace.Y + rRemainingSpace.Height - aTitleSize.Height/2 - nYDistance );
2448 break;
2449 case ALIGN_LEFT:
2450 aNewPosition = awt::Point( rRemainingSpace.X + aTitleSize.Width/2 + nXDistance
2451 , rRemainingSpace.Y + rRemainingSpace.Height/2 );
2452 break;
2453 case ALIGN_RIGHT:
2454 aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width - aTitleSize.Width/2 - nXDistance
2455 , rRemainingSpace.Y + rRemainingSpace.Height/2 );
2456 break;
2457 default:
2458 break;
2462 apVTitle->changePosition( aNewPosition );
2464 //remaining space
2465 switch( eAlignment )
2467 case ALIGN_TOP:
2468 // Push the remaining space down from top.
2469 rRemainingSpace.Y += ( aTitleSize.Height + nYDistance );
2470 rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
2471 break;
2472 case ALIGN_BOTTOM:
2473 // Push the remaining space up from bottom.
2474 rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
2475 break;
2476 case ALIGN_LEFT:
2477 // Push the remaining space to the right from left edge.
2478 rRemainingSpace.X += ( aTitleSize.Width + nXDistance );
2479 rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
2480 break;
2481 case ALIGN_RIGHT:
2482 // Push the remaining space to the left from right edge.
2483 rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
2484 break;
2485 default:
2486 break;
2489 return apVTitle;
2492 bool lcl_createLegend( const uno::Reference< XLegend > & xLegend
2493 , const uno::Reference< drawing::XShapes>& xPageShapes
2494 , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
2495 , const uno::Reference< uno::XComponentContext > & xContext
2496 , awt::Rectangle & rRemainingSpace
2497 , const awt::Size & rPageSize
2498 , ChartModel& rModel
2499 , const std::vector< LegendEntryProvider* >& rLegendEntryProviderList
2500 , sal_Int16 nDefaultWritingMode )
2502 if (!VLegend::isVisible(xLegend))
2503 return false;
2505 VLegend aVLegend( xLegend, xContext, rLegendEntryProviderList,
2506 xPageShapes, xShapeFactory, rModel);
2507 aVLegend.setDefaultWritingMode( nDefaultWritingMode );
2508 aVLegend.createShapes( awt::Size( rRemainingSpace.Width, rRemainingSpace.Height ),
2509 rPageSize );
2510 aVLegend.changePosition( rRemainingSpace, rPageSize );
2511 return true;
2514 void formatPage(
2515 ChartModel& rChartModel
2516 , const awt::Size& rPageSize
2517 , const uno::Reference< drawing::XShapes >& xTarget
2518 , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
2523 uno::Reference< beans::XPropertySet > xModelPage( rChartModel.getPageBackground());
2524 if( ! xModelPage.is())
2525 return;
2527 if( !xShapeFactory.is() )
2528 return;
2530 //format page
2531 tPropertyNameValueMap aNameValueMap;
2532 PropertyMapper::getValueMap( aNameValueMap, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage );
2534 OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) );
2535 aNameValueMap.insert( tPropertyNameValueMap::value_type( "Name", uno::makeAny( aCID ) ) ); //CID OUString
2537 tNameSequence aNames;
2538 tAnySequence aValues;
2539 PropertyMapper::getMultiPropertyListsFromValueMap( aNames, aValues, aNameValueMap );
2541 AbstractShapeFactory* pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(xShapeFactory);
2542 pShapeFactory->createRectangle(
2543 xTarget, rPageSize, awt::Point(0, 0), aNames, aValues);
2545 catch( const uno::Exception & ex )
2547 ASSERT_EXCEPTION( ex );
2551 void lcl_removeEmptyGroupShapes( const Reference< drawing::XShapes>& xParent )
2553 if(!xParent.is())
2554 return;
2555 Reference< drawing::XShapeGroup > xParentGroup( xParent, uno::UNO_QUERY );
2556 if( !xParentGroup.is() )
2558 Reference< drawing::XDrawPage > xPage( xParent, uno::UNO_QUERY );
2559 if( !xPage.is() )
2560 return;
2563 //iterate from back!
2564 for( sal_Int32 nN = xParent->getCount(); nN--; )
2566 uno::Any aAny = xParent->getByIndex( nN );
2567 Reference< drawing::XShapes> xShapes(0);
2568 if( aAny >>= xShapes )
2569 lcl_removeEmptyGroupShapes( xShapes );
2570 if( xShapes.is() && xShapes->getCount()==0 )
2572 //remove empty group shape
2573 Reference< drawing::XShapeGroup > xGroup( xShapes, uno::UNO_QUERY );
2574 Reference< drawing::XShape > xShape( xShapes, uno::UNO_QUERY );
2575 if( xGroup.is() )
2576 xParent->remove( xShape );
2583 void ChartView::impl_refreshAddIn()
2585 if( !m_bRefreshAddIn )
2586 return;
2588 uno::Reference< beans::XPropertySet > xProp( static_cast< ::cppu::OWeakObject* >( &mrChartModel ), uno::UNO_QUERY );
2589 if( xProp.is()) try
2591 uno::Reference< util::XRefreshable > xAddIn;
2592 xProp->getPropertyValue( "AddIn" ) >>= xAddIn;
2593 if( xAddIn.is() )
2595 bool bRefreshAddInAllowed = true;
2596 xProp->getPropertyValue( "RefreshAddInAllowed" ) >>= bRefreshAddInAllowed;
2597 if( bRefreshAddInAllowed )
2598 xAddIn->refresh();
2601 catch( const uno::Exception& e )
2603 ASSERT_EXCEPTION( e );
2608 * Is it a real 3D chart with a true 3D scene or a 3D chart in a 2D scene.
2610 bool ChartView::isReal3DChart()
2612 uno::Reference< XDiagram > xDiagram( mrChartModel.getFirstDiagram() );
2614 return ChartHelper::isGL3DDiagram(xDiagram);
2617 static const char* envChartDummyFactory = getenv("CHART_DUMMY_FACTORY");
2619 void ChartView::createShapes()
2621 osl::ResettableMutexGuard aTimedGuard(maTimeMutex);
2622 if(mrChartModel.isTimeBased())
2624 maTimeBased.bTimeBased = true;
2627 //make sure add-in is refreshed after creating the shapes
2628 const ::comphelper::ScopeGuard aGuard( boost::bind( &ChartView::impl_refreshAddIn, this ) );
2630 m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle(0,0,0,0);
2631 impl_deleteCoordinateSystems();
2632 if( m_pDrawModelWrapper )
2634 SolarMutexGuard aSolarGuard;
2635 // #i12587# support for shapes in chart
2636 m_pDrawModelWrapper->getSdrModel().EnableUndo( false );
2637 m_pDrawModelWrapper->clearMainDrawPage();
2640 lcl_setDefaultWritingMode( m_pDrawModelWrapper, mrChartModel );
2642 awt::Size aPageSize = mrChartModel.getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
2644 AbstractShapeFactory* pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory);
2645 if(!mxRootShape.is())
2646 mxRootShape = pShapeFactory->getOrCreateChartRootShape( m_xDrawPage );
2648 SdrPage* pPage = ChartView::getSdrPage();
2649 if(pPage) //it is necessary to use the implementation here as the uno page does not provide a propertyset
2650 pPage->SetSize(Size(aPageSize.Width,aPageSize.Height));
2651 else
2653 OSL_FAIL("could not set page size correctly");
2655 pShapeFactory->setPageSize(mxRootShape, aPageSize);
2656 pShapeFactory->clearPage(mxRootShape);
2658 #if HAVE_FEATURE_DESKTOP
2659 if(isReal3DChart())
2661 createShapes3D();
2662 return;
2664 else
2666 m_pGL3DPlotter.reset();
2668 // hide OpenGL window for now in normal charts
2669 OpenGLWindow* pWindow = mrChartModel.getOpenGLWindow();
2670 if(pWindow && !envChartDummyFactory)
2671 pWindow->Show(false);
2673 #endif
2675 createShapes2D(aPageSize);
2677 // #i12587# support for shapes in chart
2678 if ( m_pDrawModelWrapper )
2680 SolarMutexGuard aSolarGuard;
2681 m_pDrawModelWrapper->getSdrModel().EnableUndo( true );
2684 if(maTimeBased.bTimeBased)
2686 maTimeBased.nFrame++;
2690 void ChartView::render()
2692 if(!isReal3DChart())
2694 AbstractShapeFactory* pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory);
2695 OpenGLWindow* pWindow = mrChartModel.getOpenGLWindow();
2696 if(pWindow)
2697 pWindow->setRenderer(mp2DRenderer.get());
2698 bool bRender = pShapeFactory->preRender(mxRootShape, pWindow);
2699 if(bRender)
2701 pShapeFactory->render(mxRootShape, pWindow != mp2DRenderer->getOpenGLWindow());
2702 pShapeFactory->postRender(pWindow);
2707 // util::XEventListener (base of XCloseListener)
2708 void SAL_CALL ChartView::disposing( const lang::EventObject& /* rSource */ )
2709 throw(uno::RuntimeException, std::exception)
2713 void ChartView::impl_updateView( bool bCheckLockedCtrler )
2715 if( !m_pDrawModelWrapper )
2716 return;
2718 // #i12587# support for shapes in chart
2719 if ( m_bSdrViewIsInEditMode )
2721 return;
2724 if (bCheckLockedCtrler && mrChartModel.hasControllersLocked())
2725 return;
2727 if( m_bViewDirty && !m_bInViewUpdate )
2729 m_bInViewUpdate = true;
2730 //bool bOldRefreshAddIn = m_bRefreshAddIn;
2731 //m_bRefreshAddIn = false;
2734 impl_notifyModeChangeListener("invalid");
2736 //prepare draw model
2738 SolarMutexGuard aSolarGuard;
2739 m_pDrawModelWrapper->lockControllers();
2742 //create chart view
2744 m_bViewDirty = false;
2745 m_bViewUpdatePending = false;
2746 createShapes();
2748 if( m_bViewDirty )
2750 //avoid recursions due to add-in
2751 m_bRefreshAddIn = false;
2752 m_bViewDirty = false;
2753 m_bViewUpdatePending = false;
2754 //delete old chart view
2755 createShapes();
2756 m_bRefreshAddIn = true;
2760 m_bViewDirty = m_bViewUpdatePending;
2761 m_bViewUpdatePending = false;
2762 m_bInViewUpdate = false;
2764 catch( const uno::Exception& ex)
2766 m_bViewDirty = m_bViewUpdatePending;
2767 m_bViewUpdatePending = false;
2768 m_bInViewUpdate = false;
2769 ASSERT_EXCEPTION( ex );
2773 SolarMutexGuard aSolarGuard;
2774 m_pDrawModelWrapper->unlockControllers();
2777 impl_notifyModeChangeListener("valid");
2779 //m_bRefreshAddIn = bOldRefreshAddIn;
2783 // ____ XModifyListener ____
2784 void SAL_CALL ChartView::modified( const lang::EventObject& /* aEvent */ )
2785 throw (uno::RuntimeException, std::exception)
2787 m_bViewDirty = true;
2788 if( m_bInViewUpdate )
2789 m_bViewUpdatePending = true;
2791 impl_notifyModeChangeListener("dirty");
2794 //SfxListener
2795 void ChartView::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
2797 //#i77362 change notification for changes on additional shapes are missing
2798 if( m_bInViewUpdate )
2799 return;
2801 // #i12587# support for shapes in chart
2802 if ( m_bSdrViewIsInEditMode )
2804 uno::Reference< view::XSelectionSupplier > xSelectionSupplier( mrChartModel.getCurrentController(), uno::UNO_QUERY );
2805 if ( xSelectionSupplier.is() )
2807 OUString aSelObjCID;
2808 uno::Any aSelObj( xSelectionSupplier->getSelection() );
2809 aSelObj >>= aSelObjCID;
2810 if ( !aSelObjCID.isEmpty() )
2812 return;
2817 const SdrHint* pSdrHint = dynamic_cast< const SdrHint* >(&rHint);
2818 if( !pSdrHint )
2819 return;
2821 bool bShapeChanged = false;
2822 switch( pSdrHint->GetKind() )
2824 case HINT_OBJCHG:
2825 bShapeChanged = true;
2826 break;
2827 case HINT_OBJINSERTED:
2828 bShapeChanged = true;
2829 break;
2830 case HINT_OBJREMOVED:
2831 bShapeChanged = true;
2832 break;
2833 case HINT_MODELCLEARED:
2834 bShapeChanged = true;
2835 break;
2836 case HINT_ENDEDIT:
2837 bShapeChanged = true;
2838 break;
2839 default:
2840 break;
2843 if(bShapeChanged)
2845 //#i76053# do not send view modified notifications for changes on the hidden page which contains e.g. the symbols for the dialogs
2846 if( ChartView::getSdrPage() != pSdrHint->GetPage() )
2847 bShapeChanged=false;
2850 if(!bShapeChanged)
2851 return;
2853 mrChartModel.setModified(sal_True);
2856 void ChartView::impl_notifyModeChangeListener( const OUString& rNewMode )
2860 ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer
2861 .getContainer( cppu::UnoType<util::XModeChangeListener>::get());
2862 if( pIC )
2864 util::ModeChangeEvent aEvent( static_cast< uno::XWeak* >( this ), rNewMode );
2865 ::cppu::OInterfaceIteratorHelper aIt( *pIC );
2866 while( aIt.hasMoreElements() )
2868 uno::Reference< util::XModeChangeListener > xListener( aIt.next(), uno::UNO_QUERY );
2869 if( xListener.is() )
2870 xListener->modeChanged( aEvent );
2874 catch( const uno::Exception& ex)
2876 ASSERT_EXCEPTION( ex );
2880 // ____ XModeChangeBroadcaster ____
2882 void SAL_CALL ChartView::addModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
2883 throw (uno::RuntimeException, std::exception)
2885 m_aListenerContainer.addInterface(
2886 cppu::UnoType<util::XModeChangeListener>::get(), xListener );
2888 void SAL_CALL ChartView::removeModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
2889 throw (uno::RuntimeException, std::exception)
2891 m_aListenerContainer.removeInterface(
2892 cppu::UnoType<util::XModeChangeListener>::get(), xListener );
2894 void SAL_CALL ChartView::addModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
2895 throw (lang::NoSupportException, uno::RuntimeException, std::exception)
2899 void SAL_CALL ChartView::removeModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
2900 throw (lang::NoSupportException, uno::RuntimeException, std::exception)
2905 // ____ XUpdatable ____
2906 void SAL_CALL ChartView::update() throw (uno::RuntimeException, std::exception)
2908 impl_updateView(true);
2910 //#i100778# migrate all imported or old documents to a plot area sizing exclusive axes (in case the save settings allow for this):
2911 //Although in general it is a bad idea to change the model from within the view this is exceptionally the best place to do this special conversion.
2912 //When a view update is requested (what happens for creating the metafile or displaying
2913 //the chart in edit mode or printing) it is most likely that all necessary information are available - like the underlying spreadsheet data for example.
2914 //Those data are important for the correct axis label sizes which are needed during conversion.
2915 if( DiagramHelper::switchDiagramPositioningToExcludingPositioning( mrChartModel, true, false ) )
2916 impl_updateView();
2919 void SAL_CALL ChartView::updateSoft() throw (uno::RuntimeException, std::exception)
2921 update();
2924 void SAL_CALL ChartView::updateHard() throw (uno::RuntimeException, std::exception)
2926 impl_updateView(false);
2929 // ____ XPropertySet ____
2930 Reference< beans::XPropertySetInfo > SAL_CALL ChartView::getPropertySetInfo()
2931 throw (uno::RuntimeException, std::exception)
2933 OSL_FAIL("not implemented");
2934 return 0;
2937 void SAL_CALL ChartView::setPropertyValue( const OUString& rPropertyName
2938 , const Any& rValue )
2939 throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException
2940 , lang::WrappedTargetException, uno::RuntimeException, std::exception)
2942 if( rPropertyName == "Resolution" )
2944 awt::Size aNewResolution;
2945 if( ! (rValue >>= aNewResolution) )
2946 throw lang::IllegalArgumentException( "Property 'Resolution' requires value of type awt::Size", 0, 0 );
2948 if( m_aPageResolution.Width!=aNewResolution.Width || m_aPageResolution.Height!=aNewResolution.Height )
2950 //set modified only when the new resolution is higher and points were skipped before
2951 bool bSetModified = m_bPointsWereSkipped && (m_aPageResolution.Width<aNewResolution.Width || m_aPageResolution.Height<aNewResolution.Height);
2953 m_aPageResolution = aNewResolution;
2955 if( bSetModified )
2956 this->modified( lang::EventObject( static_cast< uno::XWeak* >( this ) ) );
2959 else if( rPropertyName == "ZoomFactors" )
2961 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
2962 uno::Sequence< beans::PropertyValue > aZoomFactors;
2963 if( ! (rValue >>= aZoomFactors) )
2964 throw lang::IllegalArgumentException( "Property 'ZoomFactors' requires value of type Sequence< PropertyValue >", 0, 0 );
2966 sal_Int32 nFilterArgs = aZoomFactors.getLength();
2967 beans::PropertyValue* pDataValues = aZoomFactors.getArray();
2968 while( nFilterArgs-- )
2970 if ( pDataValues->Name == "ScaleXNumerator" )
2971 pDataValues->Value >>= m_nScaleXNumerator;
2972 else if ( pDataValues->Name == "ScaleXDenominator" )
2973 pDataValues->Value >>= m_nScaleXDenominator;
2974 else if ( pDataValues->Name == "ScaleYNumerator" )
2975 pDataValues->Value >>= m_nScaleYNumerator;
2976 else if ( pDataValues->Name == "ScaleYDenominator" )
2977 pDataValues->Value >>= m_nScaleYDenominator;
2979 pDataValues++;
2982 else if( rPropertyName == "SdrViewIsInEditMode" )
2984 //#i77362 change notification for changes on additional shapes are missing
2985 if( ! (rValue >>= m_bSdrViewIsInEditMode) )
2986 throw lang::IllegalArgumentException( "Property 'SdrViewIsInEditMode' requires value of type sal_Bool", 0, 0 );
2988 else
2989 throw beans::UnknownPropertyException( "unknown property was tried to set to chart wizard", 0 );
2992 Any SAL_CALL ChartView::getPropertyValue( const OUString& rPropertyName )
2993 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
2995 Any aRet;
2996 if( rPropertyName == "Resolution" )
2998 aRet = uno::makeAny( m_aPageResolution );
3000 else
3001 throw beans::UnknownPropertyException( "unknown property was tried to get from chart wizard", 0 );
3002 return aRet;
3005 void SAL_CALL ChartView::addPropertyChangeListener(
3006 const OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* xListener */ )
3007 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
3009 OSL_FAIL("not implemented");
3011 void SAL_CALL ChartView::removePropertyChangeListener(
3012 const OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* aListener */ )
3013 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
3015 OSL_FAIL("not implemented");
3018 void SAL_CALL ChartView::addVetoableChangeListener( const OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
3019 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
3021 OSL_FAIL("not implemented");
3024 void SAL_CALL ChartView::removeVetoableChangeListener( const OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
3025 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
3027 OSL_FAIL("not implemented");
3030 // ____ XMultiServiceFactory ____
3032 Reference< uno::XInterface > ChartView::createInstance( const OUString& aServiceSpecifier )
3033 throw (uno::Exception, uno::RuntimeException, std::exception)
3035 SolarMutexGuard aSolarGuard;
3037 SdrModel* pModel = ( m_pDrawModelWrapper ? &m_pDrawModelWrapper->getSdrModel() : NULL );
3038 if ( pModel )
3040 if ( aServiceSpecifier == "com.sun.star.drawing.DashTable" )
3042 if ( !m_xDashTable.is() )
3044 m_xDashTable = SvxUnoDashTable_createInstance( pModel );
3046 return m_xDashTable;
3048 else if ( aServiceSpecifier == "com.sun.star.drawing.GradientTable" )
3050 if ( !m_xGradientTable.is() )
3052 m_xGradientTable = SvxUnoGradientTable_createInstance( pModel );
3054 return m_xGradientTable;
3056 else if ( aServiceSpecifier == "com.sun.star.drawing.HatchTable" )
3058 if ( !m_xHatchTable.is() )
3060 m_xHatchTable = SvxUnoHatchTable_createInstance( pModel );
3062 return m_xHatchTable;
3064 else if ( aServiceSpecifier == "com.sun.star.drawing.BitmapTable" )
3066 if ( !m_xBitmapTable.is() )
3068 m_xBitmapTable = SvxUnoBitmapTable_createInstance( pModel );
3070 return m_xBitmapTable;
3072 else if ( aServiceSpecifier == "com.sun.star.drawing.TransparencyGradientTable" )
3074 if ( !m_xTransGradientTable.is() )
3076 m_xTransGradientTable = SvxUnoTransGradientTable_createInstance( pModel );
3078 return m_xTransGradientTable;
3080 else if ( aServiceSpecifier == "com.sun.star.drawing.MarkerTable" )
3082 if ( !m_xMarkerTable.is() )
3084 m_xMarkerTable = SvxUnoMarkerTable_createInstance( pModel );
3086 return m_xMarkerTable;
3090 return 0;
3093 Reference< uno::XInterface > ChartView::createInstanceWithArguments( const OUString& ServiceSpecifier, const uno::Sequence< uno::Any >& Arguments )
3094 throw (uno::Exception, uno::RuntimeException, std::exception)
3096 OSL_ENSURE( Arguments.getLength(), "ChartView::createInstanceWithArguments: arguments are ignored" );
3097 (void) Arguments; // avoid warning
3098 return createInstance( ServiceSpecifier );
3101 uno::Sequence< OUString > ChartView::getAvailableServiceNames() throw (uno::RuntimeException, std::exception)
3103 uno::Sequence< OUString > aServiceNames( 6 );
3105 aServiceNames[0] = "com.sun.star.drawing.DashTable";
3106 aServiceNames[1] = "com.sun.star.drawing.GradientTable";
3107 aServiceNames[2] = "com.sun.star.drawing.HatchTable";
3108 aServiceNames[3] = "com.sun.star.drawing.BitmapTable";
3109 aServiceNames[4] = "com.sun.star.drawing.TransparencyGradientTable";
3110 aServiceNames[5] = "com.sun.star.drawing.MarkerTable";
3112 return aServiceNames;
3115 OUString ChartView::dump() throw (uno::RuntimeException, std::exception)
3117 #if HAVE_FEATURE_DESKTOP
3118 // Used for unit tests and in chartcontroller only, no need to drag in this when cross-compiling
3119 // for non-desktop
3120 impl_updateView();
3121 uno::Reference< drawing::XShapes > xShapes( m_xDrawPage, uno::UNO_QUERY_THROW );
3122 sal_Int32 n = xShapes->getCount();
3123 OUStringBuffer aBuffer;
3124 for(sal_Int32 i = 0; i < n; ++i)
3126 uno::Reference< drawing::XShapes > xShape(xShapes->getByIndex(i), uno::UNO_QUERY);
3127 if(xShape.is())
3129 XShapeDumper dumper;
3130 OUString aString = XShapeDumper::dump(mxRootShape);
3131 aBuffer.append(aString);
3133 else
3135 uno::Reference< drawing::XShape > xSingleShape(xShapes->getByIndex(i), uno::UNO_QUERY);
3136 if(!xSingleShape.is())
3137 continue;
3138 XShapeDumper dumper;
3139 OUString aString = XShapeDumper::dump(xSingleShape);
3140 aBuffer.append(aString);
3142 aBuffer.append("\n\n");
3145 return aBuffer.makeStringAndClear();
3146 #else
3147 return OUString();
3148 #endif
3151 void ChartView::setViewDirty()
3153 osl::ResettableMutexGuard aGuard(maTimeMutex);
3154 m_bViewDirty = true;
3157 IMPL_LINK_NOARG_TYPED(ChartView, UpdateTimeBased, Timer *, void)
3159 setViewDirty();
3160 update();
3163 void ChartView::createShapes2D( const awt::Size& rPageSize )
3165 AbstractShapeFactory* pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory);
3167 SolarMutexGuard aSolarGuard;
3169 // todo: it would be nicer to just pass the page m_xDrawPage and format it,
3170 // but the draw page does not support XPropertySet
3171 formatPage( mrChartModel, rPageSize, mxRootShape, m_xShapeFactory );
3173 CreateShapeParam2D aParam;
3174 aParam.maRemainingSpace.X = 0;
3175 aParam.maRemainingSpace.Y = 0;
3176 aParam.maRemainingSpace.Width = rPageSize.Width;
3177 aParam.maRemainingSpace.Height = rPageSize.Height;
3179 //create the group shape for diagram and axes first to have title and legends on top of it
3180 uno::Reference< XDiagram > xDiagram( mrChartModel.getFirstDiagram() );
3181 OUString aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) ) );//todo: other index if more than one diagram is possible
3182 uno::Reference< drawing::XShapes > xDiagramPlusAxesPlusMarkHandlesGroup_Shapes(
3183 pShapeFactory->createGroup2D(mxRootShape,aDiagramCID) );
3185 aParam.mxMarkHandles = pShapeFactory->createInvisibleRectangle(
3186 xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0));
3187 AbstractShapeFactory::setShapeName(aParam.mxMarkHandles, "MarkHandles");
3189 aParam.mxPlotAreaWithAxes = pShapeFactory->createInvisibleRectangle(
3190 xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0, 0));
3191 AbstractShapeFactory::setShapeName(aParam.mxPlotAreaWithAxes, "PlotAreaIncludingAxes");
3193 aParam.mxDiagramWithAxesShapes = pShapeFactory->createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes);
3195 bool bAutoPositionDummy = true;
3197 lcl_createTitle(
3198 TitleHelper::MAIN_TITLE, mxRootShape, m_xShapeFactory, mrChartModel,
3199 aParam.maRemainingSpace, rPageSize, ALIGN_TOP, bAutoPositionDummy);
3200 if (aParam.maRemainingSpace.Width <= 0 || aParam.maRemainingSpace.Height <= 0)
3201 return;
3203 lcl_createTitle(
3204 TitleHelper::SUB_TITLE, mxRootShape, m_xShapeFactory, mrChartModel,
3205 aParam.maRemainingSpace, rPageSize, ALIGN_TOP, bAutoPositionDummy );
3206 if (aParam.maRemainingSpace.Width <= 0|| aParam.maRemainingSpace.Height <= 0)
3207 return;
3209 aParam.mpSeriesPlotterContainer.reset(new SeriesPlotterContainer(m_aVCooSysList));
3210 aParam.mpSeriesPlotterContainer->initializeCooSysAndSeriesPlotter( mrChartModel );
3211 if(maTimeBased.bTimeBased && maTimeBased.nFrame != 0)
3213 SeriesPlottersType& rSeriesPlotter = aParam.mpSeriesPlotterContainer->getSeriesPlotterList();
3214 size_t n = rSeriesPlotter.size();
3215 for(size_t i = 0; i < n; ++i)
3217 std::vector<VDataSeries*> aAllNewDataSeries = rSeriesPlotter[i].getAllSeries();
3218 std::vector< VDataSeries* >& rAllOldDataSeries =
3219 maTimeBased.m_aDataSeriesList[i];
3220 size_t m = std::min(aAllNewDataSeries.size(), rAllOldDataSeries.size());
3221 for(size_t j = 0; j < m; ++j)
3223 aAllNewDataSeries[j]->setOldTimeBased(
3224 rAllOldDataSeries[j], (maTimeBased.nFrame % 60)/60.0);
3229 lcl_createLegend(
3230 LegendHelper::getLegend( mrChartModel ), mxRootShape, m_xShapeFactory, m_xCC,
3231 aParam.maRemainingSpace, rPageSize, mrChartModel, aParam.mpSeriesPlotterContainer->getLegendEntryProviderList(),
3232 lcl_getDefaultWritingModeFromPool( m_pDrawModelWrapper ) );
3233 if (aParam.maRemainingSpace.Width <= 0 || aParam.maRemainingSpace.Height <= 0)
3234 return;
3236 if (!createAxisTitleShapes2D(aParam, rPageSize))
3237 return;
3239 bool bDummy = false;
3240 bool bIsVertical = DiagramHelper::getVertical(xDiagram, bDummy, bDummy);
3242 if (getAvailablePosAndSizeForDiagram(aParam, rPageSize, mrChartModel.getFirstDiagram()))
3244 awt::Rectangle aUsedOuterRect = impl_createDiagramAndContent(aParam, rPageSize);
3246 if (aParam.mxPlotAreaWithAxes.is())
3248 aParam.mxPlotAreaWithAxes->setPosition(awt::Point(aUsedOuterRect.X, aUsedOuterRect.Y));
3249 aParam.mxPlotAreaWithAxes->setSize(awt::Size(aUsedOuterRect.Width, aUsedOuterRect.Height));
3252 //correct axis title position
3253 awt::Rectangle aDiagramPlusAxesRect( aUsedOuterRect );
3254 if (aParam.mbAutoPosTitleX)
3255 changePositionOfAxisTitle(aParam.mpVTitleX.get(), ALIGN_BOTTOM, aDiagramPlusAxesRect, rPageSize);
3256 if (aParam.mbAutoPosTitleY)
3257 changePositionOfAxisTitle(aParam.mpVTitleY.get(), ALIGN_LEFT, aDiagramPlusAxesRect, rPageSize);
3258 if (aParam.mbAutoPosTitleZ)
3259 changePositionOfAxisTitle(aParam.mpVTitleZ.get(), ALIGN_Z, aDiagramPlusAxesRect, rPageSize);
3260 if (aParam.mbAutoPosSecondTitleX)
3261 changePositionOfAxisTitle(aParam.mpVTitleSecondX.get(), bIsVertical? ALIGN_RIGHT : ALIGN_TOP, aDiagramPlusAxesRect, rPageSize);
3262 if (aParam.mbAutoPosSecondTitleY)
3263 changePositionOfAxisTitle(aParam.mpVTitleSecondY.get(), bIsVertical? ALIGN_TOP : ALIGN_RIGHT, aDiagramPlusAxesRect, rPageSize);
3266 //cleanup: remove all empty group shapes to avoid grey border lines:
3267 lcl_removeEmptyGroupShapes( mxRootShape );
3269 render();
3271 if(maTimeBased.bTimeBased && maTimeBased.nFrame % 60 == 0)
3273 // create copy of the data for next frame
3274 SeriesPlottersType& rSeriesPlotter = aParam.mpSeriesPlotterContainer->getSeriesPlotterList();
3275 size_t n = rSeriesPlotter.size();
3276 maTimeBased.m_aDataSeriesList.clear();
3277 maTimeBased.m_aDataSeriesList.resize(n);
3278 for(size_t i = 0; i < n; ++i)
3280 std::vector<VDataSeries*> aAllNewDataSeries = rSeriesPlotter[i].getAllSeries();
3281 std::vector<VDataSeries*>& rAllOldDataSeries = maTimeBased.m_aDataSeriesList[i];
3282 size_t m = aAllNewDataSeries.size();
3283 for(size_t j = 0; j < m; ++j)
3285 rAllOldDataSeries.push_back( aAllNewDataSeries[j]->
3286 createCopyForTimeBased() );
3290 if(maTimeBased.eMode != MANUAL)
3292 mrChartModel.setTimeBased(true);
3293 mrChartModel.getNextTimePoint();
3295 else
3296 maTimeBased.maTimer.Stop();
3299 if(maTimeBased.bTimeBased && maTimeBased.eMode != MANUAL && !maTimeBased.maTimer.IsActive())
3301 maTimeBased.maTimer.SetTimeout(15);
3302 maTimeBased.maTimer.SetTimeoutHdl(LINK(this, ChartView, UpdateTimeBased));
3303 maTimeBased.maTimer.Start();
3307 bool ChartView::createAxisTitleShapes2D( CreateShapeParam2D& rParam, const css::awt::Size& rPageSize )
3309 uno::Reference<XDiagram> xDiagram = mrChartModel.getFirstDiagram();
3311 Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
3312 sal_Int32 nDimension = DiagramHelper::getDimension( xDiagram );
3314 if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 0 ) )
3315 rParam.mpVTitleX = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, mxRootShape, m_xShapeFactory, mrChartModel
3316 , rParam.maRemainingSpace, rPageSize, ALIGN_BOTTOM, rParam.mbAutoPosTitleX );
3317 if (rParam.maRemainingSpace.Width <= 0 ||rParam.maRemainingSpace.Height <= 0)
3318 return false;
3320 if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 1 ) )
3321 rParam.mpVTitleY = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, mxRootShape, m_xShapeFactory, mrChartModel
3322 , rParam.maRemainingSpace, rPageSize, ALIGN_LEFT, rParam.mbAutoPosTitleY );
3323 if (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)
3324 return false;
3326 if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 2 ) )
3327 rParam.mpVTitleZ = lcl_createTitle( TitleHelper::Z_AXIS_TITLE, mxRootShape, m_xShapeFactory, mrChartModel
3328 , rParam.maRemainingSpace, rPageSize, ALIGN_RIGHT, rParam.mbAutoPosTitleZ );
3329 if (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)
3330 return false;
3332 bool bDummy = false;
3333 bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy );
3335 if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 0 ) )
3336 rParam.mpVTitleSecondX = lcl_createTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, mxRootShape, m_xShapeFactory, mrChartModel
3337 , rParam.maRemainingSpace, rPageSize, bIsVertical? ALIGN_RIGHT : ALIGN_TOP, rParam.mbAutoPosSecondTitleX );
3338 if (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)
3339 return false;
3341 if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 1 ) )
3342 rParam.mpVTitleSecondY = lcl_createTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, mxRootShape, m_xShapeFactory, mrChartModel
3343 , rParam.maRemainingSpace, rPageSize, bIsVertical? ALIGN_TOP : ALIGN_RIGHT, rParam.mbAutoPosSecondTitleY );
3344 if (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)
3345 return false;
3347 return true;
3350 void ChartView::createShapes3D()
3352 OpenGLWindow* pWindow = mrChartModel.getOpenGLWindow();
3353 if(!pWindow)
3354 return;
3356 if( pWindow->GetSizePixel().Width() == 0 || pWindow->GetSizePixel().Height() == 0 )
3358 awt::Size aPageSize = mrChartModel.getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
3359 Size aSize = pWindow->LogicToPixel( Size(aPageSize.Width,aPageSize.Height), MapUnit(MAP_100TH_MM) );
3360 pWindow->SetSizePixel(aSize);
3362 pWindow->Show();
3363 uno::Reference< XDiagram > xDiagram( mrChartModel.getFirstDiagram() );
3364 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
3365 if( !xCooSysContainer.is())
3366 return;
3368 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
3370 if (aCooSysList.getLength() != 1)
3371 // Supporting multiple coordinates in a truly 3D chart (which implies
3372 // it's a Cartesian coordinate system) is a bit of a challenge, if not
3373 // impossible.
3374 return;
3376 uno::Reference<XCoordinateSystem> xCooSys( aCooSysList[0] );
3378 //iterate through all chart types in the current coordinate system
3379 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
3380 OSL_ASSERT( xChartTypeContainer.is());
3381 if( !xChartTypeContainer.is() )
3382 return;
3384 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
3385 if (aChartTypeList.getLength() != 1)
3386 // Likewise, we can't really support multiple chart types here.
3387 return;
3389 uno::Reference< XChartType > xChartType( aChartTypeList[0] );
3391 if (!m_pGL3DPlotter)
3393 m_pGL3DPlotter.reset(new GL3DBarChart(xChartType, pWindow));
3395 else
3397 GL3DBarChart* pChart = dynamic_cast<GL3DBarChart*>(m_pGL3DPlotter.get());
3398 if (pChart)
3399 pChart->setOpenGLWindow(pWindow);
3402 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
3403 OSL_ASSERT( xDataSeriesContainer.is());
3404 if( !xDataSeriesContainer.is() )
3405 return;
3407 boost::ptr_vector<VDataSeries> aDataSeries;
3408 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
3409 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
3411 uno::Reference< XDataSeries > xDataSeries( aSeriesList[nS], uno::UNO_QUERY );
3412 if(!xDataSeries.is())
3413 continue;
3415 aDataSeries.push_back(new VDataSeries(xDataSeries));
3418 boost::scoped_ptr<ExplicitCategoriesProvider> pCatProvider(new ExplicitCategoriesProvider(xCooSys, mrChartModel));
3420 m_pGL3DPlotter->create3DShapes(aDataSeries, *pCatProvider);
3422 m_pGL3DPlotter->render();
3425 void ChartView::updateOpenGLWindow()
3427 if(!isReal3DChart())
3428 mp2DRenderer->updateOpenGLWindow();
3431 } //namespace chart
3433 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
3434 com_sun_star_comp_chart2_ChartView_get_implementation(css::uno::XComponentContext *context,
3435 css::uno::Sequence<css::uno::Any> const &)
3437 ::chart::ChartModel *pChartModel = new ::chart::ChartModel(context);
3438 return cppu::acquire(new ::chart::ChartView(context, *pChartModel));
3441 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */