1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: popupmenudispatcher.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 //#include "precompiled_framework.hxx"
34 //_________________________________________________________________________________________________________________
36 //_________________________________________________________________________________________________________________
38 #include <dispatch/popupmenudispatcher.hxx>
40 #include <xml/menuconfiguration.hxx>
41 #include <classes/addonmenu.hxx>
43 #include <properties.h>
45 //_________________________________________________________________________________________________________________
47 //_________________________________________________________________________________________________________________
48 #include <com/sun/star/frame/FrameSearchFlag.hpp>
49 #include <com/sun/star/awt/XToolkit.hpp>
50 #include <com/sun/star/awt/WindowAttribute.hpp>
51 #include <com/sun/star/awt/WindowDescriptor.hpp>
52 #include <com/sun/star/awt/PosSize.hpp>
53 #include <com/sun/star/awt/XWindowPeer.hpp>
54 #include <com/sun/star/beans/UnknownPropertyException.hpp>
55 #include <com/sun/star/lang/WrappedTargetException.hpp>
56 #include <com/sun/star/beans/XPropertySet.hpp>
57 #include <com/sun/star/container/XEnumeration.hpp>
59 //_________________________________________________________________________________________________________________
60 // includes of other projects
61 //_________________________________________________________________________________________________________________
63 #include <ucbhelper/content.hxx>
64 #include <vos/mutex.hxx>
65 #include <rtl/ustrbuf.hxx>
66 #include <vcl/svapp.hxx>
68 //_________________________________________________________________________________________________________________
70 //_________________________________________________________________________________________________________________
74 using namespace ::com::sun::star
;
75 using namespace ::com::sun::star::awt
;
76 using namespace ::com::sun::star::beans
;
77 using namespace ::com::sun::star::container
;
78 using namespace ::com::sun::star::frame
;
79 using namespace ::com::sun::star::lang
;
80 using namespace ::com::sun::star::uno
;
81 using namespace ::com::sun::star::util
;
82 using namespace ::cppu
;
83 using namespace ::osl
;
84 using namespace ::rtl
;
85 using namespace ::vos
;
87 //_________________________________________________________________________________________________________________
89 //_________________________________________________________________________________________________________________
90 const char* PROTOCOL_VALUE
= "vnd.sun.star.popup:";
91 const sal_Int32 PROTOCOL_LENGTH
= 19;
93 //_________________________________________________________________________________________________________________
94 // non exported definitions
95 //_________________________________________________________________________________________________________________
97 //_________________________________________________________________________________________________________________
99 //_________________________________________________________________________________________________________________
101 //*****************************************************************************************************************
103 //*****************************************************************************************************************
104 PopupMenuDispatcher::PopupMenuDispatcher(
105 const uno::Reference
< XMultiServiceFactory
>& xFactory
)
106 // Init baseclasses first
107 : ThreadHelpBase ( &Application::GetSolarMutex() )
110 , m_xFactory ( xFactory
)
111 , m_aListenerContainer ( m_aLock
.getShareableOslMutex() )
112 , m_bAlreadyDisposed ( sal_False
)
113 , m_bActivateListener ( sal_False
)
117 //*****************************************************************************************************************
119 //*****************************************************************************************************************
120 PopupMenuDispatcher::~PopupMenuDispatcher()
122 // Warn programmer if he forgot to dispose this instance.
123 // We must release all our references ...
124 // and a dtor isn't the best place to do that!
127 //*****************************************************************************************************************
128 // XInterface, XTypeProvider
129 //*****************************************************************************************************************
130 DEFINE_XINTERFACE_7 ( PopupMenuDispatcher
,
131 ::cppu::OWeakObject
,
132 DIRECT_INTERFACE( XTypeProvider
),
133 DIRECT_INTERFACE( XServiceInfo
),
134 DIRECT_INTERFACE( XDispatchProvider
),
135 DIRECT_INTERFACE( XDispatch
),
136 DIRECT_INTERFACE( XEventListener
),
137 DIRECT_INTERFACE( XInitialization
),
138 DERIVED_INTERFACE( XFrameActionListener
, XEventListener
)
141 DEFINE_XTYPEPROVIDER_7 ( PopupMenuDispatcher
,
151 DEFINE_XSERVICEINFO_MULTISERVICE( PopupMenuDispatcher
,
152 ::cppu::OWeakObject
,
153 SERVICENAME_PROTOCOLHANDLER
,
154 IMPLEMENTATIONNAME_POPUPMENUDISPATCHER
)
156 DEFINE_INIT_SERVICE(PopupMenuDispatcher
,
159 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
160 to create a new instance of this class by our own supported service factory.
161 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
166 //*****************************************************************************************************************
168 //*****************************************************************************************************************
169 void SAL_CALL
PopupMenuDispatcher::initialize(
170 const css::uno::Sequence
< css::uno::Any
>& lArguments
)
171 throw( css::uno::Exception
, css::uno::RuntimeException
)
173 css::uno::Reference
< css::frame::XFrame
> xFrame
;
176 WriteGuard
aWriteLock(m_aLock
);
178 for (int a
=0; a
<lArguments
.getLength(); ++a
)
182 lArguments
[a
] >>= xFrame
;
183 m_xWeakFrame
= xFrame
;
185 m_bActivateListener
= sal_True
;
186 uno::Reference
< css::frame::XFrameActionListener
> xFrameActionListener(
187 (OWeakObject
*)this, css::uno::UNO_QUERY
);
188 xFrame
->addFrameActionListener( xFrameActionListener
);
196 //*****************************************************************************************************************
198 //*****************************************************************************************************************
199 css::uno::Reference
< css::frame::XDispatch
>
200 SAL_CALL
PopupMenuDispatcher::queryDispatch(
201 const css::util::URL
& rURL
,
202 const ::rtl::OUString
& sTarget
,
204 throw( css::uno::RuntimeException
)
206 css::uno::Reference
< css::frame::XDispatch
> xDispatch
;
208 if ( rURL
.Complete
.compareToAscii( PROTOCOL_VALUE
, PROTOCOL_LENGTH
) == 0 )
211 ResetableGuard
aGuard( m_aLock
);
212 impl_RetrievePopupControllerQuery();
213 impl_CreateUriRefFactory();
215 css::uno::Reference
< css::container::XNameAccess
> xPopupCtrlQuery( m_xPopupCtrlQuery
);
216 css::uno::Reference
< css::uri::XUriReferenceFactory
> xUriRefFactory( m_xUriRefFactory
);
220 if ( xPopupCtrlQuery
.is() )
224 // Just use the main part of the URL for popup menu controllers
225 sal_Int32
nQueryPart( 0 );
226 sal_Int32
nSchemePart( 0 );
227 rtl::OUString
aBaseURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" ));
228 rtl::OUString
aURL( rURL
.Complete
);
230 nSchemePart
= aURL
.indexOf( ':' );
231 if (( nSchemePart
> 0 ) &&
232 ( aURL
.getLength() > ( nSchemePart
+1 )))
234 nQueryPart
= aURL
.indexOf( '?', nSchemePart
);
235 if ( nQueryPart
> 0 )
236 aBaseURL
+= aURL
.copy( nSchemePart
+1, nQueryPart
-(nSchemePart
+1) );
237 else if ( nQueryPart
== -1 )
238 aBaseURL
+= aURL
.copy( nSchemePart
+1 );
241 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatchProvider
;
243 // Find popup menu controller using the base URL
244 xPopupCtrlQuery
->getByName( aBaseURL
) >>= xDispatchProvider
;
247 // Ask popup menu dispatch provider for dispatch object
248 if ( xDispatchProvider
.is() )
249 xDispatch
= xDispatchProvider
->queryDispatch( rURL
, sTarget
, nFlags
);
251 catch ( RuntimeException
& )
263 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > SAL_CALL
264 PopupMenuDispatcher::queryDispatches(
265 const css::uno::Sequence
< css::frame::DispatchDescriptor
>& lDescriptor
)
266 throw( css::uno::RuntimeException
)
268 sal_Int32 nCount
= lDescriptor
.getLength();
269 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > lDispatcher( nCount
);
270 for( sal_Int32 i
=0; i
<nCount
; ++i
)
272 lDispatcher
[i
] = this->queryDispatch(
273 lDescriptor
[i
].FeatureURL
,
274 lDescriptor
[i
].FrameName
,
275 lDescriptor
[i
].SearchFlags
);
280 //*****************************************************************************************************************
282 //*****************************************************************************************************************
284 SAL_CALL
PopupMenuDispatcher::dispatch(
285 const URL
& /*aURL*/ ,
286 const Sequence
< PropertyValue
>& /*seqProperties*/ )
287 throw( RuntimeException
)
291 //*****************************************************************************************************************
293 //*****************************************************************************************************************
295 SAL_CALL
PopupMenuDispatcher::addStatusListener(
296 const uno::Reference
< XStatusListener
>& xControl
,
298 throw( RuntimeException
)
300 // Ready for multithreading
301 ResetableGuard
aGuard( m_aLock
);
302 // Safe impossible cases
303 // Add listener to container.
304 m_aListenerContainer
.addInterface( aURL
.Complete
, xControl
);
307 //*****************************************************************************************************************
309 //*****************************************************************************************************************
311 SAL_CALL
PopupMenuDispatcher::removeStatusListener(
312 const uno::Reference
< XStatusListener
>& xControl
,
314 throw( RuntimeException
)
316 // Ready for multithreading
317 ResetableGuard
aGuard( m_aLock
);
318 // Safe impossible cases
319 // Add listener to container.
320 m_aListenerContainer
.removeInterface( aURL
.Complete
, xControl
);
323 //*****************************************************************************************************************
324 // XFrameActionListener
325 //*****************************************************************************************************************
328 SAL_CALL
PopupMenuDispatcher::frameAction(
329 const FrameActionEvent
& aEvent
)
330 throw ( RuntimeException
)
332 ResetableGuard
aGuard( m_aLock
);
334 if (( aEvent
.Action
== css::frame::FrameAction_COMPONENT_DETACHING
) ||
335 ( aEvent
.Action
== css::frame::FrameAction_COMPONENT_ATTACHED
))
337 // Reset query reference to requery it again next time
338 m_xPopupCtrlQuery
.clear();
342 //*****************************************************************************************************************
344 //*****************************************************************************************************************
346 SAL_CALL
PopupMenuDispatcher::disposing( const EventObject
& ) throw( RuntimeException
)
348 // Ready for multithreading
349 ResetableGuard
aGuard( m_aLock
);
350 // Safe impossible cases
351 LOG_ASSERT( !(m_bAlreadyDisposed
==sal_True
), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" )
353 if( m_bAlreadyDisposed
== sal_False
)
355 m_bAlreadyDisposed
= sal_True
;
357 if ( m_bActivateListener
)
359 uno::Reference
< XFrame
> xFrame( m_xWeakFrame
.get(), UNO_QUERY
);
362 xFrame
->removeFrameActionListener( uno::Reference
< XFrameActionListener
>( (OWeakObject
*)this, UNO_QUERY
));
363 m_bActivateListener
= sal_False
;
367 // Forget our factory.
368 m_xFactory
= uno::Reference
< XMultiServiceFactory
>();
372 void PopupMenuDispatcher::impl_RetrievePopupControllerQuery()
374 if ( !m_xPopupCtrlQuery
.is() )
376 css::uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
377 css::uno::Reference
< css::frame::XFrame
> xFrame( m_xWeakFrame
);
381 css::uno::Reference
< css::beans::XPropertySet
> xPropSet( xFrame
, css::uno::UNO_QUERY
);
386 xPropSet
->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER
) >>= xLayoutManager
;
388 if ( xLayoutManager
.is() )
390 css::uno::Reference
< css::ui::XUIElement
> xMenuBar
;
391 rtl::OUString
aMenuBar( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" ));
392 xMenuBar
= xLayoutManager
->getElement( aMenuBar
);
394 m_xPopupCtrlQuery
= css::uno::Reference
< css::container::XNameAccess
>(
395 xMenuBar
, css::uno::UNO_QUERY
);
398 catch ( css::uno::RuntimeException
& )
402 catch ( css::uno::Exception
& )
410 void PopupMenuDispatcher::impl_CreateUriRefFactory()
412 if ( !m_xUriRefFactory
.is() )
414 rtl::OUString
aUriRefFactoryService(
415 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uri.UriReferenceFactory" ));
417 m_xUriRefFactory
= css::uno::Reference
< css::uri::XUriReferenceFactory
>(
418 m_xFactory
->createInstance( aUriRefFactoryService
),
419 css::uno::UNO_QUERY
);
424 } // namespace framework