bump product version to 4.1.6.2
[LibreOffice.git] / desktop / source / splash / splash.cxx
blobc5bc653460a14647029ad777a1b114ecfa79e62b
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 "splash.hxx"
22 #include <stdio.h>
23 #include <unotools/bootstrap.hxx>
24 #include <tools/stream.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/salnativewidgets.hxx>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <com/sun/star/registry/XRegistryKey.hpp>
30 #include <com/sun/star/task/XStatusIndicator.hpp>
31 #include <cppuhelper/implbase2.hxx>
32 #include <rtl/bootstrap.hxx>
33 #include <rtl/logfile.hxx>
34 #include <rtl/strbuf.hxx>
35 #include <rtl/math.hxx>
36 #include <vcl/introwin.hxx>
37 #include <vcl/virdev.hxx>
39 #define NOT_LOADED ((long)-1)
41 using namespace ::rtl;
42 using namespace ::com::sun::star::lang;
43 using namespace ::com::sun::star::registry;
44 using namespace ::com::sun::star::task;
45 using namespace ::com::sun::star::uno;
47 namespace {
49 class SplashScreen
50 : public ::cppu::WeakImplHelper2< XStatusIndicator, XInitialization >
51 , public IntroWindow
53 private:
54 enum BitmapMode { BM_FULLSCREEN, BM_DEFAULTMODE };
56 DECL_LINK( AppEventListenerHdl, VclWindowEvent * );
57 virtual ~SplashScreen();
58 void loadConfig();
59 void updateStatus();
60 void SetScreenBitmap(BitmapEx &rBitmap);
61 void determineProgressRatioValues( double& rXRelPos, double& rYRelPos, double& rRelWidth, double& rRelHeight );
63 static osl::Mutex _aMutex;
65 VirtualDevice _vdev;
66 BitmapEx _aIntroBmp;
67 Color _cProgressFrameColor;
68 Color _cProgressBarColor;
69 Color _cProgressTextColor;
70 bool _bNativeProgress;
71 OUString _sAppName;
72 OUString _sProgressText;
74 sal_Int32 _iMax;
75 sal_Int32 _iProgress;
76 BitmapMode _eBitmapMode;
77 sal_Bool _bPaintBitmap;
78 sal_Bool _bPaintProgress;
79 sal_Bool _bVisible;
80 sal_Bool _bShowLogo;
81 sal_Bool _bFullScreenSplash;
82 sal_Bool _bProgressEnd;
83 long _height, _width, _tlx, _tly, _barwidth;
84 long _barheight, _barspace, _textBaseline;
85 double _fXPos, _fYPos;
86 double _fWidth, _fHeight;
87 const long _xoffset, _yoffset;
89 public:
90 SplashScreen();
92 // XStatusIndicator
93 virtual void SAL_CALL end() throw ( RuntimeException );
94 virtual void SAL_CALL reset() throw ( RuntimeException );
95 virtual void SAL_CALL setText(const OUString& aText) throw ( RuntimeException );
96 virtual void SAL_CALL setValue(sal_Int32 nValue) throw ( RuntimeException );
97 virtual void SAL_CALL start(const OUString& aText, sal_Int32 nRange) throw ( RuntimeException );
99 // XInitialize
100 virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
101 throw ( RuntimeException );
103 // workwindow
104 virtual void Paint( const Rectangle& );
108 SplashScreen::SplashScreen()
109 : IntroWindow()
110 , _vdev(*((IntroWindow*)this))
111 , _cProgressFrameColor(sal::static_int_cast< ColorData >(NOT_LOADED))
112 , _cProgressBarColor(sal::static_int_cast< ColorData >(NOT_LOADED))
113 , _cProgressTextColor(sal::static_int_cast< ColorData >(NOT_LOADED))
114 , _bNativeProgress(true)
115 , _iMax(100)
116 , _iProgress(0)
117 , _eBitmapMode(BM_DEFAULTMODE)
118 , _bPaintBitmap(sal_True)
119 , _bPaintProgress(sal_False)
120 , _bShowLogo(sal_True)
121 , _bFullScreenSplash(sal_False)
122 , _bProgressEnd(sal_False)
123 , _tlx(NOT_LOADED)
124 , _tly(NOT_LOADED)
125 , _barwidth(NOT_LOADED)
126 , _barheight(NOT_LOADED)
127 , _barspace(2)
128 , _textBaseline(NOT_LOADED)
129 , _fXPos(-1.0)
130 , _fYPos(-1.0)
131 , _fWidth(-1.0)
132 , _fHeight(-1.0)
133 , _xoffset(12)
134 , _yoffset(18)
136 loadConfig();
137 _vdev.EnableRTL(IsRTLEnabled());
140 SplashScreen::~SplashScreen()
142 Application::RemoveEventListener(
143 LINK( this, SplashScreen, AppEventListenerHdl ) );
144 Hide();
148 void SAL_CALL SplashScreen::start(const OUString&, sal_Int32 nRange)
149 throw (RuntimeException)
151 _iMax = nRange;
152 if (_bVisible) {
153 _bProgressEnd = sal_False;
154 SolarMutexGuard aSolarGuard;
155 if ( _eBitmapMode == BM_FULLSCREEN )
156 ShowFullScreenMode( sal_True );
157 Show();
158 Paint(Rectangle());
159 Flush();
163 void SAL_CALL SplashScreen::end()
164 throw (RuntimeException)
166 _iProgress = _iMax;
167 if (_bVisible )
169 if ( _eBitmapMode == BM_FULLSCREEN )
170 EndFullScreenMode();
171 Hide();
173 _bProgressEnd = sal_True;
176 void SAL_CALL SplashScreen::reset()
177 throw (RuntimeException)
179 _iProgress = 0;
180 if (_bVisible && !_bProgressEnd )
182 if ( _eBitmapMode == BM_FULLSCREEN )
183 ShowFullScreenMode( sal_True );
184 Show();
185 updateStatus();
189 void SAL_CALL SplashScreen::setText(const OUString& rText)
190 throw (RuntimeException)
192 SolarMutexGuard aSolarGuard;
193 if ( _sProgressText != rText )
195 _sProgressText = rText;
197 if (_bVisible && !_bProgressEnd)
199 if ( _eBitmapMode == BM_FULLSCREEN )
200 ShowFullScreenMode( sal_True );
201 Show();
202 updateStatus();
207 void SAL_CALL SplashScreen::setValue(sal_Int32 nValue)
208 throw (RuntimeException)
210 RTL_LOGFILE_CONTEXT( aLog, "::SplashScreen::setValue (lo119109)" );
211 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "value=%d", nValue );
213 SolarMutexGuard aSolarGuard;
214 if (_bVisible && !_bProgressEnd) {
215 if ( _eBitmapMode == BM_FULLSCREEN )
216 ShowFullScreenMode( sal_True );
217 Show();
218 if (nValue >= _iMax) _iProgress = _iMax;
219 else _iProgress = nValue;
220 updateStatus();
224 // XInitialize
225 void SAL_CALL
226 SplashScreen::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
227 throw (RuntimeException)
229 ::osl::ClearableMutexGuard aGuard( _aMutex );
230 if (aArguments.getLength() > 0)
232 aArguments[0] >>= _bVisible;
233 if (aArguments.getLength() > 1 )
234 aArguments[1] >>= _sAppName;
236 // start to determine bitmap and all other required value
237 if ( _bShowLogo )
238 SetScreenBitmap (_aIntroBmp);
239 Size aSize = _aIntroBmp.GetSizePixel();
240 SetOutputSizePixel( aSize );
241 _vdev.SetOutputSizePixel( aSize );
242 _height = aSize.Height();
243 _width = aSize.Width();
244 if (_width > 500)
246 Point xtopleft(212,216);
247 if ( NOT_LOADED == _tlx || NOT_LOADED == _tly )
249 _tlx = xtopleft.X(); // top-left x
250 _tly = xtopleft.Y(); // top-left y
252 if ( NOT_LOADED == _barwidth )
253 _barwidth = 263;
254 if ( NOT_LOADED == _barheight )
255 _barheight = 8;
256 if (( _eBitmapMode == BM_FULLSCREEN ) &&
257 _bFullScreenSplash )
259 if( ( _fXPos >= 0.0 ) && ( _fYPos >= 0.0 ))
261 _tlx = sal_Int32( double( aSize.Width() ) * _fXPos );
262 _tly = sal_Int32( double( aSize.Height() ) * _fYPos );
264 if ( _fWidth >= 0.0 )
265 _barwidth = sal_Int32( double( aSize.Width() ) * _fWidth );
266 if ( _fHeight >= 0.0 )
267 _barheight = sal_Int32( double( aSize.Width() ) * _fHeight );
270 else
272 if ( NOT_LOADED == _barwidth )
273 _barwidth = _width - (2 * _xoffset);
274 if ( NOT_LOADED == _barheight )
275 _barheight = 6;
276 if ( NOT_LOADED == _tlx || NOT_LOADED == _tly )
278 _tlx = _xoffset; // top-left x
279 _tly = _height - _yoffset; // top-left y
283 if ( NOT_LOADED == _textBaseline )
284 _textBaseline = _height;
286 if ( sal::static_int_cast< ColorData >(NOT_LOADED) ==
287 _cProgressFrameColor.GetColor() )
288 _cProgressFrameColor = Color( COL_LIGHTGRAY );
290 if ( sal::static_int_cast< ColorData >(NOT_LOADED) ==
291 _cProgressBarColor.GetColor() )
293 // progress bar: new color only for big bitmap format
294 if ( _width > 500 )
295 _cProgressBarColor = Color( 157, 202, 18 );
296 else
297 _cProgressBarColor = Color( COL_BLUE );
300 if ( sal::static_int_cast< ColorData >(NOT_LOADED) ==
301 _cProgressTextColor.GetColor() )
302 _cProgressTextColor = Color( COL_BLACK );
304 Application::AddEventListener(
305 LINK( this, SplashScreen, AppEventListenerHdl ) );
309 void SplashScreen::updateStatus()
311 if (!_bVisible || _bProgressEnd) return;
312 if (!_bPaintProgress) _bPaintProgress = sal_True;
313 Paint(Rectangle());
314 Flush();
317 // internal private methods
318 IMPL_LINK( SplashScreen, AppEventListenerHdl, VclWindowEvent *, inEvent )
320 if ( inEvent != 0 )
322 switch ( inEvent->GetId() )
324 case VCLEVENT_WINDOW_SHOW:
325 Paint( Rectangle() );
326 break;
327 default:
328 break;
331 return 0;
334 // Read keys from soffice{.ini|rc}:
335 OUString implReadBootstrapKey( const OUString& _rKey )
337 OUString sValue;
338 rtl::Bootstrap::get(_rKey, sValue);
339 return sValue;
342 void SplashScreen::loadConfig()
344 _bShowLogo = implReadBootstrapKey( "Logo" ) != "0";
346 OUString sProgressFrameColor = implReadBootstrapKey( "ProgressFrameColor" );
347 OUString sProgressBarColor = implReadBootstrapKey( "ProgressBarColor" );
348 OUString sProgressTextColor = implReadBootstrapKey( "ProgressTextColor" );
349 OUString sProgressTextBaseline = implReadBootstrapKey( "ProgressTextBaseline" );
350 OUString sSize = implReadBootstrapKey( "ProgressSize" );
351 OUString sPosition = implReadBootstrapKey( "ProgressPosition" );
352 OUString sFullScreenSplash = implReadBootstrapKey( "FullScreenSplash" );
353 OUString sNativeProgress = implReadBootstrapKey( "NativeProgress" );
356 // Determine full screen splash mode
357 _bFullScreenSplash = (( !sFullScreenSplash.isEmpty() ) &&
358 ( !sFullScreenSplash.equals( "0" )));
360 // Try to retrieve the relative values for the progress bar. The current
361 // schema uses the screen ratio to retrieve the associated values.
362 if ( _bFullScreenSplash )
363 determineProgressRatioValues( _fXPos, _fYPos, _fWidth, _fHeight );
365 if ( !sProgressFrameColor.isEmpty() )
367 sal_uInt8 nRed = 0;
368 sal_Int32 idx = 0;
369 sal_Int32 temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32();
370 if ( idx != -1 )
372 nRed = static_cast< sal_uInt8 >( temp );
373 temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32();
375 if ( idx != -1 )
377 sal_uInt8 nGreen = static_cast< sal_uInt8 >( temp );
378 sal_uInt8 nBlue = static_cast< sal_uInt8 >( sProgressFrameColor.getToken( 0, ',', idx ).toInt32() );
379 _cProgressFrameColor = Color( nRed, nGreen, nBlue );
383 if ( !sProgressBarColor.isEmpty() )
385 sal_uInt8 nRed = 0;
386 sal_Int32 idx = 0;
387 sal_Int32 temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32();
388 if ( idx != -1 )
390 nRed = static_cast< sal_uInt8 >( temp );
391 temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32();
393 if ( idx != -1 )
395 sal_uInt8 nGreen = static_cast< sal_uInt8 >( temp );
396 sal_uInt8 nBlue = static_cast< sal_uInt8 >( sProgressBarColor.getToken( 0, ',', idx ).toInt32() );
397 _cProgressBarColor = Color( nRed, nGreen, nBlue );
401 if ( !sProgressTextColor.isEmpty() )
403 sal_uInt8 nRed = 0;
404 sal_Int32 idx = 0;
405 sal_Int32 temp = sProgressTextColor.getToken( 0, ',', idx ).toInt32();
406 if ( idx != -1 )
408 nRed = static_cast< sal_uInt8 >( temp );
409 temp = sProgressTextColor.getToken( 0, ',', idx ).toInt32();
411 if ( idx != -1 )
413 sal_uInt8 nGreen = static_cast< sal_uInt8 >( temp );
414 sal_uInt8 nBlue = static_cast< sal_uInt8 >( sProgressTextColor.getToken( 0, ',', idx ).toInt32() );
415 _cProgressTextColor = Color( nRed, nGreen, nBlue );
419 if ( !sProgressTextBaseline.isEmpty() )
421 _textBaseline = sProgressTextBaseline.toInt32();
424 if( !sNativeProgress.isEmpty() )
426 _bNativeProgress = sNativeProgress.toBoolean();
429 if ( !sSize.isEmpty() )
431 sal_Int32 idx = 0;
432 sal_Int32 temp = sSize.getToken( 0, ',', idx ).toInt32();
433 if ( idx != -1 )
435 _barwidth = temp;
436 _barheight = sSize.getToken( 0, ',', idx ).toInt32();
440 if ( _barheight >= 10 )
441 _barspace = 3; // more space between frame and bar
443 if ( !sPosition.isEmpty() )
445 sal_Int32 idx = 0;
446 sal_Int32 temp = sPosition.getToken( 0, ',', idx ).toInt32();
447 if ( idx != -1 )
449 _tlx = temp;
450 _tly = sPosition.getToken( 0, ',', idx ).toInt32();
455 void SplashScreen::SetScreenBitmap(BitmapEx &rBitmap)
457 sal_Int32 nWidth( 0 );
458 sal_Int32 nHeight( 0 );
460 // determine desktop resolution
461 sal_uInt32 nCount = Application::GetScreenCount();
462 if ( nCount > 0 )
464 // retrieve size from first screen
465 Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0);
466 nWidth = aScreenArea.GetWidth();
467 nHeight = aScreenArea.GetHeight();
470 // create file name from screen resolution information
471 OStringBuffer aStrBuf( 128 );
472 OStringBuffer aResBuf( 32 );
473 aStrBuf.append( "intro_" );
474 if ( !_sAppName.isEmpty() )
476 aStrBuf.append( OUStringToOString(_sAppName, RTL_TEXTENCODING_UTF8) );
477 aStrBuf.append( "_" );
479 aResBuf.append( OString::valueOf( nWidth ));
480 aResBuf.append( "x" );
481 aResBuf.append( OString::valueOf( nHeight ));
483 aStrBuf.append( aResBuf.getStr() );
484 if (Application::LoadBrandBitmap (aStrBuf.makeStringAndClear().getStr(), rBitmap))
485 return;
487 aStrBuf.append( "intro_" );
488 aStrBuf.append( aResBuf.getStr() );
489 if (Application::LoadBrandBitmap (aResBuf.makeStringAndClear().getStr(), rBitmap))
490 return;
492 Application::LoadBrandBitmap ("intro", rBitmap);
495 void SplashScreen::determineProgressRatioValues(
496 double& rXRelPos, double& rYRelPos,
497 double& rRelWidth, double& rRelHeight )
499 sal_Int32 nWidth( 0 );
500 sal_Int32 nHeight( 0 );
501 sal_Int32 nScreenRatio( 0 );
503 // determine desktop resolution
504 sal_uInt32 nCount = Application::GetScreenCount();
505 if ( nCount > 0 )
507 // retrieve size from first screen
508 Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0);
509 nWidth = aScreenArea.GetWidth();
510 nHeight = aScreenArea.GetHeight();
511 nScreenRatio = sal_Int32( math::round( double( nWidth ) / double( nHeight ), 2 ) * 100 );
514 char szFullScreenProgressRatio[] = "FullScreenProgressRatio0";
515 char szFullScreenProgressPos[] = "FullScreenProgressPos0";
516 char szFullScreenProgressSize[] = "FullScreenProgressSize0";
517 for ( sal_Int32 i = 0; i <= 9; i++ )
519 char cNum = '0' + char( i );
520 szFullScreenProgressRatio[23] = cNum;
521 szFullScreenProgressPos[21] = cNum;
522 szFullScreenProgressSize[22] = cNum;
524 OUString sFullScreenProgressRatio = implReadBootstrapKey(
525 OUString::createFromAscii( szFullScreenProgressRatio ) );
527 if ( !sFullScreenProgressRatio.isEmpty() )
529 double fRatio = sFullScreenProgressRatio.toDouble();
530 sal_Int32 nRatio = sal_Int32( math::round( fRatio, 2 ) * 100 );
531 if ( nRatio == nScreenRatio )
533 OUString sFullScreenProgressPos = implReadBootstrapKey(
534 OUString::createFromAscii( szFullScreenProgressPos ) );
535 OUString sFullScreenProgressSize = implReadBootstrapKey(
536 OUString::createFromAscii( szFullScreenProgressSize ) );
538 if ( !sFullScreenProgressPos.isEmpty() )
540 sal_Int32 idx = 0;
541 double temp = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble();
542 if ( idx != -1 )
544 rXRelPos = temp;
545 rYRelPos = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble();
549 if ( !sFullScreenProgressSize.isEmpty() )
551 sal_Int32 idx = 0;
552 double temp = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble();
553 if ( idx != -1 )
555 rRelWidth = temp;
556 rRelHeight = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble();
561 else
562 break;
566 void SplashScreen::Paint( const Rectangle&)
568 if(!_bVisible) return;
570 //native drawing
571 sal_Bool bNativeOK = sal_False;
573 // in case of native controls we need to draw directly to the window
574 if( _bNativeProgress && IsNativeControlSupported( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL ) )
576 DrawBitmapEx( Point(), _aIntroBmp );
578 ImplControlValue aValue( _iProgress * _barwidth / _iMax);
579 Rectangle aDrawRect( Point(_tlx, _tly), Size( _barwidth, _barheight ) );
580 Rectangle aNativeControlRegion, aNativeContentRegion;
582 if( GetNativeControlRegion( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect,
583 CTRL_STATE_ENABLED, aValue, OUString(),
584 aNativeControlRegion, aNativeContentRegion ) )
586 long nProgressHeight = aNativeControlRegion.GetHeight();
587 aDrawRect.Top() -= (nProgressHeight - _barheight)/2;
588 aDrawRect.Bottom() += (nProgressHeight - _barheight)/2;
591 if( (bNativeOK = DrawNativeControl( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect,
592 CTRL_STATE_ENABLED, aValue, _sProgressText )) != sal_False )
594 return;
597 //non native drawing
598 // draw bitmap
599 if (_bPaintBitmap)
600 _vdev.DrawBitmapEx( Point(), _aIntroBmp );
602 if (_bPaintProgress) {
603 // draw progress...
604 long length = (_iProgress * _barwidth / _iMax) - (2 * _barspace);
605 if (length < 0) length = 0;
607 // border
608 _vdev.SetFillColor();
609 _vdev.SetLineColor( _cProgressFrameColor );
610 _vdev.DrawRect(Rectangle(_tlx, _tly, _tlx+_barwidth, _tly+_barheight));
611 _vdev.SetFillColor( _cProgressBarColor );
612 _vdev.SetLineColor();
613 _vdev.DrawRect(Rectangle(_tlx+_barspace, _tly+_barspace, _tlx+_barspace+length, _tly+_barheight-_barspace));
614 Font aFont;
615 aFont.SetSize(Size(0, 12));
616 aFont.SetAlign(ALIGN_BASELINE);
617 _vdev.SetFont(aFont);
618 _vdev.SetTextColor(_cProgressTextColor);
619 _vdev.DrawText(Point(_tlx, _textBaseline), _sProgressText);
621 DrawOutDev(Point(), GetOutputSizePixel(), Point(), _vdev.GetOutputSizePixel(), _vdev );
625 // get service instance...
626 osl::Mutex SplashScreen::_aMutex;
630 css::uno::Reference< css::uno::XInterface > desktop::splash::create(
631 css::uno::Reference< css::uno::XComponentContext > const &)
633 return static_cast< cppu::OWeakObject * >(new SplashScreen);
636 OUString desktop::splash::getImplementationName() {
637 return OUString("com.sun.star.office.comp.SplashScreen");
640 css::uno::Sequence< OUString > desktop::splash::getSupportedServiceNames() {
641 OUString name("com.sun.star.office.SplashScreen");
642 return css::uno::Sequence< OUString >(&name, 1);
645 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */