Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / desktop / source / splash / splash.cxx
blobf3146b2b57822195308761a44bac16bbf0b7f864
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 <sal/log.hxx>
22 #include <vcl/bitmapex.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/salnativewidgets.hxx>
26 #include <com/sun/star/lang/XInitialization.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/task/XStatusIndicator.hpp>
29 #include <comphelper/string.hxx>
30 #include <cppuhelper/implbase.hxx>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <rtl/bootstrap.hxx>
33 #include <rtl/strbuf.hxx>
34 #include <rtl/math.hxx>
35 #include <vcl/introwin.hxx>
36 #include <vcl/virdev.hxx>
37 #include <o3tl/string_view.hxx>
39 #include <mutex>
41 #define NOT_LOADED (tools::Long(-1))
42 #define NOT_LOADED_COLOR (Color(ColorTransparency, 0xffffffff))
44 using namespace ::com::sun::star::lang;
45 using namespace ::com::sun::star::task;
46 using namespace ::com::sun::star::uno;
48 namespace {
50 class SplashScreen;
52 class SplashScreenWindow : public IntroWindow
54 public:
55 SplashScreen *pSpl;
56 ScopedVclPtr<VirtualDevice> _vdev;
57 explicit SplashScreenWindow(SplashScreen *);
58 virtual ~SplashScreenWindow() override { disposeOnce(); }
59 virtual void dispose() override;
60 // workwindow
61 virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override;
62 void Redraw();
66 class SplashScreen
67 : public ::cppu::WeakImplHelper< XStatusIndicator, XInitialization, XServiceInfo >
69 friend class SplashScreenWindow;
70 private:
71 VclPtr<SplashScreenWindow> pWindow;
73 DECL_LINK( AppEventListenerHdl, VclSimpleEvent&, void );
74 virtual ~SplashScreen() override;
75 void loadConfig();
76 void updateStatus();
77 void SetScreenBitmap(BitmapEx &rBitmap);
78 static void determineProgressRatioValues( double& rXRelPos, double& rYRelPos, double& rRelWidth, double& rRelHeight );
80 BitmapEx _aIntroBmp;
81 Color _cProgressFrameColor;
82 Color _cProgressBarColor;
83 Color _cProgressTextColor;
84 bool _bNativeProgress;
85 OUString _sAppName;
86 OUString _sProgressText;
88 sal_Int32 _iMax;
89 sal_Int32 _iProgress;
90 bool _bPaintProgress;
91 bool _bVisible;
92 bool _bShowLogo;
93 bool _bFullScreenSplash;
94 bool _bProgressEnd;
95 tools::Long _height, _width, _tlx, _tly, _barwidth;
96 tools::Long _barheight, _barspace, _textBaseline;
97 double _fXPos, _fYPos;
98 double _fWidth, _fHeight;
99 static constexpr tools::Long _xoffset = 12, _yoffset = 18;
101 public:
102 SplashScreen();
104 // XStatusIndicator
105 virtual void SAL_CALL end() override;
106 virtual void SAL_CALL reset() override;
107 virtual void SAL_CALL setText(const OUString& aText) override;
108 virtual void SAL_CALL setValue(sal_Int32 nValue) override;
109 virtual void SAL_CALL start(const OUString& aText, sal_Int32 nRange) override;
111 // XInitialize
112 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any>& aArguments ) override;
114 virtual OUString SAL_CALL getImplementationName() override
115 { return "com.sun.star.office.comp.SplashScreen"; }
117 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
118 { return cppu::supportsService(this, ServiceName); }
120 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
121 { return { "com.sun.star.office.SplashScreen" }; }
124 SplashScreenWindow::SplashScreenWindow(SplashScreen *pSplash)
125 : pSpl( pSplash )
126 , _vdev(VclPtr<VirtualDevice>::Create(*GetOutDev()))
128 _vdev->EnableRTL(IsRTLEnabled());
131 void SplashScreenWindow::dispose()
133 pSpl = nullptr;
134 IntroWindow::dispose();
137 void SplashScreenWindow::Redraw()
139 Invalidate();
140 // Trigger direct painting too - otherwise the splash screen won't be
141 // shown in some cases (when the idle timer won't be hit).
142 Paint(*GetOutDev(), tools::Rectangle());
143 GetOutDev()->Flush();
146 SplashScreen::SplashScreen()
147 : pWindow( VclPtr<SplashScreenWindow>::Create(this) )
148 , _cProgressFrameColor(NOT_LOADED_COLOR)
149 , _cProgressBarColor(NOT_LOADED_COLOR)
150 , _cProgressTextColor(NOT_LOADED_COLOR)
151 , _bNativeProgress(true)
152 , _iMax(100)
153 , _iProgress(0)
154 , _bPaintProgress(false)
155 , _bVisible(true)
156 , _bShowLogo(true)
157 , _bFullScreenSplash(false)
158 , _bProgressEnd(false)
159 , _height(0)
160 , _width(0)
161 , _tlx(NOT_LOADED)
162 , _tly(NOT_LOADED)
163 , _barwidth(NOT_LOADED)
164 , _barheight(NOT_LOADED)
165 , _barspace(2)
166 , _textBaseline(NOT_LOADED)
167 , _fXPos(-1.0)
168 , _fYPos(-1.0)
169 , _fWidth(-1.0)
170 , _fHeight(-1.0)
172 loadConfig();
175 SplashScreen::~SplashScreen()
177 Application::RemoveEventListener(
178 LINK( this, SplashScreen, AppEventListenerHdl ) );
179 pWindow->Hide();
180 pWindow.disposeAndClear();
183 void SAL_CALL SplashScreen::start(const OUString&, sal_Int32 nRange)
185 _iMax = nRange;
186 if (_bVisible) {
187 _bProgressEnd = false;
188 SolarMutexGuard aSolarGuard;
189 pWindow->Show();
190 pWindow->Redraw();
194 void SAL_CALL SplashScreen::end()
196 _iProgress = _iMax;
197 if (_bVisible )
199 pWindow->Hide();
201 _bProgressEnd = true;
204 void SAL_CALL SplashScreen::reset()
206 _iProgress = 0;
207 if (_bVisible && !_bProgressEnd )
209 pWindow->Show();
210 updateStatus();
214 void SAL_CALL SplashScreen::setText(const OUString& rText)
216 SolarMutexGuard aSolarGuard;
217 if ( _sProgressText != rText )
219 _sProgressText = rText;
221 if (_bVisible && !_bProgressEnd)
223 pWindow->Show();
224 updateStatus();
229 void SAL_CALL SplashScreen::setValue(sal_Int32 nValue)
231 SAL_INFO( "desktop.splash", "setValue: " << nValue );
233 SolarMutexGuard aSolarGuard;
234 if (_bVisible && !_bProgressEnd) {
235 pWindow->Show();
236 if (nValue >= _iMax)
237 _iProgress = _iMax;
238 else
239 _iProgress = nValue;
240 updateStatus();
244 // XInitialize
245 void SAL_CALL
246 SplashScreen::initialize( const css::uno::Sequence< css::uno::Any>& aArguments )
248 static std::mutex aMutex;
249 std::lock_guard aGuard( aMutex );
250 if (!aArguments.hasElements())
251 return;
253 aArguments[0] >>= _bVisible;
254 if (aArguments.getLength() > 1 )
255 aArguments[1] >>= _sAppName;
257 // start to determine bitmap and all other required value
258 if ( _bShowLogo )
259 SetScreenBitmap (_aIntroBmp);
260 Size aSize = _aIntroBmp.GetSizePixel();
261 pWindow->SetOutputSizePixel( aSize );
262 pWindow->_vdev->SetOutputSizePixel( aSize );
263 _height = aSize.Height();
264 _width = aSize.Width();
265 if (_width > 500)
267 Point xtopleft(212,216);
268 if ( NOT_LOADED == _tlx || NOT_LOADED == _tly )
270 _tlx = xtopleft.X(); // top-left x
271 _tly = xtopleft.Y(); // top-left y
273 if ( NOT_LOADED == _barwidth )
274 _barwidth = 263;
275 if ( NOT_LOADED == _barheight )
276 _barheight = 8;
278 else
280 if ( NOT_LOADED == _barwidth )
281 _barwidth = _width - (2 * _xoffset);
282 if ( NOT_LOADED == _barheight )
283 _barheight = 6;
284 if ( NOT_LOADED == _tlx || NOT_LOADED == _tly )
286 _tlx = _xoffset; // top-left x
287 _tly = _height - _yoffset; // top-left y
291 if ( NOT_LOADED == _textBaseline )
292 _textBaseline = _height;
294 if ( NOT_LOADED_COLOR == _cProgressFrameColor )
295 _cProgressFrameColor = COL_LIGHTGRAY;
297 if ( NOT_LOADED_COLOR == _cProgressBarColor )
299 // progress bar: new color only for big bitmap format
300 if ( _width > 500 )
301 _cProgressBarColor = Color( 157, 202, 18 );
302 else
303 _cProgressBarColor = COL_BLUE;
306 if ( NOT_LOADED_COLOR == _cProgressTextColor )
307 _cProgressTextColor = COL_BLACK;
309 Application::AddEventListener(
310 LINK( this, SplashScreen, AppEventListenerHdl ) );
313 void SplashScreen::updateStatus()
315 if (!_bVisible || _bProgressEnd)
316 return;
317 if (!_bPaintProgress)
318 _bPaintProgress = true;
319 pWindow->Redraw();
322 // internal private methods
323 IMPL_LINK( SplashScreen, AppEventListenerHdl, VclSimpleEvent&, inEvent, void )
325 if (static_cast<VclWindowEvent&>(inEvent).GetWindow() == pWindow)
327 switch ( inEvent.GetId() )
329 case VclEventId::WindowShow:
330 pWindow->Redraw();
331 break;
332 default:
333 break;
338 // Read keys from soffice{.ini|rc}:
339 OUString implReadBootstrapKey( const OUString& _rKey )
341 OUString sValue;
342 rtl::Bootstrap::get(_rKey, sValue);
343 return sValue;
346 void SplashScreen::loadConfig()
348 _bShowLogo = implReadBootstrapKey( "Logo" ) != "0";
350 OUString sProgressFrameColor = implReadBootstrapKey( "ProgressFrameColor" );
351 OUString sProgressBarColor = implReadBootstrapKey( "ProgressBarColor" );
352 OUString sProgressTextColor = implReadBootstrapKey( "ProgressTextColor" );
353 OUString sProgressTextBaseline = implReadBootstrapKey( "ProgressTextBaseline" );
354 OUString sSize = implReadBootstrapKey( "ProgressSize" );
355 OUString sPosition = implReadBootstrapKey( "ProgressPosition" );
356 OUString sFullScreenSplash = implReadBootstrapKey( "FullScreenSplash" );
357 OUString sNativeProgress = implReadBootstrapKey( "NativeProgress" );
360 // Determine full screen splash mode
361 _bFullScreenSplash = (( !sFullScreenSplash.isEmpty() ) &&
362 ( sFullScreenSplash != "0" ));
364 // Try to retrieve the relative values for the progress bar. The current
365 // schema uses the screen ratio to retrieve the associated values.
366 if ( _bFullScreenSplash )
367 determineProgressRatioValues( _fXPos, _fYPos, _fWidth, _fHeight );
369 if ( !sProgressFrameColor.isEmpty() )
371 sal_uInt8 nRed = 0;
372 sal_Int32 idx = 0;
373 sal_Int32 temp = o3tl::toInt32(o3tl::getToken(sProgressFrameColor, 0, ',', idx ));
374 if ( idx != -1 )
376 nRed = static_cast< sal_uInt8 >( temp );
377 temp = o3tl::toInt32(o3tl::getToken(sProgressFrameColor, 0, ',', idx ));
379 if ( idx != -1 )
381 sal_uInt8 nGreen = static_cast< sal_uInt8 >( temp );
382 sal_uInt8 nBlue = static_cast< sal_uInt8 >( o3tl::toInt32(o3tl::getToken(sProgressFrameColor, 0, ',', idx )) );
383 _cProgressFrameColor = Color( nRed, nGreen, nBlue );
387 if ( !sProgressBarColor.isEmpty() )
389 sal_uInt8 nRed = 0;
390 sal_Int32 idx = 0;
391 sal_Int32 temp = o3tl::toInt32(o3tl::getToken(sProgressBarColor, 0, ',', idx ));
392 if ( idx != -1 )
394 nRed = static_cast< sal_uInt8 >( temp );
395 temp = o3tl::toInt32(o3tl::getToken(sProgressBarColor, 0, ',', idx ));
397 if ( idx != -1 )
399 sal_uInt8 nGreen = static_cast< sal_uInt8 >( temp );
400 sal_uInt8 nBlue = static_cast< sal_uInt8 >( o3tl::toInt32(o3tl::getToken(sProgressBarColor, 0, ',', idx )) );
401 _cProgressBarColor = Color( nRed, nGreen, nBlue );
405 if ( !sProgressTextColor.isEmpty() )
407 sal_uInt8 nRed = 0;
408 sal_Int32 idx = 0;
409 sal_Int32 temp = o3tl::toInt32(o3tl::getToken(sProgressTextColor, 0, ',', idx ));
410 if ( idx != -1 )
412 nRed = static_cast< sal_uInt8 >( temp );
413 temp = o3tl::toInt32(o3tl::getToken(sProgressTextColor, 0, ',', idx ));
415 if ( idx != -1 )
417 sal_uInt8 nGreen = static_cast< sal_uInt8 >( temp );
418 sal_uInt8 nBlue = static_cast< sal_uInt8 >( o3tl::toInt32(o3tl::getToken(sProgressTextColor, 0, ',', idx )) );
419 _cProgressTextColor = Color( nRed, nGreen, nBlue );
423 if ( !sProgressTextBaseline.isEmpty() )
425 _textBaseline = sProgressTextBaseline.toInt32();
428 if( !sNativeProgress.isEmpty() )
430 _bNativeProgress = sNativeProgress.toBoolean();
433 if ( !sSize.isEmpty() )
435 sal_Int32 idx = 0;
436 sal_Int32 temp = o3tl::toInt32(o3tl::getToken(sSize, 0, ',', idx ));
437 if ( idx != -1 )
439 _barwidth = temp;
440 _barheight = o3tl::toInt32(o3tl::getToken(sSize, 0, ',', idx ));
444 if ( _barheight >= 10 )
445 _barspace = 3; // more space between frame and bar
447 if ( !sPosition.isEmpty() )
449 sal_Int32 idx = 0;
450 sal_Int32 temp = o3tl::toInt32(o3tl::getToken(sPosition, 0, ',', idx ));
451 if ( idx != -1 )
453 _tlx = temp;
454 _tly = o3tl::toInt32(o3tl::getToken(sPosition, 0, ',', idx ));
459 void SplashScreen::SetScreenBitmap(BitmapEx &rBitmap)
461 sal_Int32 nWidth( 0 );
462 sal_Int32 nHeight( 0 );
464 // determine desktop resolution
465 sal_uInt32 nCount = Application::GetScreenCount();
466 if ( nCount > 0 )
468 // retrieve size from first screen
469 tools::Rectangle aScreenArea = Application::GetScreenPosSizePixel(static_cast<unsigned int>(0));
470 nWidth = aScreenArea.GetWidth();
471 nHeight = aScreenArea.GetHeight();
474 // create file name from screen resolution information
475 OUString aResBuf = "_" + OUString::number(nWidth) + "x" + OUString::number(nHeight);
476 if ( !_sAppName.isEmpty() )
477 if (Application::LoadBrandBitmap(Concat2View("intro_" + _sAppName + aResBuf), rBitmap))
478 return;
480 if (Application::LoadBrandBitmap(Concat2View("intro" + aResBuf), rBitmap))
481 return;
483 (void)Application::LoadBrandBitmap (u"intro", rBitmap);
486 void SplashScreen::determineProgressRatioValues(
487 double& rXRelPos, double& rYRelPos,
488 double& rRelWidth, double& rRelHeight )
490 sal_Int32 nScreenRatio( 0 );
492 // determine desktop resolution
493 sal_uInt32 nCount = Application::GetScreenCount();
494 if ( nCount > 0 )
496 // retrieve size from first screen
497 tools::Rectangle aScreenArea = Application::GetScreenPosSizePixel(static_cast<unsigned int>(0));
498 sal_Int32 nWidth = aScreenArea.GetWidth();
499 sal_Int32 nHeight = aScreenArea.GetHeight();
500 nScreenRatio = nHeight ? sal_Int32( rtl::math::round( double( nWidth ) / double( nHeight ), 2 ) * 100 ) : 0;
503 char szFullScreenProgressRatio[] = "FullScreenProgressRatio0";
504 char szFullScreenProgressPos[] = "FullScreenProgressPos0";
505 char szFullScreenProgressSize[] = "FullScreenProgressSize0";
506 for ( sal_Int32 i = 0; i <= 9; i++ )
508 char cNum = '0' + char( i );
509 szFullScreenProgressRatio[23] = cNum;
510 szFullScreenProgressPos[21] = cNum;
511 szFullScreenProgressSize[22] = cNum;
513 OUString sFullScreenProgressRatio = implReadBootstrapKey(
514 OUString::createFromAscii( szFullScreenProgressRatio ) );
516 if ( !sFullScreenProgressRatio.isEmpty() )
518 double fRatio = sFullScreenProgressRatio.toDouble();
519 sal_Int32 nRatio = sal_Int32( rtl::math::round( fRatio, 2 ) * 100 );
520 if ( nRatio == nScreenRatio )
522 OUString sFullScreenProgressPos = implReadBootstrapKey(
523 OUString::createFromAscii( szFullScreenProgressPos ) );
524 OUString sFullScreenProgressSize = implReadBootstrapKey(
525 OUString::createFromAscii( szFullScreenProgressSize ) );
527 if ( !sFullScreenProgressPos.isEmpty() )
529 sal_Int32 idx = 0;
530 double temp = o3tl::toDouble(o3tl::getToken(sFullScreenProgressPos, 0, ',', idx ));
531 if ( idx != -1 )
533 rXRelPos = temp;
534 rYRelPos = o3tl::toDouble(o3tl::getToken(sFullScreenProgressPos, 0, ',', idx ));
538 if ( !sFullScreenProgressSize.isEmpty() )
540 sal_Int32 idx = 0;
541 double temp = o3tl::toDouble(o3tl::getToken(sFullScreenProgressSize, 0, ',', idx ));
542 if ( idx != -1 )
544 rRelWidth = temp;
545 rRelHeight = o3tl::toDouble(o3tl::getToken(sFullScreenProgressSize, 0, ',', idx ));
550 else
551 break;
555 void SplashScreenWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
557 if (!pSpl || !pSpl->_bVisible)
558 return;
560 //native drawing
561 // in case of native controls we need to draw directly to the window
562 if (pSpl->_bNativeProgress && rRenderContext.IsNativeControlSupported(ControlType::IntroProgress, ControlPart::Entire))
564 rRenderContext.DrawBitmapEx(Point(), pSpl->_aIntroBmp);
566 ImplControlValue aValue( pSpl->_iProgress * pSpl->_barwidth / pSpl->_iMax);
567 tools::Rectangle aDrawRect( Point(pSpl->_tlx, pSpl->_tly), Size( pSpl->_barwidth, pSpl->_barheight));
568 tools::Rectangle aNativeControlRegion, aNativeContentRegion;
570 if (rRenderContext.GetNativeControlRegion(ControlType::IntroProgress, ControlPart::Entire, aDrawRect,
571 ControlState::ENABLED, aValue,
572 aNativeControlRegion, aNativeContentRegion))
574 tools::Long nProgressHeight = aNativeControlRegion.GetHeight();
575 aDrawRect.AdjustTop( -((nProgressHeight - pSpl->_barheight)/2) );
576 aDrawRect.AdjustBottom((nProgressHeight - pSpl->_barheight)/2 );
579 if (rRenderContext.DrawNativeControl(ControlType::IntroProgress, ControlPart::Entire, aDrawRect,
580 ControlState::ENABLED, aValue, pSpl->_sProgressText))
582 return;
586 // non native drawing
587 // draw bitmap
588 _vdev->DrawBitmapEx(Point(), pSpl->_aIntroBmp);
590 if (pSpl->_bPaintProgress) {
591 // draw progress...
592 tools::Long length = (pSpl->_iProgress * pSpl->_barwidth / pSpl->_iMax) - (2 * pSpl->_barspace);
593 if (length < 0) length = 0;
595 // border
596 _vdev->SetFillColor();
597 _vdev->SetLineColor( pSpl->_cProgressFrameColor );
598 _vdev->DrawRect(tools::Rectangle(pSpl->_tlx, pSpl->_tly, pSpl->_tlx+pSpl->_barwidth, pSpl->_tly+pSpl->_barheight));
599 _vdev->SetFillColor( pSpl->_cProgressBarColor );
600 _vdev->SetLineColor();
601 _vdev->DrawRect(tools::Rectangle(pSpl->_tlx+pSpl->_barspace, pSpl->_tly+pSpl->_barspace, pSpl->_tlx+pSpl->_barspace+length, pSpl->_tly+pSpl->_barheight-pSpl->_barspace));
602 vcl::Font aFont;
603 aFont.SetFontSize(Size(0, 12));
604 aFont.SetAlignment(ALIGN_BASELINE);
605 _vdev->SetFont(aFont);
606 _vdev->SetTextColor(pSpl->_cProgressTextColor);
607 _vdev->DrawText(Point(pSpl->_tlx, pSpl->_textBaseline), pSpl->_sProgressText);
609 rRenderContext.DrawOutDev(Point(), GetOutputSizePixel(), Point(), _vdev->GetOutputSizePixel(), *_vdev);
614 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
615 desktop_SplashScreen_get_implementation(
616 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
618 return cppu::acquire(new SplashScreen());
622 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */