1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
28 #include "VButton.hxx"
29 #include <AbstractShapeFactory.hxx>
30 #include <VCoordinateSystem.hxx>
31 #include <VSeriesPlotter.hxx>
32 #include <CommonConverters.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 #if HAVE_FEATURE_OPENGL
54 #include <GL3DBarChart.hxx>
56 #include <editeng/frmdiritem.hxx>
58 #include <tools/globname.hxx>
59 #include <comphelper/fileformat.h>
60 #include <comphelper/scopeguard.hxx>
61 #include <comphelper/servicehelper.hxx>
62 #include <cppuhelper/supportsservice.hxx>
63 #include <unotools/streamwrap.hxx>
64 #include <unotools/localedatawrapper.hxx>
65 #include <svx/charthelper.hxx>
66 #include <svx/svdpage.hxx>
67 #include <svx/unopage.hxx>
68 #include <svx/unoshape.hxx>
69 #include <vcl/svapp.hxx>
70 #include <osl/mutex.hxx>
71 #include <svx/unofill.hxx>
72 #include <vcl/openglwin.hxx>
73 #if HAVE_FEATURE_OPENGL
74 #include <vcl/opengl/OpenGLContext.hxx>
76 #include <drawinglayer/XShapeDumper.hxx>
80 #include <com/sun/star/awt/Size.hpp>
81 #include <com/sun/star/awt/Point.hpp>
82 #include <com/sun/star/chart/ChartAxisPosition.hpp>
83 #include <com/sun/star/chart/DataLabelPlacement.hpp>
84 #include <com/sun/star/chart/MissingValueTreatment.hpp>
85 #include <com/sun/star/chart2/StackingDirection.hpp>
86 #include <com/sun/star/chart2/XChartDocument.hpp>
87 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
88 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
89 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
90 #include <com/sun/star/chart2/XTitled.hpp>
91 #include <com/sun/star/chart2/RelativePosition.hpp>
92 #include <com/sun/star/chart2/RelativeSize.hpp>
93 #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
94 #include <com/sun/star/chart2/data/PivotTableFieldEntry.hpp>
95 #include <com/sun/star/drawing/FillStyle.hpp>
96 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
97 #include <com/sun/star/drawing/LineStyle.hpp>
98 #include <com/sun/star/drawing/XShapeGroup.hpp>
99 #include <com/sun/star/drawing/XShapeDescriptor.hpp>
100 #include <com/sun/star/document/XExporter.hpp>
101 #include <com/sun/star/document/XFilter.hpp>
102 #include <com/sun/star/embed/Aspects.hpp>
103 #include <com/sun/star/io/XSeekable.hpp>
104 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
105 #include <com/sun/star/util/XModifiable.hpp>
106 #include <com/sun/star/util/XRefreshable.hpp>
107 #include <com/sun/star/util/NumberFormat.hpp>
108 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
109 #include <com/sun/star/text/XText.hpp>
110 #include <com/sun/star/text/XTextDocument.hpp>
111 #include <com/sun/star/text/WritingMode2.hpp>
112 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
113 #include <com/sun/star/view/XSelectionSupplier.hpp>
114 #include <svl/itempool.hxx>
115 #include <svl/languageoptions.hxx>
116 #include <comphelper/classids.hxx>
117 #include <servicenames_charttypes.hxx>
120 #include <rtl/strbuf.hxx>
121 #include <rtl/ustring.hxx>
123 #include <osl/conditn.hxx>
124 #include <o3tl/make_unique.hxx>
125 #include <tools/diagnose_ex.h>
131 using namespace ::com::sun::star
;
132 using namespace ::com::sun::star::chart2
;
133 using ::com::sun::star::uno::Reference
;
134 using ::com::sun::star::uno::Sequence
;
135 using ::com::sun::star::uno::Any
;
139 class theExplicitValueProviderUnoTunnelId
: public rtl::Static
<UnoTunnelIdInit
, theExplicitValueProviderUnoTunnelId
> {};
141 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
142 typedef std::map
< VCoordinateSystem
*, tFullAxisIndex
> tCoordinateSystemMap
;
144 /** This class handles a collection of coordinate systems and is used for
145 * executing some action on all coordinate systems such as
146 * `prepareAutomaticAxisScaling` and `setExplicitScaleAndIncrement`.
147 * Moreover it contains the `aAutoScaling` object that is an instance of
148 * the `ScaleAutomatism` class. The initialization of `aAutoScaling` is
149 * performed in the `SeriesPlotterContainer::initAxisUsageList` method and is
150 * used in the `SeriesPlotterContainer::doAutoScaling` for calculating explicit
151 * scale and increment objects (see `SeriesPlotterContainer::doAutoScaling`).
158 void addCoordinateSystem( VCoordinateSystem
* pCooSys
, sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
);
159 std::vector
< VCoordinateSystem
* > getCoordinateSystems( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
);
160 sal_Int32
getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex
);
162 void prepareAutomaticAxisScaling( ScaleAutomatism
& rScaleAutomatism
, sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
);
163 void setExplicitScaleAndIncrement( sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
, const ExplicitScaleData
& rScale
, const ExplicitIncrementData
& rInc
);
165 ScaleAutomatism aAutoScaling
;
168 tCoordinateSystemMap aCoordinateSystems
;
169 std::map
< sal_Int32
, sal_Int32
> aMaxIndexPerDimension
;
172 AxisUsage::AxisUsage()
173 : aAutoScaling(AxisHelper::createDefaultScale(), Date(Date::SYSTEM
))
177 AxisUsage::~AxisUsage()
179 aCoordinateSystems
.clear();
182 void AxisUsage::addCoordinateSystem( VCoordinateSystem
* pCooSys
, sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
187 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
188 tCoordinateSystemMap::const_iterator
aFound( aCoordinateSystems
.find(pCooSys
) );
190 //use one scale only once for each coordinate system
191 //main axis are preferred over secondary axis
192 //value scales are preferred
193 if(aFound
!=aCoordinateSystems
.end())
195 sal_Int32 nFoundAxisIndex
= aFound
->second
.second
;
196 if( nFoundAxisIndex
< nAxisIndex
)
198 sal_Int32 nFoundDimension
= aFound
->second
.first
;
199 if( nFoundDimension
==1 )
201 if( nFoundDimension
< nDimensionIndex
)
204 aCoordinateSystems
[pCooSys
] = aFullAxisIndex
;
206 //set maximum scale index
207 std::map
< sal_Int32
, sal_Int32
>::const_iterator aIter
= aMaxIndexPerDimension
.find(nDimensionIndex
);
208 if( aIter
!= aMaxIndexPerDimension
.end() )
210 sal_Int32 nCurrentMaxIndex
= aIter
->second
;
211 if( nCurrentMaxIndex
< nAxisIndex
)
212 aMaxIndexPerDimension
[nDimensionIndex
]=nAxisIndex
;
215 aMaxIndexPerDimension
[nDimensionIndex
]=nAxisIndex
;
218 std::vector
< VCoordinateSystem
* > AxisUsage::getCoordinateSystems( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
220 std::vector
< VCoordinateSystem
* > aRet
;
222 for (auto const& coordinateSystem
: aCoordinateSystems
)
224 if( coordinateSystem
.second
.first
!= nDimensionIndex
)
226 if( coordinateSystem
.second
.second
!= nAxisIndex
)
228 aRet
.push_back( coordinateSystem
.first
);
234 sal_Int32
AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex
)
237 std::map
< sal_Int32
, sal_Int32
>::const_iterator aIter
= aMaxIndexPerDimension
.find(nDimensionIndex
);
238 if( aIter
!= aMaxIndexPerDimension
.end() )
239 nRet
= aIter
->second
;
243 void AxisUsage::prepareAutomaticAxisScaling( ScaleAutomatism
& rScaleAutomatism
, sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
)
245 std::vector
<VCoordinateSystem
*> aVCooSysList
= getCoordinateSystems(nDimIndex
, nAxisIndex
);
246 for (VCoordinateSystem
* i
: aVCooSysList
)
247 i
->prepareAutomaticAxisScaling(rScaleAutomatism
, nDimIndex
, nAxisIndex
);
250 void AxisUsage::setExplicitScaleAndIncrement(
251 sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
, const ExplicitScaleData
& rScale
, const ExplicitIncrementData
& rInc
)
253 std::vector
<VCoordinateSystem
*> aVCooSysList
= getCoordinateSystems(nDimIndex
, nAxisIndex
);
254 for (VCoordinateSystem
* i
: aVCooSysList
)
255 i
->setExplicitScaleAndIncrement(nDimIndex
, nAxisIndex
, rScale
, rInc
);
258 typedef std::vector
<std::unique_ptr
<VSeriesPlotter
> > SeriesPlottersType
;
260 /** This class is a container of `SeriesPlotter` objects (such as `PieChart`
261 * instances). It is used for initializing coordinate systems, axes and scales
262 * of all series plotters which belongs to the container.
264 class SeriesPlotterContainer
267 explicit SeriesPlotterContainer( std::vector
< VCoordinateSystem
* >& rVCooSysList
);
268 ~SeriesPlotterContainer();
270 /** It is used to set coordinate systems (`m_rVCooSysList`), this method
271 * is invoked by `ChartView::createShapes2D` before of
272 * `ChartView::impl_createDiagramAndContent`.
273 * Coordinate systems are retrieved through the `XCoordinateSystemContainer`
274 * interface implemented by a diagram object which is provided by the
275 * `ChartModel` object passed to the method (`rChartModel.getFirstDiagram()`).
277 * It is used for creating series plotters and appending them
278 * to `m_aSeriesPlotterList`. The created series plotters are initialized
279 * through data (number formats supplier, color scheme, data series),
280 * extracted from the chart model or the diagram objects. An exception is
281 * the explicit category provider that is retrieved through the
282 * `VCoordinateSystem` object used by the series plotter.
284 * It sets the minimum-maximum supplier for a coordinate system:
285 * this supplier is the series plotter itself which utilizes the given
286 * coordinate system. In fact `VSeriesPlotter` has `MinimumMaximumSupplier`
287 * as one of its base classes.
288 * Hence, for instance, a `PieChart`, which is a series plotter, is
289 * a `MinimumMaximumSupplier`, too.
291 void initializeCooSysAndSeriesPlotter( ChartModel
& rModel
);
293 /** This method is invoked by `ChartView::impl_createDiagramAndContent`.
294 * It iterates on every axis of every coordinate systems, and if the axis
295 * is not yet present in `m_aAxisUsageList` it creates a new `AxisUsage`
296 * object and initialize its `aAutoScaling` member to the `ScaleData`
297 * object of the current axis.
299 void initAxisUsageList(const Date
& rNullDate
);
302 * Perform automatic axis scaling and determine the amount and spacing of
303 * increments. It assumes that the caller has determined the size of the
304 * largest axis label text object prior to calling this method.
306 * The new axis scaling data will be stored in the VCoordinateSystem
307 * objects. The label alignment direction for each axis will also get
308 * determined during this process, and stored in VAxis.
310 * This method is invoked by `ChartView::impl_createDiagramAndContent`
311 * soon after `initAxisUsageList`.
312 * It initializes explicit scale and increment objects for all coordinate
313 * systems in `m_rVCooSysList`.
314 * This action is achieved by iterating on the `m_aAxisUsageList` container,
315 * and performing 3 steps:
316 * 1- call `VCoordinateSystem::prepareAutomaticAxisScaling` for setting
317 * scaling parameters of the `aAutoScaling` member (a `ScaleAutomatism`
318 * object) for the current `AxisUsage` instance
319 * (see `VCoordinateSystem::prepareAutomaticAxisScaling`);
320 * 2- calculate the explicit scale and increment objects
321 * (see ScaleAutomatism::calculateExplicitScaleAndIncrement);
322 * 3- set the explicit scale and increment objects for each coordinate
325 void doAutoScaling( ChartModel
& rModel
);
328 * After auto-scaling is performed, call this method to set the explicit
329 * scaling and increment data to all relevant VAxis objects.
331 void updateScalesAndIncrementsOnAxes();
334 * After auto-scaling is performed, call this method to set the explicit
335 * scaling data to all the plotters.
337 void setScalesFromCooSysToPlotter();
339 void setNumberFormatsFromAxes();
340 drawing::Direction3D
getPreferredAspectRatio();
342 SeriesPlottersType
& getSeriesPlotterList() { return m_aSeriesPlotterList
; }
343 std::vector
< VCoordinateSystem
* >& getCooSysList() { return m_rVCooSysList
; }
344 std::vector
< LegendEntryProvider
* > getLegendEntryProviderList();
346 void AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel
& rModel
);
348 bool isCategoryPositionShifted(
349 const chart2::ScaleData
& rSourceScale
, bool bHasComplexCategories
) const;
352 /** A vector of series plotters.
354 SeriesPlottersType m_aSeriesPlotterList
;
356 /** A vector of coordinate systems.
358 std::vector
< VCoordinateSystem
* >& m_rVCooSysList
;
360 /** A map whose key is a `XAxis` interface and the related value is
361 * an object of `AxisUsage` type.
363 std::map
< uno::Reference
< XAxis
>, AxisUsage
> m_aAxisUsageList
;
366 * Max axis index of all dimensions. Currently this can be either 0 or 1
367 * since we only support primary and secondary axes per dimension. The
368 * value of 0 means all dimensions have only primary axis, while 1 means
369 * at least one dimension has a secondary axis.
371 sal_Int32 m_nMaxAxisIndex
;
373 bool m_bChartTypeUsesShiftedCategoryPositionPerDefault
;
374 sal_Int32 m_nDefaultDateNumberFormat
;
377 SeriesPlotterContainer::SeriesPlotterContainer( std::vector
< VCoordinateSystem
* >& rVCooSysList
)
378 : m_rVCooSysList( rVCooSysList
)
380 , m_bChartTypeUsesShiftedCategoryPositionPerDefault(false)
381 , m_nDefaultDateNumberFormat(0)
385 SeriesPlotterContainer::~SeriesPlotterContainer()
387 // - remove plotter from coordinatesystems
388 for(VCoordinateSystem
* nC
: m_rVCooSysList
)
389 nC
->clearMinimumAndMaximumSupplierList();
392 std::vector
< LegendEntryProvider
* > SeriesPlotterContainer::getLegendEntryProviderList()
394 std::vector
< LegendEntryProvider
* > aRet( m_aSeriesPlotterList
.size() );
396 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: m_aSeriesPlotterList
)
397 aRet
[nN
++] = aPlotter
.get();
401 VCoordinateSystem
* findInCooSysList( const std::vector
< VCoordinateSystem
* >& rVCooSysList
402 , const uno::Reference
< XCoordinateSystem
>& xCooSys
)
404 for(VCoordinateSystem
* pVCooSys
: rVCooSysList
)
406 if(pVCooSys
->getModel()==xCooSys
)
412 VCoordinateSystem
* lcl_getCooSysForPlotter( const std::vector
< VCoordinateSystem
* >& rVCooSysList
, MinimumAndMaximumSupplier
* pMinimumAndMaximumSupplier
)
414 if(!pMinimumAndMaximumSupplier
)
416 for(VCoordinateSystem
* pVCooSys
: rVCooSysList
)
418 if(pVCooSys
->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier
))
424 VCoordinateSystem
* addCooSysToList( std::vector
< VCoordinateSystem
* >& rVCooSysList
425 , const uno::Reference
< XCoordinateSystem
>& xCooSys
426 , ChartModel
& rChartModel
)
428 VCoordinateSystem
* pVCooSys
= findInCooSysList( rVCooSysList
, xCooSys
);
431 pVCooSys
= VCoordinateSystem::createCoordinateSystem(xCooSys
);
434 OUString
aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys
, rChartModel
) );
435 pVCooSys
->setParticle(aCooSysParticle
);
437 pVCooSys
->setExplicitCategoriesProvider( new ExplicitCategoriesProvider(xCooSys
, rChartModel
) );
439 rVCooSysList
.push_back( pVCooSys
);
445 void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(
446 ChartModel
& rChartModel
)
448 uno::Reference
< XDiagram
> xDiagram( rChartModel
.getFirstDiagram() );
452 uno::Reference
< util::XNumberFormatsSupplier
> xNumberFormatsSupplier( static_cast< ::cppu::OWeakObject
* >( &rChartModel
), uno::UNO_QUERY
);
453 if( rChartModel
.hasInternalDataProvider() && DiagramHelper::isSupportingDateAxis( xDiagram
) )
454 m_nDefaultDateNumberFormat
=DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier
);
456 sal_Int32 nDimensionCount
= DiagramHelper::getDimension( xDiagram
);
459 //@todo handle mixed dimension
463 bool bSortByXValues
= false;
464 bool bConnectBars
= false;
465 bool bGroupBarsPerAxis
= true;
466 bool bIncludeHiddenCells
= true;
467 sal_Int32 nStartingAngle
= 90;
468 sal_Int32 n3DRelativeHeight
= 100;
471 uno::Reference
< beans::XPropertySet
> xDiaProp( xDiagram
, uno::UNO_QUERY_THROW
);
472 xDiaProp
->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES
) >>= bSortByXValues
;
473 xDiaProp
->getPropertyValue( "ConnectBars" ) >>= bConnectBars
;
474 xDiaProp
->getPropertyValue( "GroupBarsPerAxis" ) >>= bGroupBarsPerAxis
;
475 xDiaProp
->getPropertyValue( "IncludeHiddenCells" ) >>= bIncludeHiddenCells
;
476 xDiaProp
->getPropertyValue( "StartingAngle" ) >>= nStartingAngle
;
478 if (nDimensionCount
== 3)
480 xDiaProp
->getPropertyValue( "3DRelativeHeight" ) >>= n3DRelativeHeight
;
483 catch( const uno::Exception
& )
485 DBG_UNHANDLED_EXCEPTION("chart2" );
488 //prepare for autoscaling and shape creation
489 // - create plotter for charttypes (for each first scale group at each plotter, as they are independent)
490 // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling)
491 // - add plotter to coordinate systems
493 //iterate through all coordinate systems
494 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
495 OSL_ASSERT( xCooSysContainer
.is());
496 if( !xCooSysContainer
.is())
498 uno::Reference
< XColorScheme
> xColorScheme( xDiagram
->getDefaultColorScheme());
499 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
500 sal_Int32 nGlobalSeriesIndex
= 0;//for automatic symbols
501 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
503 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
504 VCoordinateSystem
* pVCooSys
= addCooSysToList(m_rVCooSysList
,xCooSys
,rChartModel
);
506 //iterate through all chart types in the current coordinate system
507 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
508 OSL_ASSERT( xChartTypeContainer
.is());
509 if( !xChartTypeContainer
.is() )
511 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
512 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
514 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
515 if(nDimensionCount
== 3 && xChartType
->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE
))
517 uno::Reference
< beans::XPropertySet
> xPropertySet( xChartType
, uno::UNO_QUERY
);
518 if (xPropertySet
.is())
522 sal_Int32
n3DRelativeHeightOldValue(100);
523 uno::Any aAny
= xPropertySet
->getPropertyValue( "3DRelativeHeight" );
524 aAny
>>= n3DRelativeHeightOldValue
;
525 if (n3DRelativeHeightOldValue
!= n3DRelativeHeight
)
526 xPropertySet
->setPropertyValue( "3DRelativeHeight", uno::Any(n3DRelativeHeight
) );
528 catch (const uno::Exception
&) { }
533 m_bChartTypeUsesShiftedCategoryPositionPerDefault
= ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault( xChartType
);
535 bool bExcludingPositioning
= DiagramHelper::getDiagramPositioningMode( xDiagram
) == DiagramPositioningMode_EXCLUDING
;
536 VSeriesPlotter
* pPlotter
= VSeriesPlotter::createSeriesPlotter( xChartType
, nDimensionCount
, bExcludingPositioning
);
540 m_aSeriesPlotterList
.push_back( std::unique_ptr
<VSeriesPlotter
>(pPlotter
) );
541 pPlotter
->setNumberFormatsSupplier( xNumberFormatsSupplier
);
542 pPlotter
->setColorScheme( xColorScheme
);
544 pPlotter
->setExplicitCategoriesProvider( pVCooSys
->getExplicitCategoriesProvider() );
545 sal_Int32 nMissingValueTreatment
= DiagramHelper::getCorrectedMissingValueTreatment( xDiagram
, xChartType
);
548 pVCooSys
->addMinimumAndMaximumSupplier(pPlotter
);
550 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xChartType
, uno::UNO_QUERY
);
551 OSL_ASSERT( xDataSeriesContainer
.is());
552 if( !xDataSeriesContainer
.is() )
558 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
559 for( sal_Int32 nS
= 0; nS
< aSeriesList
.getLength(); ++nS
)
561 uno::Reference
< XDataSeries
> xDataSeries( aSeriesList
[nS
], uno::UNO_QUERY
);
562 if(!xDataSeries
.is())
564 if( !bIncludeHiddenCells
&& !DataSeriesHelper::hasUnhiddenData(xDataSeries
) )
567 VDataSeries
* pSeries
= new VDataSeries( xDataSeries
);
569 pSeries
->setGlobalSeriesIndex(nGlobalSeriesIndex
);
570 nGlobalSeriesIndex
++;
573 pSeries
->doSortByXValues();
575 pSeries
->setConnectBars( bConnectBars
);
576 pSeries
->setGroupBarsPerAxis( bGroupBarsPerAxis
);
577 pSeries
->setStartingAngle( nStartingAngle
);
579 pSeries
->setMissingValueTreatment( nMissingValueTreatment
);
581 OUString
aSeriesParticle( ObjectIdentifier::createParticleForSeries( 0, nCS
, nT
, nS
) );
582 pSeries
->setParticle(aSeriesParticle
);
584 OUString
aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType
) );
585 pSeries
->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole
);
587 //ignore secondary axis for charttypes that do not support them
588 if( pSeries
->getAttachedAxisIndex() != MAIN_AXIS_INDEX
&&
589 !ChartTypeHelper::isSupportingSecondaryAxis( xChartType
, nDimensionCount
) )
591 pSeries
->setAttachedAxisIndex(MAIN_AXIS_INDEX
);
594 StackingDirection eDirection
= pSeries
->getStackingDirection();
597 case StackingDirection_NO_STACKING
:
602 case StackingDirection_Y_STACKING
:
609 case StackingDirection_Z_STACKING
:
610 zSlot
++; xSlot
=-1; ySlot
=-1;
613 // UNO enums have one additional auto-generated case
616 pPlotter
->addSeries( pSeries
, zSlot
, xSlot
, ySlot
);
621 //transport seriesnames to the coordinatesystems if needed
622 if( !m_aSeriesPlotterList
.empty() )
624 uno::Sequence
< OUString
> aSeriesNames
;
625 bool bSeriesNamesInitialized
= false;
626 for(VCoordinateSystem
* pVCooSys
: m_rVCooSysList
)
630 if( pVCooSys
->needSeriesNamesForAxis() )
632 if(!bSeriesNamesInitialized
)
634 aSeriesNames
= m_aSeriesPlotterList
[0]->getSeriesNames();
635 bSeriesNamesInitialized
= true;
637 pVCooSys
->setSeriesNamesForAxis( aSeriesNames
);
643 bool SeriesPlotterContainer::isCategoryPositionShifted(
644 const chart2::ScaleData
& rSourceScale
, bool bHasComplexCategories
) const
646 if (rSourceScale
.AxisType
== AxisType::CATEGORY
&& m_bChartTypeUsesShiftedCategoryPositionPerDefault
)
649 if (rSourceScale
.AxisType
==AxisType::CATEGORY
&& bHasComplexCategories
)
652 if (rSourceScale
.AxisType
== AxisType::DATE
)
655 if (rSourceScale
.AxisType
== AxisType::SERIES
)
661 void SeriesPlotterContainer::initAxisUsageList(const Date
& rNullDate
)
663 m_aAxisUsageList
.clear();
665 // Loop through coordinate systems in the diagram (though for now
666 // there should only be one coordinate system per diagram).
667 for (VCoordinateSystem
* pVCooSys
: m_rVCooSysList
)
669 uno::Reference
<XCoordinateSystem
> xCooSys
= pVCooSys
->getModel();
670 sal_Int32 nDimCount
= xCooSys
->getDimension();
672 for (sal_Int32 nDimIndex
= 0; nDimIndex
< nDimCount
; ++nDimIndex
)
674 bool bDateAxisAllowed
= ChartTypeHelper::isSupportingDateAxis(
675 AxisHelper::getChartTypeByIndex(xCooSys
, 0), nDimIndex
);
677 // Each dimension may have primary and secondary axes.
678 const sal_Int32 nMaxAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimIndex
);
679 for (sal_Int32 nAxisIndex
= 0; nAxisIndex
<= nMaxAxisIndex
; ++nAxisIndex
)
681 uno::Reference
<XAxis
> xAxis
= xCooSys
->getAxisByDimension(nDimIndex
, nAxisIndex
);
686 if (m_aAxisUsageList
.find(xAxis
) == m_aAxisUsageList
.end())
688 // Create axis usage object for this axis.
690 chart2::ScaleData aSourceScale
= xAxis
->getScaleData();
691 ExplicitCategoriesProvider
* pCatProvider
= pVCooSys
->getExplicitCategoriesProvider();
693 AxisHelper::checkDateAxis( aSourceScale
, pCatProvider
, bDateAxisAllowed
);
695 bool bHasComplexCat
= pCatProvider
&& pCatProvider
->hasComplexCategories();
696 aSourceScale
.ShiftedCategoryPosition
= isCategoryPositionShifted(aSourceScale
, bHasComplexCat
);
698 m_aAxisUsageList
[xAxis
].aAutoScaling
= ScaleAutomatism(aSourceScale
, rNullDate
);
701 AxisUsage
& rAxisUsage
= m_aAxisUsageList
[xAxis
];
702 rAxisUsage
.addCoordinateSystem(pVCooSys
, nDimIndex
, nAxisIndex
);
707 // Determine the highest axis index of all dimensions.
709 for (VCoordinateSystem
* pVCooSys
: m_rVCooSysList
)
711 uno::Reference
<XCoordinateSystem
> xCooSys
= pVCooSys
->getModel();
712 sal_Int32 nDimCount
= xCooSys
->getDimension();
714 for (sal_Int32 nDimIndex
= 0; nDimIndex
< nDimCount
; ++nDimIndex
)
716 for (auto & axisUsage
: m_aAxisUsageList
)
718 sal_Int32 nLocalMax
= axisUsage
.second
.getMaxAxisIndexForDimension(nDimIndex
);
719 if (m_nMaxAxisIndex
< nLocalMax
)
720 m_nMaxAxisIndex
= nLocalMax
;
726 void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
728 //set scales to plotter to enable them to provide the preferred scene AspectRatio
729 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: m_aSeriesPlotterList
)
731 VSeriesPlotter
* pSeriesPlotter
= aPlotter
.get();
732 VCoordinateSystem
* pVCooSys
= lcl_getCooSysForPlotter( m_rVCooSysList
, pSeriesPlotter
);
735 pSeriesPlotter
->setScales( pVCooSys
->getExplicitScales(0,0), pVCooSys
->getPropertySwapXAndYAxis() );
736 sal_Int32 nMaxAxisIndex
= pVCooSys
->getMaximumAxisIndexByDimension(1);//only additional value axis are relevant for series plotter
737 for( sal_Int32 nI
=1; nI
<=nMaxAxisIndex
; nI
++ )
738 pSeriesPlotter
->addSecondaryValueScale( pVCooSys
->getExplicitScale(1,nI
), nI
);
743 void SeriesPlotterContainer::setNumberFormatsFromAxes()
745 //set numberformats to plotter to enable them to display the data labels in the numberformat of the axis
746 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: m_aSeriesPlotterList
)
748 VSeriesPlotter
* pSeriesPlotter
= aPlotter
.get();
749 VCoordinateSystem
* pVCooSys
= lcl_getCooSysForPlotter( m_rVCooSysList
, pSeriesPlotter
);
752 AxesNumberFormats aAxesNumberFormats
;
753 uno::Reference
< XCoordinateSystem
> xCooSys
= pVCooSys
->getModel();
754 sal_Int32 nDimensionCount
= xCooSys
->getDimension();
755 for(sal_Int32 nDimensionIndex
=0; nDimensionIndex
<nDimensionCount
; ++nDimensionIndex
)
757 const sal_Int32 nMaximumAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimensionIndex
);
758 for(sal_Int32 nAxisIndex
=0; nAxisIndex
<=nMaximumAxisIndex
; ++nAxisIndex
)
762 Reference
< beans::XPropertySet
> xAxisProp( xCooSys
->getAxisByDimension( nDimensionIndex
, nAxisIndex
), uno::UNO_QUERY
);
765 sal_Int32
nNumberFormatKey(0);
766 if( xAxisProp
->getPropertyValue(CHART_UNONAME_NUMFMT
) >>= nNumberFormatKey
)
768 aAxesNumberFormats
.setFormat( nNumberFormatKey
, nDimensionIndex
, nAxisIndex
);
770 else if( nDimensionIndex
==0 )
772 //provide a default date format for date axis with own data
773 aAxesNumberFormats
.setFormat( m_nDefaultDateNumberFormat
, nDimensionIndex
, nAxisIndex
);
777 catch( const lang::IndexOutOfBoundsException
& e
)
779 SAL_WARN("chart2", "Exception caught. " << e
);
783 pSeriesPlotter
->setAxesNumberFormats( aAxesNumberFormats
);
788 void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
790 for(VCoordinateSystem
* nC
: m_rVCooSysList
)
791 nC
->updateScalesAndIncrementsOnAxes();
794 void SeriesPlotterContainer::doAutoScaling( ChartModel
& rChartModel
)
796 if (m_aSeriesPlotterList
.empty() || m_aAxisUsageList
.empty())
797 // We need these two containers populated to do auto-scaling. Bail out.
800 //iterate over the main scales first than secondary axis
801 for (sal_Int32 nAxisIndex
= 0; nAxisIndex
<= m_nMaxAxisIndex
; ++nAxisIndex
)
803 // - first do autoscale for all x and z scales (because they are treated independent)
804 for (auto & axisUsage
: m_aAxisUsageList
)
806 AxisUsage
& rAxisUsage
= axisUsage
.second
;
808 rAxisUsage
.prepareAutomaticAxisScaling(rAxisUsage
.aAutoScaling
, 0, nAxisIndex
);
809 rAxisUsage
.prepareAutomaticAxisScaling(rAxisUsage
.aAutoScaling
, 2, nAxisIndex
);
811 ExplicitScaleData aExplicitScale
;
812 ExplicitIncrementData aExplicitIncrement
;
813 rAxisUsage
.aAutoScaling
.calculateExplicitScaleAndIncrement( aExplicitScale
, aExplicitIncrement
);
815 rAxisUsage
.setExplicitScaleAndIncrement(0, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
816 rAxisUsage
.setExplicitScaleAndIncrement(2, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
819 // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already )
820 for (auto & axisUsage
: m_aAxisUsageList
)
822 AxisUsage
& rAxisUsage
= axisUsage
.second
;
824 rAxisUsage
.prepareAutomaticAxisScaling(rAxisUsage
.aAutoScaling
, 1, nAxisIndex
);
826 ExplicitScaleData aExplicitScale
;
827 ExplicitIncrementData aExplicitIncrement
;
828 rAxisUsage
.aAutoScaling
.calculateExplicitScaleAndIncrement( aExplicitScale
, aExplicitIncrement
);
830 rAxisUsage
.setExplicitScaleAndIncrement(0, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
831 rAxisUsage
.setExplicitScaleAndIncrement(1, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
832 rAxisUsage
.setExplicitScaleAndIncrement(2, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
835 AdaptScaleOfYAxisWithoutAttachedSeries( rChartModel
);
838 void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel
& rModel
)
841 for( sal_Int32 nAxisIndex
=0; nAxisIndex
<=m_nMaxAxisIndex
; nAxisIndex
++ )
843 for (auto & axisUsage
: m_aAxisUsageList
)
845 AxisUsage
& rAxisUsage
= axisUsage
.second
;
846 std::vector
< VCoordinateSystem
* > aVCooSysList_Y
= rAxisUsage
.getCoordinateSystems( 1, nAxisIndex
);
847 if( aVCooSysList_Y
.empty() )
850 uno::Reference
< XDiagram
> xDiagram( rModel
.getFirstDiagram() );
854 bool bSeriesAttachedToThisAxis
= false;
855 sal_Int32 nAttachedAxisIndex
= -1;
857 std::vector
< Reference
< XDataSeries
> > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram
) );
858 for (auto const& series
: aSeriesVector
)
860 sal_Int32 nCurrentIndex
= DataSeriesHelper::getAttachedAxisIndex(series
);
861 if( nAxisIndex
== nCurrentIndex
)
863 bSeriesAttachedToThisAxis
= true;
866 else if( nAttachedAxisIndex
<0 || nAttachedAxisIndex
>nCurrentIndex
)
867 nAttachedAxisIndex
=nCurrentIndex
;
871 if (bSeriesAttachedToThisAxis
|| nAttachedAxisIndex
< 0)
874 for(VCoordinateSystem
* nC
: aVCooSysList_Y
)
876 nC
->prepareAutomaticAxisScaling( rAxisUsage
.aAutoScaling
, 1, nAttachedAxisIndex
);
878 ExplicitScaleData aExplicitScaleSource
= nC
->getExplicitScale( 1,nAttachedAxisIndex
);
879 ExplicitIncrementData aExplicitIncrementSource
= nC
->getExplicitIncrement( 1,nAttachedAxisIndex
);
881 ExplicitScaleData aExplicitScaleDest
= nC
->getExplicitScale( 1,nAxisIndex
);
882 ExplicitIncrementData aExplicitIncrementDest
= nC
->getExplicitIncrement( 1,nAxisIndex
);
884 aExplicitScaleDest
.Orientation
= aExplicitScaleSource
.Orientation
;
885 aExplicitScaleDest
.Scaling
= aExplicitScaleSource
.Scaling
;
886 aExplicitScaleDest
.AxisType
= aExplicitScaleSource
.AxisType
;
888 aExplicitIncrementDest
.BaseValue
= aExplicitIncrementSource
.BaseValue
;
890 ScaleData
aScale( rAxisUsage
.aAutoScaling
.getScale() );
891 if( !aScale
.Minimum
.hasValue() )
893 bool bNewMinOK
= true;
895 if( aScale
.Maximum
>>= fMax
)
896 bNewMinOK
= (aExplicitScaleSource
.Minimum
<= fMax
);
898 aExplicitScaleDest
.Minimum
= aExplicitScaleSource
.Minimum
;
901 aExplicitIncrementDest
.BaseValue
= aExplicitScaleDest
.Minimum
;
903 if( !aScale
.Maximum
.hasValue() )
905 bool bNewMaxOK
= true;
907 if( aScale
.Minimum
>>= fMin
)
908 bNewMaxOK
= (fMin
<= aExplicitScaleSource
.Maximum
);
910 aExplicitScaleDest
.Maximum
= aExplicitScaleSource
.Maximum
;
912 if( !aScale
.Origin
.hasValue() )
913 aExplicitScaleDest
.Origin
= aExplicitScaleSource
.Origin
;
915 if( !aScale
.IncrementData
.Distance
.hasValue() )
916 aExplicitIncrementDest
.Distance
= aExplicitIncrementSource
.Distance
;
918 bool bAutoMinorInterval
= true;
919 if( aScale
.IncrementData
.SubIncrements
.getLength() )
920 bAutoMinorInterval
= !( aScale
.IncrementData
.SubIncrements
[0].IntervalCount
.hasValue() );
921 if( bAutoMinorInterval
)
923 if( !aExplicitIncrementDest
.SubIncrements
.empty() && !aExplicitIncrementSource
.SubIncrements
.empty() )
924 aExplicitIncrementDest
.SubIncrements
[0].IntervalCount
=
925 aExplicitIncrementSource
.SubIncrements
[0].IntervalCount
;
928 nC
->setExplicitScaleAndIncrement( 1, nAxisIndex
, aExplicitScaleDest
, aExplicitIncrementDest
);
933 if( AxisHelper::isAxisPositioningEnabled() )
935 //correct origin for y main axis (the origin is where the other main axis crosses)
936 sal_Int32 nAxisIndex
=0;
937 sal_Int32 nDimensionIndex
=1;
938 for (auto & axisUsage
: m_aAxisUsageList
)
940 AxisUsage
& rAxisUsage
= axisUsage
.second
;
941 std::vector
< VCoordinateSystem
* > aVCooSysList
= rAxisUsage
.getCoordinateSystems(nDimensionIndex
,nAxisIndex
);
943 for( nC
=0; nC
< aVCooSysList
.size(); nC
++)
945 ExplicitScaleData
aExplicitScale( aVCooSysList
[nC
]->getExplicitScale( nDimensionIndex
, nAxisIndex
) );
946 ExplicitIncrementData
aExplicitIncrement( aVCooSysList
[nC
]->getExplicitIncrement( nDimensionIndex
, nAxisIndex
) );
948 Reference
< chart2::XCoordinateSystem
> xCooSys( aVCooSysList
[nC
]->getModel() );
949 Reference
< XAxis
> xAxis( xCooSys
->getAxisByDimension( nDimensionIndex
, nAxisIndex
) );
950 Reference
< beans::XPropertySet
> xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis
, xCooSys
), uno::UNO_QUERY
);
952 css::chart::ChartAxisPosition
eCrossingMainAxisPos( css::chart::ChartAxisPosition_ZERO
);
953 if( xCrossingMainAxis
.is() )
955 xCrossingMainAxis
->getPropertyValue("CrossoverPosition") >>= eCrossingMainAxisPos
;
956 if( eCrossingMainAxisPos
== css::chart::ChartAxisPosition_VALUE
)
959 xCrossingMainAxis
->getPropertyValue("CrossoverValue") >>= fValue
;
960 aExplicitScale
.Origin
= fValue
;
962 else if( eCrossingMainAxisPos
== css::chart::ChartAxisPosition_ZERO
)
963 aExplicitScale
.Origin
= 0.0;
964 else if( eCrossingMainAxisPos
== css::chart::ChartAxisPosition_START
)
965 aExplicitScale
.Origin
= aExplicitScale
.Minimum
;
966 else if( eCrossingMainAxisPos
== css::chart::ChartAxisPosition_END
)
967 aExplicitScale
.Origin
= aExplicitScale
.Maximum
;
970 aVCooSysList
[nC
]->setExplicitScaleAndIncrement( nDimensionIndex
, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
976 drawing::Direction3D
SeriesPlotterContainer::getPreferredAspectRatio()
978 drawing::Direction3D
aPreferredAspectRatio(1.0,1.0,1.0);
980 sal_Int32 nPlotterCount
=0;
981 //get a list of all preferred aspect ratios and combine them
982 //first with special demands wins (less or equal zero <-> arbitrary)
985 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: m_aSeriesPlotterList
)
987 drawing::Direction3D
aSingleRatio( aPlotter
->getPreferredDiagramAspectRatio() );
988 if( fx
<0 && aSingleRatio
.DirectionX
>0 )
989 fx
= aSingleRatio
.DirectionX
;
991 if( fy
<0 && aSingleRatio
.DirectionY
>0 )
993 if( fx
>0 && aSingleRatio
.DirectionX
>0 )
994 fy
= fx
*aSingleRatio
.DirectionY
/aSingleRatio
.DirectionX
;
995 else if( fz
>0 && aSingleRatio
.DirectionZ
>0 )
996 fy
= fz
*aSingleRatio
.DirectionY
/aSingleRatio
.DirectionZ
;
998 fy
= aSingleRatio
.DirectionY
;
1001 if( fz
<0 && aSingleRatio
.DirectionZ
>0 )
1003 if( fx
>0 && aSingleRatio
.DirectionX
>0 )
1004 fz
= fx
*aSingleRatio
.DirectionZ
/aSingleRatio
.DirectionX
;
1005 else if( fy
>0 && aSingleRatio
.DirectionY
>0 )
1006 fz
= fy
*aSingleRatio
.DirectionZ
/aSingleRatio
.DirectionY
;
1008 fz
= aSingleRatio
.DirectionZ
;
1011 if( fx
>0 && fy
>0 && fz
>0 )
1015 aPreferredAspectRatio
= drawing::Direction3D(fx
, fy
, fz
);
1016 return aPreferredAspectRatio
;
1021 struct CreateShapeParam2D
1023 css::awt::Rectangle maRemainingSpace
;
1025 std::shared_ptr
<SeriesPlotterContainer
> mpSeriesPlotterContainer
;
1027 std::shared_ptr
<VTitle
> mpVTitleX
;
1028 std::shared_ptr
<VTitle
> mpVTitleY
;
1029 std::shared_ptr
<VTitle
> mpVTitleZ
;
1031 std::shared_ptr
<VTitle
> mpVTitleSecondX
;
1032 std::shared_ptr
<VTitle
> mpVTitleSecondY
;
1034 css::uno::Reference
<css::drawing::XShape
> mxMarkHandles
;
1035 css::uno::Reference
<css::drawing::XShape
> mxPlotAreaWithAxes
;
1037 css::uno::Reference
<css::drawing::XShapes
> mxDiagramWithAxesShapes
;
1039 bool mbAutoPosTitleX
;
1040 bool mbAutoPosTitleY
;
1041 bool mbAutoPosTitleZ
;
1043 bool mbAutoPosSecondTitleX
;
1044 bool mbAutoPosSecondTitleY
;
1046 bool mbUseFixedInnerSize
;
1048 CreateShapeParam2D() :
1049 mbAutoPosTitleX(true),
1050 mbAutoPosTitleY(true),
1051 mbAutoPosTitleZ(true),
1052 mbAutoPosSecondTitleX(true),
1053 mbAutoPosSecondTitleY(true),
1054 mbUseFixedInnerSize(false) {}
1057 class GL2DRenderer
: public IRenderer
1060 explicit GL2DRenderer(ChartView
* pView
);
1061 virtual ~GL2DRenderer() override
;
1063 virtual void update() override
;
1064 virtual void clickedAt(const Point
& rPos
, sal_uInt16 nButton
) override
;
1065 virtual void mouseDragMove(const Point
& rBegin
, const Point
& rEnd
, sal_uInt16 nButton
) override
;
1066 virtual void scroll(long nDelta
) override
;
1067 virtual void contextDestroyed() override
;
1069 #if HAVE_FEATURE_OPENGL
1070 const OpenGLWindow
* getOpenGLWindow() const;
1071 void updateOpenGLWindow();
1075 bool mbContextDestroyed
;
1076 #if HAVE_FEATURE_OPENGL
1077 VclPtr
<OpenGLWindow
> mpWindow
;
1081 GL2DRenderer::GL2DRenderer(ChartView
* pView
)
1083 , mbContextDestroyed(false)
1084 #if HAVE_FEATURE_OPENGL
1085 , mpWindow(mpView
->mrChartModel
.getOpenGLWindow())
1090 GL2DRenderer::~GL2DRenderer()
1092 #if HAVE_FEATURE_OPENGL
1094 if(!mbContextDestroyed
&& mpWindow
)
1095 mpWindow
->setRenderer(nullptr);
1100 void GL2DRenderer::update()
1106 void GL2DRenderer::clickedAt(const Point
&, sal_uInt16
)
1110 void GL2DRenderer::mouseDragMove(const Point
& , const Point
& , sal_uInt16
)
1114 void GL2DRenderer::scroll(long )
1118 void GL2DRenderer::contextDestroyed()
1120 mbContextDestroyed
= true;
1123 #if HAVE_FEATURE_OPENGL
1125 const OpenGLWindow
* GL2DRenderer::getOpenGLWindow() const
1130 void GL2DRenderer::updateOpenGLWindow()
1132 if(mbContextDestroyed
)
1135 OpenGLWindow
* pWindow
= mpView
->mrChartModel
.getOpenGLWindow();
1136 if(pWindow
!= mpWindow
)
1140 mpWindow
->setRenderer(nullptr);
1145 pWindow
->setRenderer(this);
1153 const uno::Sequence
<sal_Int8
>& ExplicitValueProvider::getUnoTunnelId()
1155 return theExplicitValueProviderUnoTunnelId::get().getSeq();
1158 ExplicitValueProvider
* ExplicitValueProvider::getExplicitValueProvider(
1159 const Reference
< uno::XInterface
>& xChartView
)
1161 ExplicitValueProvider
* pExplicitValueProvider
=nullptr;
1163 Reference
< lang::XUnoTunnel
> xTunnel( xChartView
, uno::UNO_QUERY
);
1166 pExplicitValueProvider
= reinterpret_cast<ExplicitValueProvider
*>(xTunnel
->getSomething(
1167 ExplicitValueProvider::getUnoTunnelId() ));
1169 return pExplicitValueProvider
;
1172 ChartView::ChartView(
1173 uno::Reference
<uno::XComponentContext
> const & xContext
,
1177 , mrChartModel(rModel
)
1180 , m_pDrawModelWrapper()
1181 , m_aListenerContainer( m_aMutex
)
1182 , m_bViewDirty(true)
1183 , m_bInViewUpdate(false)
1184 , m_bViewUpdatePending(false)
1185 , m_bRefreshAddIn(true)
1186 , m_aPageResolution(1000,1000)
1187 , m_bPointsWereSkipped(false)
1188 , m_nScaleXNumerator(1)
1189 , m_nScaleXDenominator(1)
1190 , m_nScaleYNumerator(1)
1191 , m_nScaleYDenominator(1)
1192 , m_bSdrViewIsInEditMode(false)
1193 , m_aResultingDiagramRectangleExcludingAxes(0,0,0,0)
1194 , mp2DRenderer(new GL2DRenderer(this))
1199 void ChartView::init()
1201 if( !m_pDrawModelWrapper
.get() )
1203 SolarMutexGuard aSolarGuard
;
1204 m_pDrawModelWrapper
= std::make_shared
< DrawModelWrapper
>();
1205 m_xShapeFactory
= m_pDrawModelWrapper
->getShapeFactory();
1206 m_xDrawPage
= m_pDrawModelWrapper
->getMainDrawPage();
1207 StartListening( m_pDrawModelWrapper
->getSdrModel() );
1211 void SAL_CALL
ChartView::initialize( const uno::Sequence
< uno::Any
>& )
1216 ChartView::~ChartView()
1218 maTimeBased
.maTimer
.Stop();
1219 // #i120831#. In ChartView::initialize(), m_xShapeFactory is created from SdrModel::getUnoModel() and indirectly
1220 // from SfxBaseModel, it needs call dispose() to make sure SfxBaseModel object is freed correctly.
1221 uno::Reference
< lang::XComponent
> xComp( m_xShapeFactory
, uno::UNO_QUERY
);
1225 if( m_pDrawModelWrapper
.get() )
1227 SolarMutexGuard aSolarGuard
;
1228 EndListening( m_pDrawModelWrapper
->getSdrModel() );
1229 m_pDrawModelWrapper
.reset();
1231 m_xDrawPage
= nullptr;
1232 impl_deleteCoordinateSystems();
1235 void ChartView::impl_deleteCoordinateSystems()
1237 //delete all coordinate systems
1238 std::vector
< VCoordinateSystem
* > aVectorToDeleteObjects
;
1239 std::swap( aVectorToDeleteObjects
, m_aVCooSysList
);//#i109770#
1240 for (auto const& elem
: aVectorToDeleteObjects
)
1244 aVectorToDeleteObjects
.clear();
1247 // datatransfer::XTransferable
1250 const OUString
lcl_aGDIMetaFileMIMEType(
1251 "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" );
1252 const OUString
lcl_aGDIMetaFileMIMETypeHighContrast(
1253 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" );
1254 } // anonymous namespace
1256 void ChartView::getMetaFile( const uno::Reference
< io::XOutputStream
>& xOutStream
1257 , bool bUseHighContrast
)
1259 if( !m_xDrawPage
.is() )
1262 // creating the graphic exporter
1263 uno::Reference
< drawing::XGraphicExportFilter
> xExporter
= drawing::GraphicExportFilter::create( m_xCC
);
1265 uno::Sequence
< beans::PropertyValue
> aProps(3);
1266 aProps
[0].Name
= "FilterName";
1267 aProps
[0].Value
<<= OUString("SVM");
1269 aProps
[1].Name
= "OutputStream";
1270 aProps
[1].Value
<<= xOutStream
;
1272 uno::Sequence
< beans::PropertyValue
> aFilterData(8);
1273 aFilterData
[0].Name
= "ExportOnlyBackground";
1274 aFilterData
[0].Value
<<= false;
1275 aFilterData
[1].Name
= "HighContrast";
1276 aFilterData
[1].Value
<<= bUseHighContrast
;
1278 aFilterData
[2].Name
= "Version";
1279 const sal_Int32 nVersion
= SOFFICE_FILEFORMAT_50
;
1280 aFilterData
[2].Value
<<= nVersion
;
1282 aFilterData
[3].Name
= "CurrentPage";
1283 aFilterData
[3].Value
<<= uno::Reference
< uno::XInterface
>( m_xDrawPage
, uno::UNO_QUERY
);
1285 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
1286 aFilterData
[4].Name
= "ScaleXNumerator";
1287 aFilterData
[4].Value
<<= m_nScaleXNumerator
;
1288 aFilterData
[5].Name
= "ScaleXDenominator";
1289 aFilterData
[5].Value
<<= m_nScaleXDenominator
;
1290 aFilterData
[6].Name
= "ScaleYNumerator";
1291 aFilterData
[6].Value
<<= m_nScaleYNumerator
;
1292 aFilterData
[7].Name
= "ScaleYDenominator";
1293 aFilterData
[7].Value
<<= m_nScaleYDenominator
;
1296 aProps
[2].Name
= "FilterData";
1297 aProps
[2].Value
<<= aFilterData
;
1299 xExporter
->setSourceDocument( uno::Reference
< lang::XComponent
>( m_xDrawPage
, uno::UNO_QUERY
) );
1300 if( xExporter
->filter( aProps
) )
1302 xOutStream
->flush();
1303 xOutStream
->closeOutput();
1304 uno::Reference
< io::XSeekable
> xSeekable( xOutStream
, uno::UNO_QUERY
);
1305 if( xSeekable
.is() )
1310 uno::Any SAL_CALL
ChartView::getTransferData( const datatransfer::DataFlavor
& aFlavor
)
1312 bool bHighContrastMetaFile( aFlavor
.MimeType
== lcl_aGDIMetaFileMIMETypeHighContrast
);
1314 if( ! (bHighContrastMetaFile
|| aFlavor
.MimeType
== lcl_aGDIMetaFileMIMEType
) )
1319 SvMemoryStream
aStream( 1024, 1024 );
1320 utl::OStreamWrapper
* pStreamWrapper
= new utl::OStreamWrapper( aStream
);
1322 uno::Reference
< io::XOutputStream
> xOutStream( pStreamWrapper
);
1323 uno::Reference
< io::XInputStream
> xInStream( pStreamWrapper
);
1324 uno::Reference
< io::XSeekable
> xSeekable( pStreamWrapper
);
1326 if( xOutStream
.is() )
1328 this->getMetaFile( xOutStream
, bHighContrastMetaFile
);
1330 if( xInStream
.is() && xSeekable
.is() )
1333 sal_Int32 nBytesToRead
= xInStream
->available();
1334 uno::Sequence
< sal_Int8
> aSeq( nBytesToRead
);
1335 xInStream
->readBytes( aSeq
, nBytesToRead
);
1337 xInStream
->closeInput();
1343 uno::Sequence
< datatransfer::DataFlavor
> SAL_CALL
ChartView::getTransferDataFlavors()
1345 uno::Sequence
< datatransfer::DataFlavor
> aRet(2);
1347 aRet
[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType
,
1349 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
1350 aRet
[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast
,
1352 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
1356 sal_Bool SAL_CALL
ChartView::isDataFlavorSupported( const datatransfer::DataFlavor
& aFlavor
)
1358 return ( aFlavor
.MimeType
== lcl_aGDIMetaFileMIMEType
||
1359 aFlavor
.MimeType
== lcl_aGDIMetaFileMIMETypeHighContrast
);
1362 // ____ XUnoTunnel ___
1363 ::sal_Int64 SAL_CALL
ChartView::getSomething( const uno::Sequence
< ::sal_Int8
>& aIdentifier
)
1365 if( aIdentifier
.getLength() == 16 && memcmp( ExplicitValueProvider::getUnoTunnelId().getConstArray(),
1366 aIdentifier
.getConstArray(), 16 ) == 0 )
1368 ExplicitValueProvider
* pProvider
= this;
1369 return reinterpret_cast<sal_Int64
>(pProvider
);
1374 // lang::XServiceInfo
1376 OUString SAL_CALL
ChartView::getImplementationName()
1378 return OUString(CHART_VIEW_SERVICE_IMPLEMENTATION_NAME
);
1381 sal_Bool SAL_CALL
ChartView::supportsService( const OUString
& rServiceName
)
1383 return cppu::supportsService(this, rServiceName
);
1386 css::uno::Sequence
< OUString
> SAL_CALL
ChartView::getSupportedServiceNames()
1388 return { CHART_VIEW_SERVICE_NAME
};
1391 ::basegfx::B3DHomMatrix
createTransformationSceneToScreen(
1392 const ::basegfx::B2IRectangle
& rDiagramRectangleWithoutAxes
)
1394 ::basegfx::B3DHomMatrix aM
;
1395 aM
.scale(double(rDiagramRectangleWithoutAxes
.getWidth())/FIXED_SIZE_FOR_3D_CHART_VOLUME
1396 , -double(rDiagramRectangleWithoutAxes
.getHeight())/FIXED_SIZE_FOR_3D_CHART_VOLUME
, 1.0 );
1397 aM
.translate(double(rDiagramRectangleWithoutAxes
.getMinX())
1398 , double(rDiagramRectangleWithoutAxes
.getMinY()+rDiagramRectangleWithoutAxes
.getHeight()-1), 0);
1405 bool lcl_IsPieOrDonut( const uno::Reference
< XDiagram
>& xDiagram
)
1407 //special treatment for pie charts
1408 //the size is checked after complete creation to get the datalabels into the given space
1410 //todo: this is just a workaround at the moment for pie and donut labels
1411 return DiagramHelper::isPieOrDonutChart( xDiagram
);
1414 void lcl_setDefaultWritingMode( const std::shared_ptr
< DrawModelWrapper
>& pDrawModelWrapper
, ChartModel
& rModel
)
1416 //get writing mode from parent document:
1417 if( SvtLanguageOptions().IsCTLFontEnabled() )
1421 sal_Int16 nWritingMode
=-1;
1422 uno::Reference
< beans::XPropertySet
> xParentProps( rModel
.getParent(), uno::UNO_QUERY
);
1423 uno::Reference
< style::XStyleFamiliesSupplier
> xStyleFamiliesSupplier( xParentProps
, uno::UNO_QUERY
);
1424 if( xStyleFamiliesSupplier
.is() )
1426 uno::Reference
< container::XNameAccess
> xStylesFamilies( xStyleFamiliesSupplier
->getStyleFamilies() );
1427 if( xStylesFamilies
.is() )
1429 if( !xStylesFamilies
->hasByName( "PageStyles" ) )
1431 //draw/impress is parent document
1432 uno::Reference
< lang::XMultiServiceFactory
> xFatcory( xParentProps
, uno::UNO_QUERY
);
1435 uno::Reference
< beans::XPropertySet
> xDrawDefaults( xFatcory
->createInstance( "com.sun.star.drawing.Defaults" ), uno::UNO_QUERY
);
1436 if( xDrawDefaults
.is() )
1437 xDrawDefaults
->getPropertyValue( "WritingMode" ) >>= nWritingMode
;
1442 uno::Reference
< container::XNameAccess
> xPageStyles( xStylesFamilies
->getByName( "PageStyles" ), uno::UNO_QUERY
);
1443 if( xPageStyles
.is() )
1445 OUString aPageStyle
;
1447 uno::Reference
< text::XTextDocument
> xTextDocument( xParentProps
, uno::UNO_QUERY
);
1448 if( xTextDocument
.is() )
1450 //writer is parent document
1451 //retrieve the current page style from the text cursor property PageStyleName
1453 uno::Reference
< text::XTextEmbeddedObjectsSupplier
> xTextEmbeddedObjectsSupplier( xTextDocument
, uno::UNO_QUERY
);
1454 if( xTextEmbeddedObjectsSupplier
.is() )
1456 uno::Reference
< container::XNameAccess
> xEmbeddedObjects( xTextEmbeddedObjectsSupplier
->getEmbeddedObjects() );
1457 if( xEmbeddedObjects
.is() )
1459 uno::Sequence
< OUString
> aNames( xEmbeddedObjects
->getElementNames() );
1461 sal_Int32 nCount
= aNames
.getLength();
1462 for( sal_Int32 nN
=0; nN
<nCount
; nN
++ )
1464 uno::Reference
< beans::XPropertySet
> xEmbeddedProps( xEmbeddedObjects
->getByName( aNames
[nN
] ), uno::UNO_QUERY
);
1465 if( xEmbeddedProps
.is() )
1467 static OUString aChartCLSID
= SvGlobalName( SO3_SCH_CLASSID
).GetHexName();
1469 xEmbeddedProps
->getPropertyValue( "CLSID" ) >>= aCLSID
;
1470 if( aCLSID
== aChartCLSID
)
1472 uno::Reference
< text::XTextContent
> xEmbeddedObject( xEmbeddedProps
, uno::UNO_QUERY
);
1473 if( xEmbeddedObject
.is() )
1475 uno::Reference
< text::XTextRange
> xAnchor( xEmbeddedObject
->getAnchor() );
1478 uno::Reference
< beans::XPropertySet
> xAnchorProps( xAnchor
, uno::UNO_QUERY
);
1479 if( xAnchorProps
.is() )
1481 xAnchorProps
->getPropertyValue( "WritingMode" ) >>= nWritingMode
;
1483 uno::Reference
< text::XText
> xText( xAnchor
->getText() );
1486 uno::Reference
< beans::XPropertySet
> xTextCursorProps( xText
->createTextCursor(), uno::UNO_QUERY
);
1487 if( xTextCursorProps
.is() )
1488 xTextCursorProps
->getPropertyValue( "PageStyleName" ) >>= aPageStyle
;
1498 if( aPageStyle
.isEmpty() )
1500 uno::Reference
< text::XText
> xText( xTextDocument
->getText() );
1503 uno::Reference
< beans::XPropertySet
> xTextCursorProps( xText
->createTextCursor(), uno::UNO_QUERY
);
1504 if( xTextCursorProps
.is() )
1505 xTextCursorProps
->getPropertyValue( "PageStyleName" ) >>= aPageStyle
;
1511 //Calc is parent document
1512 xParentProps
->getPropertyValue( "PageStyle" ) >>= aPageStyle
;
1513 if(aPageStyle
.isEmpty())
1514 aPageStyle
= "Default";
1516 if( nWritingMode
== -1 || nWritingMode
== text::WritingMode2::PAGE
)
1518 uno::Reference
< beans::XPropertySet
> xPageStyle( xPageStyles
->getByName( aPageStyle
), uno::UNO_QUERY
);
1519 if( xPageStyle
.is() )
1520 xPageStyle
->getPropertyValue( "WritingMode" ) >>= nWritingMode
;
1526 if( nWritingMode
!= -1 && nWritingMode
!= text::WritingMode2::PAGE
)
1528 if( pDrawModelWrapper
.get() )
1529 pDrawModelWrapper
->GetItemPool().SetPoolDefaultItem(SvxFrameDirectionItem(static_cast<SvxFrameDirection
>(nWritingMode
), EE_PARA_WRITINGDIR
) );
1532 catch( const uno::Exception
& )
1534 DBG_UNHANDLED_EXCEPTION("chart2" );
1539 sal_Int16
lcl_getDefaultWritingModeFromPool( const std::shared_ptr
<DrawModelWrapper
>& pDrawModelWrapper
)
1541 sal_Int16 nWritingMode
= text::WritingMode2::LR_TB
;
1542 if(!pDrawModelWrapper
)
1543 return nWritingMode
;
1545 const SfxPoolItem
* pItem
= &(pDrawModelWrapper
->GetItemPool().GetDefaultItem( EE_PARA_WRITINGDIR
));
1547 nWritingMode
= static_cast< sal_Int16
>(static_cast< const SvxFrameDirectionItem
* >( pItem
)->GetValue());
1548 return nWritingMode
;
1551 } //end anonymous namespace
1553 awt::Rectangle
ChartView::impl_createDiagramAndContent( const CreateShapeParam2D
& rParam
, const awt::Size
& rPageSize
)
1555 //return the used rectangle
1556 awt::Rectangle
aUsedOuterRect(rParam
.maRemainingSpace
.X
, rParam
.maRemainingSpace
.Y
, 0, 0);
1558 uno::Reference
< XDiagram
> xDiagram( mrChartModel
.getFirstDiagram() );
1560 return aUsedOuterRect
;
1562 sal_Int32 nDimensionCount
= DiagramHelper::getDimension( xDiagram
);
1563 if(!nDimensionCount
)
1565 //@todo handle mixed dimension
1566 nDimensionCount
= 2;
1569 basegfx::B2IRectangle aAvailableOuterRect
= BaseGFXHelper::makeRectangle(rParam
.maRemainingSpace
);
1571 const std::vector
< VCoordinateSystem
* >& rVCooSysList( rParam
.mpSeriesPlotterContainer
->getCooSysList() );
1572 SeriesPlottersType
& rSeriesPlotterList
= rParam
.mpSeriesPlotterContainer
->getSeriesPlotterList();
1574 //create VAxis, so they can give necessary information for automatic scaling
1575 uno::Reference
<chart2::XChartDocument
> const xChartDoc(&mrChartModel
);
1576 uno::Reference
<util::XNumberFormatsSupplier
> const xNumberFormatsSupplier(
1577 mrChartModel
.getNumberFormatsSupplier());
1579 for( nC
=0; nC
< rVCooSysList
.size(); nC
++)
1581 VCoordinateSystem
* pVCooSys
= rVCooSysList
[nC
];
1582 if(nDimensionCount
==3)
1584 uno::Reference
<beans::XPropertySet
> xSceneProperties( xDiagram
, uno::UNO_QUERY
);
1585 CuboidPlanePosition
eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xSceneProperties
) );
1586 CuboidPlanePosition
eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xSceneProperties
) );
1587 CuboidPlanePosition
eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xSceneProperties
) );
1588 pVCooSys
->set3DWallPositions( eLeftWallPos
, eBackWallPos
, eBottomPos
);
1591 pVCooSys
->createVAxisList(xChartDoc
, rPageSize
, rParam
.maRemainingSpace
, rParam
.mbUseFixedInnerSize
);
1594 // - prepare list of all axis and how they are used
1595 Date aNullDate
= NumberFormatterWrapper( xNumberFormatsSupplier
).getNullDate();
1596 rParam
.mpSeriesPlotterContainer
->initAxisUsageList(aNullDate
);
1597 rParam
.mpSeriesPlotterContainer
->doAutoScaling( mrChartModel
);
1598 rParam
.mpSeriesPlotterContainer
->setScalesFromCooSysToPlotter();
1599 rParam
.mpSeriesPlotterContainer
->setNumberFormatsFromAxes();
1604 drawing::Direction3D aPreferredAspectRatio
=
1605 rParam
.mpSeriesPlotterContainer
->getPreferredAspectRatio();
1607 uno::Reference
< drawing::XShapes
> xSeriesTargetInFrontOfAxis(nullptr);
1608 uno::Reference
< drawing::XShapes
> xSeriesTargetBehindAxis(nullptr);
1609 VDiagram
aVDiagram(xDiagram
, aPreferredAspectRatio
, nDimensionCount
);
1610 bool bIsPieOrDonut
= lcl_IsPieOrDonut(xDiagram
);
1612 aVDiagram
.init(rParam
.mxDiagramWithAxesShapes
, m_xShapeFactory
);
1613 aVDiagram
.createShapes(
1614 awt::Point(rParam
.maRemainingSpace
.X
, rParam
.maRemainingSpace
.Y
),
1615 awt::Size(rParam
.maRemainingSpace
.Width
, rParam
.maRemainingSpace
.Height
));
1617 xSeriesTargetInFrontOfAxis
= aVDiagram
.getCoordinateRegion();
1618 // It is preferable to use full size than minimum for pie charts
1619 if (!bIsPieOrDonut
&& !rParam
.mbUseFixedInnerSize
)
1620 aVDiagram
.reduceToMimimumSize();
1623 uno::Reference
< drawing::XShapes
> xTextTargetShapes
=
1624 AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory
)->createGroup2D(rParam
.mxDiagramWithAxesShapes
);
1626 // - create axis and grids for all coordinate systems
1628 //init all coordinate systems
1629 for( nC
=0; nC
< rVCooSysList
.size(); nC
++)
1631 VCoordinateSystem
* pVCooSys
= rVCooSysList
[nC
];
1632 pVCooSys
->initPlottingTargets(xSeriesTargetInFrontOfAxis
,xTextTargetShapes
,m_xShapeFactory
,xSeriesTargetBehindAxis
);
1634 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1635 createTransformationSceneToScreen( aVDiagram
.getCurrentRectangle() ) ));
1637 pVCooSys
->initVAxisInList();
1640 //calculate resulting size respecting axis label layout and fontscaling
1642 uno::Reference
< drawing::XShape
> xBoundingShape(rParam
.mxDiagramWithAxesShapes
, uno::UNO_QUERY
);
1643 ::basegfx::B2IRectangle aConsumedOuterRect
;
1645 //use first coosys only so far; todo: calculate for more than one coosys if we have more in future
1646 //todo: this is just a workaround at the moment for pie and donut labels
1647 if( !bIsPieOrDonut
&& (!rVCooSysList
.empty()) )
1649 VCoordinateSystem
* pVCooSys
= rVCooSysList
[0];
1650 pVCooSys
->createMaximumAxesLabels();
1652 aConsumedOuterRect
= AbstractShapeFactory::getRectangleOfShape(xBoundingShape
);
1653 ::basegfx::B2IRectangle
aNewInnerRect( aVDiagram
.getCurrentRectangle() );
1654 if (!rParam
.mbUseFixedInnerSize
)
1655 aNewInnerRect
= aVDiagram
.adjustInnerSize( aConsumedOuterRect
);
1657 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1658 createTransformationSceneToScreen( aNewInnerRect
) ));
1660 //redo autoscaling to get size and text dependent automatic main increment count
1661 rParam
.mpSeriesPlotterContainer
->doAutoScaling( mrChartModel
);
1662 rParam
.mpSeriesPlotterContainer
->updateScalesAndIncrementsOnAxes();
1663 rParam
.mpSeriesPlotterContainer
->setScalesFromCooSysToPlotter();
1665 pVCooSys
->createAxesLabels();
1667 bool bLessSpaceConsumedThanExpected
= false;
1669 aConsumedOuterRect
= AbstractShapeFactory::getRectangleOfShape(xBoundingShape
);
1670 if( aConsumedOuterRect
.getMinX() > aAvailableOuterRect
.getMinX()
1671 || aConsumedOuterRect
.getMaxX() < aAvailableOuterRect
.getMaxX()
1672 || aConsumedOuterRect
.getMinY() > aAvailableOuterRect
.getMinY()
1673 || aConsumedOuterRect
.getMinY() < aAvailableOuterRect
.getMaxY() )
1674 bLessSpaceConsumedThanExpected
= true;
1677 if (bLessSpaceConsumedThanExpected
&& !rParam
.mbUseFixedInnerSize
)
1679 aVDiagram
.adjustInnerSize( aConsumedOuterRect
);
1680 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1681 createTransformationSceneToScreen( aVDiagram
.getCurrentRectangle() ) ));
1683 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
1686 //create axes and grids for the final size
1687 for( nC
=0; nC
< rVCooSysList
.size(); nC
++)
1689 VCoordinateSystem
* pVCooSys
= rVCooSysList
[nC
];
1691 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1692 createTransformationSceneToScreen( aVDiagram
.getCurrentRectangle() ) ));
1694 pVCooSys
->createAxesShapes();
1695 pVCooSys
->createGridShapes();
1698 // - create data series for all charttypes
1699 m_bPointsWereSkipped
= false;
1700 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1702 VSeriesPlotter
* pSeriesPlotter
= aPlotter
.get();
1703 uno::Reference
< drawing::XShapes
> xSeriesTarget(nullptr);
1704 if( pSeriesPlotter
->WantToPlotInFrontOfAxisLine() )
1705 xSeriesTarget
= xSeriesTargetInFrontOfAxis
;
1708 xSeriesTarget
= xSeriesTargetBehindAxis
;
1709 OSL_ENSURE( !bIsPieOrDonut
, "not implemented yet! - during a complete recreation this shape is destroyed so no series can be created anymore" );
1711 pSeriesPlotter
->initPlotter( xSeriesTarget
,xTextTargetShapes
,m_xShapeFactory
,OUString() );
1712 pSeriesPlotter
->setPageReferenceSize( rPageSize
);
1713 VCoordinateSystem
* pVCooSys
= lcl_getCooSysForPlotter( rVCooSysList
, pSeriesPlotter
);
1714 if(nDimensionCount
==2)
1715 pSeriesPlotter
->setTransformationSceneToScreen( pVCooSys
->getTransformationSceneToScreen() );
1716 //better performance for big data
1718 //calculate resolution for coordinate system
1719 Sequence
<sal_Int32
> aCoordinateSystemResolution
= pVCooSys
->getCoordinateSystemResolution( rPageSize
, m_aPageResolution
);
1720 pSeriesPlotter
->setCoordinateSystemResolution( aCoordinateSystemResolution
);
1723 pSeriesPlotter
->createShapes();
1724 m_bPointsWereSkipped
= m_bPointsWereSkipped
|| pSeriesPlotter
->PointsWereSkipped();
1727 //recreate all with corrected sizes if requested
1730 m_bPointsWereSkipped
= false;
1732 aConsumedOuterRect
= ::basegfx::B2IRectangle( AbstractShapeFactory::getRectangleOfShape(xBoundingShape
) );
1733 ::basegfx::B2IRectangle
aNewInnerRect( aVDiagram
.getCurrentRectangle() );
1734 if (!rParam
.mbUseFixedInnerSize
)
1735 aNewInnerRect
= aVDiagram
.adjustInnerSize( aConsumedOuterRect
);
1737 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1739 aPlotter
->releaseShapes();
1742 //clear and recreate
1743 AbstractShapeFactory::removeSubShapes( xSeriesTargetInFrontOfAxis
); //xSeriesTargetBehindAxis is a sub shape of xSeriesTargetInFrontOfAxis and will be removed here
1744 xSeriesTargetBehindAxis
.clear();
1745 AbstractShapeFactory::removeSubShapes( xTextTargetShapes
);
1747 //set new transformation
1748 for( nC
=0; nC
< rVCooSysList
.size(); nC
++)
1750 VCoordinateSystem
* pVCooSys
= rVCooSysList
[nC
];
1751 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1752 createTransformationSceneToScreen( aNewInnerRect
) ));
1755 // - create data series for all charttypes
1756 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1758 VCoordinateSystem
* pVCooSys
= lcl_getCooSysForPlotter( rVCooSysList
, aPlotter
.get() );
1759 if(nDimensionCount
==2)
1760 aPlotter
->setTransformationSceneToScreen( pVCooSys
->getTransformationSceneToScreen() );
1761 aPlotter
->createShapes();
1762 m_bPointsWereSkipped
= m_bPointsWereSkipped
|| aPlotter
->PointsWereSkipped();
1765 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1766 aPlotter
->rearrangeLabelToAvoidOverlapIfRequested(rPageSize
);
1769 if (rParam
.mbUseFixedInnerSize
)
1771 aUsedOuterRect
= awt::Rectangle( aConsumedOuterRect
.getMinX(), aConsumedOuterRect
.getMinY(), aConsumedOuterRect
.getWidth(), aConsumedOuterRect
.getHeight() );
1774 aUsedOuterRect
= rParam
.maRemainingSpace
;
1776 bool bSnapRectToUsedArea
= false;
1777 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1779 bSnapRectToUsedArea
= aPlotter
->shouldSnapRectToUsedArea();
1780 if(bSnapRectToUsedArea
)
1783 if(bSnapRectToUsedArea
)
1785 if (rParam
.mbUseFixedInnerSize
)
1786 m_aResultingDiagramRectangleExcludingAxes
= getRectangleOfObject( "PlotAreaExcludingAxes" );
1789 ::basegfx::B2IRectangle aConsumedInnerRect
= aVDiagram
.getCurrentRectangle();
1790 m_aResultingDiagramRectangleExcludingAxes
= awt::Rectangle( aConsumedInnerRect
.getMinX(), aConsumedInnerRect
.getMinY(), aConsumedInnerRect
.getWidth(), aConsumedInnerRect
.getHeight() );
1795 if (rParam
.mbUseFixedInnerSize
)
1796 m_aResultingDiagramRectangleExcludingAxes
= rParam
.maRemainingSpace
;
1799 ::basegfx::B2IRectangle aConsumedInnerRect
= aVDiagram
.getCurrentRectangle();
1800 m_aResultingDiagramRectangleExcludingAxes
= awt::Rectangle( aConsumedInnerRect
.getMinX(), aConsumedInnerRect
.getMinY(), aConsumedInnerRect
.getWidth(), aConsumedInnerRect
.getHeight() );
1804 if (rParam
.mxMarkHandles
.is())
1806 awt::Point
aPos(rParam
.maRemainingSpace
.X
, rParam
.maRemainingSpace
.Y
);
1807 awt::Size
aSize(rParam
.maRemainingSpace
.Width
, rParam
.maRemainingSpace
.Height
);
1809 bool bPosSizeExcludeAxesProperty
= true;
1810 uno::Reference
< beans::XPropertySet
> xDiaProps( xDiagram
, uno::UNO_QUERY_THROW
);
1811 if( xDiaProps
.is() )
1812 xDiaProps
->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxesProperty
;
1813 if (rParam
.mbUseFixedInnerSize
|| bPosSizeExcludeAxesProperty
)
1815 aPos
= awt::Point( m_aResultingDiagramRectangleExcludingAxes
.X
, m_aResultingDiagramRectangleExcludingAxes
.Y
);
1816 aSize
= awt::Size( m_aResultingDiagramRectangleExcludingAxes
.Width
, m_aResultingDiagramRectangleExcludingAxes
.Height
);
1818 rParam
.mxMarkHandles
->setPosition(aPos
);
1819 rParam
.mxMarkHandles
->setSize(aSize
);
1822 return aUsedOuterRect
;
1825 bool ChartView::getExplicitValuesForAxis(
1826 uno::Reference
< XAxis
> xAxis
1827 , ExplicitScaleData
& rExplicitScale
1828 , ExplicitIncrementData
& rExplicitIncrement
)
1835 uno::Reference
< XCoordinateSystem
> xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis
, mrChartModel
.getFirstDiagram() ) );
1836 const VCoordinateSystem
* pVCooSys
= findInCooSysList(m_aVCooSysList
,xCooSys
);
1840 sal_Int32 nDimensionIndex
=-1;
1841 sal_Int32 nAxisIndex
=-1;
1842 if( AxisHelper::getIndicesForAxis( xAxis
, xCooSys
, nDimensionIndex
, nAxisIndex
) )
1844 rExplicitScale
= pVCooSys
->getExplicitScale(nDimensionIndex
,nAxisIndex
);
1845 rExplicitIncrement
= pVCooSys
->getExplicitIncrement(nDimensionIndex
,nAxisIndex
);
1846 if( rExplicitScale
.ShiftedCategoryPosition
)
1848 //remove 'one' from max
1849 if( rExplicitScale
.AxisType
== css::chart2::AxisType::DATE
)
1851 Date
aMaxDate(rExplicitScale
.NullDate
); aMaxDate
.AddDays(::rtl::math::approxFloor(rExplicitScale
.Maximum
));
1852 //for explicit scales with shifted categories we need one interval more
1853 switch( rExplicitScale
.TimeResolution
)
1855 case css::chart::TimeUnit::DAY
:
1858 case css::chart::TimeUnit::MONTH
:
1859 aMaxDate
= DateHelper::GetDateSomeMonthsAway(aMaxDate
,-1);
1861 case css::chart::TimeUnit::YEAR
:
1862 aMaxDate
= DateHelper::GetDateSomeYearsAway(aMaxDate
,-1);
1865 rExplicitScale
.Maximum
= aMaxDate
- rExplicitScale
.NullDate
;
1867 else if( rExplicitScale
.AxisType
== css::chart2::AxisType::CATEGORY
)
1868 rExplicitScale
.Maximum
-= 1.0;
1869 else if( rExplicitScale
.AxisType
== css::chart2::AxisType::SERIES
)
1870 rExplicitScale
.Maximum
-= 1.0;
1877 SdrPage
* ChartView::getSdrPage()
1879 SdrPage
* pPage
=nullptr;
1880 Reference
< lang::XUnoTunnel
> xUnoTunnel(m_xDrawPage
,uno::UNO_QUERY
);
1883 SvxDrawPage
* pSvxDrawPage
= reinterpret_cast<SvxDrawPage
*>(xUnoTunnel
->getSomething(
1884 SvxDrawPage::getUnoTunnelId() ));
1887 pPage
= pSvxDrawPage
->GetSdrPage();
1893 uno::Reference
< drawing::XShape
> ChartView::getShapeForCID( const OUString
& rObjectCID
)
1895 SolarMutexGuard aSolarGuard
;
1896 SdrObject
* pObj
= DrawModelWrapper::getNamedSdrObject( rObjectCID
, this->getSdrPage() );
1898 return uno::Reference
< drawing::XShape
>( pObj
->getUnoShape(), uno::UNO_QUERY
);
1902 awt::Rectangle
ChartView::getDiagramRectangleExcludingAxes()
1905 return m_aResultingDiagramRectangleExcludingAxes
;
1908 awt::Rectangle
ChartView::getRectangleOfObject( const OUString
& rObjectCID
, bool bSnapRect
)
1912 awt::Rectangle aRet
;
1913 uno::Reference
< drawing::XShape
> xShape( getShapeForCID(rObjectCID
) );
1916 //special handling for axis for old api:
1917 //same special handling for diagram
1918 ObjectType
eObjectType( ObjectIdentifier::getObjectType( rObjectCID
) );
1919 if( eObjectType
== OBJECTTYPE_AXIS
|| eObjectType
== OBJECTTYPE_DIAGRAM
)
1921 SolarMutexGuard aSolarGuard
;
1922 SvxShape
* pRoot
= SvxShape::getImplementation( xShape
);
1925 SdrObject
* pRootSdrObject
= pRoot
->GetSdrObject();
1926 if( pRootSdrObject
)
1928 SdrObjList
* pRootList
= pRootSdrObject
->GetSubList();
1931 OUString aShapeName
= "MarkHandles";
1932 if( eObjectType
== OBJECTTYPE_DIAGRAM
)
1933 aShapeName
= "PlotAreaIncludingAxes";
1934 SdrObject
* pShape
= DrawModelWrapper::getNamedSdrObject( aShapeName
, pRootList
);
1936 xShape
.set( pShape
->getUnoShape(), uno::UNO_QUERY
);
1942 awt::Size
aSize( xShape
->getSize() );
1943 awt::Point
aPoint( xShape
->getPosition() );
1944 aRet
= awt::Rectangle( aPoint
.X
, aPoint
.Y
, aSize
.Width
, aSize
.Height
);
1947 //for rotated objects the shape size and position differs from the visible rectangle
1948 SvxShape
* pShape
= SvxShape::getImplementation( xShape
);
1951 SdrObject
* pSdrObject
= pShape
->GetSdrObject();
1954 tools::Rectangle
aSnapRect( pSdrObject
->GetSnapRect() );
1955 aRet
= awt::Rectangle(aSnapRect
.Left(),aSnapRect
.Top(),aSnapRect
.GetWidth(),aSnapRect
.GetHeight());
1963 std::shared_ptr
< DrawModelWrapper
> ChartView::getDrawModelWrapper()
1965 return m_pDrawModelWrapper
;
1970 inline sal_Int32
lcl_getDiagramTitleSpace()
1972 return 200; //=0,2 cm spacing
1974 bool lcl_getPropertySwapXAndYAxis( const uno::Reference
< XDiagram
>& xDiagram
)
1976 bool bSwapXAndY
= false;
1978 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
1979 if( xCooSysContainer
.is() )
1981 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
1982 if( aCooSysList
.getLength() )
1984 uno::Reference
<beans::XPropertySet
> xProp(aCooSysList
[0], uno::UNO_QUERY
);
1987 xProp
->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY
;
1989 catch( const uno::Exception
& e
)
1991 SAL_WARN("chart2", "Exception caught. " << e
);
2000 sal_Int32
ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
2001 const Reference
< chart2::XAxis
>& xAxis
2002 , const Reference
< chart2::XCoordinateSystem
> & xCorrespondingCoordinateSystem
2003 , const Reference
<chart2::XChartDocument
>& xChartDoc
)
2005 return AxisHelper::getExplicitNumberFormatKeyForAxis( xAxis
, xCorrespondingCoordinateSystem
, xChartDoc
2006 , true /*bSearchForParallelAxisIfNothingIsFound*/ );
2009 sal_Int32
ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
2010 const uno::Reference
< beans::XPropertySet
>& xSeriesOrPointProp
,
2011 const uno::Reference
< XDataSeries
>& xSeries
,
2012 sal_Int32 nPointIndex
/*-1 for whole series*/,
2013 const uno::Reference
< XDiagram
>& xDiagram
2016 sal_Int32 nFormat
=0;
2017 if( !xSeriesOrPointProp
.is() )
2020 bool bLinkToSource
= true;
2023 xSeriesOrPointProp
->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT
) >>= bLinkToSource
;
2025 catch ( const beans::UnknownPropertyException
& ) {}
2027 xSeriesOrPointProp
->getPropertyValue(CHART_UNONAME_NUMFMT
) >>= nFormat
;
2028 sal_Int32 nOldFormat
= nFormat
;
2031 uno::Reference
< chart2::XChartType
> xChartType( DataSeriesHelper::getChartTypeOfSeries( xSeries
, xDiagram
) );
2033 bool bFormatFound
= false;
2034 if( ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( xChartType
) )
2036 uno::Reference
< beans::XPropertySet
> xAttachedAxisProps( DiagramHelper::getAttachedAxis( xSeries
, xDiagram
), uno::UNO_QUERY
);
2037 if (xAttachedAxisProps
.is() && (xAttachedAxisProps
->getPropertyValue(CHART_UNONAME_NUMFMT
) >>= nFormat
))
2038 bFormatFound
= true;
2042 Reference
< chart2::data::XDataSource
> xSeriesSource( xSeries
, uno::UNO_QUERY
);
2043 OUString
aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType
) );
2045 Reference
< data::XLabeledDataSequence
> xLabeledSequence(
2046 DataSeriesHelper::getDataSequenceByRole( xSeriesSource
, aRole
));
2047 if( xLabeledSequence
.is() )
2049 Reference
< data::XDataSequence
> xValues( xLabeledSequence
->getValues() );
2051 nFormat
= xValues
->getNumberFormatKeyByIndex( nPointIndex
);
2055 if (nFormat
>= 0 && nOldFormat
!= nFormat
)
2056 xSeriesOrPointProp
->setPropertyValue(CHART_UNONAME_NUMFMT
, uno::Any(nFormat
));
2064 sal_Int32
ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
2065 const uno::Reference
< beans::XPropertySet
>& xSeriesOrPointProp
,
2066 const uno::Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
)
2068 sal_Int32 nFormat
=0;
2069 if( !xSeriesOrPointProp
.is() )
2071 if( !(xSeriesOrPointProp
->getPropertyValue("PercentageNumberFormat") >>= nFormat
) )
2073 nFormat
= DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier
);
2080 awt::Rectangle
ExplicitValueProvider::AddSubtractAxisTitleSizes(
2082 , const Reference
< uno::XInterface
>& xChartView
2083 , const awt::Rectangle
& rPositionAndSize
, bool bSubtract
)
2085 awt::Rectangle
aRet(rPositionAndSize
);
2087 //add axis title sizes to the diagram size
2088 uno::Reference
< chart2::XTitle
> xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION
, rModel
) );
2089 uno::Reference
< chart2::XTitle
> xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION
, rModel
) );
2090 uno::Reference
< chart2::XTitle
> xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE
, rModel
) );
2091 uno::Reference
< chart2::XTitle
> xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE
, rModel
) );
2092 if( xTitle_Height
.is() || xTitle_Width
.is() || xSecondTitle_Height
.is() || xSecondTitle_Width
.is() )
2094 ExplicitValueProvider
* pExplicitValueProvider
= ExplicitValueProvider::getExplicitValueProvider(xChartView
);
2095 if( pExplicitValueProvider
)
2097 //detect whether x axis points into x direction or not
2098 if( lcl_getPropertySwapXAndYAxis( rModel
.getFirstDiagram() ) )
2100 std::swap( xTitle_Height
, xTitle_Width
);
2101 std::swap( xSecondTitle_Height
, xSecondTitle_Width
);
2104 sal_Int32 nTitleSpaceWidth
= 0;
2105 sal_Int32 nTitleSpaceHeight
= 0;
2106 sal_Int32 nSecondTitleSpaceWidth
= 0;
2107 sal_Int32 nSecondTitleSpaceHeight
= 0;
2109 if( xTitle_Height
.is() )
2111 OUString
aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height
, rModel
) );
2112 nTitleSpaceHeight
= pExplicitValueProvider
->getRectangleOfObject( aCID_X
, true ).Height
;
2113 if( nTitleSpaceHeight
)
2114 nTitleSpaceHeight
+=lcl_getDiagramTitleSpace();
2116 if( xTitle_Width
.is() )
2118 OUString
aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width
, rModel
) );
2119 nTitleSpaceWidth
= pExplicitValueProvider
->getRectangleOfObject( aCID_Y
, true ).Width
;
2120 if(nTitleSpaceWidth
)
2121 nTitleSpaceWidth
+=lcl_getDiagramTitleSpace();
2123 if( xSecondTitle_Height
.is() )
2125 OUString
aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height
, rModel
) );
2126 nSecondTitleSpaceHeight
= pExplicitValueProvider
->getRectangleOfObject( aCID_X
, true ).Height
;
2127 if( nSecondTitleSpaceHeight
)
2128 nSecondTitleSpaceHeight
+=lcl_getDiagramTitleSpace();
2130 if( xSecondTitle_Width
.is() )
2132 OUString
aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width
, rModel
) );
2133 nSecondTitleSpaceWidth
+= pExplicitValueProvider
->getRectangleOfObject( aCID_Y
, true ).Width
;
2134 if( nSecondTitleSpaceWidth
)
2135 nSecondTitleSpaceWidth
+=lcl_getDiagramTitleSpace();
2139 aRet
.X
+= nTitleSpaceWidth
;
2140 aRet
.Y
+= nSecondTitleSpaceHeight
;
2141 aRet
.Width
-= (nTitleSpaceWidth
+ nSecondTitleSpaceWidth
);
2142 aRet
.Height
-= (nTitleSpaceHeight
+ nSecondTitleSpaceHeight
);
2147 aRet
.X
-= nTitleSpaceWidth
;
2148 aRet
.Y
-= nSecondTitleSpaceHeight
;
2149 aRet
.Width
+= nTitleSpaceWidth
+ nSecondTitleSpaceWidth
;
2150 aRet
.Height
+= nTitleSpaceHeight
+ nSecondTitleSpaceHeight
;
2159 inline double lcl_getPageLayoutDistancePercentage()
2164 bool getAvailablePosAndSizeForDiagram(
2165 CreateShapeParam2D
& rParam
, const awt::Size
& rPageSize
, const uno::Reference
<XDiagram
>& xDiagram
)
2167 rParam
.mbUseFixedInnerSize
= false;
2169 //@todo: we need a size dependent on the axis labels
2170 sal_Int32 nYDistance
= static_cast<sal_Int32
>(rPageSize
.Height
*lcl_getPageLayoutDistancePercentage());
2171 sal_Int32 nXDistance
= static_cast<sal_Int32
>(rPageSize
.Width
*lcl_getPageLayoutDistancePercentage());
2172 rParam
.maRemainingSpace
.X
+= nXDistance
;
2173 rParam
.maRemainingSpace
.Width
-= 2*nXDistance
;
2174 rParam
.maRemainingSpace
.Y
+= nYDistance
;
2175 rParam
.maRemainingSpace
.Height
-= 2*nYDistance
;
2177 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
2180 uno::Reference
< beans::XPropertySet
> xProp(xDiagram
, uno::UNO_QUERY
);
2182 bool bPosSizeExcludeAxes
= false;
2184 xProp
->getPropertyValue( "PosSizeExcludeAxes" ) >>= bPosSizeExcludeAxes
;
2187 css::chart2::RelativeSize aRelativeSize
;
2188 if( xProp
.is() && (xProp
->getPropertyValue( "RelativeSize" )>>=aRelativeSize
) )
2190 rParam
.maRemainingSpace
.Height
= static_cast<sal_Int32
>(aRelativeSize
.Secondary
*rPageSize
.Height
);
2191 rParam
.maRemainingSpace
.Width
= static_cast<sal_Int32
>(aRelativeSize
.Primary
*rPageSize
.Width
);
2192 rParam
.mbUseFixedInnerSize
= bPosSizeExcludeAxes
;
2196 chart2::RelativePosition aRelativePosition
;
2197 if( xProp
.is() && (xProp
->getPropertyValue( "RelativePosition" )>>=aRelativePosition
) )
2199 //@todo decide whether x is primary or secondary
2201 //the coordinates re relative to the page
2202 double fX
= aRelativePosition
.Primary
*rPageSize
.Width
;
2203 double fY
= aRelativePosition
.Secondary
*rPageSize
.Height
;
2205 awt::Point aPos
= RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
2206 awt::Point(static_cast<sal_Int32
>(fX
),static_cast<sal_Int32
>(fY
)),
2207 awt::Size(rParam
.maRemainingSpace
.Width
, rParam
.maRemainingSpace
.Height
),
2208 aRelativePosition
.Anchor
);
2210 rParam
.maRemainingSpace
.X
= aPos
.X
;
2211 rParam
.maRemainingSpace
.Y
= aPos
.Y
;
2213 rParam
.mbUseFixedInnerSize
= bPosSizeExcludeAxes
;
2216 //ensure that the diagram does not lap out right side or out of bottom
2217 if (rParam
.maRemainingSpace
.Y
+ rParam
.maRemainingSpace
.Height
> rPageSize
.Height
)
2218 rParam
.maRemainingSpace
.Height
= rPageSize
.Height
- rParam
.maRemainingSpace
.Y
;
2220 if (rParam
.maRemainingSpace
.X
+ rParam
.maRemainingSpace
.Width
> rPageSize
.Width
)
2221 rParam
.maRemainingSpace
.Width
= rPageSize
.Width
- rParam
.maRemainingSpace
.X
;
2226 enum TitleAlignment
{ ALIGN_LEFT
, ALIGN_TOP
, ALIGN_RIGHT
, ALIGN_BOTTOM
, ALIGN_Z
};
2228 void changePositionOfAxisTitle( VTitle
* pVTitle
, TitleAlignment eAlignment
2229 , awt::Rectangle
const & rDiagramPlusAxesRect
, const awt::Size
& rPageSize
)
2234 awt::Point
aNewPosition(0,0);
2235 awt::Size aTitleSize
= pVTitle
->getFinalSize();
2236 sal_Int32 nYDistance
= static_cast<sal_Int32
>(rPageSize
.Height
*lcl_getPageLayoutDistancePercentage());
2237 sal_Int32 nXDistance
= static_cast<sal_Int32
>(rPageSize
.Width
*lcl_getPageLayoutDistancePercentage());
2238 switch( eAlignment
)
2241 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
+ rDiagramPlusAxesRect
.Width
/2
2242 , rDiagramPlusAxesRect
.Y
- aTitleSize
.Height
/2 - nYDistance
);
2245 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
+ rDiagramPlusAxesRect
.Width
/2
2246 , rDiagramPlusAxesRect
.Y
+ rDiagramPlusAxesRect
.Height
+ aTitleSize
.Height
/2 + nYDistance
);
2249 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
- aTitleSize
.Width
/2 - nXDistance
2250 , rDiagramPlusAxesRect
.Y
+ rDiagramPlusAxesRect
.Height
/2 );
2253 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
+ rDiagramPlusAxesRect
.Width
+ aTitleSize
.Width
/2 + nXDistance
2254 , rDiagramPlusAxesRect
.Y
+ rDiagramPlusAxesRect
.Height
/2 );
2257 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
+ rDiagramPlusAxesRect
.Width
+ aTitleSize
.Width
/2 + nXDistance
2258 , rDiagramPlusAxesRect
.Y
+ rDiagramPlusAxesRect
.Height
- aTitleSize
.Height
/2 );
2264 sal_Int32 nMaxY
= rPageSize
.Height
- aTitleSize
.Height
/2;
2265 sal_Int32 nMaxX
= rPageSize
.Width
- aTitleSize
.Width
/2;
2266 sal_Int32 nMinX
= aTitleSize
.Width
/2;
2267 sal_Int32 nMinY
= aTitleSize
.Height
/2;
2268 if( aNewPosition
.Y
> nMaxY
)
2269 aNewPosition
.Y
= nMaxY
;
2270 if( aNewPosition
.X
> nMaxX
)
2271 aNewPosition
.X
= nMaxX
;
2272 if( aNewPosition
.Y
< nMinY
)
2273 aNewPosition
.Y
= nMinY
;
2274 if( aNewPosition
.X
< nMinX
)
2275 aNewPosition
.X
= nMinX
;
2277 pVTitle
->changePosition( aNewPosition
);
2280 std::shared_ptr
<VTitle
> lcl_createTitle( TitleHelper::eTitleType eType
2281 , const uno::Reference
< drawing::XShapes
>& xPageShapes
2282 , const uno::Reference
< lang::XMultiServiceFactory
>& xShapeFactory
2283 , ChartModel
& rModel
2284 , awt::Rectangle
& rRemainingSpace
2285 , const awt::Size
& rPageSize
2286 , TitleAlignment eAlignment
2287 , bool& rbAutoPosition
)
2289 std::shared_ptr
<VTitle
> apVTitle
;
2291 // #i109336# Improve auto positioning in chart
2292 double fPercentage
= lcl_getPageLayoutDistancePercentage();
2293 sal_Int32 nXDistance
= static_cast< sal_Int32
>( rPageSize
.Width
* fPercentage
);
2294 sal_Int32 nYDistance
= static_cast< sal_Int32
>( rPageSize
.Height
* fPercentage
);
2295 if ( eType
== TitleHelper::MAIN_TITLE
)
2297 nYDistance
+= 135; // 1/100 mm
2299 else if ( eType
== TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION
)
2301 nYDistance
= 420; // 1/100 mm
2303 else if ( eType
== TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION
)
2305 nXDistance
= 450; // 1/100 mm
2308 uno::Reference
< XTitle
> xTitle( TitleHelper::getTitle( eType
, rModel
) );
2309 OUString aCompleteString
= TitleHelper::getCompleteString(xTitle
);
2310 if (aCompleteString
.isEmpty())
2314 apVTitle
.reset(new VTitle(xTitle
));
2315 OUString aCID
= ObjectIdentifier::createClassifiedIdentifierForObject(xTitle
, rModel
);
2316 apVTitle
->init(xPageShapes
, xShapeFactory
, aCID
);
2317 apVTitle
->createShapes(awt::Point(0,0), rPageSize
);
2318 awt::Size aTitleUnrotatedSize
= apVTitle
->getUnrotatedSize();
2319 awt::Size aTitleSize
= apVTitle
->getFinalSize();
2322 rbAutoPosition
= true;
2323 awt::Point
aNewPosition(0,0);
2324 chart2::RelativePosition aRelativePosition
;
2325 uno::Reference
<beans::XPropertySet
> xProp(xTitle
, uno::UNO_QUERY
);
2326 if (xProp
.is() && (xProp
->getPropertyValue("RelativePosition") >>= aRelativePosition
))
2328 rbAutoPosition
= false;
2330 //@todo decide whether x is primary or secondary
2331 double fX
= aRelativePosition
.Primary
*rPageSize
.Width
;
2332 double fY
= aRelativePosition
.Secondary
*rPageSize
.Height
;
2334 double fAnglePi
= apVTitle
->getRotationAnglePi();
2335 aNewPosition
= RelativePositionHelper::getCenterOfAnchoredObject(
2336 awt::Point(static_cast<sal_Int32
>(fX
),static_cast<sal_Int32
>(fY
))
2337 , aTitleUnrotatedSize
, aRelativePosition
.Anchor
, fAnglePi
);
2339 else //auto position
2341 switch( eAlignment
)
2344 aNewPosition
= awt::Point( rRemainingSpace
.X
+ rRemainingSpace
.Width
/2
2345 , rRemainingSpace
.Y
+ aTitleSize
.Height
/2 + nYDistance
);
2348 aNewPosition
= awt::Point( rRemainingSpace
.X
+ rRemainingSpace
.Width
/2
2349 , rRemainingSpace
.Y
+ rRemainingSpace
.Height
- aTitleSize
.Height
/2 - nYDistance
);
2352 aNewPosition
= awt::Point( rRemainingSpace
.X
+ aTitleSize
.Width
/2 + nXDistance
2353 , rRemainingSpace
.Y
+ rRemainingSpace
.Height
/2 );
2356 aNewPosition
= awt::Point( rRemainingSpace
.X
+ rRemainingSpace
.Width
- aTitleSize
.Width
/2 - nXDistance
2357 , rRemainingSpace
.Y
+ rRemainingSpace
.Height
/2 );
2364 apVTitle
->changePosition( aNewPosition
);
2367 switch( eAlignment
)
2370 // Push the remaining space down from top.
2371 rRemainingSpace
.Y
+= ( aTitleSize
.Height
+ nYDistance
);
2372 rRemainingSpace
.Height
-= ( aTitleSize
.Height
+ nYDistance
);
2375 // Push the remaining space up from bottom.
2376 rRemainingSpace
.Height
-= ( aTitleSize
.Height
+ nYDistance
);
2379 // Push the remaining space to the right from left edge.
2380 rRemainingSpace
.X
+= ( aTitleSize
.Width
+ nXDistance
);
2381 rRemainingSpace
.Width
-= ( aTitleSize
.Width
+ nXDistance
);
2384 // Push the remaining space to the left from right edge.
2385 rRemainingSpace
.Width
-= ( aTitleSize
.Width
+ nXDistance
);
2394 bool lcl_createLegend( const uno::Reference
< XLegend
> & xLegend
2395 , const uno::Reference
< drawing::XShapes
>& xPageShapes
2396 , const uno::Reference
< lang::XMultiServiceFactory
>& xShapeFactory
2397 , const uno::Reference
< uno::XComponentContext
> & xContext
2398 , awt::Rectangle
& rRemainingSpace
2399 , const awt::Size
& rPageSize
2400 , ChartModel
& rModel
2401 , const std::vector
< LegendEntryProvider
* >& rLegendEntryProviderList
2402 , sal_Int16 nDefaultWritingMode
)
2404 if (!VLegend::isVisible(xLegend
))
2407 VLegend
aVLegend( xLegend
, xContext
, rLegendEntryProviderList
,
2408 xPageShapes
, xShapeFactory
, rModel
);
2409 aVLegend
.setDefaultWritingMode( nDefaultWritingMode
);
2410 aVLegend
.createShapes( awt::Size( rRemainingSpace
.Width
, rRemainingSpace
.Height
),
2412 aVLegend
.changePosition( rRemainingSpace
, rPageSize
);
2416 void lcl_createButtons(const uno::Reference
<drawing::XShapes
>& xPageShapes
,
2417 const uno::Reference
<lang::XMultiServiceFactory
>& xShapeFactory
,
2419 awt::Rectangle
& rRemainingSpace
)
2421 uno::Reference
<chart2::data::XPivotTableDataProvider
> xPivotTableDataProvider(rModel
.getDataProvider(), uno::UNO_QUERY
);
2422 if (!xPivotTableDataProvider
.is())
2425 uno::Reference
<beans::XPropertySet
> xModelPage(rModel
.getPageBackground());
2427 awt::Size
aSize(4000, 700); // size of the button
2431 if (xPivotTableDataProvider
->getPageFields().hasElements())
2435 for (css::chart2::data::PivotTableFieldEntry
const & rPageFieldEntry
: xPivotTableDataProvider
->getPageFields())
2437 std::unique_ptr
<VButton
> pButton(new VButton
);
2438 pButton
->init(xPageShapes
, xShapeFactory
);
2439 awt::Point aNewPosition
= awt::Point(rRemainingSpace
.X
+ x
+ 100, rRemainingSpace
.Y
+ 100);
2440 sal_Int32 nDimensionIndex
= rPageFieldEntry
.DimensionIndex
;
2441 OUString aFieldOutputDescription
= xPivotTableDataProvider
->getFieldOutputDescription(nDimensionIndex
);
2442 pButton
->setLabel(rPageFieldEntry
.Name
+ " | " + aFieldOutputDescription
);
2443 pButton
->setCID("FieldButton.Page." + OUString::number(nDimensionIndex
));
2444 pButton
->setPosition(aNewPosition
);
2445 pButton
->setSize(aSize
);
2446 if (rPageFieldEntry
.HasHiddenMembers
)
2447 pButton
->setArrowColor(Color(0x0000FF));
2449 pButton
->createShapes(xModelPage
);
2450 x
+= aSize
.Width
+ 100;
2452 rRemainingSpace
.Y
+= (aSize
.Height
+ 100 + 100);
2453 rRemainingSpace
.Height
-= (aSize
.Height
+ 100 + 100);
2456 aSize
= awt::Size(3000, 700); // size of the button
2458 if (xPivotTableDataProvider
->getRowFields().hasElements())
2461 for (css::chart2::data::PivotTableFieldEntry
const & rRowFieldEntry
: xPivotTableDataProvider
->getRowFields())
2464 std::unique_ptr
<VButton
> pButton(new VButton
);
2465 pButton
->init(xPageShapes
, xShapeFactory
);
2466 awt::Point aNewPosition
= awt::Point(rRemainingSpace
.X
+ x
+ 100,
2467 rRemainingSpace
.Y
+ rRemainingSpace
.Height
- aSize
.Height
- 100);
2468 pButton
->setLabel(rRowFieldEntry
.Name
);
2469 pButton
->setCID("FieldButton.Row." + OUString::number(rRowFieldEntry
.DimensionIndex
));
2470 pButton
->setPosition(aNewPosition
);
2471 pButton
->setSize(aSize
);
2472 if ( rRowFieldEntry
.Name
== "Data" )
2474 pButton
->setBGColor( Color(0x00F6F6F6) );
2475 pButton
->showArrow( false );
2477 else if (rRowFieldEntry
.HasHiddenMembers
)
2478 pButton
->setArrowColor(Color(0x0000FF));
2479 pButton
->createShapes(xModelPage
);
2480 x
+= aSize
.Width
+ 100;
2482 rRemainingSpace
.Height
-= (aSize
.Height
+ 100 + 100);
2487 ChartModel
& rChartModel
2488 , const awt::Size
& rPageSize
2489 , const uno::Reference
< drawing::XShapes
>& xTarget
2490 , const uno::Reference
< lang::XMultiServiceFactory
>& xShapeFactory
2495 uno::Reference
< beans::XPropertySet
> xModelPage( rChartModel
.getPageBackground());
2496 if( ! xModelPage
.is())
2499 if( !xShapeFactory
.is() )
2503 tPropertyNameValueMap aNameValueMap
;
2504 PropertyMapper::getValueMap( aNameValueMap
, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage
);
2506 OUString
aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE
, OUString() ) );
2507 aNameValueMap
.emplace( "Name", uno::Any( aCID
) ); //CID OUString
2509 tNameSequence aNames
;
2510 tAnySequence aValues
;
2511 PropertyMapper::getMultiPropertyListsFromValueMap( aNames
, aValues
, aNameValueMap
);
2513 AbstractShapeFactory
* pShapeFactory
= AbstractShapeFactory::getOrCreateShapeFactory(xShapeFactory
);
2514 pShapeFactory
->createRectangle(
2515 xTarget
, rPageSize
, awt::Point(0, 0), aNames
, aValues
);
2517 catch( const uno::Exception
& )
2519 DBG_UNHANDLED_EXCEPTION("chart2" );
2523 void lcl_removeEmptyGroupShapes( const Reference
< drawing::XShapes
>& xParent
)
2527 Reference
< drawing::XShapeGroup
> xParentGroup( xParent
, uno::UNO_QUERY
);
2528 if( !xParentGroup
.is() )
2530 Reference
< drawing::XDrawPage
> xPage( xParent
, uno::UNO_QUERY
);
2535 //iterate from back!
2536 for( sal_Int32 nN
= xParent
->getCount(); nN
--; )
2538 uno::Any aAny
= xParent
->getByIndex( nN
);
2539 Reference
< drawing::XShapes
> xShapes(nullptr);
2540 if( aAny
>>= xShapes
)
2541 lcl_removeEmptyGroupShapes( xShapes
);
2542 if( xShapes
.is() && xShapes
->getCount()==0 )
2544 //remove empty group shape
2545 Reference
< drawing::XShapeGroup
> xGroup( xShapes
, uno::UNO_QUERY
);
2546 Reference
< drawing::XShape
> xShape( xShapes
, uno::UNO_QUERY
);
2548 xParent
->remove( xShape
);
2555 void ChartView::impl_refreshAddIn()
2557 if( !m_bRefreshAddIn
)
2560 uno::Reference
< beans::XPropertySet
> xProp( static_cast< ::cppu::OWeakObject
* >( &mrChartModel
), uno::UNO_QUERY
);
2563 uno::Reference
< util::XRefreshable
> xAddIn
;
2564 xProp
->getPropertyValue( "AddIn" ) >>= xAddIn
;
2567 bool bRefreshAddInAllowed
= true;
2568 xProp
->getPropertyValue( "RefreshAddInAllowed" ) >>= bRefreshAddInAllowed
;
2569 if( bRefreshAddInAllowed
)
2573 catch( const uno::Exception
& e
)
2575 SAL_WARN("chart2", "Exception caught. " << e
);
2580 * Is it a real 3D chart with a true 3D scene or a 3D chart in a 2D scene.
2582 bool ChartView::isReal3DChart()
2584 uno::Reference
< XDiagram
> xDiagram( mrChartModel
.getFirstDiagram() );
2585 #if HAVE_FEATURE_OPENGL
2586 return ChartHelper::isGL3DDiagram(xDiagram
);
2592 static const char* envChartDummyFactory
= getenv("CHART_DUMMY_FACTORY");
2594 void ChartView::createShapes()
2596 osl::ResettableMutexGuard
aTimedGuard(maTimeMutex
);
2597 if(mrChartModel
.isTimeBased())
2599 maTimeBased
.bTimeBased
= true;
2602 //make sure add-in is refreshed after creating the shapes
2603 const ::comphelper::ScopeGuard
aGuard( [this]() { this->impl_refreshAddIn(); } );
2605 m_aResultingDiagramRectangleExcludingAxes
= awt::Rectangle(0,0,0,0);
2606 impl_deleteCoordinateSystems();
2607 if( m_pDrawModelWrapper
)
2609 SolarMutexGuard aSolarGuard
;
2610 // #i12587# support for shapes in chart
2611 m_pDrawModelWrapper
->getSdrModel().EnableUndo( false );
2612 m_pDrawModelWrapper
->clearMainDrawPage();
2615 lcl_setDefaultWritingMode( m_pDrawModelWrapper
, mrChartModel
);
2617 awt::Size aPageSize
= mrChartModel
.getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
2619 AbstractShapeFactory
* pShapeFactory
= AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory
);
2620 if(!mxRootShape
.is())
2621 mxRootShape
= pShapeFactory
->getOrCreateChartRootShape( m_xDrawPage
);
2623 SdrPage
* pPage
= ChartView::getSdrPage();
2624 if(pPage
) //it is necessary to use the implementation here as the uno page does not provide a propertyset
2625 pPage
->SetSize(Size(aPageSize
.Width
,aPageSize
.Height
));
2628 OSL_FAIL("could not set page size correctly");
2630 pShapeFactory
->setPageSize(mxRootShape
, aPageSize
);
2631 pShapeFactory
->clearPage(mxRootShape
);
2632 #if HAVE_FEATURE_OPENGL
2633 #if HAVE_FEATURE_DESKTOP
2641 m_pGL3DPlotter
.reset();
2643 // hide OpenGL window for now in normal charts
2644 OpenGLWindow
* pWindow
= mrChartModel
.getOpenGLWindow();
2645 if(pWindow
&& !envChartDummyFactory
)
2646 pWindow
->Show(false);
2651 createShapes2D(aPageSize
);
2653 // #i12587# support for shapes in chart
2654 if ( m_pDrawModelWrapper
)
2656 SolarMutexGuard aSolarGuard
;
2657 m_pDrawModelWrapper
->getSdrModel().EnableUndo( true );
2660 if(maTimeBased
.bTimeBased
)
2662 maTimeBased
.nFrame
++;
2666 void ChartView::render()
2668 #if HAVE_FEATURE_OPENGL
2669 if(!isReal3DChart())
2671 AbstractShapeFactory
* pShapeFactory
= AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory
);
2672 OpenGLWindow
* pWindow
= mrChartModel
.getOpenGLWindow();
2674 pWindow
->setRenderer(mp2DRenderer
.get());
2675 bool bRender
= pShapeFactory
->preRender(mxRootShape
, pWindow
);
2678 pShapeFactory
->render(mxRootShape
, pWindow
!= mp2DRenderer
->getOpenGLWindow());
2679 pShapeFactory
->postRender(pWindow
);
2687 // util::XEventListener (base of XCloseListener)
2688 void SAL_CALL
ChartView::disposing( const lang::EventObject
& /* rSource */ )
2692 void ChartView::impl_updateView( bool bCheckLockedCtrler
)
2694 if( !m_pDrawModelWrapper
)
2697 // #i12587# support for shapes in chart
2698 if ( m_bSdrViewIsInEditMode
)
2703 if (bCheckLockedCtrler
&& mrChartModel
.hasControllersLocked())
2706 if( m_bViewDirty
&& !m_bInViewUpdate
)
2708 m_bInViewUpdate
= true;
2709 //bool bOldRefreshAddIn = m_bRefreshAddIn;
2710 //m_bRefreshAddIn = false;
2713 impl_notifyModeChangeListener("invalid");
2715 //prepare draw model
2717 SolarMutexGuard aSolarGuard
;
2718 m_pDrawModelWrapper
->lockControllers();
2723 #if HAVE_FEATURE_OPENGL
2724 OpenGLWindow
* pWindow
= mrChartModel
.getOpenGLWindow();
2725 if (pWindow
&& ChartHelper::isGL3DDiagram(mrChartModel
.getFirstDiagram()))
2726 pWindow
->Initialize();
2728 m_bViewDirty
= false;
2729 m_bViewUpdatePending
= false;
2734 //avoid recursions due to add-in
2735 m_bRefreshAddIn
= false;
2736 m_bViewDirty
= false;
2737 m_bViewUpdatePending
= false;
2738 //delete old chart view
2740 m_bRefreshAddIn
= true;
2744 m_bViewDirty
= m_bViewUpdatePending
;
2745 m_bViewUpdatePending
= false;
2746 m_bInViewUpdate
= false;
2748 catch( const uno::Exception
& )
2750 DBG_UNHANDLED_EXCEPTION("chart2" );
2751 m_bViewDirty
= m_bViewUpdatePending
;
2752 m_bViewUpdatePending
= false;
2753 m_bInViewUpdate
= false;
2757 SolarMutexGuard aSolarGuard
;
2758 m_pDrawModelWrapper
->unlockControllers();
2761 impl_notifyModeChangeListener("valid");
2763 //m_bRefreshAddIn = bOldRefreshAddIn;
2767 // ____ XModifyListener ____
2768 void SAL_CALL
ChartView::modified( const lang::EventObject
& /* aEvent */ )
2770 m_bViewDirty
= true;
2771 if( m_bInViewUpdate
)
2772 m_bViewUpdatePending
= true;
2774 impl_notifyModeChangeListener("dirty");
2778 void ChartView::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
2780 //#i77362 change notification for changes on additional shapes are missing
2781 if( m_bInViewUpdate
)
2784 // #i12587# support for shapes in chart
2785 if ( m_bSdrViewIsInEditMode
)
2787 uno::Reference
< view::XSelectionSupplier
> xSelectionSupplier( mrChartModel
.getCurrentController(), uno::UNO_QUERY
);
2788 if ( xSelectionSupplier
.is() )
2790 OUString aSelObjCID
;
2791 uno::Any
aSelObj( xSelectionSupplier
->getSelection() );
2792 aSelObj
>>= aSelObjCID
;
2793 if ( !aSelObjCID
.isEmpty() )
2800 const SdrHint
* pSdrHint
= dynamic_cast< const SdrHint
* >(&rHint
);
2804 bool bShapeChanged
= false;
2805 switch( pSdrHint
->GetKind() )
2807 case SdrHintKind::ObjectChange
:
2808 bShapeChanged
= true;
2810 case SdrHintKind::ObjectInserted
:
2811 bShapeChanged
= true;
2813 case SdrHintKind::ObjectRemoved
:
2814 bShapeChanged
= true;
2816 case SdrHintKind::ModelCleared
:
2817 bShapeChanged
= true;
2819 case SdrHintKind::EndEdit
:
2820 bShapeChanged
= true;
2828 //#i76053# do not send view modified notifications for changes on the hidden page which contains e.g. the symbols for the dialogs
2829 if( ChartView::getSdrPage() != pSdrHint
->GetPage() )
2830 bShapeChanged
=false;
2836 mrChartModel
.setModified(true);
2839 void ChartView::impl_notifyModeChangeListener( const OUString
& rNewMode
)
2843 ::cppu::OInterfaceContainerHelper
* pIC
= m_aListenerContainer
2844 .getContainer( cppu::UnoType
<util::XModeChangeListener
>::get());
2847 util::ModeChangeEvent
aEvent( static_cast< uno::XWeak
* >( this ), rNewMode
);
2848 ::cppu::OInterfaceIteratorHelper
aIt( *pIC
);
2849 while( aIt
.hasMoreElements() )
2851 uno::Reference
< util::XModeChangeListener
> xListener( aIt
.next(), uno::UNO_QUERY
);
2852 if( xListener
.is() )
2853 xListener
->modeChanged( aEvent
);
2857 catch( const uno::Exception
& )
2859 DBG_UNHANDLED_EXCEPTION("chart2");
2863 // ____ XModeChangeBroadcaster ____
2865 void SAL_CALL
ChartView::addModeChangeListener( const uno::Reference
< util::XModeChangeListener
>& xListener
)
2867 m_aListenerContainer
.addInterface(
2868 cppu::UnoType
<util::XModeChangeListener
>::get(), xListener
);
2870 void SAL_CALL
ChartView::removeModeChangeListener( const uno::Reference
< util::XModeChangeListener
>& xListener
)
2872 m_aListenerContainer
.removeInterface(
2873 cppu::UnoType
<util::XModeChangeListener
>::get(), xListener
);
2875 void SAL_CALL
ChartView::addModeChangeApproveListener( const uno::Reference
< util::XModeChangeApproveListener
>& /* _rxListener */ )
2879 void SAL_CALL
ChartView::removeModeChangeApproveListener( const uno::Reference
< util::XModeChangeApproveListener
>& /* _rxListener */ )
2884 // ____ XUpdatable ____
2885 void SAL_CALL
ChartView::update()
2889 //#i100778# migrate all imported or old documents to a plot area sizing exclusive axes (in case the save settings allow for this):
2890 //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.
2891 //When a view update is requested (what happens for creating the metafile or displaying
2892 //the chart in edit mode or printing) it is most likely that all necessary information are available - like the underlying spreadsheet data for example.
2893 //Those data are important for the correct axis label sizes which are needed during conversion.
2894 if( DiagramHelper::switchDiagramPositioningToExcludingPositioning( mrChartModel
, true, false ) )
2898 void SAL_CALL
ChartView::updateSoft()
2903 void SAL_CALL
ChartView::updateHard()
2905 impl_updateView(false);
2908 // ____ XPropertySet ____
2909 Reference
< beans::XPropertySetInfo
> SAL_CALL
ChartView::getPropertySetInfo()
2911 OSL_FAIL("not implemented");
2915 void SAL_CALL
ChartView::setPropertyValue( const OUString
& rPropertyName
2916 , const Any
& rValue
)
2918 if( rPropertyName
== "Resolution" )
2920 awt::Size aNewResolution
;
2921 if( ! (rValue
>>= aNewResolution
) )
2922 throw lang::IllegalArgumentException( "Property 'Resolution' requires value of type awt::Size", nullptr, 0 );
2924 if( m_aPageResolution
.Width
!=aNewResolution
.Width
|| m_aPageResolution
.Height
!=aNewResolution
.Height
)
2926 //set modified only when the new resolution is higher and points were skipped before
2927 bool bSetModified
= m_bPointsWereSkipped
&& (m_aPageResolution
.Width
<aNewResolution
.Width
|| m_aPageResolution
.Height
<aNewResolution
.Height
);
2929 m_aPageResolution
= aNewResolution
;
2932 this->modified( lang::EventObject( static_cast< uno::XWeak
* >( this ) ) );
2935 else if( rPropertyName
== "ZoomFactors" )
2937 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
2938 uno::Sequence
< beans::PropertyValue
> aZoomFactors
;
2939 if( ! (rValue
>>= aZoomFactors
) )
2940 throw lang::IllegalArgumentException( "Property 'ZoomFactors' requires value of type Sequence< PropertyValue >", nullptr, 0 );
2942 sal_Int32 nFilterArgs
= aZoomFactors
.getLength();
2943 beans::PropertyValue
* pDataValues
= aZoomFactors
.getArray();
2944 while( nFilterArgs
-- )
2946 if ( pDataValues
->Name
== "ScaleXNumerator" )
2947 pDataValues
->Value
>>= m_nScaleXNumerator
;
2948 else if ( pDataValues
->Name
== "ScaleXDenominator" )
2949 pDataValues
->Value
>>= m_nScaleXDenominator
;
2950 else if ( pDataValues
->Name
== "ScaleYNumerator" )
2951 pDataValues
->Value
>>= m_nScaleYNumerator
;
2952 else if ( pDataValues
->Name
== "ScaleYDenominator" )
2953 pDataValues
->Value
>>= m_nScaleYDenominator
;
2958 else if( rPropertyName
== "SdrViewIsInEditMode" )
2960 //#i77362 change notification for changes on additional shapes are missing
2961 if( ! (rValue
>>= m_bSdrViewIsInEditMode
) )
2962 throw lang::IllegalArgumentException( "Property 'SdrViewIsInEditMode' requires value of type sal_Bool", nullptr, 0 );
2965 throw beans::UnknownPropertyException( "unknown property was tried to set to chart wizard", nullptr );
2968 Any SAL_CALL
ChartView::getPropertyValue( const OUString
& rPropertyName
)
2970 if( rPropertyName
!= "Resolution" )
2971 throw beans::UnknownPropertyException( "unknown property was tried to get from chart wizard", nullptr );
2973 return Any(m_aPageResolution
);
2976 void SAL_CALL
ChartView::addPropertyChangeListener(
2977 const OUString
& /* aPropertyName */, const Reference
< beans::XPropertyChangeListener
>& /* xListener */ )
2979 OSL_FAIL("not implemented");
2981 void SAL_CALL
ChartView::removePropertyChangeListener(
2982 const OUString
& /* aPropertyName */, const Reference
< beans::XPropertyChangeListener
>& /* aListener */ )
2984 OSL_FAIL("not implemented");
2987 void SAL_CALL
ChartView::addVetoableChangeListener( const OUString
& /* PropertyName */, const Reference
< beans::XVetoableChangeListener
>& /* aListener */ )
2989 OSL_FAIL("not implemented");
2992 void SAL_CALL
ChartView::removeVetoableChangeListener( const OUString
& /* PropertyName */, const Reference
< beans::XVetoableChangeListener
>& /* aListener */ )
2994 OSL_FAIL("not implemented");
2997 // ____ XMultiServiceFactory ____
2999 Reference
< uno::XInterface
> ChartView::createInstance( const OUString
& aServiceSpecifier
)
3001 SolarMutexGuard aSolarGuard
;
3003 SdrModel
* pModel
= ( m_pDrawModelWrapper
? &m_pDrawModelWrapper
->getSdrModel() : nullptr );
3006 if ( aServiceSpecifier
== "com.sun.star.drawing.DashTable" )
3008 if ( !m_xDashTable
.is() )
3010 m_xDashTable
= SvxUnoDashTable_createInstance( pModel
);
3012 return m_xDashTable
;
3014 else if ( aServiceSpecifier
== "com.sun.star.drawing.GradientTable" )
3016 if ( !m_xGradientTable
.is() )
3018 m_xGradientTable
= SvxUnoGradientTable_createInstance( pModel
);
3020 return m_xGradientTable
;
3022 else if ( aServiceSpecifier
== "com.sun.star.drawing.HatchTable" )
3024 if ( !m_xHatchTable
.is() )
3026 m_xHatchTable
= SvxUnoHatchTable_createInstance( pModel
);
3028 return m_xHatchTable
;
3030 else if ( aServiceSpecifier
== "com.sun.star.drawing.BitmapTable" )
3032 if ( !m_xBitmapTable
.is() )
3034 m_xBitmapTable
= SvxUnoBitmapTable_createInstance( pModel
);
3036 return m_xBitmapTable
;
3038 else if ( aServiceSpecifier
== "com.sun.star.drawing.TransparencyGradientTable" )
3040 if ( !m_xTransGradientTable
.is() )
3042 m_xTransGradientTable
= SvxUnoTransGradientTable_createInstance( pModel
);
3044 return m_xTransGradientTable
;
3046 else if ( aServiceSpecifier
== "com.sun.star.drawing.MarkerTable" )
3048 if ( !m_xMarkerTable
.is() )
3050 m_xMarkerTable
= SvxUnoMarkerTable_createInstance( pModel
);
3052 return m_xMarkerTable
;
3059 Reference
< uno::XInterface
> ChartView::createInstanceWithArguments( const OUString
& ServiceSpecifier
, const uno::Sequence
< uno::Any
>& Arguments
)
3061 OSL_ENSURE( Arguments
.getLength(), "ChartView::createInstanceWithArguments: arguments are ignored" );
3062 return createInstance( ServiceSpecifier
);
3065 uno::Sequence
< OUString
> ChartView::getAvailableServiceNames()
3067 uno::Sequence
< OUString
> aServiceNames( 6 );
3069 aServiceNames
[0] = "com.sun.star.drawing.DashTable";
3070 aServiceNames
[1] = "com.sun.star.drawing.GradientTable";
3071 aServiceNames
[2] = "com.sun.star.drawing.HatchTable";
3072 aServiceNames
[3] = "com.sun.star.drawing.BitmapTable";
3073 aServiceNames
[4] = "com.sun.star.drawing.TransparencyGradientTable";
3074 aServiceNames
[5] = "com.sun.star.drawing.MarkerTable";
3076 return aServiceNames
;
3079 OUString
ChartView::dump()
3081 #if HAVE_FEATURE_DESKTOP
3082 // Used for unit tests and in chartcontroller only, no need to drag in this when cross-compiling
3085 uno::Reference
< drawing::XShapes
> xShapes( m_xDrawPage
, uno::UNO_QUERY_THROW
);
3086 sal_Int32 n
= xShapes
->getCount();
3087 OUStringBuffer aBuffer
;
3088 for(sal_Int32 i
= 0; i
< n
; ++i
)
3090 uno::Reference
< drawing::XShapes
> xShape(xShapes
->getByIndex(i
), uno::UNO_QUERY
);
3093 XShapeDumper dumper
;
3094 OUString aString
= XShapeDumper::dump(mxRootShape
);
3095 aBuffer
.append(aString
);
3099 uno::Reference
< drawing::XShape
> xSingleShape(xShapes
->getByIndex(i
), uno::UNO_QUERY
);
3100 if(!xSingleShape
.is())
3102 XShapeDumper dumper
;
3103 OUString aString
= XShapeDumper::dump(xSingleShape
);
3104 aBuffer
.append(aString
);
3106 aBuffer
.append("\n\n");
3109 return aBuffer
.makeStringAndClear();
3115 void ChartView::setViewDirty()
3117 osl::ResettableMutexGuard
aGuard(maTimeMutex
);
3118 m_bViewDirty
= true;
3121 IMPL_LINK_NOARG(ChartView
, UpdateTimeBased
, Timer
*, void)
3127 void ChartView::createShapes2D( const awt::Size
& rPageSize
)
3129 AbstractShapeFactory
* pShapeFactory
= AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory
);
3131 SolarMutexGuard aSolarGuard
;
3133 // todo: it would be nicer to just pass the page m_xDrawPage and format it,
3134 // but the draw page does not support XPropertySet
3135 formatPage( mrChartModel
, rPageSize
, mxRootShape
, m_xShapeFactory
);
3137 CreateShapeParam2D aParam
;
3138 aParam
.maRemainingSpace
.X
= 0;
3139 aParam
.maRemainingSpace
.Y
= 0;
3140 aParam
.maRemainingSpace
.Width
= rPageSize
.Width
;
3141 aParam
.maRemainingSpace
.Height
= rPageSize
.Height
;
3143 //create the group shape for diagram and axes first to have title and legends on top of it
3144 uno::Reference
< XDiagram
> xDiagram( mrChartModel
.getFirstDiagram() );
3145 OUString
aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM
, OUString::number( 0 ) ) );//todo: other index if more than one diagram is possible
3146 uno::Reference
< drawing::XShapes
> xDiagramPlusAxesPlusMarkHandlesGroup_Shapes(
3147 pShapeFactory
->createGroup2D(mxRootShape
,aDiagramCID
) );
3149 aParam
.mxMarkHandles
= pShapeFactory
->createInvisibleRectangle(
3150 xDiagramPlusAxesPlusMarkHandlesGroup_Shapes
, awt::Size(0,0));
3151 AbstractShapeFactory::setShapeName(aParam
.mxMarkHandles
, "MarkHandles");
3153 aParam
.mxPlotAreaWithAxes
= pShapeFactory
->createInvisibleRectangle(
3154 xDiagramPlusAxesPlusMarkHandlesGroup_Shapes
, awt::Size(0, 0));
3155 AbstractShapeFactory::setShapeName(aParam
.mxPlotAreaWithAxes
, "PlotAreaIncludingAxes");
3157 aParam
.mxDiagramWithAxesShapes
= pShapeFactory
->createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes
);
3159 bool bAutoPositionDummy
= true;
3162 lcl_createButtons(mxRootShape
, m_xShapeFactory
, mrChartModel
, aParam
.maRemainingSpace
);
3165 TitleHelper::MAIN_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
,
3166 aParam
.maRemainingSpace
, rPageSize
, ALIGN_TOP
, bAutoPositionDummy
);
3167 if (aParam
.maRemainingSpace
.Width
<= 0 || aParam
.maRemainingSpace
.Height
<= 0)
3171 TitleHelper::SUB_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
,
3172 aParam
.maRemainingSpace
, rPageSize
, ALIGN_TOP
, bAutoPositionDummy
);
3173 if (aParam
.maRemainingSpace
.Width
<= 0|| aParam
.maRemainingSpace
.Height
<= 0)
3176 aParam
.mpSeriesPlotterContainer
.reset(new SeriesPlotterContainer(m_aVCooSysList
));
3177 aParam
.mpSeriesPlotterContainer
->initializeCooSysAndSeriesPlotter( mrChartModel
);
3178 if(maTimeBased
.bTimeBased
&& maTimeBased
.nFrame
!= 0)
3180 SeriesPlottersType
& rSeriesPlotter
= aParam
.mpSeriesPlotterContainer
->getSeriesPlotterList();
3181 size_t n
= rSeriesPlotter
.size();
3182 for(size_t i
= 0; i
< n
; ++i
)
3184 std::vector
<VDataSeries
*> aAllNewDataSeries
= rSeriesPlotter
[i
]->getAllSeries();
3185 std::vector
< VDataSeries
* >& rAllOldDataSeries
=
3186 maTimeBased
.m_aDataSeriesList
[i
];
3187 size_t m
= std::min(aAllNewDataSeries
.size(), rAllOldDataSeries
.size());
3188 for(size_t j
= 0; j
< m
; ++j
)
3190 aAllNewDataSeries
[j
]->setOldTimeBased(
3191 rAllOldDataSeries
[j
], (maTimeBased
.nFrame
% 60)/60.0);
3197 LegendHelper::getLegend( mrChartModel
), mxRootShape
, m_xShapeFactory
, m_xCC
,
3198 aParam
.maRemainingSpace
, rPageSize
, mrChartModel
, aParam
.mpSeriesPlotterContainer
->getLegendEntryProviderList(),
3199 lcl_getDefaultWritingModeFromPool( m_pDrawModelWrapper
) );
3200 if (aParam
.maRemainingSpace
.Width
<= 0 || aParam
.maRemainingSpace
.Height
<= 0)
3203 if (!createAxisTitleShapes2D(aParam
, rPageSize
))
3206 bool bDummy
= false;
3207 bool bIsVertical
= DiagramHelper::getVertical(xDiagram
, bDummy
, bDummy
);
3209 if (getAvailablePosAndSizeForDiagram(aParam
, rPageSize
, mrChartModel
.getFirstDiagram()))
3211 awt::Rectangle aUsedOuterRect
= impl_createDiagramAndContent(aParam
, rPageSize
);
3213 if (aParam
.mxPlotAreaWithAxes
.is())
3215 aParam
.mxPlotAreaWithAxes
->setPosition(awt::Point(aUsedOuterRect
.X
, aUsedOuterRect
.Y
));
3216 aParam
.mxPlotAreaWithAxes
->setSize(awt::Size(aUsedOuterRect
.Width
, aUsedOuterRect
.Height
));
3219 //correct axis title position
3220 awt::Rectangle
aDiagramPlusAxesRect( aUsedOuterRect
);
3221 if (aParam
.mbAutoPosTitleX
)
3222 changePositionOfAxisTitle(aParam
.mpVTitleX
.get(), ALIGN_BOTTOM
, aDiagramPlusAxesRect
, rPageSize
);
3223 if (aParam
.mbAutoPosTitleY
)
3224 changePositionOfAxisTitle(aParam
.mpVTitleY
.get(), ALIGN_LEFT
, aDiagramPlusAxesRect
, rPageSize
);
3225 if (aParam
.mbAutoPosTitleZ
)
3226 changePositionOfAxisTitle(aParam
.mpVTitleZ
.get(), ALIGN_Z
, aDiagramPlusAxesRect
, rPageSize
);
3227 if (aParam
.mbAutoPosSecondTitleX
)
3228 changePositionOfAxisTitle(aParam
.mpVTitleSecondX
.get(), bIsVertical
? ALIGN_RIGHT
: ALIGN_TOP
, aDiagramPlusAxesRect
, rPageSize
);
3229 if (aParam
.mbAutoPosSecondTitleY
)
3230 changePositionOfAxisTitle(aParam
.mpVTitleSecondY
.get(), bIsVertical
? ALIGN_TOP
: ALIGN_RIGHT
, aDiagramPlusAxesRect
, rPageSize
);
3233 //cleanup: remove all empty group shapes to avoid grey border lines:
3234 lcl_removeEmptyGroupShapes( mxRootShape
);
3238 if(maTimeBased
.bTimeBased
&& maTimeBased
.nFrame
% 60 == 0)
3240 // create copy of the data for next frame
3241 SeriesPlottersType
& rSeriesPlotter
= aParam
.mpSeriesPlotterContainer
->getSeriesPlotterList();
3242 size_t n
= rSeriesPlotter
.size();
3243 maTimeBased
.m_aDataSeriesList
.clear();
3244 maTimeBased
.m_aDataSeriesList
.resize(n
);
3245 for(size_t i
= 0; i
< n
; ++i
)
3247 std::vector
<VDataSeries
*> aAllNewDataSeries
= rSeriesPlotter
[i
]->getAllSeries();
3248 std::vector
<VDataSeries
*>& rAllOldDataSeries
= maTimeBased
.m_aDataSeriesList
[i
];
3249 size_t m
= aAllNewDataSeries
.size();
3250 for(size_t j
= 0; j
< m
; ++j
)
3252 rAllOldDataSeries
.push_back( aAllNewDataSeries
[j
]->
3253 createCopyForTimeBased() );
3257 maTimeBased
.maTimer
.Stop();
3260 if(maTimeBased
.bTimeBased
&& !maTimeBased
.maTimer
.IsActive())
3262 maTimeBased
.maTimer
.SetTimeout(15);
3263 maTimeBased
.maTimer
.SetInvokeHandler(LINK(this, ChartView
, UpdateTimeBased
));
3264 maTimeBased
.maTimer
.Start();
3268 bool ChartView::createAxisTitleShapes2D( CreateShapeParam2D
& rParam
, const css::awt::Size
& rPageSize
)
3270 uno::Reference
<XDiagram
> xDiagram
= mrChartModel
.getFirstDiagram();
3272 Reference
< chart2::XChartType
> xChartType( DiagramHelper::getChartTypeByIndex( xDiagram
, 0 ) );
3273 sal_Int32 nDimension
= DiagramHelper::getDimension( xDiagram
);
3275 if( ChartTypeHelper::isSupportingMainAxis( xChartType
, nDimension
, 0 ) )
3276 rParam
.mpVTitleX
= lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION
, mxRootShape
, m_xShapeFactory
, mrChartModel
3277 , rParam
.maRemainingSpace
, rPageSize
, ALIGN_BOTTOM
, rParam
.mbAutoPosTitleX
);
3278 if (rParam
.maRemainingSpace
.Width
<= 0 ||rParam
.maRemainingSpace
.Height
<= 0)
3281 if( ChartTypeHelper::isSupportingMainAxis( xChartType
, nDimension
, 1 ) )
3282 rParam
.mpVTitleY
= lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION
, mxRootShape
, m_xShapeFactory
, mrChartModel
3283 , rParam
.maRemainingSpace
, rPageSize
, ALIGN_LEFT
, rParam
.mbAutoPosTitleY
);
3284 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
3287 if( ChartTypeHelper::isSupportingMainAxis( xChartType
, nDimension
, 2 ) )
3288 rParam
.mpVTitleZ
= lcl_createTitle( TitleHelper::Z_AXIS_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
3289 , rParam
.maRemainingSpace
, rPageSize
, ALIGN_RIGHT
, rParam
.mbAutoPosTitleZ
);
3290 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
3293 bool bDummy
= false;
3294 bool bIsVertical
= DiagramHelper::getVertical( xDiagram
, bDummy
, bDummy
);
3296 if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType
, nDimension
) )
3297 rParam
.mpVTitleSecondX
= lcl_createTitle( TitleHelper::SECONDARY_X_AXIS_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
3298 , rParam
.maRemainingSpace
, rPageSize
, bIsVertical
? ALIGN_RIGHT
: ALIGN_TOP
, rParam
.mbAutoPosSecondTitleX
);
3299 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
3302 if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType
, nDimension
) )
3303 rParam
.mpVTitleSecondY
= lcl_createTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
3304 , rParam
.maRemainingSpace
, rPageSize
, bIsVertical
? ALIGN_TOP
: ALIGN_RIGHT
, rParam
.mbAutoPosSecondTitleY
);
3305 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
3311 void ChartView::createShapes3D()
3313 #if HAVE_FEATURE_OPENGL
3314 OpenGLWindow
* pWindow
= mrChartModel
.getOpenGLWindow();
3318 if( pWindow
->GetSizePixel().Width() == 0 || pWindow
->GetSizePixel().Height() == 0 )
3320 awt::Size aPageSize
= mrChartModel
.getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
3321 Size aSize
= pWindow
->LogicToPixel(Size(aPageSize
.Width
, aPageSize
.Height
), MapMode(MapUnit::Map100thMM
));
3322 pWindow
->SetSizePixel(aSize
);
3325 uno::Reference
< XDiagram
> xDiagram( mrChartModel
.getFirstDiagram() );
3326 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
3327 if( !xCooSysContainer
.is())
3330 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
3332 if (aCooSysList
.getLength() != 1)
3333 // Supporting multiple coordinates in a truly 3D chart (which implies
3334 // it's a Cartesian coordinate system) is a bit of a challenge, if not
3338 uno::Reference
<XCoordinateSystem
> xCooSys( aCooSysList
[0] );
3340 //iterate through all chart types in the current coordinate system
3341 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
3342 OSL_ASSERT( xChartTypeContainer
.is());
3343 if( !xChartTypeContainer
.is() )
3346 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
3347 if (aChartTypeList
.getLength() != 1)
3348 // Likewise, we can't really support multiple chart types here.
3351 uno::Reference
< XChartType
> xChartType( aChartTypeList
[0] );
3353 if (!m_pGL3DPlotter
)
3355 m_pGL3DPlotter
.reset(new GL3DBarChart(xChartType
, pWindow
));
3359 GL3DBarChart
* pChart
= dynamic_cast<GL3DBarChart
*>(m_pGL3DPlotter
.get());
3361 pChart
->setOpenGLWindow(pWindow
);
3364 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xChartType
, uno::UNO_QUERY
);
3365 OSL_ASSERT( xDataSeriesContainer
.is());
3366 if( !xDataSeriesContainer
.is() )
3369 std::vector
<std::unique_ptr
<VDataSeries
> > aDataSeries
;
3370 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
3371 for( sal_Int32 nS
= 0; nS
< aSeriesList
.getLength(); ++nS
)
3373 uno::Reference
< XDataSeries
> xDataSeries( aSeriesList
[nS
], uno::UNO_QUERY
);
3374 if(!xDataSeries
.is())
3377 aDataSeries
.push_back(o3tl::make_unique
<VDataSeries
>(xDataSeries
));
3380 std::unique_ptr
<ExplicitCategoriesProvider
> pCatProvider(new ExplicitCategoriesProvider(xCooSys
, mrChartModel
));
3382 m_pGL3DPlotter
->create3DShapes(aDataSeries
, *pCatProvider
);
3384 m_pGL3DPlotter
->render();
3388 #if HAVE_FEATURE_OPENGL
3390 void ChartView::updateOpenGLWindow()
3392 if(!isReal3DChart())
3393 mp2DRenderer
->updateOpenGLWindow();
3400 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
3401 com_sun_star_comp_chart2_ChartView_get_implementation(css::uno::XComponentContext
*context
,
3402 css::uno::Sequence
<css::uno::Any
> const &)
3404 ::chart::ChartModel
*pChartModel
= new ::chart::ChartModel(context
);
3405 return cppu::acquire(new ::chart::ChartView(context
, *pChartModel
));
3408 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */