Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / cui / source / tabpages / chardlg.cxx
blobd7dca728de87c82d83b3e11725c61d2aad4c1280
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/svapp.hxx>
21 #include <vcl/idle.hxx>
22 #include <svtools/ctrltool.hxx>
23 #include <sfx2/objsh.hxx>
24 #include <svx/svxids.hrc>
25 #include <svtools/unitconv.hxx>
26 #include <svl/languageoptions.hxx>
27 #include <chardlg.hxx>
28 #include <editeng/fontitem.hxx>
29 #include <editeng/postitem.hxx>
30 #include <editeng/udlnitem.hxx>
31 #include <editeng/crossedoutitem.hxx>
32 #include <editeng/contouritem.hxx>
33 #include <editeng/langitem.hxx>
34 #include <editeng/wghtitem.hxx>
35 #include <editeng/fhgtitem.hxx>
36 #include <editeng/shdditem.hxx>
37 #include <editeng/escapementitem.hxx>
38 #include <editeng/wrlmitem.hxx>
39 #include <editeng/cmapitem.hxx>
40 #include <editeng/kernitem.hxx>
41 #include <editeng/blinkitem.hxx>
42 #include <editeng/flstitem.hxx>
43 #include <editeng/autokernitem.hxx>
44 #include <editeng/colritem.hxx>
45 #include <dialmgr.hxx>
46 #include <sfx2/htmlmode.hxx>
47 #include <cui/cuicharmap.hxx>
48 #include "chardlg.h"
49 #include <editeng/emphasismarkitem.hxx>
50 #include <editeng/charreliefitem.hxx>
51 #include <editeng/twolinesitem.hxx>
52 #include <editeng/charhiddenitem.hxx>
53 #include <editeng/charscaleitem.hxx>
54 #include <editeng/charrotateitem.hxx>
55 #include <officecfg/Office/Common.hxx>
56 #include <strings.hrc>
57 #include <twolines.hrc>
58 #include <svl/intitem.hxx>
59 #include <svx/flagsdef.hxx>
60 #include <FontFeaturesDialog.hxx>
61 #include <sal/log.hxx>
62 #include <osl/diagnose.h>
64 using namespace ::com::sun::star;
66 // static ----------------------------------------------------------------
68 const sal_uInt16 SvxCharNamePage::pNameRanges[] =
70 SID_ATTR_CHAR_FONT,
71 SID_ATTR_CHAR_WEIGHT,
72 SID_ATTR_CHAR_FONTHEIGHT,
73 SID_ATTR_CHAR_FONTHEIGHT,
74 SID_ATTR_CHAR_COLOR,
75 SID_ATTR_CHAR_COLOR,
76 SID_ATTR_CHAR_LANGUAGE,
77 SID_ATTR_CHAR_LANGUAGE,
78 SID_ATTR_CHAR_CJK_FONT,
79 SID_ATTR_CHAR_CJK_WEIGHT,
80 SID_ATTR_CHAR_CTL_FONT,
81 SID_ATTR_CHAR_CTL_WEIGHT,
85 const sal_uInt16 SvxCharEffectsPage::pEffectsRanges[] =
87 SID_ATTR_CHAR_SHADOWED,
88 SID_ATTR_CHAR_UNDERLINE,
89 SID_ATTR_CHAR_COLOR,
90 SID_ATTR_CHAR_COLOR,
91 SID_ATTR_CHAR_CASEMAP,
92 SID_ATTR_CHAR_CASEMAP,
93 SID_ATTR_FLASH,
94 SID_ATTR_FLASH,
95 SID_ATTR_CHAR_EMPHASISMARK,
96 SID_ATTR_CHAR_EMPHASISMARK,
97 SID_ATTR_CHAR_RELIEF,
98 SID_ATTR_CHAR_RELIEF,
99 SID_ATTR_CHAR_HIDDEN,
100 SID_ATTR_CHAR_HIDDEN,
101 SID_ATTR_CHAR_OVERLINE,
102 SID_ATTR_CHAR_OVERLINE,
106 const sal_uInt16 SvxCharPositionPage::pPositionRanges[] =
108 SID_ATTR_CHAR_KERNING,
109 SID_ATTR_CHAR_KERNING,
110 SID_ATTR_CHAR_ESCAPEMENT,
111 SID_ATTR_CHAR_ESCAPEMENT,
112 SID_ATTR_CHAR_AUTOKERN,
113 SID_ATTR_CHAR_AUTOKERN,
114 SID_ATTR_CHAR_ROTATED,
115 SID_ATTR_CHAR_SCALEWIDTH,
116 SID_ATTR_CHAR_WIDTH_FIT_TO_LINE,
117 SID_ATTR_CHAR_WIDTH_FIT_TO_LINE,
121 const sal_uInt16 SvxCharTwoLinesPage::pTwoLinesRanges[] =
123 SID_ATTR_CHAR_TWO_LINES,
124 SID_ATTR_CHAR_TWO_LINES,
128 // C-Function ------------------------------------------------------------
130 static bool StateToAttr( TriState aState )
132 return ( TRISTATE_TRUE == aState );
135 namespace
137 void setPrevFontEscapement(SvxFont& _rFont,sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
139 _rFont.SetPropr( nProp );
140 _rFont.SetProprRel( nEscProp );
141 _rFont.SetEscapement( nEsc );
145 inline SvxFont& SvxCharBasePage::GetPreviewFont()
147 return m_aPreviewWin.GetFont();
150 inline SvxFont& SvxCharBasePage::GetPreviewCJKFont()
152 return m_aPreviewWin.GetCJKFont();
155 inline SvxFont& SvxCharBasePage::GetPreviewCTLFont()
157 return m_aPreviewWin.GetCTLFont();
160 SvxCharBasePage::SvxCharBasePage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rID, const SfxItemSet& rItemset)
161 : SfxTabPage(pPage, pController, rUIXMLDescription, rID, &rItemset)
162 , m_bPreviewBackgroundToCharacter( false )
166 SvxCharBasePage::~SvxCharBasePage()
170 void SvxCharBasePage::ActivatePage(const SfxItemSet& rSet)
172 m_aPreviewWin.SetFromItemSet(rSet, m_bPreviewBackgroundToCharacter);
175 void SvxCharBasePage::SetPrevFontWidthScale( const SfxItemSet& rSet )
177 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
178 if (rSet.GetItemState(nWhich)>=SfxItemState::DEFAULT)
180 const SvxCharScaleWidthItem &rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
181 m_aPreviewWin.SetFontWidthScale(rItem.GetValue());
185 void SvxCharBasePage::SetPrevFontEscapement( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
187 setPrevFontEscapement(GetPreviewFont(),nProp,nEscProp,nEsc);
188 setPrevFontEscapement(GetPreviewCJKFont(),nProp,nEscProp,nEsc);
189 setPrevFontEscapement(GetPreviewCTLFont(),nProp,nEscProp,nEsc);
190 m_aPreviewWin.Invalidate();
194 // SvxCharNamePage_Impl --------------------------------------------------
196 struct SvxCharNamePage_Impl
198 Idle m_aUpdateIdle;
199 OUString m_aNoStyleText;
200 std::unique_ptr<FontList> m_pFontList;
201 int m_nExtraEntryPos;
202 bool m_bInSearchMode;
204 SvxCharNamePage_Impl()
205 : m_nExtraEntryPos(std::numeric_limits<int>::max())
206 , m_bInSearchMode(false)
209 m_aUpdateIdle.SetPriority( TaskPriority::LOWEST );
213 // class SvxCharNamePage -------------------------------------------------
215 SvxCharNamePage::SvxCharNamePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
216 : SvxCharBasePage(pPage, pController, "cui/ui/charnamepage.ui", "CharNamePage", rInSet)
217 , m_pImpl(new SvxCharNamePage_Impl)
218 , m_xEastFrame(m_xBuilder->weld_widget("asian"))
219 , m_xEastFontNameFT(m_xBuilder->weld_label("eastfontnameft"))
220 , m_xEastFontNameLB(m_xBuilder->weld_combo_box("eastfontnamelb"))
221 , m_xEastFontStyleFT(m_xBuilder->weld_label("eaststyleft"))
222 , m_xEastFontStyleLB(new SvtFontStyleBox(m_xBuilder->weld_combo_box("eaststylelb")))
223 , m_xEastFontSizeFT(m_xBuilder->weld_label("eastsizeft"))
224 , m_xEastFontSizeLB(new SvtFontSizeBox(m_xBuilder->weld_combo_box("eastsizelb")))
225 , m_xEastFontLanguageFT(m_xBuilder->weld_label("eastlangft"))
226 , m_xEastFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("eastlanglb")))
227 , m_xEastFontTypeFT(m_xBuilder->weld_label("eastfontinfo"))
228 , m_xEastFontFeaturesButton(m_xBuilder->weld_button("east_features_button"))
229 , m_xCTLFrame(m_xBuilder->weld_widget("ctl"))
230 , m_xCTLFontNameFT(m_xBuilder->weld_label("ctlfontnameft"))
231 , m_xCTLFontNameLB(m_xBuilder->weld_combo_box("ctlfontnamelb"))
232 , m_xCTLFontStyleFT(m_xBuilder->weld_label("ctlstyleft"))
233 , m_xCTLFontStyleLB(new SvtFontStyleBox(m_xBuilder->weld_combo_box("ctlstylelb")))
234 , m_xCTLFontSizeFT(m_xBuilder->weld_label("ctlsizeft"))
235 , m_xCTLFontSizeLB(new SvtFontSizeBox(m_xBuilder->weld_combo_box("ctlsizelb")))
236 , m_xCTLFontLanguageFT(m_xBuilder->weld_label("ctllangft"))
237 , m_xCTLFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("ctllanglb")))
238 , m_xCTLFontTypeFT(m_xBuilder->weld_label("ctlfontinfo"))
239 , m_xCTLFontFeaturesButton(m_xBuilder->weld_button("ctl_features_button"))
241 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
242 #ifdef IOS
243 m_xPreviewWin->hide();
244 #endif
245 m_pImpl->m_aNoStyleText = CuiResId( RID_SVXSTR_CHARNAME_NOSTYLE );
247 SvtLanguageOptions aLanguageOptions;
248 bool bShowCJK = aLanguageOptions.IsCJKFontEnabled();
249 bool bShowCTL = aLanguageOptions.IsCTLFontEnabled();
250 bool bShowNonWestern = bShowCJK || bShowCTL;
252 if (bShowNonWestern)
254 m_xWestFrame = m_xBuilder->weld_widget("western");
255 m_xWestFontNameFT = m_xBuilder->weld_label("westfontnameft-cjk");
256 m_xWestFontNameLB = m_xBuilder->weld_combo_box("westfontnamelb-cjk");
257 m_xWestFontStyleFT = m_xBuilder->weld_label("weststyleft-cjk");
258 m_xWestFontSizeFT = m_xBuilder->weld_label("westsizeft-cjk");
260 m_xWestFontStyleLB.reset(new SvtFontStyleBox(m_xBuilder->weld_combo_box("weststylelb-cjk")));
261 m_xWestFontSizeLB.reset(new SvtFontSizeBox(m_xBuilder->weld_combo_box("westsizelb-cjk")));
263 m_xWestFontLanguageFT = m_xBuilder->weld_label("westlangft-cjk");
264 m_xWestFontLanguageLB.reset(new SvxLanguageBox(m_xBuilder->weld_combo_box("westlanglb-cjk")));
265 m_xWestFontTypeFT = m_xBuilder->weld_label("westfontinfo-cjk");
267 m_xWestFontFeaturesButton = m_xBuilder->weld_button("west_features_button-cjk");
269 else
271 m_xWestFrame = m_xBuilder->weld_widget("simple");
272 m_xWestFontNameFT = m_xBuilder->weld_label("westfontnameft-nocjk");
273 m_xWestFontStyleFT = m_xBuilder->weld_label("weststyleft-nocjk");
274 m_xWestFontSizeFT = m_xBuilder->weld_label("westsizeft-nocjk");
276 m_xWestFontLanguageFT = m_xBuilder->weld_label("westlangft-nocjk");
277 m_xWestFontLanguageLB.reset(new SvxLanguageBox(m_xBuilder->weld_combo_box("westlanglb-nocjk")));
278 m_xWestFontTypeFT = m_xBuilder->weld_label("westfontinfo-nocjk");
280 m_xWestFontFeaturesButton = m_xBuilder->weld_button("west_features_button-nocjk");
282 std::unique_ptr<weld::EntryTreeView> xWestFontNameLB = m_xBuilder->weld_entry_tree_view("namegrid", "westfontname-nocjk", "westfontnamelb-nocjk");
283 std::unique_ptr<weld::EntryTreeView> xWestFontStyleLB = m_xBuilder->weld_entry_tree_view("stylegrid", "weststyle-nocjk", "weststylelb-nocjk");
284 std::unique_ptr<weld::EntryTreeView> xWestFontSizeLB = m_xBuilder->weld_entry_tree_view("sizegrid", "westsize-nocjk", "westsizelb-nocjk");
286 // 7 lines in the treeview
287 xWestFontNameLB->set_height_request_by_rows(7);
288 xWestFontStyleLB->set_height_request_by_rows(7);
289 xWestFontSizeLB->set_height_request_by_rows(7);
291 m_xWestFontNameLB = std::move(xWestFontNameLB);
292 m_xWestFontStyleLB.reset(new SvtFontStyleBox(std::move(xWestFontStyleLB)));
293 m_xWestFontSizeLB.reset(new SvtFontSizeBox(std::move(xWestFontSizeLB)));
296 //In MacOSX the standard dialogs name font-name, font-style as
297 //Family, Typeface
298 //In GNOME the standard dialogs name font-name, font-style as
299 //Family, Style
300 //In Windows the standard dialogs name font-name, font-style as
301 //Font, Style
302 #ifdef _WIN32
303 OUString sFontFamilyString(CuiResId(RID_SVXSTR_CHARNAME_FONT));
304 #else
305 OUString sFontFamilyString(CuiResId(RID_SVXSTR_CHARNAME_FAMILY));
306 #endif
307 m_xWestFontNameFT->set_label(sFontFamilyString);
308 m_xEastFontNameFT->set_label(sFontFamilyString);
309 m_xCTLFontNameFT->set_label(sFontFamilyString);
311 #ifdef MACOSX
312 OUString sFontStyleString(CuiResId(RID_SVXSTR_CHARNAME_TYPEFACE));
313 #else
314 OUString sFontStyleString(CuiResId(RID_SVXSTR_CHARNAME_STYLE));
315 #endif
316 m_xWestFontStyleFT->set_label(sFontStyleString);
317 m_xEastFontStyleFT->set_label(sFontStyleString);
318 m_xCTLFontStyleFT->set_label(sFontStyleString);
320 m_xWestFrame->show();
321 m_xEastFrame->set_visible(bShowCJK);
322 m_xCTLFrame->set_visible(bShowCTL);
324 m_xWestFontLanguageLB->SetLanguageList(SvxLanguageListFlags::WESTERN, true, false, true);
325 m_xEastFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CJK, true, false, true);
326 m_xCTLFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CTL, true, false, true);
328 Initialize();
331 SvxCharNamePage::~SvxCharNamePage()
333 m_pImpl.reset();
334 m_xCTLFontStyleLB.reset();
335 m_xEastFontLanguageLB.reset();
336 m_xWestFontStyleLB.reset();
337 m_xCTLFontSizeLB.reset();
338 m_xEastFontSizeLB.reset();
339 m_xWestFontSizeLB.reset();
340 m_xWestFontLanguageLB.reset();
341 m_xPreviewWin.reset();
342 m_xCTLFontLanguageLB.reset();
343 m_xEastFontLanguageLB.reset();
346 void SvxCharNamePage::Initialize()
348 // to handle the changes of the other pages
349 SetExchangeSupport();
351 Link<weld::ComboBox&,void> aLink = LINK(this, SvxCharNamePage, FontModifyComboBoxHdl_Impl);
352 m_xWestFontNameLB->connect_changed(aLink);
353 m_xWestFontStyleLB->connect_changed(aLink);
354 m_xWestFontSizeLB->connect_changed(aLink);
355 m_xWestFontLanguageLB->connect_changed(aLink);
357 m_xWestFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
359 m_xEastFontNameLB->connect_changed(aLink);
360 m_xEastFontStyleLB->connect_changed(aLink);
361 m_xEastFontSizeLB->connect_changed(aLink);
362 m_xEastFontLanguageLB->connect_changed(aLink);
363 m_xEastFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
365 m_xCTLFontNameLB->connect_changed(aLink);
366 m_xCTLFontStyleLB->connect_changed(aLink);
367 m_xCTLFontSizeLB->connect_changed(aLink);
368 m_xCTLFontLanguageLB->connect_changed(aLink);
369 m_xCTLFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
371 m_pImpl->m_aUpdateIdle.SetInvokeHandler( LINK( this, SvxCharNamePage, UpdateHdl_Impl ) );
374 const FontList* SvxCharNamePage::GetFontList() const
376 if ( !m_pImpl->m_pFontList )
378 SfxObjectShell* pDocSh = SfxObjectShell::Current();
380 /* #110771# SvxFontListItem::GetFontList can return NULL */
381 if ( pDocSh )
383 const SfxPoolItem* pItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST );
384 if ( pItem != nullptr )
386 DBG_ASSERT(nullptr != static_cast<const SvxFontListItem*>(pItem)->GetFontList(),
387 "Where is the font list?");
388 m_pImpl->m_pFontList = static_cast<const SvxFontListItem*>(pItem )->GetFontList()->Clone();
391 if(!m_pImpl->m_pFontList)
393 m_pImpl->m_pFontList.reset(new FontList( Application::GetDefaultDevice() ));
397 return m_pImpl->m_pFontList.get();
401 namespace
403 FontMetric calcFontMetrics( SvxFont& _rFont,
404 SvxCharNamePage const * _pPage,
405 const weld::ComboBox* _pFontNameLB,
406 const SvtFontStyleBox* _pFontStyleLB,
407 const SvtFontSizeBox* _pFontSizeLB,
408 const SvxLanguageBox* _pLanguageLB,
409 const FontList* _pFontList,
410 sal_uInt16 _nFontWhich,
411 sal_uInt16 _nFontHeightWhich)
413 Size aSize = _rFont.GetFontSize();
414 aSize.setWidth( 0 );
415 FontMetric aFontMetrics;
416 OUString sFontName(_pFontNameLB->get_active_text());
417 bool bFontAvailable = _pFontList->IsAvailable( sFontName );
418 if (bFontAvailable || _pFontNameLB->get_value_changed_from_saved())
419 aFontMetrics = _pFontList->Get(sFontName, _pFontStyleLB->get_active_text());
420 else
422 //get the font from itemset
423 SfxItemState eState = _pPage->GetItemSet().GetItemState( _nFontWhich );
424 if ( eState >= SfxItemState::DEFAULT )
426 const SvxFontItem* pFontItem = static_cast<const SvxFontItem*>(&( _pPage->GetItemSet().Get( _nFontWhich ) ));
427 aFontMetrics.SetFamilyName(pFontItem->GetFamilyName());
428 aFontMetrics.SetStyleName(pFontItem->GetStyleName());
429 aFontMetrics.SetFamily(pFontItem->GetFamily());
430 aFontMetrics.SetPitch(pFontItem->GetPitch());
431 aFontMetrics.SetCharSet(pFontItem->GetCharSet());
434 if ( _pFontSizeLB->IsRelative() )
436 DBG_ASSERT( _pPage->GetItemSet().GetParent(), "No parent set" );
437 const SvxFontHeightItem& rOldItem = static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nFontHeightWhich ));
439 // old value, scaled
440 long nHeight;
441 if ( _pFontSizeLB->IsPtRelative() )
442 nHeight = rOldItem.GetHeight() + PointToTwips( static_cast<long>(_pFontSizeLB->get_value() / 10) );
443 else
444 nHeight = static_cast<long>(rOldItem.GetHeight() * _pFontSizeLB->get_value() / 100);
446 // conversion twips for the example-window
447 aSize.setHeight(
448 ItemToControl( nHeight, _pPage->GetItemSet().GetPool()->GetMetric( _nFontHeightWhich ), FieldUnit::TWIP ) );
450 else if ( !_pFontSizeLB->get_active_text().isEmpty() )
451 aSize.setHeight( PointToTwips( static_cast<long>(_pFontSizeLB->get_value() / 10) ) );
452 else
453 aSize.setHeight( 200 ); // default 10pt
454 aFontMetrics.SetFontSize( aSize );
456 _rFont.SetLanguage(_pLanguageLB->get_active_id());
458 _rFont.SetFamily( aFontMetrics.GetFamilyType() );
459 _rFont.SetFamilyName( aFontMetrics.GetFamilyName() );
460 _rFont.SetStyleName( aFontMetrics.GetStyleName() );
461 _rFont.SetPitch( aFontMetrics.GetPitch() );
462 _rFont.SetCharSet( aFontMetrics.GetCharSet() );
463 _rFont.SetWeight( aFontMetrics.GetWeight() );
464 _rFont.SetItalic( aFontMetrics.GetItalic() );
465 _rFont.SetFontSize( aFontMetrics.GetFontSize() );
467 return aFontMetrics;
472 void SvxCharNamePage::UpdatePreview_Impl()
474 SvxFont& rFont = GetPreviewFont();
475 SvxFont& rCJKFont = GetPreviewCJKFont();
476 SvxFont& rCTLFont = GetPreviewCTLFont();
477 // Font
478 const FontList* pFontList = GetFontList();
480 FontMetric aWestFontMetric = calcFontMetrics(rFont, this, m_xWestFontNameLB.get(),
481 m_xWestFontStyleLB.get(), m_xWestFontSizeLB.get(), m_xWestFontLanguageLB.get(),
482 pFontList, GetWhich(SID_ATTR_CHAR_FONT),
483 GetWhich(SID_ATTR_CHAR_FONTHEIGHT));
485 m_xWestFontTypeFT->set_label(pFontList->GetFontMapText(aWestFontMetric));
487 FontMetric aEastFontMetric = calcFontMetrics(rCJKFont, this, m_xEastFontNameLB.get(),
488 m_xEastFontStyleLB.get(), m_xEastFontSizeLB.get(), m_xEastFontLanguageLB.get(),
489 pFontList, GetWhich(SID_ATTR_CHAR_CJK_FONT),
490 GetWhich(SID_ATTR_CHAR_CJK_FONTHEIGHT));
492 m_xEastFontTypeFT->set_label(pFontList->GetFontMapText(aEastFontMetric));
494 FontMetric aCTLFontMetric = calcFontMetrics(rCTLFont,
495 this, m_xCTLFontNameLB.get(), m_xCTLFontStyleLB.get(), m_xCTLFontSizeLB.get(),
496 m_xCTLFontLanguageLB.get(), pFontList, GetWhich(SID_ATTR_CHAR_CTL_FONT),
497 GetWhich(SID_ATTR_CHAR_CTL_FONTHEIGHT));
499 m_xCTLFontTypeFT->set_label(pFontList->GetFontMapText(aCTLFontMetric));
501 m_aPreviewWin.Invalidate();
504 void SvxCharNamePage::FillStyleBox_Impl(const weld::Widget& rNameBox)
506 const FontList* pFontList = GetFontList();
507 DBG_ASSERT( pFontList, "no fontlist" );
509 SvtFontStyleBox* pStyleBox = nullptr;
510 OUString sFontName;
512 if (m_xWestFontNameLB.get() == &rNameBox)
514 pStyleBox = m_xWestFontStyleLB.get();
515 sFontName = m_xWestFontNameLB->get_active_text();
517 else if (m_xEastFontNameLB.get() == &rNameBox)
519 pStyleBox = m_xEastFontStyleLB.get();
520 sFontName = m_xEastFontStyleLB->get_active_text();
522 else if (m_xCTLFontNameLB.get() == &rNameBox)
524 pStyleBox = m_xCTLFontStyleLB.get();
525 sFontName = m_xCTLFontNameLB->get_active_text();
527 else
529 SAL_WARN( "cui.tabpages", "invalid font name box" );
530 return;
533 pStyleBox->Fill(sFontName, pFontList);
535 if ( m_pImpl->m_bInSearchMode )
537 // additional entries for the search:
538 // "not bold" and "not italic"
539 OUString aEntry = m_pImpl->m_aNoStyleText;
540 const sal_Char sS[] = "%1";
541 aEntry = aEntry.replaceFirst( sS, pFontList->GetBoldStr() );
542 m_pImpl->m_nExtraEntryPos = pStyleBox->get_count();
543 pStyleBox->append_text( aEntry );
544 aEntry = m_pImpl->m_aNoStyleText;
545 aEntry = aEntry.replaceFirst( sS, pFontList->GetItalicStr() );
546 pStyleBox->append_text(aEntry);
550 void SvxCharNamePage::FillSizeBox_Impl(const weld::Widget& rNameBox)
552 const FontList* pFontList = GetFontList();
553 DBG_ASSERT( pFontList, "no fontlist" );
555 SvtFontStyleBox* pStyleBox = nullptr;
556 SvtFontSizeBox* pSizeBox = nullptr;
557 OUString sFontName;
559 if (m_xWestFontNameLB.get() == &rNameBox)
561 pStyleBox = m_xWestFontStyleLB.get();
562 pSizeBox = m_xWestFontSizeLB.get();
563 sFontName = m_xWestFontNameLB->get_active_text();
565 else if (m_xEastFontNameLB.get() == &rNameBox)
567 pStyleBox = m_xEastFontStyleLB.get();
568 pSizeBox = m_xEastFontSizeLB.get();
569 sFontName = m_xEastFontNameLB->get_active_text();
571 else if (m_xCTLFontNameLB.get() == &rNameBox)
573 pStyleBox = m_xCTLFontStyleLB.get();
574 pSizeBox = m_xCTLFontSizeLB.get();
575 sFontName = m_xCTLFontNameLB->get_active_text();
577 else
579 SAL_WARN( "cui.tabpages", "invalid font name box" );
580 return;
583 FontMetric _aFontMetric(pFontList->Get(sFontName, pStyleBox->get_active_text()));
584 pSizeBox->Fill( &_aFontMetric, pFontList );
587 namespace
589 void FillFontNames(weld::ComboBox& rBox, const FontList& rList)
591 // insert fonts
592 sal_uInt16 nFontCount = rList.GetFontNameCount();
593 std::vector<weld::ComboBoxEntry> aVector;
594 aVector.reserve(nFontCount);
595 for (sal_uInt16 i = 0; i < nFontCount; ++i)
597 const FontMetric& rFontMetric = rList.GetFontName(i);
598 aVector.emplace_back(rFontMetric.GetFamilyName());
600 rBox.insert_vector(aVector, false);
604 void SvxCharNamePage::Reset_Impl( const SfxItemSet& rSet, LanguageGroup eLangGrp )
606 weld::ComboBox* pNameBox = nullptr;
607 weld::Label* pStyleLabel = nullptr;
608 SvtFontStyleBox* pStyleBox = nullptr;
609 weld::Label* pSizeLabel = nullptr;
610 SvtFontSizeBox* pSizeBox = nullptr;
611 weld::Label* pLangFT = nullptr;
612 SvxLanguageBox* pLangBox = nullptr;
613 sal_uInt16 nWhich = 0;
615 switch ( eLangGrp )
617 case Western :
618 pNameBox = m_xWestFontNameLB.get();
619 pStyleLabel = m_xWestFontStyleFT.get();
620 pStyleBox = m_xWestFontStyleLB.get();
621 pSizeLabel = m_xWestFontSizeFT.get();
622 pSizeBox = m_xWestFontSizeLB.get();
623 pLangFT = m_xWestFontLanguageFT.get();
624 pLangBox = m_xWestFontLanguageLB.get();
625 nWhich = GetWhich( SID_ATTR_CHAR_FONT );
626 break;
628 case Asian :
629 pNameBox = m_xEastFontNameLB.get();
630 pStyleLabel = m_xEastFontStyleFT.get();
631 pStyleBox = m_xEastFontStyleLB.get();
632 pSizeLabel = m_xEastFontSizeFT.get();
633 pSizeBox = m_xEastFontSizeLB.get();
634 pLangFT = m_xEastFontLanguageFT.get();
635 pLangBox = m_xEastFontLanguageLB.get();
636 nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONT );
637 break;
639 case Ctl :
640 pNameBox = m_xCTLFontNameLB.get();
641 pStyleLabel = m_xCTLFontStyleFT.get();
642 pStyleBox = m_xCTLFontStyleLB.get();
643 pSizeLabel = m_xCTLFontSizeFT.get();
644 pSizeBox = m_xCTLFontSizeLB.get();
645 pLangFT = m_xCTLFontLanguageFT.get();
646 pLangBox = m_xCTLFontLanguageLB.get();
647 nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONT );
648 break;
651 const FontList* pFontList = GetFontList();
652 FillFontNames(*pNameBox, *pFontList);
654 const SvxFontItem* pFontItem = nullptr;
655 SfxItemState eState = rSet.GetItemState( nWhich );
657 if ( eState >= SfxItemState::DEFAULT )
659 pFontItem = static_cast<const SvxFontItem*>(&( rSet.Get( nWhich ) ));
660 const OUString &rName = pFontItem->GetFamilyName();
661 int nIndex = pNameBox->find_text(rName);
662 pNameBox->set_active(nIndex);
663 // tdf#122992 if it didn't exist in the list, set the entry text to it anyway
664 if (nIndex == -1)
665 pNameBox->set_entry_text(rName);
667 else
669 pNameBox->set_active_text( OUString() );
672 FillStyleBox_Impl(*pNameBox);
674 bool bStyle = false;
675 bool bStyleAvailable = true;
676 FontItalic eItalic = ITALIC_NONE;
677 FontWeight eWeight = WEIGHT_NORMAL;
678 switch ( eLangGrp )
680 case Western : nWhich = GetWhich( SID_ATTR_CHAR_POSTURE ); break;
681 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_POSTURE ); break;
682 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_POSTURE ); break;
684 eState = rSet.GetItemState( nWhich );
686 if ( eState >= SfxItemState::DEFAULT )
688 const SvxPostureItem& rItem = static_cast<const SvxPostureItem&>(rSet.Get( nWhich ));
689 eItalic = rItem.GetValue();
690 bStyle = true;
692 bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE);
694 switch ( eLangGrp )
696 case Western : nWhich = GetWhich( SID_ATTR_CHAR_WEIGHT ); break;
697 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_WEIGHT ); break;
698 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_WEIGHT ); break;
700 eState = rSet.GetItemState( nWhich );
702 if ( eState >= SfxItemState::DEFAULT )
704 const SvxWeightItem& rItem = static_cast<const SvxWeightItem&>(rSet.Get( nWhich ));
705 eWeight = rItem.GetValue();
707 else
708 bStyle = false;
709 bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE);
711 // currently chosen font
712 if ( bStyle && pFontItem )
714 FontMetric aFontMetric = pFontList->Get( pFontItem->GetFamilyName(), eWeight, eItalic );
715 pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
717 else if ( !m_pImpl->m_bInSearchMode || !bStyle )
719 pStyleBox->set_active_text( OUString() );
721 else if ( bStyle )
723 FontMetric aFontMetric = pFontList->Get( OUString(), eWeight, eItalic );
724 pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
726 if (!bStyleAvailable)
728 pStyleBox->set_sensitive(false);
729 pStyleLabel->set_sensitive(false);
732 FillSizeBox_Impl(*pNameBox);
733 switch ( eLangGrp )
735 case Western : nWhich = GetWhich( SID_ATTR_CHAR_FONTHEIGHT ); break;
736 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ); break;
737 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ); break;
739 eState = rSet.GetItemState( nWhich );
741 if ( pSizeBox->IsRelativeMode() )
743 MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
744 const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));
746 if( rItem.GetProp() != 100 || MapUnit::MapRelative != rItem.GetPropUnit() )
748 bool bPtRel = MapUnit::MapPoint == rItem.GetPropUnit();
749 pSizeBox->SetPtRelative( bPtRel );
750 pSizeBox->set_value( bPtRel ? static_cast<short>(rItem.GetProp()) * 10 : rItem.GetProp() );
752 else
754 pSizeBox->SetRelative(false);
755 pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
758 else if ( eState >= SfxItemState::DEFAULT )
760 MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
761 const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));
762 pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
764 else
766 pSizeBox->set_active_text( OUString() );
767 if ( eState <= SfxItemState::READONLY )
769 pSizeBox->set_sensitive(false);
770 pSizeLabel->set_sensitive(false);
774 switch ( eLangGrp )
776 case Western : nWhich = GetWhich( SID_ATTR_CHAR_LANGUAGE ); break;
777 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_LANGUAGE ); break;
778 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_LANGUAGE ); break;
780 pLangBox->set_active(-1);
781 eState = rSet.GetItemState( nWhich );
783 switch ( eState )
785 case SfxItemState::UNKNOWN:
786 pLangFT->hide();
787 pLangBox->hide();
788 break;
790 case SfxItemState::DISABLED:
791 case SfxItemState::READONLY:
792 pLangFT->set_sensitive(false);
793 pLangBox->set_sensitive(false);
794 break;
796 case SfxItemState::DEFAULT:
797 case SfxItemState::SET:
799 const SvxLanguageItem& rItem = static_cast<const SvxLanguageItem&>(rSet.Get( nWhich ));
800 LanguageType eLangType = rItem.GetValue();
801 DBG_ASSERT( eLangType != LANGUAGE_SYSTEM, "LANGUAGE_SYSTEM not allowed" );
802 if (eLangType != LANGUAGE_DONTKNOW)
803 pLangBox->set_active_id(eLangType);
804 break;
806 case SfxItemState::DONTCARE:
807 break;
810 OUString sMapText(pFontList->GetFontMapText(
811 pFontList->Get(pNameBox->get_active_text(), pStyleBox->get_active_text())));
813 switch (eLangGrp)
815 case Western:
816 m_xWestFontTypeFT->set_label(sMapText);
817 break;
818 case Asian:
819 m_xEastFontTypeFT->set_label(sMapText);
820 break;
821 case Ctl:
822 m_xCTLFontTypeFT->set_label(sMapText);
823 break;
826 // save these settings
827 pNameBox->save_value();
828 pStyleBox->save_value();
829 pSizeBox->save_value();
830 pLangBox->save_active_id();
833 bool SvxCharNamePage::FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp )
835 bool bModified = false;
837 weld::ComboBox* pNameBox = nullptr;
838 SvtFontStyleBox* pStyleBox = nullptr;
839 SvtFontSizeBox* pSizeBox = nullptr;
840 SvxLanguageBox* pLangBox = nullptr;
841 sal_uInt16 nWhich = 0;
842 sal_uInt16 nSlot = 0;
844 switch ( eLangGrp )
846 case Western :
847 pNameBox = m_xWestFontNameLB.get();
848 pStyleBox = m_xWestFontStyleLB.get();
849 pSizeBox = m_xWestFontSizeLB.get();
850 pLangBox = m_xWestFontLanguageLB.get();
851 nSlot = SID_ATTR_CHAR_FONT;
852 break;
854 case Asian :
855 pNameBox = m_xEastFontNameLB.get();
856 pStyleBox = m_xEastFontStyleLB.get();
857 pSizeBox = m_xEastFontSizeLB.get();
858 pLangBox = m_xEastFontLanguageLB.get();
859 nSlot = SID_ATTR_CHAR_CJK_FONT;
860 break;
862 case Ctl :
863 pNameBox = m_xCTLFontNameLB.get();
864 pStyleBox = m_xCTLFontStyleLB.get();
865 pSizeBox = m_xCTLFontSizeLB.get();
866 pLangBox = m_xCTLFontLanguageLB.get();
867 nSlot = SID_ATTR_CHAR_CTL_FONT;
868 break;
871 nWhich = GetWhich( nSlot );
872 const SfxPoolItem* pItem = nullptr;
873 const SfxItemSet& rOldSet = GetItemSet();
874 const SfxPoolItem* pOld = nullptr;
876 const SfxItemSet* pExampleSet = GetDialogExampleSet();
878 bool bChanged = true;
879 const OUString& rFontName = pNameBox->get_active_text();
880 const FontList* pFontList = GetFontList();
881 OUString aStyleBoxText = pStyleBox->get_active_text();
882 int nEntryPos = pStyleBox->find_text(aStyleBoxText);
883 if (nEntryPos >= m_pImpl->m_nExtraEntryPos)
884 aStyleBoxText.clear();
885 FontMetric aInfo( pFontList->Get( rFontName, aStyleBoxText ) );
886 SvxFontItem aFontItem( aInfo.GetFamilyType(), aInfo.GetFamilyName(), aInfo.GetStyleName(),
887 aInfo.GetPitch(), aInfo.GetCharSet(), nWhich );
888 pOld = GetOldItem( rSet, nSlot );
890 if ( pOld )
892 const SvxFontItem& rItem = *static_cast<const SvxFontItem*>(pOld);
894 if ( rItem.GetFamilyName() == aFontItem.GetFamilyName() )
895 bChanged = false;
898 if ( !bChanged )
899 bChanged = pNameBox->get_saved_value().isEmpty();
901 if ( !bChanged && pExampleSet &&
902 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
903 static_cast<const SvxFontItem*>(pItem)->GetFamilyName() != aFontItem.GetFamilyName() )
904 bChanged = true;
906 if ( bChanged && !rFontName.isEmpty() )
908 rSet.Put( aFontItem );
909 bModified = true;
911 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
912 rSet.ClearItem( nWhich );
915 bChanged = true;
916 switch ( eLangGrp )
918 case Western : nSlot = SID_ATTR_CHAR_WEIGHT; break;
919 case Asian : nSlot = SID_ATTR_CHAR_CJK_WEIGHT; break;
920 case Ctl : nSlot = SID_ATTR_CHAR_CTL_WEIGHT; break;
922 nWhich = GetWhich( nSlot );
923 FontWeight eWeight = aInfo.GetWeight();
924 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
925 eWeight = WEIGHT_NORMAL;
926 SvxWeightItem aWeightItem( eWeight, nWhich );
927 pOld = GetOldItem( rSet, nSlot );
929 if ( pOld )
931 const SvxWeightItem& rItem = *static_cast<const SvxWeightItem*>(pOld);
933 if ( rItem.GetValue() == aWeightItem.GetValue() )
934 bChanged = false;
937 if ( !bChanged )
939 bChanged = pStyleBox->get_saved_value().isEmpty();
941 if ( m_pImpl->m_bInSearchMode && bChanged &&
942 aInfo.GetWeight() == WEIGHT_NORMAL && aInfo.GetItalic() != ITALIC_NONE )
943 bChanged = false;
946 if ( !bChanged && pExampleSet &&
947 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
948 static_cast<const SvxWeightItem*>(pItem)->GetValue() != aWeightItem.GetValue() )
949 bChanged = true;
951 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
952 bChanged = ( nEntryPos == m_pImpl->m_nExtraEntryPos );
954 OUString aText( pStyleBox->get_active_text() ); // Tristate, then text empty
956 if ( bChanged && !aText.isEmpty() )
958 rSet.Put( aWeightItem );
959 bModified = true;
961 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
962 rSet.InvalidateItem(nWhich);
964 bChanged = true;
965 switch ( eLangGrp )
967 case Western : nSlot = SID_ATTR_CHAR_POSTURE; break;
968 case Asian : nSlot = SID_ATTR_CHAR_CJK_POSTURE; break;
969 case Ctl : nSlot = SID_ATTR_CHAR_CTL_POSTURE; break;
971 nWhich = GetWhich( nSlot );
972 FontItalic eItalic = aInfo.GetItalic();
973 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
974 eItalic = ITALIC_NONE;
975 SvxPostureItem aPostureItem( eItalic, nWhich );
976 pOld = GetOldItem( rSet, nSlot );
978 if ( pOld )
980 const SvxPostureItem& rItem = *static_cast<const SvxPostureItem*>(pOld);
982 if ( rItem.GetValue() == aPostureItem.GetValue() )
983 bChanged = false;
986 if ( !bChanged )
988 bChanged = pStyleBox->get_saved_value().isEmpty();
990 if ( m_pImpl->m_bInSearchMode && bChanged &&
991 aInfo.GetItalic() == ITALIC_NONE && aInfo.GetWeight() != WEIGHT_NORMAL )
992 bChanged = false;
995 if ( !bChanged && pExampleSet &&
996 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
997 static_cast<const SvxPostureItem*>(pItem)->GetValue() != aPostureItem.GetValue() )
998 bChanged = true;
1000 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
1001 bChanged = ( nEntryPos == ( m_pImpl->m_nExtraEntryPos + 1 ) );
1003 if ( bChanged && !aText.isEmpty() )
1005 rSet.Put( aPostureItem );
1006 bModified = true;
1008 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1009 rSet.InvalidateItem(nWhich);
1011 // FontSize
1012 long nSize = pSizeBox->get_value();
1014 if ( pSizeBox->get_active_text().isEmpty() ) // GetValue() returns the min-value
1015 nSize = 0;
1016 long nSavedSize = pSizeBox->get_saved_value();
1017 const bool bRel = pSizeBox->IsRelative();
1019 switch ( eLangGrp )
1021 case Western : nSlot = SID_ATTR_CHAR_FONTHEIGHT; break;
1022 case Asian : nSlot = SID_ATTR_CHAR_CJK_FONTHEIGHT; break;
1023 case Ctl : nSlot = SID_ATTR_CHAR_CTL_FONTHEIGHT; break;
1025 nWhich = GetWhich( nSlot );
1026 const SvxFontHeightItem* pOldHeight = static_cast<const SvxFontHeightItem*>(GetOldItem( rSet, nSlot ));
1027 bChanged = ( nSize != nSavedSize );
1029 if ( !bChanged && pExampleSet &&
1030 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET )
1032 float fSize = static_cast<float>(nSize) / 10;
1033 long nVal = CalcToUnit( fSize, rSet.GetPool()->GetMetric( nWhich ) );
1034 if ( static_cast<const SvxFontHeightItem*>(pItem)->GetHeight() != static_cast<sal_uInt32>(nVal) )
1035 bChanged = true;
1038 if ( bChanged || !pOldHeight ||
1039 bRel != ( MapUnit::MapRelative != pOldHeight->GetPropUnit() || 100 != pOldHeight->GetProp() ) )
1041 MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
1042 if ( pSizeBox->IsRelative() )
1044 DBG_ASSERT( GetItemSet().GetParent(), "No parent set" );
1045 const SvxFontHeightItem& rOldItem =
1046 static_cast<const SvxFontHeightItem&>(GetItemSet().GetParent()->Get( nWhich ));
1048 SvxFontHeightItem aHeight( 240, 100, nWhich );
1049 if ( pSizeBox->IsPtRelative() )
1050 aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>( nSize / 10 ), MapUnit::MapPoint, eUnit );
1051 else
1052 aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>(nSize) );
1053 rSet.Put( aHeight );
1055 else
1057 float fSize = static_cast<float>(nSize) / 10;
1058 rSet.Put( SvxFontHeightItem( CalcToUnit( fSize, eUnit ), 100, nWhich ) );
1060 bModified = true;
1062 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1063 rSet.InvalidateItem(nWhich);
1065 bChanged = true;
1066 switch ( eLangGrp )
1068 case Western : nSlot = SID_ATTR_CHAR_LANGUAGE; break;
1069 case Asian : nSlot = SID_ATTR_CHAR_CJK_LANGUAGE; break;
1070 case Ctl : nSlot = SID_ATTR_CHAR_CTL_LANGUAGE; break;
1072 nWhich = GetWhich( nSlot );
1073 pOld = GetOldItem( rSet, nSlot );
1075 // For language list boxes acting as ComboBox, check for, add and select an
1076 // edited entry.
1077 if (pLangBox == m_xWestFontLanguageLB.get())
1079 switch (pLangBox->GetEditedAndValid())
1081 case SvxLanguageBox::EditedAndValid::No:
1082 ; // nothing to do
1083 break;
1084 case SvxLanguageBox::EditedAndValid::Valid:
1086 const int nPos = pLangBox->SaveEditedAsEntry();
1087 if (nPos != -1)
1088 pLangBox->set_active(nPos);
1090 break;
1091 case SvxLanguageBox::EditedAndValid::Invalid:
1092 pLangBox->set_active_id(pLangBox->get_saved_active_id());
1093 break;
1097 int nLangPos = pLangBox->get_active();
1098 LanguageType eLangType = pLangBox->get_active_id();
1100 if (pOld)
1102 const SvxLanguageItem& rItem = *static_cast<const SvxLanguageItem*>(pOld);
1103 if (nLangPos == -1 || eLangType == rItem.GetValue())
1104 bChanged = false;
1107 if (!bChanged)
1108 bChanged = pLangBox->get_active_id_changed_from_saved();
1110 if (bChanged && nLangPos != -1)
1112 rSet.Put(SvxLanguageItem(eLangType, nWhich));
1113 bModified = true;
1115 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1116 rSet.InvalidateItem(nWhich);
1118 return bModified;
1121 IMPL_LINK_NOARG(SvxCharNamePage, UpdateHdl_Impl, Timer *, void)
1123 UpdatePreview_Impl();
1126 IMPL_LINK(SvxCharNamePage, FontModifyComboBoxHdl_Impl, weld::ComboBox&, rBox, void)
1128 FontModifyHdl_Impl(rBox);
1131 IMPL_LINK(SvxCharNamePage, FontModifyEditHdl_Impl, weld::Entry&, rBox, void)
1133 FontModifyHdl_Impl(rBox);
1136 IMPL_LINK(SvxCharNamePage, FontFeatureButtonClicked, weld::Button&, rButton, void)
1138 OUString sFontName;
1139 weld::ComboBox* pNameBox = nullptr;
1141 if (&rButton == m_xWestFontFeaturesButton.get())
1143 pNameBox = m_xWestFontNameLB.get();
1144 sFontName = GetPreviewFont().GetFamilyName();
1146 else if (&rButton == m_xEastFontFeaturesButton.get())
1148 pNameBox = m_xEastFontNameLB.get();
1149 sFontName = GetPreviewCJKFont().GetFamilyName();
1151 else if (&rButton == m_xCTLFontFeaturesButton.get())
1153 pNameBox = m_xCTLFontNameLB.get();
1154 sFontName = GetPreviewCTLFont().GetFamilyName();
1157 if (!sFontName.isEmpty() && pNameBox)
1159 cui::FontFeaturesDialog aDialog(GetFrameWeld(), sFontName);
1160 if (aDialog.run() == RET_OK)
1162 pNameBox->set_entry_text(aDialog.getResultFontName());
1163 UpdatePreview_Impl();
1168 void SvxCharNamePage::FontModifyHdl_Impl(const weld::Widget& rNameBox)
1170 m_pImpl->m_aUpdateIdle.Start();
1172 if (m_xWestFontNameLB.get() == &rNameBox || m_xEastFontNameLB.get() == &rNameBox || m_xCTLFontNameLB.get() == &rNameBox)
1174 FillStyleBox_Impl(rNameBox);
1175 FillSizeBox_Impl(rNameBox);
1179 void SvxCharNamePage::ActivatePage( const SfxItemSet& rSet )
1181 SvxCharBasePage::ActivatePage( rSet );
1183 UpdatePreview_Impl(); // instead of asynchronous calling in ctor
1186 DeactivateRC SvxCharNamePage::DeactivatePage( SfxItemSet* _pSet )
1188 if ( _pSet )
1189 FillItemSet( _pSet );
1190 return DeactivateRC::LeavePage;
1193 std::unique_ptr<SfxTabPage> SvxCharNamePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
1195 return std::make_unique<SvxCharNamePage>(pPage, pController, *rSet );
1198 void SvxCharNamePage::Reset( const SfxItemSet* rSet )
1200 Reset_Impl( *rSet, Western );
1201 Reset_Impl( *rSet, Asian );
1202 Reset_Impl( *rSet, Ctl );
1204 SetPrevFontWidthScale( *rSet );
1205 UpdatePreview_Impl();
1208 void SvxCharNamePage::ChangesApplied()
1210 m_xWestFontNameLB->save_value();
1211 m_xWestFontStyleLB->save_value();
1212 m_xWestFontSizeLB->save_value();
1213 m_xWestFontLanguageLB->save_active_id();
1214 m_xEastFontNameLB->save_value();
1215 m_xEastFontStyleLB->save_value();
1216 m_xEastFontSizeLB->save_value();
1217 m_xEastFontLanguageLB->save_active_id();
1218 m_xCTLFontNameLB->save_value();
1219 m_xCTLFontStyleLB->save_value();
1220 m_xCTLFontSizeLB->save_value();
1221 m_xCTLFontLanguageLB->save_active_id();
1224 bool SvxCharNamePage::FillItemSet( SfxItemSet* rSet )
1226 bool bModified = FillItemSet_Impl( *rSet, Western );
1227 bModified |= FillItemSet_Impl( *rSet, Asian );
1228 bModified |= FillItemSet_Impl( *rSet, Ctl );
1229 return bModified;
1232 void SvxCharNamePage::SetFontList( const SvxFontListItem& rItem )
1234 m_pImpl->m_pFontList = rItem.GetFontList()->Clone();
1237 namespace
1239 void enableRelativeMode( SvxCharNamePage const * _pPage, SvtFontSizeBox* _pFontSizeLB, sal_uInt16 _nHeightWhich )
1241 _pFontSizeLB->EnableRelativeMode( 5, 995 ); // min 5%, max 995%, step 5
1243 const SvxFontHeightItem& rHeightItem =
1244 static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nHeightWhich ));
1245 MapUnit eUnit = _pPage->GetItemSet().GetPool()->GetMetric( _nHeightWhich );
1246 short nCurHeight =
1247 static_cast< short >( CalcToPoint( rHeightItem.GetHeight(), eUnit, 1 ) * 10 );
1249 // based on the current height:
1250 // - negative until minimum of 2 pt
1251 // - positive until maximum of 999 pt
1252 _pFontSizeLB->EnablePtRelativeMode( sal::static_int_cast< short >(-(nCurHeight - 20)), (9999 - nCurHeight) );
1256 void SvxCharNamePage::EnableRelativeMode()
1258 DBG_ASSERT( GetItemSet().GetParent(), "RelativeMode, but no ParentSet!" );
1259 enableRelativeMode(this,m_xWestFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_FONTHEIGHT ));
1260 enableRelativeMode(this,m_xEastFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ));
1261 enableRelativeMode(this,m_xCTLFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ));
1264 void SvxCharNamePage::EnableSearchMode()
1266 m_pImpl->m_bInSearchMode = true;
1269 void SvxCharNamePage::DisableControls( sal_uInt16 nDisable )
1271 if ( DISABLE_LANGUAGE & nDisable )
1273 if ( m_xWestFontLanguageFT ) m_xWestFontLanguageFT->set_sensitive(false);
1274 if ( m_xWestFontLanguageLB ) m_xWestFontLanguageLB->set_sensitive(false);
1275 if ( m_xEastFontLanguageFT ) m_xEastFontLanguageFT->set_sensitive(false);
1276 if ( m_xEastFontLanguageLB ) m_xEastFontLanguageLB->set_sensitive(false);
1277 if ( m_xCTLFontLanguageFT ) m_xCTLFontLanguageFT->set_sensitive(false);
1278 if ( m_xCTLFontLanguageLB ) m_xCTLFontLanguageLB->set_sensitive(false);
1281 if ( DISABLE_HIDE_LANGUAGE & nDisable )
1283 if ( m_xWestFontLanguageFT ) m_xWestFontLanguageFT->hide();
1284 if ( m_xWestFontLanguageLB ) m_xWestFontLanguageLB->hide();
1285 if ( m_xEastFontLanguageFT ) m_xEastFontLanguageFT->hide();
1286 if ( m_xEastFontLanguageLB ) m_xEastFontLanguageLB->hide();
1287 if ( m_xCTLFontLanguageFT ) m_xCTLFontLanguageFT->hide();
1288 if ( m_xCTLFontLanguageLB ) m_xCTLFontLanguageLB->hide();
1292 void SvxCharNamePage::PageCreated(const SfxAllItemSet& aSet)
1294 const SvxFontListItem* pFontListItem = aSet.GetItem<SvxFontListItem>(SID_ATTR_CHAR_FONTLIST, false);
1295 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
1296 const SfxUInt16Item* pDisalbeItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false);
1297 if (pFontListItem)
1298 SetFontList(*pFontListItem);
1300 if (pFlagItem)
1302 sal_uInt32 nFlags=pFlagItem->GetValue();
1303 if ( ( nFlags & SVX_RELATIVE_MODE ) == SVX_RELATIVE_MODE )
1304 EnableRelativeMode();
1305 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
1306 // the writer uses SID_ATTR_BRUSH as font background
1307 m_bPreviewBackgroundToCharacter = true;
1309 if (pDisalbeItem)
1310 DisableControls(pDisalbeItem->GetValue());
1312 // class SvxCharEffectsPage ----------------------------------------------
1314 SvxCharEffectsPage::SvxCharEffectsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
1315 : SvxCharBasePage(pPage, pController, "cui/ui/effectspage.ui", "EffectsPage", rInSet)
1316 , m_bOrigFontColor(false)
1317 , m_bNewFontColor(false)
1318 , m_bEnableNoneFontColor(false)
1319 , m_bUnderlineColorDisabled(false)
1320 , m_xFontColorFT(m_xBuilder->weld_label("fontcolorft"))
1321 , m_xFontColorLB(new ColorListBox(m_xBuilder->weld_menu_button("fontcolorlb"), pController->getDialog()))
1322 , m_xEffectsFT(m_xBuilder->weld_label("effectsft"))
1323 , m_xEffectsLB(m_xBuilder->weld_combo_box("effectslb"))
1324 , m_xReliefFT(m_xBuilder->weld_label("reliefft"))
1325 , m_xReliefLB(m_xBuilder->weld_combo_box("relieflb"))
1326 , m_xOutlineBtn(m_xBuilder->weld_check_button("outlinecb"))
1327 , m_xShadowBtn(m_xBuilder->weld_check_button("shadowcb"))
1328 , m_xBlinkingBtn(m_xBuilder->weld_check_button("blinkingcb"))
1329 , m_xHiddenBtn(m_xBuilder->weld_check_button("hiddencb"))
1330 , m_xOverlineLB(m_xBuilder->weld_combo_box("overlinelb"))
1331 , m_xOverlineColorFT(m_xBuilder->weld_label("overlinecolorft"))
1332 , m_xOverlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("overlinecolorlb"), pController->getDialog()))
1333 , m_xStrikeoutLB(m_xBuilder->weld_combo_box("strikeoutlb"))
1334 , m_xUnderlineLB(m_xBuilder->weld_combo_box("underlinelb"))
1335 , m_xUnderlineColorFT(m_xBuilder->weld_label("underlinecolorft"))
1336 , m_xUnderlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("underlinecolorlb"), pController->getDialog()))
1337 , m_xIndividualWordsBtn(m_xBuilder->weld_check_button("individualwordscb"))
1338 , m_xEmphasisFT(m_xBuilder->weld_label("emphasisft"))
1339 , m_xEmphasisLB(m_xBuilder->weld_combo_box("emphasislb"))
1340 , m_xPositionFT(m_xBuilder->weld_label("positionft"))
1341 , m_xPositionLB(m_xBuilder->weld_combo_box("positionlb"))
1342 , m_xA11yWarningFT(m_xBuilder->weld_label("a11ywarning"))
1344 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
1345 #ifdef IOS
1346 m_xPreviewWin->hide();
1347 #endif
1348 m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1349 m_xOverlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1350 m_xUnderlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1351 Initialize();
1354 void SvxCharEffectsPage::EnableNoneFontColor()
1356 m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR, true);
1357 m_bEnableNoneFontColor = true;
1360 Color SvxCharEffectsPage::GetPreviewFontColor(const Color& rColor) const
1362 if (rColor == COL_AUTO)
1363 return COL_BLACK;
1364 if (m_bEnableNoneFontColor && rColor == COL_NONE_COLOR)
1365 return COL_BLACK;
1366 return rColor;
1369 SvxCharEffectsPage::~SvxCharEffectsPage()
1371 m_xUnderlineColorLB.reset();
1372 m_xOverlineColorLB.reset();
1373 m_xFontColorLB.reset();
1376 void SvxCharEffectsPage::Initialize()
1378 // to handle the changes of the other pages
1379 SetExchangeSupport();
1381 // HTML-Mode
1382 const SfxPoolItem* pItem;
1383 SfxObjectShell* pShell;
1384 if ( SfxItemState::SET == GetItemSet().GetItemState( SID_HTML_MODE, false, &pItem ) ||
1385 ( nullptr != ( pShell = SfxObjectShell::Current() ) &&
1386 nullptr != ( pItem = pShell->GetItem( SID_HTML_MODE ) ) ) )
1388 m_nHtmlMode = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
1389 if ( ( m_nHtmlMode & HTMLMODE_ON ) == HTMLMODE_ON )
1391 //!!! hide some controls please
1395 m_xFontColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
1397 // handler
1398 Link<weld::ComboBox&,void> aLink = LINK( this, SvxCharEffectsPage, SelectListBoxHdl_Impl );
1399 m_xUnderlineLB->connect_changed( aLink );
1400 m_xUnderlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
1401 m_xOverlineLB->connect_changed( aLink );
1402 m_xOverlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
1403 m_xStrikeoutLB->connect_changed( aLink );
1404 m_xEmphasisLB->connect_changed( aLink );
1405 m_xPositionLB->connect_changed( aLink );
1406 m_xEffectsLB->connect_changed( aLink );
1407 m_xReliefLB->connect_changed( aLink );
1409 m_xUnderlineLB->set_active( 0 );
1410 m_xOverlineLB->set_active( 0 );
1411 m_xStrikeoutLB->set_active( 0 );
1412 m_xEmphasisLB->set_active( 0 );
1413 m_xPositionLB->set_active( 0 );
1414 SelectHdl_Impl(nullptr);
1415 SelectHdl_Impl(m_xEmphasisLB.get());
1417 m_xEffectsLB->set_active( 0 );
1419 m_xIndividualWordsBtn->connect_toggled(LINK(this, SvxCharEffectsPage, CbClickHdl_Impl));
1420 Link<weld::ToggleButton&,void> aLink2 = LINK(this, SvxCharEffectsPage, TristClickHdl_Impl);
1421 m_xOutlineBtn->connect_toggled(aLink2);
1422 m_xShadowBtn->connect_toggled(aLink2);
1424 if ( !SvtLanguageOptions().IsAsianTypographyEnabled() )
1426 m_xEmphasisFT->hide();
1427 m_xEmphasisLB->hide();
1428 m_xPositionFT->hide();
1429 m_xPositionLB->hide();
1432 m_xA11yWarningFT->set_visible(officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get());
1435 void SvxCharEffectsPage::UpdatePreview_Impl()
1437 SvxFont& rFont = GetPreviewFont();
1438 SvxFont& rCJKFont = GetPreviewCJKFont();
1439 SvxFont& rCTLFont = GetPreviewCTLFont();
1441 const Color& rSelectedColor = m_xFontColorLB->GetSelectEntryColor();
1442 rFont.SetColor(GetPreviewFontColor(rSelectedColor));
1443 rCJKFont.SetColor(GetPreviewFontColor(rSelectedColor));
1444 rCTLFont.SetColor(GetPreviewFontColor(rSelectedColor));
1446 FontLineStyle eUnderline = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32());
1447 FontLineStyle eOverline = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32());
1448 FontStrikeout eStrikeout = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32());
1449 rFont.SetUnderline( eUnderline );
1450 rCJKFont.SetUnderline( eUnderline );
1451 rCTLFont.SetUnderline( eUnderline );
1452 m_aPreviewWin.SetTextLineColor( m_xUnderlineColorLB->GetSelectEntryColor() );
1453 rFont.SetOverline( eOverline );
1454 rCJKFont.SetOverline( eOverline );
1455 rCTLFont.SetOverline( eOverline );
1456 m_aPreviewWin.SetOverlineColor( m_xOverlineColorLB->GetSelectEntryColor() );
1457 rFont.SetStrikeout( eStrikeout );
1458 rCJKFont.SetStrikeout( eStrikeout );
1459 rCTLFont.SetStrikeout( eStrikeout );
1461 auto nEmphasis = m_xEmphasisLB->get_active();
1462 if (nEmphasis != -1)
1464 bool bUnder = (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32());
1465 FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nEmphasis);
1466 eMark |= bUnder ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove;
1467 rFont.SetEmphasisMark( eMark );
1468 rCJKFont.SetEmphasisMark( eMark );
1469 rCTLFont.SetEmphasisMark( eMark );
1472 auto nRelief = m_xReliefLB->get_active();
1473 if (nRelief != -1)
1475 rFont.SetRelief( static_cast<FontRelief>(nRelief) );
1476 rCJKFont.SetRelief( static_cast<FontRelief>(nRelief) );
1477 rCTLFont.SetRelief( static_cast<FontRelief>(nRelief) );
1480 rFont.SetOutline( StateToAttr( m_xOutlineBtn->get_state() ) );
1481 rCJKFont.SetOutline( rFont.IsOutline() );
1482 rCTLFont.SetOutline( rFont.IsOutline() );
1484 rFont.SetShadow( StateToAttr( m_xShadowBtn->get_state() ) );
1485 rCJKFont.SetShadow( rFont.IsShadow() );
1486 rCTLFont.SetShadow( rFont.IsShadow() );
1488 auto nCapsPos = m_xEffectsLB->get_active();
1489 if (nCapsPos != -1)
1491 SvxCaseMap eCaps = static_cast<SvxCaseMap>(nCapsPos);
1492 rFont.SetCaseMap( eCaps );
1493 rCJKFont.SetCaseMap( eCaps );
1494 // #i78474# small caps do not exist in CTL fonts
1495 rCTLFont.SetCaseMap( eCaps == SvxCaseMap::SmallCaps ? SvxCaseMap::NotMapped : eCaps );
1498 bool bWordLine = m_xIndividualWordsBtn->get_active();
1499 rFont.SetWordLineMode( bWordLine );
1500 rCJKFont.SetWordLineMode( bWordLine );
1501 rCTLFont.SetWordLineMode( bWordLine );
1503 m_aPreviewWin.Invalidate();
1506 void SvxCharEffectsPage::SetCaseMap_Impl( SvxCaseMap eCaseMap )
1508 if ( SvxCaseMap::End > eCaseMap )
1509 m_xEffectsLB->set_active(
1510 sal::static_int_cast< sal_Int32 >( eCaseMap ) );
1511 else
1513 // not mapped
1514 m_xEffectsLB->set_active(-1);
1517 UpdatePreview_Impl();
1520 void SvxCharEffectsPage::ResetColor_Impl( const SfxItemSet& rSet )
1522 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
1523 SfxItemState eState = rSet.GetItemState( nWhich );
1525 m_bOrigFontColor = false;
1526 switch ( eState )
1528 case SfxItemState::UNKNOWN:
1529 m_xFontColorFT->hide();
1530 m_xFontColorLB->hide();
1531 break;
1533 case SfxItemState::DISABLED:
1534 case SfxItemState::READONLY:
1535 m_xFontColorFT->set_sensitive(false);
1536 m_xFontColorLB->set_sensitive(false);
1537 break;
1539 case SfxItemState::DONTCARE:
1540 //Related: tdf#106080 if there is no font color, then allow "none"
1541 //as a color so the listbox can display that state.
1542 EnableNoneFontColor();
1543 m_xFontColorLB->SetNoSelection();
1544 break;
1546 case SfxItemState::DEFAULT:
1547 case SfxItemState::SET:
1549 SvxFont& rFont = GetPreviewFont();
1550 SvxFont& rCJKFont = GetPreviewCJKFont();
1551 SvxFont& rCTLFont = GetPreviewCTLFont();
1553 const SvxColorItem& rItem = static_cast<const SvxColorItem&>(rSet.Get( nWhich ));
1554 Color aColor = rItem.GetValue();
1555 rFont.SetColor(GetPreviewFontColor(aColor));
1556 rCJKFont.SetColor(GetPreviewFontColor(aColor));
1557 rCTLFont.SetColor(GetPreviewFontColor(aColor));
1559 m_aPreviewWin.Invalidate();
1561 m_xFontColorLB->SelectEntry(aColor);
1563 m_aOrigFontColor = aColor;
1564 m_bOrigFontColor = true;
1565 break;
1568 m_bNewFontColor = false;
1571 bool SvxCharEffectsPage::FillItemSetColor_Impl( SfxItemSet& rSet )
1573 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
1574 const SfxItemSet& rOldSet = GetItemSet();
1576 Color aSelectedColor;
1577 bool bChanged = m_bNewFontColor;
1579 if (bChanged)
1581 aSelectedColor = m_xFontColorLB->GetSelectEntryColor();
1582 if (m_bOrigFontColor)
1583 bChanged = aSelectedColor != m_aOrigFontColor;
1584 if (m_bEnableNoneFontColor && bChanged && aSelectedColor == COL_NONE_COLOR)
1585 bChanged = false;
1588 if (bChanged)
1589 rSet.Put( SvxColorItem( aSelectedColor, nWhich ) );
1590 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1591 rSet.InvalidateItem(nWhich);
1593 return bChanged;
1596 IMPL_LINK( SvxCharEffectsPage, SelectListBoxHdl_Impl, weld::ComboBox&, rBox, void )
1598 SelectHdl_Impl(&rBox);
1601 void SvxCharEffectsPage::SelectHdl_Impl(const weld::ComboBox* pBox)
1603 if (m_xEmphasisLB.get() == pBox)
1605 auto nEPos = m_xEmphasisLB->get_active();
1606 bool bEnable = nEPos > 0;
1607 m_xPositionFT->set_sensitive( bEnable );
1608 m_xPositionLB->set_sensitive( bEnable );
1610 else if (m_xReliefLB.get() == pBox)
1612 bool bEnable = ( pBox->get_active() == 0 );
1613 m_xOutlineBtn->set_sensitive( bEnable );
1614 m_xShadowBtn->set_sensitive( bEnable );
1616 else if (m_xPositionLB.get() != pBox)
1618 bool bUEnable = false;
1619 if (!m_bUnderlineColorDisabled)
1621 auto nUPos = m_xUnderlineLB->get_active();
1622 bUEnable = nUPos > 0;
1623 m_xUnderlineColorFT->set_sensitive(bUEnable);
1624 m_xUnderlineColorLB->set_sensitive(bUEnable);
1627 auto nOPos = m_xOverlineLB->get_active();
1628 bool bOEnable = nOPos > 0;
1629 m_xOverlineColorFT->set_sensitive(bOEnable);
1630 m_xOverlineColorLB->set_sensitive(bOEnable);
1632 auto nSPos = m_xStrikeoutLB->get_active();
1633 m_xIndividualWordsBtn->set_sensitive( bUEnable || bOEnable || nSPos > 0);
1635 UpdatePreview_Impl();
1638 IMPL_LINK_NOARG(SvxCharEffectsPage, UpdatePreview_Impl, weld::ComboBox&, void)
1640 bool bEnable = ( ( m_xUnderlineLB->get_active() > 0 ) ||
1641 ( m_xOverlineLB->get_active() > 0 ) ||
1642 ( m_xStrikeoutLB->get_active() > 0 ) );
1643 m_xIndividualWordsBtn->set_sensitive( bEnable );
1645 UpdatePreview_Impl();
1648 IMPL_LINK_NOARG(SvxCharEffectsPage, CbClickHdl_Impl, weld::ToggleButton&, void)
1650 UpdatePreview_Impl();
1653 IMPL_LINK_NOARG(SvxCharEffectsPage, TristClickHdl_Impl, weld::ToggleButton&, void)
1655 UpdatePreview_Impl();
1658 IMPL_LINK(SvxCharEffectsPage, ColorBoxSelectHdl_Impl, ColorListBox&, rBox, void)
1660 if (m_xFontColorLB.get() == &rBox)
1661 m_bNewFontColor = true;
1662 UpdatePreview_Impl();
1665 DeactivateRC SvxCharEffectsPage::DeactivatePage( SfxItemSet* _pSet )
1667 if ( _pSet )
1668 FillItemSet( _pSet );
1669 return DeactivateRC::LeavePage;
1672 std::unique_ptr<SfxTabPage> SvxCharEffectsPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
1674 return std::make_unique<SvxCharEffectsPage>( pPage, pController, *rSet );
1677 void SvxCharEffectsPage::Reset( const SfxItemSet* rSet )
1679 SvxFont& rFont = GetPreviewFont();
1680 SvxFont& rCJKFont = GetPreviewCJKFont();
1681 SvxFont& rCTLFont = GetPreviewCTLFont();
1683 bool bEnable = false;
1685 // Underline
1686 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE );
1687 rFont.SetUnderline( LINESTYLE_NONE );
1688 rCJKFont.SetUnderline( LINESTYLE_NONE );
1689 rCTLFont.SetUnderline( LINESTYLE_NONE );
1691 m_xUnderlineLB->set_active( 0 );
1692 SfxItemState eState = rSet->GetItemState( nWhich );
1694 if ( eState >= SfxItemState::DONTCARE )
1696 if ( eState == SfxItemState::DONTCARE )
1697 m_xUnderlineLB->set_active(-1);
1698 else
1700 const SvxUnderlineItem& rItem = static_cast<const SvxUnderlineItem&>(rSet->Get( nWhich ));
1701 FontLineStyle eUnderline = rItem.GetValue();
1702 rFont.SetUnderline( eUnderline );
1703 rCJKFont.SetUnderline( eUnderline );
1704 rCTLFont.SetUnderline( eUnderline );
1706 if ( eUnderline != LINESTYLE_NONE )
1708 auto nPos = m_xUnderlineLB->find_id(OUString::number(eUnderline));
1709 if (nPos != -1)
1711 m_xUnderlineLB->set_active(nPos);
1712 bEnable = true;
1714 Color aColor = rItem.GetColor();
1715 m_xUnderlineColorLB->SelectEntry(aColor);
1717 else
1719 m_xUnderlineColorLB->SelectEntry(COL_AUTO);
1720 m_xUnderlineColorLB->set_sensitive(false);
1725 // Overline
1726 nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE );
1727 rFont.SetOverline( LINESTYLE_NONE );
1728 rCJKFont.SetOverline( LINESTYLE_NONE );
1729 rCTLFont.SetOverline( LINESTYLE_NONE );
1731 m_xOverlineLB->set_active( 0 );
1732 eState = rSet->GetItemState( nWhich );
1734 if ( eState >= SfxItemState::DONTCARE )
1736 if ( eState == SfxItemState::DONTCARE )
1737 m_xOverlineLB->set_active(-1);
1738 else
1740 const SvxOverlineItem& rItem = static_cast<const SvxOverlineItem&>(rSet->Get( nWhich ));
1741 FontLineStyle eOverline = rItem.GetValue();
1742 rFont.SetOverline( eOverline );
1743 rCJKFont.SetOverline( eOverline );
1744 rCTLFont.SetOverline( eOverline );
1746 if ( eOverline != LINESTYLE_NONE )
1748 auto nPos = m_xOverlineLB->find_id(OUString::number(eOverline));
1749 if (nPos != -1)
1751 m_xOverlineLB->set_active(nPos);
1752 bEnable = true;
1754 Color aColor = rItem.GetColor();
1755 m_xOverlineColorLB->SelectEntry(aColor);
1757 else
1759 m_xOverlineColorLB->SelectEntry(COL_AUTO);
1760 m_xOverlineColorLB->set_sensitive(false);
1765 // Strikeout
1766 nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT );
1767 rFont.SetStrikeout( STRIKEOUT_NONE );
1768 rCJKFont.SetStrikeout( STRIKEOUT_NONE );
1769 rCTLFont.SetStrikeout( STRIKEOUT_NONE );
1771 m_xStrikeoutLB->set_active( 0 );
1772 eState = rSet->GetItemState( nWhich );
1774 if ( eState >= SfxItemState::DONTCARE )
1776 if ( eState == SfxItemState::DONTCARE )
1777 m_xStrikeoutLB->set_active(-1);
1778 else
1780 const SvxCrossedOutItem& rItem = static_cast<const SvxCrossedOutItem&>(rSet->Get( nWhich ));
1781 FontStrikeout eStrikeout = rItem.GetValue();
1782 rFont.SetStrikeout( eStrikeout );
1783 rCJKFont.SetStrikeout( eStrikeout );
1784 rCTLFont.SetStrikeout( eStrikeout );
1786 if ( eStrikeout != STRIKEOUT_NONE )
1788 auto nPos = m_xStrikeoutLB->find_id(OUString::number(eStrikeout));
1789 if (nPos != -1)
1791 m_xStrikeoutLB->set_active(nPos);
1792 bEnable = true;
1798 // WordLineMode
1799 nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE );
1800 eState = rSet->GetItemState( nWhich );
1802 switch ( eState )
1804 case SfxItemState::UNKNOWN:
1805 m_xIndividualWordsBtn->hide();
1806 break;
1808 case SfxItemState::DISABLED:
1809 case SfxItemState::READONLY:
1810 m_xIndividualWordsBtn->set_sensitive(false);
1811 break;
1813 case SfxItemState::DONTCARE:
1814 m_xIndividualWordsBtn->set_state( TRISTATE_INDET );
1815 break;
1817 case SfxItemState::DEFAULT:
1818 case SfxItemState::SET:
1820 const SvxWordLineModeItem& rItem = static_cast<const SvxWordLineModeItem&>(rSet->Get( nWhich ));
1821 rFont.SetWordLineMode( rItem.GetValue() );
1822 rCJKFont.SetWordLineMode( rItem.GetValue() );
1823 rCTLFont.SetWordLineMode( rItem.GetValue() );
1825 m_xIndividualWordsBtn->set_active(rItem.GetValue());
1826 m_xIndividualWordsBtn->set_sensitive(bEnable);
1827 break;
1831 // Emphasis
1832 nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK );
1833 eState = rSet->GetItemState( nWhich );
1835 if ( eState >= SfxItemState::DEFAULT )
1837 const SvxEmphasisMarkItem& rItem = static_cast<const SvxEmphasisMarkItem&>(rSet->Get( nWhich ));
1838 FontEmphasisMark eMark = rItem.GetEmphasisMark();
1839 rFont.SetEmphasisMark( eMark );
1840 rCJKFont.SetEmphasisMark( eMark );
1841 rCTLFont.SetEmphasisMark( eMark );
1843 m_xEmphasisLB->set_active( static_cast<sal_Int32>(FontEmphasisMark( eMark & FontEmphasisMark::Style )) );
1844 eMark &= ~FontEmphasisMark::Style;
1845 int nEntryData = ( eMark == FontEmphasisMark::PosAbove )
1846 ? CHRDLG_POSITION_OVER
1847 : ( eMark == FontEmphasisMark::PosBelow ) ? CHRDLG_POSITION_UNDER : 0;
1849 auto nPos = m_xPositionLB->find_id(OUString::number(nEntryData));
1850 if (nPos != -1)
1851 m_xPositionLB->set_active(nPos);
1853 else if ( eState == SfxItemState::DONTCARE )
1854 m_xEmphasisLB->set_active(-1);
1855 else if ( eState == SfxItemState::UNKNOWN )
1857 m_xEmphasisFT->hide();
1858 m_xEmphasisLB->hide();
1860 else // SfxItemState::DISABLED or SfxItemState::READONLY
1862 m_xEmphasisFT->set_sensitive(false);
1863 m_xEmphasisLB->set_sensitive(false);
1866 // the select handler for the underline/overline/strikeout list boxes
1867 SelectHdl_Impl(m_xUnderlineLB.get());
1869 // the select handler for the emphasis listbox
1870 SelectHdl_Impl(m_xEmphasisLB.get());
1872 // Effects
1873 SvxCaseMap eCaseMap = SvxCaseMap::End;
1874 nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP );
1875 eState = rSet->GetItemState( nWhich );
1876 switch ( eState )
1878 case SfxItemState::UNKNOWN:
1879 m_xEffectsFT->hide();
1880 m_xEffectsLB->hide();
1881 break;
1883 case SfxItemState::DISABLED:
1884 case SfxItemState::READONLY:
1885 m_xEffectsFT->set_sensitive(false);
1886 m_xEffectsLB->set_sensitive(false);
1887 break;
1889 case SfxItemState::DONTCARE:
1890 m_xEffectsLB->set_active(-1);
1891 break;
1893 case SfxItemState::DEFAULT:
1894 case SfxItemState::SET:
1896 const SvxCaseMapItem& rItem = static_cast<const SvxCaseMapItem&>(rSet->Get( nWhich ));
1897 eCaseMap = rItem.GetValue();
1898 break;
1901 SetCaseMap_Impl( eCaseMap );
1903 //Relief
1904 nWhich = GetWhich(SID_ATTR_CHAR_RELIEF);
1905 eState = rSet->GetItemState( nWhich );
1906 switch ( eState )
1908 case SfxItemState::UNKNOWN:
1909 m_xReliefFT->hide();
1910 m_xReliefLB->hide();
1911 break;
1913 case SfxItemState::DISABLED:
1914 case SfxItemState::READONLY:
1915 m_xReliefFT->set_sensitive(false);
1916 m_xReliefLB->set_sensitive(false);
1917 break;
1919 case SfxItemState::DONTCARE:
1920 m_xReliefLB->set_active(-1);
1921 break;
1923 case SfxItemState::DEFAULT:
1924 case SfxItemState::SET:
1926 const SvxCharReliefItem& rItem = static_cast<const SvxCharReliefItem&>(rSet->Get( nWhich ));
1927 m_xReliefLB->set_active(static_cast<sal_Int32>(rItem.GetValue()));
1928 SelectHdl_Impl(m_xReliefLB.get());
1929 break;
1933 // Outline
1934 nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR );
1935 eState = rSet->GetItemState( nWhich );
1936 switch ( eState )
1938 case SfxItemState::UNKNOWN:
1939 m_xOutlineBtn->hide();
1940 break;
1942 case SfxItemState::DISABLED:
1943 case SfxItemState::READONLY:
1944 m_xOutlineBtn->set_sensitive(false);
1945 break;
1947 case SfxItemState::DONTCARE:
1948 m_xOutlineBtn->set_state(TRISTATE_INDET);
1949 break;
1951 case SfxItemState::DEFAULT:
1952 case SfxItemState::SET:
1954 const SvxContourItem& rItem = static_cast<const SvxContourItem&>(rSet->Get( nWhich ));
1955 m_xOutlineBtn->set_state(static_cast<TriState>(rItem.GetValue()));
1956 break;
1960 // Shadow
1961 nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED );
1962 eState = rSet->GetItemState( nWhich );
1964 switch ( eState )
1966 case SfxItemState::UNKNOWN:
1967 m_xShadowBtn->hide();
1968 break;
1970 case SfxItemState::DISABLED:
1971 case SfxItemState::READONLY:
1972 m_xShadowBtn->set_sensitive(false);
1973 break;
1975 case SfxItemState::DONTCARE:
1976 m_xShadowBtn->set_state( TRISTATE_INDET );
1977 break;
1979 case SfxItemState::DEFAULT:
1980 case SfxItemState::SET:
1982 const SvxShadowedItem& rItem = static_cast<const SvxShadowedItem&>(rSet->Get( nWhich ));
1983 m_xShadowBtn->set_state( static_cast<TriState>(rItem.GetValue()) );
1984 break;
1988 // Blinking
1989 nWhich = GetWhich( SID_ATTR_FLASH );
1990 eState = rSet->GetItemState( nWhich );
1992 switch ( eState )
1994 case SfxItemState::UNKNOWN:
1995 m_xBlinkingBtn->hide();
1996 break;
1998 case SfxItemState::DISABLED:
1999 case SfxItemState::READONLY:
2000 m_xBlinkingBtn->set_sensitive(false);
2001 break;
2003 case SfxItemState::DONTCARE:
2004 m_xBlinkingBtn->set_state( TRISTATE_INDET );
2005 break;
2007 case SfxItemState::DEFAULT:
2008 case SfxItemState::SET:
2010 const SvxBlinkItem& rItem = static_cast<const SvxBlinkItem&>(rSet->Get( nWhich ));
2011 m_xBlinkingBtn->set_state( static_cast<TriState>(rItem.GetValue()) );
2012 break;
2015 // Hidden
2016 nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN );
2017 eState = rSet->GetItemState( nWhich );
2019 switch ( eState )
2021 case SfxItemState::UNKNOWN:
2022 m_xHiddenBtn->hide();
2023 break;
2025 case SfxItemState::DISABLED:
2026 case SfxItemState::READONLY:
2027 m_xHiddenBtn->set_sensitive(false);
2028 break;
2030 case SfxItemState::DONTCARE:
2031 m_xHiddenBtn->set_state(TRISTATE_INDET);
2032 break;
2034 case SfxItemState::DEFAULT:
2035 case SfxItemState::SET:
2037 const SvxCharHiddenItem& rItem = static_cast<const SvxCharHiddenItem&>(rSet->Get( nWhich ));
2038 m_xHiddenBtn->set_state(static_cast<TriState>(rItem.GetValue()));
2039 break;
2043 SetPrevFontWidthScale( *rSet );
2044 ResetColor_Impl( *rSet );
2046 // preview update
2047 m_aPreviewWin.Invalidate();
2049 // save this settings
2050 ChangesApplied();
2053 void SvxCharEffectsPage::ChangesApplied()
2055 m_xUnderlineLB->save_value();
2056 m_xOverlineLB->save_value();
2057 m_xStrikeoutLB->save_value();
2058 m_xIndividualWordsBtn->save_state();
2059 m_xEmphasisLB->save_value();
2060 m_xPositionLB->save_value();
2061 m_xEffectsLB->save_value();
2062 m_xReliefLB->save_value();
2063 m_xOutlineBtn->save_state();
2064 m_xShadowBtn->save_state();
2065 m_xBlinkingBtn->save_state();
2066 m_xHiddenBtn->save_state();
2069 bool SvxCharEffectsPage::FillItemSet( SfxItemSet* rSet )
2071 const SfxPoolItem* pOld = nullptr;
2072 const SfxItemSet& rOldSet = GetItemSet();
2073 bool bModified = false;
2074 bool bChanged = true;
2076 // Underline
2077 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE );
2078 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_UNDERLINE );
2079 auto nPos = m_xUnderlineLB->get_active();
2080 FontLineStyle eUnder = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32());
2082 if ( pOld )
2084 //! if there are different underline styles in the selection the
2085 //! item-state in the 'rOldSet' will be invalid. In this case
2086 //! changing the underline style will be allowed if a style is
2087 //! selected in the listbox.
2088 bool bAllowChg = nPos != -1 &&
2089 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2091 const SvxUnderlineItem& rItem = *static_cast<const SvxUnderlineItem*>(pOld);
2092 if ( rItem.GetValue() == eUnder &&
2093 ( LINESTYLE_NONE == eUnder || rItem.GetColor() == m_xUnderlineColorLB->GetSelectEntryColor() ) &&
2094 ! bAllowChg )
2095 bChanged = false;
2098 if ( bChanged )
2100 SvxUnderlineItem aNewItem( eUnder, nWhich );
2101 aNewItem.SetColor( m_xUnderlineColorLB->GetSelectEntryColor() );
2102 rSet->Put( aNewItem );
2103 bModified = true;
2105 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2106 rSet->InvalidateItem(nWhich);
2108 bChanged = true;
2110 // Overline
2111 nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE );
2112 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_OVERLINE );
2113 nPos = m_xOverlineLB->get_active();
2114 FontLineStyle eOver = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32());
2116 if ( pOld )
2118 //! if there are different underline styles in the selection the
2119 //! item-state in the 'rOldSet' will be invalid. In this case
2120 //! changing the underline style will be allowed if a style is
2121 //! selected in the listbox.
2122 bool bAllowChg = nPos != -1 &&
2123 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2125 const SvxOverlineItem& rItem = *static_cast<const SvxOverlineItem*>(pOld);
2126 if ( rItem.GetValue() == eOver &&
2127 ( LINESTYLE_NONE == eOver || rItem.GetColor() == m_xOverlineColorLB->GetSelectEntryColor() ) &&
2128 ! bAllowChg )
2129 bChanged = false;
2132 if ( bChanged )
2134 SvxOverlineItem aNewItem( eOver, nWhich );
2135 aNewItem.SetColor( m_xOverlineColorLB->GetSelectEntryColor() );
2136 rSet->Put( aNewItem );
2137 bModified = true;
2139 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2140 rSet->InvalidateItem(nWhich);
2142 bChanged = true;
2144 // Strikeout
2145 nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT );
2146 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_STRIKEOUT );
2147 nPos = m_xStrikeoutLB->get_active();
2148 FontStrikeout eStrike = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32());
2150 if ( pOld )
2152 //! if there are different strikeout styles in the selection the
2153 //! item-state in the 'rOldSet' will be invalid. In this case
2154 //! changing the strikeout style will be allowed if a style is
2155 //! selected in the listbox.
2156 bool bAllowChg = nPos != -1 &&
2157 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2159 const SvxCrossedOutItem& rItem = *static_cast<const SvxCrossedOutItem*>(pOld);
2160 if ( !m_xStrikeoutLB->get_sensitive()
2161 || (rItem.GetValue() == eStrike && !bAllowChg) )
2162 bChanged = false;
2165 if ( bChanged )
2167 rSet->Put( SvxCrossedOutItem( eStrike, nWhich ) );
2168 bModified = true;
2170 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2171 rSet->InvalidateItem(nWhich);
2173 bChanged = true;
2175 // Individual words
2176 nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE );
2177 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_WORDLINEMODE );
2179 if ( pOld )
2181 const SvxWordLineModeItem& rItem = *static_cast<const SvxWordLineModeItem*>(pOld);
2182 if ( rItem.GetValue() == m_xIndividualWordsBtn->get_active() )
2183 bChanged = false;
2186 if ( rOldSet.GetItemState( nWhich ) == SfxItemState::DONTCARE &&
2187 ! m_xIndividualWordsBtn->get_state_changed_from_saved() )
2188 bChanged = false;
2190 if ( bChanged )
2192 rSet->Put( SvxWordLineModeItem( m_xIndividualWordsBtn->get_active(), nWhich ) );
2193 bModified = true;
2195 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2196 rSet->InvalidateItem(nWhich);
2198 bChanged = true;
2200 // Emphasis
2201 nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK );
2202 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_EMPHASISMARK );
2203 int nMarkPos = m_xEmphasisLB->get_active();
2204 OUString sMarkPos = m_xEmphasisLB->get_active_text();
2205 OUString sPosPos = m_xPositionLB->get_active_text();
2206 FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nMarkPos);
2207 if (m_xPositionLB->get_sensitive())
2209 eMark |= (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32())
2210 ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove;
2213 if ( pOld )
2215 if( rOldSet.GetItemState( nWhich ) != SfxItemState::DONTCARE )
2217 const SvxEmphasisMarkItem& rItem = *static_cast<const SvxEmphasisMarkItem*>(pOld);
2218 if ( rItem.GetEmphasisMark() == eMark )
2219 bChanged = false;
2223 if (rOldSet.GetItemState( nWhich ) == SfxItemState::DONTCARE &&
2224 m_xEmphasisLB->get_saved_value() == sMarkPos && m_xPositionLB->get_saved_value() == sPosPos)
2226 bChanged = false;
2229 if (bChanged)
2231 rSet->Put( SvxEmphasisMarkItem( eMark, nWhich ) );
2232 bModified = true;
2234 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2235 rSet->InvalidateItem(nWhich);
2237 bChanged = true;
2239 // Effects
2240 nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP );
2241 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CASEMAP );
2242 SvxCaseMap eCaseMap = SvxCaseMap::NotMapped;
2243 bool bChecked = false;
2244 auto nCapsPos = m_xEffectsLB->get_active();
2245 if (nCapsPos != -1)
2247 eCaseMap = static_cast<SvxCaseMap>(nCapsPos);
2248 bChecked = true;
2251 if ( pOld )
2253 //! if there are different effect styles in the selection the
2254 //! item-state in the 'rOldSet' will be invalid. In this case
2255 //! changing the effect style will be allowed if a style is
2256 //! selected in the listbox.
2257 bool bAllowChg = nPos != -1 &&
2258 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2260 const SvxCaseMapItem& rItem = *static_cast<const SvxCaseMapItem*>(pOld);
2261 if ( rItem.GetValue() == eCaseMap && !bAllowChg )
2262 bChanged = false;
2265 if ( bChanged && bChecked )
2267 rSet->Put( SvxCaseMapItem( eCaseMap, nWhich ) );
2268 bModified = true;
2270 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2271 rSet->InvalidateItem(nWhich);
2273 bChanged = true;
2275 //Relief
2276 nWhich = GetWhich(SID_ATTR_CHAR_RELIEF);
2277 if (m_xReliefLB->get_value_changed_from_saved())
2279 m_xReliefLB->save_value();
2280 SvxCharReliefItem aRelief(static_cast<FontRelief>(m_xReliefLB->get_active()), nWhich);
2281 rSet->Put(aRelief);
2284 // Outline
2285 const SfxItemSet* pExampleSet = GetDialogExampleSet();
2286 nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR );
2287 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CONTOUR );
2288 TriState eState = m_xOutlineBtn->get_state();
2289 const SfxPoolItem* pItem;
2291 if ( pOld )
2293 const SvxContourItem& rItem = *static_cast<const SvxContourItem*>(pOld);
2294 if ( rItem.GetValue() == StateToAttr( eState ) && m_xOutlineBtn->get_saved_state() == eState )
2295 bChanged = false;
2298 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2299 !StateToAttr( eState ) && static_cast<const SvxContourItem*>(pItem)->GetValue() )
2300 bChanged = true;
2302 if ( bChanged && eState != TRISTATE_INDET )
2304 rSet->Put( SvxContourItem( StateToAttr( eState ), nWhich ) );
2305 bModified = true;
2307 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2308 rSet->InvalidateItem(nWhich);
2310 bChanged = true;
2312 // Shadow
2313 nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED );
2314 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_SHADOWED );
2315 eState = m_xShadowBtn->get_state();
2317 if ( pOld )
2319 const SvxShadowedItem& rItem = *static_cast<const SvxShadowedItem*>(pOld);
2320 if ( rItem.GetValue() == StateToAttr( eState ) && m_xShadowBtn->get_saved_state() == eState )
2321 bChanged = false;
2324 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2325 !StateToAttr( eState ) && static_cast<const SvxShadowedItem*>(pItem)->GetValue() )
2326 bChanged = true;
2328 if ( bChanged && eState != TRISTATE_INDET )
2330 rSet->Put( SvxShadowedItem( StateToAttr( eState ), nWhich ) );
2331 bModified = true;
2333 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2334 rSet->InvalidateItem(nWhich);
2336 bChanged = true;
2338 // Blinking
2339 nWhich = GetWhich( SID_ATTR_FLASH );
2340 pOld = GetOldItem( *rSet, SID_ATTR_FLASH );
2341 eState = m_xBlinkingBtn->get_state();
2343 if ( pOld )
2345 const SvxBlinkItem& rItem = *static_cast<const SvxBlinkItem*>(pOld);
2346 if ( rItem.GetValue() == StateToAttr( eState ) && m_xBlinkingBtn->get_saved_state() == eState )
2347 bChanged = false;
2350 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2351 !StateToAttr( eState ) && static_cast<const SvxBlinkItem*>(pItem)->GetValue() )
2352 bChanged = true;
2354 if ( bChanged && eState != TRISTATE_INDET )
2356 rSet->Put( SvxBlinkItem( StateToAttr( eState ), nWhich ) );
2357 bModified = true;
2359 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2360 rSet->InvalidateItem(nWhich);
2362 // Hidden
2363 nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN );
2364 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_HIDDEN );
2365 eState = m_xHiddenBtn->get_state();
2366 bChanged = true;
2368 if ( pOld )
2370 const SvxCharHiddenItem& rItem = *static_cast<const SvxCharHiddenItem*>(pOld);
2371 if ( rItem.GetValue() == StateToAttr( eState ) && m_xHiddenBtn->get_saved_state() == eState )
2372 bChanged = false;
2375 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2376 !StateToAttr( eState ) && static_cast<const SvxCharHiddenItem*>(pItem)->GetValue() )
2377 bChanged = true;
2379 if ( bChanged && eState != TRISTATE_INDET )
2381 rSet->Put( SvxCharHiddenItem( StateToAttr( eState ), nWhich ) );
2382 bModified = true;
2384 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2385 rSet->InvalidateItem(nWhich);
2387 bModified |= FillItemSetColor_Impl( *rSet );
2389 return bModified;
2392 void SvxCharEffectsPage::DisableControls( sal_uInt16 nDisable )
2394 if ( ( DISABLE_CASEMAP & nDisable ) == DISABLE_CASEMAP )
2396 m_xEffectsFT->set_sensitive(false);
2397 m_xEffectsLB->set_sensitive(false);
2400 if ( ( DISABLE_WORDLINE & nDisable ) == DISABLE_WORDLINE )
2401 m_xIndividualWordsBtn->set_sensitive(false);
2403 if ( ( DISABLE_BLINK & nDisable ) == DISABLE_BLINK )
2404 m_xBlinkingBtn->set_sensitive(false);
2406 if ( ( DISABLE_UNDERLINE_COLOR & nDisable ) == DISABLE_UNDERLINE_COLOR )
2408 // disable the controls
2409 m_xUnderlineColorFT->set_sensitive(false);
2410 m_xUnderlineColorLB->set_sensitive(false);
2411 m_bUnderlineColorDisabled = true;
2415 void SvxCharEffectsPage::PageCreated(const SfxAllItemSet& aSet)
2417 const SfxUInt16Item* pDisableCtlItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false);
2418 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
2419 if (pDisableCtlItem)
2420 DisableControls(pDisableCtlItem->GetValue());
2422 if (pFlagItem)
2424 sal_uInt32 nFlags=pFlagItem->GetValue();
2425 if ( ( nFlags & SVX_ENABLE_FLASH ) == SVX_ENABLE_FLASH )
2426 m_xBlinkingBtn->show();
2427 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
2428 // the writer uses SID_ATTR_BRUSH as font background
2429 m_bPreviewBackgroundToCharacter = true;
2433 // class SvxCharPositionPage ---------------------------------------------
2435 SvxCharPositionPage::SvxCharPositionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
2436 : SvxCharBasePage(pPage, pController, "cui/ui/positionpage.ui", "PositionPage", rInSet)
2437 , m_nSuperEsc(short(DFLT_ESC_SUPER))
2438 , m_nSubEsc(short(DFLT_ESC_SUB))
2439 , m_nScaleWidthItemSetVal(100)
2440 , m_nScaleWidthInitialVal(100)
2441 , m_nSuperProp(sal_uInt8(DFLT_ESC_PROP))
2442 , m_nSubProp(sal_uInt8(DFLT_ESC_PROP))
2443 , m_xHighPosBtn(m_xBuilder->weld_radio_button("superscript"))
2444 , m_xNormalPosBtn(m_xBuilder->weld_radio_button("normal"))
2445 , m_xLowPosBtn(m_xBuilder->weld_radio_button("subscript"))
2446 , m_xHighLowFT(m_xBuilder->weld_label("raiselower"))
2447 , m_xHighLowMF(m_xBuilder->weld_metric_spin_button("raiselowersb", FieldUnit::PERCENT))
2448 , m_xHighLowRB(m_xBuilder->weld_check_button("automatic"))
2449 , m_xFontSizeFT(m_xBuilder->weld_label("relativefontsize"))
2450 , m_xFontSizeMF(m_xBuilder->weld_metric_spin_button("fontsizesb", FieldUnit::PERCENT))
2451 , m_xRotationContainer(m_xBuilder->weld_widget("rotationcontainer"))
2452 , m_xScalingFT(m_xBuilder->weld_label("scale"))
2453 , m_xScalingAndRotationFT(m_xBuilder->weld_label("rotateandscale"))
2454 , m_x0degRB(m_xBuilder->weld_radio_button("0deg"))
2455 , m_x90degRB(m_xBuilder->weld_radio_button("90deg"))
2456 , m_x270degRB(m_xBuilder->weld_radio_button("270deg"))
2457 , m_xFitToLineCB(m_xBuilder->weld_check_button("fittoline"))
2458 , m_xScaleWidthMF(m_xBuilder->weld_metric_spin_button("scalewidthsb", FieldUnit::PERCENT))
2459 , m_xKerningMF(m_xBuilder->weld_metric_spin_button("kerningsb", FieldUnit::POINT))
2460 , m_xPairKerningBtn(m_xBuilder->weld_check_button("pairkerning"))
2462 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
2463 #ifdef IOS
2464 m_xPreviewWin->hide();
2465 #endif
2466 Initialize();
2469 SvxCharPositionPage::~SvxCharPositionPage()
2474 void SvxCharPositionPage::Initialize()
2476 // to handle the changes of the other pages
2477 SetExchangeSupport();
2479 GetPreviewFont().SetFontSize( Size( 0, 240 ) );
2480 GetPreviewCJKFont().SetFontSize( Size( 0, 240 ) );
2481 GetPreviewCTLFont().SetFontSize( Size( 0, 240 ) );
2483 m_xNormalPosBtn->set_active(true);
2484 PositionHdl_Impl(*m_xNormalPosBtn);
2486 Link<weld::ToggleButton&,void> aLink2 = LINK(this, SvxCharPositionPage, PositionHdl_Impl);
2487 m_xHighPosBtn->connect_toggled(aLink2);
2488 m_xNormalPosBtn->connect_toggled(aLink2);
2489 m_xLowPosBtn->connect_toggled(aLink2);
2491 aLink2 = LINK( this, SvxCharPositionPage, RotationHdl_Impl );
2492 m_x0degRB->connect_toggled(aLink2);
2493 m_x90degRB->connect_toggled(aLink2);
2494 m_x270degRB->connect_toggled(aLink2);
2496 Link<weld::MetricSpinButton&,void> aLink3 = LINK(this, SvxCharPositionPage, ValueChangedHdl_Impl);
2497 m_xHighLowMF->connect_value_changed(aLink3);
2498 m_xFontSizeMF->connect_value_changed(aLink3);
2500 m_xHighLowRB->connect_toggled(LINK(this, SvxCharPositionPage, AutoPositionHdl_Impl));
2501 m_xFitToLineCB->connect_toggled(LINK(this, SvxCharPositionPage, FitToLineHdl_Impl));
2502 m_xKerningMF->connect_value_changed(LINK(this, SvxCharPositionPage, KerningModifyHdl_Impl));
2503 m_xScaleWidthMF->connect_value_changed(LINK(this, SvxCharPositionPage, ScaleWidthModifyHdl_Impl));
2506 void SvxCharPositionPage::UpdatePreview_Impl( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
2508 SetPrevFontEscapement( nProp, nEscProp, nEsc );
2512 void SvxCharPositionPage::SetEscapement_Impl( SvxEscapement nEsc )
2514 SvxEscapementItem aEscItm( nEsc, SID_ATTR_CHAR_ESCAPEMENT );
2516 if ( SvxEscapement::Superscript == nEsc )
2518 aEscItm.GetEsc() = m_nSuperEsc;
2519 aEscItm.GetProportionalHeight() = m_nSuperProp;
2521 else if ( SvxEscapement::Subscript == nEsc )
2523 aEscItm.GetEsc() = m_nSubEsc;
2524 aEscItm.GetProportionalHeight() = m_nSubProp;
2527 short nFac = aEscItm.GetEsc() < 0 ? -1 : 1;
2529 m_xHighLowMF->set_value(aEscItm.GetEsc() * nFac, FieldUnit::PERCENT);
2530 m_xFontSizeMF->set_value(aEscItm.GetProportionalHeight(), FieldUnit::PERCENT);
2532 if ( SvxEscapement::Off == nEsc )
2534 m_xHighLowFT->set_sensitive(false);
2535 m_xHighLowMF->set_sensitive(false);
2536 m_xFontSizeFT->set_sensitive(false);
2537 m_xFontSizeMF->set_sensitive(false);
2538 m_xHighLowRB->set_sensitive(false);
2540 else
2542 m_xFontSizeFT->set_sensitive(true);
2543 m_xFontSizeMF->set_sensitive(true);
2544 m_xHighLowRB->set_sensitive(true);
2546 if (!m_xHighLowRB->get_active())
2548 m_xHighLowFT->set_sensitive(true);
2549 m_xHighLowMF->set_sensitive(true);
2551 else
2552 AutoPositionHdl_Impl(*m_xHighLowRB);
2555 UpdatePreview_Impl( 100, aEscItm.GetProportionalHeight(), aEscItm.GetEsc() );
2559 IMPL_LINK_NOARG(SvxCharPositionPage, PositionHdl_Impl, weld::ToggleButton&, void)
2561 SvxEscapement nEsc = SvxEscapement::Off; // also when pBtn == NULL
2563 if (m_xHighPosBtn->get_active())
2564 nEsc = SvxEscapement::Superscript;
2565 else if (m_xLowPosBtn->get_active())
2566 nEsc = SvxEscapement::Subscript;
2568 SetEscapement_Impl( nEsc );
2571 IMPL_LINK_NOARG(SvxCharPositionPage, RotationHdl_Impl, weld::ToggleButton&, void)
2573 bool bEnable = false;
2574 if (m_x90degRB->get_active() || m_x270degRB->get_active())
2575 bEnable = true;
2576 else
2577 OSL_ENSURE(m_x0degRB->get_active(), "unexpected button");
2578 m_xFitToLineCB->set_sensitive(bEnable);
2581 void SvxCharPositionPage::FontModifyHdl_Impl()
2583 sal_uInt8 nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
2584 short nEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT));
2585 nEsc *= m_xLowPosBtn->get_active() ? -1 : 1;
2586 UpdatePreview_Impl( 100, nEscProp, nEsc );
2589 IMPL_LINK(SvxCharPositionPage, AutoPositionHdl_Impl, weld::ToggleButton&, rBox, void)
2591 if (rBox.get_active())
2593 m_xHighLowFT->set_sensitive(false);
2594 m_xHighLowMF->set_sensitive(false);
2596 else
2597 PositionHdl_Impl(m_xHighPosBtn->get_active() ? *m_xHighPosBtn
2598 : m_xLowPosBtn->get_active() ? *m_xLowPosBtn
2599 : *m_xNormalPosBtn);
2602 IMPL_LINK_NOARG(SvxCharPositionPage, FitToLineHdl_Impl, weld::ToggleButton&, void)
2604 sal_uInt16 nVal = m_nScaleWidthInitialVal;
2605 if (m_xFitToLineCB->get_active())
2606 nVal = m_nScaleWidthItemSetVal;
2607 m_xScaleWidthMF->set_value(nVal, FieldUnit::PERCENT);
2608 m_aPreviewWin.SetFontWidthScale( nVal );
2611 IMPL_LINK_NOARG(SvxCharPositionPage, KerningModifyHdl_Impl, weld::MetricSpinButton&, void)
2613 long nVal = static_cast<long>(m_xKerningMF->get_value(FieldUnit::POINT));
2614 nVal = OutputDevice::LogicToLogic( nVal, MapUnit::MapPoint, MapUnit::MapTwip );
2615 long nKern = static_cast<short>(m_xKerningMF->denormalize(nVal));
2617 SvxFont& rFont = GetPreviewFont();
2618 SvxFont& rCJKFont = GetPreviewCJKFont();
2619 SvxFont& rCTLFont = GetPreviewCTLFont();
2621 rFont.SetFixKerning( static_cast<short>(nKern) );
2622 rCJKFont.SetFixKerning( static_cast<short>(nKern) );
2623 rCTLFont.SetFixKerning( static_cast<short>(nKern) );
2624 m_aPreviewWin.Invalidate();
2627 IMPL_LINK(SvxCharPositionPage, ValueChangedHdl_Impl, weld::MetricSpinButton&, rField, void)
2629 bool bHigh = m_xHighPosBtn->get_active();
2630 bool bLow = m_xLowPosBtn->get_active();
2631 DBG_ASSERT( bHigh || bLow, "normal position is not valid" );
2633 if (m_xHighLowMF.get() == &rField)
2635 if ( bLow )
2636 m_nSubEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT)) * -1;
2637 else
2638 m_nSuperEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT));
2640 else if (m_xFontSizeMF.get() == &rField)
2642 if ( bLow )
2643 m_nSubProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
2644 else
2645 m_nSuperProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
2648 FontModifyHdl_Impl();
2651 IMPL_LINK_NOARG(SvxCharPositionPage, ScaleWidthModifyHdl_Impl, weld::MetricSpinButton&, void)
2653 m_aPreviewWin.SetFontWidthScale(sal_uInt16(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)));
2656 DeactivateRC SvxCharPositionPage::DeactivatePage( SfxItemSet* _pSet )
2658 if ( _pSet )
2659 FillItemSet( _pSet );
2660 return DeactivateRC::LeavePage;
2663 std::unique_ptr<SfxTabPage> SvxCharPositionPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
2665 return std::make_unique<SvxCharPositionPage>(pPage, pController, *rSet);
2668 void SvxCharPositionPage::Reset( const SfxItemSet* rSet )
2670 OUString sUser = GetUserData();
2672 if ( !sUser.isEmpty() )
2674 sal_Int32 nIdx {0};
2675 m_nSuperEsc = static_cast<short>(sUser.getToken( 0, ';', nIdx ).toInt32());
2676 m_nSubEsc = static_cast<short>(sUser.getToken( 0, ';', nIdx ).toInt32());
2677 m_nSuperProp = static_cast<sal_uInt8>(sUser.getToken( 0, ';', nIdx ).toInt32());
2678 m_nSubProp = static_cast<sal_uInt8>(sUser.getToken( 0, ';', nIdx ).toInt32());
2680 // tdf#120412 up to 14400% (eg. 1584 pt with 11 pt letters)
2681 m_xHighLowMF->set_max(MAX_ESC_POS, FieldUnit::PERCENT);
2683 //fdo#75307 validate all the entries and discard all of them if any are
2684 //out of range
2685 bool bValid = true;
2686 if (m_nSuperEsc < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSuperEsc > m_xHighLowMF->get_max(FieldUnit::PERCENT))
2687 bValid = false;
2688 if (m_nSubEsc*-1 < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSubEsc*-1 > m_xHighLowMF->get_max(FieldUnit::PERCENT))
2689 bValid = false;
2690 if (m_nSuperProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSuperProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT))
2691 bValid = false;
2692 if (m_nSubProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSubProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT))
2693 bValid = false;
2695 if (!bValid)
2697 m_nSuperEsc = DFLT_ESC_SUPER;
2698 m_nSubEsc = DFLT_ESC_SUB;
2699 m_nSuperProp = DFLT_ESC_PROP;
2700 m_nSubProp = DFLT_ESC_PROP;
2704 short nEsc = 0;
2705 sal_uInt8 nEscProp = 100;
2707 m_xHighLowFT->set_sensitive(false);
2708 m_xHighLowMF->set_sensitive(false);
2709 m_xFontSizeFT->set_sensitive(false);
2710 m_xFontSizeMF->set_sensitive(false);
2712 SvxFont& rFont = GetPreviewFont();
2713 SvxFont& rCJKFont = GetPreviewCJKFont();
2714 SvxFont& rCTLFont = GetPreviewCTLFont();
2715 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT );
2717 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2719 const SvxEscapementItem& rItem = static_cast<const SvxEscapementItem&>(rSet->Get( nWhich ));
2720 nEsc = rItem.GetEsc();
2721 nEscProp = rItem.GetProportionalHeight();
2723 if ( nEsc != 0 )
2725 m_xHighLowFT->set_sensitive(true);
2726 m_xHighLowMF->set_sensitive(true);
2727 m_xFontSizeFT->set_sensitive(true);
2728 m_xFontSizeMF->set_sensitive(true);
2730 short nFac;
2731 bool bAutomatic(false);
2733 if ( nEsc > 0 )
2735 nFac = 1;
2736 m_xHighPosBtn->set_active(true);
2737 if ( nEsc == DFLT_ESC_AUTO_SUPER )
2739 nEsc = DFLT_ESC_SUPER;
2740 bAutomatic = true;
2743 else
2745 nFac = -1;
2746 m_xLowPosBtn->set_active(true);
2747 if ( nEsc == DFLT_ESC_AUTO_SUB )
2749 nEsc = DFLT_ESC_SUB;
2750 bAutomatic = true;
2753 if (!m_xHighLowRB->get_sensitive())
2755 m_xHighLowRB->set_sensitive(true);
2757 m_xHighLowRB->set_active(bAutomatic);
2759 if (m_xHighLowRB->get_active())
2761 m_xHighLowFT->set_sensitive(false);
2762 m_xHighLowMF->set_sensitive(false);
2764 m_xHighLowMF->set_value(m_xHighLowMF->normalize(nFac * nEsc), FieldUnit::PERCENT);
2766 else
2768 m_xNormalPosBtn->set_active(true);
2769 m_xHighLowRB->set_active(true);
2770 PositionHdl_Impl(*m_xNormalPosBtn);
2772 //the height has to be set after the handler is called to keep the value also if the escapement is zero
2773 m_xFontSizeMF->set_value(m_xFontSizeMF->normalize(nEscProp), FieldUnit::PERCENT);
2775 else
2777 m_xHighPosBtn->set_active(false);
2778 m_xNormalPosBtn->set_active(false);
2779 m_xLowPosBtn->set_active(false);
2782 // set BspFont
2783 SetPrevFontEscapement( 100, nEscProp, nEsc );
2785 // Kerning
2786 nWhich = GetWhich( SID_ATTR_CHAR_KERNING );
2788 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2790 const SvxKerningItem& rItem = static_cast<const SvxKerningItem&>(rSet->Get( nWhich ));
2791 MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich );
2792 long nBig = static_cast<long>(m_xKerningMF->normalize( static_cast<long>(rItem.GetValue()) ));
2793 long nKerning = OutputDevice::LogicToLogic(nBig, eUnit, MapUnit::MapPoint);
2795 // set Kerning at the Font, convert into Twips before
2796 long nKern = OutputDevice::LogicToLogic(rItem.GetValue(), eUnit, MapUnit::MapTwip);
2797 rFont.SetFixKerning( static_cast<short>(nKern) );
2798 rCJKFont.SetFixKerning( static_cast<short>(nKern) );
2799 rCTLFont.SetFixKerning( static_cast<short>(nKern) );
2801 //the attribute value must be displayed also if it's above the maximum allowed value
2802 long nVal = static_cast<long>(m_xKerningMF->get_max(FieldUnit::POINT));
2803 if(nVal < nKerning)
2804 m_xKerningMF->set_max(nKerning, FieldUnit::POINT);
2805 m_xKerningMF->set_value(nKerning, FieldUnit::POINT);
2807 else
2808 m_xKerningMF->set_text(OUString());
2810 // Pair kerning
2811 nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN );
2813 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2815 const SvxAutoKernItem& rItem = static_cast<const SvxAutoKernItem&>(rSet->Get( nWhich ));
2816 m_xPairKerningBtn->set_active(rItem.GetValue());
2818 else
2819 m_xPairKerningBtn->set_active(false);
2821 // Scale Width
2822 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
2823 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2825 const SvxCharScaleWidthItem& rItem = static_cast<const SvxCharScaleWidthItem&>( rSet->Get( nWhich ) );
2826 m_nScaleWidthInitialVal = rItem.GetValue();
2827 m_xScaleWidthMF->set_value(m_nScaleWidthInitialVal, FieldUnit::PERCENT);
2829 else
2830 m_xScaleWidthMF->set_value(100, FieldUnit::PERCENT);
2832 nWhich = GetWhich( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE );
2833 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2834 m_nScaleWidthItemSetVal = static_cast<const SfxUInt16Item&>( rSet->Get( nWhich )).GetValue();
2836 // Rotation
2837 nWhich = GetWhich( SID_ATTR_CHAR_ROTATED );
2838 SfxItemState eState = rSet->GetItemState( nWhich );
2839 if( SfxItemState::UNKNOWN == eState )
2841 m_xRotationContainer->hide();
2842 m_xScalingAndRotationFT->hide();
2843 m_xScalingFT->show();
2845 else
2847 m_xRotationContainer->show();
2848 m_xScalingAndRotationFT->show();
2849 m_xScalingFT->hide();
2851 if( eState >= SfxItemState::DEFAULT )
2853 const SvxCharRotateItem& rItem =
2854 static_cast<const SvxCharRotateItem&>( rSet->Get( nWhich ));
2855 if (rItem.IsBottomToTop())
2856 m_x90degRB->set_active(true);
2857 else if (rItem.IsTopToBottom())
2858 m_x270degRB->set_active(true);
2859 else
2861 DBG_ASSERT( 0 == rItem.GetValue(), "incorrect value" );
2862 m_x0degRB->set_active(true);
2864 m_xFitToLineCB->set_active(rItem.IsFitToLine());
2866 else
2868 if( eState == SfxItemState::DONTCARE )
2870 m_x0degRB->set_active(false);
2871 m_x90degRB->set_active(false);
2872 m_x270degRB->set_active(false);
2874 else
2875 m_x0degRB->set_active(true);
2877 m_xFitToLineCB->set_active(false);
2879 m_xFitToLineCB->set_sensitive(!m_x0degRB->get_active());
2881 // is this value set?
2882 if( SfxItemState::UNKNOWN == rSet->GetItemState( GetWhich(
2883 SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ) ))
2884 m_xFitToLineCB->hide();
2886 ChangesApplied();
2889 void SvxCharPositionPage::ChangesApplied()
2891 m_xHighPosBtn->save_state();
2892 m_xNormalPosBtn->save_state();
2893 m_xLowPosBtn->save_state();
2894 m_xHighLowRB->save_state();
2895 m_x0degRB->save_state();
2896 m_x90degRB->save_state();
2897 m_x270degRB->save_state();
2898 m_xFitToLineCB->save_state();
2899 m_xScaleWidthMF->save_value();
2900 m_xKerningMF->save_value();
2901 m_xPairKerningBtn->save_state();
2904 bool SvxCharPositionPage::FillItemSet( SfxItemSet* rSet )
2906 // Position (high, normal or low)
2907 const SfxItemSet& rOldSet = GetItemSet();
2908 bool bModified = false, bChanged = true;
2909 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT );
2910 const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_ESCAPEMENT );
2911 const bool bHigh = m_xHighPosBtn->get_active();
2912 short nEsc;
2913 sal_uInt8 nEscProp;
2915 if (bHigh || m_xLowPosBtn->get_active())
2917 if (m_xHighLowRB->get_active())
2918 nEsc = bHigh ? DFLT_ESC_AUTO_SUPER : DFLT_ESC_AUTO_SUB;
2919 else
2921 nEsc = static_cast<short>(m_xHighLowMF->denormalize(m_xHighLowMF->get_value(FieldUnit::PERCENT)));
2922 nEsc *= (bHigh ? 1 : -1);
2924 nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->denormalize(m_xFontSizeMF->get_value(FieldUnit::PERCENT)));
2926 else
2928 nEsc = 0;
2929 nEscProp = 100;
2932 if ( pOld )
2934 const SvxEscapementItem& rItem = *static_cast<const SvxEscapementItem*>(pOld);
2935 if (rItem.GetEsc() == nEsc && rItem.GetProportionalHeight() == nEscProp)
2936 bChanged = false;
2939 if ( !bChanged && !m_xHighPosBtn->get_saved_state() &&
2940 !m_xNormalPosBtn->get_saved_state() && !m_xLowPosBtn->get_saved_state() )
2941 bChanged = true;
2943 if ( bChanged &&
2944 ( m_xHighPosBtn->get_active() || m_xNormalPosBtn->get_active() || m_xLowPosBtn->get_active() ) )
2946 rSet->Put( SvxEscapementItem( nEsc, nEscProp, nWhich ) );
2947 bModified = true;
2949 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2950 rSet->InvalidateItem(nWhich);
2952 bChanged = true;
2954 // Kerning
2955 nWhich = GetWhich( SID_ATTR_CHAR_KERNING );
2956 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_KERNING );
2957 short nKerning = 0;
2958 MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich );
2960 long nTmp = static_cast<long>(m_xKerningMF->get_value(FieldUnit::POINT));
2961 long nVal = OutputDevice::LogicToLogic(nTmp, MapUnit::MapPoint, eUnit);
2962 nKerning = static_cast<short>(m_xKerningMF->denormalize( nVal ));
2964 SfxItemState eOldKernState = rOldSet.GetItemState( nWhich, false );
2965 if ( pOld )
2967 const SvxKerningItem& rItem = *static_cast<const SvxKerningItem*>(pOld);
2968 if ( (eOldKernState >= SfxItemState::DEFAULT || m_xKerningMF->get_text().isEmpty()) && rItem.GetValue() == nKerning )
2969 bChanged = false;
2972 if ( bChanged )
2974 rSet->Put( SvxKerningItem( nKerning, nWhich ) );
2975 bModified = true;
2977 else if ( SfxItemState::DEFAULT == eOldKernState )
2978 rSet->InvalidateItem(nWhich);
2980 // Pair-Kerning
2981 nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN );
2983 if (m_xPairKerningBtn->get_state_changed_from_saved())
2985 rSet->Put( SvxAutoKernItem( m_xPairKerningBtn->get_active(), nWhich ) );
2986 bModified = true;
2988 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2989 rSet->InvalidateItem(nWhich);
2991 // Scale Width
2992 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
2993 if (m_xScaleWidthMF->get_value_changed_from_saved())
2995 rSet->Put(SvxCharScaleWidthItem(static_cast<sal_uInt16>(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)), nWhich));
2996 bModified = true;
2998 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2999 rSet->InvalidateItem(nWhich);
3001 // Rotation
3002 nWhich = GetWhich( SID_ATTR_CHAR_ROTATED );
3003 if ( m_x0degRB->get_state_changed_from_saved() ||
3004 m_x90degRB->get_state_changed_from_saved() ||
3005 m_x270degRB->get_state_changed_from_saved() ||
3006 m_xFitToLineCB->get_state_changed_from_saved() )
3008 SvxCharRotateItem aItem( 0, m_xFitToLineCB->get_active(), nWhich );
3009 if (m_x90degRB->get_active())
3010 aItem.SetBottomToTop();
3011 else if (m_x270degRB->get_active())
3012 aItem.SetTopToBottom();
3013 rSet->Put( aItem );
3014 bModified = true;
3016 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
3017 rSet->InvalidateItem(nWhich);
3019 return bModified;
3023 void SvxCharPositionPage::FillUserData()
3025 const OUString cTok( ";" );
3027 OUString sUser = OUString::number( m_nSuperEsc ) + cTok +
3028 OUString::number( m_nSubEsc ) + cTok +
3029 OUString::number( m_nSuperProp ) + cTok +
3030 OUString::number( m_nSubProp );
3031 SetUserData( sUser );
3035 void SvxCharPositionPage::PageCreated(const SfxAllItemSet& aSet)
3037 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
3038 if (pFlagItem)
3040 sal_uInt32 nFlags=pFlagItem->GetValue();
3041 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
3042 // the writer uses SID_ATTR_BRUSH as font background
3043 m_bPreviewBackgroundToCharacter = true;
3046 // class SvxCharTwoLinesPage ------------------------------------------------
3048 SvxCharTwoLinesPage::SvxCharTwoLinesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
3049 : SvxCharBasePage(pPage, pController, "cui/ui/twolinespage.ui", "TwoLinesPage", rInSet)
3050 , m_nStartBracketPosition( 0 )
3051 , m_nEndBracketPosition( 0 )
3052 , m_xTwoLinesBtn(m_xBuilder->weld_check_button("twolines"))
3053 , m_xEnclosingFrame(m_xBuilder->weld_widget("enclosing"))
3054 , m_xStartBracketLB(m_xBuilder->weld_tree_view("startbracket"))
3055 , m_xEndBracketLB(m_xBuilder->weld_tree_view("endbracket"))
3057 for (size_t i = 0; i < SAL_N_ELEMENTS(TWOLINE_OPEN); ++i)
3058 m_xStartBracketLB->append(OUString::number(TWOLINE_OPEN[i].second), CuiResId(TWOLINE_OPEN[i].first));
3059 for (size_t i = 0; i < SAL_N_ELEMENTS(TWOLINE_CLOSE); ++i)
3060 m_xEndBracketLB->append(OUString::number(TWOLINE_CLOSE[i].second), CuiResId(TWOLINE_CLOSE[i].first));
3062 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
3063 #ifdef IOS
3064 m_xPreviewWin->hide();
3065 #endif
3066 Initialize();
3069 SvxCharTwoLinesPage::~SvxCharTwoLinesPage()
3073 void SvxCharTwoLinesPage::Initialize()
3075 m_xTwoLinesBtn->set_active(false);
3076 TwoLinesHdl_Impl(*m_xTwoLinesBtn);
3078 m_xTwoLinesBtn->connect_toggled(LINK(this, SvxCharTwoLinesPage, TwoLinesHdl_Impl));
3080 Link<weld::TreeView&,void> aLink = LINK(this, SvxCharTwoLinesPage, CharacterMapHdl_Impl);
3081 m_xStartBracketLB->connect_changed(aLink);
3082 m_xEndBracketLB->connect_changed(aLink);
3084 SvxFont& rFont = GetPreviewFont();
3085 SvxFont& rCJKFont = GetPreviewCJKFont();
3086 SvxFont& rCTLFont = GetPreviewCTLFont();
3087 rFont.SetFontSize( Size( 0, 220 ) );
3088 rCJKFont.SetFontSize( Size( 0, 220 ) );
3089 rCTLFont.SetFontSize( Size( 0, 220 ) );
3092 void SvxCharTwoLinesPage::SelectCharacter(weld::TreeView* pBox)
3094 bool bStart = pBox == m_xStartBracketLB.get();
3095 SvxCharacterMap aDlg(GetFrameWeld(), nullptr, nullptr);
3096 aDlg.DisableFontSelection();
3098 if (aDlg.run() == RET_OK)
3100 sal_Unicode cChar = static_cast<sal_Unicode>(aDlg.GetChar());
3101 SetBracket( cChar, bStart );
3103 else
3105 pBox->select(bStart ? m_nStartBracketPosition : m_nEndBracketPosition);
3110 void SvxCharTwoLinesPage::SetBracket( sal_Unicode cBracket, bool bStart )
3112 int nEntryPos = 0;
3113 weld::TreeView* pBox = bStart ? m_xStartBracketLB.get() : m_xEndBracketLB.get();
3114 if (cBracket == 0)
3115 pBox->select(0);
3116 else
3118 bool bFound = false;
3119 for (int i = 1; i < pBox->n_children(); ++i)
3121 if (pBox->get_id(i).toInt32() != CHRDLG_ENCLOSE_SPECIAL_CHAR)
3123 const sal_Unicode cChar = pBox->get_text(i)[0];
3124 if (cChar == cBracket)
3126 pBox->select(i);
3127 nEntryPos = i;
3128 bFound = true;
3129 break;
3134 if (!bFound)
3136 pBox->append_text(OUString(cBracket));
3137 nEntryPos = pBox->n_children() - 1;
3138 pBox->select(nEntryPos);
3141 if (bStart)
3142 m_nStartBracketPosition = nEntryPos;
3143 else
3144 m_nEndBracketPosition = nEntryPos;
3147 IMPL_LINK_NOARG(SvxCharTwoLinesPage, TwoLinesHdl_Impl, weld::ToggleButton&, void)
3149 bool bChecked = m_xTwoLinesBtn->get_active();
3150 m_xEnclosingFrame->set_sensitive(bChecked);
3151 UpdatePreview_Impl();
3154 IMPL_LINK(SvxCharTwoLinesPage, CharacterMapHdl_Impl, weld::TreeView&, rBox, void)
3156 int nPos = rBox.get_selected_index();
3157 if (rBox.get_id(nPos).toInt32() == CHRDLG_ENCLOSE_SPECIAL_CHAR)
3158 SelectCharacter( &rBox );
3159 else
3161 bool bStart = &rBox == m_xStartBracketLB.get();
3162 if (bStart)
3163 m_nStartBracketPosition = nPos;
3164 else
3165 m_nEndBracketPosition = nPos;
3167 UpdatePreview_Impl();
3170 void SvxCharTwoLinesPage::ActivatePage( const SfxItemSet& rSet )
3172 SvxCharBasePage::ActivatePage(rSet);
3175 DeactivateRC SvxCharTwoLinesPage::DeactivatePage( SfxItemSet* _pSet )
3177 if ( _pSet )
3178 FillItemSet( _pSet );
3179 return DeactivateRC::LeavePage;
3182 std::unique_ptr<SfxTabPage> SvxCharTwoLinesPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
3184 return std::make_unique<SvxCharTwoLinesPage>(pPage, pController, *rSet);
3187 void SvxCharTwoLinesPage::Reset( const SfxItemSet* rSet )
3189 m_xTwoLinesBtn->set_active(false);
3190 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES );
3191 SfxItemState eState = rSet->GetItemState( nWhich );
3193 if ( eState >= SfxItemState::DONTCARE )
3195 const SvxTwoLinesItem& rItem = static_cast<const SvxTwoLinesItem&>(rSet->Get( nWhich ));
3196 m_xTwoLinesBtn->set_active(rItem.GetValue());
3198 if ( rItem.GetValue() )
3200 SetBracket( rItem.GetStartBracket(), true );
3201 SetBracket( rItem.GetEndBracket(), false );
3204 TwoLinesHdl_Impl(*m_xTwoLinesBtn);
3206 SetPrevFontWidthScale( *rSet );
3209 bool SvxCharTwoLinesPage::FillItemSet( SfxItemSet* rSet )
3211 const SfxItemSet& rOldSet = GetItemSet();
3212 bool bModified = false, bChanged = true;
3213 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES );
3214 const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_TWO_LINES );
3215 bool bOn = m_xTwoLinesBtn->get_active();
3216 sal_Unicode cStart = ( bOn && m_xStartBracketLB->get_selected_index() > 0 )
3217 ? m_xStartBracketLB->get_selected_text()[0] : 0;
3218 sal_Unicode cEnd = ( bOn && m_xEndBracketLB->get_selected_index() > 0 )
3219 ? m_xEndBracketLB->get_selected_text()[0] : 0;
3221 if ( pOld )
3223 const SvxTwoLinesItem& rItem = *static_cast<const SvxTwoLinesItem*>(pOld);
3224 if ( rItem.GetValue() == bOn &&
3225 ( !bOn || ( rItem.GetStartBracket() == cStart && rItem.GetEndBracket() == cEnd ) ) )
3226 bChanged = false;
3229 if ( bChanged )
3231 rSet->Put( SvxTwoLinesItem( bOn, cStart, cEnd, nWhich ) );
3232 bModified = true;
3234 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
3235 rSet->InvalidateItem(nWhich);
3237 return bModified;
3240 void SvxCharTwoLinesPage::UpdatePreview_Impl()
3242 sal_Unicode cStart = m_xStartBracketLB->get_selected_index() > 0
3243 ? m_xStartBracketLB->get_selected_text()[0] : 0;
3244 sal_Unicode cEnd = m_xEndBracketLB->get_selected_index() > 0
3245 ? m_xEndBracketLB->get_selected_text()[0] : 0;
3246 m_aPreviewWin.SetBrackets(cStart, cEnd);
3247 m_aPreviewWin.SetTwoLines(m_xTwoLinesBtn->get_active());
3248 m_aPreviewWin.Invalidate();
3251 void SvxCharTwoLinesPage::PageCreated(const SfxAllItemSet& aSet)
3253 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
3254 if (pFlagItem)
3256 sal_uInt32 nFlags=pFlagItem->GetValue();
3257 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
3258 // the writer uses SID_ATTR_BRUSH as font background
3259 m_bPreviewBackgroundToCharacter = true;
3263 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */