LibreOffice Module cui (master)  1
cuicharmap.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <stdio.h>
21 
22 #include <vcl/svapp.hxx>
23 #include <svl/eitem.hxx>
24 #include <svl/intitem.hxx>
25 #include <svl/itempool.hxx>
26 
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>
36 
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>
46 
47 using namespace css;
48 
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)
56  , m_aRecentCharView{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))
138 {
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());
150 
151  init();
152 
153  const SfxInt32Item* pCharItem = SfxItemSet::GetItem<SfxInt32Item>(pSet, SID_ATTR_CHAR, false);
154  if ( pCharItem )
155  SetChar( pCharItem->GetValue() );
156 
157  const SfxBoolItem* pDisableItem = SfxItemSet::GetItem<SfxBoolItem>(pSet, FN_PARAM_2, false);
158  if ( pDisableItem && pDisableItem->GetValue() )
159  DisableFontSelection();
160 
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 )
164  {
165  vcl::Font aTmpFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), GetCharFont().GetFontSize() );
166  aTmpFont.SetCharSet( pFontItem->GetCharSet() );
167  aTmpFont.SetPitch( pFontItem->GetPitch() );
168  SetCharFont( aTmpFont );
169  }
170  else if ( pFontNameItem )
171  {
172  vcl::Font aTmpFont( GetCharFont() );
173  aTmpFont.SetFamilyName( pFontNameItem->GetValue() );
174  SetCharFont( aTmpFont );
175  }
176 
177  m_xOutputSet.reset(new SfxAllItemSet(pSet ? *pSet->GetPool() : SfxGetpApp()->GetPool()));
178  m_xShowSet->Show();
179  m_xSearchSet->Hide();
180 }
181 
183 {
184  if( SvxShowCharSet::getSelectedChar() == ' ')
185  {
186  m_xOKBtn->set_sensitive(false);
187  setFavButtonState(OUString(), OUString());
188  }
189  else
190  {
191  sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
192  // using the new UCS4 constructor
193  OUString aOUStr( &cChar, 1 );
194  m_aShowChar.SetText(aOUStr);
195 
197  m_xOKBtn->set_sensitive(true);
198  }
199 
200  return SfxDialogController::run();
201 }
202 
204 {
205  m_xShowSet->SelectCharacter( c );
206  setFavButtonState(OUString(&c, 1), aFont.GetFamilyName());
207 }
208 
210 {
211  return m_aShowChar.GetText().toChar();
212 }
213 
215 {
216  m_xFontText->set_sensitive(false);
217  m_xFontLB->set_sensitive(false);
218 }
219 
220 
222 {
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)
226  {
227  maRecentCharList.push_back(rRecentCharList[i]);
228  }
229 
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)
233  {
234  maRecentCharFontList.push_back(rRecentCharFontList[i]);
235  }
236 }
237 
238 
240 {
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)
246  {
247  maFavCharList.push_back(rFavCharList[i]);
248  }
249 
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)
253  {
254  maFavCharFontList.push_back(rFavCharFontList[i]);
255  }
256 }
257 
258 
260 {
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++)
265  {
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();
271  }
272 
273  for(; i < 16 ; i++)
274  {
275  m_aRecentCharView[i].SetText(OUString());
276  m_aRecentCharView[i].Hide();
277  }
278 }
279 
280 void SvxCharacterMap::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont)
281 {
282  auto itChar = std::find(maRecentCharList.begin(), maRecentCharList.end(), sTitle);
283 
284  auto itChar2 = std::find(maRecentCharFontList.begin(), maRecentCharFontList.end(), rFont);
285 
286  // if recent char to be added is already in list, remove it
287  if( itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
288  {
289  maRecentCharList.erase( itChar );
290  maRecentCharFontList.erase( itChar2);
291  }
292 
293  if (maRecentCharList.size() == 16)
294  {
295  maRecentCharList.pop_back();
296  maRecentCharFontList.pop_back();
297  }
298 
299  maRecentCharList.push_front(sTitle);
300  maRecentCharFontList.push_front(rFont);
301 
302  css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
303  css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
304 
305  for (size_t i = 0; i < maRecentCharList.size(); ++i)
306  {
307  aRecentCharList[i] = maRecentCharList[i];
308  aRecentCharFontList[i] = maRecentCharFontList[i];
309  }
310 
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();
315 
317 }
318 
319 
320 void SvxCharacterMap::updateFavCharacterList(const OUString& sTitle, const OUString& rFont)
321 {
322  auto itChar = std::find(maFavCharList.begin(), maFavCharList.end(), sTitle);
323 
324  auto itChar2 = std::find(maFavCharFontList.begin(), maFavCharFontList.end(), rFont);
325 
326  // if Fav char to be added is already in list, remove it
327  if( itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
328  {
329  maFavCharList.erase( itChar );
330  maFavCharFontList.erase( itChar2);
331  }
332 
333  if (maFavCharList.size() == 16)
334  {
335  maFavCharList.pop_back();
336  maFavCharFontList.pop_back();
337  }
338 
339  maFavCharList.push_back(sTitle);
340  maFavCharFontList.push_back(rFont);
341 
342  css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
343  css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
344 
345  for (size_t i = 0; i < maFavCharList.size(); ++i)
346  {
347  aFavCharList[i] = maFavCharList[i];
348  aFavCharFontList[i] = maFavCharFontList[i];
349  }
350 
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();
355 }
356 
357 
359 {
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++)
364  {
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();
370  }
371 
372  for(; i < 16 ; i++)
373  {
374  m_aFavCharView[i].SetText(OUString());
375  m_aFavCharView[i].Hide();
376  }
377  m_xShowSet->getFavCharacterList();
378  m_xSearchSet->getFavCharacterList();
379 }
380 
381 void SvxCharacterMap::deleteFavCharacterFromList(const OUString& sTitle, const OUString& rFont)
382 {
383  auto itChar = std::find(maFavCharList.begin(), maFavCharList.end(), sTitle);
384 
385  auto itChar2 = std::find(maFavCharFontList.begin(), maFavCharFontList.end(), rFont);
386 
387  // if Fav char to be added is already in list, remove it
388  if( itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
389  {
390  maFavCharList.erase( itChar );
391  maFavCharFontList.erase( itChar2);
392  }
393 
394  css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
395  css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
396 
397  for (size_t i = 0; i < maFavCharList.size(); ++i)
398  {
399  aFavCharList[i] = maFavCharList[i];
400  aFavCharFontList[i] = maFavCharFontList[i];
401  }
402 
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();
407 }
408 
410 {
411  aFont = m_xVirDev->GetFont();
412  aFont.SetTransparent( true );
415  aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
416 
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)
423  {
424  OUString aFontName( m_xVirDev->GetDevFont( i ).GetFamilyName() );
425  if (aFontName != aLastName)
426  {
427  aLastName = aFontName;
428  aEntries.emplace_back(aFontName, OUString::number(i));
429  }
430  }
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)
437  {
438  sal_Int32 nIndex = 0;
439  do
440  {
441  OUString aToken = aDefStr.getToken(0, ';', nIndex);
442  if (m_xFontLB->find_text(aToken) != -1)
443  {
444  aDefStr = aToken;
445  bFound = true;
446  break;
447  }
448  }
449  while ( nIndex >= 0 );
450  }
451 
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);
459 
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();
464 
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 ) );
470 
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 ) );
476 
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));
480 
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);
488 
489  if( SvxShowCharSet::getSelectedChar() == ' ')
490  {
491  m_xOKBtn->set_sensitive(false);
492  }
493  else
494  {
495  sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
496  // using the new UCS4 constructor
497  OUString aOUStr( &cChar, 1 );
498  m_aShowChar.SetText(aOUStr);
499 
500  setFavButtonState(aOUStr, aDefStr);
501  m_xOKBtn->set_sensitive(true);
502  }
503 
506 
509 
510  bool bHasInsert = m_xFrame.is();
511 
512  for(int i = 0; i < 16; i++)
513  {
514  m_aRecentCharView[i].SetHasInsert(bHasInsert);
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));
522  }
523 
524  setCharName(90);
525 
526  m_xSearchText->connect_focus_in(LINK( this, SvxCharacterMap, SearchFieldGetFocusHdl ));
527  m_xSearchText->connect_changed(LINK(this, SvxCharacterMap, SearchUpdateHdl));
528 }
529 
530 bool SvxCharacterMap::isFavChar(const OUString& sTitle, const OUString& rFont)
531 {
532  auto isFavCharTitleExists = std::any_of(maFavCharList.begin(),
533  maFavCharList.end(),
534  [sTitle] (const OUString & a) { return a == sTitle; });
535 
536  auto isFavCharFontExists = std::any_of(maFavCharFontList.begin(),
537  maFavCharFontList.end(),
538  [rFont] (const OUString & a) { return a == rFont; });
539 
540  // if Fav char to be added is already in list, remove it
541  return isFavCharTitleExists && isFavCharFontExists;
542 }
543 
544 
545 void SvxCharacterMap::setFavButtonState(const OUString& sTitle, const OUString& rFont)
546 {
547  if(sTitle.isEmpty() || rFont.isEmpty())
548  {
549  m_xFavouritesBtn->set_sensitive(false);
550  return;
551  }
552  else
553  m_xFavouritesBtn->set_sensitive(true);
554 
555  if (isFavChar(sTitle, rFont))
556  {
557  m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_REMOVE_FAVORITES));
558  }
559  else
560  {
561  if(maFavCharList.size() == 16)
562  {
563  m_xFavouritesBtn->set_sensitive(false);
564  }
565 
566  m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
567  }
568 }
569 
570 
572 {
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));
576 
577  if (aTmp.GetFamilyName() == "StarSymbol" && m_xFontLB->find_text(aTmp.GetFamilyName()) == -1)
578  {
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");
582  }
583 
584  if (m_xFontLB->find_text(aTmp.GetFamilyName()) == -1)
585  return;
586 
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);
592 }
593 
595 {
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);
601 }
602 
603 void SvxCharacterMap::insertCharToDoc(const OUString& sGlyph)
604 {
605  if(sGlyph.isEmpty())
606  return;
607 
608  if (m_xFrame.is()) {
609  uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
610 
611  uno::Sequence<beans::PropertyValue> aArgs(2);
612  aArgs[0].Name = "Symbols";
613  aArgs[0].Value <<= sGlyph;
614 
615  aArgs[1].Name = "FontName";
616  aArgs[1].Value <<= aFont.GetFamilyName();
617  comphelper::dispatchCommand(".uno:InsertSymbol", m_xFrame, aArgs);
618 
620 
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 ) );
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 ) );
630  }
631 }
632 
634 {
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 );
642 
643  // notify children using this font
644  m_xShowSet->SetFont( aFont );
645  m_xSearchSet->SetFont( aFont );
646  m_aShowChar.SetFont( aFont );
647  if (isSearchMode)
648  {
649  SearchUpdateHdl(*m_xSearchText);
650  SearchCharHighlightHdl(m_xSearchSet.get());
651  }
652 
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();
658 
659  bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL);
660  if (bNeedSubset)
661  {
662  FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
663  pSubsetMap.reset(new SubsetMap( xFontCharMap ));
664 
665  // update subset listbox for new font's unicode subsets
666  for (auto const& subset : pSubsetMap->GetSubsetMap())
667  {
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
670  }
671 
672  if (m_xSubsetLB->get_count() <= 1)
673  bNeedSubset = false;
674  }
675 
676  m_xSubsetText->set_sensitive(bNeedSubset);
677  m_xSubsetLB->set_sensitive(bNeedSubset);
678 
679  // tdf#118304 reselect current glyph to see if its still there in new font
680  selectCharByCode(Radix::hexadecimal);
681 }
682 
684 {
685  isSearchMode = state;
686  m_xHexCodeText->set_editable(!state);
687  m_xDecimalCodeText->set_editable(!state);
688  m_xSubsetLB->set_sensitive(!state);
689 
690  if(state)
691  {
692  m_xSearchSet->Show();
693  m_xShowSet->Hide();
694  }
695  else
696  {
697  m_xSearchSet->Hide();
698  m_xShowSet->Show();
699  }
700 }
701 
703 {
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));
712 }
713 
715 {
716  const sal_Int32 nPos = m_xSubsetLB->get_active();
717  const Subset* pSubset = reinterpret_cast<const Subset*>(m_xSubsetLB->get_active_id().toUInt64());
718 
719  if( pSubset && !isSearchMode)
720  {
721  sal_UCS4 cFirst = pSubset->GetRangeMin();
722  m_xShowSet->SelectCharacter( cFirst );
723 
724  setFavButtonState(OUString(&cFirst, 1), aFont.GetFamilyName());
725  m_xSubsetLB->set_active(nPos);
726  }
727  else if( pSubset && isSearchMode)
728  {
729  m_xSearchSet->SelectCharacter( pSubset );
730 
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);
738 
739  sal_UCS4 sChar = m_xSearchSet->GetSelectCharacter();
740  setFavButtonState(OUString(&sChar, 1), aFont.GetFamilyName());
741  }
742 }
743 
744 IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView*, rView, void)
745 {
746  const OUString& sTitle = rView->GetText();
747  auto itChar = std::find(maRecentCharList.begin(), maRecentCharList.end(), sTitle);
748 
749  OUString sFont = rView->GetFont().GetFamilyName();
750  auto itChar2 = std::find(maRecentCharFontList.begin(), maRecentCharFontList.end(), sFont);
751 
752  // if recent char to be added is already in list, remove it
753  if( itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
754  {
755  maRecentCharList.erase( itChar );
756  maRecentCharFontList.erase( itChar2);
757  }
758 
759  css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
760  css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
761 
762  for (size_t i = 0; i < maRecentCharList.size(); ++i)
763  {
764  aRecentCharList[i] = maRecentCharList[i];
765  aRecentCharFontList[i] = maRecentCharFontList[i];
766  }
767 
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();
772 
773  updateRecentCharControl();
774 }
775 
776 IMPL_LINK_NOARG(SvxCharacterMap, RecentClearAllClickHdl, SvxCharView*, void)
777 {
778  css::uno::Sequence< OUString > aRecentCharList(0);
779  css::uno::Sequence< OUString > aRecentCharFontList(0);
780 
781  maRecentCharList.clear();
782  maRecentCharFontList.clear();
783 
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();
788 
789  updateRecentCharControl();
790 }
791 
792 IMPL_LINK(SvxCharacterMap, FavClearClickHdl, SvxCharView*, rView, void)
793 {
794  deleteFavCharacterFromList(rView->GetText(), rView->GetFont().GetFamilyName());
795  updateFavCharControl();
796 }
797 
798 IMPL_LINK_NOARG(SvxCharacterMap, FavClearAllClickHdl, SvxCharView*, void)
799 {
800  css::uno::Sequence< OUString > aFavCharList(0);
801  css::uno::Sequence< OUString > aFavCharFontList(0);
802 
803  maFavCharList.clear();
804  maFavCharFontList.clear();
805 
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();
810 
811  updateFavCharControl();
812 }
813 
814 IMPL_LINK_NOARG(SvxCharacterMap, SearchFieldGetFocusHdl, weld::Widget&, void)
815 {
816  m_xOKBtn->set_sensitive(false);
817 }
818 
819 IMPL_LINK_NOARG(SvxCharacterMap, SearchUpdateHdl, weld::Entry&, void)
820 {
821  if (!m_xSearchText->get_text().isEmpty())
822  {
823  m_xSearchSet->ClearPreviousData();
824  OUString aKeyword = m_xSearchText->get_text();
825 
826  toggleSearchView(true);
827 
828  FontCharMapRef xFontCharMap = m_xSearchSet->GetFontCharMap();
829 
830  sal_UCS4 sChar = xFontCharMap->GetFirstChar();
831  while(sChar != xFontCharMap->GetLastChar())
832  {
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))
837  {
838  OUString sName = OUString::createFromAscii(buffer);
839  if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
840  m_xSearchSet->AppendCharToList(sChar);
841  }
842  sChar = xFontCharMap->GetNextChar(sChar);
843  }
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))
849  {
850  OUString sName = OUString::createFromAscii(buffer);
851  if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
852  m_xSearchSet->AppendCharToList(sChar);
853  }
854  }
855  else
856  {
857  toggleSearchView(false);
858  }
859 }
860 
861 
862 IMPL_LINK(SvxCharacterMap, CharClickHdl, SvxCharView*, rView, void)
863 {
864  rView->GrabFocus();
865 
866  m_aShowChar.SetText( rView->GetText() );
867  m_aShowChar.SetFont(rView->GetFont());
868  m_aShowChar.Invalidate();
869 
870  setFavButtonState(rView->GetText(), rView->GetFont().GetFamilyName());//check state
871 
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();
877 
878  // Get the decimal code
879  OUString aDecimalText = OUString::number(cChar);
880 
881  m_xHexCodeText->set_text(aHexText);
882  m_xDecimalCodeText->set_text(aDecimalText);
883  setCharName(cChar);
884 
885  rView->Invalidate();
886  m_xOKBtn->set_sensitive(true);
887 }
888 
889 IMPL_LINK_NOARG(SvxCharacterMap, CharDoubleClickHdl, SvxShowCharSet*, void)
890 {
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);
896 }
897 
898 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharDoubleClickHdl, SvxShowCharSet*, void)
899 {
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);
905 }
906 
908 {
909  m_xOKBtn->set_sensitive(true);
910 }
911 
912 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharSelectHdl, SvxShowCharSet*, void)
913 {
914  m_xOKBtn->set_sensitive(true);
915 }
916 
918 {
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);
925 }
926 
928 {
929  if (m_xFavouritesBtn->get_label().match(CuiResId(RID_SVXSTR_ADD_FAVORITES)))
930  {
931  updateFavCharacterList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
932  setFavButtonState(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
933  }
934  else
935  {
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);
939  }
940 
941  updateFavCharControl();
942 }
943 
945 {
946  getFavCharacterList();
947  updateFavCharControl();
948 }
949 
951 {
952  OUString aText;
953  OUString aHexText;
954  OUString aDecimalText;
955  sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
956  bool bSelect = (cChar > 0);
957 
958  // show char sample
959  if ( bSelect )
960  {
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);
968 
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 );
974 
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);
982  }
983 
984  m_aShowChar.SetText( aText );
985  m_aShowChar.SetFont( aFont );
986  m_aShowChar.Invalidate();
987 
988  setFavButtonState(aText, aFont.GetFamilyName());
989 }
990 
991 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharHighlightHdl, SvxShowCharSet*, void)
992 {
993  OUString aText;
994  OUString aHexText;
995  OUString aDecimalText;
996  sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
997  bool bSelect = (cChar > 0);
998 
999  // show char sample
1000  if ( bSelect )
1001  {
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);
1008 
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 );
1014 
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);
1022  }
1023 
1024  if(m_xSearchSet->HasFocus())
1025  {
1026  m_aShowChar.SetText( aText );
1027  m_aShowChar.SetFont( aFont );
1028  m_aShowChar.Invalidate();
1029 
1030  setFavButtonState(aText, aFont.GetFamilyName());
1031  }
1032 }
1033 
1035 {
1036  OUString aCodeString;
1037  switch(radix)
1038  {
1039  case Radix::decimal:
1040  aCodeString = m_xDecimalCodeText->get_text();
1041  break;
1042  case Radix::hexadecimal:
1043  aCodeString = m_xHexCodeText->get_text();
1044  break;
1045  }
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)
1057  {
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;
1064  }
1065  }
1066 }
1067 
1068 IMPL_LINK_NOARG(SvxCharacterMap, DecimalCodeChangeHdl, weld::Entry&, void)
1069 {
1070  selectCharByCode(Radix::decimal);
1071 }
1072 
1073 IMPL_LINK_NOARG(SvxCharacterMap, HexCodeChangeHdl, weld::Entry&, void)
1074 {
1075  selectCharByCode(Radix::hexadecimal);
1076 }
1077 
1079 {
1080  // adjust subset selection
1081  if( pSubsetMap )
1082  {
1083  sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
1084 
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());
1089  }
1090 
1091  m_xOKBtn->set_sensitive(true);
1092 }
1093 
1094 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharPreSelectHdl, SvxShowCharSet*, void)
1095 {
1096  // adjust subset selection
1097  if( pSubsetMap )
1098  {
1099  sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
1100 
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());
1105  }
1106 
1107  m_xOKBtn->set_sensitive(true);
1108 }
1109 
1110 // class SvxShowText =====================================================
1112  : m_xVirDev(rVirDev)
1113  , mnY(0)
1114  , mbCenter(false)
1115 {
1116 }
1117 
1119 {
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();
1129 }
1130 
1132 {
1133  rRenderContext.SetFont(m_aFont);
1134 
1135  Color aTextCol = rRenderContext.GetTextColor();
1136  Color aFillCol = rRenderContext.GetFillColor();
1137 
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);
1143 
1144  const OUString aText = GetText();
1145 
1146  Size aSize(GetOutputSizePixel());
1147  long nAvailWidth = aSize.Width();
1148  long nWinHeight = aSize.Height();
1149 
1150  bool bGotBoundary = true;
1151  bool bShrankFont = false;
1152  vcl::Font aOrigFont(rRenderContext.GetFont());
1153  Size aFontSize(aOrigFont.GetFontSize());
1154  ::tools::Rectangle aBoundRect;
1155 
1156  for (long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 5)
1157  {
1158  if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty())
1159  {
1160  bGotBoundary = false;
1161  break;
1162  }
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;
1175  }
1176 
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
1182  {
1183  // adjust position before it gets out of bounds
1184  aBoundRect += aPoint;
1185 
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 );
1193 
1194  if (mbCenter)
1195  {
1196  // move glyph to middle of cell
1197  aPoint.setX( -aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2 );
1198  }
1199  else
1200  {
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 );
1208  }
1209  }
1210 
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);
1217 }
1218 
1219 void SvxShowText::SetFont( const vcl::Font& rFont )
1220 {
1221  long nWinHeight = GetOutputSizePixel().Height();
1222 
1223  m_aFont = rFont;
1226  m_aFont.SetFontSize(m_xVirDev->PixelToLogic(Size(0, nWinHeight / 2)));
1227  m_aFont.SetTransparent(true);
1228 
1229  m_xVirDev->Push(PUSH_ALLFONT);
1230  m_xVirDev->SetFont(m_aFont);
1231  mnY = (nWinHeight - m_xVirDev->GetTextHeight()) / 2;
1232  m_xVirDev->Pop();
1233 
1234  Invalidate();
1235 }
1236 
1238 {
1239  SetFont(GetFont()); //force recalculation of size
1240 }
1241 
1242 void SvxShowText::SetText(const OUString& rText)
1243 {
1244  m_sText = rText;
1245  Invalidate();
1246 }
1247 
1248 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void updateRecentCharControl()
Definition: cuicharmap.cxx:259
void SetFamily(FontFamily)
long Width() const
const Color & GetTextColor() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, MetricVector *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
bool HasChar(sal_UCS4) const
sal_Int32 GetValue() const
long GetWidth() const
SvxCharView m_aFavCharView[16]
Definition: cuicharmap.hxx:88
void SetFontSize(const Size &)
SvxShowText m_aShowChar
Definition: cuicharmap.hxx:89
ScopedVclPtr< VirtualDevice > m_xVirDev
Definition: cuicharmap.hxx:47
const OUString & GetFamilyName() const
long AdjustX(long nHorzMove)
const OUString & GetStyleName() const
long Height() const
const SubsetVec & GetSubsetMap() const
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &) override
FAMILY_DONTKNOW
const OUString & GetName() const
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
std::unique_ptr< SvxSearchCharSet > m_xSearchSet
Definition: cuicharmap.hxx:108
void SetChar(sal_UCS4)
Definition: cuicharmap.cxx:203
void SetWeight(FontWeight)
void SetFont(const vcl::Font &rFont)
std::deque< OUString > maRecentCharList
Definition: cuicharmap.hxx:81
static void fillAllSubsets(weld::ComboBox &rListBox)
Definition: cuicharmap.cxx:594
void insertCharToDoc(const OUString &sChar)
Definition: cuicharmap.cxx:603
void SetCharSet(rtl_TextEncoding)
FontPitch GetPitch() const
OUString const & GetText() const
Definition: cuicharmap.hxx:63
ScopedVclPtr< VirtualDevice > m_xVirDev
Definition: cuicharmap.hxx:76
Size const & GetOutputSizePixel() const
FontFamily GetFamilyType()
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, const long *pDXArray=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
void selectCharByCode(Radix radix)
SfxApplication * SfxGetpApp()
std::unique_ptr< SfxAllItemSet > m_xOutputSet
Definition: cuicharmap.hxx:111
OUString m_sText
Definition: cuicharmap.hxx:48
void toggleSearchView(bool state)
Definition: cuicharmap.cxx:683
void setX(long nX)
const vcl::Font & GetFont() const
std::unique_ptr< weld::Label > m_xFontText
Definition: cuicharmap.hxx:92
static sal_uInt32 & getSelectedChar()
rtl_TextEncoding GetCharSet() const
bool dispatchCommand(const OUString &rCommand, const uno::Reference< css::frame::XFrame > &rFrame, const css::uno::Sequence< css::beans::PropertyValue > &rArguments, const uno::Reference< css::frame::XDispatchResultListener > &rListener)
static std::shared_ptr< ConfigurationChanges > create(css::uno::Reference< css::uno::XComponentContext > const &context=comphelper::getProcessComponentContext())
std::unique_ptr< weld::ComboBox > m_xSubsetLB
Definition: cuicharmap.hxx:95
std::deque< OUString > maFavCharList
Definition: cuicharmap.hxx:83
void setCharName(sal_UCS4 nDecimalValue)
Definition: cuicharmap.cxx:702
void DrawRect(const tools::Rectangle &rRect)
void SetPitch(FontPitch ePitch)
SfxItemPool & GetPool() const
const OUString & GetStyleName() const
std::unique_ptr< weld::Entry > m_xDecimalCodeText
Definition: cuicharmap.hxx:98
uno::Reference< uno::XComponentContext > mxContext
Definition: cuicharmap.hxx:85
css::uno::Reference< css::frame::XFrame > m_xFrame
Definition: cuicharmap.hxx:80
WEIGHT_DONTKNOW
void SetAlignment(FontAlign)
std::unique_ptr< SvxShowCharSet > m_xShowSet
Definition: cuicharmap.hxx:106
void updateRecentCharacterList(const OUString &rChar, const OUString &rFont)
Definition: cuicharmap.cxx:280
sal_UCS4 GetFirstChar() const
std::unique_ptr< weld::Button > m_xFavouritesBtn
Definition: cuicharmap.hxx:99
void SetFamilyName(const OUString &rFamilyName)
void getRecentCharacterList()
Definition: cuicharmap.cxx:221
void SetFont(const vcl::Font &rFont)
FontPitch GetPitch()
long AdjustY(long nVertMove)
void SetHasInsert(bool bInsert)
virtual void insert_vector(const std::vector< weld::ComboBoxEntry > &rItems, bool bKeepExisting)=0
OUString sName
int i
vcl::Font m_aFont
Definition: cuicharmap.hxx:51
std::unique_ptr< weld::Entry > m_xHexCodeText
Definition: cuicharmap.hxx:97
void SetFillColor()
WEIGHT_NORMAL
void SetTextColor(const Color &rColor)
void setClearAllClickHdl(const Link< SvxCharView *, void > &rLink)
const Size & GetFontSize() const
PITCH_DONTKNOW
bool isFavChar(const OUString &sTitle, const OUString &rFont)
Definition: cuicharmap.cxx:530
void getFavCharacterList()
Definition: cuicharmap.cxx:239
void updateFavCharacterList(const OUString &rChar, const OUString &rFont)
Definition: cuicharmap.cxx:320
ITALIC_NONE
std::unique_ptr< weld::Entry > m_xSearchText
Definition: cuicharmap.hxx:96
long GetTextHeight() const
vcl::Font aFont
Definition: cuicharmap.hxx:77
OUString CuiResId(const char *pKey)
Definition: cuiresmgr.cxx:23
#define PUSH_ALLFONT
void SetText(const OUString &rText)
sal_UCS4 GetRangeMin() const
virtual short run() override
Definition: cuicharmap.cxx:182
SvxCharacterMap(weld::Widget *pParent, const SfxItemSet *pSet, const css::uno::Reference< css::frame::XFrame > &rFrame)
Definition: cuicharmap.cxx:49
IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView *, rView, void)
Definition: cuicharmap.cxx:744
const OUString & GetFamilyName() const
sal_UCS4 GetNextChar(sal_UCS4 cChar) const
std::deque< OUString > maFavCharFontList
Definition: cuicharmap.hxx:84
ALIGN_TOP
void setClearClickHdl(const Link< SvxCharView *, void > &rLink)
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
void setMouseClickHdl(const Link< SvxCharView *, void > &rLink)
WIDTH_DONTKNOW
std::deque< OUString > maRecentCharFontList
Definition: cuicharmap.hxx:82
void SetFont(const vcl::Font &rNewFont)
void SetTransparent(bool bTransparent)
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
SvxShowText(const VclPtr< VirtualDevice > &rVirDev)
sal_UCS4 GetLastChar() const
RET_OK
Reference< XComponentContext > getProcessComponentContext()
void SetCharFont(const vcl::Font &rFont)
Definition: cuicharmap.cxx:571
void updateFavCharControl()
Definition: cuicharmap.cxx:358
const Color & GetWindowColor() const
virtual void SetDrawingArea(weld::DrawingArea *pDrawingArea) override
void DisableFontSelection()
Definition: cuicharmap.cxx:214
FILE * init(int, char **)
long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
std::unique_ptr< weld::ComboBox > m_xFontLB
Definition: cuicharmap.hxx:93
void SetText(const OUString &rText)
ScXMLEditAttributeMap::Entry const aEntries[]
sal_UCS4 GetChar() const
Definition: cuicharmap.cxx:209
vcl::Font const & GetFont() const
Definition: cuicharmap.hxx:61
The main purpose of this dialog is to enable the use of characters that are not easily accessible fro...
Definition: cuicharmap.hxx:71
void setFavButtonState(const OUString &sTitle, const OUString &rFont)
Definition: cuicharmap.cxx:545
sal_uInt32 sal_UCS4
IMPL_LINK_NOARG(SvxCharacterMap, FontSelectHdl, weld::ComboBox &, void)
Definition: cuicharmap.cxx:633
std::unique_ptr< weld::Button > m_xOKBtn
Definition: cuicharmap.hxx:91
const Color & GetDialogTextColor() const
virtual void set_size_request(int nWidth, int nHeight)=0
sal_Int32 nPos
vcl::Font const & GetFont() const
rtl_TextEncoding GetCharSet() const
virtual void Resize() override
const Color & GetFillColor() const
void deleteFavCharacterFromList(const OUString &rChar, const OUString &rFont)
Definition: cuicharmap.cxx:381
SvxCharView m_aRecentCharView[16]
Definition: cuicharmap.hxx:87
std::unique_ptr< weld::Label > m_xCharName
Definition: cuicharmap.hxx:100