1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
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()),
52 mpBtnUpdater(nullptr),
53 maColorSelectFunction(PaletteManager::DispatchColorCommand
),
54 m_context(comphelper::getProcessComponentContext())
56 SfxObjectShell
* pDocSh
= SfxObjectShell::Current();
59 const SfxPoolItem
* pItem
= nullptr;
60 if( nullptr != ( pItem
= pDocSh
->GetItem(SID_COLOR_TABLE
) ) )
61 pColorList
= static_cast<const SvxColorListItem
*>(pItem
)->GetColorList();
64 pColorList
= XColorList::CreateStdColorList();
66 mnNumOfPalettes
+= m_Palettes
.size();
70 PaletteManager::~PaletteManager()
74 void PaletteManager::LoadPalettes()
77 OUString aPalPaths
= SvtPathOptions().GetPalettePath();
79 std::stack
<OUString
> aDirs
;
83 aDirs
.push(aPalPaths
.getToken(0, ';', nIndex
));
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();
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)
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() );
138 for (int i
= 0; i
< CustomColorList
.getLength(); ++i
)
140 Color
aColor(CustomColorList
[i
]);
141 rColorSet
.InsertItem(nIx
, aColor
, CustomColorNameList
[i
]);
145 else if( mnCurrentPalette
== mnNumOfPalettes
- 1 )
148 // Add doc colors to palette
149 SfxObjectShell
* pDocSh
= SfxObjectShell::Current();
152 std::set
<Color
> aColors
= pDocSh
->GetDocColors();
153 mnColorCount
= aColors
.size();
154 rColorSet
.addEntriesForColorSet(aColors
, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX
) + " " );
159 m_Palettes
[mnCurrentPalette
- 1]->LoadColorSet( rColorSet
);
160 mnColorCount
= rColorSet
.GetItemCount();
164 void PaletteManager::ReloadColorSet(ColorValueSet
&rColorSet
)
166 if( mnCurrentPalette
== 0)
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() );
172 for (int i
= 0; i
< CustomColorList
.getLength(); ++i
)
174 Color
aColor(CustomColorList
[i
]);
175 rColorSet
.InsertItem(nIx
, aColor
, CustomColorNameList
[i
]);
179 else if( mnCurrentPalette
== mnNumOfPalettes
- 1 )
181 // Add doc colors to palette
182 SfxObjectShell
* pDocSh
= SfxObjectShell::Current();
185 std::set
<Color
> aColors
= pDocSh
->GetDocColors();
186 mnColorCount
= aColors
.size();
188 rColorSet
.addEntriesForColorSet(aColors
, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX
) + " " );
193 m_Palettes
[mnCurrentPalette
- 1]->LoadColorSet( rColorSet
);
194 mnColorCount
= rColorSet
.GetItemCount();
198 void PaletteManager::ReloadRecentColorSet(SvxColorValueSet
& rColorSet
)
200 maRecentColors
.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());
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
);
216 void PaletteManager::ReloadRecentColorSet(ColorValueSet
& rColorSet
)
218 maRecentColors
.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());
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
);
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
);
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();
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();
306 long PaletteManager::GetColorCount() const
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();
328 maRecentColors
.push_front(std::make_pair(rRecentColor
, rName
));
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
);
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
);
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
);
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);
400 xDispatch
->dispatch(aTargetURL
, aArgs
);
401 if (xFrame
->getContainerWindow().is())
402 xFrame
->getContainerWindow()->setFocus();
407 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */