1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <dispatch/menudispatcher.hxx>
22 #include <framework/menuconfiguration.hxx>
23 #include <framework/addonmenu.hxx>
26 #include <com/sun/star/frame/FrameSearchFlag.hpp>
27 #include <com/sun/star/awt/WindowAttribute.hpp>
28 #include <com/sun/star/awt/WindowDescriptor.hpp>
29 #include <com/sun/star/awt/PosSize.hpp>
30 #include <com/sun/star/awt/XWindowPeer.hpp>
31 #include <com/sun/star/beans/UnknownPropertyException.hpp>
32 #include <com/sun/star/lang/WrappedTargetException.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/container/XEnumeration.hpp>
35 #include <com/sun/star/util/XURLTransformer.hpp>
37 #include <vcl/window.hxx>
38 #include <vcl/syswin.hxx>
39 #include <vcl/menu.hxx>
40 #include <vcl/svapp.hxx>
41 #include <tools/rcid.h>
42 #include <osl/mutex.hxx>
43 #include <toolkit/helper/vclunohelper.hxx>
45 #include <ucbhelper/content.hxx>
49 using namespace ::com::sun::star
;
50 using namespace ::com::sun::star::awt
;
51 using namespace ::com::sun::star::beans
;
52 using namespace ::com::sun::star::container
;
53 using namespace ::com::sun::star::frame
;
54 using namespace ::com::sun::star::lang
;
55 using namespace ::com::sun::star::uno
;
56 using namespace ::com::sun::star::util
;
57 using namespace ::cppu
;
59 const sal_uInt16 SLOTID_MDIWINDOWLIST
= 5610;
63 MenuDispatcher::MenuDispatcher( const uno::Reference
< XComponentContext
>& xContext
,
64 const uno::Reference
< XFrame
>& xOwner
)
65 : m_xOwnerWeak ( xOwner
)
66 , m_xContext ( xContext
)
67 , m_aListenerContainer ( m_mutex
)
68 , m_bAlreadyDisposed ( false )
69 , m_bActivateListener ( false )
70 , m_pMenuManager ( NULL
)
72 // Safe impossible cases
73 // We need valid information about our owner for work.
74 SAL_WARN_IF( !( xContext
.is() && xOwner
.is() ), "fwk", "MenuDispatcher::MenuDispatcher()\nInvalid parameter detected!" );
76 m_bActivateListener
= true;
77 xOwner
->addFrameActionListener( uno::Reference
< XFrameActionListener
>( (OWeakObject
*)this, UNO_QUERY
));
82 MenuDispatcher::~MenuDispatcher()
84 // Warn programmer if he forgot to dispose this instance.
85 // We must release all our references ...
86 // and a dtor isn't the best place to do that!
91 void SAL_CALL
MenuDispatcher::dispatch( const URL
& /*aURL*/ ,
92 const Sequence
< PropertyValue
>& /*seqProperties*/ ) throw( RuntimeException
, std::exception
)
98 void SAL_CALL
MenuDispatcher::addStatusListener( const uno::Reference
< XStatusListener
>& xControl
,
99 const URL
& aURL
) throw( RuntimeException
, std::exception
)
102 // Safe impossible cases
103 // Method not defined for all incoming parameter
104 SAL_WARN_IF( !xControl
.is() || aURL
.Complete
.isEmpty(), "fwk", "MenuDispatcher::addStatusListener(): Invalid parameter detected." );
105 // Add listener to container.
106 m_aListenerContainer
.addInterface( aURL
.Complete
, xControl
);
111 void SAL_CALL
MenuDispatcher::removeStatusListener( const uno::Reference
< XStatusListener
>& xControl
,
112 const URL
& aURL
) throw( RuntimeException
, std::exception
)
115 // Safe impossible cases
116 // Method not defined for all incoming parameter
117 SAL_WARN_IF( !xControl
.is() || aURL
.Complete
.isEmpty(), "fwk", "MenuDispatcher::removeStatusListener(): Invalid parameter detected." );
118 // Add listener to container.
119 m_aListenerContainer
.removeInterface( aURL
.Complete
, xControl
);
122 // XFrameActionListener
124 void SAL_CALL
MenuDispatcher::frameAction( const FrameActionEvent
& aEvent
) throw ( RuntimeException
, std::exception
)
126 SolarMutexResettableGuard aGuard
;
128 if ( m_pMenuManager
&& aEvent
.Action
== FrameAction_FRAME_UI_ACTIVATED
)
130 MenuBar
* pMenuBar
= static_cast<MenuBar
*>(m_pMenuManager
->GetMenu());
131 uno::Reference
< XFrame
> xFrame( m_xOwnerWeak
.get(), UNO_QUERY
);
134 if ( xFrame
.is() && pMenuBar
)
136 uno::Reference
< ::com::sun::star::awt::XWindow
>xContainerWindow
= xFrame
->getContainerWindow();
140 vcl::Window
* pWindow
= VCLUnoHelper::GetWindow( xContainerWindow
);
141 while ( pWindow
&& !pWindow
->IsSystemWindow() )
142 pWindow
= pWindow
->GetParent();
146 SystemWindow
* pSysWindow
= static_cast<SystemWindow
*>(pWindow
);
147 pSysWindow
->SetMenuBar( pMenuBar
);
152 else if ( m_pMenuManager
&& aEvent
.Action
== css::frame::FrameAction_COMPONENT_DETACHING
)
154 if ( m_pMenuManager
)
155 impl_setMenuBar( NULL
);
160 void SAL_CALL
MenuDispatcher::disposing( const EventObject
& ) throw( RuntimeException
, std::exception
)
163 // Safe impossible cases
164 SAL_WARN_IF( m_bAlreadyDisposed
, "fwk", "MenuDispatcher::disposing(): Object already disposed .. don't call it again!" );
166 if( !m_bAlreadyDisposed
)
168 m_bAlreadyDisposed
= true;
170 if ( m_bActivateListener
)
172 uno::Reference
< XFrame
> xFrame( m_xOwnerWeak
.get(), UNO_QUERY
);
175 xFrame
->removeFrameActionListener( uno::Reference
< XFrameActionListener
>( (OWeakObject
*)this, UNO_QUERY
));
176 m_bActivateListener
= false;
177 if ( m_pMenuManager
)
179 EventObject aEventObj
;
180 aEventObj
.Source
= xFrame
;
181 m_pMenuManager
->disposing( aEventObj
);
186 // Forget our factory.
187 m_xContext
= uno::Reference
< XComponentContext
>();
189 // Remove our menu from system window if it is still there!
190 if ( m_pMenuManager
)
191 impl_setMenuBar( NULL
);
195 void MenuDispatcher::impl_setAccelerators( Menu
* pMenu
, const Accelerator
& aAccel
)
197 for ( sal_uInt16 nPos
= 0; nPos
< pMenu
->GetItemCount(); ++nPos
)
199 sal_uInt16 nId
= pMenu
->GetItemId(nPos
);
200 ::PopupMenu
* pPopup
= pMenu
->GetPopupMenu(nId
);
202 impl_setAccelerators( (Menu
*)pPopup
, aAccel
);
203 else if ( nId
&& !pMenu
->GetPopupMenu(nId
))
205 vcl::KeyCode aCode
= aAccel
.GetKeyCode( nId
);
206 if ( aCode
.GetCode() )
207 pMenu
->SetAccelKey( nId
, aCode
);
212 bool MenuDispatcher::impl_setMenuBar( MenuBar
* pMenuBar
, bool bMenuFromResource
)
214 uno::Reference
< XFrame
> xFrame( m_xOwnerWeak
.get(), UNO_QUERY
);
217 uno::Reference
< ::com::sun::star::awt::XWindow
>xContainerWindow
= xFrame
->getContainerWindow();
218 vcl::Window
* pWindow
= NULL
;
220 SolarMutexGuard aSolarGuard
;
222 pWindow
= VCLUnoHelper::GetWindow( xContainerWindow
);
223 while ( pWindow
&& !pWindow
->IsSystemWindow() )
224 pWindow
= pWindow
->GetParent();
229 SystemWindow
* pSysWindow
= static_cast<SystemWindow
*>(pWindow
);
231 if ( m_pMenuManager
)
233 // remove old menu from our system window if it was set before
234 if ( m_pMenuManager
->GetMenu() == (Menu
*)pSysWindow
->GetMenuBar() )
235 pSysWindow
->SetMenuBar( NULL
);
237 // remove listener before we destruct ourself, so we cannot be called back afterwards
238 m_pMenuManager
->RemoveListener();
240 (static_cast< ::com::sun::star::uno::XInterface
* >((OWeakObject
*)m_pMenuManager
))->release();
245 if ( pMenuBar
!= NULL
)
247 sal_uInt16 nPos
= pMenuBar
->GetItemPos( SLOTID_MDIWINDOWLIST
);
248 if ( nPos
!= MENU_ITEM_NOTFOUND
)
250 uno::Reference
< XModel
> xModel
;
251 uno::Reference
< XController
> xController( xFrame
->getController(), UNO_QUERY
);
253 if ( xController
.is() )
254 xModel
= uno::Reference
< XModel
>( xController
->getModel(), UNO_QUERY
);
256 // retrieve addon popup menus and add them to our menu bar
257 AddonMenuManager::MergeAddonPopupMenus( xFrame
, nPos
, pMenuBar
, m_xContext
);
259 // retrieve addon help menu items and add them to our help menu
260 AddonMenuManager::MergeAddonHelpMenu( xFrame
, pMenuBar
, m_xContext
);
263 // set new menu on our system window and create new menu manager
264 if ( bMenuFromResource
)
266 m_pMenuManager
= new MenuManager( m_xContext
, xFrame
, pMenuBar
, true, false );
270 m_pMenuManager
= new MenuManager( m_xContext
, xFrame
, pMenuBar
, true, true );
273 pSysWindow
->SetMenuBar( pMenuBar
);
283 } // namespace framework
285 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */