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::Exception;
40 namespace ImageScaleMode = ::com::sun::star::awt::ImageScaleMode;
41 
42 Throbber::Throbber( vcl::Window* i_parentWindow, WinBits i_style )
43  :ImageControl( i_parentWindow, i_style )
44  ,mbRepeat( true )
45  ,mnStepTime( 100 )
46  ,mnCurStep( 0 )
47 {
48  maWaitTimer.SetTimeout( mnStepTime );
49  maWaitTimer.SetInvokeHandler( LINK( this, Throbber, TimeOutHdl ) );
50 
51  SetScaleMode( ImageScaleMode::NONE );
52  initImages();
53 }
54 
55 Throbber::~Throbber()
56 {
57  disposeOnce();
58 }
59 
60 void Throbber::dispose()
61 {
62  maWaitTimer.Stop();
63  ImageControl::dispose();
64 }
65 
66 namespace
67 {
68  ::std::vector< Image > lcl_loadImageSet( const Throbber::ImageSet i_imageSet )
69  {
70  ::std::vector< Image > aImages;
71 
72  const Reference< css::uno::XComponentContext > aContext( ::comphelper::getProcessComponentContext() );
73  const Reference< XGraphicProvider > xGraphicProvider( css::graphic::GraphicProvider::create(aContext) );
74 
75  ::std::vector< OUString > aImageURLs( Throbber::getDefaultImageURLs( i_imageSet ) );
76  aImages.reserve( aImageURLs.size() );
77 
78  ::comphelper::NamedValueCollection aMediaProperties;
79  for ( const auto& rImageURL : aImageURLs )
80  {
81  Reference< XGraphic > xGraphic;
82  aMediaProperties.put( "URL", rImageURL );
83  xGraphic = xGraphicProvider->queryGraphic( aMediaProperties.getPropertyValues() );
84  aImages.emplace_back( xGraphic );
85  }
86 
87  return aImages;
88  }
89 }
90 
91 void Throbber::Resize()
92 {
93  ImageControl::Resize();
94  initImages();
95 }
96 
97 void Throbber::initImages()
98 {
99  try
100  {
101  ::std::vector< ::std::vector< Image > > aImageSets;
102  aImageSets.push_back( lcl_loadImageSet( ImageSet::N16px ) );
103  aImageSets.push_back( lcl_loadImageSet( ImageSet::N32px ) );
104  aImageSets.push_back( lcl_loadImageSet( ImageSet::N64px ) );
105 
106  // find the best matching image set (size-wise)
107  const ::Size aWindowSizePixel = GetSizePixel();
108  size_t nPreferredSet = 0;
109  if ( aImageSets.size() > 1 )
110  {
111  tools::Long nMinimalDistance = ::std::numeric_limits< tools::Long >::max();
112  for ( ::std::vector< ::std::vector< Image > >::const_iterator check = aImageSets.begin();
113  check != aImageSets.end();
114  ++check
115  )
116  {
117  if ( check->empty() )
118  {
119  SAL_WARN( "vcl.control", "Throbber::initImages: illegal image!" );
120  continue;
121  }
122 
123  const Size aImageSize = (*check)[0].GetSizePixel();
124 
125  if ( ( aImageSize.Width() > aWindowSizePixel.Width() )
126  || ( aImageSize.Height() > aWindowSizePixel.Height() )
127  )
128  // do not use an image set which doesn't fit into the window
129  continue;
130 
131  const sal_Int64 distance =
132  ( aWindowSizePixel.Width() - aImageSize.Width() ) * ( aWindowSizePixel.Width() - aImageSize.Width() )
133  + ( aWindowSizePixel.Height() - aImageSize.Height() ) * ( aWindowSizePixel.Height() - aImageSize.Height() );
134  if ( distance < nMinimalDistance )
135  {
136  nMinimalDistance = distance;
137  nPreferredSet = check - aImageSets.begin();
138  }
139  }
140  }
141 
142  if ( nPreferredSet < aImageSets.size() )
143  setImageList( aImageSets[nPreferredSet] );
144  }
145  catch( const Exception& )
146  {
147  }
148 }
149 
150 void Throbber::start()
151 {
152  maWaitTimer.Start();
153 }
154 
155 void Throbber::stop()
156 {
157  maWaitTimer.Stop();
158 }
159 
160 bool Throbber::isRunning() const
161 {
162  return maWaitTimer.IsActive();
163 }
164 
165 void Throbber::setImageList( ::std::vector< Image > const& i_images )
166 {
167  SAL_WARN_IF( i_images.size()>=SAL_MAX_INT32, "vcl.control", "Throbber::setImageList: too many images!" );
168 
169  maImageList = i_images;
170 
171  const Image aInitialImage( !maImageList.empty() ? maImageList[ 0 ] : Image() );
172  SetImage( aInitialImage );
173 }
174 
175 ::std::vector< OUString > Throbber::getDefaultImageURLs( const ImageSet i_imageSet )
176 {
177  ::std::vector< OUString > aImageURLs;
178 
179  char const* const pResolutions[] = { "16", "32", "64" };
180  size_t const nImageCounts[] = { 6, 12, 12 };
181 
182  size_t index = 0;
183  switch ( i_imageSet )
184  {
185  case ImageSet::N16px: index = 0; break;
186  case ImageSet::N32px: index = 1; break;
187  case ImageSet::N64px: index = 2; break;
188  }
189 
190  aImageURLs.reserve( nImageCounts[index] );
191  for ( size_t i=0; i<nImageCounts[index]; ++i )
192  {
193  OUStringBuffer aURL;
194  aURL.append( "private:graphicrepository/vcl/res/spinner-" );
195  aURL.appendAscii( pResolutions[index] );
196  aURL.append( "-" );
197  if ( i < 9 )
198  aURL.append( "0" );
199  aURL.append ( sal_Int32( i + 1 ) );
200  aURL.append( ".png" );
201 
202  aImageURLs.push_back( aURL.makeStringAndClear() );
203  }
204 
205  return aImageURLs;
206 }
207 
208 IMPL_LINK_NOARG(Throbber, TimeOutHdl, Timer *, void)
209 {
210  SolarMutexGuard aGuard;
211  if ( maImageList.empty() )
212  return;
213 
214  if ( mnCurStep < static_cast<sal_Int32>(maImageList.size()-1) )
215  ++mnCurStep;
216  else
217  {
218  if ( mbRepeat )
219  {
220  // start over
221  mnCurStep = 0;
222  }
223  else
224  {
225  stop();
226  }
227  }
228 
229  SetImage( maImageList[ mnCurStep ] );
230 }
231 
232 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
URL aURL
long Long
sal_Int64 WinBits
double distance
#define SAL_MAX_INT32
int i
css::uno::Sequence< css::beans::PropertyValue > getPropertyValues() const
tools::Long Width() const
def stop
tuple index
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > check(dp_misc::DescriptionInfoset const &infoset)
#define SAL_WARN_IF(condition, area, stream)
Definition: image.hxx:39
bool put(const char *_pAsciiValueName, const VALUE_TYPE &_rValue)
tools::Long Height() const
Reference< XComponentContext > getProcessComponentContext()
#define SAL_WARN(area, stream)
Definition: timer.hxx:26
IMPL_LINK_NOARG(QuickSelectionEngine_Data, SearchStringTimeout, Timer *, void)
Reference< XGraphic > xGraphic