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