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