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 35 #include <dispatch/popupmenudispatcher.hxx> 36 #include <general.h> 37 #include <framework/menuconfiguration.hxx> 38 #include <framework/addonmenu.hxx> 39 #include <services.h> 40 #include <properties.h> 41 42 //_________________________________________________________________________________________________________________ 43 // interface includes 44 //_________________________________________________________________________________________________________________ 45 #include <com/sun/star/frame/FrameSearchFlag.hpp> 46 #include <com/sun/star/awt/XToolkit.hpp> 47 #include <com/sun/star/awt/WindowAttribute.hpp> 48 #include <com/sun/star/awt/WindowDescriptor.hpp> 49 #include <com/sun/star/awt/PosSize.hpp> 50 #include <com/sun/star/awt/XWindowPeer.hpp> 51 #include <com/sun/star/beans/UnknownPropertyException.hpp> 52 #include <com/sun/star/lang/WrappedTargetException.hpp> 53 #include <com/sun/star/beans/XPropertySet.hpp> 54 #include <com/sun/star/container/XEnumeration.hpp> 55 56 //_________________________________________________________________________________________________________________ 57 // includes of other projects 58 //_________________________________________________________________________________________________________________ 59 60 #include <ucbhelper/content.hxx> 61 #include <vos/mutex.hxx> 62 #include <rtl/ustrbuf.hxx> 63 #include <vcl/svapp.hxx> 64 65 //_________________________________________________________________________________________________________________ 66 // namespace 67 //_________________________________________________________________________________________________________________ 68 69 namespace framework{ 70 71 using namespace ::com::sun::star ; 72 using namespace ::com::sun::star::awt ; 73 using namespace ::com::sun::star::beans ; 74 using namespace ::com::sun::star::container ; 75 using namespace ::com::sun::star::frame ; 76 using namespace ::com::sun::star::lang ; 77 using namespace ::com::sun::star::uno ; 78 using namespace ::com::sun::star::util ; 79 using namespace ::cppu ; 80 using namespace ::osl ; 81 using namespace ::rtl ; 82 using namespace ::vos ; 83 84 //_________________________________________________________________________________________________________________ 85 // non exported const 86 //_________________________________________________________________________________________________________________ 87 const char* PROTOCOL_VALUE = "vnd.sun.star.popup:"; 88 const sal_Int32 PROTOCOL_LENGTH = 19; 89 90 //_________________________________________________________________________________________________________________ 91 // non exported definitions 92 //_________________________________________________________________________________________________________________ 93 94 //_________________________________________________________________________________________________________________ 95 // declarations 96 //_________________________________________________________________________________________________________________ 97 98 //***************************************************************************************************************** 99 // constructor 100 //***************************************************************************************************************** 101 PopupMenuDispatcher::PopupMenuDispatcher( 102 const uno::Reference< XMultiServiceFactory >& xFactory ) 103 // Init baseclasses first 104 : ThreadHelpBase ( &Application::GetSolarMutex() ) 105 , OWeakObject ( ) 106 // Init member 107 , m_xFactory ( xFactory ) 108 , m_aListenerContainer ( m_aLock.getShareableOslMutex() ) 109 , m_bAlreadyDisposed ( sal_False ) 110 , m_bActivateListener ( sal_False ) 111 { 112 } 113 114 //***************************************************************************************************************** 115 // destructor 116 //***************************************************************************************************************** 117 PopupMenuDispatcher::~PopupMenuDispatcher() 118 { 119 // Warn programmer if he forgot to dispose this instance. 120 // We must release all our references ... 121 // and a dtor isn't the best place to do that! 122 } 123 124 //***************************************************************************************************************** 125 // XInterface, XTypeProvider 126 //***************************************************************************************************************** 127 DEFINE_XINTERFACE_7 ( PopupMenuDispatcher , 128 ::cppu::OWeakObject , 129 DIRECT_INTERFACE( XTypeProvider ), 130 DIRECT_INTERFACE( XServiceInfo ), 131 DIRECT_INTERFACE( XDispatchProvider ), 132 DIRECT_INTERFACE( XDispatch ), 133 DIRECT_INTERFACE( XEventListener ), 134 DIRECT_INTERFACE( XInitialization ), 135 DERIVED_INTERFACE( XFrameActionListener, XEventListener ) 136 ) 137 138 DEFINE_XTYPEPROVIDER_7 ( PopupMenuDispatcher , 139 XTypeProvider , 140 XServiceInfo , 141 XDispatchProvider , 142 XDispatch , 143 XEventListener , 144 XInitialization , 145 XFrameActionListener 146 ) 147 148 DEFINE_XSERVICEINFO_MULTISERVICE( PopupMenuDispatcher , 149 ::cppu::OWeakObject , 150 SERVICENAME_PROTOCOLHANDLER , 151 IMPLEMENTATIONNAME_POPUPMENUDISPATCHER ) 152 153 DEFINE_INIT_SERVICE(PopupMenuDispatcher, 154 { 155 /*Attention 156 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance() 157 to create a new instance of this class by our own supported service factory. 158 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations! 159 */ 160 } 161 ) 162 163 //***************************************************************************************************************** 164 // XInitialization 165 //***************************************************************************************************************** 166 void SAL_CALL PopupMenuDispatcher::initialize( 167 const css::uno::Sequence< css::uno::Any >& lArguments ) 168 throw( css::uno::Exception, css::uno::RuntimeException) 169 { 170 css::uno::Reference< css::frame::XFrame > xFrame; 171 172 /* SAFE { */ 173 WriteGuard aWriteLock(m_aLock); 174 175 for (int a=0; a<lArguments.getLength(); ++a) 176 { 177 if (a==0) 178 { 179 lArguments[a] >>= xFrame; 180 m_xWeakFrame = xFrame; 181 182 m_bActivateListener = sal_True; 183 uno::Reference< css::frame::XFrameActionListener > xFrameActionListener( 184 (OWeakObject *)this, css::uno::UNO_QUERY ); 185 xFrame->addFrameActionListener( xFrameActionListener ); 186 } 187 } 188 189 aWriteLock.unlock(); 190 /* } SAFE */ 191 } 192 193 //***************************************************************************************************************** 194 // XDispatchProvider 195 //***************************************************************************************************************** 196 css::uno::Reference< css::frame::XDispatch > 197 SAL_CALL PopupMenuDispatcher::queryDispatch( 198 const css::util::URL& rURL , 199 const ::rtl::OUString& sTarget , 200 sal_Int32 nFlags ) 201 throw( css::uno::RuntimeException ) 202 { 203 css::uno::Reference< css::frame::XDispatch > xDispatch; 204 205 if ( rURL.Complete.compareToAscii( PROTOCOL_VALUE, PROTOCOL_LENGTH ) == 0 ) 206 { 207 // --- SAFE --- 208 ResetableGuard aGuard( m_aLock ); 209 impl_RetrievePopupControllerQuery(); 210 impl_CreateUriRefFactory(); 211 212 css::uno::Reference< css::container::XNameAccess > xPopupCtrlQuery( m_xPopupCtrlQuery ); 213 css::uno::Reference< css::uri::XUriReferenceFactory > xUriRefFactory( m_xUriRefFactory ); 214 aGuard.unlock(); 215 // --- SAFE --- 216 217 if ( xPopupCtrlQuery.is() ) 218 { 219 try 220 { 221 // Just use the main part of the URL for popup menu controllers 222 sal_Int32 nQueryPart( 0 ); 223 sal_Int32 nSchemePart( 0 ); 224 rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" )); 225 rtl::OUString aURL( rURL.Complete ); 226 227 nSchemePart = aURL.indexOf( ':' ); 228 if (( nSchemePart > 0 ) && 229 ( aURL.getLength() > ( nSchemePart+1 ))) 230 { 231 nQueryPart = aURL.indexOf( '?', nSchemePart ); 232 if ( nQueryPart > 0 ) 233 aBaseURL += aURL.copy( nSchemePart+1, nQueryPart-(nSchemePart+1) ); 234 else if ( nQueryPart == -1 ) 235 aBaseURL += aURL.copy( nSchemePart+1 ); 236 } 237 238 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider; 239 240 // Find popup menu controller using the base URL 241 xPopupCtrlQuery->getByName( aBaseURL ) >>= xDispatchProvider; 242 aGuard.unlock(); 243 244 // Ask popup menu dispatch provider for dispatch object 245 if ( xDispatchProvider.is() ) 246 xDispatch = xDispatchProvider->queryDispatch( rURL, sTarget, nFlags ); 247 } 248 catch ( RuntimeException& ) 249 { 250 throw; 251 } 252 catch ( Exception& ) 253 { 254 } 255 } 256 } 257 return xDispatch; 258 } 259 260 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL 261 PopupMenuDispatcher::queryDispatches( 262 const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) 263 throw( css::uno::RuntimeException ) 264 { 265 sal_Int32 nCount = lDescriptor.getLength(); 266 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount ); 267 for( sal_Int32 i=0; i<nCount; ++i ) 268 { 269 lDispatcher[i] = this->queryDispatch( 270 lDescriptor[i].FeatureURL, 271 lDescriptor[i].FrameName, 272 lDescriptor[i].SearchFlags); 273 } 274 return lDispatcher; 275 } 276 277 //***************************************************************************************************************** 278 // XDispatch 279 //***************************************************************************************************************** 280 void 281 SAL_CALL PopupMenuDispatcher::dispatch( 282 const URL& /*aURL*/ , 283 const Sequence< PropertyValue >& /*seqProperties*/ ) 284 throw( RuntimeException ) 285 { 286 } 287 288 //***************************************************************************************************************** 289 // XDispatch 290 //***************************************************************************************************************** 291 void 292 SAL_CALL PopupMenuDispatcher::addStatusListener( 293 const uno::Reference< XStatusListener >& xControl, 294 const URL& aURL ) 295 throw( RuntimeException ) 296 { 297 // Ready for multithreading 298 ResetableGuard aGuard( m_aLock ); 299 // Safe impossible cases 300 // Add listener to container. 301 m_aListenerContainer.addInterface( aURL.Complete, xControl ); 302 } 303 304 //***************************************************************************************************************** 305 // XDispatch 306 //***************************************************************************************************************** 307 void 308 SAL_CALL PopupMenuDispatcher::removeStatusListener( 309 const uno::Reference< XStatusListener >& xControl, 310 const URL& aURL ) 311 throw( RuntimeException ) 312 { 313 // Ready for multithreading 314 ResetableGuard aGuard( m_aLock ); 315 // Safe impossible cases 316 // Add listener to container. 317 m_aListenerContainer.removeInterface( aURL.Complete, xControl ); 318 } 319 320 //***************************************************************************************************************** 321 // XFrameActionListener 322 //***************************************************************************************************************** 323 324 void 325 SAL_CALL PopupMenuDispatcher::frameAction( 326 const FrameActionEvent& aEvent ) 327 throw ( RuntimeException ) 328 { 329 ResetableGuard aGuard( m_aLock ); 330 331 if (( aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) || 332 ( aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED )) 333 { 334 // Reset query reference to requery it again next time 335 m_xPopupCtrlQuery.clear(); 336 } 337 } 338 339 //***************************************************************************************************************** 340 // XEventListener 341 //***************************************************************************************************************** 342 void 343 SAL_CALL PopupMenuDispatcher::disposing( const EventObject& ) throw( RuntimeException ) 344 { 345 // Ready for multithreading 346 ResetableGuard aGuard( m_aLock ); 347 // Safe impossible cases 348 LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" ) 349 350 if( m_bAlreadyDisposed == sal_False ) 351 { 352 m_bAlreadyDisposed = sal_True; 353 354 if ( m_bActivateListener ) 355 { 356 uno::Reference< XFrame > xFrame( m_xWeakFrame.get(), UNO_QUERY ); 357 if ( xFrame.is() ) 358 { 359 xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY )); 360 m_bActivateListener = sal_False; 361 } 362 } 363 364 // Forget our factory. 365 m_xFactory = uno::Reference< XMultiServiceFactory >(); 366 } 367 } 368 369 void PopupMenuDispatcher::impl_RetrievePopupControllerQuery() 370 { 371 if ( !m_xPopupCtrlQuery.is() ) 372 { 373 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager; 374 css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame ); 375 376 if ( xFrame.is() ) 377 { 378 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY ); 379 if ( xPropSet.is() ) 380 { 381 try 382 { 383 xPropSet->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER ) >>= xLayoutManager; 384 385 if ( xLayoutManager.is() ) 386 { 387 css::uno::Reference< css::ui::XUIElement > xMenuBar; 388 rtl::OUString aMenuBar( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" )); 389 xMenuBar = xLayoutManager->getElement( aMenuBar ); 390 391 m_xPopupCtrlQuery = css::uno::Reference< css::container::XNameAccess >( 392 xMenuBar, css::uno::UNO_QUERY ); 393 } 394 } 395 catch ( css::uno::RuntimeException& ) 396 { 397 throw; 398 } 399 catch ( css::uno::Exception& ) 400 { 401 } 402 } 403 } 404 } 405 } 406 407 void PopupMenuDispatcher::impl_CreateUriRefFactory() 408 { 409 if ( !m_xUriRefFactory.is() ) 410 { 411 rtl::OUString aUriRefFactoryService( 412 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uri.UriReferenceFactory" )); 413 414 m_xUriRefFactory = css::uno::Reference< css::uri::XUriReferenceFactory >( 415 m_xFactory->createInstance( aUriRefFactoryService ), 416 css::uno::UNO_QUERY); 417 418 } 419 } 420 421 } // namespace framework 422