/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace css; namespace sd { ThemeColorChanger::ThemeColorChanger(SdrPage* pMasterPage, sd::DrawDocShell* pDocShell) : mpMasterPage(pMasterPage) , mpDocShell(pDocShell) { } ThemeColorChanger::~ThemeColorChanger() = default; namespace { void changeThemeColors(sd::DrawDocShell* pDocShell, SdrPage* pMasterPage, std::shared_ptr const& pNewColorSet) { auto pTheme = pMasterPage->getSdrPageProperties().getTheme(); if (!pTheme) { pTheme = std::make_shared("Office"); pMasterPage->getSdrPageProperties().setTheme(pTheme); } std::shared_ptr const& pOldColorSet = pTheme->getColorSet(); auto* pUndoManager = pDocShell->GetUndoManager(); if (pUndoManager) { pUndoManager->AddUndoAction(std::make_unique( pDocShell->GetDoc(), pMasterPage, pOldColorSet, pNewColorSet)); } pTheme->setColorSet(pNewColorSet); } bool changeStyle(sd::DrawDocShell* pDocShell, SdStyleSheet* pStyle, std::shared_ptr const& pColorSet) { bool bChanged = false; auto aItemSet = pStyle->GetItemSet(); if (const XFillColorItem* pItem = aItemSet.GetItemIfSet(XATTR_FILLCOLOR, false)) { model::ComplexColor const& rComplexColor = pItem->getComplexColor(); if (rComplexColor.isValidThemeType()) { Color aNewColor = pColorSet->resolveColor(rComplexColor); std::unique_ptr pNewItem(pItem->Clone()); pNewItem->SetColorValue(aNewColor); aItemSet.Put(*pNewItem); bChanged = true; } } if (const XLineColorItem* pItem = aItemSet.GetItemIfSet(XATTR_LINECOLOR, false)) { model::ComplexColor const& rComplexColor = pItem->getComplexColor(); if (rComplexColor.isValidThemeType()) { Color aNewColor = pColorSet->resolveColor(rComplexColor); std::unique_ptr pNewItem(pItem->Clone()); pNewItem->SetColorValue(aNewColor); aItemSet.Put(*pNewItem); bChanged = true; } } if (const SvxColorItem* pItem = aItemSet.GetItemIfSet(EE_CHAR_COLOR, false)) { model::ComplexColor const& rComplexColor = pItem->getComplexColor(); if (rComplexColor.isValidThemeType()) { Color aNewColor = pColorSet->resolveColor(rComplexColor); std::unique_ptr pNewItem(pItem->Clone()); pNewItem->setColor(aNewColor); aItemSet.Put(*pNewItem); bChanged = true; } } if (bChanged) { pDocShell->GetUndoManager()->AddUndoAction( std::make_unique(pDocShell->GetDoc(), pStyle, &aItemSet)); pStyle->GetItemSet().Put(aItemSet); pStyle->Broadcast(SfxHint(SfxHintId::DataChanged)); } return bChanged; } bool changeStyles(sd::DrawDocShell* pDocShell, std::shared_ptr const& pColorSet) { bool bChanged = false; SfxStyleSheetBasePool* pPool = pDocShell->GetStyleSheetPool(); SdStyleSheet* pStyle = static_cast(pPool->First(SfxStyleFamily::Para)); while (pStyle) { bChanged = changeStyle(pDocShell, pStyle, pColorSet) || bChanged; pStyle = static_cast(pPool->Next()); } return bChanged; } } // end anonymous ns void ThemeColorChanger::apply(std::shared_ptr const& pColorSet) { auto* pUndoManager = mpDocShell->GetUndoManager(); sd::ViewShell* pViewShell = mpDocShell->GetViewShell(); if (!pViewShell) return; SdrView* pView = pViewShell->GetView(); if (!pView) return; ViewShellId nViewShellId = pViewShell->GetViewShellBase().GetViewShellId(); pUndoManager->EnterListAction(SvxResId(RID_SVXSTR_UNDO_THEME_COLOR_CHANGE), "", 0, nViewShellId); changeStyles(mpDocShell, pColorSet); SdrModel& rModel = mpMasterPage->getSdrModelFromSdrPage(); for (sal_uInt16 nPage = 0; nPage < rModel.GetPageCount(); ++nPage) { SdrPage* pCurrentPage = rModel.GetPage(nPage); // TODO - for now change all the objects regardless to which master page it belongs to. // Currently we don't have a concept of master slide with a group of layouts as in MSO, but we always only // have master pages, which aren't grouped together. In MSO the theme is defined per master slide, so when // changing a theme, all the layouts get the new theme, as layouts are synonymous to master pages in LibreOffice, // this is not possible to do and we would need to change the theme for each master page separately, which // is just annoying for the user. // if (!pCurrentPage->TRG_HasMasterPage() || &pCurrentPage->TRG_GetMasterPage() != mpMasterPage) // continue; SdrObjListIter aIter(pCurrentPage, SdrIterMode::DeepWithGroups); while (aIter.IsMore()) { svx::theme::updateSdrObject(*pColorSet, aIter.Next(), pView, pUndoManager); } } changeThemeColors(mpDocShell, mpMasterPage, pColorSet); // See the TODO comment a couple of line above for the explanation - need to change the ThemeColors for all master // pages for now, but the following code will need to be changed in the future when we have the concept similar to // master slide and layouts for (sal_uInt16 nPage = 0; nPage < rModel.GetPageCount(); ++nPage) { SdrPage* pCurrentPage = rModel.GetPage(nPage); if (pCurrentPage->IsMasterPage() && pCurrentPage != mpMasterPage) changeThemeColors(mpDocShell, pCurrentPage, pColorSet); } pUndoManager->LeaveListAction(); } } // end sd namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */