xref: /trunk/main/cui/source/dialogs/about.cxx (revision 5b501c92293051a25b12b7eb43a2a29471ec1458)
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     String sDefault;
76     String sBuildId( utl::Bootstrap::getBuildIdData( sDefault ) );
77     OSL_ENSURE( sBuildId.Len() > 0, "No BUILDID in bootstrap file" );
78 
79     String sProductSource( utl::Bootstrap::getProductSource( sDefault ) );
80     OSL_ENSURE( sProductSource.Len() > 0, "No ProductSource in bootstrap file" );
81 
82     // the product source is something like "DEV300", where the
83     // build id is something like "300m12(Build:12345)". For better readability,
84     // strip the duplicate UPD ("300").
85     if ( sProductSource.Len() )
86     {
87         bool bMatchingUPD =
88                 ( sProductSource.Len() >= 3 )
89             &&  ( sBuildId.Len() >= 3 )
90             &&  ( sProductSource.Copy( sProductSource.Len() - 3 ) == sBuildId.Copy( 0, 3 ) );
91         OSL_ENSURE( bMatchingUPD, "BUILDID and ProductSource do not match in their UPD" );
92         if ( bMatchingUPD )
93             sProductSource = sProductSource.Copy( 0, sProductSource.Len() - 3 );
94 
95         // prepend the product source
96         sBuildId.Insert( sProductSource, 0 );
97     }
98 
99     return sBuildId;
100 }
101 
102 AboutDialog::AboutDialog( Window* pParent, const ResId& rId ) :
103 
104     SfxModalDialog  ( pParent,  rId ),
105 
106     aOKButton       ( this,     ResId( ABOUT_BTN_OK, *rId.GetResMgr() ) ),
107     aVersionText    ( this,     ResId( ABOUT_FTXT_VERSION, *rId.GetResMgr() ) ),
108     aCopyrightText  ( this,     ResId( ABOUT_FTXT_COPYRIGHT, *rId.GetResMgr() ) ),
109     aBuildData      ( this ),
110     pDeveloperAry(0),
111     aAccelStr       (           ResId( ABOUT_STR_ACCEL, *rId.GetResMgr() ) ),
112     aTimer          (),
113     nOff            ( 0 ),
114     m_nDeltaWidth   ( 0 ),
115     m_nPendingScrolls( 0 ),
116     bNormal         ( sal_True )
117 {
118     aDevVersionStr = InitDevVersionStr();
119 
120     ::com::sun::star::lang::Locale aLocale;
121     ResMgr* pResMgr = ResMgr::SearchCreateResMgr( "about", aLocale );
122     if ( pResMgr )
123     {
124         aCopyrightTextStr = String( ResId( ABOUT_STR_COPYRIGHT, *pResMgr ) );
125         pDeveloperAry = new ResStringArray( ResId( ABOUT_STR_DEVELOPER_ARY, *pResMgr ) );
126         delete pResMgr;
127     }
128 
129     rtl::OUString sProduct;
130     utl::ConfigManager::GetDirectConfigProperty(utl::ConfigManager::PRODUCTNAME) >>= sProduct;
131 
132     // load image from module path
133     aAppLogo = SfxApplication::GetApplicationLogo();
134 
135     // Transparenter Font
136     Font aFont = GetFont();
137     aFont.SetTransparent( sal_True );
138     SetFont( aFont );
139 
140     // if necessary more info
141     String sVersion = aVersionText.GetText();
142     sVersion.SearchAndReplaceAscii( "$(VER)", Application::GetDisplayName() );
143     aVersionText.SetText( sVersion );
144 
145     // Initialisierung fuer Aufruf Entwickler
146     if ( aAccelStr.Len() && ByteString(U2S(aAccelStr)).IsAlphaAscii() )
147     {
148         Accelerator *pAccel = 0, *pPrevAccel = 0, *pFirstAccel = 0;
149         aAccelStr.ToUpperAscii();
150 
151         for ( sal_uInt16 i = 0; i < aAccelStr.Len(); ++i )
152         {
153             pPrevAccel = pAccel;
154             pAccel = new Accelerator;
155             aAccelList.Insert( pAccel, LIST_APPEND );
156             sal_uInt16 nKey = aAccelStr.GetChar(i) - 'A' + KEY_A;
157             pAccel->InsertItem( 1, KeyCode( nKey, KEY_MOD1 ) );
158             if ( i > 0 )
159                 pPrevAccel->SetAccel( 1, pAccel );
160             if ( i == 0 )
161                 pFirstAccel = pAccel;
162         }
163         pAccel->SetSelectHdl( LINK( this, AboutDialog, AccelSelectHdl ) );
164         GetpApp()->InsertAccel( pFirstAccel );
165     }
166 
167     // set for background and text the correct system color
168     const StyleSettings& rSettings = GetSettings().GetStyleSettings();
169     Color aWhiteCol( rSettings.GetWindowColor() );
170     Wallpaper aWall( aWhiteCol );
171     SetBackground( aWall );
172     Font aNewFont( aCopyrightText.GetFont() );
173     aNewFont.SetTransparent( sal_True );
174 
175     aVersionText.SetFont( aNewFont );
176     aCopyrightText.SetFont( aNewFont );
177 
178     aVersionText.SetBackground();
179     aCopyrightText.SetBackground();
180 
181     Color aTextColor( rSettings.GetWindowTextColor() );
182     aVersionText.SetControlForeground( aTextColor );
183     aCopyrightText.SetControlForeground( aTextColor );
184     aBuildData.SetBackground( );
185 
186     Font aSmallFont = rSettings.GetInfoFont();
187     Size aSmaller = aNewFont.GetSize();
188     aSmaller.Width() = (long) (aSmaller.Width() * 0.75);
189     aSmaller.Height() = (long) (aSmaller.Height() * 0.75);
190     aNewFont.SetSize( aSmaller );
191     aBuildData.SetFont( aNewFont );
192 
193     String sRevision( utl::Bootstrap::getRevisionInfo() );
194 
195     String aBuildString(aDevVersionStr);
196     aBuildString += (DEFINE_CONST_UNICODE("  -  Rev. "));
197     aBuildString += sRevision;
198 
199 #ifdef BUILD_VER_STRING
200 #define _STRINGIFY(x) #x
201 #define STRINGIFY(x) _STRINGIFY(x)
202     aBuildString += '\n';
203     aBuildString += ( DEFINE_CONST_UNICODE( STRINGIFY( BUILD_VER_STRING ) ) );
204 #endif
205     aBuildData.SetText( aBuildString );
206     aBuildData.Show();
207 
208     // determine size and position of the dialog & elements
209     Size aAppLogoSiz = aAppLogo.GetSizePixel();
210     Size aOutSiz     = GetOutputSizePixel();
211     aOutSiz.Width()  = aAppLogoSiz.Width();
212 
213     Size a6Size      = aVersionText.LogicToPixel( Size( 6, 6 ), MAP_APPFONT );
214     long nY          = aAppLogoSiz.Height() + ( a6Size.Height() * 2 );
215     long nDlgMargin  = a6Size.Width() * 4 ;
216     long nCtrlMargin = a6Size.Height() * 2;
217     long nTextWidth  = aOutSiz.Width() - nDlgMargin;
218 
219     aCopyrightText.SetText( aCopyrightTextStr );
220 
221     // layout fixed text controls
222     layoutText( aVersionText, nY, nTextWidth, a6Size );
223     if( aBuildString.Len() > 0 )
224     {
225         nY += ( a6Size.Height() / 2 );
226         layoutText( aBuildData, nY, nTextWidth, a6Size );
227     }
228     nY += nCtrlMargin;
229 
230     // OK-Button-Position (at the bottom and centered)
231     Size aOKSiz = aOKButton.GetSizePixel();
232     Point aOKPnt = aOKButton.GetPosPixel();
233 
234     // Multiline edit with Copyright-Text
235     Point aCopyPnt = aCopyrightText.GetPosPixel();
236     Size aCopySize = aCopyrightText.GetSizePixel();
237     aCopySize.Width()  = nTextWidth;
238     aCopySize.Height() = aOutSiz.Height() - nY - ( aOKSiz.Height() * 2 ) - nCtrlMargin;
239 
240     aCopyPnt.X() = ( aOutSiz.Width() - aCopySize.Width() ) / 2;
241     aCopyPnt.Y() = nY;
242     aCopyrightText.SetPosSizePixel( aCopyPnt, aCopySize );
243 
244     nY += aCopySize.Height() + nCtrlMargin;
245     aOKPnt.X() = ( aOutSiz.Width() - aOKSiz.Width() ) / 2;
246     aOKPnt.Y() = nY;
247     aOKButton.SetPosPixel( aOKPnt );
248 
249     // Change the width of the dialog
250     SetOutputSizePixel( aOutSiz );
251 
252     FreeResource();
253 
254     SetHelpId( CMD_SID_ABOUT );
255 }
256 
257 // -----------------------------------------------------------------------
258 
259 AboutDialog::~AboutDialog()
260 {
261     // L"oschen des Entwickleraufrufs
262     delete pDeveloperAry;
263     if ( aAccelList.Count() )
264     {
265         GetpApp()->RemoveAccel( aAccelList.First() );
266         Accelerator* pAccel = aAccelList.Last();
267 
268         while ( pAccel )
269         {
270             delete pAccel;
271             pAccel = aAccelList.Prev();
272         }
273     }
274 }
275 
276 // -----------------------------------------------------------------------
277 
278 IMPL_LINK( AboutDialog, TimerHdl, Timer *, pTimer )
279 {
280     (void)pTimer; //unused
281     ++m_nPendingScrolls;
282     Invalidate( INVALIDATE_NOERASE | INVALIDATE_NOCHILDREN );
283     return 0;
284 }
285 
286 // -----------------------------------------------------------------------
287 
288 IMPL_LINK( AboutDialog, AccelSelectHdl, Accelerator *, pAccelerator )
289 {
290 #ifdef YURI_DARIO
291     aCopyrightText.SetHelpText( DEFINE_CONST_UNICODE("Conoscere qualcuno ovunque egli sia, con cui comprendersi nonostante le distanze\n"
292                       "e le differenze, puo' trasformare la terra in un giardino. baci Valeria") );
293 #endif
294 
295     (void)pAccelerator; //unused
296     // init Timer
297     aTimer.SetTimeoutHdl( LINK( this, AboutDialog, TimerHdl ) );
298 
299     // init scroll mode
300     nOff = GetOutputSizePixel().Height();
301     MapMode aMapMode( MAP_PIXEL );
302     SetMapMode( aMapMode );
303     bNormal = sal_False;
304 
305     // start scroll Timer
306     aTimer.SetTimeout( SCROLL_TIMER );
307     aTimer.Start();
308     return 0;
309 }
310 
311 // -----------------------------------------------------------------------
312 
313 sal_Bool AboutDialog::Close()
314 {
315     // stop Timer and finish the dialog
316     aTimer.Stop();
317     EndDialog( RET_OK );
318     return( sal_False );
319 }
320 
321 // -----------------------------------------------------------------------
322 
323 void AboutDialog::Paint( const Rectangle& rRect )
324 {
325     SetClipRegion( rRect );
326 
327     if ( bNormal ) // not in scroll mode
328     {
329         Point aPos( m_nDeltaWidth / 2, 0 );
330         DrawImage( aPos, aAppLogo );
331         return;
332     }
333 
334     // scroll the content
335     const int nDeltaY = -SCROLL_OFFSET * m_nPendingScrolls;
336     if( !nDeltaY )
337         return;
338     nOff += nDeltaY;
339     Scroll( 0, nDeltaY, SCROLL_NOERASE );
340     m_nPendingScrolls = 0;
341 
342     // draw the credits text
343     const Font aOrigFont = GetFont();
344     const int nFullWidth = GetOutputSizePixel().Width();
345 
346     int nY = nOff;
347     const int nDevCnt = static_cast<int>( pDeveloperAry->Count() );
348     for( int i = 0; i < nDevCnt; ++i )
349     {
350         if( nY >= rRect.Bottom() )
351             break;
352 
353         int nPos2 = nY + GetTextHeight() + 3;
354         if( nPos2 >= rRect.Top() + nDeltaY )
355         {
356             const String aStr = pDeveloperAry->GetString(i);
357             const long nVal = pDeveloperAry->GetValue(i);
358 
359             if ( nVal )
360             {
361                 // emphasize the headers
362                 Font aFont = aOrigFont;
363                 aFont.SetWeight( (FontWeight)nVal );
364                 SetFont( aFont );
365                 nPos2 = nY + GetTextHeight() + 3;
366             }
367 
368             // clear text background
369             Rectangle aEraseRect( Point(0,nY), Size( nFullWidth, nPos2-nY));
370             Erase( aEraseRect );
371 
372             // draw centered text
373             const long nTextWidth = GetTextWidth( aStr );
374             long nX = (nFullWidth - 5 - nTextWidth) / 2;
375             if( nX < 0 )
376                 nX = SPACE_OFFSET;
377             const Point aPnt( nX, nY );
378             DrawText( aPnt, aStr );
379 
380             // restore the font if needed
381             if( nVal )
382                 SetFont( aOrigFont );
383         }
384         nY = nPos2;
385     }
386 
387     // close dialog if the whole text has been scrolled
388     if ( nY <= 0 )
389     {
390         bNormal = sal_True;
391         Close();
392     }
393 }
394