bump product version to 6.3.0.0.beta1
[LibreOffice.git] / cui / source / dialogs / cuicharmap.cxx
blob7999aaba15a24370b86fe517138530b07b4c9448
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 <svtools/colorcfg.hxx>
24 #include <svl/eitem.hxx>
25 #include <svl/intitem.hxx>
26 #include <svl/itempool.hxx>
28 #include <rtl/textenc.h>
29 #include <svx/ucsubset.hxx>
30 #include <sfx2/objsh.hxx>
31 #include <vcl/settings.hxx>
32 #include <vcl/fontcharmap.hxx>
33 #include <vcl/virdev.hxx>
34 #include <svl/stritem.hxx>
35 #include <officecfg/Office/Common.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <comphelper/dispatchcommand.hxx>
39 #include <dialmgr.hxx>
40 #include <cui/cuicharmap.hxx>
41 #include <sfx2/request.hxx>
42 #include <sfx2/sfxsids.hrc>
43 #include <sfx2/app.hxx>
44 #include <svx/svxids.hrc>
45 #include <editeng/editids.hrc>
46 #include <editeng/fontitem.hxx>
47 #include <strings.hrc>
48 #include <macroass.hxx>
49 #include <unicode/uchar.h>
50 #include <unicode/utypes.h>
52 using namespace css;
54 SvxCharacterMap::SvxCharacterMap(weld::Window* pParent, const SfxItemSet* pSet,
55 const css::uno::Reference<css::frame::XFrame>& rFrame)
56 : SfxDialogController(pParent, "cui/ui/specialcharacters.ui", "SpecialCharactersDialog")
57 , m_xVirDev(VclPtr<VirtualDevice>::Create())
58 , isSearchMode(true)
59 , m_xFrame(rFrame)
60 , mxContext(comphelper::getProcessComponentContext())
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"), m_xVirDev))
140 , m_xShowSetArea(new weld::CustomWeld(*m_xBuilder, "showcharset", *m_xShowSet))
141 , m_xSearchSet(new SvxSearchCharSet(m_xBuilder->weld_scrolled_window("searchscroll"), 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());
156 init();
158 const SfxInt32Item* pCharItem = SfxItemSet::GetItem<SfxInt32Item>(pSet, SID_ATTR_CHAR, false);
159 if ( pCharItem )
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);
168 if ( pFontItem )
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()));
183 m_xShowSet->Show();
184 m_xSearchSet->Hide();
187 short SvxCharacterMap::run()
189 if( SvxShowCharSet::getSelectedChar() == ' ')
191 m_xOKBtn->set_sensitive(false);
192 setFavButtonState(OUString(), OUString());
194 else
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().toChar();
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 css::uno::Sequence< OUString > rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() );
230 for (int i = 0; i < rRecentCharList.getLength(); ++i)
232 maRecentCharList.push_back(rRecentCharList[i]);
235 //retrieve recent character font list
236 css::uno::Sequence< OUString > rRecentCharFontList( officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::get() );
237 for (int i = 0; i < rRecentCharFontList.getLength(); ++i)
239 maRecentCharFontList.push_back(rRecentCharFontList[i]);
244 void SvxCharacterMap::getFavCharacterList()
246 maFavCharList.clear();
247 maFavCharFontList.clear();
248 //retrieve recent character list
249 css::uno::Sequence< OUString > rFavCharList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::get() );
250 for (int i = 0; i < rFavCharList.getLength(); ++i)
252 maFavCharList.push_back(rFavCharList[i]);
255 //retrieve recent character font list
256 css::uno::Sequence< OUString > rFavCharFontList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::get() );
257 for (int i = 0; i < rFavCharFontList.getLength(); ++i)
259 maFavCharFontList.push_back(rFavCharFontList[i]);
264 void SvxCharacterMap::updateRecentCharControl()
266 int i = 0;
267 for ( std::deque< OUString >::iterator it = maRecentCharList.begin(), it2 = maRecentCharFontList.begin();
268 it != maRecentCharList.end() || it2 != maRecentCharFontList.end();
269 ++it, ++it2, i++)
271 m_aRecentCharView[i].SetText(*it);
272 vcl::Font rFont = m_aRecentCharView[i].GetFont();
273 rFont.SetFamilyName( *it2 );
274 m_aRecentCharView[i].SetFont(rFont);
275 m_aRecentCharView[i].Show();
278 for(; i < 16 ; i++)
280 m_aRecentCharView[i].SetText(OUString());
281 m_aRecentCharView[i].Hide();
285 void SvxCharacterMap::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont)
287 auto itChar = std::find(maRecentCharList.begin(), maRecentCharList.end(), sTitle);
289 auto itChar2 = std::find(maRecentCharFontList.begin(), maRecentCharFontList.end(), rFont);
291 // if recent char to be added is already in list, remove it
292 if( itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
294 maRecentCharList.erase( itChar );
295 maRecentCharFontList.erase( itChar2);
298 if (maRecentCharList.size() == 16)
300 maRecentCharList.pop_back();
301 maRecentCharFontList.pop_back();
304 maRecentCharList.push_front(sTitle);
305 maRecentCharFontList.push_front(rFont);
307 css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
308 css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
310 for (size_t i = 0; i < maRecentCharList.size(); ++i)
312 aRecentCharList[i] = maRecentCharList[i];
313 aRecentCharFontList[i] = maRecentCharFontList[i];
316 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
317 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
318 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
319 batch->commit();
321 updateRecentCharControl();
325 void SvxCharacterMap::updateFavCharacterList(const OUString& sTitle, const OUString& rFont)
327 auto itChar = std::find(maFavCharList.begin(), maFavCharList.end(), sTitle);
329 auto itChar2 = std::find(maFavCharFontList.begin(), maFavCharFontList.end(), rFont);
331 // if Fav char to be added is already in list, remove it
332 if( itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
334 maFavCharList.erase( itChar );
335 maFavCharFontList.erase( itChar2);
338 if (maFavCharList.size() == 16)
340 maFavCharList.pop_back();
341 maFavCharFontList.pop_back();
344 maFavCharList.push_back(sTitle);
345 maFavCharFontList.push_back(rFont);
347 css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
348 css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
350 for (size_t i = 0; i < maFavCharList.size(); ++i)
352 aFavCharList[i] = maFavCharList[i];
353 aFavCharFontList[i] = maFavCharFontList[i];
356 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
357 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
358 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
359 batch->commit();
363 void SvxCharacterMap::updateFavCharControl()
365 int i = 0;
366 for ( std::deque< OUString >::iterator it = maFavCharList.begin(), it2 = maFavCharFontList.begin();
367 it != maFavCharList.end() || it2 != maFavCharFontList.end();
368 ++it, ++it2, i++)
370 m_aFavCharView[i].SetText(*it);
371 vcl::Font rFont = m_aFavCharView[i].GetFont();
372 rFont.SetFamilyName( *it2 );
373 m_aFavCharView[i].SetFont(rFont);
374 m_aFavCharView[i].Show();
377 for(; i < 16 ; i++)
379 m_aFavCharView[i].SetText(OUString());
380 m_aFavCharView[i].Hide();
382 m_xShowSet->getFavCharacterList();
383 m_xSearchSet->getFavCharacterList();
386 void SvxCharacterMap::deleteFavCharacterFromList(const OUString& sTitle, const OUString& rFont)
388 auto itChar = std::find(maFavCharList.begin(), maFavCharList.end(), sTitle);
390 auto itChar2 = std::find(maFavCharFontList.begin(), maFavCharFontList.end(), rFont);
392 // if Fav char to be added is already in list, remove it
393 if( itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
395 maFavCharList.erase( itChar );
396 maFavCharFontList.erase( itChar2);
399 css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
400 css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
402 for (size_t i = 0; i < maFavCharList.size(); ++i)
404 aFavCharList[i] = maFavCharList[i];
405 aFavCharFontList[i] = maFavCharFontList[i];
408 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
409 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
410 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
411 batch->commit();
414 void SvxCharacterMap::init()
416 aFont = m_xVirDev->GetFont();
417 aFont.SetTransparent( true );
418 aFont.SetFamily( FAMILY_DONTKNOW );
419 aFont.SetPitch( PITCH_DONTKNOW );
420 aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
422 OUString aDefStr( aFont.GetFamilyName() );
423 OUString aLastName;
424 int nCount = m_xVirDev->GetDevFontCount();
425 std::vector<weld::ComboBoxEntry> aEntries;
426 aEntries.reserve(nCount);
427 for (int i = 0; i < nCount; ++i)
429 OUString aFontName( m_xVirDev->GetDevFont( i ).GetFamilyName() );
430 if (aFontName != aLastName)
432 aLastName = aFontName;
433 aEntries.emplace_back(aFontName, OUString::number(i));
436 m_xFontLB->insert_vector(aEntries, true);
437 // the font may not be in the list =>
438 // try to find a font name token in list and select found font,
439 // else select topmost entry
440 bool bFound = (m_xFontLB->find_text(aDefStr) == -1);
441 if (!bFound)
443 sal_Int32 nIndex = 0;
446 OUString aToken = aDefStr.getToken(0, ';', nIndex);
447 if (m_xFontLB->find_text(aToken) != -1)
449 aDefStr = aToken;
450 bFound = true;
451 break;
454 while ( nIndex >= 0 );
457 if (bFound)
458 m_xFontLB->set_active_text(aDefStr);
459 else if (m_xFontLB->get_count() )
460 m_xFontLB->set_active(0);
461 FontSelectHdl(*m_xFontLB);
462 if (m_xSubsetLB->get_count())
463 m_xSubsetLB->set_active(0);
465 m_xFontLB->connect_changed(LINK( this, SvxCharacterMap, FontSelectHdl));
466 m_xSubsetLB->connect_changed(LINK( this, SvxCharacterMap, SubsetSelectHdl));
467 m_xOKBtn->connect_clicked(LINK(this, SvxCharacterMap, InsertClickHdl));
468 m_xOKBtn->show();
470 m_xShowSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, CharDoubleClickHdl ) );
471 m_xShowSet->SetSelectHdl( LINK( this, SvxCharacterMap, CharSelectHdl ) );
472 m_xShowSet->SetHighlightHdl( LINK( this, SvxCharacterMap, CharHighlightHdl ) );
473 m_xShowSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, CharPreSelectHdl ) );
474 m_xShowSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
476 m_xSearchSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, SearchCharDoubleClickHdl ) );
477 m_xSearchSet->SetSelectHdl( LINK( this, SvxCharacterMap, SearchCharSelectHdl ) );
478 m_xSearchSet->SetHighlightHdl( LINK( this, SvxCharacterMap, SearchCharHighlightHdl ) );
479 m_xSearchSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, SearchCharPreSelectHdl ) );
480 m_xSearchSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
482 m_xDecimalCodeText->connect_changed( LINK( this, SvxCharacterMap, DecimalCodeChangeHdl ) );
483 m_xHexCodeText->connect_changed( LINK( this, SvxCharacterMap, HexCodeChangeHdl ) );
484 m_xFavouritesBtn->connect_clicked( LINK(this, SvxCharacterMap, FavSelectHdl));
486 // tdf#117038 set the buttons width to its max possible width so it doesn't
487 // make layout change when the label changes
488 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_REMOVE_FAVORITES));
489 auto nMaxWidth = m_xFavouritesBtn->get_preferred_size().Width();
490 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
491 nMaxWidth = std::max(nMaxWidth, m_xFavouritesBtn->get_preferred_size().Width());
492 m_xFavouritesBtn->set_size_request(nMaxWidth, -1);
494 if( SvxShowCharSet::getSelectedChar() == ' ')
496 m_xOKBtn->set_sensitive(false);
498 else
500 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
501 // using the new UCS4 constructor
502 OUString aOUStr( &cChar, 1 );
503 m_aShowChar.SetText(aOUStr);
505 setFavButtonState(aOUStr, aDefStr);
506 m_xOKBtn->set_sensitive(true);
509 getRecentCharacterList();
510 updateRecentCharControl();
512 getFavCharacterList();
513 updateFavCharControl();
515 bool bHasInsert = m_xFrame.is();
517 for(int i = 0; i < 16; i++)
519 m_aRecentCharView[i].SetHasInsert(bHasInsert);
520 m_aRecentCharView[i].setMouseClickHdl(LINK(this,SvxCharacterMap, CharClickHdl));
521 m_aRecentCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, RecentClearClickHdl));
522 m_aRecentCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, RecentClearAllClickHdl));
523 m_aFavCharView[i].SetHasInsert(bHasInsert);
524 m_aFavCharView[i].setMouseClickHdl(LINK(this,SvxCharacterMap, CharClickHdl));
525 m_aFavCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, FavClearClickHdl));
526 m_aFavCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, FavClearAllClickHdl));
529 setCharName(90);
531 m_xSearchText->connect_focus_in(LINK( this, SvxCharacterMap, SearchFieldGetFocusHdl ));
532 m_xSearchText->connect_changed(LINK(this, SvxCharacterMap, SearchUpdateHdl));
535 bool SvxCharacterMap::isFavChar(const OUString& sTitle, const OUString& rFont)
537 auto isFavCharTitleExists = std::any_of(maFavCharList.begin(),
538 maFavCharList.end(),
539 [sTitle] (const OUString & a) { return a == sTitle; });
541 auto isFavCharFontExists = std::any_of(maFavCharFontList.begin(),
542 maFavCharFontList.end(),
543 [rFont] (const OUString & a) { return a == rFont; });
545 // if Fav char to be added is already in list, remove it
546 return isFavCharTitleExists && isFavCharFontExists;
550 void SvxCharacterMap::setFavButtonState(const OUString& sTitle, const OUString& rFont)
552 if(sTitle.isEmpty() || rFont.isEmpty())
554 m_xFavouritesBtn->set_sensitive(false);
555 return;
557 else
558 m_xFavouritesBtn->set_sensitive(true);
560 if (isFavChar(sTitle, rFont))
562 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_REMOVE_FAVORITES));
564 else
566 if(maFavCharList.size() == 16)
568 m_xFavouritesBtn->set_sensitive(false);
571 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
576 void SvxCharacterMap::SetCharFont( const vcl::Font& rFont )
578 // first get the underlying info in order to get font names
579 // like "Times New Roman;Times" resolved
580 vcl::Font aTmp(m_xVirDev->GetFontMetric(rFont));
582 if (aTmp.GetFamilyName() == "StarSymbol" && m_xFontLB->find_text(aTmp.GetFamilyName()) == -1)
584 //if for some reason, like font in an old document, StarSymbol is requested and it's not available, then
585 //try OpenSymbol instead
586 aTmp.SetFamilyName("OpenSymbol");
589 if (m_xFontLB->find_text(aTmp.GetFamilyName()) == -1)
590 return;
592 m_xFontLB->set_active_text(aTmp.GetFamilyName());
593 aFont = aTmp;
594 FontSelectHdl(*m_xFontLB);
595 if (m_xSubsetLB->get_count())
596 m_xSubsetLB->set_active(0);
599 void SvxCharacterMap::fillAllSubsets(weld::ComboBox& rListBox)
601 SubsetMap aAll(nullptr);
602 std::vector<weld::ComboBoxEntry> aEntries;
603 for (auto & subset : aAll.GetSubsetMap())
604 aEntries.emplace_back(subset.GetName());
605 rListBox.insert_vector(aEntries, true);
608 void SvxCharacterMap::insertCharToDoc(const OUString& sGlyph)
610 if(sGlyph.isEmpty())
611 return;
613 if (m_xFrame.is()) {
614 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
616 uno::Sequence<beans::PropertyValue> aArgs(2);
617 aArgs[0].Name = "Symbols";
618 aArgs[0].Value <<= sGlyph;
620 aArgs[1].Name = "FontName";
621 aArgs[1].Value <<= aFont.GetFamilyName();
622 comphelper::dispatchCommand(".uno:InsertSymbol", m_xFrame, aArgs);
624 updateRecentCharacterList(sGlyph, aFont.GetFamilyName());
626 } else {
627 sal_Int32 tmp = 0;
628 sal_UCS4 cChar = sGlyph.iterateCodePoints(&tmp);
629 const SfxItemPool* pPool = m_xOutputSet->GetPool();
630 m_xOutputSet->Put( SfxStringItem( pPool->GetWhich(SID_CHARMAP), sGlyph ) );
631 m_xOutputSet->Put( SvxFontItem( aFont.GetFamilyType(), aFont.GetFamilyName(),
632 aFont.GetStyleName(), aFont.GetPitch(), aFont.GetCharSet(), pPool->GetWhich(SID_ATTR_CHAR_FONT) ) );
633 m_xOutputSet->Put( SfxStringItem( pPool->GetWhich(SID_FONT_NAME), aFont.GetFamilyName() ) );
634 m_xOutputSet->Put( SfxInt32Item( pPool->GetWhich(SID_ATTR_CHAR), cChar ) );
638 IMPL_LINK_NOARG(SvxCharacterMap, FontSelectHdl, weld::ComboBox&, void)
640 const sal_uInt32 nFont = m_xFontLB->get_active_id().toUInt32();
641 aFont = m_xVirDev->GetDevFont(nFont);
642 aFont.SetWeight( WEIGHT_DONTKNOW );
643 aFont.SetItalic( ITALIC_NONE );
644 aFont.SetWidthType( WIDTH_DONTKNOW );
645 aFont.SetPitch( PITCH_DONTKNOW );
646 aFont.SetFamily( FAMILY_DONTKNOW );
648 // notify children using this font
649 m_xShowSet->SetFont( aFont );
650 m_xSearchSet->SetFont( aFont );
651 m_aShowChar.SetFont( aFont );
652 if (isSearchMode)
654 SearchUpdateHdl(*m_xSearchText);
655 SearchCharHighlightHdl(m_xSearchSet.get());
658 // setup unicode subset listbar with font specific subsets,
659 // hide unicode subset listbar for symbol fonts
660 // TODO: get info from the Font once it provides it
661 pSubsetMap.reset();
662 m_xSubsetLB->clear();
664 bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL);
665 if (bNeedSubset)
667 FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
668 pSubsetMap.reset(new SubsetMap( xFontCharMap ));
670 // update subset listbox for new font's unicode subsets
671 for (auto const& subset : pSubsetMap->GetSubsetMap())
673 m_xSubsetLB->append(OUString::number(reinterpret_cast<sal_uInt64>(&subset)), subset.GetName());
674 // NOTE: subset must live at least as long as the selected font
677 if (m_xSubsetLB->get_count() <= 1)
678 bNeedSubset = false;
681 m_xSubsetText->set_sensitive(bNeedSubset);
682 m_xSubsetLB->set_sensitive(bNeedSubset);
684 // tdf#118304 reselect current glyph to see if its still there in new font
685 selectCharByCode(Radix::hexadecimal);
688 void SvxCharacterMap::toggleSearchView(bool state)
690 isSearchMode = state;
691 m_xHexCodeText->set_editable(!state);
692 m_xDecimalCodeText->set_editable(!state);
693 m_xSubsetLB->set_sensitive(!state);
695 if(state)
697 m_xSearchSet->Show();
698 m_xShowSet->Hide();
700 else
702 m_xSearchSet->Hide();
703 m_xShowSet->Show();
707 void SvxCharacterMap::setCharName(sal_UCS4 nDecimalValue)
709 /* get the character name */
710 UErrorCode errorCode = U_ZERO_ERROR;
711 // icu has a private uprv_getMaxCharNameLength function which returns the max possible
712 // length of this property. Unicode 3.2 max char name length was 83
713 char buffer[100];
714 u_charName(nDecimalValue, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
715 if (U_SUCCESS(errorCode))
716 m_xCharName->set_label(OUString::createFromAscii(buffer));
719 IMPL_LINK_NOARG(SvxCharacterMap, SubsetSelectHdl, weld::ComboBox&, void)
721 const sal_Int32 nPos = m_xSubsetLB->get_active();
722 const Subset* pSubset = reinterpret_cast<const Subset*>(m_xSubsetLB->get_active_id().toUInt64());
724 if( pSubset && !isSearchMode)
726 sal_UCS4 cFirst = pSubset->GetRangeMin();
727 m_xShowSet->SelectCharacter( cFirst );
729 setFavButtonState(OUString(&cFirst, 1), aFont.GetFamilyName());
730 m_xSubsetLB->set_active(nPos);
732 else if( pSubset && isSearchMode)
734 m_xSearchSet->SelectCharacter( pSubset );
736 const Subset* curSubset = nullptr;
737 if( pSubsetMap )
738 curSubset = pSubsetMap->GetSubsetByUnicode( m_xSearchSet->GetSelectCharacter() );
739 if( curSubset )
740 m_xSubsetLB->set_active_text(curSubset->GetName());
741 else
742 m_xSubsetLB->set_active(-1);
744 sal_UCS4 sChar = m_xSearchSet->GetSelectCharacter();
745 setFavButtonState(OUString(&sChar, 1), aFont.GetFamilyName());
749 IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView*, rView, void)
751 const OUString& sTitle = rView->GetText();
752 auto itChar = std::find(maRecentCharList.begin(), maRecentCharList.end(), sTitle);
754 OUString sFont = rView->GetFont().GetFamilyName();
755 auto itChar2 = std::find(maRecentCharFontList.begin(), maRecentCharFontList.end(), sFont);
757 // if recent char to be added is already in list, remove it
758 if( itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
760 maRecentCharList.erase( itChar );
761 maRecentCharFontList.erase( itChar2);
764 css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
765 css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
767 for (size_t i = 0; i < maRecentCharList.size(); ++i)
769 aRecentCharList[i] = maRecentCharList[i];
770 aRecentCharFontList[i] = maRecentCharFontList[i];
773 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
774 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
775 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
776 batch->commit();
778 updateRecentCharControl();
781 IMPL_LINK_NOARG(SvxCharacterMap, RecentClearAllClickHdl, SvxCharView*, void)
783 css::uno::Sequence< OUString > aRecentCharList(0);
784 css::uno::Sequence< OUString > aRecentCharFontList(0);
786 maRecentCharList.clear();
787 maRecentCharFontList.clear();
789 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
790 officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
791 officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
792 batch->commit();
794 updateRecentCharControl();
797 IMPL_LINK(SvxCharacterMap, FavClearClickHdl, SvxCharView*, rView, void)
799 deleteFavCharacterFromList(rView->GetText(), rView->GetFont().GetFamilyName());
800 updateFavCharControl();
803 IMPL_LINK_NOARG(SvxCharacterMap, FavClearAllClickHdl, SvxCharView*, void)
805 css::uno::Sequence< OUString > aFavCharList(0);
806 css::uno::Sequence< OUString > aFavCharFontList(0);
808 maFavCharList.clear();
809 maFavCharFontList.clear();
811 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
812 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
813 officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
814 batch->commit();
816 updateFavCharControl();
819 IMPL_LINK_NOARG(SvxCharacterMap, SearchFieldGetFocusHdl, weld::Widget&, void)
821 m_xOKBtn->set_sensitive(false);
824 IMPL_LINK_NOARG(SvxCharacterMap, SearchUpdateHdl, weld::Entry&, void)
826 if (!m_xSearchText->get_text().isEmpty())
828 m_xSearchSet->ClearPreviousData();
829 OUString aKeyword = m_xSearchText->get_text();
831 toggleSearchView(true);
833 FontCharMapRef xFontCharMap = m_xSearchSet->GetFontCharMap();
835 sal_UCS4 sChar = xFontCharMap->GetFirstChar();
836 while(sChar != xFontCharMap->GetLastChar())
838 UErrorCode errorCode = U_ZERO_ERROR;
839 char buffer[100];
840 u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
841 if (U_SUCCESS(errorCode))
843 OUString sName = OUString::createFromAscii(buffer);
844 if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
845 m_xSearchSet->AppendCharToList(sChar);
847 sChar = xFontCharMap->GetNextChar(sChar);
849 //for last char
850 UErrorCode errorCode = U_ZERO_ERROR;
851 char buffer[100];
852 u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
853 if (U_SUCCESS(errorCode))
855 OUString sName = OUString::createFromAscii(buffer);
856 if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
857 m_xSearchSet->AppendCharToList(sChar);
860 else
862 toggleSearchView(false);
867 IMPL_LINK(SvxCharacterMap, CharClickHdl, SvxCharView*, rView, void)
869 rView->GrabFocus();
871 m_aShowChar.SetText( rView->GetText() );
872 m_aShowChar.SetFont(rView->GetFont());
873 m_aShowChar.Invalidate();
875 setFavButtonState(rView->GetText(), rView->GetFont().GetFamilyName());//check state
877 // Get the hexadecimal code
878 OUString charValue = rView->GetText();
879 sal_Int32 tmp = 1;
880 sal_UCS4 cChar = charValue.iterateCodePoints(&tmp, -1);
881 OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
883 // Get the decimal code
884 OUString aDecimalText = OUString::number(cChar);
886 m_xHexCodeText->set_text(aHexText);
887 m_xDecimalCodeText->set_text(aDecimalText);
888 setCharName(cChar);
890 rView->Invalidate();
891 m_xOKBtn->set_sensitive(true);
894 IMPL_LINK_NOARG(SvxCharacterMap, CharDoubleClickHdl, SvxShowCharSet*, void)
896 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
897 // using the new UCS4 constructor
898 OUString aOUStr( &cChar, 1 );
899 setFavButtonState(aOUStr, aFont.GetFamilyName());
900 insertCharToDoc(aOUStr);
903 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharDoubleClickHdl, SvxShowCharSet*, void)
905 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
906 // using the new UCS4 constructor
907 OUString aOUStr( &cChar, 1 );
908 setFavButtonState(aOUStr, aFont.GetFamilyName());
909 insertCharToDoc(aOUStr);
912 IMPL_LINK_NOARG(SvxCharacterMap, CharSelectHdl, SvxShowCharSet*, void)
914 m_xOKBtn->set_sensitive(true);
917 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharSelectHdl, SvxShowCharSet*, void)
919 m_xOKBtn->set_sensitive(true);
922 IMPL_LINK_NOARG(SvxCharacterMap, InsertClickHdl, weld::Button&, void)
924 insertCharToDoc(m_aShowChar.GetText());
925 m_xDialog->response(RET_OK);
928 IMPL_LINK_NOARG(SvxCharacterMap, FavSelectHdl, weld::Button&, void)
930 if (m_xFavouritesBtn->get_label().match(CuiResId(RID_SVXSTR_ADD_FAVORITES)))
932 updateFavCharacterList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
933 setFavButtonState(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
935 else
937 deleteFavCharacterFromList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
938 m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
939 m_xFavouritesBtn->set_sensitive(false);
942 updateFavCharControl();
945 IMPL_LINK_NOARG(SvxCharacterMap, FavClickHdl, SvxShowCharSet*, void)
947 getFavCharacterList();
948 updateFavCharControl();
951 IMPL_LINK_NOARG(SvxCharacterMap, CharHighlightHdl, SvxShowCharSet*, void)
953 OUString aText;
954 OUString aHexText;
955 OUString aDecimalText;
956 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
957 bool bSelect = (cChar > 0);
959 // show char sample
960 if ( bSelect )
962 // using the new UCS4 constructor
963 aText = OUString( &cChar, 1 );
964 // Get the hexadecimal code
965 aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
966 // Get the decimal code
967 aDecimalText = OUString::number(cChar);
968 setCharName(cChar);
970 // Update the hex and decimal codes only if necessary
971 if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
972 m_xHexCodeText->set_text(aHexText);
973 if (m_xDecimalCodeText->get_text() != aDecimalText)
974 m_xDecimalCodeText->set_text( aDecimalText );
976 const Subset* pSubset = nullptr;
977 if( pSubsetMap )
978 pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
979 if( pSubset )
980 m_xSubsetLB->set_active_text(pSubset->GetName());
981 else
982 m_xSubsetLB->set_active(-1);
985 m_aShowChar.SetText( aText );
986 m_aShowChar.SetFont( aFont );
987 m_aShowChar.Invalidate();
989 setFavButtonState(aText, aFont.GetFamilyName());
992 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharHighlightHdl, SvxShowCharSet*, void)
994 OUString aText;
995 OUString aHexText;
996 OUString aDecimalText;
997 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
998 bool bSelect = (cChar > 0);
1000 // show char sample
1001 if ( bSelect )
1003 aText = OUString( &cChar, 1 );
1004 // Get the hexadecimal code
1005 aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
1006 // Get the decimal code
1007 aDecimalText = OUString::number(cChar);
1008 setCharName(cChar);
1010 // Update the hex and decimal codes only if necessary
1011 if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
1012 m_xHexCodeText->set_text(aHexText);
1013 if (m_xDecimalCodeText->get_text() != aDecimalText)
1014 m_xDecimalCodeText->set_text( aDecimalText );
1016 const Subset* pSubset = nullptr;
1017 if( pSubsetMap )
1018 pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1019 if( pSubset )
1020 m_xSubsetLB->set_active_text(pSubset->GetName());
1021 else
1022 m_xSubsetLB->set_active(-1);
1025 if(m_xSearchSet->HasFocus())
1027 m_aShowChar.SetText( aText );
1028 m_aShowChar.SetFont( aFont );
1029 m_aShowChar.Invalidate();
1031 setFavButtonState(aText, aFont.GetFamilyName());
1035 void SvxCharacterMap::selectCharByCode(Radix radix)
1037 OUString aCodeString;
1038 switch(radix)
1040 case Radix::decimal:
1041 aCodeString = m_xDecimalCodeText->get_text();
1042 break;
1043 case Radix::hexadecimal:
1044 aCodeString = m_xHexCodeText->get_text();
1045 break;
1047 // Convert the code back to a character using the appropriate radix
1048 sal_UCS4 cChar = aCodeString.toUInt32(static_cast<sal_Int16> (radix));
1049 // Use FontCharMap::HasChar(sal_UCS4 cChar) to see if the desired character is in the font
1050 FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
1051 if (xFontCharMap->HasChar(cChar))
1052 // Select the corresponding character
1053 SetChar(cChar);
1054 else {
1055 m_xCharName->set_label(CuiResId(RID_SVXSTR_MISSING_CHAR));
1056 m_aShowChar.SetText(" ");
1057 switch(radix)
1059 case Radix::decimal:
1060 m_xHexCodeText->set_text(OUString::number(cChar, 16));
1061 break;
1062 case Radix::hexadecimal:
1063 m_xDecimalCodeText->set_text(OUString::number(cChar));
1064 break;
1069 IMPL_LINK_NOARG(SvxCharacterMap, DecimalCodeChangeHdl, weld::Entry&, void)
1071 selectCharByCode(Radix::decimal);
1074 IMPL_LINK_NOARG(SvxCharacterMap, HexCodeChangeHdl, weld::Entry&, void)
1076 selectCharByCode(Radix::hexadecimal);
1079 IMPL_LINK_NOARG(SvxCharacterMap, CharPreSelectHdl, SvxShowCharSet*, void)
1081 // adjust subset selection
1082 if( pSubsetMap )
1084 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
1086 setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName());
1087 const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1088 if( pSubset )
1089 m_xSubsetLB->set_active_text(pSubset->GetName());
1092 m_xOKBtn->set_sensitive(true);
1095 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharPreSelectHdl, SvxShowCharSet*, void)
1097 // adjust subset selection
1098 if( pSubsetMap )
1100 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
1102 setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName());
1103 const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1104 if( pSubset )
1105 m_xSubsetLB->set_active_text(pSubset->GetName());
1108 m_xOKBtn->set_sensitive(true);
1111 // class SvxShowText =====================================================
1112 SvxShowText::SvxShowText(const VclPtr<VirtualDevice>& rVirDev)
1113 : m_xVirDev(rVirDev)
1114 , mnY(0)
1115 , mbCenter(false)
1119 void SvxShowText::SetDrawingArea(weld::DrawingArea* pDrawingArea)
1121 CustomWidgetController::SetDrawingArea(pDrawingArea);
1122 vcl::Font aFont = m_xVirDev->GetFont();
1123 Size aFontSize(aFont.GetFontSize().Width() * 5, aFont.GetFontSize().Height() * 5);
1124 aFont.SetFontSize(aFontSize);
1125 m_xVirDev->Push(PUSH_ALLFONT);
1126 m_xVirDev->SetFont(aFont);
1127 pDrawingArea->set_size_request(m_xVirDev->approximate_digit_width() + 2 * 12,
1128 m_xVirDev->LogicToPixel(aFontSize).Height() * 2);
1129 m_xVirDev->Pop();
1132 void SvxShowText::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
1134 rRenderContext.SetFont(m_aFont);
1136 Color aTextCol = rRenderContext.GetTextColor();
1137 Color aFillCol = rRenderContext.GetFillColor();
1139 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1140 const Color aWindowTextColor(rStyleSettings.GetDialogTextColor());
1141 const Color aWindowColor(rStyleSettings.GetWindowColor());
1142 rRenderContext.SetTextColor(aWindowTextColor);
1143 rRenderContext.SetFillColor(aWindowColor);
1145 const OUString aText = GetText();
1147 Size aSize(GetOutputSizePixel());
1148 long nAvailWidth = aSize.Width();
1149 long nWinHeight = aSize.Height();
1151 bool bGotBoundary = true;
1152 bool bShrankFont = false;
1153 vcl::Font aOrigFont(rRenderContext.GetFont());
1154 Size aFontSize(aOrigFont.GetFontSize());
1155 ::tools::Rectangle aBoundRect;
1157 for (long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 5)
1159 if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty())
1161 bGotBoundary = false;
1162 break;
1164 if (!mbCenter)
1165 break;
1166 //only shrink in the single glyph large view mode
1167 long nTextWidth = aBoundRect.GetWidth();
1168 if (nAvailWidth > nTextWidth)
1169 break;
1170 vcl::Font aFont(aOrigFont);
1171 aFontSize.setHeight( nFontHeight );
1172 aFont.SetFontSize(aFontSize);
1173 rRenderContext.SetFont(aFont);
1174 mnY = (nWinHeight - rRenderContext.GetTextHeight()) / 2;
1175 bShrankFont = true;
1178 Point aPoint(2, mnY);
1179 // adjust position using ink boundary if possible
1180 if (!bGotBoundary)
1181 aPoint.setX( (aSize.Width() - rRenderContext.GetTextWidth(aText)) / 2 );
1182 else
1184 // adjust position before it gets out of bounds
1185 aBoundRect += aPoint;
1187 // shift back vertically if needed
1188 int nYLDelta = aBoundRect.Top();
1189 int nYHDelta = aSize.Height() - aBoundRect.Bottom();
1190 if( nYLDelta <= 0 )
1191 aPoint.AdjustY( -(nYLDelta - 1) );
1192 else if( nYHDelta <= 0 )
1193 aPoint.AdjustY(nYHDelta - 1 );
1195 if (mbCenter)
1197 // move glyph to middle of cell
1198 aPoint.setX( -aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2 );
1200 else
1202 // shift back horizontally if needed
1203 int nXLDelta = aBoundRect.Left();
1204 int nXHDelta = aSize.Width() - aBoundRect.Right();
1205 if( nXLDelta <= 0 )
1206 aPoint.AdjustX( -(nXLDelta - 1) );
1207 else if( nXHDelta <= 0 )
1208 aPoint.AdjustX(nXHDelta - 1 );
1212 rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize));
1213 rRenderContext.DrawText(aPoint, aText);
1214 rRenderContext.SetTextColor(aTextCol);
1215 rRenderContext.SetFillColor(aFillCol);
1216 if (bShrankFont)
1217 rRenderContext.SetFont(aOrigFont);
1220 void SvxShowText::SetFont( const vcl::Font& rFont )
1222 long nWinHeight = GetOutputSizePixel().Height();
1224 m_aFont = rFont;
1225 m_aFont.SetWeight(WEIGHT_NORMAL);
1226 m_aFont.SetAlignment(ALIGN_TOP);
1227 m_aFont.SetFontSize(m_xVirDev->PixelToLogic(Size(0, nWinHeight / 2)));
1228 m_aFont.SetTransparent(true);
1230 m_xVirDev->Push(PUSH_ALLFONT);
1231 m_xVirDev->SetFont(m_aFont);
1232 mnY = (nWinHeight - m_xVirDev->GetTextHeight()) / 2;
1233 m_xVirDev->Pop();
1235 Invalidate();
1238 void SvxShowText::Resize()
1240 SetFont(GetFont()); //force recalculation of size
1243 void SvxShowText::SetText(const OUString& rText)
1245 m_sText = rText;
1246 Invalidate();
1249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */