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: */

Reply via email to