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 <svtools/colrdlg.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/settings.hxx>
34 #include <stack>
35 #include <set>
36 #include <officecfg/Office/Common.hxx>
37 #include <com/sun/star/frame/XDispatchProvider.hpp>
38 #include <com/sun/star/frame/XDispatch.hpp>
39 #include <com/sun/star/frame/Desktop.hpp>
40 #include <com/sun/star/util/XURLTransformer.hpp>
41 #include <com/sun/star/util/URLTransformer.hpp>
42 
43 #include <palettes.hxx>
44 
46  mnMaxRecentColors(Application::GetSettings().GetStyleSettings().GetColorValueSetColumnCount()),
47  mnNumOfPalettes(2),
48  mnCurrentPalette(0),
49  mnColorCount(0),
50  mpBtnUpdater(nullptr),
51  maColorSelectFunction(PaletteManager::DispatchColorCommand),
53 {
55  if(pDocSh)
56  {
57  const SfxPoolItem* pItem = nullptr;
58  if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) )
59  pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
60  }
61  if(!pColorList.is())
63  LoadPalettes();
64  mnNumOfPalettes += m_Palettes.size();
65 
66 }
67 
69 {
70 }
71 
73 {
74  m_Palettes.clear();
75  OUString aPalPaths = SvtPathOptions().GetPalettePath();
76 
77  std::stack<OUString> aDirs;
78  sal_Int32 nIndex = 0;
79  do
80  {
81  aDirs.push(aPalPaths.getToken(0, ';', nIndex));
82  }
83  while (nIndex >= 0);
84 
85  std::set<OUString> aNames;
86  //try all entries palette path list user first, then
87  //system, ignoring duplicate file names
88  while (!aDirs.empty())
89  {
90  OUString aPalPath = aDirs.top();
91  aDirs.pop();
92 
93  osl::Directory aDir(aPalPath);
94  osl::DirectoryItem aDirItem;
95  osl::FileStatus aFileStat( osl_FileStatus_Mask_FileName |
96  osl_FileStatus_Mask_FileURL |
97  osl_FileStatus_Mask_Type );
98  if( aDir.open() == osl::FileBase::E_None )
99  {
100  while( aDir.getNextItem(aDirItem) == osl::FileBase::E_None )
101  {
102  aDirItem.getFileStatus(aFileStat);
103  if(aFileStat.isRegular() || aFileStat.isLink())
104  {
105  OUString aFName = aFileStat.getFileName();
106  INetURLObject aURLObj( aFileStat.getFileURL() );
107  OUString aFNameWithoutExt = aURLObj.GetBase();
108  if (aNames.find(aFName) == aNames.end())
109  {
110  std::unique_ptr<Palette> pPalette;
111  if( aFName.endsWithIgnoreAsciiCase(".gpl") )
112  pPalette.reset(new PaletteGPL(aFileStat.getFileURL(), aFNameWithoutExt));
113  else if( aFName.endsWithIgnoreAsciiCase(".soc") )
114  pPalette.reset(new PaletteSOC(aFileStat.getFileURL(), aFNameWithoutExt));
115  else if ( aFName.endsWithIgnoreAsciiCase(".ase") )
116  pPalette.reset(new PaletteASE(aFileStat.getFileURL(), aFNameWithoutExt));
117 
118  if( pPalette && pPalette->IsValid() )
119  m_Palettes.push_back( std::move(pPalette) );
120  aNames.insert(aFNameWithoutExt);
121  }
122  }
123  }
124  }
125  }
126 }
127 
129 {
130  if( mnCurrentPalette == 0)
131  {
132  rColorSet.Clear();
133  css::uno::Sequence< sal_Int32 > CustomColorList( officecfg::Office::Common::UserColors::CustomColor::get() );
134  css::uno::Sequence< OUString > CustomColorNameList( officecfg::Office::Common::UserColors::CustomColorName::get() );
135  int nIx = 1;
136  for (int i = 0; i < CustomColorList.getLength(); ++i)
137  {
138  Color aColor(CustomColorList[i]);
139  rColorSet.InsertItem(nIx, aColor, CustomColorNameList[i]);
140  ++nIx;
141  }
142  }
143  else if( mnCurrentPalette == mnNumOfPalettes - 1 )
144  {
145  rColorSet.Clear();
146  // Add doc colors to palette
148  if (pDocSh)
149  {
150  std::set<Color> aColors = pDocSh->GetDocColors();
151  mnColorCount = aColors.size();
152  rColorSet.addEntriesForColorSet(aColors, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX ) + " " );
153  }
154  }
155  else
156  {
157  m_Palettes[mnCurrentPalette - 1]->LoadColorSet( rColorSet );
158  mnColorCount = rColorSet.GetItemCount();
159  }
160 }
161 
163 {
164  if( mnCurrentPalette == 0)
165  {
166  rColorSet.Clear();
167  css::uno::Sequence< sal_Int32 > CustomColorList( officecfg::Office::Common::UserColors::CustomColor::get() );
168  css::uno::Sequence< OUString > CustomColorNameList( officecfg::Office::Common::UserColors::CustomColorName::get() );
169  int nIx = 1;
170  for (int i = 0; i < CustomColorList.getLength(); ++i)
171  {
172  Color aColor(CustomColorList[i]);
173  rColorSet.InsertItem(nIx, aColor, CustomColorNameList[i]);
174  ++nIx;
175  }
176  }
177  else if( mnCurrentPalette == mnNumOfPalettes - 1 )
178  {
179  // Add doc colors to palette
181  if (pDocSh)
182  {
183  std::set<Color> aColors = pDocSh->GetDocColors();
184  mnColorCount = aColors.size();
185  rColorSet.Clear();
186  rColorSet.addEntriesForColorSet(aColors, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX ) + " " );
187  }
188  }
189  else
190  {
191  m_Palettes[mnCurrentPalette - 1]->LoadColorSet( rColorSet );
192  mnColorCount = rColorSet.GetItemCount();
193  }
194 }
195 
197 {
198  maRecentColors.clear();
199  rColorSet.Clear();
200  css::uno::Sequence< sal_Int32 > Colorlist(officecfg::Office::Common::UserColors::RecentColor::get());
201  css::uno::Sequence< OUString > ColorNamelist(officecfg::Office::Common::UserColors::RecentColorName::get());
202  int nIx = 1;
203  const bool bHasColorNames = Colorlist.getLength() == ColorNamelist.getLength();
204  for (int i = 0; i < Colorlist.getLength(); ++i)
205  {
206  Color aColor(Colorlist[i]);
207  OUString sColorName = bHasColorNames ? ColorNamelist[i] : ("#" + aColor.AsRGBHexString().toAsciiUpperCase());
208  maRecentColors.emplace_back(aColor, sColorName);
209  rColorSet.InsertItem(nIx, aColor, sColorName);
210  ++nIx;
211  }
212 }
213 
215 {
216  maRecentColors.clear();
217  rColorSet.Clear();
218  css::uno::Sequence< sal_Int32 > Colorlist(officecfg::Office::Common::UserColors::RecentColor::get());
219  css::uno::Sequence< OUString > ColorNamelist(officecfg::Office::Common::UserColors::RecentColorName::get());
220  int nIx = 1;
221  const bool bHasColorNames = Colorlist.getLength() == ColorNamelist.getLength();
222  for (int i = 0; i < Colorlist.getLength(); ++i)
223  {
224  Color aColor(Colorlist[i]);
225  OUString sColorName = bHasColorNames ? ColorNamelist[i] : ("#" + aColor.AsRGBHexString().toAsciiUpperCase());
226  maRecentColors.emplace_back(aColor, sColorName);
227  rColorSet.InsertItem(nIx, aColor, sColorName);
228  ++nIx;
229  }
230 }
231 
232 std::vector<OUString> PaletteManager::GetPaletteList()
233 {
234  std::vector<OUString> aPaletteNames;
235 
236  aPaletteNames.push_back( SvxResId( RID_SVXSTR_CUSTOM_PAL ) );
237  for (auto const& it : m_Palettes)
238  {
239  aPaletteNames.push_back( (*it).GetName() );
240  }
241  aPaletteNames.push_back( SvxResId ( RID_SVXSTR_DOC_COLORS ) );
242 
243  return aPaletteNames;
244 }
245 
246 void PaletteManager::SetPalette( sal_Int32 nPos )
247 {
248  mnCurrentPalette = nPos;
249  if( nPos != mnNumOfPalettes - 1 && nPos != 0)
250  {
254  auto name = GetPaletteName(); // may change pColorList
255  pColorList->SetName(name);
256  if(pColorList->Load())
257  {
259  if (pShell != nullptr)
260  {
261  SvxColorListItem aColorItem(pColorList, SID_COLOR_TABLE);
262  pShell->PutItem( aColorItem );
263  }
264  }
265  }
266  OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get());
267  if (aPaletteName != GetPaletteName())
268  {
269  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
270  officecfg::Office::Common::UserColors::PaletteName::set(GetPaletteName(), batch);
271  batch->commit();
272  }
273 }
274 
275 sal_Int32 PaletteManager::GetPalette() const
276 {
277  return mnCurrentPalette;
278 }
279 
281 {
282  std::vector<OUString> aNames(GetPaletteList());
284  {
286  if(pDocSh)
287  {
288  const SfxPoolItem* pItem = nullptr;
289  if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) )
290  pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
291  }
292  }
293  return aNames[mnCurrentPalette];
294 }
295 
297 {
299  return m_Palettes[mnCurrentPalette - 1]->GetPath();
300  else
301  return OUString();
302 }
303 
305 {
306  return mnColorCount;
307 }
308 
310 {
311  return maRecentColors.size();
312 }
313 
314 void PaletteManager::AddRecentColor(const Color& rRecentColor, const OUString& rName, bool bFront)
315 {
316  auto itColor = std::find_if(maRecentColors.begin(),
317  maRecentColors.end(),
318  [rRecentColor] (const NamedColor &a) { return a.first == rRecentColor; });
319  // if recent color to be added is already in list, remove it
320  if( itColor != maRecentColors.end() )
321  maRecentColors.erase( itColor );
322 
323  if (maRecentColors.size() == mnMaxRecentColors)
324  maRecentColors.pop_back();
325  if (bFront)
326  maRecentColors.push_front(std::make_pair(rRecentColor, rName));
327  else
328  maRecentColors.emplace_back(rRecentColor, rName);
329  css::uno::Sequence< sal_Int32 > aColorList(maRecentColors.size());
330  css::uno::Sequence< OUString > aColorNameList(maRecentColors.size());
331  for (size_t i = 0; i < maRecentColors.size(); ++i)
332  {
333  aColorList[i] = static_cast<sal_Int32>(maRecentColors[i].first);
334  aColorNameList[i] = maRecentColors[i].second;
335  }
336  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
337  officecfg::Office::Common::UserColors::RecentColor::set(aColorList, batch);
338  officecfg::Office::Common::UserColors::RecentColorName::set(aColorNameList, batch);
339  batch->commit();
340 }
341 
343 {
344  mpBtnUpdater = pBtnUpdater;
345 }
346 
347 void PaletteManager::SetColorSelectFunction(const std::function<void(const OUString&, const NamedColor&)>& aColorSelectFunction)
348 {
349  maColorSelectFunction = aColorSelectFunction;
350 }
351 
352 void PaletteManager::PopupColorPicker(weld::Window* pParent, const OUString& aCommand, const Color& rInitialColor)
353 {
354  // The calling object goes away during aColorDlg.Execute(), so we must copy this
355  OUString aCommandCopy = aCommand;
356  SvColorDialog aColorDlg;
357  aColorDlg.SetColor(rInitialColor);
359  if (aColorDlg.Execute(pParent) == RET_OK)
360  {
361  Color aLastColor = aColorDlg.GetColor();
362  OUString sColorName = "#" + aLastColor.AsRGBHexString().toAsciiUpperCase();
363  NamedColor aNamedColor = std::make_pair(aLastColor, sColorName);
364  if (mpBtnUpdater)
365  mpBtnUpdater->Update(aNamedColor);
366  AddRecentColor(aLastColor, sColorName);
367  maColorSelectFunction(aCommandCopy, aNamedColor);
368  }
369 }
370 
371 void PaletteManager::DispatchColorCommand(const OUString& aCommand, const NamedColor& rColor)
372 {
373  using namespace css::uno;
374  using namespace css::frame;
375  using namespace css::beans;
376  using namespace css::util;
377 
379  Reference<XDesktop2> xDesktop = Desktop::create(xContext);
380  Reference<XFrame> xFrame(xDesktop->getCurrentFrame());
381  Reference<XDispatchProvider> xDispatchProvider(xFrame, UNO_QUERY);
382  if (xDispatchProvider.is())
383  {
384  INetURLObject aObj( aCommand );
385 
386  Sequence<PropertyValue> aArgs(1);
387  aArgs[0].Name = aObj.GetURLPath();
388  aArgs[0].Value <<= sal_Int32(rColor.first);
389 
390  URL aTargetURL;
391  aTargetURL.Complete = aCommand;
392  Reference<XURLTransformer> xURLTransformer(URLTransformer::create(comphelper::getProcessComponentContext()));
393  xURLTransformer->parseStrict(aTargetURL);
394 
395  Reference<XDispatch> xDispatch = xDispatchProvider->queryDispatch(aTargetURL, OUString(), 0);
396  if (xDispatch.is())
397  {
398  xDispatch->dispatch(aTargetURL, aArgs);
399  if (xFrame->getContainerWindow().is())
400  xFrame->getContainerWindow()->setFocus();
401  }
402  }
403 }
404 
405 /* 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:31
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)
int i
std::vector< OUString > GetPaletteList()
uno_Any a
void SetColorSelectFunction(const std::function< void(const OUString &, const NamedColor &)> &aColorSelectFunction)
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:353
void Update(const NamedColor &rNamedColor)