Bump version to 24.04.3.4
[LibreOffice.git] / sfx2 / source / control / charmapcontrol.cxx
blob76e37174fd497c884661422acc98685a9ba8b216
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <comphelper/dispatchcommand.hxx>
21 #include <officecfg/Office/Common.hxx>
22 #include <charmapcontrol.hxx>
23 #include <charmappopup.hxx>
24 #include <sfx2/viewfrm.hxx>
25 #include <sfx2/strings.hrc>
26 #include <sfx2/sfxresid.hxx>
28 using namespace css;
30 SfxCharmapContainer::SfxCharmapContainer(weld::Builder& rBuilder, const VclPtr<VirtualDevice>& rVirDev, bool bLockGridSizes)
31 : m_aRecentCharView{SvxCharView(rVirDev),
32 SvxCharView(rVirDev),
33 SvxCharView(rVirDev),
34 SvxCharView(rVirDev),
35 SvxCharView(rVirDev),
36 SvxCharView(rVirDev),
37 SvxCharView(rVirDev),
38 SvxCharView(rVirDev),
39 SvxCharView(rVirDev),
40 SvxCharView(rVirDev),
41 SvxCharView(rVirDev),
42 SvxCharView(rVirDev),
43 SvxCharView(rVirDev),
44 SvxCharView(rVirDev),
45 SvxCharView(rVirDev),
46 SvxCharView(rVirDev)}
47 , m_aFavCharView{SvxCharView(rVirDev),
48 SvxCharView(rVirDev),
49 SvxCharView(rVirDev),
50 SvxCharView(rVirDev),
51 SvxCharView(rVirDev),
52 SvxCharView(rVirDev),
53 SvxCharView(rVirDev),
54 SvxCharView(rVirDev),
55 SvxCharView(rVirDev),
56 SvxCharView(rVirDev),
57 SvxCharView(rVirDev),
58 SvxCharView(rVirDev),
59 SvxCharView(rVirDev),
60 SvxCharView(rVirDev),
61 SvxCharView(rVirDev),
62 SvxCharView(rVirDev)}
63 , m_xRecentCharView{std::make_unique<weld::CustomWeld>(rBuilder, "viewchar1", m_aRecentCharView[0]),
64 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar2", m_aRecentCharView[1]),
65 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar3", m_aRecentCharView[2]),
66 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar4", m_aRecentCharView[3]),
67 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar5", m_aRecentCharView[4]),
68 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar6", m_aRecentCharView[5]),
69 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar7", m_aRecentCharView[6]),
70 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar8", m_aRecentCharView[7]),
71 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar9", m_aRecentCharView[8]),
72 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar10", m_aRecentCharView[9]),
73 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar11", m_aRecentCharView[10]),
74 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar12", m_aRecentCharView[11]),
75 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar13", m_aRecentCharView[12]),
76 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar14", m_aRecentCharView[13]),
77 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar15", m_aRecentCharView[14]),
78 std::make_unique<weld::CustomWeld>(rBuilder, "viewchar16", m_aRecentCharView[15])}
79 , m_xFavCharView{std::make_unique<weld::CustomWeld>(rBuilder, "favchar1", m_aFavCharView[0]),
80 std::make_unique<weld::CustomWeld>(rBuilder, "favchar2", m_aFavCharView[1]),
81 std::make_unique<weld::CustomWeld>(rBuilder, "favchar3", m_aFavCharView[2]),
82 std::make_unique<weld::CustomWeld>(rBuilder, "favchar4", m_aFavCharView[3]),
83 std::make_unique<weld::CustomWeld>(rBuilder, "favchar5", m_aFavCharView[4]),
84 std::make_unique<weld::CustomWeld>(rBuilder, "favchar6", m_aFavCharView[5]),
85 std::make_unique<weld::CustomWeld>(rBuilder, "favchar7", m_aFavCharView[6]),
86 std::make_unique<weld::CustomWeld>(rBuilder, "favchar8", m_aFavCharView[7]),
87 std::make_unique<weld::CustomWeld>(rBuilder, "favchar9", m_aFavCharView[8]),
88 std::make_unique<weld::CustomWeld>(rBuilder, "favchar10", m_aFavCharView[9]),
89 std::make_unique<weld::CustomWeld>(rBuilder, "favchar11", m_aFavCharView[10]),
90 std::make_unique<weld::CustomWeld>(rBuilder, "favchar12", m_aFavCharView[11]),
91 std::make_unique<weld::CustomWeld>(rBuilder, "favchar13", m_aFavCharView[12]),
92 std::make_unique<weld::CustomWeld>(rBuilder, "favchar14", m_aFavCharView[13]),
93 std::make_unique<weld::CustomWeld>(rBuilder, "favchar15", m_aFavCharView[14]),
94 std::make_unique<weld::CustomWeld>(rBuilder, "favchar16", m_aFavCharView[15])}
95 , m_xRecentGrid(rBuilder.weld_widget("viewgrid"))
96 , m_xFavGrid(rBuilder.weld_widget("favgrid"))
98 if (bLockGridSizes)
100 //so things don't jump around if all the children are hidden
101 m_xRecentGrid->set_size_request(-1, m_aRecentCharView[0].get_preferred_size().Height());
102 m_xFavGrid->set_size_request(-1, m_aFavCharView[0].get_preferred_size().Height());
106 void SfxCharmapContainer::init(bool bHasInsert, const Link<SvxCharView*,void> &rMouseClickHdl,
107 const Link<void*, void>& rUpdateFavHdl,
108 const Link<void*, void>& rUpdateRecentHdl,
109 const Link<SvxCharView*,void> &rFocusInHdl)
111 m_aUpdateFavHdl = rUpdateFavHdl;
112 m_aUpdateRecentHdl = rUpdateRecentHdl;
114 getRecentCharacterList();
115 updateRecentCharControl();
116 getFavCharacterList();
117 updateFavCharControl();
119 for(int i = 0; i < 16; i++)
121 m_aRecentCharView[i].SetHasInsert(bHasInsert);
122 m_aRecentCharView[i].setFocusInHdl(rFocusInHdl);
123 m_aRecentCharView[i].setMouseClickHdl(rMouseClickHdl);
124 m_aRecentCharView[i].setClearClickHdl(LINK(this, SfxCharmapContainer, RecentClearClickHdl));
125 m_aRecentCharView[i].setClearAllClickHdl(LINK(this, SfxCharmapContainer, RecentClearAllClickHdl));
126 m_aFavCharView[i].SetHasInsert(bHasInsert);
127 m_aFavCharView[i].setFocusInHdl(rFocusInHdl);
128 m_aFavCharView[i].setMouseClickHdl(rMouseClickHdl);
129 m_aFavCharView[i].setClearClickHdl(LINK(this, SfxCharmapContainer, FavClearClickHdl));
130 m_aFavCharView[i].setClearAllClickHdl(LINK(this, SfxCharmapContainer, FavClearAllClickHdl));
134 SfxCharmapCtrl::SfxCharmapCtrl(CharmapPopup* pControl, weld::Widget* pParent)
135 : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "sfx/ui/charmapcontrol.ui", "charmapctrl")
136 , m_xControl(pControl)
137 , m_xVirDev(VclPtr<VirtualDevice>::Create())
138 , m_aCharmapContents(*m_xBuilder, m_xVirDev, false)
139 , m_xRecentLabel(m_xBuilder->weld_label("label2"))
140 , m_xDlgBtn(m_xBuilder->weld_button("specialchardlg"))
141 , m_xCharInfoLabel(m_xBuilder->weld_label("charinfolabel"))
143 m_xCharInfoLabel->set_size_request(-1, m_xCharInfoLabel->get_text_height() * 2);
145 m_aCharmapContents.init(false, LINK(this, SfxCharmapCtrl, CharClickHdl),
146 Link<void*,void>(), LINK(this, SfxCharmapCtrl, UpdateRecentHdl),
147 LINK(this, SfxCharmapCtrl, CharFocusInHdl));
149 m_xDlgBtn->connect_clicked(LINK(this, SfxCharmapCtrl, OpenDlgHdl));
150 m_xDlgBtn->connect_focus_in(LINK(this, SfxCharmapCtrl, DlgBtnFocusInHdl));
153 SfxCharmapCtrl::~SfxCharmapCtrl()
157 void SfxCharmapContainer::getFavCharacterList()
159 m_aFavCharList.clear();
160 m_aFavCharFontList.clear();
162 //retrieve recent character list
163 const css::uno::Sequence< OUString > rFavCharList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::get() );
164 m_aFavCharList.insert( m_aFavCharList.end(), rFavCharList.begin(), rFavCharList.end() );
166 //retrieve recent character font list
167 const css::uno::Sequence< OUString > rFavCharFontList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::get() );
168 m_aFavCharFontList.insert( m_aFavCharFontList.end(), rFavCharFontList.begin(), rFavCharFontList.end() );
170 // tdf#135997: make sure that the two lists are same length
171 const auto nCommonLength = std::min(m_aFavCharList.size(), m_aFavCharFontList.size());
172 m_aFavCharList.resize(nCommonLength);
173 m_aFavCharFontList.resize(nCommonLength);
176 void SfxCharmapContainer::updateFavCharControl()
178 assert(m_aFavCharList.size() == m_aFavCharFontList.size());
180 int i = 0;
181 for ( std::deque< OUString >::iterator it = m_aFavCharList.begin(), it2 = m_aFavCharFontList.begin();
182 it != m_aFavCharList.end() && it2 != m_aFavCharFontList.end();
183 ++it, ++it2, i++)
185 m_aFavCharView[i].SetText(*it);
186 vcl::Font rFont = m_aFavCharView[i].GetFont();
187 rFont.SetFamilyName( *it2 );
188 m_aFavCharView[i].SetFont(rFont);
189 m_aFavCharView[i].Show();
192 for(; i < 16 ; i++)
194 m_aFavCharView[i].SetText(OUString());
195 m_aFavCharView[i].Hide();
198 m_aUpdateFavHdl.Call(nullptr);
201 void SfxCharmapContainer::getRecentCharacterList()
203 m_aRecentCharList.clear();
204 m_aRecentCharFontList.clear();
206 //retrieve recent character list
207 const css::uno::Sequence< OUString > rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() );
208 m_aRecentCharList.insert( m_aRecentCharList.end(), rRecentCharList.begin(), rRecentCharList.end() );
210 //retrieve recent character font list
211 const css::uno::Sequence< OUString > rRecentCharFontList( officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::get() );
212 m_aRecentCharFontList.insert( m_aRecentCharFontList.end(), rRecentCharFontList.begin(), rRecentCharFontList.end() );
214 // tdf#135997: make sure that the two lists are same length
215 const auto nCommonLength = std::min(m_aRecentCharList.size(), m_aRecentCharFontList.size());
216 m_aRecentCharList.resize(nCommonLength);
217 m_aRecentCharFontList.resize(nCommonLength);
220 IMPL_LINK(SfxCharmapCtrl, CharFocusInHdl, SvxCharView*, pView, void)
222 m_xCharInfoLabel->set_label(pView->GetCharInfoText());
225 IMPL_LINK(SfxCharmapCtrl, CharClickHdl, SvxCharView*, pView, void)
227 m_xControl->EndPopupMode();
229 pView->InsertCharToDoc();
232 IMPL_LINK_NOARG(SfxCharmapCtrl, OpenDlgHdl, weld::Button&, void)
234 m_xControl->EndPopupMode();
236 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
238 uno::Reference<frame::XFrame> xFrame = pViewFrm->GetFrame().GetFrameInterface();
239 comphelper::dispatchCommand(".uno:InsertSymbol", xFrame, {});
243 IMPL_LINK_NOARG(SfxCharmapCtrl, DlgBtnFocusInHdl, weld::Widget&, void)
245 m_xCharInfoLabel->set_label("");
248 void SfxCharmapCtrl::GrabFocus()
250 m_aCharmapContents.GrabFocusToFirstFavorite();
253 void SfxCharmapContainer::GrabFocusToFirstFavorite()
255 m_aFavCharView[0].GrabFocus();
258 static std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
259 findInPair(std::u16string_view str1, const std::deque<OUString>& rContainer1,
260 std::u16string_view str2, const std::deque<OUString>& rContainer2)
262 assert(rContainer1.size() == rContainer2.size());
264 for (auto it1 = std::find(rContainer1.begin(), rContainer1.end(), str1);
265 it1 != rContainer1.end(); it1 = std::find(std::next(it1), rContainer1.end(), str1))
267 auto it2 = rContainer2.begin() + (it1 - rContainer1.begin());
268 if (*it2 == str2)
269 return { it1, it2 };
271 return { rContainer1.end(), rContainer2.end() };
274 std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
275 SfxCharmapContainer::getRecentChar(std::u16string_view sTitle, std::u16string_view rFont) const
277 return findInPair(sTitle, m_aRecentCharList, rFont, m_aRecentCharFontList);
280 std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
281 SfxCharmapContainer::getFavChar(std::u16string_view sTitle, std::u16string_view rFont) const
283 return findInPair(sTitle, m_aFavCharList, rFont, m_aFavCharFontList);
286 void SfxCharmapContainer::updateRecentCharControl()
288 assert(m_aRecentCharList.size() == m_aRecentCharFontList.size());
290 int i = 0;
291 for ( std::deque< OUString >::iterator it = m_aRecentCharList.begin(), it2 = m_aRecentCharFontList.begin();
292 it != m_aRecentCharList.end() && it2 != m_aRecentCharFontList.end();
293 ++it, ++it2, i++)
295 m_aRecentCharView[i].SetText(*it);
296 vcl::Font rFont = m_aRecentCharView[i].GetFont();
297 rFont.SetFamilyName( *it2 );
298 m_aRecentCharView[i].SetFont(rFont);
299 m_aRecentCharView[i].Show();
302 for(; i < 16 ; i++)
304 m_aRecentCharView[i].SetText(OUString());
305 m_aRecentCharView[i].Hide();
308 m_aUpdateRecentHdl.Call(nullptr);
311 void SfxCharmapContainer::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont)
313 // if recent char to be added is already in list, remove it
314 if( const auto& [itChar, itChar2] = getRecentChar(sTitle, rFont);
315 itChar != m_aRecentCharList.end() && itChar2 != m_aRecentCharFontList.end() )
317 m_aRecentCharList.erase( itChar );
318 m_aRecentCharFontList.erase( itChar2);
321 if (m_aRecentCharList.size() == 16)
323 m_aRecentCharList.pop_back();
324 m_aRecentCharFontList.pop_back();
327 m_aRecentCharList.push_front(sTitle);
328 m_aRecentCharFontList.push_front(rFont);
330 css::uno::Sequence< OUString > aRecentCharList(m_aRecentCharList.size());
331 auto aRecentCharListRange = asNonConstRange(aRecentCharList);
332 css::uno::Sequence< OUString > aRecentCharFontList(m_aRecentCharFontList.size());
333 auto aRecentCharFontListRange = asNonConstRange(aRecentCharFontList);
335 for (size_t i = 0; i < m_aRecentCharList.size(); ++i)
337 aRecentCharListRange[i] = m_aRecentCharList[i];
338 aRecentCharFontListRange[i] = m_aRecentCharFontList[i];
341 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
342 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
343 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
344 batch->commit();
346 updateRecentCharControl();
349 void SfxCharmapContainer::updateFavCharacterList(const OUString& sTitle, const OUString& rFont)
351 // if Fav char to be added is already in list, remove it
352 if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
353 itChar != m_aFavCharList.end() && itChar2 != m_aFavCharFontList.end() )
355 m_aFavCharList.erase( itChar );
356 m_aFavCharFontList.erase( itChar2);
359 if (m_aFavCharList.size() == 16)
361 m_aFavCharList.pop_back();
362 m_aFavCharFontList.pop_back();
365 m_aFavCharList.push_back(sTitle);
366 m_aFavCharFontList.push_back(rFont);
368 css::uno::Sequence< OUString > aFavCharList(m_aFavCharList.size());
369 auto aFavCharListRange = asNonConstRange(aFavCharList);
370 css::uno::Sequence< OUString > aFavCharFontList(m_aFavCharFontList.size());
371 auto aFavCharFontListRange = asNonConstRange(aFavCharFontList);
373 for (size_t i = 0; i < m_aFavCharList.size(); ++i)
375 aFavCharListRange[i] = m_aFavCharList[i];
376 aFavCharFontListRange[i] = m_aFavCharFontList[i];
379 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
380 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
381 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
382 batch->commit();
385 void SfxCharmapContainer::deleteFavCharacterFromList(std::u16string_view sTitle, std::u16string_view rFont)
387 // if Fav char is found, remove it
388 if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
389 itChar != m_aFavCharList.end() && itChar2 != m_aFavCharFontList.end() )
391 m_aFavCharList.erase( itChar );
392 m_aFavCharFontList.erase( itChar2);
395 css::uno::Sequence< OUString > aFavCharList(m_aFavCharList.size());
396 auto aFavCharListRange = asNonConstRange(aFavCharList);
397 css::uno::Sequence< OUString > aFavCharFontList(m_aFavCharFontList.size());
398 auto aFavCharFontListRange = asNonConstRange(aFavCharFontList);
400 for (size_t i = 0; i < m_aFavCharList.size(); ++i)
402 aFavCharListRange[i] = m_aFavCharList[i];
403 aFavCharFontListRange[i] = m_aFavCharFontList[i];
406 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
407 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
408 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
409 batch->commit();
412 bool SfxCharmapContainer::isFavChar(std::u16string_view sTitle, std::u16string_view rFont)
414 const auto& [itChar, itFont] = getFavChar(sTitle, rFont);
415 return itChar != m_aFavCharList.end() && itFont != m_aFavCharFontList.end();
418 IMPL_LINK(SfxCharmapContainer, RecentClearClickHdl, SvxCharView*, rView, void)
420 const OUString& sTitle = rView->GetText();
421 OUString sFont = rView->GetFont().GetFamilyName();
423 // if recent char to be added is already in list, remove it
424 if( const auto& [itChar, itChar2] = getRecentChar(sTitle, sFont);
425 itChar != m_aRecentCharList.end() && itChar2 != m_aRecentCharFontList.end() )
427 m_aRecentCharList.erase( itChar );
428 m_aRecentCharFontList.erase( itChar2);
431 css::uno::Sequence< OUString > aRecentCharList(m_aRecentCharList.size());
432 auto aRecentCharListRange = asNonConstRange(aRecentCharList);
433 css::uno::Sequence< OUString > aRecentCharFontList(m_aRecentCharFontList.size());
434 auto aRecentCharFontListRange = asNonConstRange(aRecentCharFontList);
436 for (size_t i = 0; i < m_aRecentCharList.size(); ++i)
438 aRecentCharListRange[i] = m_aRecentCharList[i];
439 aRecentCharFontListRange[i] = m_aRecentCharFontList[i];
442 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
443 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
444 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
445 batch->commit();
447 updateRecentCharControl();
450 IMPL_LINK_NOARG(SfxCharmapContainer, RecentClearAllClickHdl, SvxCharView*, void)
452 m_aRecentCharList.clear();
453 m_aRecentCharFontList.clear();
455 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
456 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set({ }, batch);
457 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set({ }, batch);
458 batch->commit();
460 updateRecentCharControl();
463 IMPL_LINK(SfxCharmapContainer, FavClearClickHdl, SvxCharView*, rView, void)
465 deleteFavCharacterFromList(rView->GetText(), rView->GetFont().GetFamilyName());
466 updateFavCharControl();
469 IMPL_LINK_NOARG(SfxCharmapContainer, FavClearAllClickHdl, SvxCharView*, void)
471 m_aFavCharList.clear();
472 m_aFavCharFontList.clear();
474 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
475 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set({ }, batch);
476 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set({ }, batch);
477 batch->commit();
479 updateFavCharControl();
482 bool SfxCharmapContainer::FavCharListIsFull() const
484 return m_aFavCharList.size() == 16;
487 bool SfxCharmapContainer::hasRecentChars() const
489 return !m_aRecentCharList.empty();
492 IMPL_LINK_NOARG(SfxCharmapCtrl, UpdateRecentHdl, void*, void)
494 //checking if the characters are recently used or no
495 m_xRecentLabel->set_label(m_aCharmapContents.hasRecentChars() ? SfxResId(STR_RECENT) : SfxResId(STR_NORECENT));
498 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */