1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
23 #include <sal/log.hxx>
24 #include <unotools/bootstrap.hxx>
25 #include <tools/stream.hxx>
26 #include <vcl/bitmapex.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/salnativewidgets.hxx>
30 #include <com/sun/star/lang/XInitialization.hpp>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <com/sun/star/registry/XRegistryKey.hpp>
33 #include <com/sun/star/task/XStatusIndicator.hpp>
34 #include <cppuhelper/implbase.hxx>
35 #include <cppuhelper/supportsservice.hxx>
36 #include <rtl/bootstrap.hxx>
37 #include <rtl/strbuf.hxx>
38 #include <rtl/math.hxx>
39 #include <vcl/introwin.hxx>
40 #include <vcl/virdev.hxx>
42 #define NOT_LOADED (long(-1))
43 #define NOT_LOADED_COLOR (Color(0xffffffff))
45 using namespace ::com::sun::star::lang
;
46 using namespace ::com::sun::star::registry
;
47 using namespace ::com::sun::star::task
;
48 using namespace ::com::sun::star::uno
;
54 class SplashScreenWindow
: public IntroWindow
58 ScopedVclPtr
<VirtualDevice
> _vdev
;
59 explicit SplashScreenWindow(SplashScreen
*);
60 virtual ~SplashScreenWindow() override
{ disposeOnce(); }
61 virtual void dispose() override
;
63 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&) override
;
69 : public ::cppu::WeakImplHelper
< XStatusIndicator
, XInitialization
, XServiceInfo
>
71 friend class SplashScreenWindow
;
73 VclPtr
<SplashScreenWindow
> pWindow
;
75 DECL_LINK( AppEventListenerHdl
, VclSimpleEvent
&, void );
76 virtual ~SplashScreen() override
;
79 void SetScreenBitmap(BitmapEx
&rBitmap
);
80 static void determineProgressRatioValues( double& rXRelPos
, double& rYRelPos
, double& rRelWidth
, double& rRelHeight
);
82 static osl::Mutex _aMutex
;
85 Color _cProgressFrameColor
;
86 Color _cProgressBarColor
;
87 Color _cProgressTextColor
;
88 bool _bNativeProgress
;
90 OUString _sProgressText
;
97 bool _bFullScreenSplash
;
99 long _height
, _width
, _tlx
, _tly
, _barwidth
;
100 long _barheight
, _barspace
, _textBaseline
;
101 double _fXPos
, _fYPos
;
102 double _fWidth
, _fHeight
;
103 static constexpr long _xoffset
= 12, _yoffset
= 18;
109 virtual void SAL_CALL
end() override
;
110 virtual void SAL_CALL
reset() override
;
111 virtual void SAL_CALL
setText(const OUString
& aText
) override
;
112 virtual void SAL_CALL
setValue(sal_Int32 nValue
) override
;
113 virtual void SAL_CALL
start(const OUString
& aText
, sal_Int32 nRange
) override
;
116 virtual void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
) override
;
118 virtual OUString SAL_CALL
getImplementationName() override
119 { return desktop::splash::getImplementationName(); }
121 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
122 { return cppu::supportsService(this, ServiceName
); }
124 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
125 { return desktop::splash::getSupportedServiceNames(); }
128 SplashScreenWindow::SplashScreenWindow(SplashScreen
*pSplash
)
131 , _vdev(VclPtr
<VirtualDevice
>::Create(*this))
133 _vdev
->EnableRTL(IsRTLEnabled());
136 void SplashScreenWindow::dispose()
139 IntroWindow::dispose();
142 void SplashScreenWindow::Redraw()
145 // Trigger direct painting too - otherwise the splash screen won't be
146 // shown in some cases (when the idle timer won't be hit).
147 Paint(*this, tools::Rectangle());
151 SplashScreen::SplashScreen()
152 : pWindow( VclPtr
<SplashScreenWindow
>::Create(this) )
153 , _cProgressFrameColor(NOT_LOADED_COLOR
)
154 , _cProgressBarColor(NOT_LOADED_COLOR
)
155 , _cProgressTextColor(NOT_LOADED_COLOR
)
156 , _bNativeProgress(true)
159 , _bPaintProgress(false)
162 , _bFullScreenSplash(false)
163 , _bProgressEnd(false)
168 , _barwidth(NOT_LOADED
)
169 , _barheight(NOT_LOADED
)
171 , _textBaseline(NOT_LOADED
)
180 SplashScreen::~SplashScreen()
182 Application::RemoveEventListener(
183 LINK( this, SplashScreen
, AppEventListenerHdl
) );
185 pWindow
.disposeAndClear();
188 void SAL_CALL
SplashScreen::start(const OUString
&, sal_Int32 nRange
)
192 _bProgressEnd
= false;
193 SolarMutexGuard aSolarGuard
;
199 void SAL_CALL
SplashScreen::end()
206 _bProgressEnd
= true;
209 void SAL_CALL
SplashScreen::reset()
212 if (_bVisible
&& !_bProgressEnd
)
219 void SAL_CALL
SplashScreen::setText(const OUString
& rText
)
221 SolarMutexGuard aSolarGuard
;
222 if ( _sProgressText
!= rText
)
224 _sProgressText
= rText
;
226 if (_bVisible
&& !_bProgressEnd
)
234 void SAL_CALL
SplashScreen::setValue(sal_Int32 nValue
)
236 SAL_INFO( "desktop.splash", "setValue: " << nValue
);
238 SolarMutexGuard aSolarGuard
;
239 if (_bVisible
&& !_bProgressEnd
) {
251 SplashScreen::initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
)
253 osl::MutexGuard
aGuard( _aMutex
);
254 if (aArguments
.hasElements())
256 aArguments
[0] >>= _bVisible
;
257 if (aArguments
.getLength() > 1 )
258 aArguments
[1] >>= _sAppName
;
260 // start to determine bitmap and all other required value
262 SetScreenBitmap (_aIntroBmp
);
263 Size aSize
= _aIntroBmp
.GetSizePixel();
264 pWindow
->SetOutputSizePixel( aSize
);
265 pWindow
->_vdev
->SetOutputSizePixel( aSize
);
266 _height
= aSize
.Height();
267 _width
= aSize
.Width();
270 Point
xtopleft(212,216);
271 if ( NOT_LOADED
== _tlx
|| NOT_LOADED
== _tly
)
273 _tlx
= xtopleft
.X(); // top-left x
274 _tly
= xtopleft
.Y(); // top-left y
276 if ( NOT_LOADED
== _barwidth
)
278 if ( NOT_LOADED
== _barheight
)
283 if ( NOT_LOADED
== _barwidth
)
284 _barwidth
= _width
- (2 * _xoffset
);
285 if ( NOT_LOADED
== _barheight
)
287 if ( NOT_LOADED
== _tlx
|| NOT_LOADED
== _tly
)
289 _tlx
= _xoffset
; // top-left x
290 _tly
= _height
- _yoffset
; // top-left y
294 if ( NOT_LOADED
== _textBaseline
)
295 _textBaseline
= _height
;
297 if ( NOT_LOADED_COLOR
== _cProgressFrameColor
)
298 _cProgressFrameColor
= COL_LIGHTGRAY
;
300 if ( NOT_LOADED_COLOR
== _cProgressBarColor
)
302 // progress bar: new color only for big bitmap format
304 _cProgressBarColor
= Color( 157, 202, 18 );
306 _cProgressBarColor
= COL_BLUE
;
309 if ( NOT_LOADED_COLOR
== _cProgressTextColor
)
310 _cProgressTextColor
= COL_BLACK
;
312 Application::AddEventListener(
313 LINK( this, SplashScreen
, AppEventListenerHdl
) );
317 void SplashScreen::updateStatus()
319 if (!_bVisible
|| _bProgressEnd
)
321 if (!_bPaintProgress
)
322 _bPaintProgress
= true;
326 // internal private methods
327 IMPL_LINK( SplashScreen
, AppEventListenerHdl
, VclSimpleEvent
&, inEvent
, void )
329 if (static_cast<VclWindowEvent
&>(inEvent
).GetWindow() == pWindow
)
331 switch ( inEvent
.GetId() )
333 case VclEventId::WindowShow
:
342 // Read keys from soffice{.ini|rc}:
343 OUString
implReadBootstrapKey( const OUString
& _rKey
)
346 rtl::Bootstrap::get(_rKey
, sValue
);
350 void SplashScreen::loadConfig()
352 _bShowLogo
= implReadBootstrapKey( "Logo" ) != "0";
354 OUString sProgressFrameColor
= implReadBootstrapKey( "ProgressFrameColor" );
355 OUString sProgressBarColor
= implReadBootstrapKey( "ProgressBarColor" );
356 OUString sProgressTextColor
= implReadBootstrapKey( "ProgressTextColor" );
357 OUString sProgressTextBaseline
= implReadBootstrapKey( "ProgressTextBaseline" );
358 OUString sSize
= implReadBootstrapKey( "ProgressSize" );
359 OUString sPosition
= implReadBootstrapKey( "ProgressPosition" );
360 OUString sFullScreenSplash
= implReadBootstrapKey( "FullScreenSplash" );
361 OUString sNativeProgress
= implReadBootstrapKey( "NativeProgress" );
364 // Determine full screen splash mode
365 _bFullScreenSplash
= (( !sFullScreenSplash
.isEmpty() ) &&
366 ( sFullScreenSplash
!= "0" ));
368 // Try to retrieve the relative values for the progress bar. The current
369 // schema uses the screen ratio to retrieve the associated values.
370 if ( _bFullScreenSplash
)
371 determineProgressRatioValues( _fXPos
, _fYPos
, _fWidth
, _fHeight
);
373 if ( !sProgressFrameColor
.isEmpty() )
377 sal_Int32 temp
= sProgressFrameColor
.getToken( 0, ',', idx
).toInt32();
380 nRed
= static_cast< sal_uInt8
>( temp
);
381 temp
= sProgressFrameColor
.getToken( 0, ',', idx
).toInt32();
385 sal_uInt8 nGreen
= static_cast< sal_uInt8
>( temp
);
386 sal_uInt8 nBlue
= static_cast< sal_uInt8
>( sProgressFrameColor
.getToken( 0, ',', idx
).toInt32() );
387 _cProgressFrameColor
= Color( nRed
, nGreen
, nBlue
);
391 if ( !sProgressBarColor
.isEmpty() )
395 sal_Int32 temp
= sProgressBarColor
.getToken( 0, ',', idx
).toInt32();
398 nRed
= static_cast< sal_uInt8
>( temp
);
399 temp
= sProgressBarColor
.getToken( 0, ',', idx
).toInt32();
403 sal_uInt8 nGreen
= static_cast< sal_uInt8
>( temp
);
404 sal_uInt8 nBlue
= static_cast< sal_uInt8
>( sProgressBarColor
.getToken( 0, ',', idx
).toInt32() );
405 _cProgressBarColor
= Color( nRed
, nGreen
, nBlue
);
409 if ( !sProgressTextColor
.isEmpty() )
413 sal_Int32 temp
= sProgressTextColor
.getToken( 0, ',', idx
).toInt32();
416 nRed
= static_cast< sal_uInt8
>( temp
);
417 temp
= sProgressTextColor
.getToken( 0, ',', idx
).toInt32();
421 sal_uInt8 nGreen
= static_cast< sal_uInt8
>( temp
);
422 sal_uInt8 nBlue
= static_cast< sal_uInt8
>( sProgressTextColor
.getToken( 0, ',', idx
).toInt32() );
423 _cProgressTextColor
= Color( nRed
, nGreen
, nBlue
);
427 if ( !sProgressTextBaseline
.isEmpty() )
429 _textBaseline
= sProgressTextBaseline
.toInt32();
432 if( !sNativeProgress
.isEmpty() )
434 _bNativeProgress
= sNativeProgress
.toBoolean();
437 if ( !sSize
.isEmpty() )
440 sal_Int32 temp
= sSize
.getToken( 0, ',', idx
).toInt32();
444 _barheight
= sSize
.getToken( 0, ',', idx
).toInt32();
448 if ( _barheight
>= 10 )
449 _barspace
= 3; // more space between frame and bar
451 if ( !sPosition
.isEmpty() )
454 sal_Int32 temp
= sPosition
.getToken( 0, ',', idx
).toInt32();
458 _tly
= sPosition
.getToken( 0, ',', idx
).toInt32();
463 void SplashScreen::SetScreenBitmap(BitmapEx
&rBitmap
)
465 sal_Int32
nWidth( 0 );
466 sal_Int32
nHeight( 0 );
468 // determine desktop resolution
469 sal_uInt32 nCount
= Application::GetScreenCount();
472 // retrieve size from first screen
473 tools::Rectangle aScreenArea
= Application::GetScreenPosSizePixel(static_cast<unsigned int>(0));
474 nWidth
= aScreenArea
.GetWidth();
475 nHeight
= aScreenArea
.GetHeight();
478 // create file name from screen resolution information
479 OStringBuffer
aStrBuf( 128 );
480 aStrBuf
.append( "intro_" );
481 if ( !_sAppName
.isEmpty() )
483 aStrBuf
.append( OUStringToOString(_sAppName
, RTL_TEXTENCODING_UTF8
) );
484 aStrBuf
.append( "_" );
486 OString aResBuf
= OString::number( nWidth
) + "x" + OString::number( nHeight
);
488 aStrBuf
.append( aResBuf
.getStr() );
489 if (Application::LoadBrandBitmap (aStrBuf
.makeStringAndClear().getStr(), rBitmap
))
492 aStrBuf
.append( "intro_" );
493 aStrBuf
.append( aResBuf
.getStr() );
494 if (Application::LoadBrandBitmap (aResBuf
.getStr(), rBitmap
))
497 (void)Application::LoadBrandBitmap ("intro", rBitmap
);
500 void SplashScreen::determineProgressRatioValues(
501 double& rXRelPos
, double& rYRelPos
,
502 double& rRelWidth
, double& rRelHeight
)
504 sal_Int32
nWidth( 0 );
505 sal_Int32
nHeight( 0 );
506 sal_Int32
nScreenRatio( 0 );
508 // determine desktop resolution
509 sal_uInt32 nCount
= Application::GetScreenCount();
512 // retrieve size from first screen
513 tools::Rectangle aScreenArea
= Application::GetScreenPosSizePixel(static_cast<unsigned int>(0));
514 nWidth
= aScreenArea
.GetWidth();
515 nHeight
= aScreenArea
.GetHeight();
516 nScreenRatio
= nHeight
? sal_Int32( rtl::math::round( double( nWidth
) / double( nHeight
), 2 ) * 100 ) : 0;
519 char szFullScreenProgressRatio
[] = "FullScreenProgressRatio0";
520 char szFullScreenProgressPos
[] = "FullScreenProgressPos0";
521 char szFullScreenProgressSize
[] = "FullScreenProgressSize0";
522 for ( sal_Int32 i
= 0; i
<= 9; i
++ )
524 char cNum
= '0' + char( i
);
525 szFullScreenProgressRatio
[23] = cNum
;
526 szFullScreenProgressPos
[21] = cNum
;
527 szFullScreenProgressSize
[22] = cNum
;
529 OUString sFullScreenProgressRatio
= implReadBootstrapKey(
530 OUString::createFromAscii( szFullScreenProgressRatio
) );
532 if ( !sFullScreenProgressRatio
.isEmpty() )
534 double fRatio
= sFullScreenProgressRatio
.toDouble();
535 sal_Int32 nRatio
= sal_Int32( rtl::math::round( fRatio
, 2 ) * 100 );
536 if ( nRatio
== nScreenRatio
)
538 OUString sFullScreenProgressPos
= implReadBootstrapKey(
539 OUString::createFromAscii( szFullScreenProgressPos
) );
540 OUString sFullScreenProgressSize
= implReadBootstrapKey(
541 OUString::createFromAscii( szFullScreenProgressSize
) );
543 if ( !sFullScreenProgressPos
.isEmpty() )
546 double temp
= sFullScreenProgressPos
.getToken( 0, ',', idx
).toDouble();
550 rYRelPos
= sFullScreenProgressPos
.getToken( 0, ',', idx
).toDouble();
554 if ( !sFullScreenProgressSize
.isEmpty() )
557 double temp
= sFullScreenProgressSize
.getToken( 0, ',', idx
).toDouble();
561 rRelHeight
= sFullScreenProgressSize
.getToken( 0, ',', idx
).toDouble();
571 void SplashScreenWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
573 if (!pSpl
|| !pSpl
->_bVisible
)
577 // in case of native controls we need to draw directly to the window
578 if (pSpl
->_bNativeProgress
&& rRenderContext
.IsNativeControlSupported(ControlType::IntroProgress
, ControlPart::Entire
))
580 rRenderContext
.DrawBitmapEx(Point(), pSpl
->_aIntroBmp
);
582 ImplControlValue
aValue( pSpl
->_iProgress
* pSpl
->_barwidth
/ pSpl
->_iMax
);
583 tools::Rectangle
aDrawRect( Point(pSpl
->_tlx
, pSpl
->_tly
), Size( pSpl
->_barwidth
, pSpl
->_barheight
));
584 tools::Rectangle aNativeControlRegion
, aNativeContentRegion
;
586 if (rRenderContext
.GetNativeControlRegion(ControlType::IntroProgress
, ControlPart::Entire
, aDrawRect
,
587 ControlState::ENABLED
, aValue
,
588 aNativeControlRegion
, aNativeContentRegion
))
590 long nProgressHeight
= aNativeControlRegion
.GetHeight();
591 aDrawRect
.AdjustTop( -((nProgressHeight
- pSpl
->_barheight
)/2) );
592 aDrawRect
.AdjustBottom((nProgressHeight
- pSpl
->_barheight
)/2 );
595 if (rRenderContext
.DrawNativeControl(ControlType::IntroProgress
, ControlPart::Entire
, aDrawRect
,
596 ControlState::ENABLED
, aValue
, pSpl
->_sProgressText
))
602 // non native drawing
604 _vdev
->DrawBitmapEx(Point(), pSpl
->_aIntroBmp
);
606 if (pSpl
->_bPaintProgress
) {
608 long length
= (pSpl
->_iProgress
* pSpl
->_barwidth
/ pSpl
->_iMax
) - (2 * pSpl
->_barspace
);
609 if (length
< 0) length
= 0;
612 _vdev
->SetFillColor();
613 _vdev
->SetLineColor( pSpl
->_cProgressFrameColor
);
614 _vdev
->DrawRect(tools::Rectangle(pSpl
->_tlx
, pSpl
->_tly
, pSpl
->_tlx
+pSpl
->_barwidth
, pSpl
->_tly
+pSpl
->_barheight
));
615 _vdev
->SetFillColor( pSpl
->_cProgressBarColor
);
616 _vdev
->SetLineColor();
617 _vdev
->DrawRect(tools::Rectangle(pSpl
->_tlx
+pSpl
->_barspace
, pSpl
->_tly
+pSpl
->_barspace
, pSpl
->_tlx
+pSpl
->_barspace
+length
, pSpl
->_tly
+pSpl
->_barheight
-pSpl
->_barspace
));
619 aFont
.SetFontSize(Size(0, 12));
620 aFont
.SetAlignment(ALIGN_BASELINE
);
621 _vdev
->SetFont(aFont
);
622 _vdev
->SetTextColor(pSpl
->_cProgressTextColor
);
623 _vdev
->DrawText(Point(pSpl
->_tlx
, pSpl
->_textBaseline
), pSpl
->_sProgressText
);
625 rRenderContext
.DrawOutDev(Point(), GetOutputSizePixel(), Point(), _vdev
->GetOutputSizePixel(), *_vdev
.get());
629 // get service instance...
630 osl::Mutex
SplashScreen::_aMutex
;
634 css::uno::Reference
< css::uno::XInterface
> desktop::splash::create(
635 css::uno::Reference
< css::uno::XComponentContext
> const &)
637 return static_cast< cppu::OWeakObject
* >(new SplashScreen
);
640 OUString
desktop::splash::getImplementationName() {
641 return "com.sun.star.office.comp.SplashScreen";
644 css::uno::Sequence
< OUString
> desktop::splash::getSupportedServiceNames()
646 return { "com.sun.star.office.SplashScreen" };
649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */