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 // autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 #include "backingwindow.hxx"
32 #include "classes/resource.hrc"
33 #include "framework.hrc"
34 #include "classes/fwkresid.hxx"
35 #include <services.h>
36 
37 #include "vcl/metric.hxx"
38 #include "vcl/mnemonic.hxx"
39 #include "vcl/menu.hxx"
40 #include "vcl/svapp.hxx"
41 
42 #include "tools/urlobj.hxx"
43 
44 #include "unotools/dynamicmenuoptions.hxx"
45 #include "unotools/historyoptions.hxx"
46 #include "svtools/imagemgr.hxx"
47 #include "svtools/svtools.hrc"
48 
49 #include "comphelper/processfactory.hxx"
50 #include "comphelper/sequenceashashmap.hxx"
51 #include "comphelper/configurationhelper.hxx"
52 
53 #include "cppuhelper/implbase1.hxx"
54 
55 #include "rtl/strbuf.hxx"
56 #include "rtl/ustrbuf.hxx"
57 #include "osl/file.h"
58 
59 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
60 #include "com/sun/star/container/XNameAccess.hpp"
61 #include "com/sun/star/system/XSystemShellExecute.hpp"
62 #include "com/sun/star/system/SystemShellExecuteFlags.hpp"
63 #include "com/sun/star/task/XJobExecutor.hpp"
64 #include "com/sun/star/util/XStringWidth.hpp"
65 
66 
67 using namespace ::com::sun::star::beans;
68 using namespace ::com::sun::star::frame;
69 using namespace ::com::sun::star::uno;
70 using namespace ::com::sun::star;
71 using namespace framework;
72 
73 #define WRITER_URL      "private:factory/swriter"
74 #define CALC_URL        "private:factory/scalc"
75 #define IMPRESS_WIZARD_URL     "private:factory/simpress?slot=6686"
76 #define DRAW_URL        "private:factory/sdraw"
77 #define BASE_URL        "private:factory/sdatabase?Interactive"
78 #define MATH_URL        "private:factory/smath"
79 #define TEMPLATE_URL    "slot:5500"
80 #define OPEN_URL        ".uno:Open"
81 
82 DecoToolBox::DecoToolBox( Window* pParent, WinBits nStyle ) :
83     ToolBox( pParent, nStyle )
84 {
85         SetBackground();
86         SetPaintTransparent( sal_True );
87 }
88 
89 void DecoToolBox::DataChanged( const DataChangedEvent& rDCEvt )
90 {
91     Window::DataChanged( rDCEvt );
92 
93     if ( rDCEvt.GetFlags() & SETTINGS_STYLE )
94     {
95         calcMinSize();
96         SetBackground();
97         SetPaintTransparent( sal_True );
98     }
99 }
100 
101 void DecoToolBox::calcMinSize()
102 {
103     ToolBox aTbx( GetParent() );
104     sal_uInt16 nItems = GetItemCount();
105     for( sal_uInt16 i = 0; i < nItems; i++ )
106     {
107         sal_uInt16 nId = GetItemId( i );
108         aTbx.InsertItem( nId, GetItemImage( nId ) );
109     }
110     aTbx.SetOutStyle( TOOLBOX_STYLE_FLAT );
111     maMinSize = aTbx.CalcWindowSizePixel();
112 }
113 
114 Size DecoToolBox::getMinSize()
115 {
116     return maMinSize;
117 }
118 
119 class RecentFilesStringLength : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XStringWidth >
120 {
121 	public:
122 		RecentFilesStringLength() {}
123 		virtual ~RecentFilesStringLength() {}
124 
125 		// XStringWidth
126 		sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString )
127 			throw (::com::sun::star::uno::RuntimeException)
128 		{
129 			return aString.getLength();
130 		}
131 };
132 
133 #define STC_BUTTON_STYLE  (WB_LEFT | WB_VCENTER | WB_FLATBUTTON | WB_BEVELBUTTON)
134 
135 BackingWindow::BackingWindow( Window* i_pParent ) :
136     Window( i_pParent, FwkResId( DLG_BACKING ) ),
137     maWelcome( this, WB_LEFT ),
138     maProduct( this, WB_LEFT ),
139     maWriterButton( this, STC_BUTTON_STYLE ),
140     maCalcButton( this, STC_BUTTON_STYLE ),
141     maImpressButton( this, STC_BUTTON_STYLE ),
142     maOpenButton( this, STC_BUTTON_STYLE ),
143     maDrawButton( this, STC_BUTTON_STYLE ),
144     maDBButton( this, STC_BUTTON_STYLE ),
145     maMathButton( this, STC_BUTTON_STYLE ),
146     maTemplateButton( this, STC_BUTTON_STYLE ),
147     maToolbox( this, WB_DIALOGCONTROL ),
148     maWelcomeString( FwkResId( STR_BACKING_WELCOME ) ),
149     maProductString( FwkResId( STR_BACKING_WELCOMEPRODUCT ) ),
150     maOpenString( FwkResId( STR_BACKING_FILE ) ),
151     maTemplateString( FwkResId( STR_BACKING_TEMPLATE ) ),
152     maButtonImageSize( 10, 10 ),
153     mbInitControls( false ),
154     mnLayoutStyle( 0 ),
155     mpAccExec( NULL ),
156     mnBtnPos( 120 ),
157     mnBtnTop( 150 ),
158     mpRecentMenu( NULL )
159 {
160     mnColumnWidth[0] = mnColumnWidth[1] = 0;
161     mnTextColumnWidth[0] = mnTextColumnWidth[1] = 0;
162 
163     try
164     {
165         Reference<lang::XMultiServiceFactory> xConfig( comphelper::getProcessServiceFactory()->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY);
166         if( xConfig.is() )
167         {
168             Sequence<Any> args(1);
169             PropertyValue val(
170                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("nodepath") ),
171                 0,
172                 Any(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Common/Help/StartCenter"))),
173                 PropertyState_DIRECT_VALUE);
174             args.getArray()[0] <<= val;
175             Reference<container::XNameAccess> xNameAccess(xConfig->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,args), UNO_QUERY);
176             if( xNameAccess.is() )
177             {
178                 //throws css::container::NoSuchElementException, css::lang::WrappedTargetException
179                 Any value( xNameAccess->getByName(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartCenterLayoutStyle"))) );
180                 mnLayoutStyle = value.get<sal_Int32>();
181             }
182         }
183     }
184     catch (Exception& )
185     {
186     }
187 
188     String aExtHelpText( FwkResId( STR_BACKING_EXTHELP ) );
189     String aRegHelpText( FwkResId( STR_BACKING_REGHELP ) );
190     String aInfoHelpText( FwkResId( STR_BACKING_INFOHELP ) );
191     String aTplRepHelpText( FwkResId( STR_BACKING_TPLREP ) );
192 
193     // clean up resource stack
194     FreeResource();
195 
196     maWelcome.SetPaintTransparent( sal_True );
197     maProduct.SetPaintTransparent( sal_True );
198     EnableChildTransparentMode();
199 
200     SetStyle( GetStyle() | WB_DIALOGCONTROL );
201 
202     // force tab cycling in toolbox
203     maToolbox.SetStyle( maToolbox.GetStyle() | WB_FORCETABCYCLE );
204 
205     // insert toolbox items
206     maToolbox.InsertItem( nItemId_TplRep, Image() );
207     maToolbox.SetItemText( nItemId_TplRep, aTplRepHelpText );
208     maToolbox.SetQuickHelpText( nItemId_TplRep, aTplRepHelpText );
209     maToolbox.SetItemCommand( nItemId_TplRep, String( RTL_CONSTASCII_USTRINGPARAM( ".HelpId:StartCenter:TemplateRepository" ) ) );
210     maToolbox.ShowItem( nItemId_TplRep );
211 
212     maToolbox.InsertItem( nItemId_Extensions, Image() );
213     maToolbox.SetQuickHelpText( nItemId_Extensions, aExtHelpText );
214     maToolbox.SetItemText( nItemId_Extensions, aExtHelpText );
215     maToolbox.SetItemCommand( nItemId_Extensions, String( RTL_CONSTASCII_USTRINGPARAM( ".HelpId:StartCenter:Extensions" ) ) );
216     maToolbox.ShowItem( nItemId_Extensions );
217 
218     maToolbox.InsertItem( nItemId_Reg, Image() );
219     maToolbox.SetQuickHelpText( nItemId_Reg, aRegHelpText );
220     maToolbox.SetItemText( nItemId_Reg, aRegHelpText );
221     maToolbox.SetItemCommand( nItemId_Reg, String( RTL_CONSTASCII_USTRINGPARAM( ".HelpId:StartCenter:Register" ) ) );
222     maToolbox.ShowItem( nItemId_Reg );
223 
224     maToolbox.InsertItem( nItemId_Info, Image() );
225     maToolbox.SetItemText( nItemId_Info, aInfoHelpText );
226     maToolbox.SetQuickHelpText( nItemId_Info, aInfoHelpText );
227     maToolbox.SetItemCommand( nItemId_Info, String( RTL_CONSTASCII_USTRINGPARAM( ".HelpId:StartCenter:Info" ) ) );
228     maToolbox.ShowItem( nItemId_Info );
229 
230     // get dispatch provider
231     mxDesktop = Reference<XDesktop>( comphelper::getProcessServiceFactory()->createInstance(SERVICENAME_DESKTOP ),UNO_QUERY );
232     if( mxDesktop.is() )
233         mxDesktopDispatchProvider = Reference< XDispatchProvider >( mxDesktop, UNO_QUERY );
234 
235     maWriterButton.SetHelpId( ".HelpId:StartCenter:WriterButton" );
236     maCalcButton.SetHelpId( ".HelpId:StartCenter:CalcButton" );
237     maImpressButton.SetHelpId( ".HelpId:StartCenter:ImpressButton" );
238     maDrawButton.SetHelpId( ".HelpId:StartCenter:DrawButton" );
239     maDBButton.SetHelpId( ".HelpId:StartCenter:DBButton" );
240     maMathButton.SetHelpId( ".HelpId:StartCenter:MathButton" );
241     maTemplateButton.SetHelpId( ".HelpId:StartCenter:TemplateButton" );
242     maOpenButton.SetHelpId( ".HelpId:StartCenter:OpenButton" );
243     maToolbox.SetHelpId( ".HelpId:StartCenter:Toolbox" );
244 
245     // init background
246     initBackground();
247 
248     // add some breathing space for the images
249     maButtonImageSize.Width() += 12;
250     maButtonImageSize.Height() += 12;
251 
252 }
253 
254 
255 BackingWindow::~BackingWindow()
256 {
257     delete mpRecentMenu;
258     delete mpAccExec;
259 }
260 
261 void BackingWindow::GetFocus()
262 {
263     if( IsVisible() )
264         maWriterButton.GrabFocus();
265     Window::GetFocus();
266 }
267 
268 class ImageContainerRes : public Resource
269 {
270     public:
271     ImageContainerRes( const ResId& i_rId ) : Resource( i_rId ) {}
272     ~ImageContainerRes() { FreeResource(); }
273 };
274 
275 void BackingWindow::DataChanged( const DataChangedEvent& rDCEvt )
276 {
277     Window::DataChanged( rDCEvt );
278 
279     if ( rDCEvt.GetFlags() & SETTINGS_STYLE )
280     {
281         initBackground();
282         Invalidate();
283     }
284 }
285 
286 void BackingWindow::prepareRecentFileMenu()
287 {
288     if( ! mpRecentMenu )
289         mpRecentMenu = new PopupMenu();
290     mpRecentMenu->Clear();
291     maRecentFiles.clear();
292 
293     // get recent file list and dispatch arguments
294     Sequence< Sequence< PropertyValue > > aHistoryList( SvtHistoryOptions().GetList( ePICKLIST ) );
295 
296     sal_Int32 nPickListMenuItems = ( aHistoryList.getLength() > 99 ) ? 99 : aHistoryList.getLength();
297 
298     if( ( nPickListMenuItems > 0 ) )
299     {
300         maRecentFiles.reserve( nPickListMenuItems );
301         for ( sal_Int32 i = 0; i < nPickListMenuItems; i++ )
302         {
303             Sequence< PropertyValue >& rPickListEntry = aHistoryList[i];
304             rtl::OUString aURL, aFilter, aFilterOpt, aTitle;
305 
306             for ( sal_Int32 j = 0; j < rPickListEntry.getLength(); j++ )
307             {
308                 const Any& a = rPickListEntry[j].Value;
309 
310                 if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_URL )
311                     a >>= aURL;
312                 else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_FILTER )
313                 {
314                     a >>= aFilter;
315                     sal_Int32 nPos = aFilter.indexOf( '|' );
316                     if ( nPos >= 0 )
317                     {
318                         if ( nPos < ( aFilter.getLength() - 1 ) )
319                             aFilterOpt = aFilter.copy( nPos+1 );
320                         aFilter = aFilter.copy( 0, nPos-1 );
321                     }
322                 }
323                 else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_TITLE )
324                     a >>= aTitle;
325             }
326             maRecentFiles.push_back( LoadRecentFile() );
327             maRecentFiles.back().aTargetURL = aURL;
328 
329             sal_Int32 nArgs = aFilterOpt.getLength() ? 4 : 3;
330             Sequence< PropertyValue >& rArgsList( maRecentFiles.back().aArgSeq );
331             rArgsList.realloc( nArgs );
332 
333             nArgs--;
334             rArgsList[nArgs].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ));
335             rArgsList[nArgs].Value = makeAny( aFilter );
336 
337             if( aFilterOpt.getLength() )
338             {
339                 nArgs--;
340                 rArgsList[nArgs].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterOptions" ));
341                 rArgsList[nArgs].Value = makeAny( aFilterOpt );
342             }
343 
344             // documents in the picklist will never be opened as templates
345             nArgs--;
346             rArgsList[nArgs].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AsTemplate" ));
347             rArgsList[nArgs].Value = makeAny( (sal_Bool) sal_False );
348 
349             nArgs--;
350             rArgsList[nArgs].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" ));
351             rArgsList[nArgs].Value = makeAny( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:user" ) ) );
352 
353             // and finally create an entry in the popupmenu
354             rtl::OUString	aMenuTitle;
355             INetURLObject	aURLObj( aURL );
356 
357             if ( aURLObj.GetProtocol() == INET_PROT_FILE )
358             {
359                 // Do handle file URL differently => convert it to a system
360                 // path and abbreviate it with a special function:
361                 String aFileSystemPath( aURLObj.getFSysPath( INetURLObject::FSYS_DETECT ) );
362 
363                 rtl::OUString	aSystemPath( aFileSystemPath );
364                 rtl::OUString	aCompactedSystemPath;
365 
366                 oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL );
367                 if ( !nError )
368                     aMenuTitle = String( aCompactedSystemPath );
369                 else
370                     aMenuTitle = aSystemPath;
371             }
372             else
373             {
374                 // Use INetURLObject to abbreviate all other URLs
375                 Reference< util::XStringWidth > xStringLength( new RecentFilesStringLength() );
376                 aMenuTitle = aURLObj.getAbbreviated( xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS );
377             }
378             rtl::OUStringBuffer aBuf( aMenuTitle.getLength() + 5 );
379             if( i < 9 )
380             {
381                 aBuf.append( sal_Unicode( '~' ) );
382                 aBuf.append( i+1 );
383             }
384             else if( i == 9 )
385                 aBuf.appendAscii( "1~0" );
386             else
387                 aBuf.append( i+1 );
388             aBuf.appendAscii( ": " );
389             aBuf.append( aMenuTitle );
390             mpRecentMenu->InsertItem( static_cast<sal_uInt16>(i+1), aBuf.makeStringAndClear() );
391         }
392     }
393     else
394     {
395         String aNoDoc( FwkResId( STR_NODOCUMENT ) );
396         mpRecentMenu->InsertItem( 0xffff, aNoDoc );
397     }
398     maOpenButton.SetPopupMenu( mpRecentMenu );
399 }
400 
401 void BackingWindow::initBackground()
402 {
403     SetBackground();
404 
405     bool bDark = GetSettings().GetStyleSettings().GetHighContrastMode();
406     if( bDark )
407         maWelcomeTextColor = maLabelTextColor = Color( COL_WHITE );
408     else if( mnLayoutStyle == 1 )
409         maWelcomeTextColor = maLabelTextColor = Color( COL_BLACK );
410     else
411         maWelcomeTextColor = maLabelTextColor = Color( 0x26, 0x35, 0x42 );
412 
413     Color aTextBGColor( bDark ? COL_BLACK : COL_WHITE );
414 
415     // select image set
416     ImageContainerRes aRes( FwkResId( bDark ? RES_BACKING_IMAGES_HC : RES_BACKING_IMAGES ) );
417 
418     // scale middle segment
419     Size aMiddleSize;
420     if( !! maBackgroundMiddle )
421         aMiddleSize = maBackgroundMiddle.GetSizePixel();
422     // load middle segment
423     maBackgroundMiddle = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_MIDDLE ) );
424     // and scale it to previous size
425     if( aMiddleSize.Width() && aMiddleSize.Height() )
426         maBackgroundMiddle.Scale( aMiddleSize );
427 
428     if( GetSettings().GetLayoutRTL() )
429     {
430         // replace images by RTL versions
431         maBackgroundLeft = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_RTL_RIGHT ) );
432         maBackgroundRight = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_RTL_LEFT) );
433     }
434     else
435     {
436         maBackgroundLeft = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_LEFT ) );
437         maBackgroundRight = BitmapEx( FwkResId( BMP_BACKING_BACKGROUND_RIGHT ) );
438     }
439     maToolbox.SetItemImage( nItemId_Extensions, BitmapEx( FwkResId( BMP_BACKING_EXT ) ) );
440     maToolbox.SetItemImage( nItemId_Reg, BitmapEx( FwkResId( BMP_BACKING_REG ) ) );
441     maToolbox.SetItemImage( nItemId_Info, BitmapEx( FwkResId( BMP_BACKING_INFO ) ) );
442     maToolbox.SetItemImage( nItemId_TplRep, BitmapEx( FwkResId( BMP_BACKING_TPLREP ) ) );
443 
444     maWelcome.SetControlForeground( maWelcomeTextColor );
445     maWelcome.SetBackground();
446     maProduct.SetControlForeground( maWelcomeTextColor );
447     maProduct.SetBackground();
448 
449     if( mnLayoutStyle == 1 )
450     {
451         if( Application::GetSettings().GetLayoutRTL() )
452             mnBtnPos = maBackgroundRight.GetSizePixel().Width() + 40;
453         else
454             mnBtnPos = maBackgroundLeft.GetSizePixel().Width() + 40;
455     }
456 
457     // get icon images from fwk resource and set them on the appropriate buttons
458     loadImage( FwkResId( BMP_BACKING_WRITER ), maWriterButton );
459     loadImage( FwkResId( BMP_BACKING_CALC ), maCalcButton );
460     loadImage( FwkResId( BMP_BACKING_IMPRESS ), maImpressButton );
461     loadImage( FwkResId( BMP_BACKING_DRAW ), maDrawButton );
462     loadImage( FwkResId( BMP_BACKING_DATABASE ), maDBButton );
463     loadImage( FwkResId( BMP_BACKING_FORMULA ), maMathButton );
464     loadImage( FwkResId( BMP_BACKING_OPENFILE ), maOpenButton );
465     loadImage( FwkResId( BMP_BACKING_OPENTEMPLATE ), maTemplateButton );
466 
467     maOpenButton.SetMenuMode( MENUBUTTON_MENUMODE_TIMED );
468     maOpenButton.SetSelectHdl( LINK( this, BackingWindow, SelectHdl ) );
469     maOpenButton.SetActivateHdl( LINK( this, BackingWindow, ActivateHdl ) );
470 }
471 
472 void BackingWindow::initControls()
473 {
474     if( mbInitControls )
475         return;
476 
477     mbInitControls = true;
478 
479     // calculate dialog size
480     // begin with background bitmap
481     maControlRect = Rectangle( Point(), maBackgroundLeft.GetSizePixel() );
482     maControlRect.Left() += nShadowLeft;
483     maControlRect.Right() -= nShadowRight;
484     maControlRect.Top() += nShadowTop;
485     maControlRect.Bottom() -= nShadowBottom;
486 
487     long nYPos = 0;
488     // set bigger welcome string
489     maWelcome.SetText( maWelcomeString );
490     maTextFont = GetSettings().GetStyleSettings().GetLabelFont();
491     maTextFont.SetSize( Size( 0, 18 ) );
492     maTextFont.SetWeight( WEIGHT_BOLD );
493     maWelcome.SetFont( maTextFont );
494     // get metric to get correct width factor and adjust
495     long nW = (maWelcome.GetFontMetric().GetWidth()*95)/100;
496     maTextFont.SetSize( Size( nW, 18 ) );
497 
498     maWelcome.SetFont( maTextFont );
499     maWelcome.SetControlFont( maTextFont );
500     maWelcomeSize = Size( maWelcome.GetTextWidth( maWelcomeString ), maWelcome.GetTextHeight() );
501     maWelcomeSize.Width() = (maWelcomeSize.Width() * 20)/19;
502 
503     nYPos += (maWelcomeSize.Height()*3)/2;
504 
505     if( maControlRect.GetWidth() < mnBtnPos + maWelcomeSize.Width() + 20 )
506         maControlRect.Right() = maControlRect.Left() + maWelcomeSize.Width() + mnBtnPos + 20;
507 
508     nYPos += maWelcomeSize.Height();
509 
510     // set product string
511     maTextFont.SetSize( Size( 0, 30 ) );
512     maProduct.SetFont( maTextFont );
513 
514     // get metric to get correct width factor and adjust
515     nW = (maProduct.GetFontMetric().GetWidth()*95)/100;
516     maTextFont.SetSize( Size( nW, 28 ) );
517 
518     maProduct.SetFont( maTextFont );
519     maProduct.SetControlFont( maTextFont );
520     maProduct.SetText( maProductString );
521     maProductSize = Size( maProduct.GetTextWidth( maProductString ), maProduct.GetTextHeight() );
522     maProductSize.Width() = (maProductSize.Width() * 20)/19;
523 
524     if( maControlRect.GetWidth() < maProductSize.Width() + mnBtnPos + 10 )
525         maControlRect.Right() = maControlRect.Left() + maProductSize.Width() + mnBtnPos + 10;
526 
527     if( mnLayoutStyle == 1 )
528     {
529         maWelcome.Show();
530         maProduct.Show();
531     }
532 
533     nYPos += (maProductSize.Height()*3)/2;
534 
535     // set a slighly larger font than normal labels on the texts
536     maTextFont.SetSize( Size( 0, 11 ) );
537     maTextFont.SetWeight( WEIGHT_NORMAL );
538 
539     // collect the URLs of the entries in the File/New menu
540     SvtModuleOptions	aModuleOptions;
541     std::set< rtl::OUString > aFileNewAppsAvailable;
542     SvtDynamicMenuOptions aOpt;
543     Sequence < Sequence < PropertyValue > > aNewMenu = aOpt.GetMenu( E_NEWMENU );
544     const rtl::OUString sURLKey( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
545 
546     const Sequence< PropertyValue >* pNewMenu = aNewMenu.getConstArray();
547     const Sequence< PropertyValue >* pNewMenuEnd = aNewMenu.getConstArray() + aNewMenu.getLength();
548     for ( ; pNewMenu != pNewMenuEnd; ++pNewMenu )
549     {
550         comphelper::SequenceAsHashMap aEntryItems( *pNewMenu );
551         rtl::OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, rtl::OUString() ) );
552         if ( sURL.getLength() )
553             aFileNewAppsAvailable.insert( sURL );
554     }
555 
556     // create mnemonics on the fly, preregister the mnemonics of the menu
557     MnemonicGenerator aMnemns;
558     maTemplateString = MnemonicGenerator::EraseAllMnemonicChars( maTemplateString );
559     maOpenString = MnemonicGenerator::EraseAllMnemonicChars( maOpenString );
560 
561     SystemWindow* pSysWin = GetSystemWindow();
562     if( pSysWin )
563     {
564         MenuBar* pMBar = pSysWin->GetMenuBar();
565         if( pMBar )
566         {
567             for( sal_uInt16 i = 0; i < pMBar->GetItemCount(); i++ )
568             {
569                 sal_uInt16 nItemId = pMBar->GetItemId( i );
570                 String aItemText( pMBar->GetItemText( nItemId ) );
571                 if( aItemText.Len() )
572                     aMnemns.RegisterMnemonic( aItemText );
573             }
574         }
575     }
576 
577     // layout the buttons
578     layoutButton( WRITER_URL, 0, aFileNewAppsAvailable,
579                   aModuleOptions, SvtModuleOptions::E_SWRITER,
580                   maWriterButton, aMnemns );
581     layoutButton( DRAW_URL, 1, aFileNewAppsAvailable,
582                   aModuleOptions, SvtModuleOptions::E_SDRAW,
583                   maDrawButton, aMnemns );
584     nYPos += maButtonImageSize.Height() + 10;
585     layoutButton( CALC_URL, 0, aFileNewAppsAvailable,
586                   aModuleOptions, SvtModuleOptions::E_SCALC,
587                   maCalcButton, aMnemns );
588     layoutButton( BASE_URL, 1, aFileNewAppsAvailable,
589                   aModuleOptions, SvtModuleOptions::E_SDATABASE,
590                   maDBButton, aMnemns );
591     nYPos += maButtonImageSize.Height() + 10;
592     layoutButton( IMPRESS_WIZARD_URL, 0, aFileNewAppsAvailable,
593                   aModuleOptions, SvtModuleOptions::E_SIMPRESS,
594                   maImpressButton, aMnemns );
595     layoutButton( MATH_URL, 1, aFileNewAppsAvailable,
596                   aModuleOptions, SvtModuleOptions::E_SMATH,
597                   maMathButton, aMnemns );
598 
599     nYPos += 3*maButtonImageSize.Height() / 2;
600 
601     layoutButton( NULL, 0, aFileNewAppsAvailable,
602                   aModuleOptions, SvtModuleOptions::E_SWRITER,
603                   maOpenButton, aMnemns, maOpenString );
604     layoutButton( NULL, 1, aFileNewAppsAvailable,
605                   aModuleOptions, SvtModuleOptions::E_SWRITER,
606                   maTemplateButton, aMnemns, maTemplateString );
607     nYPos += 10;
608 
609     DBG_ASSERT( nYPos < maControlRect.GetHeight(), "misformatting !" );
610     if( mnColumnWidth[0] + mnColumnWidth[1] + mnBtnPos + 20 > maControlRect.GetWidth() )
611         maControlRect.Right() = maControlRect.Left() + mnColumnWidth[0] + mnColumnWidth[1] + mnBtnPos + 20;
612 
613     mnTextColumnWidth[0] = mnColumnWidth[0];
614     mnTextColumnWidth[1] = mnColumnWidth[1];
615 
616     if( mnTextColumnWidth[1] > mnTextColumnWidth[0] )
617     {
618         mnColumnWidth[0]     = mnColumnWidth[1];
619         mnTextColumnWidth[0] = mnTextColumnWidth[1];
620     }
621     else
622     {
623         mnColumnWidth[1]     = mnColumnWidth[0];
624         mnTextColumnWidth[1] = mnTextColumnWidth[0];
625     }
626     if( maControlRect.GetWidth() < maControlRect.GetHeight() * 3 / 2 )
627     {
628         maControlRect.Right() = maControlRect.Left() + maControlRect.GetHeight() * 3 / 2;
629         long nDelta = (maControlRect.GetWidth() - mnBtnPos - mnColumnWidth[1] - mnColumnWidth[0] - 20);
630         mnColumnWidth[0] += nDelta/2;
631         mnColumnWidth[1] += nDelta/2;
632     }
633 
634     maToolbox.SetSelectHdl( LINK( this, BackingWindow, ToolboxHdl ) );
635     if( mnLayoutStyle == 0 )
636         maToolbox.Show();
637 
638     // scale middle map to formatted width
639     Size aMiddleSegmentSize( maControlRect.GetSize().Width() + nShadowLeft + nShadowRight,
640                              maBackgroundMiddle.GetSizePixel().Height() );
641 
642     long nLW = maBackgroundLeft.GetSizePixel().Width();
643     long nRW = maBackgroundRight.GetSizePixel().Width();
644     if( aMiddleSegmentSize.Width() > nLW + nRW )
645     {
646         aMiddleSegmentSize.Width() -= nLW;
647         aMiddleSegmentSize.Width() -= nRW;
648         maBackgroundMiddle.Scale( aMiddleSegmentSize );
649     }
650     else
651         maBackgroundMiddle = BitmapEx();
652 
653     Resize();
654 
655     maWriterButton.GrabFocus();
656 }
657 
658 void BackingWindow::loadImage( const ResId& i_rId, PushButton& i_rButton )
659 {
660     BitmapEx aBmp( i_rId );
661     Size aImgSize( aBmp.GetSizePixel() );
662     if( aImgSize.Width() > maButtonImageSize.Width() )
663         maButtonImageSize.Width() = aImgSize.Width();
664     if( aImgSize.Height() > maButtonImageSize.Height() )
665         maButtonImageSize.Height() = aImgSize.Height();
666     i_rButton.SetModeImage( aBmp );
667 }
668 
669 void BackingWindow::layoutButton(
670                           const char* i_pURL, int nColumn,
671                           const std::set<rtl::OUString>& i_rURLS,
672                           SvtModuleOptions& i_rOpt, SvtModuleOptions::EModule i_eMod,
673                           PushButton& i_rBtn,
674                           MnemonicGenerator& i_rMnemns,
675                           const String& i_rStr
676                           )
677 {
678     rtl::OUString aURL( rtl::OUString::createFromAscii( i_pURL ? i_pURL : "" ) );
679     // setup button
680     i_rBtn.SetPaintTransparent( sal_True );
681     i_rBtn.SetClickHdl( LINK( this, BackingWindow, ClickHdl ) );
682     if( i_pURL && (! i_rOpt.IsModuleInstalled( i_eMod ) || i_rURLS.find( aURL ) == i_rURLS.end()) )
683     {
684         i_rBtn.Enable( sal_False );
685     }
686 
687     // setup text
688     i_rBtn.SetFont( maTextFont );
689     i_rBtn.SetControlFont( maTextFont );
690     String aText( i_rStr.Len() ? i_rStr : SvFileInformationManager::GetDescription( INetURLObject( aURL ) ) );
691     i_rMnemns.CreateMnemonic( aText );
692     i_rBtn.SetText( aText );
693 
694     long nTextWidth = i_rBtn.GetTextWidth( i_rBtn.GetText() );
695 
696     nTextWidth += maButtonImageSize.Width() + 8; // add some fuzz to be on the safe side
697     if( nColumn >= 0 && nColumn < static_cast<int>(sizeof(mnColumnWidth)/sizeof(mnColumnWidth[0])) )
698     {
699         if( nTextWidth > mnColumnWidth[nColumn] )
700             mnColumnWidth[nColumn] = nTextWidth;
701     }
702 
703     i_rBtn.SetImageAlign( IMAGEALIGN_LEFT );
704     // show the controls
705     i_rBtn.Show();
706 }
707 
708 void BackingWindow::Paint( const Rectangle& )
709 {
710     Wallpaper aBack( GetSettings().GetStyleSettings().GetWorkspaceGradient() );
711     Region aClip( Rectangle( Point( 0, 0 ), GetOutputSizePixel() ) );
712     Rectangle aBmpRect(maControlRect);
713     aBmpRect.Left()   -= nShadowLeft;
714     aBmpRect.Top()    -= nShadowTop;
715     aBmpRect.Right()  += nShadowRight;
716     aBmpRect.Bottom() += nShadowBottom;
717     aClip.Exclude( aBmpRect );
718     Push( PUSH_CLIPREGION );
719     IntersectClipRegion( aClip );
720     DrawWallpaper( Rectangle( Point( 0, 0 ), GetOutputSizePixel() ), aBack );
721     Pop();
722 
723     VirtualDevice aDev( *this );
724     aDev.EnableRTL( IsRTLEnabled() );
725     aDev.SetOutputSizePixel( aBmpRect.GetSize() );
726     Point aOffset( Point( 0, 0 ) - aBmpRect.TopLeft() );
727     aDev.DrawWallpaper( Rectangle( aOffset, GetOutputSizePixel() ), aBack );
728 
729     // draw bitmap
730     Point aTL( 0, 0 );
731     aDev.DrawBitmapEx( aTL, maBackgroundLeft );
732     aTL.X() += maBackgroundLeft.GetSizePixel().Width();
733     if( !!maBackgroundMiddle )
734     {
735         aDev.DrawBitmapEx( aTL, maBackgroundMiddle );
736         aTL.X() += maBackgroundMiddle.GetSizePixel().Width();
737     }
738     aDev.DrawBitmapEx( aTL, maBackgroundRight );
739 
740     DrawOutDev( aBmpRect.TopLeft(), aBmpRect.GetSize(),
741                 Point( 0, 0 ), aBmpRect.GetSize(),
742                 aDev );
743 }
744 
745 long BackingWindow::Notify( NotifyEvent& rNEvt )
746 {
747     if( rNEvt.GetType() == EVENT_KEYINPUT )
748     {
749         if( ! mpAccExec )
750         {
751             mpAccExec = svt::AcceleratorExecute::createAcceleratorHelper();
752             mpAccExec->init( comphelper::getProcessServiceFactory(), mxFrame);
753         }
754 
755         const KeyEvent* pEvt = rNEvt.GetKeyEvent();
756         const KeyCode& rKeyCode(pEvt->GetKeyCode());
757         if( pEvt && mpAccExec->execute(rKeyCode) )
758             return 1;
759         // #i110344# extrawurst: specialized arrow key control
760         if( rKeyCode.GetModifier() == 0 )
761         {
762             if( rKeyCode.GetCode() == KEY_RIGHT )
763             {
764                 if( maWriterButton.HasFocus() )
765                     maDrawButton.GrabFocus();
766                 else if( maCalcButton.HasFocus() )
767                     maDBButton.GrabFocus();
768                 else if( maImpressButton.HasFocus() )
769                     maMathButton.GrabFocus();
770                 else if( maOpenButton.HasFocus() )
771                     maTemplateButton.GrabFocus();
772                 return 1;
773             }
774             else if( rKeyCode.GetCode() == KEY_LEFT )
775             {
776                 if( maDrawButton.HasFocus() )
777                     maWriterButton.GrabFocus();
778                 else if( maDBButton.HasFocus() )
779                     maCalcButton.GrabFocus();
780                 else if( maMathButton.HasFocus() )
781                     maImpressButton.GrabFocus();
782                 else if( maTemplateButton.HasFocus() )
783                     maOpenButton.GrabFocus();
784                 return 1;
785             }
786             else if( rKeyCode.GetCode() == KEY_UP )
787             {
788                 // first column
789                 if( maOpenButton.HasFocus() )
790                     maImpressButton.GrabFocus();
791                 else if( maImpressButton.HasFocus() )
792                     maCalcButton.GrabFocus();
793                 else if( maCalcButton.HasFocus() )
794                     maWriterButton.GrabFocus();
795                 // second column
796                 else if( maTemplateButton.HasFocus() )
797                     maMathButton.GrabFocus();
798                 else if( maMathButton.HasFocus() )
799                     maDBButton.GrabFocus();
800                 else if( maDBButton.HasFocus() )
801                     maDrawButton.GrabFocus();
802                 return 1;
803             }
804             else if( rKeyCode.GetCode() == KEY_DOWN )
805             {
806                 // first column
807                 if( maWriterButton.HasFocus() )
808                     maCalcButton.GrabFocus();
809                 else if( maCalcButton.HasFocus() )
810                     maImpressButton.GrabFocus();
811                 else if( maImpressButton.HasFocus() )
812                     maOpenButton.GrabFocus();
813                 // second column
814                 else if( maDrawButton.HasFocus() )
815                     maDBButton.GrabFocus();
816                 else if( maDBButton.HasFocus() )
817                     maMathButton.GrabFocus();
818                 else if( maMathButton.HasFocus() )
819                     maTemplateButton.GrabFocus();
820                 return 1;
821             }
822         }
823     }
824     return Window::Notify( rNEvt );
825 }
826 
827 void BackingWindow::setOwningFrame( const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& xFrame )
828 {
829     mxFrame = xFrame;
830     if( ! mbInitControls )
831         initControls();
832 }
833 
834 void BackingWindow::Resize()
835 {
836     Size aWindowSize( GetSizePixel() );
837     Size aControlSize = maControlRect.GetSize();
838     maControlRect = Rectangle( Point( (aWindowSize.Width() - aControlSize.Width()) / 2,
839                                       (aWindowSize.Height() - aControlSize.Height()) / 2 ),
840                                aControlSize );
841 
842     maToolbox.calcMinSize();
843     Size aTBSize( maToolbox.getMinSize() );
844     Point aTBPos( maControlRect.Left() + mnBtnPos,
845                   maControlRect.Bottom() - aTBSize.Height() - 10 );
846     if( Application::GetSettings().GetLayoutRTL() )
847         aTBPos.X() = maControlRect.Right() - aTBSize.Width() - mnBtnPos;
848     maToolbox.SetPosSizePixel( aTBPos, aTBSize );
849 
850     // #i93631# squeeze controls so they fit into the box
851     // this can be necessary due to application font height which has small deviations
852     // from the size set
853     const long nWDelta    = maWelcomeSize.Height();
854     const long nW2Delta   = (maWelcomeSize.Height()*3)/2;
855     const long nPDelta    = (maProductSize.Height()*3)/2;
856     const long nBDelta    = maButtonImageSize.Height() + 10;
857     const long nB2Delta   = 3*maButtonImageSize.Height()/2;
858     const long nLastDelta = maButtonImageSize.Height();
859     long nDiff = 0;
860     while( ( maControlRect.Top()   +
861                  (nWDelta - nDiff) +
862                  (nW2Delta- nDiff) +
863                  (nPDelta - nDiff) +
864              3 * (nBDelta - nDiff) +
865                  (nB2Delta- nDiff) +
866                  nLastDelta
867             ) > aTBPos.Y() )
868     {
869         nDiff++;
870     }
871 
872     long nYPos = maControlRect.Top();
873     nYPos += nW2Delta - nDiff;
874     maWelcome.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ),
875                                 Size( maControlRect.GetWidth() - mnBtnPos - 5, (maWelcomeSize.Height()*20)/19 ) );
876     nYPos += nWDelta - nDiff;
877     maProduct.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( maControlRect.GetWidth() - mnBtnPos - 5, (maProductSize.Height()*20)/19 ) );
878     nYPos += nPDelta - nDiff;
879 
880     nYPos += nWDelta/2 - nDiff;
881 
882     if( mnLayoutStyle != 1 )
883         nYPos = maControlRect.Top() + mnBtnTop;
884 
885     maWriterButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
886     maDrawButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
887     nYPos += nBDelta - nDiff;
888     maCalcButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
889     maDBButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
890     nYPos += nBDelta - nDiff;
891     maImpressButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
892     maMathButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
893 
894     nYPos += nB2Delta - nDiff;
895     maOpenButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
896     maTemplateButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
897 }
898 
899 IMPL_LINK( BackingWindow, ToolboxHdl, void*, EMPTYARG )
900 {
901     const char* pNodePath = NULL;
902     const char* pNode = NULL;
903 
904     switch( maToolbox.GetCurItemId() )
905     {
906     case nItemId_Extensions:
907         pNodePath = "/org.openoffice.Office.Common/Help/StartCenter";
908         pNode = "AddFeatureURL";
909         break;
910     case nItemId_Reg:
911         try
912         {
913             // create the Desktop component which can load components
914             Reference < lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
915             if( xFactory.is() )
916             {
917                 Reference< task::XJobExecutor > xProductRegistration(
918                     xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.setup.ProductRegistration" ) ) ),
919                     UNO_QUERY_THROW );
920 
921                  // tell it that the user wants to register
922                  xProductRegistration->trigger( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RegistrationRequired" ) ) );
923             }
924         }
925         catch( const Exception& )
926         {
927         }
928         break;
929     case nItemId_Info:
930         pNodePath = "/org.openoffice.Office.Common/Help/StartCenter";
931         pNode = "InfoURL";
932         break;
933     case nItemId_TplRep:
934         pNodePath = "/org.openoffice.Office.Common/Help/StartCenter";
935         pNode = "TemplateRepositoryURL";
936         break;
937     default:
938         break;
939     }
940     if( pNodePath && pNode )
941     {
942         try
943         {
944             Reference<lang::XMultiServiceFactory> xConfig( comphelper::getProcessServiceFactory()->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY);
945             if( xConfig.is() )
946             {
947                 Sequence<Any> args(1);
948                 PropertyValue val(
949                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("nodepath") ),
950                     0,
951                     Any(rtl::OUString::createFromAscii(pNodePath)),
952                     PropertyState_DIRECT_VALUE);
953                 args.getArray()[0] <<= val;
954                 Reference<container::XNameAccess> xNameAccess(xConfig->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,args), UNO_QUERY);
955                 if( xNameAccess.is() )
956                 {
957                     rtl::OUString sURL;
958                     //throws css::container::NoSuchElementException, css::lang::WrappedTargetException
959                     Any value( xNameAccess->getByName(rtl::OUString::createFromAscii(pNode)) );
960                     sURL = value.get<rtl::OUString> ();
961 
962                     // extend the URLs with Office locale argument
963                     INetURLObject aURLObj( sURL );
964 
965                     rtl::OUString sParam = aURLObj.GetParam();
966                     rtl::OUStringBuffer aURLBuf( sParam );
967                     if ( sParam.getLength() > 0 )
968                         aURLBuf.appendAscii( "&" );
969                     aURLBuf.appendAscii( "lang=" );
970 
971                     // read locale from configuration
972                     ::rtl::OUString sLocale;
973                     ::rtl::OUString sPackage = ::rtl::OUString::createFromAscii("org.openoffice.Setup");
974                     ::rtl::OUString sRelPath = ::rtl::OUString::createFromAscii("L10N");
975                     ::rtl::OUString sKey     = ::rtl::OUString::createFromAscii("ooLocale");
976 
977                     try
978                     {
979                         ::comphelper::ConfigurationHelper::readDirectKey(comphelper::getProcessServiceFactory(),
980                                                                          sPackage,
981                                                                          sRelPath,
982                                                                          sKey,
983                                                                          ::comphelper::ConfigurationHelper::E_READONLY) >>= sLocale;
984                     }
985                     catch(const com::sun::star::uno::RuntimeException& exRun)
986                         { throw exRun; }
987                     catch(const com::sun::star::uno::Exception&)
988                     { sLocale = ::rtl::OUString::createFromAscii("en-US"); }
989 
990                     aURLBuf.append(sLocale);
991 
992                     sParam = aURLBuf.makeStringAndClear();
993 
994                     aURLObj.SetParam( sParam );
995                     sURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
996 
997                     Reference< com::sun::star::system::XSystemShellExecute > xSystemShellExecute(
998                         comphelper::getProcessServiceFactory()->createInstance(
999                             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SystemShellExecute" ) ) ),
1000                         UNO_QUERY_THROW);
1001                     //throws css::lang::IllegalArgumentException, css::system::SystemShellExecuteException
1002                     xSystemShellExecute->execute( sURL, rtl::OUString(), com::sun::star::system::SystemShellExecuteFlags::DEFAULTS);
1003                 }
1004             }
1005         }
1006         catch (Exception& )
1007         {
1008         }
1009     }
1010 
1011     return 0;
1012 }
1013 
1014 IMPL_LINK( BackingWindow, ClickHdl, Button*, pButton )
1015 {
1016     // dispatch the appropriate URL and end the dialog
1017     if( pButton == &maWriterButton )
1018         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(WRITER_URL) ) );
1019     else if( pButton == &maCalcButton )
1020         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(CALC_URL) ) );
1021     else if( pButton == &maImpressButton )
1022         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(IMPRESS_WIZARD_URL) ) );
1023     else if( pButton == &maDrawButton )
1024         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(DRAW_URL) ) );
1025     else if( pButton == &maDBButton )
1026         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(BASE_URL) ) );
1027     else if( pButton == &maMathButton )
1028         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(MATH_URL) ) );
1029     else if( pButton == &maOpenButton )
1030     {
1031         Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
1032 
1033         Sequence< com::sun::star::beans::PropertyValue > aArgs(1);
1034         PropertyValue* pArg = aArgs.getArray();
1035         pArg[0].Name = rtl::OUString::createFromAscii("Referer");
1036         pArg[0].Value <<= rtl::OUString::createFromAscii("private:user");
1037 
1038         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(OPEN_URL) ), rtl::OUString(), xFrame, aArgs );
1039     }
1040     else if( pButton == &maTemplateButton )
1041     {
1042         Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
1043 
1044         Sequence< com::sun::star::beans::PropertyValue > aArgs(1);
1045         PropertyValue* pArg = aArgs.getArray();
1046         pArg[0].Name = rtl::OUString::createFromAscii("Referer");
1047         pArg[0].Value <<= rtl::OUString::createFromAscii("private:user");
1048 
1049         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(TEMPLATE_URL) ), rtl::OUString(), xFrame, aArgs );
1050     }
1051     return 0;
1052 }
1053 
1054 IMPL_LINK( BackingWindow, SelectHdl, Button*, pButton )
1055 {
1056     if( pButton == &maOpenButton )
1057     {
1058         sal_Int32 nItem = sal_Int32(maOpenButton.GetCurItemId())-1;
1059         if( nItem >= 0 && nItem < sal_Int32(maRecentFiles.size()) )
1060         {
1061             Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
1062             dispatchURL( maRecentFiles[nItem].aTargetURL, rtl::OUString(), xFrame, maRecentFiles[nItem].aArgSeq );
1063         }
1064     }
1065     return 0;
1066 }
1067 
1068 IMPL_LINK( BackingWindow, ActivateHdl, Button*, pButton )
1069 {
1070     if( pButton == &maOpenButton )
1071         prepareRecentFileMenu();
1072     return 0;
1073 }
1074 
1075 struct ImplDelayedDispatch
1076 {
1077     Reference< XDispatch >      xDispatch;
1078     com::sun::star::util::URL   aDispatchURL;
1079     Sequence< PropertyValue >   aArgs;
1080 
1081     ImplDelayedDispatch( const Reference< XDispatch >& i_xDispatch,
1082                          const com::sun::star::util::URL& i_rURL,
1083                          const Sequence< PropertyValue >& i_rArgs )
1084     : xDispatch( i_xDispatch ),
1085       aDispatchURL( i_rURL ),
1086       aArgs( i_rArgs )
1087     {
1088     }
1089     ~ImplDelayedDispatch() {}
1090 };
1091 
1092 static long implDispatchDelayed( void*, void* pArg )
1093 {
1094     struct ImplDelayedDispatch* pDispatch = reinterpret_cast<ImplDelayedDispatch*>(pArg);
1095     try
1096     {
1097         pDispatch->xDispatch->dispatch( pDispatch->aDispatchURL, pDispatch->aArgs );
1098     }
1099     catch( Exception )
1100     {
1101     }
1102 
1103     // clean up
1104     delete pDispatch;
1105 
1106     return 0;
1107 }
1108 
1109 void BackingWindow::dispatchURL( const rtl::OUString& i_rURL,
1110                                  const rtl::OUString& rTarget,
1111                                  const Reference< XDispatchProvider >& i_xProv,
1112                                  const Sequence< PropertyValue >& i_rArgs )
1113 {
1114     // if no special dispatch provider is given, get the desktop
1115     Reference< XDispatchProvider > xProvider( i_xProv.is() ? i_xProv : mxDesktopDispatchProvider );
1116 
1117     // check for dispatch provider
1118     if( !xProvider.is())
1119         return;
1120 
1121     // get an URL transformer to clean up the URL
1122     com::sun::star::util::URL aDispatchURL;
1123     aDispatchURL.Complete = i_rURL;
1124 
1125     Reference < com::sun::star::util::XURLTransformer > xURLTransformer(
1126         comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer") ),
1127         com::sun::star::uno::UNO_QUERY );
1128     if ( xURLTransformer.is() )
1129     {
1130         try
1131         {
1132             // clean up the URL
1133             xURLTransformer->parseStrict( aDispatchURL );
1134             // get a Dispatch for the URL and target
1135             Reference< XDispatch > xDispatch(
1136                 xProvider->queryDispatch( aDispatchURL, rTarget, 0 )
1137                 );
1138             // dispatch the URL
1139             if ( xDispatch.is() )
1140             {
1141                 ImplDelayedDispatch* pDisp = new ImplDelayedDispatch( xDispatch, aDispatchURL, i_rArgs );
1142                 sal_uLong nEventId = 0;
1143                 if( ! Application::PostUserEvent( nEventId, Link( NULL, implDispatchDelayed ), pDisp ) )
1144                     delete pDisp; // event could not be posted for unknown reason, at least don't leak
1145             }
1146         }
1147         catch ( com::sun::star::uno::RuntimeException& )
1148         {
1149             throw;
1150         }
1151         catch ( com::sun::star::uno::Exception& )
1152         {
1153         }
1154     }
1155 }
1156 
1157