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