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