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 <sal/config.h>
21
22#include <stdio.h>
23
24#include <utility>
25#include <vcl/svapp.hxx>
26#include <svl/eitem.hxx>
27#include <svl/intitem.hxx>
28#include <svl/itempool.hxx>
29
30#include <rtl/textenc.h>
31#include <svx/ucsubset.hxx>
32#include <vcl/settings.hxx>
33#include <vcl/fontcharmap.hxx>
34#include <vcl/virdev.hxx>
35#include <svl/stritem.hxx>
36#include <o3tl/temporary.hxx>
37#include <officecfg/Office/Common.hxx>
38#include <com/sun/star/beans/PropertyValue.hpp>
42
43#include <dialmgr.hxx>
44#include <cui/cuicharmap.hxx>
45#include <sfx2/app.hxx>
46#include <svx/svxids.hrc>
47#include <editeng/editids.hrc>
48#include <editeng/fontitem.hxx>
49#include <strings.hrc>
50#include <unicode/uchar.h>
51#include <unicode/utypes.h>
52
53using namespace css;
54
56 css::uno::Reference<css::frame::XFrame> xFrame)
57 : SfxDialogController(pParent, "cui/ui/specialcharacters.ui", "SpecialCharactersDialog")
58 , m_xVirDev(VclPtr<VirtualDevice>::Create())
59 , isSearchMode(true)
60 , m_xFrame(std::move(xFrame))
61 , m_aCharmapContents(*m_xBuilder, m_xVirDev)
62 , m_aShowChar(m_xVirDev)
63 , m_xOKBtn(m_xFrame.is() ? m_xBuilder->weld_button("insert") : m_xBuilder->weld_button("ok"))
64 , m_xFontText(m_xBuilder->weld_label("fontft"))
65 , m_xFontLB(m_xBuilder->weld_combo_box("fontlb"))
66 , m_xSubsetText(m_xBuilder->weld_label("subsetft"))
67 , m_xSubsetLB(m_xBuilder->weld_combo_box("subsetlb"))
68 , m_xSearchText(m_xBuilder->weld_entry("search"))
69 , m_xHexCodeText(m_xBuilder->weld_entry("hexvalue"))
70 , m_xDecimalCodeText(m_xBuilder->weld_entry("decimalvalue"))
71 , m_xFavouritesBtn(m_xBuilder->weld_button("favbtn"))
72 , m_xCharName(m_xBuilder->weld_label("charname"))
73 , m_xShowChar(new weld::CustomWeld(*m_xBuilder, "showchar", m_aShowChar))
74 , m_xShowSet(new SvxShowCharSet(m_xBuilder->weld_scrolled_window("showscroll", true), m_xVirDev))
75 , m_xShowSetArea(new weld::CustomWeld(*m_xBuilder, "showcharset", *m_xShowSet))
76 , m_xSearchSet(new SvxSearchCharSet(m_xBuilder->weld_scrolled_window("searchscroll", true), m_xVirDev))
77 , m_xSearchSetArea(new weld::CustomWeld(*m_xBuilder, "searchcharset", *m_xSearchSet))
78{
80 m_xFontLB->make_sorted();
81 //lock the size request of this widget to the width of all possible entries
83 m_xSubsetLB->set_size_request(m_xSubsetLB->get_preferred_size().Width(), -1);
84 m_xCharName->set_size_request(m_aShowChar.get_preferred_size().Width(), m_xCharName->get_text_height() * 4);
85 //lock the size request of this widget to the width of the original .ui string
86 m_xHexCodeText->set_size_request(m_xHexCodeText->get_preferred_size().Width(), -1);
87
88 init();
89
90 const SfxInt32Item* pCharItem = SfxItemSet::GetItem<SfxInt32Item>(pSet, SID_ATTR_CHAR, false);
91 if ( pCharItem )
92 SetChar( pCharItem->GetValue() );
93
94 const SfxBoolItem* pDisableItem = SfxItemSet::GetItem<SfxBoolItem>(pSet, FN_PARAM_2, false);
95 if ( pDisableItem && pDisableItem->GetValue() )
97
98 const SvxFontItem* pFontItem = SfxItemSet::GetItem<SvxFontItem>(pSet, SID_ATTR_CHAR_FONT, false);
99 const SfxStringItem* pFontNameItem = SfxItemSet::GetItem<SfxStringItem>(pSet, SID_FONT_NAME, false);
100 if ( pFontItem )
101 {
102 vcl::Font aTmpFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), GetCharFont().GetFontSize() );
103 aTmpFont.SetCharSet( pFontItem->GetCharSet() );
104 aTmpFont.SetPitch( pFontItem->GetPitch() );
105 SetCharFont( aTmpFont );
106 }
107 else if ( pFontNameItem )
108 {
109 vcl::Font aTmpFont( GetCharFont() );
110 aTmpFont.SetFamilyName( pFontNameItem->GetValue() );
111 SetCharFont( aTmpFont );
112 }
113
114 m_xOutputSet.reset(new SfxAllItemSet(pSet ? *pSet->GetPool() : SfxGetpApp()->GetPool()));
115 m_xShowSet->Show();
116 m_xSearchSet->Hide();
117}
118
120{
122 {
123 m_xOKBtn->set_sensitive(false);
124 setFavButtonState(u"", u"");
125 }
126 else
127 {
128 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
129 // using the new UCS4 constructor
130 OUString aOUStr( &cChar, 1 );
131 m_aShowChar.SetText(aOUStr);
132
134 m_xOKBtn->set_sensitive(true);
135 }
136
137 return SfxDialogController::run();
138}
139
141{
142 m_xShowSet->SelectCharacter( c );
143 setFavButtonState(OUString(&c, 1), aFont.GetFamilyName());
144}
145
147{
148 return m_aShowChar.GetText().iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
149}
150
152{
153 m_xFontText->set_sensitive(false);
154 m_xFontLB->set_sensitive(false);
155}
156
157IMPL_LINK_NOARG(SvxCharacterMap, UpdateFavHdl, void*, void)
158{
159 m_xShowSet->getFavCharacterList();
160 m_xSearchSet->getFavCharacterList();
161 // tdf#109214 - redraw highlight of the favorite characters
162 m_xShowSet->Invalidate();
163}
164
166{
167 aFont = m_xVirDev->GetFont();
168 aFont.SetTransparent( true );
171 aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
172
173 OUString aDefStr( aFont.GetFamilyName() );
174 OUString aLastName;
175 int nCount = m_xVirDev->GetFontFaceCollectionCount();
176 std::vector<weld::ComboBoxEntry> aEntries;
177 aEntries.reserve(nCount);
178 for (int i = 0; i < nCount; ++i)
179 {
180 OUString aFontName( m_xVirDev->GetFontMetricFromCollection( i ).GetFamilyName() );
181 if (aFontName != aLastName)
182 {
183 aLastName = aFontName;
184 aEntries.emplace_back(aFontName, OUString::number(i));
185 }
186 }
187 m_xFontLB->insert_vector(aEntries, true);
188 // the font may not be in the list =>
189 // try to find a font name token in list and select found font,
190 // else select topmost entry
191 bool bFound = (m_xFontLB->find_text(aDefStr) != -1);
192 if (!bFound)
193 {
194 sal_Int32 nIndex = 0;
195 do
196 {
197 OUString aToken = aDefStr.getToken(0, ';', nIndex);
198 if (m_xFontLB->find_text(aToken) != -1)
199 {
200 aDefStr = aToken;
201 bFound = true;
202 break;
203 }
204 }
205 while ( nIndex >= 0 );
206 }
207
208 if (bFound)
209 m_xFontLB->set_active_text(aDefStr);
210 else if (m_xFontLB->get_count() )
211 m_xFontLB->set_active(0);
212 FontSelectHdl(*m_xFontLB);
213 if (m_xSubsetLB->get_count())
214 m_xSubsetLB->set_active(0);
215
216 m_xFontLB->connect_changed(LINK( this, SvxCharacterMap, FontSelectHdl));
217 m_xSubsetLB->connect_changed(LINK( this, SvxCharacterMap, SubsetSelectHdl));
218 m_xOKBtn->connect_clicked(LINK(this, SvxCharacterMap, InsertClickHdl));
219 m_xOKBtn->show();
220
221 m_xShowSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, CharDoubleClickHdl ) );
222 m_xShowSet->SetReturnKeyPressHdl(LINK(this, SvxCharacterMap, ReturnKeypressOnCharHdl));
223 m_xShowSet->SetSelectHdl( LINK( this, SvxCharacterMap, CharSelectHdl ) );
224 m_xShowSet->SetHighlightHdl( LINK( this, SvxCharacterMap, CharHighlightHdl ) );
225 m_xShowSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, CharPreSelectHdl ) );
226 m_xShowSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
227
228 m_xSearchSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, CharDoubleClickHdl ) );
229 m_xSearchSet->SetReturnKeyPressHdl(LINK(this, SvxCharacterMap, ReturnKeypressOnCharHdl));
230 m_xSearchSet->SetSelectHdl( LINK( this, SvxCharacterMap, CharSelectHdl ) );
231 m_xSearchSet->SetHighlightHdl( LINK( this, SvxCharacterMap, SearchCharHighlightHdl ) );
232 m_xSearchSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, CharPreSelectHdl ) );
233 m_xSearchSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
234
235 m_xDecimalCodeText->connect_changed( LINK( this, SvxCharacterMap, DecimalCodeChangeHdl ) );
236 m_xHexCodeText->connect_changed( LINK( this, SvxCharacterMap, HexCodeChangeHdl ) );
237 m_xFavouritesBtn->connect_clicked( LINK(this, SvxCharacterMap, FavSelectHdl));
238
239 // tdf#117038 set the buttons width to its max possible width so it doesn't
240 // make layout change when the label changes
241 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_REMOVE_FAVORITES));
242 auto nMaxWidth = m_xFavouritesBtn->get_preferred_size().Width();
243 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES));
244 nMaxWidth = std::max(nMaxWidth, m_xFavouritesBtn->get_preferred_size().Width());
245 m_xFavouritesBtn->set_size_request(nMaxWidth, -1);
246
248 {
249 m_xOKBtn->set_sensitive(false);
250 }
251 else
252 {
253 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
254 // using the new UCS4 constructor
255 OUString aOUStr( &cChar, 1 );
256 m_aShowChar.SetText(aOUStr);
257
258 setFavButtonState(aOUStr, aDefStr);
259 m_xOKBtn->set_sensitive(true);
260 }
261
263 LINK(this, SvxCharacterMap, CharClickHdl),
264 LINK(this, SvxCharacterMap, UpdateFavHdl),
266
267 setCharName(90);
268
269 m_xSearchText->connect_focus_in(LINK( this, SvxCharacterMap, SearchFieldGetFocusHdl ));
270 m_xSearchText->connect_changed(LINK(this, SvxCharacterMap, SearchUpdateHdl));
271}
272
273void SvxCharacterMap::setFavButtonState(std::u16string_view sTitle, std::u16string_view rFont)
274{
275 if(sTitle.empty() || rFont.empty())
276 {
277 m_xFavouritesBtn->set_sensitive(false);
278 return;
279 }
280 else
281 m_xFavouritesBtn->set_sensitive(true);
282
283 if (m_aCharmapContents.isFavChar(sTitle, rFont))
284 {
285 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_REMOVE_FAVORITES));
286 }
287 else
288 {
290 m_xFavouritesBtn->set_sensitive(false);
291
292 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES));
293 }
294}
295
296
298{
299 // first get the underlying info in order to get font names
300 // like "Times New Roman;Times" resolved
301 vcl::Font aTmp(m_xVirDev->GetFontMetric(rFont));
302
303 // tdf#56363 - search font family without the font feature after the colon
304 OUString sFontFamilyName = aTmp.GetFamilyName();
305 if (const sal_Int32 nIndex = sFontFamilyName.indexOf(":"); nIndex != -1)
306 sFontFamilyName = sFontFamilyName.copy(0, nIndex);
307 if (sFontFamilyName == "StarSymbol" && m_xFontLB->find_text(sFontFamilyName) == -1)
308 {
309 //if for some reason, like font in an old document, StarSymbol is requested and it's not available, then
310 //try OpenSymbol instead
311 aTmp.SetFamilyName("OpenSymbol");
312 }
313
314 if (m_xFontLB->find_text(sFontFamilyName) == -1)
315 return;
316
317 m_xFontLB->set_active_text(sFontFamilyName);
318 aFont = aTmp;
319 FontSelectHdl(*m_xFontLB);
320 if (m_xSubsetLB->get_count())
321 m_xSubsetLB->set_active(0);
322}
323
325{
326 SubsetMap aAll(nullptr);
327 std::vector<weld::ComboBoxEntry> aEntries;
328 for (auto & subset : aAll.GetSubsetMap())
329 aEntries.emplace_back(subset.GetName());
330 rListBox.insert_vector(aEntries, true);
331}
332
333void SvxCharacterMap::insertCharToDoc(const OUString& sGlyph)
334{
335 if(sGlyph.isEmpty())
336 return;
337
338 if (m_xFrame.is()) {
340 comphelper::makePropertyValue("Symbols", sGlyph),
342 };
343 comphelper::dispatchCommand(".uno:InsertSymbol", m_xFrame, aArgs);
344
346
347 } else {
348 sal_UCS4 cChar = sGlyph.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
349 const SfxItemPool* pPool = m_xOutputSet->GetPool();
350 m_xOutputSet->Put( SfxStringItem( SID_CHARMAP, sGlyph ) );
352 aFont.GetStyleName(), aFont.GetPitch(), aFont.GetCharSet(), pPool->GetWhich(SID_ATTR_CHAR_FONT) ) );
353 m_xOutputSet->Put( SfxStringItem( SID_FONT_NAME, aFont.GetFamilyName() ) );
354 m_xOutputSet->Put( SfxInt32Item( SID_ATTR_CHAR, cChar ) );
355 }
356}
357
359{
360 const sal_uInt32 nFont = m_xFontLB->get_active_id().toUInt32();
361 aFont = m_xVirDev->GetFontMetricFromCollection(nFont);
362 aFont.SetWeight( WEIGHT_DONTKNOW );
363 aFont.SetItalic( ITALIC_NONE );
364 aFont.SetWidthType( WIDTH_DONTKNOW );
365 aFont.SetPitch( PITCH_DONTKNOW );
366 aFont.SetFamily( FAMILY_DONTKNOW );
367
368 // notify children using this font
369 m_xShowSet->SetFont( aFont );
370 m_xSearchSet->SetFont( aFont );
371 m_aShowChar.SetFont( aFont );
372
373 // setup unicode subset listbar with font specific subsets,
374 // hide unicode subset listbar for symbol fonts
375 // TODO: get info from the Font once it provides it
376 pSubsetMap.reset();
377 m_xSubsetLB->clear();
378
379 bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL);
380 if (bNeedSubset)
381 {
382 FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
383 pSubsetMap.reset(new SubsetMap( xFontCharMap ));
384
385 // update subset listbox for new font's unicode subsets
386 for (auto const& subset : pSubsetMap->GetSubsetMap())
387 {
388 m_xSubsetLB->append(weld::toId(&subset), subset.GetName());
389 // NOTE: subset must live at least as long as the selected font
390 }
391
392 if (m_xSubsetLB->get_count() <= 1)
393 bNeedSubset = false;
394 }
395
396 m_xSubsetText->set_sensitive(bNeedSubset);
397 m_xSubsetLB->set_sensitive(bNeedSubset);
398
399 if (isSearchMode)
400 {
401 // tdf#137294 do this after modifying m_xSubsetLB sensitivity to
402 // restore insensitive for the search case
403 SearchUpdateHdl(*m_xSearchText);
404 SearchCharHighlightHdl(m_xSearchSet.get());
405 }
406
407 // tdf#118304 reselect current glyph to see if it's still there in new font
408 selectCharByCode(Radix::hexadecimal);
409}
410
412{
413 isSearchMode = state;
414 m_xHexCodeText->set_editable(!state);
415 m_xDecimalCodeText->set_editable(!state);
416 m_xSubsetLB->set_sensitive(!state);
417
418 if(state)
419 {
420 m_xSearchSet->Show();
421 m_xShowSet->Hide();
422 }
423 else
424 {
425 m_xSearchSet->Hide();
426 m_xShowSet->Show();
427 }
428}
429
431{
432 /* get the character name */
433 UErrorCode errorCode = U_ZERO_ERROR;
434 // icu has a private uprv_getMaxCharNameLength function which returns the max possible
435 // length of this property. Unicode 3.2 max char name length was 83
436 char buffer[100];
437 u_charName(nDecimalValue, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
438 if (U_SUCCESS(errorCode))
439 m_xCharName->set_label(OUString::createFromAscii(buffer));
440}
441
443{
444 const sal_Int32 nPos = m_xSubsetLB->get_active();
445 const Subset* pSubset = weld::fromId<const Subset*>(m_xSubsetLB->get_active_id());
446
447 if( pSubset && !isSearchMode)
448 {
449 sal_UCS4 cFirst = pSubset->GetRangeMin();
450 m_xShowSet->SelectCharacter( cFirst );
451
452 setFavButtonState(OUString(&cFirst, 1), aFont.GetFamilyName());
453 m_xSubsetLB->set_active(nPos);
454 }
455 else if( pSubset && isSearchMode)
456 {
457 m_xSearchSet->SelectCharacter( pSubset );
458
459 const Subset* curSubset = nullptr;
460 if( pSubsetMap )
461 curSubset = pSubsetMap->GetSubsetByUnicode( m_xSearchSet->GetSelectCharacter() );
462 if( curSubset )
463 m_xSubsetLB->set_active_text(curSubset->GetName());
464 else
465 m_xSubsetLB->set_active(-1);
466
467 sal_UCS4 sChar = m_xSearchSet->GetSelectCharacter();
468 setFavButtonState(OUString(&sChar, 1), aFont.GetFamilyName());
469 }
470}
471
472IMPL_LINK_NOARG(SvxCharacterMap, SearchFieldGetFocusHdl, weld::Widget&, void)
473{
474 m_xOKBtn->set_sensitive(false);
475}
476
478{
479 if (!m_xSearchText->get_text().isEmpty())
480 {
481 m_xSearchSet->ClearPreviousData();
482 OUString aKeyword = m_xSearchText->get_text();
483
484 toggleSearchView(true);
485
486 FontCharMapRef xFontCharMap = m_xSearchSet->GetFontCharMap();
487
488 sal_UCS4 sChar = xFontCharMap->GetFirstChar();
489 while(sChar != xFontCharMap->GetLastChar())
490 {
491 UErrorCode errorCode = U_ZERO_ERROR;
492 char buffer[100];
493 u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
494 if (U_SUCCESS(errorCode))
495 {
496 OUString sName = OUString::createFromAscii(buffer);
497 if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
498 m_xSearchSet->AppendCharToList(sChar);
499 }
500 sChar = xFontCharMap->GetNextChar(sChar);
501 }
502 //for last char
503 UErrorCode errorCode = U_ZERO_ERROR;
504 char buffer[100];
505 u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
506 if (U_SUCCESS(errorCode))
507 {
508 OUString sName = OUString::createFromAscii(buffer);
509 if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
510 m_xSearchSet->AppendCharToList(sChar);
511 }
512
513 m_xSearchSet->UpdateScrollRange();
514 }
515 else
516 {
517 toggleSearchView(false);
518 }
519}
520
521
522IMPL_LINK(SvxCharacterMap, CharClickHdl, SvxCharView*, rView, void)
523{
524 rView->GrabFocus();
525
526 m_aShowChar.SetText( rView->GetText() );
527 m_aShowChar.SetFont(rView->GetFont());
528 m_aShowChar.Invalidate();
529
530 setFavButtonState(rView->GetText(), rView->GetFont().GetFamilyName());//check state
531
532 // Get the hexadecimal code
533 OUString charValue = rView->GetText();
534 sal_UCS4 cChar = charValue.iterateCodePoints(&o3tl::temporary(sal_Int32(1)), -1);
535 OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
536
537 // Get the decimal code
538 OUString aDecimalText = OUString::number(cChar);
539
540 m_xHexCodeText->set_text(aHexText);
541 m_xDecimalCodeText->set_text(aDecimalText);
542 setCharName(cChar);
543
544 rView->Invalidate();
545 m_xOKBtn->set_sensitive(true);
546}
547
549{
550 assert(pCharSet);
551 sal_UCS4 cChar = pCharSet->GetSelectCharacter();
552 // using the new UCS4 constructor
553 OUString aOUStr( &cChar, 1 );
555 insertCharToDoc(aOUStr);
556}
557
558IMPL_LINK(SvxCharacterMap, CharDoubleClickHdl, SvxShowCharSet*, pCharSet, void)
559{
560 insertSelectedCharacter(pCharSet);
561}
562
564{
565 m_xOKBtn->set_sensitive(true);
566}
567
568IMPL_LINK(SvxCharacterMap, ReturnKeypressOnCharHdl, SvxShowCharSet*, pCharSet, void)
569{
570 insertSelectedCharacter(pCharSet);
571 m_xDialog->response(RET_OK);
572}
573
575{
576 OUString sChar = m_aShowChar.GetText();
577 insertCharToDoc(sChar);
578 // Need to update recent character list, when OK button does not insert
579 if(!m_xFrame.is())
580 m_aCharmapContents.updateRecentCharacterList(sChar, aFont.GetFamilyName());
581 m_xDialog->response(RET_OK);
582}
583
585{
586 if (m_xFavouritesBtn->get_label().match(CuiResId(RID_CUISTR_ADD_FAVORITES)))
587 {
588 m_aCharmapContents.updateFavCharacterList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
589 setFavButtonState(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
590 }
591 else
592 {
593 m_aCharmapContents.deleteFavCharacterFromList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
594 m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES));
595 m_xFavouritesBtn->set_sensitive(false);
596 }
597
598 m_aCharmapContents.updateFavCharControl();
599}
600
602{
603 m_aCharmapContents.getFavCharacterList();
604 m_aCharmapContents.updateFavCharControl();
605}
606
608{
609 OUString aText;
610 sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
611 bool bSelect = (cChar > 0);
612
613 // show char sample
614 if ( bSelect )
615 {
616 // using the new UCS4 constructor
617 aText = OUString( &cChar, 1 );
618 // Get the hexadecimal code
619 OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
620 // Get the decimal code
621 OUString aDecimalText = OUString::number(cChar);
622 setCharName(cChar);
623
624 // Update the hex and decimal codes only if necessary
625 if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
626 m_xHexCodeText->set_text(aHexText);
627 if (m_xDecimalCodeText->get_text() != aDecimalText)
628 m_xDecimalCodeText->set_text( aDecimalText );
629
630 const Subset* pSubset = nullptr;
631 if( pSubsetMap )
632 pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
633 if( pSubset )
634 m_xSubsetLB->set_active_text(pSubset->GetName());
635 else
636 m_xSubsetLB->set_active(-1);
637 }
638
639 m_aShowChar.SetText( aText );
640 m_aShowChar.SetFont( aFont );
641 m_aShowChar.Invalidate();
642
643 setFavButtonState(aText, aFont.GetFamilyName());
644}
645
646IMPL_LINK_NOARG(SvxCharacterMap, SearchCharHighlightHdl, SvxShowCharSet*, void)
647{
648 OUString aText;
649 sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
650 bool bSelect = (cChar > 0);
651
652 // show char sample
653 if ( bSelect )
654 {
655 aText = OUString( &cChar, 1 );
656 // Get the hexadecimal code
657 OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
658 // Get the decimal code
659 OUString aDecimalText = OUString::number(cChar);
660 setCharName(cChar);
661
662 // Update the hex and decimal codes only if necessary
663 if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
664 m_xHexCodeText->set_text(aHexText);
665 if (m_xDecimalCodeText->get_text() != aDecimalText)
666 m_xDecimalCodeText->set_text( aDecimalText );
667
668 const Subset* pSubset = nullptr;
669 if( pSubsetMap )
670 pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
671 if( pSubset )
672 m_xSubsetLB->set_active_text(pSubset->GetName());
673 else
674 m_xSubsetLB->set_active(-1);
675 }
676
677 if(m_xSearchSet->HasFocus())
678 {
679 m_aShowChar.SetText( aText );
680 m_aShowChar.SetFont( aFont );
681 m_aShowChar.Invalidate();
682
683 setFavButtonState(aText, aFont.GetFamilyName());
684 }
685}
686
688{
689 OUString aCodeString;
690 switch(radix)
691 {
692 case Radix::decimal:
693 aCodeString = m_xDecimalCodeText->get_text();
694 break;
696 aCodeString = m_xHexCodeText->get_text();
697 break;
698 }
699 // Convert the code back to a character using the appropriate radix
700 sal_UCS4 cChar = aCodeString.toUInt32(static_cast<sal_Int16> (radix));
701 // Use FontCharMap::HasChar(sal_UCS4 cChar) to see if the desired character is in the font
702 FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
703 if (xFontCharMap->HasChar(cChar))
704 // Select the corresponding character
705 SetChar(cChar);
706 else {
707 m_xCharName->set_label(CuiResId(RID_CUISTR_MISSING_CHAR));
708 m_aShowChar.SetText(" ");
709 switch(radix)
710 {
711 case Radix::decimal:
712 m_xHexCodeText->set_text(OUString::number(cChar, 16));
713 break;
715 m_xDecimalCodeText->set_text(OUString::number(cChar));
716 break;
717 }
718 }
719}
720
721IMPL_LINK_NOARG(SvxCharacterMap, DecimalCodeChangeHdl, weld::Entry&, void)
722{
723 selectCharByCode(Radix::decimal);
724}
725
727{
728 selectCharByCode(Radix::hexadecimal);
729}
730
731IMPL_LINK(SvxCharacterMap, CharPreSelectHdl, SvxShowCharSet*, pCharSet, void)
732{
733 assert(pCharSet);
734 // adjust subset selection
735 if( pSubsetMap )
736 {
737 sal_UCS4 cChar = pCharSet->GetSelectCharacter();
738
739 setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName());
740 const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
741 if( pSubset )
742 m_xSubsetLB->set_active_text(pSubset->GetName());
743 }
744
745 m_xOKBtn->set_sensitive(true);
746}
747
748// class SvxShowText =====================================================
750 : m_xVirDev(rVirDev)
751 , mnY(0)
752 , mbCenter(false)
753{
754}
755
757{
758 CustomWidgetController::SetDrawingArea(pDrawingArea);
759 vcl::Font aFont = m_xVirDev->GetFont();
760 Size aFontSize(aFont.GetFontSize().Width() * 5, aFont.GetFontSize().Height() * 5);
761 aFont.SetFontSize(aFontSize);
762 m_xVirDev->Push(PUSH_ALLFONT);
763 m_xVirDev->SetFont(aFont);
764 pDrawingArea->set_size_request(m_xVirDev->approximate_digit_width() + 2 * 12,
765 m_xVirDev->LogicToPixel(aFontSize).Height() * 2);
766 m_xVirDev->Pop();
767}
768
770{
771 rRenderContext.SetFont(m_aFont);
772
773 Color aTextCol = rRenderContext.GetTextColor();
774 Color aFillCol = rRenderContext.GetFillColor();
775 Color aLineCol = rRenderContext.GetLineColor();
776
777 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
778 const Color aWindowTextColor(rStyleSettings.GetDialogTextColor());
779 const Color aWindowColor(rStyleSettings.GetWindowColor());
780 const Color aShadowColor(rStyleSettings.GetShadowColor());
781 rRenderContext.SetTextColor(aWindowTextColor);
782 rRenderContext.SetFillColor(aWindowColor);
783
784 const OUString aText = GetText();
785
786 Size aSize(GetOutputSizePixel());
787 tools::Long nAvailWidth = aSize.Width();
788 tools::Long nWinHeight = aSize.Height();
789
790 bool bGotBoundary = true;
791 bool bShrankFont = false;
792 vcl::Font aOrigFont(rRenderContext.GetFont());
793 Size aFontSize(aOrigFont.GetFontSize());
794 ::tools::Rectangle aBoundRect;
795
796 for (tools::Long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 5)
797 {
798 if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty())
799 {
800 bGotBoundary = false;
801 break;
802 }
803 if (!mbCenter)
804 break;
805 //only shrink in the single glyph large view mode
806 tools::Long nTextWidth = aBoundRect.GetWidth();
807 if (nAvailWidth > nTextWidth)
808 break;
809 vcl::Font aFont(aOrigFont);
810 aFontSize.setHeight( nFontHeight );
811 aFont.SetFontSize(aFontSize);
812 rRenderContext.SetFont(aFont);
813 mnY = (nWinHeight - rRenderContext.GetTextHeight()) / 2;
814 bShrankFont = true;
815 }
816
817 Point aPoint(2, mnY);
818 // adjust position using ink boundary if possible
819 if (!bGotBoundary)
820 aPoint.setX( (aSize.Width() - rRenderContext.GetTextWidth(aText)) / 2 );
821 else
822 {
823 // adjust position before it gets out of bounds
824 aBoundRect += aPoint;
825
826 // shift back vertically if needed
827 int nYLDelta = aBoundRect.Top();
828 int nYHDelta = aSize.Height() - aBoundRect.Bottom();
829 if( nYLDelta <= 0 )
830 aPoint.AdjustY( -(nYLDelta - 1) );
831 else if( nYHDelta <= 0 )
832 aPoint.AdjustY(nYHDelta - 1 );
833
834 if (mbCenter)
835 {
836 // move glyph to middle of cell
837 aPoint.setX( -aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2 );
838 }
839 else
840 {
841 // shift back horizontally if needed
842 int nXLDelta = aBoundRect.Left();
843 int nXHDelta = aSize.Width() - aBoundRect.Right();
844 if( nXLDelta <= 0 )
845 aPoint.AdjustX( -(nXLDelta - 1) );
846 else if( nXHDelta <= 0 )
847 aPoint.AdjustX(nXHDelta - 1 );
848 }
849 }
850
851 rRenderContext.SetLineColor(aShadowColor);
852 rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize));
853 rRenderContext.DrawText(aPoint, aText);
854 rRenderContext.SetTextColor(aTextCol);
855 rRenderContext.SetFillColor(aFillCol);
856 rRenderContext.SetLineColor(aLineCol);
857 if (bShrankFont)
858 rRenderContext.SetFont(aOrigFont);
859}
860
861void SvxShowText::SetFont( const vcl::Font& rFont )
862{
863 tools::Long nWinHeight = GetOutputSizePixel().Height();
864
865 m_aFont = rFont;
868 m_aFont.SetFontSize(m_xVirDev->PixelToLogic(Size(0, nWinHeight / 2)));
870
871 m_xVirDev->Push(PUSH_ALLFONT);
872 m_xVirDev->SetFont(m_aFont);
873 mnY = (nWinHeight - m_xVirDev->GetTextHeight()) / 2;
874 m_xVirDev->Pop();
875
876 Invalidate();
877}
878
880{
881 SetFont(GetFont()); //force recalculation of size
882}
883
884void SvxShowText::SetText(const OUString& rText)
885{
886 m_sText = rText;
887 Invalidate();
888}
889
890/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define PUSH_ALLFONT
css::uno::Reference< css::lang::XComponent > m_xFrame
SfxApplication * SfxGetpApp()
Reference< XExecutableDialog > m_xDialog
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
sal_Int32 GetValue() const
const OUString & GetValue() const
const vcl::Font & GetFont() const
void SetFont(const vcl::Font &rNewFont)
void DrawRect(const tools::Rectangle &rRect)
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, KernArraySpan aDXArray=KernArraySpan(), o3tl::span< const sal_Bool > pKashidaArray={}, const SalLayoutGlyphs *pGlyphs=nullptr) const
void SetLineColor()
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void SetTextColor(const Color &rColor)
void SetFillColor()
const Color & GetLineColor() const
const Color & GetTextColor() const
tools::Long GetTextHeight() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
const Color & GetFillColor() const
void setX(tools::Long nX)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
bool GetValue() const
void updateRecentCharacterList(const OUString &sTitle, const OUString &rFont)
bool FavCharListIsFull() const
bool isFavChar(std::u16string_view sTitle, std::u16string_view rFont)
void init(bool bHasInsert, const Link< SvxCharView *, void > &rMouseClickHdl, const Link< void *, void > &rUpdateFavHdl, const Link< void *, void > &rUpdateRecentHdl)
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
SfxItemPool * GetPool() const
constexpr tools::Long Height() const
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
const Color & GetWindowColor() const
const Color & GetDialogTextColor() const
const Color & GetShadowColor() const
const SubsetVec & GetSubsetMap() const
sal_UCS4 GetRangeMin() const
const OUString & GetName() const
The main purpose of this dialog is to enable the use of characters that are not easily accessible fro...
Definition: cuicharmap.hxx:77
void toggleSearchView(bool state)
Definition: cuicharmap.cxx:411
std::unique_ptr< SvxShowCharSet > m_xShowSet
Definition: cuicharmap.hxx:102
SvxShowText m_aShowChar
Definition: cuicharmap.hxx:89
vcl::Font aFont
Definition: cuicharmap.hxx:82
std::unique_ptr< weld::Label > m_xFontText
Definition: cuicharmap.hxx:92
std::unique_ptr< weld::Entry > m_xDecimalCodeText
Definition: cuicharmap.hxx:98
void insertSelectedCharacter(const SvxShowCharSet *pCharSet)
Definition: cuicharmap.cxx:548
void DisableFontSelection()
Definition: cuicharmap.cxx:151
ScopedVclPtr< VirtualDevice > m_xVirDev
Definition: cuicharmap.hxx:81
std::unique_ptr< weld::ComboBox > m_xFontLB
Definition: cuicharmap.hxx:93
std::unique_ptr< weld::Entry > m_xHexCodeText
Definition: cuicharmap.hxx:97
virtual short run() override
Definition: cuicharmap.cxx:119
std::unique_ptr< weld::Label > m_xCharName
Definition: cuicharmap.hxx:100
const vcl::Font & GetCharFont() const
Definition: cuicharmap.hxx:150
void SetChar(sal_UCS4)
Definition: cuicharmap.cxx:140
void selectCharByCode(Radix radix)
Definition: cuicharmap.cxx:687
std::unique_ptr< SvxSearchCharSet > m_xSearchSet
Definition: cuicharmap.hxx:104
sal_UCS4 GetChar() const
Definition: cuicharmap.cxx:146
std::unique_ptr< weld::ComboBox > m_xSubsetLB
Definition: cuicharmap.hxx:95
void setCharName(sal_UCS4 nDecimalValue)
Definition: cuicharmap.cxx:430
void setFavButtonState(std::u16string_view sTitle, std::u16string_view rFont)
Definition: cuicharmap.cxx:273
std::unique_ptr< weld::Button > m_xOKBtn
Definition: cuicharmap.hxx:91
void insertCharToDoc(const OUString &sChar)
Definition: cuicharmap.cxx:333
void SetCharFont(const vcl::Font &rFont)
Definition: cuicharmap.cxx:297
SfxCharmapContainer m_aCharmapContents
Definition: cuicharmap.hxx:87
css::uno::Reference< css::frame::XFrame > m_xFrame
Definition: cuicharmap.hxx:85
SvxCharacterMap(weld::Widget *pParent, const SfxItemSet *pSet, css::uno::Reference< css::frame::XFrame > xFrame)
Definition: cuicharmap.cxx:55
std::unique_ptr< weld::Entry > m_xSearchText
Definition: cuicharmap.hxx:96
std::unique_ptr< weld::Button > m_xFavouritesBtn
Definition: cuicharmap.hxx:99
std::unique_ptr< SfxAllItemSet > m_xOutputSet
Definition: cuicharmap.hxx:107
static void fillAllSubsets(weld::ComboBox &rListBox)
Definition: cuicharmap.cxx:324
FontPitch GetPitch() const
const OUString & GetStyleName() const
rtl_TextEncoding GetCharSet() const
const OUString & GetFamilyName() const
static sal_uInt32 & getSelectedChar()
virtual sal_UCS4 GetSelectCharacter() const
SvxShowText(const VclPtr< VirtualDevice > &rVirDev)
Definition: cuicharmap.cxx:749
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &) override
Definition: cuicharmap.cxx:769
Size get_preferred_size() const
Definition: cuicharmap.hxx:71
void SetFont(const vcl::Font &rFont)
Definition: cuicharmap.cxx:861
OUString m_sText
Definition: cuicharmap.hxx:53
tools::Long mnY
Definition: cuicharmap.hxx:54
vcl::Font m_aFont
Definition: cuicharmap.hxx:56
virtual void Resize() override
Definition: cuicharmap.cxx:879
ScopedVclPtr< VirtualDevice > m_xVirDev
Definition: cuicharmap.hxx:52
vcl::Font const & GetFont() const
Definition: cuicharmap.hxx:66
void SetText(const OUString &rText)
Definition: cuicharmap.cxx:884
OUString const & GetText() const
Definition: cuicharmap.hxx:68
void SetCentered(bool bCenter)
Definition: cuicharmap.hxx:69
virtual void SetDrawingArea(weld::DrawingArea *pDrawingArea) override
Definition: cuicharmap.cxx:756
constexpr tools::Long GetWidth() const
constexpr tools::Long Top() const
constexpr tools::Long Right() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
void SetFontSize(const Size &)
FontFamily GetFamilyType()
void SetPitch(FontPitch ePitch)
void SetTransparent(bool bTransparent)
const OUString & GetStyleName() const
void SetWeight(FontWeight)
const OUString & GetFamilyName() const
void SetFamily(FontFamily)
void SetCharSet(rtl_TextEncoding)
const Size & GetFontSize() const
void SetAlignment(TextAlign)
FontPitch GetPitch()
void SetFamilyName(const OUString &rFamilyName)
rtl_TextEncoding GetCharSet() const
virtual void insert_vector(const std::vector< weld::ComboBoxEntry > &rItems, bool bKeepExisting)=0
Size const & GetOutputSizePixel() const
virtual void set_size_request(int nWidth, int nHeight)=0
IMPL_LINK_NOARG(SvxCharacterMap, UpdateFavHdl, void *, void)
Definition: cuicharmap.cxx:157
IMPL_LINK(SvxCharacterMap, CharClickHdl, SvxCharView *, rView, void)
Definition: cuicharmap.cxx:522
OUString CuiResId(TranslateId aKey)
Definition: cuiresmgr.cxx:23
int nCount
float u
ScXMLEditAttributeMap::Entry const aEntries[]
PITCH_DONTKNOW
ITALIC_NONE
WIDTH_DONTKNOW
ALIGN_TOP
FAMILY_DONTKNOW
WEIGHT_NORMAL
WEIGHT_DONTKNOW
OUString sName
sal_Int32 nIndex
sal_uInt16 nPos
sal_uInt16 GetFontSize(sal_uInt16 nPos)
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)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
int i
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
constexpr T & temporary(T &&x)
long Long
OUString toId(const void *pValue)
Reference< XFrame > xFrame
RET_OK
sal_uInt32 sal_UCS4