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     Wallpaper aBack( GetSettings().GetStyleSettings().GetWorkspaceGradient() );
701     Region aClip( Rectangle( Point( 0, 0 ), GetOutputSizePixel() ) );
702     Rectangle aBmpRect(maControlRect);
703     aBmpRect.Left()   -= nShadowLeft;
704     aBmpRect.Top()    -= nShadowTop;
705     aBmpRect.Right()  += nShadowRight;
706     aBmpRect.Bottom() += nShadowBottom;
707     aClip.Exclude( aBmpRect );
708     Push( PUSH_CLIPREGION );
709     IntersectClipRegion( aClip );
710     DrawWallpaper( Rectangle( Point( 0, 0 ), GetOutputSizePixel() ), aBack );
711     Pop();
712 
713     VirtualDevice aDev( *this );
714     aDev.EnableRTL( IsRTLEnabled() );
715     aDev.SetOutputSizePixel( aBmpRect.GetSize() );
716     Point aOffset( Point( 0, 0 ) - aBmpRect.TopLeft() );
717     aDev.DrawWallpaper( Rectangle( aOffset, GetOutputSizePixel() ), aBack );
718 
719     // draw bitmap
720     Point aTL( 0, 0 );
721     aDev.DrawBitmapEx( aTL, maBackgroundLeft );
722     aTL.X() += maBackgroundLeft.GetSizePixel().Width();
723     if( !!maBackgroundMiddle )
724     {
725         aDev.DrawBitmapEx( aTL, maBackgroundMiddle );
726         aTL.X() += maBackgroundMiddle.GetSizePixel().Width();
727     }
728     aDev.DrawBitmapEx( aTL, maBackgroundRight );
729 
730     DrawOutDev( aBmpRect.TopLeft(), aBmpRect.GetSize(),
731                 Point( 0, 0 ), aBmpRect.GetSize(),
732                 aDev );
733 }
734 
735 long BackingWindow::Notify( NotifyEvent& rNEvt )
736 {
737     if( rNEvt.GetType() == EVENT_KEYINPUT )
738     {
739         if( ! mpAccExec )
740         {
741             mpAccExec = svt::AcceleratorExecute::createAcceleratorHelper();
742             mpAccExec->init( comphelper::getProcessServiceFactory(), mxFrame);
743         }
744 
745         const KeyEvent* pEvt = rNEvt.GetKeyEvent();
746         const KeyCode& rKeyCode(pEvt->GetKeyCode());
747         if( pEvt && mpAccExec->execute(rKeyCode) )
748             return 1;
749         // #i110344# extrawurst: specialized arrow key control
750         if( rKeyCode.GetModifier() == 0 )
751         {
752             if( rKeyCode.GetCode() == KEY_RIGHT )
753             {
754                 if( maWriterButton.HasFocus() )
755                     maDrawButton.GrabFocus();
756                 else if( maCalcButton.HasFocus() )
757                     maDBButton.GrabFocus();
758                 else if( maImpressButton.HasFocus() )
759                     maMathButton.GrabFocus();
760                 else if( maOpenButton.HasFocus() )
761                     maTemplateButton.GrabFocus();
762                 return 1;
763             }
764             else if( rKeyCode.GetCode() == KEY_LEFT )
765             {
766                 if( maDrawButton.HasFocus() )
767                     maWriterButton.GrabFocus();
768                 else if( maDBButton.HasFocus() )
769                     maCalcButton.GrabFocus();
770                 else if( maMathButton.HasFocus() )
771                     maImpressButton.GrabFocus();
772                 else if( maTemplateButton.HasFocus() )
773                     maOpenButton.GrabFocus();
774                 return 1;
775             }
776             else if( rKeyCode.GetCode() == KEY_UP )
777             {
778                 // first column
779                 if( maOpenButton.HasFocus() )
780                     maImpressButton.GrabFocus();
781                 else if( maImpressButton.HasFocus() )
782                     maCalcButton.GrabFocus();
783                 else if( maCalcButton.HasFocus() )
784                     maWriterButton.GrabFocus();
785                 // second column
786                 else if( maTemplateButton.HasFocus() )
787                     maMathButton.GrabFocus();
788                 else if( maMathButton.HasFocus() )
789                     maDBButton.GrabFocus();
790                 else if( maDBButton.HasFocus() )
791                     maDrawButton.GrabFocus();
792                 return 1;
793             }
794             else if( rKeyCode.GetCode() == KEY_DOWN )
795             {
796                 // first column
797                 if( maWriterButton.HasFocus() )
798                     maCalcButton.GrabFocus();
799                 else if( maCalcButton.HasFocus() )
800                     maImpressButton.GrabFocus();
801                 else if( maImpressButton.HasFocus() )
802                     maOpenButton.GrabFocus();
803                 // second column
804                 else if( maDrawButton.HasFocus() )
805                     maDBButton.GrabFocus();
806                 else if( maDBButton.HasFocus() )
807                     maMathButton.GrabFocus();
808                 else if( maMathButton.HasFocus() )
809                     maTemplateButton.GrabFocus();
810                 return 1;
811             }
812         }
813     }
814     return Window::Notify( rNEvt );
815 }
816 
817 void BackingWindow::setOwningFrame( const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& xFrame )
818 {
819     mxFrame = xFrame;
820     if( ! mbInitControls )
821         initControls();
822 }
823 
824 void BackingWindow::Resize()
825 {
826     Size aWindowSize( GetSizePixel() );
827     Size aControlSize = maControlRect.GetSize();
828     maControlRect = Rectangle( Point( (aWindowSize.Width() - aControlSize.Width()) / 2,
829                                       (aWindowSize.Height() - aControlSize.Height()) / 2 ),
830                                aControlSize );
831 
832     maToolbox.calcMinSize();
833     Size aTBSize( maToolbox.getMinSize() );
834     Point aTBPos( maControlRect.Left() + mnBtnPos,
835                   maControlRect.Bottom() - aTBSize.Height() - 10 );
836     if( Application::GetSettings().GetLayoutRTL() )
837         aTBPos.X() = maControlRect.Right() - aTBSize.Width() - mnBtnPos;
838     maToolbox.SetPosSizePixel( aTBPos, aTBSize );
839 
840     // #i93631# squeeze controls so they fit into the box
841     // this can be necessary due to application font height which has small deviations
842     // from the size set
843     const long nWDelta    = maWelcomeSize.Height();
844     const long nW2Delta   = (maWelcomeSize.Height()*3)/2;
845     const long nPDelta    = (maProductSize.Height()*3)/2;
846     const long nBDelta    = maButtonImageSize.Height() + 10;
847     const long nB2Delta   = 3*maButtonImageSize.Height()/2;
848     const long nLastDelta = maButtonImageSize.Height();
849     long nDiff = 0;
850     while( ( maControlRect.Top()   +
851                  (nWDelta - nDiff) +
852                  (nW2Delta- nDiff) +
853                  (nPDelta - nDiff) +
854              3 * (nBDelta - nDiff) +
855                  (nB2Delta- nDiff) +
856                  nLastDelta
857             ) > aTBPos.Y() )
858     {
859         nDiff++;
860     }
861 
862     long nYPos = maControlRect.Top();
863     nYPos += nW2Delta - nDiff;
864     maWelcome.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ),
865                                 Size( maControlRect.GetWidth() - mnBtnPos - 5, (maWelcomeSize.Height()*20)/19 ) );
866     nYPos += nWDelta - nDiff;
867     maProduct.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( maControlRect.GetWidth() - mnBtnPos - 5, (maProductSize.Height()*20)/19 ) );
868     nYPos += nPDelta - nDiff;
869 
870     nYPos += nWDelta/2 - nDiff;
871 
872     if( mnLayoutStyle != 1 )
873         nYPos = maControlRect.Top() + mnBtnTop;
874 
875     maWriterButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
876     maDrawButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
877     nYPos += nBDelta - nDiff;
878     maCalcButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
879     maDBButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
880     nYPos += nBDelta - nDiff;
881     maImpressButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
882     maMathButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
883 
884     nYPos += nB2Delta - nDiff;
885     maOpenButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos, nYPos ), Size( mnTextColumnWidth[0], maButtonImageSize.Height() ) );
886     maTemplateButton.SetPosSizePixel( Point( maControlRect.Left() + mnBtnPos + mnColumnWidth[0], nYPos ), Size( mnTextColumnWidth[1], maButtonImageSize.Height() ) );
887 }
888 
889 IMPL_LINK( BackingWindow, ToolboxHdl, void*, EMPTYARG )
890 {
891     const char* pNodePath = NULL;
892     const char* pNode = NULL;
893 
894     switch( maToolbox.GetCurItemId() )
895     {
896     case nItemId_Extensions:
897         pNodePath = "/org.openoffice.Office.Common/Help/StartCenter";
898         pNode = "AddFeatureURL";
899         break;
900     case nItemId_Info:
901         pNodePath = "/org.openoffice.Office.Common/Help/StartCenter";
902         pNode = "InfoURL";
903         break;
904     case nItemId_TplRep:
905         pNodePath = "/org.openoffice.Office.Common/Help/StartCenter";
906         pNode = "TemplateRepositoryURL";
907         break;
908     default:
909         break;
910     }
911     if( pNodePath && pNode )
912     {
913         try
914         {
915             Reference<lang::XMultiServiceFactory> xConfig( comphelper::getProcessServiceFactory()->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY);
916             if( xConfig.is() )
917             {
918                 Sequence<Any> args(1);
919                 PropertyValue val(
920                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("nodepath") ),
921                     0,
922                     Any(rtl::OUString::createFromAscii(pNodePath)),
923                     PropertyState_DIRECT_VALUE);
924                 args.getArray()[0] <<= val;
925                 Reference<container::XNameAccess> xNameAccess(xConfig->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,args), UNO_QUERY);
926                 if( xNameAccess.is() )
927                 {
928                     rtl::OUString sURL;
929                     //throws css::container::NoSuchElementException, css::lang::WrappedTargetException
930                     Any value( xNameAccess->getByName(rtl::OUString::createFromAscii(pNode)) );
931                     sURL = value.get<rtl::OUString> ();
932 
933                     // extend the URLs with Office locale argument
934                     INetURLObject aURLObj( sURL );
935 
936                     rtl::OUString sParam = aURLObj.GetParam();
937                     rtl::OUStringBuffer aURLBuf( sParam );
938                     if ( sParam.getLength() > 0 )
939                         aURLBuf.appendAscii( "&" );
940                     aURLBuf.appendAscii( "lang=" );
941 
942                     // read locale from configuration
943                     ::rtl::OUString sLocale;
944                     ::rtl::OUString sPackage = ::rtl::OUString::createFromAscii("org.openoffice.Setup");
945                     ::rtl::OUString sRelPath = ::rtl::OUString::createFromAscii("L10N");
946                     ::rtl::OUString sKey     = ::rtl::OUString::createFromAscii("ooLocale");
947 
948                     try
949                     {
950                         ::comphelper::ConfigurationHelper::readDirectKey(comphelper::getProcessServiceFactory(),
951                                                                          sPackage,
952                                                                          sRelPath,
953                                                                          sKey,
954                                                                          ::comphelper::ConfigurationHelper::E_READONLY) >>= sLocale;
955                     }
956                     catch(const com::sun::star::uno::RuntimeException& exRun)
957                         { throw exRun; }
958                     catch(const com::sun::star::uno::Exception&)
959                     { sLocale = ::rtl::OUString::createFromAscii("en-US"); }
960 
961                     aURLBuf.append(sLocale);
962 
963                     sParam = aURLBuf.makeStringAndClear();
964 
965                     aURLObj.SetParam( sParam );
966                     sURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
967 
968                     Reference< com::sun::star::system::XSystemShellExecute > xSystemShellExecute(
969                         comphelper::getProcessServiceFactory()->createInstance(
970                             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SystemShellExecute" ) ) ),
971                         UNO_QUERY_THROW);
972                     //throws css::lang::IllegalArgumentException, css::system::SystemShellExecuteException
973                     xSystemShellExecute->execute( sURL, rtl::OUString(), com::sun::star::system::SystemShellExecuteFlags::DEFAULTS);
974                 }
975             }
976         }
977         catch (Exception& )
978         {
979         }
980     }
981 
982     return 0;
983 }
984 
985 IMPL_LINK( BackingWindow, ClickHdl, Button*, pButton )
986 {
987     // dispatch the appropriate URL and end the dialog
988     if( pButton == &maWriterButton )
989         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(WRITER_URL) ) );
990     else if( pButton == &maCalcButton )
991         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(CALC_URL) ) );
992     else if( pButton == &maImpressButton )
993         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(IMPRESS_WIZARD_URL) ) );
994     else if( pButton == &maDrawButton )
995         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(DRAW_URL) ) );
996     else if( pButton == &maDBButton )
997         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(BASE_URL) ) );
998     else if( pButton == &maMathButton )
999         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(MATH_URL) ) );
1000     else if( pButton == &maOpenButton )
1001     {
1002         Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
1003 
1004         Sequence< com::sun::star::beans::PropertyValue > aArgs(1);
1005         PropertyValue* pArg = aArgs.getArray();
1006         pArg[0].Name = rtl::OUString::createFromAscii("Referer");
1007         pArg[0].Value <<= rtl::OUString::createFromAscii("private:user");
1008 
1009         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(OPEN_URL) ), rtl::OUString(), xFrame, aArgs );
1010     }
1011     else if( pButton == &maTemplateButton )
1012     {
1013         Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
1014 
1015         Sequence< com::sun::star::beans::PropertyValue > aArgs(1);
1016         PropertyValue* pArg = aArgs.getArray();
1017         pArg[0].Name = rtl::OUString::createFromAscii("Referer");
1018         pArg[0].Value <<= rtl::OUString::createFromAscii("private:user");
1019 
1020         dispatchURL( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(TEMPLATE_URL) ), rtl::OUString(), xFrame, aArgs );
1021     }
1022     return 0;
1023 }
1024 
1025 IMPL_LINK( BackingWindow, SelectHdl, Button*, pButton )
1026 {
1027     if( pButton == &maOpenButton )
1028     {
1029         sal_Int32 nItem = sal_Int32(maOpenButton.GetCurItemId())-1;
1030         if( nItem >= 0 && nItem < sal_Int32(maRecentFiles.size()) )
1031         {
1032             Reference< XDispatchProvider > xFrame( mxFrame, UNO_QUERY );
1033             dispatchURL( maRecentFiles[nItem].aTargetURL, rtl::OUString(), xFrame, maRecentFiles[nItem].aArgSeq );
1034         }
1035     }
1036     return 0;
1037 }
1038 
1039 IMPL_LINK( BackingWindow, ActivateHdl, Button*, pButton )
1040 {
1041     if( pButton == &maOpenButton )
1042         prepareRecentFileMenu();
1043     return 0;
1044 }
1045 
1046 struct ImplDelayedDispatch
1047 {
1048     Reference< XDispatch >      xDispatch;
1049     com::sun::star::util::URL   aDispatchURL;
1050     Sequence< PropertyValue >   aArgs;
1051 
1052     ImplDelayedDispatch( const Reference< XDispatch >& i_xDispatch,
1053                          const com::sun::star::util::URL& i_rURL,
1054                          const Sequence< PropertyValue >& i_rArgs )
1055     : xDispatch( i_xDispatch ),
1056       aDispatchURL( i_rURL ),
1057       aArgs( i_rArgs )
1058     {
1059     }
1060     ~ImplDelayedDispatch() {}
1061 };
1062 
1063 static long implDispatchDelayed( void*, void* pArg )
1064 {
1065     struct ImplDelayedDispatch* pDispatch = reinterpret_cast<ImplDelayedDispatch*>(pArg);
1066     try
1067     {
1068         pDispatch->xDispatch->dispatch( pDispatch->aDispatchURL, pDispatch->aArgs );
1069     }
1070     catch( Exception )
1071     {
1072     }
1073 
1074     // clean up
1075     delete pDispatch;
1076 
1077     return 0;
1078 }
1079 
1080 void BackingWindow::dispatchURL( const rtl::OUString& i_rURL,
1081                                  const rtl::OUString& rTarget,
1082                                  const Reference< XDispatchProvider >& i_xProv,
1083                                  const Sequence< PropertyValue >& i_rArgs )
1084 {
1085     // if no special dispatch provider is given, get the desktop
1086     Reference< XDispatchProvider > xProvider( i_xProv.is() ? i_xProv : mxDesktopDispatchProvider );
1087 
1088     // check for dispatch provider
1089     if( !xProvider.is())
1090         return;
1091 
1092     // get an URL transformer to clean up the URL
1093     com::sun::star::util::URL aDispatchURL;
1094     aDispatchURL.Complete = i_rURL;
1095 
1096     Reference < com::sun::star::util::XURLTransformer > xURLTransformer(
1097         comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer") ),
1098         com::sun::star::uno::UNO_QUERY );
1099     if ( xURLTransformer.is() )
1100     {
1101         try
1102         {
1103             // clean up the URL
1104             xURLTransformer->parseStrict( aDispatchURL );
1105             // get a Dispatch for the URL and target
1106             Reference< XDispatch > xDispatch(
1107                 xProvider->queryDispatch( aDispatchURL, rTarget, 0 )
1108                 );
1109             // dispatch the URL
1110             if ( xDispatch.is() )
1111             {
1112                 ImplDelayedDispatch* pDisp = new ImplDelayedDispatch( xDispatch, aDispatchURL, i_rArgs );
1113                 sal_uLong nEventId = 0;
1114                 if( ! Application::PostUserEvent( nEventId, Link( NULL, implDispatchDelayed ), pDisp ) )
1115                     delete pDisp; // event could not be posted for unknown reason, at least don't leak
1116             }
1117         }
1118         catch ( com::sun::star::uno::RuntimeException& )
1119         {
1120             throw;
1121         }
1122         catch ( com::sun::star::uno::Exception& )
1123         {
1124         }
1125     }
1126 }
1127 
1128