Bump version to 6.4-15
[LibreOffice.git] / svx / source / tbxctrls / PaletteManager.cxx
blob0dba161ef7fd4b0bc402882b96592dc2c76926d3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <memory>
21 #include <svx/PaletteManager.hxx>
22 #include <tools/urlobj.hxx>
23 #include <osl/file.hxx>
24 #include <unotools/pathoptions.hxx>
25 #include <sfx2/objsh.hxx>
26 #include <svx/drawitem.hxx>
27 #include <svx/strings.hrc>
28 #include <svx/svxids.hrc>
29 #include <svx/dialmgr.hxx>
30 #include <svx/tbxcolorupdate.hxx>
31 #include <vcl/toolbox.hxx>
32 #include <svtools/colrdlg.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/settings.hxx>
35 #include <stack>
36 #include <set>
37 #include <cppu/unotype.hxx>
38 #include <officecfg/Office/Common.hxx>
39 #include <com/sun/star/frame/XDispatchProvider.hpp>
40 #include <com/sun/star/frame/XDispatch.hpp>
41 #include <com/sun/star/frame/Desktop.hpp>
42 #include <com/sun/star/util/XURLTransformer.hpp>
43 #include <com/sun/star/util/URLTransformer.hpp>
45 #include <palettes.hxx>
47 PaletteManager::PaletteManager() :
48 mnMaxRecentColors(Application::GetSettings().GetStyleSettings().GetColorValueSetColumnCount()),
49 mnNumOfPalettes(2),
50 mnCurrentPalette(0),
51 mnColorCount(0),
52 mpBtnUpdater(nullptr),
53 maColorSelectFunction(PaletteManager::DispatchColorCommand),
54 m_context(comphelper::getProcessComponentContext())
56 SfxObjectShell* pDocSh = SfxObjectShell::Current();
57 if(pDocSh)
59 const SfxPoolItem* pItem = nullptr;
60 if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) )
61 pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
63 if(!pColorList.is())
64 pColorList = XColorList::CreateStdColorList();
65 LoadPalettes();
66 mnNumOfPalettes += m_Palettes.size();
70 PaletteManager::~PaletteManager()
74 void PaletteManager::LoadPalettes()
76 m_Palettes.clear();
77 OUString aPalPaths = SvtPathOptions().GetPalettePath();
79 std::stack<OUString> aDirs;
80 sal_Int32 nIndex = 0;
83 aDirs.push(aPalPaths.getToken(0, ';', nIndex));
85 while (nIndex >= 0);
87 std::set<OUString> aNames;
88 //try all entries palette path list user first, then
89 //system, ignoring duplicate file names
90 while (!aDirs.empty())
92 OUString aPalPath = aDirs.top();
93 aDirs.pop();
95 osl::Directory aDir(aPalPath);
96 osl::DirectoryItem aDirItem;
97 osl::FileStatus aFileStat( osl_FileStatus_Mask_FileName |
98 osl_FileStatus_Mask_FileURL |
99 osl_FileStatus_Mask_Type );
100 if( aDir.open() == osl::FileBase::E_None )
102 while( aDir.getNextItem(aDirItem) == osl::FileBase::E_None )
104 aDirItem.getFileStatus(aFileStat);
105 if(aFileStat.isRegular() || aFileStat.isLink())
107 OUString aFName = aFileStat.getFileName();
108 INetURLObject aURLObj( aFileStat.getFileURL() );
109 OUString aFNameWithoutExt = aURLObj.GetBase();
110 if (aNames.find(aFName) == aNames.end())
112 std::unique_ptr<Palette> pPalette;
113 if( aFName.endsWithIgnoreAsciiCase(".gpl") )
114 pPalette.reset(new PaletteGPL(aFileStat.getFileURL(), aFNameWithoutExt));
115 else if( aFName.endsWithIgnoreAsciiCase(".soc") )
116 pPalette.reset(new PaletteSOC(aFileStat.getFileURL(), aFNameWithoutExt));
117 else if ( aFName.endsWithIgnoreAsciiCase(".ase") )
118 pPalette.reset(new PaletteASE(aFileStat.getFileURL(), aFNameWithoutExt));
120 if( pPalette && pPalette->IsValid() )
121 m_Palettes.push_back( std::move(pPalette) );
122 aNames.insert(aFNameWithoutExt);
130 void PaletteManager::ReloadColorSet(SvxColorValueSet &rColorSet)
132 if( mnCurrentPalette == 0)
134 rColorSet.Clear();
135 css::uno::Sequence< sal_Int32 > CustomColorList( officecfg::Office::Common::UserColors::CustomColor::get() );
136 css::uno::Sequence< OUString > CustomColorNameList( officecfg::Office::Common::UserColors::CustomColorName::get() );
137 int nIx = 1;
138 for (int i = 0; i < CustomColorList.getLength(); ++i)
140 Color aColor(CustomColorList[i]);
141 rColorSet.InsertItem(nIx, aColor, CustomColorNameList[i]);
142 ++nIx;
145 else if( mnCurrentPalette == mnNumOfPalettes - 1 )
147 rColorSet.Clear();
148 // Add doc colors to palette
149 SfxObjectShell* pDocSh = SfxObjectShell::Current();
150 if (pDocSh)
152 std::set<Color> aColors = pDocSh->GetDocColors();
153 mnColorCount = aColors.size();
154 rColorSet.addEntriesForColorSet(aColors, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX ) + " " );
157 else
159 m_Palettes[mnCurrentPalette - 1]->LoadColorSet( rColorSet );
160 mnColorCount = rColorSet.GetItemCount();
164 void PaletteManager::ReloadColorSet(ColorValueSet &rColorSet)
166 if( mnCurrentPalette == 0)
168 rColorSet.Clear();
169 css::uno::Sequence< sal_Int32 > CustomColorList( officecfg::Office::Common::UserColors::CustomColor::get() );
170 css::uno::Sequence< OUString > CustomColorNameList( officecfg::Office::Common::UserColors::CustomColorName::get() );
171 int nIx = 1;
172 for (int i = 0; i < CustomColorList.getLength(); ++i)
174 Color aColor(CustomColorList[i]);
175 rColorSet.InsertItem(nIx, aColor, CustomColorNameList[i]);
176 ++nIx;
179 else if( mnCurrentPalette == mnNumOfPalettes - 1 )
181 // Add doc colors to palette
182 SfxObjectShell* pDocSh = SfxObjectShell::Current();
183 if (pDocSh)
185 std::set<Color> aColors = pDocSh->GetDocColors();
186 mnColorCount = aColors.size();
187 rColorSet.Clear();
188 rColorSet.addEntriesForColorSet(aColors, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX ) + " " );
191 else
193 m_Palettes[mnCurrentPalette - 1]->LoadColorSet( rColorSet );
194 mnColorCount = rColorSet.GetItemCount();
198 void PaletteManager::ReloadRecentColorSet(SvxColorValueSet& rColorSet)
200 maRecentColors.clear();
201 rColorSet.Clear();
202 css::uno::Sequence< sal_Int32 > Colorlist(officecfg::Office::Common::UserColors::RecentColor::get());
203 css::uno::Sequence< OUString > ColorNamelist(officecfg::Office::Common::UserColors::RecentColorName::get());
204 int nIx = 1;
205 const bool bHasColorNames = Colorlist.getLength() == ColorNamelist.getLength();
206 for (int i = 0; i < Colorlist.getLength(); ++i)
208 Color aColor(Colorlist[i]);
209 OUString sColorName = bHasColorNames ? ColorNamelist[i] : ("#" + aColor.AsRGBHexString().toAsciiUpperCase());
210 maRecentColors.emplace_back(aColor, sColorName);
211 rColorSet.InsertItem(nIx, aColor, sColorName);
212 ++nIx;
216 void PaletteManager::ReloadRecentColorSet(ColorValueSet& rColorSet)
218 maRecentColors.clear();
219 rColorSet.Clear();
220 css::uno::Sequence< sal_Int32 > Colorlist(officecfg::Office::Common::UserColors::RecentColor::get());
221 css::uno::Sequence< OUString > ColorNamelist(officecfg::Office::Common::UserColors::RecentColorName::get());
222 int nIx = 1;
223 const bool bHasColorNames = Colorlist.getLength() == ColorNamelist.getLength();
224 for (int i = 0; i < Colorlist.getLength(); ++i)
226 Color aColor(Colorlist[i]);
227 OUString sColorName = bHasColorNames ? ColorNamelist[i] : ("#" + aColor.AsRGBHexString().toAsciiUpperCase());
228 maRecentColors.emplace_back(aColor, sColorName);
229 rColorSet.InsertItem(nIx, aColor, sColorName);
230 ++nIx;
234 std::vector<OUString> PaletteManager::GetPaletteList()
236 std::vector<OUString> aPaletteNames;
238 aPaletteNames.push_back( SvxResId( RID_SVXSTR_CUSTOM_PAL ) );
239 for (auto const& it : m_Palettes)
241 aPaletteNames.push_back( (*it).GetName() );
243 aPaletteNames.push_back( SvxResId ( RID_SVXSTR_DOC_COLORS ) );
245 return aPaletteNames;
248 void PaletteManager::SetPalette( sal_Int32 nPos )
250 mnCurrentPalette = nPos;
251 if( nPos != mnNumOfPalettes - 1 && nPos != 0)
253 pColorList = XPropertyList::AsColorList(
254 XPropertyList::CreatePropertyListFromURL(
255 XPropertyListType::Color, GetSelectedPalettePath()));
256 auto name = GetPaletteName(); // may change pColorList
257 pColorList->SetName(name);
258 if(pColorList->Load())
260 SfxObjectShell* pShell = SfxObjectShell::Current();
261 if (pShell != nullptr)
263 SvxColorListItem aColorItem(pColorList, SID_COLOR_TABLE);
264 pShell->PutItem( aColorItem );
268 OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get());
269 if (aPaletteName != GetPaletteName())
271 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
272 officecfg::Office::Common::UserColors::PaletteName::set(GetPaletteName(), batch);
273 batch->commit();
277 sal_Int32 PaletteManager::GetPalette() const
279 return mnCurrentPalette;
282 OUString PaletteManager::GetPaletteName()
284 std::vector<OUString> aNames(GetPaletteList());
285 if(mnCurrentPalette != mnNumOfPalettes - 1 && mnCurrentPalette != 0)
287 SfxObjectShell* pDocSh = SfxObjectShell::Current();
288 if(pDocSh)
290 const SfxPoolItem* pItem = nullptr;
291 if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) )
292 pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
295 return aNames[mnCurrentPalette];
298 OUString PaletteManager::GetSelectedPalettePath()
300 if(mnCurrentPalette != mnNumOfPalettes - 1 && mnCurrentPalette != 0)
301 return m_Palettes[mnCurrentPalette - 1]->GetPath();
302 else
303 return OUString();
306 long PaletteManager::GetColorCount() const
308 return mnColorCount;
311 long PaletteManager::GetRecentColorCount() const
313 return maRecentColors.size();
316 void PaletteManager::AddRecentColor(const Color& rRecentColor, const OUString& rName, bool bFront)
318 auto itColor = std::find_if(maRecentColors.begin(),
319 maRecentColors.end(),
320 [rRecentColor] (const NamedColor &a) { return a.first == rRecentColor; });
321 // if recent color to be added is already in list, remove it
322 if( itColor != maRecentColors.end() )
323 maRecentColors.erase( itColor );
325 if (maRecentColors.size() == mnMaxRecentColors)
326 maRecentColors.pop_back();
327 if (bFront)
328 maRecentColors.push_front(std::make_pair(rRecentColor, rName));
329 else
330 maRecentColors.emplace_back(rRecentColor, rName);
331 css::uno::Sequence< sal_Int32 > aColorList(maRecentColors.size());
332 css::uno::Sequence< OUString > aColorNameList(maRecentColors.size());
333 for (size_t i = 0; i < maRecentColors.size(); ++i)
335 aColorList[i] = static_cast<sal_Int32>(maRecentColors[i].first);
336 aColorNameList[i] = maRecentColors[i].second;
338 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
339 officecfg::Office::Common::UserColors::RecentColor::set(aColorList, batch);
340 officecfg::Office::Common::UserColors::RecentColorName::set(aColorNameList, batch);
341 batch->commit();
344 void PaletteManager::SetBtnUpdater(svx::ToolboxButtonColorUpdater* pBtnUpdater)
346 mpBtnUpdater = pBtnUpdater;
349 void PaletteManager::SetColorSelectFunction(const std::function<void(const OUString&, const NamedColor&)>& aColorSelectFunction)
351 maColorSelectFunction = aColorSelectFunction;
354 void PaletteManager::PopupColorPicker(weld::Window* pParent, const OUString& aCommand, const Color& rInitialColor)
356 // The calling object goes away during aColorDlg.Execute(), so we must copy this
357 OUString aCommandCopy = aCommand;
358 SvColorDialog aColorDlg;
359 aColorDlg.SetColor(rInitialColor);
360 aColorDlg.SetMode(svtools::ColorPickerMode::Modify);
361 if (aColorDlg.Execute(pParent) == RET_OK)
363 Color aLastColor = aColorDlg.GetColor();
364 OUString sColorName = "#" + aLastColor.AsRGBHexString().toAsciiUpperCase();
365 NamedColor aNamedColor = std::make_pair(aLastColor, sColorName);
366 if (mpBtnUpdater)
367 mpBtnUpdater->Update(aNamedColor);
368 AddRecentColor(aLastColor, sColorName);
369 maColorSelectFunction(aCommandCopy, aNamedColor);
373 void PaletteManager::DispatchColorCommand(const OUString& aCommand, const NamedColor& rColor)
375 using namespace css::uno;
376 using namespace css::frame;
377 using namespace css::beans;
378 using namespace css::util;
380 Reference<XComponentContext> xContext(comphelper::getProcessComponentContext());
381 Reference<XDesktop2> xDesktop = Desktop::create(xContext);
382 Reference<XFrame> xFrame(xDesktop->getCurrentFrame());
383 Reference<XDispatchProvider> xDispatchProvider(xFrame, UNO_QUERY);
384 if (xDispatchProvider.is())
386 INetURLObject aObj( aCommand );
388 Sequence<PropertyValue> aArgs(1);
389 aArgs[0].Name = aObj.GetURLPath();
390 aArgs[0].Value <<= sal_Int32(rColor.first);
392 URL aTargetURL;
393 aTargetURL.Complete = aCommand;
394 Reference<XURLTransformer> xURLTransformer(URLTransformer::create(comphelper::getProcessComponentContext()));
395 xURLTransformer->parseStrict(aTargetURL);
397 Reference<XDispatch> xDispatch = xDispatchProvider->queryDispatch(aTargetURL, OUString(), 0);
398 if (xDispatch.is())
400 xDispatch->dispatch(aTargetURL, aArgs);
401 if (xFrame->getContainerWindow().is())
402 xFrame->getContainerWindow()->setFocus();
407 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */