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 .
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>
30 SfxCharmapContainer::SfxCharmapContainer(weld::Builder
& rBuilder
, const VclPtr
<VirtualDevice
>& rVirDev
, bool bLockGridSizes
)
31 : m_aRecentCharView
{SvxCharView(rVirDev
),
47 , m_aFavCharView
{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"))
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());
181 for ( std::deque
< OUString
>::iterator it
= m_aFavCharList
.begin(), it2
= m_aFavCharFontList
.begin();
182 it
!= m_aFavCharList
.end() && it2
!= m_aFavCharFontList
.end();
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();
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());
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());
291 for ( std::deque
< OUString
>::iterator it
= m_aRecentCharList
.begin(), it2
= m_aRecentCharFontList
.begin();
292 it
!= m_aRecentCharList
.end() && it2
!= m_aRecentCharFontList
.end();
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();
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
);
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
);
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
);
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
);
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
);
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
);
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: */