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