/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
static Sequence< Any > ooMouseEvtToVBADblClick( const Sequence< Any >& params )
{
awt::MouseEvent evt;
if ( !( isMouseEventOk(evt, params)) ||
(evt.ClickCount != 2) ) return Sequence< Any >(); // give back orig params, this will signal that the event is good return params;
}
static Sequence< Any > ooMouseEvtToVBAMouseEvt( const Sequence< Any >& params )
{
awt::MouseEvent evt;
if ( !isMouseEventOk(evt, params) ) return Sequence< Any >();
Sequence< Any > translatedParams{ Any(evt.Buttons), // Buttons
Any(evt.Modifiers), // Shift
Any(evt.X), // X
Any(evt.Y) }; // Y return translatedParams;
}
static Sequence< Any > ooKeyPressedToVBAKeyPressed( const Sequence< Any >& params )
{
awt::KeyEvent evt;
if ( !isKeyEventOk( evt, params ) ) return Sequence< Any >();
Reference< msforms::XReturnInteger> xKeyCode = new ReturnInteger( sal_Int32( evt.KeyCode ) );
Sequence< Any > translatedParams{ Any(xKeyCode) }; return translatedParams;
}
static Sequence< Any > ooKeyPressedToVBAKeyUpDown( const Sequence< Any >& params )
{
awt::KeyEvent evt;
if ( !isKeyEventOk( evt, params ) ) return Sequence< Any >();
// #TODO check whether values from OOO conform to values generated from vba
Sequence< Any > translatedParams{ Any(xKeyCode), Any(shift) }; return translatedParams;
}
typedef Sequence< Any > (*Translator)(const Sequence< Any >&);
namespace {
//expand the "TranslateInfo" struct to support more kinds of events struct TranslateInfo
{
OUString sVBAName; //vba event name
Translator toVBA; //the method to convert OO event parameters to VBA event parameters bool (*ApproveRule)(const ScriptEvent& evt, voidconst * pPara); //this method is used to determine which types of controls should execute the event voidconst *pPara; //Parameters for the above approve method
};
staticbool ApproveAll(const ScriptEvent& evt, voidconst * pPara); //allow all types of controls to execute the event staticbool ApproveType(const ScriptEvent& evt, voidconst * pPara); //certain types of controls should execute the event, those types are given by pPara staticbool DenyType(const ScriptEvent& evt, voidconst * pPara); //certain types of controls should not execute the event, those types are given by pPara staticbool DenyMouseDrag(const ScriptEvent& evt, voidconst * pPara); //used for VBA MouseMove event when "Shift" key is pressed
namespace {
struct TypeList
{
uno::Type const * pTypeList; int nListLength;
};
}
Type const typeXFixedText = cppu::UnoType<awt::XFixedText>::get();
Type const typeXTextComponent = cppu::UnoType<awt::XTextComponent>::get();
Type const typeXComboBox = cppu::UnoType<awt::XComboBox>::get();
Type const typeXRadioButton = cppu::UnoType<awt::XRadioButton>::get();
Type const typeXListBox = cppu::UnoType<awt::XListBox>::get();
staticbool
eventMethodToDescriptor( std::u16string_view rEventMethod, ScriptEventDescriptor& evtDesc, const OUString& sCodeName )
{ // format of ControlListener is TypeName::methodname e.g. // "com.sun.star.awt.XActionListener::actionPerformed" or // "XActionListener::actionPerformed
// Only create an ScriptEventDescriptor for an event we can translate // or emulate if ( !sMethodName.isEmpty()
&& !sTypeName.isEmpty()
&& ( infos.find( sMethodName ) != infos.end() ) )
{ // just fill in CodeName, when the event fires the other // info is gathered from the event source to determine what // event handler we try to call
evtDesc.ScriptCode = sCodeName;
evtDesc.ListenerType = sTypeName;
evtDesc.EventMethod = sMethodName;
// set this it VBAInterop, ensures that it doesn't // get persisted or shown in property editors
evtDesc.ScriptType = "VBAInterop"; returntrue;
} returnfalse;
Sequence< ScriptEventDescriptor > aDest( nLength );
sal_Int32 nEvts = 0; for ( OUString const & i : aControlListeners)
{ // from getListeners eventName is of form // "com.sun.star.awt.XActionListener::actionPerformed" // we need to strip "com.sun.star.awt." from that for form // controls
ScriptEventDescriptor evtDesc; if ( eventMethodToDescriptor( i, evtDesc, sCodeName ) )
{
sal_Int32 dIndex = nEvts;
++nEvts; if ( nEvts > aDest.getLength() )
aDest.realloc( nEvts );// should never happen
aDest.getArray()[ dIndex ] = std::move(evtDesc);
}
}
aDest.realloc( nEvts );
//decide if the control should execute the event bool ApproveAll(SAL_UNUSED_PARAMETER const ScriptEvent&, SAL_UNUSED_PARAMETER voidconst * )
{ returntrue;
}
//for the given control type in evt.Arguments[0], look for if it appears in the type list in pPara staticbool FindControl(const ScriptEvent& evt, voidconst * pPara)
{
lang::EventObject aEvent;
evt.Arguments[ 0 ] >>= aEvent;
uno::Reference< uno::XInterface > xInterface( aEvent.Source, uno::UNO_QUERY );
TypeList const * pTypeListInfo = static_cast<TypeList const *>(pPara);
Type const * pType = pTypeListInfo->pTypeList; int nLen = pTypeListInfo->nListLength;
for (int i = 0; i < nLen; i++)
{ if ( xInterface->queryInterface( *pType ).hasValue() )
{ returntrue;
}
pType++;
}
returnfalse;
}
//if the given control type in evt.Arguments[0] appears in the type list in pPara, then approve the execution bool ApproveType(const ScriptEvent& evt, voidconst * pPara)
{ return FindControl(evt, pPara);
}
//if the given control type in evt.Arguments[0] appears in the type list in pPara, then deny the execution bool DenyType(const ScriptEvent& evt, voidconst * pPara)
{ return !FindControl(evt, pPara);
}
//when mouse is moving, either the mouse button is pressed or some key is pressed can trigger the OO mouseDragged event, //the former should be denied, and the latter allowed, only by doing so can the VBA MouseMove event when the "Shift" key is //pressed can be correctly triggered bool DenyMouseDrag(const ScriptEvent& evt, SAL_UNUSED_PARAMETER voidconst * )
{
awt::MouseEvent aEvent;
evt.Arguments[ 0 ] >>= aEvent; return aEvent.Buttons == 0;
}
// EventListener
void
EventListener::firing_Impl(const ScriptEvent& evt, Any* pRet )
{ // let default handlers deal with non vba stuff if ( evt.ScriptType != "VBAInterop" ) return;
lang::EventObject aEvent;
evt.Arguments[ 0 ] >>= aEvent;
OUString sName = u"UserForm"_ustr;
uno::Reference< awt::XDialog > xDlg( aEvent.Source, uno::UNO_QUERY ); if ( !xDlg.is() )
{ // evt.Source is // a) Dialog // b) xShapeControl ( from api (sheet control) ) // c) eventmanager ( I guess ) // d) vba control ( from api also )
uno::Reference< drawing::XControlShape > xCntrlShape( evt.Source, uno::UNO_QUERY );
uno::Reference< awt::XControl > xControl( aEvent.Source, uno::UNO_QUERY ); if ( xCntrlShape.is() )
{ // for sheet controls ( that fire from the api ) we don't // have the real control ( that's only available from the view ) // api code creates just a control instance that is transferred // via aEvent.Arguments[ 0 ] that control though has no // info like name etc.
uno::Reference< container::XNamed > xName( xCntrlShape->getControl(), uno::UNO_QUERY_THROW );
sName = xName->getName();
} else
{ // Userform control ( fired from the api or from event manager )
uno::Reference< beans::XPropertySet > xProps;
xProps.set( xControl->getModel(), uno::UNO_QUERY_THROW );
xProps->getPropertyValue(u"Name"_ustr) >>= sName;
}
} //dumpEvent( evt );
EventInfoHash& infos = getEventTransInfo();
EventInfoHash::const_iterator eventInfo_it = infos.find( evt.MethodName );
EventInfoHash::const_iterator it_end = infos.end(); if ( eventInfo_it == it_end )
{
SAL_WARN("scripting", "Bogus event for " << evt.ScriptType ); return;
}
BasicManager* pBasicManager = mpShell->GetBasicManager();
OUString sProject;
OUString sScriptCode( evt.ScriptCode ); // dialogs pass their own library, presence of Dot determines that if ( sScriptCode.indexOf( '.' ) == -1 )
{ //'Project' is a better default but I want to force failures //OUString sMacroLoc("Project");
sProject = "Standard";
for (constauto& rTxInfo : eventInfo_it->second)
{ // If the document is closed, we should not execute macro. if (m_bDocClosed)
{ break;
}
// see if we have a match for the handlerextension // where ScriptCode is methodname_handlerextension
OUString sToResolve = sMacroLoc + sName + rTxInfo.sVBAName;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.