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