1*5900e8ecSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*5900e8ecSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*5900e8ecSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*5900e8ecSAndrew Rist  * distributed with this work for additional information
6*5900e8ecSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*5900e8ecSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*5900e8ecSAndrew Rist  * "License"); you may not use this file except in compliance
9*5900e8ecSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*5900e8ecSAndrew Rist  *
11*5900e8ecSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*5900e8ecSAndrew Rist  *
13*5900e8ecSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*5900e8ecSAndrew Rist  * software distributed under the License is distributed on an
15*5900e8ecSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*5900e8ecSAndrew Rist  * KIND, either express or implied.  See the License for the
17*5900e8ecSAndrew Rist  * specific language governing permissions and limitations
18*5900e8ecSAndrew Rist  * under the License.
19*5900e8ecSAndrew Rist  *
20*5900e8ecSAndrew Rist  *************************************************************/
21*5900e8ecSAndrew Rist 
22*5900e8ecSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svtools.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <svtools/contextmenuhelper.hxx>
28cdf0e10cSrcweir #include <svtools/menuoptions.hxx>
29cdf0e10cSrcweir #include <svtools/miscopt.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <com/sun/star/frame/XDispatch.hpp>
32cdf0e10cSrcweir #include <com/sun/star/frame/XDispatchProvider.hpp>
33cdf0e10cSrcweir #include <com/sun/star/frame/XModuleManager.hpp>
34cdf0e10cSrcweir #include <com/sun/star/frame/XStatusListener.hpp>
35cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36cdf0e10cSrcweir #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
37cdf0e10cSrcweir #include <com/sun/star/ui/XUIConfigurationManager.hpp>
38cdf0e10cSrcweir #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
39cdf0e10cSrcweir #include <com/sun/star/ui/ImageType.hpp>
40cdf0e10cSrcweir #include <com/sun/star/beans/PropertyValue.hpp>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #include <osl/conditn.hxx>
43cdf0e10cSrcweir #include <cppuhelper/weak.hxx>
44cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
45cdf0e10cSrcweir #include <vos/mutex.hxx>
46cdf0e10cSrcweir #include <vcl/svapp.hxx>
47cdf0e10cSrcweir #include <vcl/image.hxx>
48cdf0e10cSrcweir #include <toolkit/unohlp.hxx>
49cdf0e10cSrcweir #include <toolkit/awt/vclxwindow.hxx>
50cdf0e10cSrcweir #include <toolkit/awt/vclxmenu.hxx>
51cdf0e10cSrcweir 
52cdf0e10cSrcweir using namespace ::com::sun::star;
53cdf0e10cSrcweir 
54cdf0e10cSrcweir namespace svt
55cdf0e10cSrcweir {
56cdf0e10cSrcweir 
57cdf0e10cSrcweir // internal helper class to retrieve status updates
58cdf0e10cSrcweir class StateEventHelper : public ::com::sun::star::frame::XStatusListener,
59cdf0e10cSrcweir                          public ::cppu::OWeakObject
60cdf0e10cSrcweir {
61cdf0e10cSrcweir     public:
62cdf0e10cSrcweir         StateEventHelper( const uno::Reference< frame::XDispatchProvider >& xDispatchProvider,
63cdf0e10cSrcweir                           const uno::Reference< util::XURLTransformer >& xURLTransformer,
64cdf0e10cSrcweir                           const rtl::OUString& aCommandURL );
65cdf0e10cSrcweir         virtual ~StateEventHelper();
66cdf0e10cSrcweir 
67cdf0e10cSrcweir         bool isCommandEnabled();
68cdf0e10cSrcweir 
69cdf0e10cSrcweir 		// XInterface
70cdf0e10cSrcweir 		virtual uno::Any SAL_CALL queryInterface( const uno::Type& aType ) throw ( uno::RuntimeException);
71cdf0e10cSrcweir 		virtual void SAL_CALL acquire() throw ();
72cdf0e10cSrcweir 		virtual void SAL_CALL release() throw ();
73cdf0e10cSrcweir 
74cdf0e10cSrcweir         // XEventListener
75cdf0e10cSrcweir 	    virtual void SAL_CALL disposing(const lang::EventObject& Source) throw( uno::RuntimeException );
76cdf0e10cSrcweir 
77cdf0e10cSrcweir         // XStatusListener
78cdf0e10cSrcweir 	    virtual void SAL_CALL statusChanged(const frame::FeatureStateEvent& Event) throw( uno::RuntimeException );
79cdf0e10cSrcweir 
80cdf0e10cSrcweir     private:
81cdf0e10cSrcweir         StateEventHelper();
82cdf0e10cSrcweir         StateEventHelper( const StateEventHelper& );
83cdf0e10cSrcweir         StateEventHelper& operator=( const StateEventHelper& );
84cdf0e10cSrcweir 
85cdf0e10cSrcweir         bool                                       m_bCurrentCommandEnabled;
86cdf0e10cSrcweir         ::rtl::OUString                            m_aCommandURL;
87cdf0e10cSrcweir         uno::Reference< frame::XDispatchProvider > m_xDispatchProvider;
88cdf0e10cSrcweir         uno::Reference< util::XURLTransformer >    m_xURLTransformer;
89cdf0e10cSrcweir         osl::Condition                             m_aCondition;
90cdf0e10cSrcweir };
91cdf0e10cSrcweir 
92cdf0e10cSrcweir StateEventHelper::StateEventHelper(
93cdf0e10cSrcweir     const uno::Reference< frame::XDispatchProvider >& xDispatchProvider,
94cdf0e10cSrcweir     const uno::Reference< util::XURLTransformer >& xURLTransformer,
95cdf0e10cSrcweir     const rtl::OUString& rCommandURL ) :
96cdf0e10cSrcweir     m_bCurrentCommandEnabled( true ),
97cdf0e10cSrcweir     m_aCommandURL( rCommandURL ),
98cdf0e10cSrcweir     m_xDispatchProvider( xDispatchProvider ),
99cdf0e10cSrcweir     m_xURLTransformer( xURLTransformer )
100cdf0e10cSrcweir {
101cdf0e10cSrcweir     m_aCondition.reset();
102cdf0e10cSrcweir }
103cdf0e10cSrcweir 
104cdf0e10cSrcweir StateEventHelper::~StateEventHelper()
105cdf0e10cSrcweir {}
106cdf0e10cSrcweir 
107cdf0e10cSrcweir uno::Any SAL_CALL StateEventHelper::queryInterface(
108cdf0e10cSrcweir     const uno::Type& aType )
109cdf0e10cSrcweir throw ( uno::RuntimeException )
110cdf0e10cSrcweir {
111cdf0e10cSrcweir     uno::Any a = ::cppu::queryInterface(
112cdf0e10cSrcweir 				aType,
113cdf0e10cSrcweir 				SAL_STATIC_CAST( XStatusListener*, this ));
114cdf0e10cSrcweir 
115cdf0e10cSrcweir 	if( a.hasValue() )
116cdf0e10cSrcweir 		return a;
117cdf0e10cSrcweir 
118cdf0e10cSrcweir     return ::cppu::OWeakObject::queryInterface( aType );
119cdf0e10cSrcweir }
120cdf0e10cSrcweir 
121cdf0e10cSrcweir void SAL_CALL StateEventHelper::acquire()
122cdf0e10cSrcweir throw ()
123cdf0e10cSrcweir {
124cdf0e10cSrcweir     ::cppu::OWeakObject::acquire();
125cdf0e10cSrcweir }
126cdf0e10cSrcweir 
127cdf0e10cSrcweir void SAL_CALL StateEventHelper::release()
128cdf0e10cSrcweir throw ()
129cdf0e10cSrcweir {
130cdf0e10cSrcweir     ::cppu::OWeakObject::release();
131cdf0e10cSrcweir }
132cdf0e10cSrcweir 
133cdf0e10cSrcweir void SAL_CALL StateEventHelper::disposing(
134cdf0e10cSrcweir     const lang::EventObject& )
135cdf0e10cSrcweir throw ( uno::RuntimeException )
136cdf0e10cSrcweir {
137cdf0e10cSrcweir     vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
138cdf0e10cSrcweir     m_xDispatchProvider.clear();
139cdf0e10cSrcweir     m_xURLTransformer.clear();
140cdf0e10cSrcweir     m_aCondition.set();
141cdf0e10cSrcweir }
142cdf0e10cSrcweir 
143cdf0e10cSrcweir void SAL_CALL StateEventHelper::statusChanged(
144cdf0e10cSrcweir     const frame::FeatureStateEvent& Event )
145cdf0e10cSrcweir throw ( uno::RuntimeException )
146cdf0e10cSrcweir {
147cdf0e10cSrcweir     vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
148cdf0e10cSrcweir     m_bCurrentCommandEnabled = Event.IsEnabled;
149cdf0e10cSrcweir     m_aCondition.set();
150cdf0e10cSrcweir }
151cdf0e10cSrcweir 
152cdf0e10cSrcweir bool StateEventHelper::isCommandEnabled()
153cdf0e10cSrcweir {
154cdf0e10cSrcweir     // Be sure that we cannot die during condition wait
155cdf0e10cSrcweir     uno::Reference< frame::XStatusListener > xSelf(
156cdf0e10cSrcweir         SAL_STATIC_CAST( frame::XStatusListener*, this ));
157cdf0e10cSrcweir 
158cdf0e10cSrcweir     uno::Reference< frame::XDispatch > xDispatch;
159cdf0e10cSrcweir     util::URL                          aTargetURL;
160cdf0e10cSrcweir     {
161cdf0e10cSrcweir         vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
162cdf0e10cSrcweir         if ( m_xDispatchProvider.is() && m_xURLTransformer.is() )
163cdf0e10cSrcweir         {
164cdf0e10cSrcweir             ::rtl::OUString aSelf( RTL_CONSTASCII_USTRINGPARAM( "_self" ));
165cdf0e10cSrcweir 
166cdf0e10cSrcweir             aTargetURL.Complete = m_aCommandURL;
167cdf0e10cSrcweir             m_xURLTransformer->parseStrict( aTargetURL );
168cdf0e10cSrcweir 
169cdf0e10cSrcweir             try
170cdf0e10cSrcweir             {
171cdf0e10cSrcweir                 xDispatch = m_xDispatchProvider->queryDispatch( aTargetURL, aSelf, 0 );
172cdf0e10cSrcweir             }
173cdf0e10cSrcweir             catch ( uno::RuntimeException& )
174cdf0e10cSrcweir             {
175cdf0e10cSrcweir                 throw;
176cdf0e10cSrcweir             }
177cdf0e10cSrcweir             catch ( uno::Exception& )
178cdf0e10cSrcweir             {
179cdf0e10cSrcweir             }
180cdf0e10cSrcweir         }
181cdf0e10cSrcweir     }
182cdf0e10cSrcweir 
183cdf0e10cSrcweir     bool bResult( false );
184cdf0e10cSrcweir     if ( xDispatch.is() )
185cdf0e10cSrcweir     {
186cdf0e10cSrcweir         try
187cdf0e10cSrcweir         {
188cdf0e10cSrcweir             // add/remove ourself to retrieve status by callback
189cdf0e10cSrcweir             xDispatch->addStatusListener( xSelf, aTargetURL );
190cdf0e10cSrcweir             xDispatch->removeStatusListener( xSelf, aTargetURL );
191cdf0e10cSrcweir 
192cdf0e10cSrcweir             // wait for anwser
193cdf0e10cSrcweir             m_aCondition.wait();
194cdf0e10cSrcweir         }
195cdf0e10cSrcweir         catch ( uno::RuntimeException& )
196cdf0e10cSrcweir         {
197cdf0e10cSrcweir             throw;
198cdf0e10cSrcweir         }
199cdf0e10cSrcweir         catch ( uno::Exception& )
200cdf0e10cSrcweir         {
201cdf0e10cSrcweir         }
202cdf0e10cSrcweir 
203cdf0e10cSrcweir         vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
204cdf0e10cSrcweir         bResult = m_bCurrentCommandEnabled;
205cdf0e10cSrcweir     }
206cdf0e10cSrcweir 
207cdf0e10cSrcweir     return bResult;
208cdf0e10cSrcweir }
209cdf0e10cSrcweir 
210cdf0e10cSrcweir /*************************************************************************/
211cdf0e10cSrcweir 
212cdf0e10cSrcweir struct ExecuteInfo
213cdf0e10cSrcweir {
214cdf0e10cSrcweir     uno::Reference< frame::XDispatch >    xDispatch;
215cdf0e10cSrcweir     util::URL                             aTargetURL;
216cdf0e10cSrcweir     uno::Sequence< beans::PropertyValue > aArgs;
217cdf0e10cSrcweir };
218cdf0e10cSrcweir 
219cdf0e10cSrcweir static const PopupMenu* lcl_FindPopupFromItemId( const PopupMenu* pPopupMenu, sal_uInt16 nItemId )
220cdf0e10cSrcweir {
221cdf0e10cSrcweir     if ( pPopupMenu )
222cdf0e10cSrcweir     {
223cdf0e10cSrcweir         sal_uInt16 nCount = pPopupMenu->GetItemCount();
224cdf0e10cSrcweir         for ( sal_uInt16 i = 0; i < nCount; i++ )
225cdf0e10cSrcweir         {
226cdf0e10cSrcweir             sal_uInt16 nId = pPopupMenu->GetItemId( i );
227cdf0e10cSrcweir             if ( nId == nItemId )
228cdf0e10cSrcweir                 return pPopupMenu;
229cdf0e10cSrcweir             else
230cdf0e10cSrcweir             {
231cdf0e10cSrcweir                 const PopupMenu* pResult( 0 );
232cdf0e10cSrcweir 
233cdf0e10cSrcweir                 const PopupMenu* pSubPopup = pPopupMenu->GetPopupMenu( i );
234cdf0e10cSrcweir                 if ( pPopupMenu )
235cdf0e10cSrcweir                     pResult = lcl_FindPopupFromItemId( pSubPopup, nItemId );
236cdf0e10cSrcweir                 if ( pResult != 0 )
237cdf0e10cSrcweir                     return pResult;
238cdf0e10cSrcweir             }
239cdf0e10cSrcweir         }
240cdf0e10cSrcweir     }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir     return NULL;
243cdf0e10cSrcweir }
244cdf0e10cSrcweir 
245cdf0e10cSrcweir static ::rtl::OUString lcl_GetItemCommandRecursive( const PopupMenu* pPopupMenu, sal_uInt16 nItemId )
246cdf0e10cSrcweir {
247cdf0e10cSrcweir     const PopupMenu* pPopup = lcl_FindPopupFromItemId( pPopupMenu, nItemId );
248cdf0e10cSrcweir     if ( pPopup )
249cdf0e10cSrcweir         return pPopup->GetItemCommand( nItemId );
250cdf0e10cSrcweir     else
251cdf0e10cSrcweir         return ::rtl::OUString();
252cdf0e10cSrcweir }
253cdf0e10cSrcweir 
254cdf0e10cSrcweir /*************************************************************************/
255cdf0e10cSrcweir 
256cdf0e10cSrcweir ContextMenuHelper::ContextMenuHelper(
257cdf0e10cSrcweir     const uno::Reference< frame::XFrame >& xFrame,
258cdf0e10cSrcweir     bool bAutoRefresh ) :
259cdf0e10cSrcweir     m_xWeakFrame( xFrame ),
260cdf0e10cSrcweir     m_aSelf( RTL_CONSTASCII_USTRINGPARAM( "_self" )),
261cdf0e10cSrcweir     m_bAutoRefresh( bAutoRefresh ),
262cdf0e10cSrcweir     m_bUICfgMgrAssociated( false )
263cdf0e10cSrcweir {
264cdf0e10cSrcweir }
265cdf0e10cSrcweir 
266cdf0e10cSrcweir ContextMenuHelper::~ContextMenuHelper()
267cdf0e10cSrcweir {
268cdf0e10cSrcweir }
269cdf0e10cSrcweir 
270cdf0e10cSrcweir void
271cdf0e10cSrcweir ContextMenuHelper::completeAndExecute(
272cdf0e10cSrcweir     const Point& aPos,
273cdf0e10cSrcweir     PopupMenu& rPopupMenu )
274cdf0e10cSrcweir {
275cdf0e10cSrcweir     vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
276cdf0e10cSrcweir 
277cdf0e10cSrcweir     associateUIConfigurationManagers();
278cdf0e10cSrcweir     completeMenuProperties( &rPopupMenu );
279cdf0e10cSrcweir     executePopupMenu( aPos, &rPopupMenu );
280cdf0e10cSrcweir     resetAssociations();
281cdf0e10cSrcweir }
282cdf0e10cSrcweir 
283cdf0e10cSrcweir void
284cdf0e10cSrcweir ContextMenuHelper::completeAndExecute(
285cdf0e10cSrcweir     const Point& aPos,
286cdf0e10cSrcweir     const uno::Reference< awt::XPopupMenu >& xPopupMenu )
287cdf0e10cSrcweir {
288cdf0e10cSrcweir     vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
289cdf0e10cSrcweir 
290cdf0e10cSrcweir     VCLXMenu* pXMenu = VCLXMenu::GetImplementation( xPopupMenu );
291cdf0e10cSrcweir     if ( pXMenu )
292cdf0e10cSrcweir     {
293cdf0e10cSrcweir         PopupMenu* pPopupMenu = dynamic_cast< PopupMenu* >( pXMenu->GetMenu() );
294cdf0e10cSrcweir         // as dynamic_cast can return zero check pointer
295cdf0e10cSrcweir         if ( pPopupMenu )
296cdf0e10cSrcweir         {
297cdf0e10cSrcweir             associateUIConfigurationManagers();
298cdf0e10cSrcweir             completeMenuProperties( pPopupMenu );
299cdf0e10cSrcweir             executePopupMenu( aPos, pPopupMenu );
300cdf0e10cSrcweir             resetAssociations();
301cdf0e10cSrcweir         }
302cdf0e10cSrcweir     }
303cdf0e10cSrcweir }
304cdf0e10cSrcweir 
305cdf0e10cSrcweir uno::Reference< awt::XPopupMenu >
306cdf0e10cSrcweir ContextMenuHelper::create(
307cdf0e10cSrcweir     const ::rtl::OUString& /*aPopupMenuResourceId*/ )
308cdf0e10cSrcweir {
309cdf0e10cSrcweir     // NOT IMPLEMENTED YET!
310cdf0e10cSrcweir     return uno::Reference< awt::XPopupMenu >();
311cdf0e10cSrcweir }
312cdf0e10cSrcweir 
313cdf0e10cSrcweir bool
314cdf0e10cSrcweir ContextMenuHelper::createAndExecute(
315cdf0e10cSrcweir     const Point& /*aPos*/,
316cdf0e10cSrcweir     const ::rtl::OUString& /*aPopupMenuResourceId*/ )
317cdf0e10cSrcweir {
318cdf0e10cSrcweir     // NOT IMPLEMENTED YET!
319cdf0e10cSrcweir     return false;
320cdf0e10cSrcweir }
321cdf0e10cSrcweir 
322cdf0e10cSrcweir // private member
323cdf0e10cSrcweir 
324cdf0e10cSrcweir void
325cdf0e10cSrcweir ContextMenuHelper::executePopupMenu(
326cdf0e10cSrcweir     const Point& rPos,
327cdf0e10cSrcweir     PopupMenu* pMenu )
328cdf0e10cSrcweir {
329cdf0e10cSrcweir     if ( pMenu )
330cdf0e10cSrcweir     {
331cdf0e10cSrcweir         uno::Reference< frame::XFrame > xFrame( m_xWeakFrame );
332cdf0e10cSrcweir         if ( xFrame.is() )
333cdf0e10cSrcweir         {
334cdf0e10cSrcweir             uno::Reference< awt::XWindow > xWindow( xFrame->getContainerWindow() );
335cdf0e10cSrcweir             if ( xWindow.is() )
336cdf0e10cSrcweir             {
337cdf0e10cSrcweir                 Window* pParent = VCLUnoHelper::GetWindow( xWindow );
338cdf0e10cSrcweir                 sal_uInt16 nResult = pMenu->Execute( pParent, rPos );
339cdf0e10cSrcweir 
340cdf0e10cSrcweir                 if ( nResult > 0 )
341cdf0e10cSrcweir                 {
342cdf0e10cSrcweir                     ::rtl::OUString aCommand = lcl_GetItemCommandRecursive( pMenu, nResult );
343cdf0e10cSrcweir                     if ( aCommand.getLength() > 0 )
344cdf0e10cSrcweir                         dispatchCommand( xFrame, aCommand );
345cdf0e10cSrcweir                 }
346cdf0e10cSrcweir             }
347cdf0e10cSrcweir         }
348cdf0e10cSrcweir     }
349cdf0e10cSrcweir }
350cdf0e10cSrcweir 
351cdf0e10cSrcweir bool
352cdf0e10cSrcweir ContextMenuHelper::dispatchCommand(
353cdf0e10cSrcweir     const uno::Reference< ::frame::XFrame >& rFrame,
354cdf0e10cSrcweir     const ::rtl::OUString& aCommandURL )
355cdf0e10cSrcweir {
356cdf0e10cSrcweir     if ( !m_xURLTransformer.is() )
357cdf0e10cSrcweir     {
358cdf0e10cSrcweir         m_xURLTransformer = uno::Reference< util::XURLTransformer >(
359cdf0e10cSrcweir             ::comphelper::getProcessServiceFactory()->createInstance(
360cdf0e10cSrcweir                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
361cdf0e10cSrcweir                     "com.sun.star.util.URLTransformer" ))),
362cdf0e10cSrcweir             uno::UNO_QUERY );
363cdf0e10cSrcweir     }
364cdf0e10cSrcweir 
365cdf0e10cSrcweir     util::URL aTargetURL;
366cdf0e10cSrcweir     uno::Reference< frame::XDispatch > xDispatch;
367cdf0e10cSrcweir     if ( m_xURLTransformer.is() )
368cdf0e10cSrcweir     {
369cdf0e10cSrcweir         aTargetURL.Complete = aCommandURL;
370cdf0e10cSrcweir         m_xURLTransformer->parseStrict( aTargetURL );
371cdf0e10cSrcweir 
372cdf0e10cSrcweir         uno::Reference< frame::XDispatchProvider > xDispatchProvider(
373cdf0e10cSrcweir             rFrame, uno::UNO_QUERY );
374cdf0e10cSrcweir         if ( xDispatchProvider.is() )
375cdf0e10cSrcweir         {
376cdf0e10cSrcweir             try
377cdf0e10cSrcweir             {
378cdf0e10cSrcweir                 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, m_aSelf, 0 );
379cdf0e10cSrcweir             }
380cdf0e10cSrcweir             catch ( uno::RuntimeException& )
381cdf0e10cSrcweir             {
382cdf0e10cSrcweir                 throw;
383cdf0e10cSrcweir             }
384cdf0e10cSrcweir             catch ( uno::Exception& )
385cdf0e10cSrcweir             {
386cdf0e10cSrcweir             }
387cdf0e10cSrcweir         }
388cdf0e10cSrcweir     }
389cdf0e10cSrcweir 
390cdf0e10cSrcweir     if ( xDispatch.is() )
391cdf0e10cSrcweir     {
392cdf0e10cSrcweir         ExecuteInfo* pExecuteInfo = new ExecuteInfo;
393cdf0e10cSrcweir         pExecuteInfo->xDispatch    = xDispatch;
394cdf0e10cSrcweir         pExecuteInfo->aTargetURL   = aTargetURL;
395cdf0e10cSrcweir         pExecuteInfo->aArgs        = m_aDefaultArgs;
396cdf0e10cSrcweir 
397cdf0e10cSrcweir         Application::PostUserEvent( STATIC_LINK(0, ContextMenuHelper , ExecuteHdl_Impl), pExecuteInfo );
398cdf0e10cSrcweir         return true;
399cdf0e10cSrcweir     }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir     return false;
402cdf0e10cSrcweir }
403cdf0e10cSrcweir 
404cdf0e10cSrcweir // retrieves and stores references to our user-interface
405cdf0e10cSrcweir // configuration managers, like image manager, ui command
406cdf0e10cSrcweir // description manager.
407cdf0e10cSrcweir bool
408cdf0e10cSrcweir ContextMenuHelper::associateUIConfigurationManagers()
409cdf0e10cSrcweir {
410cdf0e10cSrcweir     uno::Reference< frame::XFrame > xFrame( m_xWeakFrame );
411cdf0e10cSrcweir     if ( !m_bUICfgMgrAssociated && xFrame.is() )
412cdf0e10cSrcweir     {
413cdf0e10cSrcweir         // clear current state
414cdf0e10cSrcweir         m_xDocImageMgr.clear();
415cdf0e10cSrcweir         m_xModuleImageMgr.clear();
416cdf0e10cSrcweir         m_xUICommandLabels.clear();
417cdf0e10cSrcweir 
418cdf0e10cSrcweir         try
419cdf0e10cSrcweir         {
420cdf0e10cSrcweir             uno::Reference < frame::XController > xController;
421cdf0e10cSrcweir             uno::Reference < frame::XModel > xModel;
422cdf0e10cSrcweir             xController = xFrame->getController();
423cdf0e10cSrcweir             if ( xController.is() )
424cdf0e10cSrcweir                 xModel = xController->getModel();
425cdf0e10cSrcweir 
426cdf0e10cSrcweir             if ( xModel.is() )
427cdf0e10cSrcweir             {
428cdf0e10cSrcweir                 // retrieve document image manager form model
429cdf0e10cSrcweir                 uno::Reference< ui::XUIConfigurationManagerSupplier > xSupplier( xModel, uno::UNO_QUERY );
430cdf0e10cSrcweir                 if ( xSupplier.is() )
431cdf0e10cSrcweir                 {
432cdf0e10cSrcweir                     uno::Reference< ui::XUIConfigurationManager > xDocUICfgMgr(
433cdf0e10cSrcweir                         xSupplier->getUIConfigurationManager(), uno::UNO_QUERY );
434cdf0e10cSrcweir                     m_xDocImageMgr = uno::Reference< ui::XImageManager >(
435cdf0e10cSrcweir                         xDocUICfgMgr->getImageManager(), uno::UNO_QUERY );
436cdf0e10cSrcweir                 }
437cdf0e10cSrcweir             }
438cdf0e10cSrcweir 
439cdf0e10cSrcweir             uno::Reference< frame::XModuleManager > xModuleManager(
440cdf0e10cSrcweir                 ::comphelper::getProcessServiceFactory()->createInstance(
441cdf0e10cSrcweir                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
442cdf0e10cSrcweir                         "com.sun.star.frame.ModuleManager" ))),
443cdf0e10cSrcweir                 uno::UNO_QUERY );
444cdf0e10cSrcweir 
445cdf0e10cSrcweir             uno::Reference< ui::XImageManager > xModuleImageManager;
446cdf0e10cSrcweir             rtl::OUString                       aModuleId;
447cdf0e10cSrcweir             if ( xModuleManager.is() )
448cdf0e10cSrcweir             {
449cdf0e10cSrcweir                 // retrieve module image manager
450cdf0e10cSrcweir                 aModuleId = xModuleManager->identify( xFrame );
451cdf0e10cSrcweir 
452cdf0e10cSrcweir                 uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier(
453cdf0e10cSrcweir                     ::comphelper::getProcessServiceFactory()->createInstance(
454cdf0e10cSrcweir                         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
455cdf0e10cSrcweir                             "com.sun.star.ui.ModuleUIConfigurationManagerSupplier" ))),
456cdf0e10cSrcweir                         uno::UNO_QUERY );
457cdf0e10cSrcweir                 if ( xModuleCfgMgrSupplier.is() )
458cdf0e10cSrcweir                 {
459cdf0e10cSrcweir                     uno::Reference< ui::XUIConfigurationManager > xUICfgMgr(
460cdf0e10cSrcweir                         xModuleCfgMgrSupplier->getUIConfigurationManager( aModuleId ));
461cdf0e10cSrcweir                     if ( xUICfgMgr.is() )
462cdf0e10cSrcweir                     {
463cdf0e10cSrcweir                         m_xModuleImageMgr = uno::Reference< ui::XImageManager >(
464cdf0e10cSrcweir                             xUICfgMgr->getImageManager(), uno::UNO_QUERY );
465cdf0e10cSrcweir                     }
466cdf0e10cSrcweir                 }
467cdf0e10cSrcweir             }
468cdf0e10cSrcweir 
469cdf0e10cSrcweir             uno::Reference< container::XNameAccess > xNameAccess(
470cdf0e10cSrcweir                 ::comphelper::getProcessServiceFactory()->createInstance(
471cdf0e10cSrcweir                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
472cdf0e10cSrcweir                         "com.sun.star.frame.UICommandDescription" ))),
473cdf0e10cSrcweir                     uno::UNO_QUERY );
474cdf0e10cSrcweir             if ( xNameAccess.is() )
475cdf0e10cSrcweir             {
476cdf0e10cSrcweir                 try
477cdf0e10cSrcweir                 {
478cdf0e10cSrcweir                     uno::Any a = xNameAccess->getByName( aModuleId );
479cdf0e10cSrcweir                     a >>= m_xUICommandLabels;
480cdf0e10cSrcweir                 }
481cdf0e10cSrcweir                 catch ( container::NoSuchElementException& )
482cdf0e10cSrcweir                 {
483cdf0e10cSrcweir                 }
484cdf0e10cSrcweir             }
485cdf0e10cSrcweir         }
486cdf0e10cSrcweir         catch ( uno::RuntimeException& )
487cdf0e10cSrcweir         {
488cdf0e10cSrcweir             throw;
489cdf0e10cSrcweir         }
490cdf0e10cSrcweir         catch ( uno::Exception& )
491cdf0e10cSrcweir         {
492cdf0e10cSrcweir             m_bUICfgMgrAssociated = true;
493cdf0e10cSrcweir             return false;
494cdf0e10cSrcweir         }
495cdf0e10cSrcweir         m_bUICfgMgrAssociated = true;
496cdf0e10cSrcweir     }
497cdf0e10cSrcweir 
498cdf0e10cSrcweir     return true;
499cdf0e10cSrcweir }
500cdf0e10cSrcweir 
501cdf0e10cSrcweir Image
502cdf0e10cSrcweir ContextMenuHelper::getImageFromCommandURL(
503cdf0e10cSrcweir     const ::rtl::OUString& aCmdURL,
504cdf0e10cSrcweir     bool                   bHiContrast ) const
505cdf0e10cSrcweir {
506cdf0e10cSrcweir     Image     aImage;
507cdf0e10cSrcweir     sal_Int16 nImageType( ui::ImageType::COLOR_NORMAL|
508cdf0e10cSrcweir                           ui::ImageType::SIZE_DEFAULT );
509cdf0e10cSrcweir     if ( bHiContrast )
510cdf0e10cSrcweir         nImageType |= ui::ImageType::COLOR_HIGHCONTRAST;
511cdf0e10cSrcweir 
512cdf0e10cSrcweir     uno::Sequence< uno::Reference< graphic::XGraphic > > aGraphicSeq;
513cdf0e10cSrcweir     uno::Sequence< ::rtl::OUString > aImageCmdSeq( 1 );
514cdf0e10cSrcweir     aImageCmdSeq[0] = aCmdURL;
515cdf0e10cSrcweir 
516cdf0e10cSrcweir     if ( m_xDocImageMgr.is() )
517cdf0e10cSrcweir     {
518cdf0e10cSrcweir         try
519cdf0e10cSrcweir         {
520cdf0e10cSrcweir             aGraphicSeq = m_xDocImageMgr->getImages( nImageType, aImageCmdSeq );
521cdf0e10cSrcweir             uno::Reference< graphic::XGraphic > xGraphic = aGraphicSeq[0];
522cdf0e10cSrcweir             aImage = Image( xGraphic );
523cdf0e10cSrcweir 
524cdf0e10cSrcweir             if ( !!aImage )
525cdf0e10cSrcweir                 return aImage;
526cdf0e10cSrcweir         }
527cdf0e10cSrcweir         catch ( uno::RuntimeException& )
528cdf0e10cSrcweir         {
529cdf0e10cSrcweir             throw;
530cdf0e10cSrcweir         }
531cdf0e10cSrcweir         catch ( uno::Exception& )
532cdf0e10cSrcweir         {
533cdf0e10cSrcweir         }
534cdf0e10cSrcweir     }
535cdf0e10cSrcweir 
536cdf0e10cSrcweir     if ( m_xModuleImageMgr.is() )
537cdf0e10cSrcweir     {
538cdf0e10cSrcweir         try
539cdf0e10cSrcweir         {
540cdf0e10cSrcweir             aGraphicSeq = m_xModuleImageMgr->getImages( nImageType, aImageCmdSeq );
541cdf0e10cSrcweir             uno::Reference< ::com::sun::star::graphic::XGraphic > xGraphic = aGraphicSeq[0];
542cdf0e10cSrcweir 	    aImage = Image( xGraphic );
543cdf0e10cSrcweir 
544cdf0e10cSrcweir             if ( !!aImage )
545cdf0e10cSrcweir                 return aImage;
546cdf0e10cSrcweir         }
547cdf0e10cSrcweir         catch ( uno::RuntimeException& )
548cdf0e10cSrcweir         {
549cdf0e10cSrcweir             throw;
550cdf0e10cSrcweir         }
551cdf0e10cSrcweir         catch ( uno::Exception& )
552cdf0e10cSrcweir         {
553cdf0e10cSrcweir         }
554cdf0e10cSrcweir     }
555cdf0e10cSrcweir 
556cdf0e10cSrcweir     return aImage;
557cdf0e10cSrcweir }
558cdf0e10cSrcweir 
559cdf0e10cSrcweir rtl::OUString
560cdf0e10cSrcweir ContextMenuHelper::getLabelFromCommandURL(
561cdf0e10cSrcweir     const ::rtl::OUString& aCmdURL ) const
562cdf0e10cSrcweir {
563cdf0e10cSrcweir     ::rtl::OUString aLabel;
564cdf0e10cSrcweir 
565cdf0e10cSrcweir     if ( m_xUICommandLabels.is() )
566cdf0e10cSrcweir     {
567cdf0e10cSrcweir         try
568cdf0e10cSrcweir         {
569cdf0e10cSrcweir             if ( aCmdURL.getLength() > 0 )
570cdf0e10cSrcweir             {
571cdf0e10cSrcweir                 rtl::OUString aStr;
572cdf0e10cSrcweir                 uno::Sequence< beans::PropertyValue > aPropSeq;
573cdf0e10cSrcweir                 uno::Any a( m_xUICommandLabels->getByName( aCmdURL ));
574cdf0e10cSrcweir                 if ( a >>= aPropSeq )
575cdf0e10cSrcweir                 {
576cdf0e10cSrcweir                     for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
577cdf0e10cSrcweir                     {
578cdf0e10cSrcweir                         if ( aPropSeq[i].Name.equalsAscii( "Label" ))
579cdf0e10cSrcweir                         {
580cdf0e10cSrcweir                             aPropSeq[i].Value >>= aStr;
581cdf0e10cSrcweir                             break;
582cdf0e10cSrcweir                         }
583cdf0e10cSrcweir                     }
584cdf0e10cSrcweir                 }
585cdf0e10cSrcweir                 aLabel = aStr;
586cdf0e10cSrcweir             }
587cdf0e10cSrcweir         }
588cdf0e10cSrcweir         catch ( uno::RuntimeException& )
589cdf0e10cSrcweir         {
590cdf0e10cSrcweir         }
591cdf0e10cSrcweir         catch ( uno::Exception& )
592cdf0e10cSrcweir         {
593cdf0e10cSrcweir         }
594cdf0e10cSrcweir     }
595cdf0e10cSrcweir 
596cdf0e10cSrcweir     return aLabel;
597cdf0e10cSrcweir }
598cdf0e10cSrcweir 
599cdf0e10cSrcweir void
600cdf0e10cSrcweir ContextMenuHelper::completeMenuProperties(
601cdf0e10cSrcweir     Menu* pMenu )
602cdf0e10cSrcweir {
603cdf0e10cSrcweir     // Retrieve some settings necessary to display complete context
604cdf0e10cSrcweir     // menu correctly.
605cdf0e10cSrcweir     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
606cdf0e10cSrcweir 	bool  bShowMenuImages( rSettings.GetUseImagesInMenus() );
607cdf0e10cSrcweir 	bool  bIsHiContrast( rSettings.GetHighContrastMode() );
608cdf0e10cSrcweir 
609cdf0e10cSrcweir     if ( pMenu )
610cdf0e10cSrcweir     {
611cdf0e10cSrcweir         uno::Reference< frame::XFrame > xFrame( m_xWeakFrame );
612cdf0e10cSrcweir         uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, uno::UNO_QUERY );
613cdf0e10cSrcweir 
614cdf0e10cSrcweir         if ( !m_xURLTransformer.is() )
615cdf0e10cSrcweir         {
616cdf0e10cSrcweir             m_xURLTransformer = uno::Reference< util::XURLTransformer >(
617cdf0e10cSrcweir                 ::comphelper::getProcessServiceFactory()->createInstance(
618cdf0e10cSrcweir                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
619cdf0e10cSrcweir                         "com.sun.star.util.URLTransformer" ))),
620cdf0e10cSrcweir                 uno::UNO_QUERY );
621cdf0e10cSrcweir         }
622cdf0e10cSrcweir 
623cdf0e10cSrcweir         for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
624cdf0e10cSrcweir 	    {
625cdf0e10cSrcweir 		    sal_uInt16 nId        = pMenu->GetItemId( nPos );
626cdf0e10cSrcweir 		    PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nId );
627cdf0e10cSrcweir             if ( pPopupMenu )
628cdf0e10cSrcweir                 completeMenuProperties( pPopupMenu );
629cdf0e10cSrcweir             if ( pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR )
630cdf0e10cSrcweir 		    {
631cdf0e10cSrcweir                 ::rtl::OUString aCmdURL( pMenu->GetItemCommand( nId ));
632cdf0e10cSrcweir 
633cdf0e10cSrcweir                 if ( bShowMenuImages )
634cdf0e10cSrcweir 			    {
635cdf0e10cSrcweir 				    Image aImage;
636cdf0e10cSrcweir                     if ( aCmdURL.getLength() > 0 )
637cdf0e10cSrcweir 					    aImage = getImageFromCommandURL( aCmdURL, bIsHiContrast );
638cdf0e10cSrcweir                     pMenu->SetItemImage( nId, aImage );
639cdf0e10cSrcweir 			    }
640cdf0e10cSrcweir 			    else
641cdf0e10cSrcweir 				    pMenu->SetItemImage( nId, Image() );
642cdf0e10cSrcweir 
643cdf0e10cSrcweir                 if ( pMenu->GetItemText( nId ).Len() == 0 )
644cdf0e10cSrcweir                 {
645cdf0e10cSrcweir                     ::rtl::OUString aLabel( getLabelFromCommandURL( aCmdURL ));
646cdf0e10cSrcweir                     pMenu->SetItemText( nId, aLabel );
647cdf0e10cSrcweir                 }
648cdf0e10cSrcweir 
649cdf0e10cSrcweir                 // Use helper to retrieve state of the command URL
650cdf0e10cSrcweir 				StateEventHelper* pHelper = new StateEventHelper(
651cdf0e10cSrcweir 													xDispatchProvider,
652cdf0e10cSrcweir 													m_xURLTransformer,
653cdf0e10cSrcweir 													aCmdURL );
654cdf0e10cSrcweir 
655cdf0e10cSrcweir 				uno::Reference< frame::XStatusListener > xHelper( pHelper );
656cdf0e10cSrcweir                 pMenu->EnableItem( nId, pHelper->isCommandEnabled() );
657cdf0e10cSrcweir 		    }
658cdf0e10cSrcweir 	    }
659cdf0e10cSrcweir     }
660cdf0e10cSrcweir }
661cdf0e10cSrcweir 
662cdf0e10cSrcweir 
663cdf0e10cSrcweir IMPL_STATIC_LINK_NOINSTANCE( ContextMenuHelper, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
664cdf0e10cSrcweir {
665cdf0e10cSrcweir     // Release solar mutex to prevent deadlocks with clipboard thread
666cdf0e10cSrcweir     const sal_uInt32 nRef = Application::ReleaseSolarMutex();
667cdf0e10cSrcweir     try
668cdf0e10cSrcweir     {
669cdf0e10cSrcweir         // Asynchronous execution as this can lead to our own destruction while we are
670cdf0e10cSrcweir         // on the stack. Stack unwinding would access the destroyed context menu.
671cdf0e10cSrcweir         pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
672cdf0e10cSrcweir     }
673cdf0e10cSrcweir     catch ( uno::Exception& )
674cdf0e10cSrcweir     {
675cdf0e10cSrcweir     }
676cdf0e10cSrcweir 
677cdf0e10cSrcweir     // Acquire solar mutex again
678cdf0e10cSrcweir     Application::AcquireSolarMutex( nRef );
679cdf0e10cSrcweir     delete pExecuteInfo;
680cdf0e10cSrcweir     return 0;
681cdf0e10cSrcweir }
682cdf0e10cSrcweir 
683cdf0e10cSrcweir } // namespace svt
684