Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sc/source/ui/theme/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 11 kB image not shown  

Quelle  ThemeColorChanger.cxx   Sprache: C

 
/* -*- 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/theme/Theme.hxx>
#include <editeng/colritem.hxx>
#include <editeng/brushitem.hxx>
#include <editeng/boxitem.hxx>
#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 <docfunc.hxx>
#include <tabvwsh.hxx>
#include <undostyl.hxx>
#include <undoblk.hxx>
#include <SparklineGroup.hxx>
#include <SparklineList.hxx>
#include <sfx2/app.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 aSparklineGroups = pSparklineList->getSparklineGroups();
            for (auto const& rSparklineGroup : aSparklineGroups)
            {
                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::doApply(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);
    m_rDocShell.Broadcast(SfxHint(SfxHintId::ThemeColorsChanged));

    if (bUndo)
    {
        pUndoManager->LeaveListAction();
    }

    m_rDocShell.SetDrawModified();
    aModificator.SetDocumentModified();
}

// end sc namespace

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=93 H=93 G=92

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.