From 5feb766541d8817cdab4af5da4c9c40b48771840 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Wed, 2 Mar 2022 09:38:14 +0100 Subject: sw clearing breaks: add UNO API to insert this with custom clear / char props - if (character) properties are specified when the text content itself is inserted, then format the anchor ("dummy") character like that - add the ability to specify a clear type (none/left/right/all) on the line break object itself before insertion (cherry picked from commit 1a240807f2c051ff9a63d713625404a024d7c221) Change-Id: I219a1031e53c2e0368ff329d45b7e3fff0934038 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132107 Tested-by: Jenkins CollaboraOffice Reviewed-by: Miklos Vajna --- sw/inc/formatlinebreak.hxx | 2 +- sw/inc/textlinebreak.hxx | 5 ++ sw/inc/unomap.hxx | 4 +- sw/inc/unoprnms.hxx | 1 + sw/qa/core/unocore/unocore.cxx | 3 ++ sw/source/core/txtnode/attrlinebreak.cxx | 30 +++++++++-- sw/source/core/txtnode/thints.cxx | 5 ++ sw/source/core/unocore/unolinebreak.cxx | 85 +++++++++++++++++++++++++++----- sw/source/core/unocore/unomap.cxx | 5 ++ sw/source/core/unocore/unomap1.cxx | 18 +++++++ 10 files changed, 140 insertions(+), 18 deletions(-) (limited to 'sw') diff --git a/sw/inc/formatlinebreak.hxx b/sw/inc/formatlinebreak.hxx index 9e26ab11351f..c3a2b0164f86 100644 --- a/sw/inc/formatlinebreak.hxx +++ b/sw/inc/formatlinebreak.hxx @@ -70,7 +70,7 @@ public: void InvalidateLineBreak(); - css::uno::Reference getAnchor(SwDoc& rDoc) const; + css::uno::Reference GetAnchor() const; void SetTextLineBreak(SwTextLineBreak* pTextAttr) { m_pTextAttr = pTextAttr; } diff --git a/sw/inc/textlinebreak.hxx b/sw/inc/textlinebreak.hxx index c0853aa2bd56..33401972f60b 100644 --- a/sw/inc/textlinebreak.hxx +++ b/sw/inc/textlinebreak.hxx @@ -32,11 +32,16 @@ class SwFormatLineBreak; */ class SW_DLLPUBLIC SwTextLineBreak final : public SwTextAttr { + SwTextNode* m_pTextNode; + public: SwTextLineBreak(SwFormatLineBreak& rAttr, sal_Int32 nStart); ~SwTextLineBreak() override; + const SwTextNode& GetTextNode() const; + void SetTextNode(SwTextNode* pNew); + void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; diff --git a/sw/inc/unomap.hxx b/sw/inc/unomap.hxx index c4c166032983..413adfaf7fc3 100644 --- a/sw/inc/unomap.hxx +++ b/sw/inc/unomap.hxx @@ -125,7 +125,8 @@ struct SfxItemPropertyMapEntry; #define PROPERTY_MAP_TABLE_STYLE 100 #define PROPERTY_MAP_CELL_STYLE 101 #define PROPERTY_MAP_FIELDMARK 102 -#define PROPERTY_MAP_END 103 +#define PROPERTY_MAP_LINEBREAK 103 +#define PROPERTY_MAP_END 104 //S&E #define WID_WORDS 0 @@ -351,6 +352,7 @@ private: static const SfxItemPropertyMapEntry* GetRedlinePropertyMap(); static const SfxItemPropertyMapEntry* GetRedlinePortionPropertyMap(); static SfxItemPropertyMapEntry* GetTextDefaultPropertyMap(); + static const SfxItemPropertyMapEntry* GetLineBreakPropertyMap(); }; extern SwUnoPropertyMapProvider aSwMapProvider; diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index 5d8684c47f53..c291742a1641 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -866,6 +866,7 @@ #define UNO_NAME_RESOLVED "Resolved" #define UNO_NAME_ALLOW_OVERLAP "AllowOverlap" +#define UNO_NAME_CLEAR "Clear" #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index ddf8d4bb5362..d8c9f9559bd9 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -227,6 +227,9 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testLineBreakInsert) uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); uno::Reference xLineBreak( xMSF->createInstance("com.sun.star.text.LineBreak"), uno::UNO_QUERY); + uno::Reference xLineBreakProps(xLineBreak, uno::UNO_QUERY); + auto eClear = static_cast(SwLineBreakClear::ALL); + xLineBreakProps->setPropertyValue("Clear", uno::makeAny(eClear)); uno::Reference xText = xTextDocument->getText(); uno::Reference xCursor = xText->createTextCursor(); xText->insertTextContent(xCursor, xLineBreak, /*bAbsorb=*/false); diff --git a/sw/source/core/txtnode/attrlinebreak.cxx b/sw/source/core/txtnode/attrlinebreak.cxx index f0f583ecc2df..00d1c275e3dd 100644 --- a/sw/source/core/txtnode/attrlinebreak.cxx +++ b/sw/source/core/txtnode/attrlinebreak.cxx @@ -27,6 +27,8 @@ #include #include #include +#include +#include using namespace com::sun::star; @@ -74,17 +76,21 @@ void SwFormatLineBreak::InvalidateLineBreak() CallSwClientNotify(sw::LegacyModifyHint(&aItem, &aItem)); } -uno::Reference SwFormatLineBreak::getAnchor(SwDoc& /*rDoc*/) const +uno::Reference SwFormatLineBreak::GetAnchor() const { SolarMutexGuard aGuard; - SAL_WARN("sw.core", "SwFormatLineBreak::getAnchor: not implemented"); if (!m_pTextAttr) { return uno::Reference(); } - return {}; + SwPaM aPam(m_pTextAttr->GetTextNode(), m_pTextAttr->GetStart()); + aPam.SetMark(); + ++aPam.GetMark()->nContent; + uno::Reference xRet + = SwXTextRange::CreateXTextRange(aPam.GetDoc(), *aPam.Start(), aPam.End()); + return xRet; } void SwFormatLineBreak::dumpAsXml(xmlTextWriterPtr pWriter) const @@ -102,6 +108,7 @@ void SwFormatLineBreak::dumpAsXml(xmlTextWriterPtr pWriter) const SwTextLineBreak::SwTextLineBreak(SwFormatLineBreak& rAttr, sal_Int32 nStartPos) : SwTextAttr(rAttr, nStartPos) + , m_pTextNode(nullptr) { rAttr.SetTextLineBreak(this); SetHasDummyChar(true); @@ -112,8 +119,25 @@ SwTextLineBreak::~SwTextLineBreak() {} void SwTextLineBreak::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwTextLineBreak")); + if (m_pTextNode) + { + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_pTextNode")); + (void)xmlTextWriterWriteAttribute( + pWriter, BAD_CAST("index"), + BAD_CAST(OString::number(sal_Int32(m_pTextNode->GetIndex())).getStr())); + (void)xmlTextWriterEndElement(pWriter); + } + SwTextAttr::dumpAsXml(pWriter); (void)xmlTextWriterEndElement(pWriter); } +void SwTextLineBreak::SetTextNode(SwTextNode* pNew) { m_pTextNode = pNew; } + +const SwTextNode& SwTextLineBreak::GetTextNode() const +{ + assert(m_pTextNode); + return *m_pTextNode; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx index 7a31b1061333..ec5ef9aa7679 100644 --- a/sw/source/core/txtnode/thints.cxx +++ b/sw/source/core/txtnode/thints.cxx @@ -1528,6 +1528,11 @@ bool SwTextNode::InsertHint( SwTextAttr * const pAttr, const SetAttrMode nMode ) } } break; + case RES_TXTATR_LINEBREAK : + { + static_cast(pAttr)->SetTextNode(this); + } + break; } // CH_TXTATR_* are inserted for SwTextHints without EndIndex diff --git a/sw/source/core/unocore/unolinebreak.cxx b/sw/source/core/unocore/unolinebreak.cxx index 1d44a273df5d..1c5aeba9152e 100644 --- a/sw/source/core/unocore/unolinebreak.cxx +++ b/sw/source/core/unocore/unolinebreak.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,8 @@ #include #include #include +#include +#include using namespace com::sun::star; @@ -40,11 +43,13 @@ public: uno::WeakReference m_wThis; bool m_bIsDescriptor; SwFormatLineBreak* m_pFormatLineBreak; + SwLineBreakClear m_eClear; Impl(SwXLineBreak& rThis, SwFormatLineBreak* const pLineBreak) : m_rThis(rThis) , m_bIsDescriptor(pLineBreak == nullptr) , m_pFormatLineBreak(pLineBreak) + , m_eClear(SwLineBreakClear::NONE) { if (m_pFormatLineBreak) { @@ -52,12 +57,32 @@ public: } } + const SwFormatLineBreak* GetLineBreakFormat() const; + + const SwFormatLineBreak& GetLineBreakFormatOrThrow() const; + void Invalidate(); protected: void Notify(const SfxHint& rHint) override; }; +const SwFormatLineBreak* SwXLineBreak::Impl::GetLineBreakFormat() const +{ + return m_pFormatLineBreak; +} + +const SwFormatLineBreak& SwXLineBreak::Impl::GetLineBreakFormatOrThrow() const +{ + const SwFormatLineBreak* pLineBreak(GetLineBreakFormat()); + if (!pLineBreak) + { + throw uno::RuntimeException("SwXLineBreak: disposed or invalid", nullptr); + } + + return *pLineBreak; +} + void SwXLineBreak::Impl::Invalidate() { EndListeningAll(); @@ -126,7 +151,7 @@ void SAL_CALL SwXLineBreak::attach(const uno::Reference& xText SwUnoInternalPaM aPam(rNewDoc); sw::XTextRangeToSwPaM(aPam, xTextRange); UnoActionContext aContext(&rNewDoc); - SwFormatLineBreak aLineBreak(SwLineBreakClear::ALL); + SwFormatLineBreak aLineBreak(m_pImpl->m_eClear); SetAttrMode nInsertFlags = SetAttrMode::DEFAULT; rNewDoc.getIDocumentContentOperations().InsertPoolItem(aPam, aLineBreak, nInsertFlags); auto pTextAttr @@ -146,9 +171,7 @@ uno::Reference SAL_CALL SwXLineBreak::getAnchor() { SolarMutexGuard aGuard; - SAL_WARN("sw.uno", "SwXLineBreak::getAnnchor: not implemented"); - - return {}; + return m_pImpl->GetLineBreakFormatOrThrow().GetAnchor(); } void SAL_CALL SwXLineBreak::dispose() @@ -172,26 +195,62 @@ uno::Reference SAL_CALL SwXLineBreak::getPropertySetInf { SolarMutexGuard aGuard; - SAL_WARN("sw.uno", "SwXLineBreak::getPropertySetInfo: not implemented"); - - return {}; + static uno::Reference xRet + = aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINEBREAK)->getPropertySetInfo(); + return xRet; } -void SAL_CALL SwXLineBreak::setPropertyValue(const OUString& /*rPropertyName*/, - const css::uno::Any& /*rValue*/) +void SAL_CALL SwXLineBreak::setPropertyValue(const OUString& rPropertyName, + const css::uno::Any& rValue) { SolarMutexGuard aGuard; - SAL_WARN("sw.uno", "SwXLineBreak::setPropertySetInfo: not implemented"); + if (rPropertyName != UNO_NAME_CLEAR) + { + throw lang::IllegalArgumentException(); + } + + if (m_pImpl->m_bIsDescriptor) + { + sal_Int16 eValue{}; + if (rValue >>= eValue) + { + m_pImpl->m_eClear = static_cast(eValue); + } + } + else + { + m_pImpl->m_pFormatLineBreak->PutValue(rValue, 0); + } } -uno::Any SAL_CALL SwXLineBreak::getPropertyValue(const OUString& /*rPropertyName*/) +uno::Any SAL_CALL SwXLineBreak::getPropertyValue(const OUString& rPropertyName) { SolarMutexGuard aGuard; - SAL_WARN("sw.uno", "SwXLineBreak::getPropertyValue: not implemented"); + uno::Any aRet; + if (sw::GetDefaultTextContentValue(aRet, rPropertyName)) + { + return aRet; + } + + if (rPropertyName != UNO_NAME_CLEAR) + { + beans::UnknownPropertyException aExcept; + aExcept.Message = rPropertyName; + throw aExcept; + } - return {}; + if (m_pImpl->m_bIsDescriptor) + { + auto eValue = static_cast(m_pImpl->m_eClear); + aRet <<= eValue; + } + else + { + m_pImpl->m_pFormatLineBreak->QueryValue(aRet, 0); + } + return aRet; } void SAL_CALL SwXLineBreak::addPropertyChangeListener( diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx index 68432edc64d6..3893e6acf7af 100644 --- a/sw/source/core/unocore/unomap.cxx +++ b/sw/source/core/unocore/unomap.cxx @@ -1553,6 +1553,11 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetPropertyMapEntries(s m_aMapEntriesArr[nPropertyId] = aCellStyleMap; } break; + case PROPERTY_MAP_LINEBREAK: + { + m_aMapEntriesArr[nPropertyId] = GetLineBreakPropertyMap(); + } + break; default: OSL_FAIL( "unexpected property map ID" ); diff --git a/sw/source/core/unocore/unomap1.cxx b/sw/source/core/unocore/unomap1.cxx index 3e2bb53faab5..21a1b206c7ad 100644 --- a/sw/source/core/unocore/unomap1.cxx +++ b/sw/source/core/unocore/unomap1.cxx @@ -1008,6 +1008,18 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetFootnotePropertyMap return aFootnoteMap_Impl; } +const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetLineBreakPropertyMap() +{ + static SfxItemPropertyMapEntry const aLineBreakMap_Impl[] = + { + { u"" UNO_NAME_CLEAR, 0, cppu::UnoType::get(), PROPERTY_NONE, 0 }, + COMMON_TEXT_CONTENT_PROPERTIES + { u"", 0, css::uno::Type(), 0, 0 } + }; + + return aLineBreakMap_Impl; +} + const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetRedlinePropertyMap() { static SfxItemPropertyMapEntry const aRedlineMap_Impl[] = @@ -1661,6 +1673,12 @@ const SfxItemPropertySet* SwUnoPropertyMapProvider::GetPropertySet( sal_uInt16 m_aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_CELL_STYLE; } break; + case PROPERTY_MAP_LINEBREAK: + { + static SfxItemPropertySet aPROPERTY_MAP_LINEBREAK(pEntries); + m_aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_LINEBREAK; + } + break; } } return m_aPropertySetArr[nPropertyId]; -- cgit