1 /*************************************************************************
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * Copyright 2000, 2010 Oracle and/or its affiliates.
5  *
6  * OpenOffice.org - a multi-platform office productivity suite
7  *
8  * This file is part of OpenOffice.org.
9  *
10  * OpenOffice.org is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License version 3
12  * only, as published by the Free Software Foundation.
13  *
14  * OpenOffice.org is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License version 3 for more details
18  * (a copy is included in the LICENSE file that accompanied this code).
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * version 3 along with OpenOffice.org.  If not, see
22  * <http://www.openoffice.org/license.html>
23  * for a copy of the LGPLv3 License.
24  *
25  ************************************************************************/
26 
27 #include "precompiled_toolkit.hxx"
28 
29 #include "toolkit/controls/animatedimages.hxx"
30 #include "toolkit/helper/servicenames.hxx"
31 #include "toolkit/helper/property.hxx"
32 #include "toolkit/helper/unopropertyarrayhelper.hxx"
33 
34 /** === begin UNO includes === **/
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <com/sun/star/awt/VisualEffect.hpp>
37 #include <com/sun/star/awt/ImageScaleMode.hpp>
38 #include <com/sun/star/util/XModifyListener.hpp>
39 /** === end UNO includes === **/
40 
41 //......................................................................................................................
42 namespace toolkit
43 {
44 //......................................................................................................................
45 
46     /** === begin UNO using === **/
47     using ::com::sun::star::uno::Reference;
48     using ::com::sun::star::uno::XInterface;
49     using ::com::sun::star::uno::UNO_QUERY;
50     using ::com::sun::star::uno::UNO_QUERY_THROW;
51     using ::com::sun::star::uno::UNO_SET_THROW;
52     using ::com::sun::star::uno::Exception;
53     using ::com::sun::star::uno::RuntimeException;
54     using ::com::sun::star::uno::Any;
55     using ::com::sun::star::uno::makeAny;
56     using ::com::sun::star::uno::Sequence;
57     using ::com::sun::star::uno::Type;
58     using ::com::sun::star::container::ContainerEvent;
59     using ::com::sun::star::container::XContainerListener;
60     using ::com::sun::star::beans::XPropertySetInfo;
61     using ::com::sun::star::lang::DisposedException;
62     using ::com::sun::star::lang::IndexOutOfBoundsException;
63     using ::com::sun::star::lang::EventObject;
64     using ::com::sun::star::awt::XControlModel;
65     using ::com::sun::star::awt::XAnimatedImages;
66     using ::com::sun::star::lang::IllegalArgumentException;
67     using ::com::sun::star::awt::XWindowPeer;
68     using ::com::sun::star::util::XModifyListener;
69     using ::com::sun::star::awt::XToolkit;
70     using ::com::sun::star::lang::XMultiServiceFactory;
71     /** === end UNO using === **/
72     namespace VisualEffect = ::com::sun::star::awt::VisualEffect;
73     namespace ImageScaleMode = ::com::sun::star::awt::ImageScaleMode;
74 
75     //==================================================================================================================
76     //= AnimatedImagesControl
77     //==================================================================================================================
78     //------------------------------------------------------------------------------------------------------------------
79     AnimatedImagesControl::AnimatedImagesControl( Reference< XMultiServiceFactory > const & i_factory )
80         :AnimatedImagesControl_Base( i_factory )
81     {
82     }
83 
84     //------------------------------------------------------------------------------------------------------------------
85     ::rtl::OUString AnimatedImagesControl::GetComponentServiceName()
86     {
87         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AnimatedImages" ) );
88     }
89 
90     //------------------------------------------------------------------------------------------------------------------
91     void SAL_CALL AnimatedImagesControl::startAnimation(  ) throw (RuntimeException)
92     {
93         Reference< XAnimation > xAnimation( getPeer(), UNO_QUERY );
94         if ( xAnimation.is() )
95             xAnimation->startAnimation();
96     }
97 
98     //------------------------------------------------------------------------------------------------------------------
99     void SAL_CALL AnimatedImagesControl::stopAnimation(  ) throw (RuntimeException)
100     {
101         Reference< XAnimation > xAnimation( getPeer(), UNO_QUERY );
102         if ( xAnimation.is() )
103             xAnimation->stopAnimation();
104     }
105 
106     //------------------------------------------------------------------------------------------------------------------
107     ::sal_Bool SAL_CALL AnimatedImagesControl::isAnimationRunning(  ) throw (RuntimeException)
108     {
109         Reference< XAnimation > xAnimation( getPeer(), UNO_QUERY );
110         if ( xAnimation.is() )
111             return xAnimation->isAnimationRunning();
112         return sal_False;
113     }
114 
115     //------------------------------------------------------------------------------------------------------------------
116     ::rtl::OUString SAL_CALL AnimatedImagesControl::getImplementationName(  ) throw(RuntimeException)
117     {
118         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.toolkit.AnimatedImagesControl" ) );
119     }
120 
121     //------------------------------------------------------------------------------------------------------------------
122     Sequence< ::rtl::OUString > SAL_CALL AnimatedImagesControl::getSupportedServiceNames() throw(RuntimeException)
123     {
124         Sequence< ::rtl::OUString > aServices( AnimatedImagesControl_Base::getSupportedServiceNames() );
125         aServices.realloc( aServices.getLength() + 1 );
126         aServices[ aServices.getLength() - 1 ] = ::rtl::OUString::createFromAscii( szServiceName_AnimatedImagesControl );
127         return aServices;
128     }
129 
130     //------------------------------------------------------------------------------------------------------------------
131     namespace
132     {
133         void lcl_updatePeer( Reference< XWindowPeer > const& i_peer, Reference< XControlModel > const& i_model )
134         {
135             const Reference< XModifyListener > xPeerModify( i_peer, UNO_QUERY );
136             if ( xPeerModify.is() )
137             {
138                 EventObject aEvent;
139                 aEvent.Source = i_model;
140                 xPeerModify->modified( aEvent );
141             }
142         }
143     }
144 
145     //------------------------------------------------------------------------------------------------------------------
146     sal_Bool SAL_CALL AnimatedImagesControl::setModel( const Reference< XControlModel >& i_rModel ) throw ( RuntimeException )
147     {
148         const Reference< XAnimatedImages > xOldContainer( getModel(), UNO_QUERY );
149         const Reference< XAnimatedImages > xNewContainer( i_rModel, UNO_QUERY );
150 
151         if ( !AnimatedImagesControl_Base::setModel( i_rModel ) )
152             return sal_False;
153 
154         if ( xOldContainer.is() )
155             xOldContainer->removeContainerListener( this );
156 
157         if ( xNewContainer.is() )
158             xNewContainer->addContainerListener( this );
159 
160         lcl_updatePeer( getPeer(), getModel() );
161 
162         return sal_True;
163     }
164 
165     //------------------------------------------------------------------------------------------------------------------
166     void SAL_CALL AnimatedImagesControl::createPeer( const Reference< XToolkit >& i_toolkit, const Reference< XWindowPeer >& i_parentPeer ) throw(RuntimeException)
167     {
168         AnimatedImagesControl_Base::createPeer( i_toolkit, i_parentPeer );
169 
170         lcl_updatePeer( getPeer(), getModel() );
171     }
172 
173     //------------------------------------------------------------------------------------------------------------------
174     void SAL_CALL AnimatedImagesControl::elementInserted( const ContainerEvent& i_event ) throw (RuntimeException)
175     {
176         const Reference< XContainerListener > xPeerListener( getPeer(), UNO_QUERY );
177         if ( xPeerListener.is() )
178             xPeerListener->elementInserted( i_event );
179     }
180 
181     //------------------------------------------------------------------------------------------------------------------
182     void SAL_CALL AnimatedImagesControl::elementRemoved( const ContainerEvent& i_event ) throw (RuntimeException)
183     {
184         const Reference< XContainerListener > xPeerListener( getPeer(), UNO_QUERY );
185         if ( xPeerListener.is() )
186             xPeerListener->elementRemoved( i_event );
187     }
188 
189     //------------------------------------------------------------------------------------------------------------------
190     void SAL_CALL AnimatedImagesControl::elementReplaced( const ContainerEvent& i_event ) throw (RuntimeException)
191     {
192         const Reference< XContainerListener > xPeerListener( getPeer(), UNO_QUERY );
193         if ( xPeerListener.is() )
194             xPeerListener->elementReplaced( i_event );
195     }
196 
197     //------------------------------------------------------------------------------------------------------------------
198     void SAL_CALL AnimatedImagesControl::disposing( const EventObject& i_event ) throw (RuntimeException)
199     {
200         UnoControlBase::disposing( i_event );
201     }
202 
203     //==================================================================================================================
204     //= AnimatedImagesControlModel_Data
205     //==================================================================================================================
206     struct AnimatedImagesControlModel_Data
207     {
208         ::std::vector< Sequence< ::rtl::OUString > >    aImageSets;
209     };
210 
211     namespace
212     {
213         void lcl_checkIndex( const AnimatedImagesControlModel_Data& i_data, const sal_Int32 i_index, const Reference< XInterface >& i_context,
214             const bool i_forInsert = false )
215         {
216             if ( ( i_index < 0 ) || ( size_t( i_index ) > i_data.aImageSets.size() + ( i_forInsert ? 1 : 0 ) ) )
217                 throw IndexOutOfBoundsException( ::rtl::OUString(), i_context );
218         }
219 
220         void lcl_notify( ::osl::ClearableMutexGuard& i_guard, ::cppu::OBroadcastHelper& i_broadcaseHelper,
221             void ( SAL_CALL XContainerListener::*i_notificationMethod )( const ContainerEvent& ),
222             const sal_Int32 i_accessor, const Sequence< ::rtl::OUString >& i_imageURLs, const Reference< XInterface >& i_context )
223         {
224             ::cppu::OInterfaceContainerHelper* pContainerListeners = i_broadcaseHelper.getContainer( XContainerListener::static_type() );
225             if ( pContainerListeners == NULL )
226                 return;
227 
228             ContainerEvent aEvent;
229             aEvent.Source = i_context;
230             aEvent.Accessor <<= i_accessor;
231             aEvent.Element <<= i_imageURLs;
232 
233             i_guard.clear();
234             pContainerListeners->notifyEach( i_notificationMethod, aEvent );
235         }
236     }
237 
238     //==================================================================================================================
239     //= AnimatedImagesControlModel
240     //==================================================================================================================
241     //------------------------------------------------------------------------------------------------------------------
242     AnimatedImagesControlModel::AnimatedImagesControlModel( Reference< XMultiServiceFactory > const & i_factory )
243         :AnimatedImagesControlModel_Base( i_factory )
244         ,m_pData( new AnimatedImagesControlModel_Data )
245     {
246         ImplRegisterProperty( BASEPROPERTY_AUTO_REPEAT );
247 	    ImplRegisterProperty( BASEPROPERTY_BORDER );
248 	    ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
249         ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
250         ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
251 	    ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
252 	    ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
253 	    ImplRegisterProperty( BASEPROPERTY_HELPURL );
254 	    ImplRegisterProperty( BASEPROPERTY_IMAGE_SCALE_MODE );
255         ImplRegisterProperty( BASEPROPERTY_STEP_TIME );
256     }
257 
258     //------------------------------------------------------------------------------------------------------------------
259     AnimatedImagesControlModel::AnimatedImagesControlModel( const AnimatedImagesControlModel& i_copySource )
260         :AnimatedImagesControlModel_Base( i_copySource )
261         ,m_pData( new AnimatedImagesControlModel_Data( *i_copySource.m_pData ) )
262     {
263     }
264 
265     //------------------------------------------------------------------------------------------------------------------
266     AnimatedImagesControlModel::~AnimatedImagesControlModel()
267     {
268     }
269 
270     //------------------------------------------------------------------------------------------------------------------
271     UnoControlModel* AnimatedImagesControlModel::Clone() const
272     {
273         return new AnimatedImagesControlModel( *this );
274     }
275 
276     //------------------------------------------------------------------------------------------------------------------
277     Reference< XPropertySetInfo > SAL_CALL AnimatedImagesControlModel::getPropertySetInfo(  ) throw(RuntimeException)
278     {
279         static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
280         return xInfo;
281     }
282 
283     //------------------------------------------------------------------------------------------------------------------
284     ::rtl::OUString SAL_CALL AnimatedImagesControlModel::getServiceName() throw(RuntimeException)
285     {
286         return ::rtl::OUString::createFromAscii( szServiceName_AnimatedImagesControlModel );
287     }
288 
289     //------------------------------------------------------------------------------------------------------------------
290     ::rtl::OUString SAL_CALL AnimatedImagesControlModel::getImplementationName(  ) throw(RuntimeException)
291     {
292         return ::rtl::OUString::createFromAscii( "org.openoffice.comp.toolkit.AnimatedImagesControlModel" );
293     }
294 
295     //------------------------------------------------------------------------------------------------------------------
296     Sequence< ::rtl::OUString > SAL_CALL AnimatedImagesControlModel::getSupportedServiceNames() throw(RuntimeException)
297     {
298         Sequence< ::rtl::OUString > aServiceNames(2);
299         aServiceNames[0] = ::rtl::OUString::createFromAscii( szServiceName_AnimatedImagesControlModel );
300         aServiceNames[1] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.UnoControlModel" );
301         return aServiceNames;
302     }
303 
304     //------------------------------------------------------------------------------------------------------------------
305     void SAL_CALL AnimatedImagesControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 i_handle, const Any& i_value ) throw (Exception)
306     {
307         switch ( i_handle )
308         {
309         case BASEPROPERTY_IMAGE_SCALE_MODE:
310         {
311             sal_Int16 nImageScaleMode( ImageScaleMode::Anisotropic );
312             OSL_VERIFY( i_value >>= nImageScaleMode );  // convertFastPropertyValue ensures that this has the proper type
313             if  (   ( nImageScaleMode != ImageScaleMode::None )
314                 &&  ( nImageScaleMode != ImageScaleMode::Isotropic )
315                 &&  ( nImageScaleMode != ImageScaleMode::Anisotropic )
316                 )
317                 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
318         }
319         break;
320         }
321 
322         AnimatedImagesControlModel_Base::setFastPropertyValue_NoBroadcast( i_handle, i_value );
323     }
324 
325     //------------------------------------------------------------------------------------------------------------------
326     Any AnimatedImagesControlModel::ImplGetDefaultValue( sal_uInt16 i_propertyId ) const
327     {
328         switch ( i_propertyId )
329         {
330         case BASEPROPERTY_DEFAULTCONTROL:
331             return makeAny( ::rtl::OUString::createFromAscii( szServiceName_AnimatedImagesControl ) );
332 
333         case BASEPROPERTY_BORDER:
334             return makeAny( VisualEffect::NONE );
335 
336         case BASEPROPERTY_STEP_TIME:
337             return makeAny( (sal_Int32) 100 );
338 
339         case BASEPROPERTY_AUTO_REPEAT:
340             return makeAny( (sal_Bool)sal_True );
341 
342         case BASEPROPERTY_IMAGE_SCALE_MODE:
343             return makeAny( ImageScaleMode::None );
344 
345         default:
346             return UnoControlModel::ImplGetDefaultValue( i_propertyId );
347         }
348     }
349 
350     //------------------------------------------------------------------------------------------------------------------
351     ::cppu::IPropertyArrayHelper& SAL_CALL AnimatedImagesControlModel::getInfoHelper()
352     {
353         static UnoPropertyArrayHelper* pHelper = NULL;
354         if ( !pHelper )
355         {
356             Sequence< sal_Int32 > aIDs = ImplGetPropertyIds();
357             pHelper = new UnoPropertyArrayHelper( aIDs );
358         }
359         return *pHelper;
360     }
361 
362     //------------------------------------------------------------------------------------------------------------------
363     ::sal_Int32 SAL_CALL AnimatedImagesControlModel::getStepTime() throw (RuntimeException)
364     {
365         sal_Int32 nStepTime( 100 );
366         OSL_VERIFY( getPropertyValue( GetPropertyName( BASEPROPERTY_STEP_TIME ) ) >>= nStepTime );
367         return nStepTime;
368     }
369 
370     //------------------------------------------------------------------------------------------------------------------
371     void SAL_CALL AnimatedImagesControlModel::setStepTime( ::sal_Int32 i_stepTime ) throw (RuntimeException)
372     {
373         setPropertyValue( GetPropertyName( BASEPROPERTY_STEP_TIME ), makeAny( i_stepTime ) );
374     }
375 
376     //------------------------------------------------------------------------------------------------------------------
377     ::sal_Bool SAL_CALL AnimatedImagesControlModel::getAutoRepeat() throw (RuntimeException)
378     {
379         sal_Bool bAutoRepeat( sal_True );
380         OSL_VERIFY( getPropertyValue( GetPropertyName( BASEPROPERTY_AUTO_REPEAT ) ) >>= bAutoRepeat );
381         return bAutoRepeat;
382     }
383 
384     //------------------------------------------------------------------------------------------------------------------
385     void SAL_CALL AnimatedImagesControlModel::setAutoRepeat( ::sal_Bool i_autoRepeat ) throw (RuntimeException)
386     {
387         setPropertyValue( GetPropertyName( BASEPROPERTY_AUTO_REPEAT ), makeAny( i_autoRepeat ) );
388     }
389 
390     //------------------------------------------------------------------------------------------------------------------
391     ::sal_Int16 SAL_CALL AnimatedImagesControlModel::getScaleMode() throw (RuntimeException)
392     {
393         sal_Int16 nImageScaleMode( ImageScaleMode::Anisotropic );
394         OSL_VERIFY( getPropertyValue( GetPropertyName( BASEPROPERTY_IMAGE_SCALE_MODE ) ) >>= nImageScaleMode );
395         return nImageScaleMode;
396     }
397 
398     //------------------------------------------------------------------------------------------------------------------
399     void SAL_CALL AnimatedImagesControlModel::setScaleMode( ::sal_Int16 i_scaleMode ) throw (IllegalArgumentException, RuntimeException)
400     {
401         setPropertyValue( GetPropertyName( BASEPROPERTY_IMAGE_SCALE_MODE ), makeAny( i_scaleMode ) );
402     }
403 
404     //------------------------------------------------------------------------------------------------------------------
405     ::sal_Int32 SAL_CALL AnimatedImagesControlModel::getImageSetCount(  ) throw (RuntimeException)
406     {
407 	    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
408         if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
409             throw DisposedException();
410 
411         return m_pData->aImageSets.size();
412     }
413 
414     //------------------------------------------------------------------------------------------------------------------
415     Sequence< ::rtl::OUString > SAL_CALL AnimatedImagesControlModel::getImageSet( ::sal_Int32 i_index ) throw (IndexOutOfBoundsException, RuntimeException)
416     {
417 	    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
418         if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
419             throw DisposedException();
420 
421         lcl_checkIndex( *m_pData, i_index, *this );
422 
423         return m_pData->aImageSets[ i_index ];
424     }
425 
426     //------------------------------------------------------------------------------------------------------------------
427     void SAL_CALL AnimatedImagesControlModel::insertImageSet( ::sal_Int32 i_index, const Sequence< ::rtl::OUString >& i_imageURLs ) throw (IndexOutOfBoundsException, RuntimeException)
428     {
429 	    ::osl::ClearableMutexGuard aGuard( GetMutex() );
430         // sanity checks
431         if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
432             throw DisposedException();
433 
434         lcl_checkIndex( *m_pData, i_index, *this, true );
435 
436         // actaul insertion
437         m_pData->aImageSets.insert( m_pData->aImageSets.begin() + i_index, i_imageURLs );
438 
439         // listener notification
440         lcl_notify( aGuard, BrdcstHelper, &XContainerListener::elementInserted, i_index, i_imageURLs, *this );
441     }
442 
443     //------------------------------------------------------------------------------------------------------------------
444     void SAL_CALL AnimatedImagesControlModel::replaceImageSet( ::sal_Int32 i_index, const Sequence< ::rtl::OUString >& i_imageURLs ) throw (IndexOutOfBoundsException, RuntimeException)
445     {
446 	    ::osl::ClearableMutexGuard aGuard( GetMutex() );
447         // sanity checks
448         if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
449             throw DisposedException();
450 
451         lcl_checkIndex( *m_pData, i_index, *this );
452 
453         // actaul insertion
454         m_pData->aImageSets[ i_index ] = i_imageURLs;
455 
456         // listener notification
457         lcl_notify( aGuard, BrdcstHelper, &XContainerListener::elementReplaced, i_index, i_imageURLs, *this );
458     }
459 
460     //------------------------------------------------------------------------------------------------------------------
461     void SAL_CALL AnimatedImagesControlModel::removeImageSet( ::sal_Int32 i_index ) throw (IndexOutOfBoundsException, RuntimeException)
462     {
463 	    ::osl::ClearableMutexGuard aGuard( GetMutex() );
464         // sanity checks
465         if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
466             throw DisposedException();
467 
468         lcl_checkIndex( *m_pData, i_index, *this );
469 
470         // actual removal
471         ::std::vector< Sequence< ::rtl::OUString > >::iterator removalPos = m_pData->aImageSets.begin() + i_index;
472         Sequence< ::rtl::OUString > aRemovedElement( *removalPos );
473         m_pData->aImageSets.erase( removalPos );
474 
475         // listener notification
476         lcl_notify( aGuard, BrdcstHelper, &XContainerListener::elementRemoved, i_index, aRemovedElement, *this );
477     }
478 
479     //------------------------------------------------------------------------------------------------------------------
480     void SAL_CALL AnimatedImagesControlModel::addContainerListener( const Reference< XContainerListener >& i_listener ) throw (RuntimeException)
481     {
482         BrdcstHelper.addListener( XContainerListener::static_type(), i_listener );
483     }
484 
485     //------------------------------------------------------------------------------------------------------------------
486     void SAL_CALL AnimatedImagesControlModel::removeContainerListener( const Reference< XContainerListener >& i_listener ) throw (RuntimeException)
487     {
488         BrdcstHelper.removeListener( XContainerListener::static_type(), i_listener );
489     }
490 
491 //......................................................................................................................
492 } // namespace toolkit
493 //......................................................................................................................
494