diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2023-01-06 17:28:49 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2023-01-14 07:52:46 +0000 |
commit | 1af58b5acec4a2de095d86feef05ac4aed3edb8f (patch) | |
tree | b6cf779162c82badd33f3b0c3cb75df69f6ac643 /sw | |
parent | 8bc22ed6899bcbafc3020f0af6c939019506a5fd (diff) |
sw: add ThemeColorChanger that sweeps the model and changes colors
The ThemeColorChanger responisiblity is to recalculate and change
all the theme colors in the model. This includes styles and direct
formatting changes. It uses ModelTraverser for direct formatting
changes as it already implements traversing through nodes.
The ThemeColorChanger replaces the code to change the colors in
ThemePanel.
Also modify undo/redo for changing of attributes to not move
the cursor and selection when undoing and redoing (new flag
NO_CURSOR_CHANGE), as in this case it is very distrcting.
Change-Id: Ida1912bd0697307daad9244d474862830ab2686f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145263
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/Library_sw.mk | 1 | ||||
-rw-r--r-- | sw/inc/swtypes.hxx | 6 | ||||
-rw-r--r-- | sw/source/core/inc/ThemeColorChanger.hxx | 33 | ||||
-rw-r--r-- | sw/source/core/inc/UndoAttribute.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/model/ThemeColorChanger.cxx | 271 | ||||
-rw-r--r-- | sw/source/core/undo/unattr.cxx | 21 | ||||
-rw-r--r-- | sw/source/uibase/sidebar/ThemePanel.cxx | 44 |
7 files changed, 331 insertions, 47 deletions
diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk index 478136e50f54..fa2ca1663512 100644 --- a/sw/Library_sw.mk +++ b/sw/Library_sw.mk @@ -366,6 +366,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\ sw/source/core/layout/wsfrm \ sw/source/core/model/ModelTraverser \ sw/source/core/model/SearchResultLocator \ + sw/source/core/model/ThemeColorChanger \ sw/source/core/objectpositioning/anchoredobjectposition \ sw/source/core/objectpositioning/ascharanchoredobjectposition \ sw/source/core/objectpositioning/environmentofanchoredobject \ diff --git a/sw/inc/swtypes.hxx b/sw/inc/swtypes.hxx index 96c0fb5008c3..b3cdfa531074 100644 --- a/sw/inc/swtypes.hxx +++ b/sw/inc/swtypes.hxx @@ -143,17 +143,19 @@ enum class SetAttrMode NOHINTADJUST = 0x0008, // No merging of ranges. NOFORMATATTR = 0x0010, // Do not change into format attribute. APICALL = 0x0020, // Called from API (all UI related - // functionality will be disabled). + // functionality will be disabled). /// Force hint expand (only matters for hints with CH_TXTATR). FORCEHINTEXPAND = 0x0040, /// The inserted item is a copy -- intended for use in ndtxt.cxx. IS_COPY = 0x0080, /// for Undo, translated to SwInsertFlags::NOHINTEXPAND NOHINTEXPAND = 0x0100, + /// don't change the cursor position + NO_CURSOR_CHANGE = 0x0200 }; namespace o3tl { - template<> struct typed_flags<SetAttrMode> : is_typed_flags<SetAttrMode, 0x1ff> {}; + template<> struct typed_flags<SetAttrMode> : is_typed_flags<SetAttrMode, 0x3ff> {}; } namespace sw { diff --git a/sw/source/core/inc/ThemeColorChanger.hxx b/sw/source/core/inc/ThemeColorChanger.hxx new file mode 100644 index 000000000000..0698126da3e9 --- /dev/null +++ b/sw/source/core/inc/ThemeColorChanger.hxx @@ -0,0 +1,33 @@ +/* -*- 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 <docsh.hxx> +#include <svx/ColorSets.hxx> + +namespace sw +{ +class ThemeColorChanger +{ +private: + SwDocShell* mpDocSh; + +public: + ThemeColorChanger(SwDocShell* pDocSh) + : mpDocSh(pDocSh) + { + } + + void apply(svx::ColorSet const& rColorSet); +}; + +} // end sw namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/inc/UndoAttribute.hxx b/sw/source/core/inc/UndoAttribute.hxx index c3cf4925d95a..e3c40b7f0e87 100644 --- a/sw/source/core/inc/UndoAttribute.hxx +++ b/sw/source/core/inc/UndoAttribute.hxx @@ -45,7 +45,7 @@ class SwUndoAttr final : public SwUndo, private SwUndRng OUString m_aChrFormatName; void RemoveIdx( SwDoc& rDoc ); - + void redoAttribute(SwPaM& rPam, sw::UndoRedoContext& rContext); public: SwUndoAttr( const SwPaM&, SfxItemSet, const SetAttrMode nFlags ); SwUndoAttr( const SwPaM&, const SfxPoolItem&, const SetAttrMode nFlags ); diff --git a/sw/source/core/model/ThemeColorChanger.cxx b/sw/source/core/model/ThemeColorChanger.cxx new file mode 100644 index 000000000000..ff59c474748b --- /dev/null +++ b/sw/source/core/model/ThemeColorChanger.cxx @@ -0,0 +1,271 @@ +/* -*- 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 <ThemeColorChanger.hxx> +#include <ModelTraverser.hxx> +#include <txtftn.hxx> +#include <txtfrm.hxx> +#include <docstyle.hxx> +#include <drawdoc.hxx> +#include <ndnotxt.hxx> +#include <ndtxt.hxx> +#include <format.hxx> +#include <charatr.hxx> +#include <DocumentContentOperationsManager.hxx> +#include <IDocumentUndoRedo.hxx> + +#include <sal/config.h> +#include <svx/svdpage.hxx> +#include <svx/svditer.hxx> +#include <docmodel/uno/UnoThemeColor.hxx> +#include <editeng/unoprnms.hxx> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +namespace sw +{ +namespace +{ +/** Handler for ModelTraverser that recalculates and updates the theme colors. + * + * It checks all the SdrObjects and updates fill, line and text theme colors. + * For writer nodes it checks all the text nodes and updates the direct + * formatting in all hints. + * + */ +class ThemeColorHandler : public sw::ModelTraverseHandler +{ + SwDoc& mrDocument; + svx::ColorSet const& mrColorSet; + +public: + ThemeColorHandler(SwDoc& rDocument, svx::ColorSet const& rColorSet) + : mrDocument(rDocument) + , mrColorSet(rColorSet) + { + } + + /// Updates hints for a text node + void updateHints(SwTextNode* pTextNode) + { + if (!pTextNode->HasHints()) + return; + + SwpHints& rHints = pTextNode->GetSwpHints(); + for (size_t i = 0; i < rHints.Count(); ++i) + { + const SwTextAttr* pTextAttr = rHints.Get(i); + if (pTextAttr->Which() == RES_TXTATR_AUTOFMT) + { + SwFormatAutoFormat const& rAutoFormatPool(pTextAttr->GetAutoFormat()); + std::shared_ptr<SfxItemSet> pStyleHandle(rAutoFormatPool.GetStyleHandle()); + if (const SvxColorItem* pItem = pStyleHandle->GetItemIfSet(RES_CHRATR_COLOR)) + { + model::ThemeColor const& rThemeColor = pItem->GetThemeColor(); + auto eThemeType = rThemeColor.getType(); + if (eThemeType != model::ThemeColorType::Unknown) + { + Color aNewColor = mrColorSet.resolveColor(rThemeColor); + auto pNew = pItem->Clone(); + pNew->SetValue(aNewColor); + + SwPaM aPam(*pTextNode, pTextAttr->GetStart(), *pTextNode, + pTextAttr->GetAnyEnd()); + mrDocument.GetDocumentContentOperationsManager().InsertPoolItem( + aPam, *pNew, SetAttrMode::APICALL | SetAttrMode::NO_CURSOR_CHANGE); + } + } + } + } + } + + void handleNode(SwNode* pNode) override + { + if (!pNode->IsTextNode()) + return; + + updateHints(pNode->GetTextNode()); + } + + /// Updates text portion property colors + void updateTextPortionColorSet(const uno::Reference<beans::XPropertySet>& xPortion) + { + if (!xPortion->getPropertySetInfo()->hasPropertyByName( + UNO_NAME_EDIT_CHAR_COLOR_THEME_REFERENCE)) + return; + + uno::Reference<util::XThemeColor> xThemeColor; + xPortion->getPropertyValue(UNO_NAME_EDIT_CHAR_COLOR_THEME_REFERENCE) >>= xThemeColor; + if (!xThemeColor.is()) + return; + + model::ThemeColor aThemeColor; + model::theme::setFromXThemeColor(aThemeColor, xThemeColor); + + if (aThemeColor.getType() == model::ThemeColorType::Unknown) + return; + + Color aColor = mrColorSet.resolveColor(aThemeColor); + xPortion->setPropertyValue(UNO_NAME_EDIT_CHAR_COLOR, + uno::Any(static_cast<sal_Int32>(aColor))); + } + + /// Updates the fill property colors + void updateFillColorSet(const uno::Reference<beans::XPropertySet>& xShape) + { + if (!xShape->getPropertySetInfo()->hasPropertyByName(UNO_NAME_FILLCOLOR_THEME_REFERENCE)) + return; + + uno::Reference<util::XThemeColor> xThemeColor; + xShape->getPropertyValue(UNO_NAME_FILLCOLOR_THEME_REFERENCE) >>= xThemeColor; + if (!xThemeColor.is()) + return; + + model::ThemeColor aThemeColor; + model::theme::setFromXThemeColor(aThemeColor, xThemeColor); + + if (aThemeColor.getType() == model::ThemeColorType::Unknown) + return; + + Color aColor = mrColorSet.resolveColor(aThemeColor); + xShape->setPropertyValue(UNO_NAME_FILLCOLOR, uno::Any(static_cast<sal_Int32>(aColor))); + } + + /// Updates the line property colors + void updateLineColorSet(const uno::Reference<beans::XPropertySet>& xShape) + { + if (!xShape->getPropertySetInfo()->hasPropertyByName(UNO_NAME_LINECOLOR_THEME_REFERENCE)) + return; + + uno::Reference<util::XThemeColor> xThemeColor; + xShape->getPropertyValue(UNO_NAME_LINECOLOR_THEME_REFERENCE) >>= xThemeColor; + if (!xThemeColor.is()) + return; + + model::ThemeColor aThemeColor; + model::theme::setFromXThemeColor(aThemeColor, xThemeColor); + + if (aThemeColor.getType() == model::ThemeColorType::Unknown) + return; + + Color aColor = mrColorSet.resolveColor(aThemeColor); + xShape->setPropertyValue(UNO_NAME_LINECOLOR, uno::Any(static_cast<sal_Int32>(aColor))); + } + + /// Updates properties of the SdrObject + void updateSdrObject(SdrObject* pObject) + { + uno::Reference<drawing::XShape> xShape = pObject->getUnoShape(); + uno::Reference<text::XTextRange> xShapeText(xShape, uno::UNO_QUERY); + if (xShapeText.is()) + { + // E.g. group shapes have no text. + uno::Reference<container::XEnumerationAccess> xText(xShapeText->getText(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParagraphs = xText->createEnumeration(); + while (xParagraphs->hasMoreElements()) + { + uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration(); + while (xPortions->hasMoreElements()) + { + uno::Reference<beans::XPropertySet> xPortion(xPortions->nextElement(), + uno::UNO_QUERY); + updateTextPortionColorSet(xPortion); + } + } + } + + uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY); + updateFillColorSet(xShapeProps); + updateLineColorSet(xShapeProps); + } + + void handleSdrObject(SdrObject* pObject) override + { + // update current object + updateSdrObject(pObject); + + // update child objects + SdrObjList* pList = pObject->GetSubList(); + if (pList) + { + SdrObjListIter aIter(pList, SdrIterMode::DeepWithGroups); + while (aIter.IsMore()) + { + updateSdrObject(aIter.Next()); + } + } + } +}; + +void changeColor(SwFormat* pFormat, svx::ColorSet const& rColorSet, SwDoc* pDocument) +{ + const SwAttrSet& rAttrSet = pFormat->GetAttrSet(); + std::unique_ptr<SfxItemSet> pNewSet = rAttrSet.Clone(); + + SvxColorItem aColorItem(rAttrSet.GetColor()); + model::ThemeColor const& rThemeColor = aColorItem.GetThemeColor(); + auto eThemeType = rThemeColor.getType(); + if (eThemeType != model::ThemeColorType::Unknown) + { + Color aColor = rColorSet.getColor(eThemeType); + aColor = rThemeColor.applyTransformations(aColor); + aColorItem.SetValue(aColor); + pNewSet->Put(aColorItem); + pDocument->ChgFormat(*pFormat, *pNewSet); + } +} + +} // end anonymous namespace + +void ThemeColorChanger::apply(svx::ColorSet const& rColorSet) +{ + SwDoc* pDocument = mpDocSh->GetDoc(); + pDocument->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr); + + SfxStyleSheetBasePool* pPool = mpDocSh->GetStyleSheetPool(); + SwDocStyleSheet* pStyle; + + // Paragraph style color change + pStyle = static_cast<SwDocStyleSheet*>(pPool->First(SfxStyleFamily::Para)); + while (pStyle) + { + SwTextFormatColl* pTextFormatCollection = pStyle->GetCollection(); + if (pTextFormatCollection) + changeColor(pTextFormatCollection, rColorSet, pDocument); + pStyle = static_cast<SwDocStyleSheet*>(pPool->Next()); + } + + // Character style color change + pStyle = static_cast<SwDocStyleSheet*>(pPool->First(SfxStyleFamily::Char)); + while (pStyle) + { + SwCharFormat* pCharFormat = pStyle->GetCharFormat(); + if (pCharFormat) + changeColor(pCharFormat, rColorSet, pDocument); + pStyle = static_cast<SwDocStyleSheet*>(pPool->Next()); + } + + // Direct format change + auto pHandler = std::make_shared<ThemeColorHandler>(*pDocument, rColorSet); + sw::ModelTraverser aModelTraverser(pDocument); + aModelTraverser.addNodeHandler(pHandler); + aModelTraverser.traverse(); + + pDocument->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr); +} + +} // end sw namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/undo/unattr.cxx b/sw/source/core/undo/unattr.cxx index d8dc236c92e2..60df048d22b3 100644 --- a/sw/source/core/undo/unattr.cxx +++ b/sw/source/core/undo/unattr.cxx @@ -770,7 +770,8 @@ void SwUndoAttr::UndoImpl(::sw::UndoRedoContext & rContext) m_pHistory->SetTmpEnd( m_pHistory->Count() ); // set cursor onto Undo area - AddUndoRedoPaM(rContext); + if (!(m_nInsertFlags & SetAttrMode::NO_CURSOR_CHANGE)) + AddUndoRedoPaM(rContext); } void SwUndoAttr::RepeatImpl(::sw::RepeatContext & rContext) @@ -787,10 +788,9 @@ void SwUndoAttr::RepeatImpl(::sw::RepeatContext & rContext) } } -void SwUndoAttr::RedoImpl(::sw::UndoRedoContext & rContext) +void SwUndoAttr::redoAttribute(SwPaM& rPam, sw::UndoRedoContext & rContext) { SwDoc & rDoc = rContext.GetDoc(); - SwPaM & rPam = AddUndoRedoPaM(rContext); // Restore pointer to char format from name if (!m_aChrFormatName.isEmpty()) @@ -826,6 +826,21 @@ void SwUndoAttr::RedoImpl(::sw::UndoRedoContext & rContext) } } +void SwUndoAttr::RedoImpl(sw::UndoRedoContext & rContext) +{ + if (m_nInsertFlags & SetAttrMode::NO_CURSOR_CHANGE) + { + SwPaM aPam(rContext.GetDoc().GetNodes().GetEndOfContent()); + SetPaM(aPam, false); + redoAttribute(aPam, rContext); + } + else + { + SwPaM& rPam = AddUndoRedoPaM(rContext); + redoAttribute(rPam, rContext); + } +} + void SwUndoAttr::RemoveIdx( SwDoc& rDoc ) { if ( SfxItemState::SET != m_AttrSet.GetItemState( RES_TXTATR_FTN, false )) diff --git a/sw/source/uibase/sidebar/ThemePanel.cxx b/sw/source/uibase/sidebar/ThemePanel.cxx index 5c1f9238dc43..76fd5e59870b 100644 --- a/sw/source/uibase/sidebar/ThemePanel.cxx +++ b/sw/source/uibase/sidebar/ThemePanel.cxx @@ -13,55 +13,16 @@ #include <doc.hxx> #include <docsh.hxx> -#include <docstyle.hxx> #include <drawdoc.hxx> -#include <ndnotxt.hxx> -#include <ndtxt.hxx> -#include <fmtcol.hxx> -#include <format.hxx> -#include <charatr.hxx> #include <IDocumentDrawModelAccess.hxx> +#include <ThemeColorChanger.hxx> #include <vcl/settings.hxx> #include <vcl/svapp.hxx> #include <svx/svdpage.hxx> #include <svx/ColorSets.hxx> #include <svx/dialog/ThemeColorValueSet.hxx> -#include <sfx2/objsh.hxx> -#include <editeng/colritem.hxx> #include <com/sun/star/lang/IllegalArgumentException.hpp> -namespace -{ - -void changeColor(SwTextFormatColl* pCollection, svx::ColorSet const& rColorSet) -{ - SvxColorItem aColorItem(pCollection->GetColor()); - model::ThemeColor const& rThemeColor = aColorItem.GetThemeColor(); - auto eThemeType = rThemeColor.getType(); - if (eThemeType != model::ThemeColorType::Unknown) - { - Color aColor = rColorSet.getColor(eThemeType); - aColor = rThemeColor.applyTransformations(aColor); - aColorItem.SetValue(aColor); - pCollection->SetFormatAttr(aColorItem); - } -} - -void applyTheme(SfxStyleSheetBasePool* pPool, svx::ColorSet const& rColorSet) -{ - SwDocStyleSheet* pStyle; - - pStyle = static_cast<SwDocStyleSheet*>(pPool->First(SfxStyleFamily::Para)); - while (pStyle) - { - SwTextFormatColl* pCollection = pStyle->GetCollection(); - changeColor(pCollection, rColorSet); - pStyle = static_cast<SwDocStyleSheet*>(pPool->Next()); - } -} - -} // end anonymous namespace - namespace sw::sidebar { @@ -147,7 +108,8 @@ void ThemePanel::DoubleClickHdl() svx::ColorSet const& rColorSet = maColorSets.getColorSet(nIndex); - applyTheme(pDocSh->GetStyleSheetPool(), rColorSet); + ThemeColorChanger aChanger(pDocSh); + aChanger.apply(rColorSet); } void ThemePanel::NotifyItemUpdate(const sal_uInt16 /*nSId*/, |