Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / toolkit / source / awt / animatedimagespeer.cxx
blobe33b9ac1ada0427fde80bf5367c5f4d565d461b2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include "toolkit/awt/animatedimagespeer.hxx"
22 #include "toolkit/helper/property.hxx"
24 #include <com/sun/star/awt/XAnimatedImages.hpp>
25 #include <com/sun/star/awt/Size.hpp>
26 #include <com/sun/star/graphic/GraphicProvider.hpp>
27 #include <com/sun/star/graphic/XGraphicProvider.hpp>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/graphic/XGraphic.hpp>
30 #include <com/sun/star/awt/ImageScaleMode.hpp>
32 #include <comphelper/namedvaluecollection.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <rtl/ustrbuf.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <tools/urlobj.hxx>
37 #include <vcl/throbber.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/settings.hxx>
41 #include <limits>
44 namespace toolkit
48 using ::com::sun::star::uno::XComponentContext;
49 using ::com::sun::star::uno::Reference;
50 using ::com::sun::star::uno::XInterface;
51 using ::com::sun::star::uno::UNO_QUERY;
52 using ::com::sun::star::uno::UNO_QUERY_THROW;
53 using ::com::sun::star::uno::Exception;
54 using ::com::sun::star::uno::RuntimeException;
55 using ::com::sun::star::uno::Any;
56 using ::com::sun::star::uno::Sequence;
57 using ::com::sun::star::lang::EventObject;
58 using ::com::sun::star::container::ContainerEvent;
59 using ::com::sun::star::awt::XAnimatedImages;
60 using ::com::sun::star::awt::Size;
61 using ::com::sun::star::graphic::XGraphicProvider;
62 using ::com::sun::star::beans::XPropertySet;
63 using ::com::sun::star::graphic::XGraphic;
65 namespace ImageScaleMode = ::com::sun::star::awt::ImageScaleMode;
68 //= AnimatedImagesPeer_Data
70 struct CachedImage
72 OUString sImageURL;
73 mutable Reference< XGraphic > xGraphic;
75 CachedImage()
76 :sImageURL()
77 ,xGraphic()
81 explicit CachedImage( OUString const& i_imageURL )
82 :sImageURL( i_imageURL )
83 ,xGraphic()
88 struct AnimatedImagesPeer_Data
90 AnimatedImagesPeer& rAntiImpl;
91 ::std::vector< ::std::vector< CachedImage > > aCachedImageSets;
93 explicit AnimatedImagesPeer_Data( AnimatedImagesPeer& i_antiImpl )
94 :rAntiImpl( i_antiImpl )
95 ,aCachedImageSets()
101 //= helper
103 namespace
106 OUString lcl_getHighContrastURL( OUString const& i_imageURL )
108 INetURLObject aURL( i_imageURL );
109 if ( aURL.GetProtocol() != INetProtocol::PrivSoffice )
111 OSL_VERIFY( aURL.insertName( "hicontrast", false, 0 ) );
112 return aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
114 // the private: scheme is not considered to be hierarchical by INetURLObject, so manually insert the
115 // segment
116 const sal_Int32 separatorPos = i_imageURL.indexOf( '/' );
117 ENSURE_OR_RETURN( separatorPos != -1, "lcl_getHighContrastURL: unsupported URL scheme - cannot automatically determine HC version!", i_imageURL );
119 OUStringBuffer composer;
120 composer.append( i_imageURL.copy( 0, separatorPos ) );
121 composer.append( "/hicontrast" );
122 composer.append( i_imageURL.copy( separatorPos ) );
123 return composer.makeStringAndClear();
127 bool lcl_ensureImage_throw( Reference< XGraphicProvider > const& i_graphicProvider, const bool i_isHighContrast, const CachedImage& i_cachedImage )
129 if ( !i_cachedImage.xGraphic.is() )
131 ::comphelper::NamedValueCollection aMediaProperties;
132 if ( i_isHighContrast )
134 // try (to find) the high-contrast version of the graphic first
135 aMediaProperties.put( "URL", lcl_getHighContrastURL( i_cachedImage.sImageURL ) );
136 i_cachedImage.xGraphic.set( i_graphicProvider->queryGraphic( aMediaProperties.getPropertyValues() ), UNO_QUERY );
138 if ( !i_cachedImage.xGraphic.is() )
140 aMediaProperties.put( "URL", i_cachedImage.sImageURL );
141 i_cachedImage.xGraphic.set( i_graphicProvider->queryGraphic( aMediaProperties.getPropertyValues() ), UNO_QUERY );
144 return i_cachedImage.xGraphic.is();
148 Size lcl_getGraphicSizePixel( Reference< XGraphic > const& i_graphic )
150 Size aSizePixel;
153 if ( i_graphic.is() )
155 const Reference< XPropertySet > xGraphicProps( i_graphic, UNO_QUERY_THROW );
156 OSL_VERIFY( xGraphicProps->getPropertyValue("SizePixel") >>= aSizePixel );
159 catch( const Exception& )
161 DBG_UNHANDLED_EXCEPTION();
163 return aSizePixel;
167 void lcl_init( Sequence< OUString > const& i_imageURLs, ::std::vector< CachedImage >& o_images )
169 o_images.resize(0);
170 size_t count = size_t( i_imageURLs.getLength() );
171 o_images.reserve( count );
172 for ( size_t i = 0; i < count; ++i )
174 o_images.push_back( CachedImage( i_imageURLs[i] ) );
179 void lcl_updateImageList_nothrow( AnimatedImagesPeer_Data& i_data )
181 VclPtr<Throbber> pThrobber = i_data.rAntiImpl.GetAsDynamic<Throbber>();
182 if ( !pThrobber )
183 return;
187 // collect the image sizes of the different image sets
188 const Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
189 const Reference< XGraphicProvider > xGraphicProvider( css::graphic::GraphicProvider::create(xContext) );
191 const bool isHighContrast = pThrobber->GetSettings().GetStyleSettings().GetHighContrastMode();
193 sal_Int32 nPreferredSet = -1;
194 const size_t nImageSetCount = i_data.aCachedImageSets.size();
195 if ( nImageSetCount < 2 )
197 nPreferredSet = sal_Int32( nImageSetCount ) - 1;
199 else
201 ::std::vector< Size > aImageSizes( nImageSetCount );
202 for ( size_t nImageSet = 0; nImageSet < nImageSetCount; ++nImageSet )
204 ::std::vector< CachedImage > const& rImageSet( i_data.aCachedImageSets[ nImageSet ] );
205 if ( ( rImageSet.empty() )
206 || ( !lcl_ensureImage_throw( xGraphicProvider, isHighContrast, rImageSet[0] ) )
209 aImageSizes[ nImageSet ] = Size( SAL_MAX_INT32, SAL_MAX_INT32 );
211 else
213 aImageSizes[ nImageSet ] = lcl_getGraphicSizePixel( rImageSet[0].xGraphic );
217 // find the set with the smallest difference between window size and image size
218 const ::Size aWindowSizePixel = pThrobber->GetSizePixel();
219 long nMinimalDistance = ::std::numeric_limits< long >::max();
220 for ( ::std::vector< Size >::const_iterator check = aImageSizes.begin();
221 check != aImageSizes.end();
222 ++check
225 if ( ( check->Width > aWindowSizePixel.Width() )
226 || ( check->Height > aWindowSizePixel.Height() )
228 // do not use an image set which doesn't fit into the window
229 continue;
231 const sal_Int64 distance =
232 ( aWindowSizePixel.Width() - check->Width ) * ( aWindowSizePixel.Width() - check->Width )
233 + ( aWindowSizePixel.Height() - check->Height ) * ( aWindowSizePixel.Height() - check->Height );
234 if ( distance < nMinimalDistance )
236 nMinimalDistance = distance;
237 nPreferredSet = check - aImageSizes.begin();
242 // found a set?
243 std::vector< Image > aImages;
244 if ( ( nPreferredSet >= 0 ) && ( size_t( nPreferredSet ) < nImageSetCount ) )
246 // => set the images
247 ::std::vector< CachedImage > const& rImageSet( i_data.aCachedImageSets[ nPreferredSet ] );
248 aImages.resize( rImageSet.size() );
249 sal_Int32 imageIndex = 0;
250 for ( ::std::vector< CachedImage >::const_iterator cachedImage = rImageSet.begin();
251 cachedImage != rImageSet.end();
252 ++cachedImage, ++imageIndex
255 lcl_ensureImage_throw( xGraphicProvider, isHighContrast, *cachedImage );
256 aImages[ imageIndex ] = Image(cachedImage->xGraphic);
259 pThrobber->setImageList( aImages );
261 catch( const Exception& )
263 DBG_UNHANDLED_EXCEPTION();
268 void lcl_updateImageList_nothrow( AnimatedImagesPeer_Data& i_data, const Reference< XAnimatedImages >& i_images )
272 const sal_Int32 nImageSetCount = i_images->getImageSetCount();
273 i_data.aCachedImageSets.resize(0);
274 for ( sal_Int32 set = 0; set < nImageSetCount; ++set )
276 const Sequence< OUString > aImageURLs( i_images->getImageSet( set ) );
277 ::std::vector< CachedImage > aImages;
278 lcl_init( aImageURLs, aImages );
279 i_data.aCachedImageSets.push_back( aImages );
282 lcl_updateImageList_nothrow( i_data );
284 catch( const Exception& )
286 DBG_UNHANDLED_EXCEPTION();
292 //= AnimatedImagesPeer
295 AnimatedImagesPeer::AnimatedImagesPeer()
296 :AnimatedImagesPeer_Base()
297 ,m_xData( new AnimatedImagesPeer_Data( *this ) )
302 AnimatedImagesPeer::~AnimatedImagesPeer()
307 void SAL_CALL AnimatedImagesPeer::startAnimation()
309 SolarMutexGuard aGuard;
310 VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
311 if (pThrobber)
312 pThrobber->start();
315 void SAL_CALL AnimatedImagesPeer::stopAnimation()
317 SolarMutexGuard aGuard;
318 VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
319 if (pThrobber)
320 pThrobber->stop();
323 sal_Bool SAL_CALL AnimatedImagesPeer::isAnimationRunning()
325 SolarMutexGuard aGuard;
326 VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
327 if (pThrobber)
328 return pThrobber->isRunning();
329 return false;
332 void SAL_CALL AnimatedImagesPeer::setProperty( const OUString& i_propertyName, const Any& i_value )
334 SolarMutexGuard aGuard;
336 VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
337 if ( pThrobber )
339 VCLXWindow::setProperty( i_propertyName, i_value );
340 return;
343 const sal_uInt16 nPropertyId = GetPropertyId( i_propertyName );
344 switch ( nPropertyId )
346 case BASEPROPERTY_STEP_TIME:
348 sal_Int32 nStepTime( 0 );
349 if ( i_value >>= nStepTime )
350 pThrobber->setStepTime( nStepTime );
351 break;
353 case BASEPROPERTY_AUTO_REPEAT:
355 bool bRepeat( true );
356 if ( i_value >>= bRepeat )
357 pThrobber->setRepeat( bRepeat );
358 break;
361 case BASEPROPERTY_IMAGE_SCALE_MODE:
363 sal_Int16 nScaleMode( ImageScaleMode::ANISOTROPIC );
364 VclPtr<ImageControl> pImageControl = GetAsDynamic< ImageControl >();
365 if ( pImageControl && ( i_value >>= nScaleMode ) )
366 pImageControl->SetScaleMode( nScaleMode );
368 break;
370 default:
371 AnimatedImagesPeer_Base::setProperty( i_propertyName, i_value );
372 break;
377 Any SAL_CALL AnimatedImagesPeer::getProperty( const OUString& i_propertyName )
379 SolarMutexGuard aGuard;
381 Any aReturn;
383 VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
384 if ( !pThrobber )
385 return VCLXWindow::getProperty( i_propertyName );
387 const sal_uInt16 nPropertyId = GetPropertyId( i_propertyName );
388 switch ( nPropertyId )
390 case BASEPROPERTY_STEP_TIME:
391 aReturn <<= pThrobber->getStepTime();
392 break;
394 case BASEPROPERTY_AUTO_REPEAT:
395 aReturn <<= pThrobber->getRepeat();
396 break;
398 case BASEPROPERTY_IMAGE_SCALE_MODE:
400 VclPtr<ImageControl> pImageControl = GetAsDynamic<ImageControl>();
401 aReturn <<= ( pImageControl ? pImageControl->GetScaleMode() : ImageScaleMode::ANISOTROPIC );
403 break;
405 default:
406 aReturn = AnimatedImagesPeer_Base::getProperty( i_propertyName );
407 break;
410 return aReturn;
414 void AnimatedImagesPeer::ProcessWindowEvent( const VclWindowEvent& i_windowEvent )
416 if ( i_windowEvent.GetId() == VclEventId::WindowResize )
418 lcl_updateImageList_nothrow( *m_xData );
421 AnimatedImagesPeer_Base::ProcessWindowEvent( i_windowEvent );
425 void AnimatedImagesPeer::impl_updateImages_nolck( const Reference< XInterface >& i_animatedImages )
427 SolarMutexGuard aGuard;
429 lcl_updateImageList_nothrow( *m_xData, Reference< XAnimatedImages >( i_animatedImages, UNO_QUERY_THROW ) );
433 void SAL_CALL AnimatedImagesPeer::elementInserted( const ContainerEvent& i_event )
435 SolarMutexGuard aGuard;
436 Reference< XAnimatedImages > xAnimatedImages( i_event.Source, UNO_QUERY_THROW );
438 sal_Int32 nPosition(0);
439 OSL_VERIFY( i_event.Accessor >>= nPosition );
440 size_t position = size_t( nPosition );
441 if ( position > m_xData->aCachedImageSets.size() )
443 OSL_ENSURE( false, "AnimatedImagesPeer::elementInserted: illegal accessor/index!" );
444 lcl_updateImageList_nothrow( *m_xData, xAnimatedImages );
447 Sequence< OUString > aImageURLs;
448 OSL_VERIFY( i_event.Element >>= aImageURLs );
449 ::std::vector< CachedImage > aImages;
450 lcl_init( aImageURLs, aImages );
451 m_xData->aCachedImageSets.insert( m_xData->aCachedImageSets.begin() + position, aImages );
452 lcl_updateImageList_nothrow( *m_xData );
456 void SAL_CALL AnimatedImagesPeer::elementRemoved( const ContainerEvent& i_event )
458 SolarMutexGuard aGuard;
459 Reference< XAnimatedImages > xAnimatedImages( i_event.Source, UNO_QUERY_THROW );
461 sal_Int32 nPosition(0);
462 OSL_VERIFY( i_event.Accessor >>= nPosition );
463 size_t position = size_t( nPosition );
464 if ( position >= m_xData->aCachedImageSets.size() )
466 OSL_ENSURE( false, "AnimatedImagesPeer::elementRemoved: illegal accessor/index!" );
467 lcl_updateImageList_nothrow( *m_xData, xAnimatedImages );
470 m_xData->aCachedImageSets.erase( m_xData->aCachedImageSets.begin() + position );
471 lcl_updateImageList_nothrow( *m_xData );
475 void SAL_CALL AnimatedImagesPeer::elementReplaced( const ContainerEvent& i_event )
477 SolarMutexGuard aGuard;
478 Reference< XAnimatedImages > xAnimatedImages( i_event.Source, UNO_QUERY_THROW );
480 sal_Int32 nPosition(0);
481 OSL_VERIFY( i_event.Accessor >>= nPosition );
482 size_t position = size_t( nPosition );
483 if ( position >= m_xData->aCachedImageSets.size() )
485 OSL_ENSURE( false, "AnimatedImagesPeer::elementReplaced: illegal accessor/index!" );
486 lcl_updateImageList_nothrow( *m_xData, xAnimatedImages );
489 Sequence< OUString > aImageURLs;
490 OSL_VERIFY( i_event.Element >>= aImageURLs );
491 ::std::vector< CachedImage > aImages;
492 lcl_init( aImageURLs, aImages );
493 m_xData->aCachedImageSets[ position ] = aImages;
494 lcl_updateImageList_nothrow( *m_xData );
498 void SAL_CALL AnimatedImagesPeer::disposing( const EventObject& i_event )
500 VCLXWindow::disposing( i_event );
504 void SAL_CALL AnimatedImagesPeer::modified( const EventObject& i_event )
506 impl_updateImages_nolck( i_event.Source );
510 void SAL_CALL AnimatedImagesPeer::dispose( )
512 AnimatedImagesPeer_Base::dispose();
513 SolarMutexGuard aGuard;
514 m_xData->aCachedImageSets.resize(0);
518 } // namespace toolkit
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */