LibreOffice Module svx (master)  1
PaletteManager.cxx
Go to the documentation of this file.
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 <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>
44 
45 #include <palettes.hxx>
46 
48  mnMaxRecentColors(Application::GetSettings().GetStyleSettings().GetColorValueSetColumnCount()),
49  mnNumOfPalettes(2),
50  mnCurrentPalette(0),
51  mnColorCount(0),
52  mpBtnUpdater(nullptr),
53  maColorSelectFunction(PaletteManager::DispatchColorCommand),
55 {
57  if(pDocSh)
58  {
59  const SfxPoolItem* pItem = nullptr;
60  if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) )
61  pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
62  }
63  if(!pColorList.is())
65  LoadPalettes();
66  mnNumOfPalettes += m_Palettes.size();
67 
68 }
69 
71 {
72 }
73 
75 {
76  m_Palettes.clear();
77  OUString aPalPaths = SvtPathOptions().GetPalettePath();
78 
79  std::stack<OUString> aDirs;
80  sal_Int32 nIndex = 0;
81  do
82  {
83  aDirs.push(aPalPaths.getToken(0, ';', nIndex));
84  }
85  while (nIndex >= 0);
86 
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())
91  {
92  OUString aPalPath = aDirs.top();
93  aDirs.pop();
94 
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 )
101  {
102  while( aDir.getNextItem(aDirItem) == osl::FileBase::E_None )
103  {
104  aDirItem.getFileStatus(aFileStat);
105  if(aFileStat.isRegular() || aFileStat.isLink())
106  {
107  OUString aFName = aFileStat.getFileName();
108  INetURLObject aURLObj( aFileStat.getFileURL() );
109  OUString aFNameWithoutExt = aURLObj.GetBase();
110  if (aNames.find(aFName) == aNames.end())
111  {
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));
119 
120  if( pPalette && pPalette->IsValid() )
121  m_Palettes.push_back( std::move(pPalette) );
122  aNames.insert(aFNameWithoutExt);
123  }
124  }
125  }
126  }
127  }
128 }
129 
131 {
132  if( mnCurrentPalette == 0)
133  {
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)
139  {
140  Color aColor(CustomColorList[i]);
141  rColorSet.InsertItem(nIx, aColor, CustomColorNameList[i]);
142  ++nIx;
143  }
144  }
145  else if( mnCurrentPalette == mnNumOfPalettes - 1 )
146  {
147  rColorSet.Clear();
148  // Add doc colors to palette
150  if (pDocSh)
151  {
152  std::set<Color> aColors = pDocSh->GetDocColors();
153  mnColorCount = aColors.size();
154  rColorSet.addEntriesForColorSet(aColors, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX ) + " " );
155  }
156  }
157  else
158  {
159  m_Palettes[mnCurrentPalette - 1]->LoadColorSet( rColorSet );
160  mnColorCount = rColorSet.GetItemCount();
161  }
162 }
163 
165 {
166  if( mnCurrentPalette == 0)
167  {
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)
173  {
174  Color aColor(CustomColorList[i]);
175  rColorSet.InsertItem(nIx, aColor, CustomColorNameList[i]);
176  ++nIx;
177  }
178  }
179  else if( mnCurrentPalette == mnNumOfPalettes - 1 )
180  {
181  // Add doc colors to palette
183  if (pDocSh)
184  {
185  std::set<Color> aColors = pDocSh->GetDocColors();
186  mnColorCount = aColors.size();
187  rColorSet.Clear();
188  rColorSet.addEntriesForColorSet(aColors, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX ) + " " );
189  }
190  }
191  else
192  {
193  m_Palettes[mnCurrentPalette - 1]->LoadColorSet( rColorSet );
194  mnColorCount = rColorSet.GetItemCount();
195  }
196 }
197 
199 {
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)
207  {
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;
213  }
214 }
215 
217 {
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)
225  {
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;
231  }
232 }
233 
234 std::vector<OUString> PaletteManager::GetPaletteList()
235 {
236  std::vector<OUString> aPaletteNames;
237 
238  aPaletteNames.push_back( SvxResId( RID_SVXSTR_CUSTOM_PAL ) );
239  for (auto const& it : m_Palettes)
240  {
241  aPaletteNames.push_back( (*it).GetName() );
242  }
243  aPaletteNames.push_back( SvxResId ( RID_SVXSTR_DOC_COLORS ) );
244 
245  return aPaletteNames;
246 }
247 
248 void PaletteManager::SetPalette( sal_Int32 nPos )
249 {
250  mnCurrentPalette = nPos;
251  if( nPos != mnNumOfPalettes - 1 && nPos != 0)
252  {
256  auto name = GetPaletteName(); // may change pColorList
257  pColorList->SetName(name);
258  if(pColorList->Load())
259  {
261  if (pShell != nullptr)
262  {
263  SvxColorListItem aColorItem(pColorList, SID_COLOR_TABLE);
264  pShell->PutItem( aColorItem );
265  }
266  }
267  }
268  OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get());
269  if (aPaletteName != GetPaletteName())
270  {
271  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
272  officecfg::Office::Common::UserColors::PaletteName::set(GetPaletteName(), batch);
273  batch->commit();
274  }
275 }
276 
277 sal_Int32 PaletteManager::GetPalette() const
278 {
279  return mnCurrentPalette;
280 }
281 
283 {
284  std::vector<OUString> aNames(GetPaletteList());
286  {
288  if(pDocSh)
289  {
290  const SfxPoolItem* pItem = nullptr;
291  if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) )
292  pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
293  }
294  }
295  return aNames[mnCurrentPalette];
296 }
297 
299 {
301  return m_Palettes[mnCurrentPalette - 1]->GetPath();
302  else
303  return OUString();
304 }
305 
307 {
308  return mnColorCount;
309 }
310 
312 {
313  return maRecentColors.size();
314 }
315 
316 void PaletteManager::AddRecentColor(const Color& rRecentColor, const OUString& rName, bool bFront)
317 {
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 );
324 
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)
334  {
335  aColorList[i] = static_cast<sal_Int32>(maRecentColors[i].first);
336  aColorNameList[i] = maRecentColors[i].second;
337  }
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();
342 }
343 
345 {
346  mpBtnUpdater = pBtnUpdater;
347 }
348 
349 void PaletteManager::SetColorSelectFunction(const std::function<void(const OUString&, const NamedColor&)>& aColorSelectFunction)
350 {
351  maColorSelectFunction = aColorSelectFunction;
352 }
353 
354 void PaletteManager::PopupColorPicker(weld::Window* pParent, const OUString& aCommand, const Color& rInitialColor)
355 {
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);
361  if (aColorDlg.Execute(pParent) == RET_OK)
362  {
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);
370  }
371 }
372 
373 void PaletteManager::DispatchColorCommand(const OUString& aCommand, const NamedColor& rColor)
374 {
375  using namespace css::uno;
376  using namespace css::frame;
377  using namespace css::beans;
378  using namespace css::util;
379 
381  Reference<XDesktop2> xDesktop = Desktop::create(xContext);
382  Reference<XFrame> xFrame(xDesktop->getCurrentFrame());
383  Reference<XDispatchProvider> xDispatchProvider(xFrame, UNO_QUERY);
384  if (xDispatchProvider.is())
385  {
386  INetURLObject aObj( aCommand );
387 
388  Sequence<PropertyValue> aArgs(1);
389  aArgs[0].Name = aObj.GetURLPath();
390  aArgs[0].Value <<= sal_Int32(rColor.first);
391 
392  URL aTargetURL;
393  aTargetURL.Complete = aCommand;
394  Reference<XURLTransformer> xURLTransformer(URLTransformer::create(comphelper::getProcessComponentContext()));
395  xURLTransformer->parseStrict(aTargetURL);
396 
397  Reference<XDispatch> xDispatch = xDispatchProvider->queryDispatch(aTargetURL, OUString(), 0);
398  if (xDispatch.is())
399  {
400  xDispatch->dispatch(aTargetURL, aArgs);
401  if (xFrame->getContainerWindow().is())
402  xFrame->getContainerWindow()->setFocus();
403  }
404  }
405 }
406 
407 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString AsRGBHexString() const
std::pair< Color, OUString > NamedColor
Definition: Palette.hxx:27
void ReloadColorSet(SvxColorValueSet &rColorSet)
sal_Int32 nIndex
long GetColorCount() const
XColorListRef pColorList
static XColorListRef CreateStdColorList()
Definition: xtabcolr.cxx:32
OUString GetURLPath(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
Reference< XFrame > xFrame
svx::ToolboxButtonColorUpdaterBase * mpBtnUpdater
static SfxObjectShell * Current()
sal_Int32 GetPalette() const
void PutItem(const SfxPoolItem &rItem)
OUString GetSelectedPalettePath()
const OUString & GetPalettePath() const
void Clear()
OUString GetBase() const
void SetMode(svtools::ColorPickerMode eMode)
static void DispatchColorCommand(const OUString &aCommand, const NamedColor &rColor)
void addEntriesForColorSet(const std::set< Color > &rColorSet, const OUString &rNamePrefix)
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
short Execute(weld::Window *pParent)
void Clear()
static std::shared_ptr< ConfigurationChanges > create(css::uno::Reference< css::uno::XComponentContext > const &context=comphelper::getProcessComponentContext())
long GetRecentColorCount() const
void SetBtnUpdater(svx::ToolboxButtonColorUpdaterBase *pBtnUpdater)
static XColorListRef AsColorList(rtl::Reference< XPropertyList > const &plist)
Definition: xtable.hxx:386
void SetColor(const Color &rColor)
css::uno::Reference< css::uno::XComponentContext > m_context
const SfxPoolItem * GetItem(sal_uInt16 nSlotId) const
const sal_uInt16 mnMaxRecentColors
void SetPalette(sal_Int32 nPos)
std::vector< OUString > GetPaletteList()
uno_Any a
void SetColorSelectFunction(const std::function< void(const OUString &, const NamedColor &)> &aColorSelectFunction)
int i
OUString GetPaletteName()
void addEntriesForColorSet(const std::set< Color > &rColorSet, const OUString &rNamePrefix)
void ReloadRecentColorSet(SvxColorValueSet &rColorSet)
std::function< void(const OUString &, const NamedColor &)> maColorSelectFunction
std::deque< NamedColor > maRecentColors
void PopupColorPicker(weld::Window *pParent, const OUString &aCommand, const Color &rInitialColor)
void InsertItem(sal_uInt16 nItemId, const Image &rImage, const OUString &rStr, size_t nPos=VALUESET_APPEND)
const Color & GetColor() const
virtual std::set< Color > GetDocColors()
Reference< XDispatch > xDispatch
size_t GetItemCount() const
helper class to update a color in a toolbox button image
RET_OK
sal_uInt16 mnCurrentPalette
Reference< XComponentContext > getProcessComponentContext()
const char * name
std::vector< std::unique_ptr< Palette > > m_Palettes
void InsertItem(sal_uInt16 nItemId, const Image &rImage)
OUString aTargetURL
sal_uInt16 mnNumOfPalettes
void AddRecentColor(const Color &rRecentColor, const OUString &rColorName, bool bFront=true)
size_t GetItemCount() const
static XPropertyListRef CreatePropertyListFromURL(XPropertyListType t, const OUString &rUrl)
Definition: xtable.cxx:357
void Update(const NamedColor &rNamedColor)