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 <Diagram.hxx>
21 #include <AxisHelper.hxx>
22 #include <BaseGFXHelper.hxx>
23 #include <ChartTypeHelper.hxx>
24 #include <ChartTypeManager.hxx>
25 #include <ChartTypeTemplate.hxx>
26 #include <ChartType.hxx>
27 #include <DataSeriesHelper.hxx>
28 #include <PropertyHelper.hxx>
29 #include <RegressionCurveHelper.hxx>
30 #include <RegressionCurveModel.hxx>
32 #include <ModifyListenerHelper.hxx>
33 #include <UserDefinedProperties.hxx>
34 #include <ConfigColorScheme.hxx>
35 #include <DiagramHelper.hxx>
36 #include <ThreeDHelper.hxx>
37 #include <CloneHelper.hxx>
38 #include <SceneProperties.hxx>
39 #include <unonames.hxx>
40 #include <BaseCoordinateSystem.hxx>
43 #include <DataTable.hxx>
44 #include <servicenames_charttypes.hxx>
45 #include <defines.hxx>
47 #include <basegfx/numeric/ftools.hxx>
48 #include <com/sun/star/beans/PropertyAttribute.hpp>
49 #include <com/sun/star/chart2/AxisType.hpp>
50 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
51 #include <com/sun/star/chart2/StackingDirection.hpp>
52 #include <com/sun/star/chart2/RelativePosition.hpp>
53 #include <com/sun/star/chart2/RelativeSize.hpp>
54 #include <com/sun/star/chart2/PieChartSubType.hpp>
55 #include <com/sun/star/chart/MissingValueTreatment.hpp>
56 #include <com/sun/star/container/NoSuchElementException.hpp>
57 #include <com/sun/star/drawing/ShadeMode.hpp>
58 #include <com/sun/star/uno/XComponentContext.hpp>
59 #include <com/sun/star/util/CloseVetoException.hpp>
61 #include <cppuhelper/supportsservice.hxx>
62 #include <comphelper/diagnose_ex.hxx>
63 #include <o3tl/safeint.hxx>
64 #include <rtl/math.hxx>
65 #include <tools/helpers.hxx>
70 using namespace ::com::sun::star
;
71 using namespace ::com::sun::star::beans::PropertyAttribute
;
72 using namespace ::chart::SceneProperties
;
74 using ::com::sun::star::beans::Property
;
75 using ::com::sun::star::uno::Sequence
;
76 using ::com::sun::star::uno::Reference
;
77 using ::com::sun::star::uno::Any
;
78 using ::osl::MutexGuard
;
86 PROP_DIAGRAM_REL_SIZE
,
87 PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS
,
88 PROP_DIAGRAM_SORT_BY_X_VALUES
,
89 PROP_DIAGRAM_CONNECT_BARS
,
90 PROP_DIAGRAM_GROUP_BARS_PER_AXIS
,
91 PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS
,
92 PROP_DIAGRAM_STARTING_ANGLE
,
93 PROP_DIAGRAM_RIGHT_ANGLED_AXES
,
94 PROP_DIAGRAM_PERSPECTIVE
,
95 PROP_DIAGRAM_ROTATION_HORIZONTAL
,
96 PROP_DIAGRAM_ROTATION_VERTICAL
,
97 PROP_DIAGRAM_MISSING_VALUE_TREATMENT
,
98 PROP_DIAGRAM_3DRELATIVEHEIGHT
,
99 PROP_DIAGRAM_DATATABLEHBORDER
,
100 PROP_DIAGRAM_OF_PIE_TYPE
,
101 PROP_DIAGRAM_SPLIT_POS
,
102 PROP_DIAGRAM_DATATABLEVBORDER
,
103 PROP_DIAGRAM_DATATABLEOUTLINE
,
104 PROP_DIAGRAM_EXTERNALDATA
107 void lcl_AddPropertiesToVector(
108 std::vector
< Property
> & rOutProperties
)
110 rOutProperties
.emplace_back( "RelativePosition",
111 PROP_DIAGRAM_REL_POS
,
112 cppu::UnoType
<chart2::RelativePosition
>::get(),
113 beans::PropertyAttribute::BOUND
114 | beans::PropertyAttribute::MAYBEVOID
);
116 rOutProperties
.emplace_back( "RelativeSize",
117 PROP_DIAGRAM_REL_SIZE
,
118 cppu::UnoType
<chart2::RelativeSize
>::get(),
119 beans::PropertyAttribute::BOUND
120 | beans::PropertyAttribute::MAYBEVOID
);
122 rOutProperties
.emplace_back( "PosSizeExcludeAxes",
123 PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS
,
124 cppu::UnoType
<bool>::get(),
125 beans::PropertyAttribute::BOUND
126 | beans::PropertyAttribute::MAYBEDEFAULT
);
128 rOutProperties
.emplace_back( CHART_UNONAME_SORT_BY_XVALUES
,
129 PROP_DIAGRAM_SORT_BY_X_VALUES
,
130 cppu::UnoType
<bool>::get(),
131 beans::PropertyAttribute::BOUND
132 | beans::PropertyAttribute::MAYBEDEFAULT
);
134 rOutProperties
.emplace_back( "ConnectBars",
135 PROP_DIAGRAM_CONNECT_BARS
,
136 cppu::UnoType
<bool>::get(),
137 beans::PropertyAttribute::BOUND
138 | beans::PropertyAttribute::MAYBEDEFAULT
);
140 rOutProperties
.emplace_back( "GroupBarsPerAxis",
141 PROP_DIAGRAM_GROUP_BARS_PER_AXIS
,
142 cppu::UnoType
<bool>::get(),
143 beans::PropertyAttribute::BOUND
144 | beans::PropertyAttribute::MAYBEDEFAULT
);
146 rOutProperties
.emplace_back( "IncludeHiddenCells",
147 PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS
,
148 cppu::UnoType
<bool>::get(),
149 beans::PropertyAttribute::BOUND
150 | beans::PropertyAttribute::MAYBEDEFAULT
);
152 rOutProperties
.emplace_back( "StartingAngle",
153 PROP_DIAGRAM_STARTING_ANGLE
,
154 cppu::UnoType
<sal_Int32
>::get(),
155 beans::PropertyAttribute::BOUND
156 | beans::PropertyAttribute::MAYBEDEFAULT
);
158 rOutProperties
.emplace_back( "RightAngledAxes",
159 PROP_DIAGRAM_RIGHT_ANGLED_AXES
,
160 cppu::UnoType
<bool>::get(),
161 beans::PropertyAttribute::BOUND
162 | beans::PropertyAttribute::MAYBEDEFAULT
);
164 rOutProperties
.emplace_back( "Perspective",
165 PROP_DIAGRAM_PERSPECTIVE
,
166 cppu::UnoType
<sal_Int32
>::get(),
167 beans::PropertyAttribute::MAYBEVOID
);
169 rOutProperties
.emplace_back( "RotationHorizontal",
170 PROP_DIAGRAM_ROTATION_HORIZONTAL
,
171 cppu::UnoType
<sal_Int32
>::get(),
172 beans::PropertyAttribute::MAYBEVOID
);
174 rOutProperties
.emplace_back( "RotationVertical",
175 PROP_DIAGRAM_ROTATION_VERTICAL
,
176 cppu::UnoType
<sal_Int32
>::get(),
177 beans::PropertyAttribute::MAYBEVOID
);
179 rOutProperties
.emplace_back( "MissingValueTreatment",
180 PROP_DIAGRAM_MISSING_VALUE_TREATMENT
,
181 cppu::UnoType
<sal_Int32
>::get(),
182 beans::PropertyAttribute::BOUND
183 | beans::PropertyAttribute::MAYBEVOID
);
184 rOutProperties
.emplace_back( "3DRelativeHeight",
185 PROP_DIAGRAM_3DRELATIVEHEIGHT
,
186 cppu::UnoType
<sal_Int32
>::get(),
187 beans::PropertyAttribute::MAYBEVOID
);
188 rOutProperties
.emplace_back( "SubPieType",
189 PROP_DIAGRAM_OF_PIE_TYPE
,
190 cppu::UnoType
<chart2::PieChartSubType
>::get(),
191 beans::PropertyAttribute::MAYBEVOID
);
192 rOutProperties
.emplace_back( "SplitPos",
193 PROP_DIAGRAM_SPLIT_POS
,
194 cppu::UnoType
<sal_Int32
>::get(),
195 beans::PropertyAttribute::MAYBEVOID
);
196 rOutProperties
.emplace_back( "ExternalData",
197 PROP_DIAGRAM_EXTERNALDATA
,
198 cppu::UnoType
<OUString
>::get(),
199 beans::PropertyAttribute::MAYBEVOID
);
202 const ::chart::tPropertyValueMap
& StaticDiagramDefaults()
204 static ::chart::tPropertyValueMap aStaticDefaults
= []()
206 ::chart::tPropertyValueMap aMap
;
207 ::chart::PropertyHelper::setPropertyValueDefault( aMap
, PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS
, true );
208 ::chart::PropertyHelper::setPropertyValueDefault( aMap
, PROP_DIAGRAM_SORT_BY_X_VALUES
, false );
209 ::chart::PropertyHelper::setPropertyValueDefault( aMap
, PROP_DIAGRAM_CONNECT_BARS
, false );
210 ::chart::PropertyHelper::setPropertyValueDefault( aMap
, PROP_DIAGRAM_GROUP_BARS_PER_AXIS
, true );
211 ::chart::PropertyHelper::setPropertyValueDefault( aMap
, PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS
, true );
212 ::chart::PropertyHelper::setPropertyValueDefault( aMap
, PROP_DIAGRAM_RIGHT_ANGLED_AXES
, false );
213 ::chart::PropertyHelper::setPropertyValueDefault
< sal_Int32
>( aMap
, PROP_DIAGRAM_STARTING_ANGLE
, 90 );
214 ::chart::PropertyHelper::setPropertyValueDefault
< sal_Int32
>( aMap
, PROP_DIAGRAM_3DRELATIVEHEIGHT
, 100 );
215 ::chart::PropertyHelper::setPropertyValueDefault
< chart2::PieChartSubType
>( aMap
, PROP_DIAGRAM_OF_PIE_TYPE
,
216 chart2::PieChartSubType_NONE
);
217 ::chart::PropertyHelper::setPropertyValueDefault
< sal_Int32
>( aMap
, PROP_DIAGRAM_SPLIT_POS
, 2 );
218 ::chart::SceneProperties::AddDefaultsToMap( aMap
);
221 return aStaticDefaults
;
224 ::cppu::OPropertyArrayHelper
& StaticDiagramInfoHelper()
226 static ::cppu::OPropertyArrayHelper aPropHelper
= []()
228 std::vector
< css::beans::Property
> aProperties
;
229 lcl_AddPropertiesToVector( aProperties
);
230 ::chart::SceneProperties::AddPropertiesToVector( aProperties
);
231 ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties
);
233 std::sort( aProperties
.begin(), aProperties
.end(),
234 ::chart::PropertyNameLess() );
236 return ::cppu::OPropertyArrayHelper( aProperties
.data(), aProperties
.size() );
241 const uno::Reference
< beans::XPropertySetInfo
>& StaticDiagramInfo()
243 static const uno::Reference
< beans::XPropertySetInfo
> xPropertySetInfo(
244 ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDiagramInfoHelper() ) );
245 return xPropertySetInfo
;
248 void lcl_CloneCoordinateSystems(
249 const ::chart::Diagram::tCoordinateSystemContainerType
& rSource
,
250 ::chart::Diagram::tCoordinateSystemContainerType
& rDestination
)
252 for( rtl::Reference
< ::chart::BaseCoordinateSystem
> const & i
: rSource
)
254 auto xClone
= i
->createClone();
255 ::chart::BaseCoordinateSystem
* pClone
= dynamic_cast<::chart::BaseCoordinateSystem
*>(xClone
.get());
257 rDestination
.push_back( pClone
);
261 } // anonymous namespace
266 Diagram::Diagram( uno::Reference
< uno::XComponentContext
> xContext
) :
267 m_xContext(std::move( xContext
)),
268 m_xModifyEventForwarder( new ModifyEventForwarder() )
270 // Set camera position to a default position (that should be set hard, so
271 // that it will be exported. The property default is a camera looking
272 // straight ono the scene). These defaults have been acquired from the old
273 // chart implementation.
274 setFastPropertyValue_NoBroadcast(
275 PROP_SCENE_CAMERA_GEOMETRY
, uno::Any(
276 ThreeDHelper::getDefaultCameraGeometry()));
279 Diagram::Diagram( const Diagram
& rOther
) :
280 impl::Diagram_Base(rOther
),
281 ::property::OPropertySet( rOther
),
282 m_xContext( rOther
.m_xContext
),
283 m_xModifyEventForwarder( new ModifyEventForwarder() )
285 lcl_CloneCoordinateSystems( rOther
.m_aCoordSystems
, m_aCoordSystems
);
286 for (auto & xSystem
: m_aCoordSystems
)
287 xSystem
->addModifyListener(m_xModifyEventForwarder
);
289 if ( rOther
.m_xWall
)
290 m_xWall
= new Wall( *rOther
.m_xWall
);
291 if ( rOther
.m_xFloor
)
292 m_xFloor
= new Wall( *rOther
.m_xFloor
);
293 m_xTitle
.set( CloneHelper::CreateRefClone
< chart2::XTitle
>()( rOther
.m_xTitle
));
294 if (rOther
.m_xLegend
)
295 m_xLegend
= new Legend(*rOther
.m_xLegend
);
296 if (rOther
.m_xDataTable
)
297 m_xDataTable
= new DataTable(*rOther
.m_xDataTable
);
300 m_xWall
->addModifyListener( m_xModifyEventForwarder
);
302 m_xFloor
->addModifyListener( m_xModifyEventForwarder
);
303 ModifyListenerHelper::addListener( m_xTitle
, m_xModifyEventForwarder
);
304 ModifyListenerHelper::addListener( m_xLegend
, m_xModifyEventForwarder
);
311 for (auto & xSystem
: m_aCoordSystems
)
312 xSystem
->removeModifyListener(m_xModifyEventForwarder
);
315 m_xWall
->removeModifyListener( m_xModifyEventForwarder
);
317 m_xFloor
->removeModifyListener( m_xModifyEventForwarder
);
318 ModifyListenerHelper::removeListener( m_xTitle
, m_xModifyEventForwarder
);
319 ModifyListenerHelper::removeListener( m_xLegend
, m_xModifyEventForwarder
);
321 catch( const uno::Exception
& )
323 DBG_UNHANDLED_EXCEPTION("chart2");
327 // ____ XDiagram ____
328 uno::Reference
< beans::XPropertySet
> SAL_CALL
Diagram::getWall()
330 rtl::Reference
< Wall
> xRet
;
331 bool bAddListener
= false;
333 MutexGuard
aGuard( m_aMutex
);
336 m_xWall
.set( new Wall() );
342 xRet
->addModifyListener( m_xModifyEventForwarder
);
346 uno::Reference
< beans::XPropertySet
> SAL_CALL
Diagram::getFloor()
348 rtl::Reference
< Wall
> xRet
;
349 bool bAddListener
= false;
351 MutexGuard
aGuard( m_aMutex
);
354 m_xFloor
.set( new Wall() );
360 xRet
->addModifyListener( m_xModifyEventForwarder
);
364 uno::Reference
< chart2::XLegend
> SAL_CALL
Diagram::getLegend()
366 MutexGuard
aGuard( m_aMutex
);
370 rtl::Reference
< ::chart::Legend
> Diagram::getLegend2() const
372 MutexGuard
aGuard( m_aMutex
);
376 void SAL_CALL
Diagram::setLegend( const uno::Reference
< chart2::XLegend
>& xNewLegend
)
378 auto pLegend
= dynamic_cast<Legend
*>(xNewLegend
.get());
379 assert(!xNewLegend
|| pLegend
);
380 setLegend(rtl::Reference
< Legend
>(pLegend
));
383 void Diagram::setLegend( const rtl::Reference
< Legend
>& xNewLegend
)
385 rtl::Reference
< Legend
> xOldLegend
;
387 MutexGuard
aGuard( m_aMutex
);
388 if( m_xLegend
== xNewLegend
)
390 xOldLegend
= m_xLegend
;
391 m_xLegend
= xNewLegend
;
394 ModifyListenerHelper::removeListener( xOldLegend
, m_xModifyEventForwarder
);
396 ModifyListenerHelper::addListener( xNewLegend
, m_xModifyEventForwarder
);
400 Reference
< chart2::XColorScheme
> SAL_CALL
Diagram::getDefaultColorScheme()
402 Reference
< chart2::XColorScheme
> xRet
;
404 MutexGuard
aGuard( m_aMutex
);
405 xRet
= m_xColorScheme
;
410 xRet
.set( createConfigColorScheme( m_xContext
));
411 MutexGuard
aGuard( m_aMutex
);
412 m_xColorScheme
= xRet
;
417 void SAL_CALL
Diagram::setDefaultColorScheme( const Reference
< chart2::XColorScheme
>& xColorScheme
)
420 MutexGuard
aGuard( m_aMutex
);
421 m_xColorScheme
.set( xColorScheme
);
426 void SAL_CALL
Diagram::setDiagramData(
427 const Reference
< chart2::data::XDataSource
>& xDataSource
,
428 const Sequence
< beans::PropertyValue
>& aArguments
)
430 rtl::Reference
< ::chart::ChartTypeManager
> xChartTypeManager
= new ::chart::ChartTypeManager( m_xContext
);
431 Diagram::tTemplateWithServiceName aTemplateAndService
= getTemplate( xChartTypeManager
);
432 rtl::Reference
< ::chart::ChartTypeTemplate
> xTemplate( aTemplateAndService
.xChartTypeTemplate
);
433 if( !xTemplate
.is() )
434 xTemplate
= xChartTypeManager
->createTemplate( u
"com.sun.star.chart2.template.Column"_ustr
);
437 xTemplate
->changeDiagramData( rtl::Reference
< ::chart::Diagram
>(this), xDataSource
, aArguments
);
441 uno::Reference
< chart2::XTitle
> SAL_CALL
Diagram::getTitleObject()
443 MutexGuard
aGuard( m_aMutex
);
447 void SAL_CALL
Diagram::setTitleObject( const uno::Reference
< chart2::XTitle
>& xNewTitle
)
449 Reference
< chart2::XTitle
> xOldTitle
;
451 MutexGuard
aGuard( m_aMutex
);
452 if( m_xTitle
== xNewTitle
)
454 xOldTitle
= m_xTitle
;
455 m_xTitle
= xNewTitle
;
458 ModifyListenerHelper::removeListener( xOldTitle
, m_xModifyEventForwarder
);
460 ModifyListenerHelper::addListener( xNewTitle
, m_xModifyEventForwarder
);
464 // ____ X3DDefaultSetter ____
465 void SAL_CALL
Diagram::set3DSettingsToDefault()
467 setPropertyToDefault( u
"D3DSceneDistance"_ustr
);
468 setPropertyToDefault( u
"D3DSceneFocalLength"_ustr
);
469 setDefaultRotation();
470 setDefaultIllumination();
473 void SAL_CALL
Diagram::setDefaultRotation()
475 bool bPieOrDonut( isPieOrDonutChart() );
476 setDefaultRotation( bPieOrDonut
);
479 static ::basegfx::B3DHomMatrix
lcl_getCompleteRotationMatrix( Diagram
& rDiagram
)
481 ::basegfx::B3DHomMatrix aCompleteRotation
;
482 double fXAngleRad
=0.0;
483 double fYAngleRad
=0.0;
484 double fZAngleRad
=0.0;
485 rDiagram
.getRotationAngle( fXAngleRad
, fYAngleRad
, fZAngleRad
);
486 aCompleteRotation
.rotate( fXAngleRad
, fYAngleRad
, fZAngleRad
);
487 return aCompleteRotation
;
489 static void lcl_RotateLightSource( Diagram
& rDiagram
490 , int nLightSourceDirectionProp
491 , int nLightSourceOnProp
492 , const ::basegfx::B3DHomMatrix
& rRotationMatrix
)
494 bool bLightOn
= false;
495 if( !(rDiagram
.getFastPropertyValue( nLightSourceOnProp
) >>= bLightOn
) )
500 drawing::Direction3D aLight
;
501 if( rDiagram
.getFastPropertyValue( nLightSourceDirectionProp
) >>= aLight
)
503 ::basegfx::B3DVector
aLightVector( BaseGFXHelper::Direction3DToB3DVector( aLight
) );
504 aLightVector
= rRotationMatrix
*aLightVector
;
506 rDiagram
.setFastPropertyValue( nLightSourceDirectionProp
507 , uno::Any( BaseGFXHelper::B3DVectorToDirection3D( aLightVector
) ) );
512 static void lcl_setLightsForScheme( Diagram
& rDiagram
, const ThreeDLookScheme
& rScheme
)
514 if( rScheme
== ThreeDLookScheme::ThreeDLookScheme_Unknown
)
517 // "D3DSceneLightOn2" / UNO_NAME_3D_SCENE_LIGHTON_2
518 rDiagram
.setFastPropertyValue( PROP_SCENE_LIGHT_ON_2
, uno::Any( true ) );
520 rtl::Reference
< ChartType
> xChartType( rDiagram
.getChartTypeByIndex( 0 ) );
521 uno::Any
aADirection( rScheme
== ThreeDLookScheme::ThreeDLookScheme_Simple
522 ? ChartTypeHelper::getDefaultSimpleLightDirection(xChartType
)
523 : ChartTypeHelper::getDefaultRealisticLightDirection(xChartType
) );
525 // "D3DSceneLightDirection2" / UNO_NAME_3D_SCENE_LIGHTDIRECTION_2
526 rDiagram
.setFastPropertyValue( PROP_SCENE_LIGHT_DIRECTION_2
, aADirection
);
527 //rotate light direction when right angled axes are off but supported
529 bool bRightAngledAxes
= false;
530 rDiagram
.getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES
) >>= bRightAngledAxes
; // "RightAngledAxes"
531 if(!bRightAngledAxes
)
533 if( ChartTypeHelper::isSupportingRightAngledAxes( xChartType
) )
535 ::basegfx::B3DHomMatrix
aRotation( lcl_getCompleteRotationMatrix( rDiagram
) );
536 BaseGFXHelper::ReduceToRotationMatrix( aRotation
);
537 // "D3DSceneLightDirection2", "D3DSceneLightOn2"
538 lcl_RotateLightSource( rDiagram
, PROP_SCENE_LIGHT_DIRECTION_2
, PROP_SCENE_LIGHT_ON_2
, aRotation
);
543 sal_Int32 nColor
= ::chart::ChartTypeHelper::getDefaultDirectLightColor(
544 rScheme
== ThreeDLookScheme::ThreeDLookScheme_Simple
, xChartType
);
545 // "D3DSceneLightColor2" / UNO_NAME_3D_SCENE_LIGHTCOLOR_2
546 rDiagram
.setFastPropertyValue( PROP_SCENE_LIGHT_COLOR_2
, uno::Any( nColor
) );
548 sal_Int32 nAmbientColor
= ::chart::ChartTypeHelper::getDefaultAmbientLightColor(
549 rScheme
== ThreeDLookScheme::ThreeDLookScheme_Simple
, xChartType
);
550 // "D3DSceneAmbientColor" / UNO_NAME_3D_SCENE_AMBIENTCOLOR
551 rDiagram
.setFastPropertyValue( PROP_SCENE_AMBIENT_COLOR
, uno::Any( nAmbientColor
) );
554 void SAL_CALL
Diagram::setDefaultIllumination()
556 drawing::ShadeMode
aShadeMode( drawing::ShadeMode_SMOOTH
);
559 // "D3DSceneShadeMode"
560 getFastPropertyValue( PROP_SCENE_SHADE_MODE
)>>= aShadeMode
;
561 // "D3DSceneLightOn1" / UNO_NAME_3D_SCENE_LIGHTON_1
562 setFastPropertyValue( PROP_SCENE_LIGHT_ON_1
, uno::Any( false ) );
563 setFastPropertyValue( PROP_SCENE_LIGHT_ON_3
, uno::Any( false ) );
564 setFastPropertyValue( PROP_SCENE_LIGHT_ON_4
, uno::Any( false ) );
565 setFastPropertyValue( PROP_SCENE_LIGHT_ON_5
, uno::Any( false ) );
566 setFastPropertyValue( PROP_SCENE_LIGHT_ON_6
, uno::Any( false ) );
567 setFastPropertyValue( PROP_SCENE_LIGHT_ON_7
, uno::Any( false ) );
568 setFastPropertyValue( PROP_SCENE_LIGHT_ON_8
, uno::Any( false ) );
570 catch( const uno::Exception
& )
572 DBG_UNHANDLED_EXCEPTION("chart2");
575 ThreeDLookScheme aScheme
= (aShadeMode
== drawing::ShadeMode_FLAT
)
576 ? ThreeDLookScheme::ThreeDLookScheme_Simple
577 : ThreeDLookScheme::ThreeDLookScheme_Realistic
;
578 lcl_setLightsForScheme( *this, aScheme
);
581 // ____ XCoordinateSystemContainer ____
582 void SAL_CALL
Diagram::addCoordinateSystem(
583 const uno::Reference
< chart2::XCoordinateSystem
>& aCoordSys
)
585 ::chart::BaseCoordinateSystem
* pCoordSys
= dynamic_cast<::chart::BaseCoordinateSystem
*>(aCoordSys
.get());
588 MutexGuard
aGuard( m_aMutex
);
589 if( std::find( m_aCoordSystems
.begin(), m_aCoordSystems
.end(), pCoordSys
)
590 != m_aCoordSystems
.end())
591 throw lang::IllegalArgumentException(u
"coordsys not found"_ustr
, static_cast<cppu::OWeakObject
*>(this), 1);
593 if( !m_aCoordSystems
.empty() )
595 OSL_FAIL( "more than one coordinatesystem is not supported yet by the fileformat" );
598 m_aCoordSystems
.push_back( pCoordSys
);
600 ModifyListenerHelper::addListener( aCoordSys
, m_xModifyEventForwarder
);
604 void SAL_CALL
Diagram::removeCoordinateSystem(
605 const uno::Reference
< chart2::XCoordinateSystem
>& aCoordSys
)
607 ::chart::BaseCoordinateSystem
* pCoordSys
= dynamic_cast<::chart::BaseCoordinateSystem
*>(aCoordSys
.get());
610 MutexGuard
aGuard( m_aMutex
);
611 auto aIt
= std::find( m_aCoordSystems
.begin(), m_aCoordSystems
.end(), pCoordSys
);
612 if( aIt
== m_aCoordSystems
.end())
613 throw container::NoSuchElementException(
614 u
"The given coordinate-system is no element of the container"_ustr
,
615 static_cast< uno::XWeak
* >( this ));
616 m_aCoordSystems
.erase( aIt
);
618 ModifyListenerHelper::removeListener( aCoordSys
, m_xModifyEventForwarder
);
622 uno::Sequence
< uno::Reference
< chart2::XCoordinateSystem
> > SAL_CALL
Diagram::getCoordinateSystems()
624 MutexGuard
aGuard( m_aMutex
);
625 return comphelper::containerToSequence
<uno::Reference
< chart2::XCoordinateSystem
>>( m_aCoordSystems
);
628 Diagram::tCoordinateSystemContainerType
Diagram::getBaseCoordinateSystems() const
630 MutexGuard
aGuard( m_aMutex
);
631 return m_aCoordSystems
;
634 void SAL_CALL
Diagram::setCoordinateSystems(
635 const Sequence
< Reference
< chart2::XCoordinateSystem
> >& aCoordinateSystems
)
637 tCoordinateSystemContainerType aNew
;
638 tCoordinateSystemContainerType aOld
;
639 if( aCoordinateSystems
.hasElements() )
641 OSL_ENSURE( aCoordinateSystems
.getLength()<=1, "more than one coordinatesystem is not supported yet by the fileformat" );
642 ::chart::BaseCoordinateSystem
* pCoordSys
= dynamic_cast<::chart::BaseCoordinateSystem
*>(aCoordinateSystems
[0].get());
644 aNew
.push_back( pCoordSys
);
647 MutexGuard
aGuard( m_aMutex
);
648 std::swap( aOld
, m_aCoordSystems
);
649 m_aCoordSystems
= aNew
;
651 for (auto & xSystem
: aOld
)
652 xSystem
->removeModifyListener(m_xModifyEventForwarder
);
653 for (auto & xSystem
: aNew
)
654 xSystem
->addModifyListener(m_xModifyEventForwarder
);
658 void Diagram::setCoordinateSystems(
659 const std::vector
< rtl::Reference
< BaseCoordinateSystem
> >& aCoordinateSystems
)
661 tCoordinateSystemContainerType aNew
;
662 tCoordinateSystemContainerType aOld
;
663 if( !aCoordinateSystems
.empty() )
665 OSL_ENSURE( aCoordinateSystems
.size()<=1, "more than one coordinatesystem is not supported yet by the fileformat" );
666 aNew
.push_back( aCoordinateSystems
[0] );
669 MutexGuard
aGuard( m_aMutex
);
670 std::swap( aOld
, m_aCoordSystems
);
671 m_aCoordSystems
= aNew
;
673 for (auto & xSystem
: aOld
)
674 xSystem
->removeModifyListener(m_xModifyEventForwarder
);
675 for (auto & xSystem
: aNew
)
676 xSystem
->addModifyListener(m_xModifyEventForwarder
);
680 // ____ XCloneable ____
681 Reference
< util::XCloneable
> SAL_CALL
Diagram::createClone()
683 MutexGuard
aGuard( m_aMutex
);
684 return Reference
< util::XCloneable
>( new Diagram( *this ));
687 // ____ XModifyBroadcaster ____
688 void SAL_CALL
Diagram::addModifyListener( const Reference
< util::XModifyListener
>& aListener
)
690 m_xModifyEventForwarder
->addModifyListener( aListener
);
693 void SAL_CALL
Diagram::removeModifyListener( const Reference
< util::XModifyListener
>& aListener
)
695 m_xModifyEventForwarder
->removeModifyListener( aListener
);
698 // ____ XModifyListener ____
699 void SAL_CALL
Diagram::modified( const lang::EventObject
& aEvent
)
701 m_xModifyEventForwarder
->modified( aEvent
);
704 // ____ XEventListener (base of XModifyListener) ____
705 void SAL_CALL
Diagram::disposing( const lang::EventObject
& /* Source */ )
710 // ____ OPropertySet ____
711 void Diagram::firePropertyChangeEvent()
716 void Diagram::fireModifyEvent()
718 m_xModifyEventForwarder
->modified( lang::EventObject( static_cast< uno::XWeak
* >( this )));
721 // ____ OPropertySet ____
722 void Diagram::GetDefaultValue( sal_Int32 nHandle
, uno::Any
& rAny
) const
724 const tPropertyValueMap
& rStaticDefaults
= StaticDiagramDefaults();
725 tPropertyValueMap::const_iterator
aFound( rStaticDefaults
.find( nHandle
) );
726 if( aFound
== rStaticDefaults
.end() )
729 rAny
= (*aFound
).second
;
732 // ____ OPropertySet ____
733 ::cppu::IPropertyArrayHelper
& SAL_CALL
Diagram::getInfoHelper()
735 return StaticDiagramInfoHelper();
738 // ____ XPropertySet ____
739 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
Diagram::getPropertySetInfo()
741 return StaticDiagramInfo();
744 // ____ XFastPropertySet ____
745 void SAL_CALL
Diagram::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle
, const Any
& rValue
)
747 //special treatment for some 3D properties
748 if( nHandle
== PROP_DIAGRAM_PERSPECTIVE
)
750 sal_Int32 fPerspective
= 20;
751 if( rValue
>>=fPerspective
)
752 setCameraDistance( ThreeDHelper::PerspectiveToCameraDistance( fPerspective
) );
754 else if( nHandle
== PROP_DIAGRAM_ROTATION_HORIZONTAL
755 || nHandle
== PROP_DIAGRAM_ROTATION_VERTICAL
)
757 sal_Int32 nNewAngleDegree
= 0;
758 if( rValue
>>=nNewAngleDegree
)
760 sal_Int32 nHorizontal
, nVertical
;
761 getRotation( nHorizontal
, nVertical
);
762 if( nHandle
== PROP_DIAGRAM_ROTATION_HORIZONTAL
)
763 nHorizontal
= nNewAngleDegree
;
765 nVertical
= nNewAngleDegree
;
766 setRotation( nHorizontal
, nVertical
);
770 ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle
, rValue
);
773 void SAL_CALL
Diagram::getFastPropertyValue( Any
& rValue
, sal_Int32 nHandle
) const
775 //special treatment for some 3D properties
776 if( nHandle
== PROP_DIAGRAM_PERSPECTIVE
)
778 sal_Int32 nPerspective
= ::basegfx::fround( ThreeDHelper::CameraDistanceToPerspective(
779 const_cast< Diagram
* >( this )->getCameraDistance() ) );
780 rValue
<<= nPerspective
;
782 else if( nHandle
== PROP_DIAGRAM_ROTATION_HORIZONTAL
783 || nHandle
== PROP_DIAGRAM_ROTATION_VERTICAL
)
785 sal_Int32 nHorizontal
, nVertical
;
786 const_cast< Diagram
* >( this )->getRotation( nHorizontal
, nVertical
);
787 sal_Int32 nAngleDegree
= 0;
788 if( nHandle
== PROP_DIAGRAM_ROTATION_HORIZONTAL
)
789 nAngleDegree
= nHorizontal
;
791 nAngleDegree
= nVertical
;
792 rValue
<<= nAngleDegree
;
795 ::property::OPropertySet::getFastPropertyValue( rValue
,nHandle
);
798 uno::Reference
<chart2::XDataTable
> SAL_CALL
Diagram::getDataTable()
800 MutexGuard
aGuard( m_aMutex
);
804 rtl::Reference
<::chart::DataTable
> Diagram::getDataTableRef() const
806 MutexGuard
aGuard( m_aMutex
);
810 void SAL_CALL
Diagram::setDataTable(const uno::Reference
<chart2::XDataTable
>& xDataTable
)
812 auto* pDataTable
= dynamic_cast<DataTable
*>(xDataTable
.get());
813 assert(!xDataTable
|| pDataTable
);
814 setDataTable(rtl::Reference
<DataTable
>(pDataTable
));
817 void Diagram::setDataTable(const rtl::Reference
<DataTable
>& xNewDataTable
)
819 rtl::Reference
<DataTable
> xOldDataTable
;
821 MutexGuard
aGuard(m_aMutex
);
822 if (m_xDataTable
== xNewDataTable
)
824 xOldDataTable
= m_xDataTable
;
825 m_xDataTable
= xNewDataTable
;
827 if (xOldDataTable
.is())
828 ModifyListenerHelper::removeListener(xOldDataTable
, m_xModifyEventForwarder
);
829 if (xNewDataTable
.is())
830 ModifyListenerHelper::addListener(xNewDataTable
, m_xModifyEventForwarder
);
834 using impl::Diagram_Base
;
836 IMPLEMENT_FORWARD_XINTERFACE2( Diagram
, Diagram_Base
, ::property::OPropertySet
)
837 IMPLEMENT_FORWARD_XTYPEPROVIDER2( Diagram
, Diagram_Base
, ::property::OPropertySet
)
839 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
840 OUString SAL_CALL
Diagram::getImplementationName()
842 return u
"com.sun.star.comp.chart2.Diagram"_ustr
;
845 sal_Bool SAL_CALL
Diagram::supportsService( const OUString
& rServiceName
)
847 return cppu::supportsService(this, rServiceName
);
850 css::uno::Sequence
< OUString
> SAL_CALL
Diagram::getSupportedServiceNames()
853 u
"com.sun.star.chart2.Diagram"_ustr
,
854 u
"com.sun.star.layout.LayoutElement"_ustr
,
855 u
"com.sun.star.beans.PropertySet"_ustr
};
858 DiagramPositioningMode
Diagram::getDiagramPositioningMode()
860 DiagramPositioningMode eMode
= DiagramPositioningMode::Auto
;
861 chart2::RelativePosition aRelPos
;
862 chart2::RelativeSize aRelSize
;
863 if( (getFastPropertyValue(PROP_DIAGRAM_REL_POS
) >>= aRelPos
) &&
864 (getFastPropertyValue(PROP_DIAGRAM_REL_SIZE
) >>= aRelSize
) )
866 bool bPosSizeExcludeAxes
=false;
867 getFastPropertyValue(PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS
) >>= bPosSizeExcludeAxes
;
868 if( bPosSizeExcludeAxes
)
869 eMode
= DiagramPositioningMode::Excluding
;
871 eMode
= DiagramPositioningMode::Including
;
877 sal_Int32
Diagram::getCorrectedMissingValueTreatment(
878 const rtl::Reference
< ChartType
>& xChartType
)
880 sal_Int32 nResult
= css::chart::MissingValueTreatment::LEAVE_GAP
;
881 const uno::Sequence
< sal_Int32
> aAvailableMissingValueTreatments(
882 ChartTypeHelper::getSupportedMissingValueTreatments( xChartType
) );
884 if( getFastPropertyValue( PROP_DIAGRAM_MISSING_VALUE_TREATMENT
) >>= nResult
)
886 //ensure that the set value is supported by this charttype
887 for( sal_Int32 n
: aAvailableMissingValueTreatments
)
892 //otherwise use the first supported one
893 if( aAvailableMissingValueTreatments
.hasElements() )
895 nResult
= aAvailableMissingValueTreatments
[0];
902 void Diagram::setGeometry3D( sal_Int32 nNewGeometry
)
904 std::vector
< rtl::Reference
< DataSeries
> > aSeriesVec
=
907 for (auto const& series
: aSeriesVec
)
909 DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(
910 series
, u
"Geometry3D"_ustr
, uno::Any( nNewGeometry
));
914 sal_Int32
Diagram::getGeometry3D( bool& rbFound
, bool& rbAmbiguous
)
916 sal_Int32
nCommonGeom( css::chart2::DataPointGeometry3D::CUBOID
);
920 std::vector
< rtl::Reference
< DataSeries
> > aSeriesVec
= getDataSeries();
922 if( aSeriesVec
.empty())
925 for (auto const& series
: aSeriesVec
)
930 if( series
->getPropertyValue( u
"Geometry3D"_ustr
) >>= nGeom
)
938 // further series: compare for uniqueness
939 else if( nCommonGeom
!= nGeom
)
946 catch( const uno::Exception
& )
948 DBG_UNHANDLED_EXCEPTION("chart2");
955 bool Diagram::isPieOrDonutChart()
957 rtl::Reference
< ChartType
> xChartType
= getChartTypeByIndex( 0 );
959 if( xChartType
.is() )
961 OUString aChartType
= xChartType
->getChartType();
962 if( aChartType
== CHART2_SERVICE_NAME_CHARTTYPE_PIE
)
968 bool Diagram::isSupportingFloorAndWall()
970 //pies and donuts currently do not support this because of wrong files from older versions
971 //todo: allow this in future again, if fileversion is available for OLE objects (metastream)
972 //thus the wrong bottom can be removed on import
974 const std::vector
< rtl::Reference
< ChartType
> > aTypes
= getChartTypes();
975 for( rtl::Reference
< ChartType
> const & xType
: aTypes
)
977 OUString sChartType
= xType
->getChartType();
978 if( sChartType
.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE
) )
980 if( sChartType
.match(CHART2_SERVICE_NAME_CHARTTYPE_NET
) )
982 if( sChartType
.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET
) )
989 * This method implements the logic of checking if a series can be moved
990 * forward/backward. Depending on the "bDoMove" parameter the series will
991 * be moved (bDoMove = true) or the function just will test if the
992 * series can be moved without doing the move (bDoMove = false).
995 * Reference to the diagram that contains the series.
997 * @param xGivenDataSeries
998 * Reference to the series that should moved or tested for moving.
1001 * Direction in which the series should be moved or tested for moving.
1004 * Should this function really move the series (true) or just test if it is
1009 * in case of bDoMove == true
1010 * - True : if the move was done
1011 * - False : the move failed
1012 * in case of bDoMove == false
1013 * - True : the series can be moved
1014 * - False : the series can not be moved
1017 static bool lcl_moveSeriesOrCheckIfMoveIsAllowed(
1019 const rtl::Reference
< DataSeries
>& xGivenDataSeries
,
1023 bool bMovedOrMoveAllowed
= false;
1027 if( !xGivenDataSeries
.is() )
1030 //find position of series.
1031 bool bFound
= false;
1032 const std::vector
< rtl::Reference
< BaseCoordinateSystem
> > aCooSysList( rDiagram
.getBaseCoordinateSystems() );
1034 for( std::size_t nCS
= 0; !bFound
&& nCS
< aCooSysList
.size(); ++nCS
)
1036 const rtl::Reference
< BaseCoordinateSystem
> & xCooSys( aCooSysList
[nCS
] );
1038 //iterate through all chart types in the current coordinate system
1039 std::vector
< rtl::Reference
< ChartType
> > aChartTypeList( xCooSys
->getChartTypes2() );
1040 rtl::Reference
< ChartType
> xFormerChartType
;
1042 for( std::size_t nT
= 0; !bFound
&& nT
< aChartTypeList
.size(); ++nT
)
1044 rtl::Reference
< ChartType
> xCurrentChartType( aChartTypeList
[nT
] );
1046 //iterate through all series in this chart type
1048 std::vector
< rtl::Reference
< DataSeries
> > aSeriesList
= xCurrentChartType
->getDataSeries2();
1050 for( std::size_t nS
= 0; !bFound
&& nS
< aSeriesList
.size(); ++nS
)
1053 // We found the series we are interested in!
1054 if( xGivenDataSeries
==aSeriesList
[nS
] )
1056 std::size_t nOldSeriesIndex
= nS
;
1061 sal_Int32 nNewSeriesIndex
= nS
;
1063 // tdf#34517 Bringing forward means increasing, backwards means decreasing series position
1069 if( nNewSeriesIndex
>= 0 && o3tl::make_unsigned(nNewSeriesIndex
) < aSeriesList
.size() )
1071 //move series in the same charttype
1072 bMovedOrMoveAllowed
= true;
1075 aSeriesList
[ nOldSeriesIndex
] = aSeriesList
[ nNewSeriesIndex
];
1076 aSeriesList
[ nNewSeriesIndex
] = xGivenDataSeries
;
1077 xCurrentChartType
->setDataSeries( aSeriesList
);
1080 else if( nNewSeriesIndex
<0 )
1082 //exchange series with former charttype
1083 if( xFormerChartType
.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType
, xCurrentChartType
) )
1085 bMovedOrMoveAllowed
= true;
1088 std::vector
< rtl::Reference
< DataSeries
> > aOtherSeriesList
= xFormerChartType
->getDataSeries2();
1089 sal_Int32 nOtherSeriesIndex
= aOtherSeriesList
.size()-1;
1090 if( nOtherSeriesIndex
>= 0 && o3tl::make_unsigned(nOtherSeriesIndex
) < aOtherSeriesList
.size() )
1092 rtl::Reference
< DataSeries
> xExchangeSeries( aOtherSeriesList
[nOtherSeriesIndex
] );
1093 aOtherSeriesList
[nOtherSeriesIndex
] = xGivenDataSeries
;
1094 xFormerChartType
->setDataSeries(aOtherSeriesList
);
1096 aSeriesList
[nOldSeriesIndex
] = std::move(xExchangeSeries
);
1097 xCurrentChartType
->setDataSeries(aSeriesList
);
1102 else if( nT
+1 < aChartTypeList
.size() )
1104 //exchange series with next charttype
1105 const rtl::Reference
< ChartType
>& xOtherChartType( aChartTypeList
[nT
+1] );
1106 if( xOtherChartType
.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType
, xCurrentChartType
) )
1108 bMovedOrMoveAllowed
= true;
1111 std::vector
< rtl::Reference
< DataSeries
> > aOtherSeriesList
= xOtherChartType
->getDataSeries2();
1112 if( !aOtherSeriesList
.empty() )
1114 rtl::Reference
<DataSeries
> xExchangeSeries(aOtherSeriesList
[0]);
1115 aOtherSeriesList
[0] = xGivenDataSeries
;
1116 xOtherChartType
->setDataSeries(aOtherSeriesList
);
1118 aSeriesList
[nOldSeriesIndex
] = std::move(xExchangeSeries
);
1119 xCurrentChartType
->setDataSeries(aSeriesList
);
1125 catch( const util::CloseVetoException
& )
1128 catch( const uno::RuntimeException
& )
1133 xFormerChartType
= std::move(xCurrentChartType
);
1137 catch( const util::CloseVetoException
& )
1140 catch( const uno::RuntimeException
& )
1143 return bMovedOrMoveAllowed
;
1146 bool Diagram::isSeriesMoveable(
1147 const rtl::Reference
< DataSeries
>& xGivenDataSeries
,
1150 const bool bDoMove
= false;
1152 bool bIsMoveable
= lcl_moveSeriesOrCheckIfMoveIsAllowed(
1153 *this, xGivenDataSeries
, bForward
, bDoMove
);
1158 bool Diagram::moveSeries( const rtl::Reference
< DataSeries
>& xGivenDataSeries
, bool bForward
)
1160 const bool bDoMove
= true;
1162 bool bMoved
= lcl_moveSeriesOrCheckIfMoveIsAllowed(
1163 *this, xGivenDataSeries
, bForward
, bDoMove
);
1168 std::vector
< rtl::Reference
< ChartType
> > Diagram::getChartTypes()
1170 std::vector
< rtl::Reference
< ChartType
> > aResult
;
1173 for( rtl::Reference
< BaseCoordinateSystem
> const & coords
: getBaseCoordinateSystems() )
1175 const std::vector
< rtl::Reference
< ChartType
> > & aChartTypeSeq( coords
->getChartTypes2());
1176 aResult
.insert( aResult
.end(), aChartTypeSeq
.begin(), aChartTypeSeq
.end() );
1179 catch( const uno::Exception
& )
1181 DBG_UNHANDLED_EXCEPTION("chart2");
1187 rtl::Reference
< ChartType
> Diagram::getChartTypeByIndex( sal_Int32 nIndex
)
1189 rtl::Reference
< ChartType
> xChartType
;
1191 //iterate through all coordinate systems
1192 sal_Int32 nTypesSoFar
= 0;
1193 for( rtl::Reference
< BaseCoordinateSystem
> const & coords
: getBaseCoordinateSystems() )
1195 const std::vector
< rtl::Reference
< ChartType
> > & aChartTypeList( coords
->getChartTypes2() );
1196 if( nIndex
>= 0 && o3tl::make_unsigned(nIndex
) < nTypesSoFar
+ aChartTypeList
.size() )
1198 xChartType
= aChartTypeList
[nIndex
- nTypesSoFar
];
1201 nTypesSoFar
+= aChartTypeList
.size();
1207 bool Diagram::isSupportingDateAxis()
1209 return ::chart::ChartTypeHelper::isSupportingDateAxis( getChartTypeByIndex( 0 ), 0 );
1212 static std::vector
< rtl::Reference
< Axis
> > lcl_getAxisHoldingCategoriesFromDiagram(
1215 std::vector
< rtl::Reference
< Axis
> > aRet
;
1217 // return first x-axis as fall-back
1218 rtl::Reference
< Axis
> xFallBack
;
1221 for( rtl::Reference
< BaseCoordinateSystem
> const & xCooSys
: rDiagram
.getBaseCoordinateSystems() )
1223 OSL_ASSERT( xCooSys
.is());
1224 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
1226 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
1227 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
1229 rtl::Reference
< Axis
> xAxis
= xCooSys
->getAxisByDimension2( nN
,nI
);
1230 OSL_ASSERT( xAxis
.is());
1233 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
1234 if( aScaleData
.Categories
.is() || (aScaleData
.AxisType
== chart2::AxisType::CATEGORY
) )
1236 aRet
.push_back(xAxis
);
1238 if( (nN
== 0) && !xFallBack
.is())
1239 xFallBack
= std::move(xAxis
);
1245 catch( const uno::Exception
& )
1247 DBG_UNHANDLED_EXCEPTION("chart2" );
1251 aRet
.push_back(xFallBack
);
1256 uno::Reference
< chart2::data::XLabeledDataSequence
> Diagram::getCategories()
1258 uno::Reference
< chart2::data::XLabeledDataSequence
> xResult
;
1262 std::vector
< rtl::Reference
< Axis
> > aCatAxes(
1263 lcl_getAxisHoldingCategoriesFromDiagram( *this ));
1264 //search for first categories
1265 if (aCatAxes
.empty())
1268 const rtl::Reference
< Axis
>& xCatAxis(aCatAxes
[0]);
1272 chart2::ScaleData
aScaleData( xCatAxis
->getScaleData());
1273 if( !aScaleData
.Categories
.is() )
1276 xResult
= aScaleData
.Categories
;
1277 uno::Reference
<beans::XPropertySet
> xProp(xResult
->getValues(), uno::UNO_QUERY
);
1282 xProp
->setPropertyValue( u
"Role"_ustr
, uno::Any( u
"categories"_ustr
) );
1284 catch( const uno::Exception
& )
1286 DBG_UNHANDLED_EXCEPTION("chart2");
1290 catch( const uno::Exception
& )
1292 DBG_UNHANDLED_EXCEPTION("chart2");
1298 void Diagram::setCategories(
1299 const uno::Reference
< chart2::data::XLabeledDataSequence
>& xCategories
,
1300 bool bSetAxisType
/* = false */,
1301 bool bCategoryAxis
/* = true */ )
1303 std::vector
< rtl::Reference
< Axis
> > aCatAxes(
1304 lcl_getAxisHoldingCategoriesFromDiagram( *this ));
1306 for (const rtl::Reference
< Axis
>& xCatAxis
: aCatAxes
)
1310 chart2::ScaleData
aScaleData( xCatAxis
->getScaleData());
1311 aScaleData
.Categories
= xCategories
;
1315 aScaleData
.AxisType
= chart2::AxisType::CATEGORY
;
1316 else if( aScaleData
.AxisType
== chart2::AxisType::CATEGORY
|| aScaleData
.AxisType
== chart2::AxisType::DATE
)
1317 aScaleData
.AxisType
= chart2::AxisType::REALNUMBER
;
1319 xCatAxis
->setScaleData( aScaleData
);
1324 bool Diagram::isCategory()
1328 for( rtl::Reference
< BaseCoordinateSystem
> const & xCooSys
: getBaseCoordinateSystems() )
1330 for( sal_Int32 nN
= xCooSys
->getDimension(); nN
--; )
1332 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nN
);
1333 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
1335 rtl::Reference
< Axis
> xAxis
= xCooSys
->getAxisByDimension2( nN
,nI
);
1336 OSL_ASSERT( xAxis
.is());
1339 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
1340 if( aScaleData
.AxisType
== chart2::AxisType::CATEGORY
|| aScaleData
.AxisType
== chart2::AxisType::DATE
)
1347 catch( const uno::Exception
& )
1349 DBG_UNHANDLED_EXCEPTION("chart2");
1355 std::vector
< std::vector
< rtl::Reference
< DataSeries
> > >
1356 Diagram::getDataSeriesGroups()
1358 std::vector
< std::vector
< rtl::Reference
< DataSeries
> > > aResult
;
1360 //iterate through all coordinate systems
1361 for( rtl::Reference
< BaseCoordinateSystem
> const & coords
: getBaseCoordinateSystems() )
1363 //iterate through all chart types in the current coordinate system
1364 for( rtl::Reference
< ChartType
> const & chartType
: coords
->getChartTypes2() )
1366 aResult
.push_back( chartType
->getDataSeries2() );
1372 std::vector
< rtl::Reference
< ::chart::DataSeries
> >
1373 Diagram::getDataSeries()
1375 std::vector
< rtl::Reference
< DataSeries
> > aResult
;
1378 for( rtl::Reference
< BaseCoordinateSystem
> const & coords
: getBaseCoordinateSystems() )
1380 for( rtl::Reference
< ChartType
> const & chartType
: coords
->getChartTypes2() )
1382 const std::vector
< rtl::Reference
< DataSeries
> > aSeriesSeq( chartType
->getDataSeries2() );
1383 aResult
.insert( aResult
.end(), aSeriesSeq
.begin(), aSeriesSeq
.end() );
1387 catch( const uno::Exception
& )
1389 DBG_UNHANDLED_EXCEPTION("chart2");
1395 rtl::Reference
< ChartType
> Diagram::getChartTypeOfSeries(
1396 const rtl::Reference
< DataSeries
>& xGivenDataSeries
)
1398 if( !xGivenDataSeries
.is() )
1401 //iterate through the model to find the given xSeries
1402 //the found parent indicates the charttype
1404 //iterate through all coordinate systems
1406 for( rtl::Reference
< BaseCoordinateSystem
> const & xCooSys
: getBaseCoordinateSystems() )
1408 //iterate through all chart types in the current coordinate system
1409 const std::vector
< rtl::Reference
< ChartType
> > & aChartTypeList( xCooSys
->getChartTypes2() );
1410 for( rtl::Reference
< ChartType
> const & xChartType
: aChartTypeList
)
1412 //iterate through all series in this chart type
1413 for( rtl::Reference
< DataSeries
> const & dataSeries
: xChartType
->getDataSeries2() )
1415 if( xGivenDataSeries
==dataSeries
)
1423 rtl::Reference
< Axis
> Diagram::getAttachedAxis(
1424 const rtl::Reference
< DataSeries
>& xSeries
)
1426 return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries
), this );
1429 bool Diagram::attachSeriesToAxis( bool bAttachToMainAxis
1430 , const rtl::Reference
< DataSeries
>& xDataSeries
1431 , const uno::Reference
< uno::XComponentContext
> & xContext
1434 bool bChanged
= false;
1436 //set property at axis
1438 sal_Int32 nNewAxisIndex
= bAttachToMainAxis
? 0 : 1;
1439 sal_Int32 nOldAxisIndex
= DataSeriesHelper::getAttachedAxisIndex(xDataSeries
);
1440 rtl::Reference
< Axis
> xOldAxis
= getAttachedAxis( xDataSeries
);
1442 if( nOldAxisIndex
!= nNewAxisIndex
)
1446 xDataSeries
->setPropertyValue( u
"AttachedAxisIndex"_ustr
, uno::Any( nNewAxisIndex
) );
1449 catch( const uno::Exception
& )
1451 DBG_UNHANDLED_EXCEPTION("chart2");
1457 rtl::Reference
< Axis
> xAxis
= AxisHelper::getAxis( 1, bAttachToMainAxis
, this );
1458 if(!xAxis
.is()) //create an axis if necessary
1459 xAxis
= AxisHelper::createAxis( 1, bAttachToMainAxis
, this, xContext
);
1462 AxisHelper::makeAxisVisible( xAxis
);
1463 AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis
, this );
1470 void Diagram::replaceCoordinateSystem(
1471 const rtl::Reference
< BaseCoordinateSystem
> & xCooSysToReplace
,
1472 const rtl::Reference
< BaseCoordinateSystem
> & xReplacement
)
1474 // update the coordinate-system container
1477 uno::Reference
< chart2::data::XLabeledDataSequence
> xCategories
= getCategories();
1479 // move chart types of xCooSysToReplace to xReplacement
1480 xReplacement
->setChartTypes( xCooSysToReplace
->getChartTypes());
1482 removeCoordinateSystem( xCooSysToReplace
);
1483 addCoordinateSystem( xReplacement
);
1485 if( xCategories
.is() )
1486 setCategories( xCategories
);
1488 catch( const uno::Exception
& )
1490 DBG_UNHANDLED_EXCEPTION("chart2");
1494 sal_Int32
Diagram::getDimension()
1497 sal_Int32 nResult
= -1;
1501 for( rtl::Reference
< BaseCoordinateSystem
> const & xCooSys
: getBaseCoordinateSystems() )
1505 nResult
= xCooSys
->getDimension();
1510 catch( const uno::Exception
& )
1512 DBG_UNHANDLED_EXCEPTION("chart2");
1518 void Diagram::setDimension( sal_Int32 nNewDimensionCount
)
1520 if( getDimension() == nNewDimensionCount
)
1525 bool rbFound
= false;
1526 bool rbAmbiguous
= true;
1527 StackMode eStackMode
= getStackMode( rbFound
, rbAmbiguous
);
1528 bool bIsSupportingOnlyDeepStackingFor3D
=false;
1530 //change all coordinate systems:
1531 auto aCoordSystems
= getBaseCoordinateSystems();
1532 for( rtl::Reference
<BaseCoordinateSystem
> const & xOldCooSys
: aCoordSystems
)
1534 rtl::Reference
< BaseCoordinateSystem
> xNewCooSys
;
1536 const std::vector
< rtl::Reference
< ChartType
> > aChartTypeList( xOldCooSys
->getChartTypes2() );
1537 for( rtl::Reference
< ChartType
> const & xChartType
: aChartTypeList
)
1539 bIsSupportingOnlyDeepStackingFor3D
= ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType
);
1540 if(!xNewCooSys
.is())
1542 xNewCooSys
= dynamic_cast<BaseCoordinateSystem
*>(xChartType
->createCoordinateSystem( nNewDimensionCount
).get());
1546 //@todo make sure that all following charttypes are also capable of the new dimension
1547 //otherwise separate them in a different group
1548 //BM: might be done in replaceCoordinateSystem()
1551 // replace the old coordinate system at all places where it was used
1552 replaceCoordinateSystem( xOldCooSys
, xNewCooSys
);
1555 //correct stack mode if necessary
1556 if( nNewDimensionCount
==3 && eStackMode
!= StackMode::ZStacked
&& bIsSupportingOnlyDeepStackingFor3D
)
1557 setStackMode( StackMode::ZStacked
);
1558 else if( nNewDimensionCount
==2 && eStackMode
== StackMode::ZStacked
)
1559 setStackMode( StackMode::NONE
);
1561 catch( const uno::Exception
& )
1563 DBG_UNHANDLED_EXCEPTION("chart2");
1567 void Diagram::setStackMode( StackMode eStackMode
)
1571 bool bValueFound
= false;
1572 bool bIsAmbiguous
= false;
1573 StackMode eOldStackMode
= getStackMode( bValueFound
, bIsAmbiguous
);
1575 if( eStackMode
== eOldStackMode
&& !bIsAmbiguous
)
1578 chart2::StackingDirection eNewDirection
= chart2::StackingDirection_NO_STACKING
;
1579 if( eStackMode
== StackMode::YStacked
|| eStackMode
== StackMode::YStackedPercent
)
1580 eNewDirection
= chart2::StackingDirection_Y_STACKING
;
1581 else if( eStackMode
== StackMode::ZStacked
)
1582 eNewDirection
= chart2::StackingDirection_Z_STACKING
;
1584 uno::Any
aNewDirection( eNewDirection
);
1586 bool bPercent
= false;
1587 if( eStackMode
== StackMode::YStackedPercent
)
1590 //iterate through all coordinate systems
1591 for( rtl::Reference
< BaseCoordinateSystem
> const & xCooSys
: getBaseCoordinateSystems() )
1593 //set correct percent stacking
1594 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(1);
1595 for(sal_Int32 nI
=0; nI
<=nMaximumScaleIndex
; ++nI
)
1597 rtl::Reference
< Axis
> xAxis
= xCooSys
->getAxisByDimension2( 1,nI
);
1600 chart2::ScaleData aScaleData
= xAxis
->getScaleData();
1601 if( (aScaleData
.AxisType
==chart2::AxisType::PERCENT
) != bPercent
)
1604 aScaleData
.AxisType
= chart2::AxisType::PERCENT
;
1606 aScaleData
.AxisType
= chart2::AxisType::REALNUMBER
;
1607 xAxis
->setScaleData( aScaleData
);
1611 //iterate through all chart types in the current coordinate system
1612 const std::vector
< rtl::Reference
< ChartType
> > & aChartTypeList( xCooSys
->getChartTypes2() );
1613 if (aChartTypeList
.empty())
1616 rtl::Reference
< ChartType
> xChartType( aChartTypeList
[0] );
1618 //iterate through all series in this chart type
1619 for( rtl::Reference
< DataSeries
> const & dataSeries
: xChartType
->getDataSeries2() )
1621 dataSeries
->setPropertyValue( u
"StackingDirection"_ustr
, aNewDirection
);
1625 catch( const uno::Exception
& )
1627 DBG_UNHANDLED_EXCEPTION("chart2");
1631 StackMode
Diagram::getStackMode( bool& rbFound
, bool& rbAmbiguous
)
1636 StackMode eGlobalStackMode
= StackMode::NONE
;
1638 //iterate through all coordinate systems
1639 for( rtl::Reference
< BaseCoordinateSystem
> const & xCooSys
: getBaseCoordinateSystems() )
1641 //iterate through all chart types in the current coordinate system
1642 std::vector
< rtl::Reference
< ChartType
> > aChartTypeList( xCooSys
->getChartTypes2() );
1643 for( std::size_t nT
= 0; nT
< aChartTypeList
.size(); ++nT
)
1645 const rtl::Reference
< ChartType
>& xChartType( aChartTypeList
[nT
] );
1647 StackMode eLocalStackMode
= DiagramHelper::getStackModeFromChartType(
1648 xChartType
, rbFound
, rbAmbiguous
, xCooSys
);
1650 if( rbFound
&& eLocalStackMode
!= eGlobalStackMode
&& nT
>0 )
1653 return eGlobalStackMode
;
1656 eGlobalStackMode
= eLocalStackMode
;
1660 return eGlobalStackMode
;
1663 void Diagram::setVertical( bool bVertical
/* = true */ )
1668 aValue
<<= bVertical
;
1669 for( rtl::Reference
< BaseCoordinateSystem
> const & xCooSys
: getBaseCoordinateSystems() )
1671 bool bChanged
= false;
1672 bool bOldSwap
= false;
1673 if( !(xCooSys
->getPropertyValue(u
"SwapXAndYAxis"_ustr
) >>= bOldSwap
)
1674 || bVertical
!= bOldSwap
)
1678 xCooSys
->setPropertyValue(u
"SwapXAndYAxis"_ustr
, aValue
);
1680 const sal_Int32 nDimensionCount
= xCooSys
->getDimension();
1681 sal_Int32 nDimIndex
= 0;
1682 for (nDimIndex
=0; nDimIndex
< nDimensionCount
; ++nDimIndex
)
1684 const sal_Int32 nMaximumScaleIndex
= xCooSys
->getMaximumAxisIndexByDimension(nDimIndex
);
1685 for (sal_Int32 nI
= 0; nI
<= nMaximumScaleIndex
; ++nI
)
1687 rtl::Reference
<Axis
> xAxis
= xCooSys
->getAxisByDimension2(nDimIndex
,nI
);
1691 //adapt title rotation only when axis swapping has changed
1695 Reference
< beans::XPropertySet
> xTitleProps( xAxis
->getTitleObject(), uno::UNO_QUERY
);
1696 if (!xTitleProps
.is())
1699 double fAngleDegree
= 0.0;
1700 xTitleProps
->getPropertyValue(u
"TextRotation"_ustr
) >>= fAngleDegree
;
1701 if (fAngleDegree
!= 0.0 &&
1702 !rtl::math::approxEqual(fAngleDegree
, 90.0))
1705 double fNewAngleDegree
= 0.0;
1706 if( !bVertical
&& nDimIndex
== 1 )
1707 fNewAngleDegree
= 90.0;
1708 else if( bVertical
&& nDimIndex
== 0 )
1709 fNewAngleDegree
= 90.0;
1711 xTitleProps
->setPropertyValue(u
"TextRotation"_ustr
, uno::Any(fNewAngleDegree
));
1716 catch( const uno::Exception
& )
1718 DBG_UNHANDLED_EXCEPTION("chart2");
1722 bool Diagram::getVertical( bool& rbFound
, bool& rbAmbiguous
)
1724 bool bValue
= false;
1726 rbAmbiguous
= false;
1728 for (rtl::Reference
<BaseCoordinateSystem
> const & coords
: getBaseCoordinateSystems())
1730 bool bCurrent
= false;
1731 if (coords
->getPropertyValue(u
"SwapXAndYAxis"_ustr
) >>= bCurrent
)
1738 else if (bCurrent
!= bValue
)
1740 // ambiguous -> choose always first found
1748 Diagram::tTemplateWithServiceName
1749 Diagram::getTemplate(
1750 const rtl::Reference
< ::chart::ChartTypeManager
> & xChartTypeManager
)
1752 tTemplateWithServiceName aResult
;
1754 if( !xChartTypeManager
)
1757 Sequence
< OUString
> aServiceNames( xChartTypeManager
->getAvailableServiceNames());
1758 const sal_Int32 nLength
= aServiceNames
.getLength();
1760 bool bTemplateFound
= false;
1762 for( sal_Int32 i
= 0; ! bTemplateFound
&& i
< nLength
; ++i
)
1766 rtl::Reference
< ::chart::ChartTypeTemplate
> xTempl
=
1767 xChartTypeManager
->createTemplate( aServiceNames
[ i
] );
1769 if (xTempl
.is() && xTempl
->matchesTemplate2(this, true))
1771 aResult
.xChartTypeTemplate
= std::move(xTempl
);
1772 aResult
.sServiceName
= aServiceNames
[ i
];
1773 bTemplateFound
= true;
1776 catch( const uno::Exception
& )
1778 DBG_UNHANDLED_EXCEPTION("chart2");
1785 std::vector
< rtl::Reference
< RegressionCurveModel
> >
1786 Diagram::getAllRegressionCurvesNotMeanValueLine()
1788 std::vector
< rtl::Reference
< RegressionCurveModel
> > aResult
;
1789 std::vector
< rtl::Reference
< DataSeries
> > aSeries( getDataSeries());
1790 for (auto const& elem
: aSeries
)
1792 for( rtl::Reference
< RegressionCurveModel
> const & curve
: elem
->getRegressionCurves2() )
1794 if( ! RegressionCurveHelper::isMeanValueLine( curve
))
1795 aResult
.push_back( curve
);
1802 double Diagram::getCameraDistance()
1804 double fCameraDistance
= FIXED_SIZE_FOR_3D_CHART_VOLUME
;
1808 drawing::CameraGeometry
aCG( ThreeDHelper::getDefaultCameraGeometry() );
1809 getFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY
) >>= aCG
;
1810 ::basegfx::B3DVector
aVRP( BaseGFXHelper::Position3DToB3DVector( aCG
.vrp
) );
1811 fCameraDistance
= aVRP
.getLength();
1813 ThreeDHelper::ensureCameraDistanceRange( fCameraDistance
);
1815 catch( const uno::Exception
& )
1817 DBG_UNHANDLED_EXCEPTION("chart2");
1819 return fCameraDistance
;
1822 void Diagram::setCameraDistance(double fCameraDistance
)
1826 if( fCameraDistance
<= 0 )
1827 fCameraDistance
= FIXED_SIZE_FOR_3D_CHART_VOLUME
;
1829 drawing::CameraGeometry
aCG( ThreeDHelper::getDefaultCameraGeometry() );
1830 getFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY
) >>= aCG
;
1831 ::basegfx::B3DVector
aVRP( BaseGFXHelper::Position3DToB3DVector( aCG
.vrp
) );
1832 if( ::basegfx::fTools::equalZero( aVRP
.getLength() ) )
1833 aVRP
= ::basegfx::B3DVector(0,0,1);
1834 aVRP
.setLength(fCameraDistance
);
1835 aCG
.vrp
= BaseGFXHelper::B3DVectorToPosition3D( aVRP
);
1837 setFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY
, uno::Any( aCG
));
1839 catch( const uno::Exception
& )
1841 DBG_UNHANDLED_EXCEPTION("chart2");
1845 static bool lcl_isRightAngledAxesSetAndSupported( Diagram
& rDiagram
)
1847 bool bRightAngledAxes
= false;
1848 rDiagram
.getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES
) >>= bRightAngledAxes
; // "RightAngledAxes"
1849 if(bRightAngledAxes
)
1851 if( ChartTypeHelper::isSupportingRightAngledAxes(
1852 rDiagram
.getChartTypeByIndex( 0 ) ) )
1860 void Diagram::getRotation( sal_Int32
& rnHorizontalAngleDegree
, sal_Int32
& rnVerticalAngleDegree
)
1862 double fXAngle
, fYAngle
, fZAngle
;
1863 getRotationAngle( fXAngle
, fYAngle
, fZAngle
);
1865 if( !lcl_isRightAngledAxesSetAndSupported( *this ) )
1867 ThreeDHelper::convertXYZAngleRadToElevationRotationDeg(
1868 rnHorizontalAngleDegree
, rnVerticalAngleDegree
, fXAngle
, fYAngle
, fZAngle
);
1869 rnVerticalAngleDegree
*=-1;
1873 rnHorizontalAngleDegree
= basegfx::fround(basegfx::rad2deg(fXAngle
));
1874 rnVerticalAngleDegree
= basegfx::fround(-1.0 * basegfx::rad2deg(fYAngle
));
1875 // nZRotation = basegfx::fround(-1.0 * basegfx::rad2deg(fZAngle));
1878 rnHorizontalAngleDegree
= NormAngle180(rnHorizontalAngleDegree
);
1879 rnVerticalAngleDegree
= NormAngle180(rnVerticalAngleDegree
);
1882 void Diagram::setRotation( sal_Int32 nHorizontalAngleDegree
, sal_Int32 nVerticalYAngleDegree
)
1884 //todo: x and y is not equal to horz and vert in case of RightAngledAxes==false
1885 double fXAngle
= basegfx::deg2rad(nHorizontalAngleDegree
);
1886 double fYAngle
= basegfx::deg2rad(-1 * nVerticalYAngleDegree
);
1887 double fZAngle
= 0.0;
1889 if( !lcl_isRightAngledAxesSetAndSupported( *this ) )
1890 ThreeDHelper::convertElevationRotationDegToXYZAngleRad(
1891 nHorizontalAngleDegree
, -1*nVerticalYAngleDegree
, fXAngle
, fYAngle
, fZAngle
);
1893 setRotationAngle( fXAngle
, fYAngle
, fZAngle
);
1896 static ::basegfx::B3DHomMatrix
lcl_getCameraMatrix( Diagram
& rDiagram
)
1898 drawing::HomogenMatrix aCameraMatrix
;
1900 drawing::CameraGeometry
aCG( ThreeDHelper::getDefaultCameraGeometry() );
1901 rDiagram
.getFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY
) >>= aCG
; // "D3DCameraGeometry"
1903 ::basegfx::B3DVector
aVPN( BaseGFXHelper::Direction3DToB3DVector( aCG
.vpn
) );
1904 ::basegfx::B3DVector
aVUP( BaseGFXHelper::Direction3DToB3DVector( aCG
.vup
) );
1906 //normalize vectors:
1910 ::basegfx::B3DVector aCross
= ::basegfx::cross( aVUP
, aVPN
);
1912 //first line is VUP x VPN
1913 aCameraMatrix
.Line1
.Column1
= aCross
[0];
1914 aCameraMatrix
.Line1
.Column2
= aCross
[1];
1915 aCameraMatrix
.Line1
.Column3
= aCross
[2];
1916 aCameraMatrix
.Line1
.Column4
= 0.0;
1918 //second line is VUP
1919 aCameraMatrix
.Line2
.Column1
= aVUP
[0];
1920 aCameraMatrix
.Line2
.Column2
= aVUP
[1];
1921 aCameraMatrix
.Line2
.Column3
= aVUP
[2];
1922 aCameraMatrix
.Line2
.Column4
= 0.0;
1925 aCameraMatrix
.Line3
.Column1
= aVPN
[0];
1926 aCameraMatrix
.Line3
.Column2
= aVPN
[1];
1927 aCameraMatrix
.Line3
.Column3
= aVPN
[2];
1928 aCameraMatrix
.Line3
.Column4
= 0.0;
1930 //fourth line is 0 0 0 1
1931 aCameraMatrix
.Line4
.Column1
= 0.0;
1932 aCameraMatrix
.Line4
.Column2
= 0.0;
1933 aCameraMatrix
.Line4
.Column3
= 0.0;
1934 aCameraMatrix
.Line4
.Column4
= 1.0;
1936 return BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aCameraMatrix
);
1939 static double lcl_shiftAngleToIntervalMinusPiToPi( double fAngleRad
)
1941 //valid range: ]-Pi,Pi]
1942 while( fAngleRad
<=-M_PI
)
1943 fAngleRad
+=(2*M_PI
);
1944 while( fAngleRad
>M_PI
)
1945 fAngleRad
-=(2*M_PI
);
1949 void Diagram::getRotationAngle( double& rfXAngleRad
, double& rfYAngleRad
, double& rfZAngleRad
)
1951 //takes the camera and the transformation matrix into account
1953 rfXAngleRad
= rfYAngleRad
= rfZAngleRad
= 0.0;
1955 //get camera rotation
1956 ::basegfx::B3DHomMatrix
aFixCameraRotationMatrix( lcl_getCameraMatrix( *this ) );
1957 BaseGFXHelper::ReduceToRotationMatrix( aFixCameraRotationMatrix
);
1959 //get scene rotation
1960 ::basegfx::B3DHomMatrix aSceneRotation
;
1962 drawing::HomogenMatrix aHomMatrix
;
1963 // "D3DTransformMatrix"
1964 if( getFastPropertyValue( PROP_SCENE_TRANSF_MATRIX
) >>= aHomMatrix
)
1966 aSceneRotation
= BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aHomMatrix
);
1967 BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation
);
1971 ::basegfx::B3DHomMatrix aResultRotation
= aFixCameraRotationMatrix
* aSceneRotation
;
1972 ::basegfx::B3DTuple
aRotation( BaseGFXHelper::GetRotationFromMatrix( aResultRotation
) );
1974 rfXAngleRad
= lcl_shiftAngleToIntervalMinusPiToPi(aRotation
.getX());
1975 rfYAngleRad
= lcl_shiftAngleToIntervalMinusPiToPi(aRotation
.getY());
1976 rfZAngleRad
= lcl_shiftAngleToIntervalMinusPiToPi(aRotation
.getZ());
1978 if(rfZAngleRad
<-M_PI_2
|| rfZAngleRad
>M_PI_2
)
1982 rfYAngleRad
=(M_PI
-rfYAngleRad
);
1984 rfXAngleRad
= lcl_shiftAngleToIntervalMinusPiToPi(rfXAngleRad
);
1985 rfYAngleRad
= lcl_shiftAngleToIntervalMinusPiToPi(rfYAngleRad
);
1986 rfZAngleRad
= lcl_shiftAngleToIntervalMinusPiToPi(rfZAngleRad
);
1990 static ::basegfx::B3DHomMatrix
lcl_getInverseRotationMatrix( Diagram
& rDiagram
)
1992 ::basegfx::B3DHomMatrix aInverseRotation
;
1993 double fXAngleRad
=0.0;
1994 double fYAngleRad
=0.0;
1995 double fZAngleRad
=0.0;
1996 rDiagram
.getRotationAngle( fXAngleRad
, fYAngleRad
, fZAngleRad
);
1997 aInverseRotation
.rotate( 0.0, 0.0, -fZAngleRad
);
1998 aInverseRotation
.rotate( 0.0, -fYAngleRad
, 0.0 );
1999 aInverseRotation
.rotate( -fXAngleRad
, 0.0, 0.0 );
2000 return aInverseRotation
;
2003 static void lcl_rotateLights( const ::basegfx::B3DHomMatrix
& rLightRotation
, Diagram
& rDiagram
)
2005 ::basegfx::B3DHomMatrix
aLightRotation( rLightRotation
);
2006 BaseGFXHelper::ReduceToRotationMatrix( aLightRotation
);
2008 // "D3DSceneLightDirection1","D3DSceneLightOn1",
2009 lcl_RotateLightSource( rDiagram
, PROP_SCENE_LIGHT_DIRECTION_1
, PROP_SCENE_LIGHT_ON_1
, aLightRotation
);
2010 lcl_RotateLightSource( rDiagram
, PROP_SCENE_LIGHT_DIRECTION_2
, PROP_SCENE_LIGHT_ON_2
, aLightRotation
);
2011 lcl_RotateLightSource( rDiagram
, PROP_SCENE_LIGHT_DIRECTION_3
, PROP_SCENE_LIGHT_ON_3
, aLightRotation
);
2012 lcl_RotateLightSource( rDiagram
, PROP_SCENE_LIGHT_DIRECTION_4
, PROP_SCENE_LIGHT_ON_4
, aLightRotation
);
2013 lcl_RotateLightSource( rDiagram
, PROP_SCENE_LIGHT_DIRECTION_5
, PROP_SCENE_LIGHT_ON_5
, aLightRotation
);
2014 lcl_RotateLightSource( rDiagram
, PROP_SCENE_LIGHT_DIRECTION_6
, PROP_SCENE_LIGHT_ON_6
, aLightRotation
);
2015 lcl_RotateLightSource( rDiagram
, PROP_SCENE_LIGHT_DIRECTION_7
, PROP_SCENE_LIGHT_ON_7
, aLightRotation
);
2016 lcl_RotateLightSource( rDiagram
, PROP_SCENE_LIGHT_DIRECTION_8
, PROP_SCENE_LIGHT_ON_8
, aLightRotation
);
2019 void Diagram::setRotationAngle(
2020 double fXAngleRad
, double fYAngleRad
, double fZAngleRad
)
2022 //the rotation of the camera is not touched but taken into account
2023 //the rotation difference is applied to the transformation matrix
2025 //the light sources will be adapted also
2029 //remind old rotation for adaptation of light directions
2030 ::basegfx::B3DHomMatrix
aInverseOldRotation( lcl_getInverseRotationMatrix( *this ) );
2032 ::basegfx::B3DHomMatrix aInverseCameraRotation
;
2034 ::basegfx::B3DTuple
aR( BaseGFXHelper::GetRotationFromMatrix(
2035 lcl_getCameraMatrix( *this ) ) );
2036 aInverseCameraRotation
.rotate( 0.0, 0.0, -aR
.getZ() );
2037 aInverseCameraRotation
.rotate( 0.0, -aR
.getY(), 0.0 );
2038 aInverseCameraRotation
.rotate( -aR
.getX(), 0.0, 0.0 );
2041 ::basegfx::B3DHomMatrix aCumulatedRotation
;
2042 aCumulatedRotation
.rotate( fXAngleRad
, fYAngleRad
, fZAngleRad
);
2044 //calculate new scene matrix
2045 ::basegfx::B3DHomMatrix aSceneRotation
= aInverseCameraRotation
*aCumulatedRotation
;
2046 BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation
);
2048 //set new rotation to transformation matrix ("D3DTransformMatrix")
2049 setFastPropertyValue(
2050 PROP_SCENE_TRANSF_MATRIX
, uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation
)));
2052 //rotate lights if RightAngledAxes are not set or not supported
2053 bool bRightAngledAxes
= false;
2054 getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES
) >>= bRightAngledAxes
;
2055 if(!bRightAngledAxes
|| !ChartTypeHelper::isSupportingRightAngledAxes(
2056 getChartTypeByIndex( 0 ) ) )
2058 ::basegfx::B3DHomMatrix aNewRotation
;
2059 aNewRotation
.rotate( fXAngleRad
, fYAngleRad
, fZAngleRad
);
2060 lcl_rotateLights( aNewRotation
*aInverseOldRotation
, *this );
2063 catch( const uno::Exception
& )
2065 DBG_UNHANDLED_EXCEPTION("chart2");
2069 static bool lcl_isEqual( const drawing::Direction3D
& rA
, const drawing::Direction3D
& rB
)
2071 return ::rtl::math::approxEqual(rA
.DirectionX
, rB
.DirectionX
)
2072 && ::rtl::math::approxEqual(rA
.DirectionY
, rB
.DirectionY
)
2073 && ::rtl::math::approxEqual(rA
.DirectionZ
, rB
.DirectionZ
);
2075 static bool lcl_isSimpleScheme( drawing::ShadeMode aShadeMode
2076 , sal_Int32 nRoundedEdges
2077 , sal_Int32 nObjectLines
2078 , const rtl::Reference
< Diagram
>& xDiagram
)
2080 if(aShadeMode
!=drawing::ShadeMode_FLAT
)
2082 if(nRoundedEdges
!=0)
2086 rtl::Reference
< ChartType
> xChartType( xDiagram
->getChartTypeByIndex( 0 ) );
2087 return ChartTypeHelper::noBordersForSimpleScheme( xChartType
);
2093 static bool lcl_isRealisticScheme( drawing::ShadeMode aShadeMode
2094 , sal_Int32 nRoundedEdges
2095 , sal_Int32 nObjectLines
)
2097 if(aShadeMode
!=drawing::ShadeMode_SMOOTH
)
2099 if(nRoundedEdges
!=5)
2105 static bool lcl_isLightScheme( Diagram
& rDiagram
, bool bRealistic
)
2108 // "D3DSceneLightOn2" / UNO_NAME_3D_SCENE_LIGHTON_2
2109 rDiagram
.getFastPropertyValue( PROP_SCENE_LIGHT_ON_2
) >>= bIsOn
;
2113 rtl::Reference
< ChartType
> xChartType( rDiagram
.getChartTypeByIndex( 0 ) );
2115 sal_Int32 nColor
= 0;
2116 // "D3DSceneLightColor2" / UNO_NAME_3D_SCENE_LIGHTCOLOR_2
2117 rDiagram
.getFastPropertyValue( PROP_SCENE_LIGHT_COLOR_2
) >>= nColor
;
2118 if( nColor
!= ::chart::ChartTypeHelper::getDefaultDirectLightColor( !bRealistic
, xChartType
) )
2121 sal_Int32 nAmbientColor
= 0;
2122 // "D3DSceneAmbientColor" / UNO_NAME_3D_SCENE_AMBIENTCOLOR
2123 rDiagram
.getFastPropertyValue( PROP_SCENE_AMBIENT_COLOR
) >>= nAmbientColor
;
2124 if( nAmbientColor
!= ::chart::ChartTypeHelper::getDefaultAmbientLightColor( !bRealistic
, xChartType
) )
2127 drawing::Direction3D
aDirection(0,0,0);
2128 // "D3DSceneLightDirection2" / UNO_NAME_3D_SCENE_LIGHTDIRECTION_2
2129 rDiagram
.getFastPropertyValue( PROP_SCENE_LIGHT_DIRECTION_2
) >>= aDirection
;
2131 drawing::Direction3D
aDefaultDirection( bRealistic
2132 ? ChartTypeHelper::getDefaultRealisticLightDirection(xChartType
)
2133 : ChartTypeHelper::getDefaultSimpleLightDirection(xChartType
) );
2135 //rotate default light direction when right angled axes are off but supported
2137 bool bRightAngledAxes
= false;
2138 rDiagram
.getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES
) >>= bRightAngledAxes
; // "RightAngledAxes"
2139 if(!bRightAngledAxes
)
2141 if( ChartTypeHelper::isSupportingRightAngledAxes(
2142 rDiagram
.getChartTypeByIndex( 0 ) ) )
2144 ::basegfx::B3DHomMatrix
aRotation( lcl_getCompleteRotationMatrix( rDiagram
) );
2145 BaseGFXHelper::ReduceToRotationMatrix( aRotation
);
2146 ::basegfx::B3DVector
aLightVector( BaseGFXHelper::Direction3DToB3DVector( aDefaultDirection
) );
2147 aLightVector
= aRotation
*aLightVector
;
2148 aDefaultDirection
= BaseGFXHelper::B3DVectorToDirection3D( aLightVector
);
2153 return lcl_isEqual( aDirection
, aDefaultDirection
);
2155 static bool lcl_isRealisticLightScheme( Diagram
& rDiagram
)
2157 return lcl_isLightScheme( rDiagram
, true /*bRealistic*/ );
2159 static bool lcl_isSimpleLightScheme( Diagram
& rDiagram
)
2161 return lcl_isLightScheme( rDiagram
, false /*bRealistic*/ );
2164 ThreeDLookScheme
Diagram::detectScheme()
2166 ThreeDLookScheme aScheme
= ThreeDLookScheme::ThreeDLookScheme_Unknown
;
2168 sal_Int32 nRoundedEdges
;
2169 sal_Int32 nObjectLines
;
2170 ThreeDHelper::getRoundedEdgesAndObjectLines( this, nRoundedEdges
, nObjectLines
);
2172 //get shade mode and light settings:
2173 drawing::ShadeMode
aShadeMode( drawing::ShadeMode_SMOOTH
);
2176 getFastPropertyValue( PROP_SCENE_SHADE_MODE
)>>= aShadeMode
; // "D3DSceneShadeMode"
2178 catch( const uno::Exception
& )
2180 DBG_UNHANDLED_EXCEPTION("chart2");
2183 if( lcl_isSimpleScheme( aShadeMode
, nRoundedEdges
, nObjectLines
, this ) )
2185 if( lcl_isSimpleLightScheme(*this) )
2186 aScheme
= ThreeDLookScheme::ThreeDLookScheme_Simple
;
2188 else if( lcl_isRealisticScheme( aShadeMode
, nRoundedEdges
, nObjectLines
) )
2190 if( lcl_isRealisticLightScheme(*this) )
2191 aScheme
= ThreeDLookScheme::ThreeDLookScheme_Realistic
;
2197 static void lcl_setRealisticScheme( drawing::ShadeMode
& rShadeMode
2198 , sal_Int32
& rnRoundedEdges
2199 , sal_Int32
& rnObjectLines
)
2201 rShadeMode
= drawing::ShadeMode_SMOOTH
;
2206 static void lcl_setSimpleScheme( drawing::ShadeMode
& rShadeMode
2207 , sal_Int32
& rnRoundedEdges
2208 , sal_Int32
& rnObjectLines
2209 , const rtl::Reference
< Diagram
>& xDiagram
)
2211 rShadeMode
= drawing::ShadeMode_FLAT
;
2214 rtl::Reference
< ChartType
> xChartType( xDiagram
->getChartTypeByIndex( 0 ) );
2215 rnObjectLines
= ChartTypeHelper::noBordersForSimpleScheme( xChartType
) ? 0 : 1;
2217 void Diagram::setScheme( ThreeDLookScheme aScheme
)
2219 if( aScheme
== ThreeDLookScheme::ThreeDLookScheme_Unknown
)
2222 drawing::ShadeMode aShadeMode
;
2223 sal_Int32 nRoundedEdges
;
2224 sal_Int32 nObjectLines
;
2226 if( aScheme
== ThreeDLookScheme::ThreeDLookScheme_Simple
)
2227 lcl_setSimpleScheme(aShadeMode
,nRoundedEdges
,nObjectLines
,this);
2229 lcl_setRealisticScheme(aShadeMode
,nRoundedEdges
,nObjectLines
);
2233 ThreeDHelper::setRoundedEdgesAndObjectLines( this, nRoundedEdges
, nObjectLines
);
2235 drawing::ShadeMode aOldShadeMode
;
2236 if( ! (getFastPropertyValue( PROP_SCENE_SHADE_MODE
)>>=aOldShadeMode
) ||
2237 aOldShadeMode
!= aShadeMode
)
2239 setFastPropertyValue( PROP_SCENE_SHADE_MODE
, uno::Any( aShadeMode
)); // "D3DSceneShadeMode"
2242 lcl_setLightsForScheme( *this, aScheme
);
2244 catch( const uno::Exception
& )
2246 DBG_UNHANDLED_EXCEPTION("chart2");
2251 void Diagram::setDefaultRotation( bool bPieOrDonut
)
2253 drawing::CameraGeometry
aCameraGeo( ThreeDHelper::getDefaultCameraGeometry( bPieOrDonut
) );
2254 // "D3DCameraGeometry"
2255 setFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY
, uno::Any( aCameraGeo
));
2257 ::basegfx::B3DHomMatrix aSceneRotation
;
2259 aSceneRotation
.rotate( -M_PI
/3.0, 0, 0 );
2260 // "D3DTransformMatrix"
2261 setFastPropertyValue( PROP_SCENE_TRANSF_MATRIX
,
2262 uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation
)));
2265 void Diagram::switchRightAngledAxes( bool bRightAngledAxes
)
2269 bool bOldRightAngledAxes
= false;
2270 getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES
) >>= bOldRightAngledAxes
; // "RightAngledAxes"
2271 if( bOldRightAngledAxes
!=bRightAngledAxes
)
2273 setFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES
, uno::Any( bRightAngledAxes
));
2274 if(bRightAngledAxes
)
2276 ::basegfx::B3DHomMatrix
aInverseRotation( lcl_getInverseRotationMatrix( *this ) );
2277 lcl_rotateLights( aInverseRotation
, *this );
2281 ::basegfx::B3DHomMatrix
aCompleteRotation( lcl_getCompleteRotationMatrix( *this ) );
2282 lcl_rotateLights( aCompleteRotation
, *this );
2286 catch( const uno::Exception
& )
2288 DBG_UNHANDLED_EXCEPTION("chart2");
2292 } // namespace chart
2294 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
2295 com_sun_star_comp_chart2_Diagram_get_implementation(css::uno::XComponentContext
*context
,
2296 css::uno::Sequence
<css::uno::Any
> const &)
2298 return cppu::acquire(new ::chart::Diagram(context
));
2301 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */