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