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