tdf#151548 vba ContentControls: Add basic word::XContentControl
This adds basic VBA macro support for accessing
the modern content controls used for creating forms.
I ran out of time to make it fully functional.
TODO
-Invalidation: the screen isn't updating the modified results until
interaction from the user (mouse click, etc.)
-Unlike FormFields, content controls really depend on having
Range working. I didn't have time to look into that.
-I was hoping to check that my approach could accommodate the other
methods that create a filtered ContentControls object:
* Document.SelectLinkedControls,
* Document.SelectUnlinkedControls
* Range.ContentControls.
I guess it will be left up to whoever needs these to add the bits
that will create an appropriate collection for these limited sets.
-setType: changing one type to another - both LO and Word allow
limited use of this - depending on the text contents fitting
the new type.
What works:
-getByIndex - which probably is the "normal" way to do it,
since the UI doesn't provide a name/ID; just got via msgbox .ID.
-full checkbox support (minus the visual invalidation)
-VBA accepts almost all properties/methods that are requested.
make CppunitTest_sw_macros_test CPPUNIT_TEST_NAME=testVba
If Not ActiveDocument.ContentControls(1).Checked
If ActiveDocument.ContentControls(2).Checked
'If ActiveDocument.ContentControls(2).Range.Text <> "$"
ActiveDocument.SelectContentControlsByTag("checkboxes").Item(1).Checked
= ActiveDocument.SelectContentControlsByTag("checkboxes").Item(2).Checked
ActiveDocument.SelectContentControlsByTag("checkboxes")
.Item(2).SetUncheckedSymbol (8364) '€
With ActiveDocument.SelectContentControlsByTitle("listbox").Item(1)
If Not .ShowingPlaceholderText
'If .Range.Text <> "Choose an item."
If .Type <> wdContentControlDropdownList
End With
With ActiveDocument.ContentControls.Item(5)
'If Not .Temporary Then GoTo errorhandler:
If .Temporary <> False Then GoTo errorhandler:
If .Tag <> "" Then GoTo errorhandler:
If .Title <> "" Then GoTo errorhandler:
End With
With ActiveDocument.ContentControls.Item(6)
If .Type <> wdContentControlText
If .MultiLine Then GoTo errorhandler:
If ActiveDocument.ContentControls.Count <> 7
.Delete 'Doesn't actually Delete in LO yet - unsafe
' If ActiveDocument.ContentControls.Count <> 6
End With
' Change to 6 when delete is working safely
With ActiveDocument.ContentControls.Item(7)
If .Type <> wdContentControlDate Then GoTo errorhandler:
.Color = wdColorBlueGray 'unknown to Word 2010
If .Color <> wdColorBlueGray Then GoTo errorhandler:
If .DateDisplayFormat <> "mm/yy/dd" Then GoTo errorhandler:
If .DateCalendarType <> wdCalendarWestern Then GoTo errorhandler:
If .LockContents <> False Then GoTo errorhandler:
End With
Change-Id: I1c636f671de81e0283c040a578838a0433ef1f5b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143080
Tested-by: Jenkins
Reviewed-by: Justin Luth <jluth@mail.com>
diff --git a/oovbaapi/UnoApi_oovbaapi.mk b/oovbaapi/UnoApi_oovbaapi.mk
index 331cf49..06370076 100644
--- a/oovbaapi/UnoApi_oovbaapi.mk
+++ b/oovbaapi/UnoApi_oovbaapi.mk
@@ -833,6 +833,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,oovbaapi,ooo/vba/word,\
WdFarEastLineBreakLevel \
WdFieldKind \
WdFieldShading \
WdContentControlType \
WdFieldType \
WdFindMatch \
WdFindWrap \
@@ -1057,6 +1058,8 @@ $(eval $(call gb_UnoApi_add_idlfiles,oovbaapi,ooo/vba/word,\
XFields \
XFind \
XFont \
XContentControl \
XContentControls \
XFormField \
XFormFields \
XFrame \
diff --git a/oovbaapi/ooo/vba/word/WdContentControlType.idl b/oovbaapi/ooo/vba/word/WdContentControlType.idl
new file mode 100644
index 0000000..d93159a
--- /dev/null
+++ b/oovbaapi/ooo/vba/word/WdContentControlType.idl
@@ -0,0 +1,25 @@
/* -*- 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/.
*/
module ooo { module vba { module word {
constants WdContentControlType {
const long wdContentControlRichText = 0;
const long wdContentControlText = 1;
const long wdContentControlPicture = 2;
const long wdContentControlComboBox = 3;
const long wdContentControlDropdownList = 4;
const long wdContentControlBuildingBlockGallery = 5;
const long wdContentControlDate = 6;
const long wdContentControlGroup = 7;
const long wdContentControlCheckbox = 8;
const long wdContentControlRepeatingSection = 9;
};
}; }; };
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oovbaapi/ooo/vba/word/XContentControl.idl b/oovbaapi/ooo/vba/word/XContentControl.idl
new file mode 100644
index 0000000..e538460
--- /dev/null
+++ b/oovbaapi/ooo/vba/word/XContentControl.idl
@@ -0,0 +1,103 @@
/* -*- 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/.
*/
module ooo { module vba { module word {
interface XRange;
interface XContentControlListEntries;
interface XContentControl
{
interface ooo::vba::XHelperInterface;
/// returns or sets whether users can add/remove sections from the specified repeating section
/// content control by using the user interface.
/// Use only with repeating section content controls.
[attribute] boolean AllowInsertDeleteSection;
/// returns or sets the appearance of the content control.
/// (wdContentControlBoundingBox/wdContentControlHidden/wdContentControlTags)
[attribute] long Appearance;
/// returns or sets a String that represents the category for a building block content control.
[attribute] string BuildingBlockCategory;
/// returns or sets a WdBuildingBlockTypes constant that represents the type of building block
/// for a building block content control.
[attribute] long BuildingBlockType;
/// returns or sets a Boolean that represents a check box's current state (checked/unchecked).
[attribute] boolean Checked;
/// returns or sets the color of the content control.
[attribute] long Color;
/// returns or sets a WdCalendarType constant that represents the calendar type.
[attribute] long DateCalendarType;
/// returns or sets a String that represents the format in which dates are displayed.
[attribute] string DateDisplayFormat;
/// returns a WdLanguageID that represents the language format for the date displayed.
[attribute, readonly] long DateDisplayLocale;
/// returns or sets a WdContentControlDateStorageFormat that represents the format for storage
/// and retrieval of dates when a date content control is bound to the XML data store.
[attribute] long DateStorageFormat;
/// returns or sets a Variant that represents the name of the character style to use to format text in a text content control.
//[attribute] string DefaultTextStyle;
/// returns a ContentControlListEntries collection that represents the items
/// in a drop-down list content control or in a combo box content control.
[attribute, readonly] any DropdownListEntries;
/// returns a String that represents the identification for a content control.
[attribute, readonly] string ID;
/// returns the level of the content control—whether the content control surrounds text, paragraphs, table cells, or table rows; or if it is inline.
/// (wdContentControlLevelCell/wdContentControlLevelInline/wdContentControlLevelParagraph/wdContentControlLevelRow)
[attribute, readonly] long Level;
/// returns or sets whether the user can delete a content control from the active document.
[attribute] boolean LockContentControl;
/// returns or sets whether the user can edit the contents of a content control.
[attribute] boolean LockContents;
/// returns or sets whether a text content control allows multiple lines of text.
[attribute] boolean MultiLine;
/// returns a ContentControl that represents the parent content control for a content control that is nested inside a rich-text control or group control.
//[attribute, readonly] XContentControl ParentContentControl;
/// returns a BuildingBlock object that represents the placeholder text for a content control.
[attribute, readonly] /*WRONG - should be XBuildingBlock*/ string PlaceholderText;
/// returns a Range that represents the contents of the content control in the active document.
[attribute, readonly] XRange Range;
/// returns the collection of repeating section items in the specified repeating section content control.
//[attribute, readonly] RepeatingSectionItems;
/// returns or sets the name of the repeating section items used in the context menu associated
/// with the specified repeating section content control.
[attribute] string RepeatingSectionItemTitle;
/// returns whether the placeholder text for the content control is displayed.
[attribute, readonly] boolean ShowingPlaceholderText;
/// returns or sets a String that represents a value to identify a content control.
[attribute] string Tag;
/// returns or sets whether to remove a content control from the active document
/// when the user edits the contents of the control.
[attribute] boolean Temporary;
/// returns or sets a String that represents the title for a content control.
[attribute] string Title;
/// returns or sets a WdContentControlType that represents the type for a content control.
[attribute] long Type;
/// returns an XMLMapping object that represents the mapping of a content control to XML data in the data store of a document.
//[attribute, readonly] XMLMapping;
/// Copies the content control from the active document to the Clipboard.
void Copy();
/// Removes the content control from the active document and moves it to the Clipboard.
void Cut();
/// Deletes the specified content control and the contents of the content control.
void Delete( [in] /*optional*/ any bDeleteContents );
/// Sets the symbol used to represent the checked state of a check box content control.
void SetCheckedSymbol( [in] long Character, [in] /*optional*/ any sFont );
/// Sets the symbol used to represent the unchecked state of a check box content control.
void SetUnCheckedSymbol( [in] long Character, [in] /*optional*/ any sFont );
/// Sets the placeholder text that displays until a user enters their own text.
void SetPlaceholderText( [in] /*optional*/ any BuildingBlock, [in] /*optional*/ any Range, [in] /*optional*/ any sFont );
/// Removes a group content control. Its children are no longer nested and can be freely edited.
void Ungroup();
};
}; }; };
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oovbaapi/ooo/vba/word/XContentControls.idl b/oovbaapi/ooo/vba/word/XContentControls.idl
new file mode 100644
index 0000000..49facea
--- /dev/null
+++ b/oovbaapi/ooo/vba/word/XContentControls.idl
@@ -0,0 +1,23 @@
/* -*- 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/.
*/
module ooo { module vba { module word {
interface XContentControl;
interface XContentControls
{
interface ::ooo::vba::XCollection;
/// Returns a ContentControl object that represents a new WdContentControlType added at a range
//XContentControl Add( [in] /*optional*/ any Type, [in] /*optional*/ any Range ) raises ( com::sun::star::script::BasicErrorException );
};
}; }; };
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oovbaapi/ooo/vba/word/XDocument.idl b/oovbaapi/ooo/vba/word/XDocument.idl
index 0f7b5f9..354cac1 100644
--- a/oovbaapi/ooo/vba/word/XDocument.idl
+++ b/oovbaapi/ooo/vba/word/XDocument.idl
@@ -37,6 +37,9 @@ interface XDocument
any BuiltInDocumentProperties( [in] any Index );
any CustomDocumentProperties( [in] any Index );
any Bookmarks( [in] any Index );
any ContentControls( [in] any Index );
any SelectContentControlsByTag( [in] any Index );
any SelectContentControlsByTitle( [in] any Index );
any Variables( [in] any Index );
any Paragraphs( [in] any Index );
any Styles( [in] any Index ) raises (com::sun::star::script::BasicErrorException);
diff --git a/sw/Library_vbaswobj.mk b/sw/Library_vbaswobj.mk
index 1b0ca04..e6b45b4 100644
--- a/sw/Library_vbaswobj.mk
+++ b/sw/Library_vbaswobj.mk
@@ -72,6 +72,8 @@ $(eval $(call gb_Library_add_exception_objects,vbaswobj,\
sw/source/ui/vba/vbacells \
sw/source/ui/vba/vbacolumn \
sw/source/ui/vba/vbacolumns \
sw/source/ui/vba/vbacontentcontrol \
sw/source/ui/vba/vbacontentcontrols \
sw/source/ui/vba/vbaformfield \
sw/source/ui/vba/vbaformfields \
sw/source/ui/vba/vbaformfieldcheckbox \
diff --git a/sw/qa/core/data/docm/testModernVBA.docm b/sw/qa/core/data/docm/testModernVBA.docm
new file mode 100644
index 0000000..faa8576
--- /dev/null
+++ b/sw/qa/core/data/docm/testModernVBA.docm
Binary files differ
diff --git a/sw/qa/core/macros-test.cxx b/sw/qa/core/macros-test.cxx
index a4030b0..df56212 100644
--- a/sw/qa/core/macros-test.cxx
+++ b/sw/qa/core/macros-test.cxx
@@ -91,6 +91,10 @@ void SwMacrosTest::testVba()
OUString("vnd.sun.Star.script:Project.ThisDocument.testAll?language=Basic&location=document")
},
{
OUString("testModernVBA.docm"),
OUString("vnd.sun.Star.script:Project.ThisDocument.testAll?language=Basic&location=document")
},
{
OUString("testFind.docm"),
OUString("vnd.sun.Star.script:Project.Module1.testAll?language=Basic&location=document")
},
diff --git a/sw/source/ui/vba/vbacontentcontrol.cxx b/sw/source/ui/vba/vbacontentcontrol.cxx
new file mode 100644
index 0000000..3d51d8b
--- /dev/null
+++ b/sw/source/ui/vba/vbacontentcontrol.cxx
@@ -0,0 +1,754 @@
/* -*- 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/WdColor.hpp>
#include <ooo/vba/word/WdCalendarType.hpp>
#include <ooo/vba/word/WdContentControlType.hpp>
#include <ooo/vba/word/WdLanguageID.hpp>
#include <sal/log.hxx>
#include <ndtxt.hxx>
#include "vbacontentcontrol.hxx"
//#include "vbacontentcontroldropdownlistentries.hxx"
using namespace ::ooo::vba;
using namespace ::com::sun::star;
/**
* Content controls are the modern version of FormFields, providing inline functionality similar
* to that of ActiveX form controls. Individual content controls may contain contents
* such as dates, lists, or paragraphs of formatted text.
*
* Not all functions are applicable to each type of control, so use getType verification liberally.
*/
SwVbaContentControl::SwVbaContentControl(const uno::Reference<XHelperInterface>& rParent,
const uno::Reference<uno::XComponentContext>& rContext,
const uno::Reference<text::XTextDocument>& xTextDocument,
SwTextContentControl& rContentControl)
: SwVbaContentControl_BASE(rParent, rContext)
, mxTextDocument(xTextDocument)
, m_rCC(rContentControl)
{
}
SwVbaContentControl::~SwVbaContentControl() {}
sal_Bool SwVbaContentControl::getAllowInsertDeleteSection()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getAllowInsertDeleteSection stub");
return false;
}
void SwVbaContentControl::setAllowInsertDeleteSection(sal_Bool /*bSet*/)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setAllowInsertDeleteSection stub");
}
sal_Int32 SwVbaContentControl::getAppearance()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getAppearance stub");
// wdContentControlBoundingBox / wdContentControlHidden / wdContentControlTags
return 0;
}
void SwVbaContentControl::setAppearance(sal_Int32 nSet)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setAppearance[" << nSet << "] stub");
}
OUString SwVbaContentControl::getBuildingBlockCategory()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getBuildingBlockCategory stub");
return OUString();
}
void SwVbaContentControl::setBuildingBlockCategory(const OUString& sSet)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setBuildingBlockCategory[" << sSet << "] stub");
}
sal_Int32 SwVbaContentControl::getBuildingBlockType()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getBuildingBlockType stub");
// returns a WdBuildingBlockTypes that represents the type of building block
return 0;
}
void SwVbaContentControl::setBuildingBlockType(sal_Int32 nSet)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setBuildingBlockType[" << nSet << "] stub");
}
sal_Bool SwVbaContentControl::getChecked()
{
const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl();
return pCC->GetCheckbox() && pCC->GetChecked();
}
void SwVbaContentControl::setChecked(sal_Bool bSet)
{
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
if (pCC->GetCheckbox() && pCC->GetChecked() != static_cast<bool>(bSet))
{
pCC->SetChecked(bSet);
//pCC->Invalidate();
}
}
sal_Int32 SwVbaContentControl::getColor()
{
const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl();
//This is just an assumed implementation - I have no testing environment to confirm.
OUString sColor = pCC->GetColor();
if (sColor == "wdColorAutomatic")
return word::WdColor::wdColorAutomatic;
if (sColor == "wdColorBlack")
return word::WdColor::wdColorBlack;
if (sColor == "wdColorBlue")
return word::WdColor::wdColorBlue;
if (sColor == "wdColorBlueGray")
return word::WdColor::wdColorBlueGray;
if (sColor == "wdColorBrightGreen")
return word::WdColor::wdColorBrightGreen;
if (sColor == "wdColorBrown")
return word::WdColor::wdColorBrown;
if (sColor == "wdColorDarkBlue")
return word::WdColor::wdColorDarkBlue;
if (sColor == "wdColorDarkGreen")
return word::WdColor::wdColorDarkGreen;
if (sColor == "wdColorDarkRed")
return word::WdColor::wdColorDarkRed;
if (sColor == "wdColorDarkTeal")
return word::WdColor::wdColorDarkTeal;
if (sColor == "wdColorDarkYellow")
return word::WdColor::wdColorDarkYellow;
if (sColor == "wdColorGold")
return word::WdColor::wdColorGold;
if (sColor == "wdColorGray05")
return word::WdColor::wdColorGray05;
if (sColor == "wdColorGray10")
return word::WdColor::wdColorGray10;
if (sColor == "wdColorGray125")
return word::WdColor::wdColorGray125;
if (sColor == "wdColorGray15")
return word::WdColor::wdColorGray15;
if (sColor == "wdColorGray20")
return word::WdColor::wdColorGray20;
if (sColor == "wdColorGray25")
return word::WdColor::wdColorGray25;
if (sColor == "wdColorGray30")
return word::WdColor::wdColorGray30;
if (sColor == "wdColorGray35")
return word::WdColor::wdColorGray35;
if (sColor == "wdColorGray375")
return word::WdColor::wdColorGray375;
if (sColor == "wdColorGray40")
return word::WdColor::wdColorGray40;
if (sColor == "wdColorGray45")
return word::WdColor::wdColorGray45;
if (sColor == "wdColorGray50")
return word::WdColor::wdColorGray50;
if (sColor == "wdColorGray55")
return word::WdColor::wdColorGray55;
if (sColor == "wdColorGray60")
return word::WdColor::wdColorGray60;
if (sColor == "wdColorGray625")
return word::WdColor::wdColorGray625;
if (sColor == "wdColorGray65")
return word::WdColor::wdColorGray65;
if (sColor == "wdColorGray70")
return word::WdColor::wdColorGray70;
if (sColor == "wdColorGray75")
return word::WdColor::wdColorGray75;
if (sColor == "wdColorGray80")
return word::WdColor::wdColorGray80;
if (sColor == "wdColorGray85")
return word::WdColor::wdColorGray85;
if (sColor == "wdColorGray875")
return word::WdColor::wdColorGray875;
if (sColor == "wdColorGray90")
return word::WdColor::wdColorGray90;
if (sColor == "wdColorGray95")
return word::WdColor::wdColorGray95;
if (sColor == "wdColorGreen")
return word::WdColor::wdColorGreen;
if (sColor == "wdColorIndigo")
return word::WdColor::wdColorIndigo;
if (sColor == "wdColorLavender")
return word::WdColor::wdColorLavender;
if (sColor == "wdColorLightBlue")
return word::WdColor::wdColorLightBlue;
if (sColor == "wdColorLightGreen")
return word::WdColor::wdColorLightGreen;
if (sColor == "wdColorLightOrange")
return word::WdColor::wdColorLightOrange;
if (sColor == "wdColorLightTurquoise")
return word::WdColor::wdColorLightTurquoise;
if (sColor == "wdColorLightYellow")
return word::WdColor::wdColorLightYellow;
if (sColor == "wdColorLime")
return word::WdColor::wdColorLime;
if (sColor == "wdColorOliveGreen")
return word::WdColor::wdColorOliveGreen;
if (sColor == "wdColorOrange")
return word::WdColor::wdColorOrange;
if (sColor == "wdColorPaleBlue")
return word::WdColor::wdColorPaleBlue;
if (sColor == "wdColorPink")
return word::WdColor::wdColorPink;
if (sColor == "wdColorPlum")
return word::WdColor::wdColorPlum;
if (sColor == "wdColorRed")
return word::WdColor::wdColorRed;
if (sColor == "wdColorRose")
return word::WdColor::wdColorRose;
if (sColor == "wdColorSeaGreen")
return word::WdColor::wdColorSeaGreen;
if (sColor == "wdColorSkyBlue")
return word::WdColor::wdColorSkyBlue;
if (sColor == "wdColorTan")
return word::WdColor::wdColorTan;
if (sColor == "wdColorTeal")
return word::WdColor::wdColorTeal;
if (sColor == "wdColorTurquoise")
return word::WdColor::wdColorTurquoise;
if (sColor == "wdColorViolet")
return word::WdColor::wdColorViolet;
if (sColor == "wdColorWhite")
return word::WdColor::wdColorWhite;
if (sColor == "wdColorYellow")
return word::WdColor::wdColorYellow;
return word::WdColor::wdColorBlack;
}
void SwVbaContentControl::setColor(sal_Int32 nWdColor)
{
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
switch (nWdColor)
{
case word::WdColor::wdColorAqua:
pCC->SetColor("wdColorAqua");
break;
case word::WdColor::wdColorAutomatic:
pCC->SetColor("wdColorAutomatic");
break;
case word::WdColor::wdColorBlack:
pCC->SetColor("wdColorBlack");
break;
case word::WdColor::wdColorBlue:
pCC->SetColor("wdColorBlue");
break;
case word::WdColor::wdColorBlueGray:
pCC->SetColor("wdColorBlueGray");
break;
case word::WdColor::wdColorBrightGreen:
pCC->SetColor("wdColorBrightGreen");
break;
case word::WdColor::wdColorBrown:
pCC->SetColor("wdColorBrown");
break;
case word::WdColor::wdColorDarkBlue:
pCC->SetColor("wdColorDarkBlue");
break;
case word::WdColor::wdColorDarkGreen:
pCC->SetColor("wdColorDarkGreen");
break;
case word::WdColor::wdColorDarkRed:
pCC->SetColor("wdColorDarkRed");
break;
case word::WdColor::wdColorDarkTeal:
pCC->SetColor("wdColorDarkTeal");
break;
case word::WdColor::wdColorDarkYellow:
pCC->SetColor("wdColorDarkYellow");
break;
case word::WdColor::wdColorGold:
pCC->SetColor("wdColorGold");
break;
case word::WdColor::wdColorGray05:
pCC->SetColor("wdColorGray05");
break;
case word::WdColor::wdColorGray10:
pCC->SetColor("wdColorGray10");
break;
case word::WdColor::wdColorGray125:
pCC->SetColor("wdColorGray125");
break;
case word::WdColor::wdColorGray15:
pCC->SetColor("wdColorGray15");
break;
case word::WdColor::wdColorGray20:
pCC->SetColor("wdColorGray20");
break;
case word::WdColor::wdColorGray25:
pCC->SetColor("wdColorGray25");
break;
case word::WdColor::wdColorGray30:
pCC->SetColor("wdColorGray30");
break;
case word::WdColor::wdColorGray35:
pCC->SetColor("wdColorGray35");
break;
case word::WdColor::wdColorGray375:
pCC->SetColor("wdColorGray375");
break;
case word::WdColor::wdColorGray40:
pCC->SetColor("wdColorGray40");
break;
case word::WdColor::wdColorGray45:
pCC->SetColor("wdColorGray45");
break;
case word::WdColor::wdColorGray50:
pCC->SetColor("wdColorGray50");
break;
case word::WdColor::wdColorGray55:
pCC->SetColor("wdColorGray55");
break;
case word::WdColor::wdColorGray60:
pCC->SetColor("wdColorGray60");
break;
case word::WdColor::wdColorGray625:
pCC->SetColor("wdColorGray625");
break;
case word::WdColor::wdColorGray65:
pCC->SetColor("wdColorGray65");
break;
case word::WdColor::wdColorGray70:
pCC->SetColor("wdColorGray70");
break;
case word::WdColor::wdColorGray75:
pCC->SetColor("wdColorGray75");
break;
case word::WdColor::wdColorGray80:
pCC->SetColor("wdColorGray80");
break;
case word::WdColor::wdColorGray85:
pCC->SetColor("wdColorGray85");
break;
case word::WdColor::wdColorGray875:
pCC->SetColor("wdColorGray875");
break;
case word::WdColor::wdColorGray90:
pCC->SetColor("wdColorGray90");
break;
case word::WdColor::wdColorGray95:
pCC->SetColor("wdColorGray95");
break;
case word::WdColor::wdColorGreen:
pCC->SetColor("wdColorGreen");
break;
case word::WdColor::wdColorIndigo:
pCC->SetColor("wdColorIndigo");
break;
case word::WdColor::wdColorLavender:
pCC->SetColor("wdColorLavender");
break;
case word::WdColor::wdColorLightBlue:
pCC->SetColor("wdColorLightBlue");
break;
case word::WdColor::wdColorLightGreen:
pCC->SetColor("wdColorLightGreen");
break;
case word::WdColor::wdColorLightOrange:
pCC->SetColor("wdColorLightOrange");
break;
case word::WdColor::wdColorLightTurquoise:
pCC->SetColor("wdColorLightTurquoise");
break;
case word::WdColor::wdColorLightYellow:
pCC->SetColor("wdColorLightYellow");
break;
case word::WdColor::wdColorLime:
pCC->SetColor("wdColorLime");
break;
case word::WdColor::wdColorOliveGreen:
pCC->SetColor("wdColorOliveGreen");
break;
case word::WdColor::wdColorOrange:
pCC->SetColor("wdColorOrange");
break;
case word::WdColor::wdColorPaleBlue:
pCC->SetColor("wdColorPaleBlue");
break;
case word::WdColor::wdColorPink:
pCC->SetColor("wdColorPink");
break;
case word::WdColor::wdColorPlum:
pCC->SetColor("wdColorPlum");
break;
case word::WdColor::wdColorRed:
pCC->SetColor("wdColorRed");
break;
case word::WdColor::wdColorRose:
pCC->SetColor("wdColorRose");
break;
case word::WdColor::wdColorSeaGreen:
pCC->SetColor("wdColorSeaGreen");
break;
case word::WdColor::wdColorSkyBlue:
pCC->SetColor("wdColorSkyBlue");
break;
case word::WdColor::wdColorTan:
pCC->SetColor("wdColorTan");
break;
case word::WdColor::wdColorTeal:
pCC->SetColor("wdColorTeal");
break;
case word::WdColor::wdColorTurquoise:
pCC->SetColor("wdColorTurquoise");
break;
case word::WdColor::wdColorViolet:
pCC->SetColor("wdColorViolet");
break;
case word::WdColor::wdColorWhite:
pCC->SetColor("wdColorWhite");
break;
default:;
}
}
sal_Int32 SwVbaContentControl::getDateCalendarType()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getDateCalendarType stub");
// returns a WdCalendarTypes that represents the type of building block
return word::WdCalendarType::wdCalendarWestern;
}
void SwVbaContentControl::setDateCalendarType(sal_Int32 nSet)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setDateCalendarType[" << nSet << "] stub");
}
OUString SwVbaContentControl::getDateDisplayFormat()
{
const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl();
return pCC->GetDateFormat();
}
void SwVbaContentControl::setDateDisplayFormat(const OUString& sSet)
{
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
pCC->SetDateFormat(sSet);
}
sal_Int32 SwVbaContentControl::getDateStorageFormat()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getDateStorageFormat stub");
// returns a WdContentControlDateStorageFormat when bound to the XML data store.
return 0;
}
void SwVbaContentControl::setDateStorageFormat(sal_Int32 nSet)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setDateStorageFormat[" << nSet << "] stub");
}
sal_Int32 SwVbaContentControl::getDateDisplayLocale()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getDateDisplayLocale stub");
// returns a WdLanguageID that represents the language format for a date content control.
return word::WdLanguageID::wdEnglishUS;
}
uno::Any SwVbaContentControl::getDropdownListEntries()
{
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
//if (!pCC->GetDropDown() && !pCC->GetComboBox())
// return uno::Any();
//return uno::Any(uno::Reference<XCollection>(
// new SwVbaContentControlDropDownListEntries(this, mxContext, m_rCC)));
return uno::Any();
}
OUString SwVbaContentControl::getID()
{
//const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl();
//return OUString::number(static_cast<sal_uInt32>(pCC->GetId()));
return OUString();
}
sal_Int32 SwVbaContentControl::getLevel()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getLevel stub");
// returns a WdContentControlLevel
return 0;
}
sal_Bool SwVbaContentControl::getLockContentControl()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getLockContentControl stub");
// returns whether the user can delete a content control from the active document.
return true;
}
void SwVbaContentControl::setLockContentControl(sal_Bool /*bSet*/)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setLockContentControl stub");
}
sal_Bool SwVbaContentControl::getLockContents()
{
// Pseudo-implementation - the need for locking in a form would be very rare.
// LO uses this for internal purposes. Only expose it to VBA when safe.
const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl();
// Checkbox/DropDown/Picture are normally locked - but not in this sense. Report as unlocked.
if (pCC->GetType() == SwContentControlType::CHECKBOX
|| pCC->GetType() == SwContentControlType::DROP_DOWN_LIST
|| pCC->GetType() == SwContentControlType::PICTURE)
{
return false;
}
return pCC->GetReadWrite();
}
void SwVbaContentControl::setLockContents(sal_Bool bSet)
{
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
// Checkbox/DropDown/Picture are normally locked in LO implementation - don't unlock them.
if (pCC->GetType() == SwContentControlType::CHECKBOX
|| pCC->GetType() == SwContentControlType::DROP_DOWN_LIST
|| pCC->GetType() == SwContentControlType::PICTURE)
{
return;
}
pCC->SetReadWrite(bSet);
}
sal_Bool SwVbaContentControl::getMultiLine()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getMultiLine stub");
return false;
}
void SwVbaContentControl::setMultiLine(sal_Bool /*bSet*/)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setMultiLine stub");
}
OUString SwVbaContentControl::getPlaceholderText()
{
// return pCC->GetPlaceholderDocPart(); // This is not correct. Much more complex than this...
SAL_INFO("sw.vba", "SwVbaContentControl::getPlaceholderText stub");
return OUString();
}
sal_Bool SwVbaContentControl::getShowingPlaceholderText()
{
const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl();
return pCC->GetShowingPlaceHolder();
}
uno::Reference<word::XRange> SwVbaContentControl::getRange()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getRange stub");
return uno::Reference<word::XRange>();
}
OUString SwVbaContentControl::getRepeatingSectionItemTitle()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getRepeatingSectionItemTitle stub");
return OUString();
}
void SwVbaContentControl::setRepeatingSectionItemTitle(const OUString& rSet)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setRepeatingSectionItemTitle[" << rSet << "] stub");
}
OUString SwVbaContentControl::getTag()
{
const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl();
return pCC->GetTag();
}
void SwVbaContentControl::setTag(const OUString& rSet)
{
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
return pCC->SetTag(rSet);
}
sal_Bool SwVbaContentControl::getTemporary()
{
SAL_INFO("sw.vba", "SwVbaContentControl::getTemporary stub");
// Is content control removed when user edits (one time use)? Not implemented in LO.
return false;
}
void SwVbaContentControl::setTemporary(sal_Bool /*bSet*/)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setTemporary stub");
}
OUString SwVbaContentControl::getTitle()
{
const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl();
return pCC->GetAlias();
}
void SwVbaContentControl::setTitle(const OUString& rSet)
{
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
return pCC->SetAlias(rSet);
}
sal_Int32 SwVbaContentControl::getType()
{
const std::shared_ptr<SwContentControl>& pCC = m_rCC.GetContentControl().GetContentControl();
SwContentControlType eType = pCC->GetType();
sal_Int32 eVbaType = word::WdContentControlType::wdContentControlRichText;
switch (eType)
{
case SwContentControlType::CHECKBOX:
eVbaType = word::WdContentControlType::wdContentControlCheckbox;
break;
case SwContentControlType::DROP_DOWN_LIST:
eVbaType = word::WdContentControlType::wdContentControlDropdownList;
break;
case SwContentControlType::PICTURE:
eVbaType = word::WdContentControlType::wdContentControlPicture;
break;
case SwContentControlType::DATE:
eVbaType = word::WdContentControlType::wdContentControlDate;
break;
case SwContentControlType::PLAIN_TEXT:
eVbaType = word::WdContentControlType::wdContentControlText;
break;
case SwContentControlType::COMBO_BOX:
eVbaType = word::WdContentControlType::wdContentControlComboBox;
break;
case SwContentControlType::RICH_TEXT:
default:;
}
return eVbaType;
}
void SwVbaContentControl::setType(sal_Int32 nSet)
{
SAL_INFO("sw.vba", "SwVbaContentControl::setType[" << nSet << "] stub");
// std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
// SwContentControlType eType = SwContentControlType::RICH_TEXT;
// switch(nSet)
// {
// case word::WdContentControlType::wdContentControlCheckbox:
// eType = SwContentControlType::CHECKBOX;
// break;
// case word::WdContentControlType::wdContentControlDropdownList:
// eType = SwContentControlType::DROP_DOWN_LIST;
// break;
// case word::WdContentControlType::wdContentControlPicture:
// eType = SwContentControlType::PICTURE;
// break;
// case word::WdContentControlType::wdContentControlDate:
// eType = SwContentControlType::DATE;
// break;
// case word::WdContentControlType::wdContentControlText:
// eType = SwContentControlType::PLAIN_TEXT;
// break;
// case word::WdContentControlType::wdContentControlComboBox:
// eType = SwContentControlType::COMBO_BOX;
// break;
// case word::WdContentControlType::wdContentControlRichText:
// default:;
// }
// pCC->SetType(eType);
}
void SwVbaContentControl::Copy()
{
SAL_INFO("sw.vba", "SwVbaContentControl::Copy[" << getID() << "] stub");
}
void SwVbaContentControl::Cut()
{
SAL_INFO("sw.vba",
"SwVbaContentControl::Cut[" << getID() << "], but missing sending to clipboard");
Delete(uno::Any(false));
}
void SwVbaContentControl::Delete(const uno::Any& DeleteContents)
{
bool bDeleteContents = false;
DeleteContents >>= bDeleteContents;
SAL_INFO("sw.vba", "SwVbaContentControl::Delete[" << DeleteContents << "] stub");
//m_rCC.ChgTextNode(nullptr); // works, but crashes on UI touch - probably requires invalidation
}
void SwVbaContentControl::SetCheckedSymbol(sal_Int32 Character, const uno::Any& Font)
{
SAL_INFO_IF(Font.hasValue(), "sw.vba", "SetCheckedSymbol Font[" << Font << "] stub");
if (Character < 31 || Character > SAL_MAX_UINT16)
return; // unsupported character. Would such a thing exist in VBA?
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
pCC->SetCheckedState(OUString(static_cast<sal_Unicode>(Character)));
//if (getChecked())
// pCC->Invalidate();
}
void SwVbaContentControl::SetUnCheckedSymbol(sal_Int32 Character, const uno::Any& Font)
{
SAL_INFO_IF(Font.hasValue(), "sw.vba", "SetUnCheckedSymbol Font[" << Font << "] stub");
if (Character < 31 || Character > SAL_MAX_UINT16)
return; // unsupported character. Would such a thing exist in VBA?
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
pCC->SetUncheckedState(OUString(static_cast<sal_Unicode>(Character)));
//if (!getChecked())
// pCC->Invalidate();
}
void SwVbaContentControl::SetPlaceholderText(const uno::Any& BuildingBlock, const uno::Any& Range,
const uno::Any& Text)
{
SAL_INFO("sw.vba", "SwVbaContentControl::SetPlaceholderText stub");
std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl();
if (BuildingBlock.hasValue())
{
// Set placeholder text to the building block - whatever that is.
}
else if (Range.hasValue())
{
// Set placeholder text to the contents of the Range, however you do that.
}
else if (Text.hasValue())
{
// Set placeholder text to the provided string
}
else
{
// Remove placeholder text.
pCC->SetPlaceholderDocPart("");
}
//if (getShowingPlaceholderText())
//{
// if (!pCC->GetCheckbox())
// pCC->Invalidate();
// // Ensure that invalidation doesn't turn off showing placeholder as true
// pCC->SetShowingPlaceHolder(true);
//}
}
void SwVbaContentControl::Ungroup() { SAL_INFO("sw.vba", "SwVbaContentControl::UnGroup stub"); }
OUString SwVbaContentControl::getServiceImplName() { return "SwVbaContentControl"; }
uno::Sequence<OUString> SwVbaContentControl::getServiceNames()
{
static uno::Sequence<OUString> const aServiceNames{ "ooo.vba.word.ContentControl" };
return aServiceNames;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbacontentcontrol.hxx b/sw/source/ui/vba/vbacontentcontrol.hxx
new file mode 100644
index 0000000..e5fa927
--- /dev/null
+++ b/sw/source/ui/vba/vbacontentcontrol.hxx
@@ -0,0 +1,142 @@
/* -*- 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 <com/sun/star/text/XTextDocument.hpp>
#include <ooo/vba/word/XContentControl.hpp>
#include <vbahelper/vbahelperinterface.hxx>
#include <textcontentcontrol.hxx>
typedef InheritedHelperInterfaceWeakImpl<ooo::vba::word::XContentControl> SwVbaContentControl_BASE;
class SwVbaContentControl : public SwVbaContentControl_BASE
{
private:
css::uno::Reference<css::text::XTextDocument> mxTextDocument;
SwTextContentControl& m_rCC;
public:
/// @throws css::uno::RuntimeException
SwVbaContentControl(const css::uno::Reference<ooo::vba::XHelperInterface>& rParent,
const css::uno::Reference<css::uno::XComponentContext>& rContext,
const css::uno::Reference<css::text::XTextDocument>& xTextDocument,
SwTextContentControl& rContentControl);
~SwVbaContentControl() override;
// XContentControl Properties
sal_Bool SAL_CALL getAllowInsertDeleteSection() override;
void SAL_CALL setAllowInsertDeleteSection(sal_Bool bSet) override;
sal_Int32 SAL_CALL getAppearance() override;
void SAL_CALL setAppearance(sal_Int32 nSet) override;
OUString SAL_CALL getBuildingBlockCategory() override;
void SAL_CALL setBuildingBlockCategory(const OUString& sSet) override;
sal_Int32 SAL_CALL getBuildingBlockType() override;
void SAL_CALL setBuildingBlockType(sal_Int32 nSet) override;
sal_Bool SAL_CALL getChecked() override;
void SAL_CALL setChecked(sal_Bool bSet) override;
// returns or sets a WdColor (@since after 2010 I assume)
sal_Int32 SAL_CALL getColor() override;
void SAL_CALL setColor(sal_Int32 nSet) override;
sal_Int32 SAL_CALL getDateCalendarType() override;
void SAL_CALL setDateCalendarType(sal_Int32 nSet) override;
OUString SAL_CALL getDateDisplayFormat() override;
void SAL_CALL setDateDisplayFormat(const OUString& sSet) override;
sal_Int32 SAL_CALL getDateDisplayLocale() override;
sal_Int32 SAL_CALL getDateStorageFormat() override;
void SAL_CALL setDateStorageFormat(sal_Int32 nSet) override;
css::uno::Any SAL_CALL getDropdownListEntries() override;
// This is an integer used as a unique indentifier string
OUString SAL_CALL getID() override;
sal_Int32 SAL_CALL getLevel() override;
// returns or sets if the user can delete the control
sal_Bool SAL_CALL getLockContentControl() override;
void SAL_CALL setLockContentControl(sal_Bool bSet) override;
// returns or sets if the user can edit the contents (i.e. read-only flag)
sal_Bool SAL_CALL getLockContents() override;
void SAL_CALL setLockContents(sal_Bool bSet) override;
sal_Bool SAL_CALL getMultiLine() override;
void SAL_CALL setMultiLine(sal_Bool bSet) override;
// WRONG- THIS SHOULD RETURN XBUILDINGBLOCK
OUString SAL_CALL getPlaceholderText() override;
sal_Bool SAL_CALL getShowingPlaceholderText() override;
OUString SAL_CALL getRepeatingSectionItemTitle() override;
void SAL_CALL setRepeatingSectionItemTitle(const OUString& rSet) override;
css::uno::Reference<ooo::vba::word::XRange> SAL_CALL getRange() override;
OUString SAL_CALL getTag() override;
void SAL_CALL setTag(const OUString& rSet) override;
// returns or sets if the control is removed after accepting user change (i.e. control -> text)
sal_Bool SAL_CALL getTemporary() override;
void SAL_CALL setTemporary(sal_Bool bSet) override;
OUString SAL_CALL getTitle() override;
void SAL_CALL setTitle(const OUString& rSet) override;
// returns or sets a WdContentControlType that represents the type for a content control.
sal_Int32 SAL_CALL getType() override;
void SAL_CALL setType(sal_Int32 nSet) override;
// XContentControl Methods
// Copies the content control from the active document to the Clipboard.
// Retreive from the clipboard using the Paste method of the Selection object
// or of the Range object, or use the Paste function from within Microsoft Word.
void SAL_CALL Copy() override;
// Removes the control from the active document and moves it to the Clipboard.
void SAL_CALL Cut() override;
// Specifies whether to delete the contents of the content control. The default value is False.
// True removes both the content control and its contents.
// False removes the control but leaves the contents of the content control in the document.
void SAL_CALL Delete(const css::uno::Any& bDeleteContents) override;
// Set the Unicode character used to display the checked state.
void SAL_CALL SetCheckedSymbol(sal_Int32 Character, const css::uno::Any& sFont) override;
// Set the Unicode character used to display the unchecked state.
void SAL_CALL SetUnCheckedSymbol(sal_Int32 Character, const css::uno::Any& sFont) override;
// Sets the placeholder text that displays until a user enters their own text.
// Only one of the parameters is used when specifying placeholder text.
// If more than one parameter is provided, use the text specified in the first parameter.
// If all parameters are omitted, the placeholder text is blank.
void SAL_CALL SetPlaceholderText(const css::uno::Any& BuildingBlock, const css::uno::Any& Range,
const css::uno::Any& sText) override;
void SAL_CALL Ungroup() override;
// XHelperInterface
OUString getServiceImplName() override;
css::uno::Sequence<OUString> getServiceNames() override;
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbacontentcontrols.cxx b/sw/source/ui/vba/vbacontentcontrols.cxx
new file mode 100644
index 0000000..549541c
--- /dev/null
+++ b/sw/source/ui/vba/vbacontentcontrols.cxx
@@ -0,0 +1,264 @@
/* -*- 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 <comphelper/sequence.hxx>
#include <sal/log.hxx>
#include <doc.hxx>
#include <docsh.hxx>
#include <textcontentcontrol.hxx>
#include "vbacontentcontrol.hxx"
#include "vbacontentcontrols.hxx"
#include "wordvbahelper.hxx"
using namespace ::ooo::vba;
using namespace ::com::sun::star;
// Helper function to access the content controls
// @param rIndex
// [in] negative indexes indicate the need to search by name, otherwise get by index,
// using SAL_MAX_INT32 to indicate the need to just get the total count.
// [out] rIndex indicates the found index, or the total number of content controls
static SwTextContentControl*
lcl_getContentControl(std::u16string_view sName, std::u16string_view sTag,
std::u16string_view sTitle, sal_Int32& rIndex,
const uno::Reference<text::XTextDocument>& xTextDocument,
uno::Sequence<OUString>* pElementNames = nullptr)
{
SwDoc* pDoc = word::getDocShell(xTextDocument)->GetDoc();
if (!pDoc)
return nullptr;
assert(sTag.empty() || sTitle.empty()); // only one grouping at a time is allowed
SwTextContentControl* pControl = nullptr;
std::vector<OUString> vElementNames;
SwContentControlManager& rManager = pDoc->GetContentControlManager();
size_t i = static_cast<size_t>(rIndex);
const size_t nLen = rManager.GetCount();
if (!pElementNames && rIndex > 0 && sName.empty() && sTag.empty() && sTitle.empty())
{
// This is the normal get-by-index/getCount mode - no need for fancy filtering.
if (i < nLen)
pControl = rManager.Get(i);
else
rIndex = nLen;
}
else
{
// loop through everything collecting names, filtering by Tag/Title
sal_Int32 nCounter = 0;
for (i = 0; i < nLen; ++i)
{
pControl = rManager.Get(i);
if (!sTag.empty()
&& sTag != pControl->GetContentControl().GetContentControl()->GetTag())
continue;
if (!sTitle.empty()
&& sTitle != pControl->GetContentControl().GetContentControl()->GetAlias())
continue;
//OUString sID = OUString::number(static_cast<sal_uInt32>(
// pControl->GetContentControl().GetContentControl()->GetId()));
//if (!sName.empty() && sName != sID)
// continue;
//if (pElementNames)
// vElementNames.push_back(sID);
if (rIndex == nCounter /*|| !sName.empty()*/)
break;
pControl = nullptr;
++nCounter;
}
rIndex = nCounter;
}
if (pElementNames)
*pElementNames = comphelper::containerToSequence(vElementNames);
return pControl;
}
namespace
{
class ContentControlsEnumWrapper : public EnumerationHelper_BASE
{
uno::Reference<container::XIndexAccess> mxIndexAccess;
sal_Int32 nIndex;
public:
explicit ContentControlsEnumWrapper(uno::Reference<container::XIndexAccess> xIndexAccess)
: mxIndexAccess(std::move(xIndexAccess))
, nIndex(0)
{
}
sal_Bool SAL_CALL hasMoreElements() override { return (nIndex < mxIndexAccess->getCount()); }
uno::Any SAL_CALL nextElement() override
{
if (nIndex < mxIndexAccess->getCount())
{
return mxIndexAccess->getByIndex(nIndex++);
}
throw container::NoSuchElementException();
}
};
class ContentControlCollectionHelper
: public ::cppu::WeakImplHelper<container::XNameAccess, container::XIndexAccess,
container::XEnumerationAccess>
{
private:
uno::Reference<XHelperInterface> mxParent;
uno::Reference<uno::XComponentContext> mxContext;
uno::Reference<text::XTextDocument> mxTextDocument;
const OUString m_sTag;
const OUString m_sTitle;
SwTextContentControl* m_pCache;
public:
/// @throws css::uno::RuntimeException
ContentControlCollectionHelper(uno::Reference<ov::XHelperInterface> xParent,
uno::Reference<uno::XComponentContext> xContext,
uno::Reference<text::XTextDocument> xTextDocument,
const OUString& rTag, const OUString& rTitle)
: mxParent(std::move(xParent))
, mxContext(std::move(xContext))
, mxTextDocument(std::move(xTextDocument))
, m_sTag(rTag)
, m_sTitle(rTitle)
, m_pCache(nullptr)
{
}
// XIndexAccess
sal_Int32 SAL_CALL getCount() override
{
sal_Int32 nCount = SAL_MAX_INT32;
lcl_getContentControl(u"", m_sTag, m_sTitle, nCount, mxTextDocument);
return nCount == SAL_MAX_INT32 || nCount < 0 ? 0 : nCount;
}
uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
{
m_pCache = lcl_getContentControl(u"", m_sTag, m_sTitle, Index, mxTextDocument);
if (!m_pCache)
throw lang::IndexOutOfBoundsException();
return uno::Any(uno::Reference<word::XContentControl>(
new SwVbaContentControl(mxParent, mxContext, mxTextDocument, *m_pCache)));
}
// XNameAccess
uno::Sequence<OUString> SAL_CALL getElementNames() override
{
sal_Int32 nCount = SAL_MAX_INT32;
uno::Sequence<OUString> aSeq;
lcl_getContentControl(u"", m_sTag, m_sTitle, nCount, mxTextDocument, &aSeq);
return aSeq;
}
uno::Any SAL_CALL getByName(const OUString& aName) override
{
if (!hasByName(aName))
throw container::NoSuchElementException();
return uno::Any(uno::Reference<word::XContentControl>(
new SwVbaContentControl(mxParent, mxContext, mxTextDocument, *m_pCache)));
}
sal_Bool SAL_CALL hasByName(const OUString& aName) override
{
sal_Int32 nCount = -1;
m_pCache = lcl_getContentControl(aName, m_sTag, m_sTitle, nCount, mxTextDocument);
return m_pCache != nullptr;
}
// XElementAccess
uno::Type SAL_CALL getElementType() override
{
return cppu::UnoType<word::XContentControl>::get();
}
sal_Bool SAL_CALL hasElements() override { return getCount() != 0; }
// XEnumerationAccess
uno::Reference<container::XEnumeration> SAL_CALL createEnumeration() override
{
return new ContentControlsEnumWrapper(this);
}
};
}
/**
* Content Controls can be accessed and filtered in many different ways.
* Surprisingly however, there is no clear, descriptive "by name" access.
* Instead, each content control (probably) has a unique _signed-integer_ identifier,
* which can be passed to Item() as a float or _unsigned-integer_ string
* (to differentiate it from getByIndex).
*
* Index access can be filtered by Tag, Title, Range, and XML link.
* TODO: add filtering for Range, SelectLinkedControls, SelectUnlinkedControls
*/
SwVbaContentControls::SwVbaContentControls(const uno::Reference<XHelperInterface>& xParent,
const uno::Reference<uno::XComponentContext>& xContext,
const uno::Reference<text::XTextDocument>& xTextDocument,
const OUString& rTag, const OUString& rTitle)
: SwVbaContentControls_BASE(
xParent, xContext,
uno::Reference<container::XIndexAccess>(
new ContentControlCollectionHelper(xParent, xContext, xTextDocument, rTag, rTitle)))
, m_sTag(rTag)
, m_sTitle(rTitle)
{
}
// uno::Reference<ooo::vba::word::XContentControl> SwVbaContentControls::Add(const uno::Any& Range,
// sal_Int32 Type)
// {
// sw::mark::IFieldmark* pFieldmark = nullptr;
// switch (Type)
// {
// case ooo::vba::word::WdFieldType::wdFieldFormCheckBox:
// break;
// case ooo::vba::word::WdFieldType::wdFieldFormDropDown:
// break;
// case ooo::vba::word::WdFieldType::wdFieldFormTextInput:
// default:;
// }
//
// return uno::Reference<ooo::vba::word::XContentControl>(
// new SwVbaContentControl(mxParent, mxContext, m_xTextDocument, *pFieldmark));
// }
// XEnumerationAccess
uno::Type SwVbaContentControls::getElementType()
{
return cppu::UnoType<word::XContentControl>::get();
}
uno::Reference<container::XEnumeration> SwVbaContentControls::createEnumeration()
{
return new ContentControlsEnumWrapper(m_xIndexAccess);
}
uno::Any SwVbaContentControls::createCollectionObject(const uno::Any& aSource) { return aSource; }
OUString SwVbaContentControls::getServiceImplName() { return "SwVbaContentControls"; }
uno::Sequence<OUString> SwVbaContentControls::getServiceNames()
{
static uno::Sequence<OUString> const sNames{ "ooo.vba.word.ContentControls" };
return sNames;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbacontentcontrols.hxx b/sw/source/ui/vba/vbacontentcontrols.hxx
new file mode 100644
index 0000000..a31ca58
--- /dev/null
+++ b/sw/source/ui/vba/vbacontentcontrols.hxx
@@ -0,0 +1,44 @@
/* -*- 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 <com/sun/star/text/XTextDocument.hpp>
#include <ooo/vba/word/XContentControls.hpp>
#include <vbahelper/vbacollectionimpl.hxx>
typedef CollTestImplHelper<ooo::vba::word::XContentControls> SwVbaContentControls_BASE;
class SwVbaContentControls : public SwVbaContentControls_BASE
{
private:
OUString m_sTag;
OUString m_sTitle;
public:
/// @throws css::uno::RuntimeException
SwVbaContentControls(const css::uno::Reference<ov::XHelperInterface>& xParent,
const css::uno::Reference<css::uno::XComponentContext>& xContext,
const css::uno::Reference<css::text::XTextDocument>& xTextDocument,
const OUString& rTag, const OUString& rTitle);
// XContentControls
//css::uno::Reference<ooo::vba::word::XContentControl> SAL_CALL Add(const css::uno::Any& Type, const css::uno::Any& Range) override;
// XEnumerationAccess
css::uno::Type SAL_CALL getElementType() override;
css::uno::Reference<css::container::XEnumeration> SAL_CALL createEnumeration() override;
// SwVbaContentControls_BASE
css::uno::Any createCollectionObject(const css::uno::Any& aSource) override;
OUString getServiceImplName() override;
css::uno::Sequence<OUString> getServiceNames() override;
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbadocument.cxx b/sw/source/ui/vba/vbadocument.cxx
index 6dcbdbf..f08974e 100644
--- a/sw/source/ui/vba/vbadocument.cxx
+++ b/sw/source/ui/vba/vbadocument.cxx
@@ -21,6 +21,7 @@
#include <sal/log.hxx>
#include "vbafilterpropsfromformat.hxx"
#include "vbacontentcontrols.hxx"
#include "vbadocument.hxx"
#include "vbaformfields.hxx"
#include "vbarange.hxx"
@@ -217,6 +218,32 @@ SwVbaDocument::Bookmarks( const uno::Any& rIndex )
return xBookmarksVba->Item( rIndex, uno::Any() );
}
uno::Any SAL_CALL SwVbaDocument::ContentControls(const uno::Any& index)
{
uno::Reference<XCollection> xContentControls(
new SwVbaContentControls(this, mxContext, mxTextDocument, "", ""));
if (index.hasValue())
return xContentControls->Item(index, uno::Any());
return uno::Any(xContentControls);
}
uno::Any SAL_CALL SwVbaDocument::SelectContentControlsByTag(const uno::Any& index)
{
OUString sTag;
index >>= sTag;
return uno::Any(uno::Reference<XCollection>(
new SwVbaContentControls(this, mxContext, mxTextDocument, sTag, "")));
}
uno::Any SAL_CALL SwVbaDocument::SelectContentControlsByTitle(const uno::Any& index)
{
OUString sTitle;
index >>= sTitle;
return uno::Any(uno::Reference<XCollection>(
new SwVbaContentControls(this, mxContext, mxTextDocument, "", sTitle)));
}
uno::Any SAL_CALL
SwVbaDocument::Variables( const uno::Any& rIndex )
{
diff --git a/sw/source/ui/vba/vbadocument.hxx b/sw/source/ui/vba/vbadocument.hxx
index f1352e4..31ca375 100644
--- a/sw/source/ui/vba/vbadocument.hxx
+++ b/sw/source/ui/vba/vbadocument.hxx
@@ -55,6 +55,9 @@ public:
virtual css::uno::Any SAL_CALL BuiltInDocumentProperties( const css::uno::Any& index ) override;
virtual css::uno::Any SAL_CALL CustomDocumentProperties( const css::uno::Any& index ) override;
virtual css::uno::Any SAL_CALL Bookmarks( const css::uno::Any& rIndex ) override;
css::uno::Any SAL_CALL ContentControls(const css::uno::Any& index) override;
css::uno::Any SAL_CALL SelectContentControlsByTag(const css::uno::Any& index) override;
css::uno::Any SAL_CALL SelectContentControlsByTitle(const css::uno::Any& index) override;
virtual css::uno::Any SAL_CALL Variables( const css::uno::Any& rIndex ) override;
virtual css::uno::Any SAL_CALL getAttachedTemplate() override;
virtual void SAL_CALL setAttachedTemplate( const css::uno::Any& _attachedtemplate ) override;