summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Monastirsky <momonasmon@gmail.com>2023-06-15 11:16:18 +0300
committerMaxim Monastirsky <momonasmon@gmail.com>2023-06-16 00:48:44 +0200
commitd934aeace6e7049db3959421538ae382cb97b1d1 (patch)
treeb60b5ff3a1bbec87e2505d6f5ca2892ca489b6d8
parentcc483a88a03f9ee847f3cb5fac83fb5dd49d0ba1 (diff)
tdf#103064 sw,editeng: make para styles work inside comments
- Style objects for comments are stored in a dedicated stylesheet pool, and constantly updated from the "real" styles using modification broadcasts. In theory, it should be possible to use same objects for both Writer core and EditEngine, as they use separate item ranges. But unfortunately SwDocStyleSheetPool isn't really a styles container, but just a wrapper around Writer's core styles, with a single mxStyleSheet member that is filled each time with data from different styles (while EditEngine expects different styles to be represented by different objects). - EditEngine switched to allow duplicate listeners for styles - one per paragraph. The use case is 2 paragraphs of the same style, and then one of them is switched to another style. In that case we still need to keep listening to the former style for the other paragraph. There is probably some opportunity for optimization, but it should be good enough for now. - Copying formatted text from document's body doesn't preserve style assignment for now. The editeng RTF import should be tweaked to not insert styles into our "special" stylesheet pool (or somehow forward them to Writer's core style handling) before we can enable this part. Change-Id: Ib67c5388f9cd078c73ec0d453017f815843161ed Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153156 Tested-by: Jenkins Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com>
-rw-r--r--editeng/source/editeng/impedit.hxx4
-rw-r--r--editeng/source/editeng/impedit2.cxx2
-rw-r--r--editeng/source/editeng/impedit5.cxx2
-rw-r--r--include/svl/style.hxx2
-rw-r--r--svl/source/items/style.cxx2
-rw-r--r--sw/inc/docstyle.hxx4
-rw-r--r--sw/inc/docufld.hxx1
-rw-r--r--sw/source/core/fields/docufld.cxx6
-rw-r--r--sw/source/uibase/app/docstyle.cxx191
-rw-r--r--sw/source/uibase/docvw/AnnotationWin2.cxx5
-rw-r--r--sw/source/uibase/docvw/PostItMgr.cxx14
11 files changed, 225 insertions, 8 deletions
diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx
index 6db82ab2392a..a5e2e3c89593 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -477,7 +477,7 @@ public:
// ImpEditEngine
-class ImpEditEngine : public SfxListener
+class ImpEditEngine : public SfxListener, public svl::StyleSheetUser
{
friend class EditEngine;
@@ -1014,6 +1014,8 @@ public:
void UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle );
void RemoveStyleFromParagraphs( SfxStyleSheet const * pStyle );
+ bool isUsedByModel() const override { return true; }
+
OutputDevice* GetRefDevice() const { return pRefDev.get(); }
void SetRefDevice( OutputDevice* pRefDef );
diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx
index cc8b39154844..000c0b39a1f6 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -2925,6 +2925,8 @@ EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttrib
InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, aEditDoc.GetPos(rPaM.GetNode()), rPaM.GetIndex()));
EditPaM aPaM( aEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) );
+ if (auto pStyle = aPaM.GetNode()->GetStyleSheet())
+ StartListening(*pStyle, DuplicateHandling::Allow);
if ( GetStatus().DoOnlineSpelling() )
{
diff --git a/editeng/source/editeng/impedit5.cxx b/editeng/source/editeng/impedit5.cxx
index 8438f0be7632..afb1b424d907 100644
--- a/editeng/source/editeng/impedit5.cxx
+++ b/editeng/source/editeng/impedit5.cxx
@@ -86,7 +86,7 @@ void ImpEditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle )
EndListening( *pCurStyle );
pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() );
if ( pStyle )
- StartListening(*pStyle, DuplicateHandling::Prevent);
+ StartListening(*pStyle, DuplicateHandling::Allow);
if (pNode->GetWrongList())
pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len());
diff --git a/include/svl/style.hxx b/include/svl/style.hxx
index cb8498a2d118..257b1786eb57 100644
--- a/include/svl/style.hxx
+++ b/include/svl/style.hxx
@@ -272,7 +272,7 @@ public:
SfxStyleSheetBase* First(SfxStyleFamily eFamily, SfxStyleSearchBits eMask = SfxStyleSearchBits::All);
SfxStyleSheetBase* Next();
- virtual SfxStyleSheetBase* Find( const OUString&, SfxStyleFamily eFam, SfxStyleSearchBits n=SfxStyleSearchBits::All ) const;
+ virtual SfxStyleSheetBase* Find( const OUString&, SfxStyleFamily eFam, SfxStyleSearchBits n=SfxStyleSearchBits::All );
virtual bool SetParent(SfxStyleFamily eFam,
const OUString &rStyle,
diff --git a/svl/source/items/style.cxx b/svl/source/items/style.cxx
index ff21cd91c804..e766dcb09f65 100644
--- a/svl/source/items/style.cxx
+++ b/svl/source/items/style.cxx
@@ -690,7 +690,7 @@ SfxStyleSheetBasePool& SfxStyleSheetBasePool::operator+=( const SfxStyleSheetBas
SfxStyleSheetBase* SfxStyleSheetBasePool::Find(const OUString& rName,
SfxStyleFamily eFamily,
- SfxStyleSearchBits eMask) const
+ SfxStyleSearchBits eMask)
{
SfxStyleSheetIterator aIter(this, eFamily, eMask);
return aIter.Find(rName);
diff --git a/sw/inc/docstyle.hxx b/sw/inc/docstyle.hxx
index e71fb73c9828..2d7bfdf3ff99 100644
--- a/sw/inc/docstyle.hxx
+++ b/sw/inc/docstyle.hxx
@@ -207,6 +207,7 @@ public:
class SwDocStyleSheetPool final : public SfxStyleSheetBasePool
{
rtl::Reference< SwDocStyleSheet > mxStyleSheet;
+ rtl::Reference< SfxStyleSheetPool > mxEEStyleSheetPool;
SwDoc& m_rDoc;
bool m_bOrganizer : 1; ///< Organizer
@@ -222,7 +223,7 @@ public:
SfxStyleSearchBits nMask = SfxStyleSearchBits::All) override;
virtual SfxStyleSheetBase* Find( const OUString&, SfxStyleFamily eFam,
- SfxStyleSearchBits n=SfxStyleSearchBits::All ) const override;
+ SfxStyleSearchBits n=SfxStyleSearchBits::All ) override;
virtual bool SetParent( SfxStyleFamily eFam, const OUString &rStyle,
const OUString &rParent ) override;
@@ -234,6 +235,7 @@ public:
virtual std::unique_ptr<SfxStyleSheetIterator> CreateIterator( SfxStyleFamily, SfxStyleSearchBits nMask = SfxStyleSearchBits::All) override;
SwDoc& GetDoc() const { return m_rDoc; }
+ SfxStyleSheetPool* GetEEStyleSheetPool() { return mxEEStyleSheetPool.get(); }
void dispose();
diff --git a/sw/inc/docufld.hxx b/sw/inc/docufld.hxx
index 89a5341222db..17e99a94225e 100644
--- a/sw/inc/docufld.hxx
+++ b/sw/inc/docufld.hxx
@@ -511,6 +511,7 @@ public:
bool GetResolved() const;
sal_Int32 GetNumberOfParagraphs() const;
+ void ChangeStyleSheetName(std::u16string_view rOldName, const SfxStyleSheetBase* pStyleSheet);
virtual bool QueryValue( css::uno::Any& rVal, sal_uInt16 nWhich ) const override;
virtual bool PutValue( const css::uno::Any& rVal, sal_uInt16 nWhich ) override;
diff --git a/sw/source/core/fields/docufld.cxx b/sw/source/core/fields/docufld.cxx
index e604985e7d0f..97156636ef60 100644
--- a/sw/source/core/fields/docufld.cxx
+++ b/sw/source/core/fields/docufld.cxx
@@ -1846,6 +1846,12 @@ sal_Int32 SwPostItField::GetNumberOfParagraphs() const
return mpText ? mpText->Count() : 1;
}
+void SwPostItField::ChangeStyleSheetName(std::u16string_view rOldName, const SfxStyleSheetBase* pStyleSheet)
+{
+ if (mpText && pStyleSheet)
+ mpText->ChangeStyleSheetName(pStyleSheet->GetFamily(), rOldName, pStyleSheet->GetName());
+}
+
void SwPostItField::SetPostItId(const sal_uInt32 nPostItId)
{
m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId;
diff --git a/sw/source/uibase/app/docstyle.cxx b/sw/source/uibase/app/docstyle.cxx
index 0738b2ce6bd1..c869b10f7a5c 100644
--- a/sw/source/uibase/app/docstyle.cxx
+++ b/sw/source/uibase/app/docstyle.cxx
@@ -63,6 +63,9 @@
#include <SwRewriter.hxx>
#include <hints.hxx>
#include <frameformats.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/eeitem.hxx>
#include <svx/xfillit0.hxx>
#include <svx/xflftrit.hxx>
#include <svx/drawitem.hxx>
@@ -77,6 +80,179 @@ using namespace com::sun::star;
namespace {
+class EEStyleSheet : public SfxStyleSheet
+{
+public:
+ using SfxStyleSheet::SfxStyleSheet;
+ bool IsUsed() const override
+ {
+ bool bResult = false;
+ ForAllListeners(
+ [&bResult] (SfxListener* pListener)
+ {
+ auto pUser(dynamic_cast<svl::StyleSheetUser*>(pListener));
+ bResult = pUser && pUser->isUsedByModel();
+ return bResult;
+ });
+ return bResult;
+ }
+ void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override
+ {
+ if (rHint.GetId() == SfxHintId::DataChanged)
+ Broadcast(rHint);
+ else
+ SfxStyleSheet::Notify(rBC, rHint);
+ }
+ bool SetParent(const OUString& rName) override
+ {
+ if (SfxStyleSheet::SetParent(rName))
+ {
+ auto pStyle = m_pPool->Find(rName, nFamily);
+ pSet->SetParent(pStyle ? &pStyle->GetItemSet() : nullptr);
+ Broadcast(SfxHint(SfxHintId::DataChanged));
+ return true;
+ }
+ return false;
+ }
+};
+
+class EEStyleSheetPool : public SfxStyleSheetPool, public SfxListener
+{
+ SfxStyleSheetBasePool* m_pOwner;
+
+public:
+ explicit EEStyleSheetPool(SfxStyleSheetBasePool* pOwner)
+ : SfxStyleSheetPool(pOwner->GetPool())
+ , m_pOwner(pOwner)
+ {
+ StartListening(*m_pOwner);
+ }
+
+ using SfxStyleSheetPool::Create;
+ rtl::Reference<SfxStyleSheetBase> Create(const OUString& rName, SfxStyleFamily eFamily,
+ SfxStyleSearchBits nMask) override
+ {
+ return new EEStyleSheet(rName, *this, eFamily, nMask);
+ }
+
+ void Notify(SfxBroadcaster&, const SfxHint& rHint) override
+ {
+ auto pHint = dynamic_cast<const SfxStyleSheetHint*>(&rHint);
+ if (!pHint)
+ return;
+
+ auto nId = pHint->GetId();
+ auto pDocStyleSheet = pHint->GetStyleSheet();
+ auto pExtendedHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint);
+ const OUString aName = pExtendedHint ? pExtendedHint->GetOldName() : pDocStyleSheet->GetName();
+ auto pStyleSheet = SfxStyleSheetPool::Find(aName, pDocStyleSheet->GetFamily());
+ if (!pStyleSheet)
+ return;
+
+ if (nId == SfxHintId::StyleSheetModified)
+ {
+ pStyleSheet->SetName(pDocStyleSheet->GetName());
+ pStyleSheet->GetItemSet().ClearItem();
+ EnsureStyleHierarchy(pDocStyleSheet->GetName(), pDocStyleSheet->GetFamily());
+ }
+ else if (nId == SfxHintId::StyleSheetErased)
+ Remove(pStyleSheet);
+ }
+
+ SfxStyleSheetBase* Find(const OUString& rName, SfxStyleFamily eFamily,
+ SfxStyleSearchBits = SfxStyleSearchBits::All) override
+ {
+ if (eFamily != SfxStyleFamily::All)
+ EnsureStyleHierarchy(rName, eFamily);
+ return SfxStyleSheetPool::Find(rName, eFamily);
+ }
+
+ void EnsureStyleHierarchy(const OUString& rName, SfxStyleFamily eFamily)
+ {
+ auto pDocStyleSheet = m_pOwner->Find(rName, eFamily);
+ if (!pDocStyleSheet)
+ return;
+
+ auto pStyleSheet = SfxStyleSheetPool::Find(rName, eFamily);
+ if (!pStyleSheet)
+ pStyleSheet = &Make(rName, eFamily);
+
+ FillItemSet(pStyleSheet, pDocStyleSheet);
+
+ // Remember now, as the next calls will invalidate pDocStyleSheet.
+ const OUString aParent = pDocStyleSheet->GetParent();
+ const OUString aFollow = pDocStyleSheet->GetFollow();
+
+ if (pStyleSheet->GetParent() != aParent)
+ pStyleSheet->SetParent(aParent);
+
+ if (pStyleSheet->GetFollow() != aFollow)
+ pStyleSheet->SetFollow(aFollow);
+ }
+
+ void FillItemSet(SfxStyleSheetBase* pDestSheet, SfxStyleSheetBase* pSourceSheet)
+ {
+ auto& rItemSet = pDestSheet->GetItemSet();
+ if (rItemSet.Count() > 0)
+ return;
+
+ auto pCol = static_cast<SwDocStyleSheet*>(pSourceSheet)->GetCollection();
+ if (!pCol->GetAttrSet().Count())
+ return;
+
+ const WhichRangesContainer aRanges(svl::Items<RES_CHRATR_BEGIN, RES_CHRATR_END,
+ RES_PARATR_BEGIN, RES_PARATR_END,
+ RES_FRMATR_BEGIN, RES_FRMATR_END>);
+
+ for (const auto& range : aRanges)
+ {
+ std::optional<SvxLRSpaceItem> oLRSpaceItem;
+
+ for (auto i = range.first; i < range.second; ++i)
+ {
+ const SfxPoolItem* pItem;
+ if (pCol->GetItemState(i, false, &pItem) != SfxItemState::SET)
+ continue;
+
+ auto nSlotId = rPool.GetSlotId(i);
+ auto nNewWhich = rPool.GetSecondaryPool()->GetWhich(nSlotId);
+ if (nNewWhich != nSlotId)
+ rItemSet.Put(pItem->CloneSetWhich(nNewWhich));
+ else if (i == RES_MARGIN_FIRSTLINE)
+ {
+ if (!oLRSpaceItem)
+ oLRSpaceItem.emplace(EE_PARA_LRSPACE);
+ auto pFirstLineItem = static_cast<const SvxFirstLineIndentItem*>(pItem);
+ (*oLRSpaceItem).SetTextFirstLineOffsetValue(pFirstLineItem->GetTextFirstLineOffset());
+ (*oLRSpaceItem).SetAutoFirst(pFirstLineItem->IsAutoFirst());
+ }
+ else if (i == RES_MARGIN_TEXTLEFT)
+ {
+ if (!oLRSpaceItem)
+ oLRSpaceItem.emplace(EE_PARA_LRSPACE);
+ (*oLRSpaceItem).SetTextLeft(static_cast<const SvxTextLeftMarginItem*>(pItem)->GetTextLeft());
+ }
+ else if (i == RES_MARGIN_RIGHT)
+ {
+ if (!oLRSpaceItem)
+ oLRSpaceItem.emplace(EE_PARA_LRSPACE);
+ (*oLRSpaceItem).SetRight(static_cast<const SvxRightMarginItem*>(pItem)->GetRight());
+ }
+ else if (i == RES_CHRATR_BACKGROUND)
+ {
+ auto pBrushItem = static_cast<const SvxBrushItem*>(pItem);
+ rItemSet.Put(SvxColorItem(pBrushItem->GetColor(), EE_CHAR_BKGCOLOR));
+ }
+ }
+
+ if (oLRSpaceItem)
+ rItemSet.Put(*oLRSpaceItem);
+ }
+
+ static_cast<SfxStyleSheet*>(pDestSheet)->Broadcast(SfxHint(SfxHintId::DataChanged));
+ }
+};
+
class SwImplShellAction
{
SwWrtShell* m_pSh;
@@ -2291,7 +2467,16 @@ bool SwDocStyleSheet::IsUsed() const
OSL_ENSURE(false, "unknown style family");
return false;
}
- return m_rDoc.IsUsed( *pMod );
+
+ if (m_rDoc.IsUsed(*pMod))
+ return true;
+
+ SfxStyleSheetIterator aIter(static_cast<SwDocStyleSheetPool*>(m_pPool)->GetEEStyleSheetPool(), nFamily);
+ auto pStyle = aIter.Find(GetName());
+ if (pStyle && pStyle->IsUsed())
+ return true;
+
+ return false;
}
OUString SwDocStyleSheet::GetUsedBy()
@@ -2434,6 +2619,7 @@ void SwDocStyleSheet::SetHelpId( const OUString& r, sal_uLong nId )
SwDocStyleSheetPool::SwDocStyleSheetPool( SwDoc& rDocument, bool bOrg )
: SfxStyleSheetBasePool(rDocument.GetAttrPool())
, mxStyleSheet(new SwDocStyleSheet(rDocument, *this))
+ , mxEEStyleSheetPool(new EEStyleSheetPool(this))
, m_rDoc(rDocument)
{
m_bOrganizer = bOrg;
@@ -2479,6 +2665,7 @@ std::unique_ptr<SfxStyleSheetIterator> SwDocStyleSheetPool::CreateIterator( SfxS
void SwDocStyleSheetPool::dispose()
{
mxStyleSheet.clear();
+ mxEEStyleSheetPool.clear();
}
void SwDocStyleSheetPool::Remove( SfxStyleSheetBase* pStyle)
@@ -2598,7 +2785,7 @@ bool SwDocStyleSheetPool::SetParent( SfxStyleFamily eFam,
}
SfxStyleSheetBase* SwDocStyleSheetPool::Find(const OUString& rName,
- SfxStyleFamily eFam, SfxStyleSearchBits n) const
+ SfxStyleFamily eFam, SfxStyleSearchBits n)
{
SfxStyleSearchBits nSMask = n;
if( SfxStyleFamily::Para == eFam && m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) )
diff --git a/sw/source/uibase/docvw/AnnotationWin2.cxx b/sw/source/uibase/docvw/AnnotationWin2.cxx
index 2c4bc7ce3d5e..d531a62e1f57 100644
--- a/sw/source/uibase/docvw/AnnotationWin2.cxx
+++ b/sw/source/uibase/docvw/AnnotationWin2.cxx
@@ -67,6 +67,7 @@
#include <docsh.hxx>
#include <wrtsh.hxx>
#include <doc.hxx>
+#include <docstyle.hxx>
#include <docufld.hxx>
#include <swmodule.hxx>
@@ -321,6 +322,7 @@ void SwAnnotationWin::InitControls()
SwDocShell* aShell = mrView.GetDocShell();
mpOutliner.reset(new Outliner(&aShell->GetPool(),OutlinerMode::TextObject));
+ mpOutliner->SetStyleSheetPool(static_cast<SwDocStyleSheetPool*>(aShell->GetStyleSheetPool())->GetEEStyleSheetPool());
aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner.get() );
mpOutliner->SetUpdateLayout( true );
@@ -352,6 +354,9 @@ void SwAnnotationWin::InitControls()
EEControlBits nCntrl = mpOutliner->GetControlWord();
// TODO: crash when AUTOCOMPLETE enabled
nCntrl |= EEControlBits::MARKFIELDS | EEControlBits::PASTESPECIAL | EEControlBits::AUTOCORRECT | EEControlBits::USECHARATTRIBS; // | EEControlBits::AUTOCOMPLETE;
+ // Our stylesheet pool follows closely the core paragraph styles.
+ // We don't want the rtf import (during paste) to mess with that.
+ nCntrl &= ~EEControlBits::RTFSTYLESHEETS;
if (SwWrtShell* pWrtShell = mrView.GetWrtShellPtr())
{
diff --git a/sw/source/uibase/docvw/PostItMgr.cxx b/sw/source/uibase/docvw/PostItMgr.cxx
index 68c1a00221f7..bd92adadbf03 100644
--- a/sw/source/uibase/docvw/PostItMgr.cxx
+++ b/sw/source/uibase/docvw/PostItMgr.cxx
@@ -45,6 +45,7 @@
#include <doc.hxx>
#include <IDocumentSettingAccess.hxx>
#include <IDocumentFieldsAccess.hxx>
+#include <docstyle.hxx>
#include <fldbas.hxx>
#include <fmtfld.hxx>
#include <docufld.hxx>
@@ -223,6 +224,9 @@ SwPostItMgr::SwPostItMgr(SwView* pView)
*/
// we want to receive stuff like SfxHintId::DocChanged
StartListening(*mpView->GetDocShell());
+ // listen to stylesheet pool to update on stylesheet rename,
+ // as EditTextObject references styles by name.
+ StartListening(*static_cast<SwDocStyleSheetPool*>(mpView->GetDocShell()->GetStyleSheetPool())->GetEEStyleSheetPool());
if (!mvPostItFields.empty())
{
mbWaitingForCalcRects = true;
@@ -236,7 +240,7 @@ SwPostItMgr::~SwPostItMgr()
Application::RemoveUserEvent( mnEventId );
// forget about all our Sidebar windows
RemoveSidebarWin();
- EndListening( *mpView->GetDocShell() );
+ EndListeningAll();
mPages.clear();
}
@@ -469,6 +473,14 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
}
}
}
+ else if ( const SfxStyleSheetModifiedHint * pStyleHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint) )
+ {
+ for (const auto& postItField : mvPostItFields)
+ {
+ auto pField = static_cast<SwPostItField*>(postItField->GetFormatField().GetField());
+ pField->ChangeStyleSheetName(pStyleHint->GetOldName(), pStyleHint->GetStyleSheet());
+ }
+ }
else
{
SfxHintId nId = rHint.GetId();