1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 
31 #include "BaseCoordinateSystem.hxx"
32 #include "macros.hxx"
33 #include "PropertyHelper.hxx"
34 #include "UserDefinedProperties.hxx"
35 #include "ContainerHelper.hxx"
36 #include "CloneHelper.hxx"
37 #include "Axis.hxx"
38 #include "AxisHelper.hxx"
39 #include <com/sun/star/chart2/AxisType.hpp>
40 
41 #include <algorithm>
42 
43 #if OSL_DEBUG_LEVEL > 1
44 #include <rtl/math.hxx>
45 #endif
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 
48 using namespace ::com::sun::star;
49 using ::com::sun::star::uno::Reference;
50 using ::com::sun::star::uno::Sequence;
51 using ::rtl::OUString;
52 using ::com::sun::star::beans::Property;
53 
54 namespace
55 {
56 enum
57 {
58     PROP_COORDINATESYSTEM_SWAPXANDYAXIS
59 };
60 
61 void lcl_AddPropertiesToVector(
62     ::std::vector< Property > & rOutProperties )
63 {
64     rOutProperties.push_back(
65         Property( C2U( "SwapXAndYAxis" ),
66                   PROP_COORDINATESYSTEM_SWAPXANDYAXIS,
67                   ::getBooleanCppuType(),
68                   beans::PropertyAttribute::BOUND
69                   | beans::PropertyAttribute::MAYBEVOID ));
70 }
71 
72 struct StaticCooSysDefaults_Initializer
73 {
74     ::chart::tPropertyValueMap* operator()()
75     {
76         static ::chart::tPropertyValueMap aStaticDefaults;
77         lcl_AddDefaultsToMap( aStaticDefaults );
78         return &aStaticDefaults;
79     }
80 private:
81     void lcl_AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap )
82     {
83         ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_COORDINATESYSTEM_SWAPXANDYAXIS, false );
84     }
85 };
86 
87 struct StaticCooSysDefaults : public rtl::StaticAggregate< ::chart::tPropertyValueMap, StaticCooSysDefaults_Initializer >
88 {
89 };
90 
91 struct StaticCooSysInfoHelper_Initializer
92 {
93     ::cppu::OPropertyArrayHelper* operator()()
94     {
95         static ::cppu::OPropertyArrayHelper aPropHelper( lcl_GetPropertySequence() );
96         return &aPropHelper;
97     }
98 
99 private:
100     Sequence< Property > lcl_GetPropertySequence()
101     {
102         ::std::vector< ::com::sun::star::beans::Property > aProperties;
103         lcl_AddPropertiesToVector( aProperties );
104         ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
105 
106         ::std::sort( aProperties.begin(), aProperties.end(),
107                      ::chart::PropertyNameLess() );
108 
109         return ::chart::ContainerHelper::ContainerToSequence( aProperties );
110     }
111 };
112 
113 struct StaticCooSysInfoHelper : public rtl::StaticAggregate< ::cppu::OPropertyArrayHelper, StaticCooSysInfoHelper_Initializer >
114 {
115 };
116 
117 struct StaticCooSysInfo_Initializer
118 {
119     uno::Reference< beans::XPropertySetInfo >* operator()()
120     {
121         static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
122             ::cppu::OPropertySetHelper::createPropertySetInfo(*StaticCooSysInfoHelper::get() ) );
123         return &xPropertySetInfo;
124     }
125 };
126 
127 struct StaticCooSysInfo : public rtl::StaticAggregate< uno::Reference< beans::XPropertySetInfo >, StaticCooSysInfo_Initializer >
128 {
129 };
130 
131 } // anonymous namespace
132 
133 namespace chart
134 {
135 
136 BaseCoordinateSystem::BaseCoordinateSystem(
137     const Reference< uno::XComponentContext > & xContext,
138     sal_Int32 nDimensionCount /* = 2 */,
139     sal_Bool bSwapXAndYAxis /* = sal_False */ ) :
140         ::property::OPropertySet( m_aMutex ),
141         m_xContext( xContext ),
142         m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()),
143         m_nDimensionCount( nDimensionCount )
144  {
145     m_aAllAxis.resize( m_nDimensionCount );
146     for( sal_Int32 nN=0; nN<m_nDimensionCount; nN++ )
147     {
148         m_aAllAxis[nN].resize( 1 );
149         Reference< chart2::XAxis > xAxis( new Axis(m_xContext) );
150         m_aAllAxis[nN][0] = xAxis;
151 
152         ModifyListenerHelper::addListenerToAllElements( m_aAllAxis[nN], m_xModifyEventForwarder );
153         chart2::ScaleData aScaleData( xAxis->getScaleData() );
154         if(nN==0)
155         {
156             aScaleData.AxisType = chart2::AxisType::CATEGORY;
157         }
158         else if( nN==1)
159         {
160             aScaleData.AxisType = chart2::AxisType::REALNUMBER;
161         }
162         else if( nN==2)
163         {
164             aScaleData.AxisType = chart2::AxisType::SERIES;
165         }
166         xAxis->setScaleData( aScaleData );
167     }
168 
169     m_aOrigin.realloc( m_nDimensionCount );
170     for( sal_Int32 i = 0; i < m_nDimensionCount; ++i )
171         m_aOrigin[ i ] = uno::makeAny( double( 0.0 ) );
172 
173     setFastPropertyValue_NoBroadcast( PROP_COORDINATESYSTEM_SWAPXANDYAXIS, uno::makeAny( sal_Bool( bSwapXAndYAxis )));
174 }
175 
176 // explicit
177 BaseCoordinateSystem::BaseCoordinateSystem(
178     const BaseCoordinateSystem & rSource ) :
179         impl::BaseCoordinateSystem_Base(),
180         MutexContainer(),
181         ::property::OPropertySet( rSource, m_aMutex ),
182     m_xContext( rSource.m_xContext ),
183     m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder()),
184     m_nDimensionCount( rSource.m_nDimensionCount ),
185     m_aOrigin( rSource.m_aOrigin )
186 {
187     m_aAllAxis.resize(rSource.m_aAllAxis.size());
188     tAxisVecVecType::size_type nN=0;
189     for( nN=0; nN<m_aAllAxis.size(); nN++ )
190         CloneHelper::CloneRefVector< Reference< chart2::XAxis > >( rSource.m_aAllAxis[nN], m_aAllAxis[nN] );
191     CloneHelper::CloneRefVector< Reference< chart2::XChartType > >( rSource.m_aChartTypes, m_aChartTypes );
192 
193     for( nN=0; nN<m_aAllAxis.size(); nN++ )
194         ModifyListenerHelper::addListenerToAllElements( m_aAllAxis[nN], m_xModifyEventForwarder );
195     ModifyListenerHelper::addListenerToAllElements( m_aChartTypes, m_xModifyEventForwarder );
196 }
197 
198 BaseCoordinateSystem::~BaseCoordinateSystem()
199 {
200     try
201     {
202         for( tAxisVecVecType::size_type nN=0; nN<m_aAllAxis.size(); nN++ )
203             ModifyListenerHelper::removeListenerFromAllElements( m_aAllAxis[nN], m_xModifyEventForwarder );
204         ModifyListenerHelper::removeListenerFromAllElements( m_aChartTypes, m_xModifyEventForwarder );
205     }
206     catch( const uno::Exception & ex )
207     {
208         ASSERT_EXCEPTION( ex );
209     }
210 }
211 
212 // ____ XCoordinateSystem ____
213 sal_Int32 SAL_CALL BaseCoordinateSystem::getDimension()
214     throw (uno::RuntimeException)
215 {
216     return m_nDimensionCount;
217 }
218 
219 void SAL_CALL BaseCoordinateSystem::setAxisByDimension(
220     sal_Int32 nDimensionIndex,
221     const Reference< chart2::XAxis >& xAxis,
222     sal_Int32 nIndex )
223     throw (lang::IndexOutOfBoundsException,
224            uno::RuntimeException)
225 {
226     if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
227         throw lang::IndexOutOfBoundsException();
228 
229     if( nIndex < 0 )
230         throw lang::IndexOutOfBoundsException();
231 
232     if( m_aAllAxis[ nDimensionIndex ].size() < static_cast< tAxisVecVecType::size_type >( nIndex+1 ))
233     {
234         m_aAllAxis[ nDimensionIndex ].resize( nIndex+1 );
235         m_aAllAxis[ nDimensionIndex ][nIndex] = 0;
236     }
237 
238     Reference< chart2::XAxis > xOldAxis( m_aAllAxis[ nDimensionIndex ][nIndex] );
239     if( xOldAxis.is())
240         ModifyListenerHelper::removeListener( xOldAxis, m_xModifyEventForwarder );
241     m_aAllAxis[ nDimensionIndex ][nIndex] = xAxis;
242     if( xAxis.is())
243         ModifyListenerHelper::addListener( xAxis, m_xModifyEventForwarder );
244     fireModifyEvent();
245 }
246 
247 Reference< chart2::XAxis > SAL_CALL BaseCoordinateSystem::getAxisByDimension(
248             sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
249     throw (lang::IndexOutOfBoundsException,
250            uno::RuntimeException)
251 {
252     if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
253         throw lang::IndexOutOfBoundsException();
254 
255     OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( getDimension()));
256 
257     if( nAxisIndex < 0 || nAxisIndex > this->getMaximumAxisIndexByDimension(nDimensionIndex) )
258         throw lang::IndexOutOfBoundsException();
259 
260     return m_aAllAxis[ nDimensionIndex ][nAxisIndex];
261 }
262 
263 sal_Int32 SAL_CALL BaseCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex )
264         throw (lang::IndexOutOfBoundsException,
265            uno::RuntimeException)
266 {
267     if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
268         throw lang::IndexOutOfBoundsException();
269 
270     OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( getDimension()));
271 
272     sal_Int32 nRet = m_aAllAxis[ nDimensionIndex ].size();
273     if(nRet)
274         nRet-=1;
275 
276     return nRet;
277 }
278 
279 // ____ XChartTypeContainer ____
280 void SAL_CALL BaseCoordinateSystem::addChartType( const Reference< chart2::XChartType >& aChartType )
281     throw (lang::IllegalArgumentException,
282            uno::RuntimeException)
283 {
284     if( ::std::find( m_aChartTypes.begin(), m_aChartTypes.end(), aChartType )
285         != m_aChartTypes.end())
286         throw lang::IllegalArgumentException();
287 
288     m_aChartTypes.push_back( aChartType );
289     ModifyListenerHelper::addListener( aChartType, m_xModifyEventForwarder );
290     fireModifyEvent();
291 }
292 
293 void SAL_CALL BaseCoordinateSystem::removeChartType( const Reference< chart2::XChartType >& aChartType )
294     throw (container::NoSuchElementException,
295            uno::RuntimeException)
296 {
297     ::std::vector< uno::Reference< chart2::XChartType > >::iterator
298           aIt( ::std::find( m_aChartTypes.begin(), m_aChartTypes.end(), aChartType ));
299     if( aIt == m_aChartTypes.end())
300         throw container::NoSuchElementException(
301             C2U( "The given chart type is no element of the container" ),
302             static_cast< uno::XWeak * >( this ));
303 
304     m_aChartTypes.erase( aIt );
305     ModifyListenerHelper::removeListener( aChartType, m_xModifyEventForwarder );
306     fireModifyEvent();
307 }
308 
309 Sequence< Reference< chart2::XChartType > > SAL_CALL BaseCoordinateSystem::getChartTypes()
310     throw (uno::RuntimeException)
311 {
312     return ContainerHelper::ContainerToSequence( m_aChartTypes );
313 }
314 
315 void SAL_CALL BaseCoordinateSystem::setChartTypes( const Sequence< Reference< chart2::XChartType > >& aChartTypes )
316     throw (lang::IllegalArgumentException,
317            uno::RuntimeException)
318 {
319     ModifyListenerHelper::removeListenerFromAllElements( m_aChartTypes, m_xModifyEventForwarder );
320     m_aChartTypes = ContainerHelper::SequenceToVector( aChartTypes );
321     ModifyListenerHelper::addListenerToAllElements( m_aChartTypes, m_xModifyEventForwarder );
322     fireModifyEvent();
323 }
324 
325 // ____ XModifyBroadcaster ____
326 void SAL_CALL BaseCoordinateSystem::addModifyListener( const Reference< util::XModifyListener >& aListener )
327     throw (uno::RuntimeException)
328 {
329     try
330     {
331         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
332         xBroadcaster->addModifyListener( aListener );
333     }
334     catch( const uno::Exception & ex )
335     {
336         ASSERT_EXCEPTION( ex );
337     }
338 }
339 
340 void SAL_CALL BaseCoordinateSystem::removeModifyListener( const Reference< util::XModifyListener >& aListener )
341     throw (uno::RuntimeException)
342 {
343     try
344     {
345         Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
346         xBroadcaster->removeModifyListener( aListener );
347     }
348     catch( const uno::Exception & ex )
349     {
350         ASSERT_EXCEPTION( ex );
351     }
352 }
353 
354 // ____ XModifyListener ____
355 void SAL_CALL BaseCoordinateSystem::modified( const lang::EventObject& aEvent )
356     throw (uno::RuntimeException)
357 {
358     m_xModifyEventForwarder->modified( aEvent );
359 }
360 
361 // ____ XEventListener (base of XModifyListener) ____
362 void SAL_CALL BaseCoordinateSystem::disposing( const lang::EventObject& /* Source */ )
363     throw (uno::RuntimeException)
364 {
365     // nothing
366 }
367 
368 // ____ OPropertySet ____
369 void BaseCoordinateSystem::firePropertyChangeEvent()
370 {
371     fireModifyEvent();
372 }
373 
374 void BaseCoordinateSystem::fireModifyEvent()
375 {
376     m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
377 }
378 
379 
380 // ____ OPropertySet ____
381 uno::Any BaseCoordinateSystem::GetDefaultValue( sal_Int32 nHandle ) const
382     throw(beans::UnknownPropertyException)
383 {
384     const tPropertyValueMap& rStaticDefaults = *StaticCooSysDefaults::get();
385     tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
386     if( aFound == rStaticDefaults.end() )
387         return uno::Any();
388     return (*aFound).second;
389 }
390 
391 // ____ OPropertySet ____
392 ::cppu::IPropertyArrayHelper & SAL_CALL BaseCoordinateSystem::getInfoHelper()
393 {
394     return *StaticCooSysInfoHelper::get();
395 }
396 
397 
398 // ____ XPropertySet ____
399 Reference< beans::XPropertySetInfo > SAL_CALL BaseCoordinateSystem::getPropertySetInfo()
400     throw (uno::RuntimeException)
401 {
402     return *StaticCooSysInfo::get();
403 }
404 
405 using impl::BaseCoordinateSystem_Base;
406 
407 IMPLEMENT_FORWARD_XINTERFACE2( BaseCoordinateSystem, BaseCoordinateSystem_Base, ::property::OPropertySet )
408 IMPLEMENT_FORWARD_XTYPEPROVIDER2( BaseCoordinateSystem, BaseCoordinateSystem_Base, ::property::OPropertySet )
409 
410 } //  namespace chart
411