xref: /AOO42X/main/chart2/source/model/main/Diagram.cxx (revision ba7cc37420601ac61d3c7be3d055fba1506f5fd7)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "Diagram.hxx"
27 #include "macros.hxx"
28 #include "PropertyHelper.hxx"
29 #include "Wall.hxx"
30 #include "UserDefinedProperties.hxx"
31 #include "ConfigColorScheme.hxx"
32 #include "DiagramHelper.hxx"
33 #include "ContainerHelper.hxx"
34 #include "ThreeDHelper.hxx"
35 #include "CloneHelper.hxx"
36 #include "AxisHelper.hxx"
37 #include "SceneProperties.hxx"
38 #include "DisposeHelper.hxx"
39 #include "BaseGFXHelper.hxx"
40 #include <basegfx/numeric/ftools.hxx>
41 #include <rtl/instance.hxx>
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/chart2/RelativePosition.hpp>
44 #include <com/sun/star/chart2/RelativeSize.hpp>
45 #include <com/sun/star/drawing/CameraGeometry.hpp>
46 
47 #include <com/sun/star/drawing/HomogenMatrix.hpp>
48 
49 #include <algorithm>
50 #include <iterator>
51 #include <functional>
52 
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::beans::PropertyAttribute;
55 
56 using ::rtl::OUString;
57 using ::com::sun::star::beans::Property;
58 using ::com::sun::star::uno::Sequence;
59 using ::com::sun::star::uno::Reference;
60 using ::com::sun::star::uno::Any;
61 using ::osl::MutexGuard;
62 
63 // ======================================================================
64 
65 namespace
66 {
67 
68 enum
69 {
70     PROP_DIAGRAM_REL_POS,
71     PROP_DIAGRAM_REL_SIZE,
72     PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS,
73     PROP_DIAGRAM_SORT_BY_X_VALUES,
74     PROP_DIAGRAM_CONNECT_BARS,
75     PROP_DIAGRAM_GROUP_BARS_PER_AXIS,
76     PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS,
77     PROP_DIAGRAM_STARTING_ANGLE,
78     PROP_DIAGRAM_RIGHT_ANGLED_AXES,
79     PROP_DIAGRAM_PERSPECTIVE,
80     PROP_DIAGRAM_ROTATION_HORIZONTAL,
81     PROP_DIAGRAM_ROTATION_VERTICAL,
82     PROP_DIAGRAM_MISSING_VALUE_TREATMENT
83 };
84 
85 void lcl_AddPropertiesToVector(
86     ::std::vector< Property > & rOutProperties )
87 {
88     rOutProperties.push_back(
89         Property( C2U( "RelativePosition" ),
90                   PROP_DIAGRAM_REL_POS,
91                   ::getCppuType( reinterpret_cast< const chart2::RelativePosition * >(0)),
92                   beans::PropertyAttribute::BOUND
93                   | beans::PropertyAttribute::MAYBEVOID ));
94 
95     rOutProperties.push_back(
96         Property( C2U( "RelativeSize" ),
97                   PROP_DIAGRAM_REL_SIZE,
98                   ::getCppuType( reinterpret_cast< const chart2::RelativeSize * >(0)),
99                   beans::PropertyAttribute::BOUND
100                   | beans::PropertyAttribute::MAYBEVOID ));
101 
102     rOutProperties.push_back(
103         Property( C2U( "PosSizeExcludeAxes" ),
104                   PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS,
105                   ::getBooleanCppuType(),
106                   beans::PropertyAttribute::BOUND
107                   | beans::PropertyAttribute::MAYBEDEFAULT ));
108 
109     rOutProperties.push_back(
110         Property( C2U( "SortByXValues" ),
111                   PROP_DIAGRAM_SORT_BY_X_VALUES,
112                   ::getBooleanCppuType(),
113                   beans::PropertyAttribute::BOUND
114                   | beans::PropertyAttribute::MAYBEDEFAULT ));
115 
116     rOutProperties.push_back(
117         Property( C2U("ConnectBars"),
118                   PROP_DIAGRAM_CONNECT_BARS,
119                   ::getBooleanCppuType(),
120                   beans::PropertyAttribute::BOUND
121                   | beans::PropertyAttribute::MAYBEDEFAULT ));
122 
123     rOutProperties.push_back(
124         Property( C2U("GroupBarsPerAxis"),
125                   PROP_DIAGRAM_GROUP_BARS_PER_AXIS,
126                   ::getBooleanCppuType(),
127                   beans::PropertyAttribute::BOUND
128                   | beans::PropertyAttribute::MAYBEDEFAULT ));
129 
130     rOutProperties.push_back(
131         Property( C2U("IncludeHiddenCells"),
132                   PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS,
133                   ::getBooleanCppuType(),
134                   beans::PropertyAttribute::BOUND
135                   | beans::PropertyAttribute::MAYBEDEFAULT ));
136 
137     rOutProperties.push_back(
138         Property( C2U( "StartingAngle" ),
139                   PROP_DIAGRAM_STARTING_ANGLE,
140                   ::getCppuType( reinterpret_cast< const sal_Int32 * >(0) ),
141                   beans::PropertyAttribute::BOUND
142                   | beans::PropertyAttribute::MAYBEDEFAULT ));
143 
144     rOutProperties.push_back(
145         Property( C2U("RightAngledAxes"),
146                   PROP_DIAGRAM_RIGHT_ANGLED_AXES,
147                   ::getBooleanCppuType(),
148                   beans::PropertyAttribute::BOUND
149                   | beans::PropertyAttribute::MAYBEDEFAULT ));
150 
151     rOutProperties.push_back(
152         Property( C2U("Perspective"),
153                   PROP_DIAGRAM_PERSPECTIVE,
154                   ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)),
155                   beans::PropertyAttribute::MAYBEVOID ));
156 
157     rOutProperties.push_back(
158         Property( C2U("RotationHorizontal"),
159                   PROP_DIAGRAM_ROTATION_HORIZONTAL,
160                   ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)),
161                   beans::PropertyAttribute::MAYBEVOID ));
162 
163     rOutProperties.push_back(
164         Property( C2U("RotationVertical"),
165                   PROP_DIAGRAM_ROTATION_VERTICAL,
166                   ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)),
167                   beans::PropertyAttribute::MAYBEVOID ));
168 
169     rOutProperties.push_back(
170         Property( C2U( "MissingValueTreatment" ),
171                   PROP_DIAGRAM_MISSING_VALUE_TREATMENT,
172                   ::getCppuType( reinterpret_cast< const sal_Int32 * >(0)),
173                   beans::PropertyAttribute::BOUND
174                   | beans::PropertyAttribute::MAYBEVOID ));
175 }
176 
177 struct StaticDiagramDefaults_Initializer
178 {
179     ::chart::tPropertyValueMap* operator()()
180     {
181         static ::chart::tPropertyValueMap aStaticDefaults;
182         lcl_AddDefaultsToMap( aStaticDefaults );
183         return &aStaticDefaults;
184     }
185 private:
186     void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap )
187     {
188         ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS, true );
189         ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_SORT_BY_X_VALUES, false );
190         ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_CONNECT_BARS, false );
191         ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_GROUP_BARS_PER_AXIS, true );
192         ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS, true );
193         ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DIAGRAM_RIGHT_ANGLED_AXES, false );
194         ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( rOutMap, PROP_DIAGRAM_STARTING_ANGLE, 90 );
195         ::chart::SceneProperties::AddDefaultsToMap( rOutMap );
196     }
197 };
198 
199 struct StaticDiagramDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticDiagramDefaults_Initializer >
200 {
201 };
202 
203 struct StaticDiagramInfoHelper_Initializer
204 {
205     ::cppu::OPropertyArrayHelper* operator()()
206     {
207         static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() );
208         return &aPropHelper;
209     }
210 
211 private:
212     Sequence< Property > lcl_GetPropertySequence()
213     {
214         ::std::vector< ::com::sun::star::beans::Property > aProperties;
215         lcl_AddPropertiesToVector( aProperties );
216         ::chart::SceneProperties::AddPropertiesToVector( aProperties );
217         ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
218 
219         ::std::sort( aProperties.begin(), aProperties.end(),
220                      ::chart::PropertyNameLess() );
221 
222         return ::chart::ContainerHelper::ContainerToSequence( aProperties );
223     }
224 };
225 
226 struct StaticDiagramInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticDiagramInfoHelper_Initializer >
227 {
228 };
229 
230 struct StaticDiagramInfo_Initializer
231 {
232     uno::Reference< beans::XPropertySetInfo >* operator()()
233     {
234         static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
235             ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticDiagramInfoHelper::get() ) );
236         return &xPropertySetInfo;
237     }
238 };
239 
240 struct StaticDiagramInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticDiagramInfo_Initializer >
241 {
242 };
243 
244 /// clones a UNO-sequence of UNO-References
245 typedef Reference< chart2::XCoordinateSystem > lcl_tCooSysRef;
246 typedef ::std::map< lcl_tCooSysRef, lcl_tCooSysRef >  lcl_tCooSysMapping;
247 typedef ::std::vector< lcl_tCooSysRef >               lcl_tCooSysVector;
248 
249 lcl_tCooSysMapping lcl_CloneCoordinateSystems(
250         const lcl_tCooSysVector & rSource,
251         lcl_tCooSysVector & rDestination )
252 {
253     lcl_tCooSysMapping aResult;
254 
255     for( lcl_tCooSysVector::const_iterator aIt( rSource.begin());
256          aIt != rSource.end(); ++aIt )
257     {
258         lcl_tCooSysRef xClone;
259         ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable >
260               xCloneable( *aIt, ::com::sun::star::uno::UNO_QUERY );
261         if( xCloneable.is())
262             xClone.set( xCloneable->createClone(), ::com::sun::star::uno::UNO_QUERY );
263 
264         if( xClone.is())
265         {
266             rDestination.push_back( xClone );
267             aResult.insert( lcl_tCooSysMapping::value_type( *aIt, xClone ));
268         }
269         else
270             rDestination.push_back( *aIt );
271     }
272 
273     return aResult;
274 }
275 
276 } // anonymous namespace
277 
278 // ======================================================================
279 
280 namespace chart
281 {
282 
283 Diagram::Diagram( uno::Reference< uno::XComponentContext > const & xContext ) :
284         ::property::OPropertySet( m_aMutex ),
285         m_xContext( xContext ),
286         m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
287 {
288     // Set camera position to a default position (that should be set hard, so
289     // that it will be exported.  The property default is a camera looking
290     // straight ono the scene).  These defaults have been acquired from the old
291     // chart implemetation.
292     setFastPropertyValue_NoBroadcast(
293         SceneProperties::PROP_SCENE_CAMERA_GEOMETRY, uno::makeAny(
294             ThreeDHelper::getDefaultCameraGeometry()));
295 }
296 
297 Diagram::Diagram( const Diagram & rOther ) :
298         MutexContainer(),
299         impl::Diagram_Base(),
300         ::property::OPropertySet( rOther, m_aMutex ),
301     m_xContext( rOther.m_xContext ),
302     m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
303 {
304     lcl_tCooSysMapping aCooSysMapping =
305         lcl_CloneCoordinateSystems( rOther.m_aCoordSystems, m_aCoordSystems );
306     ModifyListenerHelper::addListenerToAllElements( m_aCoordSystems, m_xModifyEventForwarder );
307 
308     m_xWall.set( CloneHelper::CreateRefClone< Reference< beans::XPropertySet > >()( rOther.m_xWall ));
309     m_xFloor.set( CloneHelper::CreateRefClone< Reference< beans::XPropertySet > >()( rOther.m_xFloor ));
310     m_xTitle.set( CloneHelper::CreateRefClone< Reference< chart2::XTitle > >()( rOther.m_xTitle ));
311     m_xLegend.set( CloneHelper::CreateRefClone< Reference< chart2::XLegend > >()( rOther.m_xLegend ));
312 
313     ModifyListenerHelper::addListener( m_xWall, m_xModifyEventForwarder );
314     ModifyListenerHelper::addListener( m_xFloor, m_xModifyEventForwarder );
315     ModifyListenerHelper::addListener( m_xTitle, m_xModifyEventForwarder );
316     ModifyListenerHelper::addListener( m_xLegend, m_xModifyEventForwarder );
317 }
318 
319 Diagram::~Diagram()
320 {
321     try
322     {
323         ModifyListenerHelper::removeListenerFromAllElements( m_aCoordSystems, m_xModifyEventForwarder );
324 
325         ModifyListenerHelper::removeListener( m_xWall, m_xModifyEventForwarder );
326         ModifyListenerHelper::removeListener( m_xFloor, m_xModifyEventForwarder );
327         ModifyListenerHelper::removeListener( m_xTitle, m_xModifyEventForwarder );
328         ModifyListenerHelper::removeListener( m_xLegend, m_xModifyEventForwarder );
329     }
330     catch( const uno::Exception & ex )
331     {
332         ASSERT_EXCEPTION( ex );
333     }
334 }
335 
336 // ____ XDiagram ____
337 uno::Reference< beans::XPropertySet > SAL_CALL Diagram::getWall()
338     throw (uno::RuntimeException)
339 {
340     uno::Reference< beans::XPropertySet > xRet;
341     bool bAddListener = false;
342     {
343         MutexGuard aGuard( GetMutex() );
344         if( !m_xWall.is() )
345         {
346             m_xWall.set( new Wall() );
347             bAddListener = true;
348         }
349         xRet =  m_xWall;
350     }
351     if(bAddListener)
352         ModifyListenerHelper::addListener( xRet, m_xModifyEventForwarder );
353     return xRet;
354 }
355 
356 uno::Reference< beans::XPropertySet > SAL_CALL Diagram::getFloor()
357     throw (uno::RuntimeException)
358 {
359     uno::Reference< beans::XPropertySet > xRet;
360     bool bAddListener = false;
361     {
362         MutexGuard aGuard( GetMutex() );
363         if( !m_xFloor.is() )
364         {
365             m_xFloor.set( new Wall() );
366             bAddListener = true;
367         }
368         xRet = m_xFloor;
369     }
370     if(bAddListener)
371         ModifyListenerHelper::addListener( xRet, m_xModifyEventForwarder );
372     return xRet;
373 }
374 
375 uno::Reference< chart2::XLegend > SAL_CALL Diagram::getLegend()
376     throw (uno::RuntimeException)
377 {
378     MutexGuard aGuard( GetMutex() );
379     return m_xLegend;
380 }
381 
382 void SAL_CALL Diagram::setLegend( const uno::Reference< chart2::XLegend >& xNewLegend )
383     throw (uno::RuntimeException)
384 {
385     Reference< chart2::XLegend > xOldLegend;
386     {
387         MutexGuard aGuard( GetMutex() );
388         if( m_xLegend == xNewLegend )
389             return;
390         xOldLegend = m_xLegend;
391         m_xLegend = xNewLegend;
392     }
393     if( xOldLegend.is())
394         ModifyListenerHelper::removeListener( xOldLegend, m_xModifyEventForwarder );
395     if( xNewLegend.is())
396         ModifyListenerHelper::addListener( xNewLegend, m_xModifyEventForwarder );
397     fireModifyEvent();
398 }
399 
400 Reference< chart2::XColorScheme > SAL_CALL Diagram::getDefaultColorScheme()
401     throw (uno::RuntimeException)
402 {
403     Reference< chart2::XColorScheme > xRet;
404     {
405         MutexGuard aGuard( GetMutex() );
406         xRet = m_xColorScheme;
407     }
408 
409     if( !xRet.is())
410     {
411         xRet.set( createConfigColorScheme( m_xContext ));
412         MutexGuard aGuard( GetMutex() );
413         m_xColorScheme = xRet;
414     }
415     return xRet;
416 }
417 
418 void SAL_CALL Diagram::setDefaultColorScheme( const Reference< chart2::XColorScheme >& xColorScheme )
419     throw (uno::RuntimeException)
420 {
421     {
422         MutexGuard aGuard( GetMutex() );
423         m_xColorScheme.set( xColorScheme );
424     }
425     fireModifyEvent();
426 }
427 
428 void SAL_CALL Diagram::setDiagramData(
429     const Reference< chart2::data::XDataSource >& xDataSource,
430     const Sequence< beans::PropertyValue >& aArguments )
431         throw (uno::RuntimeException)
432 {
433     uno::Reference< lang::XMultiServiceFactory > xChartTypeManager( m_xContext->getServiceManager()->createInstanceWithContext(
434             C2U( "com.sun.star.chart2.ChartTypeManager" ), m_xContext ), uno::UNO_QUERY );
435     DiagramHelper::tTemplateWithServiceName aTemplateAndService = DiagramHelper::getTemplateForDiagram( this, xChartTypeManager );
436     uno::Reference< chart2::XChartTypeTemplate > xTemplate( aTemplateAndService.first );
437     if( !xTemplate.is() )
438         xTemplate.set( xChartTypeManager->createInstance( C2U("com.sun.star.chart2.template.Column") ), uno::UNO_QUERY );
439     if(!xTemplate.is())
440         return;
441     xTemplate->changeDiagramData( this, xDataSource, aArguments );
442 }
443 
444 // ____ XTitled ____
445 uno::Reference< chart2::XTitle > SAL_CALL Diagram::getTitleObject()
446     throw (uno::RuntimeException)
447 {
448     MutexGuard aGuard( GetMutex() );
449     return m_xTitle;
450 }
451 
452 void SAL_CALL Diagram::setTitleObject( const uno::Reference< chart2::XTitle >& xNewTitle )
453     throw (uno::RuntimeException)
454 {
455     Reference< chart2::XTitle > xOldTitle;
456     {
457         MutexGuard aGuard( GetMutex() );
458         if( m_xTitle == xNewTitle )
459             return;
460         xOldTitle = m_xTitle;
461         m_xTitle = xNewTitle;
462     }
463     if( xOldTitle.is())
464         ModifyListenerHelper::removeListener( xOldTitle, m_xModifyEventForwarder );
465     if( xNewTitle.is())
466         ModifyListenerHelper::addListener( xNewTitle, m_xModifyEventForwarder );
467     fireModifyEvent();
468 }
469 
470 // ____ X3DDefaultSetter ____
471 void SAL_CALL Diagram::set3DSettingsToDefault()
472     throw (uno::RuntimeException)
473 {
474     ThreeDHelper::set3DSettingsToDefault( this );
475 }
476 
477 void SAL_CALL Diagram::setDefaultRotation()
478     throw (uno::RuntimeException)
479 {
480     ThreeDHelper::setDefaultRotation( this );
481 }
482 
483 void SAL_CALL Diagram::setDefaultIllumination()
484     throw (uno::RuntimeException)
485 {
486     ThreeDHelper::setDefaultIllumination( this );
487 }
488 
489 // ____ XCoordinateSystemContainer ____
490 void SAL_CALL Diagram::addCoordinateSystem(
491     const uno::Reference< chart2::XCoordinateSystem >& aCoordSys )
492     throw (lang::IllegalArgumentException,
493            uno::RuntimeException)
494 {
495     {
496         MutexGuard aGuard( GetMutex() );
497         if( ::std::find( m_aCoordSystems.begin(), m_aCoordSystems.end(), aCoordSys )
498             != m_aCoordSystems.end())
499             throw lang::IllegalArgumentException();
500 
501         if( m_aCoordSystems.size()>=1 )
502         {
503             OSL_ENSURE( false, "more than one coordinatesystem is not supported yet by the fileformat" );
504             return;
505         }
506         m_aCoordSystems.push_back( aCoordSys );
507     }
508     ModifyListenerHelper::addListener( aCoordSys, m_xModifyEventForwarder );
509     fireModifyEvent();
510 }
511 
512 void SAL_CALL Diagram::removeCoordinateSystem(
513     const uno::Reference< chart2::XCoordinateSystem >& aCoordSys )
514     throw (container::NoSuchElementException,
515            uno::RuntimeException)
516 {
517     {
518         MutexGuard aGuard( GetMutex() );
519         ::std::vector< uno::Reference< chart2::XCoordinateSystem > >::iterator
520               aIt( ::std::find( m_aCoordSystems.begin(), m_aCoordSystems.end(), aCoordSys ));
521         if( aIt == m_aCoordSystems.end())
522             throw container::NoSuchElementException(
523                 C2U( "The given coordinate-system is no element of the container" ),
524                 static_cast< uno::XWeak * >( this ));
525         m_aCoordSystems.erase( aIt );
526     }
527     ModifyListenerHelper::removeListener( aCoordSys, m_xModifyEventForwarder );
528     fireModifyEvent();
529 }
530 
531 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > SAL_CALL Diagram::getCoordinateSystems()
532     throw (uno::RuntimeException)
533 {
534     MutexGuard aGuard( GetMutex() );
535     return ContainerHelper::ContainerToSequence( m_aCoordSystems );
536 }
537 
538 void SAL_CALL Diagram::setCoordinateSystems(
539     const Sequence< Reference< chart2::XCoordinateSystem > >& aCoordinateSystems )
540     throw (lang::IllegalArgumentException,
541            uno::RuntimeException)
542 {
543     tCoordinateSystemContainerType aNew;
544     tCoordinateSystemContainerType aOld;
545     if( aCoordinateSystems.getLength()>0 )
546     {
547         OSL_ENSURE( aCoordinateSystems.getLength()<=1, "more than one coordinatesystem is not supported yet by the fileformat" );
548         aNew.push_back( aCoordinateSystems[0] );
549     }
550     {
551         MutexGuard aGuard( GetMutex() );
552         std::swap( aOld, m_aCoordSystems );
553         m_aCoordSystems = aNew;
554     }
555     ModifyListenerHelper::removeListenerFromAllElements( aOld, m_xModifyEventForwarder );
556     ModifyListenerHelper::addListenerToAllElements( aNew, m_xModifyEventForwarder );
557     fireModifyEvent();
558 }
559 
560 // ____ XCloneable ____
561 Reference< util::XCloneable > SAL_CALL Diagram::createClone()
562     throw (uno::RuntimeException)
563 {
564     MutexGuard aGuard( GetMutex() );
565     return Reference< util::XCloneable >( new Diagram( *this ));
566 }
567 
568 // ____ XModifyBroadcaster ____
569 void SAL_CALL Diagram::addModifyListener( const Reference< util::XModifyListener >& aListener )
570     throw (uno::RuntimeException)
571 {
572     try
573     {
574         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
575         xBroadcaster->addModifyListener( aListener );
576     }
577     catch( const uno::Exception & ex )
578     {
579         ASSERT_EXCEPTION( ex );
580     }
581 }
582 
583 void SAL_CALL Diagram::removeModifyListener( const Reference< util::XModifyListener >& aListener )
584     throw (uno::RuntimeException)
585 {
586     try
587     {
588         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
589         xBroadcaster->removeModifyListener( aListener );
590     }
591     catch( const uno::Exception & ex )
592     {
593         ASSERT_EXCEPTION( ex );
594     }
595 }
596 
597 // ____ XModifyListener ____
598 void SAL_CALL Diagram::modified( const lang::EventObject& aEvent )
599     throw (uno::RuntimeException)
600 {
601     m_xModifyEventForwarder->modified( aEvent );
602 }
603 
604 // ____ XEventListener (base of XModifyListener) ____
605 void SAL_CALL Diagram::disposing( const lang::EventObject& /* Source */ )
606     throw (uno::RuntimeException)
607 {
608     // nothing
609 }
610 
611 // ____ OPropertySet ____
612 void Diagram::firePropertyChangeEvent()
613 {
614     fireModifyEvent();
615 }
616 
617 void Diagram::fireModifyEvent()
618 {
619     m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
620 }
621 
622 // ============================================================
623 
624 Sequence< OUString > Diagram::getSupportedServiceNames_Static()
625 {
626     Sequence< OUString > aServices( 3 );
627 
628     aServices[ 0 ] = C2U( "com.sun.star.chart2.Diagram" );
629     aServices[ 1 ] = C2U( "com.sun.star.layout.LayoutElement" );
630     aServices[ 2 ] = C2U( "com.sun.star.beans.PropertySet" );
631     return aServices;
632 }
633 
634 // ____ OPropertySet ____
635 uno::Any Diagram::GetDefaultValue( sal_Int32 nHandle ) const
636     throw(beans::UnknownPropertyException)
637 {
638     const tPropertyValueMap& rStaticDefaults = *StaticDiagramDefaults::get();
639     tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
640     if( aFound == rStaticDefaults.end() )
641         return uno::Any();
642     return (*aFound).second;
643 }
644 
645 // ____ OPropertySet ____
646 ::cppu::IPropertyArrayHelper & SAL_CALL Diagram::getInfoHelper()
647 {
648     return *StaticDiagramInfoHelper::get();
649 }
650 
651 // ____ XPropertySet ____
652 uno::Reference< beans::XPropertySetInfo > SAL_CALL Diagram::getPropertySetInfo()
653     throw (uno::RuntimeException)
654 {
655     return *StaticDiagramInfo::get();
656 }
657 
658 // ____ XFastPropertySet ____
659 void SAL_CALL Diagram::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
660     throw(beans::UnknownPropertyException,
661           beans::PropertyVetoException,
662           lang::IllegalArgumentException,
663           lang::WrappedTargetException, uno::RuntimeException)
664 {
665     //special treatment for some 3D properties
666     if( PROP_DIAGRAM_PERSPECTIVE == nHandle )
667     {
668         sal_Int32 fPerspective = 20;
669         if( rValue >>=fPerspective )
670             ThreeDHelper::setCameraDistance( this, ThreeDHelper::PerspectiveToCameraDistance( fPerspective ) );
671     }
672     else if( PROP_DIAGRAM_ROTATION_HORIZONTAL == nHandle
673         || PROP_DIAGRAM_ROTATION_VERTICAL == nHandle )
674     {
675         sal_Int32 nNewAngleDegree = 0;
676         if( rValue >>=nNewAngleDegree )
677         {
678             sal_Int32 nHorizontal, nVertical;
679             ThreeDHelper::getRotationFromDiagram( const_cast< Diagram* >( this ), nHorizontal, nVertical );
680             if( PROP_DIAGRAM_ROTATION_HORIZONTAL == nHandle )
681                 nHorizontal = nNewAngleDegree;
682             else
683                 nVertical = nNewAngleDegree;
684             ThreeDHelper::setRotationToDiagram( this, nHorizontal, nVertical );
685         }
686     }
687     else
688         ::property::OPropertySet::setFastPropertyValue( nHandle, rValue );
689 }
690 
691 void SAL_CALL Diagram::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
692 {
693     //special treatment for some 3D properties
694     if( nHandle == PROP_DIAGRAM_PERSPECTIVE )
695     {
696         sal_Int32 nPerspective = ::basegfx::fround( ThreeDHelper::CameraDistanceToPerspective(
697             ThreeDHelper::getCameraDistance( const_cast< Diagram* >( this ) ) ) );
698         rValue = uno::makeAny(nPerspective);
699     }
700     else if( PROP_DIAGRAM_ROTATION_HORIZONTAL == nHandle
701         || PROP_DIAGRAM_ROTATION_VERTICAL == nHandle )
702     {
703         sal_Int32 nHorizontal, nVertical;
704         ThreeDHelper::getRotationFromDiagram( const_cast< Diagram* >( this ), nHorizontal, nVertical );
705         sal_Int32 nAngleDegree = 0;
706         if( PROP_DIAGRAM_ROTATION_HORIZONTAL == nHandle )
707             nAngleDegree = nHorizontal;
708         else
709             nAngleDegree = nVertical;
710         rValue = uno::makeAny(nAngleDegree);
711     }
712     else
713         ::property::OPropertySet::getFastPropertyValue( rValue,nHandle );
714 }
715 
716 // ================================================================================
717 
718 using impl::Diagram_Base;
719 
720 IMPLEMENT_FORWARD_XINTERFACE2( Diagram, Diagram_Base, ::property::OPropertySet )
721 IMPLEMENT_FORWARD_XTYPEPROVIDER2( Diagram, Diagram_Base, ::property::OPropertySet )
722 
723 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
724 APPHELPER_XSERVICEINFO_IMPL( Diagram,
725                              C2U( "com.sun.star.comp.chart2.Diagram" ));
726 
727 } //  namespace chart
728