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