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