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