diff options
author | Justin Luth <justin.luth@collabora.com> | 2022-11-03 17:59:14 -0400 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-11-14 09:43:52 +0100 |
commit | 98d322d6c0e935a24f46bef014824084b6fcfdfd (patch) | |
tree | 7b321318365f9d49b922db1719c4ffd03532b899 /sw | |
parent | b257b4f247bc2a1fa4d469ec82e37bdbb268951b (diff) |
tdf#151548 vba FormFields: Add basic word::XTextInput support
make CppunitTest_sw_macros_test CPPUNIT_TEST_NAME=testVba
This now allows MS Word Basic legacy text form fields
to be controlled by VBA basic.
-allows getting and setting the text string
Change-Id: Ib4601d4e087233a3db257728374b362bb34d1ecb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142262
Tested-by: Jenkins
Reviewed-by: Justin Luth <jluth@mail.com>
Reviewed-by: Tor Lillqvist <tml@collabora.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/Library_vbaswobj.mk | 1 | ||||
-rw-r--r-- | sw/qa/core/data/docm/testVBA.docm | bin | 30997 -> 30732 bytes | |||
-rw-r--r-- | sw/source/core/crsr/bookmark.cxx | 41 | ||||
-rw-r--r-- | sw/source/core/inc/bookmark.hxx | 6 | ||||
-rw-r--r-- | sw/source/ui/vba/vbaformfield.cxx | 6 | ||||
-rw-r--r-- | sw/source/ui/vba/vbaformfieldtextinput.cxx | 132 | ||||
-rw-r--r-- | sw/source/ui/vba/vbaformfieldtextinput.hxx | 68 |
7 files changed, 251 insertions, 3 deletions
diff --git a/sw/Library_vbaswobj.mk b/sw/Library_vbaswobj.mk index 027b67a5f12c..5785f11f14cf 100644 --- a/sw/Library_vbaswobj.mk +++ b/sw/Library_vbaswobj.mk @@ -75,6 +75,7 @@ $(eval $(call gb_Library_add_exception_objects,vbaswobj,\ sw/source/ui/vba/vbaformfield \ sw/source/ui/vba/vbaformfields \ sw/source/ui/vba/vbaformfieldcheckbox \ + sw/source/ui/vba/vbaformfieldtextinput \ sw/source/ui/vba/vbaframe \ sw/source/ui/vba/vbaframes \ sw/source/ui/vba/vbalistformat \ diff --git a/sw/qa/core/data/docm/testVBA.docm b/sw/qa/core/data/docm/testVBA.docm Binary files differindex 58ac4e8bd3ae..9abcd091638d 100644 --- a/sw/qa/core/data/docm/testVBA.docm +++ b/sw/qa/core/data/docm/testVBA.docm diff --git a/sw/source/core/crsr/bookmark.cxx b/sw/source/core/crsr/bookmark.cxx index 8bc383f01b23..da13b5165849 100644 --- a/sw/source/core/crsr/bookmark.cxx +++ b/sw/source/core/crsr/bookmark.cxx @@ -554,6 +554,7 @@ namespace sw::mark TextFieldmark::TextFieldmark(const SwPaM& rPaM, const OUString& rName) : Fieldmark(rPaM) + , m_pDocumentContentOperationsManager(nullptr) { if ( !rName.isEmpty() ) m_aName = rName; @@ -562,6 +563,7 @@ namespace sw::mark void TextFieldmark::InitDoc(SwDoc& io_rDoc, sw::mark::InsertMode const eMode, SwPosition const*const pSepPos) { + m_pDocumentContentOperationsManager = &io_rDoc.GetDocumentContentOperationsManager(); if (eMode == sw::mark::InsertMode::New) { lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, pSepPos); @@ -586,6 +588,45 @@ namespace sw::mark sw::UpdateFramesForRemoveDeleteRedline(rDoc, tmp); } + OUString TextFieldmark::GetContent() const + { + const SwTextNode& rTextNode = *GetMarkEnd().GetNode().GetTextNode(); + SwPosition const sepPos(sw::mark::FindFieldSep(*this)); + const sal_Int32 nStart(sepPos.GetContentIndex()); + const sal_Int32 nEnd(GetMarkEnd().GetContentIndex()); + + OUString sContent; + const sal_Int32 nLen = rTextNode.GetText().getLength(); + if (nStart + 1 < nLen && nEnd <= nLen && nEnd > nStart + 2) + sContent = rTextNode.GetText().copy(nStart + 1, nEnd - nStart - 2); + + return sContent; + } + + void TextFieldmark::ReplaceContent(const OUString& sNewContent) + { + if (!m_pDocumentContentOperationsManager) + return; + + SwPosition const sepPos(sw::mark::FindFieldSep(*this)); + const sal_Int32 nStart(sepPos.GetContentIndex()); + const sal_Int32 nEnd(GetMarkEnd().GetContentIndex()); + + const sal_Int32 nLen = GetMarkEnd().GetNode().GetTextNode()->GetText().getLength(); + if (nStart + 1 < nLen && nEnd <= nLen && nEnd > nStart + 2) + { + SwPaM aFieldPam(GetMarkStart().GetNode(), nStart + 1, + GetMarkStart().GetNode(), nEnd - 1); + m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false); + } + else + { + SwPaM aFieldStartPam(GetMarkStart().GetNode(), nStart + 1); + m_pDocumentContentOperationsManager->InsertString(aFieldStartPam, sNewContent); + } + Invalidate(); + } + NonTextFieldmark::NonTextFieldmark(const SwPaM& rPaM) : Fieldmark(rPaM) { } diff --git a/sw/source/core/inc/bookmark.hxx b/sw/source/core/inc/bookmark.hxx index 94788b8dcdcf..14c176c96a36 100644 --- a/sw/source/core/inc/bookmark.hxx +++ b/sw/source/core/inc/bookmark.hxx @@ -241,6 +241,12 @@ namespace sw::mark { TextFieldmark(const SwPaM& rPaM, const OUString& rName); virtual void InitDoc(SwDoc& io_rDoc, sw::mark::InsertMode eMode, SwPosition const* pSepPos) override; virtual void ReleaseDoc(SwDoc& rDoc) override; + + OUString GetContent() const override; + void ReplaceContent(const OUString& sNewContent) override; + + private: + sw::DocumentContentOperationsManager* m_pDocumentContentOperationsManager; }; // Non text fieldmarks have no content between the start and end marks. diff --git a/sw/source/ui/vba/vbaformfield.cxx b/sw/source/ui/vba/vbaformfield.cxx index 35e8927fe02e..dd43e47b84bf 100644 --- a/sw/source/ui/vba/vbaformfield.cxx +++ b/sw/source/ui/vba/vbaformfield.cxx @@ -26,6 +26,7 @@ #include "vbaformfield.hxx" #include "vbaformfieldcheckbox.hxx" +#include "vbaformfieldtextinput.hxx" #include "wordvbahelper.hxx" using namespace ::ooo::vba; @@ -67,9 +68,8 @@ uno::Any SAL_CALL SwVbaFormField::DropDown() uno::Any SAL_CALL SwVbaFormField::TextInput() { - // return uno::Any(uno::Reference<word::XTextInput>( - // new SwVbaFormFieldTextInput(mxParent, mxContext, m_rFormField))); - return uno::Any(); + return uno::Any(uno::Reference<word::XTextInput>( + new SwVbaFormFieldTextInput(mxParent, mxContext, m_rFormField))); } uno::Any SAL_CALL SwVbaFormField::Previous() diff --git a/sw/source/ui/vba/vbaformfieldtextinput.cxx b/sw/source/ui/vba/vbaformfieldtextinput.cxx new file mode 100644 index 000000000000..8fb65395ef88 --- /dev/null +++ b/sw/source/ui/vba/vbaformfieldtextinput.cxx @@ -0,0 +1,132 @@ +/* -*- 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/. + */ + +#include <ooo/vba/word/WdTextFormFieldType.hpp> + +#include <sal/log.hxx> + +#include "vbaformfieldtextinput.hxx" + +using namespace ::ooo::vba; +using namespace ::com::sun::star; + +/** + * Official documentation at https://learn.microsoft.com/en-us/office/vba/api/word.textinput + * + * TextInput formfields are inline text objects that are only found in MS Word. + * They cannot be created in Excel or in Calc. + * + * Note that VBA might call this a TextInput, but it might not actually be one, + * so make good use of getValid() + */ +SwVbaFormFieldTextInput::SwVbaFormFieldTextInput( + const uno::Reference<ooo::vba::XHelperInterface>& rParent, + const uno::Reference<uno::XComponentContext>& rContext, sw::mark::IFieldmark& rFormField) + : SwVbaFormFieldTextInput_BASE(rParent, rContext) + , m_rTextInput(rFormField) +{ +} + +SwVbaFormFieldTextInput::~SwVbaFormFieldTextInput() {} + +OUString SwVbaFormFieldTextInput::getDefaultPropertyName() { return "Valid"; } + +sal_Bool SwVbaFormFieldTextInput::getValid() +{ + return IDocumentMarkAccess::GetType(m_rTextInput) + == IDocumentMarkAccess::MarkType::TEXT_FIELDMARK; +} + +OUString SwVbaFormFieldTextInput::getDefault() +{ + if (!getValid()) + return OUString(); + + return m_rTextInput.GetContent(); +} + +void SwVbaFormFieldTextInput::setDefault(const OUString& sSet) +{ + // Hard to know what to do here, since LO doesn't have a default property for text input. + // This really only makes sense when macro-adding a text input. + // In that case, we want it to affect the actual text content. + // However, if the text has already been set by the user, then this shouldn't do anything. + // Assuming this is only ever set when adding a text input seems the sanest approach. + if (!getValid() || getDefault() == sSet) + return; + + m_rTextInput.ReplaceContent(sSet); +} + +OUString SwVbaFormFieldTextInput::getFormat() +{ + if (!getValid()) + return OUString(); + + SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::getFormat stub"); + return OUString(); +} + +sal_Int32 SwVbaFormFieldTextInput::getType() +{ + if (!getValid()) + return word::WdTextFormFieldType::wdRegularText; + + SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::getType stub"); + return word::WdTextFormFieldType::wdRegularText; +} + +sal_Int32 SwVbaFormFieldTextInput::getWidth() +{ + if (!getValid()) + return 0; + + SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::getWidth stub"); + return 11 * 50; +} + +void SwVbaFormFieldTextInput::setWidth(sal_Int32 nWidth) +{ + if (!getValid()) + return; + + SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::setWidth[" << nWidth << "] stub"); +} + +void SwVbaFormFieldTextInput::Clear() +{ + if (!getValid() || m_rTextInput.GetContent().isEmpty()) + return; + + m_rTextInput.ReplaceContent(""); +} + +void SwVbaFormFieldTextInput::EditType(sal_Int32 nType, const uno::Any& rDefault, + const uno::Any& rFormat, const uno::Any& rEnabled) +{ + OUString sDefault; + OUString sFormat; + bool bEnabled = true; + rDefault >>= sDefault; + rFormat >>= sFormat; + rEnabled >>= bEnabled; + SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::EditType[" + << nType << "] sDefault[" << sDefault << "] sFormat[" << sFormat + << "] bEnabled[" << bEnabled << "] stub"); +} + +OUString SwVbaFormFieldTextInput::getServiceImplName() { return "SwVbaFormFieldTextInput"; } + +uno::Sequence<OUString> SwVbaFormFieldTextInput::getServiceNames() +{ + static uno::Sequence<OUString> const aServiceNames{ "ooo.vba.word.TextInput" }; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/vba/vbaformfieldtextinput.hxx b/sw/source/ui/vba/vbaformfieldtextinput.hxx new file mode 100644 index 000000000000..513cac64defd --- /dev/null +++ b/sw/source/ui/vba/vbaformfieldtextinput.hxx @@ -0,0 +1,68 @@ +/* -*- 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/. + */ +#pragma once + +#include <ooo/vba/word/XTextInput.hpp> + +#include <vbahelper/vbahelperinterface.hxx> + +#include <IDocumentMarkAccess.hxx> + +typedef InheritedHelperInterfaceWeakImpl<ooo::vba::word::XTextInput> SwVbaFormFieldTextInput_BASE; + +class SwVbaFormFieldTextInput : public SwVbaFormFieldTextInput_BASE +{ +private: + sw::mark::IFieldmark& m_rTextInput; + +public: + /// @throws css::uno::RuntimeException + SwVbaFormFieldTextInput(const css::uno::Reference<ooo::vba::XHelperInterface>& rParent, + const css::uno::Reference<css::uno::XComponentContext>& rContext, + sw::mark::IFieldmark& rFormField); + ~SwVbaFormFieldTextInput() override; + + // XTextInput + OUString SAL_CALL getDefaultPropertyName() override; + + // default member: True if the specified form field object is a valid text form field + sal_Bool SAL_CALL getValid() override; + + // Returns and sets the default text string of the input box + OUString SAL_CALL getDefault() override; + void SAL_CALL setDefault(const OUString& bSet) override; + // Returns the format string for the current text + OUString SAL_CALL getFormat() override; + /* + * Returns the type of text form field. + * Possible return values are: + * wdCalculationText - Calculation text field, + * wdCurrentDateText - Current date text field, + * wdCurrentTimeText - Current time text field, + * wdDateText - Date text field, + * wdNumberText - Number text field, + * wdRegularText - Regular text field. + */ + sal_Int32 SAL_CALL getType() override; + // Returns and sets the width, in points + sal_Int32 SAL_CALL getWidth() override; + void SAL_CALL setWidth(sal_Int32 nSet) override; + + // Deletes the text from the text form field. + void SAL_CALL Clear() override; + // Sets the type, default text string, format string, and enabled status + void SAL_CALL EditType(sal_Int32 nType, const css::uno::Any& rDefault, + const css::uno::Any& rFormat, const css::uno::Any& rEnabled) override; + + // XHelperInterface + OUString getServiceImplName() override; + css::uno::Sequence<OUString> getServiceNames() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |