1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_framework.hxx" 30 31 //_________________________________________________________________________________________________________________ 32 // my own includes 33 //_________________________________________________________________________________________________________________ 34 #include <dispatch/menudispatcher.hxx> 35 #include <general.h> 36 #include <framework/menuconfiguration.hxx> 37 #include <framework/addonmenu.hxx> 38 #include <services.h> 39 40 //_________________________________________________________________________________________________________________ 41 // interface includes 42 //_________________________________________________________________________________________________________________ 43 #include <com/sun/star/frame/FrameSearchFlag.hpp> 44 #include <com/sun/star/awt/XToolkit.hpp> 45 #include <com/sun/star/awt/WindowAttribute.hpp> 46 #include <com/sun/star/awt/WindowDescriptor.hpp> 47 #include <com/sun/star/awt/PosSize.hpp> 48 #include <com/sun/star/awt/XWindowPeer.hpp> 49 #include <com/sun/star/beans/UnknownPropertyException.hpp> 50 #include <com/sun/star/lang/WrappedTargetException.hpp> 51 #include <com/sun/star/beans/XPropertySet.hpp> 52 #include <com/sun/star/container/XEnumeration.hpp> 53 #include <com/sun/star/util/XURLTransformer.hpp> 54 55 #include <vcl/window.hxx> 56 #include <vcl/syswin.hxx> 57 #include <vcl/menu.hxx> 58 #include <vcl/svapp.hxx> 59 #include <tools/resmgr.hxx> 60 #include <tools/rcid.h> 61 #include <vos/mutex.hxx> 62 #include <toolkit/helper/vclunohelper.hxx> 63 #include <rtl/logfile.hxx> 64 65 //_________________________________________________________________________________________________________________ 66 // includes of other projects 67 //_________________________________________________________________________________________________________________ 68 69 #include <ucbhelper/content.hxx> 70 71 //_________________________________________________________________________________________________________________ 72 // namespace 73 //_________________________________________________________________________________________________________________ 74 75 namespace framework{ 76 77 using namespace ::com::sun::star ; 78 using namespace ::com::sun::star::awt ; 79 using namespace ::com::sun::star::beans ; 80 using namespace ::com::sun::star::container ; 81 using namespace ::com::sun::star::frame ; 82 using namespace ::com::sun::star::lang ; 83 using namespace ::com::sun::star::uno ; 84 using namespace ::com::sun::star::util ; 85 using namespace ::cppu ; 86 using namespace ::osl ; 87 using namespace ::rtl ; 88 using namespace ::vos ; 89 90 //_________________________________________________________________________________________________________________ 91 // non exported const 92 //_________________________________________________________________________________________________________________ 93 94 const sal_uInt16 SLOTID_MDIWINDOWLIST = 5610; 95 96 //_________________________________________________________________________________________________________________ 97 // non exported definitions 98 //_________________________________________________________________________________________________________________ 99 100 //_________________________________________________________________________________________________________________ 101 // declarations 102 //_________________________________________________________________________________________________________________ 103 104 //***************************************************************************************************************** 105 // constructor 106 //***************************************************************************************************************** 107 MenuDispatcher::MenuDispatcher( const uno::Reference< XMultiServiceFactory >& xFactory , 108 const uno::Reference< XFrame >& xOwner ) 109 // Init baseclasses first 110 : ThreadHelpBase ( &Application::GetSolarMutex() ) 111 , OWeakObject ( ) 112 // Init member 113 , m_xOwnerWeak ( xOwner ) 114 , m_xFactory ( xFactory ) 115 , m_aListenerContainer ( m_aLock.getShareableOslMutex() ) 116 , m_bAlreadyDisposed ( sal_False ) 117 , m_bActivateListener ( sal_False ) 118 , m_pMenuManager ( NULL ) 119 { 120 // Safe impossible cases 121 // We need valid informations about ouer ownerfor work. 122 LOG_ASSERT( impldbg_checkParameter_MenuDispatcher( xFactory, xOwner ), "MenuDispatcher::MenuDispatcher()\nInvalid parameter detected!\n" ) 123 124 m_bActivateListener = sal_True; 125 xOwner->addFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY )); 126 } 127 128 //***************************************************************************************************************** 129 // destructor 130 //***************************************************************************************************************** 131 MenuDispatcher::~MenuDispatcher() 132 { 133 // Warn programmer if he forgot to dispose this instance. 134 // We must release all our references ... 135 // and a dtor isn't the best place to do that! 136 } 137 138 //***************************************************************************************************************** 139 // XInterface, XTypeProvider 140 //***************************************************************************************************************** 141 DEFINE_XINTERFACE_4 ( MenuDispatcher , 142 OWeakObject , 143 DIRECT_INTERFACE( XTypeProvider ), 144 DIRECT_INTERFACE( XDispatch ), 145 DIRECT_INTERFACE( XEventListener ), 146 DERIVED_INTERFACE( XFrameActionListener, XEventListener ) 147 ) 148 149 DEFINE_XTYPEPROVIDER_4 ( MenuDispatcher , 150 XTypeProvider , 151 XDispatch , 152 XEventListener , 153 XFrameActionListener 154 ) 155 156 157 //***************************************************************************************************************** 158 // XDispatch 159 //***************************************************************************************************************** 160 void SAL_CALL MenuDispatcher::dispatch( const URL& /*aURL*/ , 161 const Sequence< PropertyValue >& /*seqProperties*/ ) throw( RuntimeException ) 162 { 163 } 164 165 //***************************************************************************************************************** 166 // XDispatch 167 //***************************************************************************************************************** 168 void SAL_CALL MenuDispatcher::addStatusListener( const uno::Reference< XStatusListener >& xControl, 169 const URL& aURL ) throw( RuntimeException ) 170 { 171 // Ready for multithreading 172 ResetableGuard aGuard( m_aLock ); 173 // Safe impossible cases 174 // Method not defined for all incoming parameter 175 LOG_ASSERT( impldbg_checkParameter_addStatusListener( xControl, aURL ), "MenuDispatcher::addStatusListener()\nInvalid parameter detected.\n" ) 176 // Add listener to container. 177 m_aListenerContainer.addInterface( aURL.Complete, xControl ); 178 } 179 180 //***************************************************************************************************************** 181 // XDispatch 182 //***************************************************************************************************************** 183 void SAL_CALL MenuDispatcher::removeStatusListener( const uno::Reference< XStatusListener >& xControl, 184 const URL& aURL ) throw( RuntimeException ) 185 { 186 // Ready for multithreading 187 ResetableGuard aGuard( m_aLock ); 188 // Safe impossible cases 189 // Method not defined for all incoming parameter 190 LOG_ASSERT( impldbg_checkParameter_removeStatusListener( xControl, aURL ), "MenuDispatcher::removeStatusListener()\nInvalid parameter detected.\n" ) 191 // Add listener to container. 192 m_aListenerContainer.removeInterface( aURL.Complete, xControl ); 193 } 194 195 //***************************************************************************************************************** 196 // XFrameActionListener 197 //***************************************************************************************************************** 198 199 void SAL_CALL MenuDispatcher::frameAction( const FrameActionEvent& aEvent ) throw ( RuntimeException ) 200 { 201 ResetableGuard aGuard( m_aLock ); 202 203 if ( m_pMenuManager && aEvent.Action == FrameAction_FRAME_UI_ACTIVATED ) 204 { 205 MenuBar* pMenuBar = (MenuBar *)m_pMenuManager->GetMenu(); 206 uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY ); 207 aGuard.unlock(); 208 209 if ( xFrame.is() && pMenuBar ) 210 { 211 uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow(); 212 213 OGuard aSolarGuard( Application::GetSolarMutex() ); 214 { 215 Window* pWindow = VCLUnoHelper::GetWindow( xContainerWindow ); 216 while ( pWindow && !pWindow->IsSystemWindow() ) 217 pWindow = pWindow->GetParent(); 218 219 if ( pWindow ) 220 { 221 SystemWindow* pSysWindow = (SystemWindow *)pWindow; 222 pSysWindow->SetMenuBar( pMenuBar ); 223 } 224 } 225 } 226 } 227 else if ( m_pMenuManager && aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) 228 { 229 if ( m_pMenuManager ) 230 impl_setMenuBar( NULL ); 231 } 232 } 233 234 //***************************************************************************************************************** 235 // XEventListener 236 //***************************************************************************************************************** 237 void SAL_CALL MenuDispatcher::disposing( const EventObject& ) throw( RuntimeException ) 238 { 239 // Ready for multithreading 240 ResetableGuard aGuard( m_aLock ); 241 // Safe impossible cases 242 LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" ) 243 244 if( m_bAlreadyDisposed == sal_False ) 245 { 246 m_bAlreadyDisposed = sal_True; 247 248 if ( m_bActivateListener ) 249 { 250 uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY ); 251 if ( xFrame.is() ) 252 { 253 xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY )); 254 m_bActivateListener = sal_False; 255 if ( m_pMenuManager ) 256 { 257 EventObject aEventObj; 258 aEventObj.Source = xFrame; 259 m_pMenuManager->disposing( aEventObj ); 260 } 261 } 262 } 263 264 // Forget our factory. 265 m_xFactory = uno::Reference< XMultiServiceFactory >(); 266 267 // Remove our menu from system window if it is still there! 268 if ( m_pMenuManager ) 269 impl_setMenuBar( NULL ); 270 } 271 } 272 273 //***************************************************************************************************************** 274 // private method 275 // 276 // 277 //***************************************************************************************************************** 278 void MenuDispatcher::impl_setAccelerators( Menu* pMenu, const Accelerator& aAccel ) 279 { 280 for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); ++nPos ) 281 { 282 sal_uInt16 nId = pMenu->GetItemId(nPos); 283 PopupMenu* pPopup = pMenu->GetPopupMenu(nId); 284 if ( pPopup ) 285 impl_setAccelerators( (Menu *)pPopup, aAccel ); 286 else if ( nId && !pMenu->GetPopupMenu(nId)) 287 { 288 KeyCode aCode = aAccel.GetKeyCode( nId ); 289 if ( aCode.GetCode() ) 290 pMenu->SetAccelKey( nId, aCode ); 291 } 292 } 293 } 294 295 //***************************************************************************************************************** 296 // private method 297 // 298 // 299 //***************************************************************************************************************** 300 sal_Bool MenuDispatcher::impl_setMenuBar( MenuBar* pMenuBar, sal_Bool bMenuFromResource ) 301 { 302 uno::Reference< XFrame > xFrame( m_xOwnerWeak.get(), UNO_QUERY ); 303 if ( xFrame.is() ) 304 { 305 uno::Reference< ::com::sun::star::awt::XWindow >xContainerWindow = xFrame->getContainerWindow(); 306 Window* pWindow = NULL; 307 308 // Use SolarMutex for threadsafe code too! 309 OGuard aSolarGuard( Application::GetSolarMutex() ); 310 { 311 pWindow = VCLUnoHelper::GetWindow( xContainerWindow ); 312 while ( pWindow && !pWindow->IsSystemWindow() ) 313 pWindow = pWindow->GetParent(); 314 } 315 316 if ( pWindow ) 317 { 318 // Ready for multithreading 319 ResetableGuard aGuard( m_aLock ); 320 321 SystemWindow* pSysWindow = (SystemWindow *)pWindow; 322 323 if ( m_pMenuManager ) 324 { 325 // remove old menu from our system window if it was set before 326 if ( m_pMenuManager->GetMenu() == (Menu *)pSysWindow->GetMenuBar() ) 327 pSysWindow->SetMenuBar( NULL ); 328 329 // remove listener before we destruct ourself, so we cannot be called back afterwards 330 m_pMenuManager->RemoveListener(); 331 332 SAL_STATIC_CAST( ::com::sun::star::uno::XInterface*, (OWeakObject*)m_pMenuManager )->release(); 333 334 m_pMenuManager = 0; 335 } 336 337 if ( pMenuBar != NULL ) 338 { 339 sal_uInt16 nPos = pMenuBar->GetItemPos( SLOTID_MDIWINDOWLIST ); 340 if ( nPos != MENU_ITEM_NOTFOUND ) 341 { 342 OUString aNoContext; 343 344 uno::Reference< XModel > xModel; 345 uno::Reference< XController > xController( xFrame->getController(), UNO_QUERY ); 346 347 if ( xController.is() ) 348 xModel = uno::Reference< XModel >( xController->getModel(), UNO_QUERY ); 349 350 // retrieve addon popup menus and add them to our menu bar 351 AddonMenuManager::MergeAddonPopupMenus( xFrame, xModel, nPos, pMenuBar ); 352 353 // retrieve addon help menu items and add them to our help menu 354 AddonMenuManager::MergeAddonHelpMenu( xFrame, pMenuBar ); 355 } 356 357 // set new menu on our system window and create new menu manager 358 if ( bMenuFromResource ) 359 { 360 // #110897# 361 // m_pMenuManager = new MenuManager( xFrame, pMenuBar, sal_True, sal_False ); 362 m_pMenuManager = new MenuManager( m_xFactory, xFrame, pMenuBar, sal_True, sal_False ); 363 } 364 else 365 { 366 // #110897# 367 // m_pMenuManager = new MenuManager( xFrame, pMenuBar, sal_True, sal_True ); 368 m_pMenuManager = new MenuManager( m_xFactory, xFrame, pMenuBar, sal_True, sal_True ); 369 } 370 371 pSysWindow->SetMenuBar( pMenuBar ); 372 } 373 374 return sal_True; 375 } 376 } 377 378 return sal_False; 379 } 380 381 IMPL_LINK( MenuDispatcher, Close_Impl, void*, EMPTYARG ) 382 { 383 css::uno::Reference < css::frame::XFrame > xFrame( m_xOwnerWeak.get(), css::uno::UNO_QUERY ); 384 if ( !xFrame.is() ) 385 return 0; 386 387 css::util::URL aURL; 388 aURL.Complete = ::rtl::OUString::createFromAscii(".uno:CloseWin"); 389 css::uno::Reference< css::util::XURLTransformer > xTrans ( m_xFactory->createInstance( 390 SERVICENAME_URLTRANSFORMER ), css::uno::UNO_QUERY ); 391 if( xTrans.is() ) 392 { 393 // Datei laden 394 xTrans->parseStrict( aURL ); 395 uno::Reference< XDispatchProvider > xProv( xFrame, UNO_QUERY ); 396 if ( xProv.is() ) 397 { 398 css::uno::Reference < css::frame::XDispatch > aDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 ); 399 if ( aDisp.is() ) 400 aDisp->dispatch( aURL, css::uno::Sequence < css::beans::PropertyValue>() ); 401 } 402 } 403 404 return 0; 405 } 406 407 408 //_________________________________________________________________________________________________________________ 409 // debug methods 410 //_________________________________________________________________________________________________________________ 411 412 /*----------------------------------------------------------------------------------------------------------------- 413 The follow methods checks the parameter for other functions. If a parameter or his value is non valid, 414 we return "sal_False". (else sal_True) This mechanism is used to throw an ASSERT! 415 416 ATTENTION 417 418 If you miss a test for one of this parameters, contact the autor or add it himself !(?) 419 But ... look for right testing! See using of this methods! 420 -----------------------------------------------------------------------------------------------------------------*/ 421 422 #ifdef ENABLE_ASSERTIONS 423 424 //***************************************************************************************************************** 425 sal_Bool MenuDispatcher::impldbg_checkParameter_MenuDispatcher( const uno::Reference< XMultiServiceFactory >& xFactory , 426 const uno::Reference< XFrame >& xOwner ) 427 { 428 // Set default return value. 429 sal_Bool bOK = sal_True; 430 // Check parameter. 431 if ( 432 ( &xFactory == NULL ) || 433 ( &xOwner == NULL ) || 434 ( xFactory.is() == sal_False ) || 435 ( xOwner.is() == sal_False ) 436 ) 437 { 438 bOK = sal_False ; 439 } 440 // Return result of check. 441 return bOK ; 442 } 443 444 //***************************************************************************************************************** 445 // We need a valid URL. What is meaning with "register for nothing"?! 446 // xControl must correct to - nobody can advised otherwise! 447 sal_Bool MenuDispatcher::impldbg_checkParameter_addStatusListener( const uno::Reference< XStatusListener >& xControl, 448 const URL& aURL ) 449 { 450 // Set default return value. 451 sal_Bool bOK = sal_True; 452 // Check parameter. 453 if ( 454 ( &xControl == NULL ) || 455 ( &aURL == NULL ) || 456 ( aURL.Complete.getLength() < 1 ) 457 ) 458 { 459 bOK = sal_False ; 460 } 461 // Return result of check. 462 return bOK ; 463 } 464 465 //***************************************************************************************************************** 466 // The same goes for these case! We have added valid listener for correct URL only. 467 // We can't remove invalid listener for nothing! 468 sal_Bool MenuDispatcher::impldbg_checkParameter_removeStatusListener( const uno::Reference< XStatusListener >& xControl, 469 const URL& aURL ) 470 { 471 // Set default return value. 472 sal_Bool bOK = sal_True; 473 // Check parameter. 474 if ( 475 ( &xControl == NULL ) || 476 ( &aURL == NULL ) || 477 ( aURL.Complete.getLength() < 1 ) 478 ) 479 { 480 bOK = sal_False ; 481 } 482 // Return result of check. 483 return bOK ; 484 } 485 486 #endif // #ifdef ENABLE_ASSERTIONS 487 488 } // namespace framework 489