LibreOffice Module cui (master) 1
cuicharmap.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 <sal/config.h>
21
22#include <stdio.h>
23
24#include <utility>
25#include <vcl/svapp.hxx>
26#include <svl/eitem.hxx>
27#include <svl/intitem.hxx>
28#include <svl/itempool.hxx>
29
30#include <rtl/textenc.h>
31#include <svx/ucsubset.hxx>
32#include <vcl/settings.hxx>
33#include <vcl/fontcharmap.hxx>
34#include <vcl/virdev.hxx>
35#include <svl/stritem.hxx>
36#include <o3tl/temporary.hxx>
37#include <officecfg/Office/Common.hxx>
38#include <com/sun/star/beans/PropertyValue.hpp>
42
43#include <dialmgr.hxx>
44#include <cui/cuicharmap.hxx>
45#include <sfx2/app.hxx>
46#include <svx/svxids.hrc>
47#include <editeng/editids.hrc>
48#include <editeng/fontitem.hxx>
49#include <strings.hrc>
50#include <unicode/uchar.h>
51#include <unicode/utypes.h>
52
53using namespace css;
54
56 css::uno::Reference<css::frame::XFrame> xFrame)
57 : SfxDialogController(pParent, "cui/ui/specialcharacters.ui", "SpecialCharactersDialog")
58 , m_xVirDev(VclPtr<VirtualDevice>::Create())
59 , isSearchMode(true)
60 , m_xFrame(std::move(xFrame))
61 , m_aRecentCharView{SvxCharView(m_xVirDev),
62 SvxCharView(m_xVirDev),
63 SvxCharView(m_xVirDev),
64 SvxCharView(m_xVirDev),
65 SvxCharView(m_xVirDev),
66 SvxCharView(m_xVirDev),
67 SvxCharView(m_xVirDev),
68 SvxCharView(m_xVirDev),
69 SvxCharView(m_xVirDev),
70 SvxCharView(m_xVirDev),
71 SvxCharView(m_xVirDev),
72 SvxCharView(m_xVirDev),
73 SvxCharView(m_xVirDev),
74 SvxCharView(m_xVirDev),
75 SvxCharView(m_xVirDev),
76 SvxCharView(m_xVirDev)}
77 , m_aFavCharView{SvxCharView(m_xVirDev),
78 SvxCharView(m_xVirDev),
79 SvxCharView(m_xVirDev),
80 SvxCharView(m_xVirDev),
81 SvxCharView(m_xVirDev),
82 SvxCharView(m_xVirDev),
83 SvxCharView(m_xVirDev),
84 SvxCharView(m_xVirDev),
85 SvxCharView(m_xVirDev),
86 SvxCharView(m_xVirDev),
87 SvxCharView(m_xVirDev),
88 SvxCharView(m_xVirDev),
89 SvxCharView(m_xVirDev),
90 SvxCharView(m_xVirDev),
91 SvxCharView(m_xVirDev),
92 SvxCharView(m_xVirDev)}
93 , m_aShowChar(m_xVirDev)
94 , m_xOKBtn(m_xFrame.is() ? m_xBuilder->weld_button("insert") : m_xBuilder->weld_button("ok"))
95 , m_xFontText(m_xBuilder->weld_label("fontft"))
96 , m_xFontLB(m_xBuilder->weld_combo_box("fontlb"))
97 , m_xSubsetText(m_xBuilder->weld_label("subsetft"))
98 , m_xSubsetLB(m_xBuilder->weld_combo_box("subsetlb"))
99 , m_xSearchText(m_xBuilder->weld_entry("search"))
100 , m_xHexCodeText(m_xBuilder->weld_entry("hexvalue"))
101 , m_xDecimalCodeText(m_xBuilder->weld_entry("decimalvalue"))
102 , m_xFavouritesBtn(m_xBuilder->weld_button("favbtn"))
103 , m_xCharName(m_xBuilder->weld_label("charname"))
104 , m_xRecentGrid(m_xBuilder->weld_widget("viewgrid"))
105 , m_xFavGrid(m_xBuilder->weld_widget("favgrid"))
106 , m_xShowChar(new weld::CustomWeld(*m_xBuilder, "showchar", m_aShowChar))
107 , m_xRecentCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar1", m_aRecentCharView[0]),
108 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar2", m_aRecentCharView[1]),
109 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar3", m_aRecentCharView[2]),
110 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar4", m_aRecentCharView[3]),
111 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar5", m_aRecentCharView[4]),
112 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar6", m_aRecentCharView[5]),
113 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar7", m_aRecentCharView[6]),
114 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar8", m_aRecentCharView[7]),
115 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar9", m_aRecentCharView[8]),
116 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar10", m_aRecentCharView[9]),
117 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar11", m_aRecentCharView[10]),
118 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar12", m_aRecentCharView[11]),
119 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar13", m_aRecentCharView[12]),
120 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar14", m_aRecentCharView[13]),
121 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar15", m_aRecentCharView[14]),
122 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar16", m_aRecentCharView[15])}
123 , m_xFavCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar1", m_aFavCharView[0]),
124 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar2", m_aFavCharView[1]),
125 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar3", m_aFavCharView[2]),
126 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar4", m_aFavCharView[3]),
127 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar5", m_aFavCharView[4]),
128 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar6", m_aFavCharView[5]),
129 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar7", m_aFavCharView[6]),
130 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar8", m_aFavCharView[7]),
131 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar9", m_aFavCharView[8]),
132 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar10", m_aFavCharView[9]),
133 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar11", m_aFavCharView[10]),
134 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar12", m_aFavCharView[11]),
135 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar13", m_aFavCharView[12]),
136 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar14", m_aFavCharView[13]),
137 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar15", m_aFavCharView[14]),
138 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar16", m_aFavCharView[15])}
139 , m_xShowSet(new SvxShowCharSet(m_xBuilder->weld_scrolled_window("showscroll", true), m_xVirDev))
140 , m_xShowSetArea(new weld::CustomWeld(*m_xBuilder, "showcharset", *m_xShowSet))
141 , m_xSearchSet(new SvxSearchCharSet(m_xBuilder->weld_scrolled_window("searchscroll", true), m_xVirDev))
142 , m_xSearchSetArea(new weld::CustomWeld(*m_xBuilder, "searchcharset", *m_xSearchSet))
143{
145 m_xFontLB->make_sorted();
146 //lock the size request of this widget to the width of all possible entries
148 m_xSubsetLB->set_size_request(m_xSubsetLB->get_preferred_size().Width(), -1);
149 m_xCharName->set_size_request(m_aShowChar.get_preferred_size().Width(), m_xCharName->get_text_height() * 4);
150 //lock the size request of this widget to the width of the original .ui string
151 m_xHexCodeText->set_size_request(m_xHexCodeText->get_preferred_size().Width(), -1);
152 //so things don't jump around if all the children are hidden
153 m_xRecentGrid->set_size_request(-1, m_aRecentCharView[0].get_preferred_size().Height());
154 m_xFavGrid->set_size_request(-1, m_aFavCharView[0].get_preferred_size().Height());
155
156 init();
157
158 const SfxInt32Item* pCharItem = SfxItemSet::GetItem<SfxInt32Item>(pSet, SID_ATTR_CHAR, false);
159 if ( pCharItem )
160 SetChar( pCharItem->GetValue() );
161
162 const SfxBoolItem* pDisableItem = SfxItemSet::GetItem<SfxBoolItem>(pSet, FN_PARAM_2, false);
163 if ( pDisableItem && pDisableItem->GetValue() )
165
166 const SvxFontItem* pFontItem = SfxItemSet::GetItem<SvxFontItem>(pSet, SID_ATTR_CHAR_FONT, false);
167 const SfxStringItem* pFontNameItem = SfxItemSet::GetItem<SfxStringItem>(pSet, SID_FONT_NAME, false);
168 if ( pFontItem )
169 {
170 vcl::Font aTmpFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), GetCharFont().GetFontSize() );
171 aTmpFont.SetCharSet( pFontItem->GetCharSet() );
172 aTmpFont.SetPitch( pFontItem->GetPitch() );
173 SetCharFont( aTmpFont );
174 }
175 else if ( pFontNameItem )
176 {
177 vcl::Font aTmpFont( GetCharFont() );
178 aTmpFont.SetFamilyName( pFontNameItem->GetValue() );
179 SetCharFont( aTmpFont );
180 }
181
182 m_xOutputSet.reset(new SfxAllItemSet(pSet ? *pSet->GetPool() : SfxGetpApp()->GetPool()));
183 m_xShowSet->Show();
184 m_xSearchSet->Hide();
185}
186
188{
190 {
191 m_xOKBtn->set_sensitive(false);
192 setFavButtonState(u"", u"");
193 }
194 else
195 {
196 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
197 // using the new UCS4 constructor
198 OUString aOUStr( &cChar, 1 );
199 m_aShowChar.SetText(aOUStr);
200
202 m_xOKBtn->set_sensitive(true);
203 }
204
205 return SfxDialogController::run();
206}
207
209{
210 m_xShowSet->SelectCharacter( c );
211 setFavButtonState(OUString(&c, 1), aFont.GetFamilyName());
212}
213
215{
216 return m_aShowChar.GetText().iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
217}
218
220{
221 m_xFontText->set_sensitive(false);
222 m_xFontLB->set_sensitive(false);
223}
224
225
227{
228 //retrieve recent character list
229 const css::uno::Sequence< OUString > rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() );
230 for (OUString const & s : rRecentCharList)
231 {
232 maRecentCharList.push_back(s);
233 }
234
235 //retrieve recent character font list
236 const css::uno::Sequence< OUString > rRecentCharFontList( officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::get() );
237 for (OUString const & s : rRecentCharFontList)
238 {
239 maRecentCharFontList.push_back(s);
240 }
241
242 // tdf#135997: make sure that the two lists are same length
243 const auto nCommonLength = std::min(maRecentCharList.size(), maRecentCharFontList.size());
244 maRecentCharList.resize(nCommonLength);
245 maRecentCharFontList.resize(nCommonLength);
246}
247
248
250{
251 maFavCharList.clear();
252 maFavCharFontList.clear();
253 //retrieve recent character list
254 const css::uno::Sequence< OUString > rFavCharList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::get() );
255 for (const OUString& s : rFavCharList)
256 {
257 maFavCharList.push_back(s);
258 }
259
260 //retrieve recent character font list
261 const css::uno::Sequence< OUString > rFavCharFontList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::get() );
262 for (const OUString& s : rFavCharFontList)
263 {
264 maFavCharFontList.push_back(s);
265 }
266
267 // tdf#135997: make sure that the two lists are same length
268 const auto nCommonLength = std::min(maFavCharList.size(), maFavCharFontList.size());
269 maFavCharList.resize(nCommonLength);
270 maFavCharFontList.resize(nCommonLength);
271}
272
273static std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
274findInPair(std::u16string_view str1, const std::deque<OUString>& rContainer1,
275 std::u16string_view str2, const std::deque<OUString>& rContainer2)
276{
277 assert(rContainer1.size() == rContainer2.size());
278
279 if (auto it1 = std::find(rContainer1.begin(), rContainer1.end(), str1);
280 it1 != rContainer1.end())
281 {
282 auto it2 = rContainer2.begin() + (it1 - rContainer1.begin());
283 if (*it2 == str2)
284 return { it1, it2 };
285 }
286 return { rContainer1.end(), rContainer2.end() };
287}
288
289std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
290SvxCharacterMap::getRecentChar(std::u16string_view sTitle, std::u16string_view rFont) const
291{
292 return findInPair(sTitle, maRecentCharList, rFont, maRecentCharFontList);
293}
294
295std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
296SvxCharacterMap::getFavChar(std::u16string_view sTitle, std::u16string_view rFont) const
297{
298 return findInPair(sTitle, maFavCharList, rFont, maFavCharFontList);
299}
300
301
303{
304 assert(maRecentCharList.size() == maRecentCharFontList.size());
305
306 int i = 0;
307 for ( std::deque< OUString >::iterator it = maRecentCharList.begin(), it2 = maRecentCharFontList.begin();
308 it != maRecentCharList.end() && it2 != maRecentCharFontList.end();
309 ++it, ++it2, i++)
310 {
313 rFont.SetFamilyName( *it2 );
315 m_aRecentCharView[i].Show();
316 }
317
318 for(; i < 16 ; i++)
319 {
320 m_aRecentCharView[i].SetText(OUString());
321 m_aRecentCharView[i].Hide();
322 }
323}
324
325void SvxCharacterMap::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont)
326{
327 // if recent char to be added is already in list, remove it
328 if( const auto& [itChar, itChar2] = getRecentChar(sTitle, rFont);
329 itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
330 {
331 maRecentCharList.erase( itChar );
332 maRecentCharFontList.erase( itChar2);
333 }
334
335 if (maRecentCharList.size() == 16)
336 {
337 maRecentCharList.pop_back();
338 maRecentCharFontList.pop_back();
339 }
340
341 maRecentCharList.push_front(sTitle);
342 maRecentCharFontList.push_front(rFont);
343
344 css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
345 auto aRecentCharListRange = asNonConstRange(aRecentCharList);
346 css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
347 auto aRecentCharFontListRange = asNonConstRange(aRecentCharFontList);
348
349 for (size_t i = 0; i < maRecentCharList.size(); ++i)
350 {
351 aRecentCharListRange[i] = maRecentCharList[i];
352 aRecentCharFontListRange[i] = maRecentCharFontList[i];
353 }
354
355 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
356 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
357 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
358 batch->commit();
359
361}
362
363
364void SvxCharacterMap::updateFavCharacterList(const OUString& sTitle, const OUString& rFont)
365{
366 // if Fav char to be added is already in list, remove it
367 if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
368 itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
369 {
370 maFavCharList.erase( itChar );
371 maFavCharFontList.erase( itChar2);
372 }
373
374 if (maFavCharList.size() == 16)
375 {
376 maFavCharList.pop_back();
377 maFavCharFontList.pop_back();
378 }
379
380 maFavCharList.push_back(sTitle);
381 maFavCharFontList.push_back(rFont);
382
383 css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
384 auto aFavCharListRange = asNonConstRange(aFavCharList);
385 css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
386 auto aFavCharFontListRange = asNonConstRange(aFavCharFontList);
387
388 for (size_t i = 0; i < maFavCharList.size(); ++i)
389 {
390 aFavCharListRange[i] = maFavCharList[i];
391 aFavCharFontListRange[i] = maFavCharFontList[i];
392 }
393
394 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
395 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
396 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
397 batch->commit();
398}
399
400
402{
403 assert(maFavCharList.size() == maFavCharFontList.size());
404
405 int i = 0;
406 for ( std::deque< OUString >::iterator it = maFavCharList.begin(), it2 = maFavCharFontList.begin();
407 it != maFavCharList.end() && it2 != maFavCharFontList.end();
408 ++it, ++it2, i++)
409 {
412 rFont.SetFamilyName( *it2 );
413 m_aFavCharView[i].SetFont(rFont);
414 m_aFavCharView[i].Show();
415 }
416
417 for(; i < 16 ; i++)
418 {
419 m_aFavCharView[i].SetText(OUString());
420 m_aFavCharView[i].Hide();
421 }
422 m_xShowSet->getFavCharacterList();
423 m_xSearchSet->getFavCharacterList();
424 // tdf#109214 - redraw highlight of the favorite characters
425 m_xShowSet->Invalidate();
426}
427
428void SvxCharacterMap::deleteFavCharacterFromList(std::u16string_view sTitle, std::u16string_view rFont)
429{
430 // if Fav char is found, remove it
431 if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
432 itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
433 {
434 maFavCharList.erase( itChar );
435 maFavCharFontList.erase( itChar2);
436 }
437
438 css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
439 auto aFavCharListRange = asNonConstRange(aFavCharList);
440 css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
441 auto aFavCharFontListRange = asNonConstRange(aFavCharFontList);
442
443 for (size_t i = 0; i < maFavCharList.size(); ++i)
444 {
445 aFavCharListRange[i] = maFavCharList[i];
446 aFavCharFontListRange[i] = maFavCharFontList[i];
447 }
448
449 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
450 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
451 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
452 batch->commit();
453}
454
456{
457 aFont = m_xVirDev->GetFont();
458 aFont.SetTransparent( true );
461 aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
462
463 OUString aDefStr( aFont.GetFamilyName() );
464 OUString aLastName;
465 int nCount = m_xVirDev->GetFontFaceCollectionCount();
466 std::vector<weld::ComboBoxEntry> aEntries;
467 aEntries.reserve(nCount);
468 for (int i = 0; i < nCount; ++i)
469 {
470 OUString aFontName( m_xVirDev->GetFontMetricFromCollection( i ).GetFamilyName() );
471 if (aFontName != aLastName)
472 {
473 aLastName = aFontName;
474 aEntries.emplace_back(aFontName, OUString::number(i));
475 }
476 }
477 m_xFontLB->insert_vector(aEntries, true);
478 // the font may not be in the list =>
479 // try to find a font name token in list and select found font,
480 // else select topmost entry
481 bool bFound = (m_xFontLB->find_text(aDefStr) != -1);
482 if (!bFound)
483 {
484 sal_Int32 nIndex = 0;
485 do
486 {
487 OUString aToken = aDefStr.getToken(0, ';', nIndex);
488 if (m_xFontLB->find_text(aToken) != -1)
489 {
490 aDefStr = aToken;
491 bFound = true;
492 break;
493 }
494 }
495 while ( nIndex >= 0 );
496 }
497
498 if (bFound)
499 m_xFontLB->set_active_text(aDefStr);
500 else if (m_xFontLB->get_count() )
501 m_xFontLB->set_active(0);
502 FontSelectHdl(*m_xFontLB);
503 if (m_xSubsetLB->get_count())
504 m_xSubsetLB->set_active(0);
505
506 m_xFontLB->connect_changed(LINK( this, SvxCharacterMap, FontSelectHdl));
507 m_xSubsetLB->connect_changed(LINK( this, SvxCharacterMap, SubsetSelectHdl));
508 m_xOKBtn->connect_clicked(LINK(this, SvxCharacterMap, InsertClickHdl));
509 m_xOKBtn->show();
510
511 m_xShowSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, CharDoubleClickHdl ) );
512 m_xShowSet->SetSelectHdl( LINK( this, SvxCharacterMap, CharSelectHdl ) );
513 m_xShowSet->SetHighlightHdl( LINK( this, SvxCharacterMap, CharHighlightHdl ) );
514 m_xShowSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, CharPreSelectHdl ) );
515 m_xShowSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
516
517 m_xSearchSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, SearchCharDoubleClickHdl ) );
518 m_xSearchSet->SetSelectHdl( LINK( this, SvxCharacterMap, SearchCharSelectHdl ) );
519 m_xSearchSet->SetHighlightHdl( LINK( this, SvxCharacterMap, SearchCharHighlightHdl ) );
520 m_xSearchSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, SearchCharPreSelectHdl ) );
521 m_xSearchSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
522
523 m_xDecimalCodeText->connect_changed( LINK( this, SvxCharacterMap, DecimalCodeChangeHdl ) );
524 m_xHexCodeText->connect_changed( LINK( this, SvxCharacterMap, HexCodeChangeHdl ) );
525 m_xFavouritesBtn->connect_clicked( LINK(this, SvxCharacterMap, FavSelectHdl));
526
527 // tdf#117038 set the buttons width to its max possible width so it doesn't
528 // make layout change when the label changes
529 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_REMOVE_FAVORITES));
530 auto nMaxWidth = m_xFavouritesBtn->get_preferred_size().Width();
531 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES));
532 nMaxWidth = std::max(nMaxWidth, m_xFavouritesBtn->get_preferred_size().Width());
533 m_xFavouritesBtn->set_size_request(nMaxWidth, -1);
534
536 {
537 m_xOKBtn->set_sensitive(false);
538 }
539 else
540 {
541 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
542 // using the new UCS4 constructor
543 OUString aOUStr( &cChar, 1 );
544 m_aShowChar.SetText(aOUStr);
545
546 setFavButtonState(aOUStr, aDefStr);
547 m_xOKBtn->set_sensitive(true);
548 }
549
552
555
556 bool bHasInsert = m_xFrame.is();
557
558 for(int i = 0; i < 16; i++)
559 {
560 m_aRecentCharView[i].SetHasInsert(bHasInsert);
562 m_aRecentCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, RecentClearClickHdl));
563 m_aRecentCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, RecentClearAllClickHdl));
564 m_aFavCharView[i].SetHasInsert(bHasInsert);
566 m_aFavCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, FavClearClickHdl));
567 m_aFavCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, FavClearAllClickHdl));
568 }
569
570 setCharName(90);
571
572 m_xSearchText->connect_focus_in(LINK( this, SvxCharacterMap, SearchFieldGetFocusHdl ));
573 m_xSearchText->connect_changed(LINK(this, SvxCharacterMap, SearchUpdateHdl));
574}
575
576bool SvxCharacterMap::isFavChar(std::u16string_view sTitle, std::u16string_view rFont)
577{
578 const auto& [itChar, itFont] = getFavChar(sTitle, rFont);
579 return itChar != maFavCharList.end() && itFont != maFavCharFontList.end();
580}
581
582
583void SvxCharacterMap::setFavButtonState(std::u16string_view sTitle, std::u16string_view rFont)
584{
585 if(sTitle.empty() || rFont.empty())
586 {
587 m_xFavouritesBtn->set_sensitive(false);
588 return;
589 }
590 else
591 m_xFavouritesBtn->set_sensitive(true);
592
593 if (isFavChar(sTitle, rFont))
594 {
595 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_REMOVE_FAVORITES));
596 }
597 else
598 {
599 if(maFavCharList.size() == 16)
600 {
601 m_xFavouritesBtn->set_sensitive(false);
602 }
603
604 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES));
605 }
606}
607
608
610{
611 // first get the underlying info in order to get font names
612 // like "Times New Roman;Times" resolved
613 vcl::Font aTmp(m_xVirDev->GetFontMetric(rFont));
614
615 // tdf#56363 - search font family without the font feature after the colon
616 OUString sFontFamilyName = aTmp.GetFamilyName();
617 if (const sal_Int32 nIndex = sFontFamilyName.indexOf(":"); nIndex != -1)
618 sFontFamilyName = sFontFamilyName.copy(0, nIndex);
619 if (sFontFamilyName == "StarSymbol" && m_xFontLB->find_text(sFontFamilyName) == -1)
620 {
621 //if for some reason, like font in an old document, StarSymbol is requested and it's not available, then
622 //try OpenSymbol instead
623 aTmp.SetFamilyName("OpenSymbol");
624 }
625
626 if (m_xFontLB->find_text(sFontFamilyName) == -1)
627 return;
628
629 m_xFontLB->set_active_text(sFontFamilyName);
630 aFont = aTmp;
631 FontSelectHdl(*m_xFontLB);
632 if (m_xSubsetLB->get_count())
633 m_xSubsetLB->set_active(0);
634}
635
637{
638 SubsetMap aAll(nullptr);
639 std::vector<weld::ComboBoxEntry> aEntries;
640 for (auto & subset : aAll.GetSubsetMap())
641 aEntries.emplace_back(subset.GetName());
642 rListBox.insert_vector(aEntries, true);
643}
644
645void SvxCharacterMap::insertCharToDoc(const OUString& sGlyph)
646{
647 if(sGlyph.isEmpty())
648 return;
649
650 if (m_xFrame.is()) {
652 comphelper::makePropertyValue("Symbols", sGlyph),
654 };
655 comphelper::dispatchCommand(".uno:InsertSymbol", m_xFrame, aArgs);
656
658
659 } else {
660 sal_UCS4 cChar = sGlyph.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
661 const SfxItemPool* pPool = m_xOutputSet->GetPool();
662 m_xOutputSet->Put( SfxStringItem( SID_CHARMAP, sGlyph ) );
664 aFont.GetStyleName(), aFont.GetPitch(), aFont.GetCharSet(), pPool->GetWhich(SID_ATTR_CHAR_FONT) ) );
665 m_xOutputSet->Put( SfxStringItem( SID_FONT_NAME, aFont.GetFamilyName() ) );
666 m_xOutputSet->Put( SfxInt32Item( SID_ATTR_CHAR, cChar ) );
667 }
668}
669
671{
672 const sal_uInt32 nFont = m_xFontLB->get_active_id().toUInt32();
673 aFont = m_xVirDev->GetFontMetricFromCollection(nFont);
674 aFont.SetWeight( WEIGHT_DONTKNOW );
675 aFont.SetItalic( ITALIC_NONE );
676 aFont.SetWidthType( WIDTH_DONTKNOW );
677 aFont.SetPitch( PITCH_DONTKNOW );
678 aFont.SetFamily( FAMILY_DONTKNOW );
679
680 // notify children using this font
681 m_xShowSet->SetFont( aFont );
682 m_xSearchSet->SetFont( aFont );
683 m_aShowChar.SetFont( aFont );
684
685 // setup unicode subset listbar with font specific subsets,
686 // hide unicode subset listbar for symbol fonts
687 // TODO: get info from the Font once it provides it
688 pSubsetMap.reset();
689 m_xSubsetLB->clear();
690
691 bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL);
692 if (bNeedSubset)
693 {
694 FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
695 pSubsetMap.reset(new SubsetMap( xFontCharMap ));
696
697 // update subset listbox for new font's unicode subsets
698 for (auto const& subset : pSubsetMap->GetSubsetMap())
699 {
700 m_xSubsetLB->append(weld::toId(&subset), subset.GetName());
701 // NOTE: subset must live at least as long as the selected font
702 }
703
704 if (m_xSubsetLB->get_count() <= 1)
705 bNeedSubset = false;
706 }
707
708 m_xSubsetText->set_sensitive(bNeedSubset);
709 m_xSubsetLB->set_sensitive(bNeedSubset);
710
711 if (isSearchMode)
712 {
713 // tdf#137294 do this after modifying m_xSubsetLB sensitivity to
714 // restore insensitive for the search case
715 SearchUpdateHdl(*m_xSearchText);
716 SearchCharHighlightHdl(m_xSearchSet.get());
717 }
718
719 // tdf#118304 reselect current glyph to see if it's still there in new font
720 selectCharByCode(Radix::hexadecimal);
721}
722
724{
725 isSearchMode = state;
726 m_xHexCodeText->set_editable(!state);
727 m_xDecimalCodeText->set_editable(!state);
728 m_xSubsetLB->set_sensitive(!state);
729
730 if(state)
731 {
732 m_xSearchSet->Show();
733 m_xShowSet->Hide();
734 }
735 else
736 {
737 m_xSearchSet->Hide();
738 m_xShowSet->Show();
739 }
740}
741
743{
744 /* get the character name */
745 UErrorCode errorCode = U_ZERO_ERROR;
746 // icu has a private uprv_getMaxCharNameLength function which returns the max possible
747 // length of this property. Unicode 3.2 max char name length was 83
748 char buffer[100];
749 u_charName(nDecimalValue, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
750 if (U_SUCCESS(errorCode))
751 m_xCharName->set_label(OUString::createFromAscii(buffer));
752}
753
755{
756 const sal_Int32 nPos = m_xSubsetLB->get_active();
757 const Subset* pSubset = weld::fromId<const Subset*>(m_xSubsetLB->get_active_id());
758
759 if( pSubset && !isSearchMode)
760 {
761 sal_UCS4 cFirst = pSubset->GetRangeMin();
762 m_xShowSet->SelectCharacter( cFirst );
763
764 setFavButtonState(OUString(&cFirst, 1), aFont.GetFamilyName());
765 m_xSubsetLB->set_active(nPos);
766 }
767 else if( pSubset && isSearchMode)
768 {
769 m_xSearchSet->SelectCharacter( pSubset );
770
771 const Subset* curSubset = nullptr;
772 if( pSubsetMap )
773 curSubset = pSubsetMap->GetSubsetByUnicode( m_xSearchSet->GetSelectCharacter() );
774 if( curSubset )
775 m_xSubsetLB->set_active_text(curSubset->GetName());
776 else
777 m_xSubsetLB->set_active(-1);
778
779 sal_UCS4 sChar = m_xSearchSet->GetSelectCharacter();
780 setFavButtonState(OUString(&sChar, 1), aFont.GetFamilyName());
781 }
782}
783
784IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView*, rView, void)
785{
786 const OUString& sTitle = rView->GetText();
787 OUString sFont = rView->GetFont().GetFamilyName();
788
789 // if recent char to be added is already in list, remove it
790 if( const auto& [itChar, itChar2] = getRecentChar(sTitle, sFont);
791 itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
792 {
793 maRecentCharList.erase( itChar );
794 maRecentCharFontList.erase( itChar2);
795 }
796
797 css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
798 auto aRecentCharListRange = asNonConstRange(aRecentCharList);
799 css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
800 auto aRecentCharFontListRange = asNonConstRange(aRecentCharFontList);
801
802 for (size_t i = 0; i < maRecentCharList.size(); ++i)
803 {
804 aRecentCharListRange[i] = maRecentCharList[i];
805 aRecentCharFontListRange[i] = maRecentCharFontList[i];
806 }
807
808 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
809 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
810 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
811 batch->commit();
812
813 updateRecentCharControl();
814}
815
816IMPL_LINK_NOARG(SvxCharacterMap, RecentClearAllClickHdl, SvxCharView*, void)
817{
818 maRecentCharList.clear();
819 maRecentCharFontList.clear();
820
821 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
822 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set({ }, batch);
823 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set({ }, batch);
824 batch->commit();
825
826 updateRecentCharControl();
827}
828
829IMPL_LINK(SvxCharacterMap, FavClearClickHdl, SvxCharView*, rView, void)
830{
831 deleteFavCharacterFromList(rView->GetText(), rView->GetFont().GetFamilyName());
832 updateFavCharControl();
833}
834
835IMPL_LINK_NOARG(SvxCharacterMap, FavClearAllClickHdl, SvxCharView*, void)
836{
837 maFavCharList.clear();
838 maFavCharFontList.clear();
839
840 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
841 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set({ }, batch);
842 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set({ }, batch);
843 batch->commit();
844
845 updateFavCharControl();
846}
847
848IMPL_LINK_NOARG(SvxCharacterMap, SearchFieldGetFocusHdl, weld::Widget&, void)
849{
850 m_xOKBtn->set_sensitive(false);
851}
852
854{
855 if (!m_xSearchText->get_text().isEmpty())
856 {
857 m_xSearchSet->ClearPreviousData();
858 OUString aKeyword = m_xSearchText->get_text();
859
860 toggleSearchView(true);
861
862 FontCharMapRef xFontCharMap = m_xSearchSet->GetFontCharMap();
863
864 sal_UCS4 sChar = xFontCharMap->GetFirstChar();
865 while(sChar != xFontCharMap->GetLastChar())
866 {
867 UErrorCode errorCode = U_ZERO_ERROR;
868 char buffer[100];
869 u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
870 if (U_SUCCESS(errorCode))
871 {
872 OUString sName = OUString::createFromAscii(buffer);
873 if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
874 m_xSearchSet->AppendCharToList(sChar);
875 }
876 sChar = xFontCharMap->GetNextChar(sChar);
877 }
878 //for last char
879 UErrorCode errorCode = U_ZERO_ERROR;
880 char buffer[100];
881 u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
882 if (U_SUCCESS(errorCode))
883 {
884 OUString sName = OUString::createFromAscii(buffer);
885 if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
886 m_xSearchSet->AppendCharToList(sChar);
887 }
888 }
889 else
890 {
891 toggleSearchView(false);
892 }
893}
894
895
896IMPL_LINK(SvxCharacterMap, CharClickHdl, SvxCharView*, rView, void)
897{
898 rView->GrabFocus();
899
900 m_aShowChar.SetText( rView->GetText() );
901 m_aShowChar.SetFont(rView->GetFont());
902 m_aShowChar.Invalidate();
903
904 setFavButtonState(rView->GetText(), rView->GetFont().GetFamilyName());//check state
905
906 // Get the hexadecimal code
907 OUString charValue = rView->GetText();
908 sal_UCS4 cChar = charValue.iterateCodePoints(&o3tl::temporary(sal_Int32(1)), -1);
909 OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
910
911 // Get the decimal code
912 OUString aDecimalText = OUString::number(cChar);
913
914 m_xHexCodeText->set_text(aHexText);
915 m_xDecimalCodeText->set_text(aDecimalText);
916 setCharName(cChar);
917
918 rView->Invalidate();
919 m_xOKBtn->set_sensitive(true);
920}
921
923{
924 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
925 // using the new UCS4 constructor
926 OUString aOUStr( &cChar, 1 );
927 setFavButtonState(aOUStr, aFont.GetFamilyName());
928 insertCharToDoc(aOUStr);
929}
930
931IMPL_LINK_NOARG(SvxCharacterMap, SearchCharDoubleClickHdl, SvxShowCharSet*, void)
932{
933 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
934 // using the new UCS4 constructor
935 OUString aOUStr( &cChar, 1 );
936 setFavButtonState(aOUStr, aFont.GetFamilyName());
937 insertCharToDoc(aOUStr);
938}
939
941{
942 m_xOKBtn->set_sensitive(true);
943}
944
945IMPL_LINK_NOARG(SvxCharacterMap, SearchCharSelectHdl, SvxShowCharSet*, void)
946{
947 m_xOKBtn->set_sensitive(true);
948}
949
951{
952 OUString sChar = m_aShowChar.GetText();
953 insertCharToDoc(sChar);
954 // Need to update recent character list, when OK button does not insert
955 if(!m_xFrame.is())
956 updateRecentCharacterList(sChar, aFont.GetFamilyName());
957 m_xDialog->response(RET_OK);
958}
959
961{
962 if (m_xFavouritesBtn->get_label().match(CuiResId(RID_CUISTR_ADD_FAVORITES)))
963 {
964 updateFavCharacterList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
965 setFavButtonState(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
966 }
967 else
968 {
969 deleteFavCharacterFromList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
970 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES));
971 m_xFavouritesBtn->set_sensitive(false);
972 }
973
974 updateFavCharControl();
975}
976
978{
979 getFavCharacterList();
980 updateFavCharControl();
981}
982
984{
985 OUString aText;
986 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
987 bool bSelect = (cChar > 0);
988
989 // show char sample
990 if ( bSelect )
991 {
992 // using the new UCS4 constructor
993 aText = OUString( &cChar, 1 );
994 // Get the hexadecimal code
995 OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
996 // Get the decimal code
997 OUString aDecimalText = OUString::number(cChar);
998 setCharName(cChar);
999
1000 // Update the hex and decimal codes only if necessary
1001 if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
1002 m_xHexCodeText->set_text(aHexText);
1003 if (m_xDecimalCodeText->get_text() != aDecimalText)
1004 m_xDecimalCodeText->set_text( aDecimalText );
1005
1006 const Subset* pSubset = nullptr;
1007 if( pSubsetMap )
1008 pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1009 if( pSubset )
1010 m_xSubsetLB->set_active_text(pSubset->GetName());
1011 else
1012 m_xSubsetLB->set_active(-1);
1013 }
1014
1015 m_aShowChar.SetText( aText );
1016 m_aShowChar.SetFont( aFont );
1017 m_aShowChar.Invalidate();
1018
1019 setFavButtonState(aText, aFont.GetFamilyName());
1020}
1021
1022IMPL_LINK_NOARG(SvxCharacterMap, SearchCharHighlightHdl, SvxShowCharSet*, void)
1023{
1024 OUString aText;
1025 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
1026 bool bSelect = (cChar > 0);
1027
1028 // show char sample
1029 if ( bSelect )
1030 {
1031 aText = OUString( &cChar, 1 );
1032 // Get the hexadecimal code
1033 OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
1034 // Get the decimal code
1035 OUString aDecimalText = OUString::number(cChar);
1036 setCharName(cChar);
1037
1038 // Update the hex and decimal codes only if necessary
1039 if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
1040 m_xHexCodeText->set_text(aHexText);
1041 if (m_xDecimalCodeText->get_text() != aDecimalText)
1042 m_xDecimalCodeText->set_text( aDecimalText );
1043
1044 const Subset* pSubset = nullptr;
1045 if( pSubsetMap )
1046 pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1047 if( pSubset )
1048 m_xSubsetLB->set_active_text(pSubset->GetName());
1049 else
1050 m_xSubsetLB->set_active(-1);
1051 }
1052
1053 if(m_xSearchSet->HasFocus())
1054 {
1055 m_aShowChar.SetText( aText );
1056 m_aShowChar.SetFont( aFont );
1057 m_aShowChar.Invalidate();
1058
1059 setFavButtonState(aText, aFont.GetFamilyName());
1060 }
1061}
1062
1064{
1065 OUString aCodeString;
1066 switch(radix)
1067 {
1068 case Radix::decimal:
1069 aCodeString = m_xDecimalCodeText->get_text();
1070 break;
1071 case Radix::hexadecimal:
1072 aCodeString = m_xHexCodeText->get_text();
1073 break;
1074 }
1075 // Convert the code back to a character using the appropriate radix
1076 sal_UCS4 cChar = aCodeString.toUInt32(static_cast<sal_Int16> (radix));
1077 // Use FontCharMap::HasChar(sal_UCS4 cChar) to see if the desired character is in the font
1078 FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
1079 if (xFontCharMap->HasChar(cChar))
1080 // Select the corresponding character
1081 SetChar(cChar);
1082 else {
1083 m_xCharName->set_label(CuiResId(RID_CUISTR_MISSING_CHAR));
1084 m_aShowChar.SetText(" ");
1085 switch(radix)
1086 {
1087 case Radix::decimal:
1088 m_xHexCodeText->set_text(OUString::number(cChar, 16));
1089 break;
1090 case Radix::hexadecimal:
1091 m_xDecimalCodeText->set_text(OUString::number(cChar));
1092 break;
1093 }
1094 }
1095}
1096
1097IMPL_LINK_NOARG(SvxCharacterMap, DecimalCodeChangeHdl, weld::Entry&, void)
1098{
1099 selectCharByCode(Radix::decimal);
1100}
1101
1103{
1104 selectCharByCode(Radix::hexadecimal);
1105}
1106
1108{
1109 // adjust subset selection
1110 if( pSubsetMap )
1111 {
1112 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
1113
1114 setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName());
1115 const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1116 if( pSubset )
1117 m_xSubsetLB->set_active_text(pSubset->GetName());
1118 }
1119
1120 m_xOKBtn->set_sensitive(true);
1121}
1122
1123IMPL_LINK_NOARG(SvxCharacterMap, SearchCharPreSelectHdl, SvxShowCharSet*, void)
1124{
1125 // adjust subset selection
1126 if( pSubsetMap )
1127 {
1128 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
1129
1130 setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName());
1131 const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1132 if( pSubset )
1133 m_xSubsetLB->set_active_text(pSubset->GetName());
1134 }
1135
1136 m_xOKBtn->set_sensitive(true);
1137}
1138
1139// class SvxShowText =====================================================
1141 : m_xVirDev(rVirDev)
1142 , mnY(0)
1143 , mbCenter(false)
1144{
1145}
1146
1148{
1149 CustomWidgetController::SetDrawingArea(pDrawingArea);
1150 vcl::Font aFont = m_xVirDev->GetFont();
1151 Size aFontSize(aFont.GetFontSize().Width() * 5, aFont.GetFontSize().Height() * 5);
1152 aFont.SetFontSize(aFontSize);
1153 m_xVirDev->Push(PUSH_ALLFONT);
1154 m_xVirDev->SetFont(aFont);
1155 pDrawingArea->set_size_request(m_xVirDev->approximate_digit_width() + 2 * 12,
1156 m_xVirDev->LogicToPixel(aFontSize).Height() * 2);
1157 m_xVirDev->Pop();
1158}
1159
1161{
1162 rRenderContext.SetFont(m_aFont);
1163
1164 Color aTextCol = rRenderContext.GetTextColor();
1165 Color aFillCol = rRenderContext.GetFillColor();
1166
1167 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1168 const Color aWindowTextColor(rStyleSettings.GetDialogTextColor());
1169 const Color aWindowColor(rStyleSettings.GetWindowColor());
1170 rRenderContext.SetTextColor(aWindowTextColor);
1171 rRenderContext.SetFillColor(aWindowColor);
1172
1173 const OUString aText = GetText();
1174
1175 Size aSize(GetOutputSizePixel());
1176 tools::Long nAvailWidth = aSize.Width();
1177 tools::Long nWinHeight = aSize.Height();
1178
1179 bool bGotBoundary = true;
1180 bool bShrankFont = false;
1181 vcl::Font aOrigFont(rRenderContext.GetFont());
1182 Size aFontSize(aOrigFont.GetFontSize());
1183 ::tools::Rectangle aBoundRect;
1184
1185 for (tools::Long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 5)
1186 {
1187 if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty())
1188 {
1189 bGotBoundary = false;
1190 break;
1191 }
1192 if (!mbCenter)
1193 break;
1194 //only shrink in the single glyph large view mode
1195 tools::Long nTextWidth = aBoundRect.GetWidth();
1196 if (nAvailWidth > nTextWidth)
1197 break;
1198 vcl::Font aFont(aOrigFont);
1199 aFontSize.setHeight( nFontHeight );
1200 aFont.SetFontSize(aFontSize);
1201 rRenderContext.SetFont(aFont);
1202 mnY = (nWinHeight - rRenderContext.GetTextHeight()) / 2;
1203 bShrankFont = true;
1204 }
1205
1206 Point aPoint(2, mnY);
1207 // adjust position using ink boundary if possible
1208 if (!bGotBoundary)
1209 aPoint.setX( (aSize.Width() - rRenderContext.GetTextWidth(aText)) / 2 );
1210 else
1211 {
1212 // adjust position before it gets out of bounds
1213 aBoundRect += aPoint;
1214
1215 // shift back vertically if needed
1216 int nYLDelta = aBoundRect.Top();
1217 int nYHDelta = aSize.Height() - aBoundRect.Bottom();
1218 if( nYLDelta <= 0 )
1219 aPoint.AdjustY( -(nYLDelta - 1) );
1220 else if( nYHDelta <= 0 )
1221 aPoint.AdjustY(nYHDelta - 1 );
1222
1223 if (mbCenter)
1224 {
1225 // move glyph to middle of cell
1226 aPoint.setX( -aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2 );
1227 }
1228 else
1229 {
1230 // shift back horizontally if needed
1231 int nXLDelta = aBoundRect.Left();
1232 int nXHDelta = aSize.Width() - aBoundRect.Right();
1233 if( nXLDelta <= 0 )
1234 aPoint.AdjustX( -(nXLDelta - 1) );
1235 else if( nXHDelta <= 0 )
1236 aPoint.AdjustX(nXHDelta - 1 );
1237 }
1238 }
1239
1240 rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize));
1241 rRenderContext.DrawText(aPoint, aText);
1242 rRenderContext.SetTextColor(aTextCol);
1243 rRenderContext.SetFillColor(aFillCol);
1244 if (bShrankFont)
1245 rRenderContext.SetFont(aOrigFont);
1246}
1247
1249{
1250 tools::Long nWinHeight = GetOutputSizePixel().Height();
1251
1252 m_aFont = rFont;
1255 m_aFont.SetFontSize(m_xVirDev->PixelToLogic(Size(0, nWinHeight / 2)));
1256 m_aFont.SetTransparent(true);
1257
1258 m_xVirDev->Push(PUSH_ALLFONT);
1259 m_xVirDev->SetFont(m_aFont);
1260 mnY = (nWinHeight - m_xVirDev->GetTextHeight()) / 2;
1261 m_xVirDev->Pop();
1262
1263 Invalidate();
1264}
1265
1267{
1268 SetFont(GetFont()); //force recalculation of size
1269}
1270
1271void SvxShowText::SetText(const OUString& rText)
1272{
1273 m_sText = rText;
1274 Invalidate();
1275}
1276
1277/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define PUSH_ALLFONT
css::uno::Reference< css::lang::XComponent > m_xFrame
SfxApplication * SfxGetpApp()
Reference< XExecutableDialog > m_xDialog
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
sal_Int32 GetValue() const
const OUString & GetValue() const
const vcl::Font & GetFont() const
void SetFont(const vcl::Font &rNewFont)
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, o3tl::span< const sal_Int32 > pDXArray={}, o3tl::span< const sal_Bool > pKashidaArray={}, const SalLayoutGlyphs *pGlyphs=nullptr) const
void DrawRect(const tools::Rectangle &rRect)
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void SetTextColor(const Color &rColor)
void SetFillColor()
const Color & GetTextColor() const
tools::Long GetTextHeight() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
const Color & GetFillColor() const
bool GetValue() const
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
SfxItemPool * GetPool() const
constexpr tools::Long Height() const
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
const Color & GetWindowColor() const
const Color & GetDialogTextColor() const
const SubsetVec & GetSubsetMap() const
sal_UCS4 GetRangeMin() const
const OUString & GetName() const
vcl::Font const & GetFont() const
void setMouseClickHdl(const Link< SvxCharView *, void > &rLink)
void SetFont(const vcl::Font &rFont)
void SetHasInsert(bool bInsert)
void SetText(const OUString &rText)
void setClearClickHdl(const Link< SvxCharView *, void > &rLink)
void setClearAllClickHdl(const Link< SvxCharView *, void > &rLink)
The main purpose of this dialog is to enable the use of characters that are not easily accessible fro...
Definition: cuicharmap.hxx:77
void toggleSearchView(bool state)
Definition: cuicharmap.cxx:723
std::unique_ptr< SvxShowCharSet > m_xShowSet
Definition: cuicharmap.hxx:110
SvxShowText m_aShowChar
Definition: cuicharmap.hxx:93
vcl::Font aFont
Definition: cuicharmap.hxx:82
std::unique_ptr< weld::Label > m_xFontText
Definition: cuicharmap.hxx:96
std::unique_ptr< weld::Entry > m_xDecimalCodeText
Definition: cuicharmap.hxx:102
void getFavCharacterList()
Definition: cuicharmap.cxx:249
SvxCharView m_aFavCharView[16]
Definition: cuicharmap.hxx:92
std::deque< OUString > maRecentCharFontList
Definition: cuicharmap.hxx:87
void DisableFontSelection()
Definition: cuicharmap.cxx:219
ScopedVclPtr< VirtualDevice > m_xVirDev
Definition: cuicharmap.hxx:81
void updateFavCharacterList(const OUString &rChar, const OUString &rFont)
Definition: cuicharmap.cxx:364
std::unique_ptr< weld::ComboBox > m_xFontLB
Definition: cuicharmap.hxx:97
void updateRecentCharControl()
Definition: cuicharmap.cxx:302
std::pair< std::deque< OUString >::const_iterator, std::deque< OUString >::const_iterator > getRecentChar(std::u16string_view sTitle, std::u16string_view rFont) const
Definition: cuicharmap.cxx:290
std::unique_ptr< weld::Entry > m_xHexCodeText
Definition: cuicharmap.hxx:101
virtual short run() override
Definition: cuicharmap.cxx:187
bool isFavChar(std::u16string_view sTitle, std::u16string_view rFont)
Definition: cuicharmap.cxx:576
std::deque< OUString > maRecentCharList
Definition: cuicharmap.hxx:86
std::unique_ptr< weld::Label > m_xCharName
Definition: cuicharmap.hxx:104
const vcl::Font & GetCharFont() const
Definition: cuicharmap.hxx:160
void SetChar(sal_UCS4)
Definition: cuicharmap.cxx:208
void selectCharByCode(Radix radix)
SvxCharView m_aRecentCharView[16]
Definition: cuicharmap.hxx:91
std::unique_ptr< SvxSearchCharSet > m_xSearchSet
Definition: cuicharmap.hxx:112
void getRecentCharacterList()
Definition: cuicharmap.cxx:226
sal_UCS4 GetChar() const
Definition: cuicharmap.cxx:214
std::unique_ptr< weld::ComboBox > m_xSubsetLB
Definition: cuicharmap.hxx:99
void setCharName(sal_UCS4 nDecimalValue)
Definition: cuicharmap.cxx:742
void setFavButtonState(std::u16string_view sTitle, std::u16string_view rFont)
Definition: cuicharmap.cxx:583
std::unique_ptr< weld::Button > m_xOKBtn
Definition: cuicharmap.hxx:95
std::unique_ptr< weld::Widget > m_xRecentGrid
Definition: cuicharmap.hxx:105
std::unique_ptr< weld::Widget > m_xFavGrid
Definition: cuicharmap.hxx:106
void deleteFavCharacterFromList(std::u16string_view rChar, std::u16string_view rFont)
Definition: cuicharmap.cxx:428
void insertCharToDoc(const OUString &sChar)
Definition: cuicharmap.cxx:645
void SetCharFont(const vcl::Font &rFont)
Definition: cuicharmap.cxx:609
std::deque< OUString > maFavCharList
Definition: cuicharmap.hxx:88
void updateFavCharControl()
Definition: cuicharmap.cxx:401
css::uno::Reference< css::frame::XFrame > m_xFrame
Definition: cuicharmap.hxx:85
void updateRecentCharacterList(const OUString &rChar, const OUString &rFont)
Definition: cuicharmap.cxx:325
SvxCharacterMap(weld::Widget *pParent, const SfxItemSet *pSet, css::uno::Reference< css::frame::XFrame > xFrame)
Definition: cuicharmap.cxx:55
std::unique_ptr< weld::Entry > m_xSearchText
Definition: cuicharmap.hxx:100
std::unique_ptr< weld::Button > m_xFavouritesBtn
Definition: cuicharmap.hxx:103
std::unique_ptr< SfxAllItemSet > m_xOutputSet
Definition: cuicharmap.hxx:115
std::deque< OUString > maFavCharFontList
Definition: cuicharmap.hxx:89
static void fillAllSubsets(weld::ComboBox &rListBox)
Definition: cuicharmap.cxx:636
std::pair< std::deque< OUString >::const_iterator, std::deque< OUString >::const_iterator > getFavChar(std::u16string_view sTitle, std::u16string_view rFont) const
Definition: cuicharmap.cxx:296
FontPitch GetPitch() const
const OUString & GetStyleName() const
rtl_TextEncoding GetCharSet() const
const OUString & GetFamilyName() const
static sal_uInt32 & getSelectedChar()
SvxShowText(const VclPtr< VirtualDevice > &rVirDev)
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &) override
Size get_preferred_size() const
Definition: cuicharmap.hxx:71
void SetFont(const vcl::Font &rFont)
OUString m_sText
Definition: cuicharmap.hxx:53
tools::Long mnY
Definition: cuicharmap.hxx:54
vcl::Font m_aFont
Definition: cuicharmap.hxx:56
virtual void Resize() override
ScopedVclPtr< VirtualDevice > m_xVirDev
Definition: cuicharmap.hxx:52
vcl::Font const & GetFont() const
Definition: cuicharmap.hxx:66
void SetText(const OUString &rText)
OUString const & GetText() const
Definition: cuicharmap.hxx:68
void SetCentered(bool bCenter)
Definition: cuicharmap.hxx:69
virtual void SetDrawingArea(weld::DrawingArea *pDrawingArea) override
static std::shared_ptr< ConfigurationChanges > create()
constexpr tools::Long GetWidth() const
constexpr tools::Long Top() const
constexpr tools::Long Right() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
void SetFontSize(const Size &)
FontFamily GetFamilyType()
void SetPitch(FontPitch ePitch)
void SetTransparent(bool bTransparent)
const OUString & GetStyleName() const
void SetWeight(FontWeight)
const OUString & GetFamilyName() const
void SetFamily(FontFamily)
void SetCharSet(rtl_TextEncoding)
const Size & GetFontSize() const
void SetAlignment(TextAlign)
FontPitch GetPitch()
void SetFamilyName(const OUString &rFamilyName)
rtl_TextEncoding GetCharSet() const
virtual void insert_vector(const std::vector< weld::ComboBoxEntry > &rItems, bool bKeepExisting)=0
Size const & GetOutputSizePixel() const
virtual void set_size_request(int nWidth, int nHeight)=0
IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView *, rView, void)
Definition: cuicharmap.cxx:784
IMPL_LINK_NOARG(SvxCharacterMap, FontSelectHdl, weld::ComboBox &, void)
Definition: cuicharmap.cxx:670
static std::pair< std::deque< OUString >::const_iterator, std::deque< OUString >::const_iterator > findInPair(std::u16string_view str1, const std::deque< OUString > &rContainer1, std::u16string_view str2, const std::deque< OUString > &rContainer2)
Definition: cuicharmap.cxx:274
OUString CuiResId(TranslateId aKey)
Definition: cuiresmgr.cxx:23
int nCount
float u
ScXMLEditAttributeMap::Entry const aEntries[]
PITCH_DONTKNOW
ITALIC_NONE
WIDTH_DONTKNOW
ALIGN_TOP
FAMILY_DONTKNOW
WEIGHT_NORMAL
WEIGHT_DONTKNOW
sal_Int32 nIndex
sal_uInt16 nPos
const char * sName
sal_uInt16 GetFontSize(sal_uInt16 nPos)
bool dispatchCommand(const OUString &rCommand, const uno::Reference< css::frame::XFrame > &rFrame, const css::uno::Sequence< css::beans::PropertyValue > &rArguments, const uno::Reference< css::frame::XDispatchResultListener > &rListener)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
int i
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
constexpr T & temporary(T &&x)
long Long
OUString toId(const void *pValue)
Reference< XFrame > xFrame
RET_OK
sal_uInt32 sal_UCS4