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