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  // Add doc colors to palette
147  if (pDocSh)
148  {
149  std::set<Color> aColors = pDocSh->GetDocColors();
150  mnColorCount = aColors.size();
151  rColorSet.Clear();
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  maRecentColors.clear();
165  rColorSet.Clear();
166  css::uno::Sequence< sal_Int32 > Colorlist(officecfg::Office::Common::UserColors::RecentColor::get());
167  css::uno::Sequence< OUString > ColorNamelist(officecfg::Office::Common::UserColors::RecentColorName::get());
168  int nIx = 1;
169  const bool bHasColorNames = Colorlist.getLength() == ColorNamelist.getLength();
170  for (int i = 0; i < Colorlist.getLength(); ++i)
171  {
172  Color aColor(Colorlist[i]);
173  OUString sColorName = bHasColorNames ? ColorNamelist[i] : ("#" + aColor.AsRGBHexString().toAsciiUpperCase());
174  maRecentColors.emplace_back(aColor, sColorName);
175  rColorSet.InsertItem(nIx, aColor, sColorName);
176  ++nIx;
177  }
178 }
179 
180 std::vector<OUString> PaletteManager::GetPaletteList()
181 {
182  std::vector<OUString> aPaletteNames;
183 
184  aPaletteNames.push_back( SvxResId( RID_SVXSTR_CUSTOM_PAL ) );
185  for (auto const& it : m_Palettes)
186  {
187  aPaletteNames.push_back( (*it).GetName() );
188  }
189  aPaletteNames.push_back( SvxResId ( RID_SVXSTR_DOC_COLORS ) );
190 
191  return aPaletteNames;
192 }
193 
194 void PaletteManager::SetPalette( sal_Int32 nPos )
195 {
196  mnCurrentPalette = nPos;
197  if( nPos != mnNumOfPalettes - 1 && nPos != 0)
198  {
202  auto name = GetPaletteName(); // may change pColorList
203  pColorList->SetName(name);
204  if(pColorList->Load())
205  {
207  if (pShell != nullptr)
208  {
209  SvxColorListItem aColorItem(pColorList, SID_COLOR_TABLE);
210  pShell->PutItem( aColorItem );
211  }
212  }
213  }
214  OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get());
215  if (aPaletteName != GetPaletteName())
216  {
217  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
218  officecfg::Office::Common::UserColors::PaletteName::set(GetPaletteName(), batch);
219  batch->commit();
220  }
221 }
222 
223 sal_Int32 PaletteManager::GetPalette() const
224 {
225  return mnCurrentPalette;
226 }
227 
229 {
230  std::vector<OUString> aNames(GetPaletteList());
232  {
234  if(pDocSh)
235  {
236  const SfxPoolItem* pItem = nullptr;
237  if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) )
238  pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
239  }
240  }
241  return aNames[mnCurrentPalette];
242 }
243 
245 {
247  return m_Palettes[mnCurrentPalette - 1]->GetPath();
248  else
249  return OUString();
250 }
251 
253 {
254  return mnColorCount;
255 }
256 
258 {
259  return maRecentColors.size();
260 }
261 
262 void PaletteManager::AddRecentColor(const Color& rRecentColor, const OUString& rName, bool bFront)
263 {
264  auto itColor = std::find_if(maRecentColors.begin(),
265  maRecentColors.end(),
266  [rRecentColor] (const NamedColor &a) { return a.first == rRecentColor; });
267  // if recent color to be added is already in list, remove it
268  if( itColor != maRecentColors.end() )
269  maRecentColors.erase( itColor );
270 
271  if (maRecentColors.size() == mnMaxRecentColors)
272  maRecentColors.pop_back();
273  if (bFront)
274  maRecentColors.push_front(std::make_pair(rRecentColor, rName));
275  else
276  maRecentColors.emplace_back(rRecentColor, rName);
277  css::uno::Sequence< sal_Int32 > aColorList(maRecentColors.size());
278  css::uno::Sequence< OUString > aColorNameList(maRecentColors.size());
279  for (size_t i = 0; i < maRecentColors.size(); ++i)
280  {
281  aColorList[i] = static_cast<sal_Int32>(maRecentColors[i].first);
282  aColorNameList[i] = maRecentColors[i].second;
283  }
284  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
285  officecfg::Office::Common::UserColors::RecentColor::set(aColorList, batch);
286  officecfg::Office::Common::UserColors::RecentColorName::set(aColorNameList, batch);
287  batch->commit();
288 }
289 
291 {
292  mpBtnUpdater = pBtnUpdater;
293 }
294 
295 void PaletteManager::SetColorSelectFunction(const std::function<void(const OUString&, const NamedColor&)>& aColorSelectFunction)
296 {
297  maColorSelectFunction = aColorSelectFunction;
298 }
299 
300 void PaletteManager::PopupColorPicker(weld::Window* pParent, const OUString& aCommand, const Color& rInitialColor)
301 {
302  // The calling object goes away during aColorDlg.Execute(), so we must copy this
303  OUString aCommandCopy = aCommand;
304  SvColorDialog aColorDlg;
305  aColorDlg.SetColor(rInitialColor);
307  if (aColorDlg.Execute(pParent) == RET_OK)
308  {
309  Color aLastColor = aColorDlg.GetColor();
310  OUString sColorName = "#" + aLastColor.AsRGBHexString().toAsciiUpperCase();
311  NamedColor aNamedColor = std::make_pair(aLastColor, sColorName);
312  if (mpBtnUpdater)
313  mpBtnUpdater->Update(aNamedColor);
314  AddRecentColor(aLastColor, sColorName);
315  maColorSelectFunction(aCommandCopy, aNamedColor);
316  }
317 }
318 
319 void PaletteManager::DispatchColorCommand(const OUString& aCommand, const NamedColor& rColor)
320 {
321  using namespace css::uno;
322  using namespace css::frame;
323  using namespace css::beans;
324  using namespace css::util;
325 
327  Reference<XDesktop2> xDesktop = Desktop::create(xContext);
328  Reference<XFrame> xFrame(xDesktop->getCurrentFrame());
329  Reference<XDispatchProvider> xDispatchProvider(xFrame, UNO_QUERY);
330  if (xDispatchProvider.is())
331  {
332  INetURLObject aObj( aCommand );
333 
334  Sequence<PropertyValue> aArgs(1);
335  aArgs[0].Name = aObj.GetURLPath();
336  aArgs[0].Value <<= sal_Int32(rColor.first);
337 
338  URL aTargetURL;
339  aTargetURL.Complete = aCommand;
340  Reference<XURLTransformer> xURLTransformer(URLTransformer::create(comphelper::getProcessComponentContext()));
341  xURLTransformer->parseStrict(aTargetURL);
342 
343  Reference<XDispatch> xDispatch = xDispatchProvider->queryDispatch(aTargetURL, OUString(), 0);
344  if (xDispatch.is())
345  {
346  xDispatch->dispatch(aTargetURL, aArgs);
347  if (xFrame->getContainerWindow().is())
348  xFrame->getContainerWindow()->setFocus();
349  }
350  }
351 }
352 
353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString AsRGBHexString() const
std::pair< Color, OUString > NamedColor
Definition: Palette.hxx:26
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)
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 InsertItem(sal_uInt16 nItemId, const Image &rImage)
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)
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
OUString aTargetURL
sal_uInt16 mnNumOfPalettes
void AddRecentColor(const Color &rRecentColor, const OUString &rColorName, bool bFront=true)
static XPropertyListRef CreatePropertyListFromURL(XPropertyListType t, const OUString &rUrl)
Definition: xtable.cxx:353
void Update(const NamedColor &rNamedColor)