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