diff options
Diffstat (limited to 'sc/source/ui/theme')
-rw-r--r-- | sc/source/ui/theme/ThemeColorChanger.cxx | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/sc/source/ui/theme/ThemeColorChanger.cxx b/sc/source/ui/theme/ThemeColorChanger.cxx new file mode 100644 index 0000000000..c9b88652dc --- /dev/null +++ b/sc/source/ui/theme/ThemeColorChanger.cxx @@ -0,0 +1,359 @@ +/* -*- 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 <sal/config.h> + +#include <docmodel/uno/UnoComplexColor.hxx> +#include <docmodel/theme/Theme.hxx> +#include <editeng/colritem.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/borderline.hxx> +#include <svx/svditer.hxx> +#include <svx/theme/ThemeColorChangerCommon.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 <docfunc.hxx> +#include <tabvwsh.hxx> +#include <undostyl.hxx> +#include <undoblk.hxx> +#include <SparklineGroup.hxx> +#include <SparklineList.hxx> + +#include <undo/UndoThemeChange.hxx> + +namespace sc +{ +ThemeColorChanger::ThemeColorChanger(ScDocShell& rDocShell) + : m_rDocShell(rDocShell) +{ +} + +ThemeColorChanger::~ThemeColorChanger() = default; + +namespace +{ +bool changeBorderLine(editeng::SvxBorderLine* pBorderLine, model::ColorSet const& rColorSet) +{ + if (!pBorderLine) + return false; + + model::ComplexColor const& rComplexColor = pBorderLine->getComplexColor(); + if (rComplexColor.isValidThemeType()) + { + Color aColor = rColorSet.resolveColor(rComplexColor); + pBorderLine->SetColor(aColor); + return true; + } + return false; +} + +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); + model::ComplexColor const& rComplexColor = pColorItem->getComplexColor(); + if (rComplexColor.isValidThemeType()) + { + Color aColor = rColorSet.resolveColor(rComplexColor); + + SvxColorItem aColorItem(*pColorItem); + aColorItem.setColor(aColor); + rItemSet.Put(aColorItem); + bChanged = true; + } + } + if (rItemSet.HasItem(ATTR_BACKGROUND, &pItem)) + { + auto const* pBrushItem = static_cast<const SvxBrushItem*>(pItem); + model::ComplexColor const& rComplexColor = pBrushItem->getComplexColor(); + if (rComplexColor.isValidThemeType()) + { + Color aColor = rColorSet.resolveColor(rComplexColor); + + SvxBrushItem aNewBrushItem(*pBrushItem); + aNewBrushItem.SetColor(aColor); + rItemSet.Put(aNewBrushItem); + bChanged = true; + } + } + if (rItemSet.HasItem(ATTR_BORDER, &pItem)) + { + auto const* pBoxItem = static_cast<const SvxBoxItem*>(pItem); + SvxBoxItem rNewItem(*pBoxItem); + bool bLineChanged = false; + + 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 (bLineChanged) + { + rItemSet.Put(rNewItem); + bChanged = true; + } + } + return bChanged; +} + +bool changeStyles(ScDocShell& rDocShell, model::ColorSet const& rColorSet) +{ + ScDocument& rDocument = rDocShell.GetDocument(); + ScStyleSheetPool* pPool = rDocument.GetStyleSheetPool(); + ScStyleSheet* pStyle = nullptr; + bool bChanged = false; + + // Paragraph style color change + pStyle = static_cast<ScStyleSheet*>(pPool->First(SfxStyleFamily::Para)); + while (pStyle) + { + ScStyleSaveData aOldData; + aOldData.InitFromStyle(pStyle); + + auto rItemSet = pStyle->GetItemSet(); + if (changeCellItems(rItemSet, rColorSet)) + { + 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, ScTabViewShell* pViewShell, ScDrawLayer* pModel, + model::ColorSet const& rColorSet) +{ + 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)) + { + if (!pPattern || !pPattern->IsVisible()) + continue; + + ScPatternAttr aNewPattern(*pPattern); + auto& rItemSet = aNewPattern.GetItemSet(); + bool bItemChanged = changeCellItems(rItemSet, rColorSet); + 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 + { + pModel->BeginCalcUndo(true); + SdrView* pView = nullptr; + if (pViewShell) + pView = pViewShell->GetScDrawView(); + + SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); + SdrObjListIter aIter(pPage, SdrIterMode::DeepNoGroups); + for (SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next()) + { + svx::theme::updateSdrObject(rColorSet, pObject, pView, rDocShell.GetUndoManager()); + } + + std::unique_ptr<SdrUndoGroup> pUndo = pModel->GetCalcUndo(); + + if (pUndo) + { + bChanged = true; + auto pUndoDraw = std::make_unique<ScUndoDraw>(std::move(pUndo), &rDocShell); + rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndoDraw)); + } + } + } + + return bChanged; +} + +model::ComplexColor modifyComplexColor(model::ComplexColor const& rComplexColor, + model::ColorSet const& rColorSet) +{ + model::ComplexColor aComplexColor(rComplexColor); + + if (aComplexColor.isValidThemeType()) + { + Color aColor = rColorSet.resolveColor(aComplexColor); + aComplexColor.setFinalColor(aColor); + } + return aComplexColor; +} + +void changeSparklines(ScDocShell& rDocShell, model::ColorSet const& rColorSet) +{ + ScDocument& rDocument = rDocShell.GetDocument(); + auto& rDocFunc = rDocShell.GetDocFunc(); + for (SCTAB nTab = 0; nTab < rDocument.GetTableCount(); ++nTab) + { + auto* pSparklineList = rDocument.GetSparklineList(nTab); + if (pSparklineList && !pSparklineList->getSparklineGroups().empty()) + { + auto const& rSparklineGroups = pSparklineList->getSparklineGroups(); + for (auto const& rSparklineGroup : rSparklineGroups) + { + auto aAttributes = rSparklineGroup->getAttributes(); + + aAttributes.setColorAxis(modifyComplexColor(aAttributes.getColorAxis(), rColorSet)); + aAttributes.setColorSeries( + modifyComplexColor(aAttributes.getColorSeries(), rColorSet)); + aAttributes.setColorNegative( + modifyComplexColor(aAttributes.getColorNegative(), rColorSet)); + aAttributes.setColorMarkers( + modifyComplexColor(aAttributes.getColorMarkers(), rColorSet)); + aAttributes.setColorHigh(modifyComplexColor(aAttributes.getColorHigh(), rColorSet)); + aAttributes.setColorLow(modifyComplexColor(aAttributes.getColorLow(), rColorSet)); + aAttributes.setColorFirst( + modifyComplexColor(aAttributes.getColorFirst(), rColorSet)); + aAttributes.setColorLast(modifyComplexColor(aAttributes.getColorLast(), rColorSet)); + rDocFunc.ChangeSparklineGroupAttributes(rSparklineGroup, aAttributes); + } + } + } +} + +std::shared_ptr<model::Theme> getTheme(ScDocShell& rDocShell) +{ + ScDrawLayer* pModel = rDocShell.GetDocument().GetDrawLayer(); + + auto pTheme = pModel->getTheme(); + if (!pTheme) + { + pTheme = std::make_shared<model::Theme>("Office"); + pModel->setTheme(pTheme); + } + return pTheme; +} + +void changeThemeColorInTheDocModel(ScDocShell& rDocShell, + std::shared_ptr<model::ColorSet> const& pColorSet) +{ + auto pTheme = getTheme(rDocShell); + std::shared_ptr<model::ColorSet> pNewColorSet = pColorSet; + std::shared_ptr<model::ColorSet> pOldColorSet = pTheme->getColorSet(); + pTheme->setColorSet(pNewColorSet); + + ScDocument& rDocument = rDocShell.GetDocument(); + 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) +{ + // Can't change to an empty color set + if (!pColorSet) + return; + + m_rDocShell.MakeDrawLayer(); + + ScDocShellModificator aModificator(m_rDocShell); + ScDocument& rDocument = m_rDocShell.GetDocument(); + auto pUndoManager = m_rDocShell.GetUndoManager(); + + const bool bUndo(rDocument.IsUndoEnabled()); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + ViewShellId nViewShellId(-1); + if (pViewShell) + nViewShellId = pViewShell->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, pViewShell, rDocument.GetDrawLayer(), *pColorSet) || bChanged; + changeSparklines(m_rDocShell, *pColorSet); + + changeThemeColorInTheDocModel(m_rDocShell, pColorSet); + + if (bUndo) + { + pUndoManager->LeaveListAction(); + } + + m_rDocShell.SetDrawModified(); + aModificator.SetDocumentModified(); +} + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |