LibreOffice Module vcl (master)  1
throbber.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <vcl/toolkit/throbber.hxx>
21 #include <vcl/svapp.hxx>
22 
23 #include <com/sun/star/uno/XComponentContext.hpp>
24 #include <com/sun/star/graphic/GraphicProvider.hpp>
25 #include <com/sun/star/graphic/XGraphicProvider.hpp>
26 #include <com/sun/star/awt/ImageScaleMode.hpp>
27 
30 #include <rtl/ustrbuf.hxx>
31 #include <sal/log.hxx>
32 #include <tools/urlobj.hxx>
33 
34 #include <limits>
35 
36 using ::com::sun::star::uno::Reference;
37 using ::com::sun::star::graphic::XGraphic;
38 using ::com::sun::star::graphic::XGraphicProvider;
39 using ::com::sun::star::uno::UNO_QUERY;
40 using ::com::sun::star::uno::Exception;
41 namespace ImageScaleMode = ::com::sun::star::awt::ImageScaleMode;
42 
43 Throbber::Throbber( vcl::Window* i_parentWindow, WinBits i_style )
44  :ImageControl( i_parentWindow, i_style )
45  ,mbRepeat( true )
46  ,mnStepTime( 100 )
47  ,mnCurStep( 0 )
48 {
50  maWaitTimer.SetInvokeHandler( LINK( this, Throbber, TimeOutHdl ) );
51 
52  SetScaleMode( ImageScaleMode::NONE );
53  initImages();
54 }
55 
57 {
58  disposeOnce();
59 }
60 
62 {
63  maWaitTimer.Stop();
65 }
66 
67 namespace
68 {
69  ::std::vector< Image > lcl_loadImageSet( const Throbber::ImageSet i_imageSet )
70  {
71  ::std::vector< Image > aImages;
72 
73  const Reference< css::uno::XComponentContext > aContext( ::comphelper::getProcessComponentContext() );
74  const Reference< XGraphicProvider > xGraphicProvider( css::graphic::GraphicProvider::create(aContext) );
75 
76  ::std::vector< OUString > aImageURLs( Throbber::getDefaultImageURLs( i_imageSet ) );
77  aImages.reserve( aImageURLs.size() );
78 
79  ::comphelper::NamedValueCollection aMediaProperties;
80  for ( const auto& rImageURL : aImageURLs )
81  {
82  Reference< XGraphic > xGraphic;
83  aMediaProperties.put( "URL", rImageURL );
84  xGraphic = xGraphicProvider->queryGraphic( aMediaProperties.getPropertyValues() );
85  aImages.emplace_back( xGraphic );
86  }
87 
88  return aImages;
89  }
90 }
91 
93 {
95  initImages();
96 }
97 
99 {
100  try
101  {
102  ::std::vector< ::std::vector< Image > > aImageSets;
103  aImageSets.push_back( lcl_loadImageSet( ImageSet::N16px ) );
104  aImageSets.push_back( lcl_loadImageSet( ImageSet::N32px ) );
105  aImageSets.push_back( lcl_loadImageSet( ImageSet::N64px ) );
106 
107  // find the best matching image set (size-wise)
108  const ::Size aWindowSizePixel = GetSizePixel();
109  size_t nPreferredSet = 0;
110  if ( aImageSets.size() > 1 )
111  {
112  long nMinimalDistance = ::std::numeric_limits< long >::max();
113  for ( ::std::vector< ::std::vector< Image > >::const_iterator check = aImageSets.begin();
114  check != aImageSets.end();
115  ++check
116  )
117  {
118  if ( check->empty() )
119  {
120  SAL_WARN( "vcl.control", "Throbber::initImages: illegal image!" );
121  continue;
122  }
123 
124  const Size aImageSize = (*check)[0].GetSizePixel();
125 
126  if ( ( aImageSize.Width() > aWindowSizePixel.Width() )
127  || ( aImageSize.Height() > aWindowSizePixel.Height() )
128  )
129  // do not use an image set which doesn't fit into the window
130  continue;
131 
132  const sal_Int64 distance =
133  ( aWindowSizePixel.Width() - aImageSize.Width() ) * ( aWindowSizePixel.Width() - aImageSize.Width() )
134  + ( aWindowSizePixel.Height() - aImageSize.Height() ) * ( aWindowSizePixel.Height() - aImageSize.Height() );
135  if ( distance < nMinimalDistance )
136  {
137  nMinimalDistance = distance;
138  nPreferredSet = check - aImageSets.begin();
139  }
140  }
141  }
142 
143  if ( nPreferredSet < aImageSets.size() )
144  setImageList( aImageSets[nPreferredSet] );
145  }
146  catch( const Exception& )
147  {
148  }
149 }
150 
152 {
153  maWaitTimer.Start();
154 }
155 
157 {
158  maWaitTimer.Stop();
159 }
160 
162 {
163  return maWaitTimer.IsActive();
164 }
165 
166 void Throbber::setImageList( ::std::vector< Image > const& i_images )
167 {
168  SAL_WARN_IF( i_images.size()>=SAL_MAX_INT32, "vcl.control", "Throbber::setImageList: too many images!" );
169 
170  maImageList = i_images;
171 
172  const Image aInitialImage( !maImageList.empty() ? maImageList[ 0 ] : Image() );
173  SetImage( aInitialImage );
174 }
175 
176 ::std::vector< OUString > Throbber::getDefaultImageURLs( const ImageSet i_imageSet )
177 {
178  ::std::vector< OUString > aImageURLs;
179 
180  sal_Char const* const pResolutions[] = { "16", "32", "64" };
181  size_t const nImageCounts[] = { 6, 12, 12 };
182 
183  size_t index = 0;
184  switch ( i_imageSet )
185  {
186  case ImageSet::N16px: index = 0; break;
187  case ImageSet::N32px: index = 1; break;
188  case ImageSet::N64px: index = 2; break;
189  }
190 
191  aImageURLs.reserve( nImageCounts[index] );
192  for ( size_t i=0; i<nImageCounts[index]; ++i )
193  {
194  OUStringBuffer aURL;
195  aURL.append( "private:graphicrepository/vcl/res/spinner-" );
196  aURL.appendAscii( pResolutions[index] );
197  aURL.append( "-" );
198  if ( i < 9 )
199  aURL.append( "0" );
200  aURL.append ( sal_Int32( i + 1 ) );
201  aURL.append( ".png" );
202 
203  aImageURLs.push_back( aURL.makeStringAndClear() );
204  }
205 
206  return aImageURLs;
207 }
208 
209 IMPL_LINK_NOARG(Throbber, TimeOutHdl, Timer *, void)
210 {
211  SolarMutexGuard aGuard;
212  if ( maImageList.empty() )
213  return;
214 
215  if ( mnCurStep < static_cast<sal_Int32>(maImageList.size()-1) )
216  ++mnCurStep;
217  else
218  {
219  if ( mbRepeat )
220  {
221  // start over
222  mnCurStep = 0;
223  }
224  else
225  {
226  stop();
227  }
228  }
229 
230  SetImage( maImageList[ mnCurStep ] );
231 }
232 
233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetScaleMode(const ::sal_Int16 _nMode)
Definition: imgctrl.cxx:33
long Width() const
long Height() const
virtual Size GetSizePixel() const
Definition: window.cxx:2364
SAL_DLLPRIVATE void initImages()
Definition: throbber.cxx:98
virtual ~Throbber() override
Definition: throbber.cxx:56
default images, 16x16 pixels
void start()
Definition: throbber.cxx:151
virtual void Resize() override
Definition: throbber.cxx:92
bool IsActive() const
Definition: task.hxx:90
sal_Int64 WinBits
default images, 32x32 pixels
char sal_Char
static::std::vector< OUString > getDefaultImageURLs(const ImageSet i_imageSet)
Definition: throbber.cxx:176
bool isRunning() const
Definition: throbber.cxx:161
AutoTimer maWaitTimer
Definition: throbber.hxx:80
sal_Int32 mnStepTime
Definition: throbber.hxx:78
virtual void Resize() override
Definition: imgctrl.cxx:42
default images, 64x64 pixels
double distance
Throbber(vcl::Window *i_parentWindow, WinBits i_style)
Definition: throbber.cxx:43
#define SAL_MAX_INT32
css::uno::Sequence< css::beans::PropertyValue > getPropertyValues() const
int i
virtual void Start() override
Activates the timer task.
Definition: timer.cxx:83
def stop
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: ctrl.cxx:59
void SetImage(const Image &rImage)
Definition: fixed.cxx:933
tuple index
void SetTimeout(sal_uInt64 nTimeoutMs)
Definition: timer.cxx:89
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > check(dp_misc::DescriptionInfoset const &infoset)
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: throbber.cxx:61
void setImageList(::std::vector< Image > const &i_images)
Definition: throbber.cxx:166
void Stop()
Definition: scheduler.cxx:593
bool put(const sal_Char *_pAsciiValueName, const VALUE_TYPE &_rValue)
#define SAL_WARN_IF(condition, area, stream)
Definition: image.hxx:40
Reference< XComponentContext > getProcessComponentContext()
void SetInvokeHandler(const Link< Timer *, void > &rLink)
Definition: timer.hxx:56
IMPL_LINK_NOARG(Throbber, TimeOutHdl, Timer *, void)
Definition: throbber.cxx:209
::std::vector< Image > maImageList
Definition: throbber.hxx:75
#define SAL_WARN(area, stream)
Definition: timer.hxx:26
void stop()
Definition: throbber.cxx:156