diff options
-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*/, |