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 <sal/config.h>
25 #include <vcl/svapp.hxx>
26 #include <svl/eitem.hxx>
27 #include <svl/intitem.hxx>
28 #include <svl/itempool.hxx>
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>
39 #include <comphelper/processfactory.hxx>
40 #include <comphelper/propertyvalue.hxx>
41 #include <comphelper/dispatchcommand.hxx>
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>
55 SvxCharacterMap::SvxCharacterMap(weld::Widget
* pParent
, const SfxItemSet
* pSet
,
56 css::uno::Reference
<css::frame::XFrame
> xFrame
)
57 : SfxDialogController(pParent
, "cui/ui/specialcharacters.ui", "SpecialCharactersDialog")
58 , m_xVirDev(VclPtr
<VirtualDevice
>::Create())
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
))
144 m_aShowChar
.SetCentered(true);
145 m_xFontLB
->make_sorted();
146 //lock the size request of this widget to the width of all possible entries
147 fillAllSubsets(*m_xSubsetLB
);
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());
158 const SfxInt32Item
* pCharItem
= SfxItemSet::GetItem
<SfxInt32Item
>(pSet
, SID_ATTR_CHAR
, false);
160 SetChar( pCharItem
->GetValue() );
162 const SfxBoolItem
* pDisableItem
= SfxItemSet::GetItem
<SfxBoolItem
>(pSet
, FN_PARAM_2
, false);
163 if ( pDisableItem
&& pDisableItem
->GetValue() )
164 DisableFontSelection();
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);
170 vcl::Font
aTmpFont( pFontItem
->GetFamilyName(), pFontItem
->GetStyleName(), GetCharFont().GetFontSize() );
171 aTmpFont
.SetCharSet( pFontItem
->GetCharSet() );
172 aTmpFont
.SetPitch( pFontItem
->GetPitch() );
173 SetCharFont( aTmpFont
);
175 else if ( pFontNameItem
)
177 vcl::Font
aTmpFont( GetCharFont() );
178 aTmpFont
.SetFamilyName( pFontNameItem
->GetValue() );
179 SetCharFont( aTmpFont
);
182 m_xOutputSet
.reset(new SfxAllItemSet(pSet
? *pSet
->GetPool() : SfxGetpApp()->GetPool()));
184 m_xSearchSet
->Hide();
187 short SvxCharacterMap::run()
189 if( SvxShowCharSet::getSelectedChar() == ' ')
191 m_xOKBtn
->set_sensitive(false);
192 setFavButtonState(u
"", u
"");
196 sal_UCS4 cChar
= m_xShowSet
->GetSelectCharacter();
197 // using the new UCS4 constructor
198 OUString
aOUStr( &cChar
, 1 );
199 m_aShowChar
.SetText(aOUStr
);
201 setFavButtonState(aOUStr
, m_aShowChar
.GetFont().GetFamilyName());
202 m_xOKBtn
->set_sensitive(true);
205 return SfxDialogController::run();
208 void SvxCharacterMap::SetChar( sal_UCS4 c
)
210 m_xShowSet
->SelectCharacter( c
);
211 setFavButtonState(OUString(&c
, 1), aFont
.GetFamilyName());
214 sal_UCS4
SvxCharacterMap::GetChar() const
216 return m_aShowChar
.GetText().iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
219 void SvxCharacterMap::DisableFontSelection()
221 m_xFontText
->set_sensitive(false);
222 m_xFontLB
->set_sensitive(false);
226 void SvxCharacterMap::getRecentCharacterList()
228 //retrieve recent character list
229 const css::uno::Sequence
< OUString
> rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() );
230 for (OUString
const & s
: rRecentCharList
)
232 maRecentCharList
.push_back(s
);
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
)
239 maRecentCharFontList
.push_back(s
);
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
);
249 void SvxCharacterMap::getFavCharacterList()
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
)
257 maFavCharList
.push_back(s
);
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
)
264 maFavCharFontList
.push_back(s
);
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
);
273 static std::pair
<std::deque
<OUString
>::const_iterator
, std::deque
<OUString
>::const_iterator
>
274 findInPair(std::u16string_view str1
, const std::deque
<OUString
>& rContainer1
,
275 std::u16string_view str2
, const std::deque
<OUString
>& rContainer2
)
277 assert(rContainer1
.size() == rContainer2
.size());
279 for (auto it1
= std::find(rContainer1
.begin(), rContainer1
.end(), str1
);
280 it1
!= rContainer1
.end(); it1
= std::find(std::next(it1
), rContainer1
.end(), str1
))
282 auto it2
= rContainer2
.begin() + (it1
- rContainer1
.begin());
286 return { rContainer1
.end(), rContainer2
.end() };
289 std::pair
<std::deque
<OUString
>::const_iterator
, std::deque
<OUString
>::const_iterator
>
290 SvxCharacterMap::getRecentChar(std::u16string_view sTitle
, std::u16string_view rFont
) const
292 return findInPair(sTitle
, maRecentCharList
, rFont
, maRecentCharFontList
);
295 std::pair
<std::deque
<OUString
>::const_iterator
, std::deque
<OUString
>::const_iterator
>
296 SvxCharacterMap::getFavChar(std::u16string_view sTitle
, std::u16string_view rFont
) const
298 return findInPair(sTitle
, maFavCharList
, rFont
, maFavCharFontList
);
302 void SvxCharacterMap::updateRecentCharControl()
304 assert(maRecentCharList
.size() == maRecentCharFontList
.size());
307 for ( std::deque
< OUString
>::iterator it
= maRecentCharList
.begin(), it2
= maRecentCharFontList
.begin();
308 it
!= maRecentCharList
.end() && it2
!= maRecentCharFontList
.end();
311 m_aRecentCharView
[i
].SetText(*it
);
312 vcl::Font rFont
= m_aRecentCharView
[i
].GetFont();
313 rFont
.SetFamilyName( *it2
);
314 m_aRecentCharView
[i
].SetFont(rFont
);
315 m_aRecentCharView
[i
].Show();
320 m_aRecentCharView
[i
].SetText(OUString());
321 m_aRecentCharView
[i
].Hide();
325 void SvxCharacterMap::updateRecentCharacterList(const OUString
& sTitle
, const OUString
& rFont
)
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() )
331 maRecentCharList
.erase( itChar
);
332 maRecentCharFontList
.erase( itChar2
);
335 if (maRecentCharList
.size() == 16)
337 maRecentCharList
.pop_back();
338 maRecentCharFontList
.pop_back();
341 maRecentCharList
.push_front(sTitle
);
342 maRecentCharFontList
.push_front(rFont
);
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
);
349 for (size_t i
= 0; i
< maRecentCharList
.size(); ++i
)
351 aRecentCharListRange
[i
] = maRecentCharList
[i
];
352 aRecentCharFontListRange
[i
] = maRecentCharFontList
[i
];
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
);
360 updateRecentCharControl();
364 void SvxCharacterMap::updateFavCharacterList(const OUString
& sTitle
, const OUString
& rFont
)
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() )
370 maFavCharList
.erase( itChar
);
371 maFavCharFontList
.erase( itChar2
);
374 if (maFavCharList
.size() == 16)
376 maFavCharList
.pop_back();
377 maFavCharFontList
.pop_back();
380 maFavCharList
.push_back(sTitle
);
381 maFavCharFontList
.push_back(rFont
);
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
);
388 for (size_t i
= 0; i
< maFavCharList
.size(); ++i
)
390 aFavCharListRange
[i
] = maFavCharList
[i
];
391 aFavCharFontListRange
[i
] = maFavCharFontList
[i
];
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
);
401 void SvxCharacterMap::updateFavCharControl()
403 assert(maFavCharList
.size() == maFavCharFontList
.size());
406 for ( std::deque
< OUString
>::iterator it
= maFavCharList
.begin(), it2
= maFavCharFontList
.begin();
407 it
!= maFavCharList
.end() && it2
!= maFavCharFontList
.end();
410 m_aFavCharView
[i
].SetText(*it
);
411 vcl::Font rFont
= m_aFavCharView
[i
].GetFont();
412 rFont
.SetFamilyName( *it2
);
413 m_aFavCharView
[i
].SetFont(rFont
);
414 m_aFavCharView
[i
].Show();
419 m_aFavCharView
[i
].SetText(OUString());
420 m_aFavCharView
[i
].Hide();
422 m_xShowSet
->getFavCharacterList();
423 m_xSearchSet
->getFavCharacterList();
424 // tdf#109214 - redraw highlight of the favorite characters
425 m_xShowSet
->Invalidate();
428 void SvxCharacterMap::deleteFavCharacterFromList(std::u16string_view sTitle
, std::u16string_view rFont
)
430 // if Fav char is found, remove it
431 if( const auto& [itChar
, itChar2
] = getFavChar(sTitle
, rFont
);
432 itChar
!= maFavCharList
.end() && itChar2
!= maFavCharFontList
.end() )
434 maFavCharList
.erase( itChar
);
435 maFavCharFontList
.erase( itChar2
);
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
);
443 for (size_t i
= 0; i
< maFavCharList
.size(); ++i
)
445 aFavCharListRange
[i
] = maFavCharList
[i
];
446 aFavCharFontListRange
[i
] = maFavCharFontList
[i
];
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
);
455 void SvxCharacterMap::init()
457 aFont
= m_xVirDev
->GetFont();
458 aFont
.SetTransparent( true );
459 aFont
.SetFamily( FAMILY_DONTKNOW
);
460 aFont
.SetPitch( PITCH_DONTKNOW
);
461 aFont
.SetCharSet( RTL_TEXTENCODING_DONTKNOW
);
463 OUString
aDefStr( aFont
.GetFamilyName() );
465 int nCount
= m_xVirDev
->GetFontFaceCollectionCount();
466 std::vector
<weld::ComboBoxEntry
> aEntries
;
467 aEntries
.reserve(nCount
);
468 for (int i
= 0; i
< nCount
; ++i
)
470 OUString
aFontName( m_xVirDev
->GetFontMetricFromCollection( i
).GetFamilyName() );
471 if (aFontName
!= aLastName
)
473 aLastName
= aFontName
;
474 aEntries
.emplace_back(aFontName
, OUString::number(i
));
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);
484 sal_Int32 nIndex
= 0;
487 OUString aToken
= aDefStr
.getToken(0, ';', nIndex
);
488 if (m_xFontLB
->find_text(aToken
) != -1)
495 while ( nIndex
>= 0 );
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);
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
));
511 m_xShowSet
->SetDoubleClickHdl( LINK( this, SvxCharacterMap
, CharDoubleClickHdl
) );
512 m_xShowSet
->SetReturnKeyPressHdl(LINK(this, SvxCharacterMap
, ReturnKeypressOnCharHdl
));
513 m_xShowSet
->SetSelectHdl( LINK( this, SvxCharacterMap
, CharSelectHdl
) );
514 m_xShowSet
->SetHighlightHdl( LINK( this, SvxCharacterMap
, CharHighlightHdl
) );
515 m_xShowSet
->SetPreSelectHdl( LINK( this, SvxCharacterMap
, CharPreSelectHdl
) );
516 m_xShowSet
->SetFavClickHdl( LINK( this, SvxCharacterMap
, FavClickHdl
) );
518 m_xSearchSet
->SetDoubleClickHdl( LINK( this, SvxCharacterMap
, CharDoubleClickHdl
) );
519 m_xSearchSet
->SetReturnKeyPressHdl(LINK(this, SvxCharacterMap
, ReturnKeypressOnCharHdl
));
520 m_xSearchSet
->SetSelectHdl( LINK( this, SvxCharacterMap
, CharSelectHdl
) );
521 m_xSearchSet
->SetHighlightHdl( LINK( this, SvxCharacterMap
, SearchCharHighlightHdl
) );
522 m_xSearchSet
->SetPreSelectHdl( LINK( this, SvxCharacterMap
, CharPreSelectHdl
) );
523 m_xSearchSet
->SetFavClickHdl( LINK( this, SvxCharacterMap
, FavClickHdl
) );
525 m_xDecimalCodeText
->connect_changed( LINK( this, SvxCharacterMap
, DecimalCodeChangeHdl
) );
526 m_xHexCodeText
->connect_changed( LINK( this, SvxCharacterMap
, HexCodeChangeHdl
) );
527 m_xFavouritesBtn
->connect_clicked( LINK(this, SvxCharacterMap
, FavSelectHdl
));
529 // tdf#117038 set the buttons width to its max possible width so it doesn't
530 // make layout change when the label changes
531 m_xFavouritesBtn
->set_label(CuiResId(RID_CUISTR_REMOVE_FAVORITES
));
532 auto nMaxWidth
= m_xFavouritesBtn
->get_preferred_size().Width();
533 m_xFavouritesBtn
->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES
));
534 nMaxWidth
= std::max(nMaxWidth
, m_xFavouritesBtn
->get_preferred_size().Width());
535 m_xFavouritesBtn
->set_size_request(nMaxWidth
, -1);
537 if( SvxShowCharSet::getSelectedChar() == ' ')
539 m_xOKBtn
->set_sensitive(false);
543 sal_UCS4 cChar
= m_xShowSet
->GetSelectCharacter();
544 // using the new UCS4 constructor
545 OUString
aOUStr( &cChar
, 1 );
546 m_aShowChar
.SetText(aOUStr
);
548 setFavButtonState(aOUStr
, aDefStr
);
549 m_xOKBtn
->set_sensitive(true);
552 getRecentCharacterList();
553 updateRecentCharControl();
555 getFavCharacterList();
556 updateFavCharControl();
558 bool bHasInsert
= m_xFrame
.is();
560 for(int i
= 0; i
< 16; i
++)
562 m_aRecentCharView
[i
].SetHasInsert(bHasInsert
);
563 m_aRecentCharView
[i
].setMouseClickHdl(LINK(this,SvxCharacterMap
, CharClickHdl
));
564 m_aRecentCharView
[i
].setClearClickHdl(LINK(this,SvxCharacterMap
, RecentClearClickHdl
));
565 m_aRecentCharView
[i
].setClearAllClickHdl(LINK(this,SvxCharacterMap
, RecentClearAllClickHdl
));
566 m_aFavCharView
[i
].SetHasInsert(bHasInsert
);
567 m_aFavCharView
[i
].setMouseClickHdl(LINK(this,SvxCharacterMap
, CharClickHdl
));
568 m_aFavCharView
[i
].setClearClickHdl(LINK(this,SvxCharacterMap
, FavClearClickHdl
));
569 m_aFavCharView
[i
].setClearAllClickHdl(LINK(this,SvxCharacterMap
, FavClearAllClickHdl
));
574 m_xSearchText
->connect_focus_in(LINK( this, SvxCharacterMap
, SearchFieldGetFocusHdl
));
575 m_xSearchText
->connect_changed(LINK(this, SvxCharacterMap
, SearchUpdateHdl
));
578 bool SvxCharacterMap::isFavChar(std::u16string_view sTitle
, std::u16string_view rFont
)
580 const auto& [itChar
, itFont
] = getFavChar(sTitle
, rFont
);
581 return itChar
!= maFavCharList
.end() && itFont
!= maFavCharFontList
.end();
585 void SvxCharacterMap::setFavButtonState(std::u16string_view sTitle
, std::u16string_view rFont
)
587 if(sTitle
.empty() || rFont
.empty())
589 m_xFavouritesBtn
->set_sensitive(false);
593 m_xFavouritesBtn
->set_sensitive(true);
595 if (isFavChar(sTitle
, rFont
))
597 m_xFavouritesBtn
->set_label(CuiResId(RID_CUISTR_REMOVE_FAVORITES
));
601 if(maFavCharList
.size() == 16)
603 m_xFavouritesBtn
->set_sensitive(false);
606 m_xFavouritesBtn
->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES
));
611 void SvxCharacterMap::SetCharFont( const vcl::Font
& rFont
)
613 // first get the underlying info in order to get font names
614 // like "Times New Roman;Times" resolved
615 vcl::Font
aTmp(m_xVirDev
->GetFontMetric(rFont
));
617 // tdf#56363 - search font family without the font feature after the colon
618 OUString sFontFamilyName
= aTmp
.GetFamilyName();
619 if (const sal_Int32 nIndex
= sFontFamilyName
.indexOf(":"); nIndex
!= -1)
620 sFontFamilyName
= sFontFamilyName
.copy(0, nIndex
);
621 if (sFontFamilyName
== "StarSymbol" && m_xFontLB
->find_text(sFontFamilyName
) == -1)
623 //if for some reason, like font in an old document, StarSymbol is requested and it's not available, then
624 //try OpenSymbol instead
625 aTmp
.SetFamilyName("OpenSymbol");
628 if (m_xFontLB
->find_text(sFontFamilyName
) == -1)
631 m_xFontLB
->set_active_text(sFontFamilyName
);
633 FontSelectHdl(*m_xFontLB
);
634 if (m_xSubsetLB
->get_count())
635 m_xSubsetLB
->set_active(0);
638 void SvxCharacterMap::fillAllSubsets(weld::ComboBox
& rListBox
)
640 SubsetMap
aAll(nullptr);
641 std::vector
<weld::ComboBoxEntry
> aEntries
;
642 for (auto & subset
: aAll
.GetSubsetMap())
643 aEntries
.emplace_back(subset
.GetName());
644 rListBox
.insert_vector(aEntries
, true);
647 void SvxCharacterMap::insertCharToDoc(const OUString
& sGlyph
)
653 uno::Sequence
<beans::PropertyValue
> aArgs
{
654 comphelper::makePropertyValue("Symbols", sGlyph
),
655 comphelper::makePropertyValue("FontName", aFont
.GetFamilyName())
657 comphelper::dispatchCommand(".uno:InsertSymbol", m_xFrame
, aArgs
);
659 updateRecentCharacterList(sGlyph
, aFont
.GetFamilyName());
662 sal_UCS4 cChar
= sGlyph
.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
663 const SfxItemPool
* pPool
= m_xOutputSet
->GetPool();
664 m_xOutputSet
->Put( SfxStringItem( SID_CHARMAP
, sGlyph
) );
665 m_xOutputSet
->Put( SvxFontItem( aFont
.GetFamilyType(), aFont
.GetFamilyName(),
666 aFont
.GetStyleName(), aFont
.GetPitch(), aFont
.GetCharSet(), pPool
->GetWhich(SID_ATTR_CHAR_FONT
) ) );
667 m_xOutputSet
->Put( SfxStringItem( SID_FONT_NAME
, aFont
.GetFamilyName() ) );
668 m_xOutputSet
->Put( SfxInt32Item( SID_ATTR_CHAR
, cChar
) );
672 IMPL_LINK_NOARG(SvxCharacterMap
, FontSelectHdl
, weld::ComboBox
&, void)
674 const sal_uInt32 nFont
= m_xFontLB
->get_active_id().toUInt32();
675 aFont
= m_xVirDev
->GetFontMetricFromCollection(nFont
);
676 aFont
.SetWeight( WEIGHT_DONTKNOW
);
677 aFont
.SetItalic( ITALIC_NONE
);
678 aFont
.SetWidthType( WIDTH_DONTKNOW
);
679 aFont
.SetPitch( PITCH_DONTKNOW
);
680 aFont
.SetFamily( FAMILY_DONTKNOW
);
682 // notify children using this font
683 m_xShowSet
->SetFont( aFont
);
684 m_xSearchSet
->SetFont( aFont
);
685 m_aShowChar
.SetFont( aFont
);
687 // setup unicode subset listbar with font specific subsets,
688 // hide unicode subset listbar for symbol fonts
689 // TODO: get info from the Font once it provides it
691 m_xSubsetLB
->clear();
693 bool bNeedSubset
= (aFont
.GetCharSet() != RTL_TEXTENCODING_SYMBOL
);
696 FontCharMapRef xFontCharMap
= m_xShowSet
->GetFontCharMap();
697 pSubsetMap
.reset(new SubsetMap( xFontCharMap
));
699 // update subset listbox for new font's unicode subsets
700 for (auto const& subset
: pSubsetMap
->GetSubsetMap())
702 m_xSubsetLB
->append(weld::toId(&subset
), subset
.GetName());
703 // NOTE: subset must live at least as long as the selected font
706 if (m_xSubsetLB
->get_count() <= 1)
710 m_xSubsetText
->set_sensitive(bNeedSubset
);
711 m_xSubsetLB
->set_sensitive(bNeedSubset
);
715 // tdf#137294 do this after modifying m_xSubsetLB sensitivity to
716 // restore insensitive for the search case
717 SearchUpdateHdl(*m_xSearchText
);
718 SearchCharHighlightHdl(m_xSearchSet
.get());
721 // tdf#118304 reselect current glyph to see if it's still there in new font
722 selectCharByCode(Radix::hexadecimal
);
725 void SvxCharacterMap::toggleSearchView(bool state
)
727 isSearchMode
= state
;
728 m_xHexCodeText
->set_editable(!state
);
729 m_xDecimalCodeText
->set_editable(!state
);
730 m_xSubsetLB
->set_sensitive(!state
);
734 m_xSearchSet
->Show();
739 m_xSearchSet
->Hide();
744 void SvxCharacterMap::setCharName(sal_UCS4 nDecimalValue
)
746 /* get the character name */
747 UErrorCode errorCode
= U_ZERO_ERROR
;
748 // icu has a private uprv_getMaxCharNameLength function which returns the max possible
749 // length of this property. Unicode 3.2 max char name length was 83
751 u_charName(nDecimalValue
, U_UNICODE_CHAR_NAME
, buffer
, sizeof(buffer
), &errorCode
);
752 if (U_SUCCESS(errorCode
))
753 m_xCharName
->set_label(OUString::createFromAscii(buffer
));
756 IMPL_LINK_NOARG(SvxCharacterMap
, SubsetSelectHdl
, weld::ComboBox
&, void)
758 const sal_Int32 nPos
= m_xSubsetLB
->get_active();
759 const Subset
* pSubset
= weld::fromId
<const Subset
*>(m_xSubsetLB
->get_active_id());
761 if( pSubset
&& !isSearchMode
)
763 sal_UCS4 cFirst
= pSubset
->GetRangeMin();
764 m_xShowSet
->SelectCharacter( cFirst
);
766 setFavButtonState(OUString(&cFirst
, 1), aFont
.GetFamilyName());
767 m_xSubsetLB
->set_active(nPos
);
769 else if( pSubset
&& isSearchMode
)
771 m_xSearchSet
->SelectCharacter( pSubset
);
773 const Subset
* curSubset
= nullptr;
775 curSubset
= pSubsetMap
->GetSubsetByUnicode( m_xSearchSet
->GetSelectCharacter() );
777 m_xSubsetLB
->set_active_text(curSubset
->GetName());
779 m_xSubsetLB
->set_active(-1);
781 sal_UCS4 sChar
= m_xSearchSet
->GetSelectCharacter();
782 setFavButtonState(OUString(&sChar
, 1), aFont
.GetFamilyName());
786 IMPL_LINK(SvxCharacterMap
, RecentClearClickHdl
, SvxCharView
*, rView
, void)
788 const OUString
& sTitle
= rView
->GetText();
789 OUString sFont
= rView
->GetFont().GetFamilyName();
791 // if recent char to be added is already in list, remove it
792 if( const auto& [itChar
, itChar2
] = getRecentChar(sTitle
, sFont
);
793 itChar
!= maRecentCharList
.end() && itChar2
!= maRecentCharFontList
.end() )
795 maRecentCharList
.erase( itChar
);
796 maRecentCharFontList
.erase( itChar2
);
799 css::uno::Sequence
< OUString
> aRecentCharList(maRecentCharList
.size());
800 auto aRecentCharListRange
= asNonConstRange(aRecentCharList
);
801 css::uno::Sequence
< OUString
> aRecentCharFontList(maRecentCharFontList
.size());
802 auto aRecentCharFontListRange
= asNonConstRange(aRecentCharFontList
);
804 for (size_t i
= 0; i
< maRecentCharList
.size(); ++i
)
806 aRecentCharListRange
[i
] = maRecentCharList
[i
];
807 aRecentCharFontListRange
[i
] = maRecentCharFontList
[i
];
810 std::shared_ptr
<comphelper::ConfigurationChanges
> batch(comphelper::ConfigurationChanges::create());
811 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList
, batch
);
812 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList
, batch
);
815 updateRecentCharControl();
818 IMPL_LINK_NOARG(SvxCharacterMap
, RecentClearAllClickHdl
, SvxCharView
*, void)
820 maRecentCharList
.clear();
821 maRecentCharFontList
.clear();
823 std::shared_ptr
<comphelper::ConfigurationChanges
> batch(comphelper::ConfigurationChanges::create());
824 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set({ }, batch
);
825 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set({ }, batch
);
828 updateRecentCharControl();
831 IMPL_LINK(SvxCharacterMap
, FavClearClickHdl
, SvxCharView
*, rView
, void)
833 deleteFavCharacterFromList(rView
->GetText(), rView
->GetFont().GetFamilyName());
834 updateFavCharControl();
837 IMPL_LINK_NOARG(SvxCharacterMap
, FavClearAllClickHdl
, SvxCharView
*, void)
839 maFavCharList
.clear();
840 maFavCharFontList
.clear();
842 std::shared_ptr
<comphelper::ConfigurationChanges
> batch(comphelper::ConfigurationChanges::create());
843 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set({ }, batch
);
844 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set({ }, batch
);
847 updateFavCharControl();
850 IMPL_LINK_NOARG(SvxCharacterMap
, SearchFieldGetFocusHdl
, weld::Widget
&, void)
852 m_xOKBtn
->set_sensitive(false);
855 IMPL_LINK_NOARG(SvxCharacterMap
, SearchUpdateHdl
, weld::Entry
&, void)
857 if (!m_xSearchText
->get_text().isEmpty())
859 m_xSearchSet
->ClearPreviousData();
860 OUString aKeyword
= m_xSearchText
->get_text();
862 toggleSearchView(true);
864 FontCharMapRef xFontCharMap
= m_xSearchSet
->GetFontCharMap();
866 sal_UCS4 sChar
= xFontCharMap
->GetFirstChar();
867 while(sChar
!= xFontCharMap
->GetLastChar())
869 UErrorCode errorCode
= U_ZERO_ERROR
;
871 u_charName(sChar
, U_UNICODE_CHAR_NAME
, buffer
, sizeof(buffer
), &errorCode
);
872 if (U_SUCCESS(errorCode
))
874 OUString sName
= OUString::createFromAscii(buffer
);
875 if(!sName
.isEmpty() && sName
.toAsciiLowerCase().indexOf(aKeyword
.toAsciiLowerCase()) >= 0)
876 m_xSearchSet
->AppendCharToList(sChar
);
878 sChar
= xFontCharMap
->GetNextChar(sChar
);
881 UErrorCode errorCode
= U_ZERO_ERROR
;
883 u_charName(sChar
, U_UNICODE_CHAR_NAME
, buffer
, sizeof(buffer
), &errorCode
);
884 if (U_SUCCESS(errorCode
))
886 OUString sName
= OUString::createFromAscii(buffer
);
887 if(!sName
.isEmpty() && sName
.toAsciiLowerCase().indexOf(aKeyword
.toAsciiLowerCase()) >= 0)
888 m_xSearchSet
->AppendCharToList(sChar
);
891 m_xSearchSet
->UpdateScrollRange();
895 toggleSearchView(false);
900 IMPL_LINK(SvxCharacterMap
, CharClickHdl
, SvxCharView
*, rView
, void)
904 m_aShowChar
.SetText( rView
->GetText() );
905 m_aShowChar
.SetFont(rView
->GetFont());
906 m_aShowChar
.Invalidate();
908 setFavButtonState(rView
->GetText(), rView
->GetFont().GetFamilyName());//check state
910 // Get the hexadecimal code
911 OUString charValue
= rView
->GetText();
912 sal_UCS4 cChar
= charValue
.iterateCodePoints(&o3tl::temporary(sal_Int32(1)), -1);
913 OUString aHexText
= OUString::number(cChar
, 16).toAsciiUpperCase();
915 // Get the decimal code
916 OUString aDecimalText
= OUString::number(cChar
);
918 m_xHexCodeText
->set_text(aHexText
);
919 m_xDecimalCodeText
->set_text(aDecimalText
);
923 m_xOKBtn
->set_sensitive(true);
926 void SvxCharacterMap::insertSelectedCharacter(const SvxShowCharSet
* pCharSet
)
929 sal_UCS4 cChar
= pCharSet
->GetSelectCharacter();
930 // using the new UCS4 constructor
931 OUString
aOUStr( &cChar
, 1 );
932 setFavButtonState(aOUStr
, aFont
.GetFamilyName());
933 insertCharToDoc(aOUStr
);
936 IMPL_LINK(SvxCharacterMap
, CharDoubleClickHdl
, SvxShowCharSet
*, pCharSet
, void)
938 insertSelectedCharacter(pCharSet
);
941 IMPL_LINK_NOARG(SvxCharacterMap
, CharSelectHdl
, SvxShowCharSet
*, void)
943 m_xOKBtn
->set_sensitive(true);
946 IMPL_LINK(SvxCharacterMap
, ReturnKeypressOnCharHdl
, SvxShowCharSet
*, pCharSet
, void)
948 insertSelectedCharacter(pCharSet
);
949 m_xDialog
->response(RET_OK
);
952 IMPL_LINK_NOARG(SvxCharacterMap
, InsertClickHdl
, weld::Button
&, void)
954 OUString sChar
= m_aShowChar
.GetText();
955 insertCharToDoc(sChar
);
956 // Need to update recent character list, when OK button does not insert
958 updateRecentCharacterList(sChar
, aFont
.GetFamilyName());
959 m_xDialog
->response(RET_OK
);
962 IMPL_LINK_NOARG(SvxCharacterMap
, FavSelectHdl
, weld::Button
&, void)
964 if (m_xFavouritesBtn
->get_label().match(CuiResId(RID_CUISTR_ADD_FAVORITES
)))
966 updateFavCharacterList(m_aShowChar
.GetText(), m_aShowChar
.GetFont().GetFamilyName());
967 setFavButtonState(m_aShowChar
.GetText(), m_aShowChar
.GetFont().GetFamilyName());
971 deleteFavCharacterFromList(m_aShowChar
.GetText(), m_aShowChar
.GetFont().GetFamilyName());
972 m_xFavouritesBtn
->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES
));
973 m_xFavouritesBtn
->set_sensitive(false);
976 updateFavCharControl();
979 IMPL_LINK_NOARG(SvxCharacterMap
, FavClickHdl
, SvxShowCharSet
*, void)
981 getFavCharacterList();
982 updateFavCharControl();
985 IMPL_LINK_NOARG(SvxCharacterMap
, CharHighlightHdl
, SvxShowCharSet
*, void)
988 sal_UCS4 cChar
= m_xShowSet
->GetSelectCharacter();
989 bool bSelect
= (cChar
> 0);
994 // using the new UCS4 constructor
995 aText
= OUString( &cChar
, 1 );
996 // Get the hexadecimal code
997 OUString aHexText
= OUString::number(cChar
, 16).toAsciiUpperCase();
998 // Get the decimal code
999 OUString aDecimalText
= OUString::number(cChar
);
1002 // Update the hex and decimal codes only if necessary
1003 if (!m_xHexCodeText
->get_text().equalsIgnoreAsciiCase(aHexText
))
1004 m_xHexCodeText
->set_text(aHexText
);
1005 if (m_xDecimalCodeText
->get_text() != aDecimalText
)
1006 m_xDecimalCodeText
->set_text( aDecimalText
);
1008 const Subset
* pSubset
= nullptr;
1010 pSubset
= pSubsetMap
->GetSubsetByUnicode( cChar
);
1012 m_xSubsetLB
->set_active_text(pSubset
->GetName());
1014 m_xSubsetLB
->set_active(-1);
1017 m_aShowChar
.SetText( aText
);
1018 m_aShowChar
.SetFont( aFont
);
1019 m_aShowChar
.Invalidate();
1021 setFavButtonState(aText
, aFont
.GetFamilyName());
1024 IMPL_LINK_NOARG(SvxCharacterMap
, SearchCharHighlightHdl
, SvxShowCharSet
*, void)
1027 sal_UCS4 cChar
= m_xSearchSet
->GetSelectCharacter();
1028 bool bSelect
= (cChar
> 0);
1033 aText
= OUString( &cChar
, 1 );
1034 // Get the hexadecimal code
1035 OUString aHexText
= OUString::number(cChar
, 16).toAsciiUpperCase();
1036 // Get the decimal code
1037 OUString aDecimalText
= OUString::number(cChar
);
1040 // Update the hex and decimal codes only if necessary
1041 if (!m_xHexCodeText
->get_text().equalsIgnoreAsciiCase(aHexText
))
1042 m_xHexCodeText
->set_text(aHexText
);
1043 if (m_xDecimalCodeText
->get_text() != aDecimalText
)
1044 m_xDecimalCodeText
->set_text( aDecimalText
);
1046 const Subset
* pSubset
= nullptr;
1048 pSubset
= pSubsetMap
->GetSubsetByUnicode( cChar
);
1050 m_xSubsetLB
->set_active_text(pSubset
->GetName());
1052 m_xSubsetLB
->set_active(-1);
1055 if(m_xSearchSet
->HasFocus())
1057 m_aShowChar
.SetText( aText
);
1058 m_aShowChar
.SetFont( aFont
);
1059 m_aShowChar
.Invalidate();
1061 setFavButtonState(aText
, aFont
.GetFamilyName());
1065 void SvxCharacterMap::selectCharByCode(Radix radix
)
1067 OUString aCodeString
;
1070 case Radix::decimal
:
1071 aCodeString
= m_xDecimalCodeText
->get_text();
1073 case Radix::hexadecimal
:
1074 aCodeString
= m_xHexCodeText
->get_text();
1077 // Convert the code back to a character using the appropriate radix
1078 sal_UCS4 cChar
= aCodeString
.toUInt32(static_cast<sal_Int16
> (radix
));
1079 // Use FontCharMap::HasChar(sal_UCS4 cChar) to see if the desired character is in the font
1080 FontCharMapRef xFontCharMap
= m_xShowSet
->GetFontCharMap();
1081 if (xFontCharMap
->HasChar(cChar
))
1082 // Select the corresponding character
1085 m_xCharName
->set_label(CuiResId(RID_CUISTR_MISSING_CHAR
));
1086 m_aShowChar
.SetText(" ");
1089 case Radix::decimal
:
1090 m_xHexCodeText
->set_text(OUString::number(cChar
, 16));
1092 case Radix::hexadecimal
:
1093 m_xDecimalCodeText
->set_text(OUString::number(cChar
));
1099 IMPL_LINK_NOARG(SvxCharacterMap
, DecimalCodeChangeHdl
, weld::Entry
&, void)
1101 selectCharByCode(Radix::decimal
);
1104 IMPL_LINK_NOARG(SvxCharacterMap
, HexCodeChangeHdl
, weld::Entry
&, void)
1106 selectCharByCode(Radix::hexadecimal
);
1109 IMPL_LINK(SvxCharacterMap
, CharPreSelectHdl
, SvxShowCharSet
*, pCharSet
, void)
1112 // adjust subset selection
1115 sal_UCS4 cChar
= pCharSet
->GetSelectCharacter();
1117 setFavButtonState(OUString(&cChar
, 1), aFont
.GetFamilyName());
1118 const Subset
* pSubset
= pSubsetMap
->GetSubsetByUnicode( cChar
);
1120 m_xSubsetLB
->set_active_text(pSubset
->GetName());
1123 m_xOKBtn
->set_sensitive(true);
1126 // class SvxShowText =====================================================
1127 SvxShowText::SvxShowText(const VclPtr
<VirtualDevice
>& rVirDev
)
1128 : m_xVirDev(rVirDev
)
1134 void SvxShowText::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
1136 CustomWidgetController::SetDrawingArea(pDrawingArea
);
1137 vcl::Font aFont
= m_xVirDev
->GetFont();
1138 Size
aFontSize(aFont
.GetFontSize().Width() * 5, aFont
.GetFontSize().Height() * 5);
1139 aFont
.SetFontSize(aFontSize
);
1140 m_xVirDev
->Push(PUSH_ALLFONT
);
1141 m_xVirDev
->SetFont(aFont
);
1142 pDrawingArea
->set_size_request(m_xVirDev
->approximate_digit_width() + 2 * 12,
1143 m_xVirDev
->LogicToPixel(aFontSize
).Height() * 2);
1147 void SvxShowText::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
1149 rRenderContext
.SetFont(m_aFont
);
1151 Color aTextCol
= rRenderContext
.GetTextColor();
1152 Color aFillCol
= rRenderContext
.GetFillColor();
1153 Color aLineCol
= rRenderContext
.GetLineColor();
1155 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
1156 const Color
aWindowTextColor(rStyleSettings
.GetDialogTextColor());
1157 const Color
aWindowColor(rStyleSettings
.GetWindowColor());
1158 const Color
aShadowColor(rStyleSettings
.GetShadowColor());
1159 rRenderContext
.SetTextColor(aWindowTextColor
);
1160 rRenderContext
.SetFillColor(aWindowColor
);
1162 const OUString aText
= GetText();
1164 Size
aSize(GetOutputSizePixel());
1165 tools::Long nAvailWidth
= aSize
.Width();
1166 tools::Long nWinHeight
= aSize
.Height();
1168 bool bGotBoundary
= true;
1169 bool bShrankFont
= false;
1170 vcl::Font
aOrigFont(rRenderContext
.GetFont());
1171 Size
aFontSize(aOrigFont
.GetFontSize());
1172 ::tools::Rectangle aBoundRect
;
1174 for (tools::Long nFontHeight
= aFontSize
.Height(); nFontHeight
> 0; nFontHeight
-= 5)
1176 if (!rRenderContext
.GetTextBoundRect( aBoundRect
, aText
) || aBoundRect
.IsEmpty())
1178 bGotBoundary
= false;
1183 //only shrink in the single glyph large view mode
1184 tools::Long nTextWidth
= aBoundRect
.GetWidth();
1185 if (nAvailWidth
> nTextWidth
)
1187 vcl::Font
aFont(aOrigFont
);
1188 aFontSize
.setHeight( nFontHeight
);
1189 aFont
.SetFontSize(aFontSize
);
1190 rRenderContext
.SetFont(aFont
);
1191 mnY
= (nWinHeight
- rRenderContext
.GetTextHeight()) / 2;
1195 Point
aPoint(2, mnY
);
1196 // adjust position using ink boundary if possible
1198 aPoint
.setX( (aSize
.Width() - rRenderContext
.GetTextWidth(aText
)) / 2 );
1201 // adjust position before it gets out of bounds
1202 aBoundRect
+= aPoint
;
1204 // shift back vertically if needed
1205 int nYLDelta
= aBoundRect
.Top();
1206 int nYHDelta
= aSize
.Height() - aBoundRect
.Bottom();
1208 aPoint
.AdjustY( -(nYLDelta
- 1) );
1209 else if( nYHDelta
<= 0 )
1210 aPoint
.AdjustY(nYHDelta
- 1 );
1214 // move glyph to middle of cell
1215 aPoint
.setX( -aBoundRect
.Left() + (aSize
.Width() - aBoundRect
.GetWidth()) / 2 );
1219 // shift back horizontally if needed
1220 int nXLDelta
= aBoundRect
.Left();
1221 int nXHDelta
= aSize
.Width() - aBoundRect
.Right();
1223 aPoint
.AdjustX( -(nXLDelta
- 1) );
1224 else if( nXHDelta
<= 0 )
1225 aPoint
.AdjustX(nXHDelta
- 1 );
1229 rRenderContext
.SetLineColor(aShadowColor
);
1230 rRenderContext
.DrawRect(tools::Rectangle(Point(0, 0), aSize
));
1231 rRenderContext
.DrawText(aPoint
, aText
);
1232 rRenderContext
.SetTextColor(aTextCol
);
1233 rRenderContext
.SetFillColor(aFillCol
);
1234 rRenderContext
.SetLineColor(aLineCol
);
1236 rRenderContext
.SetFont(aOrigFont
);
1239 void SvxShowText::SetFont( const vcl::Font
& rFont
)
1241 tools::Long nWinHeight
= GetOutputSizePixel().Height();
1244 m_aFont
.SetWeight(WEIGHT_NORMAL
);
1245 m_aFont
.SetAlignment(ALIGN_TOP
);
1246 m_aFont
.SetFontSize(m_xVirDev
->PixelToLogic(Size(0, nWinHeight
/ 2)));
1247 m_aFont
.SetTransparent(true);
1249 m_xVirDev
->Push(PUSH_ALLFONT
);
1250 m_xVirDev
->SetFont(m_aFont
);
1251 mnY
= (nWinHeight
- m_xVirDev
->GetTextHeight()) / 2;
1257 void SvxShowText::Resize()
1259 SetFont(GetFont()); //force recalculation of size
1262 void SvxShowText::SetText(const OUString
& rText
)
1268 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */