xref: /aoo41x/main/sc/source/ui/vba/vbaeventshelper.cxx (revision cdf0e10c)
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