1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_cui.hxx" 30 31 // include --------------------------------------------------------------- 32 33 #include <vcl/svapp.hxx> 34 #include <vcl/msgbox.hxx> 35 #include <tools/stream.hxx> 36 #include <tools/urlobj.hxx> 37 #include <rtl/bootstrap.hxx> 38 #include <unotools/configmgr.hxx> 39 #include <unotools/bootstrap.hxx> 40 #include <com/sun/star/uno/Any.h> 41 #include <vcl/graph.hxx> 42 #include <svtools/filter.hxx> 43 #include <sfx2/sfxuno.hxx> 44 #include "about.hxx" 45 #include <sfx2/sfxdefs.hxx> 46 #include <sfx2/app.hxx> 47 #include <sfx2/sfxcommands.h> 48 #include "about.hrc" 49 #include <dialmgr.hxx> 50 #include <svtools/svtools.hrc> 51 52 // defines --------------------------------------------------------------- 53 54 #define SCROLL_OFFSET 1 55 #define SPACE_OFFSET 5 56 #define SCROLL_TIMER 30 57 58 #define WELCOME_URL DEFINE_CONST_UNICODE( "http://www.openoffice.org/welcome/credits.html" ) 59 60 // class AboutDialog ----------------------------------------------------- 61 static void layoutText( FixedInfo &rText, long &nY, long nTextWidth, Size a6Size ) 62 { 63 Point aTextPos = rText.GetPosPixel(); 64 aTextPos.X() = a6Size.Width() * 2; 65 aTextPos.Y() = nY; 66 rText.SetPosPixel( aTextPos ); 67 68 Size aTxtSiz = rText.GetSizePixel(); 69 aTxtSiz.Width() = nTextWidth; 70 Size aCalcSize = rText.CalcMinimumSize( nTextWidth ); 71 aTxtSiz.Height() = aCalcSize.Height(); 72 rText.SetSizePixel( aTxtSiz ); 73 74 nY += aTxtSiz.Height(); 75 } 76 77 String InitDevVersionStr() 78 { 79 const String sCWSSchema( String::CreateFromAscii( "[CWS:" ) ); 80 rtl::OUString sDefault; 81 String sBuildId( utl::Bootstrap::getBuildIdData( sDefault ) ); 82 OSL_ENSURE( sBuildId.Len() > 0, "No BUILDID in bootstrap file" ); 83 if ( sBuildId.Len() > 0 && sBuildId.Search( sCWSSchema ) == STRING_NOTFOUND ) 84 { 85 // no cws part in brand buildid -> try basis buildid 86 rtl::OUString sBasisBuildId( DEFINE_CONST_OUSTRING( 87 "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" ) ); 88 rtl::Bootstrap::expandMacros( sBasisBuildId ); 89 sal_Int32 nIndex = sBasisBuildId.indexOf( sCWSSchema ); 90 if ( nIndex != -1 ) 91 sBuildId += String( sBasisBuildId.copy( nIndex ) ); 92 } 93 94 String sProductSource( utl::Bootstrap::getProductSource( sDefault ) ); 95 OSL_ENSURE( sProductSource.Len() > 0, "No ProductSource in bootstrap file" ); 96 97 // the product source is something like "DEV300", where the 98 // build id is something like "300m12(Build:12345)". For better readability, 99 // strip the duplicate UPD ("300"). 100 if ( sProductSource.Len() ) 101 { 102 bool bMatchingUPD = 103 ( sProductSource.Len() >= 3 ) 104 && ( sBuildId.Len() >= 3 ) 105 && ( sProductSource.Copy( sProductSource.Len() - 3 ) == sBuildId.Copy( 0, 3 ) ); 106 OSL_ENSURE( bMatchingUPD, "BUILDID and ProductSource do not match in their UPD" ); 107 if ( bMatchingUPD ) 108 sProductSource = sProductSource.Copy( 0, sProductSource.Len() - 3 ); 109 110 // prepend the product source 111 sBuildId.Insert( sProductSource, 0 ); 112 } 113 114 // --> PB 2008-10-30 #i94693# 115 // if the build ids of the basis or ure layer are different from the build id 116 // of the brand layer then show them 117 rtl::OUString aBasisProductBuildId( DEFINE_CONST_OUSTRING( 118 "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":ProductBuildid}" ) ); 119 rtl::Bootstrap::expandMacros( aBasisProductBuildId ); 120 rtl::OUString aUREProductBuildId( DEFINE_CONST_OUSTRING( 121 "${$URE_BIN_DIR/" SAL_CONFIGFILE("version") ":ProductBuildid}" ) ); 122 rtl::Bootstrap::expandMacros( aUREProductBuildId ); 123 if ( sBuildId.Search( String( aBasisProductBuildId ) ) == STRING_NOTFOUND 124 || sBuildId.Search( String( aUREProductBuildId ) ) == STRING_NOTFOUND ) 125 { 126 String sTemp( '-' ); 127 sTemp += String( aBasisProductBuildId ); 128 sTemp += '-'; 129 sTemp += String( aUREProductBuildId ); 130 sBuildId.Insert( sTemp, sBuildId.Search( ')' ) ); 131 } 132 // <-- 133 134 // the build id format is "milestone(build)[cwsname]". For readability, it would 135 // be nice to have some more spaces in there. 136 xub_StrLen nPos = 0; 137 if ( ( nPos = sBuildId.Search( sal_Unicode( '(' ) ) ) != STRING_NOTFOUND ) 138 sBuildId.Insert( sal_Unicode( ' ' ), nPos ); 139 if ( ( nPos = sBuildId.Search( sal_Unicode( '[' ) ) ) != STRING_NOTFOUND ) 140 sBuildId.Insert( sal_Unicode( ' ' ), nPos ); 141 return sBuildId; 142 } 143 144 AboutDialog::AboutDialog( Window* pParent, const ResId& rId ) : 145 146 SfxModalDialog ( pParent, rId ), 147 148 aOKButton ( this, ResId( ABOUT_BTN_OK, *rId.GetResMgr() ) ), 149 aVersionText ( this, ResId( ABOUT_FTXT_VERSION, *rId.GetResMgr() ) ), 150 aCopyrightText ( this, ResId( ABOUT_FTXT_COPYRIGHT, *rId.GetResMgr() ) ), 151 aBuildData ( this ), 152 pDeveloperAry(0), 153 aAccelStr ( ResId( ABOUT_STR_ACCEL, *rId.GetResMgr() ) ), 154 aTimer (), 155 nOff ( 0 ), 156 m_nDeltaWidth ( 0 ), 157 m_nPendingScrolls( 0 ), 158 bNormal ( sal_True ) 159 { 160 aDevVersionStr = InitDevVersionStr(); 161 162 ::com::sun::star::lang::Locale aLocale; 163 ResMgr* pResMgr = ResMgr::SearchCreateResMgr( "about", aLocale ); 164 if ( pResMgr ) 165 { 166 aCopyrightTextStr = String( ResId( ABOUT_STR_COPYRIGHT, *pResMgr ) ); 167 pDeveloperAry = new ResStringArray( ResId( ABOUT_STR_DEVELOPER_ARY, *pResMgr ) ); 168 delete pResMgr; 169 } 170 171 rtl::OUString sProduct; 172 utl::ConfigManager::GetDirectConfigProperty(utl::ConfigManager::PRODUCTNAME) >>= sProduct; 173 174 // load image from module path 175 aAppLogo = SfxApplication::GetApplicationLogo(); 176 177 // Transparenter Font 178 Font aFont = GetFont(); 179 aFont.SetTransparent( sal_True ); 180 SetFont( aFont ); 181 182 // if necessary more info 183 String sVersion = aVersionText.GetText(); 184 sVersion.SearchAndReplaceAscii( "$(VER)", Application::GetDisplayName() ); 185 sVersion += '\n'; 186 sVersion += aDevVersionStr; 187 aVersionText.SetText( sVersion ); 188 189 // Initialisierung fuer Aufruf Entwickler 190 if ( aAccelStr.Len() && ByteString(U2S(aAccelStr)).IsAlphaAscii() ) 191 { 192 Accelerator *pAccel = 0, *pPrevAccel = 0, *pFirstAccel = 0; 193 aAccelStr.ToUpperAscii(); 194 195 for ( sal_uInt16 i = 0; i < aAccelStr.Len(); ++i ) 196 { 197 pPrevAccel = pAccel; 198 pAccel = new Accelerator; 199 aAccelList.Insert( pAccel, LIST_APPEND ); 200 sal_uInt16 nKey = aAccelStr.GetChar(i) - 'A' + KEY_A; 201 pAccel->InsertItem( 1, KeyCode( nKey, KEY_MOD1 ) ); 202 if ( i > 0 ) 203 pPrevAccel->SetAccel( 1, pAccel ); 204 if ( i == 0 ) 205 pFirstAccel = pAccel; 206 } 207 pAccel->SetSelectHdl( LINK( this, AboutDialog, AccelSelectHdl ) ); 208 GetpApp()->InsertAccel( pFirstAccel ); 209 } 210 211 // set for background and text the correct system color 212 const StyleSettings& rSettings = GetSettings().GetStyleSettings(); 213 Color aWhiteCol( rSettings.GetWindowColor() ); 214 Wallpaper aWall( aWhiteCol ); 215 SetBackground( aWall ); 216 Font aNewFont( aCopyrightText.GetFont() ); 217 aNewFont.SetTransparent( sal_True ); 218 219 aVersionText.SetFont( aNewFont ); 220 aCopyrightText.SetFont( aNewFont ); 221 222 aVersionText.SetBackground(); 223 aCopyrightText.SetBackground(); 224 225 Color aTextColor( rSettings.GetWindowTextColor() ); 226 aVersionText.SetControlForeground( aTextColor ); 227 aCopyrightText.SetControlForeground( aTextColor ); 228 aBuildData.SetBackground( aWall ); 229 230 Font aSmallFont = rSettings.GetInfoFont(); 231 Size aSmaller = aNewFont.GetSize(); 232 aSmaller.Width() = (long) (aSmaller.Width() * 0.75); 233 aSmaller.Height() = (long) (aSmaller.Height() * 0.75); 234 aNewFont.SetSize( aSmaller ); 235 aBuildData.SetFont( aNewFont ); 236 aBuildData.SetBackground( aWall ); 237 #ifdef BUILD_VER_STRING 238 String aBuildString( DEFINE_CONST_UNICODE( BUILD_VER_STRING ) ); 239 #else 240 String aBuildString; 241 #endif 242 aBuildData.SetText( aBuildString ); 243 aBuildData.Show(); 244 245 // determine size and position of the dialog & elements 246 Size aAppLogoSiz = aAppLogo.GetSizePixel(); 247 Size aOutSiz = GetOutputSizePixel(); 248 aOutSiz.Width() = aAppLogoSiz.Width(); 249 250 Size a6Size = aVersionText.LogicToPixel( Size( 6, 6 ), MAP_APPFONT ); 251 long nY = aAppLogoSiz.Height() + ( a6Size.Height() * 2 ); 252 long nDlgMargin = a6Size.Width() * 4 ; 253 long nCtrlMargin = a6Size.Height() * 2; 254 long nTextWidth = aOutSiz.Width() - nDlgMargin; 255 256 aCopyrightText.SetText( aCopyrightTextStr ); 257 258 layoutText( aVersionText, nY, nTextWidth, a6Size ); 259 nY += nCtrlMargin; 260 261 // OK-Button-Position (at the bottom and centered) 262 Size aOKSiz = aOKButton.GetSizePixel(); 263 Point aOKPnt = aOKButton.GetPosPixel(); 264 265 // Multiline edit with Copyright-Text 266 Point aCopyPnt = aCopyrightText.GetPosPixel(); 267 Size aCopySize = aCopyrightText.GetSizePixel(); 268 aCopySize.Width() = nTextWidth; 269 aCopySize.Height() = aOutSiz.Height() - nY - ( aOKSiz.Height() * 2 ) - nCtrlMargin; 270 271 aCopyPnt.X() = ( aOutSiz.Width() - aCopySize.Width() ) / 2; 272 aCopyPnt.Y() = nY; 273 aCopyrightText.SetPosSizePixel( aCopyPnt, aCopySize ); 274 275 nY += aCopySize.Height() + nCtrlMargin; 276 aOKPnt.X() = ( aOutSiz.Width() - aOKSiz.Width() ) / 2; 277 aOKPnt.Y() = nY; 278 aOKButton.SetPosPixel( aOKPnt ); 279 280 // Change the width of the dialog 281 SetOutputSizePixel( aOutSiz ); 282 283 FreeResource(); 284 285 SetHelpId( CMD_SID_ABOUT ); 286 } 287 288 // ----------------------------------------------------------------------- 289 290 AboutDialog::~AboutDialog() 291 { 292 // L"oschen des Entwickleraufrufs 293 delete pDeveloperAry; 294 if ( aAccelList.Count() ) 295 { 296 GetpApp()->RemoveAccel( aAccelList.First() ); 297 Accelerator* pAccel = aAccelList.Last(); 298 299 while ( pAccel ) 300 { 301 delete pAccel; 302 pAccel = aAccelList.Prev(); 303 } 304 } 305 } 306 307 // ----------------------------------------------------------------------- 308 309 IMPL_LINK( AboutDialog, TimerHdl, Timer *, pTimer ) 310 { 311 (void)pTimer; //unused 312 ++m_nPendingScrolls; 313 Invalidate( INVALIDATE_NOERASE | INVALIDATE_NOCHILDREN ); 314 return 0; 315 } 316 317 // ----------------------------------------------------------------------- 318 319 IMPL_LINK( AboutDialog, AccelSelectHdl, Accelerator *, pAccelerator ) 320 { 321 #ifdef YURI_DARIO 322 aCopyrightText.SetHelpText( DEFINE_CONST_UNICODE("Conoscere qualcuno ovunque egli sia, con cui comprendersi nonostante le distanze\n" 323 "e le differenze, puo' trasformare la terra in un giardino. baci Valeria") ); 324 #endif 325 326 (void)pAccelerator; //unused 327 // init Timer 328 aTimer.SetTimeoutHdl( LINK( this, AboutDialog, TimerHdl ) ); 329 330 // init scroll mode 331 nOff = GetOutputSizePixel().Height(); 332 MapMode aMapMode( MAP_PIXEL ); 333 SetMapMode( aMapMode ); 334 bNormal = sal_False; 335 336 // start scroll Timer 337 aTimer.SetTimeout( SCROLL_TIMER ); 338 aTimer.Start(); 339 return 0; 340 } 341 342 // ----------------------------------------------------------------------- 343 344 sal_Bool AboutDialog::Close() 345 { 346 // stop Timer and finish the dialog 347 aTimer.Stop(); 348 EndDialog( RET_OK ); 349 return( sal_False ); 350 } 351 352 // ----------------------------------------------------------------------- 353 354 void AboutDialog::Paint( const Rectangle& rRect ) 355 { 356 SetClipRegion( rRect ); 357 358 if ( bNormal ) // not in scroll mode 359 { 360 Point aPos( m_nDeltaWidth / 2, 0 ); 361 DrawImage( aPos, aAppLogo ); 362 return; 363 } 364 365 // scroll the content 366 const int nDeltaY = -SCROLL_OFFSET * m_nPendingScrolls; 367 if( !nDeltaY ) 368 return; 369 nOff += nDeltaY; 370 Scroll( 0, nDeltaY, SCROLL_NOERASE ); 371 m_nPendingScrolls = 0; 372 373 // draw the credits text 374 const Font aOrigFont = GetFont(); 375 const int nFullWidth = GetOutputSizePixel().Width(); 376 377 int nY = nOff; 378 const int nDevCnt = static_cast<int>( pDeveloperAry->Count() ); 379 for( int i = 0; i < nDevCnt; ++i ) 380 { 381 if( nY >= rRect.Bottom() ) 382 break; 383 384 int nPos2 = nY + GetTextHeight() + 3; 385 if( nPos2 >= rRect.Top() + nDeltaY ) 386 { 387 const String aStr = pDeveloperAry->GetString(i); 388 const long nVal = pDeveloperAry->GetValue(i); 389 390 if ( nVal ) 391 { 392 // emphasize the headers 393 Font aFont = aOrigFont; 394 aFont.SetWeight( (FontWeight)nVal ); 395 SetFont( aFont ); 396 nPos2 = nY + GetTextHeight() + 3; 397 } 398 399 // clear text background 400 Rectangle aEraseRect( Point(0,nY), Size( nFullWidth, nPos2-nY)); 401 Erase( aEraseRect ); 402 403 // draw centered text 404 const long nTextWidth = GetTextWidth( aStr ); 405 long nX = (nFullWidth - 5 - nTextWidth) / 2; 406 if( nX < 0 ) 407 nX = SPACE_OFFSET; 408 const Point aPnt( nX, nY ); 409 DrawText( aPnt, aStr ); 410 411 // restore the font if needed 412 if( nVal ) 413 SetFont( aOrigFont ); 414 } 415 nY = nPos2; 416 } 417 418 // close dialog if the whole text has been scrolled 419 if ( nY <= 0 ) 420 { 421 bNormal = sal_True; 422 Close(); 423 } 424 } 425