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 { 165 css::uno::Reference< css::frame::XFrame > xFrame; 166 167 /* SAFE { */ 168 WriteGuard aWriteLock(m_aLock); 169 170 for (int a=0; a<lArguments.getLength(); ++a) 171 { 172 if (a==0) 173 { 174 lArguments[a] >>= xFrame; 175 m_xWeakFrame = xFrame; 176 177 m_bActivateListener = sal_True; 178 uno::Reference< css::frame::XFrameActionListener > xFrameActionListener( 179 (OWeakObject *)this, css::uno::UNO_QUERY ); 180 xFrame->addFrameActionListener( xFrameActionListener ); 181 } 182 } 183 184 aWriteLock.unlock(); 185 /* } SAFE */ 186 } 187 188 //***************************************************************************************************************** 189 // XDispatchProvider 190 //***************************************************************************************************************** 191 css::uno::Reference< css::frame::XDispatch > 192 SAL_CALL PopupMenuDispatcher::queryDispatch( 193 const css::util::URL& rURL , 194 const ::rtl::OUString& sTarget , 195 sal_Int32 nFlags ) 196 { 197 css::uno::Reference< css::frame::XDispatch > xDispatch; 198 199 if ( rURL.Complete.compareToAscii( PROTOCOL_VALUE, PROTOCOL_LENGTH ) == 0 ) 200 { 201 // --- SAFE --- 202 ResetableGuard aGuard( m_aLock ); 203 impl_RetrievePopupControllerQuery(); 204 impl_CreateUriRefFactory(); 205 206 css::uno::Reference< css::container::XNameAccess > xPopupCtrlQuery( m_xPopupCtrlQuery ); 207 css::uno::Reference< css::uri::XUriReferenceFactory > xUriRefFactory( m_xUriRefFactory ); 208 aGuard.unlock(); 209 // --- SAFE --- 210 211 if ( xPopupCtrlQuery.is() ) 212 { 213 try 214 { 215 // Just use the main part of the URL for popup menu controllers 216 sal_Int32 nQueryPart( 0 ); 217 sal_Int32 nSchemePart( 0 ); 218 rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" )); 219 rtl::OUString aURL( rURL.Complete ); 220 221 nSchemePart = aURL.indexOf( ':' ); 222 if (( nSchemePart > 0 ) && 223 ( aURL.getLength() > ( nSchemePart+1 ))) 224 { 225 nQueryPart = aURL.indexOf( '?', nSchemePart ); 226 if ( nQueryPart > 0 ) 227 aBaseURL += aURL.copy( nSchemePart+1, nQueryPart-(nSchemePart+1) ); 228 else if ( nQueryPart == -1 ) 229 aBaseURL += aURL.copy( nSchemePart+1 ); 230 } 231 232 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider; 233 234 // Find popup menu controller using the base URL 235 xPopupCtrlQuery->getByName( aBaseURL ) >>= xDispatchProvider; 236 aGuard.unlock(); 237 238 // Ask popup menu dispatch provider for dispatch object 239 if ( xDispatchProvider.is() ) 240 xDispatch = xDispatchProvider->queryDispatch( rURL, sTarget, nFlags ); 241 } 242 catch ( RuntimeException& ) 243 { 244 throw; 245 } 246 catch ( Exception& ) 247 { 248 } 249 } 250 } 251 return xDispatch; 252 } 253 254 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL 255 PopupMenuDispatcher::queryDispatches( 256 const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) 257 { 258 sal_Int32 nCount = lDescriptor.getLength(); 259 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount ); 260 for( sal_Int32 i=0; i<nCount; ++i ) 261 { 262 lDispatcher[i] = this->queryDispatch( 263 lDescriptor[i].FeatureURL, 264 lDescriptor[i].FrameName, 265 lDescriptor[i].SearchFlags); 266 } 267 return lDispatcher; 268 } 269 270 //***************************************************************************************************************** 271 // XDispatch 272 //***************************************************************************************************************** 273 void 274 SAL_CALL PopupMenuDispatcher::dispatch( 275 const URL& /*aURL*/ , 276 const Sequence< PropertyValue >& /*seqProperties*/ ) 277 { 278 } 279 280 //***************************************************************************************************************** 281 // XDispatch 282 //***************************************************************************************************************** 283 void 284 SAL_CALL PopupMenuDispatcher::addStatusListener( 285 const uno::Reference< XStatusListener >& xControl, 286 const URL& aURL ) 287 { 288 // Ready for multithreading 289 ResetableGuard aGuard( m_aLock ); 290 // Safe impossible cases 291 // Add listener to container. 292 m_aListenerContainer.addInterface( aURL.Complete, xControl ); 293 } 294 295 //***************************************************************************************************************** 296 // XDispatch 297 //***************************************************************************************************************** 298 void 299 SAL_CALL PopupMenuDispatcher::removeStatusListener( 300 const uno::Reference< XStatusListener >& xControl, 301 const URL& aURL ) 302 { 303 // Ready for multithreading 304 ResetableGuard aGuard( m_aLock ); 305 // Safe impossible cases 306 // Add listener to container. 307 m_aListenerContainer.removeInterface( aURL.Complete, xControl ); 308 } 309 310 //***************************************************************************************************************** 311 // XFrameActionListener 312 //***************************************************************************************************************** 313 314 void 315 SAL_CALL PopupMenuDispatcher::frameAction( 316 const FrameActionEvent& aEvent ) 317 { 318 ResetableGuard aGuard( m_aLock ); 319 320 if (( aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) || 321 ( aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED )) 322 { 323 // Reset query reference to requery it again next time 324 m_xPopupCtrlQuery.clear(); 325 } 326 } 327 328 //***************************************************************************************************************** 329 // XEventListener 330 //***************************************************************************************************************** 331 void 332 SAL_CALL PopupMenuDispatcher::disposing( const EventObject& ) 333 { 334 // Ready for multithreading 335 ResetableGuard aGuard( m_aLock ); 336 // Safe impossible cases 337 LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" ) 338 339 if( m_bAlreadyDisposed == sal_False ) 340 { 341 m_bAlreadyDisposed = sal_True; 342 343 if ( m_bActivateListener ) 344 { 345 uno::Reference< XFrame > xFrame( m_xWeakFrame.get(), UNO_QUERY ); 346 if ( xFrame.is() ) 347 { 348 xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY )); 349 m_bActivateListener = sal_False; 350 } 351 } 352 353 // Forget our factory. 354 m_xFactory = uno::Reference< XMultiServiceFactory >(); 355 } 356 } 357 358 void PopupMenuDispatcher::impl_RetrievePopupControllerQuery() 359 { 360 if ( !m_xPopupCtrlQuery.is() ) 361 { 362 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager; 363 css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame ); 364 365 if ( xFrame.is() ) 366 { 367 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY ); 368 if ( xPropSet.is() ) 369 { 370 try 371 { 372 xPropSet->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER ) >>= xLayoutManager; 373 374 if ( xLayoutManager.is() ) 375 { 376 css::uno::Reference< css::ui::XUIElement > xMenuBar; 377 rtl::OUString aMenuBar( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" )); 378 xMenuBar = xLayoutManager->getElement( aMenuBar ); 379 380 m_xPopupCtrlQuery = css::uno::Reference< css::container::XNameAccess >( 381 xMenuBar, css::uno::UNO_QUERY ); 382 } 383 } 384 catch ( css::uno::RuntimeException& ) 385 { 386 throw; 387 } 388 catch ( css::uno::Exception& ) 389 { 390 } 391 } 392 } 393 } 394 } 395 396 void PopupMenuDispatcher::impl_CreateUriRefFactory() 397 { 398 if ( !m_xUriRefFactory.is() ) 399 { 400 rtl::OUString aUriRefFactoryService( 401 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uri.UriReferenceFactory" )); 402 403 m_xUriRefFactory = css::uno::Reference< css::uri::XUriReferenceFactory >( 404 m_xFactory->createInstance( aUriRefFactoryService ), 405 css::uno::UNO_QUERY); 406 407 } 408 } 409 410 } // namespace framework 411