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 #include "controllerframe.hxx" 29 #include "IController.hxx" 30 31 /** === begin UNO includes === **/ 32 #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp> 33 #include <com/sun/star/awt/XTopWindow.hpp> 34 #include <com/sun/star/awt/XWindow2.hpp> 35 #include <com/sun/star/lang/DisposedException.hpp> 36 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp> 37 #include <com/sun/star/frame/XController2.hpp> 38 /** === end UNO includes === **/ 39 40 #include <cppuhelper/implbase1.hxx> 41 #include <rtl/ref.hxx> 42 #include <sfx2/objsh.hxx> 43 #include <tools/diagnose_ex.h> 44 #include <toolkit/helper/vclunohelper.hxx> 45 #include <vcl/window.hxx> 46 47 //........................................................................ 48 namespace dbaui 49 { 50 //........................................................................ 51 52 /** === begin UNO using === **/ 53 using ::com::sun::star::uno::Reference; 54 using ::com::sun::star::uno::XInterface; 55 using ::com::sun::star::uno::UNO_QUERY; 56 using ::com::sun::star::uno::UNO_QUERY_THROW; 57 using ::com::sun::star::uno::UNO_SET_THROW; 58 using ::com::sun::star::uno::Exception; 59 using ::com::sun::star::uno::RuntimeException; 60 using ::com::sun::star::uno::Any; 61 using ::com::sun::star::uno::makeAny; 62 using ::com::sun::star::frame::XFrame; 63 using ::com::sun::star::frame::FrameAction; 64 using ::com::sun::star::frame::FrameAction_FRAME_ACTIVATED; 65 using ::com::sun::star::frame::FrameAction_FRAME_UI_ACTIVATED; 66 using ::com::sun::star::frame::FrameAction_FRAME_DEACTIVATING; 67 using ::com::sun::star::frame::FrameAction_FRAME_UI_DEACTIVATING; 68 using ::com::sun::star::frame::XModel; 69 using ::com::sun::star::frame::XController; 70 using ::com::sun::star::frame::XController2; 71 using ::com::sun::star::frame::XFramesSupplier; 72 using ::com::sun::star::sdb::XOfficeDatabaseDocument; 73 using ::com::sun::star::awt::XTopWindow; 74 using ::com::sun::star::awt::XTopWindowListener; 75 using ::com::sun::star::awt::XWindow2; 76 using ::com::sun::star::lang::DisposedException; 77 using ::com::sun::star::lang::EventObject; 78 using ::com::sun::star::document::XDocumentEventBroadcaster; 79 using ::com::sun::star::awt::XWindow; 80 /** === end UNO using === **/ 81 82 //==================================================================== 83 //= FrameWindowActivationListener 84 //==================================================================== 85 typedef ::cppu::WeakImplHelper1 < XTopWindowListener 86 > FrameWindowActivationListener_Base; 87 class FrameWindowActivationListener : public FrameWindowActivationListener_Base 88 { 89 public: 90 FrameWindowActivationListener( ControllerFrame_Data& _rData ); 91 92 void dispose(); 93 94 protected: 95 ~FrameWindowActivationListener(); 96 97 // XTopWindowListener 98 virtual void SAL_CALL windowOpened( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); 99 virtual void SAL_CALL windowClosing( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); 100 virtual void SAL_CALL windowClosed( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); 101 virtual void SAL_CALL windowMinimized( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); 102 virtual void SAL_CALL windowNormalized( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); 103 virtual void SAL_CALL windowActivated( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); 104 virtual void SAL_CALL windowDeactivated( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); 105 106 // XEventListener 107 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); 108 109 private: 110 void impl_checkDisposed_throw() const; 111 void impl_registerOnFrameContainerWindow_nothrow( bool _bRegister ); 112 113 private: 114 ControllerFrame_Data* m_pData; 115 }; 116 117 //==================================================================== 118 //= ControllerFrame_Data 119 //==================================================================== 120 struct ControllerFrame_Data 121 { 122 ControllerFrame_Data( IController& _rController ) 123 :m_rController( _rController ) 124 ,m_xFrame() 125 ,m_xDocEventBroadcaster() 126 ,m_pListener() 127 ,m_bActive( false ) 128 ,m_bIsTopLevelDocumentWindow( false ) 129 { 130 } 131 132 IController& m_rController; 133 Reference< XFrame > m_xFrame; 134 Reference< XDocumentEventBroadcaster > m_xDocEventBroadcaster; 135 ::rtl::Reference< FrameWindowActivationListener > m_pListener; 136 bool m_bActive; 137 bool m_bIsTopLevelDocumentWindow; 138 }; 139 140 //==================================================================== 141 //= helper 142 //==================================================================== 143 //-------------------------------------------------------------------- 144 static void lcl_setFrame_nothrow( ControllerFrame_Data& _rData, const Reference< XFrame >& _rxFrame ) 145 { 146 // release old listener 147 if ( _rData.m_pListener.get() ) 148 { 149 _rData.m_pListener->dispose(); 150 _rData.m_pListener = NULL; 151 } 152 153 // remember new frame 154 _rData.m_xFrame = _rxFrame; 155 156 // create new listener 157 if ( _rData.m_xFrame.is() ) 158 _rData.m_pListener = new FrameWindowActivationListener( _rData ); 159 160 // at this point in time, we can assume the controller also has a model set, if it supports models 161 try 162 { 163 Reference< XController > xController( _rData.m_rController.getXController(), UNO_SET_THROW ); 164 Reference< XModel > xModel( xController->getModel() ); 165 if ( xModel.is() ) 166 _rData.m_xDocEventBroadcaster.set( xModel, UNO_QUERY ); 167 } 168 catch( const Exception& ) 169 { 170 DBG_UNHANDLED_EXCEPTION(); 171 } 172 } 173 174 //-------------------------------------------------------------------- 175 static bool lcl_isActive_nothrow( const Reference< XFrame >& _rxFrame ) 176 { 177 bool bIsActive = false; 178 try 179 { 180 if ( _rxFrame.is() ) 181 { 182 Reference< XWindow2 > xWindow( _rxFrame->getContainerWindow(), UNO_QUERY_THROW ); 183 bIsActive = xWindow->isActive(); 184 } 185 186 } 187 catch( const Exception& ) 188 { 189 DBG_UNHANDLED_EXCEPTION(); 190 } 191 return bIsActive; 192 } 193 194 //-------------------------------------------------------------------- 195 /** updates various global and local states with a new active component 196 197 In particular, the following are updated 198 * the global working document (aka Basic's ThisComponent in the application 199 Basic), with our controller's model, or the controller itself if there is no such 200 model. 201 */ 202 static void lcl_updateActiveComponents_nothrow( const ControllerFrame_Data& _rData ) 203 { 204 try 205 { 206 Reference< XController > xCompController( _rData.m_rController.getXController() ); 207 OSL_ENSURE( xCompController.is(), "lcl_updateActiveComponents_nothrow: can't do anything without a controller!" ); 208 if ( !xCompController.is() ) 209 return; 210 211 if ( _rData.m_bActive && _rData.m_bIsTopLevelDocumentWindow ) 212 { 213 // set the "current component" at the SfxObjectShell 214 Reference< XModel > xModel( xCompController->getModel() ); 215 Reference< XInterface > xCurrentComponent; 216 if ( xModel.is() ) 217 xCurrentComponent = xModel; 218 else 219 xCurrentComponent = xCompController; 220 SfxObjectShell::SetCurrentComponent( xCurrentComponent ); 221 } 222 } 223 catch( const Exception& ) 224 { 225 DBG_UNHANDLED_EXCEPTION(); 226 } 227 } 228 229 //-------------------------------------------------------------------- 230 /** broadcasts the OnFocus resp. OnUnfocus event 231 */ 232 static void lcl_notifyFocusChange_nothrow( ControllerFrame_Data& _rData, bool _bActive ) 233 { 234 try 235 { 236 if ( _rData.m_xDocEventBroadcaster.is() ) 237 { 238 ::rtl::OUString sEventName( ::rtl::OUString::createFromAscii( _bActive ? "OnFocus" : "OnUnfocus" ) ); 239 Reference< XController2 > xController( _rData.m_rController.getXController(), UNO_QUERY_THROW ); 240 _rData.m_xDocEventBroadcaster->notifyDocumentEvent( sEventName, xController, Any() ); 241 } 242 } 243 catch( const Exception& ) 244 { 245 DBG_UNHANDLED_EXCEPTION(); 246 } 247 } 248 249 //-------------------------------------------------------------------- 250 static void lcl_updateActive_nothrow( ControllerFrame_Data& _rData, bool _bActive ) 251 { 252 if ( _rData.m_bActive == _bActive ) 253 return; 254 _rData.m_bActive = _bActive; 255 256 lcl_updateActiveComponents_nothrow( _rData ); 257 lcl_notifyFocusChange_nothrow( _rData, _bActive ); 258 } 259 260 //-------------------------------------------------------------------- 261 FrameWindowActivationListener::FrameWindowActivationListener( ControllerFrame_Data& _rData ) 262 :m_pData( &_rData ) 263 { 264 impl_registerOnFrameContainerWindow_nothrow( true ); 265 } 266 267 //-------------------------------------------------------------------- 268 FrameWindowActivationListener::~FrameWindowActivationListener() 269 { 270 } 271 272 //-------------------------------------------------------------------- 273 void FrameWindowActivationListener::dispose() 274 { 275 impl_registerOnFrameContainerWindow_nothrow( false ); 276 m_pData = NULL; 277 } 278 279 //-------------------------------------------------------------------- 280 void FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow( bool _bRegister ) 281 { 282 OSL_ENSURE( m_pData && m_pData->m_xFrame.is(), "FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow: no frame!" ); 283 if ( !m_pData || !m_pData->m_xFrame.is() ) 284 return; 285 286 try 287 { 288 void ( SAL_CALL XTopWindow::*pListenerAction )( const Reference< XTopWindowListener >& ) = 289 _bRegister ? &XTopWindow::addTopWindowListener : &XTopWindow::removeTopWindowListener; 290 291 const Reference< XWindow > xContainerWindow( m_pData->m_xFrame->getContainerWindow(), UNO_SET_THROW ); 292 if ( _bRegister ) 293 { 294 const Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow ); 295 ENSURE_OR_THROW( pContainerWindow, "no Window implementation for the frame's container window!" ); 296 297 /*const Window* pContainerParentWindow = pContainerWindow->GetParent(); 298 if ( pContainerParentWindow && ( pContainerParentWindow->GetType() == WINDOW_BORDERWINDOW ) ) 299 pContainerParentWindow = pContainerParentWindow->GetParent(); 300 m_pData->m_bIsTopLevelDocumentWindow = ( pContainerParentWindow == NULL );*/ 301 302 m_pData->m_bIsTopLevelDocumentWindow = ( pContainerWindow->GetExtendedStyle() & WB_EXT_DOCUMENT ) != 0; 303 } 304 305 const Reference< XTopWindow > xFrameContainer( xContainerWindow, UNO_QUERY ); 306 if ( xFrameContainer.is() ) 307 (xFrameContainer.get()->*pListenerAction)( this ); 308 } 309 catch( const Exception& ) 310 { 311 DBG_UNHANDLED_EXCEPTION(); 312 } 313 } 314 315 //-------------------------------------------------------------------- 316 void FrameWindowActivationListener::impl_checkDisposed_throw() const 317 { 318 if ( !m_pData ) 319 throw DisposedException( ::rtl::OUString(), *const_cast< FrameWindowActivationListener* >( this ) ); 320 } 321 322 //-------------------------------------------------------------------- 323 void SAL_CALL FrameWindowActivationListener::windowOpened( const EventObject& /*_rEvent*/ ) throw (RuntimeException) 324 { 325 // not interested in 326 } 327 328 //-------------------------------------------------------------------- 329 void SAL_CALL FrameWindowActivationListener::windowClosing( const EventObject& /*_rEvent*/ ) throw (RuntimeException) 330 { 331 // not interested in 332 } 333 334 //-------------------------------------------------------------------- 335 void SAL_CALL FrameWindowActivationListener::windowClosed( const EventObject& /*_rEvent*/ ) throw (RuntimeException) 336 { 337 // not interested in 338 } 339 340 //-------------------------------------------------------------------- 341 void SAL_CALL FrameWindowActivationListener::windowMinimized( const EventObject& /*_rEvent*/ ) throw (RuntimeException) 342 { 343 // not interested in 344 } 345 346 //-------------------------------------------------------------------- 347 void SAL_CALL FrameWindowActivationListener::windowNormalized( const EventObject& /*_rEvent*/ ) throw (RuntimeException) 348 { 349 // not interested in 350 } 351 352 //-------------------------------------------------------------------- 353 void SAL_CALL FrameWindowActivationListener::windowActivated( const EventObject& /*_rEvent*/ ) throw (RuntimeException) 354 { 355 impl_checkDisposed_throw(); 356 lcl_updateActive_nothrow( *m_pData, true ); 357 } 358 359 //-------------------------------------------------------------------- 360 void SAL_CALL FrameWindowActivationListener::windowDeactivated( const EventObject& /*_rEvent*/ ) throw (RuntimeException) 361 { 362 impl_checkDisposed_throw(); 363 lcl_updateActive_nothrow( *m_pData, false ); 364 } 365 366 //-------------------------------------------------------------------- 367 void SAL_CALL FrameWindowActivationListener::disposing( const EventObject& /*_rEvent*/ ) throw (RuntimeException) 368 { 369 dispose(); 370 } 371 372 //==================================================================== 373 //= ControllerFrame 374 //==================================================================== 375 //-------------------------------------------------------------------- 376 ControllerFrame::ControllerFrame( IController& _rController ) 377 :m_pData( new ControllerFrame_Data( _rController ) ) 378 { 379 } 380 381 //-------------------------------------------------------------------- 382 ControllerFrame::~ControllerFrame() 383 { 384 } 385 386 //-------------------------------------------------------------------- 387 const Reference< XFrame >& ControllerFrame::attachFrame( const Reference< XFrame >& _rxFrame ) 388 { 389 // set new frame, including listener handling 390 lcl_setFrame_nothrow( *m_pData, _rxFrame ); 391 392 // determine whether we're active 393 m_pData->m_bActive = lcl_isActive_nothrow( m_pData->m_xFrame ); 394 395 // update active component 396 if ( m_pData->m_bActive ) 397 { 398 lcl_updateActiveComponents_nothrow( *m_pData ); 399 lcl_notifyFocusChange_nothrow( *m_pData, true ); 400 } 401 402 return m_pData->m_xFrame; 403 } 404 405 //-------------------------------------------------------------------- 406 const Reference< XFrame >& ControllerFrame::getFrame() const 407 { 408 return m_pData->m_xFrame; 409 } 410 411 //-------------------------------------------------------------------- 412 bool ControllerFrame::isActive() const 413 { 414 return m_pData->m_bActive; 415 } 416 417 //-------------------------------------------------------------------- 418 void ControllerFrame::frameAction( FrameAction _eAction ) 419 { 420 bool bActive = m_pData->m_bActive; 421 422 switch ( _eAction ) 423 { 424 case FrameAction_FRAME_ACTIVATED: 425 case FrameAction_FRAME_UI_ACTIVATED: 426 bActive = true; 427 break; 428 429 case FrameAction_FRAME_DEACTIVATING: 430 case FrameAction_FRAME_UI_DEACTIVATING: 431 bActive = false; 432 break; 433 434 default: 435 break; 436 } 437 438 lcl_updateActive_nothrow( *m_pData, bActive ); 439 } 440 441 //........................................................................ 442 } // namespace dbaui 443 //........................................................................ 444