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_feature_desktop.h>
22 #include <ChartView.hxx>
23 #include <chartview/DrawModelWrapper.hxx>
24 #include <NumberFormatterWrapper.hxx>
25 #include <VDiagram.hxx>
27 #include "VButton.hxx"
28 #include <ShapeFactory.hxx>
29 #include <VCoordinateSystem.hxx>
30 #include <VSeriesPlotter.hxx>
31 #include <CommonConverters.hxx>
32 #include <TitleHelper.hxx>
33 #include <LegendHelper.hxx>
34 #include "VLegend.hxx"
35 #include <PropertyMapper.hxx>
36 #include <ChartModel.hxx>
37 #include <ChartTypeHelper.hxx>
38 #include <ScaleAutomatism.hxx>
39 #include <ObjectIdentifier.hxx>
40 #include <DiagramHelper.hxx>
41 #include <RelativePositionHelper.hxx>
42 #include <servicenames.hxx>
43 #include <AxisHelper.hxx>
44 #include <AxisIndexDefines.hxx>
45 #include <BaseGFXHelper.hxx>
46 #include <DataSeriesHelper.hxx>
47 #include <DateHelper.hxx>
48 #include <ExplicitCategoriesProvider.hxx>
49 #include <defines.hxx>
50 #include <unonames.hxx>
51 #include <editeng/frmdiritem.hxx>
52 #include <tools/globname.hxx>
53 #include <comphelper/fileformat.h>
54 #include <comphelper/scopeguard.hxx>
55 #include <comphelper/servicehelper.hxx>
56 #include <cppuhelper/supportsservice.hxx>
57 #include <unotools/streamwrap.hxx>
58 #include <svx/svdpage.hxx>
59 #include <svx/unopage.hxx>
60 #include <svx/unoshape.hxx>
61 #include <vcl/svapp.hxx>
62 #include <osl/mutex.hxx>
63 #include <svx/unofill.hxx>
64 #include <drawinglayer/XShapeDumper.hxx>
68 #include <com/sun/star/awt/Size.hpp>
69 #include <com/sun/star/awt/Point.hpp>
70 #include <com/sun/star/chart/ChartAxisPosition.hpp>
71 #include <com/sun/star/chart/TimeUnit.hpp>
72 #include <com/sun/star/chart2/AxisType.hpp>
73 #include <com/sun/star/chart2/StackingDirection.hpp>
74 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
75 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
76 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
77 #include <com/sun/star/chart2/RelativePosition.hpp>
78 #include <com/sun/star/chart2/RelativeSize.hpp>
79 #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
80 #include <com/sun/star/chart2/data/PivotTableFieldEntry.hpp>
81 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
82 #include <com/sun/star/drawing/XShapeGroup.hpp>
83 #include <com/sun/star/embed/Aspects.hpp>
84 #include <com/sun/star/io/XSeekable.hpp>
85 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
86 #include <com/sun/star/util/XRefreshable.hpp>
87 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
88 #include <com/sun/star/text/XText.hpp>
89 #include <com/sun/star/text/XTextDocument.hpp>
90 #include <com/sun/star/text/WritingMode2.hpp>
91 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
92 #include <com/sun/star/view/XSelectionSupplier.hpp>
93 #include <svl/itempool.hxx>
94 #include <svl/languageoptions.hxx>
95 #include <comphelper/classids.hxx>
96 #include <servicenames_charttypes.hxx>
99 #include <rtl/ustring.hxx>
100 #include <sal/log.hxx>
102 #include <tools/diagnose_ex.h>
103 #include <tools/stream.hxx>
106 namespace com
{ namespace sun
{ namespace star
{ namespace chart2
{ class XChartDocument
; } } } }
110 using namespace ::com::sun::star
;
111 using namespace ::com::sun::star::chart2
;
112 using ::com::sun::star::uno::Reference
;
113 using ::com::sun::star::uno::Sequence
;
114 using ::com::sun::star::uno::Any
;
118 class theExplicitValueProviderUnoTunnelId
: public rtl::Static
<UnoTunnelIdInit
, theExplicitValueProviderUnoTunnelId
> {};
120 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
121 typedef std::map
< VCoordinateSystem
*, tFullAxisIndex
> tCoordinateSystemMap
;
123 /** This class handles a collection of coordinate systems and is used for
124 * executing some action on all coordinate systems such as
125 * `prepareAutomaticAxisScaling` and `setExplicitScaleAndIncrement`.
126 * Moreover it contains the `aAutoScaling` object that is an instance of
127 * the `ScaleAutomatism` class. The initialization of `aAutoScaling` is
128 * performed in the `SeriesPlotterContainer::initAxisUsageList` method and is
129 * used in the `SeriesPlotterContainer::doAutoScaling` for calculating explicit
130 * scale and increment objects (see `SeriesPlotterContainer::doAutoScaling`).
137 void addCoordinateSystem( VCoordinateSystem
* pCooSys
, sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
);
138 std::vector
< VCoordinateSystem
* > getCoordinateSystems( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
);
139 sal_Int32
getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex
);
141 void prepareAutomaticAxisScaling( ScaleAutomatism
& rScaleAutomatism
, sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
);
142 void setExplicitScaleAndIncrement( sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
, const ExplicitScaleData
& rScale
, const ExplicitIncrementData
& rInc
);
144 ScaleAutomatism aAutoScaling
;
147 tCoordinateSystemMap aCoordinateSystems
;
148 std::map
< sal_Int32
, sal_Int32
> aMaxIndexPerDimension
;
151 AxisUsage::AxisUsage()
152 : aAutoScaling(AxisHelper::createDefaultScale(), Date(Date::SYSTEM
))
156 AxisUsage::~AxisUsage()
158 aCoordinateSystems
.clear();
161 void AxisUsage::addCoordinateSystem( VCoordinateSystem
* pCooSys
, sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
166 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
167 tCoordinateSystemMap::const_iterator
aFound( aCoordinateSystems
.find(pCooSys
) );
169 //use one scale only once for each coordinate system
170 //main axis are preferred over secondary axis
171 //value scales are preferred
172 if(aFound
!=aCoordinateSystems
.end())
174 sal_Int32 nFoundAxisIndex
= aFound
->second
.second
;
175 if( nFoundAxisIndex
< nAxisIndex
)
177 sal_Int32 nFoundDimension
= aFound
->second
.first
;
178 if( nFoundDimension
==1 )
180 if( nFoundDimension
< nDimensionIndex
)
183 aCoordinateSystems
[pCooSys
] = aFullAxisIndex
;
185 //set maximum scale index
186 std::map
< sal_Int32
, sal_Int32
>::const_iterator aIter
= aMaxIndexPerDimension
.find(nDimensionIndex
);
187 if( aIter
!= aMaxIndexPerDimension
.end() )
189 sal_Int32 nCurrentMaxIndex
= aIter
->second
;
190 if( nCurrentMaxIndex
< nAxisIndex
)
191 aMaxIndexPerDimension
[nDimensionIndex
]=nAxisIndex
;
194 aMaxIndexPerDimension
[nDimensionIndex
]=nAxisIndex
;
197 std::vector
< VCoordinateSystem
* > AxisUsage::getCoordinateSystems( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
199 std::vector
< VCoordinateSystem
* > aRet
;
201 for (auto const& coordinateSystem
: aCoordinateSystems
)
203 if( coordinateSystem
.second
.first
!= nDimensionIndex
)
205 if( coordinateSystem
.second
.second
!= nAxisIndex
)
207 aRet
.push_back( coordinateSystem
.first
);
213 sal_Int32
AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex
)
216 std::map
< sal_Int32
, sal_Int32
>::const_iterator aIter
= aMaxIndexPerDimension
.find(nDimensionIndex
);
217 if( aIter
!= aMaxIndexPerDimension
.end() )
218 nRet
= aIter
->second
;
222 void AxisUsage::prepareAutomaticAxisScaling( ScaleAutomatism
& rScaleAutomatism
, sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
)
224 std::vector
<VCoordinateSystem
*> aVCooSysList
= getCoordinateSystems(nDimIndex
, nAxisIndex
);
225 for (VCoordinateSystem
* i
: aVCooSysList
)
226 i
->prepareAutomaticAxisScaling(rScaleAutomatism
, nDimIndex
, nAxisIndex
);
229 void AxisUsage::setExplicitScaleAndIncrement(
230 sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
, const ExplicitScaleData
& rScale
, const ExplicitIncrementData
& rInc
)
232 std::vector
<VCoordinateSystem
*> aVCooSysList
= getCoordinateSystems(nDimIndex
, nAxisIndex
);
233 for (VCoordinateSystem
* i
: aVCooSysList
)
234 i
->setExplicitScaleAndIncrement(nDimIndex
, nAxisIndex
, rScale
, rInc
);
237 typedef std::vector
<std::unique_ptr
<VSeriesPlotter
> > SeriesPlottersType
;
239 /** This class is a container of `SeriesPlotter` objects (such as `PieChart`
240 * instances). It is used for initializing coordinate systems, axes and scales
241 * of all series plotters which belongs to the container.
243 class SeriesPlotterContainer
246 explicit SeriesPlotterContainer( std::vector
< std::unique_ptr
<VCoordinateSystem
> >& rVCooSysList
);
247 ~SeriesPlotterContainer();
249 /** It is used to set coordinate systems (`m_rVCooSysList`), this method
250 * is invoked by `ChartView::createShapes2D` before of
251 * `ChartView::impl_createDiagramAndContent`.
252 * Coordinate systems are retrieved through the `XCoordinateSystemContainer`
253 * interface implemented by a diagram object which is provided by the
254 * `ChartModel` object passed to the method (`rChartModel.getFirstDiagram()`).
256 * It is used for creating series plotters and appending them
257 * to `m_aSeriesPlotterList`. The created series plotters are initialized
258 * through data (number formats supplier, color scheme, data series),
259 * extracted from the chart model or the diagram objects. An exception is
260 * the explicit category provider that is retrieved through the
261 * `VCoordinateSystem` object used by the series plotter.
263 * It sets the minimum-maximum supplier for a coordinate system:
264 * this supplier is the series plotter itself which utilizes the given
265 * coordinate system. In fact `VSeriesPlotter` has `MinimumMaximumSupplier`
266 * as one of its base classes.
267 * Hence, for instance, a `PieChart`, which is a series plotter, is
268 * a `MinimumMaximumSupplier`, too.
270 void initializeCooSysAndSeriesPlotter( ChartModel
& rModel
);
272 /** This method is invoked by `ChartView::impl_createDiagramAndContent`.
273 * It iterates on every axis of every coordinate systems, and if the axis
274 * is not yet present in `m_aAxisUsageList` it creates a new `AxisUsage`
275 * object and initialize its `aAutoScaling` member to the `ScaleData`
276 * object of the current axis.
278 void initAxisUsageList(const Date
& rNullDate
);
281 * Perform automatic axis scaling and determine the amount and spacing of
282 * increments. It assumes that the caller has determined the size of the
283 * largest axis label text object prior to calling this method.
285 * The new axis scaling data will be stored in the VCoordinateSystem
286 * objects. The label alignment direction for each axis will also get
287 * determined during this process, and stored in VAxis.
289 * This method is invoked by `ChartView::impl_createDiagramAndContent`
290 * soon after `initAxisUsageList`.
291 * It initializes explicit scale and increment objects for all coordinate
292 * systems in `m_rVCooSysList`.
293 * This action is achieved by iterating on the `m_aAxisUsageList` container,
294 * and performing 3 steps:
295 * 1- call `VCoordinateSystem::prepareAutomaticAxisScaling` for setting
296 * scaling parameters of the `aAutoScaling` member (a `ScaleAutomatism`
297 * object) for the current `AxisUsage` instance
298 * (see `VCoordinateSystem::prepareAutomaticAxisScaling`);
299 * 2- calculate the explicit scale and increment objects
300 * (see ScaleAutomatism::calculateExplicitScaleAndIncrement);
301 * 3- set the explicit scale and increment objects for each coordinate
304 void doAutoScaling( ChartModel
& rModel
);
307 * After auto-scaling is performed, call this method to set the explicit
308 * scaling and increment data to all relevant VAxis objects.
310 void updateScalesAndIncrementsOnAxes();
313 * After auto-scaling is performed, call this method to set the explicit
314 * scaling data to all the plotters.
316 void setScalesFromCooSysToPlotter();
318 void setNumberFormatsFromAxes();
319 drawing::Direction3D
getPreferredAspectRatio();
321 SeriesPlottersType
& getSeriesPlotterList() { return m_aSeriesPlotterList
; }
322 std::vector
< std::unique_ptr
<VCoordinateSystem
> >& getCooSysList() { return m_rVCooSysList
; }
323 std::vector
< LegendEntryProvider
* > getLegendEntryProviderList();
325 void AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel
& rModel
);
327 static bool isCategoryPositionShifted(
328 const chart2::ScaleData
& rSourceScale
, bool bHasComplexCategories
);
331 /** A vector of series plotters.
333 SeriesPlottersType m_aSeriesPlotterList
;
335 /** A vector of coordinate systems.
337 std::vector
< std::unique_ptr
<VCoordinateSystem
> >& m_rVCooSysList
;
339 /** A map whose key is a `XAxis` interface and the related value is
340 * an object of `AxisUsage` type.
342 std::map
< uno::Reference
< XAxis
>, AxisUsage
> m_aAxisUsageList
;
345 * Max axis index of all dimensions. Currently this can be either 0 or 1
346 * since we only support primary and secondary axes per dimension. The
347 * value of 0 means all dimensions have only primary axis, while 1 means
348 * at least one dimension has a secondary axis.
350 sal_Int32 m_nMaxAxisIndex
;
352 sal_Int32 m_nDefaultDateNumberFormat
;
355 SeriesPlotterContainer::SeriesPlotterContainer( std::vector
< std::unique_ptr
<VCoordinateSystem
> >& rVCooSysList
)
356 : m_rVCooSysList( rVCooSysList
)
358 , m_nDefaultDateNumberFormat(0)
362 SeriesPlotterContainer::~SeriesPlotterContainer()
364 // - remove plotter from coordinatesystems
365 for(auto & nC
: m_rVCooSysList
)
366 nC
->clearMinimumAndMaximumSupplierList();
369 std::vector
< LegendEntryProvider
* > SeriesPlotterContainer::getLegendEntryProviderList()
371 std::vector
< LegendEntryProvider
* > aRet( m_aSeriesPlotterList
.size() );
373 for( const std::unique_ptr
<VSeriesPlotter
>& aPlotter
: m_aSeriesPlotterList
)
374 aRet
[nN
++] = aPlotter
.get();
378 VCoordinateSystem
* findInCooSysList( const std::vector
< std::unique_ptr
<VCoordinateSystem
> >& rVCooSysList
379 , const uno::Reference
< XCoordinateSystem
>& xCooSys
)
381 for(auto & pVCooSys
: rVCooSysList
)
383 if(pVCooSys
->getModel()==xCooSys
)
384 return pVCooSys
.get();
389 VCoordinateSystem
* lcl_getCooSysForPlotter( const std::vector
< std::unique_ptr
<VCoordinateSystem
> >& rVCooSysList
, MinimumAndMaximumSupplier
* pMinimumAndMaximumSupplier
)
391 if(!pMinimumAndMaximumSupplier
)
393 for(auto & pVCooSys
: rVCooSysList
)
395 if(pVCooSys
->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier
))
396 return pVCooSys
.get();
401 VCoordinateSystem
* addCooSysToList( std::vector
< std::unique_ptr
<VCoordinateSystem
> >& rVCooSysList
402 , const uno::Reference
< XCoordinateSystem
>& xCooSys
403 , ChartModel
& rChartModel
)
405 VCoordinateSystem
* pExistingVCooSys
= findInCooSysList( rVCooSysList
, xCooSys
);
406 if( pExistingVCooSys
)
407 return pExistingVCooSys
;
409 std::unique_ptr
<VCoordinateSystem
> pVCooSys
= VCoordinateSystem::createCoordinateSystem(xCooSys
);
413 OUString
aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys
, rChartModel
) );
414 pVCooSys
->setParticle(aCooSysParticle
);
416 pVCooSys
->setExplicitCategoriesProvider( new ExplicitCategoriesProvider(xCooSys
, rChartModel
) );
417 rVCooSysList
.push_back( std::move(pVCooSys
) );
418 return rVCooSysList
.back().get();
421 void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(
422 ChartModel
& rChartModel
)
424 uno::Reference
< XDiagram
> xDiagram( rChartModel
.getFirstDiagram() );
428 uno::Reference
< util::XNumberFormatsSupplier
> xNumberFormatsSupplier( static_cast< ::cppu::OWeakObject
* >( &rChartModel
), uno::UNO_QUERY
);
429 if( rChartModel
.hasInternalDataProvider() && DiagramHelper::isSupportingDateAxis( xDiagram
) )
430 m_nDefaultDateNumberFormat
=DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier
);
432 sal_Int32 nDimensionCount
= DiagramHelper::getDimension( xDiagram
);
435 //@todo handle mixed dimension
439 bool bSortByXValues
= false;
440 bool bConnectBars
= false;
441 bool bGroupBarsPerAxis
= true;
442 bool bIncludeHiddenCells
= true;
443 bool bSecondaryYaxisVisible
= true;
444 sal_Int32 nStartingAngle
= 90;
445 sal_Int32 n3DRelativeHeight
= 100;
448 uno::Reference
< beans::XPropertySet
> xDiaProp( xDiagram
, uno::UNO_QUERY_THROW
);
449 xDiaProp
->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES
) >>= bSortByXValues
;
450 xDiaProp
->getPropertyValue( "ConnectBars" ) >>= bConnectBars
;
451 xDiaProp
->getPropertyValue( "GroupBarsPerAxis" ) >>= bGroupBarsPerAxis
;
452 xDiaProp
->getPropertyValue( "IncludeHiddenCells" ) >>= bIncludeHiddenCells
;
453 xDiaProp
->getPropertyValue( "StartingAngle" ) >>= nStartingAngle
;
455 if (nDimensionCount
== 3)
457 xDiaProp
->getPropertyValue( "3DRelativeHeight" ) >>= n3DRelativeHeight
;
460 catch( const uno::Exception
& )
462 DBG_UNHANDLED_EXCEPTION("chart2" );
465 //prepare for autoscaling and shape creation
466 // - create plotter for charttypes (for each first scale group at each plotter, as they are independent)
467 // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling)
468 // - add plotter to coordinate systems
470 //iterate through all coordinate systems
471 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
472 OSL_ASSERT( xCooSysContainer
.is());
473 if( !xCooSysContainer
.is())
475 uno::Reference
< XColorScheme
> xColorScheme( xDiagram
->getDefaultColorScheme());
476 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
477 sal_Int32 nGlobalSeriesIndex
= 0;//for automatic symbols
478 for( sal_Int32 nCS
= 0; nCS
< aCooSysList
.getLength(); ++nCS
)
480 uno::Reference
< XCoordinateSystem
> xCooSys( aCooSysList
[nCS
] );
481 VCoordinateSystem
* pVCooSys
= addCooSysToList(m_rVCooSysList
,xCooSys
,rChartModel
);
482 // Let's check whether the secondary Y axis is visible
485 Reference
< beans::XPropertySet
> xAxisProp(xCooSys
->getAxisByDimension(1, 1), uno::UNO_QUERY
);
488 xAxisProp
->getPropertyValue("Show") >>= bSecondaryYaxisVisible
;
491 catch (const lang::IndexOutOfBoundsException
&)
493 TOOLS_WARN_EXCEPTION("chart2", "" );
495 //iterate through all chart types in the current coordinate system
496 uno::Reference
< XChartTypeContainer
> xChartTypeContainer( xCooSys
, uno::UNO_QUERY
);
497 OSL_ASSERT( xChartTypeContainer
.is());
498 if( !xChartTypeContainer
.is() )
500 uno::Sequence
< uno::Reference
< XChartType
> > aChartTypeList( xChartTypeContainer
->getChartTypes() );
501 for( sal_Int32 nT
= 0; nT
< aChartTypeList
.getLength(); ++nT
)
503 uno::Reference
< XChartType
> xChartType( aChartTypeList
[nT
] );
504 if(nDimensionCount
== 3 && xChartType
->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE
))
506 uno::Reference
< beans::XPropertySet
> xPropertySet( xChartType
, uno::UNO_QUERY
);
507 if (xPropertySet
.is())
511 sal_Int32
n3DRelativeHeightOldValue(100);
512 uno::Any aAny
= xPropertySet
->getPropertyValue( "3DRelativeHeight" );
513 aAny
>>= n3DRelativeHeightOldValue
;
514 if (n3DRelativeHeightOldValue
!= n3DRelativeHeight
)
515 xPropertySet
->setPropertyValue( "3DRelativeHeight", uno::Any(n3DRelativeHeight
) );
517 catch (const uno::Exception
&) { }
521 bool bExcludingPositioning
= DiagramHelper::getDiagramPositioningMode( xDiagram
) == DiagramPositioningMode_EXCLUDING
;
522 VSeriesPlotter
* pPlotter
= VSeriesPlotter::createSeriesPlotter( xChartType
, nDimensionCount
, bExcludingPositioning
);
526 m_aSeriesPlotterList
.push_back( std::unique_ptr
<VSeriesPlotter
>(pPlotter
) );
527 pPlotter
->setNumberFormatsSupplier( xNumberFormatsSupplier
);
528 pPlotter
->setColorScheme( xColorScheme
);
530 pPlotter
->setExplicitCategoriesProvider( pVCooSys
->getExplicitCategoriesProvider() );
531 sal_Int32 nMissingValueTreatment
= DiagramHelper::getCorrectedMissingValueTreatment( xDiagram
, xChartType
);
534 pVCooSys
->addMinimumAndMaximumSupplier(pPlotter
);
536 uno::Reference
< XDataSeriesContainer
> xDataSeriesContainer( xChartType
, uno::UNO_QUERY
);
537 OSL_ASSERT( xDataSeriesContainer
.is());
538 if( !xDataSeriesContainer
.is() )
544 uno::Sequence
< uno::Reference
< XDataSeries
> > aSeriesList( xDataSeriesContainer
->getDataSeries() );
545 for( sal_Int32 nS
= 0; nS
< aSeriesList
.getLength(); ++nS
)
547 uno::Reference
< XDataSeries
> xDataSeries( aSeriesList
[nS
], uno::UNO_QUERY
);
548 if(!xDataSeries
.is())
550 if( !bIncludeHiddenCells
&& !DataSeriesHelper::hasUnhiddenData(xDataSeries
) )
553 std::unique_ptr
<VDataSeries
> pSeries(new VDataSeries( xDataSeries
));
555 pSeries
->setGlobalSeriesIndex(nGlobalSeriesIndex
);
556 nGlobalSeriesIndex
++;
559 pSeries
->doSortByXValues();
561 pSeries
->setConnectBars( bConnectBars
);
562 pSeries
->setGroupBarsPerAxis( bGroupBarsPerAxis
);
563 pSeries
->setStartingAngle( nStartingAngle
);
565 pSeries
->setMissingValueTreatment( nMissingValueTreatment
);
567 OUString
aSeriesParticle( ObjectIdentifier::createParticleForSeries( 0, nCS
, nT
, nS
) );
568 pSeries
->setParticle(aSeriesParticle
);
570 OUString
aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType
) );
571 pSeries
->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole
);
573 //ignore secondary axis for charttypes that do not support them
574 if( pSeries
->getAttachedAxisIndex() != MAIN_AXIS_INDEX
&&
575 ( !ChartTypeHelper::isSupportingSecondaryAxis( xChartType
, nDimensionCount
) ||
576 !bSecondaryYaxisVisible
) )
578 pSeries
->setAttachedAxisIndex(MAIN_AXIS_INDEX
);
581 StackingDirection eDirection
= pSeries
->getStackingDirection();
584 case StackingDirection_NO_STACKING
:
589 case StackingDirection_Y_STACKING
:
596 case StackingDirection_Z_STACKING
:
597 zSlot
++; xSlot
=-1; ySlot
=-1;
600 // UNO enums have one additional auto-generated case
603 pPlotter
->addSeries( std::move(pSeries
), zSlot
, xSlot
, ySlot
);
608 //transport seriesnames to the coordinatesystems if needed
609 if( !m_aSeriesPlotterList
.empty() )
611 uno::Sequence
< OUString
> aSeriesNames
;
612 bool bSeriesNamesInitialized
= false;
613 for(auto & pVCooSys
: m_rVCooSysList
)
615 if( pVCooSys
->needSeriesNamesForAxis() )
617 if(!bSeriesNamesInitialized
)
619 aSeriesNames
= m_aSeriesPlotterList
[0]->getSeriesNames();
620 bSeriesNamesInitialized
= true;
622 pVCooSys
->setSeriesNamesForAxis( aSeriesNames
);
628 bool SeriesPlotterContainer::isCategoryPositionShifted(
629 const chart2::ScaleData
& rSourceScale
, bool bHasComplexCategories
)
631 if (rSourceScale
.AxisType
== AxisType::CATEGORY
&& rSourceScale
.ShiftedCategoryPosition
)
634 if (rSourceScale
.AxisType
== AxisType::CATEGORY
&& bHasComplexCategories
)
637 if (rSourceScale
.AxisType
== AxisType::DATE
)
640 if (rSourceScale
.AxisType
== AxisType::SERIES
)
646 void SeriesPlotterContainer::initAxisUsageList(const Date
& rNullDate
)
648 m_aAxisUsageList
.clear();
650 // Loop through coordinate systems in the diagram (though for now
651 // there should only be one coordinate system per diagram).
652 for (auto & pVCooSys
: m_rVCooSysList
)
654 uno::Reference
<XCoordinateSystem
> xCooSys
= pVCooSys
->getModel();
655 sal_Int32 nDimCount
= xCooSys
->getDimension();
657 for (sal_Int32 nDimIndex
= 0; nDimIndex
< nDimCount
; ++nDimIndex
)
659 bool bDateAxisAllowed
= ChartTypeHelper::isSupportingDateAxis(
660 AxisHelper::getChartTypeByIndex(xCooSys
, 0), nDimIndex
);
662 // Each dimension may have primary and secondary axes.
663 const sal_Int32 nMaxAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimIndex
);
664 for (sal_Int32 nAxisIndex
= 0; nAxisIndex
<= nMaxAxisIndex
; ++nAxisIndex
)
666 uno::Reference
<XAxis
> xAxis
= xCooSys
->getAxisByDimension(nDimIndex
, nAxisIndex
);
671 if (m_aAxisUsageList
.find(xAxis
) == m_aAxisUsageList
.end())
673 // Create axis usage object for this axis.
675 chart2::ScaleData aSourceScale
= xAxis
->getScaleData();
676 ExplicitCategoriesProvider
* pCatProvider
= pVCooSys
->getExplicitCategoriesProvider();
678 AxisHelper::checkDateAxis( aSourceScale
, pCatProvider
, bDateAxisAllowed
);
680 bool bHasComplexCat
= pCatProvider
&& pCatProvider
->hasComplexCategories();
681 aSourceScale
.ShiftedCategoryPosition
= isCategoryPositionShifted(aSourceScale
, bHasComplexCat
);
683 m_aAxisUsageList
[xAxis
].aAutoScaling
= ScaleAutomatism(aSourceScale
, rNullDate
);
686 AxisUsage
& rAxisUsage
= m_aAxisUsageList
[xAxis
];
687 rAxisUsage
.addCoordinateSystem(pVCooSys
.get(), nDimIndex
, nAxisIndex
);
692 // Determine the highest axis index of all dimensions.
694 for (const auto & pVCooSys
: m_rVCooSysList
)
696 uno::Reference
<XCoordinateSystem
> xCooSys
= pVCooSys
->getModel();
697 sal_Int32 nDimCount
= xCooSys
->getDimension();
699 for (sal_Int32 nDimIndex
= 0; nDimIndex
< nDimCount
; ++nDimIndex
)
701 for (auto & axisUsage
: m_aAxisUsageList
)
703 sal_Int32 nLocalMax
= axisUsage
.second
.getMaxAxisIndexForDimension(nDimIndex
);
704 if (m_nMaxAxisIndex
< nLocalMax
)
705 m_nMaxAxisIndex
= nLocalMax
;
711 void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
713 //set scales to plotter to enable them to provide the preferred scene AspectRatio
714 for( const std::unique_ptr
<VSeriesPlotter
>& aPlotter
: m_aSeriesPlotterList
)
716 VSeriesPlotter
* pSeriesPlotter
= aPlotter
.get();
717 VCoordinateSystem
* pVCooSys
= lcl_getCooSysForPlotter( m_rVCooSysList
, pSeriesPlotter
);
720 pSeriesPlotter
->setScales( pVCooSys
->getExplicitScales(0,0), pVCooSys
->getPropertySwapXAndYAxis() );
721 sal_Int32 nMaxAxisIndex
= pVCooSys
->getMaximumAxisIndexByDimension(1);//only additional value axis are relevant for series plotter
722 for( sal_Int32 nI
=1; nI
<=nMaxAxisIndex
; nI
++ )
723 pSeriesPlotter
->addSecondaryValueScale( pVCooSys
->getExplicitScale(1,nI
), nI
);
728 void SeriesPlotterContainer::setNumberFormatsFromAxes()
730 //set numberformats to plotter to enable them to display the data labels in the numberformat of the axis
731 for( const std::unique_ptr
<VSeriesPlotter
>& aPlotter
: m_aSeriesPlotterList
)
733 VSeriesPlotter
* pSeriesPlotter
= aPlotter
.get();
734 VCoordinateSystem
* pVCooSys
= lcl_getCooSysForPlotter( m_rVCooSysList
, pSeriesPlotter
);
737 AxesNumberFormats aAxesNumberFormats
;
738 const uno::Reference
< XCoordinateSystem
>& xCooSys
= pVCooSys
->getModel();
739 sal_Int32 nDimensionCount
= xCooSys
->getDimension();
740 for(sal_Int32 nDimensionIndex
=0; nDimensionIndex
<nDimensionCount
; ++nDimensionIndex
)
742 const sal_Int32 nMaximumAxisIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimensionIndex
);
743 for(sal_Int32 nAxisIndex
=0; nAxisIndex
<=nMaximumAxisIndex
; ++nAxisIndex
)
747 Reference
< beans::XPropertySet
> xAxisProp( xCooSys
->getAxisByDimension( nDimensionIndex
, nAxisIndex
), uno::UNO_QUERY
);
750 sal_Int32
nNumberFormatKey(0);
751 if( xAxisProp
->getPropertyValue(CHART_UNONAME_NUMFMT
) >>= nNumberFormatKey
)
753 aAxesNumberFormats
.setFormat( nNumberFormatKey
, nDimensionIndex
, nAxisIndex
);
755 else if( nDimensionIndex
==0 )
757 //provide a default date format for date axis with own data
758 aAxesNumberFormats
.setFormat( m_nDefaultDateNumberFormat
, nDimensionIndex
, nAxisIndex
);
762 catch( const lang::IndexOutOfBoundsException
& )
764 TOOLS_WARN_EXCEPTION("chart2", "" );
768 pSeriesPlotter
->setAxesNumberFormats( aAxesNumberFormats
);
773 void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
775 for(auto & nC
: m_rVCooSysList
)
776 nC
->updateScalesAndIncrementsOnAxes();
779 void SeriesPlotterContainer::doAutoScaling( ChartModel
& rChartModel
)
781 if (m_aSeriesPlotterList
.empty() || m_aAxisUsageList
.empty())
782 // We need these two containers populated to do auto-scaling. Bail out.
785 //iterate over the main scales first than secondary axis
786 for (sal_Int32 nAxisIndex
= 0; nAxisIndex
<= m_nMaxAxisIndex
; ++nAxisIndex
)
788 // - first do autoscale for all x and z scales (because they are treated independent)
789 for (auto & axisUsage
: m_aAxisUsageList
)
791 AxisUsage
& rAxisUsage
= axisUsage
.second
;
793 rAxisUsage
.prepareAutomaticAxisScaling(rAxisUsage
.aAutoScaling
, 0, nAxisIndex
);
794 rAxisUsage
.prepareAutomaticAxisScaling(rAxisUsage
.aAutoScaling
, 2, nAxisIndex
);
796 ExplicitScaleData aExplicitScale
;
797 ExplicitIncrementData aExplicitIncrement
;
798 rAxisUsage
.aAutoScaling
.calculateExplicitScaleAndIncrement( aExplicitScale
, aExplicitIncrement
);
800 rAxisUsage
.setExplicitScaleAndIncrement(0, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
801 rAxisUsage
.setExplicitScaleAndIncrement(2, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
804 // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already )
805 for (auto & axisUsage
: m_aAxisUsageList
)
807 AxisUsage
& rAxisUsage
= axisUsage
.second
;
809 rAxisUsage
.prepareAutomaticAxisScaling(rAxisUsage
.aAutoScaling
, 1, nAxisIndex
);
811 ExplicitScaleData aExplicitScale
;
812 ExplicitIncrementData aExplicitIncrement
;
813 rAxisUsage
.aAutoScaling
.calculateExplicitScaleAndIncrement( aExplicitScale
, aExplicitIncrement
);
815 rAxisUsage
.setExplicitScaleAndIncrement(0, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
816 rAxisUsage
.setExplicitScaleAndIncrement(1, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
817 rAxisUsage
.setExplicitScaleAndIncrement(2, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
820 AdaptScaleOfYAxisWithoutAttachedSeries( rChartModel
);
823 void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries( ChartModel
& rModel
)
826 for( sal_Int32 nAxisIndex
=0; nAxisIndex
<=m_nMaxAxisIndex
; nAxisIndex
++ )
828 for (auto & axisUsage
: m_aAxisUsageList
)
830 AxisUsage
& rAxisUsage
= axisUsage
.second
;
831 std::vector
< VCoordinateSystem
* > aVCooSysList_Y
= rAxisUsage
.getCoordinateSystems( 1, nAxisIndex
);
832 if( aVCooSysList_Y
.empty() )
835 uno::Reference
< XDiagram
> xDiagram( rModel
.getFirstDiagram() );
839 bool bSeriesAttachedToThisAxis
= false;
840 sal_Int32 nAttachedAxisIndex
= -1;
842 std::vector
< Reference
< XDataSeries
> > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram
) );
843 for (auto const& series
: aSeriesVector
)
845 sal_Int32 nCurrentIndex
= DataSeriesHelper::getAttachedAxisIndex(series
);
846 if( nAxisIndex
== nCurrentIndex
)
848 bSeriesAttachedToThisAxis
= true;
851 else if( nAttachedAxisIndex
<0 || nAttachedAxisIndex
>nCurrentIndex
)
852 nAttachedAxisIndex
=nCurrentIndex
;
856 if (bSeriesAttachedToThisAxis
|| nAttachedAxisIndex
< 0)
859 for(VCoordinateSystem
* nC
: aVCooSysList_Y
)
861 nC
->prepareAutomaticAxisScaling( rAxisUsage
.aAutoScaling
, 1, nAttachedAxisIndex
);
863 ExplicitScaleData aExplicitScaleSource
= nC
->getExplicitScale( 1,nAttachedAxisIndex
);
864 ExplicitIncrementData aExplicitIncrementSource
= nC
->getExplicitIncrement( 1,nAttachedAxisIndex
);
866 ExplicitScaleData aExplicitScaleDest
= nC
->getExplicitScale( 1,nAxisIndex
);
867 ExplicitIncrementData aExplicitIncrementDest
= nC
->getExplicitIncrement( 1,nAxisIndex
);
869 aExplicitScaleDest
.Orientation
= aExplicitScaleSource
.Orientation
;
870 aExplicitScaleDest
.Scaling
= aExplicitScaleSource
.Scaling
;
871 aExplicitScaleDest
.AxisType
= aExplicitScaleSource
.AxisType
;
873 aExplicitIncrementDest
.BaseValue
= aExplicitIncrementSource
.BaseValue
;
875 ScaleData
aScale( rAxisUsage
.aAutoScaling
.getScale() );
876 if( !aScale
.Minimum
.hasValue() )
878 bool bNewMinOK
= true;
880 if( aScale
.Maximum
>>= fMax
)
881 bNewMinOK
= (aExplicitScaleSource
.Minimum
<= fMax
);
883 aExplicitScaleDest
.Minimum
= aExplicitScaleSource
.Minimum
;
886 aExplicitIncrementDest
.BaseValue
= aExplicitScaleDest
.Minimum
;
888 if( !aScale
.Maximum
.hasValue() )
890 bool bNewMaxOK
= true;
892 if( aScale
.Minimum
>>= fMin
)
893 bNewMaxOK
= (fMin
<= aExplicitScaleSource
.Maximum
);
895 aExplicitScaleDest
.Maximum
= aExplicitScaleSource
.Maximum
;
897 if( !aScale
.Origin
.hasValue() )
898 aExplicitScaleDest
.Origin
= aExplicitScaleSource
.Origin
;
900 if( !aScale
.IncrementData
.Distance
.hasValue() )
901 aExplicitIncrementDest
.Distance
= aExplicitIncrementSource
.Distance
;
903 bool bAutoMinorInterval
= true;
904 if( aScale
.IncrementData
.SubIncrements
.hasElements() )
905 bAutoMinorInterval
= !( aScale
.IncrementData
.SubIncrements
[0].IntervalCount
.hasValue() );
906 if( bAutoMinorInterval
)
908 if( !aExplicitIncrementDest
.SubIncrements
.empty() && !aExplicitIncrementSource
.SubIncrements
.empty() )
909 aExplicitIncrementDest
.SubIncrements
[0].IntervalCount
=
910 aExplicitIncrementSource
.SubIncrements
[0].IntervalCount
;
913 nC
->setExplicitScaleAndIncrement( 1, nAxisIndex
, aExplicitScaleDest
, aExplicitIncrementDest
);
918 if( AxisHelper::isAxisPositioningEnabled() )
920 //correct origin for y main axis (the origin is where the other main axis crosses)
921 sal_Int32 nAxisIndex
=0;
922 sal_Int32 nDimensionIndex
=1;
923 for (auto & axisUsage
: m_aAxisUsageList
)
925 AxisUsage
& rAxisUsage
= axisUsage
.second
;
926 std::vector
< VCoordinateSystem
* > aVCooSysList
= rAxisUsage
.getCoordinateSystems(nDimensionIndex
,nAxisIndex
);
928 for( nC
=0; nC
< aVCooSysList
.size(); nC
++)
930 ExplicitScaleData
aExplicitScale( aVCooSysList
[nC
]->getExplicitScale( nDimensionIndex
, nAxisIndex
) );
931 ExplicitIncrementData
aExplicitIncrement( aVCooSysList
[nC
]->getExplicitIncrement( nDimensionIndex
, nAxisIndex
) );
933 Reference
< chart2::XCoordinateSystem
> xCooSys( aVCooSysList
[nC
]->getModel() );
934 Reference
< XAxis
> xAxis( xCooSys
->getAxisByDimension( nDimensionIndex
, nAxisIndex
) );
935 Reference
< beans::XPropertySet
> xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis
, xCooSys
), uno::UNO_QUERY
);
937 css::chart::ChartAxisPosition
eCrossingMainAxisPos( css::chart::ChartAxisPosition_ZERO
);
938 if( xCrossingMainAxis
.is() )
940 xCrossingMainAxis
->getPropertyValue("CrossoverPosition") >>= eCrossingMainAxisPos
;
941 if( eCrossingMainAxisPos
== css::chart::ChartAxisPosition_VALUE
)
944 xCrossingMainAxis
->getPropertyValue("CrossoverValue") >>= fValue
;
945 aExplicitScale
.Origin
= fValue
;
947 else if( eCrossingMainAxisPos
== css::chart::ChartAxisPosition_ZERO
)
948 aExplicitScale
.Origin
= 0.0;
949 else if( eCrossingMainAxisPos
== css::chart::ChartAxisPosition_START
)
950 aExplicitScale
.Origin
= aExplicitScale
.Minimum
;
951 else if( eCrossingMainAxisPos
== css::chart::ChartAxisPosition_END
)
952 aExplicitScale
.Origin
= aExplicitScale
.Maximum
;
955 aVCooSysList
[nC
]->setExplicitScaleAndIncrement( nDimensionIndex
, nAxisIndex
, aExplicitScale
, aExplicitIncrement
);
961 drawing::Direction3D
SeriesPlotterContainer::getPreferredAspectRatio()
963 drawing::Direction3D
aPreferredAspectRatio(1.0,1.0,1.0);
965 //get a list of all preferred aspect ratios and combine them
966 //first with special demands wins (less or equal zero <-> arbitrary)
969 for( const std::unique_ptr
<VSeriesPlotter
>& aPlotter
: m_aSeriesPlotterList
)
971 drawing::Direction3D
aSingleRatio( aPlotter
->getPreferredDiagramAspectRatio() );
972 if( fx
<0 && aSingleRatio
.DirectionX
>0 )
973 fx
= aSingleRatio
.DirectionX
;
975 if( fy
<0 && aSingleRatio
.DirectionY
>0 )
977 if( fx
>0 && aSingleRatio
.DirectionX
>0 )
978 fy
= fx
*aSingleRatio
.DirectionY
/aSingleRatio
.DirectionX
;
979 else if( fz
>0 && aSingleRatio
.DirectionZ
>0 )
980 fy
= fz
*aSingleRatio
.DirectionY
/aSingleRatio
.DirectionZ
;
982 fy
= aSingleRatio
.DirectionY
;
985 if( fz
<0 && aSingleRatio
.DirectionZ
>0 )
987 if( fx
>0 && aSingleRatio
.DirectionX
>0 )
988 fz
= fx
*aSingleRatio
.DirectionZ
/aSingleRatio
.DirectionX
;
989 else if( fy
>0 && aSingleRatio
.DirectionY
>0 )
990 fz
= fy
*aSingleRatio
.DirectionZ
/aSingleRatio
.DirectionY
;
992 fz
= aSingleRatio
.DirectionZ
;
995 if( fx
>0 && fy
>0 && fz
>0 )
998 aPreferredAspectRatio
= drawing::Direction3D(fx
, fy
, fz
);
999 return aPreferredAspectRatio
;
1004 struct CreateShapeParam2D
1006 css::awt::Rectangle maRemainingSpace
;
1008 std::shared_ptr
<SeriesPlotterContainer
> mpSeriesPlotterContainer
;
1010 std::shared_ptr
<VTitle
> mpVTitleX
;
1011 std::shared_ptr
<VTitle
> mpVTitleY
;
1012 std::shared_ptr
<VTitle
> mpVTitleZ
;
1014 std::shared_ptr
<VTitle
> mpVTitleSecondX
;
1015 std::shared_ptr
<VTitle
> mpVTitleSecondY
;
1017 css::uno::Reference
<css::drawing::XShape
> mxMarkHandles
;
1018 css::uno::Reference
<css::drawing::XShape
> mxPlotAreaWithAxes
;
1020 css::uno::Reference
<css::drawing::XShapes
> mxDiagramWithAxesShapes
;
1022 bool mbAutoPosTitleX
;
1023 bool mbAutoPosTitleY
;
1024 bool mbAutoPosTitleZ
;
1026 bool mbAutoPosSecondTitleX
;
1027 bool mbAutoPosSecondTitleY
;
1029 bool mbUseFixedInnerSize
;
1031 CreateShapeParam2D() :
1032 mbAutoPosTitleX(true),
1033 mbAutoPosTitleY(true),
1034 mbAutoPosTitleZ(true),
1035 mbAutoPosSecondTitleX(true),
1036 mbAutoPosSecondTitleY(true),
1037 mbUseFixedInnerSize(false) {}
1040 const uno::Sequence
<sal_Int8
>& ExplicitValueProvider::getUnoTunnelId()
1042 return theExplicitValueProviderUnoTunnelId::get().getSeq();
1045 ChartView::ChartView(
1046 uno::Reference
<uno::XComponentContext
> const & xContext
,
1050 , mrChartModel(rModel
)
1053 , m_pDrawModelWrapper()
1054 , m_aListenerContainer( m_aMutex
)
1055 , m_bViewDirty(true)
1056 , m_bInViewUpdate(false)
1057 , m_bViewUpdatePending(false)
1058 , m_bRefreshAddIn(true)
1059 , m_aPageResolution(1000,1000)
1060 , m_bPointsWereSkipped(false)
1061 , m_nScaleXNumerator(1)
1062 , m_nScaleXDenominator(1)
1063 , m_nScaleYNumerator(1)
1064 , m_nScaleYDenominator(1)
1065 , m_bSdrViewIsInEditMode(false)
1066 , m_aResultingDiagramRectangleExcludingAxes(0,0,0,0)
1071 void ChartView::init()
1073 if( !m_pDrawModelWrapper
.get() )
1075 SolarMutexGuard aSolarGuard
;
1076 m_pDrawModelWrapper
= std::make_shared
< DrawModelWrapper
>();
1077 m_xShapeFactory
= m_pDrawModelWrapper
->getShapeFactory();
1078 m_xDrawPage
= m_pDrawModelWrapper
->getMainDrawPage();
1079 StartListening( m_pDrawModelWrapper
->getSdrModel() );
1083 void SAL_CALL
ChartView::initialize( const uno::Sequence
< uno::Any
>& )
1088 ChartView::~ChartView()
1090 maTimeBased
.maTimer
.Stop();
1091 // #i120831#. In ChartView::initialize(), m_xShapeFactory is created from SdrModel::getUnoModel() and indirectly
1092 // from SfxBaseModel, it needs call dispose() to make sure SfxBaseModel object is freed correctly.
1093 uno::Reference
< lang::XComponent
> xComp( m_xShapeFactory
, uno::UNO_QUERY
);
1097 if( m_pDrawModelWrapper
.get() )
1099 SolarMutexGuard aSolarGuard
;
1100 EndListening( m_pDrawModelWrapper
->getSdrModel() );
1101 m_pDrawModelWrapper
.reset();
1103 m_xDrawPage
= nullptr;
1104 impl_deleteCoordinateSystems();
1107 void ChartView::impl_deleteCoordinateSystems()
1109 //delete all coordinate systems
1110 m_aVCooSysList
.clear();
1113 // datatransfer::XTransferable
1116 const OUString
lcl_aGDIMetaFileMIMEType(
1117 "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" );
1118 const OUString
lcl_aGDIMetaFileMIMETypeHighContrast(
1119 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" );
1120 } // anonymous namespace
1122 void ChartView::getMetaFile( const uno::Reference
< io::XOutputStream
>& xOutStream
1123 , bool bUseHighContrast
)
1125 if( !m_xDrawPage
.is() )
1128 // creating the graphic exporter
1129 uno::Reference
< drawing::XGraphicExportFilter
> xExporter
= drawing::GraphicExportFilter::create( m_xCC
);
1131 uno::Sequence
< beans::PropertyValue
> aProps(3);
1132 aProps
[0].Name
= "FilterName";
1133 aProps
[0].Value
<<= OUString("SVM");
1135 aProps
[1].Name
= "OutputStream";
1136 aProps
[1].Value
<<= xOutStream
;
1138 uno::Sequence
< beans::PropertyValue
> aFilterData(8);
1139 aFilterData
[0].Name
= "ExportOnlyBackground";
1140 aFilterData
[0].Value
<<= false;
1141 aFilterData
[1].Name
= "HighContrast";
1142 aFilterData
[1].Value
<<= bUseHighContrast
;
1144 aFilterData
[2].Name
= "Version";
1145 const sal_Int32 nVersion
= SOFFICE_FILEFORMAT_50
;
1146 aFilterData
[2].Value
<<= nVersion
;
1148 aFilterData
[3].Name
= "CurrentPage";
1149 aFilterData
[3].Value
<<= uno::Reference
< uno::XInterface
>( m_xDrawPage
, uno::UNO_QUERY
);
1151 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
1152 aFilterData
[4].Name
= "ScaleXNumerator";
1153 aFilterData
[4].Value
<<= m_nScaleXNumerator
;
1154 aFilterData
[5].Name
= "ScaleXDenominator";
1155 aFilterData
[5].Value
<<= m_nScaleXDenominator
;
1156 aFilterData
[6].Name
= "ScaleYNumerator";
1157 aFilterData
[6].Value
<<= m_nScaleYNumerator
;
1158 aFilterData
[7].Name
= "ScaleYDenominator";
1159 aFilterData
[7].Value
<<= m_nScaleYDenominator
;
1162 aProps
[2].Name
= "FilterData";
1163 aProps
[2].Value
<<= aFilterData
;
1165 xExporter
->setSourceDocument( uno::Reference
< lang::XComponent
>( m_xDrawPage
, uno::UNO_QUERY
) );
1166 if( xExporter
->filter( aProps
) )
1168 xOutStream
->flush();
1169 xOutStream
->closeOutput();
1170 uno::Reference
< io::XSeekable
> xSeekable( xOutStream
, uno::UNO_QUERY
);
1171 if( xSeekable
.is() )
1176 uno::Any SAL_CALL
ChartView::getTransferData( const datatransfer::DataFlavor
& aFlavor
)
1178 bool bHighContrastMetaFile( aFlavor
.MimeType
== lcl_aGDIMetaFileMIMETypeHighContrast
);
1180 if( ! (bHighContrastMetaFile
|| aFlavor
.MimeType
== lcl_aGDIMetaFileMIMEType
) )
1185 SvMemoryStream
aStream( 1024, 1024 );
1186 utl::OStreamWrapper
* pStreamWrapper
= new utl::OStreamWrapper( aStream
);
1188 uno::Reference
< io::XOutputStream
> xOutStream( pStreamWrapper
);
1189 uno::Reference
< io::XInputStream
> xInStream( pStreamWrapper
);
1190 uno::Reference
< io::XSeekable
> xSeekable( pStreamWrapper
);
1192 if( xOutStream
.is() )
1194 this->getMetaFile( xOutStream
, bHighContrastMetaFile
);
1196 if( xInStream
.is() && xSeekable
.is() )
1199 sal_Int32 nBytesToRead
= xInStream
->available();
1200 uno::Sequence
< sal_Int8
> aSeq( nBytesToRead
);
1201 xInStream
->readBytes( aSeq
, nBytesToRead
);
1203 xInStream
->closeInput();
1209 uno::Sequence
< datatransfer::DataFlavor
> SAL_CALL
ChartView::getTransferDataFlavors()
1211 uno::Sequence
< datatransfer::DataFlavor
> aRet(2);
1213 aRet
[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType
,
1215 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
1216 aRet
[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast
,
1218 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
1222 sal_Bool SAL_CALL
ChartView::isDataFlavorSupported( const datatransfer::DataFlavor
& aFlavor
)
1224 return ( aFlavor
.MimeType
== lcl_aGDIMetaFileMIMEType
||
1225 aFlavor
.MimeType
== lcl_aGDIMetaFileMIMETypeHighContrast
);
1228 // ____ XUnoTunnel ___
1229 ::sal_Int64 SAL_CALL
ChartView::getSomething( const uno::Sequence
< ::sal_Int8
>& aIdentifier
)
1231 if( isUnoTunnelId
<ExplicitValueProvider
>(aIdentifier
) )
1233 ExplicitValueProvider
* pProvider
= this;
1234 return reinterpret_cast<sal_Int64
>(pProvider
);
1239 // lang::XServiceInfo
1241 OUString SAL_CALL
ChartView::getImplementationName()
1243 return CHART_VIEW_SERVICE_IMPLEMENTATION_NAME
;
1246 sal_Bool SAL_CALL
ChartView::supportsService( const OUString
& rServiceName
)
1248 return cppu::supportsService(this, rServiceName
);
1251 css::uno::Sequence
< OUString
> SAL_CALL
ChartView::getSupportedServiceNames()
1253 return { CHART_VIEW_SERVICE_NAME
};
1256 static ::basegfx::B3DHomMatrix
createTransformationSceneToScreen(
1257 const ::basegfx::B2IRectangle
& rDiagramRectangleWithoutAxes
)
1259 ::basegfx::B3DHomMatrix aM
;
1260 aM
.scale(double(rDiagramRectangleWithoutAxes
.getWidth())/FIXED_SIZE_FOR_3D_CHART_VOLUME
1261 , -double(rDiagramRectangleWithoutAxes
.getHeight())/FIXED_SIZE_FOR_3D_CHART_VOLUME
, 1.0 );
1262 aM
.translate(double(rDiagramRectangleWithoutAxes
.getMinX())
1263 , double(rDiagramRectangleWithoutAxes
.getMinY()+rDiagramRectangleWithoutAxes
.getHeight()-1), 0);
1270 bool lcl_IsPieOrDonut( const uno::Reference
< XDiagram
>& xDiagram
)
1272 //special treatment for pie charts
1273 //the size is checked after complete creation to get the datalabels into the given space
1275 //todo: this is just a workaround at the moment for pie and donut labels
1276 return DiagramHelper::isPieOrDonutChart( xDiagram
);
1279 void lcl_setDefaultWritingMode( const std::shared_ptr
< DrawModelWrapper
>& pDrawModelWrapper
, ChartModel
& rModel
)
1281 //get writing mode from parent document:
1282 if( SvtLanguageOptions().IsCTLFontEnabled() )
1286 sal_Int16 nWritingMode
=-1;
1287 uno::Reference
< beans::XPropertySet
> xParentProps( rModel
.getParent(), uno::UNO_QUERY
);
1288 uno::Reference
< style::XStyleFamiliesSupplier
> xStyleFamiliesSupplier( xParentProps
, uno::UNO_QUERY
);
1289 if( xStyleFamiliesSupplier
.is() )
1291 uno::Reference
< container::XNameAccess
> xStylesFamilies( xStyleFamiliesSupplier
->getStyleFamilies() );
1292 if( xStylesFamilies
.is() )
1294 if( !xStylesFamilies
->hasByName( "PageStyles" ) )
1296 //draw/impress is parent document
1297 uno::Reference
< lang::XMultiServiceFactory
> xFatcory( xParentProps
, uno::UNO_QUERY
);
1300 uno::Reference
< beans::XPropertySet
> xDrawDefaults( xFatcory
->createInstance( "com.sun.star.drawing.Defaults" ), uno::UNO_QUERY
);
1301 if( xDrawDefaults
.is() )
1302 xDrawDefaults
->getPropertyValue( "WritingMode" ) >>= nWritingMode
;
1307 uno::Reference
< container::XNameAccess
> xPageStyles( xStylesFamilies
->getByName( "PageStyles" ), uno::UNO_QUERY
);
1308 if( xPageStyles
.is() )
1310 OUString aPageStyle
;
1312 uno::Reference
< text::XTextDocument
> xTextDocument( xParentProps
, uno::UNO_QUERY
);
1313 if( xTextDocument
.is() )
1315 //writer is parent document
1316 //retrieve the current page style from the text cursor property PageStyleName
1318 uno::Reference
< text::XTextEmbeddedObjectsSupplier
> xTextEmbeddedObjectsSupplier( xTextDocument
, uno::UNO_QUERY
);
1319 if( xTextEmbeddedObjectsSupplier
.is() )
1321 uno::Reference
< container::XNameAccess
> xEmbeddedObjects( xTextEmbeddedObjectsSupplier
->getEmbeddedObjects() );
1322 if( xEmbeddedObjects
.is() )
1324 uno::Sequence
< OUString
> aNames( xEmbeddedObjects
->getElementNames() );
1326 sal_Int32 nCount
= aNames
.getLength();
1327 for( sal_Int32 nN
=0; nN
<nCount
; nN
++ )
1329 uno::Reference
< beans::XPropertySet
> xEmbeddedProps( xEmbeddedObjects
->getByName( aNames
[nN
] ), uno::UNO_QUERY
);
1330 if( xEmbeddedProps
.is() )
1332 static OUString aChartCLSID
= SvGlobalName( SO3_SCH_CLASSID
).GetHexName();
1334 xEmbeddedProps
->getPropertyValue( "CLSID" ) >>= aCLSID
;
1335 if( aCLSID
== aChartCLSID
)
1337 uno::Reference
< text::XTextContent
> xEmbeddedObject( xEmbeddedProps
, uno::UNO_QUERY
);
1338 if( xEmbeddedObject
.is() )
1340 uno::Reference
< text::XTextRange
> xAnchor( xEmbeddedObject
->getAnchor() );
1343 uno::Reference
< beans::XPropertySet
> xAnchorProps( xAnchor
, uno::UNO_QUERY
);
1344 if( xAnchorProps
.is() )
1346 xAnchorProps
->getPropertyValue( "WritingMode" ) >>= nWritingMode
;
1348 uno::Reference
< text::XText
> xText( xAnchor
->getText() );
1351 uno::Reference
< beans::XPropertySet
> xTextCursorProps( xText
->createTextCursor(), uno::UNO_QUERY
);
1352 if( xTextCursorProps
.is() )
1353 xTextCursorProps
->getPropertyValue( "PageStyleName" ) >>= aPageStyle
;
1363 if( aPageStyle
.isEmpty() )
1365 uno::Reference
< text::XText
> xText( xTextDocument
->getText() );
1368 uno::Reference
< beans::XPropertySet
> xTextCursorProps( xText
->createTextCursor(), uno::UNO_QUERY
);
1369 if( xTextCursorProps
.is() )
1370 xTextCursorProps
->getPropertyValue( "PageStyleName" ) >>= aPageStyle
;
1376 //Calc is parent document
1377 xParentProps
->getPropertyValue( "PageStyle" ) >>= aPageStyle
;
1378 if(aPageStyle
.isEmpty())
1379 aPageStyle
= "Default";
1381 if( nWritingMode
== -1 || nWritingMode
== text::WritingMode2::PAGE
)
1383 uno::Reference
< beans::XPropertySet
> xPageStyle( xPageStyles
->getByName( aPageStyle
), uno::UNO_QUERY
);
1384 if( xPageStyle
.is() )
1385 xPageStyle
->getPropertyValue( "WritingMode" ) >>= nWritingMode
;
1391 if( nWritingMode
!= -1 && nWritingMode
!= text::WritingMode2::PAGE
)
1393 if( pDrawModelWrapper
.get() )
1394 pDrawModelWrapper
->GetItemPool().SetPoolDefaultItem(SvxFrameDirectionItem(static_cast<SvxFrameDirection
>(nWritingMode
), EE_PARA_WRITINGDIR
) );
1397 catch( const uno::Exception
& )
1399 DBG_UNHANDLED_EXCEPTION("chart2" );
1404 sal_Int16
lcl_getDefaultWritingModeFromPool( const std::shared_ptr
<DrawModelWrapper
>& pDrawModelWrapper
)
1406 sal_Int16 nWritingMode
= text::WritingMode2::LR_TB
;
1407 if(!pDrawModelWrapper
)
1408 return nWritingMode
;
1410 const SfxPoolItem
& rItem
= pDrawModelWrapper
->GetItemPool().GetDefaultItem(EE_PARA_WRITINGDIR
);
1412 = static_cast<sal_Int16
>(static_cast<const SvxFrameDirectionItem
&>(rItem
).GetValue());
1413 return nWritingMode
;
1416 } //end anonymous namespace
1418 awt::Rectangle
ChartView::impl_createDiagramAndContent( const CreateShapeParam2D
& rParam
, const awt::Size
& rPageSize
)
1420 //return the used rectangle
1421 awt::Rectangle
aUsedOuterRect(rParam
.maRemainingSpace
.X
, rParam
.maRemainingSpace
.Y
, 0, 0);
1423 uno::Reference
< XDiagram
> xDiagram( mrChartModel
.getFirstDiagram() );
1425 return aUsedOuterRect
;
1427 sal_Int32 nDimensionCount
= DiagramHelper::getDimension( xDiagram
);
1428 if(!nDimensionCount
)
1430 //@todo handle mixed dimension
1431 nDimensionCount
= 2;
1434 basegfx::B2IRectangle aAvailableOuterRect
= BaseGFXHelper::makeRectangle(rParam
.maRemainingSpace
);
1436 const std::vector
< std::unique_ptr
<VCoordinateSystem
> >& rVCooSysList( rParam
.mpSeriesPlotterContainer
->getCooSysList() );
1437 SeriesPlottersType
& rSeriesPlotterList
= rParam
.mpSeriesPlotterContainer
->getSeriesPlotterList();
1439 //create VAxis, so they can give necessary information for automatic scaling
1440 uno::Reference
<chart2::XChartDocument
> const xChartDoc(&mrChartModel
);
1441 uno::Reference
<util::XNumberFormatsSupplier
> const xNumberFormatsSupplier(
1442 mrChartModel
.getNumberFormatsSupplier());
1444 for( nC
=0; nC
< rVCooSysList
.size(); nC
++)
1446 VCoordinateSystem
* pVCooSys
= rVCooSysList
[nC
].get();
1447 if(nDimensionCount
==3)
1449 uno::Reference
<beans::XPropertySet
> xSceneProperties( xDiagram
, uno::UNO_QUERY
);
1450 CuboidPlanePosition
eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xSceneProperties
) );
1451 CuboidPlanePosition
eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xSceneProperties
) );
1452 CuboidPlanePosition
eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xSceneProperties
) );
1453 pVCooSys
->set3DWallPositions( eLeftWallPos
, eBackWallPos
, eBottomPos
);
1456 pVCooSys
->createVAxisList(xChartDoc
, rPageSize
, rParam
.maRemainingSpace
, rParam
.mbUseFixedInnerSize
);
1459 // - prepare list of all axis and how they are used
1460 Date aNullDate
= NumberFormatterWrapper( xNumberFormatsSupplier
).getNullDate();
1461 rParam
.mpSeriesPlotterContainer
->initAxisUsageList(aNullDate
);
1462 rParam
.mpSeriesPlotterContainer
->doAutoScaling( mrChartModel
);
1463 rParam
.mpSeriesPlotterContainer
->setScalesFromCooSysToPlotter();
1464 rParam
.mpSeriesPlotterContainer
->setNumberFormatsFromAxes();
1469 drawing::Direction3D aPreferredAspectRatio
=
1470 rParam
.mpSeriesPlotterContainer
->getPreferredAspectRatio();
1472 uno::Reference
< drawing::XShapes
> xSeriesTargetInFrontOfAxis
;
1473 uno::Reference
< drawing::XShapes
> xSeriesTargetBehindAxis
;
1474 VDiagram
aVDiagram(xDiagram
, aPreferredAspectRatio
, nDimensionCount
);
1476 aVDiagram
.init(rParam
.mxDiagramWithAxesShapes
, m_xShapeFactory
);
1477 aVDiagram
.createShapes(
1478 awt::Point(rParam
.maRemainingSpace
.X
, rParam
.maRemainingSpace
.Y
),
1479 awt::Size(rParam
.maRemainingSpace
.Width
, rParam
.maRemainingSpace
.Height
));
1481 xSeriesTargetInFrontOfAxis
= aVDiagram
.getCoordinateRegion();
1482 // It is preferable to use full size than minimum for pie charts
1483 if (!rParam
.mbUseFixedInnerSize
)
1484 aVDiagram
.reduceToMimimumSize();
1487 uno::Reference
< drawing::XShapes
> xTextTargetShapes
=
1488 ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory
)->createGroup2D(rParam
.mxDiagramWithAxesShapes
);
1490 // - create axis and grids for all coordinate systems
1492 //init all coordinate systems
1493 for( nC
=0; nC
< rVCooSysList
.size(); nC
++)
1495 VCoordinateSystem
* pVCooSys
= rVCooSysList
[nC
].get();
1496 pVCooSys
->initPlottingTargets(xSeriesTargetInFrontOfAxis
,xTextTargetShapes
,m_xShapeFactory
,xSeriesTargetBehindAxis
);
1498 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1499 createTransformationSceneToScreen( aVDiagram
.getCurrentRectangle() ) ));
1501 pVCooSys
->initVAxisInList();
1504 //calculate resulting size respecting axis label layout and fontscaling
1506 uno::Reference
< drawing::XShape
> xBoundingShape(rParam
.mxDiagramWithAxesShapes
, uno::UNO_QUERY
);
1507 ::basegfx::B2IRectangle aConsumedOuterRect
;
1509 //use first coosys only so far; todo: calculate for more than one coosys if we have more in future
1510 //todo: this is just a workaround at the moment for pie and donut labels
1511 bool bIsPieOrDonut
= lcl_IsPieOrDonut(xDiagram
);
1512 if( !bIsPieOrDonut
&& (!rVCooSysList
.empty()) )
1514 VCoordinateSystem
* pVCooSys
= rVCooSysList
[0].get();
1515 pVCooSys
->createMaximumAxesLabels();
1517 aConsumedOuterRect
= ShapeFactory::getRectangleOfShape(xBoundingShape
);
1518 ::basegfx::B2IRectangle
aNewInnerRect( aVDiagram
.getCurrentRectangle() );
1519 if (!rParam
.mbUseFixedInnerSize
)
1520 aNewInnerRect
= aVDiagram
.adjustInnerSize( aConsumedOuterRect
);
1522 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1523 createTransformationSceneToScreen( aNewInnerRect
) ));
1525 //redo autoscaling to get size and text dependent automatic main increment count
1526 rParam
.mpSeriesPlotterContainer
->doAutoScaling( mrChartModel
);
1527 rParam
.mpSeriesPlotterContainer
->updateScalesAndIncrementsOnAxes();
1528 rParam
.mpSeriesPlotterContainer
->setScalesFromCooSysToPlotter();
1530 pVCooSys
->createAxesLabels();
1532 bool bLessSpaceConsumedThanExpected
= false;
1534 aConsumedOuterRect
= ShapeFactory::getRectangleOfShape(xBoundingShape
);
1535 if( aConsumedOuterRect
.getMinX() > aAvailableOuterRect
.getMinX()
1536 || aConsumedOuterRect
.getMaxX() < aAvailableOuterRect
.getMaxX()
1537 || aConsumedOuterRect
.getMinY() > aAvailableOuterRect
.getMinY()
1538 || aConsumedOuterRect
.getMinY() < aAvailableOuterRect
.getMaxY() )
1539 bLessSpaceConsumedThanExpected
= true;
1542 if (bLessSpaceConsumedThanExpected
&& !rParam
.mbUseFixedInnerSize
)
1544 aVDiagram
.adjustInnerSize( aConsumedOuterRect
);
1545 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1546 createTransformationSceneToScreen( aVDiagram
.getCurrentRectangle() ) ));
1548 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
1551 //create axes and grids for the final size
1552 for( nC
=0; nC
< rVCooSysList
.size(); nC
++)
1554 VCoordinateSystem
* pVCooSys
= rVCooSysList
[nC
].get();
1556 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1557 createTransformationSceneToScreen( aVDiagram
.getCurrentRectangle() ) ));
1559 pVCooSys
->createAxesShapes();
1560 pVCooSys
->createGridShapes();
1563 // - create data series for all charttypes
1564 m_bPointsWereSkipped
= false;
1565 for( const std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1567 VSeriesPlotter
* pSeriesPlotter
= aPlotter
.get();
1568 uno::Reference
< drawing::XShapes
> xSeriesTarget
;
1569 if( pSeriesPlotter
->WantToPlotInFrontOfAxisLine() )
1570 xSeriesTarget
= xSeriesTargetInFrontOfAxis
;
1573 xSeriesTarget
= xSeriesTargetBehindAxis
;
1574 OSL_ENSURE( !bIsPieOrDonut
, "not implemented yet! - during a complete recreation this shape is destroyed so no series can be created anymore" );
1576 pSeriesPlotter
->initPlotter( xSeriesTarget
,xTextTargetShapes
,m_xShapeFactory
,OUString() );
1577 pSeriesPlotter
->setPageReferenceSize( rPageSize
);
1578 VCoordinateSystem
* pVCooSys
= lcl_getCooSysForPlotter( rVCooSysList
, pSeriesPlotter
);
1579 if(nDimensionCount
==2)
1580 pSeriesPlotter
->setTransformationSceneToScreen( pVCooSys
->getTransformationSceneToScreen() );
1581 //better performance for big data
1583 //calculate resolution for coordinate system
1584 Sequence
<sal_Int32
> aCoordinateSystemResolution
= pVCooSys
->getCoordinateSystemResolution( rPageSize
, m_aPageResolution
);
1585 pSeriesPlotter
->setCoordinateSystemResolution( aCoordinateSystemResolution
);
1588 pSeriesPlotter
->createShapes();
1589 m_bPointsWereSkipped
= m_bPointsWereSkipped
|| pSeriesPlotter
->PointsWereSkipped();
1592 //recreate all with corrected sizes if requested
1595 m_bPointsWereSkipped
= false;
1597 aConsumedOuterRect
= ShapeFactory::getRectangleOfShape(xBoundingShape
);
1598 ::basegfx::B2IRectangle
aNewInnerRect( aVDiagram
.getCurrentRectangle() );
1599 if (!rParam
.mbUseFixedInnerSize
)
1600 aNewInnerRect
= aVDiagram
.adjustInnerSize( aConsumedOuterRect
);
1602 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1604 aPlotter
->releaseShapes();
1607 //clear and recreate
1608 ShapeFactory::removeSubShapes( xSeriesTargetInFrontOfAxis
); //xSeriesTargetBehindAxis is a sub shape of xSeriesTargetInFrontOfAxis and will be removed here
1609 xSeriesTargetBehindAxis
.clear();
1610 ShapeFactory::removeSubShapes( xTextTargetShapes
);
1612 //set new transformation
1613 for( nC
=0; nC
< rVCooSysList
.size(); nC
++)
1615 VCoordinateSystem
* pVCooSys
= rVCooSysList
[nC
].get();
1616 pVCooSys
->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1617 createTransformationSceneToScreen( aNewInnerRect
) ));
1620 // - create data series for all charttypes
1621 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1623 VCoordinateSystem
* pVCooSys
= lcl_getCooSysForPlotter( rVCooSysList
, aPlotter
.get() );
1624 if(nDimensionCount
==2)
1625 aPlotter
->setTransformationSceneToScreen( pVCooSys
->getTransformationSceneToScreen() );
1626 aPlotter
->createShapes();
1627 m_bPointsWereSkipped
= m_bPointsWereSkipped
|| aPlotter
->PointsWereSkipped();
1630 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1631 aPlotter
->rearrangeLabelToAvoidOverlapIfRequested(rPageSize
);
1634 if (rParam
.mbUseFixedInnerSize
)
1636 aUsedOuterRect
= awt::Rectangle( aConsumedOuterRect
.getMinX(), aConsumedOuterRect
.getMinY(), aConsumedOuterRect
.getWidth(), aConsumedOuterRect
.getHeight() );
1639 aUsedOuterRect
= rParam
.maRemainingSpace
;
1641 bool bSnapRectToUsedArea
= false;
1642 for( std::unique_ptr
<VSeriesPlotter
>& aPlotter
: rSeriesPlotterList
)
1644 bSnapRectToUsedArea
= aPlotter
->shouldSnapRectToUsedArea();
1645 if(bSnapRectToUsedArea
)
1648 if(bSnapRectToUsedArea
)
1650 if (rParam
.mbUseFixedInnerSize
)
1651 m_aResultingDiagramRectangleExcludingAxes
= getRectangleOfObject( "PlotAreaExcludingAxes" );
1654 ::basegfx::B2IRectangle aConsumedInnerRect
= aVDiagram
.getCurrentRectangle();
1655 m_aResultingDiagramRectangleExcludingAxes
= awt::Rectangle( aConsumedInnerRect
.getMinX(), aConsumedInnerRect
.getMinY(), aConsumedInnerRect
.getWidth(), aConsumedInnerRect
.getHeight() );
1660 if (rParam
.mbUseFixedInnerSize
)
1661 m_aResultingDiagramRectangleExcludingAxes
= rParam
.maRemainingSpace
;
1664 ::basegfx::B2IRectangle aConsumedInnerRect
= aVDiagram
.getCurrentRectangle();
1665 m_aResultingDiagramRectangleExcludingAxes
= awt::Rectangle( aConsumedInnerRect
.getMinX(), aConsumedInnerRect
.getMinY(), aConsumedInnerRect
.getWidth(), aConsumedInnerRect
.getHeight() );
1669 if (rParam
.mxMarkHandles
.is())
1671 awt::Point
aPos(rParam
.maRemainingSpace
.X
, rParam
.maRemainingSpace
.Y
);
1672 awt::Size
aSize(rParam
.maRemainingSpace
.Width
, rParam
.maRemainingSpace
.Height
);
1674 bool bPosSizeExcludeAxesProperty
= true;
1675 uno::Reference
< beans::XPropertySet
> xDiaProps( xDiagram
, uno::UNO_QUERY_THROW
);
1676 xDiaProps
->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxesProperty
;
1677 if (rParam
.mbUseFixedInnerSize
|| bPosSizeExcludeAxesProperty
)
1679 aPos
= awt::Point( m_aResultingDiagramRectangleExcludingAxes
.X
, m_aResultingDiagramRectangleExcludingAxes
.Y
);
1680 aSize
= awt::Size( m_aResultingDiagramRectangleExcludingAxes
.Width
, m_aResultingDiagramRectangleExcludingAxes
.Height
);
1682 rParam
.mxMarkHandles
->setPosition(aPos
);
1683 rParam
.mxMarkHandles
->setSize(aSize
);
1686 return aUsedOuterRect
;
1689 bool ChartView::getExplicitValuesForAxis(
1690 uno::Reference
< XAxis
> xAxis
1691 , ExplicitScaleData
& rExplicitScale
1692 , ExplicitIncrementData
& rExplicitIncrement
)
1694 SolarMutexGuard aSolarGuard
;
1701 uno::Reference
< XCoordinateSystem
> xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis
, mrChartModel
.getFirstDiagram() ) );
1702 const VCoordinateSystem
* pVCooSys
= findInCooSysList(m_aVCooSysList
,xCooSys
);
1706 sal_Int32 nDimensionIndex
=-1;
1707 sal_Int32 nAxisIndex
=-1;
1708 if( AxisHelper::getIndicesForAxis( xAxis
, xCooSys
, nDimensionIndex
, nAxisIndex
) )
1710 rExplicitScale
= pVCooSys
->getExplicitScale(nDimensionIndex
,nAxisIndex
);
1711 rExplicitIncrement
= pVCooSys
->getExplicitIncrement(nDimensionIndex
,nAxisIndex
);
1712 if( rExplicitScale
.ShiftedCategoryPosition
)
1714 //remove 'one' from max
1715 if( rExplicitScale
.AxisType
== css::chart2::AxisType::DATE
)
1717 Date
aMaxDate(rExplicitScale
.NullDate
); aMaxDate
.AddDays(::rtl::math::approxFloor(rExplicitScale
.Maximum
));
1718 //for explicit scales with shifted categories we need one interval more
1719 switch( rExplicitScale
.TimeResolution
)
1721 case css::chart::TimeUnit::DAY
:
1724 case css::chart::TimeUnit::MONTH
:
1725 aMaxDate
= DateHelper::GetDateSomeMonthsAway(aMaxDate
,-1);
1727 case css::chart::TimeUnit::YEAR
:
1728 aMaxDate
= DateHelper::GetDateSomeYearsAway(aMaxDate
,-1);
1731 rExplicitScale
.Maximum
= aMaxDate
- rExplicitScale
.NullDate
;
1733 else if( rExplicitScale
.AxisType
== css::chart2::AxisType::CATEGORY
)
1734 rExplicitScale
.Maximum
-= 1.0;
1735 else if( rExplicitScale
.AxisType
== css::chart2::AxisType::SERIES
)
1736 rExplicitScale
.Maximum
-= 1.0;
1743 SdrPage
* ChartView::getSdrPage()
1745 auto pSvxDrawPage
= comphelper::getUnoTunnelImplementation
<SvxDrawPage
>(m_xDrawPage
);
1747 return pSvxDrawPage
->GetSdrPage();
1752 uno::Reference
< drawing::XShape
> ChartView::getShapeForCID( const OUString
& rObjectCID
)
1754 SolarMutexGuard aSolarGuard
;
1755 SdrObject
* pObj
= DrawModelWrapper::getNamedSdrObject( rObjectCID
, this->getSdrPage() );
1757 return uno::Reference
< drawing::XShape
>( pObj
->getUnoShape(), uno::UNO_QUERY
);
1761 awt::Rectangle
ChartView::getDiagramRectangleExcludingAxes()
1764 return m_aResultingDiagramRectangleExcludingAxes
;
1767 awt::Rectangle
ChartView::getRectangleOfObject( const OUString
& rObjectCID
, bool bSnapRect
)
1771 awt::Rectangle aRet
;
1772 uno::Reference
< drawing::XShape
> xShape( getShapeForCID(rObjectCID
) );
1775 //special handling for axis for old api:
1776 //same special handling for diagram
1777 ObjectType
eObjectType( ObjectIdentifier::getObjectType( rObjectCID
) );
1778 if( eObjectType
== OBJECTTYPE_AXIS
|| eObjectType
== OBJECTTYPE_DIAGRAM
)
1780 SolarMutexGuard aSolarGuard
;
1781 SvxShape
* pRoot
= comphelper::getUnoTunnelImplementation
<SvxShape
>( xShape
);
1784 SdrObject
* pRootSdrObject
= pRoot
->GetSdrObject();
1785 if( pRootSdrObject
)
1787 SdrObjList
* pRootList
= pRootSdrObject
->GetSubList();
1790 OUString aShapeName
= "MarkHandles";
1791 if( eObjectType
== OBJECTTYPE_DIAGRAM
)
1792 aShapeName
= "PlotAreaIncludingAxes";
1793 SdrObject
* pShape
= DrawModelWrapper::getNamedSdrObject( aShapeName
, pRootList
);
1795 xShape
.set( pShape
->getUnoShape(), uno::UNO_QUERY
);
1801 awt::Size
aSize( xShape
->getSize() );
1802 awt::Point
aPoint( xShape
->getPosition() );
1803 aRet
= awt::Rectangle( aPoint
.X
, aPoint
.Y
, aSize
.Width
, aSize
.Height
);
1806 //for rotated objects the shape size and position differs from the visible rectangle
1807 SvxShape
* pShape
= comphelper::getUnoTunnelImplementation
<SvxShape
>( xShape
);
1810 SdrObject
* pSdrObject
= pShape
->GetSdrObject();
1813 tools::Rectangle
aSnapRect( pSdrObject
->GetSnapRect() );
1814 aRet
= awt::Rectangle(aSnapRect
.Left(),aSnapRect
.Top(),aSnapRect
.GetWidth(),aSnapRect
.GetHeight());
1822 std::shared_ptr
< DrawModelWrapper
> ChartView::getDrawModelWrapper()
1824 return m_pDrawModelWrapper
;
1829 sal_Int32
lcl_getDiagramTitleSpace()
1831 return 200; //=0,2 cm spacing
1833 bool lcl_getPropertySwapXAndYAxis( const uno::Reference
< XDiagram
>& xDiagram
)
1835 bool bSwapXAndY
= false;
1837 uno::Reference
< XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
1838 if( xCooSysContainer
.is() )
1840 uno::Sequence
< uno::Reference
< XCoordinateSystem
> > aCooSysList( xCooSysContainer
->getCoordinateSystems() );
1841 if( aCooSysList
.hasElements() )
1843 uno::Reference
<beans::XPropertySet
> xProp(aCooSysList
[0], uno::UNO_QUERY
);
1846 xProp
->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY
;
1848 catch( const uno::Exception
& )
1850 TOOLS_WARN_EXCEPTION("chart2", "" );
1859 sal_Int32
ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
1860 const Reference
< chart2::XAxis
>& xAxis
1861 , const Reference
< chart2::XCoordinateSystem
> & xCorrespondingCoordinateSystem
1862 , const Reference
<chart2::XChartDocument
>& xChartDoc
)
1864 return AxisHelper::getExplicitNumberFormatKeyForAxis( xAxis
, xCorrespondingCoordinateSystem
, xChartDoc
1865 , true /*bSearchForParallelAxisIfNothingIsFound*/ );
1868 sal_Int32
ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
1869 const uno::Reference
< beans::XPropertySet
>& xSeriesOrPointProp
,
1870 const uno::Reference
< XDataSeries
>& xSeries
,
1871 sal_Int32 nPointIndex
/*-1 for whole series*/,
1872 const uno::Reference
< XDiagram
>& xDiagram
1875 sal_Int32 nFormat
=0;
1876 if( !xSeriesOrPointProp
.is() )
1879 bool bLinkToSource
= true;
1882 xSeriesOrPointProp
->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT
) >>= bLinkToSource
;
1884 catch ( const beans::UnknownPropertyException
& ) {}
1886 xSeriesOrPointProp
->getPropertyValue(CHART_UNONAME_NUMFMT
) >>= nFormat
;
1887 sal_Int32 nOldFormat
= nFormat
;
1890 uno::Reference
< chart2::XChartType
> xChartType( DataSeriesHelper::getChartTypeOfSeries( xSeries
, xDiagram
) );
1892 bool bFormatFound
= false;
1893 if( ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( xChartType
) )
1895 uno::Reference
< beans::XPropertySet
> xAttachedAxisProps( DiagramHelper::getAttachedAxis( xSeries
, xDiagram
), uno::UNO_QUERY
);
1896 if (xAttachedAxisProps
.is() && (xAttachedAxisProps
->getPropertyValue(CHART_UNONAME_NUMFMT
) >>= nFormat
))
1897 bFormatFound
= true;
1901 Reference
< chart2::data::XDataSource
> xSeriesSource( xSeries
, uno::UNO_QUERY
);
1902 OUString
aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType
) );
1904 Reference
< data::XLabeledDataSequence
> xLabeledSequence(
1905 DataSeriesHelper::getDataSequenceByRole( xSeriesSource
, aRole
));
1906 if( xLabeledSequence
.is() )
1908 Reference
< data::XDataSequence
> xValues( xLabeledSequence
->getValues() );
1910 nFormat
= xValues
->getNumberFormatKeyByIndex( nPointIndex
);
1914 if (nFormat
>= 0 && nOldFormat
!= nFormat
)
1915 xSeriesOrPointProp
->setPropertyValue(CHART_UNONAME_NUMFMT
, uno::Any(nFormat
));
1923 sal_Int32
ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
1924 const uno::Reference
< beans::XPropertySet
>& xSeriesOrPointProp
,
1925 const uno::Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
)
1927 sal_Int32 nFormat
=0;
1928 if( !xSeriesOrPointProp
.is() )
1930 if( !(xSeriesOrPointProp
->getPropertyValue("PercentageNumberFormat") >>= nFormat
) )
1932 nFormat
= DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier
);
1939 awt::Rectangle
ExplicitValueProvider::AddSubtractAxisTitleSizes(
1941 , const Reference
< uno::XInterface
>& xChartView
1942 , const awt::Rectangle
& rPositionAndSize
, bool bSubtract
)
1944 awt::Rectangle
aRet(rPositionAndSize
);
1946 //add axis title sizes to the diagram size
1947 uno::Reference
< chart2::XTitle
> xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION
, rModel
) );
1948 uno::Reference
< chart2::XTitle
> xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION
, rModel
) );
1949 uno::Reference
< chart2::XTitle
> xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE
, rModel
) );
1950 uno::Reference
< chart2::XTitle
> xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE
, rModel
) );
1951 if( xTitle_Height
.is() || xTitle_Width
.is() || xSecondTitle_Height
.is() || xSecondTitle_Width
.is() )
1953 ExplicitValueProvider
* pExplicitValueProvider
= comphelper::getUnoTunnelImplementation
<ExplicitValueProvider
>(xChartView
);
1954 if( pExplicitValueProvider
)
1956 //detect whether x axis points into x direction or not
1957 if( lcl_getPropertySwapXAndYAxis( rModel
.getFirstDiagram() ) )
1959 std::swap( xTitle_Height
, xTitle_Width
);
1960 std::swap( xSecondTitle_Height
, xSecondTitle_Width
);
1963 sal_Int32 nTitleSpaceWidth
= 0;
1964 sal_Int32 nTitleSpaceHeight
= 0;
1965 sal_Int32 nSecondTitleSpaceWidth
= 0;
1966 sal_Int32 nSecondTitleSpaceHeight
= 0;
1968 if( xTitle_Height
.is() )
1970 OUString
aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height
, rModel
) );
1971 nTitleSpaceHeight
= pExplicitValueProvider
->getRectangleOfObject( aCID_X
, true ).Height
;
1972 if( nTitleSpaceHeight
)
1973 nTitleSpaceHeight
+=lcl_getDiagramTitleSpace();
1975 if( xTitle_Width
.is() )
1977 OUString
aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width
, rModel
) );
1978 nTitleSpaceWidth
= pExplicitValueProvider
->getRectangleOfObject( aCID_Y
, true ).Width
;
1979 if(nTitleSpaceWidth
)
1980 nTitleSpaceWidth
+=lcl_getDiagramTitleSpace();
1982 if( xSecondTitle_Height
.is() )
1984 OUString
aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height
, rModel
) );
1985 nSecondTitleSpaceHeight
= pExplicitValueProvider
->getRectangleOfObject( aCID_X
, true ).Height
;
1986 if( nSecondTitleSpaceHeight
)
1987 nSecondTitleSpaceHeight
+=lcl_getDiagramTitleSpace();
1989 if( xSecondTitle_Width
.is() )
1991 OUString
aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width
, rModel
) );
1992 nSecondTitleSpaceWidth
+= pExplicitValueProvider
->getRectangleOfObject( aCID_Y
, true ).Width
;
1993 if( nSecondTitleSpaceWidth
)
1994 nSecondTitleSpaceWidth
+=lcl_getDiagramTitleSpace();
1998 aRet
.X
+= nTitleSpaceWidth
;
1999 aRet
.Y
+= nSecondTitleSpaceHeight
;
2000 aRet
.Width
-= (nTitleSpaceWidth
+ nSecondTitleSpaceWidth
);
2001 aRet
.Height
-= (nTitleSpaceHeight
+ nSecondTitleSpaceHeight
);
2006 aRet
.X
-= nTitleSpaceWidth
;
2007 aRet
.Y
-= nSecondTitleSpaceHeight
;
2008 aRet
.Width
+= nTitleSpaceWidth
+ nSecondTitleSpaceWidth
;
2009 aRet
.Height
+= nTitleSpaceHeight
+ nSecondTitleSpaceHeight
;
2018 double lcl_getPageLayoutDistancePercentage()
2023 bool getAvailablePosAndSizeForDiagram(
2024 CreateShapeParam2D
& rParam
, const awt::Size
& rPageSize
, const uno::Reference
<XDiagram
>& xDiagram
)
2026 rParam
.mbUseFixedInnerSize
= false;
2028 //@todo: we need a size dependent on the axis labels
2029 sal_Int32 nYDistance
= static_cast<sal_Int32
>(rPageSize
.Height
*lcl_getPageLayoutDistancePercentage());
2030 sal_Int32 nXDistance
= static_cast<sal_Int32
>(rPageSize
.Width
*lcl_getPageLayoutDistancePercentage());
2031 rParam
.maRemainingSpace
.X
+= nXDistance
;
2032 rParam
.maRemainingSpace
.Width
-= 2*nXDistance
;
2033 rParam
.maRemainingSpace
.Y
+= nYDistance
;
2034 rParam
.maRemainingSpace
.Height
-= 2*nYDistance
;
2036 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
2039 uno::Reference
< beans::XPropertySet
> xProp(xDiagram
, uno::UNO_QUERY
);
2041 bool bPosSizeExcludeAxes
= false;
2043 xProp
->getPropertyValue( "PosSizeExcludeAxes" ) >>= bPosSizeExcludeAxes
;
2046 css::chart2::RelativeSize aRelativeSize
;
2047 if( xProp
.is() && (xProp
->getPropertyValue( "RelativeSize" )>>=aRelativeSize
) )
2049 rParam
.maRemainingSpace
.Height
= static_cast<sal_Int32
>(aRelativeSize
.Secondary
*rPageSize
.Height
);
2050 rParam
.maRemainingSpace
.Width
= static_cast<sal_Int32
>(aRelativeSize
.Primary
*rPageSize
.Width
);
2051 rParam
.mbUseFixedInnerSize
= bPosSizeExcludeAxes
;
2055 chart2::RelativePosition aRelativePosition
;
2056 if( xProp
.is() && (xProp
->getPropertyValue( "RelativePosition" )>>=aRelativePosition
) )
2058 //@todo decide whether x is primary or secondary
2060 //the coordinates re relative to the page
2061 double fX
= aRelativePosition
.Primary
*rPageSize
.Width
;
2062 double fY
= aRelativePosition
.Secondary
*rPageSize
.Height
;
2064 awt::Point aPos
= RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
2065 awt::Point(static_cast<sal_Int32
>(fX
),static_cast<sal_Int32
>(fY
)),
2066 awt::Size(rParam
.maRemainingSpace
.Width
, rParam
.maRemainingSpace
.Height
),
2067 aRelativePosition
.Anchor
);
2069 rParam
.maRemainingSpace
.X
= aPos
.X
;
2070 rParam
.maRemainingSpace
.Y
= aPos
.Y
;
2072 rParam
.mbUseFixedInnerSize
= bPosSizeExcludeAxes
;
2075 //ensure that the diagram does not lap out right side or out of bottom
2076 if (rParam
.maRemainingSpace
.Y
+ rParam
.maRemainingSpace
.Height
> rPageSize
.Height
)
2077 rParam
.maRemainingSpace
.Height
= rPageSize
.Height
- rParam
.maRemainingSpace
.Y
;
2079 if (rParam
.maRemainingSpace
.X
+ rParam
.maRemainingSpace
.Width
> rPageSize
.Width
)
2080 rParam
.maRemainingSpace
.Width
= rPageSize
.Width
- rParam
.maRemainingSpace
.X
;
2085 enum TitleAlignment
{ ALIGN_LEFT
, ALIGN_TOP
, ALIGN_RIGHT
, ALIGN_BOTTOM
, ALIGN_Z
};
2087 void changePositionOfAxisTitle( VTitle
* pVTitle
, TitleAlignment eAlignment
2088 , awt::Rectangle
const & rDiagramPlusAxesRect
, const awt::Size
& rPageSize
)
2093 awt::Point
aNewPosition(0,0);
2094 awt::Size aTitleSize
= pVTitle
->getFinalSize();
2095 sal_Int32 nYDistance
= static_cast<sal_Int32
>(rPageSize
.Height
*lcl_getPageLayoutDistancePercentage());
2096 sal_Int32 nXDistance
= static_cast<sal_Int32
>(rPageSize
.Width
*lcl_getPageLayoutDistancePercentage());
2097 switch( eAlignment
)
2100 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
+ rDiagramPlusAxesRect
.Width
/2
2101 , rDiagramPlusAxesRect
.Y
- aTitleSize
.Height
/2 - nYDistance
);
2104 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
+ rDiagramPlusAxesRect
.Width
/2
2105 , rDiagramPlusAxesRect
.Y
+ rDiagramPlusAxesRect
.Height
+ aTitleSize
.Height
/2 + nYDistance
);
2108 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
- aTitleSize
.Width
/2 - nXDistance
2109 , rDiagramPlusAxesRect
.Y
+ rDiagramPlusAxesRect
.Height
/2 );
2112 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
+ rDiagramPlusAxesRect
.Width
+ aTitleSize
.Width
/2 + nXDistance
2113 , rDiagramPlusAxesRect
.Y
+ rDiagramPlusAxesRect
.Height
/2 );
2116 aNewPosition
= awt::Point( rDiagramPlusAxesRect
.X
+ rDiagramPlusAxesRect
.Width
+ aTitleSize
.Width
/2 + nXDistance
2117 , rDiagramPlusAxesRect
.Y
+ rDiagramPlusAxesRect
.Height
- aTitleSize
.Height
/2 );
2123 sal_Int32 nMaxY
= rPageSize
.Height
- aTitleSize
.Height
/2;
2124 sal_Int32 nMaxX
= rPageSize
.Width
- aTitleSize
.Width
/2;
2125 sal_Int32 nMinX
= aTitleSize
.Width
/2;
2126 sal_Int32 nMinY
= aTitleSize
.Height
/2;
2127 if( aNewPosition
.Y
> nMaxY
)
2128 aNewPosition
.Y
= nMaxY
;
2129 if( aNewPosition
.X
> nMaxX
)
2130 aNewPosition
.X
= nMaxX
;
2131 if( aNewPosition
.Y
< nMinY
)
2132 aNewPosition
.Y
= nMinY
;
2133 if( aNewPosition
.X
< nMinX
)
2134 aNewPosition
.X
= nMinX
;
2136 pVTitle
->changePosition( aNewPosition
);
2139 std::shared_ptr
<VTitle
> lcl_createTitle( TitleHelper::eTitleType eType
2140 , const uno::Reference
< drawing::XShapes
>& xPageShapes
2141 , const uno::Reference
< lang::XMultiServiceFactory
>& xShapeFactory
2142 , ChartModel
& rModel
2143 , awt::Rectangle
& rRemainingSpace
2144 , const awt::Size
& rPageSize
2145 , TitleAlignment eAlignment
2146 , bool& rbAutoPosition
)
2148 std::shared_ptr
<VTitle
> apVTitle
;
2150 // #i109336# Improve auto positioning in chart
2151 double fPercentage
= lcl_getPageLayoutDistancePercentage();
2152 sal_Int32 nXDistance
= static_cast< sal_Int32
>( rPageSize
.Width
* fPercentage
);
2153 sal_Int32 nYDistance
= static_cast< sal_Int32
>( rPageSize
.Height
* fPercentage
);
2154 if ( eType
== TitleHelper::MAIN_TITLE
)
2156 nYDistance
+= 135; // 1/100 mm
2158 else if ( eType
== TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION
)
2160 nYDistance
= 420; // 1/100 mm
2162 else if ( eType
== TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION
)
2164 nXDistance
= 450; // 1/100 mm
2167 uno::Reference
< XTitle
> xTitle( TitleHelper::getTitle( eType
, rModel
) );
2168 OUString aCompleteString
= TitleHelper::getCompleteString(xTitle
);
2169 if (aCompleteString
.isEmpty())
2173 apVTitle
.reset(new VTitle(xTitle
));
2174 OUString aCID
= ObjectIdentifier::createClassifiedIdentifierForObject(xTitle
, rModel
);
2175 apVTitle
->init(xPageShapes
, xShapeFactory
, aCID
);
2176 apVTitle
->createShapes(awt::Point(0,0), rPageSize
);
2177 awt::Size aTitleUnrotatedSize
= apVTitle
->getUnrotatedSize();
2178 awt::Size aTitleSize
= apVTitle
->getFinalSize();
2181 rbAutoPosition
= true;
2182 awt::Point
aNewPosition(0,0);
2183 chart2::RelativePosition aRelativePosition
;
2184 uno::Reference
<beans::XPropertySet
> xProp(xTitle
, uno::UNO_QUERY
);
2185 if (xProp
.is() && (xProp
->getPropertyValue("RelativePosition") >>= aRelativePosition
))
2187 rbAutoPosition
= false;
2189 //@todo decide whether x is primary or secondary
2190 double fX
= aRelativePosition
.Primary
*rPageSize
.Width
;
2191 double fY
= aRelativePosition
.Secondary
*rPageSize
.Height
;
2193 double fAnglePi
= apVTitle
->getRotationAnglePi();
2194 aNewPosition
= RelativePositionHelper::getCenterOfAnchoredObject(
2195 awt::Point(static_cast<sal_Int32
>(fX
),static_cast<sal_Int32
>(fY
))
2196 , aTitleUnrotatedSize
, aRelativePosition
.Anchor
, fAnglePi
);
2198 else //auto position
2200 switch( eAlignment
)
2203 aNewPosition
= awt::Point( rRemainingSpace
.X
+ rRemainingSpace
.Width
/2
2204 , rRemainingSpace
.Y
+ aTitleSize
.Height
/2 + nYDistance
);
2207 aNewPosition
= awt::Point( rRemainingSpace
.X
+ rRemainingSpace
.Width
/2
2208 , rRemainingSpace
.Y
+ rRemainingSpace
.Height
- aTitleSize
.Height
/2 - nYDistance
);
2211 aNewPosition
= awt::Point( rRemainingSpace
.X
+ aTitleSize
.Width
/2 + nXDistance
2212 , rRemainingSpace
.Y
+ rRemainingSpace
.Height
/2 );
2215 aNewPosition
= awt::Point( rRemainingSpace
.X
+ rRemainingSpace
.Width
- aTitleSize
.Width
/2 - nXDistance
2216 , rRemainingSpace
.Y
+ rRemainingSpace
.Height
/2 );
2223 apVTitle
->changePosition( aNewPosition
);
2226 switch( eAlignment
)
2229 // Push the remaining space down from top.
2230 rRemainingSpace
.Y
+= ( aTitleSize
.Height
+ nYDistance
);
2231 rRemainingSpace
.Height
-= ( aTitleSize
.Height
+ nYDistance
);
2234 // Push the remaining space up from bottom.
2235 rRemainingSpace
.Height
-= ( aTitleSize
.Height
+ nYDistance
);
2238 // Push the remaining space to the right from left edge.
2239 rRemainingSpace
.X
+= ( aTitleSize
.Width
+ nXDistance
);
2240 rRemainingSpace
.Width
-= ( aTitleSize
.Width
+ nXDistance
);
2243 // Push the remaining space to the left from right edge.
2244 rRemainingSpace
.Width
-= ( aTitleSize
.Width
+ nXDistance
);
2253 bool lcl_createLegend( const uno::Reference
< XLegend
> & xLegend
2254 , const uno::Reference
< drawing::XShapes
>& xPageShapes
2255 , const uno::Reference
< lang::XMultiServiceFactory
>& xShapeFactory
2256 , const uno::Reference
< uno::XComponentContext
> & xContext
2257 , awt::Rectangle
& rRemainingSpace
2258 , const awt::Size
& rPageSize
2259 , ChartModel
& rModel
2260 , const std::vector
< LegendEntryProvider
* >& rLegendEntryProviderList
2261 , sal_Int16 nDefaultWritingMode
)
2263 if (!VLegend::isVisible(xLegend
))
2266 VLegend
aVLegend( xLegend
, xContext
, rLegendEntryProviderList
,
2267 xPageShapes
, xShapeFactory
, rModel
);
2268 aVLegend
.setDefaultWritingMode( nDefaultWritingMode
);
2269 aVLegend
.createShapes( awt::Size( rRemainingSpace
.Width
, rRemainingSpace
.Height
),
2271 aVLegend
.changePosition( rRemainingSpace
, rPageSize
);
2275 void lcl_createButtons(const uno::Reference
<drawing::XShapes
>& xPageShapes
,
2276 const uno::Reference
<lang::XMultiServiceFactory
>& xShapeFactory
,
2278 awt::Rectangle
& rRemainingSpace
)
2280 uno::Reference
<chart2::data::XPivotTableDataProvider
> xPivotTableDataProvider(rModel
.getDataProvider(), uno::UNO_QUERY
);
2281 if (!xPivotTableDataProvider
.is())
2284 uno::Reference
<beans::XPropertySet
> xModelPage(rModel
.getPageBackground());
2286 awt::Size
aSize(4000, 700); // size of the button
2290 if (xPivotTableDataProvider
->getPageFields().hasElements())
2294 const css::uno::Sequence
<chart2::data::PivotTableFieldEntry
> aPivotFieldEntries
= xPivotTableDataProvider
->getPageFields();
2295 for (css::chart2::data::PivotTableFieldEntry
const & rPageFieldEntry
: aPivotFieldEntries
)
2297 std::unique_ptr
<VButton
> pButton(new VButton
);
2298 pButton
->init(xPageShapes
, xShapeFactory
);
2299 awt::Point
aNewPosition(rRemainingSpace
.X
+ x
+ 100, rRemainingSpace
.Y
+ 100);
2300 sal_Int32 nDimensionIndex
= rPageFieldEntry
.DimensionIndex
;
2301 OUString aFieldOutputDescription
= xPivotTableDataProvider
->getFieldOutputDescription(nDimensionIndex
);
2302 pButton
->setLabel(rPageFieldEntry
.Name
+ " | " + aFieldOutputDescription
);
2303 pButton
->setCID("FieldButton.Page." + OUString::number(nDimensionIndex
));
2304 pButton
->setPosition(aNewPosition
);
2305 pButton
->setSize(aSize
);
2306 if (rPageFieldEntry
.HasHiddenMembers
)
2307 pButton
->setArrowColor(Color(0x0000FF));
2309 pButton
->createShapes(xModelPage
);
2310 x
+= aSize
.Width
+ 100;
2312 rRemainingSpace
.Y
+= (aSize
.Height
+ 100 + 100);
2313 rRemainingSpace
.Height
-= (aSize
.Height
+ 100 + 100);
2316 aSize
= awt::Size(3000, 700); // size of the button
2318 if (xPivotTableDataProvider
->getRowFields().hasElements())
2321 const css::uno::Sequence
<chart2::data::PivotTableFieldEntry
> aPivotFieldEntries
= xPivotTableDataProvider
->getRowFields();
2322 for (css::chart2::data::PivotTableFieldEntry
const & rRowFieldEntry
: aPivotFieldEntries
)
2325 std::unique_ptr
<VButton
> pButton(new VButton
);
2326 pButton
->init(xPageShapes
, xShapeFactory
);
2327 awt::Point
aNewPosition(rRemainingSpace
.X
+ x
+ 100,
2328 rRemainingSpace
.Y
+ rRemainingSpace
.Height
- aSize
.Height
- 100);
2329 pButton
->setLabel(rRowFieldEntry
.Name
);
2330 pButton
->setCID("FieldButton.Row." + OUString::number(rRowFieldEntry
.DimensionIndex
));
2331 pButton
->setPosition(aNewPosition
);
2332 pButton
->setSize(aSize
);
2333 if ( rRowFieldEntry
.Name
== "Data" )
2335 pButton
->setBGColor( Color(0x00F6F6F6) );
2336 pButton
->showArrow( false );
2338 else if (rRowFieldEntry
.HasHiddenMembers
)
2339 pButton
->setArrowColor(Color(0x0000FF));
2340 pButton
->createShapes(xModelPage
);
2341 x
+= aSize
.Width
+ 100;
2343 rRemainingSpace
.Height
-= (aSize
.Height
+ 100 + 100);
2348 ChartModel
& rChartModel
2349 , const awt::Size
& rPageSize
2350 , const uno::Reference
< drawing::XShapes
>& xTarget
2351 , const uno::Reference
< lang::XMultiServiceFactory
>& xShapeFactory
2356 uno::Reference
< beans::XPropertySet
> xModelPage( rChartModel
.getPageBackground());
2357 if( ! xModelPage
.is())
2360 if( !xShapeFactory
.is() )
2364 tPropertyNameValueMap aNameValueMap
;
2365 PropertyMapper::getValueMap( aNameValueMap
, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage
);
2367 OUString
aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE
, OUString() ) );
2368 aNameValueMap
.emplace( "Name", uno::Any( aCID
) ); //CID OUString
2370 tNameSequence aNames
;
2371 tAnySequence aValues
;
2372 PropertyMapper::getMultiPropertyListsFromValueMap( aNames
, aValues
, aNameValueMap
);
2374 ShapeFactory
* pShapeFactory
= ShapeFactory::getOrCreateShapeFactory(xShapeFactory
);
2375 pShapeFactory
->createRectangle(
2376 xTarget
, rPageSize
, awt::Point(0, 0), aNames
, aValues
);
2378 catch( const uno::Exception
& )
2380 DBG_UNHANDLED_EXCEPTION("chart2" );
2384 void lcl_removeEmptyGroupShapes( const Reference
< drawing::XShapes
>& xParent
)
2388 Reference
< drawing::XShapeGroup
> xParentGroup( xParent
, uno::UNO_QUERY
);
2389 if( !xParentGroup
.is() )
2391 Reference
< drawing::XDrawPage
> xPage( xParent
, uno::UNO_QUERY
);
2396 //iterate from back!
2397 for( sal_Int32 nN
= xParent
->getCount(); nN
--; )
2399 uno::Any aAny
= xParent
->getByIndex( nN
);
2400 Reference
< drawing::XShapes
> xShapes
;
2401 if( aAny
>>= xShapes
)
2402 lcl_removeEmptyGroupShapes( xShapes
);
2403 if( xShapes
.is() && xShapes
->getCount()==0 )
2405 //remove empty group shape
2406 Reference
< drawing::XShapeGroup
> xGroup( xShapes
, uno::UNO_QUERY
);
2407 Reference
< drawing::XShape
> xShape( xShapes
, uno::UNO_QUERY
);
2409 xParent
->remove( xShape
);
2416 void ChartView::impl_refreshAddIn()
2418 if( !m_bRefreshAddIn
)
2421 uno::Reference
< beans::XPropertySet
> xProp( static_cast< ::cppu::OWeakObject
* >( &mrChartModel
), uno::UNO_QUERY
);
2424 uno::Reference
< util::XRefreshable
> xAddIn
;
2425 xProp
->getPropertyValue( "AddIn" ) >>= xAddIn
;
2428 bool bRefreshAddInAllowed
= true;
2429 xProp
->getPropertyValue( "RefreshAddInAllowed" ) >>= bRefreshAddInAllowed
;
2430 if( bRefreshAddInAllowed
)
2434 catch( const uno::Exception
& )
2436 TOOLS_WARN_EXCEPTION("chart2", "" );
2440 static const char* envChartDummyFactory
= getenv("CHART_DUMMY_FACTORY");
2442 void ChartView::createShapes()
2444 SolarMutexGuard aSolarGuard
;
2446 osl::MutexGuard
aTimedGuard(maTimeMutex
);
2447 if(mrChartModel
.isTimeBased())
2449 maTimeBased
.bTimeBased
= true;
2452 //make sure add-in is refreshed after creating the shapes
2453 const ::comphelper::ScopeGuard
aGuard( [this]() { this->impl_refreshAddIn(); } );
2455 m_aResultingDiagramRectangleExcludingAxes
= awt::Rectangle(0,0,0,0);
2456 impl_deleteCoordinateSystems();
2457 if( m_pDrawModelWrapper
)
2459 // #i12587# support for shapes in chart
2460 m_pDrawModelWrapper
->getSdrModel().EnableUndo( false );
2461 m_pDrawModelWrapper
->clearMainDrawPage();
2464 lcl_setDefaultWritingMode( m_pDrawModelWrapper
, mrChartModel
);
2466 awt::Size aPageSize
= mrChartModel
.getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
2468 ShapeFactory
* pShapeFactory
= ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory
);
2469 if(!mxRootShape
.is())
2470 mxRootShape
= pShapeFactory
->getOrCreateChartRootShape( m_xDrawPage
);
2472 SdrPage
* pPage
= ChartView::getSdrPage();
2473 if(pPage
) //it is necessary to use the implementation here as the uno page does not provide a propertyset
2474 pPage
->SetSize(Size(aPageSize
.Width
,aPageSize
.Height
));
2477 OSL_FAIL("could not set page size correctly");
2479 ShapeFactory::setPageSize(mxRootShape
, aPageSize
);
2481 createShapes2D(aPageSize
);
2483 // #i12587# support for shapes in chart
2484 if ( m_pDrawModelWrapper
)
2486 m_pDrawModelWrapper
->getSdrModel().EnableUndo( true );
2489 if(maTimeBased
.bTimeBased
)
2491 maTimeBased
.nFrame
++;
2495 // util::XEventListener (base of XCloseListener)
2496 void SAL_CALL
ChartView::disposing( const lang::EventObject
& /* rSource */ )
2500 void ChartView::impl_updateView( bool bCheckLockedCtrler
)
2502 if( !m_pDrawModelWrapper
)
2505 // #i12587# support for shapes in chart
2506 if ( m_bSdrViewIsInEditMode
)
2511 if (bCheckLockedCtrler
&& mrChartModel
.hasControllersLocked())
2514 if( m_bViewDirty
&& !m_bInViewUpdate
)
2516 m_bInViewUpdate
= true;
2517 //bool bOldRefreshAddIn = m_bRefreshAddIn;
2518 //m_bRefreshAddIn = false;
2521 impl_notifyModeChangeListener("invalid");
2523 //prepare draw model
2525 SolarMutexGuard aSolarGuard
;
2526 m_pDrawModelWrapper
->lockControllers();
2531 m_bViewDirty
= false;
2532 m_bViewUpdatePending
= false;
2537 //avoid recursions due to add-in
2538 m_bRefreshAddIn
= false;
2539 m_bViewDirty
= false;
2540 m_bViewUpdatePending
= false;
2541 //delete old chart view
2543 m_bRefreshAddIn
= true;
2547 m_bViewDirty
= m_bViewUpdatePending
;
2548 m_bViewUpdatePending
= false;
2549 m_bInViewUpdate
= false;
2551 catch( const uno::Exception
& )
2553 DBG_UNHANDLED_EXCEPTION("chart2" );
2554 m_bViewDirty
= m_bViewUpdatePending
;
2555 m_bViewUpdatePending
= false;
2556 m_bInViewUpdate
= false;
2560 SolarMutexGuard aSolarGuard
;
2561 m_pDrawModelWrapper
->unlockControllers();
2564 impl_notifyModeChangeListener("valid");
2566 //m_bRefreshAddIn = bOldRefreshAddIn;
2570 // ____ XModifyListener ____
2571 void SAL_CALL
ChartView::modified( const lang::EventObject
& /* aEvent */ )
2573 m_bViewDirty
= true;
2574 if( m_bInViewUpdate
)
2575 m_bViewUpdatePending
= true;
2577 impl_notifyModeChangeListener("dirty");
2581 void ChartView::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
2583 //#i77362 change notification for changes on additional shapes are missing
2584 if( m_bInViewUpdate
)
2587 // #i12587# support for shapes in chart
2588 if ( m_bSdrViewIsInEditMode
)
2590 uno::Reference
< view::XSelectionSupplier
> xSelectionSupplier( mrChartModel
.getCurrentController(), uno::UNO_QUERY
);
2591 if ( xSelectionSupplier
.is() )
2593 OUString aSelObjCID
;
2594 uno::Any
aSelObj( xSelectionSupplier
->getSelection() );
2595 aSelObj
>>= aSelObjCID
;
2596 if ( !aSelObjCID
.isEmpty() )
2603 if (rHint
.GetId() != SfxHintId::ThisIsAnSdrHint
)
2605 const SdrHint
* pSdrHint
= static_cast< const SdrHint
* >(&rHint
);
2607 bool bShapeChanged
= false;
2608 switch( pSdrHint
->GetKind() )
2610 case SdrHintKind::ObjectChange
:
2611 bShapeChanged
= true;
2613 case SdrHintKind::ObjectInserted
:
2614 bShapeChanged
= true;
2616 case SdrHintKind::ObjectRemoved
:
2617 bShapeChanged
= true;
2619 case SdrHintKind::ModelCleared
:
2620 bShapeChanged
= true;
2622 case SdrHintKind::EndEdit
:
2623 bShapeChanged
= true;
2631 //#i76053# do not send view modified notifications for changes on the hidden page which contains e.g. the symbols for the dialogs
2632 if( ChartView::getSdrPage() != pSdrHint
->GetPage() )
2633 bShapeChanged
=false;
2639 mrChartModel
.setModified(true);
2642 void ChartView::impl_notifyModeChangeListener( const OUString
& rNewMode
)
2646 ::cppu::OInterfaceContainerHelper
* pIC
= m_aListenerContainer
2647 .getContainer( cppu::UnoType
<util::XModeChangeListener
>::get());
2650 util::ModeChangeEvent
aEvent( static_cast< uno::XWeak
* >( this ), rNewMode
);
2651 ::cppu::OInterfaceIteratorHelper
aIt( *pIC
);
2652 while( aIt
.hasMoreElements() )
2654 uno::Reference
< util::XModeChangeListener
> xListener( aIt
.next(), uno::UNO_QUERY
);
2655 if( xListener
.is() )
2656 xListener
->modeChanged( aEvent
);
2660 catch( const uno::Exception
& )
2662 DBG_UNHANDLED_EXCEPTION("chart2");
2666 // ____ XModeChangeBroadcaster ____
2668 void SAL_CALL
ChartView::addModeChangeListener( const uno::Reference
< util::XModeChangeListener
>& xListener
)
2670 m_aListenerContainer
.addInterface(
2671 cppu::UnoType
<util::XModeChangeListener
>::get(), xListener
);
2673 void SAL_CALL
ChartView::removeModeChangeListener( const uno::Reference
< util::XModeChangeListener
>& xListener
)
2675 m_aListenerContainer
.removeInterface(
2676 cppu::UnoType
<util::XModeChangeListener
>::get(), xListener
);
2678 void SAL_CALL
ChartView::addModeChangeApproveListener( const uno::Reference
< util::XModeChangeApproveListener
>& /* _rxListener */ )
2682 void SAL_CALL
ChartView::removeModeChangeApproveListener( const uno::Reference
< util::XModeChangeApproveListener
>& /* _rxListener */ )
2687 // ____ XUpdatable ____
2688 void SAL_CALL
ChartView::update()
2692 //#i100778# migrate all imported or old documents to a plot area sizing exclusive axes (in case the save settings allow for this):
2693 //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.
2694 //When a view update is requested (what happens for creating the metafile or displaying
2695 //the chart in edit mode or printing) it is most likely that all necessary information is available - like the underlying spreadsheet data for example.
2696 //Those data are important for the correct axis label sizes which are needed during conversion.
2697 if( DiagramHelper::switchDiagramPositioningToExcludingPositioning( mrChartModel
, true, false ) )
2701 void SAL_CALL
ChartView::updateSoft()
2706 void SAL_CALL
ChartView::updateHard()
2708 impl_updateView(false);
2711 // ____ XPropertySet ____
2712 Reference
< beans::XPropertySetInfo
> SAL_CALL
ChartView::getPropertySetInfo()
2714 OSL_FAIL("not implemented");
2718 void SAL_CALL
ChartView::setPropertyValue( const OUString
& rPropertyName
2719 , const Any
& rValue
)
2721 if( rPropertyName
== "Resolution" )
2723 awt::Size aNewResolution
;
2724 if( ! (rValue
>>= aNewResolution
) )
2725 throw lang::IllegalArgumentException( "Property 'Resolution' requires value of type awt::Size", nullptr, 0 );
2727 if( m_aPageResolution
.Width
!=aNewResolution
.Width
|| m_aPageResolution
.Height
!=aNewResolution
.Height
)
2729 //set modified only when the new resolution is higher and points were skipped before
2730 bool bSetModified
= m_bPointsWereSkipped
&& (m_aPageResolution
.Width
<aNewResolution
.Width
|| m_aPageResolution
.Height
<aNewResolution
.Height
);
2732 m_aPageResolution
= aNewResolution
;
2735 this->modified( lang::EventObject( static_cast< uno::XWeak
* >( this ) ) );
2738 else if( rPropertyName
== "ZoomFactors" )
2740 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
2741 uno::Sequence
< beans::PropertyValue
> aZoomFactors
;
2742 if( ! (rValue
>>= aZoomFactors
) )
2743 throw lang::IllegalArgumentException( "Property 'ZoomFactors' requires value of type Sequence< PropertyValue >", nullptr, 0 );
2745 sal_Int32 nFilterArgs
= aZoomFactors
.getLength();
2746 beans::PropertyValue
* pDataValues
= aZoomFactors
.getArray();
2747 while( nFilterArgs
-- )
2749 if ( pDataValues
->Name
== "ScaleXNumerator" )
2750 pDataValues
->Value
>>= m_nScaleXNumerator
;
2751 else if ( pDataValues
->Name
== "ScaleXDenominator" )
2752 pDataValues
->Value
>>= m_nScaleXDenominator
;
2753 else if ( pDataValues
->Name
== "ScaleYNumerator" )
2754 pDataValues
->Value
>>= m_nScaleYNumerator
;
2755 else if ( pDataValues
->Name
== "ScaleYDenominator" )
2756 pDataValues
->Value
>>= m_nScaleYDenominator
;
2761 else if( rPropertyName
== "SdrViewIsInEditMode" )
2763 //#i77362 change notification for changes on additional shapes are missing
2764 if( ! (rValue
>>= m_bSdrViewIsInEditMode
) )
2765 throw lang::IllegalArgumentException( "Property 'SdrViewIsInEditMode' requires value of type sal_Bool", nullptr, 0 );
2768 throw beans::UnknownPropertyException( "unknown property was tried to set to chart wizard " + rPropertyName
, nullptr );
2771 Any SAL_CALL
ChartView::getPropertyValue( const OUString
& rPropertyName
)
2773 if( rPropertyName
!= "Resolution" )
2774 throw beans::UnknownPropertyException( "unknown property was tried to get from chart wizard " + rPropertyName
, nullptr );
2776 return Any(m_aPageResolution
);
2779 void SAL_CALL
ChartView::addPropertyChangeListener(
2780 const OUString
& /* aPropertyName */, const Reference
< beans::XPropertyChangeListener
>& /* xListener */ )
2782 OSL_FAIL("not implemented");
2784 void SAL_CALL
ChartView::removePropertyChangeListener(
2785 const OUString
& /* aPropertyName */, const Reference
< beans::XPropertyChangeListener
>& /* aListener */ )
2787 OSL_FAIL("not implemented");
2790 void SAL_CALL
ChartView::addVetoableChangeListener( const OUString
& /* PropertyName */, const Reference
< beans::XVetoableChangeListener
>& /* aListener */ )
2792 OSL_FAIL("not implemented");
2795 void SAL_CALL
ChartView::removeVetoableChangeListener( const OUString
& /* PropertyName */, const Reference
< beans::XVetoableChangeListener
>& /* aListener */ )
2797 OSL_FAIL("not implemented");
2800 // ____ XMultiServiceFactory ____
2802 Reference
< uno::XInterface
> ChartView::createInstance( const OUString
& aServiceSpecifier
)
2804 SolarMutexGuard aSolarGuard
;
2806 SdrModel
* pModel
= ( m_pDrawModelWrapper
? &m_pDrawModelWrapper
->getSdrModel() : nullptr );
2809 if ( aServiceSpecifier
== "com.sun.star.drawing.DashTable" )
2811 if ( !m_xDashTable
.is() )
2813 m_xDashTable
= SvxUnoDashTable_createInstance( pModel
);
2815 return m_xDashTable
;
2817 else if ( aServiceSpecifier
== "com.sun.star.drawing.GradientTable" )
2819 if ( !m_xGradientTable
.is() )
2821 m_xGradientTable
= SvxUnoGradientTable_createInstance( pModel
);
2823 return m_xGradientTable
;
2825 else if ( aServiceSpecifier
== "com.sun.star.drawing.HatchTable" )
2827 if ( !m_xHatchTable
.is() )
2829 m_xHatchTable
= SvxUnoHatchTable_createInstance( pModel
);
2831 return m_xHatchTable
;
2833 else if ( aServiceSpecifier
== "com.sun.star.drawing.BitmapTable" )
2835 if ( !m_xBitmapTable
.is() )
2837 m_xBitmapTable
= SvxUnoBitmapTable_createInstance( pModel
);
2839 return m_xBitmapTable
;
2841 else if ( aServiceSpecifier
== "com.sun.star.drawing.TransparencyGradientTable" )
2843 if ( !m_xTransGradientTable
.is() )
2845 m_xTransGradientTable
= SvxUnoTransGradientTable_createInstance( pModel
);
2847 return m_xTransGradientTable
;
2849 else if ( aServiceSpecifier
== "com.sun.star.drawing.MarkerTable" )
2851 if ( !m_xMarkerTable
.is() )
2853 m_xMarkerTable
= SvxUnoMarkerTable_createInstance( pModel
);
2855 return m_xMarkerTable
;
2862 Reference
< uno::XInterface
> ChartView::createInstanceWithArguments( const OUString
& ServiceSpecifier
, const uno::Sequence
< uno::Any
>& Arguments
)
2864 OSL_ENSURE( Arguments
.hasElements(), "ChartView::createInstanceWithArguments: arguments are ignored" );
2865 return createInstance( ServiceSpecifier
);
2868 uno::Sequence
< OUString
> ChartView::getAvailableServiceNames()
2870 uno::Sequence
< OUString
> aServiceNames( 6 );
2872 aServiceNames
[0] = "com.sun.star.drawing.DashTable";
2873 aServiceNames
[1] = "com.sun.star.drawing.GradientTable";
2874 aServiceNames
[2] = "com.sun.star.drawing.HatchTable";
2875 aServiceNames
[3] = "com.sun.star.drawing.BitmapTable";
2876 aServiceNames
[4] = "com.sun.star.drawing.TransparencyGradientTable";
2877 aServiceNames
[5] = "com.sun.star.drawing.MarkerTable";
2879 return aServiceNames
;
2882 OUString
ChartView::dump()
2884 #if HAVE_FEATURE_DESKTOP
2885 // Used for unit tests and in chartcontroller only, no need to drag in this when cross-compiling
2888 uno::Reference
< drawing::XShapes
> xShapes( m_xDrawPage
, uno::UNO_QUERY_THROW
);
2889 sal_Int32 n
= xShapes
->getCount();
2890 OUStringBuffer aBuffer
;
2891 for(sal_Int32 i
= 0; i
< n
; ++i
)
2893 uno::Reference
< drawing::XShapes
> xShape(xShapes
->getByIndex(i
), uno::UNO_QUERY
);
2896 OUString aString
= XShapeDumper::dump(mxRootShape
);
2897 aBuffer
.append(aString
);
2901 uno::Reference
< drawing::XShape
> xSingleShape(xShapes
->getByIndex(i
), uno::UNO_QUERY
);
2902 if(!xSingleShape
.is())
2904 OUString aString
= XShapeDumper::dump(xSingleShape
);
2905 aBuffer
.append(aString
);
2907 aBuffer
.append("\n\n");
2910 return aBuffer
.makeStringAndClear();
2916 void ChartView::setViewDirty()
2918 osl::MutexGuard
aGuard(maTimeMutex
);
2919 m_bViewDirty
= true;
2922 IMPL_LINK_NOARG(ChartView
, UpdateTimeBased
, Timer
*, void)
2928 void ChartView::createShapes2D( const awt::Size
& rPageSize
)
2930 ShapeFactory
* pShapeFactory
= ShapeFactory::getOrCreateShapeFactory(m_xShapeFactory
);
2932 // todo: it would be nicer to just pass the page m_xDrawPage and format it,
2933 // but the draw page does not support XPropertySet
2934 formatPage( mrChartModel
, rPageSize
, mxRootShape
, m_xShapeFactory
);
2936 CreateShapeParam2D aParam
;
2937 aParam
.maRemainingSpace
.X
= 0;
2938 aParam
.maRemainingSpace
.Y
= 0;
2939 aParam
.maRemainingSpace
.Width
= rPageSize
.Width
;
2940 aParam
.maRemainingSpace
.Height
= rPageSize
.Height
;
2942 //create the group shape for diagram and axes first to have title and legends on top of it
2943 uno::Reference
< XDiagram
> xDiagram( mrChartModel
.getFirstDiagram() );
2944 OUString
aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM
, OUString::number( 0 ) ) );//todo: other index if more than one diagram is possible
2945 uno::Reference
< drawing::XShapes
> xDiagramPlusAxesPlusMarkHandlesGroup_Shapes(
2946 pShapeFactory
->createGroup2D(mxRootShape
,aDiagramCID
) );
2948 aParam
.mxMarkHandles
= pShapeFactory
->createInvisibleRectangle(
2949 xDiagramPlusAxesPlusMarkHandlesGroup_Shapes
, awt::Size(0,0));
2950 ShapeFactory::setShapeName(aParam
.mxMarkHandles
, "MarkHandles");
2952 aParam
.mxPlotAreaWithAxes
= pShapeFactory
->createInvisibleRectangle(
2953 xDiagramPlusAxesPlusMarkHandlesGroup_Shapes
, awt::Size(0, 0));
2954 ShapeFactory::setShapeName(aParam
.mxPlotAreaWithAxes
, "PlotAreaIncludingAxes");
2956 aParam
.mxDiagramWithAxesShapes
= pShapeFactory
->createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes
);
2958 bool bAutoPositionDummy
= true;
2961 lcl_createButtons(mxRootShape
, m_xShapeFactory
, mrChartModel
, aParam
.maRemainingSpace
);
2964 TitleHelper::MAIN_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
,
2965 aParam
.maRemainingSpace
, rPageSize
, ALIGN_TOP
, bAutoPositionDummy
);
2966 if (aParam
.maRemainingSpace
.Width
<= 0 || aParam
.maRemainingSpace
.Height
<= 0)
2970 TitleHelper::SUB_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
,
2971 aParam
.maRemainingSpace
, rPageSize
, ALIGN_TOP
, bAutoPositionDummy
);
2972 if (aParam
.maRemainingSpace
.Width
<= 0|| aParam
.maRemainingSpace
.Height
<= 0)
2975 aParam
.mpSeriesPlotterContainer
.reset(new SeriesPlotterContainer(m_aVCooSysList
));
2976 aParam
.mpSeriesPlotterContainer
->initializeCooSysAndSeriesPlotter( mrChartModel
);
2977 if(maTimeBased
.bTimeBased
&& maTimeBased
.nFrame
!= 0)
2979 SeriesPlottersType
& rSeriesPlotter
= aParam
.mpSeriesPlotterContainer
->getSeriesPlotterList();
2980 size_t n
= rSeriesPlotter
.size();
2981 for(size_t i
= 0; i
< n
; ++i
)
2983 std::vector
<VDataSeries
*> aAllNewDataSeries
= rSeriesPlotter
[i
]->getAllSeries();
2984 std::vector
< VDataSeries
* >& rAllOldDataSeries
=
2985 maTimeBased
.m_aDataSeriesList
[i
];
2986 size_t m
= std::min(aAllNewDataSeries
.size(), rAllOldDataSeries
.size());
2987 for(size_t j
= 0; j
< m
; ++j
)
2989 aAllNewDataSeries
[j
]->setOldTimeBased(
2990 rAllOldDataSeries
[j
], (maTimeBased
.nFrame
% 60)/60.0);
2996 LegendHelper::getLegend( mrChartModel
), mxRootShape
, m_xShapeFactory
, m_xCC
,
2997 aParam
.maRemainingSpace
, rPageSize
, mrChartModel
, aParam
.mpSeriesPlotterContainer
->getLegendEntryProviderList(),
2998 lcl_getDefaultWritingModeFromPool( m_pDrawModelWrapper
) );
2999 if (aParam
.maRemainingSpace
.Width
<= 0 || aParam
.maRemainingSpace
.Height
<= 0)
3002 if (!createAxisTitleShapes2D(aParam
, rPageSize
))
3005 bool bDummy
= false;
3006 bool bIsVertical
= DiagramHelper::getVertical(xDiagram
, bDummy
, bDummy
);
3008 if (getAvailablePosAndSizeForDiagram(aParam
, rPageSize
, mrChartModel
.getFirstDiagram()))
3010 awt::Rectangle aUsedOuterRect
= impl_createDiagramAndContent(aParam
, rPageSize
);
3012 if (aParam
.mxPlotAreaWithAxes
.is())
3014 aParam
.mxPlotAreaWithAxes
->setPosition(awt::Point(aUsedOuterRect
.X
, aUsedOuterRect
.Y
));
3015 aParam
.mxPlotAreaWithAxes
->setSize(awt::Size(aUsedOuterRect
.Width
, aUsedOuterRect
.Height
));
3018 //correct axis title position
3019 awt::Rectangle
aDiagramPlusAxesRect( aUsedOuterRect
);
3020 if (aParam
.mbAutoPosTitleX
)
3021 changePositionOfAxisTitle(aParam
.mpVTitleX
.get(), ALIGN_BOTTOM
, aDiagramPlusAxesRect
, rPageSize
);
3022 if (aParam
.mbAutoPosTitleY
)
3023 changePositionOfAxisTitle(aParam
.mpVTitleY
.get(), ALIGN_LEFT
, aDiagramPlusAxesRect
, rPageSize
);
3024 if (aParam
.mbAutoPosTitleZ
)
3025 changePositionOfAxisTitle(aParam
.mpVTitleZ
.get(), ALIGN_Z
, aDiagramPlusAxesRect
, rPageSize
);
3026 if (aParam
.mbAutoPosSecondTitleX
)
3027 changePositionOfAxisTitle(aParam
.mpVTitleSecondX
.get(), bIsVertical
? ALIGN_RIGHT
: ALIGN_TOP
, aDiagramPlusAxesRect
, rPageSize
);
3028 if (aParam
.mbAutoPosSecondTitleY
)
3029 changePositionOfAxisTitle(aParam
.mpVTitleSecondY
.get(), bIsVertical
? ALIGN_TOP
: ALIGN_RIGHT
, aDiagramPlusAxesRect
, rPageSize
);
3032 //cleanup: remove all empty group shapes to avoid grey border lines:
3033 lcl_removeEmptyGroupShapes( mxRootShape
);
3035 if(maTimeBased
.bTimeBased
&& maTimeBased
.nFrame
% 60 == 0)
3037 // create copy of the data for next frame
3038 SeriesPlottersType
& rSeriesPlotter
= aParam
.mpSeriesPlotterContainer
->getSeriesPlotterList();
3039 size_t n
= rSeriesPlotter
.size();
3040 maTimeBased
.m_aDataSeriesList
.clear();
3041 maTimeBased
.m_aDataSeriesList
.resize(n
);
3042 for(size_t i
= 0; i
< n
; ++i
)
3044 std::vector
<VDataSeries
*> aAllNewDataSeries
= rSeriesPlotter
[i
]->getAllSeries();
3045 std::vector
<VDataSeries
*>& rAllOldDataSeries
= maTimeBased
.m_aDataSeriesList
[i
];
3046 size_t m
= aAllNewDataSeries
.size();
3047 for(size_t j
= 0; j
< m
; ++j
)
3049 rAllOldDataSeries
.push_back( aAllNewDataSeries
[j
]->
3050 createCopyForTimeBased() );
3054 maTimeBased
.maTimer
.Stop();
3057 if(maTimeBased
.bTimeBased
&& !maTimeBased
.maTimer
.IsActive())
3059 maTimeBased
.maTimer
.SetTimeout(15);
3060 maTimeBased
.maTimer
.SetInvokeHandler(LINK(this, ChartView
, UpdateTimeBased
));
3061 maTimeBased
.maTimer
.Start();
3065 bool ChartView::createAxisTitleShapes2D( CreateShapeParam2D
& rParam
, const css::awt::Size
& rPageSize
)
3067 uno::Reference
<XDiagram
> xDiagram
= mrChartModel
.getFirstDiagram();
3069 Reference
< chart2::XChartType
> xChartType( DiagramHelper::getChartTypeByIndex( xDiagram
, 0 ) );
3070 sal_Int32 nDimension
= DiagramHelper::getDimension( xDiagram
);
3072 if( ChartTypeHelper::isSupportingMainAxis( xChartType
, nDimension
, 0 ) )
3073 rParam
.mpVTitleX
= lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION
, mxRootShape
, m_xShapeFactory
, mrChartModel
3074 , rParam
.maRemainingSpace
, rPageSize
, ALIGN_BOTTOM
, rParam
.mbAutoPosTitleX
);
3075 if (rParam
.maRemainingSpace
.Width
<= 0 ||rParam
.maRemainingSpace
.Height
<= 0)
3078 if( ChartTypeHelper::isSupportingMainAxis( xChartType
, nDimension
, 1 ) )
3079 rParam
.mpVTitleY
= lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION
, mxRootShape
, m_xShapeFactory
, mrChartModel
3080 , rParam
.maRemainingSpace
, rPageSize
, ALIGN_LEFT
, rParam
.mbAutoPosTitleY
);
3081 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
3084 if( ChartTypeHelper::isSupportingMainAxis( xChartType
, nDimension
, 2 ) )
3085 rParam
.mpVTitleZ
= lcl_createTitle( TitleHelper::Z_AXIS_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
3086 , rParam
.maRemainingSpace
, rPageSize
, ALIGN_RIGHT
, rParam
.mbAutoPosTitleZ
);
3087 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
3090 bool bDummy
= false;
3091 bool bIsVertical
= DiagramHelper::getVertical( xDiagram
, bDummy
, bDummy
);
3093 if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType
, nDimension
) )
3094 rParam
.mpVTitleSecondX
= lcl_createTitle( TitleHelper::SECONDARY_X_AXIS_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
3095 , rParam
.maRemainingSpace
, rPageSize
, bIsVertical
? ALIGN_RIGHT
: ALIGN_TOP
, rParam
.mbAutoPosSecondTitleX
);
3096 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
3099 if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType
, nDimension
) )
3100 rParam
.mpVTitleSecondY
= lcl_createTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE
, mxRootShape
, m_xShapeFactory
, mrChartModel
3101 , rParam
.maRemainingSpace
, rPageSize
, bIsVertical
? ALIGN_TOP
: ALIGN_RIGHT
, rParam
.mbAutoPosSecondTitleY
);
3102 if (rParam
.maRemainingSpace
.Width
<= 0 || rParam
.maRemainingSpace
.Height
<= 0)
3110 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
3111 com_sun_star_comp_chart2_ChartView_get_implementation(css::uno::XComponentContext
*context
,
3112 css::uno::Sequence
<css::uno::Any
> const &)
3114 ::chart::ChartModel
*pChartModel
= new ::chart::ChartModel(context
);
3115 return cppu::acquire(new ::chart::ChartView(context
, *pChartModel
));
3118 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */