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