Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/tbxctrls/PaletteManager.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <svx/PaletteManager.hxx>
21
22
#include <comphelper/propertyvalue.hxx>
23
#include <tools/urlobj.hxx>
24
#include <tools/json_writer.hxx>
25
#include <osl/file.hxx>
26
#include <unotools/pathoptions.hxx>
27
#include <sfx2/objsh.hxx>
28
#include <svx/drawitem.hxx>
29
#include <svx/strings.hrc>
30
#include <svx/svxids.hrc>
31
#include <svx/dialmgr.hxx>
32
33
#include <tbxcolorupdate.hxx>
34
#include <vcl/svapp.hxx>
35
#include <vcl/settings.hxx>
36
#include <comphelper/sequence.hxx>
37
#include <officecfg/Office/Common.hxx>
38
#include <com/sun/star/frame/XDispatchProvider.hpp>
39
#include <com/sun/star/frame/XDispatch.hpp>
40
#include <com/sun/star/frame/Desktop.hpp>
41
#include <com/sun/star/util/XURLTransformer.hpp>
42
#include <com/sun/star/util/URLTransformer.hpp>
43
#include <docmodel/color/ComplexColor.hxx>
44
#include <docmodel/color/ComplexColorJSON.hxx>
45
46
#include <palettes.hxx>
47
48
#include <memory>
49
#include <array>
50
#include <stack>
51
52
PaletteManager::PaletteManager() :
53
0
    mnMaxRecentColors(Application::GetSettings().GetStyleSettings().GetColorValueSetColumnCount()),
54
0
    mnNumOfPalettes(3),
55
0
    mnCurrentPalette(0),
56
0
    mnColorCount(0),
57
0
    mpBtnUpdater(nullptr),
58
0
    maColorSelectFunction(PaletteManager::DispatchColorCommand)
59
60
0
{
61
0
    SfxObjectShell* pDocSh = SfxObjectShell::Current();
62
0
    if(pDocSh)
63
0
    {
64
0
        if (const SvxColorListItem* pItem = pDocSh->GetItem(SID_COLOR_TABLE))
65
0
            mpColorList = pItem->GetColorList();
66
0
    }
67
0
    if(!mpColorList.is())
68
0
        mpColorList = XColorList::CreateStdColorList();
69
0
    LoadPalettes();
70
0
    mnNumOfPalettes += m_Palettes.size();
71
0
}
72
73
PaletteManager::~PaletteManager()
74
0
{
75
0
}
76
77
void PaletteManager::LoadPalettes()
78
0
{
79
0
    m_Palettes.clear();
80
0
    OUString aPalPaths = SvtPathOptions().GetPalettePath();
81
82
0
    std::stack<OUString> aDirs;
83
0
    sal_Int32 nIndex = 0;
84
0
    do
85
0
    {
86
0
        aDirs.push(aPalPaths.getToken(0, ';', nIndex));
87
0
    }
88
0
    while (nIndex >= 0);
89
90
0
    std::set<OUString> aNames;
91
    //try all entries palette path list user first, then
92
    //system, ignoring duplicate file names
93
0
    while (!aDirs.empty())
94
0
    {
95
0
        OUString aPalPath = aDirs.top();
96
0
        aDirs.pop();
97
98
0
        osl::Directory aDir(aPalPath);
99
0
        osl::DirectoryItem aDirItem;
100
0
        osl::FileStatus aFileStat( osl_FileStatus_Mask_FileName |
101
0
                                   osl_FileStatus_Mask_FileURL  |
102
0
                                   osl_FileStatus_Mask_Type     );
103
0
        if( aDir.open() == osl::FileBase::E_None )
104
0
        {
105
0
            while( aDir.getNextItem(aDirItem) == osl::FileBase::E_None )
106
0
            {
107
0
                aDirItem.getFileStatus(aFileStat);
108
0
                if(aFileStat.isRegular() || aFileStat.isLink())
109
0
                {
110
0
                    OUString aFName = aFileStat.getFileName();
111
0
                    INetURLObject aURLObj( aFileStat.getFileURL() );
112
0
                    OUString aFNameWithoutExt = aURLObj.GetBase();
113
0
                    if (aNames.find(aFName) == aNames.end())
114
0
                    {
115
0
                        std::unique_ptr<Palette> pPalette;
116
0
                        if( aFName.endsWithIgnoreAsciiCase(".gpl") )
117
0
                            pPalette.reset(new PaletteGPL(aFileStat.getFileURL(), aFNameWithoutExt));
118
0
                        else if( aFName.endsWithIgnoreAsciiCase(".soc") )
119
0
                        {
120
0
                            if (aFNameWithoutExt == "standard")
121
0
                                aFNameWithoutExt = SvxResId(RID_SVXSTR_COLOR_PALETTE_STANDARD);
122
0
                            else if (aFNameWithoutExt == "tonal")
123
0
                                aFNameWithoutExt = SvxResId(RID_SVXSTR_COLOR_PALETTE_TONAL);
124
0
                            else if (aFNameWithoutExt == "html")
125
0
                                aFNameWithoutExt = SvxResId(RID_SVXSTR_COLOR_PALETTE_HTML);
126
0
                            else if (aFNameWithoutExt == "chart-palettes")
127
0
                                aFNameWithoutExt = SvxResId(RID_SVXSTR_COLOR_PALETTE_CHARTPALETTES);
128
0
                            else if (aFNameWithoutExt == "compatibility")
129
0
                                aFNameWithoutExt = SvxResId(RID_SVXSTR_COLOR_PALETTE_COMPATIBILITY);
130
0
                            else if (aFNameWithoutExt == "material")
131
0
                                aFNameWithoutExt = SvxResId(RID_SVXSTR_COLOR_PALETTE_MATERIAL);
132
0
                            else if (aFNameWithoutExt == "libreoffice")
133
0
                                aFNameWithoutExt = "LibreOffice";
134
0
                            else if (aFNameWithoutExt == "freecolour-hlc")
135
0
                                aFNameWithoutExt = SvxResId(RID_SVXSTR_COLOR_PALETTE_FREECOLOURHLC);
136
0
                            pPalette.reset(new PaletteSOC(aFileStat.getFileURL(), aFNameWithoutExt));
137
0
                        }
138
0
                        else if ( aFName.endsWithIgnoreAsciiCase(".ase") )
139
0
                            pPalette.reset(new PaletteASE(aFileStat.getFileURL(), aFNameWithoutExt));
140
141
0
                        if( pPalette && pPalette->IsValid() )
142
0
                            m_Palettes.push_back( std::move(pPalette) );
143
144
0
                        aNames.insert(aFNameWithoutExt);
145
0
                    }
146
0
                }
147
0
            }
148
0
        }
149
0
    }
150
0
}
151
152
bool PaletteManager::IsThemePaletteSelected() const
153
0
{
154
0
    return mnCurrentPalette == mnNumOfPalettes - 2;
155
0
}
156
157
bool PaletteManager::GetThemeAndEffectIndex(sal_uInt16 nItemId, sal_uInt16& rThemeIndex, sal_uInt16& rEffectIndex)
158
0
{
159
    // tdf#157034, nItemId begins with 1 but list of themes begin with 0
160
    // so decrement nItemId
161
0
    --nItemId;
162
163
    // Each column is the same color with different effects.
164
0
    rThemeIndex = nItemId % 12;
165
166
0
    rEffectIndex = nItemId / 12;
167
0
    if (rEffectIndex > 5)
168
0
        return false;
169
0
    return true;
170
0
}
171
172
bool PaletteManager::GetLumModOff(sal_uInt16 nThemeIndex, sal_uInt16 nEffect, sal_Int16& rLumMod, sal_Int16& rLumOff)
173
0
{
174
0
    if (!moThemePaletteCollection)
175
0
        return false;
176
177
0
    auto const& aThemeColorData = moThemePaletteCollection->maColors[nThemeIndex];
178
179
0
    rLumMod = aThemeColorData.getLumMod(nEffect);
180
0
    rLumOff = aThemeColorData.getLumOff(nEffect);
181
182
0
    return true;
183
0
}
184
185
void PaletteManager::ReloadColorSet(SvxColorValueSet &rColorSet)
186
0
{
187
0
    moThemePaletteCollection.reset();
188
0
    if( mnCurrentPalette == 0)
189
0
    {
190
0
        rColorSet.Clear();
191
0
        css::uno::Sequence< sal_Int32 > CustomColorList( officecfg::Office::Common::UserColors::CustomColor::get() );
192
0
        css::uno::Sequence< OUString > CustomColorNameList( officecfg::Office::Common::UserColors::CustomColorName::get() );
193
0
        int nIx = 1;
194
0
        for (int i = 0; i < CustomColorList.getLength(); ++i)
195
0
        {
196
0
            Color aColor(ColorTransparency, CustomColorList[i]);
197
0
            rColorSet.InsertItem(nIx, aColor, CustomColorNameList[i]);
198
0
            ++nIx;
199
0
        }
200
0
    }
201
0
    else if (IsThemePaletteSelected())
202
0
    {
203
0
        SfxObjectShell* pObjectShell = SfxObjectShell::Current();
204
0
        if (pObjectShell)
205
0
        {
206
0
            auto pColorSet = pObjectShell->GetThemeColors();
207
0
            mnColorCount = 12;
208
0
            rColorSet.Clear();
209
0
            sal_uInt16 nItemId = 1;
210
211
0
            if (!pColorSet)
212
0
                return;
213
214
0
            svx::ThemeColorPaletteManager aThemeColorManager(pColorSet);
215
0
            moThemePaletteCollection = aThemeColorManager.generate();
216
217
            // Each row is one effect type (no effect + each type).
218
0
            for (size_t nEffect : {0, 1, 2, 3, 4, 5})
219
0
            {
220
                // Each column is one color type.
221
0
                for (auto const& rColorData : moThemePaletteCollection->maColors)
222
0
                {
223
0
                    auto const& rEffect = rColorData.maEffects[nEffect];
224
0
                    rColorSet.InsertItem(nItemId++, rEffect.maColor, rEffect.maColorName);
225
0
                }
226
0
            }
227
0
        }
228
0
    }
229
0
    else if( mnCurrentPalette == mnNumOfPalettes - 1 )
230
0
    {
231
        // Add doc colors to palette
232
0
        SfxObjectShell* pDocSh = SfxObjectShell::Current();
233
0
        if (pDocSh)
234
0
        {
235
0
            std::set<Color> aColors = pDocSh->GetDocColors();
236
0
            mnColorCount = aColors.size();
237
0
            rColorSet.Clear();
238
0
            const OUString sNamePrefix = SvxResId(RID_SVXSTR_DOC_COLOR_PREFIX) + u" ";
239
0
            sal_uInt32 nIndex = 1;
240
0
            for(const auto& rColor : aColors)
241
0
            {
242
0
                rColorSet.InsertItem(nIndex, rColor, sNamePrefix + OUString::number(nIndex));
243
0
                nIndex++;
244
0
            }
245
0
        }
246
0
    }
247
0
    else
248
0
    {
249
0
        m_Palettes[mnCurrentPalette - 1]->LoadColorSet( rColorSet );
250
0
        mnColorCount = rColorSet.GetItemCount();
251
0
    }
252
0
}
253
254
void PaletteManager::ReloadRecentColorSet(SvxColorValueSet& rColorSet)
255
0
{
256
0
    maRecentColors.clear();
257
0
    rColorSet.Clear();
258
0
    css::uno::Sequence< sal_Int32 > Colorlist(officecfg::Office::Common::UserColors::RecentColor::get());
259
0
    css::uno::Sequence< OUString > ColorNamelist(officecfg::Office::Common::UserColors::RecentColorName::get());
260
0
    int nIx = 1;
261
0
    const bool bHasColorNames = Colorlist.getLength() == ColorNamelist.getLength();
262
0
    for (int i = 0; i < Colorlist.getLength(); ++i)
263
0
    {
264
0
        Color aColor(ColorTransparency, Colorlist[i]);
265
0
        OUString sColorName = bHasColorNames ? ColorNamelist[i] : ("#" + aColor.AsRGBHexString().toAsciiUpperCase());
266
0
        maRecentColors.emplace_back(aColor, sColorName);
267
0
        rColorSet.InsertItem(nIx, aColor, sColorName);
268
0
        ++nIx;
269
0
    }
270
0
}
271
272
std::vector<OUString> PaletteManager::GetPaletteList()
273
0
{
274
0
    std::vector<OUString> aPaletteNames
275
0
    {
276
0
        SvxResId( RID_SVXSTR_CUSTOM_PAL )
277
0
    };
278
0
    for (auto const& it : m_Palettes)
279
0
    {
280
0
        aPaletteNames.push_back( (*it).GetName() );
281
0
    }
282
0
    aPaletteNames.push_back(SvxResId(RID_SVXSTR_THEME_COLORS));
283
0
    aPaletteNames.push_back( SvxResId ( RID_SVXSTR_DOC_COLORS ) );
284
285
0
    return aPaletteNames;
286
0
}
287
288
void PaletteManager::SetPalette(sal_Int32 nPos, bool bPosOnly)
289
0
{
290
0
    mnCurrentPalette = nPos;
291
0
    if (bPosOnly)
292
0
        return;
293
0
    if( nPos != mnNumOfPalettes - 1 && nPos != 0)
294
0
    {
295
0
        mpColorList = XPropertyList::AsColorList(
296
0
                            XPropertyList::CreatePropertyListFromURL(
297
0
                            XPropertyListType::Color, GetSelectedPalettePath()));
298
0
        auto name = GetPaletteName(); // may change pColorList
299
0
        mpColorList->SetName(name);
300
0
        if(mpColorList->Load())
301
0
        {
302
0
            SfxObjectShell* pShell = SfxObjectShell::Current();
303
0
            if (pShell != nullptr)
304
0
            {
305
0
                SvxColorListItem aColorItem(mpColorList, SID_COLOR_TABLE);
306
0
                pShell->PutItem( aColorItem );
307
0
            }
308
0
        }
309
0
    }
310
0
    OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get());
311
0
    if (aPaletteName != GetPaletteName())
312
0
    {
313
0
        std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
314
0
        officecfg::Office::Common::UserColors::PaletteName::set(GetPaletteName(), batch);
315
0
        batch->commit();
316
0
    }
317
0
}
318
319
sal_Int32 PaletteManager::GetPalette() const
320
0
{
321
0
    return mnCurrentPalette;
322
0
}
323
324
OUString PaletteManager::GetPaletteName()
325
0
{
326
0
    std::vector<OUString> aNames(GetPaletteList());
327
0
    if(mnCurrentPalette != mnNumOfPalettes - 1 && mnCurrentPalette != 0)
328
0
    {
329
0
        SfxObjectShell* pDocSh = SfxObjectShell::Current();
330
0
        if(pDocSh)
331
0
        {
332
0
            if (const SvxColorListItem* pItem = pDocSh->GetItem(SID_COLOR_TABLE))
333
0
                mpColorList = pItem->GetColorList();
334
0
        }
335
0
    }
336
0
    return aNames[mnCurrentPalette];
337
0
}
338
339
const OUString & PaletteManager::GetSelectedPalettePath()
340
0
{
341
0
    auto nPalettesIndex = mnCurrentPalette - 1;
342
0
    if (nPalettesIndex >= 0 && o3tl::make_unsigned(nPalettesIndex) < m_Palettes.size())
343
0
        return m_Palettes[nPalettesIndex]->GetPath();
344
0
    else
345
0
        return EMPTY_OUSTRING;
346
0
}
347
348
tools::Long PaletteManager::GetColorCount() const
349
0
{
350
0
    return mnColorCount;
351
0
}
352
353
tools::Long PaletteManager::GetRecentColorCount() const
354
0
{
355
0
    return maRecentColors.size();
356
0
}
357
358
void PaletteManager::AddRecentColor(const Color& rRecentColor, const OUString& rName, bool bFront)
359
0
{
360
0
    auto itColor = std::find_if(maRecentColors.begin(),
361
0
                                maRecentColors.end(),
362
0
                                [rRecentColor] (const NamedColor &aColor) { return aColor.m_aColor == rRecentColor; });
363
    // if recent color to be added is already in list, remove it
364
0
    if( itColor != maRecentColors.end() )
365
0
        maRecentColors.erase( itColor );
366
367
0
    if (maRecentColors.size() == mnMaxRecentColors)
368
0
        maRecentColors.pop_back();
369
0
    if (bFront)
370
0
        maRecentColors.emplace_front(rRecentColor, rName);
371
0
    else
372
0
        maRecentColors.emplace_back(rRecentColor, rName);
373
0
    css::uno::Sequence< sal_Int32 > aColorList(maRecentColors.size());
374
0
    auto aColorListRange = asNonConstRange(aColorList);
375
0
    css::uno::Sequence< OUString > aColorNameList(maRecentColors.size());
376
0
    auto aColorNameListRange = asNonConstRange(aColorNameList);
377
0
    for (size_t i = 0; i < maRecentColors.size(); ++i)
378
0
    {
379
0
        aColorListRange[i] = static_cast<sal_Int32>(maRecentColors[i].m_aColor);
380
0
        aColorNameListRange[i] = maRecentColors[i].m_aName;
381
0
    }
382
0
    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
383
0
    officecfg::Office::Common::UserColors::RecentColor::set(aColorList, batch);
384
0
    officecfg::Office::Common::UserColors::RecentColorName::set(aColorNameList, batch);
385
0
    batch->commit();
386
0
}
387
388
void PaletteManager::SetSplitButtonColor(const NamedColor& rColor)
389
0
{
390
0
    if (mpBtnUpdater)
391
0
        mpBtnUpdater->SetRecentColor(rColor);
392
0
}
393
394
void PaletteManager::SetBtnUpdater(svx::ToolboxButtonColorUpdaterBase* pBtnUpdater)
395
0
{
396
0
    mpBtnUpdater = pBtnUpdater;
397
0
}
398
399
void PaletteManager::SetColorSelectFunction(const ColorSelectFunction& aColorSelectFunction)
400
0
{
401
0
    maColorSelectFunction = aColorSelectFunction;
402
0
}
403
404
void PaletteManager::PopupColorPicker(weld::Window* pParent, const OUString& aCommand, const Color& rInitialColor)
405
0
{
406
    // The calling object goes away during aColorDlg.Execute(), so we must copy this
407
0
    OUString aCommandCopy = aCommand;
408
0
    m_pColorDlg = std::make_unique<ColorDialog>(pParent, vcl::ColorPickerMode::Modify);
409
0
    m_pColorDlg->SetColor(rInitialColor);
410
0
    std::shared_ptr<PaletteManager> xSelf(shared_from_this());
411
0
    m_pColorDlg->ExecuteAsync([xSelf=std::move(xSelf),
412
0
                               aCommandCopy=std::move(aCommandCopy)] (sal_Int32 nResult) {
413
0
        if (nResult == RET_OK)
414
0
        {
415
0
            Color aLastColor = xSelf->m_pColorDlg->GetColor();
416
0
            OUString sColorName = "#" + aLastColor.AsRGBHexString().toAsciiUpperCase();
417
0
            NamedColor aNamedColor(aLastColor, sColorName);
418
0
            xSelf->SetSplitButtonColor(aNamedColor);
419
0
            xSelf->AddRecentColor(aLastColor, sColorName);
420
0
            xSelf->maColorSelectFunction(aCommandCopy, aNamedColor);
421
0
        }
422
0
    });
423
0
}
424
425
void PaletteManager::DispatchColorCommand(const OUString& aCommand, const NamedColor& rColor)
426
0
{
427
0
    using namespace css;
428
0
    using namespace css::uno;
429
0
    using namespace css::frame;
430
0
    using namespace css::beans;
431
0
    using namespace css::util;
432
433
0
    const Reference<XComponentContext>& xContext(comphelper::getProcessComponentContext());
434
0
    Reference<XDesktop2> xDesktop = Desktop::create(xContext);
435
0
    Reference<XFrame> xFrame(xDesktop->getCurrentFrame());
436
0
    Reference<XDispatchProvider> xDispatchProvider(xFrame, UNO_QUERY);
437
0
    if (!xDispatchProvider.is())
438
0
        return;
439
440
0
    INetURLObject aObj( aCommand );
441
442
0
    std::vector<PropertyValue> aArgs{
443
0
        comphelper::makePropertyValue(aObj.GetURLPath()+ ".Color", sal_Int32(rColor.m_aColor)),
444
0
    };
445
446
0
    if (rColor.m_nThemeIndex != -1)
447
0
    {
448
0
        model::ComplexColor aComplexColor;
449
0
        aComplexColor.setThemeColor(model::convertToThemeColorType(rColor.m_nThemeIndex));
450
0
        if (rColor.m_nLumMod != 10000)
451
0
            aComplexColor.addTransformation({model::TransformationType::LumMod, rColor.m_nLumMod});
452
0
        if (rColor.m_nLumMod != 0)
453
0
            aComplexColor.addTransformation({model::TransformationType::LumOff, rColor.m_nLumOff});
454
455
0
        uno::Any aAny;
456
0
        aAny <<= OStringToOUString(model::color::convertToJSON(aComplexColor), RTL_TEXTENCODING_UTF8);
457
458
0
        aArgs.push_back(comphelper::makePropertyValue(aObj.GetURLPath() + ".ComplexColorJSON", aAny));
459
0
    }
460
461
0
    URL aTargetURL;
462
0
    aTargetURL.Complete = aCommand;
463
0
    Reference<XURLTransformer> xURLTransformer(URLTransformer::create(comphelper::getProcessComponentContext()));
464
0
    xURLTransformer->parseStrict(aTargetURL);
465
466
0
    Reference<XDispatch> xDispatch = xDispatchProvider->queryDispatch(aTargetURL, OUString(), 0);
467
0
    if (xDispatch.is())
468
0
    {
469
0
        xDispatch->dispatch(aTargetURL, comphelper::containerToSequence(aArgs));
470
0
        if (xFrame->getContainerWindow().is())
471
0
            xFrame->getContainerWindow()->setFocus();
472
0
    }
473
0
}
474
475
void PaletteManager::generateColorNamesJSON(tools::JsonWriter& aTree)
476
0
{
477
0
    XColorListRef xUserColorList;
478
0
    OUString aPaletteStandard = SvxResId(RID_SVXSTR_COLOR_PALETTE_STANDARD);
479
0
    PaletteManager aPaletteManager;
480
0
    std::vector<OUString> aPaletteNames = aPaletteManager.GetPaletteList();
481
0
    for (size_t i = 0, nLen = aPaletteNames.size(); i < nLen; ++i)
482
0
    {
483
0
        if (aPaletteStandard == aPaletteNames[i])
484
0
        {
485
0
            aPaletteManager.SetPalette(i);
486
0
            xUserColorList
487
0
                = XPropertyList::AsColorList(XPropertyList::CreatePropertyListFromURL(
488
0
                    XPropertyListType::Color, aPaletteManager.GetSelectedPalettePath()));
489
0
            if (!xUserColorList->Load())
490
0
                xUserColorList = nullptr;
491
0
            break;
492
0
        }
493
0
    }
494
0
    if (xUserColorList)
495
0
    {
496
0
        auto colorNames = aTree.startArray("ColorNames");
497
0
        int nCount = xUserColorList->Count();
498
499
0
        for (int i = 0; i < nCount; i++)
500
0
        {
501
0
            XColorEntry* pColorEntry = xUserColorList->GetColor(i);
502
0
            if (pColorEntry)
503
0
            {
504
0
                auto aColorTree = aTree.startStruct();
505
0
                aTree.put("hexCode", pColorEntry->GetColor().AsRGBHEXString());
506
0
                aTree.put("name", pColorEntry->GetName());
507
0
            }
508
0
        }
509
0
    }
510
0
}
511
512
// TODO: make it generic, send any palette
513
void PaletteManager::generateJSON(tools::JsonWriter& aTree, const std::set<Color>& rColors)
514
0
{
515
0
    auto aColorListTree = aTree.startArray("DocumentColors");
516
0
    sal_uInt32 nStartIndex = 1;
517
518
0
    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
519
0
    sal_uInt32 nColumnCount = rStyleSettings.GetColorValueSetColumnCount();
520
0
    const OUString aNamePrefix(Concat2View(SvxResId(RID_SVXSTR_DOC_COLOR_PREFIX) + " "));
521
522
0
    auto aColorIt = rColors.begin();
523
0
    while (aColorIt != rColors.end())
524
0
    {
525
0
        auto aColorRowTree = aTree.startAnonArray();
526
527
0
        for (sal_uInt32 nColumn = 0; nColumn < nColumnCount; nColumn++)
528
0
        {
529
0
            auto aColorTree = aTree.startStruct();
530
0
            OUString sName = aNamePrefix + OUString::number(nStartIndex++);
531
0
            aTree.put("Value", aColorIt->AsRGBHexString().toUtf8());
532
0
            aTree.put("Name", sName);
533
534
0
            aColorIt++;
535
0
            if (aColorIt == rColors.end())
536
0
                break;
537
0
        }
538
0
    }
539
0
}
540
541
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */