Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <dispatch/menudispatcher.hxx>
21 : #include <general.h>
22 : #include <framework/menuconfiguration.hxx>
23 : #include <framework/addonmenu.hxx>
24 : #include <services.h>
25 :
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>
36 :
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>
44 :
45 : #include <ucbhelper/content.hxx>
46 :
47 : namespace framework{
48 :
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;
58 :
59 : const sal_uInt16 SLOTID_MDIWINDOWLIST = 5610;
60 :
61 : // constructor
62 :
63 1 : 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 1 : , m_pMenuManager ( NULL )
71 : {
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!" );
75 :
76 1 : m_bActivateListener = true;
77 1 : xOwner->addFrameActionListener( uno::Reference< XFrameActionListener >( static_cast<OWeakObject *>(this), UNO_QUERY ));
78 1 : }
79 :
80 : // destructor
81 :
82 2 : MenuDispatcher::~MenuDispatcher()
83 : {
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!
87 2 : }
88 :
89 : // XDispatch
90 :
91 1 : void SAL_CALL MenuDispatcher::dispatch( const URL& /*aURL*/ ,
92 : const Sequence< PropertyValue >& /*seqProperties*/ ) throw( RuntimeException, std::exception )
93 : {
94 1 : }
95 :
96 : // XDispatch
97 :
98 0 : void SAL_CALL MenuDispatcher::addStatusListener( const uno::Reference< XStatusListener >& xControl,
99 : const URL& aURL ) throw( RuntimeException, std::exception )
100 : {
101 0 : SolarMutexGuard g;
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 0 : m_aListenerContainer.addInterface( aURL.Complete, xControl );
107 0 : }
108 :
109 : // XDispatch
110 :
111 0 : void SAL_CALL MenuDispatcher::removeStatusListener( const uno::Reference< XStatusListener >& xControl,
112 : const URL& aURL ) throw( RuntimeException, std::exception )
113 : {
114 0 : SolarMutexGuard g;
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 0 : m_aListenerContainer.removeInterface( aURL.Complete, xControl );
120 0 : }
121 :
122 : // XFrameActionListener
123 :
124 0 : void SAL_CALL MenuDispatcher::frameAction( const FrameActionEvent& aEvent ) throw ( RuntimeException, std::exception )
125 : {
126 0 : SolarMutexResettableGuard aGuard;
127 :
128 0 : if ( m_pMenuManager && aEvent.Action == FrameAction_FRAME_UI_ACTIVATED )
129 : {
130 0 : MenuBar* pMenuBar = static_cast<MenuBar *>(m_pMenuManager->GetMenu());
131 0 : uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
132 0 : aGuard.clear();
133 :
134 0 : if ( xFrame.is() && pMenuBar )
135 : {
136 0 : uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow();
137 :
138 0 : aGuard.reset();
139 : {
140 0 : vcl::Window* pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
141 0 : while ( pWindow && !pWindow->IsSystemWindow() )
142 0 : pWindow = pWindow->GetParent();
143 :
144 0 : if ( pWindow )
145 : {
146 0 : SystemWindow* pSysWindow = static_cast<SystemWindow *>(pWindow);
147 0 : pSysWindow->SetMenuBar( pMenuBar );
148 : }
149 0 : }
150 0 : }
151 : }
152 0 : else if ( m_pMenuManager && aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
153 : {
154 0 : if ( m_pMenuManager )
155 0 : impl_setMenuBar( NULL );
156 0 : }
157 0 : }
158 :
159 : // XEventListener
160 1 : void SAL_CALL MenuDispatcher::disposing( const EventObject& ) throw( RuntimeException, std::exception )
161 : {
162 1 : SolarMutexGuard g;
163 : // Safe impossible cases
164 : SAL_WARN_IF( m_bAlreadyDisposed, "fwk", "MenuDispatcher::disposing(): Object already disposed .. don't call it again!" );
165 :
166 1 : if( !m_bAlreadyDisposed )
167 : {
168 1 : m_bAlreadyDisposed = true;
169 :
170 1 : if ( m_bActivateListener )
171 : {
172 1 : uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
173 1 : if ( xFrame.is() )
174 : {
175 1 : xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( static_cast<OWeakObject *>(this), UNO_QUERY ));
176 1 : m_bActivateListener = false;
177 1 : if ( m_pMenuManager )
178 : {
179 0 : EventObject aEventObj;
180 0 : aEventObj.Source = xFrame;
181 0 : m_pMenuManager->disposing( aEventObj );
182 : }
183 1 : }
184 : }
185 :
186 : // Forget our factory.
187 1 : m_xContext = uno::Reference< XComponentContext >();
188 :
189 : // Remove our menu from system window if it is still there!
190 1 : if ( m_pMenuManager )
191 0 : impl_setMenuBar( NULL );
192 1 : }
193 1 : }
194 :
195 0 : void MenuDispatcher::impl_setAccelerators( Menu* pMenu, const Accelerator& aAccel )
196 : {
197 0 : for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); ++nPos )
198 : {
199 0 : sal_uInt16 nId = pMenu->GetItemId(nPos);
200 0 : ::PopupMenu* pPopup = pMenu->GetPopupMenu(nId);
201 0 : if ( pPopup )
202 0 : impl_setAccelerators( static_cast<Menu *>(pPopup), aAccel );
203 0 : else if ( nId && !pMenu->GetPopupMenu(nId))
204 : {
205 0 : vcl::KeyCode aCode = aAccel.GetKeyCode( nId );
206 0 : if ( aCode.GetCode() )
207 0 : pMenu->SetAccelKey( nId, aCode );
208 : }
209 : }
210 0 : }
211 :
212 0 : bool MenuDispatcher::impl_setMenuBar( MenuBar* pMenuBar, bool bMenuFromResource )
213 : {
214 0 : uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY );
215 0 : if ( xFrame.is() )
216 : {
217 0 : uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow();
218 0 : vcl::Window* pWindow = NULL;
219 :
220 0 : SolarMutexGuard aSolarGuard;
221 : {
222 0 : pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
223 0 : while ( pWindow && !pWindow->IsSystemWindow() )
224 0 : pWindow = pWindow->GetParent();
225 : }
226 :
227 0 : if ( pWindow )
228 : {
229 0 : SystemWindow* pSysWindow = static_cast<SystemWindow *>(pWindow);
230 :
231 0 : if ( m_pMenuManager )
232 : {
233 : // remove old menu from our system window if it was set before
234 0 : if ( m_pMenuManager->GetMenu() == static_cast<Menu *>(pSysWindow->GetMenuBar()) )
235 0 : pSysWindow->SetMenuBar( NULL );
236 :
237 : // remove listener before we destruct ourself, so we cannot be called back afterwards
238 0 : m_pMenuManager->RemoveListener();
239 :
240 0 : (static_cast< ::com::sun::star::uno::XInterface* >(static_cast<OWeakObject*>(m_pMenuManager)))->release();
241 :
242 0 : m_pMenuManager = 0;
243 : }
244 :
245 0 : if ( pMenuBar != NULL )
246 : {
247 0 : sal_uInt16 nPos = pMenuBar->GetItemPos( SLOTID_MDIWINDOWLIST );
248 0 : if ( nPos != MENU_ITEM_NOTFOUND )
249 : {
250 0 : uno::Reference< XModel > xModel;
251 0 : uno::Reference< XController > xController( xFrame->getController(), UNO_QUERY );
252 :
253 0 : if ( xController.is() )
254 0 : xModel = uno::Reference< XModel >( xController->getModel(), UNO_QUERY );
255 :
256 : // retrieve addon popup menus and add them to our menu bar
257 0 : AddonMenuManager::MergeAddonPopupMenus( xFrame, nPos, pMenuBar, m_xContext );
258 :
259 : // retrieve addon help menu items and add them to our help menu
260 0 : AddonMenuManager::MergeAddonHelpMenu( xFrame, pMenuBar, m_xContext );
261 : }
262 :
263 : // set new menu on our system window and create new menu manager
264 0 : if ( bMenuFromResource )
265 : {
266 0 : m_pMenuManager = new MenuManager( m_xContext, xFrame, pMenuBar, true, false );
267 : }
268 : else
269 : {
270 0 : m_pMenuManager = new MenuManager( m_xContext, xFrame, pMenuBar, true, true );
271 : }
272 :
273 0 : pSysWindow->SetMenuBar( pMenuBar );
274 : }
275 :
276 0 : return true;
277 0 : }
278 : }
279 :
280 0 : return false;
281 : }
282 :
283 : } // namespace framework
284 :
285 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|