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 String sDefault; 76 String sBuildId( utl::Bootstrap::getBuildIdData( sDefault ) ); 77 OSL_ENSURE( sBuildId.Len() > 0, "No BUILDID in bootstrap file" ); 78 79 String sProductSource( utl::Bootstrap::getProductSource( sDefault ) ); 80 OSL_ENSURE( sProductSource.Len() > 0, "No ProductSource in bootstrap file" ); 81 82 // the product source is something like "DEV300", where the 83 // build id is something like "300m12(Build:12345)". For better readability, 84 // strip the duplicate UPD ("300"). 85 if ( sProductSource.Len() ) 86 { 87 bool bMatchingUPD = 88 ( sProductSource.Len() >= 3 ) 89 && ( sBuildId.Len() >= 3 ) 90 && ( sProductSource.Copy( sProductSource.Len() - 3 ) == sBuildId.Copy( 0, 3 ) ); 91 OSL_ENSURE( bMatchingUPD, "BUILDID and ProductSource do not match in their UPD" ); 92 if ( bMatchingUPD ) 93 sProductSource = sProductSource.Copy( 0, sProductSource.Len() - 3 ); 94 95 // prepend the product source 96 sBuildId.Insert( sProductSource, 0 ); 97 } 98 99 return sBuildId; 100 } 101 102 AboutDialog::AboutDialog( Window* pParent, const ResId& rId ) : 103 104 SfxModalDialog ( pParent, rId ), 105 106 aOKButton ( this, ResId( ABOUT_BTN_OK, *rId.GetResMgr() ) ), 107 aVersionText ( this, ResId( ABOUT_FTXT_VERSION, *rId.GetResMgr() ) ), 108 aCopyrightText ( this, ResId( ABOUT_FTXT_COPYRIGHT, *rId.GetResMgr() ) ), 109 aBuildData ( this ), 110 pDeveloperAry(0), 111 aAccelStr ( ResId( ABOUT_STR_ACCEL, *rId.GetResMgr() ) ), 112 aTimer (), 113 nOff ( 0 ), 114 m_nDeltaWidth ( 0 ), 115 m_nPendingScrolls( 0 ), 116 bNormal ( sal_True ) 117 { 118 aDevVersionStr = InitDevVersionStr(); 119 120 ::com::sun::star::lang::Locale aLocale; 121 ResMgr* pResMgr = ResMgr::SearchCreateResMgr( "about", aLocale ); 122 if ( pResMgr ) 123 { 124 aCopyrightTextStr = String( ResId( ABOUT_STR_COPYRIGHT, *pResMgr ) ); 125 pDeveloperAry = new ResStringArray( ResId( ABOUT_STR_DEVELOPER_ARY, *pResMgr ) ); 126 delete pResMgr; 127 } 128 129 rtl::OUString sProduct; 130 utl::ConfigManager::GetDirectConfigProperty(utl::ConfigManager::PRODUCTNAME) >>= sProduct; 131 132 // load image from module path 133 aAppLogo = SfxApplication::GetApplicationLogo(); 134 135 // Transparenter Font 136 Font aFont = GetFont(); 137 aFont.SetTransparent( sal_True ); 138 SetFont( aFont ); 139 140 // if necessary more info 141 String sVersion = aVersionText.GetText(); 142 sVersion.SearchAndReplaceAscii( "$(VER)", Application::GetDisplayName() ); 143 aVersionText.SetText( sVersion ); 144 145 // Initialisierung fuer Aufruf Entwickler 146 if ( aAccelStr.Len() && ByteString(U2S(aAccelStr)).IsAlphaAscii() ) 147 { 148 Accelerator *pAccel = 0, *pPrevAccel = 0, *pFirstAccel = 0; 149 aAccelStr.ToUpperAscii(); 150 151 for ( sal_uInt16 i = 0; i < aAccelStr.Len(); ++i ) 152 { 153 pPrevAccel = pAccel; 154 pAccel = new Accelerator; 155 aAccelList.Insert( pAccel, LIST_APPEND ); 156 sal_uInt16 nKey = aAccelStr.GetChar(i) - 'A' + KEY_A; 157 pAccel->InsertItem( 1, KeyCode( nKey, KEY_MOD1 ) ); 158 if ( i > 0 ) 159 pPrevAccel->SetAccel( 1, pAccel ); 160 if ( i == 0 ) 161 pFirstAccel = pAccel; 162 } 163 pAccel->SetSelectHdl( LINK( this, AboutDialog, AccelSelectHdl ) ); 164 GetpApp()->InsertAccel( pFirstAccel ); 165 } 166 167 // set for background and text the correct system color 168 const StyleSettings& rSettings = GetSettings().GetStyleSettings(); 169 Color aWhiteCol( rSettings.GetWindowColor() ); 170 Wallpaper aWall( aWhiteCol ); 171 SetBackground( aWall ); 172 Font aNewFont( aCopyrightText.GetFont() ); 173 aNewFont.SetTransparent( sal_True ); 174 175 aVersionText.SetFont( aNewFont ); 176 aCopyrightText.SetFont( aNewFont ); 177 178 aVersionText.SetBackground(); 179 aCopyrightText.SetBackground(); 180 181 Color aTextColor( rSettings.GetWindowTextColor() ); 182 aVersionText.SetControlForeground( aTextColor ); 183 aCopyrightText.SetControlForeground( aTextColor ); 184 aBuildData.SetBackground( ); 185 186 Font aSmallFont = rSettings.GetInfoFont(); 187 Size aSmaller = aNewFont.GetSize(); 188 aSmaller.Width() = (long) (aSmaller.Width() * 0.75); 189 aSmaller.Height() = (long) (aSmaller.Height() * 0.75); 190 aNewFont.SetSize( aSmaller ); 191 aBuildData.SetFont( aNewFont ); 192 193 String sRevision( utl::Bootstrap::getRevisionInfo() ); 194 195 String aBuildString(aDevVersionStr); 196 aBuildString += (DEFINE_CONST_UNICODE(" - Rev. ")); 197 aBuildString += sRevision; 198 199 #ifdef BUILD_VER_STRING 200 #define _STRINGIFY(x) #x 201 #define STRINGIFY(x) _STRINGIFY(x) 202 aBuildString += '\n'; 203 aBuildString += ( DEFINE_CONST_UNICODE( STRINGIFY( BUILD_VER_STRING ) ) ); 204 #endif 205 aBuildData.SetText( aBuildString ); 206 aBuildData.Show(); 207 208 // determine size and position of the dialog & elements 209 Size aAppLogoSiz = aAppLogo.GetSizePixel(); 210 Size aOutSiz = GetOutputSizePixel(); 211 aOutSiz.Width() = aAppLogoSiz.Width(); 212 213 Size a6Size = aVersionText.LogicToPixel( Size( 6, 6 ), MAP_APPFONT ); 214 long nY = aAppLogoSiz.Height() + ( a6Size.Height() * 2 ); 215 long nDlgMargin = a6Size.Width() * 4 ; 216 long nCtrlMargin = a6Size.Height() * 2; 217 long nTextWidth = aOutSiz.Width() - nDlgMargin; 218 219 aCopyrightText.SetText( aCopyrightTextStr ); 220 221 // layout fixed text controls 222 layoutText( aVersionText, nY, nTextWidth, a6Size ); 223 if( aBuildString.Len() > 0 ) 224 { 225 nY += ( a6Size.Height() / 2 ); 226 layoutText( aBuildData, nY, nTextWidth, a6Size ); 227 } 228 nY += nCtrlMargin; 229 230 // OK-Button-Position (at the bottom and centered) 231 Size aOKSiz = aOKButton.GetSizePixel(); 232 Point aOKPnt = aOKButton.GetPosPixel(); 233 234 // Multiline edit with Copyright-Text 235 Point aCopyPnt = aCopyrightText.GetPosPixel(); 236 Size aCopySize = aCopyrightText.GetSizePixel(); 237 aCopySize.Width() = nTextWidth; 238 aCopySize.Height() = aOutSiz.Height() - nY - ( aOKSiz.Height() * 2 ) - nCtrlMargin; 239 240 aCopyPnt.X() = ( aOutSiz.Width() - aCopySize.Width() ) / 2; 241 aCopyPnt.Y() = nY; 242 aCopyrightText.SetPosSizePixel( aCopyPnt, aCopySize ); 243 244 nY += aCopySize.Height() + nCtrlMargin; 245 aOKPnt.X() = ( aOutSiz.Width() - aOKSiz.Width() ) / 2; 246 aOKPnt.Y() = nY; 247 aOKButton.SetPosPixel( aOKPnt ); 248 249 // Change the width of the dialog 250 SetOutputSizePixel( aOutSiz ); 251 252 FreeResource(); 253 254 SetHelpId( CMD_SID_ABOUT ); 255 } 256 257 // ----------------------------------------------------------------------- 258 259 AboutDialog::~AboutDialog() 260 { 261 // L"oschen des Entwickleraufrufs 262 delete pDeveloperAry; 263 if ( aAccelList.Count() ) 264 { 265 GetpApp()->RemoveAccel( aAccelList.First() ); 266 Accelerator* pAccel = aAccelList.Last(); 267 268 while ( pAccel ) 269 { 270 delete pAccel; 271 pAccel = aAccelList.Prev(); 272 } 273 } 274 } 275 276 // ----------------------------------------------------------------------- 277 278 IMPL_LINK( AboutDialog, TimerHdl, Timer *, pTimer ) 279 { 280 (void)pTimer; //unused 281 ++m_nPendingScrolls; 282 Invalidate( INVALIDATE_NOERASE | INVALIDATE_NOCHILDREN ); 283 return 0; 284 } 285 286 // ----------------------------------------------------------------------- 287 288 IMPL_LINK( AboutDialog, AccelSelectHdl, Accelerator *, pAccelerator ) 289 { 290 #ifdef YURI_DARIO 291 aCopyrightText.SetHelpText( DEFINE_CONST_UNICODE("Conoscere qualcuno ovunque egli sia, con cui comprendersi nonostante le distanze\n" 292 "e le differenze, puo' trasformare la terra in un giardino. baci Valeria") ); 293 #endif 294 295 (void)pAccelerator; //unused 296 // init Timer 297 aTimer.SetTimeoutHdl( LINK( this, AboutDialog, TimerHdl ) ); 298 299 // init scroll mode 300 nOff = GetOutputSizePixel().Height(); 301 MapMode aMapMode( MAP_PIXEL ); 302 SetMapMode( aMapMode ); 303 bNormal = sal_False; 304 305 // start scroll Timer 306 aTimer.SetTimeout( SCROLL_TIMER ); 307 aTimer.Start(); 308 return 0; 309 } 310 311 // ----------------------------------------------------------------------- 312 313 sal_Bool AboutDialog::Close() 314 { 315 // stop Timer and finish the dialog 316 aTimer.Stop(); 317 EndDialog( RET_OK ); 318 return( sal_False ); 319 } 320 321 // ----------------------------------------------------------------------- 322 323 void AboutDialog::Paint( const Rectangle& rRect ) 324 { 325 SetClipRegion( rRect ); 326 327 if ( bNormal ) // not in scroll mode 328 { 329 Point aPos( m_nDeltaWidth / 2, 0 ); 330 DrawImage( aPos, aAppLogo ); 331 return; 332 } 333 334 // scroll the content 335 const int nDeltaY = -SCROLL_OFFSET * m_nPendingScrolls; 336 if( !nDeltaY ) 337 return; 338 nOff += nDeltaY; 339 Scroll( 0, nDeltaY, SCROLL_NOERASE ); 340 m_nPendingScrolls = 0; 341 342 // draw the credits text 343 const Font aOrigFont = GetFont(); 344 const int nFullWidth = GetOutputSizePixel().Width(); 345 346 int nY = nOff; 347 const int nDevCnt = static_cast<int>( pDeveloperAry->Count() ); 348 for( int i = 0; i < nDevCnt; ++i ) 349 { 350 if( nY >= rRect.Bottom() ) 351 break; 352 353 int nPos2 = nY + GetTextHeight() + 3; 354 if( nPos2 >= rRect.Top() + nDeltaY ) 355 { 356 const String aStr = pDeveloperAry->GetString(i); 357 const long nVal = pDeveloperAry->GetValue(i); 358 359 if ( nVal ) 360 { 361 // emphasize the headers 362 Font aFont = aOrigFont; 363 aFont.SetWeight( (FontWeight)nVal ); 364 SetFont( aFont ); 365 nPos2 = nY + GetTextHeight() + 3; 366 } 367 368 // clear text background 369 Rectangle aEraseRect( Point(0,nY), Size( nFullWidth, nPos2-nY)); 370 Erase( aEraseRect ); 371 372 // draw centered text 373 const long nTextWidth = GetTextWidth( aStr ); 374 long nX = (nFullWidth - 5 - nTextWidth) / 2; 375 if( nX < 0 ) 376 nX = SPACE_OFFSET; 377 const Point aPnt( nX, nY ); 378 DrawText( aPnt, aStr ); 379 380 // restore the font if needed 381 if( nVal ) 382 SetFont( aOrigFont ); 383 } 384 nY = nPos2; 385 } 386 387 // close dialog if the whole text has been scrolled 388 if ( nY <= 0 ) 389 { 390 bNormal = sal_True; 391 Close(); 392 } 393 } 394