summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAttila Bakos (NISZ) <bakos.attilakaroly@nisz.hu>2021-11-30 15:38:26 +0100
committerMiklos Vajna <vmiklos@collabora.com>2023-01-17 09:24:00 +0000
commitd4b87c11b451cb08aa950e09efed3cc6fa1422f3 (patch)
tree5b7b8df2510d335e1fc91f164161ac7fef8e015d
parentd3daa7ed0361785d8667f726340538ada1607937 (diff)
tdf#143574 sw: textboxes in group shapes -- part 4
A new UNO property has been added and implemented for the filters. This provides the possibility of assigning textboxes in the filter at import time via UNO. Follow-up to commit e5650de86072b9db586a4532b5239acda77598c4 "tdf#143574 sw: textboxes in group shapes - part 3 take 2". Change-Id: I58c445cb7f6d865c1d82dbe68f985e4c11ff832e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126162 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143366 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--sw/inc/textboxhelper.hxx3
-rw-r--r--sw/inc/unomid.h3
-rw-r--r--sw/inc/unoprnms.hxx1
-rw-r--r--sw/qa/extras/layout/data/TextBoxFrame.odtbin0 -> 9414 bytes
-rw-r--r--sw/qa/extras/layout/layout2.cxx41
-rw-r--r--sw/source/core/doc/textboxhelper.cxx121
-rw-r--r--sw/source/core/unocore/unodraw.cxx62
-rw-r--r--sw/source/core/unocore/unomap.cxx3
8 files changed, 216 insertions, 18 deletions
diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index 924b3e6b5c91..1a0cadabc0e9 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -60,6 +60,9 @@ public:
/// the original text in the shape will be copied to the frame
/// The textbox is created for the shape given by the pObject parameter.
static void create(SwFrameFormat* pShape, SdrObject* pObject, bool bCopyText = false);
+ /// Sets the given textframe as textbox for the given (group member) shape.
+ static void set(SwFrameFormat* pShape, SdrObject* pObject,
+ css::uno::Reference<css::text::XTextFrame> xNew);
/// Destroy a TextBox for a shape. If the format has more textboxes
/// like group shapes, it will destroy only that textbox what belongs
/// to the given pObject shape.
diff --git a/sw/inc/unomid.h b/sw/inc/unomid.h
index d249b32fc25a..9f413509ae1c 100644
--- a/sw/inc/unomid.h
+++ b/sw/inc/unomid.h
@@ -151,6 +151,9 @@
// SwFormatFollowTextFlow
#define MID_FOLLOW_TEXT_FLOW 0
+#define MID_TEXT_BOX 0
+#define MID_TEXT_BOX_CONTENT 1
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index 3a8df7c69182..bb3ee1f47b3c 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -74,6 +74,7 @@
#define UNO_NAME_FOOTER_RIGHT_MARGIN "FooterRightMargin"
#define UNO_NAME_TEXT_RANGE "TextRange"
#define UNO_NAME_TEXT_BOX "TextBox"
+#define UNO_NAME_TEXT_BOX_CONTENT "TextBoxContent"
#define UNO_NAME_NAME "Name"
#define UNO_NAME_CHAR_STYLE_NAME "CharStyleName"
#define UNO_NAME_ANCHOR_CHAR_STYLE_NAME "AnchorCharStyleName"
diff --git a/sw/qa/extras/layout/data/TextBoxFrame.odt b/sw/qa/extras/layout/data/TextBoxFrame.odt
new file mode 100644
index 000000000000..a6155e34fdfb
--- /dev/null
+++ b/sw/qa/extras/layout/data/TextBoxFrame.odt
Binary files differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 466f640beeee..9fd595eafefc 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -1647,6 +1647,47 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf141220)
CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(15), nTextBoxTop - nShapeTop);
}
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, TestTextBoxChangeViaUNO)
+{
+ CPPUNIT_ASSERT(createSwDoc(DATA_DIRECTORY, "TextBoxFrame.odt"));
+ // this file has a shape and a frame inside. Try to set up
+ // the frame for the shape as textbox. Before this was not
+ // implemented. This will be necesary for proper WPG import.
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There must be a shape and a frame!", 2, getShapes());
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("This must be a custom shape!",
+ OUString("com.sun.star.drawing.CustomShape"),
+ getShape(1)->getShapeType());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("This must be a frame shape!", OUString("FrameShape"),
+ getShape(2)->getShapeType());
+
+ CPPUNIT_ASSERT_MESSAGE("This is not supposed to be a textbox!",
+ !uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
+ ->getPropertyValue("TextBox")
+ .get<bool>());
+ // Without the fix it will crash at this line:
+ CPPUNIT_ASSERT_MESSAGE("This is not supposed to be a textbox!",
+ !uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
+ ->getPropertyValue("TextBoxContent")
+ .hasValue());
+
+ // So now set the frame as textbox for the shape!
+ uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
+ ->setPropertyValue("TextBoxContent", uno::Any(uno::Reference<text::XTextFrame>(
+ getShape(2), uno::UNO_QUERY_THROW)));
+
+ CPPUNIT_ASSERT_MESSAGE("This is supposed to be a textbox!",
+ uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
+ ->getPropertyValue("TextBox")
+ .get<bool>());
+
+ CPPUNIT_ASSERT_MESSAGE("This is supposed to be a textbox!",
+ uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
+ ->getPropertyValue("TextBoxContent")
+ .hasValue());
+}
+
CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf121509)
{
auto pDoc = createSwDoc(DATA_DIRECTORY, "Tdf121509.odt");
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 7889fd443b89..1b9155f9b6e8 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -199,6 +199,127 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool bCo
}
}
+void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj,
+ uno::Reference<text::XTextFrame> xNew)
+{
+ // Do not set invalid data
+ assert(pShapeFormat && pObj && xNew);
+ // Firstly find the format of the new textbox.
+ SwFrameFormat* pFormat = nullptr;
+ if (auto pTextFrame = dynamic_cast<SwXTextFrame*>(xNew.get()))
+ pFormat = pTextFrame->GetFrameFormat();
+ if (!pFormat)
+ return;
+ std::vector<std::pair<beans::Property, uno::Any>> aOldProps;
+ // If there is a format, check if the shape already has a textbox assigned to.
+ if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormat())
+ {
+ // If it has a texbox, destroy it.
+ if (pTextBoxNode->GetTextBox(pObj))
+ {
+ auto xOldFrame
+ = pObj->getUnoShape()->queryInterface(cppu::UnoType<text::XTextRange>::get());
+ if (xOldFrame.hasValue())
+ {
+ uno::Reference<beans::XPropertySet> xOldprops(xOldFrame, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertyState> xOldPropStates(xOldFrame, uno::UNO_QUERY);
+ for (auto& rProp : xOldprops->getPropertySetInfo()->getProperties())
+ {
+ try
+ {
+ if (xOldPropStates->getPropertyState(rProp.Name)
+ == beans::PropertyState::PropertyState_DIRECT_VALUE)
+ aOldProps.push_back(
+ std::pair(rProp, xOldprops->getPropertyValue(rProp.Name)));
+ }
+ catch (...)
+ {
+ }
+ }
+ }
+ destroy(pShapeFormat, pObj);
+ }
+ // And set the new one.
+ pTextBoxNode->AddTextBox(pObj, pFormat);
+ pFormat->SetOtherTextBoxFormat(pTextBoxNode);
+ }
+ else
+ {
+ // If the shape do not have a texbox node and textbox,
+ // create that for the shape.
+ auto* pTextBox = new SwTextBoxNode(pShapeFormat);
+ pTextBox->AddTextBox(pObj, pFormat);
+ pShapeFormat->SetOtherTextBoxFormat(pTextBox);
+ pFormat->SetOtherTextBoxFormat(pTextBox);
+ }
+ // Initialize its properties
+ uno::Reference<beans::XPropertySet> xPropertySet(xNew, uno::UNO_QUERY);
+ uno::Any aEmptyBorder = uno::makeAny(table::BorderLine2());
+ xPropertySet->setPropertyValue(UNO_NAME_TOP_BORDER, aEmptyBorder);
+ xPropertySet->setPropertyValue(UNO_NAME_BOTTOM_BORDER, aEmptyBorder);
+ xPropertySet->setPropertyValue(UNO_NAME_LEFT_BORDER, aEmptyBorder);
+ xPropertySet->setPropertyValue(UNO_NAME_RIGHT_BORDER, aEmptyBorder);
+ xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(sal_Int32(100)));
+ xPropertySet->setPropertyValue(UNO_NAME_SIZE_TYPE, uno::makeAny(text::SizeType::FIX));
+ xPropertySet->setPropertyValue(UNO_NAME_SURROUND, uno::makeAny(text::WrapTextMode_THROUGH));
+ // Add a new name to it
+ uno::Reference<container::XNamed> xNamed(xNew, uno::UNO_QUERY);
+ xNamed->setName(pShapeFormat->GetDoc()->GetUniqueFrameName());
+ // And sync. properties.
+ uno::Reference<drawing::XShape> xShape(pObj->getUnoShape(), uno::UNO_QUERY);
+ syncProperty(pShapeFormat, RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::makeAny(xShape->getSize()),
+ pObj);
+ uno::Reference<beans::XPropertySet> xShapePropertySet(xShape, uno::UNO_QUERY);
+ syncProperty(pShapeFormat, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE,
+ xShapePropertySet->getPropertyValue(UNO_NAME_ANCHOR_TYPE), pObj);
+ syncProperty(pShapeFormat, RES_HORI_ORIENT, MID_HORIORIENT_ORIENT,
+ xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT), pObj);
+ syncProperty(pShapeFormat, RES_HORI_ORIENT, MID_HORIORIENT_RELATION,
+ xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_RELATION), pObj);
+ syncProperty(pShapeFormat, RES_VERT_ORIENT, MID_VERTORIENT_ORIENT,
+ xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT), pObj);
+ syncProperty(pShapeFormat, RES_VERT_ORIENT, MID_VERTORIENT_RELATION,
+ xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_RELATION), pObj);
+ syncProperty(pShapeFormat, RES_HORI_ORIENT, MID_HORIORIENT_POSITION,
+ xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_POSITION), pObj);
+ syncProperty(pShapeFormat, RES_VERT_ORIENT, MID_VERTORIENT_POSITION,
+ xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_POSITION), pObj);
+ syncProperty(pShapeFormat, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT,
+ xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT), pObj);
+ drawing::TextVerticalAdjust aVertAdj = drawing::TextVerticalAdjust_CENTER;
+ if ((uno::Reference<beans::XPropertyState>(xShape, uno::UNO_QUERY_THROW))
+ ->getPropertyState(UNO_NAME_TEXT_VERT_ADJUST)
+ != beans::PropertyState::PropertyState_DEFAULT_VALUE)
+ {
+ aVertAdj = xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_VERT_ADJUST)
+ .get<drawing::TextVerticalAdjust>();
+ }
+ xPropertySet->setPropertyValue(UNO_NAME_TEXT_VERT_ADJUST, uno::makeAny(aVertAdj));
+ text::WritingMode eMode;
+ if (xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_WRITINGMODE) >>= eMode)
+ syncProperty(pShapeFormat, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode)), pObj);
+ if (aOldProps.size())
+ {
+ for (auto& rProp : aOldProps)
+ {
+ try
+ {
+ xPropertySet->setPropertyValue(rProp.first.Name, rProp.second);
+ }
+ catch (...)
+ {
+ }
+ }
+ }
+ if (pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE
+ && pFormat->GetAnchor().GetPageNum() == 0)
+ {
+ pFormat->SetFormatAttr(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, 1));
+ }
+ // Do sync for the new textframe.
+ synchronizeGroupTextBoxProperty(&changeAnchor, pShapeFormat, pObj);
+}
+
void SwTextBoxHelper::destroy(const SwFrameFormat* pShape, const SdrObject* pObject)
{
// If a TextBox was enabled previously
diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx
index 4d0b404e9a1c..1104df24085a 100644
--- a/sw/source/core/unocore/unodraw.cxx
+++ b/sw/source/core/unocore/unodraw.cxx
@@ -1164,18 +1164,29 @@ void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& a
}
else if (pEntry->nWID == FN_TEXT_BOX)
{
- bool bValue(false);
- aValue >>= bValue;
- if (bValue)
- SwTextBoxHelper::create(pFormat, GetSvxShape()->GetSdrObject());
- else
- SwTextBoxHelper::destroy(pFormat, GetSvxShape()->GetSdrObject());
-
+ if (pEntry->nMemberId == MID_TEXT_BOX)
+ {
+ bool bValue(false);
+ aValue >>= bValue;
+ if (bValue)
+ SwTextBoxHelper::create(pFormat, GetSvxShape()->GetSdrObject());
+ else
+ SwTextBoxHelper::destroy(pFormat, GetSvxShape()->GetSdrObject());
+ }
+ else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
+ {
+ if (aValue.getValueType() == cppu::UnoType<uno::Reference<text::XTextFrame>>::get())
+ SwTextBoxHelper::set(pFormat, GetSvxShape()->GetSdrObject(),
+ aValue.get<uno::Reference<text::XTextFrame>>());
+ else
+ SAL_WARN( "sw.uno", "This is not a TextFrame!" );
+ }
}
else if (pEntry->nWID == RES_CHAIN)
{
if (pEntry->nMemberId == MID_CHAIN_NEXTNAME || pEntry->nMemberId == MID_CHAIN_PREVNAME)
- SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue);
+ SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
+ SdrObject::getSdrObjectFromXShape(mxShape));
}
// #i28749#
else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
@@ -1346,7 +1357,8 @@ void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& a
pFormat->SetFormatAttr(aSet);
}
// We have a pFormat and a pEntry as well: try to sync TextBox property.
- SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue);
+ SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
+ SdrObject::getSdrObjectFromXShape(mxShape));
}
else
{
@@ -1436,7 +1448,8 @@ void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& a
if (pFormat)
{
// We have a pFormat (but no pEntry): try to sync TextBox property.
- SwTextBoxHelper::syncProperty(pFormat, rPropertyName, aValue);
+ SwTextBoxHelper::syncProperty(pFormat, rPropertyName, aValue,
+ SdrObject::getSdrObjectFromXShape(mxShape));
}
// #i31698# - restore object position, if caption point is set.
@@ -1517,12 +1530,25 @@ uno::Any SwXShape::getPropertyValue(const OUString& rPropertyName)
}
else if (pEntry->nWID == FN_TEXT_BOX)
{
- auto pSvxShape = GetSvxShape();
- bool bValue = SwTextBoxHelper::isTextBox(
- pFormat, RES_DRAWFRMFMT,
- ((pSvxShape && pSvxShape->GetSdrObject()) ? pSvxShape->GetSdrObject()
- : pFormat->FindRealSdrObject()));
- aRet <<= bValue;
+ if (pEntry->nMemberId == MID_TEXT_BOX)
+ {
+ auto pSvxShape = GetSvxShape();
+ bool bValue = SwTextBoxHelper::isTextBox(
+ pFormat, RES_DRAWFRMFMT,
+ ((pSvxShape && pSvxShape->GetSdrObject()) ? pSvxShape->GetSdrObject()
+ : pFormat->FindRealSdrObject()));
+ aRet <<= bValue;
+ }
+ else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
+ {
+ auto pObj = SdrObject::getSdrObjectFromXShape(mxShape);
+ auto xRange = SwTextBoxHelper::queryInterface(
+ pFormat, cppu::UnoType<text::XText>::get(),
+ pObj ? pObj : pFormat->FindRealSdrObject());
+ uno::Reference<text::XTextFrame> xFrame(xRange, uno::UNO_QUERY);
+ if (xFrame.is())
+ aRet <<= xFrame;
+ }
}
else if (pEntry->nWID == RES_CHAIN)
{
@@ -1803,7 +1829,9 @@ uno::Sequence< beans::PropertyState > SwXShape::getPropertyStates(
else if (pEntry->nWID == FN_TEXT_BOX)
{
// The TextBox property is set, if we can find a textbox for this shape.
- if (pFormat && SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT))
+ if (pFormat
+ && SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT,
+ SdrObject::getSdrObjectFromXShape(mxShape)))
pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
else
pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx
index abad86f1ce65..db62cc990d69 100644
--- a/sw/source/core/unocore/unomap.cxx
+++ b/sw/source/core/unocore/unomap.cxx
@@ -291,7 +291,8 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetPropertyMapEntries(s
{ u"" UNO_NAME_RELATIVE_HEIGHT_RELATION, RES_FRM_SIZE, cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE, MID_FRMSIZE_REL_HEIGHT_RELATION },
{ u"" UNO_NAME_RELATIVE_WIDTH, RES_FRM_SIZE, cppu::UnoType<sal_Int16>::get() , PROPERTY_NONE, MID_FRMSIZE_REL_WIDTH },
{ u"" UNO_NAME_RELATIVE_WIDTH_RELATION, RES_FRM_SIZE, cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE, MID_FRMSIZE_REL_WIDTH_RELATION },
- { u"" UNO_NAME_TEXT_BOX, FN_TEXT_BOX, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0},
+ { u"" UNO_NAME_TEXT_BOX, FN_TEXT_BOX, cppu::UnoType<bool>::get(), PROPERTY_NONE, MID_TEXT_BOX},
+ { u"" UNO_NAME_TEXT_BOX_CONTENT, FN_TEXT_BOX, cppu::UnoType<text::XTextFrame>::get(), PROPERTY_NONE, MID_TEXT_BOX_CONTENT},
{ u"" UNO_NAME_CHAIN_NEXT_NAME, RES_CHAIN, cppu::UnoType<OUString>::get(), PropertyAttribute::MAYBEVOID ,MID_CHAIN_NEXTNAME},
{ u"" UNO_NAME_CHAIN_PREV_NAME, RES_CHAIN, cppu::UnoType<OUString>::get(), PropertyAttribute::MAYBEVOID ,MID_CHAIN_PREVNAME},
{ u"" UNO_NAME_CHAIN_NAME, RES_CHAIN, cppu::UnoType<OUString>::get(), PropertyAttribute::MAYBEVOID ,MID_CHAIN_NAME },