diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /vbahelper/source/vbahelper | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vbahelper/source/vbahelper')
34 files changed, 8358 insertions, 0 deletions
diff --git a/vbahelper/source/vbahelper/vbaapplicationbase.cxx b/vbahelper/source/vbahelper/vbaapplicationbase.cxx new file mode 100644 index 000000000..fe00e0c89 --- /dev/null +++ b/vbahelper/source/vbahelper/vbaapplicationbase.cxx @@ -0,0 +1,481 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 . + */ + +#include <vbahelper/vbaapplicationbase.hxx> +#include <sal/macros.h> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <com/sun/star/awt/XWindow2.hpp> + +#include <filter/msfilter/msvbahelper.hxx> +#include <rtl/ref.hxx> +#include <tools/datetime.hxx> +#include <vcl/timer.hxx> +#include <vcl/svapp.hxx> + +#include <basic/sbstar.hxx> +#include <basic/sbmeth.hxx> +#include <basic/sbmod.hxx> +#include <basic/vbahelper.hxx> + +#include <comphelper/asyncquithandler.hxx> + +#include "vbacommandbars.hxx" + +#include <o3tl/hash_combine.hxx> +#include <o3tl/string_view.hxx> +#include <unordered_map> + +using namespace ::com::sun::star; +using namespace ::ooo::vba; + +constexpr OUStringLiteral OFFICEVERSION = u"11.0"; + +typedef ::std::pair< OUString, ::std::pair< double, double > > VbaTimerInfo; + +namespace { + +class VbaTimer +{ + Timer m_aTimer; + VbaTimerInfo m_aTimerInfo; + ::rtl::Reference< VbaApplicationBase > m_xBase; + +public: + VbaTimer() : m_aTimer("VbaTimer") + {} + + ~VbaTimer() + { + m_aTimer.Stop(); + } + + VbaTimer(const VbaTimer&) = delete; + VbaTimer& operator=(const VbaTimer&) = delete; + + static double GetNow() + { + DateTime aNow( DateTime::SYSTEM ); + Date aRefDate(1899'12'30); + tools::Long nDiffDays = aNow - aRefDate; + + tools::Long nDiffSeconds = aNow.GetHour() * 3600 + aNow.GetMin() * 60 + aNow.GetSec(); + return static_cast<double>(nDiffDays) + static_cast<double>(nDiffSeconds)/double(24*3600); + } + + static sal_Int32 GetTimerMilliseconds( double nFrom, double nTo ) + { + double nResult = nTo - nFrom; + if ( nResult > 0 ) + nResult *= 24*3600*1000; + else + nResult = 50; + + return static_cast<sal_Int32>(nResult); + } + + void Start( const ::rtl::Reference< VbaApplicationBase >& xBase, const OUString& aFunction, double nFrom, double nTo ) + { + if ( !xBase.is() || aFunction.isEmpty() ) + throw uno::RuntimeException( "Unexpected arguments!" ); + + m_xBase = xBase; + m_aTimerInfo = VbaTimerInfo( aFunction, ::std::pair< double, double >( nFrom, nTo ) ); + m_aTimer.SetInvokeHandler( LINK( this, VbaTimer, MacroCallHdl ) ); + m_aTimer.SetTimeout( GetTimerMilliseconds( GetNow(), nFrom ) ); + m_aTimer.Start(); + } + + DECL_LINK( MacroCallHdl, Timer*, void ); +}; + +} + +IMPL_LINK_NOARG(VbaTimer, MacroCallHdl, Timer *, void) +{ + if ( m_aTimerInfo.second.second == 0 || GetNow() < m_aTimerInfo.second.second ) + { + uno::Any aDummyArg; + try + { + m_xBase->Run( m_aTimerInfo.first, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg, aDummyArg ); + } + catch( uno::Exception& ) + {} + } + + // must be the last call in the method since it deletes the timer + try + { + m_xBase->OnTime( uno::Any( m_aTimerInfo.second.first ), m_aTimerInfo.first, uno::Any( m_aTimerInfo.second.second ), uno::Any( false ) ); + } catch( uno::Exception& ) + {} +} + +namespace { + +struct VbaTimerInfoHash +{ + size_t operator()( const VbaTimerInfo& rTimerInfo ) const + { + std::size_t seed = 0; + o3tl::hash_combine(seed, rTimerInfo.first.hashCode()); + o3tl::hash_combine(seed, rTimerInfo.second.first); + o3tl::hash_combine(seed, rTimerInfo.second.second); + return seed; + } +}; + +} + +typedef std::unordered_map< VbaTimerInfo, std::unique_ptr<VbaTimer>, VbaTimerInfoHash > VbaTimerHashMap; + +struct VbaApplicationBase_Impl final +{ + VbaTimerHashMap m_aTimerHash; + bool mbVisible; + OUString msCaption; + + VbaApplicationBase_Impl() : mbVisible( true ) {} +}; + +VbaApplicationBase::VbaApplicationBase( const uno::Reference< uno::XComponentContext >& xContext ) + : ApplicationBase_BASE( uno::Reference< XHelperInterface >(), xContext ) + , m_pImpl( new VbaApplicationBase_Impl ) +{ +} + +VbaApplicationBase::~VbaApplicationBase() +{ +} + +sal_Bool SAL_CALL +VbaApplicationBase::getScreenUpdating() +{ + uno::Reference< frame::XModel > xModel = getCurrentDocument(); + if (!xModel.is()) + return true; + return !xModel->hasControllersLocked(); +} + +void SAL_CALL +VbaApplicationBase::setScreenUpdating(sal_Bool bUpdate) +{ + uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_SET_THROW ); + // #163808# use helper from module "basic" to lock all documents of this application + ::basic::vba::lockControllersOfAllDocuments( xModel, !bUpdate ); +} + +sal_Bool SAL_CALL +VbaApplicationBase::getDisplayStatusBar() +{ + uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_SET_THROW ); + uno::Reference< frame::XFrame > xFrame( xModel->getCurrentController()->getFrame(), uno::UNO_SET_THROW ); + uno::Reference< beans::XPropertySet > xProps( xFrame, uno::UNO_QUERY_THROW ); + + uno::Reference< frame::XLayoutManager > xLayoutManager( xProps->getPropertyValue( "LayoutManager"), uno::UNO_QUERY_THROW ); + if( xLayoutManager->isElementVisible( "private:resource/statusbar/statusbar" ) ){ + return true; + } + return false; +} + +void SAL_CALL +VbaApplicationBase::setDisplayStatusBar(sal_Bool bDisplayStatusBar) +{ + uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_SET_THROW ); + uno::Reference< frame::XFrame > xFrame( xModel->getCurrentController()->getFrame(), uno::UNO_SET_THROW ); + uno::Reference< beans::XPropertySet > xProps( xFrame, uno::UNO_QUERY_THROW ); + + uno::Reference< frame::XLayoutManager > xLayoutManager( xProps->getPropertyValue( "LayoutManager" ), uno::UNO_QUERY_THROW ); + OUString url( "private:resource/statusbar/statusbar" ); + if( bDisplayStatusBar && !xLayoutManager->isElementVisible( url ) ){ + if( !xLayoutManager->showElement( url ) ) + xLayoutManager->createElement( url ); + return; + } + else if( !bDisplayStatusBar && xLayoutManager->isElementVisible( url ) ){ + xLayoutManager->hideElement( url ); + return; + } +} + +sal_Bool SAL_CALL VbaApplicationBase::getInteractive() +{ + uno::Reference< frame::XModel > xModel = getCurrentDocument(); + if (!xModel.is()) + return true; + + uno::Reference< frame::XController > xController( xModel->getCurrentController() ); + if (!xController.is()) + return true; + + uno::Reference< frame::XFrame > xFrame( xController->getFrame() ); + if (!xFrame.is()) + return true; + + uno::Reference< awt::XWindow2 > xWindow( xFrame->getContainerWindow(), uno::UNO_QUERY ); + if (!xWindow.is()) + return true; + + return xWindow->isEnabled(); +} + +void SAL_CALL VbaApplicationBase::setInteractive( sal_Bool bInteractive ) +{ + uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_SET_THROW ); + // #163808# use helper from module "basic" to enable/disable all container windows of all documents of this application + ::basic::vba::enableContainerWindowsOfAllDocuments( xModel, bInteractive ); +} + +sal_Bool SAL_CALL VbaApplicationBase::getVisible() +{ + return m_pImpl->mbVisible; // dummy implementation +} + +void SAL_CALL VbaApplicationBase::setVisible( sal_Bool bVisible ) +{ + m_pImpl->mbVisible = bVisible; // dummy implementation +} + +OUString SAL_CALL VbaApplicationBase::getCaption() +{ + SbMethod* pMeth = StarBASIC::GetActiveMethod(); + if (!pMeth) + { + // When called from Automation clients, we don't even try, as there doesn't seem to be any + // good way to get at the actual "caption" (title) of the application's window (any of them, + // if there are several). We just keep a copy of a fake caption in the VbaApplicationBase_Impl. + return m_pImpl->msCaption; + } + + // No idea if this code, which uses APIs that apparently are related to StarBasic (check + // getCurrentDoc() in vbahelper.cxx), actually works any better. + uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_SET_THROW ); + uno::Reference< frame::XFrame > xFrame( xModel->getCurrentController()->getFrame(), uno::UNO_SET_THROW ); + return xFrame->getName(); +} + +void SAL_CALL VbaApplicationBase::setCaption( const OUString& sCaption ) +{ + // See comments in getCaption(). + + SbMethod* pMeth = StarBASIC::GetActiveMethod(); + if (!pMeth) + { + m_pImpl->msCaption = sCaption; + return; + } + + uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_SET_THROW ); + uno::Reference< frame::XFrame > xFrame( xModel->getCurrentController()->getFrame(), uno::UNO_SET_THROW ); + xFrame->setName( sCaption ); +} + +void SAL_CALL +VbaApplicationBase::OnKey( const OUString& Key, const uno::Any& Procedure ) +{ + // parse the Key & modifiers + awt::KeyEvent aKeyEvent = parseKeyEvent( Key ); + OUString MacroName; + Procedure >>= MacroName; + uno::Reference< frame::XModel > xModel; + SbMethod* pMeth = StarBASIC::GetActiveMethod(); + if ( pMeth ) + { + SbModule* pMod = dynamic_cast< SbModule* >( pMeth->GetParent() ); + if ( pMod ) + xModel = StarBASIC::GetModelFromBasic( pMod ); + } + + if ( !xModel.is() ) + xModel = getCurrentDocument(); + + applyShortCutKeyBinding( xModel, aKeyEvent, MacroName ); +} + +uno::Any SAL_CALL +VbaApplicationBase::CommandBars( const uno::Any& aIndex ) +{ + uno::Reference< XCommandBars > xCommandBars( new ScVbaCommandBars( this, mxContext, uno::Reference< container::XIndexAccess >(), getCurrentDocument() ) ); + if( aIndex.hasValue() ) + return xCommandBars->Item( aIndex, uno::Any() ); + return uno::Any( xCommandBars ); +} + +OUString SAL_CALL +VbaApplicationBase::getVersion() +{ + return OFFICEVERSION; +} + +uno::Any SAL_CALL VbaApplicationBase::Run( const OUString& MacroName, const uno::Any& varg1, const uno::Any& varg2, const uno::Any& varg3, const uno::Any& varg4, const uno::Any& varg5, const uno::Any& varg6, const uno::Any& varg7, const uno::Any& varg8, const uno::Any& varg9, const uno::Any& varg10, const uno::Any& varg11, const uno::Any& varg12, const uno::Any& varg13, const uno::Any& varg14, const uno::Any& varg15, const uno::Any& varg16, const uno::Any& varg17, const uno::Any& varg18, const uno::Any& varg19, const uno::Any& varg20, const uno::Any& varg21, const uno::Any& varg22, const uno::Any& varg23, const uno::Any& varg24, const uno::Any& varg25, const uno::Any& varg26, const uno::Any& varg27, const uno::Any& varg28, const uno::Any& varg29, const uno::Any& varg30 ) +{ + OUString aMacroName = MacroName.trim(); + if( aMacroName.startsWith("!") ) + aMacroName = o3tl::trim(aMacroName.subView(1)); + + uno::Reference< frame::XModel > xModel; + SbMethod* pMeth = StarBASIC::GetActiveMethod(); + if ( pMeth ) + { + SbModule* pMod = dynamic_cast< SbModule* >( pMeth->GetParent() ); + if ( pMod ) + xModel = StarBASIC::GetModelFromBasic( pMod ); + } + + if ( !xModel.is() ) + xModel = getCurrentDocument(); + + MacroResolvedInfo aMacroInfo = resolveVBAMacro( getSfxObjShell( xModel ), aMacroName ); + if( !aMacroInfo.mbFound ) + { + throw uno::RuntimeException( "The macro doesn't exist" ); + } + + // handle the arguments + const uno::Any* aArgsPtrArray[] = { &varg1, &varg2, &varg3, &varg4, &varg5, &varg6, &varg7, &varg8, &varg9, &varg10, &varg11, &varg12, &varg13, &varg14, &varg15, &varg16, &varg17, &varg18, &varg19, &varg20, &varg21, &varg22, &varg23, &varg24, &varg25, &varg26, &varg27, &varg28, &varg29, &varg30 }; + + int nArg = SAL_N_ELEMENTS( aArgsPtrArray ); + uno::Sequence< uno::Any > aArgs( nArg ); + auto pArgs = aArgs.getArray(); + + const uno::Any** pArg = aArgsPtrArray; + const uno::Any** pArgEnd = aArgsPtrArray + nArg; + + sal_Int32 nArgProcessed = 0; + + for ( ; pArg != pArgEnd; ++pArg, ++nArgProcessed ) + pArgs[ nArgProcessed ] = **pArg; + + // resize array to position of last param with value + aArgs.realloc( nArgProcessed + 1 ); + + uno::Any aRet; + uno::Any aDummyCaller; + executeMacro( aMacroInfo.mpDocContext, aMacroInfo.msResolvedMacro, aArgs, aRet, aDummyCaller ); + + return aRet; +} + +void SAL_CALL VbaApplicationBase::OnTime( const uno::Any& aEarliestTime, const OUString& aFunction, const uno::Any& aLatestTime, const uno::Any& aSchedule ) +{ + if ( aFunction.isEmpty() ) + throw uno::RuntimeException( "Unexpected function name!" ); + + double nEarliestTime = 0; + double nLatestTime = 0; + if ( !( aEarliestTime >>= nEarliestTime ) + || ( aLatestTime.hasValue() && !( aLatestTime >>= nLatestTime ) ) ) + throw uno::RuntimeException( "Only double is supported as time for now!" ); + + bool bSetTimer = true; + aSchedule >>= bSetTimer; + + VbaTimerInfo aTimerIndex( aFunction, ::std::pair< double, double >( nEarliestTime, nLatestTime ) ); + + VbaTimerHashMap::iterator aIter = m_pImpl->m_aTimerHash.find( aTimerIndex ); + if ( aIter != m_pImpl->m_aTimerHash.end() ) + { + m_pImpl->m_aTimerHash.erase( aIter ); + } + + if ( bSetTimer ) + { + VbaTimer* pTimer = new VbaTimer; + m_pImpl->m_aTimerHash[ aTimerIndex ].reset(pTimer); + pTimer->Start( this, aFunction, nEarliestTime, nLatestTime ); + } +} + +float SAL_CALL VbaApplicationBase::CentimetersToPoints( float Centimeters ) +{ + // i cm = 28.35 points + static const float rate = 28.35f; + return ( Centimeters * rate ); +} + +uno::Any SAL_CALL VbaApplicationBase::getVBE() +{ + try // return empty object on error + { + // "VBE" object does not have a parent, but pass document model to be able to determine application type + uno::Sequence< uno::Any > aArgs{ uno::Any(getCurrentDocument()) }; + uno::Reference< lang::XMultiComponentFactory > xServiceManager( mxContext->getServiceManager(), uno::UNO_SET_THROW ); + uno::Reference< uno::XInterface > xVBE = xServiceManager->createInstanceWithArgumentsAndContext( + "ooo.vba.vbide.VBE" , aArgs, mxContext ); + return uno::Any( xVBE ); + } + catch( const uno::Exception& ) + { + } + return uno::Any(); +} + +OUString +VbaApplicationBase::getServiceImplName() +{ + return "VbaApplicationBase"; +} + +uno::Sequence<OUString> +VbaApplicationBase::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.VbaApplicationBase" + }; + return aServiceNames; +} + +void SAL_CALL VbaApplicationBase::Undo() +{ + uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_SET_THROW ); + dispatchRequests( xModel, ".uno:Undo" ); +} + +void VbaApplicationBase::Quit() +{ + // need to stop basic + SbMethod* pMeth = StarBASIC::GetActiveMethod(); + if ( pMeth ) + { + SbModule* pMod = dynamic_cast< SbModule* >( pMeth->GetParent() ); + if ( pMod ) + { + StarBASIC* pBasic = dynamic_cast< StarBASIC* >( pMod->GetParent() ); + if ( pBasic ) + pBasic->QuitAndExitApplication(); + } + } + else + { + // This is the case of a call from an (OLE) Automation client. + + // TODO: Probably we should just close any document windows open by the "application" + // (Writer or Calc) the call being handled is for. And only then, if no document windows + // are left open, quit the actual LibreOffice application. + Application::PostUserEvent( LINK( &AsyncQuitHandler::instance(), AsyncQuitHandler, OnAsyncQuit ) ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacolorformat.cxx b/vbahelper/source/vbahelper/vbacolorformat.cxx new file mode 100644 index 000000000..56180a98f --- /dev/null +++ b/vbahelper/source/vbahelper/vbacolorformat.cxx @@ -0,0 +1,169 @@ +/* -*- 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 . + */ +#include <com/sun/star/beans/XPropertySet.hpp> +#include "vbacolorformat.hxx" + +using namespace ooo::vba; +using namespace com::sun::star; + +sal_Int32 +MsoColorIndices::getColorIndex( sal_Int32 nIndex ) +{ + const static sal_Int32 COLORINDICES[56] = + { HAPICOLOR_BLACK, HAPICOLOR_WHITE, HAPICOLOR_RED, HAPICOLOR_BRIGHTGREEN, HAPICOLOR_BLUE, HAPICOLOR_YELLOW, HAPICOLOR_PINK, + HAPICOLOR_TURQUOISE, HAPICOLOR_DARKRED, HAPICOLOR_GREEN, HAPICOLOR_DARKBLUE, HAPICOLOR_DARKYELLOW, HAPICOLOR_VIOLET, + HAPICOLOR_TEAL, HAPICOLOR_GRAY_25_PERCENT, HAPICOLOR_GRAY_50_PERCENT, HAPICOLOR_PERIWINCKLE, HAPICOLOR_PLUM, + HAPICOLOR_IVORY, HAPICOLOR_LIGHTTURQUOISE, HAPICOLOR_DARKPRUPLE, HAPICOLOR_CORAL, HAPICOLOR_OCEANBLUE, HAPICOLOR_ICEBLUE, + HAPICOLOR_GREEN, HAPICOLOR_PINK, HAPICOLOR_YELLOW, HAPICOLOR_TURQUOISE, HAPICOLOR_VIOLET, HAPICOLOR_DARKRED, HAPICOLOR_TEAL, + HAPICOLOR_BLUE, HAPICOLOR_SKYBLUE, HAPICOLOR_LIGHTTURQUOISE, HAPICOLOR_LIGHTGREEN, HAPICOLOR_LIGHTYELLOW, HAPICOLOR_PALEBLUE, + HAPICOLOR_ROSE, HAPICOLOR_LAVENDER, HAPICOLOR_TAN, HAPICOLOR_LIGHTBLUE, HAPICOLOR_AQUA, HAPICOLOR_LIME, HAPICOLOR_GOLD, + HAPICOLOR_LIGHTORANGE, HAPICOLOR_ORANGE, HAPICOLOR_BLUEGRAY, HAPICOLOR_GRAY_40_PERCENT, HAPICOLOR_DARKTEAL, + HAPICOLOR_SEAGREEN, HAPICOLOR_NONAME, HAPICOLOR_OLIVEGREEN, HAPICOLOR_BROWN, HAPICOLOR_PLUM, HAPICOLOR_INDIGO, + HAPICOLOR_GRAY_80_PERCENT + }; + return COLORINDICES[nIndex]; +} +ScVbaColorFormat::ScVbaColorFormat( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< XHelperInterface >& xInternalParent, const uno::Reference< drawing::XShape >& xShape, const sal_Int16 nColorFormatType ) : ScVbaColorFormat_BASE( xParent, xContext ), m_nColorFormatType( nColorFormatType ) +{ + m_xPropertySet.set( xShape, uno::UNO_QUERY_THROW ); + m_nFillFormatBackColor = 0; + try + { + uno::Reference< ov::msforms::XFillFormat > xFillFormat( xInternalParent, uno::UNO_QUERY_THROW ); + m_pFillFormat = static_cast<ScVbaFillFormat*>( xFillFormat.get() ); + }catch ( uno::RuntimeException& ) + { + m_pFillFormat = nullptr; + } +} + +// Attribute +sal_Int32 SAL_CALL +ScVbaColorFormat::getRGB() +{ + sal_Int32 nRGB = 0; + switch( m_nColorFormatType ) + { + case ColorFormatType::LINEFORMAT_FORECOLOR: + m_xPropertySet->getPropertyValue( "LineColor" ) >>= nRGB; + break; + case ColorFormatType::LINEFORMAT_BACKCOLOR: + //TODO BackColor not supported + // m_xPropertySet->setPropertyValue("Color", uno::makeAny( nRGB ) ); + break; + case ColorFormatType::FILLFORMAT_FORECOLOR: + m_xPropertySet->getPropertyValue( "FillColor" ) >>= nRGB; + break; + case ColorFormatType::FILLFORMAT_BACKCOLOR: + nRGB = m_nFillFormatBackColor; + break; + default: + throw uno::RuntimeException( "Second parameter of ColorFormat is wrong." ); + } + nRGB = OORGBToXLRGB( Color(ColorTransparency, nRGB) ); + return nRGB; +} + +void SAL_CALL +ScVbaColorFormat::setRGB( sal_Int32 _rgb ) +{ + sal_Int32 nRGB = XLRGBToOORGB( _rgb ); + switch( m_nColorFormatType ) + { + case ColorFormatType::LINEFORMAT_FORECOLOR: + m_xPropertySet->setPropertyValue( "LineColor" , uno::Any( nRGB ) ); + break; + case ColorFormatType::LINEFORMAT_BACKCOLOR: + // TODO BackColor not supported + break; + case ColorFormatType::FILLFORMAT_FORECOLOR: + m_xPropertySet->setPropertyValue( "FillColor" , uno::Any( nRGB ) ); + if( m_pFillFormat ) + { + m_pFillFormat->setForeColorAndInternalStyle(nRGB); + } + break; + case ColorFormatType::FILLFORMAT_BACKCOLOR: + m_nFillFormatBackColor = nRGB; + if( m_pFillFormat ) + { + m_pFillFormat->setForeColorAndInternalStyle(nRGB); + } + break; + default: + throw uno::RuntimeException( "Second parameter of ColorFormat is wrong." ); + } +} + +sal_Int32 SAL_CALL +ScVbaColorFormat::getSchemeColor() +{ + sal_Int32 nColor = getRGB(); + // #TODO I guess the number of elements is determined by the correct scheme + // the implementation here seems to be a rehash of color index ( which seems to be a + // different thing ) - I would guess we need to know/import etc. the correct color scheme + // or at least find out a little more + sal_Int32 i = 0; + for( ; i < 56; i++ ) + { + if( nColor == MsoColorIndices::getColorIndex(i) ) + break; + } + + if( i == 56 ) // this is most likely an error condition + --i; + return i; + // #TODO figure out what craziness is this, + // the 56 colors seems incorrect, as in default XL ( 2003 ) there are 80 colors +/* + if( i == 56 ) + { + i = -2; + } + + return ( i + 2 ); +*/ +} + +void SAL_CALL +ScVbaColorFormat::setSchemeColor( sal_Int32 _schemecolor ) +{ + // the table is 0 based + sal_Int32 nColor = MsoColorIndices::getColorIndex( _schemecolor ); + // nColor is already xl RGB + setRGB( nColor ); +} + +OUString +ScVbaColorFormat::getServiceImplName() +{ + return "ScVbaColorFormat"; +} + +uno::Sequence< OUString > +ScVbaColorFormat::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.msforms.ColorFormat" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacolorformat.hxx b/vbahelper/source/vbahelper/vbacolorformat.hxx new file mode 100644 index 000000000..0e94db6de --- /dev/null +++ b/vbahelper/source/vbahelper/vbacolorformat.hxx @@ -0,0 +1,115 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOLORFORMAT_HXX +#define INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOLORFORMAT_HXX + +#include <com/sun/star/drawing/XShape.hpp> +#include <ooo/vba/msforms/XColorFormat.hpp> +#include <vbahelper/vbahelperinterface.hxx> +#include "vbafillformat.hxx" + +typedef InheritedHelperInterfaceWeakImpl< ov::msforms::XColorFormat > ScVbaColorFormat_BASE; + +class ColorFormatType +{ +public: + const static sal_Int16 LINEFORMAT_FORECOLOR = 1; + const static sal_Int16 LINEFORMAT_BACKCOLOR = 2; + const static sal_Int16 FILLFORMAT_FORECOLOR = 3; + const static sal_Int16 FILLFORMAT_BACKCOLOR = 4; + const static sal_Int16 THREEDFORMAT_EXTRUSIONCOLOR = 5; +}; + +struct MsoColorIndices +{ + const static sal_Int32 HAPICOLOR_BLACK = 0; + const static sal_Int32 HAPICOLOR_WHITE = 16777215; + const static sal_Int32 HAPICOLOR_RED = 16711680; + const static sal_Int32 HAPICOLOR_BRIGHTGREEN = 65280; + const static sal_Int32 HAPICOLOR_BLUE = 255; + const static sal_Int32 HAPICOLOR_YELLOW = 16776960; + const static sal_Int32 HAPICOLOR_PINK = 16711935; + const static sal_Int32 HAPICOLOR_TURQUOISE = 65535; + const static sal_Int32 HAPICOLOR_DARKRED = 8388608; + const static sal_Int32 HAPICOLOR_GREEN = 32768; + const static sal_Int32 HAPICOLOR_DARKBLUE = 128; + const static sal_Int32 HAPICOLOR_DARKYELLOW = 8421376; + const static sal_Int32 HAPICOLOR_VIOLET = 8388736; + const static sal_Int32 HAPICOLOR_TEAL = 32896; + const static sal_Int32 HAPICOLOR_GRAY_25_PERCENT = 12632256; + const static sal_Int32 HAPICOLOR_GRAY_50_PERCENT = 8421504; + const static sal_Int32 HAPICOLOR_PERIWINCKLE = 10066431; + const static sal_Int32 HAPICOLOR_PLUM = 10040166; + const static sal_Int32 HAPICOLOR_IVORY = 16777164; + const static sal_Int32 HAPICOLOR_LIGHTTURQUOISE = 13434879; + const static sal_Int32 HAPICOLOR_DARKPRUPLE = 6684774; + const static sal_Int32 HAPICOLOR_CORAL = 16744576; + const static sal_Int32 HAPICOLOR_OCEANBLUE = 26316; + const static sal_Int32 HAPICOLOR_ICEBLUE = 13421823; + const static sal_Int32 HAPICOLOR_SKYBLUE = 52479; + const static sal_Int32 HAPICOLOR_LIGHTGREEN = 13434828; + const static sal_Int32 HAPICOLOR_LIGHTYELLOW = 16777113; + const static sal_Int32 HAPICOLOR_PALEBLUE = 10079487; + const static sal_Int32 HAPICOLOR_ROSE = 16751052; + const static sal_Int32 HAPICOLOR_LAVENDER = 13408767; + const static sal_Int32 HAPICOLOR_TAN = 16764057; + const static sal_Int32 HAPICOLOR_LIGHTBLUE = 3368703; + const static sal_Int32 HAPICOLOR_AQUA = 3394764; + const static sal_Int32 HAPICOLOR_LIME = 10079232; + const static sal_Int32 HAPICOLOR_GOLD = 16763904; + const static sal_Int32 HAPICOLOR_LIGHTORANGE = 16750848; + const static sal_Int32 HAPICOLOR_ORANGE = 16737792; + const static sal_Int32 HAPICOLOR_BLUEGRAY = 6710937; + const static sal_Int32 HAPICOLOR_GRAY_40_PERCENT = 9868950; + const static sal_Int32 HAPICOLOR_DARKTEAL = 13158; + const static sal_Int32 HAPICOLOR_SEAGREEN = 3381606; + const static sal_Int32 HAPICOLOR_NONAME = 13056; + const static sal_Int32 HAPICOLOR_OLIVEGREEN = 3355392; + const static sal_Int32 HAPICOLOR_BROWN = 10040064; + const static sal_Int32 HAPICOLOR_INDIGO = 3355545; + const static sal_Int32 HAPICOLOR_GRAY_80_PERCENT = 3355443; + + static sal_Int32 getColorIndex( sal_Int32 nIndex ); + +}; + +class ScVbaColorFormat : public ScVbaColorFormat_BASE +{ +private: + css::uno::Reference< css::beans::XPropertySet > m_xPropertySet; + ScVbaFillFormat *m_pFillFormat; + sal_Int16 m_nColorFormatType; + sal_Int32 m_nFillFormatBackColor; +protected: + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; +public: + ScVbaColorFormat( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< ov::XHelperInterface >& xInternalParent, const css::uno::Reference< css::drawing::XShape >& xShape, const sal_Int16 nColorFormatType ); + + // Attributes + virtual sal_Int32 SAL_CALL getRGB() override; + virtual void SAL_CALL setRGB( sal_Int32 _rgb ) override; + virtual sal_Int32 SAL_CALL getSchemeColor() override; + virtual void SAL_CALL setSchemeColor( sal_Int32 _schemecolor ) override; + +}; + +#endif // INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOLORFORMAT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbar.cxx b/vbahelper/source/vbahelper/vbacommandbar.cxx new file mode 100644 index 000000000..ba8f9fe21 --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbar.cxx @@ -0,0 +1,273 @@ +/* -*- 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 . + */ +#include "vbacommandbar.hxx" +#include "vbacommandbarcontrols.hxx" +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <ooo/vba/office/MsoBarType.hpp> +#include <sal/log.hxx> + +using namespace com::sun::star; +using namespace ooo::vba; + +ScVbaCommandBar::ScVbaCommandBar( const uno::Reference< ov::XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext, + VbaCommandBarHelperRef const & pHelper, + const uno::Reference< container::XIndexAccess >& xBarSettings, + const OUString& sResourceUrl, bool bIsMenu ) + : CommandBar_BASE( xParent, xContext ), pCBarHelper( pHelper ), m_xBarSettings( xBarSettings ), m_sResourceUrl( sResourceUrl ), m_bIsMenu( bIsMenu ) +{ +} + +OUString SAL_CALL +ScVbaCommandBar::getName() +{ + // This will get a "NULL length string" when Name is not set. + uno::Reference< beans::XPropertySet > xPropertySet( m_xBarSettings, uno::UNO_QUERY_THROW ); + uno::Any aName = xPropertySet->getPropertyValue( "UIName" ); + OUString sName; + aName >>= sName; + if( sName.isEmpty() ) + { + if( m_bIsMenu ) + { + if( m_sResourceUrl == ITEM_MENUBAR_URL ) + { + if( pCBarHelper->getModuleId() == "com.sun.star.sheet.SpreadsheetDocument" ) + sName = "Worksheet Menu Bar"; + else if( pCBarHelper->getModuleId() == "com.sun.star.text.TextDocument" ) + sName = "Menu Bar"; + return sName; + } + } + // Toolbar name + uno::Reference< container::XNameAccess > xNameAccess = pCBarHelper->getPersistentWindowState(); + if( xNameAccess->hasByName( m_sResourceUrl ) ) + { + uno::Sequence< beans::PropertyValue > aToolBar; + xNameAccess->getByName( m_sResourceUrl ) >>= aToolBar; + getPropertyValue( aToolBar, "UIName" ) >>= sName; + } + } + return sName; +} +void SAL_CALL +ScVbaCommandBar::setName( const OUString& _name ) +{ + uno::Reference< beans::XPropertySet > xPropertySet( m_xBarSettings, uno::UNO_QUERY_THROW ); + xPropertySet->setPropertyValue( "UIName" , uno::Any( _name ) ); + + pCBarHelper->ApplyTempChange( m_sResourceUrl, m_xBarSettings ); +} +sal_Bool SAL_CALL +ScVbaCommandBar::getVisible() +{ + // menu bar is always visible in OOo + if( m_bIsMenu ) + return true; + + bool bVisible = false; + try + { + uno::Reference< container::XNameAccess > xNameAccess = pCBarHelper->getPersistentWindowState(); + if( xNameAccess->hasByName( m_sResourceUrl ) ) + { + uno::Sequence< beans::PropertyValue > aToolBar; + xNameAccess->getByName( m_sResourceUrl ) >>= aToolBar; + getPropertyValue( aToolBar, "Visible" ) >>= bVisible; + } + } + catch (const uno::Exception&) + { + } + return bVisible; +} +void SAL_CALL +ScVbaCommandBar::setVisible( sal_Bool _visible ) +{ + try + { + uno::Reference< frame::XLayoutManager > xLayoutManager = pCBarHelper->getLayoutManager(); + if( _visible ) + { + xLayoutManager->createElement( m_sResourceUrl ); + xLayoutManager->showElement( m_sResourceUrl ); + } + else + { + xLayoutManager->hideElement( m_sResourceUrl ); + xLayoutManager->destroyElement( m_sResourceUrl ); + } + } + catch(const uno::Exception&) + { + SAL_INFO("vbahelper", "SetVisible get an exception" ); + } +} + +sal_Bool SAL_CALL +ScVbaCommandBar::getEnabled() +{ + // emulated with Visible + return getVisible(); +} + +void SAL_CALL +ScVbaCommandBar::setEnabled( sal_Bool _enabled ) +{ + // emulated with Visible + setVisible( _enabled ); +} + +void SAL_CALL +ScVbaCommandBar::Delete( ) +{ + pCBarHelper->removeSettings( m_sResourceUrl ); + uno::Reference< container::XNameContainer > xNameContainer( pCBarHelper->getPersistentWindowState(), uno::UNO_QUERY_THROW ); + if( xNameContainer->hasByName( m_sResourceUrl ) ) + { + xNameContainer->removeByName( m_sResourceUrl ); + } +} +uno::Any SAL_CALL +ScVbaCommandBar::Controls( const uno::Any& aIndex ) +{ + uno::Reference< XCommandBarControls > xCommandBarControls( new ScVbaCommandBarControls( this, mxContext, m_xBarSettings, pCBarHelper, m_xBarSettings, m_sResourceUrl ) ); + if( aIndex.hasValue() ) + { + return xCommandBarControls->Item( aIndex, uno::Any() ); + } + return uno::Any( xCommandBarControls ); +} + +sal_Int32 SAL_CALL +ScVbaCommandBar::Type() +{ + // #FIXME support msoBarTypePopup + sal_Int32 nType + = m_bIsMenu ? office::MsoBarType::msoBarTypeNormal : office::MsoBarType::msoBarTypeMenuBar; + return nType; +} + +uno::Any SAL_CALL +ScVbaCommandBar::FindControl( const uno::Any& /*aType*/, const uno::Any& /*aId*/, const uno::Any& /*aTag*/, const uno::Any& /*aVisible*/, const uno::Any& /*aRecursive*/ ) +{ + // alwayse fail to find control + return uno::Any( uno::Reference< XCommandBarControl > () ); +} + +OUString +ScVbaCommandBar::getServiceImplName() +{ + return "ScVbaCommandBar"; +} + +uno::Sequence<OUString> +ScVbaCommandBar::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.CommandBar" + }; + return aServiceNames; +} + + +VbaDummyCommandBar::VbaDummyCommandBar( + const uno::Reference< ov::XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext, + const OUString& rName ) : + CommandBar_BASE( xParent, xContext ), + maName( rName ) +{ +} + +OUString SAL_CALL VbaDummyCommandBar::getName() +{ + return maName; +} + +void SAL_CALL VbaDummyCommandBar::setName( const OUString& _name ) +{ + maName = _name; +} + +sal_Bool SAL_CALL VbaDummyCommandBar::getVisible() +{ + // #STUB + return true; +} + +void SAL_CALL VbaDummyCommandBar::setVisible( sal_Bool /*_visible*/ ) +{ + // #STUB +} + +sal_Bool SAL_CALL VbaDummyCommandBar::getEnabled() +{ + // emulated with Visible + return getVisible(); +} + +void SAL_CALL VbaDummyCommandBar::setEnabled( sal_Bool _enabled ) +{ + // emulated with Visible + setVisible( _enabled ); +} + +void SAL_CALL VbaDummyCommandBar::Delete( ) +{ + // no-op + // #STUB +} + +uno::Any SAL_CALL VbaDummyCommandBar::Controls( const uno::Any& aIndex ) +{ + uno::Reference< XCommandBarControls > xCommandBarControls( new VbaDummyCommandBarControls( this, mxContext ) ); + if( aIndex.hasValue() ) + return xCommandBarControls->Item( aIndex, uno::Any() ); + return uno::Any( xCommandBarControls ); +} + +sal_Int32 SAL_CALL VbaDummyCommandBar::Type() +{ + return office::MsoBarType::msoBarTypePopup; +} + +uno::Any SAL_CALL VbaDummyCommandBar::FindControl( const uno::Any& /*aType*/, const uno::Any& /*aId*/, const uno::Any& /*aTag*/, const uno::Any& /*aVisible*/, const uno::Any& /*aRecursive*/ ) +{ + return uno::Any( uno::Reference< XCommandBarControl >() ); +} + +OUString VbaDummyCommandBar::getServiceImplName() +{ + return "VbaDummyCommandBar"; +} + +uno::Sequence< OUString > VbaDummyCommandBar::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.CommandBar" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbar.hxx b/vbahelper/source/vbahelper/vbacommandbar.hxx new file mode 100644 index 000000000..8aa9675ad --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbar.hxx @@ -0,0 +1,94 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBAR_HXX +#define INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBAR_HXX + +#include <ooo/vba/XCommandBar.hpp> + +#include <vbahelper/vbahelperinterface.hxx> +#include "vbacommandbarhelper.hxx" + +typedef InheritedHelperInterfaceWeakImpl< ov::XCommandBar > CommandBar_BASE; + +class ScVbaCommandBar : public CommandBar_BASE +{ +private: + VbaCommandBarHelperRef pCBarHelper; + css::uno::Reference< css::container::XIndexAccess > m_xBarSettings; + OUString m_sResourceUrl; + bool m_bIsMenu; + +public: + /// @throws css::uno::RuntimeException + ScVbaCommandBar( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, VbaCommandBarHelperRef const & pHelper, const css::uno::Reference< css::container::XIndexAccess >& xBarSettings, const OUString& sResourceUrl, bool bIsMenu ); + + // Attributes + virtual OUString SAL_CALL getName() override; + virtual void SAL_CALL setName( const OUString& _name ) override; + virtual sal_Bool SAL_CALL getVisible() override; + virtual void SAL_CALL setVisible( sal_Bool _visible ) override; + virtual sal_Bool SAL_CALL getEnabled() override; + virtual void SAL_CALL setEnabled( sal_Bool _enabled ) override; + + // Methods + virtual void SAL_CALL Delete( ) override; + virtual css::uno::Any SAL_CALL Controls( const css::uno::Any& aIndex ) override; + virtual sal_Int32 SAL_CALL Type( ) override; + virtual css::uno::Any SAL_CALL FindControl( const css::uno::Any& aType, const css::uno::Any& aId, const css::uno::Any& aTag, const css::uno::Any& aVisible, const css::uno::Any& aRecursive ) override; + + // XHelperInterface + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; +}; + +/** Dummy command bar implementation. Does nothing but provide its name. */ +class VbaDummyCommandBar : public CommandBar_BASE +{ +public: + /// @throws css::uno::RuntimeException + VbaDummyCommandBar( + const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const OUString& rName ); + + // Attributes + virtual OUString SAL_CALL getName() override; + virtual void SAL_CALL setName( const OUString& _name ) override; + virtual sal_Bool SAL_CALL getVisible() override; + virtual void SAL_CALL setVisible( sal_Bool _visible ) override; + virtual sal_Bool SAL_CALL getEnabled() override; + virtual void SAL_CALL setEnabled( sal_Bool _enabled ) override; + + // Methods + virtual void SAL_CALL Delete( ) override; + virtual css::uno::Any SAL_CALL Controls( const css::uno::Any& aIndex ) override; + virtual sal_Int32 SAL_CALL Type( ) override; + virtual css::uno::Any SAL_CALL FindControl( const css::uno::Any& aType, const css::uno::Any& aId, const css::uno::Any& aTag, const css::uno::Any& aVisible, const css::uno::Any& aRecursive ) override; + + // XHelperInterface + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; + +private: + OUString maName; +}; + +#endif // INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBAR_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbarcontrol.cxx b/vbahelper/source/vbahelper/vbacommandbarcontrol.cxx new file mode 100644 index 000000000..2ab2794e4 --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbarcontrol.cxx @@ -0,0 +1,255 @@ +/* -*- 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 . + */ +#include "vbacommandbarcontrol.hxx" +#include "vbacommandbarcontrols.hxx" +#include <vbahelper/vbahelper.hxx> +#include <filter/msfilter/msvbahelper.hxx> +#include <sal/log.hxx> + +using namespace com::sun::star; +using namespace ooo::vba; + +ScVbaCommandBarControl::ScVbaCommandBarControl( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xSettings, const VbaCommandBarHelperRef& pHelper, const css::uno::Reference< css::container::XIndexAccess >& xBarSettings, const OUString& sResourceUrl ) : CommandBarControl_BASE( xParent, xContext ), pCBarHelper( pHelper ), m_sResourceUrl( sResourceUrl ), m_xCurrentSettings( xSettings ), m_xBarSettings( xBarSettings ), m_nPosition( 0 ) +{ +} + +void ScVbaCommandBarControl::ApplyChange() +{ + uno::Reference< container::XIndexContainer > xIndexContainer( m_xCurrentSettings, uno::UNO_QUERY_THROW ); + xIndexContainer->replaceByIndex( m_nPosition, uno::Any( m_aPropertyValues ) ); + pCBarHelper->ApplyTempChange( m_sResourceUrl, m_xBarSettings ); +} + +OUString SAL_CALL +ScVbaCommandBarControl::getCaption() +{ + // "Label" always empty + OUString sCaption; + getPropertyValue( m_aPropertyValues, "Label" ) >>= sCaption; + return sCaption; +} + +void SAL_CALL +ScVbaCommandBarControl::setCaption( const OUString& _caption ) +{ + OUString sCaption = _caption.replace('&','~'); + setPropertyValue( m_aPropertyValues, "Label" , uno::Any( sCaption ) ); + ApplyChange(); +} + +OUString SAL_CALL +ScVbaCommandBarControl::getOnAction() +{ + OUString sCommandURL; + getPropertyValue( m_aPropertyValues, "CommandURL" ) >>= sCommandURL; + return sCommandURL; +} + +void SAL_CALL +ScVbaCommandBarControl::setOnAction( const OUString& _onaction ) +{ + // get the current model + uno::Reference< frame::XModel > xModel( pCBarHelper->getModel() ); + MacroResolvedInfo aResolvedMacro = ooo::vba::resolveVBAMacro( getSfxObjShell( xModel ), _onaction, true ); + if ( aResolvedMacro.mbFound ) + { + OUString aCommandURL = ooo::vba::makeMacroURL( aResolvedMacro.msResolvedMacro ); + SAL_INFO("vbahelper", "ScVbaCommandBarControl::setOnAction: " << aCommandURL); + setPropertyValue( m_aPropertyValues, "CommandURL" , uno::Any( aCommandURL ) ); + ApplyChange(); + } +} + +sal_Bool SAL_CALL +ScVbaCommandBarControl::getVisible() +{ + bool bVisible = true; + uno::Any aValue = getPropertyValue( m_aPropertyValues, ITEM_DESCRIPTOR_ISVISIBLE ); + if( aValue.hasValue() ) + aValue >>= bVisible; + return bVisible; +} +void SAL_CALL +ScVbaCommandBarControl::setVisible( sal_Bool _visible ) +{ + uno::Any aValue = getPropertyValue( m_aPropertyValues, ITEM_DESCRIPTOR_ISVISIBLE ); + if( aValue.hasValue() ) + { + setPropertyValue( m_aPropertyValues, ITEM_DESCRIPTOR_ISVISIBLE , uno::Any( _visible ) ); + ApplyChange(); + } +} + +sal_Bool SAL_CALL +ScVbaCommandBarControl::getEnabled() +{ + bool bEnabled = true; + + uno::Any aValue = getPropertyValue( m_aPropertyValues, ITEM_DESCRIPTOR_ENABLED ); + if( aValue.hasValue() ) + { + aValue >>= bEnabled; + } + else + { + // emulated with Visible + bEnabled = getVisible(); + } + return bEnabled; +} + +void SAL_CALL +ScVbaCommandBarControl::setEnabled( sal_Bool _enabled ) +{ + uno::Any aValue = getPropertyValue( m_aPropertyValues, ITEM_DESCRIPTOR_ENABLED ); + if( aValue.hasValue() ) + { + setPropertyValue( m_aPropertyValues, ITEM_DESCRIPTOR_ENABLED , uno::Any( _enabled ) ); + ApplyChange(); + } + else + { + // emulated with Visible + setVisible( _enabled ); + } +} + +sal_Bool SAL_CALL +ScVbaCommandBarControl::getBeginGroup() +{ + // TODO: need to check if the item before this item is of type 'separator' + //#STUB + return false; +} + +void SAL_CALL +ScVbaCommandBarControl::setBeginGroup( sal_Bool _begin ) +{ + if( getBeginGroup() != _begin ) + { + // TODO: need to insert or remove an item of type 'separator' before this item + } +} + +void SAL_CALL +ScVbaCommandBarControl::Delete( ) +{ + if( m_xCurrentSettings.is() ) + { + uno::Reference< container::XIndexContainer > xIndexContainer( m_xCurrentSettings, uno::UNO_QUERY_THROW ); + xIndexContainer->removeByIndex( m_nPosition ); + + pCBarHelper->ApplyTempChange( m_sResourceUrl, m_xBarSettings ); + } +} + +uno::Any SAL_CALL +ScVbaCommandBarControl::Controls( const uno::Any& aIndex ) +{ + // only Popup Menu has controls + uno::Reference< container::XIndexAccess > xSubMenu; + getPropertyValue( m_aPropertyValues, ITEM_DESCRIPTOR_CONTAINER ) >>= xSubMenu; + if( !xSubMenu.is() ) + throw uno::RuntimeException(); + + uno::Reference< XCommandBarControls > xCommandBarControls( new ScVbaCommandBarControls( this, mxContext, xSubMenu, pCBarHelper, m_xBarSettings, m_sResourceUrl ) ); + if( aIndex.hasValue() ) + { + return xCommandBarControls->Item( aIndex, uno::Any() ); + } + return uno::Any( xCommandBarControls ); +} + +OUString +ScVbaCommandBarControl::getServiceImplName() +{ + return "ScVbaCommandBarControl"; +} + +uno::Sequence<OUString> +ScVbaCommandBarControl::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.CommandBarControl" + }; + return aServiceNames; +} + +// ScVbaCommandBarPopup +ScVbaCommandBarPopup::ScVbaCommandBarPopup( const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::container::XIndexAccess >& xSettings, + const VbaCommandBarHelperRef& pHelper, + const css::uno::Reference< css::container::XIndexAccess >& xBarSettings, + const OUString& sResourceUrl, + sal_Int32 nPosition ) + : CommandBarPopup_BASE( xParent, xContext, xSettings, pHelper, xBarSettings, sResourceUrl ) +{ + m_nPosition = nPosition; + m_xCurrentSettings->getByIndex( m_nPosition ) >>= m_aPropertyValues; +} + +OUString +ScVbaCommandBarPopup::getServiceImplName() +{ + return "ScVbaCommandBarPopup"; +} + +uno::Sequence<OUString> +ScVbaCommandBarPopup::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.CommandBarPopup" + }; + return aServiceNames; +} + +// ScVbaCommandBarButton +ScVbaCommandBarButton::ScVbaCommandBarButton( const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::container::XIndexAccess >& xSettings, + const VbaCommandBarHelperRef& pHelper, + const css::uno::Reference< css::container::XIndexAccess >& xBarSettings, + const OUString& sResourceUrl, + sal_Int32 nPosition ) + : CommandBarButton_BASE( xParent, xContext, xSettings, pHelper, xBarSettings, sResourceUrl ) +{ + m_nPosition = nPosition; + m_xCurrentSettings->getByIndex( m_nPosition ) >>= m_aPropertyValues; +} + +OUString +ScVbaCommandBarButton::getServiceImplName() +{ + return "ScVbaCommandBarButton"; +} + +uno::Sequence<OUString> +ScVbaCommandBarButton::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.CommandBarButton" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbarcontrol.hxx b/vbahelper/source/vbahelper/vbacommandbarcontrol.hxx new file mode 100644 index 000000000..348518b5b --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbarcontrol.hxx @@ -0,0 +1,111 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARCONTROL_HXX +#define INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARCONTROL_HXX + +#include <ooo/vba/XCommandBarControl.hpp> +#include <ooo/vba/XCommandBarPopup.hpp> +#include <ooo/vba/XCommandBarButton.hpp> +#include <ooo/vba/office/MsoControlType.hpp> +#include <com/sun/star/awt/XMenu.hpp> +#include <vbahelper/vbahelperinterface.hxx> +#include "vbacommandbarhelper.hxx" +#include <cppuhelper/implbase.hxx> + +typedef InheritedHelperInterfaceWeakImpl< ov::XCommandBarControl > CommandBarControl_BASE; + +class ScVbaCommandBarControl : public CommandBarControl_BASE +{ +protected: + VbaCommandBarHelperRef pCBarHelper; + OUString m_sResourceUrl; + css::uno::Reference< css::container::XIndexAccess > m_xCurrentSettings; + css::uno::Reference< css::container::XIndexAccess > m_xBarSettings; + css::uno::Sequence< css::beans::PropertyValue > m_aPropertyValues; + + sal_Int32 m_nPosition; + +private: + /// @throws css::uno::RuntimeException + void ApplyChange(); + +public: + /// @throws css::uno::RuntimeException + ScVbaCommandBarControl( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xSettings, const VbaCommandBarHelperRef& pHelper, const css::uno::Reference< css::container::XIndexAccess >& xBarSettings, const OUString& sResourceUrl ); + + // Attributes + virtual OUString SAL_CALL getCaption() override; + virtual void SAL_CALL setCaption( const OUString& _caption ) override; + virtual OUString SAL_CALL getOnAction() override; + virtual void SAL_CALL setOnAction( const OUString& _onaction ) override; + virtual sal_Bool SAL_CALL getVisible() override; + virtual void SAL_CALL setVisible( sal_Bool _visible ) override; + virtual sal_Bool SAL_CALL getEnabled() override; + virtual void SAL_CALL setEnabled( sal_Bool _enabled ) override; + virtual sal_Bool SAL_CALL getBeginGroup() override; + virtual void SAL_CALL setBeginGroup( sal_Bool _begin ) override; + virtual sal_Int32 SAL_CALL getType() override + { + return ov::office::MsoControlType::msoControlButton; + } + + // Methods + virtual void SAL_CALL Delete( ) override; + virtual css::uno::Any SAL_CALL Controls( const css::uno::Any& aIndex ) override; + + // XHelperInterface + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; +}; + +typedef cppu::ImplInheritanceHelper< ScVbaCommandBarControl, ov::XCommandBarPopup > CommandBarPopup_BASE; +class ScVbaCommandBarPopup : public CommandBarPopup_BASE +{ +public: + /// @throws css::uno::RuntimeException + ScVbaCommandBarPopup( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xSettings, const VbaCommandBarHelperRef& pHelper, const css::uno::Reference< css::container::XIndexAccess >& xBarSettings, const OUString& sResourceUrl, sal_Int32 nPosition ); + + virtual sal_Int32 SAL_CALL getType() override + { + return ov::office::MsoControlType::msoControlPopup; + } + // XHelperInterface + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; +}; + +typedef cppu::ImplInheritanceHelper< ScVbaCommandBarControl, ov::XCommandBarButton > CommandBarButton_BASE; +class ScVbaCommandBarButton : public CommandBarButton_BASE +{ +public: + /// @throws css::uno::RuntimeException + ScVbaCommandBarButton( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xSettings, const VbaCommandBarHelperRef& pHelper, const css::uno::Reference< css::container::XIndexAccess >& xBarSettings, const OUString& sResourceUrl, sal_Int32 nPosition ); + + virtual sal_Int32 SAL_CALL getType() override + { + return ov::office::MsoControlType::msoControlButton; + } + // XHelperInterface + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; +}; + +#endif // INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARCONTROL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbarcontrols.cxx b/vbahelper/source/vbahelper/vbacommandbarcontrols.cxx new file mode 100644 index 000000000..27f2d5088 --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbarcontrols.cxx @@ -0,0 +1,308 @@ +/* -*- 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 . + */ +#include "vbacommandbarcontrols.hxx" +#include "vbacommandbarcontrol.hxx" +#include <com/sun/star/lang/XSingleComponentFactory.hpp> + +#include <comphelper/propertyvalue.hxx> +#include <rtl/ref.hxx> + +using namespace com::sun::star; +using namespace ooo::vba; + +namespace { + +class CommandBarControlEnumeration : public ::cppu::WeakImplHelper< container::XEnumeration > +{ + //uno::Reference< uno::XComponentContext > m_xContext; + CommandBarControls_BASE* m_pCommandBarControls; + sal_Int32 m_nCurrentPosition; +public: + explicit CommandBarControlEnumeration( CommandBarControls_BASE* pCommandBarControls ) : m_pCommandBarControls( pCommandBarControls ), m_nCurrentPosition( 0 ) {} + virtual sal_Bool SAL_CALL hasMoreElements() override + { + if( m_nCurrentPosition < m_pCommandBarControls->getCount() ) + return true; + return false; + } + virtual uno::Any SAL_CALL nextElement() override + { + if( !hasMoreElements() ) + throw container::NoSuchElementException(); + + return m_pCommandBarControls->createCollectionObject( uno::Any( m_nCurrentPosition++ ) ); + } +}; + +} + +ScVbaCommandBarControls::ScVbaCommandBarControls( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XIndexAccess>& xIndexAccess, VbaCommandBarHelperRef const & pHelper, const uno::Reference< container::XIndexAccess>& xBarSettings, const OUString& sResourceUrl ) : CommandBarControls_BASE( xParent, xContext, xIndexAccess ), pCBarHelper( pHelper ), m_xBarSettings( xBarSettings ), m_sResourceUrl( sResourceUrl ) +{ + m_bIsMenu = sResourceUrl == ITEM_MENUBAR_URL; +} + +uno::Sequence< beans::PropertyValue > ScVbaCommandBarControls::CreateMenuItemData( const OUString& sCommandURL, + const OUString& sHelpURL, + const OUString& sLabel, + sal_uInt16 nType, + const uno::Any& aSubMenu, + bool isVisible, + bool isEnabled ) +{ + uno::Sequence< beans::PropertyValue > aProps{ + comphelper::makePropertyValue(ITEM_DESCRIPTOR_COMMANDURL, sCommandURL), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_HELPURL, sHelpURL), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_LABEL, sLabel), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_TYPE, nType), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_CONTAINER, aSubMenu), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_ISVISIBLE, isVisible), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_ENABLED, isEnabled) + }; + + return aProps; +} + +uno::Sequence< beans::PropertyValue > ScVbaCommandBarControls::CreateToolbarItemData( const OUString& sCommandURL, + const OUString& sHelpURL, + const OUString& sLabel, + sal_uInt16 nType, + const uno::Any& aSubMenu, + bool isVisible, + sal_Int32 nStyle ) +{ + uno::Sequence< beans::PropertyValue > aProps{ + comphelper::makePropertyValue(ITEM_DESCRIPTOR_COMMANDURL, sCommandURL), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_HELPURL, sHelpURL), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_LABEL, sLabel), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_TYPE, nType), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_CONTAINER, aSubMenu), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_ISVISIBLE, isVisible), + comphelper::makePropertyValue(ITEM_DESCRIPTOR_STYLE, nStyle) + }; + + return aProps; +} + +// XEnumerationAccess +uno::Type SAL_CALL +ScVbaCommandBarControls::getElementType() +{ + return cppu::UnoType<XCommandBarControl>::get(); +} + +uno::Reference< container::XEnumeration > +ScVbaCommandBarControls::createEnumeration() +{ + return uno::Reference< container::XEnumeration >( new CommandBarControlEnumeration( this ) ); +} + +uno::Any +ScVbaCommandBarControls::createCollectionObject( const uno::Any& aSource ) +{ + sal_Int32 nPosition = -1; + aSource >>= nPosition; + uno::Sequence< beans::PropertyValue > aProps; + m_xIndexAccess->getByIndex( nPosition ) >>= aProps; + uno::Reference< container::XIndexAccess > xSubMenu; + getPropertyValue( aProps, ITEM_DESCRIPTOR_CONTAINER ) >>= xSubMenu; + rtl::Reference<ScVbaCommandBarControl> pNewCommandBarControl; + if( xSubMenu.is() ) + pNewCommandBarControl = new ScVbaCommandBarPopup( this, mxContext, m_xIndexAccess, pCBarHelper, m_xBarSettings, m_sResourceUrl, nPosition ); + else + pNewCommandBarControl = new ScVbaCommandBarButton( this, mxContext, m_xIndexAccess, pCBarHelper, m_xBarSettings, m_sResourceUrl, nPosition ); + + return uno::Any( uno::Reference< XCommandBarControl > ( pNewCommandBarControl ) ); +} + +// Methods +uno::Any SAL_CALL +ScVbaCommandBarControls::Item( const uno::Any& aIndex, const uno::Any& /*aIndex*/ ) +{ + sal_Int32 nPosition = -1; + if( aIndex.getValueTypeClass() == uno::TypeClass_STRING ) + { + OUString sName; + aIndex >>= sName; + nPosition = VbaCommandBarHelper::findControlByName( m_xIndexAccess, sName, m_bIsMenu ); + } + else + { + aIndex >>= nPosition; + } + + if( nPosition < 0 || nPosition >= getCount() ) + { + throw uno::RuntimeException(); + } + + return createCollectionObject( uno::Any( nPosition ) ); +} + +uno::Reference< XCommandBarControl > SAL_CALL +ScVbaCommandBarControls::Add( const uno::Any& Type, const uno::Any& Id, const uno::Any& Parameter, const uno::Any& Before, SAL_UNUSED_PARAMETER const uno::Any& ) +{ + // Parameter is not supported + // the following name needs to be individually created; + OUString sLabel("Custom"); + OUString sCommandUrl( CUSTOM_MENU_STR + sLabel); + sal_Int32 nType = office::MsoControlType::msoControlButton; + sal_Int32 nPosition = 0; + + if( Type.hasValue() ) + { + Type >>= nType; + } + + if( nType != office::MsoControlType::msoControlButton && + nType != office::MsoControlType::msoControlPopup ) + throw uno::RuntimeException( "Not implemented" ); + + if( Id.hasValue() || Parameter.hasValue( ) ) + { + throw uno::RuntimeException( "Not implemented" ); + } + + if( Before.hasValue() ) + Before >>= nPosition; + else + nPosition = m_xIndexAccess->getCount(); + + uno::Any aSubMenu; + if( nType == office::MsoControlType::msoControlPopup ) + { + // it is a Popmenu + uno::Reference< lang::XSingleComponentFactory > xSCF( m_xBarSettings, uno::UNO_QUERY_THROW ); + aSubMenu <<= xSCF->createInstanceWithContext( mxContext ); + } + + // create control + uno::Sequence< beans::PropertyValue > aProps; + sal_uInt16 nItemType = 0; + if( m_bIsMenu ) + { + aProps = CreateMenuItemData( sCommandUrl, "", sLabel, nItemType, aSubMenu, true, true ); + } + else + { + aProps = CreateToolbarItemData( sCommandUrl, "", sLabel, nItemType, aSubMenu, true/*isVisible*/, 0/*nStyle*/ ); + } + + + uno::Reference< container::XIndexContainer > xIndexContainer( m_xIndexAccess, uno::UNO_QUERY_THROW ); + xIndexContainer->insertByIndex( nPosition, uno::Any( aProps ) ); + + pCBarHelper->ApplyTempChange( m_sResourceUrl, m_xBarSettings ); + + rtl::Reference<ScVbaCommandBarControl> pNewCommandBarControl; + if( nType == office::MsoControlType::msoControlPopup ) + pNewCommandBarControl = new ScVbaCommandBarPopup( this, mxContext, m_xIndexAccess, pCBarHelper, m_xBarSettings, m_sResourceUrl, nPosition ); + else + pNewCommandBarControl = new ScVbaCommandBarButton( this, mxContext, m_xIndexAccess, pCBarHelper, m_xBarSettings, m_sResourceUrl, nPosition ); + + return pNewCommandBarControl; +} + +// XHelperInterface +OUString +ScVbaCommandBarControls::getServiceImplName() +{ + return "ScVbaCommandBarControls"; +} + +uno::Sequence<OUString> +ScVbaCommandBarControls::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.CommandBarControls" + }; + return aServiceNames; +} + +namespace { + +class VbaDummyIndexAccess : public ::cppu::WeakImplHelper< container::XIndexAccess > +{ +public: + VbaDummyIndexAccess() {} + // XIndexAccess + virtual ::sal_Int32 SAL_CALL getCount( ) override + { return 0; } + virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 /*Index*/ ) override + { throw lang::IndexOutOfBoundsException(); } + // XElementAccess + virtual uno::Type SAL_CALL getElementType( ) override + { return cppu::UnoType<XCommandBarControl>::get(); } + virtual sal_Bool SAL_CALL hasElements( ) override + { return false; } +}; + +} + +VbaDummyCommandBarControls::VbaDummyCommandBarControls( + const uno::Reference< XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext ) : + CommandBarControls_BASE( xParent, xContext, new VbaDummyIndexAccess ) +{ +} + +// XEnumerationAccess +uno::Type SAL_CALL VbaDummyCommandBarControls::getElementType() +{ + return cppu::UnoType<XCommandBarControl>::get(); +} + +uno::Reference< container::XEnumeration > VbaDummyCommandBarControls::createEnumeration() +{ + return uno::Reference< container::XEnumeration >( new CommandBarControlEnumeration( this ) ); +} + +uno::Any VbaDummyCommandBarControls::createCollectionObject( const uno::Any& /*aSource*/ ) +{ + return uno::Any( uno::Reference< XCommandBarControl >() ); +} + +// Methods +uno::Any SAL_CALL VbaDummyCommandBarControls::Item( const uno::Any& /*aIndex*/, const uno::Any& /*aIndex*/ ) +{ + return uno::Any( uno::Reference< XCommandBarControl >() ); +} + +uno::Reference< XCommandBarControl > SAL_CALL VbaDummyCommandBarControls::Add( + const uno::Any& /*Type*/, const uno::Any& /*Id*/, const uno::Any& /*Parameter*/, const uno::Any& /*Before*/, const uno::Any& /*Temporary*/ ) +{ + return uno::Reference< XCommandBarControl >(); +} + +// XHelperInterface +OUString VbaDummyCommandBarControls::getServiceImplName() +{ + return "VbaDummyCommandBarControls"; +} + +uno::Sequence<OUString> VbaDummyCommandBarControls::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.CommandBarControls" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbarcontrols.hxx b/vbahelper/source/vbahelper/vbacommandbarcontrols.hxx new file mode 100644 index 000000000..5e86b359f --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbarcontrols.hxx @@ -0,0 +1,85 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARCONTROLS_HXX +#define INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARCONTROLS_HXX + +#include <ooo/vba/XCommandBarControls.hpp> +#include <vbahelper/vbacollectionimpl.hxx> +#include "vbacommandbarhelper.hxx" + +typedef CollTestImplHelper< ov::XCommandBarControls > CommandBarControls_BASE; + +class ScVbaCommandBarControls : public CommandBarControls_BASE +{ +private: + VbaCommandBarHelperRef pCBarHelper; + css::uno::Reference< css::container::XIndexAccess > m_xBarSettings; + OUString m_sResourceUrl; + bool m_bIsMenu; + + static css::uno::Sequence< css::beans::PropertyValue > CreateMenuItemData( const OUString& sCommandURL, + const OUString& sHelpURL, + const OUString& sLabel, + sal_uInt16 nType, + const css::uno::Any& aSubMenu, + bool isVisible, + bool isEnabled ); + static css::uno::Sequence< css::beans::PropertyValue > CreateToolbarItemData( const OUString& sCommandURL, const OUString& sHelpURL, const OUString& sLabel, sal_uInt16 nType, const css::uno::Any& aSubMenu, bool isVisible, sal_Int32 nStyle ); + +public: + /// @throws css::uno::RuntimeException + ScVbaCommandBarControls( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess, VbaCommandBarHelperRef const & pHelper, const css::uno::Reference< css::container::XIndexAccess >& xBarSettings, const OUString& sResourceUrl ); + + // XEnumerationAccess + virtual css::uno::Type SAL_CALL getElementType() override; + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override; + virtual css::uno::Any createCollectionObject( const css::uno::Any& aSource ) override; + + // Methods + virtual css::uno::Any SAL_CALL Item( const css::uno::Any& Index, const css::uno::Any& /*Index2*/ ) override; + virtual css::uno::Reference< ov::XCommandBarControl > SAL_CALL Add( const css::uno::Any& Type, const css::uno::Any& Id, const css::uno::Any& Parameter, const css::uno::Any& Before, const css::uno::Any& Temporary ) override; + // XHelperInterface + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; +}; + +class VbaDummyCommandBarControls : public CommandBarControls_BASE +{ +public: + /// @throws css::uno::RuntimeException + VbaDummyCommandBarControls( + const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext ); + + // XEnumerationAccess + virtual css::uno::Type SAL_CALL getElementType() override; + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override; + virtual css::uno::Any createCollectionObject( const css::uno::Any& aSource ) override; + + // Methods + virtual css::uno::Any SAL_CALL Item( const css::uno::Any& Index, const css::uno::Any& /*Index2*/ ) override; + virtual css::uno::Reference< ov::XCommandBarControl > SAL_CALL Add( const css::uno::Any& Type, const css::uno::Any& Id, const css::uno::Any& Parameter, const css::uno::Any& Before, const css::uno::Any& Temporary ) override; + // XHelperInterface + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; +}; + +#endif // INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARCONTROLS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbarhelper.cxx b/vbahelper/source/vbahelper/vbacommandbarhelper.cxx new file mode 100644 index 000000000..fdc2fee94 --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbarhelper.cxx @@ -0,0 +1,244 @@ +/* -*- 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 . + */ +#include "vbacommandbarhelper.hxx" +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/theWindowStateConfiguration.hpp> +#include <comphelper/random.hxx> +#include <vbahelper/vbahelper.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> +#include <o3tl/string_view.hxx> +#include <map> +#include <string_view> + +using namespace com::sun::star; +using namespace ooo::vba; + +typedef std::map< OUString, OUString > MSO2OOCommandbarMap; + +namespace { + +class MSO2OOCommandbarHelper final +{ +private: + static MSO2OOCommandbarHelper* pMSO2OOCommandbarHelper; + MSO2OOCommandbarMap maBuildinToolbarMap; + + MSO2OOCommandbarHelper() + { + // Buildin toolbars + maBuildinToolbarMap.insert( std::make_pair( OUString("Standard") , OUString("private:resource/toolbar/standardbar" ) ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("Formatting"), OUString("private:resource/toolbar/formatobjectbar") ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("Drawing"), OUString("private:resource/toolbar/drawbar") ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("Toolbar List"), OUString("private:resource/toolbar/toolbar") ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("Forms"), OUString("private:resource/toolbar/formcontrols") ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("Form Controls"),OUString("private:resource/toolbar/formcontrols") ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("Full Screen"), OUString("private:resource/toolbar/fullscreenbar") ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("Chart"), OUString("private:resource/toolbar/flowchartshapes") ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("Picture"), OUString("private:resource/toolbar/graphicobjectbar") ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("WordArt"), OUString("private:resource/toolbar/fontworkobjectbar") ) ); + maBuildinToolbarMap.insert( std::make_pair( OUString("3-D Settings"), OUString("private:resource/toolbar/extrusionobjectbar") ) ); + } + +public: + static MSO2OOCommandbarHelper* getMSO2OOCommandbarHelper() + { + if( pMSO2OOCommandbarHelper == nullptr ) + { + pMSO2OOCommandbarHelper = new MSO2OOCommandbarHelper(); + } + return pMSO2OOCommandbarHelper; + } + + OUString findBuildinToolbar( const OUString& sToolbarName ) + { + auto it = std::find_if(maBuildinToolbarMap.begin(), maBuildinToolbarMap.end(), + [&sToolbarName](const MSO2OOCommandbarMap::value_type& rItem) { return rItem.first.equalsIgnoreAsciiCase( sToolbarName ); }); + if( it != maBuildinToolbarMap.end() ) + return it->second; + return OUString(); + } +}; + +} + +MSO2OOCommandbarHelper* MSO2OOCommandbarHelper::pMSO2OOCommandbarHelper = nullptr; + + +VbaCommandBarHelper::VbaCommandBarHelper( const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::frame::XModel >& xModel ) : mxContext( xContext ), mxModel( xModel ) +{ + Init(); +} + +void VbaCommandBarHelper::Init( ) +{ + uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUICfgSupplier( mxModel, uno::UNO_QUERY_THROW ); + m_xDocCfgMgr = xUICfgSupplier->getUIConfigurationManager(); + + uno::Reference< lang::XServiceInfo > xServiceInfo( mxModel, uno::UNO_QUERY_THROW ); + if( xServiceInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) ) + { + maModuleId = "com.sun.star.sheet.SpreadsheetDocument"; + } + else if( xServiceInfo->supportsService( "com.sun.star.text.TextDocument" ) ) + { + maModuleId = "com.sun.star.text.TextDocument"; + } + + if( maModuleId.isEmpty() ) + { + throw uno::RuntimeException( "Not implemented" ); + } + + css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUICfgMgrSupp( + css::ui::theModuleUIConfigurationManagerSupplier::get(mxContext) ); + + m_xAppCfgMgr.set( xUICfgMgrSupp->getUIConfigurationManager( maModuleId ), uno::UNO_SET_THROW ); + + css::uno::Reference< css::container::XNameAccess > xNameAccess = css::ui::theWindowStateConfiguration::get( mxContext ); + + m_xWindowState.set( xNameAccess->getByName( maModuleId ), uno::UNO_QUERY_THROW ); +} + +css::uno::Reference< css::container::XIndexAccess > VbaCommandBarHelper::getSettings( const OUString& sResourceUrl ) +{ + if( m_xDocCfgMgr->hasSettings( sResourceUrl ) ) + return m_xDocCfgMgr->getSettings( sResourceUrl, true ); + else if( m_xAppCfgMgr->hasSettings( sResourceUrl ) ) + return m_xAppCfgMgr->getSettings( sResourceUrl, true ); + else + { + css::uno::Reference< css::container::XIndexAccess > xSettings( m_xAppCfgMgr->createSettings( ), uno::UNO_QUERY_THROW ); + return xSettings; + } +} + +void VbaCommandBarHelper::removeSettings( const OUString& sResourceUrl ) +{ + if( m_xDocCfgMgr->hasSettings( sResourceUrl ) ) + m_xDocCfgMgr->removeSettings( sResourceUrl ); + else if( m_xAppCfgMgr->hasSettings( sResourceUrl ) ) + m_xAppCfgMgr->removeSettings( sResourceUrl ); + + // persistChanges(); +} + +void VbaCommandBarHelper::ApplyTempChange( const OUString& sResourceUrl, const css::uno::Reference< css::container::XIndexAccess >& xSettings ) +{ + if( m_xDocCfgMgr->hasSettings( sResourceUrl ) ) + { + m_xDocCfgMgr->replaceSettings( sResourceUrl, xSettings ); + } + else + { + m_xDocCfgMgr->insertSettings( sResourceUrl, xSettings ); + } +} + +uno::Reference< frame::XLayoutManager > VbaCommandBarHelper::getLayoutManager() const +{ + uno::Reference< frame::XFrame > xFrame( getModel()->getCurrentController()->getFrame(), uno::UNO_SET_THROW ); + uno::Reference< beans::XPropertySet > xPropertySet( xFrame, uno::UNO_QUERY_THROW ); + uno::Reference< frame::XLayoutManager > xLayoutManager( xPropertySet->getPropertyValue( "LayoutManager" ), uno::UNO_QUERY_THROW ); + return xLayoutManager; +} + +bool VbaCommandBarHelper::hasToolbar( const OUString& sResourceUrl, std::u16string_view sName ) +{ + if( m_xDocCfgMgr->hasSettings( sResourceUrl ) ) + { + OUString sUIName; + uno::Reference< beans::XPropertySet > xPropertySet( m_xDocCfgMgr->getSettings( sResourceUrl, false ), uno::UNO_QUERY_THROW ); + xPropertySet->getPropertyValue( ITEM_DESCRIPTOR_UINAME ) >>= sUIName; + if( o3tl::equalsIgnoreAsciiCase( sName, sUIName ) ) + return true; + } + return false; +} + +// return the resource url if found +OUString VbaCommandBarHelper::findToolbarByName( const css::uno::Reference< css::container::XNameAccess >& xNameAccess, const OUString& sName ) +{ + // check if it is a buildin toolbar + OUString sResourceUrl = MSO2OOCommandbarHelper::getMSO2OOCommandbarHelper()->findBuildinToolbar( sName ); + if( !sResourceUrl.isEmpty() ) + return sResourceUrl; + + const uno::Sequence< OUString > allNames = xNameAccess->getElementNames(); + auto pName = std::find_if(allNames.begin(), allNames.end(), + [this, &sName](const OUString& rName) { + return rName.startsWith( ITEM_TOOLBAR_URL ) + && hasToolbar( rName, sName ); + }); + if (pName != allNames.end()) + return *pName; + + // the customize toolbars creating during importing, should found there. + sResourceUrl = "private:resource/toolbar/custom_" + sName; + if( hasToolbar( sResourceUrl, sName ) ) + return sResourceUrl; + + return OUString(); +} + +// if found, return the position of the control. if not found, return -1 +sal_Int32 VbaCommandBarHelper::findControlByName( const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess, std::u16string_view sName, bool bMenu ) +{ + sal_Int32 nCount = xIndexAccess->getCount(); + css::uno::Sequence< css::beans::PropertyValue > aProps; + for( sal_Int32 i = 0; i < nCount; i++ ) + { + OUString sLabel; + xIndexAccess->getByIndex( i ) >>= aProps; + getPropertyValue( aProps, ITEM_DESCRIPTOR_LABEL ) >>= sLabel; + // handle the hotkey marker '~' (remove in toolbars (?), replace by '&' in menus) + OUStringBuffer aBuffer; + sal_Int32 index = sLabel.indexOf( '~' ); + if( index < 0 ) + { + aBuffer = sLabel; + } + else + { + aBuffer.append( sLabel.subView(0, index) ); + if( bMenu ) + aBuffer.append( '&' ); + aBuffer.append( sLabel.subView(index + 1) ); + } + OUString sNewLabel = aBuffer.makeStringAndClear(); + SAL_INFO("vbahelper", "VbaCommandBarHelper::findControlByName, control name: " << sNewLabel); + if( o3tl::equalsIgnoreAsciiCase( sName, sNewLabel ) ) + return i; + } + + // not found + return -1; +} + +OUString VbaCommandBarHelper::generateCustomURL() +{ + return OUString::Concat(ITEM_TOOLBAR_URL) + CUSTOM_TOOLBAR_STR + + // use a random number to minimize possible clash with existing custom toolbars + OUString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max()), 16); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbarhelper.hxx b/vbahelper/source/vbahelper/vbacommandbarhelper.hxx new file mode 100644 index 000000000..774ec4839 --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbarhelper.hxx @@ -0,0 +1,94 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARHELPER_HXX +#define INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARHELPER_HXX + +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/ui/XUIConfigurationManager.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <memory> + +inline constexpr OUStringLiteral ITEM_DESCRIPTOR_COMMANDURL = u"CommandURL"; +inline constexpr OUStringLiteral ITEM_DESCRIPTOR_HELPURL = u"HelpURL"; +inline constexpr OUStringLiteral ITEM_DESCRIPTOR_CONTAINER = u"ItemDescriptorContainer"; +inline constexpr OUStringLiteral ITEM_DESCRIPTOR_LABEL = u"Label"; +inline constexpr OUStringLiteral ITEM_DESCRIPTOR_TYPE = u"Type"; +inline constexpr OUStringLiteral ITEM_DESCRIPTOR_STYLE = u"Style"; +inline constexpr OUStringLiteral ITEM_DESCRIPTOR_ISVISIBLE = u"IsVisible"; +inline constexpr OUStringLiteral ITEM_DESCRIPTOR_UINAME = u"UIName"; +inline constexpr OUStringLiteral ITEM_DESCRIPTOR_ENABLED = u"Enabled"; + +inline constexpr OUStringLiteral ITEM_MENUBAR_URL = u"private:resource/menubar/menubar"; +constexpr char16_t ITEM_TOOLBAR_URL[] = u"private:resource/toolbar/"; + +inline constexpr OUStringLiteral CUSTOM_TOOLBAR_STR = u"custom_toolbar_"; +inline constexpr OUStringLiteral CUSTOM_MENU_STR = u"vnd.openoffice.org:CustomMenu"; + +class VbaCommandBarHelper; +typedef std::shared_ptr< VbaCommandBarHelper > VbaCommandBarHelperRef; + +class VbaCommandBarHelper +{ +private: + css::uno::Reference< css::uno::XComponentContext > mxContext; + css::uno::Reference< css::frame::XModel > mxModel; + css::uno::Reference< css::ui::XUIConfigurationManager > m_xDocCfgMgr; // current document + css::uno::Reference< css::ui::XUIConfigurationManager > m_xAppCfgMgr; + css::uno::Reference< css::container::XNameAccess > m_xWindowState; + OUString maModuleId; + + /// @throws css::uno::RuntimeException + void Init(); + /// @throws css::uno::RuntimeException + bool hasToolbar( const OUString& sResourceUrl, std::u16string_view sName ); +public: + /// @throws css::uno::RuntimeException + VbaCommandBarHelper( const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::frame::XModel >& xModel ); + + const css::uno::Reference< css::frame::XModel >& getModel() const { return mxModel; } + + /// @throws css::uno::RuntimeException + const css::uno::Reference< css::container::XNameAccess >& getPersistentWindowState() const + { + return m_xWindowState; + } + /// @throws css::uno::RuntimeException + css::uno::Reference< css::container::XIndexAccess > getSettings( const OUString& sResourceUrl ); + /// @throws css::uno::RuntimeException + void removeSettings( const OUString& sResourceUrl ); + /// @throws css::uno::RuntimeException + void ApplyTempChange( const OUString& sResourceUrl, const css::uno::Reference< css::container::XIndexAccess >& xSettings); + + /// @throws css::uno::RuntimeException + css::uno::Reference< css::frame::XLayoutManager > getLayoutManager() const; + + const OUString& getModuleId() const { return maModuleId; } + /// @throws css::uno::RuntimeException + OUString findToolbarByName( const css::uno::Reference< css::container::XNameAccess >& xNameAccess, const OUString& sName ); + /// @throws css::uno::RuntimeException + static sal_Int32 findControlByName( const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess, std::u16string_view sName, bool bMenu ); + static OUString generateCustomURL(); +}; + +#endif // INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbars.cxx b/vbahelper/source/vbahelper/vbacommandbars.cxx new file mode 100644 index 000000000..0ee8eaccf --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbars.cxx @@ -0,0 +1,235 @@ +/* -*- 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 . + */ + +#include <com/sun/star/container/XNameAccess.hpp> +#include <ooo/vba/office/MsoBarType.hpp> +#include <cppuhelper/implbase.hxx> + +#include "vbacommandbars.hxx" +#include "vbacommandbar.hxx" + +using namespace com::sun::star; +using namespace ooo::vba; + +namespace { + +class CommandBarEnumeration : public ::cppu::WeakImplHelper< container::XEnumeration > +{ + uno::Reference< XHelperInterface > m_xParent; + uno::Reference< uno::XComponentContext > m_xContext; + VbaCommandBarHelperRef m_pCBarHelper; + uno::Sequence< OUString > m_sNames; + sal_Int32 m_nCurrentPosition; +public: + /// @throws uno::RuntimeException + CommandBarEnumeration( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const VbaCommandBarHelperRef& pHelper) : m_xParent( xParent ), m_xContext( xContext ), m_pCBarHelper( pHelper ) , m_nCurrentPosition( 0 ) + { + uno::Reference< container::XNameAccess > xNameAccess = m_pCBarHelper->getPersistentWindowState(); + m_sNames = xNameAccess->getElementNames(); + } + virtual sal_Bool SAL_CALL hasMoreElements() override + { + return m_nCurrentPosition < m_sNames.getLength(); + } + virtual uno::Any SAL_CALL nextElement() override + { + // FIXME: should be add menubar + if( !hasMoreElements() ) + throw container::NoSuchElementException(); + + OUString sResourceUrl( m_sNames[ m_nCurrentPosition++ ] ); + if( sResourceUrl.indexOf( "private:resource/toolbar/" ) != -1 ) + { + uno::Reference< container::XIndexAccess > xCBarSetting = m_pCBarHelper->getSettings( sResourceUrl ); + uno::Reference< XCommandBar > xCommandBar( new ScVbaCommandBar( m_xParent, m_xContext, m_pCBarHelper, xCBarSetting, sResourceUrl, false ) ); + // Strange, shouldn't the Enumeration support match/share the + // iteration code? ( e.g. ScVbaCommandBars::Item(...) ) + // and we at least should return here ( something ) it seems + return uno::Any( xCommandBar ); + } + else + return nextElement(); + } +}; + +} + +ScVbaCommandBars::ScVbaCommandBars( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XIndexAccess >& xIndexAccess, const uno::Reference< frame::XModel >& xModel ) : CommandBars_BASE( xParent, xContext, xIndexAccess ) +{ + m_pCBarHelper = std::make_shared<VbaCommandBarHelper>( mxContext, xModel ); + m_xNameAccess = m_pCBarHelper->getPersistentWindowState(); +} + +ScVbaCommandBars::~ScVbaCommandBars() +{ +} + +// XEnumerationAccess +uno::Type SAL_CALL +ScVbaCommandBars::getElementType() +{ + return cppu::UnoType<XCommandBar>::get(); +} + +uno::Reference< container::XEnumeration > +ScVbaCommandBars::createEnumeration() +{ + return uno::Reference< container::XEnumeration >( new CommandBarEnumeration( this, mxContext, m_pCBarHelper ) ); +} + +uno::Any +ScVbaCommandBars::createCollectionObject( const uno::Any& aSource ) +{ + // aSource should be a name at this time, because of the class is API wrapper. + OUString sResourceUrl; + uno::Reference< container::XIndexAccess > xBarSettings; + OUString sBarName; + bool bMenu = false; + uno::Any aRet; + + if( aSource >>= sBarName ) + { + // some built-in command bars + if( m_pCBarHelper->getModuleId() == "com.sun.star.sheet.SpreadsheetDocument" ) + { + if( sBarName.equalsIgnoreAsciiCase( "Worksheet Menu Bar" ) ) + { + // spreadsheet menu bar + sResourceUrl = ITEM_MENUBAR_URL; + bMenu = true; + } + else if( sBarName.equalsIgnoreAsciiCase( "Cell" ) ) + { + // EVIL HACK (tm): spreadsheet cell context menu as dummy object without functionality + aRet <<= uno::Reference< XCommandBar >( new VbaDummyCommandBar( this, mxContext, sBarName ) ); + } + } + else if( m_pCBarHelper->getModuleId() == "com.sun.star.text.TextDocument" ) + { + if( sBarName.equalsIgnoreAsciiCase( "Menu Bar" ) ) + { + // text processor menu bar + sResourceUrl = ITEM_MENUBAR_URL; + bMenu = true; + } + } + + // nothing found - try to resolve from name + if( !aRet.hasValue() && sResourceUrl.isEmpty() ) + { + sResourceUrl = m_pCBarHelper->findToolbarByName( m_xNameAccess, sBarName ); + bMenu = false; + } + } + + if( !sResourceUrl.isEmpty() ) + { + xBarSettings = m_pCBarHelper->getSettings( sResourceUrl ); + aRet <<= uno::Reference< XCommandBar >( new ScVbaCommandBar( this, mxContext, m_pCBarHelper, xBarSettings, sResourceUrl, bMenu ) ); + } + + if( !aRet.hasValue() ) + throw uno::RuntimeException( "Toolbar do not exist" ); + + return aRet; +} + +// XCommandBars +uno::Reference< XCommandBar > SAL_CALL +ScVbaCommandBars::Add( const css::uno::Any& Name, const css::uno::Any& /*Position*/, const css::uno::Any& /*MenuBar*/, const css::uno::Any& /*Temporary*/ ) +{ + // FIXME: only support to add Toolbar + // Position - MsoBar MenuBar - sal_Bool + // Currently only the Name is supported. + OUString sName; + if( Name.hasValue() ) + Name >>= sName; + + OUString sResourceUrl; + if( !sName.isEmpty() ) + { + sResourceUrl = m_pCBarHelper->findToolbarByName( m_xNameAccess, sName ); + if( !sResourceUrl.isEmpty() ) + throw uno::RuntimeException( "Toolbar exists" ); + } + else + { + sName = "Custom1"; + } + + sResourceUrl = VbaCommandBarHelper::generateCustomURL(); + uno::Reference< container::XIndexAccess > xBarSettings( m_pCBarHelper->getSettings( sResourceUrl ), uno::UNO_SET_THROW ); + uno::Reference< XCommandBar > xCBar( new ScVbaCommandBar( this, mxContext, m_pCBarHelper, xBarSettings, sResourceUrl, false ) ); + xCBar->setName( sName ); + return xCBar; +} +sal_Int32 SAL_CALL +ScVbaCommandBars::getCount() +{ + // Filter out all toolbars from the window collection + sal_Int32 nCount = 1; // there is a Menubar in OOo + const uno::Sequence< ::OUString > allNames = m_xNameAccess->getElementNames(); + nCount += std::count_if(allNames.begin(), allNames.end(), + [](const OUString& rName) { return rName.indexOf( "private:resource/toolbar/" ) != -1; }); + return nCount; +} + +// ScVbaCollectionBaseImpl +uno::Any SAL_CALL +ScVbaCommandBars::Item( const uno::Any& aIndex, const uno::Any& /*aIndex2*/ ) +{ + if( aIndex.getValueTypeClass() == uno::TypeClass_STRING ) + { + return createCollectionObject( aIndex ); + } + + // hardcode if "aIndex = 1" that would return "main menu". + sal_Int32 nIndex = 0; + aIndex >>= nIndex; + if( nIndex == 1 ) + { + uno::Any aSource; + if( m_pCBarHelper->getModuleId() == "com.sun.star.sheet.SpreadsheetDocument" ) + aSource <<= OUString("Worksheet Menu Bar"); + else if( m_pCBarHelper->getModuleId() == "com.sun.star.text.TextDocument" ) + aSource <<= OUString("Menu Bar"); + if( aSource.hasValue() ) + return createCollectionObject( aSource ); + } + return uno::Any(); +} + +// XHelperInterface +OUString +ScVbaCommandBars::getServiceImplName() +{ + return "ScVbaCommandBars"; +} + +uno::Sequence<OUString> +ScVbaCommandBars::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.CommandBars" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbacommandbars.hxx b/vbahelper/source/vbahelper/vbacommandbars.hxx new file mode 100644 index 000000000..ba7c8cbcd --- /dev/null +++ b/vbahelper/source/vbahelper/vbacommandbars.hxx @@ -0,0 +1,55 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARS_HXX +#define INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARS_HXX + +#include <ooo/vba/XCommandBar.hpp> +#include <ooo/vba/XCommandBars.hpp> +#include <vbahelper/vbacollectionimpl.hxx> +#include "vbacommandbarhelper.hxx" + +typedef CollTestImplHelper< ov::XCommandBars > CommandBars_BASE; + +class ScVbaCommandBars : public CommandBars_BASE +{ +private: + VbaCommandBarHelperRef m_pCBarHelper; + +public: + /// @throws css::uno::RuntimeException + ScVbaCommandBars( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess, const css::uno::Reference< css::frame::XModel >& xModel ); + virtual ~ScVbaCommandBars() override; + + // XCommandBars + virtual css::uno::Reference< ov::XCommandBar > SAL_CALL Add( const css::uno::Any& Name, const css::uno::Any& Position, const css::uno::Any& MenuBar, const css::uno::Any& Temporary ) override; + // XEnumerationAccess + virtual css::uno::Type SAL_CALL getElementType() override; + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override; + virtual css::uno::Any createCollectionObject( const css::uno::Any& aSource ) override; + + virtual sal_Int32 SAL_CALL getCount() override; + virtual css::uno::Any SAL_CALL Item( const css::uno::Any& aIndex, const css::uno::Any& /*aIndex2*/ ) override; + // XHelperInterface + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; +}; + +#endif // INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBACOMMANDBARS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbadialogbase.cxx b/vbahelper/source/vbahelper/vbadialogbase.cxx new file mode 100644 index 000000000..9b9087bd2 --- /dev/null +++ b/vbahelper/source/vbahelper/vbadialogbase.cxx @@ -0,0 +1,37 @@ +/* -*- 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 . + */ +#include <vbahelper/vbadialogbase.hxx> +#include <vbahelper/vbahelper.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> + +using namespace ::ooo::vba; +using namespace ::com::sun::star; + +void SAL_CALL VbaDialogBase::Show() +{ + if (m_xModel.is()) + { + OUString aURL = mapIndexToName(mnIndex); + if (aURL.isEmpty()) + throw uno::RuntimeException("Unable to open the specified dialog"); + + dispatchRequests(m_xModel, aURL, {}); + } +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbadialogsbase.cxx b/vbahelper/source/vbahelper/vbadialogsbase.cxx new file mode 100644 index 000000000..959047314 --- /dev/null +++ b/vbahelper/source/vbahelper/vbadialogsbase.cxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ +#include <vbahelper/vbadialogsbase.hxx> + +using namespace ::ooo::vba; +using namespace ::com::sun::star; + +::sal_Int32 VbaDialogsBase::getCount() +{ + //#STUB + return 0; +} + +uno::Any VbaDialogsBase::Item(const uno::Any& /* &aItem */) +{ + //#STUB + return uno::Any(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbadocumentbase.cxx b/vbahelper/source/vbahelper/vbadocumentbase.cxx new file mode 100644 index 000000000..d27804012 --- /dev/null +++ b/vbahelper/source/vbahelper/vbadocumentbase.cxx @@ -0,0 +1,309 @@ +/* -*- 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 . + */ + +#include <vbahelper/vbadocumentbase.hxx> + +#include <com/sun/star/beans/PropertyVetoException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/util/XProtectable.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/URLTransformer.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XTitle.hpp> +#include <ooo/vba/XApplicationBase.hpp> + +#include <comphelper/automationinvokedzone.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <tools/urlobj.hxx> +#include <osl/file.hxx> +#include <sal/log.hxx> + +using namespace ::com::sun::star; +using namespace ::ooo::vba; + +VbaDocumentBase::VbaDocumentBase( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, uno::Reference< frame::XModel > const & xModel ) : VbaDocumentBase_BASE( xParent, xContext ), mxModel( xModel ) +{ +} + +VbaDocumentBase::VbaDocumentBase( uno::Sequence< uno::Any> const & args, + uno::Reference< uno::XComponentContext> const & xContext ) : VbaDocumentBase_BASE( getXSomethingFromArgs< XHelperInterface >( args, 0 ), xContext ), mxModel( getXSomethingFromArgs< frame::XModel >( args, 1 ) ) +{ +} + +OUString +VbaDocumentBase::getName() +{ + OUString sName = VbaDocumentBase::getNameFromModel( getModel() ); + SAL_INFO("vbahelper", "VbaDocumentBase::getName: '" << sName << "'"); + + return sName; +} + +OUString VbaDocumentBase::getNameFromModel( const uno::Reference< frame::XModel >& xModel ) +{ + OUString sName = xModel.is() ? xModel->getURL() : OUString(); + if ( !sName.isEmpty() ) + { + + INetURLObject aURL( xModel->getURL() ); + ::osl::File::getSystemPathFromFileURL( aURL.GetLastName(), sName ); + } + else + { + uno::Reference< frame::XTitle > xTitle( xModel, uno::UNO_QUERY_THROW ); + sName = xTitle->getTitle(); + sName = sName.trim(); + } + return sName; +} +OUString +VbaDocumentBase::getPath() +{ + INetURLObject aURL( getModel()->getURL() ); + OUString sURL = aURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ); + OUString sPath; + if( !sURL.isEmpty() ) + { + sURL = sURL.copy( 0, sURL.getLength() - aURL.GetLastName().getLength() - 1 ); + ::osl::File::getSystemPathFromFileURL( sURL, sPath ); + } + SAL_INFO("vbahelper", "VbaDocumentBase::getPath: '" << sPath << "'"); + + return sPath; +} + +OUString +VbaDocumentBase::getFullName() +{ + // In the Automation case, follow the specs. + if (comphelper::Automation::AutomationInvokedZone::isActive()) + { + // We know that Automation is relevant only on Windows, so hardcode "\\". + OUString sPath = getPath() + "\\" + getName(); + SAL_INFO("vbahelper", "VbaDocumentBase::getFullName: '" << sPath << "'"); + return sPath; + } + + OUString sPath = getName(); + //::osl::File::getSystemPathFromFileURL( getModel()->getURL(), sPath ); + SAL_INFO("vbahelper", "VbaDocumentBase::getFullName: '" << sPath << "'"); + return sPath; +} + +void +VbaDocumentBase::Close( const uno::Any &rSaveArg, const uno::Any &rFileArg, + const uno::Any &rRouteArg ) +{ + bool bSaveChanges = false; + OUString aFileName; + bool bRouteWorkbook = true; + + rSaveArg >>= bSaveChanges; + bool bFileName = ( rFileArg >>= aFileName ); + rRouteArg >>= bRouteWorkbook; + uno::Reference< frame::XStorable > xStorable( getModel(), uno::UNO_QUERY_THROW ); + uno::Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY_THROW ); + + if( bSaveChanges ) + { + if( xStorable->isReadonly() ) + { + throw uno::RuntimeException("Unable to save to a read only file " ); + } + if( bFileName ) + xStorable->storeAsURL( aFileName, uno::Sequence< beans::PropertyValue >(0) ); + else + xStorable->store(); + } + else + xModifiable->setModified( false ); + + // first try to close the document using UI dispatch functionality + bool bUIClose = false; + try + { + uno::Reference< frame::XController > xController( getModel()->getCurrentController(), uno::UNO_SET_THROW ); + uno::Reference< frame::XDispatchProvider > xDispatchProvider( xController->getFrame(), uno::UNO_QUERY_THROW ); + + uno::Reference< lang::XMultiComponentFactory > xServiceManager( mxContext->getServiceManager(), uno::UNO_SET_THROW ); + uno::Reference< util::XURLTransformer > xURLTransformer( util::URLTransformer::create(mxContext) ); + + util::URL aURL; + aURL.Complete = ".uno:CloseDoc"; + xURLTransformer->parseStrict( aURL ); + + uno::Reference< css::frame::XDispatch > xDispatch( + xDispatchProvider->queryDispatch( aURL, "_self" , 0 ), + uno::UNO_SET_THROW ); + xDispatch->dispatch( aURL, uno::Sequence< beans::PropertyValue >() ); + bUIClose = true; + } + catch(const uno::Exception&) + { + } + + if ( bUIClose ) + return; + + // if it is not possible to use UI dispatch, try to close the model directly + bool bCloseable = false; + uno::Reference< frame::XModel > xModel = getModel(); + try + { + uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY ); + + // use close(boolean DeliverOwnership) + // The boolean parameter DeliverOwnership tells objects vetoing the close + // process that they may assume ownership if they object the closure by + // throwing a CloseVetoException. Here we give up ownership. To be on the + // safe side, catch possible veto exception anyway. + if ( xCloseable.is() ) + { + bCloseable = true; + xCloseable->close(true); + } + } + catch (const uno::Exception &) + { + // vetoed + } + if (bCloseable) + return; + + try { + // If close is not supported by this model - try to dispose it. + // But if the model disagree with a reset request for the modify state + // we shouldn't do so. Otherwise some strange things can happen. + uno::Reference< lang::XComponent > xDisposable ( xModel, uno::UNO_QUERY_THROW ); + xDisposable->dispose(); + } + catch(const uno::Exception&) + { + } +} + +void +VbaDocumentBase::Protect( const uno::Any &aPassword ) +{ + OUString rPassword; + uno::Reference< util::XProtectable > xProt( getModel(), uno::UNO_QUERY_THROW ); + SAL_INFO("vbahelper", "Workbook::Protect stub"); + if( aPassword >>= rPassword ) + xProt->protect( rPassword ); + else + xProt->protect( OUString() ); +} + +void +VbaDocumentBase::Unprotect( const uno::Any &aPassword ) +{ + OUString rPassword; + uno::Reference< util::XProtectable > xProt( getModel(), uno::UNO_QUERY_THROW ); + if( !xProt->isProtected() ) + throw uno::RuntimeException("File is already unprotected" ); + if( aPassword >>= rPassword ) + xProt->unprotect( rPassword ); + else + xProt->unprotect( OUString() ); +} + +void +VbaDocumentBase::setSaved( sal_Bool bSave ) +{ + uno::Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY_THROW ); + try + { + xModifiable->setModified( !bSave ); + } + catch (const lang::DisposedException&) + { + // impossibility to set the modified state on disposed document should not trigger an error + } + catch (const beans::PropertyVetoException&) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + "Can't change modified state of model!", + uno::Reference< uno::XInterface >(), + aCaught ); + } +} + +sal_Bool +VbaDocumentBase::getSaved() +{ + uno::Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY_THROW ); + return !xModifiable->isModified(); +} + +void +VbaDocumentBase::Save() +{ + uno::Reference< frame::XModel > xModel = getModel(); + dispatchRequests(xModel,".uno:Save"); +} + +void +VbaDocumentBase::Activate() +{ + uno::Reference< frame::XFrame > xFrame( getModel()->getCurrentController()->getFrame(), uno::UNO_SET_THROW ); + xFrame->activate(); +} + +uno::Any SAL_CALL +VbaDocumentBase::getVBProject() +{ + if( !mxVBProject.is() ) try + { + uno::Reference< XApplicationBase > xApp( Application(), uno::UNO_QUERY_THROW ); + uno::Reference< XInterface > xVBE( xApp->getVBE(), uno::UNO_QUERY_THROW ); + uno::Sequence< uno::Any > aArgs{ uno::Any(xVBE), // the VBE + uno::Any(getModel()) }; // document model for script container access + uno::Reference< lang::XMultiComponentFactory > xServiceManager( mxContext->getServiceManager(), uno::UNO_SET_THROW ); + mxVBProject = xServiceManager->createInstanceWithArgumentsAndContext( + "ooo.vba.vbide.VBProject", aArgs, mxContext ); + } + catch(const uno::Exception&) + { + } + return uno::Any( mxVBProject ); +} + +OUString +VbaDocumentBase::getServiceImplName() +{ + return "VbaDocumentBase"; +} + +uno::Sequence< OUString > +VbaDocumentBase::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.VbaDocumentBase" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbadocumentsbase.cxx b/vbahelper/source/vbahelper/vbadocumentsbase.cxx new file mode 100644 index 000000000..607ad57fc --- /dev/null +++ b/vbahelper/source/vbahelper/vbadocumentsbase.cxx @@ -0,0 +1,319 @@ +/* -*- 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 . + */ + +#include <vbahelper/vbadocumentsbase.hxx> + +#include <unotools/mediadescriptor.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <tools/urlobj.hxx> +#include <o3tl/safeint.hxx> +#include <osl/file.hxx> +#include <unordered_map> + +#include <vbahelper/vbadocumentbase.hxx> +#include <ooo/vba/XApplicationBase.hpp> + +using namespace ::ooo::vba; +using namespace ::com::sun::star; + +typedef std::unordered_map< OUString, + sal_Int32 > NameIndexHash; + +typedef std::vector < uno::Reference< frame::XModel > > Documents; + +// #FIXME clearly this is a candidate for some sort of helper base class as +// this is a copy of SelectedSheetsEnum ( vbawindow.cxx ) + +namespace { + +class DocumentsEnumImpl : public ::cppu::WeakImplHelper< container::XEnumeration > +{ + uno::Reference< uno::XComponentContext > m_xContext; + Documents m_documents; + Documents::const_iterator m_it; + +public: + /// @throws uno::RuntimeException + DocumentsEnumImpl( const uno::Reference< uno::XComponentContext >& xContext, Documents&& docs ) : m_xContext( xContext ), m_documents( std::move(docs) ) + { + m_it = m_documents.begin(); + } + /// @throws uno::RuntimeException + explicit DocumentsEnumImpl( const uno::Reference< uno::XComponentContext >& xContext ) : m_xContext( xContext ) + { + uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( m_xContext ); + uno::Reference< container::XEnumeration > xComponents = xDesktop->getComponents()->createEnumeration(); + while( xComponents->hasMoreElements() ) + { + uno::Reference< frame::XModel > xNext( xComponents->nextElement(), uno::UNO_QUERY ); + if ( xNext.is() ) + m_documents.push_back( xNext ); + } + m_it = m_documents.begin(); + } + // XEnumeration + virtual sal_Bool SAL_CALL hasMoreElements( ) override + { + return m_it != m_documents.end(); + } + + virtual uno::Any SAL_CALL nextElement( ) override + { + if ( !hasMoreElements() ) + { + throw container::NoSuchElementException(); + } + return css::uno::Any( *(m_it++) ); + } +}; + +} + +// #FIXME clearly this is also a candidate for some sort of helper base class as +// a very similar one is used in vbawindow ( SelectedSheetsEnumAccess ) +// Maybe a template base class that does all of the operations on the hashmap +// and vector only, and the sub-class does everything else +// => ctor, createEnumeration & factory method need be defined ( to be called +// by getByIndex, getByName ) +typedef ::cppu::WeakImplHelper< container::XEnumerationAccess + , css::container::XIndexAccess + , css::container::XNameAccess + > DocumentsAccessImpl_BASE; + +namespace { + +class DocumentsAccessImpl : public DocumentsAccessImpl_BASE +{ + uno::Reference< uno::XComponentContext > m_xContext; + Documents m_documents; + NameIndexHash namesToIndices; +public: + /// @throws uno::RuntimeException + DocumentsAccessImpl( const uno::Reference< uno::XComponentContext >& xContext, VbaDocumentsBase::DOCUMENT_TYPE eDocType ) :m_xContext( xContext ) + { + uno::Reference< container::XEnumeration > xEnum = new DocumentsEnumImpl( m_xContext ); + sal_Int32 nIndex=0; + while( xEnum->hasMoreElements() ) + { + uno::Reference< lang::XServiceInfo > xServiceInfo( xEnum->nextElement(), uno::UNO_QUERY ); + if ( xServiceInfo.is() + && ( ( xServiceInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) && eDocType == VbaDocumentsBase::EXCEL_DOCUMENT ) + || ( xServiceInfo->supportsService( "com.sun.star.text.TextDocument" ) && eDocType == VbaDocumentsBase::WORD_DOCUMENT ) ) ) + { + uno::Reference< frame::XModel > xModel( xServiceInfo, uno::UNO_QUERY_THROW ); // that the spreadsheetdocument is a xmodel is a given + m_documents.push_back( xModel ); + OUString sName = VbaDocumentBase::getNameFromModel( xModel ); + namesToIndices[ sName ] = nIndex++; + } + } + + } + + //XEnumerationAccess + virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) override + { + return new DocumentsEnumImpl( m_xContext, std::vector(m_documents) ); + } + // XIndexAccess + virtual ::sal_Int32 SAL_CALL getCount( ) override + { + return m_documents.size(); + } + virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override + { + if ( Index < 0 + || o3tl::make_unsigned(Index) >= m_documents.size() ) + throw lang::IndexOutOfBoundsException(); + return css::uno::Any( m_documents[ Index ] ); // returns xspreadsheetdoc + } + + //XElementAccess + virtual uno::Type SAL_CALL getElementType( ) override + { + return cppu::UnoType<frame::XModel>::get(); + } + + virtual sal_Bool SAL_CALL hasElements( ) override + { + return (!m_documents.empty()); + } + + //XNameAccess + virtual uno::Any SAL_CALL getByName( const OUString& aName ) override + { + NameIndexHash::const_iterator it = namesToIndices.find( aName ); + if ( it == namesToIndices.end() ) + throw container::NoSuchElementException(); + return css::uno::Any( m_documents[ it->second ] ); + + } + + virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override + { + return comphelper::mapKeysToSequence( namesToIndices ); + } + + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override + { + NameIndexHash::const_iterator it = namesToIndices.find( aName ); + return (it != namesToIndices.end()); + } + +}; + +} + +VbaDocumentsBase::VbaDocumentsBase( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< css::uno::XComponentContext >& xContext, DOCUMENT_TYPE eDocType ) : VbaDocumentsBase_BASE( xParent, xContext, uno::Reference< container::XIndexAccess >( new DocumentsAccessImpl( xContext, eDocType ) ) ), meDocType( eDocType ) +{ +} + +namespace { + +void lclSetupComponent( const uno::Reference< lang::XComponent >& rxComponent, bool bScreenUpdating, bool bInteractive ) +{ + if( !bScreenUpdating ) try + { + uno::Reference< frame::XModel >( rxComponent, uno::UNO_QUERY_THROW )->lockControllers(); + } + catch( uno::Exception& ) + { + } + + if( !bInteractive ) try + { + uno::Reference< frame::XModel > xModel( rxComponent, uno::UNO_QUERY_THROW ); + uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_SET_THROW ); + uno::Reference< frame::XFrame > xFrame( xController->getFrame(), uno::UNO_SET_THROW ); + uno::Reference< awt::XWindow >( xFrame->getContainerWindow(), uno::UNO_SET_THROW )->setEnable( false ); + } + catch( uno::Exception& ) + { + } +} + +} // namespace + +uno::Any VbaDocumentsBase::createDocument() +{ + // #163808# determine state of Application.ScreenUpdating and Application.Interactive symbols (before new document is opened) + uno::Reference< XApplicationBase > xApplication( Application(), uno::UNO_QUERY ); + bool bScreenUpdating = !xApplication.is() || xApplication->getScreenUpdating(); + bool bInteractive = true; + + try + { + bInteractive = !xApplication.is() || xApplication->getInteractive(); + } + catch( const uno::Exception& ) + { + } + + uno::Reference< frame::XDesktop2 > xLoader = frame::Desktop::create(mxContext); + OUString sURL; + if( meDocType == WORD_DOCUMENT ) + sURL = "private:factory/swriter"; + else if( meDocType == EXCEL_DOCUMENT ) + sURL = "private:factory/scalc"; + else + throw uno::RuntimeException( "Not implemented" ); + + // prepare the media descriptor + utl::MediaDescriptor aMediaDesc; + aMediaDesc[ utl::MediaDescriptor::PROP_MACROEXECUTIONMODE ] <<= document::MacroExecMode::USE_CONFIG; + aMediaDesc.setComponentDataEntry( "ApplyFormDesignMode" , uno::Any( false ) ); + + // create the new document + uno::Reference< lang::XComponent > xComponent = xLoader->loadComponentFromURL( + sURL , "_blank", 0, + aMediaDesc.getAsConstPropertyValueList() ); + + // #163808# lock document controllers and container window if specified by application + lclSetupComponent( xComponent, bScreenUpdating, bInteractive ); + + return uno::Any( xComponent ); +} + +// #TODO# #FIXME# can any of the unused params below be used? +uno::Any VbaDocumentsBase::openDocument( const OUString& rFileName, const uno::Any& ReadOnly, const uno::Sequence< beans::PropertyValue >& rProps ) +{ + // #163808# determine state of Application.ScreenUpdating and Application.Interactive symbols (before new document is opened) + uno::Reference< XApplicationBase > xApplication( Application(), uno::UNO_QUERY ); + bool bScreenUpdating = !xApplication.is() || xApplication->getScreenUpdating(); + bool bInteractive = true; + + try + { + bInteractive = !xApplication.is() || xApplication->getInteractive(); + } + catch( const uno::Exception& ) + { + } + + // we need to detect if this is a URL, if not then assume it's a file path + OUString aURL; + INetURLObject aObj; + aObj.SetURL( rFileName ); + bool bIsURL = aObj.GetProtocol() != INetProtocol::NotValid; + if ( bIsURL ) + aURL = rFileName; + else + osl::FileBase::getFileURLFromSystemPath( rFileName, aURL ); + uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( mxContext ); + + uno::Sequence< beans::PropertyValue > sProps( rProps ); + sProps.realloc( sProps.getLength() + 1 ); + auto pProps = sProps.getArray(); + pProps[ sProps.getLength() - 1 ].Name = "MacroExecutionMode"; + pProps[ sProps.getLength() - 1 ].Value <<= document::MacroExecMode::ALWAYS_EXECUTE_NO_WARN; + + if ( ReadOnly.hasValue() ) + { + bool bIsReadOnly = false; + ReadOnly >>= bIsReadOnly; + if ( bIsReadOnly ) + { + sProps.realloc( sProps.getLength() + 1 ); + pProps = sProps.getArray(); + pProps[ sProps.getLength() - 1 ].Name = "ReadOnly"; + pProps[ sProps.getLength() - 1 ].Value <<= true; + } + } + + uno::Reference< lang::XComponent > xComponent = xDesktop->loadComponentFromURL( aURL, + "_default" , + frame::FrameSearchFlag::CREATE, + sProps); + + // #163808# lock document controllers and container window if specified by application + lclSetupComponent( xComponent, bScreenUpdating, bInteractive ); + + return uno::Any( xComponent ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbaeventshelperbase.cxx b/vbahelper/source/vbahelper/vbaeventshelperbase.cxx new file mode 100644 index 000000000..1f92e449a --- /dev/null +++ b/vbahelper/source/vbahelper/vbaeventshelperbase.cxx @@ -0,0 +1,359 @@ +/* -*- 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 . + */ + +#include <vbahelper/vbaeventshelperbase.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/document/XEventBroadcaster.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/script/ModuleType.hpp> +#include <com/sun/star/script/vba/XVBAModuleInfo.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/util/VetoException.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <filter/msfilter/msvbahelper.hxx> +#include <unotools/eventcfg.hxx> +#include <vbahelper/vbahelper.hxx> +#include <sal/log.hxx> + +using namespace ::com::sun::star; +using namespace ::ooo::vba; + + +VbaEventsHelperBase::VbaEventsHelperBase( const uno::Sequence< uno::Any >& rArgs ) : + mpShell( nullptr ), + mbDisposed( true ) +{ + try + { + mxModel = getXSomethingFromArgs< frame::XModel >( rArgs, 0, false ); + mpShell = getSfxObjShell( mxModel ); + } + catch( uno::Exception& ) + { + } + mbDisposed = mpShell == nullptr; + startListening(); +} + +VbaEventsHelperBase::~VbaEventsHelperBase() +{ + SAL_WARN_IF( !mbDisposed, "vbahelper", "VbaEventsHelperBase::~VbaEventsHelperBase - missing disposing notification" ); +} + +sal_Bool SAL_CALL VbaEventsHelperBase::processVbaEvent( sal_Int32 nEventId, const uno::Sequence< uno::Any >& rArgs ) +{ + /* Derived classes may add new event identifiers to be processed while + processing the original event. All unprocessed events are collected in + a queue. First element in the queue is the next event to be processed. */ + EventQueue aEventQueue; + aEventQueue.emplace_back( nEventId, rArgs ); + + /* bCancel will contain the current Cancel value. It is possible that + multiple events will try to modify the Cancel value. Every event + handler receives the Cancel value of the previous event handler. */ + bool bCancel = false; + + /* bExecuted will change to true if at least one event handler has been + found and executed. */ + bool bExecuted = false; + + /* Loop as long as there are more events to be processed. Derived classes + may add new events to be processed in the virtual implPrepareEvent() + function. */ + while( !aEventQueue.empty() ) + { + /* Check that all class members are available, and that we are not + disposed (this may have happened at any time during execution of + the last event handler). */ + if( mbDisposed || !mxModel.is() || !mpShell ) + throw uno::RuntimeException(); + + // get info for next event + const EventHandlerInfo& rInfo = getEventHandlerInfo( aEventQueue.front().mnEventId ); + uno::Sequence< uno::Any > aEventArgs = aEventQueue.front().maArgs; + aEventQueue.pop_front(); + SAL_INFO("vbahelper", "VbaEventsHelperBase::processVbaEvent( \"" << rInfo.maMacroName << "\" )"); + + /* Let derived classes prepare the event, they may add new events for + next iteration. If false is returned, the event handler must not be + called. */ + if( implPrepareEvent( aEventQueue, rInfo, aEventArgs ) ) + { + // search the event handler macro in the document + OUString aMacroPath = getEventHandlerPath( rInfo, aEventArgs ); + if( !aMacroPath.isEmpty() ) + { + // build the argument list + uno::Sequence< uno::Any > aVbaArgs = implBuildArgumentList( rInfo, aEventArgs ); + // insert current cancel value + if( rInfo.mnCancelIndex >= 0 ) + { + if( rInfo.mnCancelIndex >= aVbaArgs.getLength() ) + throw lang::IllegalArgumentException(); + aVbaArgs.getArray()[ rInfo.mnCancelIndex ] <<= bCancel; + } + // execute the event handler + uno::Any aRet, aCaller; + executeMacro( mpShell, aMacroPath, aVbaArgs, aRet, aCaller ); + // extract new cancel value (may be boolean or any integer type) + if( rInfo.mnCancelIndex >= 0 ) + { + checkArgument( aVbaArgs, rInfo.mnCancelIndex ); + bCancel = extractBoolFromAny( aVbaArgs[ rInfo.mnCancelIndex ] ); + } + // event handler has been found + bExecuted = true; + } + } + // post processing (also, if event handler does not exist, or disabled, or on error + implPostProcessEvent( aEventQueue, rInfo, bCancel ); + } + + // if event handlers want to cancel the event, do so regardless of any errors + if( bCancel ) + throw util::VetoException(); + + // return true, if at least one event handler has been found + return bExecuted; +} + +void SAL_CALL VbaEventsHelperBase::notifyEvent( const document::EventObject& rEvent ) +{ + SAL_INFO("vbahelper", "VbaEventsHelperBase::notifyEvent( \"" << rEvent.EventName << "\" )"); + if( rEvent.EventName == GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC ) ) + stopListening(); +} + +void SAL_CALL VbaEventsHelperBase::changesOccurred( const util::ChangesEvent& rEvent ) +{ + // make sure the VBA library exists + try + { + ensureVBALibrary(); + } + catch( uno::Exception& ) + { + return; + } + + // check that the sender of the event is the VBA library + uno::Reference< script::vba::XVBAModuleInfo > xSender( rEvent.Base, uno::UNO_QUERY ); + if( mxModuleInfos.get() != xSender.get() ) + return; + + // process all changed modules + for( const util::ElementChange& rChange : rEvent.Changes ) + { + OUString aModuleName; + if( (rChange.Accessor >>= aModuleName) && !aModuleName.isEmpty() ) try + { + // invalidate event handler path map depending on module type + if( getModuleType( aModuleName ) == script::ModuleType::NORMAL ) + // paths to global event handlers are stored with empty key (will be searched in all normal code modules) + maEventPaths.erase( OUString() ); + else + // paths to class/form/document event handlers are keyed by module name + maEventPaths.erase( aModuleName ); + } + catch( uno::Exception& ) + { + } + } +} + +void SAL_CALL VbaEventsHelperBase::disposing( const lang::EventObject& rEvent ) +{ + uno::Reference< frame::XModel > xSender( rEvent.Source, uno::UNO_QUERY ); + if( xSender.is() ) + stopListening(); +} + +sal_Bool VbaEventsHelperBase::supportsService(OUString const & ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +void VbaEventsHelperBase::processVbaEventNoThrow( sal_Int32 nEventId, const uno::Sequence< uno::Any >& rArgs ) +{ + try + { + processVbaEvent( nEventId, rArgs ); + } + catch( uno::Exception& ) + { + } +} + +// protected ------------------------------------------------------------------ + +void VbaEventsHelperBase::registerEventHandler( sal_Int32 nEventId, sal_Int32 nModuleType, + const char* pcMacroName, sal_Int32 nCancelIndex, const uno::Any& rUserData ) +{ + EventHandlerInfo& rInfo = maEventInfos[ nEventId ]; + rInfo.mnEventId = nEventId; + rInfo.mnModuleType = nModuleType; + rInfo.maMacroName = OUString::createFromAscii( pcMacroName ); + rInfo.mnCancelIndex = nCancelIndex; + rInfo.maUserData = rUserData; +} + +// private -------------------------------------------------------------------- + +void VbaEventsHelperBase::startListening() +{ + if( mbDisposed ) + return; + + uno::Reference< document::XEventBroadcaster > xEventBroadcaster( mxModel, uno::UNO_QUERY ); + if( xEventBroadcaster.is() ) + try { xEventBroadcaster->addEventListener( this ); } catch( uno::Exception& ) {} +} + +void VbaEventsHelperBase::stopListening() +{ + if( mbDisposed ) + return; + + uno::Reference< document::XEventBroadcaster > xEventBroadcaster( mxModel, uno::UNO_QUERY ); + if( xEventBroadcaster.is() ) + try { xEventBroadcaster->removeEventListener( this ); } catch( uno::Exception& ) {} + + mxModel.clear(); + mpShell = nullptr; + maEventInfos.clear(); + mbDisposed = true; +} + +sal_Bool SAL_CALL VbaEventsHelperBase::hasVbaEventHandler( sal_Int32 nEventId, const uno::Sequence< uno::Any >& rArgs ) +{ + EventHandlerInfoMap::const_iterator aIt = maEventInfos.find( nEventId ); + if( aIt == maEventInfos.end() ) + return false; // throwing a lot of exceptions is slow. + else // getEventHandlerPath() searches for the macro in the document + return !getEventHandlerPath( aIt->second, rArgs ).isEmpty(); +} + +const VbaEventsHelperBase::EventHandlerInfo& VbaEventsHelperBase::getEventHandlerInfo( + sal_Int32 nEventId ) const +{ + EventHandlerInfoMap::const_iterator aIt = maEventInfos.find( nEventId ); + if( aIt == maEventInfos.end() ) + throw lang::IllegalArgumentException(); + return aIt->second; +} + +OUString VbaEventsHelperBase::getEventHandlerPath( const EventHandlerInfo& rInfo, + const uno::Sequence< uno::Any >& rArgs ) +{ + OUString aModuleName; + switch( rInfo.mnModuleType ) + { + // global event handlers may exist in any standard code module + case script::ModuleType::NORMAL: + break; + + // document event: get name of the code module associated to the event sender + case script::ModuleType::DOCUMENT: + aModuleName = implGetDocumentModuleName( rInfo, rArgs ); + if( aModuleName.isEmpty() ) + throw lang::IllegalArgumentException(); + break; + + default: + throw uno::RuntimeException("This module type is unsupported"); // unsupported module type + } + + /* Performance improvement: Check the list of existing event handlers + instead of searching in Basic source code every time. */ + EventHandlerPathMap::iterator aIt = maEventPaths.find( aModuleName ); + ModulePathMap& rPathMap = (aIt == maEventPaths.end()) ? updateModulePathMap( aModuleName ) : aIt->second; + return rPathMap[ rInfo.mnEventId ]; +} + +void VbaEventsHelperBase::ensureVBALibrary() +{ + if( mxModuleInfos.is() ) return; + + try + { + maLibraryName = getDefaultProjectName( mpShell ); + if( maLibraryName.isEmpty() ) + throw uno::RuntimeException(); + uno::Reference< beans::XPropertySet > xModelProps( mxModel, uno::UNO_QUERY_THROW ); + uno::Reference< container::XNameAccess > xBasicLibs( xModelProps->getPropertyValue( + "BasicLibraries" ), uno::UNO_QUERY_THROW ); + + if(!xBasicLibs->hasByName(maLibraryName) ) + { + uno::Reference< script::XLibraryContainer > xLibContainer( + xModelProps->getPropertyValue("BasicLibraries"), uno::UNO_QUERY_THROW); + xLibContainer->createLibrary(maLibraryName); + } + + mxModuleInfos.set( xBasicLibs->getByName( maLibraryName ), uno::UNO_QUERY_THROW ); + // listen to changes in the VBA source code + uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModuleInfos, uno::UNO_QUERY_THROW ); + xChangesNotifier->addChangesListener( this ); + } + catch( uno::Exception& ) + { + // error accessing the Basic library, so this object is useless + stopListening(); + throw uno::RuntimeException(); + } +} + +sal_Int32 VbaEventsHelperBase::getModuleType( const OUString& rModuleName ) +{ + // make sure the VBA library exists + ensureVBALibrary(); + + // no module specified: global event handler in standard code modules + if( rModuleName.isEmpty() ) + return script::ModuleType::NORMAL; + + // get module type from module info + try + { + return mxModuleInfos->getModuleInfo( rModuleName ).ModuleType; + } + catch( uno::Exception& ) + { + } + throw uno::RuntimeException(); +} + +VbaEventsHelperBase::ModulePathMap& VbaEventsHelperBase::updateModulePathMap( const OUString& rModuleName ) +{ + // get type of the specified module (throws on error) + sal_Int32 nModuleType = getModuleType( rModuleName ); + // search for all event handlers + ModulePathMap& rPathMap = maEventPaths[ rModuleName ]; + for( const auto& rEventInfo : maEventInfos ) + { + const EventHandlerInfo& rInfo = rEventInfo.second; + if( rInfo.mnModuleType == nModuleType ) + rPathMap[ rInfo.mnEventId ] = resolveVBAMacro( mpShell, maLibraryName, rModuleName, rInfo.maMacroName ); + } + return rPathMap; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbafillformat.cxx b/vbahelper/source/vbahelper/vbafillformat.cxx new file mode 100644 index 000000000..442efbccb --- /dev/null +++ b/vbahelper/source/vbahelper/vbafillformat.cxx @@ -0,0 +1,187 @@ +/* -*- 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 . + */ +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/awt/GradientStyle.hpp> +#include <ooo/vba/office/MsoGradientStyle.hpp> +#include "vbafillformat.hxx" +#include "vbacolorformat.hxx" + +using namespace ooo::vba; +using namespace com::sun::star; + +ScVbaFillFormat::ScVbaFillFormat( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< drawing::XShape >& xShape ) : ScVbaFillFormat_BASE( xParent, xContext ), m_xShape( xShape ) +{ + m_xPropertySet.set( xShape, uno::UNO_QUERY_THROW ); + m_nFillStyle = drawing::FillStyle_SOLID; + m_nForeColor = 0; + m_nGradientAngle = 0; +} + +void +ScVbaFillFormat::setFillStyle( drawing::FillStyle nFillStyle ) +{ + m_nFillStyle = nFillStyle; + if( m_nFillStyle == drawing::FillStyle_GRADIENT ) + { + m_xPropertySet->setPropertyValue( "FillStyle" , uno::Any( drawing::FillStyle_GRADIENT ) ); + awt::Gradient aGradient; + // AXIAL + // RADIAL + // ELLIPTICAL + // SQUARE + // RECT + aGradient.Style = awt::GradientStyle_LINEAR; + aGradient.StartColor = ForeColor()->getRGB(); + aGradient.EndColor = BackColor()->getRGB(); + aGradient.Angle = m_nGradientAngle; + aGradient.Border = 0; + aGradient.XOffset = 0; + aGradient.YOffset = 0; + aGradient.StartIntensity = 100; + aGradient.EndIntensity = 100; + aGradient.StepCount = 1; + m_xPropertySet->setPropertyValue( "FillGradient" , uno::Any( aGradient ) ); + } + else if( m_nFillStyle == drawing::FillStyle_SOLID ) + { + m_xPropertySet->setPropertyValue( "FillStyle" , uno::Any(drawing::FillStyle_SOLID) ); + } +} + +void +ScVbaFillFormat::setForeColorAndInternalStyle( sal_Int32 nForeColor ) +{ + m_nForeColor = nForeColor; + setFillStyle( m_nFillStyle ); +} + +// Attributes +sal_Bool SAL_CALL +ScVbaFillFormat::getVisible() +{ + drawing::FillStyle nFillStyle; + m_xPropertySet->getPropertyValue( "FillStyle" ) >>= nFillStyle; + if( nFillStyle == drawing::FillStyle_NONE ) + return false; + return true; +} + +void SAL_CALL +ScVbaFillFormat::setVisible( sal_Bool _visible ) +{ + drawing::FillStyle aFillStyle; + m_xPropertySet->getPropertyValue( "FillStyle" ) >>= aFillStyle; + if( !_visible ) + { + m_xPropertySet->setPropertyValue( "FillStyle" , uno::Any( drawing::FillStyle_NONE ) ); + } + else + { + if( aFillStyle == drawing::FillStyle_NONE ) + { + setFillStyle( m_nFillStyle ); + } + } +} + +double SAL_CALL +ScVbaFillFormat::getTransparency() +{ + sal_Int16 nTransparence = 0; + double dTransparence = 0; + m_xPropertySet->getPropertyValue( "FillTransparence" ) >>= nTransparence; + dTransparence = static_cast<double>( nTransparence ); + dTransparence /= 100; + return dTransparence; +} + +void SAL_CALL +ScVbaFillFormat::setTransparency( double _transparency ) +{ + sal_Int16 nTransparence = static_cast< sal_Int16 >( _transparency * 100 ); + m_xPropertySet->setPropertyValue( "FillTransparence" , uno::Any( nTransparence ) ); +} + + +// Methods +void SAL_CALL +ScVbaFillFormat::Solid() +{ + setFillStyle( drawing::FillStyle_SOLID ); +} + +void SAL_CALL +ScVbaFillFormat::TwoColorGradient( sal_Int32 style, sal_Int32 /*variant*/ ) +{ + if( style == office::MsoGradientStyle::msoGradientHorizontal ) + { + m_nGradientAngle = 0; + setFillStyle( drawing::FillStyle_GRADIENT ); + } + else if( style == office::MsoGradientStyle::msoGradientVertical ) + { + m_nGradientAngle = 900; + setFillStyle( drawing::FillStyle_GRADIENT ); + } + else if( style == office::MsoGradientStyle::msoGradientDiagonalDown ) + { + m_nGradientAngle = 450; + setFillStyle( drawing::FillStyle_GRADIENT ); + } + else if( style == office::MsoGradientStyle::msoGradientDiagonalUp ) + { + m_nGradientAngle = 900 + 450; + setFillStyle( drawing::FillStyle_GRADIENT ); + } +} + +uno::Reference< msforms::XColorFormat > SAL_CALL +ScVbaFillFormat::BackColor() +{ + if( !m_xColorFormat.is() ) + m_xColorFormat.set( new ScVbaColorFormat( getParent(), mxContext, this, m_xShape, ColorFormatType::FILLFORMAT_BACKCOLOR ) ); + return m_xColorFormat; +} + +uno::Reference< msforms::XColorFormat > SAL_CALL +ScVbaFillFormat::ForeColor() +{ + if( !m_xColorFormat.is() ) + m_xColorFormat.set( new ScVbaColorFormat( getParent(), mxContext, this, m_xShape, ColorFormatType::FILLFORMAT_FORECOLOR ) ); + return m_xColorFormat; +} + +OUString +ScVbaFillFormat::getServiceImplName() +{ + return "ScVbaFillFormat"; +} + +uno::Sequence< OUString > +ScVbaFillFormat::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.msforms.FillFormat" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbafillformat.hxx b/vbahelper/source/vbahelper/vbafillformat.hxx new file mode 100644 index 000000000..e1635a80d --- /dev/null +++ b/vbahelper/source/vbahelper/vbafillformat.hxx @@ -0,0 +1,66 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBAFILLFORMAT_HXX +#define INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBAFILLFORMAT_HXX + +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <ooo/vba/msforms/XFillFormat.hpp> +#include <vbahelper/vbahelperinterface.hxx> + +typedef InheritedHelperInterfaceWeakImpl< ov::msforms::XFillFormat > ScVbaFillFormat_BASE; + +class ScVbaFillFormat : public ScVbaFillFormat_BASE +{ +private: + css::uno::Reference< css::drawing::XShape > m_xShape; + css::uno::Reference< css::beans::XPropertySet > m_xPropertySet; + css::uno::Reference< ov::msforms::XColorFormat > m_xColorFormat; + css::drawing::FillStyle m_nFillStyle; + sal_Int32 m_nForeColor; + sal_Int16 m_nGradientAngle; +private: + /// @throws css::uno::RuntimeException + void setFillStyle( css::drawing::FillStyle nFillStyle ); +protected: + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; + +public: + ScVbaFillFormat( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::drawing::XShape >& xShape ); + + /// @throws css::uno::RuntimeException + void setForeColorAndInternalStyle( sal_Int32 nForeColor ); + // Attributes + virtual sal_Bool SAL_CALL getVisible() override; + virtual void SAL_CALL setVisible( sal_Bool _visible ) override; + virtual double SAL_CALL getTransparency() override; + virtual void SAL_CALL setTransparency( double _transparency ) override; + + // Methods + virtual void SAL_CALL Solid() override; + virtual void SAL_CALL TwoColorGradient( sal_Int32 style, sal_Int32 variant ) override; + virtual css::uno::Reference< ov::msforms::XColorFormat > SAL_CALL BackColor() override; + virtual css::uno::Reference< ov::msforms::XColorFormat > SAL_CALL ForeColor() override; + +}; + +#endif // INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBAFILLFORMAT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbafontbase.cxx b/vbahelper/source/vbahelper/vbafontbase.cxx new file mode 100644 index 000000000..50bac8f92 --- /dev/null +++ b/vbahelper/source/vbahelper/vbafontbase.cxx @@ -0,0 +1,270 @@ +/* -*- 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 . + */ + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/awt/FontStrikeout.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <vbahelper/vbafontbase.hxx> + +using namespace ::ooo::vba; +using namespace ::com::sun::star; + + +// form controls use other property name as the remaining OOo API +#define VBAFONTBASE_PROPNAME( ascii_normal, ascii_control ) \ + mbFormControl ? OUString( ascii_control ) : OUString( ascii_normal ) + +VbaFontBase::VbaFontBase( + const uno::Reference< XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext, + const uno::Reference< css::container::XIndexAccess >& xPalette, + const uno::Reference< beans::XPropertySet >& xPropertySet, + bool bFormControl ) : + VbaFontBase_BASE( xParent, xContext ), + mxFont( xPropertySet, uno::UNO_SET_THROW ), + mxPalette( xPalette, uno::UNO_SET_THROW ), + mbFormControl( bFormControl ) +{ +} + +VbaFontBase::~VbaFontBase() +{ +} + +void SAL_CALL +VbaFontBase::setSuperscript( const uno::Any& aValue ) +{ + // not supported in form controls + if( mbFormControl ) + return; + + bool bValue = false; + aValue >>= bValue; + sal_Int16 nValue = NORMAL; + sal_Int8 nValue2 = NORMALHEIGHT; + + if( bValue ) + { + nValue = SUPERSCRIPT; + nValue2 = SUPERSCRIPTHEIGHT; + } + mxFont->setPropertyValue( "CharEscapement" , uno::Any(nValue) ); + mxFont->setPropertyValue( "CharEscapementHeight" , uno::Any(nValue2) ); +} + +uno::Any SAL_CALL +VbaFontBase::getSuperscript() +{ + short nValue = NORMAL; + // not supported in form controls + if( !mbFormControl ) + mxFont->getPropertyValue( "CharEscapement" ) >>= nValue; + return uno::Any( nValue == SUPERSCRIPT ); +} + +void SAL_CALL +VbaFontBase::setSubscript( const uno::Any& aValue ) +{ + // not supported in form controls + if( mbFormControl ) + return; + + bool bValue = false; + aValue >>= bValue; + sal_Int16 nValue = NORMAL; + sal_Int8 nValue2 = NORMALHEIGHT; + + if( bValue ) + { + nValue= SUBSCRIPT; + nValue2 = SUBSCRIPTHEIGHT; + } + + mxFont->setPropertyValue( "CharEscapementHeight" , uno::Any(nValue2) ); + mxFont->setPropertyValue( "CharEscapement" , uno::Any(nValue) ); + +} + +uno::Any SAL_CALL +VbaFontBase::getSubscript() +{ + short nValue = NORMAL; + // not supported in form controls + if( !mbFormControl ) + mxFont->getPropertyValue( "CharEscapement" ) >>= nValue; + return uno::Any( nValue == SUBSCRIPT ); +} + +void SAL_CALL +VbaFontBase::setSize( const uno::Any& aValue ) +{ + // form controls need a sal_Int16 containing points, other APIs need a float + uno::Any aVal( aValue ); + if( mbFormControl ) + { + float fVal = 0.0; + aVal >>= fVal; + aVal <<= static_cast< sal_Int16 >( fVal ); + } + mxFont->setPropertyValue( VBAFONTBASE_PROPNAME( "CharHeight", "FontHeight" ), aVal ); +} + +uno::Any SAL_CALL +VbaFontBase::getSize() +{ + return mxFont->getPropertyValue( VBAFONTBASE_PROPNAME( "CharHeight", "FontHeight" ) ); +} + +void SAL_CALL +VbaFontBase::setColorIndex( const uno::Any& _colorindex ) +{ + sal_Int32 nIndex = 0; + _colorindex >>= nIndex; + + --nIndex; // OOo indices are zero bases + + // setColor expects colors in XL RGB values + // #FIXME this is daft we convert OO RGB val to XL RGB val and + // then back again to OO RGB value + setColor( OORGBToXLRGB(mxPalette->getByIndex( nIndex )) ); +} + + +uno::Any SAL_CALL +VbaFontBase::getColorIndex() +{ + sal_Int32 nColor = 0; + + XLRGBToOORGB( getColor() ) >>= nColor; + sal_Int32 nElems = mxPalette->getCount(); + sal_Int32 nIndex = -1; + for ( sal_Int32 count=0; count<nElems; ++count ) + { + sal_Int32 nPaletteColor = 0; + mxPalette->getByIndex( count ) >>= nPaletteColor; + if ( nPaletteColor == nColor ) + { + nIndex = count + 1; // 1 based + break; + } + } + return uno::Any( nIndex ); +} + +void SAL_CALL +VbaFontBase::setBold( const uno::Any& aValue ) +{ + bool bValue = false; + aValue >>= bValue; + double fBoldValue = awt::FontWeight::NORMAL; + if( bValue ) + fBoldValue = awt::FontWeight::BOLD; + mxFont->setPropertyValue( VBAFONTBASE_PROPNAME( "CharWeight", "FontWeight" ), uno::Any( fBoldValue ) ); + +} + +uno::Any SAL_CALL +VbaFontBase::getBold() +{ + double fValue = 0.0; + mxFont->getPropertyValue( VBAFONTBASE_PROPNAME( "CharWeight", "FontWeight" ) ) >>= fValue; + return uno::Any( fValue == awt::FontWeight::BOLD ); +} + +void SAL_CALL +VbaFontBase::setStrikethrough( const uno::Any& aValue ) +{ + bool bValue = false; + aValue >>= bValue; + short nValue = awt::FontStrikeout::NONE; + if( bValue ) + nValue = awt::FontStrikeout::SINGLE; + mxFont->setPropertyValue( VBAFONTBASE_PROPNAME( "CharStrikeout", "FontStrikeout" ), uno::Any( nValue ) ); +} + +uno::Any SAL_CALL +VbaFontBase::getStrikethrough() +{ + short nValue = 0; + mxFont->getPropertyValue( VBAFONTBASE_PROPNAME( "CharStrikeout", "FontStrikeout" ) ) >>= nValue; + return uno::Any( nValue == awt::FontStrikeout::SINGLE ); +} + +void SAL_CALL +VbaFontBase::setShadow( const uno::Any& aValue ) +{ + if( !mbFormControl ) + mxFont->setPropertyValue( "CharShadowed" , aValue ); +} + +uno::Any SAL_CALL +VbaFontBase::getShadow() +{ + return mbFormControl ? uno::Any( false ) : mxFont->getPropertyValue( "CharShadowed" ); +} + +void SAL_CALL +VbaFontBase::setItalic( const uno::Any& aValue ) +{ + bool bValue = false; + aValue >>= bValue; + awt::FontSlant nValue = awt::FontSlant_NONE; + if( bValue ) + nValue = awt::FontSlant_ITALIC; + mxFont->setPropertyValue( VBAFONTBASE_PROPNAME( "CharPosture", "FontSlant" ), uno::Any( static_cast<short>(nValue) ) ); +} + +uno::Any SAL_CALL +VbaFontBase::getItalic() +{ + awt::FontSlant aFS; + mxFont->getPropertyValue( VBAFONTBASE_PROPNAME( "CharPosture", "FontSlant" ) ) >>= aFS; + return uno::Any( aFS == awt::FontSlant_ITALIC ); +} + +void SAL_CALL +VbaFontBase::setName( const uno::Any& aValue ) +{ + OUString sString; + aValue >>= sString; + mxFont->setPropertyValue( VBAFONTBASE_PROPNAME( "CharFontName", "FontName" ), aValue ); +} + +uno::Any SAL_CALL +VbaFontBase::getName() +{ + return mxFont->getPropertyValue( VBAFONTBASE_PROPNAME( "CharFontName", "FontName" ) ); +} + +uno::Any +VbaFontBase::getColor() +{ + uno::Any aAny = OORGBToXLRGB( mxFont->getPropertyValue( VBAFONTBASE_PROPNAME( "CharColor", "TextColor" ) ) ); + return aAny; +} + +void +VbaFontBase::setColor( const uno::Any& _color ) +{ + mxFont->setPropertyValue( VBAFONTBASE_PROPNAME( "CharColor", "TextColor" ), XLRGBToOORGB(_color) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbaglobalbase.cxx b/vbahelper/source/vbahelper/vbaglobalbase.cxx new file mode 100644 index 000000000..13273f246 --- /dev/null +++ b/vbahelper/source/vbahelper/vbaglobalbase.cxx @@ -0,0 +1,171 @@ +/* -*- 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 . + */ +#include <vbahelper/vbaglobalbase.hxx> +#include <sal/macros.h> + +#include <comphelper/sequence.hxx> +#include <cppuhelper/component_context.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +using namespace com::sun::star; +using namespace ooo::vba; + +// special key to return the Application +const char sAppService[] = "ooo.vba.Application"; +constexpr OUStringLiteral gsApplication( u"Application" ); + +VbaGlobalsBase::VbaGlobalsBase( +const uno::Reference< ov::XHelperInterface >& xParent, +const uno::Reference< uno::XComponentContext >& xContext, const OUString& sDocCtxName ) + : Globals_BASE( xParent, xContext ) + , msDocCtxName( sDocCtxName ) +{ + // overwrite context with custom one ( that contains the application ) + // wrap the service manager as we don't want the disposing context to tear down the 'normal' ServiceManager ( or at least that's what the code appears like it wants to do ) + uno::Reference< uno::XInterface > aSrvMgr; + if ( xContext.is() && xContext->getServiceManager().is() ) + { + aSrvMgr = xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.comp.stoc.OServiceManagerWrapper" , xContext ); + } + + ::cppu::ContextEntry_Init aHandlerContextInfo[] = + { + ::cppu::ContextEntry_Init( gsApplication, uno::Any() ), + ::cppu::ContextEntry_Init( sDocCtxName, uno::Any() ), + ::cppu::ContextEntry_Init( "/singletons/com.sun.star.lang.theServiceManager" , uno::Any( aSrvMgr ) ) + }; + // don't pass a delegate, this seems to introduce yet another cyclic dependency ( and + // some strange behavior + mxContext = ::cppu::createComponentContext( + aHandlerContextInfo, + SAL_N_ELEMENTS( aHandlerContextInfo ), nullptr ); + if ( !aSrvMgr.is() ) + return; + + try + { + uno::Reference< beans::XPropertySet >( + aSrvMgr, uno::UNO_QUERY_THROW )-> + setPropertyValue( "DefaultContext", uno::Any( mxContext ) ); + } + catch ( uno::RuntimeException & ) + { + throw; + } + catch ( uno::Exception & ) + { + uno::Any e(cppu::getCaughtException()); + throw lang::WrappedTargetRuntimeException( + ("VbaGlobalsBase ctor, setting OServiceManagerWrapper" + " DefaultContext failed"), + uno::Reference< uno::XInterface >(), e); + } +} + +VbaGlobalsBase::~VbaGlobalsBase() +{ + try + { + uno::Reference< container::XNameContainer > xNameContainer( mxContext, uno::UNO_QUERY ); + if ( xNameContainer.is() ) + { + // release document reference (we don't want the component context trying to dispose that) + xNameContainer->removeByName( msDocCtxName ); + // release application reference, as it is holding onto the context + xNameContainer->removeByName( gsApplication ); + } + uno::Reference< lang::XComponent > xComponent( mxContext, uno::UNO_QUERY ); + if (xComponent) + xComponent->dispose(); + } + catch ( const uno::Exception& ) + { + } +} + +void +VbaGlobalsBase::init( const uno::Sequence< beans::PropertyValue >& aInitArgs ) +{ + for ( const auto& rInitArg : aInitArgs ) + { + uno::Reference< container::XNameContainer > xNameContainer( mxContext, uno::UNO_QUERY_THROW ); + if ( rInitArg.Name == gsApplication ) + { + xNameContainer->replaceByName( gsApplication, rInitArg.Value ); + uno::Reference< XHelperInterface > xParent( rInitArg.Value, uno::UNO_QUERY ); + mxParent = xParent; + } + else + xNameContainer->replaceByName( rInitArg.Name, rInitArg.Value ); + } +} + +uno::Reference< uno::XInterface > SAL_CALL +VbaGlobalsBase::createInstance( const OUString& aServiceSpecifier ) +{ + uno::Reference< uno::XInterface > xReturn; + if ( aServiceSpecifier == sAppService ) + { + // try to extract the Application from the context + uno::Reference< container::XNameContainer > xNameContainer( mxContext, uno::UNO_QUERY ); + xNameContainer->getByName( gsApplication ) >>= xReturn; + } + else if ( hasServiceName( aServiceSpecifier ) ) + xReturn = mxContext->getServiceManager()->createInstanceWithContext( aServiceSpecifier, mxContext ); + return xReturn; +} + +uno::Reference< uno::XInterface > SAL_CALL +VbaGlobalsBase::createInstanceWithArguments( const OUString& aServiceSpecifier, const uno::Sequence< uno::Any >& Arguments ) +{ + + uno::Reference< uno::XInterface > xReturn; + if ( aServiceSpecifier == sAppService ) + { + // try to extract the Application from the context + uno::Reference< container::XNameContainer > xNameContainer( mxContext, uno::UNO_QUERY ); + xNameContainer->getByName( gsApplication ) >>= xReturn; + } + else if ( hasServiceName( aServiceSpecifier ) ) + xReturn = mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( aServiceSpecifier, Arguments, mxContext ); + return xReturn; +} + +uno::Sequence< OUString > SAL_CALL +VbaGlobalsBase::getAvailableServiceNames( ) +{ + uno::Sequence< OUString > serviceNames { "ooo.vba.msforms.UserForm" }; + return serviceNames; +} + +bool +VbaGlobalsBase::hasServiceName( const OUString& serviceName ) +{ + uno::Sequence< OUString > sServiceNames( getAvailableServiceNames() ); + return comphelper::findValue(sServiceNames, serviceName) != -1; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbahelper.cxx b/vbahelper/source/vbahelper/vbahelper.cxx new file mode 100644 index 000000000..b0f6b291e --- /dev/null +++ b/vbahelper/source/vbahelper/vbahelper.cxx @@ -0,0 +1,1113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column:100 -*- */ +/* + * 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 . + */ + +#include <com/sun/star/util/URLTransformer.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XModel2.hpp> +#include <com/sun/star/script/BasicErrorException.hpp> +#include <com/sun/star/script/XDefaultProperty.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <com/sun/star/script/Converter.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/theIntrospection.hpp> +#include <com/sun/star/util/MeasureUnit.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XDialog.hpp> +#include <com/sun/star/awt/XUnitConversion.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <ooo/vba/XHelperInterface.hpp> + +#include <comphelper/automationinvokedzone.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/servicehelper.hxx> + +#include <sfx2/objsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/app.hxx> +#include <sfx2/sfxsids.hrc> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/itemset.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/viewfac.hxx> + +#include <basic/sbstar.hxx> +#include <basic/basmgr.hxx> +#include <basic/sbmod.hxx> +#include <basic/sbuno.hxx> +#include <basic/sberrors.hxx> +#include <rtl/ustrbuf.hxx> +#include <sfx2/viewsh.hxx> +#include <sal/log.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> +#include <vcl/syswin.hxx> +#include <tools/diagnose_ex.h> +#include <tools/UnitConversion.hxx> +#include <vbahelper/vbahelper.hxx> + +using namespace ::com::sun::star; +using namespace ::ooo::vba; + + +namespace ooo::vba +{ + +// helper method to determine if the view ( calc ) is in print-preview mode +static bool isInPrintPreview( SfxViewFrame* pView ) +{ + sal_uInt16 nViewNo = SID_VIEWSHELL1 - SID_VIEWSHELL0; + if ( pView->GetObjectShell()->GetFactory().GetViewFactoryCount() > +nViewNo && !pView->GetObjectShell()->IsInPlaceActive() ) + { + SfxViewFactory &rViewFactory = + pView->GetObjectShell()->GetFactory().GetViewFactory(nViewNo); + if ( pView->GetCurViewId() == rViewFactory.GetOrdinal() ) + return true; + } + return false; +} + +uno::Reference< beans::XIntrospectionAccess > +getIntrospectionAccess( const uno::Any& aObject ) +{ + static uno::Reference< beans::XIntrospection > xIntrospection( beans::theIntrospection::get( comphelper::getProcessComponentContext() ) ); + return xIntrospection->inspect( aObject ); +} + +uno::Reference< script::XTypeConverter > const & +getTypeConverter( const uno::Reference< uno::XComponentContext >& xContext ) +{ + static uno::Reference< script::XTypeConverter > xTypeConv( script::Converter::create(xContext) ); + return xTypeConv; +} +const uno::Any& +aNULL() +{ + static uno::Any aNULLL{ uno::Reference< uno::XInterface >() }; + return aNULLL; +} + +void dispatchExecute(SfxViewShell const * pViewShell, sal_uInt16 nSlot) +{ + SfxViewFrame* pViewFrame = nullptr; + if ( pViewShell ) + pViewFrame = pViewShell->GetViewFrame(); + if ( pViewFrame ) + { + SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher(); + if( pDispatcher ) + { + pDispatcher->Execute( nSlot , SfxCallMode::SYNCHRON ); + } + } +} + +void +dispatchRequests (const uno::Reference< frame::XModel>& xModel, const OUString & aUrl, const uno::Sequence< beans::PropertyValue >& sProps ) +{ + util::URL url; + url.Complete = aUrl; + uno::Reference<frame::XController> xController = xModel->getCurrentController(); + uno::Reference<frame::XFrame> xFrame = xController->getFrame(); + uno::Reference<frame::XDispatchProvider> xDispatchProvider (xFrame,uno::UNO_QUERY_THROW); + try + { + uno::Reference<uno::XComponentContext > xContext( + comphelper::getProcessComponentContext() ); + uno::Reference<util::XURLTransformer> xParser( util::URLTransformer::create(xContext) ); + xParser->parseStrict (url); + } + catch (const uno::Exception&) + { + return; + } + + uno::Reference<frame::XDispatch> xDispatcher = xDispatchProvider->queryDispatch(url,"",0); + + sal_Int32 nProps = sProps.getLength(); + uno::Sequence<beans::PropertyValue> dispatchProps(nProps + 1); + + if ( nProps ) + { + std::copy(sProps.begin(), sProps.end(), dispatchProps.getArray()); + } + + if ( xDispatcher.is() ) + { + xDispatcher->dispatch( url, dispatchProps ); + } +} + +void +dispatchRequests( const uno::Reference< frame::XModel>& xModel, const OUString& aUrl ) +{ + uno::Sequence<beans::PropertyValue> dispatchProps; + dispatchRequests( xModel, aUrl, dispatchProps ); +} + +uno::Reference< frame::XModel > +getCurrentDoc( const OUString& sKey ) +{ + uno::Reference< frame::XModel > xModel; + StarBASIC* pBasic = SfxApplication::GetBasic(); + if (pBasic == nullptr) + { + SAL_INFO("vbahelper", "getModelFromBasic() StarBASIC* is NULL" ); + return xModel; + } + SbxObject* basicChosen = pBasic; + SbxObject* pParent = pBasic->GetParent(); + SbxObject* pParentParent = pParent ? pParent->GetParent() : nullptr; + + if( pParentParent ) + { + basicChosen = pParentParent; + } + else if( pParent ) + { + basicChosen = pParent; + } + + + uno::Any aModel; + SbxVariable *pCompVar = basicChosen->Find( sKey, SbxClassType::Object ); + + if ( pCompVar ) + { + aModel = sbxToUnoValue( pCompVar ); + if ( !( aModel >>= xModel ) || !xModel.is() ) + { + throw uno::RuntimeException( + "Can't extract model from basic ( it's obviously not set yet therefore don't know the current document context)" ); + } + SAL_INFO("vbahelper", "Have model points to url " << xModel->getURL()); + } + else + { + SAL_INFO("vbahelper", "Failed to get " << sKey); + throw uno::RuntimeException( "Can't determine the currently selected document" ); + } + return xModel; +} + +/// @throws uno::RuntimeException +static uno::Reference< frame::XModel > +getCurrentDocCtx( const OUString& ctxName, const uno::Reference< uno::XComponentContext >& xContext ) +{ + uno::Reference< frame::XModel > xModel; + // try fallback to calling doc + css::uno::Reference< css::container::XNameAccess > xNameAccess( xContext, css::uno::UNO_QUERY_THROW ); + xModel.set( xNameAccess->getByName( ctxName ), uno::UNO_QUERY_THROW ); + return xModel; +} + +uno::Reference< frame::XModel > +getThisExcelDoc( const uno::Reference< uno::XComponentContext >& xContext ) +{ + return getCurrentDocCtx( "ExcelDocumentContext" , xContext ); +} + +uno::Reference< frame::XModel > +getThisWordDoc( const uno::Reference< uno::XComponentContext >& xContext ) +{ + return getCurrentDocCtx( "WordDocumentContext" , xContext ); +} + + uno::Reference< frame::XModel > +getCurrentExcelDoc( const uno::Reference< uno::XComponentContext >& xContext ) +{ + uno::Reference< frame::XModel > xModel; + try + { + xModel = getCurrentDoc( "ThisExcelDoc" ); + } + catch (const uno::Exception&) + { + try + { + xModel = getThisExcelDoc( xContext ); + } + catch (const uno::Exception&) + { + } + } + return xModel; +} + + uno::Reference< frame::XModel > +getCurrentWordDoc( const uno::Reference< uno::XComponentContext >& xContext ) +{ + uno::Reference< frame::XModel > xModel; + try + { + xModel = getCurrentDoc( "ThisWordDoc" ); + } + catch (const uno::Exception&) + { + try + { + xModel = getThisWordDoc( xContext ); + } + catch (const uno::Exception&) + { + } + } + return xModel; +} + +sal_Int32 +OORGBToXLRGB( sal_Int32 nCol ) +{ + sal_Int32 nAutoBits = nCol; + nAutoBits &= 0xFF000000; + sal_Int32 nRed = nCol; + nRed &= 0x00FF0000; + nRed >>= 16; + sal_Int32 nGreen = nCol; + nGreen &= 0x0000FF00; + nGreen >>= 8; + sal_Int32 nBlue = nCol; + nBlue &= 0x000000FF; + sal_Int32 nRGB = ( nAutoBits | (nBlue << 16) | (nGreen << 8) | nRed ); + return nRGB; +} + +sal_Int32 +XLRGBToOORGB( sal_Int32 nCol ) +{ + sal_Int32 nAutoBits = nCol; + nAutoBits &= 0xFF000000; + + sal_Int32 nBlue = nCol; + nBlue &= 0x00FF0000; + nBlue >>= 16; + sal_Int32 nGreen = nCol; + nGreen &= 0x0000FF00; + nGreen >>= 8; + sal_Int32 nRed = nCol; + nRed &= 0x000000FF; + sal_Int32 nRGB = ( nAutoBits | (nRed << 16) | (nGreen << 8) | nBlue ); + return nRGB; +} +uno::Any +OORGBToXLRGB( const uno::Any& aCol ) +{ + sal_Int32 nCol(0); + aCol >>= nCol; + nCol = OORGBToXLRGB( nCol ); + return uno::Any( nCol ); +} +uno::Any +XLRGBToOORGB( const uno::Any& aCol ) +{ + sal_Int32 nCol(0); + aCol >>= nCol; + nCol = XLRGBToOORGB( nCol ); + return uno::Any( nCol ); +} + +void PrintOutHelper( SfxViewShell const * pViewShell, const uno::Any& From, const uno::Any& To, const uno::Any& Copies, const uno::Any& Preview, const uno::Any& /*ActivePrinter*/, const uno::Any& /*PrintToFile*/, const uno::Any& Collate, const uno::Any& PrToFileName, bool bUseSelection ) +{ + sal_Int32 nTo = 0; + sal_Int32 nFrom = 0; + sal_Int16 nCopies = 1; + bool bPreview = false; + bool bCollate = false; + bool bSelection = bUseSelection; + From >>= nFrom; + To >>= nTo; + Copies >>= nCopies; + Preview >>= bPreview; + if ( nCopies > 1 ) // Collate only useful when more that 1 copy + Collate >>= bCollate; + + OUString sRange( "-" ); + OUString sFileName; + + if ( nFrom || nTo ) + { + if ( nFrom ) + sRange = OUString::number( nFrom ) + sRange; + if ( nTo ) + sRange += OUString::number( nTo ); + } + + PrToFileName >>= sFileName; + SfxViewFrame* pViewFrame = nullptr; + if ( pViewShell ) + pViewFrame = pViewShell->GetViewFrame(); + if ( !pViewFrame ) + return; + + SfxAllItemSet aArgs( SfxGetpApp()->GetPool() ); + + SfxBoolItem sfxCollate( SID_PRINT_COLLATE, bCollate ); + aArgs.Put( sfxCollate, sfxCollate.Which() ); + SfxInt16Item sfxCopies( SID_PRINT_COPIES, nCopies ); + aArgs.Put( sfxCopies, sfxCopies.Which() ); + if ( !sFileName.isEmpty() ) + { + SfxStringItem sfxFileName( SID_FILE_NAME, sFileName); + aArgs.Put( sfxFileName, sfxFileName.Which() ); + + } + if ( !sRange.isEmpty() ) + { + SfxStringItem sfxRange( SID_PRINT_PAGES, sRange ); + aArgs.Put( sfxRange, sfxRange.Which() ); + } + SfxBoolItem sfxSelection( SID_SELECTION, bSelection ); + aArgs.Put( sfxSelection, sfxSelection.Which() ); + SfxBoolItem sfxAsync( SID_ASYNCHRON, false ); + aArgs.Put( sfxAsync, sfxAsync.Which() ); + SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher(); + + if ( !pDispatcher ) + return; + + if ( bPreview ) + { + if ( !pViewFrame->GetFrame().IsInPlace() ) + { + // #TODO is this necessary ( calc specific ) +// SC_MOD()->InputEnterHandler(); + pViewFrame->GetDispatcher()->Execute( SID_VIEWSHELL1, SfxCallMode::SYNCHRON ); + WaitUntilPreviewIsClosed( pViewFrame ); + } + } + else + pDispatcher->Execute( sal_uInt16(SID_PRINTDOC), SfxCallMode::SYNCHRON, aArgs ); + + + // #FIXME #TODO + // 1 ActivePrinter ( how/can we switch a printer via API? ) + // 2 PrintToFile ( ms behaviour if this option is specified but no + // filename supplied 'PrToFileName' then the user will be prompted ) + // 3 Need to check behaviour of Selected sheets with range ( e.g. From & To + // values ) in oOO these options are mutually exclusive + // 4 There is a pop up to do with transparent objects in the print source + // should be able to disable that via configuration for the duration + // of this method +} + +void PrintPreviewHelper( const css::uno::Any& /*EnableChanges*/, SfxViewShell const * pViewShell ) +{ + SfxViewFrame* pViewFrame = nullptr; + if ( pViewShell ) + pViewFrame = pViewShell->GetViewFrame(); + if ( pViewFrame ) + { + if ( !pViewFrame->GetFrame().IsInPlace() ) + { + dispatchExecute( pViewShell, SID_VIEWSHELL1 ); + WaitUntilPreviewIsClosed( pViewFrame ); + } + } +} + +void WaitUntilPreviewIsClosed( SfxViewFrame* pViewFrame ) +{ + while ( pViewFrame && isInPrintPreview( pViewFrame ) && !Application::IsQuit()) + Application::Yield(); +} + +bool extractBoolFromAny( const uno::Any& rAny ) +{ + switch( rAny.getValueType().getTypeClass() ) + { + case uno::TypeClass_BOOLEAN: + return rAny.get< bool >(); + case uno::TypeClass_FLOAT: + return rAny.get< float >() != 0.0; + case uno::TypeClass_DOUBLE: + return rAny.get< double >() != 0.0; + case uno::TypeClass_BYTE: + case uno::TypeClass_SHORT: + case uno::TypeClass_LONG: + return rAny.get< sal_Int32 >() != 0; + case uno::TypeClass_HYPER: + return rAny.get< sal_Int64 >() != 0; + default:; + } + throw uno::RuntimeException( "Invalid type, cannot convert to boolean." , nullptr ); +} + +OUString extractStringFromAny( const uno::Any& rAny, bool bUppercaseBool ) +{ + switch( rAny.getValueType().getTypeClass() ) + { + case uno::TypeClass_STRING: + return rAny.get< OUString >(); + case uno::TypeClass_BOOLEAN: + return bUppercaseBool ? + (rAny.get< bool >() ? OUString( "TRUE" ) : OUString( "FALSE" )) : + OUString::boolean( rAny.get< bool >() ); + case uno::TypeClass_FLOAT: + return OUString::number( rAny.get< float >() ); + case uno::TypeClass_DOUBLE: + return OUString::number( rAny.get< double >() ); + case uno::TypeClass_BYTE: + case uno::TypeClass_SHORT: + case uno::TypeClass_LONG: + return OUString::number( rAny.get< sal_Int32 >() ); + case uno::TypeClass_HYPER: + return OUString::number( rAny.get< sal_Int64 >() ); + default:; + } + throw uno::RuntimeException( "Invalid type, cannot convert to string." , nullptr ); +} + +OUString extractStringFromAny( const uno::Any& rAny, const OUString& rDefault, bool bUppercaseBool ) +{ + return rAny.hasValue() ? extractStringFromAny( rAny, bUppercaseBool ) : rDefault; +} + +OUString getAnyAsString( const uno::Any& pvargItem ) +{ + return extractStringFromAny( pvargItem ); +} + + +OUString +ContainerUtilities::getUniqueName( const uno::Sequence< OUString >& _slist, const OUString& _sElementName, std::u16string_view _sSuffixSeparator) +{ + return getUniqueName(_slist, _sElementName, _sSuffixSeparator, sal_Int32(2)); +} + +OUString +ContainerUtilities::getUniqueName( const uno::Sequence< OUString >& _slist, const OUString& _sElementName, std::u16string_view _sSuffixSeparator, sal_Int32 _nStartSuffix) +{ + if ( !_slist.hasElements() ) + return _sElementName; + + OUString scompname = _sElementName; + sal_Int32 a = _nStartSuffix; + + for (;;) + { + if (FieldInList(_slist, scompname) == -1) + return scompname; + + scompname = _sElementName + _sSuffixSeparator + OUString::number( a++ ); + } +} + +sal_Int32 +ContainerUtilities::FieldInList( const uno::Sequence< OUString >& SearchList, const OUString& SearchString ) +{ + // I wonder why comparing lexicographically is done + // when it's a match, is it interesting? + return comphelper::findValue(SearchList, SearchString); +} + +static bool NeedEsc(sal_Unicode cCode) +{ + return OUString(".^$+\\|{}()").indexOf(cCode) != -1; +} + +OUString VBAToRegexp(const OUString &rIn) +{ + OUStringBuffer sResult; + const sal_Unicode *start = rIn.getStr(); + const sal_Unicode *end = start + rIn.getLength(); + + int seenright = 0; + + while (start < end) + { + switch (*start) + { + case '?': + sResult.append('.'); + start++; + break; + case '*': + sResult.append(".*"); + start++; + break; + case '#': + sResult.append("[0-9]"); + start++; + break; + case '~': + sResult.append('\\'); + sResult.append(*(++start)); + start++; + break; + // dump the ~ and escape the next character + case ']': + sResult.append('\\'); + sResult.append(*start++); + break; + case '[': + sResult.append(*start++); + seenright = 0; + while (start < end && !seenright) + { + switch (*start) + { + case '[': + case '?': + case '*': + sResult.append('\\'); + sResult.append(*start); + break; + case ']': + sResult.append(*start); + seenright = 1; + break; + case '!': + sResult.append('^'); + break; + default: + if (NeedEsc(*start)) + sResult.append('\\'); + sResult.append(*start); + break; + } + start++; + } + break; + default: + if (NeedEsc(*start)) + sResult.append('\\'); + sResult.append(*start++); + } + } + + return sResult.makeStringAndClear( ); +} + +double getPixelTo100thMillimeterConversionFactor( const css::uno::Reference< css::awt::XDevice >& xDevice, bool bVertical) +{ + double fConvertFactor = 1.0; + if( bVertical ) + { + fConvertFactor = xDevice->getInfo().PixelPerMeterY/100000; + } + else + { + fConvertFactor = xDevice->getInfo().PixelPerMeterX/100000; + } + return fConvertFactor; +} + +double PointsToPixels( const css::uno::Reference< css::awt::XDevice >& xDevice, double fPoints, bool bVertical) +{ + double fConvertFactor = getPixelTo100thMillimeterConversionFactor( xDevice, bVertical ); + return convertPointToMm100(fPoints) * fConvertFactor; +} +double PixelsToPoints( const css::uno::Reference< css::awt::XDevice >& xDevice, double fPixels, bool bVertical) +{ + double fConvertFactor = getPixelTo100thMillimeterConversionFactor( xDevice, bVertical ); + return convertMm100ToPoint(fPixels / fConvertFactor); +} + +sal_Int32 PointsToHmm(double fPoints) { return std::round(convertPointToMm100(fPoints)); } + +double HmmToPoints(sal_Int32 nHmm) { return convertMm100ToPoint<double>(nHmm); } + +ConcreteXShapeGeometryAttributes::ConcreteXShapeGeometryAttributes( const css::uno::Reference< css::drawing::XShape >& xShape ) +{ + m_pShapeHelper.reset( new ShapeHelper( xShape ) ); +} +ConcreteXShapeGeometryAttributes::~ConcreteXShapeGeometryAttributes() +{ +} + +PointerStyle getPointerStyle( const uno::Reference< frame::XModel >& xModel ) +{ + + PointerStyle nPointerStyle( PointerStyle::Arrow ); + try + { + const uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_SET_THROW ); + const uno::Reference< frame::XFrame > xFrame ( xController->getFrame(), uno::UNO_SET_THROW ); + const uno::Reference< awt::XWindow > xWindow ( xFrame->getContainerWindow(), uno::UNO_SET_THROW ); + // why the heck isn't there an XWindowPeer::getPointer, but a setPointer only? + const vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); + if ( pWindow ) + nPointerStyle = pWindow->GetSystemWindow()->GetPointer(); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("vbahelper"); + } + return nPointerStyle; +} + +// #FIXME this method looks wrong, shouldn't it just affect calc *or* writer +// document/frame/window(s) but not both ( and depending on what api called +// this ) +void setCursorHelper( const uno::Reference< frame::XModel >& xModel, PointerStyle nPointer, bool bOverWrite ) +{ + ::std::vector< uno::Reference< frame::XController > > aControllers; + + uno::Reference< frame::XModel2 > xModel2( xModel, uno::UNO_QUERY ); + if ( xModel2.is() ) + { + const uno::Reference< container::XEnumeration > xEnumControllers( xModel2->getControllers(), uno::UNO_SET_THROW ); + while ( xEnumControllers->hasMoreElements() ) + { + const uno::Reference< frame::XController > xController( xEnumControllers->nextElement(), uno::UNO_QUERY_THROW ); + aControllers.push_back( xController ); + } + } + else + { + if ( xModel.is() ) + { + const uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_SET_THROW ); + aControllers.push_back( xController ); + } + } + + for ( const auto& rController : aControllers ) + { + const uno::Reference< frame::XFrame > xFrame ( rController->getFrame(), uno::UNO_SET_THROW ); + const uno::Reference< awt::XWindow > xWindow ( xFrame->getContainerWindow(), uno::UNO_SET_THROW ); + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow ); + SAL_WARN_IF( !pWindow, "vbahelper", "ScVbaApplication::setCursor: no window!" ); + if ( !pWindow ) + continue; + + pWindow->GetSystemWindow()->SetPointer( nPointer ); + pWindow->GetSystemWindow()->EnableChildPointerOverwrite( bOverWrite ); + } +} + +void setDefaultPropByIntrospection( const uno::Any& aObj, const uno::Any& aValue ) +{ + uno::Reference< beans::XIntrospectionAccess > xUnoAccess( getIntrospectionAccess( aObj ) ); + + // #MAYBE #FIXME sort of a bit of a hack, + uno::Reference< script::XDefaultProperty > xDflt( aObj, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xPropSet; + + if ( xUnoAccess.is() ) + xPropSet.set( xUnoAccess->queryAdapter( cppu::UnoType<beans::XPropertySet>::get()), uno::UNO_QUERY); + + if ( !xPropSet.is() ) + throw uno::RuntimeException(); + + xPropSet->setPropertyValue( xDflt->getDefaultPropertyName(), aValue ); +} + +uno::Any getPropertyValue( const uno::Sequence< beans::PropertyValue >& aProp, const OUString& aName ) +{ + auto pProp = std::find_if(aProp.begin(), aProp.end(), + [&aName](const beans::PropertyValue& rProp) { return rProp.Name == aName; }); + if (pProp != aProp.end()) + return pProp->Value; + return uno::Any(); +} + +bool setPropertyValue( uno::Sequence< beans::PropertyValue >& aProp, const OUString& aName, const uno::Any& aValue ) +{ + auto [begin, end] = asNonConstRange(aProp); + auto pProp = std::find_if(begin, end, + [&aName](const beans::PropertyValue& rProp) { return rProp.Name == aName; }); + if (pProp != end) + { + pProp->Value = aValue; + return true; + } + return false; +} + +void setOrAppendPropertyValue( uno::Sequence< beans::PropertyValue >& aProp, const OUString& aName, const uno::Any& aValue ) +{ + if( setPropertyValue( aProp, aName, aValue ) ) + return; + + // append the property + sal_Int32 nLength = aProp.getLength(); + aProp.realloc( nLength + 1 ); + auto pProp = aProp.getArray(); + pProp[ nLength ].Name = aName; + pProp[ nLength ].Value = aValue; +} + +// ====UserFormGeomentryHelper==== + +UserFormGeometryHelper::UserFormGeometryHelper( + const uno::Reference< awt::XControl >& xControl, + double fOffsetX, double fOffsetY ) : + mfOffsetX( fOffsetX ), + mfOffsetY( fOffsetY ), + mbDialog( uno::Reference< awt::XDialog >( xControl, uno::UNO_QUERY ).is() ) +{ + if ( !xControl.is() ) + throw uno::RuntimeException( "No control is provided!" ); + + mxWindow.set( xControl->getPeer(), uno::UNO_QUERY_THROW ); + mxModelProps.set( xControl->getModel(), uno::UNO_QUERY_THROW ); + mxUnitConv.set( mxWindow, uno::UNO_QUERY_THROW ); +} + +double UserFormGeometryHelper::getLeft() const +{ + return implGetPos( false ); +} + +void UserFormGeometryHelper::setLeft( double fLeft ) +{ + implSetPos( fLeft, false ); +} + +double UserFormGeometryHelper::getTop() const +{ + return implGetPos( true ); +} + +void UserFormGeometryHelper::setTop( double fTop ) +{ + implSetPos( fTop, true ); +} + +double UserFormGeometryHelper::getWidth() const +{ + return implGetSize( false, true ); +} + +void UserFormGeometryHelper::setWidth( double fWidth ) +{ + implSetSize( fWidth, false, true ); +} + +double UserFormGeometryHelper::getHeight() const +{ + return implGetSize( true, true ); +} + +void UserFormGeometryHelper::setHeight( double fHeight ) +{ + implSetSize( fHeight, true, true ); +} + +double UserFormGeometryHelper::getInnerWidth() const +{ + return implGetSize( false, false ); +} + +void UserFormGeometryHelper::setInnerWidth( double fWidth ) +{ + implSetSize( fWidth, false, false ); +} + +double UserFormGeometryHelper::getInnerHeight() const +{ + return implGetSize( true, false ); +} + +void UserFormGeometryHelper::setInnerHeight( double fHeight ) +{ + implSetSize( fHeight, true, false ); +} + +double UserFormGeometryHelper::getOffsetX() const +{ + return mfOffsetX; +} + +double UserFormGeometryHelper::getOffsetY() const +{ + return mfOffsetY; +} + +constexpr OUStringLiteral saPosXName = u"PositionX"; +constexpr OUStringLiteral saPosYName = u"PositionY"; +constexpr OUStringLiteral saWidthName = u"Width"; +constexpr OUStringLiteral saHeightName = u"Height"; + +double UserFormGeometryHelper::implGetPos( bool bPosY ) const +{ + sal_Int32 nPosAppFont = mxModelProps->getPropertyValue( bPosY ? OUString(saPosYName) : OUString(saPosXName) ).get< sal_Int32 >(); + // appfont to pixel + awt::Point aPosPixel = mxUnitConv->convertPointToPixel( awt::Point( nPosAppFont, nPosAppFont ), util::MeasureUnit::APPFONT ); + // pixel to VBA points + awt::Point aPosPoint = mxUnitConv->convertPointToLogic( aPosPixel, util::MeasureUnit::POINT ); + return bPosY ? (aPosPoint.Y - mfOffsetY) : (aPosPoint.X - mfOffsetX); +} + +void UserFormGeometryHelper::implSetPos( double fPos, bool bPosY ) +{ + // convert passed VBA points to pixels + sal_Int32 nPosPixel = static_cast< sal_Int32 >( fPos + (bPosY ? mfOffsetY : mfOffsetX) ); + awt::Point aPosPixel = mxUnitConv->convertPointToPixel( awt::Point( nPosPixel, nPosPixel ), util::MeasureUnit::POINT ); + // pixel to appfont + awt::Point aPosAppFont = mxUnitConv->convertPointToLogic( aPosPixel, util::MeasureUnit::APPFONT ); + mxModelProps->setPropertyValue( bPosY ? OUString(saPosYName) : OUString(saPosXName), uno::Any( bPosY ? aPosAppFont.Y : aPosAppFont.X ) ); +} + +double UserFormGeometryHelper::implGetSize( bool bHeight, bool bOuter ) const +{ + sal_Int32 nSizeAppFont = mxModelProps->getPropertyValue( bHeight ? OUString(saHeightName) : OUString(saWidthName) ).get< sal_Int32 >(); + // appfont to pixel + awt::Size aSizePixel = mxUnitConv->convertSizeToPixel( awt::Size( nSizeAppFont, nSizeAppFont ), util::MeasureUnit::APPFONT ); + + /* The VBA symbols 'Width' and 'Height' return the outer size including + window decoration (in difference to the symbols 'InnerWidth' and + 'InnerHeight'), but the window API returns the inner size. */ + if( mbDialog && bOuter ) + { + if( const vcl::Window* pWindow = VCLUnoHelper::GetWindow( mxWindow ) ) + { + tools::Rectangle aOuterRect = pWindow->GetWindowExtentsRelative( nullptr ); + aSizePixel = awt::Size( aOuterRect.getWidth(), aOuterRect.getHeight() ); + } + } + + // pixel to VBA points + awt::Size aSizePoint = mxUnitConv->convertSizeToLogic( aSizePixel, util::MeasureUnit::POINT ); + return bHeight ? aSizePoint.Height : aSizePoint.Width; +} + +void UserFormGeometryHelper::implSetSize( double fSize, bool bHeight, bool bOuter ) +{ + // convert passed VBA points to pixels + sal_Int32 nSize = static_cast< sal_Int32 >( fSize ); + awt::Size aSizePixel = mxUnitConv->convertSizeToPixel( awt::Size( nSize, nSize ), util::MeasureUnit::POINT ); + + /* The VBA symbols 'Width' and 'Height' set the outer size (in difference + to the symbols 'InnerWidth' and 'InnerHeight'), but the dialog model + expects the inner size. We have to remove the window extents from the + pixel height to get the same result. */ + if ( mbDialog && bOuter ) + { + if( const vcl::Window* pWindow = VCLUnoHelper::GetWindow( mxWindow ) ) + { + tools::Rectangle aOuterRect = pWindow->GetWindowExtentsRelative( nullptr ); + if( !aOuterRect.IsEmpty() ) + { + awt::Rectangle aInnerRect = mxWindow->getPosSize(); + sal_Int32 nDecorWidth = aOuterRect.getWidth() - aInnerRect.Width; + sal_Int32 nDecorHeight = aOuterRect.getHeight() - aInnerRect.Height; + aSizePixel.Width = ::std::max< sal_Int32 >( aSizePixel.Width - nDecorWidth, 1 ); + aSizePixel.Height = ::std::max< sal_Int32 >( aSizePixel.Height - nDecorHeight, 1 ); + } + } + } + + awt::Size aSizeAppFont = mxUnitConv->convertSizeToLogic( aSizePixel, util::MeasureUnit::APPFONT ); + mxModelProps->setPropertyValue( bHeight ? OUString(saHeightName) : OUString(saWidthName), uno::Any( bHeight ? aSizeAppFont.Height : aSizeAppFont.Width ) ); +} + + +double ConcreteXShapeGeometryAttributes::getLeft() const +{ + return m_pShapeHelper->getLeft(); +} +void ConcreteXShapeGeometryAttributes::setLeft( double nLeft ) +{ + m_pShapeHelper->setLeft( nLeft ); +} +double ConcreteXShapeGeometryAttributes::getTop() const +{ + return m_pShapeHelper->getTop(); +} +void ConcreteXShapeGeometryAttributes::setTop( double nTop ) +{ + m_pShapeHelper->setTop( nTop ); +} + +double ConcreteXShapeGeometryAttributes::getHeight() const +{ + return m_pShapeHelper->getHeight(); +} +void ConcreteXShapeGeometryAttributes::setHeight( double nHeight ) +{ + m_pShapeHelper->setHeight( nHeight ); +} +double ConcreteXShapeGeometryAttributes::getWidth() const +{ + return m_pShapeHelper->getWidth(); +} +void ConcreteXShapeGeometryAttributes::setWidth( double nWidth) +{ + m_pShapeHelper->setWidth( nWidth ); +} + + +ShapeHelper::ShapeHelper( const css::uno::Reference< css::drawing::XShape >& _xShape) + : xShape( _xShape ) +{ + if( !xShape.is() ) + throw css::uno::RuntimeException( "No valid shape for helper" ); +} + +double ShapeHelper::getHeight() const +{ + return Millimeter::getInPoints(xShape->getSize().Height); +} + +void ShapeHelper::setHeight(double _fheight) +{ + css::awt::Size aSize = xShape->getSize(); + aSize.Height = Millimeter::getInHundredthsOfOneMillimeter(_fheight); + xShape->setSize(aSize); +} + +double ShapeHelper::getWidth() const +{ + return Millimeter::getInPoints(xShape->getSize().Width); +} + +void ShapeHelper::setWidth(double _fWidth) +{ + css::awt::Size aSize = xShape->getSize(); + aSize.Width = Millimeter::getInHundredthsOfOneMillimeter(_fWidth); + xShape->setSize(aSize); +} + +double ShapeHelper::getLeft() const +{ + return Millimeter::getInPoints(xShape->getPosition().X); +} + +void ShapeHelper::setLeft(double _fLeft) +{ + css::awt::Point aPoint = xShape->getPosition(); + aPoint.X = Millimeter::getInHundredthsOfOneMillimeter(_fLeft); + xShape->setPosition(aPoint); +} + +double ShapeHelper::getTop() const +{ + return Millimeter::getInPoints(xShape->getPosition().Y); +} + +void ShapeHelper::setTop(double _fTop) +{ + css::awt::Point aPoint = xShape->getPosition(); + aPoint.Y = Millimeter::getInHundredthsOfOneMillimeter(_fTop); + xShape->setPosition(aPoint); +} + +void DebugHelper::basicexception( const css::uno::Exception& ex, ErrCode err, std::u16string_view /*additionalArgument*/ ) +{ + // #TODO #FIXME ( do we want to support additionalArg here ) + throw css::script::BasicErrorException( ex.Message, css::uno::Reference< css::uno::XInterface >(), sal_uInt32(err), OUString() ); +} + +void DebugHelper::basicexception( ErrCode err, std::u16string_view additionalArgument ) +{ + basicexception( css::uno::Exception(), err, additionalArgument ); +} + +void DebugHelper::basicexception( const css::uno::Exception& ex ) +{ + basicexception( ex, ERRCODE_BASIC_INTERNAL_ERROR, {} ); +} + +void DebugHelper::runtimeexception( ErrCode err ) +{ + // #TODO #FIXME ( do we want to support additionalArg here ) + throw css::uno::RuntimeException( css::uno::Exception().Message + " " + OUString::number(sal_uInt32(err)), + css::uno::Reference< css::uno::XInterface >() ); +} + +Millimeter::Millimeter():m_nMillimeter(0) {} + +Millimeter::Millimeter(double mm):m_nMillimeter(mm) {} + +void Millimeter::setInPoints(double points) +{ + m_nMillimeter = convertPointToMm100(points) / 100.0; +} + +double Millimeter::getInHundredthsOfOneMillimeter() const +{ + return m_nMillimeter * 100; +} + +sal_Int32 Millimeter::getInHundredthsOfOneMillimeter(double points) +{ + sal_Int32 mm = std::round(convertPointToMm100(points)); + return mm; +} + +double Millimeter::getInPoints(int _hmm) +{ + double points = convertMm100ToPoint<double>(_hmm); + return points; +} + +uno::Reference< XHelperInterface > getVBADocument( const uno::Reference< frame::XModel >& xModel ) +{ + uno::Reference< XHelperInterface > xIf; + try + { + uno::Reference< beans::XPropertySet > xDocProps( xModel, uno::UNO_QUERY_THROW ); + OUString aCodeName; + xDocProps->getPropertyValue( "CodeName" ) >>= aCodeName; + xIf = getUnoDocModule( aCodeName, getSfxObjShell( xModel ) ); + } + catch (const uno::Exception&) + { + } + return xIf; +} + +uno::Reference< XHelperInterface > getUnoDocModule( std::u16string_view aModName, SfxObjectShell const * pShell ) +{ + uno::Reference< XHelperInterface > xIf; + if ( pShell ) + { + OUString sProj( "Standard" ); + // GetBasicManager() causes a SolarMutex assertion failure in some use cases from + // Automation, at least when opening a Calc Document through ooo::vba::excel:: + // XWorkbooks::Open(). Let's see if this check is a good way around that. It does seem that + // callers are prepared for this to return null? + if (comphelper::Automation::AutomationInvokedZone::isActive()) + return xIf; + BasicManager* pBasMgr = pShell->GetBasicManager(); + if ( pBasMgr && !pBasMgr->GetName().isEmpty() ) + sProj = pBasMgr->GetName(); + if( StarBASIC* pBasic = pShell->GetBasicManager()->GetLib( sProj ) ) + if( SbModule* pMod = pBasic->FindModule( aModName ) ) + xIf.set( pMod->GetUnoModule(), uno::UNO_QUERY ); + } + return xIf; +} + +SfxObjectShell* getSfxObjShell( const uno::Reference< frame::XModel >& xModel ) +{ + SfxObjectShell* pFoundShell = comphelper::getFromUnoTunnel<SfxObjectShell>(xModel); + if ( !pFoundShell ) + throw uno::RuntimeException(); + return pFoundShell; +} + +} //org + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbalineformat.cxx b/vbahelper/source/vbahelper/vbalineformat.cxx new file mode 100644 index 000000000..2f5bf2140 --- /dev/null +++ b/vbahelper/source/vbahelper/vbalineformat.cxx @@ -0,0 +1,442 @@ +/* -*- 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 . + */ +#include <ooo/vba/office/MsoArrowheadStyle.hpp> +#include <ooo/vba/office/MsoLineDashStyle.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include "vbalineformat.hxx" +#include "vbacolorformat.hxx" + +using namespace ooo::vba; +using namespace com::sun::star; + +ScVbaLineFormat::ScVbaLineFormat( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< drawing::XShape >& xShape ) : ScVbaLineFormat_BASE( xParent, xContext ), m_xShape( xShape ) +{ + m_xPropertySet.set( xShape, uno::UNO_QUERY_THROW ); + m_nLineDashStyle = office::MsoLineDashStyle::msoLineSolid; + m_nLineWeight = 1; +} + +sal_Int32 +ScVbaLineFormat::convertLineStartEndNameToArrowheadStyle( std::u16string_view sLineName ) +{ + sal_Int32 nLineType = office::MsoArrowheadStyle::msoArrowheadNone; + if ( sLineName == u"Small Arrow" || sLineName == u"Arrow" || sLineName == u"msArrowEnd" || sLineName == u"Double Arrow") + { + // msoArrowheadTriangle + nLineType = office::MsoArrowheadStyle::msoArrowheadTriangle; + } + else if ( sLineName == u"Square 45" || sLineName == u"Square" || sLineName == u"msArrowDiamondEnd") + { + // msoArrowheadDiamond + nLineType = office::MsoArrowheadStyle::msoArrowheadDiamond; + } + else if (sLineName == u"Circle" || sLineName == u"msArrowOvalEnd" || sLineName == u"Dimension Lines" ) + { + // msoArrowheadOval + nLineType = office::MsoArrowheadStyle::msoArrowheadOval; + } + else if ( sLineName == u"Arrow concave" || sLineName == u"msArrowStealthEnd" ) + { + // msoArrowheadStealth + nLineType = office::MsoArrowheadStyle::msoArrowheadStealth; + } + else if ( sLineName == u"Rounded short Arrow" || sLineName == u"Rounded large Arrow" || sLineName == u"Symmetric Arrow" + || sLineName == u"msArrowOpenEnd" || sLineName == u"Line Arrow" ) + { + // msoArrowheadOpen + nLineType = office::MsoArrowheadStyle::msoArrowheadOpen; + } + else + { + // msoArrowheadNone + nLineType = office::MsoArrowheadStyle::msoArrowheadNone; + } + return nLineType; +} + +OUString +ScVbaLineFormat::convertArrowheadStyleToLineStartEndName( sal_Int32 nArrowheadStyle ) +{ + switch( nArrowheadStyle ) + { + case office::MsoArrowheadStyle::msoArrowheadNone: + return OUString(); + case office::MsoArrowheadStyle::msoArrowheadStealth: + return "Arrow concave"; + case office::MsoArrowheadStyle::msoArrowheadOpen: + return "Line Arrow"; + case office::MsoArrowheadStyle::msoArrowheadOval: + return "Circle"; + case office::MsoArrowheadStyle::msoArrowheadDiamond: + return "Square 45"; + case office::MsoArrowheadStyle::msoArrowheadTriangle: + return "Arrow"; + default: + throw uno::RuntimeException( "Invalid Arrow Style!" ); + } +} + +// Attributes +sal_Int32 SAL_CALL +ScVbaLineFormat::getBeginArrowheadStyle() +{ + sal_Int32 nLineType = office::MsoArrowheadStyle::msoArrowheadNone; + OUString sLineName; + m_xPropertySet->getPropertyValue( "LineStartName" ) >>= sLineName; + if( ( sLineName.getLength() > 7 ) && ( sLineName.indexOf( "msArray" ) ) != -1 ) + { + sal_Int32 nIndex = sLineName.indexOf( ' ' ); + OUString sName = sLineName.copy( 0, nIndex ); + //sal_Int32 nSize = o3tl::toInt32(sLineName.subView( nIndex + 1 )); + nLineType = convertLineStartEndNameToArrowheadStyle( sName ); + } + else + { + nLineType = convertLineStartEndNameToArrowheadStyle( sLineName ); + } + return nLineType; +} + +void SAL_CALL +ScVbaLineFormat::setBeginArrowheadStyle( sal_Int32 _beginarrowheadstyle ) +{ + OUString sArrayName = convertArrowheadStyleToLineStartEndName( _beginarrowheadstyle ); + m_xPropertySet->setPropertyValue( "LineStartName" , uno::Any( sArrayName ) ); +} + +sal_Int32 SAL_CALL +ScVbaLineFormat::getBeginArrowheadLength() +{ + // #STUB + // force error + throw uno::RuntimeException( "Property 'EndArrowheadWidth' is not supported." ); +} + +void SAL_CALL +ScVbaLineFormat::setBeginArrowheadLength( sal_Int32 /*_beginarrowheadlength*/ ) +{ + // #STUB + // force error + throw uno::RuntimeException( "Property 'EndArrowheadWidth' is not supported." ); +} + +sal_Int32 SAL_CALL +ScVbaLineFormat::getBeginArrowheadWidth() +{ + // #STUB + // force error + throw uno::RuntimeException( "Property 'EndArrowheadWidth' is not supported." ); +} + +void SAL_CALL +ScVbaLineFormat::setBeginArrowheadWidth( sal_Int32 /*_beginarrowheadwidth*/ ) +{ + // #STUB + // force error + throw uno::RuntimeException( "Property 'EndArrowheadWidth' is not supported." ); +} + +sal_Int32 SAL_CALL +ScVbaLineFormat::getEndArrowheadStylel() +{ + // #STUB + return 0; +} + +void SAL_CALL +ScVbaLineFormat::setEndArrowheadStylel( sal_Int32 /*_endarrowheadstylel*/ ) +{ + // #STUB +} + +sal_Int32 SAL_CALL +ScVbaLineFormat::getEndArrowheadLength() +{ + // #STUB + // force error + throw uno::RuntimeException( "Property 'EndArrowheadWidth' is not supported." ); +} + +void SAL_CALL +ScVbaLineFormat::setEndArrowheadLength( sal_Int32 /*_endarrowheadlength*/ ) +{ + // #STUB + throw uno::RuntimeException( "Property 'EndArrowheadWidth' is not supported." ); +} + +sal_Int32 SAL_CALL +ScVbaLineFormat::getEndArrowheadWidth() +{ + // #STUB + throw uno::RuntimeException( "Property 'EndArrowheadWidth' is not supported." ); +} + +void SAL_CALL +ScVbaLineFormat::setEndArrowheadWidth( sal_Int32 /*_endarrowheadwidth*/ ) +{ + // #STUB + throw uno::RuntimeException( "Property 'EndArrowheadWidth' is not supported." ); +} + +double SAL_CALL +ScVbaLineFormat::getWeight() +{ + sal_Int32 nLineWidth=0; + m_xPropertySet->getPropertyValue( "LineWidth" ) >>= nLineWidth; + double dLineWidth = Millimeter::getInPoints( nLineWidth ); + return dLineWidth; +} + +void SAL_CALL +ScVbaLineFormat::setWeight( double _weight ) +{ + if( _weight < 0 ) + throw uno::RuntimeException( "Parameter: Must be positive." ); + if( _weight == 0 ) + _weight = 0.5; + m_nLineWeight = _weight; + Millimeter aMillimeter; + aMillimeter.setInPoints( _weight ); + + sal_Int32 nLineWidth = static_cast<sal_Int32>( aMillimeter.getInHundredthsOfOneMillimeter() ); + m_xPropertySet->setPropertyValue( "LineWidth" , uno::Any( nLineWidth ) ); + setDashStyle( m_nLineDashStyle ); +} + +sal_Bool SAL_CALL +ScVbaLineFormat::getVisible() +{ + drawing::LineStyle aLineStyle; + m_xPropertySet->getPropertyValue( "LineStyle" ) >>= aLineStyle; + if( aLineStyle == drawing::LineStyle_NONE ) + { + return false; + } + return true; +} + +void SAL_CALL +ScVbaLineFormat::setVisible( sal_Bool _visible ) +{ + drawing::LineStyle aLineStyle; + m_xPropertySet->getPropertyValue( "LineStyle" ) >>= aLineStyle; + if( !_visible ) + { + aLineStyle = drawing::LineStyle_NONE; + m_xPropertySet->setPropertyValue( "LineStyle" , uno::Any( aLineStyle ) ); + } + else + { + if( aLineStyle == drawing::LineStyle_NONE ) + { + setDashStyle( m_nLineDashStyle ); + } + } +} + +double SAL_CALL +ScVbaLineFormat::getTransparency() +{ + sal_Int16 nTransparency = 0; + m_xPropertySet->getPropertyValue( "LineTransparence" ) >>= nTransparency; + double fTransparency = static_cast<double>( nTransparency ); + return fTransparency / 100; +} + +void SAL_CALL +ScVbaLineFormat::setTransparency( double _transparency ) +{ + sal_Int16 nTransparency = static_cast<sal_Int16>( _transparency * 100 ); + m_xPropertySet->setPropertyValue( "LineTransparence" , uno::Any( nTransparency ) ); +} + +sal_Int16 SAL_CALL +ScVbaLineFormat::getStyle() +{ + //OpenOffice.org only supports one LineStyle (other than the DashStyles) + //Therefore we can only return the SingleLine + return 1; +} + +void SAL_CALL +ScVbaLineFormat::setStyle( sal_Int16 /*_style */) +{ + //OpenOffice.org only supports one LineStyle (other than the DashStyles) + //Therefore we do not set the LineStyle, because it maybe is already set + //to Dashed or Single Line. Setting the 'Visible' or 'DashStyle' properties + //will be done with the according methods. + + // #STUB +} + +sal_Int32 SAL_CALL +ScVbaLineFormat::getDashStyle() +{ + drawing::LineStyle eLineStyle; + //LineStyle integer in Xray + m_xPropertySet->getPropertyValue( "LineStyle" ) >>= eLineStyle; + if( eLineStyle == drawing::LineStyle_SOLID ) + m_nLineDashStyle = office::MsoLineDashStyle::msoLineSolid; + else + { + drawing::LineDash aLineDash; + m_xPropertySet->getPropertyValue( "LineDash" ) >>= aLineDash; + if( aLineDash.Dots == 0 ) + { + //LineDash + //LineLongDash + m_nLineDashStyle = office::MsoLineDashStyle::msoLineDash; + if( aLineDash.Distance > 0 && ( aLineDash.DashLen / aLineDash.Distance > 1 ) ) + { + m_nLineDashStyle = office::MsoLineDashStyle::msoLineLongDash; + } + } + else if( aLineDash.Dots == 1 ) + { + // LineDashDot + // LineLongDashDot + // LineSquareDot + // LineRoundDot ! not supported + m_nLineDashStyle = office::MsoLineDashStyle::msoLineDashDot; + if( aLineDash.Dashes == 0 ) + { + m_nLineDashStyle = office::MsoLineDashStyle::msoLineSquareDot; + } + else + { + if( aLineDash.Distance > 0 && ( aLineDash.DashLen / aLineDash.Distance > 1 ) ) + { + m_nLineDashStyle = office::MsoLineDashStyle::msoLineLongDashDot; + } + } + } + else if( aLineDash.Dots == 2 ) + { + // LineDashDotDot + m_nLineDashStyle = office::MsoLineDashStyle::msoLineDashDotDot; + } + } + + return m_nLineDashStyle; +} + +void SAL_CALL +ScVbaLineFormat::setDashStyle( sal_Int32 _dashstyle ) +{ + m_nLineDashStyle = _dashstyle; + if( _dashstyle == office::MsoLineDashStyle::msoLineSolid ) + { + m_xPropertySet->setPropertyValue( "LineStyle" , uno::Any( drawing::LineStyle_SOLID )); + } + else + { + m_xPropertySet->setPropertyValue( "LineStyle" , uno::Any( drawing::LineStyle_DASH ) ); + drawing::LineDash aLineDash; + Millimeter aMillimeter( m_nLineWeight ); + sal_Int32 nPixel = static_cast< sal_Int32 >( aMillimeter.getInHundredthsOfOneMillimeter() ); + switch( _dashstyle ) + { + case office::MsoLineDashStyle::msoLineDashDot: + aLineDash.Dots = 1; + aLineDash.DotLen = nPixel; + aLineDash.Dashes = 1; + aLineDash.DashLen = 5 * nPixel; + aLineDash.Distance = 4 * nPixel; + break; + case office::MsoLineDashStyle::msoLineLongDashDot: + aLineDash.Dots = 1; + aLineDash.DotLen = nPixel; + aLineDash.Dashes = 1; + aLineDash.DashLen = 10 * nPixel; + aLineDash.Distance = 4 * nPixel; + break; + case office::MsoLineDashStyle::msoLineDash: + aLineDash.Dots = 0; + aLineDash.DotLen = 0; + aLineDash.Dashes = 1; + aLineDash.DashLen = 6 * nPixel; + aLineDash.Distance = 4 * nPixel; + break; + case office::MsoLineDashStyle::msoLineDashDotDot: + aLineDash.Dots = 2; + aLineDash.DotLen = nPixel; + aLineDash.Dashes = 1; + aLineDash.DashLen = 10 * nPixel; + aLineDash.Distance = 3 * nPixel; + break; + case office::MsoLineDashStyle::msoLineLongDash: + aLineDash.Dots = 0; + aLineDash.DotLen = 0; + aLineDash.Dashes = 1; + aLineDash.DashLen = 10 * nPixel; + aLineDash.Distance = 4 * nPixel; + break; + case office::MsoLineDashStyle::msoLineSquareDot: + aLineDash.Dots = 1; + aLineDash.DotLen = nPixel; + aLineDash.Dashes = 0; + aLineDash.DashLen = 0; + aLineDash.Distance = nPixel; + break; + case office::MsoLineDashStyle::msoLineRoundDot: + aLineDash.Dots = 1; + aLineDash.DotLen = nPixel; + aLineDash.Dashes = 0; + aLineDash.DashLen = 0; + aLineDash.Distance = nPixel; + break; + default: + throw uno::RuntimeException( "this MsoLineDashStyle is not supported." ); + } + m_xPropertySet->setPropertyValue( "LineDash" , uno::Any( aLineDash ) ); + } +} + +// Methods +uno::Reference< msforms::XColorFormat > SAL_CALL +ScVbaLineFormat::BackColor() +{ + return uno::Reference< msforms::XColorFormat >( new ScVbaColorFormat( getParent(), mxContext, this, m_xShape, ::ColorFormatType::LINEFORMAT_BACKCOLOR ) ); +} + +uno::Reference< msforms::XColorFormat > SAL_CALL +ScVbaLineFormat::ForeColor() +{ + return uno::Reference< msforms::XColorFormat >( new ScVbaColorFormat( getParent(), mxContext, this, m_xShape, ::ColorFormatType::LINEFORMAT_FORECOLOR ) ); +} + +OUString +ScVbaLineFormat::getServiceImplName() +{ + return "ScVbaLineFormat"; +} + +uno::Sequence< OUString > +ScVbaLineFormat::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.msform.LineFormat" + }; + return aServiceNames; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbalineformat.hxx b/vbahelper/source/vbahelper/vbalineformat.hxx new file mode 100644 index 000000000..c6d3c513e --- /dev/null +++ b/vbahelper/source/vbahelper/vbalineformat.hxx @@ -0,0 +1,75 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBALINEFORMAT_HXX +#define INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBALINEFORMAT_HXX + +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <ooo/vba/msforms/XLineFormat.hpp> +#include <vbahelper/vbahelperinterface.hxx> + +typedef InheritedHelperInterfaceWeakImpl< ov::msforms::XLineFormat > ScVbaLineFormat_BASE; + +class ScVbaLineFormat : public ScVbaLineFormat_BASE +{ +private: + css::uno::Reference< css::drawing::XShape > m_xShape; + css::uno::Reference< css::beans::XPropertySet > m_xPropertySet; + sal_Int32 m_nLineDashStyle; + double m_nLineWeight; + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; + static sal_Int32 convertLineStartEndNameToArrowheadStyle( std::u16string_view sLineName ); + /// @throws css::uno::RuntimeException + static OUString convertArrowheadStyleToLineStartEndName( sal_Int32 nArrowheadStyle ); +public: + ScVbaLineFormat( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::drawing::XShape >& xShape ); + + // Attributes + virtual sal_Int32 SAL_CALL getBeginArrowheadStyle() override; + virtual void SAL_CALL setBeginArrowheadStyle( sal_Int32 _beginarrowheadstyle ) override; + virtual sal_Int32 SAL_CALL getBeginArrowheadLength() override; + virtual void SAL_CALL setBeginArrowheadLength( sal_Int32 _beginarrowheadlength ) override; + virtual sal_Int32 SAL_CALL getBeginArrowheadWidth() override; + virtual void SAL_CALL setBeginArrowheadWidth( sal_Int32 _beginarrowheadwidth ) override; + virtual sal_Int32 SAL_CALL getEndArrowheadStylel() override; + virtual void SAL_CALL setEndArrowheadStylel( sal_Int32 _endarrowheadstylel ) override; + virtual sal_Int32 SAL_CALL getEndArrowheadLength() override; + virtual void SAL_CALL setEndArrowheadLength( sal_Int32 _endarrowheadlength ) override; + virtual sal_Int32 SAL_CALL getEndArrowheadWidth() override; + virtual void SAL_CALL setEndArrowheadWidth( sal_Int32 _endarrowheadwidth ) override; + virtual double SAL_CALL getWeight() override; + virtual void SAL_CALL setWeight( double _weight ) override; + virtual sal_Bool SAL_CALL getVisible() override; + virtual void SAL_CALL setVisible( sal_Bool _visible ) override; + virtual double SAL_CALL getTransparency() override; + virtual void SAL_CALL setTransparency( double _transparency ) override; + virtual sal_Int16 SAL_CALL getStyle() override; + virtual void SAL_CALL setStyle( sal_Int16 _style ) override; + virtual sal_Int32 SAL_CALL getDashStyle() override; + virtual void SAL_CALL setDashStyle( sal_Int32 _dashstyle ) override; + + // Methods + virtual css::uno::Reference< ov::msforms::XColorFormat > SAL_CALL BackColor() override; + virtual css::uno::Reference< ov::msforms::XColorFormat > SAL_CALL ForeColor() override; +}; + +#endif // INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBALINEFORMAT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbapagesetupbase.cxx b/vbahelper/source/vbahelper/vbapagesetupbase.cxx new file mode 100644 index 000000000..d50fe188c --- /dev/null +++ b/vbahelper/source/vbahelper/vbapagesetupbase.cxx @@ -0,0 +1,308 @@ +/* -*- 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 . + */ +#include <vbahelper/vbapagesetupbase.hxx> +#include <basic/sberrors.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> + +using namespace ::com::sun::star; +using namespace ::ooo::vba; + +VbaPageSetupBase::VbaPageSetupBase(const uno::Reference< XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext ) + : VbaPageSetupBase_BASE( xParent, xContext ) + , mnOrientLandscape(0) + , mnOrientPortrait(0) +{ +} + +double SAL_CALL VbaPageSetupBase::getTopMargin() +{ + sal_Int32 topMargin = 0; + + try + { + bool headerOn = false; + + uno::Any aValue = mxPageProps->getPropertyValue( "HeaderIsOn" ); + aValue >>= headerOn; + + aValue = mxPageProps->getPropertyValue( "TopMargin" ); + aValue >>= topMargin; + + if( headerOn ) + { + sal_Int32 headerHeight = 0; + aValue = mxPageProps->getPropertyValue( "HeaderHeight" ); + aValue >>= headerHeight; + topMargin = topMargin + headerHeight; + } + } + catch( uno::Exception& ) + { + } + + return Millimeter::getInPoints( topMargin ); +} + +void SAL_CALL VbaPageSetupBase::setTopMargin( double margin ) +{ + sal_Int32 topMargin = Millimeter::getInHundredthsOfOneMillimeter( margin ); + + try + { + bool headerOn = false; + + uno::Any aValue = mxPageProps->getPropertyValue( "HeaderIsOn" ); + aValue >>= headerOn; + + if( headerOn ) + { + sal_Int32 headerHeight = 0; + aValue = mxPageProps->getPropertyValue( "HeaderHeight" ); + aValue >>= headerHeight; + topMargin -= headerHeight; + } + + mxPageProps->setPropertyValue( "TopMargin" , uno::Any(topMargin) ); + } + catch( uno::Exception& ) + { + } +} + +double SAL_CALL VbaPageSetupBase::getBottomMargin() +{ + sal_Int32 bottomMargin = 0; + + try + { + bool footerOn = false; + + uno::Any aValue = mxPageProps->getPropertyValue( "FooterIsOn" ); + aValue >>= footerOn; + + aValue = mxPageProps->getPropertyValue( "BottomMargin" ); + aValue >>= bottomMargin; + + if( footerOn ) + { + sal_Int32 footerHeight = 0; + aValue = mxPageProps->getPropertyValue( "FooterHeight" ); + aValue >>= footerHeight; + bottomMargin += footerHeight; + } + } + catch( uno::Exception& ) + { + } + + return Millimeter::getInPoints( bottomMargin ); +} + +void SAL_CALL VbaPageSetupBase::setBottomMargin( double margin ) +{ + sal_Int32 bottomMargin = Millimeter::getInHundredthsOfOneMillimeter( margin ); + + try + { + bool footerOn = false; + + uno::Any aValue = mxPageProps->getPropertyValue( "FooterIsOn" ); + aValue >>= footerOn; + + if( footerOn ) + { + sal_Int32 footerHeight = 0; + aValue = mxPageProps->getPropertyValue( "FooterHeight" ); + aValue >>= footerHeight; + bottomMargin -= footerHeight; + } + + mxPageProps->setPropertyValue( "BottomMargin", uno::Any(bottomMargin) ); + } + catch( uno::Exception& ) + { + } +} + +double SAL_CALL VbaPageSetupBase::getRightMargin() +{ + sal_Int32 rightMargin = 0; + try + { + uno::Any aValue = mxPageProps->getPropertyValue( "RightMargin" ); + aValue >>= rightMargin; + } + catch( uno::Exception& ) + { + } + + return Millimeter::getInPoints( rightMargin ); +} + +void SAL_CALL VbaPageSetupBase::setRightMargin( double margin ) +{ + sal_Int32 rightMargin = Millimeter::getInHundredthsOfOneMillimeter( margin ); + try + { + mxPageProps->setPropertyValue( "RightMargin", uno::Any(rightMargin) ); + } + catch( uno::Exception& ) + { + } + +} + +double SAL_CALL VbaPageSetupBase::getLeftMargin() +{ + sal_Int32 leftMargin = 0; + try + { + uno::Any aValue = mxPageProps->getPropertyValue( "LeftMargin" ); + aValue >>= leftMargin; + } + catch( uno::Exception& ) + { + } + + return Millimeter::getInPoints( leftMargin ); +} + +void SAL_CALL VbaPageSetupBase::setLeftMargin( double margin ) +{ + sal_Int32 leftMargin = Millimeter::getInHundredthsOfOneMillimeter( margin ); + try + { + mxPageProps->setPropertyValue( "LeftMargin", uno::Any(leftMargin) ); + } + catch( uno::Exception& ) + { + } +} + +double VbaPageSetupBase::getHeaderMargin() +{ + sal_Int32 headerMargin = 0; + try + { + uno::Any aValue = mxPageProps->getPropertyValue( "TopMargin" ); + aValue >>= headerMargin; + } + catch( uno::Exception& ) + { + } + + return Millimeter::getInPoints( headerMargin ); +} + +void VbaPageSetupBase::setHeaderMargin( double margin ) +{ + sal_Int32 headerMargin = Millimeter::getInHundredthsOfOneMillimeter( margin ); + try + { + mxPageProps->setPropertyValue( "TopMargin", uno::Any(headerMargin) ); + } + catch( uno::Exception& ) + { + } +} + +double VbaPageSetupBase::getFooterMargin() +{ + sal_Int32 footerMargin = 0; + try + { + uno::Any aValue = mxPageProps->getPropertyValue( "BottomMargin" ); + aValue >>= footerMargin; + } + catch( uno::Exception& ) + { + } + + return Millimeter::getInPoints( footerMargin ); +} + +void VbaPageSetupBase::setFooterMargin( double margin ) +{ + sal_Int32 footerMargin = Millimeter::getInHundredthsOfOneMillimeter( margin ); + try + { + mxPageProps->setPropertyValue( "BottomMargin", uno::Any(footerMargin) ); + } + catch( uno::Exception& ) + { + } +} + +sal_Int32 SAL_CALL VbaPageSetupBase::getOrientation() +{ + sal_Int32 orientation = mnOrientPortrait; + try + { + bool isLandscape = false; + uno::Any aValue = mxPageProps->getPropertyValue( "IsLandscape" ); + aValue >>= isLandscape; + + if( isLandscape ) + { + orientation = mnOrientLandscape; + } + } + catch( uno::Exception& ) + { + } + return orientation; +} + +void SAL_CALL VbaPageSetupBase::setOrientation( sal_Int32 orientation ) +{ + if( ( orientation != mnOrientPortrait ) && + ( orientation != mnOrientLandscape ) ) + { + DebugHelper::runtimeexception(ERRCODE_BASIC_BAD_PARAMETER ); + } + + try + { + bool isLandscape = false; + uno::Any aValue = mxPageProps->getPropertyValue( "IsLandscape" ); + aValue >>= isLandscape; + + bool switchOrientation = false; + if(( isLandscape && orientation != mnOrientLandscape ) || + ( !isLandscape && orientation != mnOrientPortrait )) + { + switchOrientation = true; + } + + if( switchOrientation ) + { + uno::Any aHeight = mxPageProps->getPropertyValue( "Height" ); + uno::Any aWidth = mxPageProps->getPropertyValue( "Width" ); + mxPageProps->setPropertyValue( "IsLandscape", uno::Any(!isLandscape) ); + mxPageProps->setPropertyValue( "Width" , aHeight ); + mxPageProps->setPropertyValue( "Height" , aWidth ); + } + } + catch( uno::Exception& ) + { + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbapictureformat.cxx b/vbahelper/source/vbahelper/vbapictureformat.cxx new file mode 100644 index 000000000..a5cdcaed2 --- /dev/null +++ b/vbahelper/source/vbahelper/vbapictureformat.cxx @@ -0,0 +1,134 @@ +/* -*- 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 . + */ +#include "vbapictureformat.hxx" + +using namespace ooo::vba; +using namespace com::sun::star; + +ScVbaPictureFormat::ScVbaPictureFormat( const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + uno::Reference< drawing::XShape > const & xShape ) + : ScVbaPictureFormat_BASE( xParent, xContext ), m_xShape( xShape ) +{ + m_xPropertySet.set( m_xShape, uno::UNO_QUERY_THROW ); +} + +void +ScVbaPictureFormat::checkParameterRangeInDouble( double nRange, double nMin, double nMax ) +{ + if( nRange < nMin ) + { + throw uno::RuntimeException( "Parameter out of range, value is too small." ); + } + if( nRange > nMax ) + { + throw uno::RuntimeException( "Parameter out of range, value is too high." ); + } +} + +// Attributes +double SAL_CALL +ScVbaPictureFormat::getBrightness() +{ + sal_Int16 nLuminance = 0; + m_xPropertySet->getPropertyValue( "AdjustLuminance" ) >>= nLuminance; + double fBrightness = static_cast< double >( nLuminance ); + fBrightness = ( fBrightness +100 ) / 200; + return fBrightness; +} + +void SAL_CALL +ScVbaPictureFormat::setBrightness( double _brightness ) +{ + checkParameterRangeInDouble( _brightness, 0.0, 1.0 ); + double fLuminance = _brightness * 200 - 100; + sal_Int16 nLuminance = static_cast< sal_Int16 >( fLuminance ); + m_xPropertySet->setPropertyValue( "AdjustLuminance" , uno::Any( nLuminance ) ); +} + +double SAL_CALL +ScVbaPictureFormat::getContrast() +{ + sal_Int16 nContrast = 0; + m_xPropertySet->getPropertyValue( "AdjustContrast" ) >>= nContrast; + double fContrast = static_cast< double >( nContrast ); + fContrast = ( fContrast + 100 ) / 200; + return fContrast; +} + +void SAL_CALL +ScVbaPictureFormat::setContrast( double _contrast ) +{ + checkParameterRangeInDouble( _contrast, 0.0, 1.0 ); + double fContrast = _contrast * 200 - 100; + sal_Int16 nContrast = static_cast< sal_Int16 >( fContrast ); + m_xPropertySet->setPropertyValue( "AdjustContrast" , uno::Any( nContrast ) ); +} + + +// Methods +void SAL_CALL +ScVbaPictureFormat::IncrementBrightness( double increment ) +{ + double fBrightness = getBrightness(); + fBrightness += increment; + if( fBrightness < 0 ) + { + fBrightness = 0.0; + } + if( fBrightness > 1 ) + { + fBrightness = 1; + } + setBrightness( fBrightness ); +} + +void SAL_CALL +ScVbaPictureFormat::IncrementContrast( double increment ) +{ + double nContrast = getContrast(); + nContrast += increment; + if( nContrast < 0 ) + { + nContrast = 0.0; + } + if( nContrast > 1 ) + { + nContrast = 1.0; + } + setContrast( nContrast ); +} + +OUString +ScVbaPictureFormat::getServiceImplName() +{ + return "ScVbaPictureFormat"; +} + +uno::Sequence< OUString > +ScVbaPictureFormat::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.msform.PictureFormat" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbapictureformat.hxx b/vbahelper/source/vbahelper/vbapictureformat.hxx new file mode 100644 index 000000000..8ee2dba53 --- /dev/null +++ b/vbahelper/source/vbahelper/vbapictureformat.hxx @@ -0,0 +1,58 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBAPICTUREFORMAT_HXX +#define INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBAPICTUREFORMAT_HXX + +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <ooo/vba/msforms/XPictureFormat.hpp> +#include <vbahelper/vbahelperinterface.hxx> + +typedef InheritedHelperInterfaceWeakImpl< ov::msforms::XPictureFormat > ScVbaPictureFormat_BASE; + +class ScVbaPictureFormat : public ScVbaPictureFormat_BASE +{ +private: + css::uno::Reference< css::drawing::XShape > m_xShape; + css::uno::Reference< css::beans::XPropertySet > m_xPropertySet; +protected: + virtual OUString getServiceImplName() override; + virtual css::uno::Sequence<OUString> getServiceNames() override; +private: + /// @throws css::uno::RuntimeException + static void checkParameterRangeInDouble( double nRange, double nMin, double nMax ); +public: + /// @throws css::lang::IllegalArgumentException + /// @throws css::uno::RuntimeException + ScVbaPictureFormat( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, css::uno::Reference< css::drawing::XShape > const & xShape ); + + // Attributes + virtual double SAL_CALL getBrightness() override; + virtual void SAL_CALL setBrightness( double _brightness ) override; + virtual double SAL_CALL getContrast() override; + virtual void SAL_CALL setContrast( double _contrast ) override; + + // Methods + virtual void SAL_CALL IncrementBrightness( double increment ) override; + virtual void SAL_CALL IncrementContrast( double increment ) override; +}; + +#endif // INCLUDED_VBAHELPER_SOURCE_VBAHELPER_VBAPICTUREFORMAT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbapropvalue.cxx b/vbahelper/source/vbahelper/vbapropvalue.cxx new file mode 100644 index 000000000..f5249ec6d --- /dev/null +++ b/vbahelper/source/vbahelper/vbapropvalue.cxx @@ -0,0 +1,39 @@ +/* -*- 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 . + */ +#include <vbahelper/vbapropvalue.hxx> + +using namespace com::sun::star; + +ScVbaPropValue::ScVbaPropValue( PropListener* pListener ) : m_pListener( pListener ) +{ +} + +css::uno::Any SAL_CALL +ScVbaPropValue::getValue() +{ + return m_pListener->getValueEvent(); +} + +void SAL_CALL +ScVbaPropValue::setValue( const css::uno::Any& _value ) +{ + m_pListener->setValueEvent( _value ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbashape.cxx b/vbahelper/source/vbahelper/vbashape.cxx new file mode 100644 index 000000000..1f13c70d5 --- /dev/null +++ b/vbahelper/source/vbahelper/vbashape.cxx @@ -0,0 +1,748 @@ +/* -*- 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 . + */ +#include <ooo/vba/office/MsoZOrderCmd.hpp> +#include <ooo/vba/office/MsoScaleFrom.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/ConnectorType.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/text/RelOrientation.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <ooo/vba/office/MsoShapeType.hpp> +#include <ooo/vba/office/MsoAutoShapeType.hpp> +#include <ooo/vba/word/WdRelativeHorizontalPosition.hpp> +#include <ooo/vba/word/WdRelativeVerticalPosition.hpp> + +#include <basic/sberrors.hxx> +#include <comphelper/processfactory.hxx> +#include <vcl/svapp.hxx> +#include <sal/log.hxx> + +#include <vbahelper/vbashape.hxx> +#include <vbahelper/vbatextframe.hxx> +#include "vbalineformat.hxx" +#include "vbafillformat.hxx" +#include "vbapictureformat.hxx" +#include <vbahelper/vbashaperange.hxx> + +using namespace ::ooo::vba; +using namespace ::com::sun::star; + +ScVbaShape::ScVbaShape( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< drawing::XShape >& xShape, const uno::Reference< drawing::XShapes >& xShapes, const uno::Reference< frame::XModel >& xModel, sal_Int32 nType ) + : ScVbaShape_BASE( xParent, xContext ), m_xShape( xShape ), m_xShapes( xShapes ), m_nType( nType ), m_xModel( xModel ) +{ + m_xPropertySet.set( m_xShape, uno::UNO_QUERY_THROW ); + m_pShapeHelper.reset( new ShapeHelper( m_xShape ) ); + addListeners(); +} + +ScVbaShape::~ScVbaShape() +{ +} + +void SAL_CALL +ScVbaShape::disposing( const lang::EventObject& rEventObject ) +{ + try + { + uno::Reference< drawing::XShapes > xShapes( rEventObject.Source, uno::UNO_QUERY ); + uno::Reference< drawing::XShape > xShape( rEventObject.Source, uno::UNO_QUERY ); + if ( xShapes.is() ) + removeShapesListener(); + if ( xShape.is() ) + removeShapeListener(); + } + catch( uno::Exception& ) + { + } +} + + +void ScVbaShape::addListeners() +{ + uno::Reference< lang::XComponent > xComponent( m_xShape, uno::UNO_QUERY ); + if ( xComponent.is() ) + xComponent->addEventListener( this ); + + xComponent.set( m_xShapes, uno::UNO_QUERY ); + if ( xComponent.is() ) + xComponent->addEventListener( this ); +} + +void +ScVbaShape::removeShapeListener() +{ + if( m_xShape.is() ) + { + uno::Reference< lang::XComponent > xComponent( m_xShape, uno::UNO_QUERY_THROW ); + xComponent->removeEventListener( this ); + } + m_xShape = nullptr; + m_xPropertySet = nullptr; +} + +void +ScVbaShape::removeShapesListener() +{ + if( m_xShapes.is() ) + { + uno::Reference< lang::XComponent > xComponent( m_xShapes, uno::UNO_QUERY_THROW ); + xComponent->removeEventListener( this ); + } + m_xShapes = nullptr; +} + +sal_Int32 +ScVbaShape::getType( const css::uno::Reference< drawing::XShape >& xShape ) +{ + OUString sShapeType; + uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor( xShape, uno::UNO_QUERY_THROW ); + sShapeType = xShapeDescriptor->getShapeType(); + SAL_INFO("vbahelper", "ScVbaShape::getType: " << sShapeType); + // office::MsoShapeType::msoDiagram to "com.sun.star.drawing.GroupShape" + if( sShapeType == "com.sun.star.drawing.GroupShape" ) + return office::MsoShapeType::msoGroup; + else if( sShapeType == "com.sun.star.drawing.GraphicObjectShape" ) + return office::MsoShapeType::msoPicture; + else if( sShapeType == "com.sun.star.drawing.ControlShape" || sShapeType == "FrameShape" ) + return office::MsoShapeType::msoOLEControlObject; + // OOo don't support office::MsoShapeType::msoComment as a Shape. + else if( sShapeType == "com.sun.star.drawing.OLE2Shape" ) + return office::MsoShapeType::msoChart; + // Art characters office::MsoShapeType::msoTextEffect, in OOo corresponding to "com.sun.star.drawing.CustomShape" + else if( sShapeType == "com.sun.star.drawing.ConnectorShape" ) + { + drawing::ConnectorType connectorType; + uno::Reference< beans::XPropertySet > xPropertySet( xShape, uno::UNO_QUERY_THROW ); + xPropertySet->getPropertyValue( "EdgeKind" ) >>= connectorType; + if( connectorType == drawing::ConnectorType_CURVE ) + return office::MsoShapeType::msoFreeform; + else if( connectorType == drawing::ConnectorType_LINE ) + return office::MsoShapeType::msoLine; + else + return office::MsoShapeType::msoAutoShape; + } + else if( sShapeType == "com.sun.star.drawing.LineShape" ) + return office::MsoShapeType::msoLine; + else if( sShapeType == "com.sun.star.drawing.CustomShape" + || sShapeType == "com.sun.star.drawing.RectangleShape" + || sShapeType == "com.sun.star.drawing.EllipseShape" ) + return office::MsoShapeType::msoAutoShape; + else if( sShapeType == "com.sun.star.drawing.TextShape" ) + return office::MsoShapeType::msoTextBox; + else + throw uno::RuntimeException("the shape type do not be supported: " + sShapeType ); +} + +sal_Int32 ScVbaShape::getAutoShapeType(const css::uno::Reference< drawing::XShape >& xShape) +{ + assert( ScVbaShape::getType( xShape ) == office::MsoShapeType::msoAutoShape ); + + OUString sShapeType; + uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor( xShape, uno::UNO_QUERY_THROW ); + sShapeType = xShapeDescriptor->getShapeType(); + SAL_INFO("vbahelper", "ScVbaShape::getAutoShapeType: " << sShapeType); + + if( sShapeType == "com.sun.star.drawing.EllipseShape" ) + return office::MsoAutoShapeType::msoShapeOval; + else if ( sShapeType == "com.sun.star.drawing.RectangleShape" ) + return office::MsoAutoShapeType::msoShapeRectangle; + else if ( sShapeType == "com.sun.star.drawing.CustomShape" ) + { + uno::Reference< beans::XPropertySet > aXPropSet( xShape, uno::UNO_QUERY ); + uno::Any aGeoPropSet = aXPropSet->getPropertyValue( "CustomShapeGeometry" ); + uno::Sequence< beans::PropertyValue > aGeoPropSeq; + if ( aGeoPropSet >>= aGeoPropSeq ) + { + for( const auto& rProp : std::as_const(aGeoPropSeq) ) + { + if( rProp.Name == "Type" ) + { + OUString sType; + if( rProp.Value >>= sType ) + { + if( sType.endsWith( "ellipse" ) ) + return office::MsoAutoShapeType::msoShapeOval; + // TODO other custom shapes here + } + } + } + } + } + + SAL_WARN( "vbahelper", "ScVbaShape::getAutoShapeType: unknown auto type" ); + return -1; // could not decide + +} + +// Attributes +OUString SAL_CALL +ScVbaShape::getName() +{ + OUString sName; + uno::Reference< container::XNamed > xNamed( m_xShape, uno::UNO_QUERY_THROW ); + sName = xNamed->getName(); + return sName; +} + +void SAL_CALL +ScVbaShape::setName( const OUString& _name ) +{ + uno::Reference< container::XNamed > xNamed( m_xShape, uno::UNO_QUERY_THROW ); + xNamed->setName( _name ); +} + +OUString SAL_CALL +ScVbaShape::getAlternativeText() +{ + OUString sAltText; + uno::Reference< beans::XPropertySet > xProps( m_xShape, uno::UNO_QUERY_THROW ); + xProps->getPropertyValue("Title") >>= sAltText; + return sAltText; +} + +void SAL_CALL +ScVbaShape::setAlternativeText( const OUString& sAltText ) +{ + uno::Reference< beans::XPropertySet > xProps( m_xShape, uno::UNO_QUERY_THROW ); + xProps->setPropertyValue("Title", uno::Any( sAltText ) ); +} + +double SAL_CALL +ScVbaShape::getHeight() +{ + return m_pShapeHelper->getHeight(); +} + +void SAL_CALL +ScVbaShape::setHeight(double _height) +{ + m_pShapeHelper->setHeight( _height ); +} + +double SAL_CALL +ScVbaShape::getWidth() +{ + return m_pShapeHelper->getWidth(); +} + +void SAL_CALL +ScVbaShape::setWidth(double _width) +{ + m_pShapeHelper->setWidth( _width ); +} + +double SAL_CALL +ScVbaShape::getLeft() +{ + double left = 0; + try + { + left = m_pShapeHelper->getLeft(); + } + catch( uno::Exception& ) + { + // fail to get position by using XShape::getPosition() + sal_Int32 nLeft = 0; + m_xPropertySet->getPropertyValue( "HoriOrientPosition" ) >>= nLeft; + left = Millimeter::getInPoints( nLeft ); + } + return left; +} + +void SAL_CALL +ScVbaShape::setLeft( double _left ) +{ + try + { + m_pShapeHelper->setLeft( _left ); + } + catch( uno::Exception& ) + { + sal_Int32 nLeft = Millimeter::getInHundredthsOfOneMillimeter( _left ); + m_xPropertySet->setPropertyValue( "HoriOrientPosition" , uno::Any( nLeft ) ); + } +} + +double SAL_CALL +ScVbaShape::getTop() +{ + double top = 0; + try + { + top = m_pShapeHelper->getTop(); + } + catch( uno::Exception& ) + { + sal_Int32 nTop = 0; + m_xPropertySet->getPropertyValue( "VertOrientPosition" ) >>= nTop; + top = Millimeter::getInPoints( nTop ); + } + return top; +} + +void SAL_CALL +ScVbaShape::setTop( double _top ) +{ + try + { + m_pShapeHelper->setTop( _top ); + } + catch( uno::Exception& ) + { + sal_Int32 nTop = Millimeter::getInHundredthsOfOneMillimeter( _top ); + m_xPropertySet->setPropertyValue( "VertOrientPosition" , uno::Any( nTop ) ); + } +} + +sal_Bool SAL_CALL +ScVbaShape::getVisible() +{ + // #STUB + //UNO Shapes are always visible + return true; +} + +void SAL_CALL +ScVbaShape::setVisible( sal_Bool /*_visible*/ ) +{ + // #STUB + //UNO Shapes are always visible +} + +sal_Int32 SAL_CALL +ScVbaShape::getZOrderPosition() +{ + sal_Int32 nZOrderPosition = 0; + uno::Any aZOrderPosition = m_xPropertySet->getPropertyValue( "ZOrder" ); + aZOrderPosition >>= nZOrderPosition; + return nZOrderPosition + 1; +} + +sal_Int32 SAL_CALL +ScVbaShape::getType() +{ + return m_nType; +} + +double SAL_CALL +ScVbaShape::getRotation() +{ + double dRotation = 0; + sal_Int32 nRotation = 0; + m_xPropertySet->getPropertyValue( "RotateAngle" ) >>= nRotation; + dRotation = static_cast< double >( nRotation /100 ); + return dRotation; +} + +void SAL_CALL +ScVbaShape::setRotation( double _rotation ) +{ + sal_Int32 nRotation = static_cast < sal_Int32 > ( _rotation * 100 ); + m_xPropertySet->setPropertyValue( "RotateAngle" , uno::Any( nRotation ) ); +} + +uno::Reference< msforms::XLineFormat > SAL_CALL +ScVbaShape::getLine() +{ + // TODO should only return line + return uno::Reference< msforms::XLineFormat >( new ScVbaLineFormat( this, mxContext, m_xShape ) ); +} + +uno::Reference< msforms::XFillFormat > SAL_CALL +ScVbaShape::getFill() +{ + return uno::Reference< msforms::XFillFormat >( new ScVbaFillFormat( this, mxContext, m_xShape ) ); +} + +uno::Reference< msforms::XPictureFormat > SAL_CALL +ScVbaShape::getPictureFormat() +{ + return uno::Reference< msforms::XPictureFormat >( new ScVbaPictureFormat( this, mxContext, m_xShape ) ); +} + +// Methods +uno::Any SAL_CALL +ScVbaShape::TextFrame() +{ + uno::Reference< lang::XServiceInfo > xServiceInfo( m_xModel, uno::UNO_QUERY_THROW ); + if( xServiceInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) ) + { + uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext(); + uno::Reference< uno::XInterface > xTextFrame = xContext->getServiceManager()->createInstanceWithArgumentsAndContext( "ooo.vba.excel.TextFrame" , { uno::Any(getParent()), uno::Any(m_xShape) }, xContext ); + return uno::Any( xTextFrame ); + } + + return uno::Any( uno::Reference< msforms::XTextFrame >( new VbaTextFrame( this, mxContext, m_xShape ) ) ); +} + +void SAL_CALL +ScVbaShape::Delete() +{ + SolarMutexGuard aGuard; + m_xShapes->remove( m_xShape ); +} + +void SAL_CALL +ScVbaShape::ZOrder( sal_Int32 ZOrderCmd ) +{ + sal_Int32 nOrderPosition; + uno::Any aOrderPosition = m_xPropertySet->getPropertyValue( "ZOrder" ); + aOrderPosition >>= nOrderPosition; + switch( ZOrderCmd ) + { + case office::MsoZOrderCmd::msoBringToFront: + m_xPropertySet->setPropertyValue( "ZOrder" , uno::Any( SAL_MAX_INT32 ) ); + break; + case office::MsoZOrderCmd::msoSendToBack: + m_xPropertySet->setPropertyValue( "ZOrder" , uno::Any( sal_Int32(0) ) ); + break; + case office::MsoZOrderCmd::msoBringForward: + nOrderPosition += 1; + m_xPropertySet->setPropertyValue( "ZOrder" , uno::Any( nOrderPosition ) ); + break; + case office::MsoZOrderCmd::msoSendBackward: + if( nOrderPosition > 0 ) + { + nOrderPosition -= 1; + m_xPropertySet->setPropertyValue( "ZOrder" , uno::Any( nOrderPosition ) ); + } + break; + // below two commands use with Writer for text and image object. + case office::MsoZOrderCmd::msoBringInFrontOfText: + case office::MsoZOrderCmd::msoSendBehindText: + throw uno::RuntimeException( "This ZOrderCmd is not implemented, it is use with writer." ); + default: + throw uno::RuntimeException( "Invalid Parameter." ); + } +} + +void SAL_CALL +ScVbaShape::IncrementRotation( double Increment ) +{ + double nCurrentRotation = getRotation(); + nCurrentRotation += Increment; + setRotation(nCurrentRotation); +} + +void SAL_CALL +ScVbaShape::IncrementLeft( double Increment ) +{ + double nCurrentLeft = getLeft(); + nCurrentLeft += Increment; + setLeft(nCurrentLeft); +} + +void SAL_CALL +ScVbaShape::IncrementTop( double Increment ) +{ + double nCurrentTop = getTop(); + nCurrentTop += Increment; + setTop(nCurrentTop); +} + +void SAL_CALL +ScVbaShape::ScaleHeight( double Factor, sal_Bool /*RelativeToOriginalSize*/, sal_Int32 Scale ) +{ + double nHeight = getHeight(); + double nNewHeight = nHeight * Factor; + if( Scale == office::MsoScaleFrom::msoScaleFromTopLeft ) + { + setHeight(nNewHeight); + } + else if( Scale == office::MsoScaleFrom::msoScaleFromBottomRight ) + { + double nDeltaHeight = nNewHeight - nHeight; + double nNewTop = getTop() - nDeltaHeight; + setTop(nNewTop); + setHeight(nNewHeight); + } + else if( Scale == office::MsoScaleFrom::msoScaleFromMiddle ) + { + double nDeltaHeight = (nNewHeight - nHeight) / 2; + double nNewTop = getTop() - nDeltaHeight; + setTop(nNewTop); + setHeight(nNewHeight); + } + else + { + throw uno::RuntimeException( "ScaleHeight.Scale wrong value is given." ); + } +} + +void SAL_CALL +ScVbaShape::ScaleWidth( double Factor, sal_Bool /*RelativeToOriginalSize*/, sal_Int32 Scale ) +{ + double nWidth = getWidth(); + double nNewWidth = nWidth * Factor; + if( Scale == office::MsoScaleFrom::msoScaleFromTopLeft ) + { + setWidth(nNewWidth); + } + else if( Scale == office::MsoScaleFrom::msoScaleFromBottomRight ) + { + double nDeltaWidth = nNewWidth - nWidth; + double nNewLeft = getLeft() - nDeltaWidth; + setLeft(nNewLeft); + setWidth(nNewWidth); + } + else if( Scale == office::MsoScaleFrom::msoScaleFromMiddle ) + { + double nDeltaWidth = (nNewWidth - nWidth) / 2; + double nNewLeft = getLeft() - nDeltaWidth; + setLeft(nNewLeft); + setWidth(nNewWidth); + } + else + { + throw uno::RuntimeException( "ScaleHeight.Scale wrong value is given." ); + } +} + +void SAL_CALL +ScVbaShape::Select( const uno::Any& /*Replace*/ ) +{ + uno::Reference< view::XSelectionSupplier > xSelectSupp( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); + xSelectSupp->select( uno::Any( m_xShape ) ); +} + +// This method should not be part of Shape, what we really need to do is... +// dynamically create the appropriate objects e.g. TextBox, Oval, Picture etc. +// ( e.g. the ones that really do have ShapeRange as an attribute ) +uno::Any SAL_CALL +ScVbaShape::ShapeRange( const uno::Any& index ) +{ + // perhaps we should store a reference to the Shapes Collection + // in this class + // but anyway this method should not even be in this class + // #TODO not sure what the parent of the Shapes collection should be + + XNamedObjectCollectionHelper< drawing::XShape >::XNamedVec aVec; + aVec.push_back( m_xShape ); + uno::Reference< container::XIndexAccess > xIndexAccess( new XNamedObjectCollectionHelper< drawing::XShape >( aVec ) ); + uno::Reference< container::XChild > xChild( m_xShape, uno::UNO_QUERY_THROW ); + // #FIXME for want of a better parent, setting this + uno::Reference< msforms::XShapeRange > xShapeRange( new ScVbaShapeRange( mxParent, mxContext, xIndexAccess, uno::Reference< drawing::XDrawPage >( xChild->getParent(), uno::UNO_QUERY_THROW ), m_xModel ) ); + if ( index.hasValue() ) + return xShapeRange->Item( index, uno::Any() ); + return uno::Any( xShapeRange ); +} + +sal_Bool SAL_CALL +ScVbaShape::getLockAspectRatio() +{ + // #STUB + return false; +} + +void SAL_CALL +ScVbaShape::setLockAspectRatio( sal_Bool /*_lockaspectratio*/ ) +{ + // #STUB +} + +sal_Bool SAL_CALL +ScVbaShape::getLockAnchor() +{ + // #STUB + return true; +} + +void SAL_CALL +ScVbaShape::setLockAnchor( sal_Bool /*_lockanchor*/ ) +{ + // #STUB +} + +sal_Int32 SAL_CALL +ScVbaShape::getRelativeHorizontalPosition() +{ + sal_Int32 nRelativeHorizontalPosition = word::WdRelativeHorizontalPosition::wdRelativeHorizontalPositionMargin; + sal_Int16 nType = text::RelOrientation::PAGE_LEFT; + m_xPropertySet->getPropertyValue( "HoriOrientRelation" ) >>= nType; + + switch( nType ) + { + case text::RelOrientation::FRAME: + { + nRelativeHorizontalPosition = word::WdRelativeHorizontalPosition::wdRelativeHorizontalPositionColumn; + break; + } + case text::RelOrientation::PAGE_FRAME: + { + nRelativeHorizontalPosition = word::WdRelativeHorizontalPosition::wdRelativeHorizontalPositionPage; + break; + } + case text::RelOrientation::CHAR: + { + nRelativeHorizontalPosition = word::WdRelativeHorizontalPosition::wdRelativeHorizontalPositionCharacter; + break; + } + case text::RelOrientation::PAGE_PRINT_AREA: + { + nRelativeHorizontalPosition = word::WdRelativeHorizontalPosition::wdRelativeHorizontalPositionMargin; + break; + } + default: + { + throw uno::RuntimeException( "Shape::RelativeHorizontalPosition: not implemented" ); + } + } + return nRelativeHorizontalPosition; +} + +void SAL_CALL +ScVbaShape::setRelativeHorizontalPosition(::sal_Int32 _relativehorizontalposition) +{ + sal_Int16 nType = text::RelOrientation::PAGE_FRAME; + switch( _relativehorizontalposition ) + { + case word::WdRelativeHorizontalPosition::wdRelativeHorizontalPositionCharacter: + { + nType = text::RelOrientation::CHAR; + break; + } + case word::WdRelativeHorizontalPosition::wdRelativeHorizontalPositionColumn: + { + nType = text::RelOrientation::PAGE_FRAME; + break; + } + case word::WdRelativeHorizontalPosition::wdRelativeHorizontalPositionMargin: + { + nType = text::RelOrientation::PAGE_PRINT_AREA; + break; + } + case word::WdRelativeHorizontalPosition::wdRelativeHorizontalPositionPage: + { + nType = text::RelOrientation::PAGE_FRAME; + break; + } + default: + { + DebugHelper::runtimeexception(ERRCODE_BASIC_BAD_ARGUMENT); + } + } + m_xPropertySet->setPropertyValue( "HoriOrientRelation" , uno::Any( nType ) ); +} + +sal_Int32 SAL_CALL +ScVbaShape::getRelativeVerticalPosition() +{ + sal_Int32 nRelativeVerticalPosition = word::WdRelativeVerticalPosition::wdRelativeVerticalPositionMargin; + sal_Int16 nType = text::RelOrientation::PAGE_FRAME; + m_xPropertySet->getPropertyValue( "VertOrientRelation" ) >>= nType; + + switch( nType ) + { + case text::RelOrientation::FRAME: + { + nRelativeVerticalPosition = word::WdRelativeVerticalPosition::wdRelativeVerticalPositionParagraph; + break; + } + case text::RelOrientation::PAGE_FRAME: + { + nRelativeVerticalPosition = word::WdRelativeVerticalPosition::wdRelativeVerticalPositionPage; + break; + } + case text::RelOrientation::TEXT_LINE: + { + nRelativeVerticalPosition = word::WdRelativeVerticalPosition::wdRelativeVerticalPositionLine; + break; + } + case text::RelOrientation::PAGE_PRINT_AREA: + { + nRelativeVerticalPosition = word::WdRelativeVerticalPosition::wdRelativeVerticalPositionMargin; + break; + } + default: + { + throw uno::RuntimeException( "Shape::RelativeVerticalPosition: not implemented" ); + } + } + return nRelativeVerticalPosition; +} + +void SAL_CALL +ScVbaShape::setRelativeVerticalPosition(::sal_Int32 _relativeverticalposition) +{ + sal_Int16 nType = text::RelOrientation::PAGE_FRAME; + switch( _relativeverticalposition ) + { + case word::WdRelativeVerticalPosition::wdRelativeVerticalPositionLine: + { + nType = text::RelOrientation::TEXT_LINE; + break; + } + case word::WdRelativeVerticalPosition::wdRelativeVerticalPositionParagraph: + { + nType = text::RelOrientation::FRAME; + break; + } + case word::WdRelativeVerticalPosition::wdRelativeVerticalPositionMargin: + { + nType = text::RelOrientation::PAGE_PRINT_AREA; + break; + } + case word::WdRelativeVerticalPosition::wdRelativeVerticalPositionPage: + { + nType = text::RelOrientation::PAGE_FRAME; + break; + } + default: + { + DebugHelper::runtimeexception(ERRCODE_BASIC_BAD_ARGUMENT); + } + } + m_xPropertySet->setPropertyValue( "VertOrientRelation" , uno::Any( nType ) ); +} + +uno::Any SAL_CALL +ScVbaShape::WrapFormat() +{ + uno::Reference< lang::XServiceInfo > xServiceInfo( m_xModel, uno::UNO_QUERY_THROW ); + if( xServiceInfo->supportsService( "com.sun.star.text.TextDocument" )) + { + uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext(); + uno::Reference< uno::XInterface > xWrapFormat = xContext->getServiceManager()->createInstanceWithArgumentsAndContext( "ooo.vba.word.WrapFormat" ,{ uno::Any(getParent()), uno::Any(m_xShape) }, xContext ); + return uno::Any( xWrapFormat ); + } + throw uno::RuntimeException( "Not implemented" ); +} + +OUString +ScVbaShape::getServiceImplName() +{ + return "ScVbaShape"; +} + +uno::Sequence< OUString > +ScVbaShape::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.msform.Shape" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbashaperange.cxx b/vbahelper/source/vbahelper/vbashaperange.cxx new file mode 100644 index 000000000..71641eef7 --- /dev/null +++ b/vbahelper/source/vbahelper/vbashaperange.cxx @@ -0,0 +1,419 @@ +/* -*- 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 . + */ +#include <com/sun/star/drawing/ShapeCollection.hpp> +#include <com/sun/star/drawing/XShapeGrouper.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <ooo/vba/office/MsoShapeType.hpp> + +#include <vbahelper/vbashaperange.hxx> +#include <vbahelper/vbashape.hxx> +using namespace ::ooo::vba; +using namespace ::com::sun::star; + +namespace { + +class VbShapeRangeEnumHelper : public EnumerationHelper_BASE +{ + uno::Reference< XCollection > m_xParent; + uno::Reference<container::XIndexAccess > m_xIndexAccess; + sal_Int32 nIndex; +public: + VbShapeRangeEnumHelper( const uno::Reference< XCollection >& xParent, const uno::Reference< container::XIndexAccess >& xIndexAccess ) : m_xParent( xParent ), m_xIndexAccess( xIndexAccess ), nIndex( 0 ) {} + virtual sal_Bool SAL_CALL hasMoreElements( ) override + { + return ( nIndex < m_xIndexAccess->getCount() ); + } + virtual uno::Any SAL_CALL nextElement( ) override + { + ScVbaShapeRange* pCollectionImpl = dynamic_cast< ScVbaShapeRange* >(m_xParent.get()); + if ( pCollectionImpl && hasMoreElements() ) + return pCollectionImpl->createCollectionObject( m_xIndexAccess->getByIndex( nIndex++ ) ); + throw container::NoSuchElementException(); + } + +}; + +} + +ScVbaShapeRange::ScVbaShapeRange( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XIndexAccess >& xShapes, const uno::Reference< drawing::XDrawPage >& xDrawPage, const uno::Reference< frame::XModel >& xModel ) : ScVbaShapeRange_BASE( xParent, xContext, xShapes ), m_xDrawPage( xDrawPage ), m_xModel( xModel ) +{ +} + +// Methods +void SAL_CALL +ScVbaShapeRange::Select( ) +{ + uno::Reference< view::XSelectionSupplier > xSelectSupp( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); + xSelectSupp->select( uno::Any( getShapes() ) ); +} + +uno::Reference< msforms::XShape > SAL_CALL +ScVbaShapeRange::Group() +{ + uno::Reference< drawing::XShapeGrouper > xShapeGrouper( m_xDrawPage, uno::UNO_QUERY_THROW ); + uno::Reference< drawing::XShapeGroup > xShapeGroup( xShapeGrouper->group( getShapes() ), uno::UNO_SET_THROW ); + uno::Reference< drawing::XShape > xShape( xShapeGroup, uno::UNO_QUERY_THROW ); + return uno::Reference< msforms::XShape >( new ScVbaShape( getParent(), mxContext, xShape, getShapes(), m_xModel, office::MsoShapeType::msoGroup ) ); +} + +uno::Reference< drawing::XShapes > const & +ScVbaShapeRange::getShapes() +{ + if ( !m_xShapes.is() ) + { + m_xShapes.set( drawing::ShapeCollection::create(mxContext) ); + sal_Int32 nLen = m_xIndexAccess->getCount(); + for ( sal_Int32 index = 0; index < nLen; ++index ) + m_xShapes->add( uno::Reference< drawing::XShape >( m_xIndexAccess->getByIndex( index ), uno::UNO_QUERY_THROW ) ); + + } + return m_xShapes; +} + + +void SAL_CALL +ScVbaShapeRange::IncrementRotation( double Increment ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->IncrementRotation( Increment ); + } +} + +void SAL_CALL +ScVbaShapeRange::IncrementLeft( double Increment ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->IncrementLeft( Increment ); + } +} + +void SAL_CALL +ScVbaShapeRange::IncrementTop( double Increment ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->IncrementTop( Increment ); + } +} + +OUString SAL_CALL ScVbaShapeRange::getName() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getName( ); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::setName( const OUString& _name ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->setName( _name ); + } +} + +double SAL_CALL ScVbaShapeRange::getHeight() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getHeight( ); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::setHeight( double _height ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->setHeight( _height ); + } +} + +double SAL_CALL ScVbaShapeRange::getWidth() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getWidth( ); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::setWidth( double _width ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->setWidth( _width ); + } +} + +double SAL_CALL ScVbaShapeRange::getLeft() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getLeft(); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::setLeft( double _left ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->setLeft( _left ); + } +} + +double SAL_CALL ScVbaShapeRange::getTop() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getTop(); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::setTop( double _top ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->setTop( _top ); + } +} + +uno::Reference< ov::msforms::XLineFormat > SAL_CALL ScVbaShapeRange::getLine() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getLine(); + } + throw uno::RuntimeException(); +} + +uno::Reference< ov::msforms::XFillFormat > SAL_CALL ScVbaShapeRange::getFill() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getFill(); + } + throw uno::RuntimeException(); +} + +sal_Bool SAL_CALL ScVbaShapeRange::getLockAspectRatio() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getLockAspectRatio(); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::setLockAspectRatio( sal_Bool _lockaspectratio ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->setLockAspectRatio( _lockaspectratio ); + } +} + +sal_Bool SAL_CALL ScVbaShapeRange::getLockAnchor() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getLockAnchor(); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::setLockAnchor( sal_Bool _lockanchor ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->setLockAnchor( _lockanchor ); + } +} + +::sal_Int32 SAL_CALL ScVbaShapeRange::getRelativeHorizontalPosition() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getRelativeHorizontalPosition(); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::setRelativeHorizontalPosition( ::sal_Int32 _relativehorizontalposition ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->setRelativeHorizontalPosition( _relativehorizontalposition ); + } +} + +::sal_Int32 SAL_CALL ScVbaShapeRange::getRelativeVerticalPosition() +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->getRelativeVerticalPosition(); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::setRelativeVerticalPosition( ::sal_Int32 _relativeverticalposition ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->setRelativeVerticalPosition( _relativeverticalposition ); + } +} + +uno::Any SAL_CALL ScVbaShapeRange::TextFrame( ) +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->TextFrame(); + } + throw uno::RuntimeException(); +} + +uno::Any SAL_CALL ScVbaShapeRange::WrapFormat( ) +{ + sal_Int32 nLen = getCount(); + sal_Int32 index = 1; + if (index <= nLen) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + return xShape->WrapFormat(); + } + throw uno::RuntimeException(); +} + +void SAL_CALL ScVbaShapeRange::ZOrder( sal_Int32 ZOrderCmd ) +{ + sal_Int32 nLen = getCount(); + for ( sal_Int32 index = 1; index <= nLen; ++index ) + { + uno::Reference< msforms::XShape > xShape( Item( uno::Any( index ), uno::Any() ), uno::UNO_QUERY_THROW ); + xShape->ZOrder( ZOrderCmd ); + } +} + +uno::Type SAL_CALL +ScVbaShapeRange::getElementType() +{ + return cppu::UnoType<msforms::XShape>::get(); +} + +uno::Reference< container::XEnumeration > SAL_CALL +ScVbaShapeRange::createEnumeration() +{ + return new VbShapeRangeEnumHelper( this, m_xIndexAccess ); +} + +uno::Any +ScVbaShapeRange:: createCollectionObject( const css::uno::Any& aSource ) +{ + uno::Reference< drawing::XShape > xShape( aSource, uno::UNO_QUERY_THROW ); + // #TODO #FIXME Shape parent should always be the sheet the shapes belong + // to + uno::Reference< msforms::XShape > xVbShape( new ScVbaShape( uno::Reference< XHelperInterface >(), mxContext, xShape, getShapes(), m_xModel, ScVbaShape::getType( xShape ) ) ); + return uno::Any( xVbShape ); +} + +OUString +ScVbaShapeRange::getServiceImplName() +{ + return "ScVbaShapeRange"; +} + +uno::Sequence< OUString > +ScVbaShapeRange::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.msform.ShapeRange" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbashapes.cxx b/vbahelper/source/vbahelper/vbashapes.cxx new file mode 100644 index 000000000..951c913d2 --- /dev/null +++ b/vbahelper/source/vbahelper/vbashapes.cxx @@ -0,0 +1,421 @@ +/* -*- 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 . + */ + +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/text/WrapTextMode.hpp> +#include <ooo/vba/msforms/XShapeRange.hpp> +#include <ooo/vba/office/MsoAutoShapeType.hpp> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/script/BasicErrorException.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/text/TextContentAnchorType.hpp> +#include <com/sun/star/text/HoriOrientation.hpp> +#include <com/sun/star/text/VertOrientation.hpp> +#include <com/sun/star/text/RelOrientation.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/drawing/XShapes.hpp> + +#include <vbahelper/vbahelper.hxx> +#include <vbahelper/vbashape.hxx> +#include <vbahelper/vbashapes.hxx> +#include <vbahelper/vbashaperange.hxx> +#include <rtl/ref.hxx> + +using namespace ::ooo::vba; +using namespace ::com::sun::star; + +namespace { + +class VbShapeEnumHelper : public EnumerationHelper_BASE +{ + uno::Reference<msforms::XShapes > m_xParent; + uno::Reference<container::XIndexAccess > m_xIndexAccess; + sal_Int32 nIndex; +public: + VbShapeEnumHelper( const uno::Reference< msforms::XShapes >& xParent, const uno::Reference< container::XIndexAccess >& xIndexAccess ) : m_xParent( xParent ), m_xIndexAccess( xIndexAccess ), nIndex( 0 ) {} + virtual sal_Bool SAL_CALL hasMoreElements( ) override + { + return ( nIndex < m_xIndexAccess->getCount() ); + } + virtual uno::Any SAL_CALL nextElement( ) override + { + ScVbaShapes* pShapes = dynamic_cast< ScVbaShapes* >(m_xParent.get()); + if ( pShapes && hasMoreElements() ) + return pShapes->createCollectionObject( m_xIndexAccess->getByIndex( nIndex++ ) ); + throw container::NoSuchElementException(); + } + +}; + +} + +void ScVbaShapes::initBaseCollection() +{ + if ( m_xNameAccess.is() ) // already has NameAccess + return; + // no NameAccess then use ShapeCollectionHelper + XNamedObjectCollectionHelper< drawing::XShape >::XNamedVec aShapes; + sal_Int32 nLen = m_xIndexAccess->getCount(); + aShapes.reserve( nLen ); + for ( sal_Int32 index=0; index<nLen; ++index ) + aShapes.emplace_back( m_xIndexAccess->getByIndex( index ) , uno::UNO_QUERY ); + uno::Reference< container::XIndexAccess > xShapes( new XNamedObjectCollectionHelper< drawing::XShape >( aShapes ) ); + m_xIndexAccess = xShapes; + m_xNameAccess.set( xShapes, uno::UNO_QUERY ); +} + +ScVbaShapes::ScVbaShapes( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xShapes, const uno::Reference< frame::XModel>& xModel ): ScVbaShapes_BASE( xParent, xContext, xShapes, true ), m_nNewShapeCount(0), m_xModel( xModel ) +{ + m_xShapes.set( xShapes, uno::UNO_QUERY_THROW ); + m_xDrawPage.set( xShapes, uno::UNO_QUERY_THROW ); + initBaseCollection(); +} + +uno::Reference< container::XEnumeration > +ScVbaShapes::createEnumeration() +{ + return new VbShapeEnumHelper( this, m_xIndexAccess ); +} + +uno::Any +ScVbaShapes::createCollectionObject( const css::uno::Any& aSource ) +{ + if( aSource.hasValue() ) + { + uno::Reference< drawing::XShape > xShape( aSource, uno::UNO_QUERY_THROW ); + return uno::Any( uno::Reference< msforms::XShape >( new ScVbaShape( getParent(), mxContext, xShape, m_xShapes, m_xModel, ScVbaShape::getType( xShape ) ) ) ); + } + return uno::Any(); +} + +uno::Type +ScVbaShapes::getElementType() +{ + return cppu::UnoType<ooo::vba::msforms::XShape>::get(); +} + +OUString +ScVbaShapes::getServiceImplName() +{ + return "ScVbaShapes"; +} + +uno::Sequence< OUString > +ScVbaShapes::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.msform.Shapes" + }; + return aServiceNames; +} + +css::uno::Reference< css::container::XIndexAccess > +ScVbaShapes::getShapesByArrayIndices( const uno::Any& Index ) +{ + if ( Index.getValueTypeClass() != uno::TypeClass_SEQUENCE ) + throw uno::RuntimeException(); + + const uno::Reference< script::XTypeConverter >& xConverter = getTypeConverter(mxContext); + uno::Any aConverted = xConverter->convertTo( Index, cppu::UnoType<uno::Sequence< uno::Any >>::get() ); + + uno::Sequence< uno::Any > sIndices; + aConverted >>= sIndices; + XNamedObjectCollectionHelper< drawing::XShape >::XNamedVec aShapes; + for( const auto& rIndex : std::as_const(sIndices) ) + { + uno::Reference< drawing::XShape > xShape; + if ( rIndex.getValueTypeClass() == uno::TypeClass_STRING ) + { + OUString sName; + rIndex >>= sName; + xShape.set( m_xNameAccess->getByName( sName ), uno::UNO_QUERY ); + } + else + { + sal_Int32 nIndex = 0; + rIndex >>= nIndex; + // adjust for 1 based mso indexing + xShape.set( m_xIndexAccess->getByIndex( nIndex - 1 ), uno::UNO_QUERY ); + + } + // populate map with drawing::XShapes + if ( xShape.is() ) + aShapes.push_back( xShape ); + } + uno::Reference< container::XIndexAccess > xIndexAccess( new XNamedObjectCollectionHelper< drawing::XShape >( aShapes ) ); + return xIndexAccess; +} + +uno::Reference< msforms::XShapeRange > SAL_CALL +ScVbaShapes::Range( const uno::Any& shapes ) +{ + // shapes, can be an index or an array of indices + uno::Reference< container::XIndexAccess > xShapes; + if ( shapes.getValueTypeClass() == uno::TypeClass_SEQUENCE ) + xShapes = getShapesByArrayIndices( shapes ); + else + { + // wrap single index into a sequence + uno::Sequence< uno::Any > sIndices { shapes }; + uno::Any aIndex; + aIndex <<= sIndices; + xShapes = getShapesByArrayIndices( aIndex ); + } + return new ScVbaShapeRange( getParent(), mxContext, xShapes, m_xDrawPage, m_xModel ); +} + +void SAL_CALL +ScVbaShapes::SelectAll() +{ + uno::Reference< view::XSelectionSupplier > xSelectSupp( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); + try + { + xSelectSupp->select( uno::Any( m_xShapes ) ); + } + // viewuno.cxx ScTabViewObj::select will throw IllegalArgumentException + // if one of the shapes is no 'markable' e.g. a button + // the method still works + catch(const lang::IllegalArgumentException&) + { + } +} + +uno::Reference< drawing::XShape > +ScVbaShapes::createShape( const OUString& service ) +{ + uno::Reference< lang::XMultiServiceFactory > xMSF( m_xModel, uno::UNO_QUERY_THROW ); + uno::Reference< drawing::XShape > xShape( xMSF->createInstance( service ), uno::UNO_QUERY_THROW ); + return xShape; +} + +uno::Any +ScVbaShapes::AddRectangle(sal_Int32 startX, sal_Int32 startY, sal_Int32 nLineWidth, sal_Int32 nLineHeight) +{ + sal_Int32 nXPos = Millimeter::getInHundredthsOfOneMillimeter( startX ); + sal_Int32 nYPos = Millimeter::getInHundredthsOfOneMillimeter( startY ); + sal_Int32 nWidth = Millimeter::getInHundredthsOfOneMillimeter( nLineWidth ); + sal_Int32 nHeight = Millimeter::getInHundredthsOfOneMillimeter( nLineHeight ); + + uno::Reference< drawing::XShape > xShape( createShape( "com.sun.star.drawing.RectangleShape" ), uno::UNO_SET_THROW ); + m_xShapes->add( xShape ); + + OUString sName(createName( u"Rectangle" )); + setDefaultShapeProperties( xShape ); + setShape_NameProperty( xShape, sName ); + + awt::Point aMovePositionIfRange(0, 0); + awt::Point position; + position.X = nXPos - aMovePositionIfRange.X; + position.Y = nYPos - aMovePositionIfRange.Y; + xShape->setPosition( position ); + + awt::Size size; + size.Height = nHeight; + size.Width = nWidth; + xShape->setSize( size ); + + rtl::Reference<ScVbaShape> pScVbaShape = new ScVbaShape( getParent(), mxContext, xShape, m_xShapes, m_xModel, ScVbaShape::getType( xShape ) ); + return uno::Any( uno::Reference< msforms::XShape > ( pScVbaShape ) ); +} + +uno::Any +ScVbaShapes::AddEllipse(sal_Int32 startX, sal_Int32 startY, sal_Int32 nLineWidth, sal_Int32 nLineHeight) +{ + sal_Int32 nXPos = Millimeter::getInHundredthsOfOneMillimeter( startX ); + sal_Int32 nYPos = Millimeter::getInHundredthsOfOneMillimeter( startY ); + sal_Int32 nWidth = Millimeter::getInHundredthsOfOneMillimeter( nLineWidth ); + sal_Int32 nHeight = Millimeter::getInHundredthsOfOneMillimeter( nLineHeight ); + + uno::Reference< drawing::XShape > xShape( createShape( "com.sun.star.drawing.EllipseShape" ), uno::UNO_SET_THROW ); + m_xShapes->add( xShape ); + + awt::Point aMovePositionIfRange( 0, 0 ); + //TODO helperapi using a writer document + /* + XDocument xDocument = (XDocument)getParent(); + if (AnyConverter.isVoid(_aRange)) + { + _aRange = xDocument.Range(new Integer(0), new Integer(1)); + // Top&Left in Word is Top&Left of the paper and not the writeable area. + aMovePositionIfRange = calculateTopLeftMargin((HelperInterfaceAdaptor)xDocument); + } + + setShape_AnchorTypeAndRangeProperty(xShape, _aRange); + */ + OUString name(createName( u"Oval" )); + setDefaultShapeProperties(xShape); + setShape_NameProperty(xShape, name); + + awt::Point position; + position.X = nXPos - aMovePositionIfRange.X; + position.Y = nYPos - aMovePositionIfRange.Y; + xShape->setPosition(position); + + awt::Size size; + size.Height = nHeight; + size.Width = nWidth; + xShape->setSize(size); + + rtl::Reference<ScVbaShape> pScVbaShape = new ScVbaShape( getParent(), mxContext, xShape, m_xShapes, m_xModel, ScVbaShape::getType( xShape ) ); + return uno::Any( uno::Reference< msforms::XShape > ( pScVbaShape ) ); +} + +//helperapi calc +uno::Any SAL_CALL +ScVbaShapes::AddLine( sal_Int32 StartX, sal_Int32 StartY, sal_Int32 endX, sal_Int32 endY ) +{ + sal_Int32 nLineWidth = endX - StartX; + sal_Int32 nLineHeight = endY - StartY; + + sal_Int32 nHeight = Millimeter::getInHundredthsOfOneMillimeter( nLineHeight ); + sal_Int32 nWidth = Millimeter::getInHundredthsOfOneMillimeter( nLineWidth ); + sal_Int32 nXPos = Millimeter::getInHundredthsOfOneMillimeter( StartX ); + sal_Int32 nYPos = Millimeter::getInHundredthsOfOneMillimeter( StartY ); + + uno::Reference< drawing::XShape > xShape( createShape( "com.sun.star.drawing.LineShape" ), uno::UNO_SET_THROW ); + m_xShapes->add( xShape ); + + awt::Point aMovePositionIfRange( 0, 0 ); + + OUString name(createName( u"Line" )); + setDefaultShapeProperties(xShape); + setShape_NameProperty(xShape, name); + + awt::Point position; + position.X = nXPos - aMovePositionIfRange.X; + position.Y = nYPos - aMovePositionIfRange.Y; + xShape->setPosition(position); + + awt::Size size; + size.Height = nHeight; + size.Width = nWidth; + xShape->setSize(size); + + rtl::Reference<ScVbaShape> pScVbaShape = new ScVbaShape( getParent(), mxContext, xShape, m_xShapes, m_xModel, ScVbaShape::getType( xShape ) ); + return uno::Any( uno::Reference< msforms::XShape > ( pScVbaShape ) ); +} + +uno::Any SAL_CALL +ScVbaShapes::AddShape( sal_Int32 _nType, sal_Int32 _nLeft, sal_Int32 _nTop, sal_Int32 _nWidth, sal_Int32 _nHeight ) +{ + if (_nType == office::MsoAutoShapeType::msoShapeRectangle) + { + return AddRectangle(_nLeft, _nTop, _nWidth, _nHeight); + } + else if (_nType == office::MsoAutoShapeType::msoShapeOval) + { + return AddEllipse(_nLeft, _nTop, _nWidth, _nHeight); + } + return uno::Any(); +} + +uno::Any SAL_CALL +ScVbaShapes::AddTextbox( sal_Int32 /*_nOrientation*/, sal_Int32 _nLeft, sal_Int32 _nTop, sal_Int32 _nWidth, sal_Int32 _nHeight ) +{ + uno::Reference< lang::XServiceInfo > xServiceInfo( m_xModel, uno::UNO_QUERY_THROW ); + if( xServiceInfo->supportsService( "com.sun.star.text.TextDocument" ) ) + { + return AddTextboxInWriter( _nLeft, _nTop, _nWidth, _nHeight ); + } + throw uno::RuntimeException( "Not implemented" ); +} + +uno::Any +ScVbaShapes::AddTextboxInWriter( sal_Int32 _nLeft, sal_Int32 _nTop, sal_Int32 _nWidth, sal_Int32 _nHeight ) +{ + sal_Int32 nXPos = Millimeter::getInHundredthsOfOneMillimeter( _nLeft ); + sal_Int32 nYPos = Millimeter::getInHundredthsOfOneMillimeter( _nTop ); + sal_Int32 nWidth = Millimeter::getInHundredthsOfOneMillimeter( _nWidth ); + sal_Int32 nHeight = Millimeter::getInHundredthsOfOneMillimeter( _nHeight ); + + uno::Reference< drawing::XShape > xShape( createShape( "com.sun.star.drawing.TextShape" ), uno::UNO_SET_THROW ); + m_xShapes->add( xShape ); + + setDefaultShapeProperties(xShape); + + OUString sName(createName( u"Text Box" )); + setShape_NameProperty( xShape, sName ); + + awt::Size size; + size.Height = nHeight; + size.Width = nWidth; + xShape->setSize(size); + + uno::Reference< beans::XPropertySet > xShapeProps( xShape, uno::UNO_QUERY_THROW ); + xShapeProps->setPropertyValue( "AnchorType", uno::Any( text::TextContentAnchorType_AT_PAGE ) ); + xShapeProps->setPropertyValue( "HoriOrientRelation", uno::Any( text::RelOrientation::PAGE_LEFT ) ); + xShapeProps->setPropertyValue( "HoriOrient", uno::Any( text::HoriOrientation::NONE ) ); + xShapeProps->setPropertyValue( "HoriOrientPosition", uno::Any( nXPos ) ); + + xShapeProps->setPropertyValue( "VertOrientRelation", uno::Any( text::RelOrientation::PAGE_FRAME ) ); + xShapeProps->setPropertyValue( "VertOrient", uno::Any( text::VertOrientation::NONE ) ); + xShapeProps->setPropertyValue( "VertOrientPosition", uno::Any( nYPos ) ); + + // set to visible + xShapeProps->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID ) ); + // set to font + xShapeProps->setPropertyValue( "LayerID", uno::Any( sal_Int16(1) ) ); + xShapeProps->setPropertyValue( "LayerName", uno::Any( OUString("Heaven") ) ); + + + rtl::Reference<ScVbaShape> pScVbaShape = new ScVbaShape( getParent(), mxContext, xShape, m_xShapes, m_xModel, ScVbaShape::getType( xShape ) ); + return uno::Any( uno::Reference< msforms::XShape > ( pScVbaShape ) ); +} + +void +ScVbaShapes::setDefaultShapeProperties( const uno::Reference< drawing::XShape >& xShape ) +{ + uno::Reference< beans::XPropertySet > xPropertySet( xShape, uno::UNO_QUERY_THROW ); + xPropertySet->setPropertyValue( "FillStyle", uno::Any( OUString("SOLID") ) ); + xPropertySet->setPropertyValue( "FillColor", uno::Any( sal_Int32(0xFFFFFF) ) ); + xPropertySet->setPropertyValue( "TextWordWrap", uno::Any( text::WrapTextMode_THROUGH ) ); + //not find in OOo2.3 + //xPropertySet->setPropertyValue("Opaque", uno::makeAny( sal_True ) ); +} + +void +ScVbaShapes::setShape_NameProperty( const uno::Reference< css::drawing::XShape >& xShape, const OUString& sName ) +{ + uno::Reference< beans::XPropertySet > xPropertySet( xShape, uno::UNO_QUERY_THROW ); + try + { + xPropertySet->setPropertyValue( "Name", uno::Any( sName ) ); + } + catch(const script::BasicErrorException&) + { + } +} + +OUString +ScVbaShapes::createName( std::u16string_view sName ) +{ + sal_Int32 nActNumber = 1 + m_nNewShapeCount; + m_nNewShapeCount++; + return sName + OUString::number( nActNumber ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbatextframe.cxx b/vbahelper/source/vbahelper/vbatextframe.cxx new file mode 100644 index 000000000..d9373cb4e --- /dev/null +++ b/vbahelper/source/vbahelper/vbatextframe.cxx @@ -0,0 +1,157 @@ +/* -*- 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 . + */ + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/TextFitToSizeType.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <vbahelper/vbatextframe.hxx> + +using namespace ::ooo::vba; +using namespace ::com::sun::star; + +VbaTextFrame::VbaTextFrame( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, uno::Reference< drawing::XShape > const & xShape ) : VbaTextFrame_BASE( xParent, xContext ), m_xShape( xShape ) +{ + m_xPropertySet.set( m_xShape, uno::UNO_QUERY_THROW ); +} + +void +VbaTextFrame::setAsMSObehavior() +{ + //set property TextWordWrap default as False. + // TextFitToSize control the text content. It seems we should set the default as False. + // com.sun.star.drawing.TextFitToSizeType.NONE + m_xPropertySet->setPropertyValue( "TextWordWrap", uno::Any( false ) ); + m_xPropertySet->setPropertyValue( "TextFitToSize", uno::Any( drawing::TextFitToSizeType_NONE ) ); +} + +sal_Int32 VbaTextFrame::getMargin( const OUString& sMarginType ) +{ + sal_Int32 nMargin = 0; + uno::Any aMargin = m_xPropertySet->getPropertyValue( sMarginType ); + aMargin >>= nMargin; + return nMargin; +} + +void VbaTextFrame::setMargin( const OUString& sMarginType, float fMargin ) +{ + sal_Int32 nMargin = Millimeter::getInHundredthsOfOneMillimeter( fMargin ); + m_xPropertySet->setPropertyValue( sMarginType, uno::Any( nMargin ) ); +} + +// Attributes +sal_Bool SAL_CALL +VbaTextFrame::getAutoSize() +{ + // I don't know why, but in OOo, TextAutoGrowHeight is the property control autosize. not TextFitToSize. + // TextFitToSize control the text content. + // and in mso, there isnot option TextWordWrap which means auto wrap. the default is False. + bool bAutosize = false; + uno::Any aTextAutoGrowHeight = m_xPropertySet->getPropertyValue( "TextAutoGrowHeight" ); + aTextAutoGrowHeight >>= bAutosize; + return bAutosize; +} + +void SAL_CALL +VbaTextFrame::setAutoSize( sal_Bool _autosize ) +{ + setAsMSObehavior(); + m_xPropertySet->setPropertyValue( "TextAutoGrowHeight", uno::Any( _autosize ) ); +} + +float SAL_CALL +VbaTextFrame::getMarginBottom() +{ + sal_Int32 nMargin = getMargin( "TextLowerDistance" ); + float fMargin = static_cast<float>(Millimeter::getInPoints( nMargin )); + return fMargin; +} + +void SAL_CALL +VbaTextFrame::setMarginBottom( float _marginbottom ) +{ + setMargin( "TextLowerDistance", _marginbottom ); +} + +float SAL_CALL +VbaTextFrame::getMarginTop() +{ + sal_Int32 nMargin = getMargin( "TextUpperDistance" ); + float fMargin = static_cast<float>(Millimeter::getInPoints( nMargin )); + return fMargin; +} + +void SAL_CALL +VbaTextFrame::setMarginTop( float _margintop ) +{ + setMargin( "TextUpperDistance", _margintop ); +} + +float SAL_CALL +VbaTextFrame::getMarginLeft() +{ + sal_Int32 nMargin = getMargin( "TextLeftDistance" ); + float fMargin = static_cast<float>(Millimeter::getInPoints( nMargin )); + return fMargin; +} + +void SAL_CALL +VbaTextFrame::setMarginLeft( float _marginleft ) +{ + setMargin( "TextLeftDistance", _marginleft ); +} + +float SAL_CALL +VbaTextFrame::getMarginRight() +{ + sal_Int32 nMargin = getMargin( "TextRightDistance" ); + float fMargin = static_cast<float>(Millimeter::getInPoints( nMargin )); + return fMargin; +} + +void SAL_CALL +VbaTextFrame::setMarginRight( float _marginright ) +{ + setMargin( "TextRightDistance" , _marginright ); +} + + +// Methods +uno::Any SAL_CALL +VbaTextFrame::Characters() +{ + throw uno::RuntimeException( "Not implemented" ); +} + +OUString +VbaTextFrame::getServiceImplName() +{ + return "VbaTextFrame"; +} + +uno::Sequence< OUString > +VbaTextFrame::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.msforms.TextFrame" + }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vbahelper/source/vbahelper/vbawindowbase.cxx b/vbahelper/source/vbahelper/vbawindowbase.cxx new file mode 100644 index 000000000..a2735e31f --- /dev/null +++ b/vbahelper/source/vbahelper/vbawindowbase.cxx @@ -0,0 +1,171 @@ +/* -*- 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 . + */ + +#include <vbahelper/vbawindowbase.hxx> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XWindow2.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XModel.hpp> + +using namespace ::com::sun::star; +using namespace ::ooo::vba; + +VbaWindowBase::VbaWindowBase( + const uno::Reference< XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XModel >& xModel, + const uno::Reference< frame::XController >& xController ) : + WindowBaseImpl_BASE( xParent, xContext ), + m_xModel( xModel, uno::UNO_SET_THROW ) +{ + construct( xController ); +} + +VbaWindowBase::VbaWindowBase( uno::Sequence< uno::Any > const & args, + uno::Reference< uno::XComponentContext > const & xContext ) : + WindowBaseImpl_BASE( getXSomethingFromArgs< XHelperInterface >( args, 0, false ), xContext ), + m_xModel( getXSomethingFromArgs< frame::XModel >( args, 1, false ) ) +{ + construct( getXSomethingFromArgs< frame::XController >( args, 2 ) ); +} + +sal_Bool SAL_CALL +VbaWindowBase::getVisible() +{ + return getWindow2()->isVisible(); +} + +void SAL_CALL +VbaWindowBase::setVisible( sal_Bool _visible ) +{ + getWindow2()->setVisible( _visible ); +} + +static void setPosSize( const uno::Reference< awt::XWindow >& xWindow, sal_Int32 nValue, sal_Int16 nFlag ) +{ + css::awt::Rectangle aRect = xWindow->getPosSize(); + switch( nFlag ) + { + case css::awt::PosSize::X: + xWindow->setPosSize( nValue, aRect.Y, 0, 0, css::awt::PosSize::X ); + break; + case css::awt::PosSize::Y: + xWindow->setPosSize( aRect.X, nValue, 0, 0, css::awt::PosSize::Y ); + break; + case css::awt::PosSize::WIDTH: + xWindow->setPosSize( 0, 0, nValue, aRect.Height, css::awt::PosSize::WIDTH ); + break; + case css::awt::PosSize::HEIGHT: + xWindow->setPosSize( 0, 0, aRect.Width, nValue, css::awt::PosSize::HEIGHT ); + break; + default: + break; + } +} + +sal_Int32 SAL_CALL +VbaWindowBase::getHeight() +{ + return getWindow()->getPosSize().Height; +} + +void SAL_CALL +VbaWindowBase::setHeight( sal_Int32 _height ) +{ + setPosSize( getWindow(), _height, css::awt::PosSize::HEIGHT ); +} + +sal_Int32 SAL_CALL +VbaWindowBase::getLeft() +{ + return getWindow()->getPosSize().X; +} + +void SAL_CALL +VbaWindowBase::setLeft( sal_Int32 _left ) +{ + setPosSize( getWindow(), _left, css::awt::PosSize::X ); +} + +sal_Int32 SAL_CALL +VbaWindowBase::getTop() +{ + return getWindow()->getPosSize().Y; +} + +void SAL_CALL +VbaWindowBase::setTop( sal_Int32 _top ) +{ + setPosSize( getWindow(), _top, css::awt::PosSize::Y ); +} + +sal_Int32 SAL_CALL +VbaWindowBase::getWidth() +{ + return getWindow()->getPosSize().Width; +} + +void SAL_CALL +VbaWindowBase::setWidth( sal_Int32 _width ) +{ + setPosSize( getWindow(), _width, css::awt::PosSize::WIDTH ); +} + +OUString +VbaWindowBase::getServiceImplName() +{ + return "VbaWindowBase"; +} + +uno::Sequence< OUString > +VbaWindowBase::getServiceNames() +{ + static uno::Sequence< OUString > const aServiceNames + { + "ooo.vba.VbaWindowBase" + }; + return aServiceNames; +} + +uno::Reference< frame::XController > VbaWindowBase::getController() const +{ + return uno::Reference< frame::XController >( m_xController, uno::UNO_SET_THROW ); +} + +uno::Reference< awt::XWindow > VbaWindowBase::getWindow() const +{ + return uno::Reference< awt::XWindow >( m_xWindow, uno::UNO_SET_THROW ); +} + +uno::Reference< awt::XWindow2 > VbaWindowBase::getWindow2() const +{ + return uno::Reference< awt::XWindow2 >( getWindow(), uno::UNO_QUERY_THROW ); +} + +void VbaWindowBase::construct( const uno::Reference< frame::XController >& xController ) +{ + if( !xController.is() ) throw uno::RuntimeException(); + uno::Reference< frame::XFrame > xFrame( xController->getFrame(), uno::UNO_SET_THROW ); + uno::Reference< awt::XWindow > xWindow( xFrame->getContainerWindow(), uno::UNO_SET_THROW ); + m_xController = xController; + m_xWindow = xWindow; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |