LCOV - code coverage report
Current view: top level - sc/source/ui/vba - vbaeventshelper.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 303 417 72.7 %
Date: 2015-06-13 12:38:46 Functions: 39 47 83.0 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.11