/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_desktop.hxx" #include #include "splash.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NOT_LOADED ((long)-1) using namespace ::rtl; using namespace ::com::sun::star::registry; namespace desktop { SplashScreen::SplashScreen(const Reference< XMultiServiceFactory >& rSMgr) : IntroWindow() , _vdev(*((IntroWindow*)this)) , _cProgressFrameColor(sal::static_int_cast< ColorData >(NOT_LOADED)) , _bShowProgressFrame(true) , _cProgressBarColor(sal::static_int_cast< ColorData >(NOT_LOADED)) , _bNativeProgress(true) , _iMax(100) , _iProgress(0) , _eBitmapMode(BM_DEFAULTMODE) , _bPaintBitmap(sal_True) , _bPaintProgress(sal_False) , _bShowLogo(sal_True) , _bFullScreenSplash(sal_False) , _bProgressEnd(sal_False) , _tlx(NOT_LOADED) , _tly(NOT_LOADED) , _barwidth(NOT_LOADED) , _barheight(NOT_LOADED) , _barspace(2) , _fXPos(-1.0) , _fYPos(-1.0) , _fWidth(-1.0) , _fHeight(-1.0) , _xoffset(12) , _yoffset(18) { _rFactory = rSMgr; loadConfig(); } SplashScreen::~SplashScreen() { Application::RemoveEventListener( LINK( this, SplashScreen, AppEventListenerHdl ) ); Hide(); } void SAL_CALL SplashScreen::start(const OUString&, sal_Int32 nRange) throw (RuntimeException) { _iMax = nRange; if (_bVisible) { _bProgressEnd = sal_False; ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); if ( _eBitmapMode == BM_FULLSCREEN ) ShowFullScreenMode( sal_True ); Show(); Paint(Rectangle()); Flush(); } } void SAL_CALL SplashScreen::end() throw (RuntimeException) { _iProgress = _iMax; if (_bVisible ) { if ( _eBitmapMode == BM_FULLSCREEN ) EndFullScreenMode(); Hide(); } _bProgressEnd = sal_True; } void SAL_CALL SplashScreen::reset() throw (RuntimeException) { _iProgress = 0; if (_bVisible && !_bProgressEnd ) { if ( _eBitmapMode == BM_FULLSCREEN ) ShowFullScreenMode( sal_True ); Show(); updateStatus(); } } void SAL_CALL SplashScreen::setText(const OUString& rText) throw (RuntimeException) { ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); if ( _sProgressText != rText ) { _sProgressText = rText; if (_bVisible && !_bProgressEnd) { if ( _eBitmapMode == BM_FULLSCREEN ) ShowFullScreenMode( sal_True ); Show(); updateStatus(); } } } void SAL_CALL SplashScreen::setValue(sal_Int32 nValue) throw (RuntimeException) { RTL_LOGFILE_CONTEXT( aLog, "::SplashScreen::setValue (lo119109)" ); RTL_LOGFILE_CONTEXT_TRACE1( aLog, "value=%d", nValue ); ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); if (_bVisible && !_bProgressEnd) { if ( _eBitmapMode == BM_FULLSCREEN ) ShowFullScreenMode( sal_True ); Show(); if (nValue >= _iMax) _iProgress = _iMax; else _iProgress = nValue; updateStatus(); } } // XInitialize void SAL_CALL SplashScreen::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments ) throw (RuntimeException) { ::osl::ClearableMutexGuard aGuard( _aMutex ); if (aArguments.getLength() > 0) { aArguments[0] >>= _bVisible; if (aArguments.getLength() > 1 ) aArguments[1] >>= _sAppName; // start to determine bitmap and all other required value initBitmap(); Size aSize = _aIntroBmp.GetSizePixel(); SetOutputSizePixel( aSize ); _vdev.SetOutputSizePixel( aSize ); _height = aSize.Height(); _width = aSize.Width(); if (_width > 500) { Point xtopleft(212,216); if ( NOT_LOADED == _tlx || NOT_LOADED == _tly ) { _tlx = xtopleft.X(); // top-left x _tly = xtopleft.Y(); // top-left y } if ( NOT_LOADED == _barwidth ) _barwidth = 263; if ( NOT_LOADED == _barheight ) _barheight = 8; if (( _eBitmapMode == BM_FULLSCREEN ) && _bFullScreenSplash ) { if( ( _fXPos >= 0.0 ) && ( _fYPos >= 0.0 )) { _tlx = sal_Int32( double( aSize.Width() ) * _fXPos ); _tly = sal_Int32( double( aSize.Height() ) * _fYPos ); } if ( _fWidth >= 0.0 ) _barwidth = sal_Int32( double( aSize.Width() ) * _fWidth ); if ( _fHeight >= 0.0 ) _barheight = sal_Int32( double( aSize.Width() ) * _fHeight ); } } else { if ( NOT_LOADED == _barwidth ) _barwidth = _width - (2 * _xoffset); if ( NOT_LOADED == _barheight ) _barheight = 6; if ( NOT_LOADED == _tlx || NOT_LOADED == _tly ) { _tlx = _xoffset; // top-left x _tly = _height - _yoffset; // top-left y } } if ( sal::static_int_cast< ColorData >(NOT_LOADED) == _cProgressFrameColor.GetColor() ) _cProgressFrameColor = Color( COL_LIGHTGRAY ); if ( sal::static_int_cast< ColorData >(NOT_LOADED) == _cProgressBarColor.GetColor() ) { // progress bar: new color only for big bitmap format if ( _width > 500 ) _cProgressBarColor = Color( 157, 202, 18 ); else _cProgressBarColor = Color( COL_BLUE ); } Application::AddEventListener( LINK( this, SplashScreen, AppEventListenerHdl ) ); SetBackgroundBitmap( _aIntroBmp ); } } void SplashScreen::updateStatus() { if (!_bVisible || _bProgressEnd) return; if (!_bPaintProgress) _bPaintProgress = sal_True; //_bPaintBitmap=sal_False; Paint(Rectangle()); //_bPaintBitmap=sal_True; Flush(); } // internal private methods IMPL_LINK( SplashScreen, AppEventListenerHdl, VclWindowEvent *, inEvent ) { if ( inEvent != 0 ) { // Paint( Rectangle() ); switch ( inEvent->GetId() ) { case VCLEVENT_WINDOW_SHOW: Paint( Rectangle() ); break; default: break; } } return 0; } // Read keys from edition/edition.ini or soffice{.ini|rc}: OUString implReadBootstrapKey( const OUString& _rKey ) { OUString sValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "${.override:${OOO_BASE_DIR}/program/edition/edition.ini:")) + _rKey + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("}"))); rtl::Bootstrap::expandMacros(sValue); return sValue; } void SplashScreen::loadConfig() { _bShowLogo = !implReadBootstrapKey( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Logo"))). equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("0")); OUString sProgressFrameColor = implReadBootstrapKey( OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressFrameColor" ) ) ); OUString sProgressBarColor = implReadBootstrapKey( OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressBarColor" ) ) ); OUString sSize = implReadBootstrapKey( OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressSize" ) ) ); OUString sPosition = implReadBootstrapKey( OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressPosition" ) ) ); OUString sFullScreenSplash = implReadBootstrapKey( OUString( RTL_CONSTASCII_USTRINGPARAM( "FullScreenSplash" ) ) ); OUString sNativeProgress = implReadBootstrapKey( OUString( RTL_CONSTASCII_USTRINGPARAM( "NativeProgress" ) ) ); OUString sShowProgressFrame = implReadBootstrapKey( OUString( RTL_CONSTASCII_USTRINGPARAM( "ShowProgressFrame" ) ) ); // Determine full screen splash mode _bFullScreenSplash = (( sFullScreenSplash.getLength() > 0 ) && ( !sFullScreenSplash.equalsAsciiL( "0", 1 ))); // Try to retrieve the relative values for the progress bar. The current // schema uses the screen ratio to retrieve the associated values. if ( _bFullScreenSplash ) determineProgressRatioValues( _fXPos, _fYPos, _fWidth, _fHeight ); if ( sProgressFrameColor.getLength() ) { sal_uInt8 nRed = 0; sal_uInt8 nGreen = 0; sal_uInt8 nBlue = 0; sal_Int32 idx = 0; sal_Int32 temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32(); if ( idx != -1 ) { nRed = static_cast< sal_uInt8 >( temp ); temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32(); } if ( idx != -1 ) { nGreen = static_cast< sal_uInt8 >( temp ); nBlue = static_cast< sal_uInt8 >( sProgressFrameColor.getToken( 0, ',', idx ).toInt32() ); _cProgressFrameColor = Color( nRed, nGreen, nBlue ); } } if (sShowProgressFrame.getLength() > 0) { _bShowProgressFrame = sShowProgressFrame.toBoolean(); } if ( sProgressBarColor.getLength() ) { sal_uInt8 nRed = 0; sal_uInt8 nGreen = 0; sal_uInt8 nBlue = 0; sal_Int32 idx = 0; sal_Int32 temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32(); if ( idx != -1 ) { nRed = static_cast< sal_uInt8 >( temp ); temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32(); } if ( idx != -1 ) { nGreen = static_cast< sal_uInt8 >( temp ); nBlue = static_cast< sal_uInt8 >( sProgressBarColor.getToken( 0, ',', idx ).toInt32() ); _cProgressBarColor = Color( nRed, nGreen, nBlue ); } } if( sNativeProgress.getLength() ) { _bNativeProgress = sNativeProgress.toBoolean(); } if ( sSize.getLength() ) { sal_Int32 idx = 0; sal_Int32 temp = sSize.getToken( 0, ',', idx ).toInt32(); if ( idx != -1 ) { _barwidth = temp; _barheight = sSize.getToken( 0, ',', idx ).toInt32(); } } if ( _barheight >= 10 ) _barspace = 3; // more space between frame and bar if ( sPosition.getLength() ) { sal_Int32 idx = 0; sal_Int32 temp = sPosition.getToken( 0, ',', idx ).toInt32(); if ( idx != -1 ) { _tlx = temp; _tly = sPosition.getToken( 0, ',', idx ).toInt32(); } } } void SplashScreen::initBitmap() { if ( _bShowLogo ) { OUString sExecutePath; ::rtl::Bootstrap::get( OUString( RTL_CONSTASCII_USTRINGPARAM( "OOO_BASE_DIR" ) ), sExecutePath ); sExecutePath += OUString( RTL_CONSTASCII_USTRINGPARAM( "/program/" ) ); bool haveBitmap = false; // Try all bitmaps in INTRO_BITMAP_NAMES sal_Int32 nIndex = 0; OUString aIntroBitmapFiles( RTL_CONSTASCII_USTRINGPARAM( INTRO_BITMAP_STRINGLIST )); do { haveBitmap = loadBitmap( sExecutePath, aIntroBitmapFiles.getToken( 0, ',', nIndex ) ); } while ( !haveBitmap && ( nIndex >= 0 ) ); if (!haveBitmap) { rtl::OUString edition( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "${OOO_BASE_DIR}/program/edition"))); rtl::Bootstrap::expandMacros(edition); haveBitmap = findBitmap(edition); } if (!haveBitmap) { findBitmap(sExecutePath); } } } bool SplashScreen::loadBitmap( rtl::OUString const & path, const rtl::OUString &rBmpFileName ) { if ( rBmpFileName.getLength() == 0 ) return false; INetURLObject aObj( path, INET_PROT_FILE ); aObj.insertName( rBmpFileName ); SvFileStream aStrm( aObj.PathToFileName(), STREAM_STD_READ ); if ( !aStrm.GetError() ) { // Use graphic class to also support more graphic formats (bmp,png,...) Graphic aGraphic; GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); pGF->ImportGraphic( aGraphic, String(), aStrm, GRFILTER_FORMAT_DONTKNOW ); // Default case, we load the intro bitmap from a separate file // (e.g. staroffice_intro.bmp or starsuite_intro.bmp) _aIntroBmp = aGraphic.GetBitmapEx(); return true; } return false; } bool SplashScreen::findBitmap(rtl::OUString const & path) { bool haveBitmap = false; if ( _bFullScreenSplash ) { haveBitmap = findScreenBitmap(path); if ( haveBitmap ) _eBitmapMode = BM_FULLSCREEN; else haveBitmap = findAppBitmap(path); } if ( !haveBitmap ) { haveBitmap = loadBitmap( path, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("intro.png"))); if ( !haveBitmap ) haveBitmap = loadBitmap( path, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("intro.bmp"))); } return haveBitmap; } bool SplashScreen::findScreenBitmap(rtl::OUString const & path) { sal_Int32 nWidth( 0 ); sal_Int32 nHeight( 0 ); // determine desktop resolution sal_uInt32 nCount = Application::GetScreenCount(); if ( nCount > 0 ) { // retrieve size from first screen Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0); nWidth = aScreenArea.GetWidth(); nHeight = aScreenArea.GetHeight(); } // create file name from screen resolution information OUStringBuffer aStrBuf( 128 ); aStrBuf.appendAscii( "intro_" ); if ( _sAppName.getLength() > 0 ) { aStrBuf.append( _sAppName ); aStrBuf.appendAscii( "_" ); } aStrBuf.append( OUString::valueOf( nWidth )); aStrBuf.appendAscii( "x" ); aStrBuf.append( OUString::valueOf( nHeight )); OUString aRootIntroFileName = aStrBuf.makeStringAndClear(); OUString aBmpFileName = aRootIntroFileName + OUString::createFromAscii(".png"); bool haveBitmap = loadBitmap( path, aBmpFileName ); if ( !haveBitmap ) { aBmpFileName = aRootIntroFileName + OUString::createFromAscii(".bmp"); haveBitmap = loadBitmap( path, aBmpFileName ); } if ( !haveBitmap ) { aStrBuf.appendAscii( "intro_" ); aStrBuf.appendAscii( "_" ); aStrBuf.append( OUString::valueOf( nWidth )); aStrBuf.appendAscii( "x" ); aStrBuf.append( OUString::valueOf( nHeight )); aRootIntroFileName = aStrBuf.makeStringAndClear(); aBmpFileName = aRootIntroFileName + OUString::createFromAscii(".png"); haveBitmap = loadBitmap( path, aBmpFileName ); if ( !haveBitmap ) { aBmpFileName = aRootIntroFileName + OUString::createFromAscii(".bmp"); haveBitmap = loadBitmap( path, aBmpFileName ); } } return haveBitmap; } bool SplashScreen::findAppBitmap(rtl::OUString const & path) { bool haveBitmap = false; if ( _sAppName.getLength() > 0 ) { OUStringBuffer aStrBuf( 128 ); aStrBuf.appendAscii( "intro_" ); aStrBuf.appendAscii( "_" ); aStrBuf.append( _sAppName ); OUString aRootIntroFileName = aStrBuf.makeStringAndClear(); OUString aBmpFileName = aRootIntroFileName + OUString::createFromAscii( ".png" ); haveBitmap = loadBitmap( path, aBmpFileName ); if ( !haveBitmap ) { aBmpFileName = aRootIntroFileName + OUString::createFromAscii( ".bmp" ); haveBitmap = loadBitmap( path, aBmpFileName ); } } return haveBitmap; } void SplashScreen::determineProgressRatioValues( double& rXRelPos, double& rYRelPos, double& rRelWidth, double& rRelHeight ) { sal_Int32 nWidth( 0 ); sal_Int32 nHeight( 0 ); sal_Int32 nScreenRatio( 0 ); // determine desktop resolution sal_uInt32 nCount = Application::GetScreenCount(); if ( nCount > 0 ) { // retrieve size from first screen Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0); nWidth = aScreenArea.GetWidth(); nHeight = aScreenArea.GetHeight(); nScreenRatio = sal_Int32( math::round( double( nWidth ) / double( nHeight ), 2 ) * 100 ); } char szFullScreenProgressRatio[] = "FullScreenProgressRatio0"; char szFullScreenProgressPos[] = "FullScreenProgressPos0"; char szFullScreenProgressSize[] = "FullScreenProgressSize0"; for ( sal_Int32 i = 0; i <= 9; i++ ) { char cNum = '0' + char( i ); szFullScreenProgressRatio[23] = cNum; szFullScreenProgressPos[21] = cNum; szFullScreenProgressSize[22] = cNum; OUString sFullScreenProgressRatio = implReadBootstrapKey( OUString::createFromAscii( szFullScreenProgressRatio ) ); if ( sFullScreenProgressRatio.getLength() > 0 ) { double fRatio = sFullScreenProgressRatio.toDouble(); sal_Int32 nRatio = sal_Int32( math::round( fRatio, 2 ) * 100 ); if ( nRatio == nScreenRatio ) { OUString sFullScreenProgressPos = implReadBootstrapKey( OUString::createFromAscii( szFullScreenProgressPos ) ); OUString sFullScreenProgressSize = implReadBootstrapKey( OUString::createFromAscii( szFullScreenProgressSize ) ); if ( sFullScreenProgressPos.getLength() ) { sal_Int32 idx = 0; double temp = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble(); if ( idx != -1 ) { rXRelPos = temp; rYRelPos = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble(); } } if ( sFullScreenProgressSize.getLength() ) { sal_Int32 idx = 0; double temp = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble(); if ( idx != -1 ) { rRelWidth = temp; rRelHeight = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble(); } } } } else break; } } void SplashScreen::Paint( const Rectangle&) { if(!_bVisible) return; //native drawing sal_Bool bNativeOK = sal_False; // in case of native controls we need to draw directly to the window if( _bNativeProgress && IsNativeControlSupported( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL ) ) { DrawBitmapEx( Point(), _aIntroBmp ); ImplControlValue aValue( _iProgress * _barwidth / _iMax); Rectangle aDrawRect( Point(_tlx, _tly), Size( _barwidth, _barheight ) ); Rectangle aNativeControlRegion, aNativeContentRegion; if( GetNativeControlRegion( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect, CTRL_STATE_ENABLED, aValue, rtl::OUString(), aNativeControlRegion, aNativeContentRegion ) ) { long nProgressHeight = aNativeControlRegion.GetHeight(); aDrawRect.Top() -= (nProgressHeight - _barheight)/2; aDrawRect.Bottom() += (nProgressHeight - _barheight)/2; } if( (bNativeOK = DrawNativeControl( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect, CTRL_STATE_ENABLED, aValue, _sProgressText )) != sal_False ) { return; } } //non native drawing // draw bitmap if (_bPaintBitmap) _vdev.DrawBitmapEx( Point(), _aIntroBmp ); if (_bPaintProgress) { // draw progress... long length = (_iProgress * _barwidth / _iMax); if (_bShowProgressFrame) length -= (2 * _barspace); if (length < 0) length = 0; if (_bShowProgressFrame) { // border _vdev.SetFillColor(); _vdev.SetLineColor( _cProgressFrameColor ); _vdev.DrawRect(Rectangle(_tlx, _tly, _tlx+_barwidth, _tly+_barheight)); _vdev.SetFillColor( _cProgressBarColor ); _vdev.SetLineColor(); _vdev.DrawRect(Rectangle(_tlx+_barspace, _tly+_barspace, _tlx+_barspace+length, _tly+_barheight-_barspace)); _vdev.DrawText( Rectangle(_tlx, _tly+_barheight+5, _tlx+_barwidth, _tly+_barheight+5+20), _sProgressText, TEXT_DRAW_CENTER ); } else { // Show flat progress bar without frame. // border _vdev.SetFillColor( _cProgressFrameColor ); _vdev.SetLineColor(); _vdev.DrawRect(Rectangle(_tlx, _tly, _tlx+_barwidth, _tly+_barheight)); _vdev.SetFillColor( _cProgressBarColor ); _vdev.SetLineColor(); _vdev.DrawRect(Rectangle(_tlx, _tly, _tlx+length, _tly+_barheight)); } _vdev.DrawText( Rectangle(_tlx, _tly+_barheight+5, _tlx+_barwidth, _tly+_barheight+5+20), _sProgressText, TEXT_DRAW_CENTER ); } Size aSize = GetOutputSizePixel(); Size bSize = _vdev.GetOutputSizePixel(); //_vdev.Flush(); //_vdev.DrawOutDev(Point(), GetOutputSize(), Point(), GetOutputSize(), *((IntroWindow*)this) ); DrawOutDev(Point(), GetOutputSizePixel(), Point(), _vdev.GetOutputSizePixel(), _vdev ); //Flush(); } // get service instance... SplashScreen *SplashScreen::_pINSTANCE = NULL; osl::Mutex SplashScreen::_aMutex; Reference< XInterface > SplashScreen::getInstance(const Reference< XMultiServiceFactory >& rSMgr) { if ( _pINSTANCE == 0 ) { osl::MutexGuard guard(_aMutex); if (_pINSTANCE == 0) return (XComponent*)new SplashScreen(rSMgr); } return (XComponent*)0; } // static service info... const char* SplashScreen::interfaces[] = { "com.sun.star.task.XStartusIndicator", "com.sun.star.lang.XInitialization", NULL, }; const sal_Char *SplashScreen::serviceName = "com.sun.star.office.SplashScreen"; const sal_Char *SplashScreen::implementationName = "com.sun.star.office.comp.SplashScreen"; const sal_Char *SplashScreen::supportedServiceNames[] = {"com.sun.star.office.SplashScreen", NULL}; }