xref: /trunk/main/cui/source/dialogs/about.cxx (revision a392ac37)
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 #define _STRINGIFY(x) #x
235 #define STRINGIFY(x) _STRINGIFY(x)
236 	String aBuildString( DEFINE_CONST_UNICODE( STRINGIFY( BUILD_VER_STRING ) ) );
237 #else
238 	String aBuildString;
239 #endif
240 	aBuildData.SetText( aBuildString );
241 	aBuildData.Show();
242 
243     // determine size and position of the dialog & elements
244 	Size aAppLogoSiz = aAppLogo.GetSizePixel();
245 	Size aOutSiz     = GetOutputSizePixel();
246     aOutSiz.Width()  = aAppLogoSiz.Width();
247 
248     Size a6Size      = aVersionText.LogicToPixel( Size( 6, 6 ), MAP_APPFONT );
249     long nY          = aAppLogoSiz.Height() + ( a6Size.Height() * 2 );
250     long nDlgMargin  = a6Size.Width() * 4 ;
251     long nCtrlMargin = a6Size.Height() * 2;
252     long nTextWidth  = aOutSiz.Width() - nDlgMargin;
253 
254     aCopyrightText.SetText( aCopyrightTextStr );
255 
256     // layout fixed text controls
257     layoutText( aVersionText, nY, nTextWidth, a6Size );
258     if( aBuildString.Len() > 0 )
259     {
260         nY += ( a6Size.Height() / 2 );
261         layoutText( aBuildData, nY, nTextWidth, a6Size );
262     }
263     nY += nCtrlMargin;
264 
265 	// OK-Button-Position (at the bottom and centered)
266 	Size aOKSiz = aOKButton.GetSizePixel();
267 	Point aOKPnt = aOKButton.GetPosPixel();
268 
269     // Multiline edit with Copyright-Text
270     Point aCopyPnt = aCopyrightText.GetPosPixel();
271     Size aCopySize = aCopyrightText.GetSizePixel();
272     aCopySize.Width()  = nTextWidth;
273     aCopySize.Height() = aOutSiz.Height() - nY - ( aOKSiz.Height() * 2 ) - nCtrlMargin;
274 
275     aCopyPnt.X() = ( aOutSiz.Width() - aCopySize.Width() ) / 2;
276     aCopyPnt.Y() = nY;
277     aCopyrightText.SetPosSizePixel( aCopyPnt, aCopySize );
278 
279     nY += aCopySize.Height() + nCtrlMargin;
280 	aOKPnt.X() = ( aOutSiz.Width() - aOKSiz.Width() ) / 2;
281 	aOKPnt.Y() = nY;
282 	aOKButton.SetPosPixel( aOKPnt );
283 
284     // Change the width of the dialog
285     SetOutputSizePixel( aOutSiz );
286 
287 	FreeResource();
288 
289 	SetHelpId( CMD_SID_ABOUT );
290 }
291 
292 // -----------------------------------------------------------------------
293 
294 AboutDialog::~AboutDialog()
295 {
296 	// L"oschen des Entwickleraufrufs
297     delete pDeveloperAry;
298 	if ( aAccelList.Count() )
299 	{
300 		GetpApp()->RemoveAccel( aAccelList.First() );
301 		Accelerator* pAccel = aAccelList.Last();
302 
303 		while ( pAccel )
304 		{
305 			delete pAccel;
306 			pAccel = aAccelList.Prev();
307 		}
308 	}
309 }
310 
311 // -----------------------------------------------------------------------
312 
313 IMPL_LINK( AboutDialog, TimerHdl, Timer *, pTimer )
314 {
315     (void)pTimer; //unused
316 	++m_nPendingScrolls;
317 	Invalidate( INVALIDATE_NOERASE | INVALIDATE_NOCHILDREN );
318 	return 0;
319 }
320 
321 // -----------------------------------------------------------------------
322 
323 IMPL_LINK( AboutDialog, AccelSelectHdl, Accelerator *, pAccelerator )
324 {
325 #ifdef YURI_DARIO
326 	aCopyrightText.SetHelpText( DEFINE_CONST_UNICODE("Conoscere qualcuno ovunque egli sia, con cui comprendersi nonostante le distanze\n"
327 					  "e le differenze, puo' trasformare la terra in un giardino. baci Valeria") );
328 #endif
329 
330     (void)pAccelerator; //unused
331     // init Timer
332 	aTimer.SetTimeoutHdl( LINK( this, AboutDialog, TimerHdl ) );
333 
334 	// init scroll mode
335 	nOff = GetOutputSizePixel().Height();
336 	MapMode aMapMode( MAP_PIXEL );
337 	SetMapMode( aMapMode );
338 	bNormal = sal_False;
339 
340 	// start scroll Timer
341 	aTimer.SetTimeout( SCROLL_TIMER );
342 	aTimer.Start();
343 	return 0;
344 }
345 
346 // -----------------------------------------------------------------------
347 
348 sal_Bool AboutDialog::Close()
349 {
350 	// stop Timer and finish the dialog
351 	aTimer.Stop();
352 	EndDialog( RET_OK );
353 	return( sal_False );
354 }
355 
356 // -----------------------------------------------------------------------
357 
358 void AboutDialog::Paint( const Rectangle& rRect )
359 {
360 	SetClipRegion( rRect );
361 
362     if ( bNormal ) // not in scroll mode
363 	{
364         Point aPos( m_nDeltaWidth / 2, 0 );
365         DrawImage( aPos, aAppLogo );
366 		return;
367 	}
368 
369 	// scroll the content
370 	const int nDeltaY = -SCROLL_OFFSET * m_nPendingScrolls;
371 	if( !nDeltaY )
372 		return;
373 	nOff += nDeltaY;
374 	Scroll( 0, nDeltaY, SCROLL_NOERASE );
375 	m_nPendingScrolls = 0;
376 
377 	// draw the credits text
378 	const Font aOrigFont = GetFont();
379 	const int nFullWidth = GetOutputSizePixel().Width();
380 
381 	int nY = nOff;
382 	const int nDevCnt = static_cast<int>( pDeveloperAry->Count() );
383 	for( int i = 0; i < nDevCnt; ++i )
384 	{
385 		if( nY >= rRect.Bottom() )
386 			break;
387 
388 		int nPos2 = nY + GetTextHeight() + 3;
389 		if( nPos2 >= rRect.Top() + nDeltaY )
390 		{
391 			const String aStr = pDeveloperAry->GetString(i);
392 			const long nVal = pDeveloperAry->GetValue(i);
393 
394 			if ( nVal )
395 			{
396 				// emphasize the headers
397 				Font aFont = aOrigFont;
398 				aFont.SetWeight( (FontWeight)nVal );
399 				SetFont( aFont );
400 				nPos2 = nY + GetTextHeight() + 3;
401 			}
402 
403 			// clear text background
404 			Rectangle aEraseRect( Point(0,nY), Size( nFullWidth, nPos2-nY));
405 			Erase( aEraseRect );
406 
407 			// draw centered text
408 			const long nTextWidth = GetTextWidth( aStr );
409 			long nX = (nFullWidth - 5 - nTextWidth) / 2;
410 			if( nX < 0 )
411 				nX = SPACE_OFFSET;
412 			const Point aPnt( nX, nY );
413 			DrawText( aPnt, aStr );
414 
415 			// restore the font if needed
416 			if( nVal )
417 				SetFont( aOrigFont );
418 		}
419 		nY = nPos2;
420 	}
421 
422 	// close dialog if the whole text has been scrolled
423 	if ( nY <= 0 )
424 	{
425 		bNormal = sal_True;
426 		Close();
427 	}
428 }
429