1*b3f79822SAndrew Rist /************************************************************** 2*b3f79822SAndrew Rist * 3*b3f79822SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*b3f79822SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*b3f79822SAndrew Rist * distributed with this work for additional information 6*b3f79822SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*b3f79822SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*b3f79822SAndrew Rist * "License"); you may not use this file except in compliance 9*b3f79822SAndrew Rist * with the License. You may obtain a copy of the License at 10*b3f79822SAndrew Rist * 11*b3f79822SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*b3f79822SAndrew Rist * 13*b3f79822SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*b3f79822SAndrew Rist * software distributed under the License is distributed on an 15*b3f79822SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b3f79822SAndrew Rist * KIND, either express or implied. See the License for the 17*b3f79822SAndrew Rist * specific language governing permissions and limitations 18*b3f79822SAndrew Rist * under the License. 19*b3f79822SAndrew Rist * 20*b3f79822SAndrew Rist *************************************************************/ 21*b3f79822SAndrew Rist 22*b3f79822SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "vbaeventshelper.hxx" 25cdf0e10cSrcweir 26cdf0e10cSrcweir #include <com/sun/star/awt/XTopWindow.hpp> 27cdf0e10cSrcweir #include <com/sun/star/awt/XTopWindowListener.hpp> 28cdf0e10cSrcweir #include <com/sun/star/awt/XWindowListener.hpp> 29cdf0e10cSrcweir #include <com/sun/star/frame/XBorderResizeListener.hpp> 30cdf0e10cSrcweir #include <com/sun/star/frame/XControllerBorder.hpp> 31cdf0e10cSrcweir #include <com/sun/star/script/ModuleType.hpp> 32cdf0e10cSrcweir #include <com/sun/star/script/vba/VBAEventId.hpp> 33cdf0e10cSrcweir #include <com/sun/star/sheet/XCellRangeAddressable.hpp> 34cdf0e10cSrcweir #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp> 35cdf0e10cSrcweir #include <com/sun/star/table/XCellRange.hpp> 36cdf0e10cSrcweir #include <com/sun/star/util/XChangesListener.hpp> 37cdf0e10cSrcweir #include <com/sun/star/util/XChangesNotifier.hpp> 38cdf0e10cSrcweir 39cdf0e10cSrcweir #include <cppuhelper/implbase4.hxx> 40cdf0e10cSrcweir #include <toolkit/unohlp.hxx> 41cdf0e10cSrcweir #include <unotools/eventcfg.hxx> 42cdf0e10cSrcweir #include <vbahelper/helperdecl.hxx> 43cdf0e10cSrcweir #include <vcl/svapp.hxx> 44cdf0e10cSrcweir #include <vcl/window.hxx> 45cdf0e10cSrcweir 46cdf0e10cSrcweir #include "cellsuno.hxx" 47cdf0e10cSrcweir #include "convuno.hxx" 48cdf0e10cSrcweir #include "vbaapplication.hxx" 49cdf0e10cSrcweir 50cdf0e10cSrcweir using namespace ::com::sun::star; 51cdf0e10cSrcweir using namespace ::com::sun::star::script::vba::VBAEventId; 52cdf0e10cSrcweir using namespace ::ooo::vba; 53cdf0e10cSrcweir 54cdf0e10cSrcweir using ::rtl::OUString; 55cdf0e10cSrcweir 56cdf0e10cSrcweir // ============================================================================ 57cdf0e10cSrcweir 58cdf0e10cSrcweir namespace { 59cdf0e10cSrcweir 60cdf0e10cSrcweir /** Extracts a sheet index from the specified element of the passed sequence. 61cdf0e10cSrcweir The element may be an integer, a Calc range or ranges object, or a VBA Range object. */ 62cdf0e10cSrcweir SCTAB lclGetTabFromArgs( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) throw (lang::IllegalArgumentException) 63cdf0e10cSrcweir { 64cdf0e10cSrcweir VbaEventsHelperBase::checkArgument( rArgs, nIndex ); 65cdf0e10cSrcweir 66cdf0e10cSrcweir // first try to extract a sheet index 67cdf0e10cSrcweir sal_Int32 nTab = -1; 68cdf0e10cSrcweir if( rArgs[ nIndex ] >>= nTab ) 69cdf0e10cSrcweir { 70cdf0e10cSrcweir if( (nTab < 0) || (nTab > MAXTAB) ) 71cdf0e10cSrcweir throw lang::IllegalArgumentException(); 72cdf0e10cSrcweir return static_cast< SCTAB >( nTab ); 73cdf0e10cSrcweir } 74cdf0e10cSrcweir 75cdf0e10cSrcweir // try VBA Range object 76cdf0e10cSrcweir uno::Reference< excel::XRange > xVbaRange = getXSomethingFromArgs< excel::XRange >( rArgs, nIndex ); 77cdf0e10cSrcweir if( xVbaRange.is() ) 78cdf0e10cSrcweir { 79cdf0e10cSrcweir uno::Reference< XHelperInterface > xVbaHelper( xVbaRange, uno::UNO_QUERY_THROW ); 80cdf0e10cSrcweir // TODO: in the future, the parent may be an excel::XChart (chart sheet) -> will there be a common base interface? 81cdf0e10cSrcweir uno::Reference< excel::XWorksheet > xVbaSheet( xVbaHelper->getParent(), uno::UNO_QUERY_THROW ); 82cdf0e10cSrcweir // VBA sheet index is 1-based 83cdf0e10cSrcweir return static_cast< SCTAB >( xVbaSheet->getIndex() - 1 ); 84cdf0e10cSrcweir } 85cdf0e10cSrcweir 86cdf0e10cSrcweir // try single UNO range object 87cdf0e10cSrcweir uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable = getXSomethingFromArgs< sheet::XCellRangeAddressable >( rArgs, nIndex ); 88cdf0e10cSrcweir if( xCellRangeAddressable.is() ) 89cdf0e10cSrcweir return xCellRangeAddressable->getRangeAddress().Sheet; 90cdf0e10cSrcweir 91cdf0e10cSrcweir // at last, try UNO range list 92cdf0e10cSrcweir uno::Reference< sheet::XSheetCellRangeContainer > xRanges = getXSomethingFromArgs< sheet::XSheetCellRangeContainer >( rArgs, nIndex ); 93cdf0e10cSrcweir if( xRanges.is() ) 94cdf0e10cSrcweir { 95cdf0e10cSrcweir uno::Sequence< table::CellRangeAddress > aRangeAddresses = xRanges->getRangeAddresses(); 96cdf0e10cSrcweir if( aRangeAddresses.getLength() > 0 ) 97cdf0e10cSrcweir return aRangeAddresses[ 0 ].Sheet; 98cdf0e10cSrcweir } 99cdf0e10cSrcweir 100cdf0e10cSrcweir throw lang::IllegalArgumentException(); 101cdf0e10cSrcweir } 102cdf0e10cSrcweir 103cdf0e10cSrcweir /** Returns the AWT container window of the passed controller. */ 104cdf0e10cSrcweir uno::Reference< awt::XWindow > lclGetWindowForController( const uno::Reference< frame::XController >& rxController ) 105cdf0e10cSrcweir { 106cdf0e10cSrcweir if( rxController.is() ) try 107cdf0e10cSrcweir { 108cdf0e10cSrcweir uno::Reference< frame::XFrame > xFrame( rxController->getFrame(), uno::UNO_SET_THROW ); 109cdf0e10cSrcweir return xFrame->getContainerWindow(); 110cdf0e10cSrcweir } 111cdf0e10cSrcweir catch( uno::Exception& ) 112cdf0e10cSrcweir { 113cdf0e10cSrcweir } 114cdf0e10cSrcweir return 0; 115cdf0e10cSrcweir } 116cdf0e10cSrcweir 117cdf0e10cSrcweir } // namespace 118cdf0e10cSrcweir 119cdf0e10cSrcweir // ============================================================================ 120cdf0e10cSrcweir 121cdf0e10cSrcweir typedef ::cppu::WeakImplHelper4< awt::XTopWindowListener, awt::XWindowListener, frame::XBorderResizeListener, util::XChangesListener > ScVbaEventListener_BASE; 122cdf0e10cSrcweir 123cdf0e10cSrcweir // This class is to process Workbook window related event 124cdf0e10cSrcweir class ScVbaEventListener : public ScVbaEventListener_BASE 125cdf0e10cSrcweir { 126cdf0e10cSrcweir public : 127cdf0e10cSrcweir ScVbaEventListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell ); 128cdf0e10cSrcweir virtual ~ScVbaEventListener(); 129cdf0e10cSrcweir 130cdf0e10cSrcweir /** Starts listening to the passed document controller. */ 131cdf0e10cSrcweir void startControllerListening( const uno::Reference< frame::XController >& rxController ); 132cdf0e10cSrcweir /** Stops listening to the passed document controller. */ 133cdf0e10cSrcweir void stopControllerListening( const uno::Reference< frame::XController >& rxController ); 134cdf0e10cSrcweir 135cdf0e10cSrcweir // XTopWindowListener 136cdf0e10cSrcweir virtual void SAL_CALL windowOpened( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 137cdf0e10cSrcweir virtual void SAL_CALL windowClosing( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 138cdf0e10cSrcweir virtual void SAL_CALL windowClosed( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 139cdf0e10cSrcweir virtual void SAL_CALL windowMinimized( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 140cdf0e10cSrcweir virtual void SAL_CALL windowNormalized( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 141cdf0e10cSrcweir virtual void SAL_CALL windowActivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 142cdf0e10cSrcweir virtual void SAL_CALL windowDeactivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 143cdf0e10cSrcweir 144cdf0e10cSrcweir // XWindowListener 145cdf0e10cSrcweir virtual void SAL_CALL windowResized( const awt::WindowEvent& rEvent ) throw (uno::RuntimeException); 146cdf0e10cSrcweir virtual void SAL_CALL windowMoved( const awt::WindowEvent& rEvent ) throw (uno::RuntimeException); 147cdf0e10cSrcweir virtual void SAL_CALL windowShown( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 148cdf0e10cSrcweir virtual void SAL_CALL windowHidden( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 149cdf0e10cSrcweir 150cdf0e10cSrcweir // XBorderResizeListener 151cdf0e10cSrcweir virtual void SAL_CALL borderWidthsChanged( const uno::Reference< uno::XInterface >& rSource, const frame::BorderWidths& aNewSize ) throw (uno::RuntimeException); 152cdf0e10cSrcweir 153cdf0e10cSrcweir // XChangesListener 154cdf0e10cSrcweir virtual void SAL_CALL changesOccurred( const util::ChangesEvent& rEvent ) throw (uno::RuntimeException); 155cdf0e10cSrcweir 156cdf0e10cSrcweir // XEventListener 157cdf0e10cSrcweir virtual void SAL_CALL disposing( const lang::EventObject& rEvent ) throw (uno::RuntimeException); 158cdf0e10cSrcweir 159cdf0e10cSrcweir private: 160cdf0e10cSrcweir /** Starts listening to the document model. */ 161cdf0e10cSrcweir void startModelListening(); 162cdf0e10cSrcweir /** Stops listening to the document model. */ 163cdf0e10cSrcweir void stopModelListening(); 164cdf0e10cSrcweir 165cdf0e10cSrcweir /** Returns the controller for the passed VCL window. */ 166cdf0e10cSrcweir uno::Reference< frame::XController > getControllerForWindow( Window* pWindow ) const; 167cdf0e10cSrcweir 168cdf0e10cSrcweir /** Calls the Workbook_Window[Activate|Deactivate] event handler. */ 169cdf0e10cSrcweir void processWindowActivateEvent( Window* pWindow, bool bActivate ); 170cdf0e10cSrcweir /** Posts a Workbook_WindowResize user event. */ 171cdf0e10cSrcweir void postWindowResizeEvent( Window* pWindow ); 172cdf0e10cSrcweir /** Callback link for Application::PostUserEvent(). */ 173cdf0e10cSrcweir DECL_LINK( processWindowResizeEvent, Window* ); 174cdf0e10cSrcweir 175cdf0e10cSrcweir private: 176cdf0e10cSrcweir typedef ::std::map< Window*, uno::Reference< frame::XController > > WindowControllerMap; 177cdf0e10cSrcweir 178cdf0e10cSrcweir ::osl::Mutex maMutex; 179cdf0e10cSrcweir ScVbaEventsHelper& mrVbaEvents; 180cdf0e10cSrcweir uno::Reference< frame::XModel > mxModel; 181cdf0e10cSrcweir ScDocShell* mpDocShell; 182cdf0e10cSrcweir WindowControllerMap maControllers; /// Maps VCL top windows to their controllers. 183cdf0e10cSrcweir Window* mpActiveWindow; /// Currently activated window, to prevent multiple (de)activation. 184cdf0e10cSrcweir bool mbWindowResized; /// True = window resize system event processed. 185cdf0e10cSrcweir bool mbBorderChanged; /// True = borders changed system event processed. 186cdf0e10cSrcweir bool mbDisposed; 187cdf0e10cSrcweir }; 188cdf0e10cSrcweir 189cdf0e10cSrcweir // ---------------------------------------------------------------------------- 190cdf0e10cSrcweir 191cdf0e10cSrcweir ScVbaEventListener::ScVbaEventListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell ) : 192cdf0e10cSrcweir mrVbaEvents( rVbaEvents ), 193cdf0e10cSrcweir mxModel( rxModel ), 194cdf0e10cSrcweir mpDocShell( pDocShell ), 195cdf0e10cSrcweir mpActiveWindow( 0 ), 196cdf0e10cSrcweir mbWindowResized( false ), 197cdf0e10cSrcweir mbBorderChanged( false ), 198cdf0e10cSrcweir mbDisposed( !rxModel.is() ) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir if( !mxModel.is() ) 201cdf0e10cSrcweir return; 202cdf0e10cSrcweir 203cdf0e10cSrcweir startModelListening(); 204cdf0e10cSrcweir try 205cdf0e10cSrcweir { 206cdf0e10cSrcweir uno::Reference< frame::XController > xController( mxModel->getCurrentController(), uno::UNO_QUERY_THROW ); 207cdf0e10cSrcweir startControllerListening( xController ); 208cdf0e10cSrcweir } 209cdf0e10cSrcweir catch( uno::Exception& ) 210cdf0e10cSrcweir { 211cdf0e10cSrcweir } 212cdf0e10cSrcweir } 213cdf0e10cSrcweir 214cdf0e10cSrcweir ScVbaEventListener::~ScVbaEventListener() 215cdf0e10cSrcweir { 216cdf0e10cSrcweir } 217cdf0e10cSrcweir 218cdf0e10cSrcweir void ScVbaEventListener::startControllerListening( const uno::Reference< frame::XController >& rxController ) 219cdf0e10cSrcweir { 220cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 221cdf0e10cSrcweir 222cdf0e10cSrcweir uno::Reference< awt::XWindow > xWindow = lclGetWindowForController( rxController ); 223cdf0e10cSrcweir if( xWindow.is() ) 224cdf0e10cSrcweir try { xWindow->addWindowListener( this ); } catch( uno::Exception& ) {} 225cdf0e10cSrcweir 226cdf0e10cSrcweir uno::Reference< awt::XTopWindow > xTopWindow( xWindow, uno::UNO_QUERY ); 227cdf0e10cSrcweir if( xTopWindow.is() ) 228cdf0e10cSrcweir try { xTopWindow->addTopWindowListener( this ); } catch( uno::Exception& ) {} 229cdf0e10cSrcweir 230cdf0e10cSrcweir uno::Reference< frame::XControllerBorder > xControllerBorder( rxController, uno::UNO_QUERY ); 231cdf0e10cSrcweir if( xControllerBorder.is() ) 232cdf0e10cSrcweir try { xControllerBorder->addBorderResizeListener( this ); } catch( uno::Exception& ) {} 233cdf0e10cSrcweir 234cdf0e10cSrcweir if( Window* pWindow = VCLUnoHelper::GetWindow( xWindow ) ) 235cdf0e10cSrcweir maControllers[ pWindow ] = rxController; 236cdf0e10cSrcweir } 237cdf0e10cSrcweir 238cdf0e10cSrcweir void ScVbaEventListener::stopControllerListening( const uno::Reference< frame::XController >& rxController ) 239cdf0e10cSrcweir { 240cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 241cdf0e10cSrcweir 242cdf0e10cSrcweir uno::Reference< awt::XWindow > xWindow = lclGetWindowForController( rxController ); 243cdf0e10cSrcweir if( xWindow.is() ) 244cdf0e10cSrcweir try { xWindow->removeWindowListener( this ); } catch( uno::Exception& ) {} 245cdf0e10cSrcweir 246cdf0e10cSrcweir uno::Reference< awt::XTopWindow > xTopWindow( xWindow, uno::UNO_QUERY ); 247cdf0e10cSrcweir if( xTopWindow.is() ) 248cdf0e10cSrcweir try { xTopWindow->removeTopWindowListener( this ); } catch( uno::Exception& ) {} 249cdf0e10cSrcweir 250cdf0e10cSrcweir uno::Reference< frame::XControllerBorder > xControllerBorder( rxController, uno::UNO_QUERY ); 251cdf0e10cSrcweir if( xControllerBorder.is() ) 252cdf0e10cSrcweir try { xControllerBorder->removeBorderResizeListener( this ); } catch( uno::Exception& ) {} 253cdf0e10cSrcweir 254cdf0e10cSrcweir if( Window* pWindow = VCLUnoHelper::GetWindow( xWindow ) ) 255cdf0e10cSrcweir { 256cdf0e10cSrcweir maControllers.erase( pWindow ); 257cdf0e10cSrcweir if( pWindow == mpActiveWindow ) 258cdf0e10cSrcweir mpActiveWindow = 0; 259cdf0e10cSrcweir } 260cdf0e10cSrcweir } 261cdf0e10cSrcweir 262cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowOpened( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) 263cdf0e10cSrcweir { 264cdf0e10cSrcweir } 265cdf0e10cSrcweir 266cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowClosing( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) 267cdf0e10cSrcweir { 268cdf0e10cSrcweir } 269cdf0e10cSrcweir 270cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowClosed( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) 271cdf0e10cSrcweir { 272cdf0e10cSrcweir } 273cdf0e10cSrcweir 274cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowMinimized( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) 275cdf0e10cSrcweir { 276cdf0e10cSrcweir } 277cdf0e10cSrcweir 278cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowNormalized( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) 279cdf0e10cSrcweir { 280cdf0e10cSrcweir } 281cdf0e10cSrcweir 282cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowActivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException) 283cdf0e10cSrcweir { 284cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 285cdf0e10cSrcweir 286cdf0e10cSrcweir if( !mbDisposed ) 287cdf0e10cSrcweir { 288cdf0e10cSrcweir uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY ); 289cdf0e10cSrcweir Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); 290cdf0e10cSrcweir OSL_TRACE( "ScVbaEventListener::windowActivated - pWindow = 0x%x, mpActiveWindow = 0x%x", pWindow, mpActiveWindow ); 291cdf0e10cSrcweir // do not fire activation event multiple time for the same window 292cdf0e10cSrcweir if( pWindow && (pWindow != mpActiveWindow) ) 293cdf0e10cSrcweir { 294cdf0e10cSrcweir // if another window is active, fire deactivation event first 295cdf0e10cSrcweir if( mpActiveWindow ) 296cdf0e10cSrcweir processWindowActivateEvent( mpActiveWindow, false ); 297cdf0e10cSrcweir // fire activation event for the new window 298cdf0e10cSrcweir processWindowActivateEvent( pWindow, true ); 299cdf0e10cSrcweir mpActiveWindow = pWindow; 300cdf0e10cSrcweir } 301cdf0e10cSrcweir } 302cdf0e10cSrcweir } 303cdf0e10cSrcweir 304cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowDeactivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException) 305cdf0e10cSrcweir { 306cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 307cdf0e10cSrcweir 308cdf0e10cSrcweir if( !mbDisposed ) 309cdf0e10cSrcweir { 310cdf0e10cSrcweir uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY ); 311cdf0e10cSrcweir Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); 312cdf0e10cSrcweir OSL_TRACE( "ScVbaEventListener::windowDeactivated - pWindow = 0x%x, mpActiveWindow = 0x%x", pWindow, mpActiveWindow ); 313cdf0e10cSrcweir // do not fire the deactivation event, if the window is not active (prevent multiple deactivation) 314cdf0e10cSrcweir if( pWindow && (pWindow == mpActiveWindow) ) 315cdf0e10cSrcweir processWindowActivateEvent( pWindow, false ); 316cdf0e10cSrcweir // forget pointer to the active window 317cdf0e10cSrcweir mpActiveWindow = 0; 318cdf0e10cSrcweir } 319cdf0e10cSrcweir } 320cdf0e10cSrcweir 321cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowResized( const awt::WindowEvent& rEvent ) throw (uno::RuntimeException) 322cdf0e10cSrcweir { 323cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 324cdf0e10cSrcweir 325cdf0e10cSrcweir mbWindowResized = true; 326cdf0e10cSrcweir if( !mbDisposed && mbBorderChanged ) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY ); 329cdf0e10cSrcweir postWindowResizeEvent( VCLUnoHelper::GetWindow( xWindow ) ); 330cdf0e10cSrcweir } 331cdf0e10cSrcweir } 332cdf0e10cSrcweir 333cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowMoved( const awt::WindowEvent& /*rEvent*/ ) throw (uno::RuntimeException) 334cdf0e10cSrcweir { 335cdf0e10cSrcweir } 336cdf0e10cSrcweir 337cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowShown( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) 338cdf0e10cSrcweir { 339cdf0e10cSrcweir } 340cdf0e10cSrcweir 341cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::windowHidden( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) 342cdf0e10cSrcweir { 343cdf0e10cSrcweir } 344cdf0e10cSrcweir 345cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::borderWidthsChanged( const uno::Reference< uno::XInterface >& rSource, const frame::BorderWidths& /*aNewSize*/ ) throw (uno::RuntimeException) 346cdf0e10cSrcweir { 347cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 348cdf0e10cSrcweir 349cdf0e10cSrcweir mbBorderChanged = true; 350cdf0e10cSrcweir if( !mbDisposed && mbWindowResized ) 351cdf0e10cSrcweir { 352cdf0e10cSrcweir uno::Reference< frame::XController > xController( rSource, uno::UNO_QUERY ); 353cdf0e10cSrcweir uno::Reference< awt::XWindow > xWindow = lclGetWindowForController( xController ); 354cdf0e10cSrcweir postWindowResizeEvent( VCLUnoHelper::GetWindow( xWindow ) ); 355cdf0e10cSrcweir } 356cdf0e10cSrcweir } 357cdf0e10cSrcweir 358cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::changesOccurred( const util::ChangesEvent& rEvent ) throw (uno::RuntimeException) 359cdf0e10cSrcweir { 360cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 361cdf0e10cSrcweir 362cdf0e10cSrcweir sal_Int32 nCount = rEvent.Changes.getLength(); 363cdf0e10cSrcweir if( mbDisposed || !mpDocShell || (nCount == 0) ) 364cdf0e10cSrcweir return; 365cdf0e10cSrcweir 366cdf0e10cSrcweir util::ElementChange aChange = rEvent.Changes[ 0 ]; 367cdf0e10cSrcweir OUString sOperation; 368cdf0e10cSrcweir aChange.Accessor >>= sOperation; 369cdf0e10cSrcweir if( !sOperation.equalsIgnoreAsciiCaseAscii("cell-change") ) 370cdf0e10cSrcweir return; 371cdf0e10cSrcweir 372cdf0e10cSrcweir if( nCount == 1 ) 373cdf0e10cSrcweir { 374cdf0e10cSrcweir uno::Reference< table::XCellRange > xRangeObj; 375cdf0e10cSrcweir aChange.ReplacedElement >>= xRangeObj; 376cdf0e10cSrcweir if( xRangeObj.is() ) 377cdf0e10cSrcweir { 378cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 1 ); 379cdf0e10cSrcweir aArgs[0] <<= xRangeObj; 380cdf0e10cSrcweir mrVbaEvents.processVbaEventNoThrow( WORKSHEET_CHANGE, aArgs ); 381cdf0e10cSrcweir } 382cdf0e10cSrcweir return; 383cdf0e10cSrcweir } 384cdf0e10cSrcweir 385cdf0e10cSrcweir ScRangeList aRangeList; 386cdf0e10cSrcweir for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) 387cdf0e10cSrcweir { 388cdf0e10cSrcweir aChange = rEvent.Changes[ nIndex ]; 389cdf0e10cSrcweir aChange.Accessor >>= sOperation; 390cdf0e10cSrcweir uno::Reference< table::XCellRange > xRangeObj; 391cdf0e10cSrcweir aChange.ReplacedElement >>= xRangeObj; 392cdf0e10cSrcweir if( xRangeObj.is() && sOperation.equalsIgnoreAsciiCaseAscii("cell-change") ) 393cdf0e10cSrcweir { 394cdf0e10cSrcweir uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable( xRangeObj, uno::UNO_QUERY ); 395cdf0e10cSrcweir if( xCellRangeAddressable.is() ) 396cdf0e10cSrcweir { 397cdf0e10cSrcweir ScRange aRange; 398cdf0e10cSrcweir ScUnoConversion::FillScRange( aRange, xCellRangeAddressable->getRangeAddress() ); 399cdf0e10cSrcweir aRangeList.Append( aRange ); 400cdf0e10cSrcweir } 401cdf0e10cSrcweir } 402cdf0e10cSrcweir } 403cdf0e10cSrcweir 404cdf0e10cSrcweir if( aRangeList.Count() > 0 ) 405cdf0e10cSrcweir { 406cdf0e10cSrcweir uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( mpDocShell, aRangeList ) ); 407cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs(1); 408cdf0e10cSrcweir aArgs[0] <<= xRanges; 409cdf0e10cSrcweir mrVbaEvents.processVbaEventNoThrow( WORKSHEET_CHANGE, aArgs ); 410cdf0e10cSrcweir } 411cdf0e10cSrcweir } 412cdf0e10cSrcweir 413cdf0e10cSrcweir void SAL_CALL ScVbaEventListener::disposing( const lang::EventObject& rEvent ) throw (uno::RuntimeException) 414cdf0e10cSrcweir { 415cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 416cdf0e10cSrcweir 417cdf0e10cSrcweir uno::Reference< frame::XModel > xModel( rEvent.Source, uno::UNO_QUERY ); 418cdf0e10cSrcweir if( xModel.is() ) 419cdf0e10cSrcweir { 420cdf0e10cSrcweir OSL_ENSURE( xModel.get() == mxModel.get(), "ScVbaEventListener::disposing - disposing from unknown model" ); 421cdf0e10cSrcweir stopModelListening(); 422cdf0e10cSrcweir mbDisposed = true; 423cdf0e10cSrcweir return; 424cdf0e10cSrcweir } 425cdf0e10cSrcweir 426cdf0e10cSrcweir uno::Reference< frame::XController > xController( rEvent.Source, uno::UNO_QUERY ); 427cdf0e10cSrcweir if( xController.is() ) 428cdf0e10cSrcweir { 429cdf0e10cSrcweir stopControllerListening( xController ); 430cdf0e10cSrcweir return; 431cdf0e10cSrcweir } 432cdf0e10cSrcweir } 433cdf0e10cSrcweir 434cdf0e10cSrcweir // private -------------------------------------------------------------------- 435cdf0e10cSrcweir 436cdf0e10cSrcweir void ScVbaEventListener::startModelListening() 437cdf0e10cSrcweir { 438cdf0e10cSrcweir try 439cdf0e10cSrcweir { 440cdf0e10cSrcweir uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW ); 441cdf0e10cSrcweir xChangesNotifier->addChangesListener( this ); 442cdf0e10cSrcweir } 443cdf0e10cSrcweir catch( uno::Exception& ) 444cdf0e10cSrcweir { 445cdf0e10cSrcweir } 446cdf0e10cSrcweir } 447cdf0e10cSrcweir 448cdf0e10cSrcweir void ScVbaEventListener::stopModelListening() 449cdf0e10cSrcweir { 450cdf0e10cSrcweir try 451cdf0e10cSrcweir { 452cdf0e10cSrcweir uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW ); 453cdf0e10cSrcweir xChangesNotifier->removeChangesListener( this ); 454cdf0e10cSrcweir } 455cdf0e10cSrcweir catch( uno::Exception& ) 456cdf0e10cSrcweir { 457cdf0e10cSrcweir } 458cdf0e10cSrcweir } 459cdf0e10cSrcweir 460cdf0e10cSrcweir uno::Reference< frame::XController > ScVbaEventListener::getControllerForWindow( Window* pWindow ) const 461cdf0e10cSrcweir { 462cdf0e10cSrcweir WindowControllerMap::const_iterator aIt = maControllers.find( pWindow ); 463cdf0e10cSrcweir return (aIt == maControllers.end()) ? uno::Reference< frame::XController >() : aIt->second; 464cdf0e10cSrcweir } 465cdf0e10cSrcweir 466cdf0e10cSrcweir void ScVbaEventListener::processWindowActivateEvent( Window* pWindow, bool bActivate ) 467cdf0e10cSrcweir { 468cdf0e10cSrcweir uno::Reference< frame::XController > xController = getControllerForWindow( pWindow ); 469cdf0e10cSrcweir if( xController.is() ) 470cdf0e10cSrcweir { 471cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 1 ); 472cdf0e10cSrcweir aArgs[ 0 ] <<= xController; 473cdf0e10cSrcweir mrVbaEvents.processVbaEventNoThrow( bActivate ? WORKBOOK_WINDOWACTIVATE : WORKBOOK_WINDOWDEACTIVATE, aArgs ); 474cdf0e10cSrcweir } 475cdf0e10cSrcweir } 476cdf0e10cSrcweir 477cdf0e10cSrcweir void ScVbaEventListener::postWindowResizeEvent( Window* pWindow ) 478cdf0e10cSrcweir { 479cdf0e10cSrcweir // check that the passed window is still alive (it must be registered in maControllers) 480cdf0e10cSrcweir if( pWindow && (maControllers.count( pWindow ) > 0) ) 481cdf0e10cSrcweir { 482cdf0e10cSrcweir mbWindowResized = mbBorderChanged = false; 483cdf0e10cSrcweir acquire(); // ensure we don't get deleted before the timer fires 484cdf0e10cSrcweir Application::PostUserEvent( LINK( this, ScVbaEventListener, processWindowResizeEvent ), pWindow ); 485cdf0e10cSrcweir } 486cdf0e10cSrcweir } 487cdf0e10cSrcweir 488cdf0e10cSrcweir IMPL_LINK( ScVbaEventListener, processWindowResizeEvent, Window*, EMPTYARG pWindow ) 489cdf0e10cSrcweir { 490cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 491cdf0e10cSrcweir 492cdf0e10cSrcweir /* Check that the passed window is still alive (it must be registered in 493cdf0e10cSrcweir maControllers). While closing a document, postWindowResizeEvent() may 494cdf0e10cSrcweir be called on the last window which posts a user event via 495cdf0e10cSrcweir Application::PostUserEvent to call this event handler. VCL will trigger 496cdf0e10cSrcweir the handler some time later. Sometimes, the window gets deleted before. 497cdf0e10cSrcweir This is handled via the disposing() function which removes the window 498cdf0e10cSrcweir pointer from the member maControllers. Thus, checking whether 499cdf0e10cSrcweir maControllers contains pWindow ensures that the window is still alive. */ 500cdf0e10cSrcweir if( !mbDisposed && pWindow && (maControllers.count( pWindow ) > 0) ) 501cdf0e10cSrcweir { 502cdf0e10cSrcweir // do not fire event unless all mouse buttons have been released 503cdf0e10cSrcweir Window::PointerState aPointerState = pWindow->GetPointerState(); 504cdf0e10cSrcweir if( (aPointerState.mnState & (MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT)) == 0 ) 505cdf0e10cSrcweir { 506cdf0e10cSrcweir uno::Reference< frame::XController > xController = getControllerForWindow( pWindow ); 507cdf0e10cSrcweir if( xController.is() ) 508cdf0e10cSrcweir { 509cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 1 ); 510cdf0e10cSrcweir aArgs[ 0 ] <<= xController; 511cdf0e10cSrcweir // #163419# do not throw exceptions into application core 512cdf0e10cSrcweir mrVbaEvents.processVbaEventNoThrow( WORKBOOK_WINDOWRESIZE, aArgs ); 513cdf0e10cSrcweir } 514cdf0e10cSrcweir } 515cdf0e10cSrcweir } 516cdf0e10cSrcweir release(); 517cdf0e10cSrcweir return 0; 518cdf0e10cSrcweir } 519cdf0e10cSrcweir 520cdf0e10cSrcweir // ============================================================================ 521cdf0e10cSrcweir 522cdf0e10cSrcweir ScVbaEventsHelper::ScVbaEventsHelper( const uno::Sequence< uno::Any >& rArgs, const uno::Reference< uno::XComponentContext >& xContext ) : 523cdf0e10cSrcweir VbaEventsHelperBase( rArgs, xContext ), 524cdf0e10cSrcweir mbOpened( false ) 525cdf0e10cSrcweir { 526cdf0e10cSrcweir mpDocShell = dynamic_cast< ScDocShell* >( mpShell ); // mpShell from base class 527cdf0e10cSrcweir mpDoc = mpDocShell ? mpDocShell->GetDocument() : 0; 528cdf0e10cSrcweir 529cdf0e10cSrcweir if( !mxModel.is() || !mpDocShell || !mpDoc ) 530cdf0e10cSrcweir return; 531cdf0e10cSrcweir 532cdf0e10cSrcweir #define REGISTER_EVENT( eventid, moduletype, classname, eventname, cancelindex, worksheet ) \ 533cdf0e10cSrcweir registerEventHandler( eventid, moduletype, classname "_" eventname, cancelindex, uno::Any( worksheet ) ) 534cdf0e10cSrcweir #define REGISTER_AUTO_EVENT( eventid, eventname ) \ 535cdf0e10cSrcweir REGISTER_EVENT( AUTO_##eventid, script::ModuleType::NORMAL, "Auto", eventname, -1, false ) 536cdf0e10cSrcweir #define REGISTER_WORKBOOK_EVENT( eventid, eventname, cancelindex ) \ 537cdf0e10cSrcweir REGISTER_EVENT( WORKBOOK_##eventid, script::ModuleType::DOCUMENT, "Workbook", eventname, cancelindex, false ) 538cdf0e10cSrcweir #define REGISTER_WORKSHEET_EVENT( eventid, eventname, cancelindex ) \ 539cdf0e10cSrcweir REGISTER_EVENT( WORKSHEET_##eventid, script::ModuleType::DOCUMENT, "Worksheet", eventname, cancelindex, true ); \ 540cdf0e10cSrcweir REGISTER_EVENT( (USERDEFINED_START + WORKSHEET_##eventid), script::ModuleType::DOCUMENT, "Workbook", "Sheet" eventname, (((cancelindex) >= 0) ? ((cancelindex) + 1) : -1), false ) 541cdf0e10cSrcweir 542cdf0e10cSrcweir // global 543cdf0e10cSrcweir REGISTER_AUTO_EVENT( OPEN, "Open" ); 544cdf0e10cSrcweir REGISTER_AUTO_EVENT( CLOSE, "Close" ); 545cdf0e10cSrcweir 546cdf0e10cSrcweir // Workbook 547cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( ACTIVATE, "Activate", -1 ); 548cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( DEACTIVATE, "Deactivate", -1 ); 549cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( OPEN, "Open", -1 ); 550cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( BEFORECLOSE, "BeforeClose", 0 ); 551cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( BEFOREPRINT, "BeforePrint", 0 ); 552cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( BEFORESAVE, "BeforeSave", 1 ); 553cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( AFTERSAVE, "AfterSave", -1 ); 554cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( NEWSHEET, "NewSheet", -1 ); 555cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( WINDOWACTIVATE, "WindowActivate", -1 ); 556cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( WINDOWDEACTIVATE, "WindowDeactivate", -1 ); 557cdf0e10cSrcweir REGISTER_WORKBOOK_EVENT( WINDOWRESIZE, "WindowResize", -1 ); 558cdf0e10cSrcweir 559cdf0e10cSrcweir // Worksheet events. All events have a corresponding workbook event. 560cdf0e10cSrcweir REGISTER_WORKSHEET_EVENT( ACTIVATE, "Activate", -1 ); 561cdf0e10cSrcweir REGISTER_WORKSHEET_EVENT( DEACTIVATE, "Deactivate", -1 ); 562cdf0e10cSrcweir REGISTER_WORKSHEET_EVENT( BEFOREDOUBLECLICK, "BeforeDoubleClick", 1 ); 563cdf0e10cSrcweir REGISTER_WORKSHEET_EVENT( BEFORERIGHTCLICK, "BeforeRightClick", 1 ); 564cdf0e10cSrcweir REGISTER_WORKSHEET_EVENT( CALCULATE, "Calculate", -1 ); 565cdf0e10cSrcweir REGISTER_WORKSHEET_EVENT( CHANGE, "Change", -1 ); 566cdf0e10cSrcweir REGISTER_WORKSHEET_EVENT( SELECTIONCHANGE, "SelectionChange", -1 ); 567cdf0e10cSrcweir REGISTER_WORKSHEET_EVENT( FOLLOWHYPERLINK, "FollowHyperlink", -1 ); 568cdf0e10cSrcweir 569cdf0e10cSrcweir #undef REGISTER_WORKSHEET_EVENT 570cdf0e10cSrcweir #undef REGISTER_WORKBOOK_EVENT 571cdf0e10cSrcweir #undef REGISTER_AUTO_EVENT 572cdf0e10cSrcweir #undef REGISTER_EVENT 573cdf0e10cSrcweir } 574cdf0e10cSrcweir 575cdf0e10cSrcweir ScVbaEventsHelper::~ScVbaEventsHelper() 576cdf0e10cSrcweir { 577cdf0e10cSrcweir } 578cdf0e10cSrcweir 579cdf0e10cSrcweir void SAL_CALL ScVbaEventsHelper::notifyEvent( const css::document::EventObject& rEvent ) throw (css::uno::RuntimeException) 580cdf0e10cSrcweir { 581cdf0e10cSrcweir static const uno::Sequence< uno::Any > saEmptyArgs; 582cdf0e10cSrcweir if( (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_OPENDOC )) || 583cdf0e10cSrcweir (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_CREATEDOC )) ) // CREATEDOC triggered e.g. during VBA Workbooks.Add 584cdf0e10cSrcweir { 585cdf0e10cSrcweir processVbaEventNoThrow( WORKBOOK_OPEN, saEmptyArgs ); 586cdf0e10cSrcweir } 587cdf0e10cSrcweir else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_ACTIVATEDOC ) ) 588cdf0e10cSrcweir { 589cdf0e10cSrcweir processVbaEventNoThrow( WORKBOOK_ACTIVATE, saEmptyArgs ); 590cdf0e10cSrcweir } 591cdf0e10cSrcweir else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_DEACTIVATEDOC ) ) 592cdf0e10cSrcweir { 593cdf0e10cSrcweir processVbaEventNoThrow( WORKBOOK_DEACTIVATE, saEmptyArgs ); 594cdf0e10cSrcweir } 595cdf0e10cSrcweir else if( (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEDOCDONE )) || 596cdf0e10cSrcweir (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEASDOCDONE )) || 597cdf0e10cSrcweir (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVETODOCDONE )) ) 598cdf0e10cSrcweir { 599cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 1 ); 600cdf0e10cSrcweir aArgs[ 0 ] <<= true; 601cdf0e10cSrcweir processVbaEventNoThrow( WORKBOOK_AFTERSAVE, aArgs ); 602cdf0e10cSrcweir } 603cdf0e10cSrcweir else if( (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEDOCFAILED )) || 604cdf0e10cSrcweir (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEASDOCFAILED )) || 605cdf0e10cSrcweir (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVETODOCFAILED )) ) 606cdf0e10cSrcweir { 607cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 1 ); 608cdf0e10cSrcweir aArgs[ 0 ] <<= false; 609cdf0e10cSrcweir processVbaEventNoThrow( WORKBOOK_AFTERSAVE, aArgs ); 610cdf0e10cSrcweir } 611cdf0e10cSrcweir else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_CLOSEDOC ) ) 612cdf0e10cSrcweir { 613cdf0e10cSrcweir /* Trigger the WORKBOOK_WINDOWDEACTIVATE and WORKBOOK_DEACTIVATE 614cdf0e10cSrcweir events and stop listening to the model (done in base class). */ 615cdf0e10cSrcweir uno::Reference< frame::XController > xController( mxModel->getCurrentController() ); 616cdf0e10cSrcweir if( xController.is() ) 617cdf0e10cSrcweir { 618cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 1 ); 619cdf0e10cSrcweir aArgs[ 0 ] <<= xController; 620cdf0e10cSrcweir processVbaEventNoThrow( WORKBOOK_WINDOWDEACTIVATE, aArgs ); 621cdf0e10cSrcweir } 622cdf0e10cSrcweir processVbaEventNoThrow( WORKBOOK_DEACTIVATE, saEmptyArgs ); 623cdf0e10cSrcweir } 624cdf0e10cSrcweir else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_VIEWCREATED ) ) 625cdf0e10cSrcweir { 626cdf0e10cSrcweir uno::Reference< frame::XController > xController( mxModel->getCurrentController() ); 627cdf0e10cSrcweir if( mxListener.get() && xController.is() ) 628cdf0e10cSrcweir mxListener->startControllerListening( xController ); 629cdf0e10cSrcweir } 630cdf0e10cSrcweir VbaEventsHelperBase::notifyEvent( rEvent ); 631cdf0e10cSrcweir } 632cdf0e10cSrcweir 633cdf0e10cSrcweir // protected ------------------------------------------------------------------ 634cdf0e10cSrcweir 635cdf0e10cSrcweir bool ScVbaEventsHelper::implPrepareEvent( EventQueue& rEventQueue, 636cdf0e10cSrcweir const EventHandlerInfo& rInfo, const uno::Sequence< uno::Any >& rArgs ) throw (uno::RuntimeException) 637cdf0e10cSrcweir { 638cdf0e10cSrcweir // document and document shell are needed during event processing 639cdf0e10cSrcweir if( !mpShell || !mpDoc ) 640cdf0e10cSrcweir throw uno::RuntimeException(); 641cdf0e10cSrcweir 642cdf0e10cSrcweir /* For document events: check if events are enabled via the 643cdf0e10cSrcweir Application.EnableEvents symbol (this is an Excel-only attribute). 644cdf0e10cSrcweir Check this again for every event, as the event handler may change the 645cdf0e10cSrcweir state of the EnableEvents symbol. Global events such as AUTO_OPEN and 646cdf0e10cSrcweir AUTO_CLOSE are always enabled. */ 647cdf0e10cSrcweir bool bExecuteEvent = (rInfo.mnModuleType != script::ModuleType::DOCUMENT) || ScVbaApplication::getDocumentEventsEnabled(); 648cdf0e10cSrcweir 649cdf0e10cSrcweir // framework and Calc fire a few events before 'OnLoad', ignore them 650cdf0e10cSrcweir if( bExecuteEvent ) 651cdf0e10cSrcweir bExecuteEvent = (rInfo.mnEventId == WORKBOOK_OPEN) ? !mbOpened : mbOpened; 652cdf0e10cSrcweir 653cdf0e10cSrcweir // special handling for some events 654cdf0e10cSrcweir if( bExecuteEvent ) switch( rInfo.mnEventId ) 655cdf0e10cSrcweir { 656cdf0e10cSrcweir case WORKBOOK_OPEN: 657cdf0e10cSrcweir { 658cdf0e10cSrcweir // execute delayed Activate event too (see above) 659cdf0e10cSrcweir rEventQueue.push_back( WORKBOOK_ACTIVATE ); 660cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 1 ); 661cdf0e10cSrcweir aArgs[ 0 ] <<= mxModel->getCurrentController(); 662cdf0e10cSrcweir rEventQueue.push_back( EventQueueEntry( WORKBOOK_WINDOWACTIVATE, aArgs ) ); 663cdf0e10cSrcweir rEventQueue.push_back( AUTO_OPEN ); 664cdf0e10cSrcweir // remember initial selection 665cdf0e10cSrcweir maOldSelection <<= mxModel->getCurrentSelection(); 666cdf0e10cSrcweir } 667cdf0e10cSrcweir break; 668cdf0e10cSrcweir case WORKSHEET_SELECTIONCHANGE: 669cdf0e10cSrcweir // if selection is not changed, then do not fire the event 670cdf0e10cSrcweir bExecuteEvent = isSelectionChanged( rArgs, 0 ); 671cdf0e10cSrcweir break; 672cdf0e10cSrcweir } 673cdf0e10cSrcweir 674cdf0e10cSrcweir if( bExecuteEvent ) 675cdf0e10cSrcweir { 676cdf0e10cSrcweir // add workbook event associated to a sheet event 677cdf0e10cSrcweir bool bSheetEvent = false; 678cdf0e10cSrcweir if( (rInfo.maUserData >>= bSheetEvent) && bSheetEvent ) 679cdf0e10cSrcweir rEventQueue.push_back( EventQueueEntry( rInfo.mnEventId + USERDEFINED_START, rArgs ) ); 680cdf0e10cSrcweir } 681cdf0e10cSrcweir 682cdf0e10cSrcweir return bExecuteEvent; 683cdf0e10cSrcweir } 684cdf0e10cSrcweir 685cdf0e10cSrcweir uno::Sequence< uno::Any > ScVbaEventsHelper::implBuildArgumentList( const EventHandlerInfo& rInfo, 686cdf0e10cSrcweir const uno::Sequence< uno::Any >& rArgs ) throw (lang::IllegalArgumentException) 687cdf0e10cSrcweir { 688cdf0e10cSrcweir // fill arguments for workbook events associated to sheet events according to sheet events, sheet will be added below 689cdf0e10cSrcweir bool bSheetEventAsBookEvent = rInfo.mnEventId > USERDEFINED_START; 690cdf0e10cSrcweir sal_Int32 nEventId = bSheetEventAsBookEvent ? (rInfo.mnEventId - USERDEFINED_START) : rInfo.mnEventId; 691cdf0e10cSrcweir 692cdf0e10cSrcweir uno::Sequence< uno::Any > aVbaArgs; 693cdf0e10cSrcweir switch( nEventId ) 694cdf0e10cSrcweir { 695cdf0e10cSrcweir // *** Workbook *** 696cdf0e10cSrcweir 697cdf0e10cSrcweir // no arguments 698cdf0e10cSrcweir case WORKBOOK_ACTIVATE: 699cdf0e10cSrcweir case WORKBOOK_DEACTIVATE: 700cdf0e10cSrcweir case WORKBOOK_OPEN: 701cdf0e10cSrcweir break; 702cdf0e10cSrcweir // 1 arg: cancel 703cdf0e10cSrcweir case WORKBOOK_BEFORECLOSE: 704cdf0e10cSrcweir case WORKBOOK_BEFOREPRINT: 705cdf0e10cSrcweir aVbaArgs.realloc( 1 ); 706cdf0e10cSrcweir // current cancel state will be inserted by caller 707cdf0e10cSrcweir break; 708cdf0e10cSrcweir // 2 args: saveAs, cancel 709cdf0e10cSrcweir case WORKBOOK_BEFORESAVE: 710cdf0e10cSrcweir aVbaArgs.realloc( 2 ); 711cdf0e10cSrcweir checkArgumentType< bool >( rArgs, 0 ); 712cdf0e10cSrcweir aVbaArgs[ 0 ] = rArgs[ 0 ]; 713cdf0e10cSrcweir // current cancel state will be inserted by caller 714cdf0e10cSrcweir break; 715cdf0e10cSrcweir // 1 arg: success 716cdf0e10cSrcweir case WORKBOOK_AFTERSAVE: 717cdf0e10cSrcweir aVbaArgs.realloc( 1 ); 718cdf0e10cSrcweir checkArgumentType< bool >( rArgs, 0 ); 719cdf0e10cSrcweir aVbaArgs[ 0 ] = rArgs[ 0 ]; 720cdf0e10cSrcweir break; 721cdf0e10cSrcweir // 1 arg: window 722cdf0e10cSrcweir case WORKBOOK_WINDOWACTIVATE: 723cdf0e10cSrcweir case WORKBOOK_WINDOWDEACTIVATE: 724cdf0e10cSrcweir case WORKBOOK_WINDOWRESIZE: 725cdf0e10cSrcweir aVbaArgs.realloc( 1 ); 726cdf0e10cSrcweir aVbaArgs[ 0 ] = createWindow( rArgs, 0 ); 727cdf0e10cSrcweir break; 728cdf0e10cSrcweir // 1 arg: worksheet 729cdf0e10cSrcweir case WORKBOOK_NEWSHEET: 730cdf0e10cSrcweir aVbaArgs.realloc( 1 ); 731cdf0e10cSrcweir aVbaArgs[ 0 ] = createWorksheet( rArgs, 0 ); 732cdf0e10cSrcweir break; 733cdf0e10cSrcweir 734cdf0e10cSrcweir // *** Worksheet *** 735cdf0e10cSrcweir 736cdf0e10cSrcweir // no arguments 737cdf0e10cSrcweir case WORKSHEET_ACTIVATE: 738cdf0e10cSrcweir case WORKSHEET_CALCULATE: 739cdf0e10cSrcweir case WORKSHEET_DEACTIVATE: 740cdf0e10cSrcweir break; 741cdf0e10cSrcweir // 1 arg: range 742cdf0e10cSrcweir case WORKSHEET_CHANGE: 743cdf0e10cSrcweir case WORKSHEET_SELECTIONCHANGE: 744cdf0e10cSrcweir aVbaArgs.realloc( 1 ); 745cdf0e10cSrcweir aVbaArgs[ 0 ] = createRange( rArgs, 0 ); 746cdf0e10cSrcweir break; 747cdf0e10cSrcweir // 2 args: range, cancel 748cdf0e10cSrcweir case WORKSHEET_BEFOREDOUBLECLICK: 749cdf0e10cSrcweir case WORKSHEET_BEFORERIGHTCLICK: 750cdf0e10cSrcweir aVbaArgs.realloc( 2 ); 751cdf0e10cSrcweir aVbaArgs[ 0 ] = createRange( rArgs, 0 ); 752cdf0e10cSrcweir // current cancel state will be inserted by caller 753cdf0e10cSrcweir break; 754cdf0e10cSrcweir // 1 arg: hyperlink 755cdf0e10cSrcweir case WORKSHEET_FOLLOWHYPERLINK: 756cdf0e10cSrcweir aVbaArgs.realloc( 1 ); 757cdf0e10cSrcweir aVbaArgs[ 0 ] = createHyperlink( rArgs, 0 ); 758cdf0e10cSrcweir break; 759cdf0e10cSrcweir } 760cdf0e10cSrcweir 761cdf0e10cSrcweir /* For workbook events associated to sheet events, the workbook event gets 762cdf0e10cSrcweir the same arguments but with a Worksheet object in front of them. */ 763cdf0e10cSrcweir if( bSheetEventAsBookEvent ) 764cdf0e10cSrcweir { 765cdf0e10cSrcweir sal_Int32 nLength = aVbaArgs.getLength(); 766cdf0e10cSrcweir uno::Sequence< uno::Any > aVbaArgs2( nLength + 1 ); 767cdf0e10cSrcweir aVbaArgs2[ 0 ] = createWorksheet( rArgs, 0 ); 768cdf0e10cSrcweir for( sal_Int32 nIndex = 0; nIndex < nLength; ++nIndex ) 769cdf0e10cSrcweir aVbaArgs2[ nIndex + 1 ] = aVbaArgs[ nIndex ]; 770cdf0e10cSrcweir aVbaArgs = aVbaArgs2; 771cdf0e10cSrcweir } 772cdf0e10cSrcweir 773cdf0e10cSrcweir return aVbaArgs; 774cdf0e10cSrcweir } 775cdf0e10cSrcweir 776cdf0e10cSrcweir void ScVbaEventsHelper::implPostProcessEvent( EventQueue& rEventQueue, 777cdf0e10cSrcweir const EventHandlerInfo& rInfo, bool bCancel ) throw (uno::RuntimeException) 778cdf0e10cSrcweir { 779cdf0e10cSrcweir switch( rInfo.mnEventId ) 780cdf0e10cSrcweir { 781cdf0e10cSrcweir case WORKBOOK_OPEN: 782cdf0e10cSrcweir mbOpened = true; 783cdf0e10cSrcweir // register the listeners 784cdf0e10cSrcweir if( !mxListener.is() ) 785cdf0e10cSrcweir mxListener = new ScVbaEventListener( *this, mxModel, mpDocShell ); 786cdf0e10cSrcweir break; 787cdf0e10cSrcweir case WORKBOOK_BEFORECLOSE: 788cdf0e10cSrcweir /* Execute Auto_Close only if not cancelled by event handler, but 789cdf0e10cSrcweir before UI asks user whether to cancel closing the document. */ 790cdf0e10cSrcweir if( !bCancel ) 791cdf0e10cSrcweir rEventQueue.push_back( AUTO_CLOSE ); 792cdf0e10cSrcweir break; 793cdf0e10cSrcweir } 794cdf0e10cSrcweir } 795cdf0e10cSrcweir 796cdf0e10cSrcweir OUString ScVbaEventsHelper::implGetDocumentModuleName( const EventHandlerInfo& rInfo, 797cdf0e10cSrcweir const uno::Sequence< uno::Any >& rArgs ) const throw (lang::IllegalArgumentException) 798cdf0e10cSrcweir { 799cdf0e10cSrcweir bool bSheetEvent = false; 800cdf0e10cSrcweir rInfo.maUserData >>= bSheetEvent; 801cdf0e10cSrcweir SCTAB nTab = bSheetEvent ? lclGetTabFromArgs( rArgs, 0 ) : -1; 802cdf0e10cSrcweir if( bSheetEvent && (nTab < 0) ) 803cdf0e10cSrcweir throw lang::IllegalArgumentException(); 804cdf0e10cSrcweir 805cdf0e10cSrcweir String aCodeName; 806cdf0e10cSrcweir if( bSheetEvent ) 807cdf0e10cSrcweir mpDoc->GetCodeName( nTab, aCodeName ); 808cdf0e10cSrcweir else 809cdf0e10cSrcweir aCodeName = mpDoc->GetCodeName(); 810cdf0e10cSrcweir return aCodeName; 811cdf0e10cSrcweir } 812cdf0e10cSrcweir 813cdf0e10cSrcweir // private -------------------------------------------------------------------- 814cdf0e10cSrcweir 815cdf0e10cSrcweir namespace { 816cdf0e10cSrcweir 817cdf0e10cSrcweir /** Compares the passed range lists representing sheet selections. Ignores 818cdf0e10cSrcweir selections that refer to different sheets (returns false in this case). */ 819cdf0e10cSrcweir bool lclSelectionChanged( const ScRangeList& rLeft, const ScRangeList& rRight ) 820cdf0e10cSrcweir { 821cdf0e10cSrcweir // one of the range lists empty? -> return false, if both lists empty 822cdf0e10cSrcweir bool bLeftEmpty = rLeft.Count() == 0; 823cdf0e10cSrcweir bool bRightEmpty = rRight.Count() == 0; 824cdf0e10cSrcweir if( bLeftEmpty || bRightEmpty ) 825cdf0e10cSrcweir return !(bLeftEmpty && bRightEmpty); 826cdf0e10cSrcweir 827cdf0e10cSrcweir // check sheet indexes of the range lists (assuming that all ranges in a list are on the same sheet) 828cdf0e10cSrcweir if( rLeft.GetObject( 0 )->aStart.Tab() != rRight.GetObject( 0 )->aStart.Tab() ) 829cdf0e10cSrcweir return false; 830cdf0e10cSrcweir 831cdf0e10cSrcweir // compare all ranges 832cdf0e10cSrcweir return rLeft != rRight; 833cdf0e10cSrcweir } 834cdf0e10cSrcweir 835cdf0e10cSrcweir } // namespace 836cdf0e10cSrcweir 837cdf0e10cSrcweir bool ScVbaEventsHelper::isSelectionChanged( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) throw (lang::IllegalArgumentException, uno::RuntimeException) 838cdf0e10cSrcweir { 839cdf0e10cSrcweir uno::Reference< uno::XInterface > xOldSelection( maOldSelection, uno::UNO_QUERY ); 840cdf0e10cSrcweir uno::Reference< uno::XInterface > xNewSelection = getXSomethingFromArgs< uno::XInterface >( rArgs, nIndex, false ); 841cdf0e10cSrcweir ScCellRangesBase* pOldCellRanges = ScCellRangesBase::getImplementation( xOldSelection ); 842cdf0e10cSrcweir ScCellRangesBase* pNewCellRanges = ScCellRangesBase::getImplementation( xNewSelection ); 843cdf0e10cSrcweir bool bChanged = !pOldCellRanges || !pNewCellRanges || lclSelectionChanged( pOldCellRanges->GetRangeList(), pNewCellRanges->GetRangeList() ); 844cdf0e10cSrcweir maOldSelection <<= xNewSelection; 845cdf0e10cSrcweir return bChanged; 846cdf0e10cSrcweir } 847cdf0e10cSrcweir 848cdf0e10cSrcweir uno::Any ScVbaEventsHelper::createWorksheet( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const 849cdf0e10cSrcweir throw (lang::IllegalArgumentException, uno::RuntimeException) 850cdf0e10cSrcweir { 851cdf0e10cSrcweir // extract sheet index, will throw, if parameter is invalid 852cdf0e10cSrcweir SCTAB nTab = lclGetTabFromArgs( rArgs, nIndex ); 853cdf0e10cSrcweir return uno::Any( excel::getUnoSheetModuleObj( mxModel, nTab ) ); 854cdf0e10cSrcweir } 855cdf0e10cSrcweir 856cdf0e10cSrcweir uno::Any ScVbaEventsHelper::createRange( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const 857cdf0e10cSrcweir throw (lang::IllegalArgumentException, uno::RuntimeException) 858cdf0e10cSrcweir { 859cdf0e10cSrcweir // it is possible to pass an existing VBA Range object 860cdf0e10cSrcweir uno::Reference< excel::XRange > xVbaRange = getXSomethingFromArgs< excel::XRange >( rArgs, nIndex ); 861cdf0e10cSrcweir if( !xVbaRange.is() ) 862cdf0e10cSrcweir { 863cdf0e10cSrcweir uno::Reference< sheet::XSheetCellRangeContainer > xRanges = getXSomethingFromArgs< sheet::XSheetCellRangeContainer >( rArgs, nIndex ); 864cdf0e10cSrcweir uno::Reference< table::XCellRange > xRange = getXSomethingFromArgs< table::XCellRange >( rArgs, nIndex ); 865cdf0e10cSrcweir if ( !xRanges.is() && !xRange.is() ) 866cdf0e10cSrcweir throw lang::IllegalArgumentException(); 867cdf0e10cSrcweir 868cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 2 ); 869cdf0e10cSrcweir if ( xRanges.is() ) 870cdf0e10cSrcweir { 871cdf0e10cSrcweir aArgs[ 0 ] <<= excel::getUnoSheetModuleObj( xRanges ); 872cdf0e10cSrcweir aArgs[ 1 ] <<= xRanges; 873cdf0e10cSrcweir } 874cdf0e10cSrcweir else 875cdf0e10cSrcweir { 876cdf0e10cSrcweir aArgs[ 0 ] <<= excel::getUnoSheetModuleObj( xRange ); 877cdf0e10cSrcweir aArgs[ 1 ] <<= xRange; 878cdf0e10cSrcweir } 879cdf0e10cSrcweir xVbaRange.set( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Range", aArgs ), uno::UNO_QUERY_THROW ); 880cdf0e10cSrcweir } 881cdf0e10cSrcweir return uno::Any( xVbaRange ); 882cdf0e10cSrcweir } 883cdf0e10cSrcweir 884cdf0e10cSrcweir uno::Any ScVbaEventsHelper::createHyperlink( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const 885cdf0e10cSrcweir throw (lang::IllegalArgumentException, uno::RuntimeException) 886cdf0e10cSrcweir { 887cdf0e10cSrcweir uno::Reference< table::XCell > xCell = getXSomethingFromArgs< table::XCell >( rArgs, nIndex, false ); 888cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 2 ); 889cdf0e10cSrcweir aArgs[ 0 ] <<= excel::getUnoSheetModuleObj( xCell ); 890cdf0e10cSrcweir aArgs[ 1 ] <<= xCell; 891cdf0e10cSrcweir uno::Reference< uno::XInterface > xHyperlink( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Hyperlink", aArgs ), uno::UNO_SET_THROW ); 892cdf0e10cSrcweir return uno::Any( xHyperlink ); 893cdf0e10cSrcweir } 894cdf0e10cSrcweir 895cdf0e10cSrcweir uno::Any ScVbaEventsHelper::createWindow( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const 896cdf0e10cSrcweir throw (lang::IllegalArgumentException, uno::RuntimeException) 897cdf0e10cSrcweir { 898cdf0e10cSrcweir uno::Sequence< uno::Any > aArgs( 3 ); 899cdf0e10cSrcweir aArgs[ 0 ] <<= getVBADocument( mxModel ); 900cdf0e10cSrcweir aArgs[ 1 ] <<= mxModel; 901cdf0e10cSrcweir aArgs[ 2 ] <<= getXSomethingFromArgs< frame::XController >( rArgs, nIndex, false ); 902cdf0e10cSrcweir uno::Reference< uno::XInterface > xWindow( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Window", aArgs ), uno::UNO_SET_THROW ); 903cdf0e10cSrcweir return uno::Any( xWindow ); 904cdf0e10cSrcweir } 905cdf0e10cSrcweir 906cdf0e10cSrcweir // ============================================================================ 907cdf0e10cSrcweir 908cdf0e10cSrcweir namespace vbaeventshelper 909cdf0e10cSrcweir { 910cdf0e10cSrcweir namespace sdecl = comphelper::service_decl; 911cdf0e10cSrcweir sdecl::class_<ScVbaEventsHelper, sdecl::with_args<true> > serviceImpl; 912cdf0e10cSrcweir extern sdecl::ServiceDecl const serviceDecl( 913cdf0e10cSrcweir serviceImpl, 914cdf0e10cSrcweir "ScVbaEventsHelper", 915cdf0e10cSrcweir "com.sun.star.script.vba.VBASpreadsheetEventProcessor" ); 916cdf0e10cSrcweir } 917cdf0e10cSrcweir 918cdf0e10cSrcweir // ============================================================================ 919