sc/Library_sc.mk | 1 sc/inc/globstr.hrc | 2 sc/source/ui/inc/undo/UndoThemeChange.hxx | 36 +++++ sc/source/ui/theme/ThemeColorChanger.cxx | 209 +++++++++++++++++++++++++----- sc/source/ui/undo/UndoThemeChange.cxx | 75 ++++++++++ 5 files changed, 293 insertions(+), 30 deletions(-)
New commits: commit 6f77ed620bbff11a1232b593be97e7d6f29aa8ac Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Tue Jul 11 16:02:02 2023 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Wed Jul 12 04:04:45 2023 +0200 sc: Theme color change undo/redo - styles and direct format This adds the code for undo/redo for change of theme colors in styles and direct formatting. Change-Id: I58568b18ab18562e6148ec8530d3d22c62ef2b95 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154305 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 75e9a1743d12..2b4082d3688e 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -569,6 +569,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/ui/undo/UndoUngroupSparklines \ sc/source/ui/undo/UndoGroupSparklines \ sc/source/ui/undo/UndoEditSparkline \ + sc/source/ui/undo/UndoThemeChange \ sc/source/ui/unoobj/ChartRangeSelectionListener \ sc/source/ui/unoobj/addruno \ sc/source/ui/unoobj/afmtuno \ diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc index 600cf9354fc0..5e6880d973d1 100644 --- a/sc/inc/globstr.hrc +++ b/sc/inc/globstr.hrc @@ -564,6 +564,8 @@ #define STR_UNDO_GROUP_SPARKLINES NC_("STR_UNDO_GROUP_SPARKLINES", "Group Sparklines") #define STR_UNDO_UNGROUP_SPARKLINES NC_("STR_UNDO_UNGROUP_SPARKLINES", "Ungroup Sparklines") #define STR_UNDO_EDIT_SPARKLINE NC_("STR_UNDO_EDIT_SPARKLINE", "Edit Sparkline") +#define STR_UNDO_THEME_CHANGE NC_("STR_UNDO_THEME_CHANGE", "Theme Change") +#define STR_UNDO_THEME_COLOR_CHANGE NC_("STR_UNDO_THEME_COLOR_CHANGE", "Theme Color Change") #endif diff --git a/sc/source/ui/inc/undo/UndoThemeChange.hxx b/sc/source/ui/inc/undo/UndoThemeChange.hxx new file mode 100644 index 000000000000..6c0558df8a7f --- /dev/null +++ b/sc/source/ui/inc/undo/UndoThemeChange.hxx @@ -0,0 +1,36 @@ +/* -*- 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 <undobase.hxx> + +namespace sc +{ +class UndoThemeChange : public ScSimpleUndo +{ +private: + std::shared_ptr<model::ColorSet> mpOldColorSet; + std::shared_ptr<model::ColorSet> mpNewColorSet; + +public: + UndoThemeChange(ScDocShell& rDocShell, std::shared_ptr<model::ColorSet> const& pOldColorSet, + std::shared_ptr<model::ColorSet> const& pNewColorSet); + virtual ~UndoThemeChange() override; + + void Undo() override; + void Redo() override; + bool CanRepeat(SfxRepeatTarget& rTarget) const override; + void Repeat(SfxRepeatTarget& rTarget) override; + OUString GetComment() const override; +}; + +} // namespace sc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/theme/ThemeColorChanger.cxx b/sc/source/ui/theme/ThemeColorChanger.cxx index 8eaa6ed0fcb6..66683adbd682 100644 --- a/sc/source/ui/theme/ThemeColorChanger.cxx +++ b/sc/source/ui/theme/ThemeColorChanger.cxx @@ -20,12 +20,20 @@ #include <editeng/borderline.hxx> #include <svx/svditer.hxx> +#include <undodraw.hxx> #include <stlpool.hxx> #include <stlsheet.hxx> #include <scitems.hxx> +#include <scresid.hxx> +#include <globstr.hrc> #include <document.hxx> #include <address.hxx> #include <dociter.hxx> +#include <tabvwsh.hxx> +#include <undostyl.hxx> +#include <undoblk.hxx> + +#include <undo/UndoThemeChange.hxx> namespace sc { @@ -58,10 +66,10 @@ bool changeBorderLine(editeng::SvxBorderLine* pBorderLine, model::ColorSet const return false; } -void changeCellItems(SfxItemSet& rItemSet, model::ColorSet const& rColorSet) +bool changeCellItems(SfxItemSet& rItemSet, model::ColorSet const& rColorSet) { const SfxPoolItem* pItem = nullptr; - + bool bChanged = false; if (rItemSet.HasItem(ATTR_FONT_COLOR, &pItem)) { auto const* pColorItem = static_cast<const SvxColorItem*>(pItem); @@ -77,6 +85,7 @@ void changeCellItems(SfxItemSet& rItemSet, model::ColorSet const& rColorSet) SvxColorItem aColorItem(*pColorItem); aColorItem.setColor(aColor); rItemSet.Put(aColorItem); + bChanged = true; } } } @@ -95,6 +104,7 @@ void changeCellItems(SfxItemSet& rItemSet, model::ColorSet const& rColorSet) SvxBrushItem aNewBrushItem(*pBrushItem); aNewBrushItem.SetColor(aColor); rItemSet.Put(aNewBrushItem); + bChanged = true; } } } @@ -102,60 +112,199 @@ void changeCellItems(SfxItemSet& rItemSet, model::ColorSet const& rColorSet) { auto const* pBoxItem = static_cast<const SvxBoxItem*>(pItem); SvxBoxItem rNewItem(*pBoxItem); - bool bChanged = false; + bool bLineChanged = false; - bChanged = changeBorderLine(rNewItem.GetBottom(), rColorSet) || bChanged; - bChanged = changeBorderLine(rNewItem.GetTop(), rColorSet) || bChanged; - bChanged = changeBorderLine(rNewItem.GetLeft(), rColorSet) || bChanged; - bChanged = changeBorderLine(rNewItem.GetRight(), rColorSet) || bChanged; + bLineChanged = changeBorderLine(rNewItem.GetBottom(), rColorSet) || bChanged; + bLineChanged = changeBorderLine(rNewItem.GetTop(), rColorSet) || bChanged; + bLineChanged = changeBorderLine(rNewItem.GetLeft(), rColorSet) || bChanged; + bLineChanged = changeBorderLine(rNewItem.GetRight(), rColorSet) || bChanged; - if (bChanged) + if (bLineChanged) + { rItemSet.Put(rNewItem); + bChanged = true; + } } + return bChanged; } -} // end anonymous ns -void ThemeColorChanger::apply(std::shared_ptr<model::ColorSet> const& pColorSet) +bool changeStyles(ScDocShell& rDocShell, std::shared_ptr<model::ColorSet> const& pColorSet) { - auto& rDocument = m_rDocShell.GetDocument(); + ScDocument& rDocument = rDocShell.GetDocument(); ScStyleSheetPool* pPool = rDocument.GetStyleSheetPool(); - ScStyleSheet* pStyle; + ScStyleSheet* pStyle = nullptr; + bool bChanged = false; // Paragraph style color change pStyle = static_cast<ScStyleSheet*>(pPool->First(SfxStyleFamily::Para)); while (pStyle) { - auto& rItemSet = pStyle->GetItemSet(); - changeCellItems(rItemSet, *pColorSet); + ScStyleSaveData aOldData; + aOldData.InitFromStyle(pStyle); + + auto rItemSet = pStyle->GetItemSet(); + if (changeCellItems(rItemSet, *pColorSet)) + { + if (rDocument.IsUndoEnabled()) + { + ScStyleSaveData aNewData; + aNewData.InitFromStyle(pStyle); + rDocShell.GetUndoManager()->AddUndoAction(std::make_unique<ScUndoModifyStyle>( + &rDocShell, SfxStyleFamily::Para, aOldData, aNewData)); + } + static_cast<SfxStyleSheet*>(pStyle)->Broadcast(SfxHint(SfxHintId::DataChanged)); + bChanged = true; + } + pStyle = static_cast<ScStyleSheet*>(pPool->Next()); } + return bChanged; +} + +bool changeSheets(ScDocShell& rDocShell, ScDrawLayer* pModel, + std::shared_ptr<model::ColorSet> const& pColorSet) +{ + ScDocument& rDocument = rDocShell.GetDocument(); + bool bChanged = false; + for (SCTAB nTab = 0; nTab < rDocument.GetTableCount(); nTab++) { // Change Cell / Text attributes - ScDocAttrIterator aAttributeIterator(rDocument, nTab, 0, 0, rDocument.MaxCol(), - rDocument.MaxRow()); - SCCOL nCol = 0; - SCROW nRow1 = 0; - SCROW nRow2 = 0; - - while (const ScPatternAttr* pPattern = aAttributeIterator.GetNext(nCol, nRow1, nRow2)) { - auto* pNonConstPattern = const_cast<ScPatternAttr*>(pPattern); - auto& rItemSet = pNonConstPattern->GetItemSet(); - changeCellItems(rItemSet, *pColorSet); + ScDocAttrIterator aAttributeIterator(rDocument, nTab, 0, 0, rDocument.MaxCol(), + rDocument.MaxRow()); + SCCOL nCol = 0; + SCROW nRow1 = 0; + SCROW nRow2 = 0; + + while (const ScPatternAttr* pPattern = aAttributeIterator.GetNext(nCol, nRow1, nRow2)) + { + if (!pPattern || !pPattern->IsVisible()) + continue; + + ScPatternAttr aNewPattern(*pPattern); + auto& rItemSet = aNewPattern.GetItemSet(); + bool bItemChanged = changeCellItems(rItemSet, *pColorSet); + bChanged = bChanged || bItemChanged; + + if (bItemChanged && rDocument.IsUndoEnabled()) + { + ScRange aRange(nCol, nRow1, nTab, nCol, nRow2, nTab); + ScMarkData aMark(rDocument.GetSheetLimits()); + aMark.SetMarkArea(aRange); + + ScDocumentUniquePtr pUndoDoc(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndo(rDocument, nTab, nTab); + pUndoDoc->AddUndoTab(nTab, nTab); + + aMark.MarkToMulti(); + + rDocument.CopyToDocument(aRange, InsertDeleteFlags::ATTRIB, true, *pUndoDoc, + &aMark); + + auto pUndo = std::make_unique<ScUndoSelectionAttr>( + &rDocShell, aMark, aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), aRange.aEnd.Col(), aRange.aEnd.Row(), + aRange.aEnd.Tab(), std::move(pUndoDoc), true, &aNewPattern); + + ScEditDataArray* pDataArray = pUndo->GetDataArray(); + + rDocument.ApplySelectionPattern(aNewPattern, aMark, pDataArray); + + rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); + } + } } // Change all SdrObjects - SdrPage* pPage = rDocument.GetDrawLayer()->GetPage(static_cast<sal_uInt16>(nTab)); - SdrObjListIter aIter(pPage, SdrIterMode::DeepNoGroups); - SdrObject* pObject = aIter.Next(); - while (pObject) { - svx::theme::updateSdrObject(*pColorSet, pObject); - pObject = aIter.Next(); + pModel->BeginCalcUndo(true); + + SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); + SdrObjListIter aIter(pPage, SdrIterMode::DeepNoGroups); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + svx::theme::updateSdrObject(*pColorSet, pObject); + pObject = aIter.Next(); + } + + std::unique_ptr<SdrUndoGroup> pUndo = pModel->GetCalcUndo(); + + if (pUndo) + { + bChanged = true; + pUndo->SetComment("Hi!"); + auto pUndoDraw = std::make_unique<ScUndoDraw>(std::move(pUndo), &rDocShell); + rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoDraw)); + } } } + + return bChanged; +} + +void changeTheTheme(ScDocShell& rDocShell, std::shared_ptr<model::ColorSet> const& pColorSet) +{ + ScDocument& rDocument = rDocShell.GetDocument(); + ScDrawLayer* pModel = rDocument.GetDrawLayer(); + SdrPage* pPage = pModel->GetPage(0); + + auto pTheme = pPage->getSdrPageProperties().GetTheme(); + if (!pTheme) + { + pTheme = std::make_shared<model::Theme>("Office"); + pPage->getSdrPageProperties().SetTheme(pTheme); + } + + std::shared_ptr<model::ColorSet> pNewColorSet = pColorSet; + std::shared_ptr<model::ColorSet> pOldColorSet = pTheme->getColorSet(); + pTheme->setColorSet(pNewColorSet); + + if (rDocument.IsUndoEnabled()) + { + auto pUndoThemeChange + = std::make_unique<sc::UndoThemeChange>(rDocShell, pOldColorSet, pNewColorSet); + rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoThemeChange)); + } +} + +} // end anonymous ns + +void ThemeColorChanger::apply(std::shared_ptr<model::ColorSet> const& pColorSet) +{ + m_rDocShell.MakeDrawLayer(); + + ScDocShellModificator aModificator(m_rDocShell); + ScDocument& rDocument = m_rDocShell.GetDocument(); + auto pUndoManager = m_rDocShell.GetUndoManager(); + + const bool bUndo(rDocument.IsUndoEnabled()); + + ViewShellId nViewShellId(-1); + if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell()) + nViewShellId = pViewSh->GetViewShellId(); + + if (bUndo) + { + OUString aUndo = ScResId(STR_UNDO_THEME_COLOR_CHANGE); + pUndoManager->EnterListAction(aUndo, aUndo, 0, nViewShellId); + } + + bool bChanged = false; + bChanged = changeStyles(m_rDocShell, pColorSet) || bChanged; + bChanged = changeSheets(m_rDocShell, rDocument.GetDrawLayer(), pColorSet) || bChanged; + + changeTheTheme(m_rDocShell, pColorSet); + + if (bUndo) + { + pUndoManager->LeaveListAction(); + } + + m_rDocShell.SetDrawModified(); + aModificator.SetDocumentModified(); } } // end sw namespace diff --git a/sc/source/ui/undo/UndoThemeChange.cxx b/sc/source/ui/undo/UndoThemeChange.cxx new file mode 100644 index 000000000000..a6a3fe83652e --- /dev/null +++ b/sc/source/ui/undo/UndoThemeChange.cxx @@ -0,0 +1,75 @@ +/* -*- 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 <undo/UndoThemeChange.hxx> +#include <docmodel/theme/Theme.hxx> +#include <svx/svdpage.hxx> +#include <scresid.hxx> +#include <globstr.hrc> + +namespace sc +{ +UndoThemeChange::UndoThemeChange(ScDocShell& rDocShell, + std::shared_ptr<model::ColorSet> const& pOldColorSet, + std::shared_ptr<model::ColorSet> const& pNewColorSet) + : ScSimpleUndo(&rDocShell) + , mpOldColorSet(pOldColorSet) + , mpNewColorSet(pNewColorSet) +{ +} + +UndoThemeChange::~UndoThemeChange() = default; + +void UndoThemeChange::Undo() +{ + BeginUndo(); + + ScDocument& rDocument = pDocShell->GetDocument(); + ScDrawLayer* pModel = rDocument.GetDrawLayer(); + SdrPage* pPage = pModel->GetPage(0); + + auto pTheme = pPage->getSdrPageProperties().GetTheme(); + if (!pTheme) + { + pTheme = std::make_shared<model::Theme>("Office"); + pPage->getSdrPageProperties().SetTheme(pTheme); + } + pTheme->setColorSet(mpOldColorSet); + + EndUndo(); +} + +void UndoThemeChange::Redo() +{ + BeginRedo(); + + ScDocument& rDocument = pDocShell->GetDocument(); + ScDrawLayer* pModel = rDocument.GetDrawLayer(); + SdrPage* pPage = pModel->GetPage(0); + + auto pTheme = pPage->getSdrPageProperties().GetTheme(); + if (!pTheme) + { + pTheme = std::make_shared<model::Theme>("Office"); + pPage->getSdrPageProperties().SetTheme(pTheme); + } + pTheme->setColorSet(mpNewColorSet); + + EndRedo(); +} + +void UndoThemeChange::Repeat(SfxRepeatTarget& /*rTarget*/) {} + +bool UndoThemeChange::CanRepeat(SfxRepeatTarget& /*rTarget*/) const { return false; } + +OUString UndoThemeChange::GetComment() const { return ScResId(STR_UNDO_THEME_CHANGE); } + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */