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