Bump version to 5.0-43
[LibreOffice.git] / basic / source / classes / eventatt.cxx
blob6472d00d0cada98fed39e8a4a418b4dece12b82f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <osl/mutex.hxx>
22 #include <comphelper/processfactory.hxx>
23 #include <comphelper/string.hxx>
25 #include <com/sun/star/awt/XControlContainer.hpp>
26 #include <com/sun/star/awt/XControlModel.hpp>
27 #include <com/sun/star/awt/XControl.hpp>
28 #include <com/sun/star/awt/XDialog.hpp>
29 #include <com/sun/star/awt/XWindow.hpp>
30 #include <com/sun/star/awt/DialogProvider.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/container/XEnumerationAccess.hpp>
33 #include <com/sun/star/container/XNameContainer.hpp>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/frame/Desktop.hpp>
36 #include <com/sun/star/resource/XStringResourceSupplier.hpp>
37 #include <com/sun/star/resource/XStringResourceManager.hpp>
38 #include <com/sun/star/script/XEventAttacher.hpp>
39 #include <com/sun/star/script/XAllListener.hpp>
40 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
41 #include <com/sun/star/script/XScriptEventsAttacher.hpp>
42 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
43 #include <com/sun/star/script/XLibraryContainer.hpp>
44 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
45 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
46 #include <com/sun/star/script/provider/XScriptProvider.hpp>
48 #include <basic/basicmanagerrepository.hxx>
49 #include <basic/basmgr.hxx>
51 #include <vcl/svapp.hxx>
52 #include <xmlscript/xmldlg_imexp.hxx>
53 #include <sbunoobj.hxx>
54 #include <basic/sbstar.hxx>
55 #include <basic/sbmeth.hxx>
56 #include <basic/sbuno.hxx>
57 #include <runtime.hxx>
58 #include <sbintern.hxx>
59 #include <eventatt.hxx>
61 #include <cppuhelper/implbase1.hxx>
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::uno;
64 using namespace ::com::sun::star::script;
65 using namespace ::com::sun::star::resource;
66 using namespace ::com::sun::star::lang;
67 using namespace ::com::sun::star::beans;
68 using namespace ::com::sun::star::container;
69 using namespace ::com::sun::star::reflection;
70 using namespace ::com::sun::star::awt;
71 using namespace ::com::sun::star::io;
72 using namespace ::cppu;
73 using namespace ::osl;
76 void SFURL_firing_impl( const ScriptEvent& aScriptEvent, Any* pRet, const Reference< frame::XModel >& xModel )
78 SAL_INFO("basic", "Processing script url " << aScriptEvent.ScriptCode);
79 try
81 Reference< provider::XScriptProvider > xScriptProvider;
82 if ( xModel.is() )
84 Reference< provider::XScriptProviderSupplier > xSupplier( xModel, UNO_QUERY );
85 OSL_ENSURE( xSupplier.is(), "SFURL_firing_impl: failed to get script provider supplier" );
86 if ( xSupplier.is() )
87 xScriptProvider.set( xSupplier->getScriptProvider() );
89 else
91 Reference< XComponentContext > xContext(
92 comphelper::getProcessComponentContext() );
93 Reference< provider::XScriptProviderFactory > xFactory =
94 provider::theMasterScriptProviderFactory::get( xContext );
96 Any aCtx;
97 aCtx <<= OUString("user");
98 xScriptProvider.set( xFactory->createScriptProvider( aCtx ), UNO_QUERY );
101 if ( !xScriptProvider.is() )
103 SAL_INFO("basic", "Failed to create msp");
104 return;
106 Sequence< Any > inArgs( 0 );
107 Sequence< Any > outArgs( 0 );
108 Sequence< sal_Int16 > outIndex;
110 // get Arguments for script
111 inArgs = aScriptEvent.Arguments;
113 Reference< provider::XScript > xScript = xScriptProvider->getScript( aScriptEvent.ScriptCode );
115 if ( !xScript.is() )
117 SAL_INFO("basic", "Failed to Failed to obtain XScript");
118 return;
121 Any result = xScript->invoke( inArgs, outIndex, outArgs );
122 if ( pRet )
124 *pRet = result;
127 catch ( const RuntimeException& re )
129 SAL_INFO("basic", "Caught RuntimeException reason " << re.Message);
131 catch ( const Exception& e )
133 SAL_INFO("basic", "Caught Exception reason " << e.Message);
139 class BasicScriptListener_Impl : public WeakImplHelper1< XScriptListener >
141 StarBASICRef maBasicRef;
142 Reference< frame::XModel > m_xModel;
144 void firing_impl(const ScriptEvent& aScriptEvent, Any* pRet);
146 public:
147 BasicScriptListener_Impl( StarBASIC* pBasic, const Reference< frame::XModel >& xModel )
148 : maBasicRef( pBasic ), m_xModel( xModel ) {}
150 // Methods of XAllListener
151 virtual void SAL_CALL firing(const ScriptEvent& aScriptEvent)
152 throw( RuntimeException, std::exception ) SAL_OVERRIDE;
153 virtual Any SAL_CALL approveFiring(const ScriptEvent& aScriptEvent)
154 throw( InvocationTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
156 // Methods of XEventListener
157 virtual void SAL_CALL disposing(const EventObject& Source)
158 throw( RuntimeException, std::exception ) SAL_OVERRIDE;
161 // Methods XAllListener
162 void BasicScriptListener_Impl::firing( const ScriptEvent& aScriptEvent ) throw ( RuntimeException, std::exception )
164 SolarMutexGuard g;
166 firing_impl( aScriptEvent, NULL );
169 Any BasicScriptListener_Impl::approveFiring( const ScriptEvent& aScriptEvent )
170 throw ( InvocationTargetException, RuntimeException, std::exception )
172 SolarMutexGuard g;
174 Any aRetAny;
175 firing_impl( aScriptEvent, &aRetAny );
176 return aRetAny;
179 // Methods XEventListener
180 void BasicScriptListener_Impl::disposing(const EventObject& ) throw ( RuntimeException, std::exception )
182 // TODO: ???
183 //SolarMutexGuard aGuard;
184 //xSbxObj.Clear();
188 void BasicScriptListener_Impl::firing_impl( const ScriptEvent& aScriptEvent, Any* pRet )
190 if( aScriptEvent.ScriptType == "StarBasic" )
192 // Full qualified name?
193 OUString aMacro( aScriptEvent.ScriptCode );
194 OUString aLibName;
195 OUString aLocation;
196 if( comphelper::string::getTokenCount(aMacro, '.') == 3 )
198 sal_Int32 nLast = 0;
199 OUString aFullLibName = aMacro.getToken( (sal_Int32)0, (sal_Unicode)'.', nLast );
201 sal_Int32 nIndex = aFullLibName.indexOf( (sal_Unicode)':' );
202 if (nIndex >= 0)
204 aLocation = aFullLibName.copy( 0, nIndex );
205 aLibName = aFullLibName.copy( nIndex + 1 );
208 aMacro = aMacro.copy( nLast );
211 SbxObject* p = maBasicRef;
212 SbxObject* pParent = p->GetParent();
213 SbxObject* pParentParent = pParent ? pParent->GetParent() : NULL;
215 StarBASICRef xAppStandardBasic;
216 StarBASICRef xDocStandardBasic;
217 if( pParentParent )
219 // Own basic must be document library
220 xAppStandardBasic = static_cast<StarBASIC*>(pParentParent);
221 xDocStandardBasic = static_cast<StarBASIC*>(pParent);
223 else if( pParent )
225 OUString aName = p->GetName();
226 if( aName == "Standard" )
228 // Own basic is doc standard lib
229 xDocStandardBasic = static_cast<StarBASIC*>(p);
231 xAppStandardBasic = static_cast<StarBASIC*>(pParent);
233 else
235 xAppStandardBasic = static_cast<StarBASIC*>(p);
238 bool bSearchLib = true;
239 StarBASICRef xLibSearchBasic;
240 if( aLocation == "application" )
242 xLibSearchBasic = xAppStandardBasic;
244 else if( aLocation == "document" )
246 xLibSearchBasic = xDocStandardBasic;
248 else
250 bSearchLib = false;
252 SbxVariable* pMethVar = NULL;
253 // Be still tolerant and make default search if no search basic exists
254 if( bSearchLib && xLibSearchBasic.Is() )
256 StarBASICRef xLibBasic;
257 sal_Int16 nCount = xLibSearchBasic->GetObjects()->Count();
258 for( sal_Int16 nObj = -1; nObj < nCount ; nObj++ )
260 StarBASIC* pBasic;
261 if( nObj == -1 )
263 pBasic = (StarBASIC*)xLibSearchBasic;
265 else
267 SbxVariable* pVar = xLibSearchBasic->GetObjects()->Get( nObj );
268 pBasic = PTR_CAST(StarBASIC,pVar);
270 if( pBasic )
272 OUString aName = pBasic->GetName();
273 if( aName == aLibName )
275 // Search only in the lib, not automatically in application basic
276 SbxFlagBits nFlags = pBasic->GetFlags();
277 pBasic->ResetFlag( SBX_GBLSEARCH );
278 pMethVar = pBasic->Find( aMacro, SbxCLASS_DONTCARE );
279 pBasic->SetFlags( nFlags );
280 break;
286 // Default: Be tolerant and search everywhere
287 if( (!pMethVar || !pMethVar->ISA(SbMethod)) && maBasicRef.Is() )
289 pMethVar = maBasicRef->FindQualified( aMacro, SbxCLASS_DONTCARE );
291 SbMethod* pMeth = PTR_CAST(SbMethod,pMethVar);
292 if( !pMeth )
294 return;
296 // Setup parameters
297 SbxArrayRef xArray;
298 sal_Int32 nCnt = aScriptEvent.Arguments.getLength();
299 if( nCnt )
301 xArray = new SbxArray;
302 const Any *pArgs = aScriptEvent.Arguments.getConstArray();
303 for( sal_Int32 i = 0; i < nCnt; i++ )
305 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
306 unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
307 xArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
311 // Call method
312 SbxVariableRef xValue = pRet ? new SbxVariable : 0;
313 if( xArray.Is() )
315 pMeth->SetParameters( xArray );
317 pMeth->Call( xValue );
318 if( pRet )
320 *pRet = sbxToUnoValue( xValue );
322 pMeth->SetParameters( NULL );
324 else // scripting framework script
326 //callBasic via scripting framework
327 SFURL_firing_impl( aScriptEvent, pRet, m_xModel );
331 css::uno::Reference< css::container::XNameContainer > implFindDialogLibForDialog( const Any& rDlgAny, SbxObject* pBasic )
333 css::uno::Reference< css::container::XNameContainer > aRetDlgLib;
335 SbxVariable* pDlgLibContVar = pBasic->Find(OUString("DialogLibraries"), SbxCLASS_OBJECT);
336 if( pDlgLibContVar && pDlgLibContVar->ISA(SbUnoObject) )
338 SbUnoObject* pDlgLibContUnoObj = static_cast<SbUnoObject*>((SbxBase*)pDlgLibContVar);
339 Any aDlgLibContAny = pDlgLibContUnoObj->getUnoAny();
341 Reference< XLibraryContainer > xDlgLibContNameAccess( aDlgLibContAny, UNO_QUERY );
342 OSL_ENSURE( xDlgLibContNameAccess.is(), "implFindDialogLibForDialog: no lib container for the given dialog!" );
343 if( xDlgLibContNameAccess.is() )
345 Sequence< OUString > aLibNames = xDlgLibContNameAccess->getElementNames();
346 const OUString* pLibNames = aLibNames.getConstArray();
347 sal_Int32 nLibNameCount = aLibNames.getLength();
349 for( sal_Int32 iLib = 0 ; iLib < nLibNameCount ; iLib++ )
351 if ( !xDlgLibContNameAccess->isLibraryLoaded( pLibNames[ iLib ] ) )
352 // if the library isn't loaded, then the dialog cannot originate from this lib
353 continue;
355 Any aDlgLibAny = xDlgLibContNameAccess->getByName( pLibNames[ iLib ] );
357 Reference< XNameContainer > xDlgLibNameCont( aDlgLibAny, UNO_QUERY );
358 OSL_ENSURE( xDlgLibNameCont.is(), "implFindDialogLibForDialog: invalid dialog lib!" );
359 if( xDlgLibNameCont.is() )
361 Sequence< OUString > aDlgNames = xDlgLibNameCont->getElementNames();
362 const OUString* pDlgNames = aDlgNames.getConstArray();
363 sal_Int32 nDlgNameCount = aDlgNames.getLength();
365 for( sal_Int32 iDlg = 0 ; iDlg < nDlgNameCount ; iDlg++ )
367 Any aDlgAny = xDlgLibNameCont->getByName( pDlgNames[ iDlg ] );
368 if( aDlgAny == rDlgAny )
370 aRetDlgLib = xDlgLibNameCont;
371 break;
379 return aRetDlgLib;
382 css::uno::Reference< css::container::XNameContainer > implFindDialogLibForDialogBasic( const Any& aAnyISP, SbxObject* pBasic, StarBASIC*& pFoundBasic )
384 css::uno::Reference< css::container::XNameContainer > aDlgLib;
385 // Find dialog library for dialog, direct access is not possible here
386 StarBASIC* pStartedBasic = static_cast<StarBASIC*>(pBasic);
387 SbxObject* pParentBasic = pStartedBasic ? pStartedBasic->GetParent() : NULL;
388 SbxObject* pParentParentBasic = pParentBasic ? pParentBasic->GetParent() : NULL;
390 SbxObject* pSearchBasic1 = NULL;
391 SbxObject* pSearchBasic2 = NULL;
392 if( pParentParentBasic )
394 pSearchBasic1 = pParentBasic;
395 pSearchBasic2 = pParentParentBasic;
397 else
399 pSearchBasic1 = pStartedBasic;
400 pSearchBasic2 = pParentBasic;
402 if( pSearchBasic1 )
404 aDlgLib = implFindDialogLibForDialog( aAnyISP, pSearchBasic1 );
406 if ( aDlgLib.is() )
407 pFoundBasic = static_cast<StarBASIC*>(pSearchBasic1);
409 else if( pSearchBasic2 )
411 aDlgLib = implFindDialogLibForDialog( aAnyISP, pSearchBasic2 );
412 if ( aDlgLib.is() )
413 pFoundBasic = static_cast<StarBASIC*>(pSearchBasic2);
416 return aDlgLib;
419 void RTL_Impl_CreateUnoDialog( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
421 (void)pBasic;
422 (void)bWrite;
424 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
426 // We need at least 1 parameter
427 if ( rPar.Count() < 2 )
429 StarBASIC::Error( SbERR_BAD_ARGUMENT );
430 return;
433 // Get dialog
434 SbxBaseRef pObj = rPar.Get( 1 )->GetObject();
435 if( !(pObj && pObj->ISA(SbUnoObject)) )
437 StarBASIC::Error( SbERR_BAD_ARGUMENT );
438 return;
440 SbUnoObject* pUnoObj = static_cast<SbUnoObject*>((SbxBase*)pObj);
441 Any aAnyISP = pUnoObj->getUnoAny();
442 TypeClass eType = aAnyISP.getValueType().getTypeClass();
444 if( eType != TypeClass_INTERFACE )
446 StarBASIC::Error( SbERR_BAD_ARGUMENT );
447 return;
450 // Create new uno dialog
451 Reference< XNameContainer > xDialogModel( xContext->getServiceManager()->createInstanceWithContext(
452 "com.sun.star.awt.UnoControlDialogModel", xContext), UNO_QUERY );
453 if( !xDialogModel.is() )
455 return;
457 Reference< XInputStreamProvider > xISP;
458 aAnyISP >>= xISP;
459 if( !xISP.is() )
461 return;
464 // Import the DialogModel
465 Reference< XInputStream > xInput( xISP->createInputStream() );
467 // i83963 Force decoration
468 uno::Reference< beans::XPropertySet > xDlgModPropSet( xDialogModel, uno::UNO_QUERY );
469 if( xDlgModPropSet.is() )
473 bool bDecoration = true;
474 OUString aDecorationPropName("Decoration");
475 Any aDecorationAny = xDlgModPropSet->getPropertyValue( aDecorationPropName );
476 aDecorationAny >>= bDecoration;
477 if( !bDecoration )
479 xDlgModPropSet->setPropertyValue( aDecorationPropName, makeAny( true ) );
481 OUString aTitlePropName("Title");
482 xDlgModPropSet->setPropertyValue( aTitlePropName, makeAny( OUString() ) );
485 catch(const UnknownPropertyException& )
489 css::uno::Reference< css::container::XNameContainer > aDlgLib;
490 bool bDocDialog = false;
491 StarBASIC* pFoundBasic = NULL;
492 SAL_INFO("basic", "About to try get a hold of ThisComponent");
493 Reference< frame::XModel > xModel = StarBASIC::GetModelFromBasic( GetSbData()->pInst->GetBasic() ) ;
494 aDlgLib = implFindDialogLibForDialogBasic( aAnyISP, GetSbData()->pInst->GetBasic(), pFoundBasic );
495 // If we found the dialog then it belongs to the Search basic
496 if ( !pFoundBasic )
498 Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( xContext );
499 Reference< container::XEnumeration > xModels;
500 Reference< container::XEnumerationAccess > xComponents( xDesktop->getComponents(), UNO_QUERY );
501 if ( xComponents.is() )
503 xModels.set( xComponents->createEnumeration(), UNO_QUERY );
505 if ( xModels.is() )
507 while ( xModels->hasMoreElements() )
509 Reference< frame::XModel > xNextModel( xModels->nextElement(), UNO_QUERY );
510 if ( xNextModel.is() )
512 BasicManager* pMgr = basic::BasicManagerRepository::getDocumentBasicManager( xNextModel );
513 if ( pMgr )
515 aDlgLib = implFindDialogLibForDialogBasic( aAnyISP, pMgr->GetLib(0), pFoundBasic );
517 if ( aDlgLib.is() )
519 bDocDialog = true;
520 xModel = xNextModel;
521 break;
527 if ( pFoundBasic )
529 bDocDialog = pFoundBasic->IsDocBasic();
531 Reference< XScriptListener > xScriptListener = new BasicScriptListener_Impl( GetSbData()->pInst->GetBasic(), xModel );
533 // Create a "living" Dialog
534 Reference< XControl > xCntrl;
537 Reference< XDialogProvider > xDlgProv;;
538 if( bDocDialog )
539 xDlgProv = css::awt::DialogProvider::createWithModelAndScripting( xContext, xModel, xInput, aDlgLib, xScriptListener );
540 else
541 xDlgProv = css::awt::DialogProvider::createWithModelAndScripting( xContext, uno::Reference< frame::XModel >(), xInput, aDlgLib, xScriptListener );
543 xCntrl.set( xDlgProv->createDialog(OUString() ), UNO_QUERY_THROW );
544 // Add dialog model to dispose vector
545 Reference< XComponent > xDlgComponent( xCntrl->getModel(), UNO_QUERY );
546 GetSbData()->pInst->getComponentVector().push_back( xDlgComponent );
547 // need ThisCompoent from calling script
549 // preserve existing bad behaviour, it's possible... but probably
550 // illegal to open 2 dialogs ( they ARE modal ) when this happens, sometimes
551 // create dialog fails. So, in this case let's not throw, just leave basic
552 // detect the unset object.
553 catch(const uno::Exception& )
557 // Return dialog
558 Any aRetVal;
559 aRetVal <<= xCntrl;
560 SbxVariableRef refVar = rPar.Get(0);
561 unoToSbxValue( (SbxVariable*)refVar, aRetVal );
567 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */