bump product version to 6.4.0.3
[LibreOffice.git] / cui / source / dialogs / cuicharmap.cxx
blobdba595d5dd21bbeba6b3864ac727df43328341b5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <stdio.h>
22 #include <vcl/svapp.hxx>
23 #include <svl/eitem.hxx>
24 #include <svl/intitem.hxx>
25 #include <svl/itempool.hxx>
27 #include <rtl/textenc.h>
28 #include <svx/ucsubset.hxx>
29 #include <vcl/settings.hxx>
30 #include <vcl/fontcharmap.hxx>
31 #include <vcl/virdev.hxx>
32 #include <svl/stritem.hxx>
33 #include <officecfg/Office/Common.hxx>
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/dispatchcommand.hxx>
37 #include <dialmgr.hxx>
38 #include <cui/cuicharmap.hxx>
39 #include <sfx2/app.hxx>
40 #include <svx/svxids.hrc>
41 #include <editeng/editids.hrc>
42 #include <editeng/fontitem.hxx>
43 #include <strings.hrc>
44 #include <unicode/uchar.h>
45 #include <unicode/utypes.h>
47 using namespace css;
49 SvxCharacterMap::SvxCharacterMap(weld::Widget* pParent, const SfxItemSet* pSet,
50 const css::uno::Reference<css::frame::XFrame>& rFrame)
51 : SfxDialogController(pParent, "cui/ui/specialcharacters.ui", "SpecialCharactersDialog")
52 , m_xVirDev(VclPtr<VirtualDevice>::Create())
53 , isSearchMode(true)
54 , m_xFrame(rFrame)
55 , mxContext(comphelper::getProcessComponentContext())
56 , m_aRecentCharView{SvxCharView(m_xVirDev),
57 SvxCharView(m_xVirDev),
58 SvxCharView(m_xVirDev),
59 SvxCharView(m_xVirDev),
60 SvxCharView(m_xVirDev),
61 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 , m_aFavCharView{SvxCharView(m_xVirDev),
73 SvxCharView(m_xVirDev),
74 SvxCharView(m_xVirDev),
75 SvxCharView(m_xVirDev),
76 SvxCharView(m_xVirDev),
77 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 , m_aShowChar(m_xVirDev)
89 , m_xOKBtn(m_xFrame.is() ? m_xBuilder->weld_button("insert") : m_xBuilder->weld_button("ok"))
90 , m_xFontText(m_xBuilder->weld_label("fontft"))
91 , m_xFontLB(m_xBuilder->weld_combo_box("fontlb"))
92 , m_xSubsetText(m_xBuilder->weld_label("subsetft"))
93 , m_xSubsetLB(m_xBuilder->weld_combo_box("subsetlb"))
94 , m_xSearchText(m_xBuilder->weld_entry("search"))
95 , m_xHexCodeText(m_xBuilder->weld_entry("hexvalue"))
96 , m_xDecimalCodeText(m_xBuilder->weld_entry("decimalvalue"))
97 , m_xFavouritesBtn(m_xBuilder->weld_button("favbtn"))
98 , m_xCharName(m_xBuilder->weld_label("charname"))
99 , m_xRecentGrid(m_xBuilder->weld_widget("viewgrid"))
100 , m_xFavGrid(m_xBuilder->weld_widget("favgrid"))
101 , m_xShowChar(new weld::CustomWeld(*m_xBuilder, "showchar", m_aShowChar))
102 , m_xRecentCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar1", m_aRecentCharView[0]),
103 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar2", m_aRecentCharView[1]),
104 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar3", m_aRecentCharView[2]),
105 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar4", m_aRecentCharView[3]),
106 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar5", m_aRecentCharView[4]),
107 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar6", m_aRecentCharView[5]),
108 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar7", m_aRecentCharView[6]),
109 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar8", m_aRecentCharView[7]),
110 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar9", m_aRecentCharView[8]),
111 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar10", m_aRecentCharView[9]),
112 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar11", m_aRecentCharView[10]),
113 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar12", m_aRecentCharView[11]),
114 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar13", m_aRecentCharView[12]),
115 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar14", m_aRecentCharView[13]),
116 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar15", m_aRecentCharView[14]),
117 std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar16", m_aRecentCharView[15])}
118 , m_xFavCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar1", m_aFavCharView[0]),
119 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar2", m_aFavCharView[1]),
120 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar3", m_aFavCharView[2]),
121 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar4", m_aFavCharView[3]),
122 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar5", m_aFavCharView[4]),
123 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar6", m_aFavCharView[5]),
124 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar7", m_aFavCharView[6]),
125 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar8", m_aFavCharView[7]),
126 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar9", m_aFavCharView[8]),
127 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar10", m_aFavCharView[9]),
128 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar11", m_aFavCharView[10]),
129 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar12", m_aFavCharView[11]),
130 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar13", m_aFavCharView[12]),
131 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar14", m_aFavCharView[13]),
132 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar15", m_aFavCharView[14]),
133 std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar16", m_aFavCharView[15])}
134 , m_xShowSet(new SvxShowCharSet(m_xBuilder->weld_scrolled_window("showscroll"), m_xVirDev))
135 , m_xShowSetArea(new weld::CustomWeld(*m_xBuilder, "showcharset", *m_xShowSet))
136 , m_xSearchSet(new SvxSearchCharSet(m_xBuilder->weld_scrolled_window("searchscroll"), m_xVirDev))
137 , m_xSearchSetArea(new weld::CustomWeld(*m_xBuilder, "searchcharset", *m_xSearchSet))
139 m_aShowChar.SetCentered(true);
140 m_xFontLB->make_sorted();
141 //lock the size request of this widget to the width of all possible entries
142 fillAllSubsets(*m_xSubsetLB);
143 m_xSubsetLB->set_size_request(m_xSubsetLB->get_preferred_size().Width(), -1);
144 m_xCharName->set_size_request(m_aShowChar.get_preferred_size().Width(), m_xCharName->get_text_height() * 4);
145 //lock the size request of this widget to the width of the original .ui string
146 m_xHexCodeText->set_size_request(m_xHexCodeText->get_preferred_size().Width(), -1);
147 //so things don't jump around if all the children are hidden
148 m_xRecentGrid->set_size_request(-1, m_aRecentCharView[0].get_preferred_size().Height());
149 m_xFavGrid->set_size_request(-1, m_aFavCharView[0].get_preferred_size().Height());
151 init();
153 const SfxInt32Item* pCharItem = SfxItemSet::GetItem<SfxInt32Item>(pSet, SID_ATTR_CHAR, false);
154 if ( pCharItem )
155 SetChar( pCharItem->GetValue() );
157 const SfxBoolItem* pDisableItem = SfxItemSet::GetItem<SfxBoolItem>(pSet, FN_PARAM_2, false);
158 if ( pDisableItem && pDisableItem->GetValue() )
159 DisableFontSelection();
161 const SvxFontItem* pFontItem = SfxItemSet::GetItem<SvxFontItem>(pSet, SID_ATTR_CHAR_FONT, false);
162 const SfxStringItem* pFontNameItem = SfxItemSet::GetItem<SfxStringItem>(pSet, SID_FONT_NAME, false);
163 if ( pFontItem )
165 vcl::Font aTmpFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), GetCharFont().GetFontSize() );
166 aTmpFont.SetCharSet( pFontItem->GetCharSet() );
167 aTmpFont.SetPitch( pFontItem->GetPitch() );
168 SetCharFont( aTmpFont );
170 else if ( pFontNameItem )
172 vcl::Font aTmpFont( GetCharFont() );
173 aTmpFont.SetFamilyName( pFontNameItem->GetValue() );
174 SetCharFont( aTmpFont );
177 m_xOutputSet.reset(new SfxAllItemSet(pSet ? *pSet->GetPool() : SfxGetpApp()->GetPool()));
178 m_xShowSet->Show();
179 m_xSearchSet->Hide();
182 short SvxCharacterMap::run()
184 if( SvxShowCharSet::getSelectedChar() == ' ')
186 m_xOKBtn->set_sensitive(false);
187 setFavButtonState(OUString(), OUString());
189 else
191 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
192 // using the new UCS4 constructor
193 OUString aOUStr( &cChar, 1 );
194 m_aShowChar.SetText(aOUStr);
196 setFavButtonState(aOUStr, m_aShowChar.GetFont().GetFamilyName());
197 m_xOKBtn->set_sensitive(true);
200 return SfxDialogController::run();
203 void SvxCharacterMap::SetChar( sal_UCS4 c )
205 m_xShowSet->SelectCharacter( c );
206 setFavButtonState(OUString(&c, 1), aFont.GetFamilyName());
209 sal_UCS4 SvxCharacterMap::GetChar() const
211 return m_aShowChar.GetText().toChar();
214 void SvxCharacterMap::DisableFontSelection()
216 m_xFontText->set_sensitive(false);
217 m_xFontLB->set_sensitive(false);
221 void SvxCharacterMap::getRecentCharacterList()
223 //retrieve recent character list
224 css::uno::Sequence< OUString > rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() );
225 for (int i = 0; i < rRecentCharList.getLength(); ++i)
227 maRecentCharList.push_back(rRecentCharList[i]);
230 //retrieve recent character font list
231 css::uno::Sequence< OUString > rRecentCharFontList( officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::get() );
232 for (int i = 0; i < rRecentCharFontList.getLength(); ++i)
234 maRecentCharFontList.push_back(rRecentCharFontList[i]);
239 void SvxCharacterMap::getFavCharacterList()
241 maFavCharList.clear();
242 maFavCharFontList.clear();
243 //retrieve recent character list
244 css::uno::Sequence< OUString > rFavCharList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::get() );
245 for (int i = 0; i < rFavCharList.getLength(); ++i)
247 maFavCharList.push_back(rFavCharList[i]);
250 //retrieve recent character font list
251 css::uno::Sequence< OUString > rFavCharFontList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::get() );
252 for (int i = 0; i < rFavCharFontList.getLength(); ++i)
254 maFavCharFontList.push_back(rFavCharFontList[i]);
259 void SvxCharacterMap::updateRecentCharControl()
261 int i = 0;
262 for ( std::deque< OUString >::iterator it = maRecentCharList.begin(), it2 = maRecentCharFontList.begin();
263 it != maRecentCharList.end() || it2 != maRecentCharFontList.end();
264 ++it, ++it2, i++)
266 m_aRecentCharView[i].SetText(*it);
267 vcl::Font rFont = m_aRecentCharView[i].GetFont();
268 rFont.SetFamilyName( *it2 );
269 m_aRecentCharView[i].SetFont(rFont);
270 m_aRecentCharView[i].Show();
273 for(; i < 16 ; i++)
275 m_aRecentCharView[i].SetText(OUString());
276 m_aRecentCharView[i].Hide();
280 void SvxCharacterMap::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont)
282 auto itChar = std::find(maRecentCharList.begin(), maRecentCharList.end(), sTitle);
284 auto itChar2 = std::find(maRecentCharFontList.begin(), maRecentCharFontList.end(), rFont);
286 // if recent char to be added is already in list, remove it
287 if( itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
289 maRecentCharList.erase( itChar );
290 maRecentCharFontList.erase( itChar2);
293 if (maRecentCharList.size() == 16)
295 maRecentCharList.pop_back();
296 maRecentCharFontList.pop_back();
299 maRecentCharList.push_front(sTitle);
300 maRecentCharFontList.push_front(rFont);
302 css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
303 css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
305 for (size_t i = 0; i < maRecentCharList.size(); ++i)
307 aRecentCharList[i] = maRecentCharList[i];
308 aRecentCharFontList[i] = maRecentCharFontList[i];
311 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
312 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
313 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
314 batch->commit();
316 updateRecentCharControl();
320 void SvxCharacterMap::updateFavCharacterList(const OUString& sTitle, const OUString& rFont)
322 auto itChar = std::find(maFavCharList.begin(), maFavCharList.end(), sTitle);
324 auto itChar2 = std::find(maFavCharFontList.begin(), maFavCharFontList.end(), rFont);
326 // if Fav char to be added is already in list, remove it
327 if( itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
329 maFavCharList.erase( itChar );
330 maFavCharFontList.erase( itChar2);
333 if (maFavCharList.size() == 16)
335 maFavCharList.pop_back();
336 maFavCharFontList.pop_back();
339 maFavCharList.push_back(sTitle);
340 maFavCharFontList.push_back(rFont);
342 css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
343 css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
345 for (size_t i = 0; i < maFavCharList.size(); ++i)
347 aFavCharList[i] = maFavCharList[i];
348 aFavCharFontList[i] = maFavCharFontList[i];
351 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
352 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
353 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
354 batch->commit();
358 void SvxCharacterMap::updateFavCharControl()
360 int i = 0;
361 for ( std::deque< OUString >::iterator it = maFavCharList.begin(), it2 = maFavCharFontList.begin();
362 it != maFavCharList.end() || it2 != maFavCharFontList.end();
363 ++it, ++it2, i++)
365 m_aFavCharView[i].SetText(*it);
366 vcl::Font rFont = m_aFavCharView[i].GetFont();
367 rFont.SetFamilyName( *it2 );
368 m_aFavCharView[i].SetFont(rFont);
369 m_aFavCharView[i].Show();
372 for(; i < 16 ; i++)
374 m_aFavCharView[i].SetText(OUString());
375 m_aFavCharView[i].Hide();
377 m_xShowSet->getFavCharacterList();
378 m_xSearchSet->getFavCharacterList();
381 void SvxCharacterMap::deleteFavCharacterFromList(const OUString& sTitle, const OUString& rFont)
383 auto itChar = std::find(maFavCharList.begin(), maFavCharList.end(), sTitle);
385 auto itChar2 = std::find(maFavCharFontList.begin(), maFavCharFontList.end(), rFont);
387 // if Fav char to be added is already in list, remove it
388 if( itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
390 maFavCharList.erase( itChar );
391 maFavCharFontList.erase( itChar2);
394 css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
395 css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
397 for (size_t i = 0; i < maFavCharList.size(); ++i)
399 aFavCharList[i] = maFavCharList[i];
400 aFavCharFontList[i] = maFavCharFontList[i];
403 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
404 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
405 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
406 batch->commit();
409 void SvxCharacterMap::init()
411 aFont = m_xVirDev->GetFont();
412 aFont.SetTransparent( true );
413 aFont.SetFamily( FAMILY_DONTKNOW );
414 aFont.SetPitch( PITCH_DONTKNOW );
415 aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
417 OUString aDefStr( aFont.GetFamilyName() );
418 OUString aLastName;
419 int nCount = m_xVirDev->GetDevFontCount();
420 std::vector<weld::ComboBoxEntry> aEntries;
421 aEntries.reserve(nCount);
422 for (int i = 0; i < nCount; ++i)
424 OUString aFontName( m_xVirDev->GetDevFont( i ).GetFamilyName() );
425 if (aFontName != aLastName)
427 aLastName = aFontName;
428 aEntries.emplace_back(aFontName, OUString::number(i));
431 m_xFontLB->insert_vector(aEntries, true);
432 // the font may not be in the list =>
433 // try to find a font name token in list and select found font,
434 // else select topmost entry
435 bool bFound = (m_xFontLB->find_text(aDefStr) == -1);
436 if (!bFound)
438 sal_Int32 nIndex = 0;
441 OUString aToken = aDefStr.getToken(0, ';', nIndex);
442 if (m_xFontLB->find_text(aToken) != -1)
444 aDefStr = aToken;
445 bFound = true;
446 break;
449 while ( nIndex >= 0 );
452 if (bFound)
453 m_xFontLB->set_active_text(aDefStr);
454 else if (m_xFontLB->get_count() )
455 m_xFontLB->set_active(0);
456 FontSelectHdl(*m_xFontLB);
457 if (m_xSubsetLB->get_count())
458 m_xSubsetLB->set_active(0);
460 m_xFontLB->connect_changed(LINK( this, SvxCharacterMap, FontSelectHdl));
461 m_xSubsetLB->connect_changed(LINK( this, SvxCharacterMap, SubsetSelectHdl));
462 m_xOKBtn->connect_clicked(LINK(this, SvxCharacterMap, InsertClickHdl));
463 m_xOKBtn->show();
465 m_xShowSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, CharDoubleClickHdl ) );
466 m_xShowSet->SetSelectHdl( LINK( this, SvxCharacterMap, CharSelectHdl ) );
467 m_xShowSet->SetHighlightHdl( LINK( this, SvxCharacterMap, CharHighlightHdl ) );
468 m_xShowSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, CharPreSelectHdl ) );
469 m_xShowSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
471 m_xSearchSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, SearchCharDoubleClickHdl ) );
472 m_xSearchSet->SetSelectHdl( LINK( this, SvxCharacterMap, SearchCharSelectHdl ) );
473 m_xSearchSet->SetHighlightHdl( LINK( this, SvxCharacterMap, SearchCharHighlightHdl ) );
474 m_xSearchSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, SearchCharPreSelectHdl ) );
475 m_xSearchSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
477 m_xDecimalCodeText->connect_changed( LINK( this, SvxCharacterMap, DecimalCodeChangeHdl ) );
478 m_xHexCodeText->connect_changed( LINK( this, SvxCharacterMap, HexCodeChangeHdl ) );
479 m_xFavouritesBtn->connect_clicked( LINK(this, SvxCharacterMap, FavSelectHdl));
481 // tdf#117038 set the buttons width to its max possible width so it doesn't
482 // make layout change when the label changes
483 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_REMOVE_FAVORITES));
484 auto nMaxWidth = m_xFavouritesBtn->get_preferred_size().Width();
485 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
486 nMaxWidth = std::max(nMaxWidth, m_xFavouritesBtn->get_preferred_size().Width());
487 m_xFavouritesBtn->set_size_request(nMaxWidth, -1);
489 if( SvxShowCharSet::getSelectedChar() == ' ')
491 m_xOKBtn->set_sensitive(false);
493 else
495 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
496 // using the new UCS4 constructor
497 OUString aOUStr( &cChar, 1 );
498 m_aShowChar.SetText(aOUStr);
500 setFavButtonState(aOUStr, aDefStr);
501 m_xOKBtn->set_sensitive(true);
504 getRecentCharacterList();
505 updateRecentCharControl();
507 getFavCharacterList();
508 updateFavCharControl();
510 bool bHasInsert = m_xFrame.is();
512 for(int i = 0; i < 16; i++)
514 m_aRecentCharView[i].SetHasInsert(bHasInsert);
515 m_aRecentCharView[i].setMouseClickHdl(LINK(this,SvxCharacterMap, CharClickHdl));
516 m_aRecentCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, RecentClearClickHdl));
517 m_aRecentCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, RecentClearAllClickHdl));
518 m_aFavCharView[i].SetHasInsert(bHasInsert);
519 m_aFavCharView[i].setMouseClickHdl(LINK(this,SvxCharacterMap, CharClickHdl));
520 m_aFavCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, FavClearClickHdl));
521 m_aFavCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, FavClearAllClickHdl));
524 setCharName(90);
526 m_xSearchText->connect_focus_in(LINK( this, SvxCharacterMap, SearchFieldGetFocusHdl ));
527 m_xSearchText->connect_changed(LINK(this, SvxCharacterMap, SearchUpdateHdl));
530 bool SvxCharacterMap::isFavChar(const OUString& sTitle, const OUString& rFont)
532 auto isFavCharTitleExists = std::any_of(maFavCharList.begin(),
533 maFavCharList.end(),
534 [sTitle] (const OUString & a) { return a == sTitle; });
536 auto isFavCharFontExists = std::any_of(maFavCharFontList.begin(),
537 maFavCharFontList.end(),
538 [rFont] (const OUString & a) { return a == rFont; });
540 // if Fav char to be added is already in list, remove it
541 return isFavCharTitleExists && isFavCharFontExists;
545 void SvxCharacterMap::setFavButtonState(const OUString& sTitle, const OUString& rFont)
547 if(sTitle.isEmpty() || rFont.isEmpty())
549 m_xFavouritesBtn->set_sensitive(false);
550 return;
552 else
553 m_xFavouritesBtn->set_sensitive(true);
555 if (isFavChar(sTitle, rFont))
557 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_REMOVE_FAVORITES));
559 else
561 if(maFavCharList.size() == 16)
563 m_xFavouritesBtn->set_sensitive(false);
566 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
571 void SvxCharacterMap::SetCharFont( const vcl::Font& rFont )
573 // first get the underlying info in order to get font names
574 // like "Times New Roman;Times" resolved
575 vcl::Font aTmp(m_xVirDev->GetFontMetric(rFont));
577 if (aTmp.GetFamilyName() == "StarSymbol" && m_xFontLB->find_text(aTmp.GetFamilyName()) == -1)
579 //if for some reason, like font in an old document, StarSymbol is requested and it's not available, then
580 //try OpenSymbol instead
581 aTmp.SetFamilyName("OpenSymbol");
584 if (m_xFontLB->find_text(aTmp.GetFamilyName()) == -1)
585 return;
587 m_xFontLB->set_active_text(aTmp.GetFamilyName());
588 aFont = aTmp;
589 FontSelectHdl(*m_xFontLB);
590 if (m_xSubsetLB->get_count())
591 m_xSubsetLB->set_active(0);
594 void SvxCharacterMap::fillAllSubsets(weld::ComboBox& rListBox)
596 SubsetMap aAll(nullptr);
597 std::vector<weld::ComboBoxEntry> aEntries;
598 for (auto & subset : aAll.GetSubsetMap())
599 aEntries.emplace_back(subset.GetName());
600 rListBox.insert_vector(aEntries, true);
603 void SvxCharacterMap::insertCharToDoc(const OUString& sGlyph)
605 if(sGlyph.isEmpty())
606 return;
608 if (m_xFrame.is()) {
609 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
611 uno::Sequence<beans::PropertyValue> aArgs(2);
612 aArgs[0].Name = "Symbols";
613 aArgs[0].Value <<= sGlyph;
615 aArgs[1].Name = "FontName";
616 aArgs[1].Value <<= aFont.GetFamilyName();
617 comphelper::dispatchCommand(".uno:InsertSymbol", m_xFrame, aArgs);
619 updateRecentCharacterList(sGlyph, aFont.GetFamilyName());
621 } else {
622 sal_Int32 tmp = 0;
623 sal_UCS4 cChar = sGlyph.iterateCodePoints(&tmp);
624 const SfxItemPool* pPool = m_xOutputSet->GetPool();
625 m_xOutputSet->Put( SfxStringItem( pPool->GetWhich(SID_CHARMAP), sGlyph ) );
626 m_xOutputSet->Put( SvxFontItem( aFont.GetFamilyType(), aFont.GetFamilyName(),
627 aFont.GetStyleName(), aFont.GetPitch(), aFont.GetCharSet(), pPool->GetWhich(SID_ATTR_CHAR_FONT) ) );
628 m_xOutputSet->Put( SfxStringItem( pPool->GetWhich(SID_FONT_NAME), aFont.GetFamilyName() ) );
629 m_xOutputSet->Put( SfxInt32Item( pPool->GetWhich(SID_ATTR_CHAR), cChar ) );
633 IMPL_LINK_NOARG(SvxCharacterMap, FontSelectHdl, weld::ComboBox&, void)
635 const sal_uInt32 nFont = m_xFontLB->get_active_id().toUInt32();
636 aFont = m_xVirDev->GetDevFont(nFont);
637 aFont.SetWeight( WEIGHT_DONTKNOW );
638 aFont.SetItalic( ITALIC_NONE );
639 aFont.SetWidthType( WIDTH_DONTKNOW );
640 aFont.SetPitch( PITCH_DONTKNOW );
641 aFont.SetFamily( FAMILY_DONTKNOW );
643 // notify children using this font
644 m_xShowSet->SetFont( aFont );
645 m_xSearchSet->SetFont( aFont );
646 m_aShowChar.SetFont( aFont );
647 if (isSearchMode)
649 SearchUpdateHdl(*m_xSearchText);
650 SearchCharHighlightHdl(m_xSearchSet.get());
653 // setup unicode subset listbar with font specific subsets,
654 // hide unicode subset listbar for symbol fonts
655 // TODO: get info from the Font once it provides it
656 pSubsetMap.reset();
657 m_xSubsetLB->clear();
659 bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL);
660 if (bNeedSubset)
662 FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
663 pSubsetMap.reset(new SubsetMap( xFontCharMap ));
665 // update subset listbox for new font's unicode subsets
666 for (auto const& subset : pSubsetMap->GetSubsetMap())
668 m_xSubsetLB->append(OUString::number(reinterpret_cast<sal_uInt64>(&subset)), subset.GetName());
669 // NOTE: subset must live at least as long as the selected font
672 if (m_xSubsetLB->get_count() <= 1)
673 bNeedSubset = false;
676 m_xSubsetText->set_sensitive(bNeedSubset);
677 m_xSubsetLB->set_sensitive(bNeedSubset);
679 // tdf#118304 reselect current glyph to see if its still there in new font
680 selectCharByCode(Radix::hexadecimal);
683 void SvxCharacterMap::toggleSearchView(bool state)
685 isSearchMode = state;
686 m_xHexCodeText->set_editable(!state);
687 m_xDecimalCodeText->set_editable(!state);
688 m_xSubsetLB->set_sensitive(!state);
690 if(state)
692 m_xSearchSet->Show();
693 m_xShowSet->Hide();
695 else
697 m_xSearchSet->Hide();
698 m_xShowSet->Show();
702 void SvxCharacterMap::setCharName(sal_UCS4 nDecimalValue)
704 /* get the character name */
705 UErrorCode errorCode = U_ZERO_ERROR;
706 // icu has a private uprv_getMaxCharNameLength function which returns the max possible
707 // length of this property. Unicode 3.2 max char name length was 83
708 char buffer[100];
709 u_charName(nDecimalValue, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
710 if (U_SUCCESS(errorCode))
711 m_xCharName->set_label(OUString::createFromAscii(buffer));
714 IMPL_LINK_NOARG(SvxCharacterMap, SubsetSelectHdl, weld::ComboBox&, void)
716 const sal_Int32 nPos = m_xSubsetLB->get_active();
717 const Subset* pSubset = reinterpret_cast<const Subset*>(m_xSubsetLB->get_active_id().toUInt64());
719 if( pSubset && !isSearchMode)
721 sal_UCS4 cFirst = pSubset->GetRangeMin();
722 m_xShowSet->SelectCharacter( cFirst );
724 setFavButtonState(OUString(&cFirst, 1), aFont.GetFamilyName());
725 m_xSubsetLB->set_active(nPos);
727 else if( pSubset && isSearchMode)
729 m_xSearchSet->SelectCharacter( pSubset );
731 const Subset* curSubset = nullptr;
732 if( pSubsetMap )
733 curSubset = pSubsetMap->GetSubsetByUnicode( m_xSearchSet->GetSelectCharacter() );
734 if( curSubset )
735 m_xSubsetLB->set_active_text(curSubset->GetName());
736 else
737 m_xSubsetLB->set_active(-1);
739 sal_UCS4 sChar = m_xSearchSet->GetSelectCharacter();
740 setFavButtonState(OUString(&sChar, 1), aFont.GetFamilyName());
744 IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView*, rView, void)
746 const OUString& sTitle = rView->GetText();
747 auto itChar = std::find(maRecentCharList.begin(), maRecentCharList.end(), sTitle);
749 OUString sFont = rView->GetFont().GetFamilyName();
750 auto itChar2 = std::find(maRecentCharFontList.begin(), maRecentCharFontList.end(), sFont);
752 // if recent char to be added is already in list, remove it
753 if( itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
755 maRecentCharList.erase( itChar );
756 maRecentCharFontList.erase( itChar2);
759 css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
760 css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
762 for (size_t i = 0; i < maRecentCharList.size(); ++i)
764 aRecentCharList[i] = maRecentCharList[i];
765 aRecentCharFontList[i] = maRecentCharFontList[i];
768 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
769 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
770 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
771 batch->commit();
773 updateRecentCharControl();
776 IMPL_LINK_NOARG(SvxCharacterMap, RecentClearAllClickHdl, SvxCharView*, void)
778 css::uno::Sequence< OUString > aRecentCharList(0);
779 css::uno::Sequence< OUString > aRecentCharFontList(0);
781 maRecentCharList.clear();
782 maRecentCharFontList.clear();
784 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
785 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
786 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
787 batch->commit();
789 updateRecentCharControl();
792 IMPL_LINK(SvxCharacterMap, FavClearClickHdl, SvxCharView*, rView, void)
794 deleteFavCharacterFromList(rView->GetText(), rView->GetFont().GetFamilyName());
795 updateFavCharControl();
798 IMPL_LINK_NOARG(SvxCharacterMap, FavClearAllClickHdl, SvxCharView*, void)
800 css::uno::Sequence< OUString > aFavCharList(0);
801 css::uno::Sequence< OUString > aFavCharFontList(0);
803 maFavCharList.clear();
804 maFavCharFontList.clear();
806 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
807 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
808 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
809 batch->commit();
811 updateFavCharControl();
814 IMPL_LINK_NOARG(SvxCharacterMap, SearchFieldGetFocusHdl, weld::Widget&, void)
816 m_xOKBtn->set_sensitive(false);
819 IMPL_LINK_NOARG(SvxCharacterMap, SearchUpdateHdl, weld::Entry&, void)
821 if (!m_xSearchText->get_text().isEmpty())
823 m_xSearchSet->ClearPreviousData();
824 OUString aKeyword = m_xSearchText->get_text();
826 toggleSearchView(true);
828 FontCharMapRef xFontCharMap = m_xSearchSet->GetFontCharMap();
830 sal_UCS4 sChar = xFontCharMap->GetFirstChar();
831 while(sChar != xFontCharMap->GetLastChar())
833 UErrorCode errorCode = U_ZERO_ERROR;
834 char buffer[100];
835 u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
836 if (U_SUCCESS(errorCode))
838 OUString sName = OUString::createFromAscii(buffer);
839 if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
840 m_xSearchSet->AppendCharToList(sChar);
842 sChar = xFontCharMap->GetNextChar(sChar);
844 //for last char
845 UErrorCode errorCode = U_ZERO_ERROR;
846 char buffer[100];
847 u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
848 if (U_SUCCESS(errorCode))
850 OUString sName = OUString::createFromAscii(buffer);
851 if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
852 m_xSearchSet->AppendCharToList(sChar);
855 else
857 toggleSearchView(false);
862 IMPL_LINK(SvxCharacterMap, CharClickHdl, SvxCharView*, rView, void)
864 rView->GrabFocus();
866 m_aShowChar.SetText( rView->GetText() );
867 m_aShowChar.SetFont(rView->GetFont());
868 m_aShowChar.Invalidate();
870 setFavButtonState(rView->GetText(), rView->GetFont().GetFamilyName());//check state
872 // Get the hexadecimal code
873 OUString charValue = rView->GetText();
874 sal_Int32 tmp = 1;
875 sal_UCS4 cChar = charValue.iterateCodePoints(&tmp, -1);
876 OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
878 // Get the decimal code
879 OUString aDecimalText = OUString::number(cChar);
881 m_xHexCodeText->set_text(aHexText);
882 m_xDecimalCodeText->set_text(aDecimalText);
883 setCharName(cChar);
885 rView->Invalidate();
886 m_xOKBtn->set_sensitive(true);
889 IMPL_LINK_NOARG(SvxCharacterMap, CharDoubleClickHdl, SvxShowCharSet*, void)
891 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
892 // using the new UCS4 constructor
893 OUString aOUStr( &cChar, 1 );
894 setFavButtonState(aOUStr, aFont.GetFamilyName());
895 insertCharToDoc(aOUStr);
898 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharDoubleClickHdl, SvxShowCharSet*, void)
900 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
901 // using the new UCS4 constructor
902 OUString aOUStr( &cChar, 1 );
903 setFavButtonState(aOUStr, aFont.GetFamilyName());
904 insertCharToDoc(aOUStr);
907 IMPL_LINK_NOARG(SvxCharacterMap, CharSelectHdl, SvxShowCharSet*, void)
909 m_xOKBtn->set_sensitive(true);
912 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharSelectHdl, SvxShowCharSet*, void)
914 m_xOKBtn->set_sensitive(true);
917 IMPL_LINK_NOARG(SvxCharacterMap, InsertClickHdl, weld::Button&, void)
919 OUString sChar = m_aShowChar.GetText();
920 insertCharToDoc(sChar);
921 // Need to update recent character list, when OK button does not insert
922 if(!m_xFrame.is())
923 updateRecentCharacterList(sChar, aFont.GetFamilyName());
924 m_xDialog->response(RET_OK);
927 IMPL_LINK_NOARG(SvxCharacterMap, FavSelectHdl, weld::Button&, void)
929 if (m_xFavouritesBtn->get_label().match(CuiResId(RID_SVXSTR_ADD_FAVORITES)))
931 updateFavCharacterList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
932 setFavButtonState(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
934 else
936 deleteFavCharacterFromList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
937 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
938 m_xFavouritesBtn->set_sensitive(false);
941 updateFavCharControl();
944 IMPL_LINK_NOARG(SvxCharacterMap, FavClickHdl, SvxShowCharSet*, void)
946 getFavCharacterList();
947 updateFavCharControl();
950 IMPL_LINK_NOARG(SvxCharacterMap, CharHighlightHdl, SvxShowCharSet*, void)
952 OUString aText;
953 OUString aHexText;
954 OUString aDecimalText;
955 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
956 bool bSelect = (cChar > 0);
958 // show char sample
959 if ( bSelect )
961 // using the new UCS4 constructor
962 aText = OUString( &cChar, 1 );
963 // Get the hexadecimal code
964 aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
965 // Get the decimal code
966 aDecimalText = OUString::number(cChar);
967 setCharName(cChar);
969 // Update the hex and decimal codes only if necessary
970 if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
971 m_xHexCodeText->set_text(aHexText);
972 if (m_xDecimalCodeText->get_text() != aDecimalText)
973 m_xDecimalCodeText->set_text( aDecimalText );
975 const Subset* pSubset = nullptr;
976 if( pSubsetMap )
977 pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
978 if( pSubset )
979 m_xSubsetLB->set_active_text(pSubset->GetName());
980 else
981 m_xSubsetLB->set_active(-1);
984 m_aShowChar.SetText( aText );
985 m_aShowChar.SetFont( aFont );
986 m_aShowChar.Invalidate();
988 setFavButtonState(aText, aFont.GetFamilyName());
991 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharHighlightHdl, SvxShowCharSet*, void)
993 OUString aText;
994 OUString aHexText;
995 OUString aDecimalText;
996 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
997 bool bSelect = (cChar > 0);
999 // show char sample
1000 if ( bSelect )
1002 aText = OUString( &cChar, 1 );
1003 // Get the hexadecimal code
1004 aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
1005 // Get the decimal code
1006 aDecimalText = OUString::number(cChar);
1007 setCharName(cChar);
1009 // Update the hex and decimal codes only if necessary
1010 if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
1011 m_xHexCodeText->set_text(aHexText);
1012 if (m_xDecimalCodeText->get_text() != aDecimalText)
1013 m_xDecimalCodeText->set_text( aDecimalText );
1015 const Subset* pSubset = nullptr;
1016 if( pSubsetMap )
1017 pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1018 if( pSubset )
1019 m_xSubsetLB->set_active_text(pSubset->GetName());
1020 else
1021 m_xSubsetLB->set_active(-1);
1024 if(m_xSearchSet->HasFocus())
1026 m_aShowChar.SetText( aText );
1027 m_aShowChar.SetFont( aFont );
1028 m_aShowChar.Invalidate();
1030 setFavButtonState(aText, aFont.GetFamilyName());
1034 void SvxCharacterMap::selectCharByCode(Radix radix)
1036 OUString aCodeString;
1037 switch(radix)
1039 case Radix::decimal:
1040 aCodeString = m_xDecimalCodeText->get_text();
1041 break;
1042 case Radix::hexadecimal:
1043 aCodeString = m_xHexCodeText->get_text();
1044 break;
1046 // Convert the code back to a character using the appropriate radix
1047 sal_UCS4 cChar = aCodeString.toUInt32(static_cast<sal_Int16> (radix));
1048 // Use FontCharMap::HasChar(sal_UCS4 cChar) to see if the desired character is in the font
1049 FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
1050 if (xFontCharMap->HasChar(cChar))
1051 // Select the corresponding character
1052 SetChar(cChar);
1053 else {
1054 m_xCharName->set_label(CuiResId(RID_SVXSTR_MISSING_CHAR));
1055 m_aShowChar.SetText(" ");
1056 switch(radix)
1058 case Radix::decimal:
1059 m_xHexCodeText->set_text(OUString::number(cChar, 16));
1060 break;
1061 case Radix::hexadecimal:
1062 m_xDecimalCodeText->set_text(OUString::number(cChar));
1063 break;
1068 IMPL_LINK_NOARG(SvxCharacterMap, DecimalCodeChangeHdl, weld::Entry&, void)
1070 selectCharByCode(Radix::decimal);
1073 IMPL_LINK_NOARG(SvxCharacterMap, HexCodeChangeHdl, weld::Entry&, void)
1075 selectCharByCode(Radix::hexadecimal);
1078 IMPL_LINK_NOARG(SvxCharacterMap, CharPreSelectHdl, SvxShowCharSet*, void)
1080 // adjust subset selection
1081 if( pSubsetMap )
1083 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
1085 setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName());
1086 const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1087 if( pSubset )
1088 m_xSubsetLB->set_active_text(pSubset->GetName());
1091 m_xOKBtn->set_sensitive(true);
1094 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharPreSelectHdl, SvxShowCharSet*, void)
1096 // adjust subset selection
1097 if( pSubsetMap )
1099 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
1101 setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName());
1102 const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1103 if( pSubset )
1104 m_xSubsetLB->set_active_text(pSubset->GetName());
1107 m_xOKBtn->set_sensitive(true);
1110 // class SvxShowText =====================================================
1111 SvxShowText::SvxShowText(const VclPtr<VirtualDevice>& rVirDev)
1112 : m_xVirDev(rVirDev)
1113 , mnY(0)
1114 , mbCenter(false)
1118 void SvxShowText::SetDrawingArea(weld::DrawingArea* pDrawingArea)
1120 CustomWidgetController::SetDrawingArea(pDrawingArea);
1121 vcl::Font aFont = m_xVirDev->GetFont();
1122 Size aFontSize(aFont.GetFontSize().Width() * 5, aFont.GetFontSize().Height() * 5);
1123 aFont.SetFontSize(aFontSize);
1124 m_xVirDev->Push(PUSH_ALLFONT);
1125 m_xVirDev->SetFont(aFont);
1126 pDrawingArea->set_size_request(m_xVirDev->approximate_digit_width() + 2 * 12,
1127 m_xVirDev->LogicToPixel(aFontSize).Height() * 2);
1128 m_xVirDev->Pop();
1131 void SvxShowText::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
1133 rRenderContext.SetFont(m_aFont);
1135 Color aTextCol = rRenderContext.GetTextColor();
1136 Color aFillCol = rRenderContext.GetFillColor();
1138 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1139 const Color aWindowTextColor(rStyleSettings.GetDialogTextColor());
1140 const Color aWindowColor(rStyleSettings.GetWindowColor());
1141 rRenderContext.SetTextColor(aWindowTextColor);
1142 rRenderContext.SetFillColor(aWindowColor);
1144 const OUString aText = GetText();
1146 Size aSize(GetOutputSizePixel());
1147 long nAvailWidth = aSize.Width();
1148 long nWinHeight = aSize.Height();
1150 bool bGotBoundary = true;
1151 bool bShrankFont = false;
1152 vcl::Font aOrigFont(rRenderContext.GetFont());
1153 Size aFontSize(aOrigFont.GetFontSize());
1154 ::tools::Rectangle aBoundRect;
1156 for (long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 5)
1158 if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty())
1160 bGotBoundary = false;
1161 break;
1163 if (!mbCenter)
1164 break;
1165 //only shrink in the single glyph large view mode
1166 long nTextWidth = aBoundRect.GetWidth();
1167 if (nAvailWidth > nTextWidth)
1168 break;
1169 vcl::Font aFont(aOrigFont);
1170 aFontSize.setHeight( nFontHeight );
1171 aFont.SetFontSize(aFontSize);
1172 rRenderContext.SetFont(aFont);
1173 mnY = (nWinHeight - rRenderContext.GetTextHeight()) / 2;
1174 bShrankFont = true;
1177 Point aPoint(2, mnY);
1178 // adjust position using ink boundary if possible
1179 if (!bGotBoundary)
1180 aPoint.setX( (aSize.Width() - rRenderContext.GetTextWidth(aText)) / 2 );
1181 else
1183 // adjust position before it gets out of bounds
1184 aBoundRect += aPoint;
1186 // shift back vertically if needed
1187 int nYLDelta = aBoundRect.Top();
1188 int nYHDelta = aSize.Height() - aBoundRect.Bottom();
1189 if( nYLDelta <= 0 )
1190 aPoint.AdjustY( -(nYLDelta - 1) );
1191 else if( nYHDelta <= 0 )
1192 aPoint.AdjustY(nYHDelta - 1 );
1194 if (mbCenter)
1196 // move glyph to middle of cell
1197 aPoint.setX( -aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2 );
1199 else
1201 // shift back horizontally if needed
1202 int nXLDelta = aBoundRect.Left();
1203 int nXHDelta = aSize.Width() - aBoundRect.Right();
1204 if( nXLDelta <= 0 )
1205 aPoint.AdjustX( -(nXLDelta - 1) );
1206 else if( nXHDelta <= 0 )
1207 aPoint.AdjustX(nXHDelta - 1 );
1211 rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize));
1212 rRenderContext.DrawText(aPoint, aText);
1213 rRenderContext.SetTextColor(aTextCol);
1214 rRenderContext.SetFillColor(aFillCol);
1215 if (bShrankFont)
1216 rRenderContext.SetFont(aOrigFont);
1219 void SvxShowText::SetFont( const vcl::Font& rFont )
1221 long nWinHeight = GetOutputSizePixel().Height();
1223 m_aFont = rFont;
1224 m_aFont.SetWeight(WEIGHT_NORMAL);
1225 m_aFont.SetAlignment(ALIGN_TOP);
1226 m_aFont.SetFontSize(m_xVirDev->PixelToLogic(Size(0, nWinHeight / 2)));
1227 m_aFont.SetTransparent(true);
1229 m_xVirDev->Push(PUSH_ALLFONT);
1230 m_xVirDev->SetFont(m_aFont);
1231 mnY = (nWinHeight - m_xVirDev->GetTextHeight()) / 2;
1232 m_xVirDev->Pop();
1234 Invalidate();
1237 void SvxShowText::Resize()
1239 SetFont(GetFont()); //force recalculation of size
1242 void SvxShowText::SetText(const OUString& rText)
1244 m_sText = rText;
1245 Invalidate();
1248 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */