xref: /trunk/main/cui/source/dialogs/about.cxx (revision cdf0e10c)
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