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 
24 #include <tools/urlobj.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 #include <tbxcolorupdate.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/settings.hxx>
35 #include <stack>
36 #include <set>
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 
44 #include <palettes.hxx>
45 
47  mnMaxRecentColors(Application::GetSettings().GetStyleSettings().GetColorValueSetColumnCount()),
48  mnNumOfPalettes(2),
49  mnCurrentPalette(0),
50  mnColorCount(0),
51  mpBtnUpdater(nullptr),
52  maColorSelectFunction(PaletteManager::DispatchColorCommand),
54 {
56  if(pDocSh)
57  {
58  const SfxPoolItem* pItem = nullptr;
59  if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) )
60  pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
61  }
62  if(!pColorList.is())
64  LoadPalettes();
65  mnNumOfPalettes += m_Palettes.size();
66 
67 }
68 
70 {
71 }
72 
74 {
75  m_Palettes.clear();
76  OUString aPalPaths = SvtPathOptions().GetPalettePath();
77 
78  std::stack<OUString> aDirs;
79  sal_Int32 nIndex = 0;
80  do
81  {
82  aDirs.push(aPalPaths.getToken(0, ';', nIndex));
83  }
84  while (nIndex >= 0);
85 
86  std::set<OUString> aNames;
87  //try all entries palette path list user first, then
88  //system, ignoring duplicate file names
89  while (!aDirs.empty())
90  {
91  OUString aPalPath = aDirs.top();
92  aDirs.pop();
93 
94  osl::Directory aDir(aPalPath);
95  osl::DirectoryItem aDirItem;
96  osl::FileStatus aFileStat( osl_FileStatus_Mask_FileName |
97  osl_FileStatus_Mask_FileURL |
98  osl_FileStatus_Mask_Type );
99  if( aDir.open() == osl::FileBase::E_None )
100  {
101  while( aDir.getNextItem(aDirItem) == osl::FileBase::E_None )
102  {
103  aDirItem.getFileStatus(aFileStat);
104  if(aFileStat.isRegular() || aFileStat.isLink())
105  {
106  OUString aFName = aFileStat.getFileName();
107  INetURLObject aURLObj( aFileStat.getFileURL() );
108  OUString aFNameWithoutExt = aURLObj.GetBase();
109  if (aNames.find(aFName) == aNames.end())
110  {
111  std::unique_ptr<Palette> pPalette;
112  if( aFName.endsWithIgnoreAsciiCase(".gpl") )
113  pPalette.reset(new PaletteGPL(aFileStat.getFileURL(), aFNameWithoutExt));
114  else if( aFName.endsWithIgnoreAsciiCase(".soc") )
115  pPalette.reset(new PaletteSOC(aFileStat.getFileURL(), aFNameWithoutExt));
116  else if ( aFName.endsWithIgnoreAsciiCase(".ase") )
117  pPalette.reset(new PaletteASE(aFileStat.getFileURL(), aFNameWithoutExt));
118 
119  if( pPalette && pPalette->IsValid() )
120  m_Palettes.push_back( std::move(pPalette) );
121  aNames.insert(aFNameWithoutExt);
122  }
123  }
124  }
125  }
126  }
127 }
128 
130 {
131  if( mnCurrentPalette == 0)
132  {
133  rColorSet.Clear();
134  css::uno::Sequence< sal_Int32 > CustomColorList( officecfg::Office::Common::UserColors::CustomColor::get() );
135  css::uno::Sequence< OUString > CustomColorNameList( officecfg::Office::Common::UserColors::CustomColorName::get() );
136  int nIx = 1;
137  for (int i = 0; i < CustomColorList.getLength(); ++i)
138  {
139  Color aColor(ColorTransparency, CustomColorList[i]);
140  rColorSet.InsertItem(nIx, aColor, CustomColorNameList[i]);
141  ++nIx;
142  }
143  }
144  else if( mnCurrentPalette == mnNumOfPalettes - 1 )
145  {
146  // Add doc colors to palette
148  if (pDocSh)
149  {
150  std::set<Color> aColors = pDocSh->GetDocColors();
151  mnColorCount = aColors.size();
152  rColorSet.Clear();
153  rColorSet.addEntriesForColorSet(aColors, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX ) + " " );
154  }
155  }
156  else
157  {
158  m_Palettes[mnCurrentPalette - 1]->LoadColorSet( rColorSet );
159  mnColorCount = rColorSet.GetItemCount();
160  }
161 }
162 
164 {
165  maRecentColors.clear();
166  rColorSet.Clear();
167  css::uno::Sequence< sal_Int32 > Colorlist(officecfg::Office::Common::UserColors::RecentColor::get());
168  css::uno::Sequence< OUString > ColorNamelist(officecfg::Office::Common::UserColors::RecentColorName::get());
169  int nIx = 1;
170  const bool bHasColorNames = Colorlist.getLength() == ColorNamelist.getLength();
171  for (int i = 0; i < Colorlist.getLength(); ++i)
172  {
173  Color aColor(ColorTransparency, Colorlist[i]);
174  OUString sColorName = bHasColorNames ? ColorNamelist[i] : ("#" + aColor.AsRGBHexString().toAsciiUpperCase());
175  maRecentColors.emplace_back(aColor, sColorName);
176  rColorSet.InsertItem(nIx, aColor, sColorName);
177  ++nIx;
178  }
179 }
180 
181 std::vector<OUString> PaletteManager::GetPaletteList()
182 {
183  std::vector<OUString> aPaletteNames
184  {
185  SvxResId( RID_SVXSTR_CUSTOM_PAL )
186  };
187  for (auto const& it : m_Palettes)
188  {
189  aPaletteNames.push_back( (*it).GetName() );
190  }
191  aPaletteNames.push_back( SvxResId ( RID_SVXSTR_DOC_COLORS ) );
192 
193  return aPaletteNames;
194 }
195 
196 void PaletteManager::SetPalette( sal_Int32 nPos )
197 {
198  mnCurrentPalette = nPos;
199  if( nPos != mnNumOfPalettes - 1 && nPos != 0)
200  {
204  auto name = GetPaletteName(); // may change pColorList
205  pColorList->SetName(name);
206  if(pColorList->Load())
207  {
209  if (pShell != nullptr)
210  {
211  SvxColorListItem aColorItem(pColorList, SID_COLOR_TABLE);
212  pShell->PutItem( aColorItem );
213  }
214  }
215  }
216  OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get());
217  if (aPaletteName != GetPaletteName())
218  {
219  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
220  officecfg::Office::Common::UserColors::PaletteName::set(GetPaletteName(), batch);
221  batch->commit();
222  }
223 }
224 
225 sal_Int32 PaletteManager::GetPalette() const
226 {
227  return mnCurrentPalette;
228 }
229 
231 {
232  std::vector<OUString> aNames(GetPaletteList());
234  {
236  if(pDocSh)
237  {
238  const SfxPoolItem* pItem = nullptr;
239  if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) )
240  pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
241  }
242  }
243  return aNames[mnCurrentPalette];
244 }
245 
247 {
249  return m_Palettes[mnCurrentPalette - 1]->GetPath();
250  else
251  return OUString();
252 }
253 
255 {
256  return mnColorCount;
257 }
258 
260 {
261  return maRecentColors.size();
262 }
263 
264 void PaletteManager::AddRecentColor(const Color& rRecentColor, const OUString& rName, bool bFront)
265 {
266  auto itColor = std::find_if(maRecentColors.begin(),
267  maRecentColors.end(),
268  [rRecentColor] (const NamedColor &a) { return a.first == rRecentColor; });
269  // if recent color to be added is already in list, remove it
270  if( itColor != maRecentColors.end() )
271  maRecentColors.erase( itColor );
272 
273  if (maRecentColors.size() == mnMaxRecentColors)
274  maRecentColors.pop_back();
275  if (bFront)
276  maRecentColors.push_front(std::make_pair(rRecentColor, rName));
277  else
278  maRecentColors.emplace_back(rRecentColor, rName);
279  css::uno::Sequence< sal_Int32 > aColorList(maRecentColors.size());
280  auto aColorListRange = asNonConstRange(aColorList);
281  css::uno::Sequence< OUString > aColorNameList(maRecentColors.size());
282  auto aColorNameListRange = asNonConstRange(aColorNameList);
283  for (size_t i = 0; i < maRecentColors.size(); ++i)
284  {
285  aColorListRange[i] = static_cast<sal_Int32>(maRecentColors[i].first);
286  aColorNameListRange[i] = maRecentColors[i].second;
287  }
288  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context));
289  officecfg::Office::Common::UserColors::RecentColor::set(aColorList, batch);
290  officecfg::Office::Common::UserColors::RecentColorName::set(aColorNameList, batch);
291  batch->commit();
292 }
293 
295 {
296  mpBtnUpdater = pBtnUpdater;
297 }
298 
300 {
301  maColorSelectFunction = aColorSelectFunction;
302 }
303 
304 void PaletteManager::PopupColorPicker(weld::Window* pParent, const OUString& aCommand, const Color& rInitialColor)
305 {
306  // The calling object goes away during aColorDlg.Execute(), so we must copy this
307  OUString aCommandCopy = aCommand;
308  m_pColorDlg = std::make_unique<SvColorDialog>();
309  m_pColorDlg->SetColor(rInitialColor);
311  m_pColorDlg->ExecuteAsync(pParent, [this, aCommandCopy] (sal_Int32 nResult) {
312  if (nResult == RET_OK)
313  {
314  Color aLastColor = m_pColorDlg->GetColor();
315  OUString sColorName = "#" + aLastColor.AsRGBHexString().toAsciiUpperCase();
316  NamedColor aNamedColor = std::make_pair(aLastColor, sColorName);
317  if (mpBtnUpdater)
318  mpBtnUpdater->Update(aNamedColor);
319  AddRecentColor(aLastColor, sColorName);
320  maColorSelectFunction(aCommandCopy, aNamedColor);
321  }
322  });
323 }
324 
325 void PaletteManager::DispatchColorCommand(const OUString& aCommand, const NamedColor& rColor)
326 {
327  using namespace css::uno;
328  using namespace css::frame;
329  using namespace css::beans;
330  using namespace css::util;
331 
333  Reference<XDesktop2> xDesktop = Desktop::create(xContext);
334  Reference<XFrame> xFrame(xDesktop->getCurrentFrame());
335  Reference<XDispatchProvider> xDispatchProvider(xFrame, UNO_QUERY);
336  if (!xDispatchProvider.is())
337  return;
338 
339  INetURLObject aObj( aCommand );
340 
341  Sequence<PropertyValue> aArgs{ comphelper::makePropertyValue(aObj.GetURLPath(),
342  sal_Int32(rColor.first)) };
343 
344  URL aTargetURL;
345  aTargetURL.Complete = aCommand;
346  Reference<XURLTransformer> xURLTransformer(URLTransformer::create(comphelper::getProcessComponentContext()));
347  xURLTransformer->parseStrict(aTargetURL);
348 
349  Reference<XDispatch> xDispatch = xDispatchProvider->queryDispatch(aTargetURL, OUString(), 0);
350  if (xDispatch.is())
351  {
352  xDispatch->dispatch(aTargetURL, aArgs);
353  if (xFrame->getContainerWindow().is())
354  xFrame->getContainerWindow()->setFocus();
355  }
356 }
357 
358 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString AsRGBHexString() const
std::pair< Color, OUString > NamedColor
Definition: Palette.hxx:29
void ReloadColorSet(SvxColorValueSet &rColorSet)
sal_Int32 nIndex
XColorListRef pColorList
static XColorListRef CreateStdColorList()
Definition: xtabcolr.cxx:31
OUString GetURLPath(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
long Long
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
Reference< XFrame > xFrame
svx::ToolboxButtonColorUpdaterBase * mpBtnUpdater
tools::Long mnColorCount
static SfxObjectShell * Current()
sal_Int32 GetPalette() const
void PutItem(const SfxPoolItem &rItem)
OUString GetSelectedPalettePath()
tools::Long GetColorCount() const
const OUString & GetPalettePath() const
void Clear()
tools::Long GetRecentColorCount() const
OUString GetBase() const
static void DispatchColorCommand(const OUString &aCommand, const NamedColor &rColor)
void addEntriesForColorSet(const std::set< Color > &rColorSet, const OUString &rNamePrefix)
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
static std::shared_ptr< ConfigurationChanges > create(css::uno::Reference< css::uno::XComponentContext > const &context=comphelper::getProcessComponentContext())
void SetBtnUpdater(svx::ToolboxButtonColorUpdaterBase *pBtnUpdater)
static XColorListRef AsColorList(rtl::Reference< XPropertyList > const &plist)
Definition: xtable.hxx:376
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
OUString GetPaletteName()
void InsertItem(sal_uInt16 nItemId, const Image &rImage)
void ReloadRecentColorSet(SvxColorValueSet &rColorSet)
ColorSelectFunction maColorSelectFunction
ColorTransparency
std::deque< NamedColor > maRecentColors
void PopupColorPicker(weld::Window *pParent, const OUString &aCommand, const Color &rInitialColor)
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::function< void(const OUString &, const NamedColor &)> ColorSelectFunction
Definition: Palette.hxx:33
void SetColorSelectFunction(const ColorSelectFunction &aColorSelectFunction)
std::vector< std::unique_ptr< Palette > > m_Palettes
OUString aTargetURL
sal_uInt16 mnNumOfPalettes
void AddRecentColor(const Color &rRecentColor, const OUString &rColorName, bool bFront=true)
std::unique_ptr< SvColorDialog > m_pColorDlg
static XPropertyListRef CreatePropertyListFromURL(XPropertyListType t, const OUString &rUrl)
Definition: xtable.cxx:353
void Update(const NamedColor &rNamedColor)