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