android: Update app-specific/MIME type icons
[LibreOffice.git] / cui / source / tabpages / chardlg.cxx
blob7679df2bf3613da36f1a2a8fd6cb4f60151e7d00
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/cjkoptions.hxx>
27 #include <svl/ctloptions.hxx>
28 #include <chardlg.hxx>
29 #include <editeng/fontitem.hxx>
30 #include <editeng/postitem.hxx>
31 #include <editeng/udlnitem.hxx>
32 #include <editeng/crossedoutitem.hxx>
33 #include <editeng/contouritem.hxx>
34 #include <editeng/langitem.hxx>
35 #include <editeng/wghtitem.hxx>
36 #include <editeng/fhgtitem.hxx>
37 #include <editeng/shdditem.hxx>
38 #include <editeng/escapementitem.hxx>
39 #include <editeng/wrlmitem.hxx>
40 #include <editeng/cmapitem.hxx>
41 #include <editeng/kernitem.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 <FontFeatures.hxx>
61 #include <FontFeaturesDialog.hxx>
62 #include <sal/log.hxx>
63 #include <osl/diagnose.h>
64 #include <o3tl/unit_conversion.hxx>
65 #include <o3tl/string_view.hxx>
67 using namespace ::com::sun::star;
69 // static ----------------------------------------------------------------
71 const WhichRangesContainer SvxCharNamePage::pNameRanges(svl::Items<
72 SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_WEIGHT,
73 SID_ATTR_CHAR_FONTHEIGHT, SID_ATTR_CHAR_FONTHEIGHT,
74 SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR,
75 SID_ATTR_CHAR_LANGUAGE, SID_ATTR_CHAR_LANGUAGE,
76 SID_ATTR_CHAR_CJK_FONT, SID_ATTR_CHAR_CJK_WEIGHT,
77 SID_ATTR_CHAR_CTL_FONT, SID_ATTR_CHAR_CTL_WEIGHT
78 >);
80 const WhichRangesContainer SvxCharEffectsPage::pEffectsRanges(svl::Items<
81 SID_ATTR_CHAR_SHADOWED, SID_ATTR_CHAR_UNDERLINE,
82 SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR,
83 SID_ATTR_CHAR_CASEMAP, SID_ATTR_CHAR_CASEMAP,
84 SID_ATTR_FLASH, SID_ATTR_FLASH,
85 SID_ATTR_CHAR_EMPHASISMARK, SID_ATTR_CHAR_EMPHASISMARK,
86 SID_ATTR_CHAR_RELIEF, SID_ATTR_CHAR_RELIEF,
87 SID_ATTR_CHAR_HIDDEN, SID_ATTR_CHAR_HIDDEN,
88 SID_ATTR_CHAR_OVERLINE, SID_ATTR_CHAR_OVERLINE
89 >);
91 const WhichRangesContainer SvxCharPositionPage::pPositionRanges(svl::Items<
92 SID_ATTR_CHAR_KERNING, SID_ATTR_CHAR_KERNING,
93 SID_ATTR_CHAR_ESCAPEMENT, SID_ATTR_CHAR_ESCAPEMENT,
94 SID_ATTR_CHAR_AUTOKERN, SID_ATTR_CHAR_AUTOKERN,
95 SID_ATTR_CHAR_ROTATED, SID_ATTR_CHAR_SCALEWIDTH,
96 SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, SID_ATTR_CHAR_WIDTH_FIT_TO_LINE
97 >);
99 const WhichRangesContainer SvxCharTwoLinesPage::pTwoLinesRanges(svl::Items<
100 SID_ATTR_CHAR_TWO_LINES, SID_ATTR_CHAR_TWO_LINES
103 // C-Function ------------------------------------------------------------
105 static bool StateToAttr( TriState aState )
107 return ( TRISTATE_TRUE == aState );
110 namespace
112 void setPrevFontEscapement(SvxFont& _rFont,sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
114 _rFont.SetPropr( nProp );
115 _rFont.SetProprRel( nEscProp );
116 _rFont.SetEscapement( nEsc );
120 inline SvxFont& SvxCharBasePage::GetPreviewFont()
122 return m_aPreviewWin.GetFont();
125 inline SvxFont& SvxCharBasePage::GetPreviewCJKFont()
127 return m_aPreviewWin.GetCJKFont();
130 inline SvxFont& SvxCharBasePage::GetPreviewCTLFont()
132 return m_aPreviewWin.GetCTLFont();
135 SvxCharBasePage::SvxCharBasePage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OUString& rID, const SfxItemSet& rItemset)
136 : SfxTabPage(pPage, pController, rUIXMLDescription, rID, &rItemset)
137 , m_bPreviewBackgroundToCharacter( false )
141 SvxCharBasePage::~SvxCharBasePage()
145 void SvxCharBasePage::ActivatePage(const SfxItemSet& rSet)
147 m_aPreviewWin.SetFromItemSet(rSet, m_bPreviewBackgroundToCharacter);
150 void SvxCharBasePage::SetPrevFontWidthScale( const SfxItemSet& rSet )
152 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
153 if (rSet.GetItemState(nWhich)>=SfxItemState::DEFAULT)
155 const SvxCharScaleWidthItem &rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
156 m_aPreviewWin.SetFontWidthScale(rItem.GetValue());
160 void SvxCharBasePage::SetPrevFontEscapement( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
162 setPrevFontEscapement(GetPreviewFont(),nProp,nEscProp,nEsc);
163 setPrevFontEscapement(GetPreviewCJKFont(),nProp,nEscProp,nEsc);
164 setPrevFontEscapement(GetPreviewCTLFont(),nProp,nEscProp,nEsc);
165 m_aPreviewWin.Invalidate();
169 // SvxCharNamePage_Impl --------------------------------------------------
171 struct SvxCharNamePage_Impl
173 Idle m_aUpdateIdle { "cui SvxCharNamePage_Impl m_aUpdateIdle" };
174 OUString m_aNoStyleText;
175 std::unique_ptr<FontList> m_pFontList;
176 int m_nExtraEntryPos;
177 bool m_bInSearchMode;
179 SvxCharNamePage_Impl()
180 : m_nExtraEntryPos(std::numeric_limits<int>::max())
181 , m_bInSearchMode(false)
184 m_aUpdateIdle.SetPriority( TaskPriority::LOWEST );
188 // class SvxCharNamePage -------------------------------------------------
190 SvxCharNamePage::SvxCharNamePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
191 : SvxCharBasePage(pPage, pController, "cui/ui/charnamepage.ui", "CharNamePage", rInSet)
192 , m_pImpl(new SvxCharNamePage_Impl)
193 // Western
194 , m_xWestern(m_xBuilder->weld_notebook("nbWestern"))
195 , m_xWestFontNameFT(m_xBuilder->weld_label("lbWestFontname"))
196 , m_xWestFontStyleFT(m_xBuilder->weld_label("lbWestStyle"))
197 , m_xWestFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("cbWestStyle")))
198 , m_xWestFontSizeFT(m_xBuilder->weld_label("lbWestSize"))
199 , m_xWestFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("cbWestSize")))
200 , m_xWestFontLanguageFT(m_xBuilder->weld_label("lbWestLanguage"))
201 , m_xWestFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("cbWestLanguage")))
202 , m_xWestFontFeaturesButton(m_xBuilder->weld_button("btnWestFeatures"))
203 , m_xWestFontTypeFT(m_xBuilder->weld_label("lbWestFontinfo"))
204 , m_xCJK_CTL(m_xBuilder->weld_notebook("nbCJKCTL"))
205 // CJK
206 , m_xEastFontNameFT(m_xBuilder->weld_label("lbCJKFontname"))
207 , m_xEastFontStyleFT(m_xBuilder->weld_label("lbCJKStyle"))
208 , m_xEastFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("cbCJKStyle")))
209 , m_xEastFontSizeFT(m_xBuilder->weld_label("lbCJKSize"))
210 , m_xEastFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("cbCJKSize")))
211 , m_xEastFontLanguageFT(m_xBuilder->weld_label("lbCJKLanguage"))
212 , m_xEastFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("cbCJKLanguage")))
213 , m_xEastFontFeaturesButton(m_xBuilder->weld_button("btnCJKFeatures"))
214 , m_xEastFontTypeFT(m_xBuilder->weld_label("lbCJKFontinfo"))
215 // CTL
216 , m_xCTLFontNameFT(m_xBuilder->weld_label("lbCTLFontname"))
217 // tree
218 , m_xCTLFontStyleFT(m_xBuilder->weld_label("lbCTLStyle"))
219 , m_xCTLFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("cbCTLStyle")))
220 , m_xCTLFontSizeFT(m_xBuilder->weld_label("lbCTLSize"))
221 , m_xCTLFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("cbCTLSize")))
222 , m_xCTLFontLanguageFT(m_xBuilder->weld_label("lbCTLLanguage"))
223 , m_xCTLFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("cbCTLLanguage")))
224 , m_xCTLFontFeaturesButton(m_xBuilder->weld_button("btnCTLFeatures"))
225 , m_xCTLFontTypeFT(m_xBuilder->weld_label("lbCTLFontinfo"))
227 , m_xVDev(*Application::GetDefaultDevice(), DeviceFormat::WITH_ALPHA)
229 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
230 #ifdef IOS
231 m_xPreviewWin->hide();
232 #endif
233 m_pImpl->m_aNoStyleText = CuiResId( RID_CUISTR_CHARNAME_NOSTYLE );
235 std::unique_ptr<weld::EntryTreeView> xWestFontName = m_xBuilder->weld_entry_tree_view("gdWestern", "edWestFontName", "trWestFontName");
236 std::unique_ptr<weld::EntryTreeView> xCJKFontName = m_xBuilder->weld_entry_tree_view("gdCJK", "edCJKFontName", "trCJKFontName");
237 std::unique_ptr<weld::EntryTreeView> xCTLFontName = m_xBuilder->weld_entry_tree_view("gdCTL", "edCTLFontName", "trCTLFontName");
239 // 7 lines in the treeview
240 xWestFontName->set_height_request_by_rows(7);
241 xCJKFontName->set_height_request_by_rows(7);
242 xCTLFontName->set_height_request_by_rows(7);
244 m_xWestFontNameLB = std::move(xWestFontName);
245 m_xEastFontNameLB = std::move(xCJKFontName);
246 m_xCTLFontNameLB = std::move(xCTLFontName);
248 bool bShowCJK = SvtCJKOptions::IsCJKFontEnabled();
249 bool bShowCTL = SvtCTLOptions::IsCTLFontEnabled();
250 bool bShowNonWestern = bShowCJK || bShowCTL;
251 if (!bShowNonWestern)
253 m_xCJK_CTL->hide();
254 m_xWestern->set_show_tabs(false); //hide single tab in case of Western only
256 else if (!bShowCJK) m_xCJK_CTL->remove_page("nbCJK");
257 else if (!bShowCTL) m_xCJK_CTL->remove_page("nbCTL");
260 //In MacOSX the standard dialogs name font-name, font-style as
261 //Family, Typeface
262 //In GNOME the standard dialogs name font-name, font-style as
263 //Family, Style
264 //In Windows the standard dialogs name font-name, font-style as
265 //Font, Style
266 #ifdef _WIN32
267 OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FONT));
268 #else
269 OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FAMILY));
270 #endif
271 m_xWestFontNameFT->set_label(sFontFamilyString);
272 m_xCTLFontNameFT->set_label(sFontFamilyString);
273 m_xEastFontNameFT->set_label(sFontFamilyString);
275 #ifdef MACOSX
276 OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_TYPEFACE));
277 #else
278 OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_STYLE));
279 #endif
280 m_xWestFontStyleFT->set_label(sFontStyleString);
281 m_xEastFontStyleFT->set_label(sFontStyleString);
282 m_xCTLFontStyleFT->set_label(sFontStyleString);
284 m_xWestFontLanguageLB->SetLanguageList(SvxLanguageListFlags::WESTERN, true, false, true, true,
285 LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN);
286 m_xEastFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CJK, true, false, true, true,
287 LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN);
288 m_xCTLFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CTL, true, false, true, true,
289 LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX);
290 int nVisibleChars = 15;
291 // read-only combobox / HasEntry asserts on set_width_char()
292 m_xWestFontLanguageLB->set_width_chars(nVisibleChars);
293 m_xEastFontLanguageLB->set_width_chars(nVisibleChars);
294 m_xCTLFontLanguageLB->set_width_chars(nVisibleChars);
296 Initialize();
299 SvxCharNamePage::~SvxCharNamePage()
301 m_pImpl.reset();
302 m_xCTLFontStyleLB.reset();
303 m_xEastFontLanguageLB.reset();
304 m_xWestFontStyleLB.reset();
305 m_xCTLFontSizeLB.reset();
306 m_xEastFontSizeLB.reset();
307 m_xWestFontSizeLB.reset();
308 m_xWestFontLanguageLB.reset();
309 m_xPreviewWin.reset();
310 m_xCTLFontLanguageLB.reset();
311 m_xEastFontLanguageLB.reset();
314 void SvxCharNamePage::Initialize()
316 // to handle the changes of the other pages
317 SetExchangeSupport();
319 Link<weld::ComboBox&,void> aLink = LINK(this, SvxCharNamePage, FontModifyComboBoxHdl_Impl);
320 m_xWestFontNameLB->connect_changed(aLink);
321 m_xWestFontStyleLB->connect_changed(aLink);
322 m_xWestFontSizeLB->connect_changed(aLink);
323 m_xWestFontLanguageLB->connect_changed(aLink);
325 m_xWestFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
327 m_xEastFontNameLB->connect_changed(aLink);
328 m_xEastFontStyleLB->connect_changed(aLink);
329 m_xEastFontSizeLB->connect_changed(aLink);
330 m_xEastFontLanguageLB->connect_changed(aLink);
331 m_xEastFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
333 m_xCTLFontNameLB->connect_changed(aLink);
334 m_xCTLFontStyleLB->connect_changed(aLink);
335 m_xCTLFontSizeLB->connect_changed(aLink);
336 m_xCTLFontLanguageLB->connect_changed(aLink);
337 m_xCTLFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
339 m_pImpl->m_aUpdateIdle.SetInvokeHandler( LINK( this, SvxCharNamePage, UpdateHdl_Impl ) );
342 const FontList* SvxCharNamePage::GetFontList() const
344 if ( !m_pImpl->m_pFontList )
346 /* #110771# SvxFontListItem::GetFontList can return NULL */
347 if (SfxObjectShell* pDocSh = SfxObjectShell::Current())
349 const SfxPoolItem* pItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST );
350 if ( pItem != nullptr )
352 DBG_ASSERT(nullptr != static_cast<const SvxFontListItem*>(pItem)->GetFontList(),
353 "Where is the font list?");
354 m_pImpl->m_pFontList = static_cast<const SvxFontListItem*>(pItem )->GetFontList()->Clone();
357 if(!m_pImpl->m_pFontList)
359 m_pImpl->m_pFontList.reset(new FontList( Application::GetDefaultDevice() ));
363 return m_pImpl->m_pFontList.get();
367 namespace
369 FontMetric calcFontMetrics( SvxFont& _rFont,
370 SvxCharNamePage const * _pPage,
371 const weld::ComboBox* _pFontNameLB,
372 const FontStyleBox* _pFontStyleLB,
373 const FontSizeBox* _pFontSizeLB,
374 const SvxLanguageBox* _pLanguageLB,
375 const FontList* _pFontList,
376 sal_uInt16 _nFontWhich,
377 sal_uInt16 _nFontHeightWhich)
379 Size aSize = _rFont.GetFontSize();
380 aSize.setWidth( 0 );
381 FontMetric aFontMetrics;
382 OUString sFontName(_pFontNameLB->get_active_text());
383 bool bFontAvailable = _pFontList->IsAvailable( sFontName );
384 if (bFontAvailable || _pFontNameLB->get_value_changed_from_saved())
385 aFontMetrics = _pFontList->Get(sFontName, _pFontStyleLB->get_active_text());
386 else
388 //get the font from itemset
389 SfxItemState eState = _pPage->GetItemSet().GetItemState( _nFontWhich );
390 if ( eState >= SfxItemState::DEFAULT )
392 const SvxFontItem* pFontItem = static_cast<const SvxFontItem*>(&( _pPage->GetItemSet().Get( _nFontWhich ) ));
393 aFontMetrics.SetFamilyName(pFontItem->GetFamilyName());
394 aFontMetrics.SetStyleName(pFontItem->GetStyleName());
395 aFontMetrics.SetFamily(pFontItem->GetFamily());
396 aFontMetrics.SetPitch(pFontItem->GetPitch());
397 aFontMetrics.SetCharSet(pFontItem->GetCharSet());
400 if ( _pFontSizeLB->IsRelative() )
402 DBG_ASSERT( _pPage->GetItemSet().GetParent(), "No parent set" );
403 const SvxFontHeightItem& rOldItem = static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nFontHeightWhich ));
405 // old value, scaled
406 tools::Long nHeight;
407 if ( _pFontSizeLB->IsPtRelative() )
408 nHeight = rOldItem.GetHeight()
409 + o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt,
410 o3tl::Length::twip) / 10;
411 else
412 nHeight = static_cast<tools::Long>(rOldItem.GetHeight() * _pFontSizeLB->get_value() / 100);
414 // conversion twips for the example-window
415 aSize.setHeight(
416 ItemToControl( nHeight, _pPage->GetItemSet().GetPool()->GetMetric( _nFontHeightWhich ), FieldUnit::TWIP ) );
418 else if ( !_pFontSizeLB->get_active_text().isEmpty() )
419 aSize.setHeight(o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt,
420 o3tl::Length::twip) / 10);
421 else
422 aSize.setHeight( 200 ); // default 10pt
423 aFontMetrics.SetFontSize( aSize );
425 _rFont.SetLanguage(_pLanguageLB->get_active_id());
427 _rFont.SetFamily( aFontMetrics.GetFamilyType() );
428 _rFont.SetFamilyName( aFontMetrics.GetFamilyName() );
429 _rFont.SetStyleName( aFontMetrics.GetStyleName() );
430 _rFont.SetPitch( aFontMetrics.GetPitch() );
431 _rFont.SetCharSet( aFontMetrics.GetCharSet() );
432 _rFont.SetWeight( aFontMetrics.GetWeight() );
433 _rFont.SetItalic( aFontMetrics.GetItalic() );
434 _rFont.SetFontSize( aFontMetrics.GetFontSize() );
436 return aFontMetrics;
441 void SvxCharNamePage::UpdatePreview_Impl()
443 SvxFont& rFont = GetPreviewFont();
444 SvxFont& rCJKFont = GetPreviewCJKFont();
445 SvxFont& rCTLFont = GetPreviewCTLFont();
446 // Font
447 const FontList* pFontList = GetFontList();
449 FontMetric aWestFontMetric = calcFontMetrics(rFont, this, m_xWestFontNameLB.get(),
450 m_xWestFontStyleLB.get(), m_xWestFontSizeLB.get(), m_xWestFontLanguageLB.get(),
451 pFontList, GetWhich(SID_ATTR_CHAR_FONT),
452 GetWhich(SID_ATTR_CHAR_FONTHEIGHT));
454 m_xWestFontTypeFT->set_label(pFontList->GetFontMapText(aWestFontMetric));
456 FontMetric aEastFontMetric = calcFontMetrics(rCJKFont, this, m_xEastFontNameLB.get(),
457 m_xEastFontStyleLB.get(), m_xEastFontSizeLB.get(), m_xEastFontLanguageLB.get(),
458 pFontList, GetWhich(SID_ATTR_CHAR_CJK_FONT),
459 GetWhich(SID_ATTR_CHAR_CJK_FONTHEIGHT));
461 m_xEastFontTypeFT->set_label(pFontList->GetFontMapText(aEastFontMetric));
463 FontMetric aCTLFontMetric = calcFontMetrics(rCTLFont,
464 this, m_xCTLFontNameLB.get(), m_xCTLFontStyleLB.get(), m_xCTLFontSizeLB.get(),
465 m_xCTLFontLanguageLB.get(), pFontList, GetWhich(SID_ATTR_CHAR_CTL_FONT),
466 GetWhich(SID_ATTR_CHAR_CTL_FONTHEIGHT));
468 m_xCTLFontTypeFT->set_label(pFontList->GetFontMapText(aCTLFontMetric));
470 m_aPreviewWin.Invalidate();
472 void SvxCharNamePage::EnableFeatureButton(const weld::Widget& rNameBox)
474 OUString sFontName;
475 weld::Button* pButton= nullptr;
476 if (m_xWestFontNameLB.get() == &rNameBox)
478 sFontName = m_xWestFontNameLB->get_active_text();
479 pButton= m_xWestFontFeaturesButton.get();
481 else if (m_xEastFontNameLB.get() == &rNameBox)
483 sFontName = m_xEastFontNameLB->get_active_text();
484 pButton=m_xEastFontFeaturesButton.get();
486 else if (m_xCTLFontNameLB.get() == &rNameBox)
488 sFontName = m_xCTLFontNameLB->get_active_text();
489 pButton= m_xCTLFontFeaturesButton.get();
491 else
493 SAL_WARN( "cui.tabpages", "invalid font name box" );
494 return;
497 bool bEnable = !getFontFeatureList(sFontName, *m_xVDev).empty();
499 pButton->set_sensitive(bEnable);
502 void SvxCharNamePage::FillStyleBox_Impl(const weld::Widget& rNameBox)
504 const FontList* pFontList = GetFontList();
505 DBG_ASSERT( pFontList, "no fontlist" );
507 FontStyleBox* pStyleBox = nullptr;
508 OUString sFontName;
510 if (m_xWestFontNameLB.get() == &rNameBox)
512 pStyleBox = m_xWestFontStyleLB.get();
513 sFontName = m_xWestFontNameLB->get_active_text();
515 else if (m_xEastFontNameLB.get() == &rNameBox)
517 pStyleBox = m_xEastFontStyleLB.get();
518 sFontName = m_xEastFontStyleLB->get_active_text();
520 else if (m_xCTLFontNameLB.get() == &rNameBox)
522 pStyleBox = m_xCTLFontStyleLB.get();
523 sFontName = m_xCTLFontNameLB->get_active_text();
525 else
527 SAL_WARN( "cui.tabpages", "invalid font name box" );
528 return;
531 pStyleBox->Fill(sFontName, pFontList);
533 if ( !m_pImpl->m_bInSearchMode )
534 return;
536 // additional entries for the search:
537 // "not bold" and "not italic"
538 OUString aEntry = m_pImpl->m_aNoStyleText;
539 const char sS[] = "%1";
540 aEntry = aEntry.replaceFirst( sS, pFontList->GetBoldStr() );
541 m_pImpl->m_nExtraEntryPos = pStyleBox->get_count();
542 pStyleBox->append_text( aEntry );
543 aEntry = m_pImpl->m_aNoStyleText;
544 aEntry = aEntry.replaceFirst( sS, pFontList->GetItalicStr() );
545 pStyleBox->append_text(aEntry);
548 void SvxCharNamePage::FillSizeBox_Impl(const weld::Widget& rNameBox)
550 const FontList* pFontList = GetFontList();
551 DBG_ASSERT( pFontList, "no fontlist" );
553 FontSizeBox* pSizeBox = nullptr;
555 if (m_xWestFontNameLB.get() == &rNameBox)
557 pSizeBox = m_xWestFontSizeLB.get();
559 else if (m_xEastFontNameLB.get() == &rNameBox)
561 pSizeBox = m_xEastFontSizeLB.get();
563 else if (m_xCTLFontNameLB.get() == &rNameBox)
565 pSizeBox = m_xCTLFontSizeLB.get();
567 else
569 SAL_WARN( "cui.tabpages", "invalid font name box" );
570 return;
573 pSizeBox->Fill( pFontList );
576 namespace
578 void FillFontNames(weld::ComboBox& rBox, const FontList& rList)
580 // insert fonts
581 sal_uInt16 nFontCount = rList.GetFontNameCount();
582 std::vector<weld::ComboBoxEntry> aVector;
583 aVector.reserve(nFontCount);
584 for (sal_uInt16 i = 0; i < nFontCount; ++i)
586 const FontMetric& rFontMetric = rList.GetFontName(i);
587 aVector.emplace_back(rFontMetric.GetFamilyName());
589 rBox.insert_vector(aVector, false);
593 void SvxCharNamePage::Reset_Impl( const SfxItemSet& rSet, LanguageGroup eLangGrp )
595 weld::ComboBox* pNameBox = nullptr;
596 weld::Label* pStyleLabel = nullptr;
597 FontStyleBox* pStyleBox = nullptr;
598 weld::Label* pSizeLabel = nullptr;
599 FontSizeBox* pSizeBox = nullptr;
600 weld::Label* pLangFT = nullptr;
601 SvxLanguageBox* pLangBox = nullptr;
602 sal_uInt16 nWhich = 0;
604 switch ( eLangGrp )
606 case Western :
607 pNameBox = m_xWestFontNameLB.get();
608 pStyleLabel = m_xWestFontStyleFT.get();
609 pStyleBox = m_xWestFontStyleLB.get();
610 pSizeLabel = m_xWestFontSizeFT.get();
611 pSizeBox = m_xWestFontSizeLB.get();
612 pLangFT = m_xWestFontLanguageFT.get();
613 pLangBox = m_xWestFontLanguageLB.get();
614 nWhich = GetWhich( SID_ATTR_CHAR_FONT );
615 break;
617 case Asian :
618 pNameBox = m_xEastFontNameLB.get();
619 pStyleLabel = m_xEastFontStyleFT.get();
620 pStyleBox = m_xEastFontStyleLB.get();
621 pSizeLabel = m_xEastFontSizeFT.get();
622 pSizeBox = m_xEastFontSizeLB.get();
623 pLangFT = m_xEastFontLanguageFT.get();
624 pLangBox = m_xEastFontLanguageLB.get();
625 nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONT );
626 break;
628 case Ctl :
629 pNameBox = m_xCTLFontNameLB.get();
630 pStyleLabel = m_xCTLFontStyleFT.get();
631 pStyleBox = m_xCTLFontStyleLB.get();
632 pSizeLabel = m_xCTLFontSizeFT.get();
633 pSizeBox = m_xCTLFontSizeLB.get();
634 pLangFT = m_xCTLFontLanguageFT.get();
635 pLangBox = m_xCTLFontLanguageLB.get();
636 nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONT );
637 break;
640 const FontList* pFontList = GetFontList();
641 FillFontNames(*pNameBox, *pFontList);
643 const SvxFontItem* pFontItem = nullptr;
644 SfxItemState eState = rSet.GetItemState( nWhich );
646 if ( eState >= SfxItemState::DEFAULT )
648 pFontItem = static_cast<const SvxFontItem*>(&( rSet.Get( nWhich ) ));
649 const OUString &rName = pFontItem->GetFamilyName();
650 int nIndex = pNameBox->find_text(rName);
651 pNameBox->set_active(nIndex);
652 // tdf#122992 if it didn't exist in the list, set the entry text to it anyway
653 if (nIndex == -1)
654 pNameBox->set_entry_text(rName);
656 else
658 pNameBox->set_active_text( OUString() );
661 FillStyleBox_Impl(*pNameBox);
663 bool bStyle = false;
664 bool bStyleAvailable = true;
665 FontItalic eItalic = ITALIC_NONE;
666 FontWeight eWeight = WEIGHT_NORMAL;
667 switch ( eLangGrp )
669 case Western : nWhich = GetWhich( SID_ATTR_CHAR_POSTURE ); break;
670 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_POSTURE ); break;
671 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_POSTURE ); break;
673 eState = rSet.GetItemState( nWhich );
675 if ( eState >= SfxItemState::DEFAULT )
677 const SvxPostureItem& rItem = static_cast<const SvxPostureItem&>(rSet.Get( nWhich ));
678 eItalic = rItem.GetValue();
679 bStyle = true;
681 bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE);
683 switch ( eLangGrp )
685 case Western : nWhich = GetWhich( SID_ATTR_CHAR_WEIGHT ); break;
686 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_WEIGHT ); break;
687 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_WEIGHT ); break;
689 eState = rSet.GetItemState( nWhich );
691 if ( eState >= SfxItemState::DEFAULT )
693 const SvxWeightItem& rItem = static_cast<const SvxWeightItem&>(rSet.Get( nWhich ));
694 eWeight = rItem.GetValue();
696 else
697 bStyle = false;
698 bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE);
700 // currently chosen font
701 if ( bStyle && pFontItem )
703 FontMetric aFontMetric = pFontList->Get( pFontItem->GetFamilyName(), eWeight, eItalic );
704 pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
706 else if ( !m_pImpl->m_bInSearchMode || !bStyle )
708 pStyleBox->set_active_text( OUString() );
710 else if ( bStyle )
712 FontMetric aFontMetric = pFontList->Get( OUString(), eWeight, eItalic );
713 pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
715 if (!bStyleAvailable)
717 pStyleBox->set_sensitive(false);
718 pStyleLabel->set_sensitive(false);
721 FillSizeBox_Impl(*pNameBox);
722 switch ( eLangGrp )
724 case Western : nWhich = GetWhich( SID_ATTR_CHAR_FONTHEIGHT ); break;
725 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ); break;
726 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ); break;
728 eState = rSet.GetItemState( nWhich );
730 if ( pSizeBox->IsRelativeMode() )
732 MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
733 const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));
735 if( rItem.GetProp() != 100 || MapUnit::MapRelative != rItem.GetPropUnit() )
737 bool bPtRel = MapUnit::MapPoint == rItem.GetPropUnit();
738 pSizeBox->SetPtRelative( bPtRel );
739 pSizeBox->set_value( bPtRel ? static_cast<short>(rItem.GetProp()) * 10 : rItem.GetProp() );
741 else
743 pSizeBox->SetRelative(false);
744 pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
747 else if ( eState >= SfxItemState::DEFAULT )
749 MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
750 const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));
751 pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
753 else
755 pSizeBox->set_active_or_entry_text(OUString());
756 if ( eState <= SfxItemState::DISABLED )
758 pSizeBox->set_sensitive(false);
759 pSizeLabel->set_sensitive(false);
763 switch ( eLangGrp )
765 case Western : nWhich = GetWhich( SID_ATTR_CHAR_LANGUAGE ); break;
766 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_LANGUAGE ); break;
767 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_LANGUAGE ); break;
769 pLangBox->set_active(-1);
770 eState = rSet.GetItemState( nWhich );
772 switch ( eState )
774 case SfxItemState::UNKNOWN:
775 pLangFT->hide();
776 pLangBox->hide();
777 break;
779 case SfxItemState::DISABLED:
780 pLangFT->set_sensitive(false);
781 pLangBox->set_sensitive(false);
782 break;
784 case SfxItemState::DEFAULT:
785 case SfxItemState::SET:
787 const SvxLanguageItem& rItem = static_cast<const SvxLanguageItem&>(rSet.Get( nWhich ));
788 LanguageType eLangType = rItem.GetValue();
789 DBG_ASSERT( eLangType != LANGUAGE_SYSTEM, "LANGUAGE_SYSTEM not allowed" );
790 if (eLangType != LANGUAGE_DONTKNOW)
791 pLangBox->set_active_id(eLangType);
792 break;
794 case SfxItemState::DONTCARE:
795 break;
798 OUString sMapText(pFontList->GetFontMapText(
799 pFontList->Get(pNameBox->get_active_text(), pStyleBox->get_active_text())));
801 switch (eLangGrp)
803 case Western:
804 m_xWestFontTypeFT->set_label(sMapText);
805 break;
806 case Asian:
807 m_xEastFontTypeFT->set_label(sMapText);
808 break;
809 case Ctl:
810 m_xCTLFontTypeFT->set_label(sMapText);
811 break;
814 EnableFeatureButton(*pNameBox);
816 // save these settings
817 pNameBox->save_value();
818 pStyleBox->save_value();
819 pSizeBox->save_value();
820 pLangBox->save_active_id();
823 bool SvxCharNamePage::FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp )
825 bool bModified = false;
827 weld::ComboBox* pNameBox = nullptr;
828 FontStyleBox* pStyleBox = nullptr;
829 FontSizeBox* pSizeBox = nullptr;
830 SvxLanguageBox* pLangBox = nullptr;
831 sal_uInt16 nWhich = 0;
832 sal_uInt16 nSlot = 0;
834 switch ( eLangGrp )
836 case Western :
837 pNameBox = m_xWestFontNameLB.get();
838 pStyleBox = m_xWestFontStyleLB.get();
839 pSizeBox = m_xWestFontSizeLB.get();
840 pLangBox = m_xWestFontLanguageLB.get();
841 nSlot = SID_ATTR_CHAR_FONT;
842 break;
844 case Asian :
845 pNameBox = m_xEastFontNameLB.get();
846 pStyleBox = m_xEastFontStyleLB.get();
847 pSizeBox = m_xEastFontSizeLB.get();
848 pLangBox = m_xEastFontLanguageLB.get();
849 nSlot = SID_ATTR_CHAR_CJK_FONT;
850 break;
852 case Ctl :
853 pNameBox = m_xCTLFontNameLB.get();
854 pStyleBox = m_xCTLFontStyleLB.get();
855 pSizeBox = m_xCTLFontSizeLB.get();
856 pLangBox = m_xCTLFontLanguageLB.get();
857 nSlot = SID_ATTR_CHAR_CTL_FONT;
858 break;
861 nWhich = GetWhich( nSlot );
862 const SfxPoolItem* pItem = nullptr;
863 const SfxItemSet& rOldSet = GetItemSet();
864 const SfxPoolItem* pOld = nullptr;
866 const SfxItemSet* pExampleSet = GetDialogExampleSet();
868 bool bChanged = true;
869 const OUString& rFontName = pNameBox->get_active_text();
870 const FontList* pFontList = GetFontList();
871 OUString aStyleBoxText = pStyleBox->get_active_text();
872 int nEntryPos = pStyleBox->find_text(aStyleBoxText);
873 if (nEntryPos >= m_pImpl->m_nExtraEntryPos)
874 aStyleBoxText.clear();
875 FontMetric aInfo( pFontList->Get( rFontName, aStyleBoxText ) );
876 SvxFontItem aFontItem( aInfo.GetFamilyType(), aInfo.GetFamilyName(), aInfo.GetStyleName(),
877 aInfo.GetPitch(), aInfo.GetCharSet(), nWhich );
878 pOld = GetOldItem( rSet, nSlot );
880 if ( pOld )
882 const SvxFontItem& rItem = *static_cast<const SvxFontItem*>(pOld);
884 if ( rItem.GetFamilyName() == aFontItem.GetFamilyName() )
885 bChanged = false;
888 if ( !bChanged )
889 bChanged = pNameBox->get_saved_value().isEmpty();
891 if ( !bChanged && pExampleSet &&
892 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
893 static_cast<const SvxFontItem*>(pItem)->GetFamilyName() != aFontItem.GetFamilyName() )
894 bChanged = true;
896 if ( bChanged && !rFontName.isEmpty() )
898 rSet.Put( aFontItem );
899 bModified = true;
901 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
902 rSet.ClearItem( nWhich );
905 bChanged = true;
906 switch ( eLangGrp )
908 case Western : nSlot = SID_ATTR_CHAR_WEIGHT; break;
909 case Asian : nSlot = SID_ATTR_CHAR_CJK_WEIGHT; break;
910 case Ctl : nSlot = SID_ATTR_CHAR_CTL_WEIGHT; break;
912 nWhich = GetWhich( nSlot );
913 FontWeight eWeight = aInfo.GetWeight();
914 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
915 eWeight = WEIGHT_NORMAL;
916 SvxWeightItem aWeightItem( eWeight, nWhich );
917 pOld = GetOldItem( rSet, nSlot );
919 if ( pOld )
921 const SvxWeightItem& rItem = *static_cast<const SvxWeightItem*>(pOld);
923 if ( rItem.GetValue() == aWeightItem.GetValue() )
924 bChanged = false;
927 if ( !bChanged )
929 bChanged = pStyleBox->get_saved_value().isEmpty();
931 if ( m_pImpl->m_bInSearchMode && bChanged &&
932 aInfo.GetWeight() == WEIGHT_NORMAL && aInfo.GetItalic() != ITALIC_NONE )
933 bChanged = false;
936 if ( !bChanged && pExampleSet &&
937 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
938 static_cast<const SvxWeightItem*>(pItem)->GetValue() != aWeightItem.GetValue() )
939 bChanged = true;
941 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
942 bChanged = ( nEntryPos == m_pImpl->m_nExtraEntryPos );
944 OUString aText( pStyleBox->get_active_text() ); // Tristate, then text empty
946 if ( bChanged && !aText.isEmpty() )
948 rSet.Put( aWeightItem );
949 bModified = true;
951 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
952 rSet.InvalidateItem(nWhich);
954 bChanged = true;
955 switch ( eLangGrp )
957 case Western : nSlot = SID_ATTR_CHAR_POSTURE; break;
958 case Asian : nSlot = SID_ATTR_CHAR_CJK_POSTURE; break;
959 case Ctl : nSlot = SID_ATTR_CHAR_CTL_POSTURE; break;
961 nWhich = GetWhich( nSlot );
962 FontItalic eItalic = aInfo.GetItalic();
963 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
964 eItalic = ITALIC_NONE;
965 SvxPostureItem aPostureItem( eItalic, nWhich );
966 pOld = GetOldItem( rSet, nSlot );
968 if ( pOld )
970 const SvxPostureItem& rItem = *static_cast<const SvxPostureItem*>(pOld);
972 if ( rItem.GetValue() == aPostureItem.GetValue() )
973 bChanged = false;
976 if ( !bChanged )
978 bChanged = pStyleBox->get_saved_value().isEmpty();
980 if ( m_pImpl->m_bInSearchMode && bChanged &&
981 aInfo.GetItalic() == ITALIC_NONE && aInfo.GetWeight() != WEIGHT_NORMAL )
982 bChanged = false;
985 if ( !bChanged && pExampleSet &&
986 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
987 static_cast<const SvxPostureItem*>(pItem)->GetValue() != aPostureItem.GetValue() )
988 bChanged = true;
990 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
991 bChanged = ( nEntryPos == ( m_pImpl->m_nExtraEntryPos + 1 ) );
993 if ( bChanged && !aText.isEmpty() )
995 rSet.Put( aPostureItem );
996 bModified = true;
998 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
999 rSet.InvalidateItem(nWhich);
1001 // FontSize
1002 tools::Long nSize = pSizeBox->get_value();
1004 if ( pSizeBox->get_active_text().isEmpty() ) // GetValue() returns the min-value
1005 nSize = 0;
1006 tools::Long nSavedSize = pSizeBox->get_saved_value();
1007 const bool bRel = pSizeBox->IsRelative();
1009 switch ( eLangGrp )
1011 case Western : nSlot = SID_ATTR_CHAR_FONTHEIGHT; break;
1012 case Asian : nSlot = SID_ATTR_CHAR_CJK_FONTHEIGHT; break;
1013 case Ctl : nSlot = SID_ATTR_CHAR_CTL_FONTHEIGHT; break;
1015 nWhich = GetWhich( nSlot );
1016 const SvxFontHeightItem* pOldHeight = static_cast<const SvxFontHeightItem*>(GetOldItem( rSet, nSlot ));
1017 bChanged = ( nSize != nSavedSize );
1019 if ( !bChanged && pExampleSet &&
1020 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET )
1022 float fSize = static_cast<float>(nSize) / 10;
1023 tools::Long nVal = CalcToUnit( fSize, rSet.GetPool()->GetMetric( nWhich ) );
1024 if ( static_cast<const SvxFontHeightItem*>(pItem)->GetHeight() != static_cast<sal_uInt32>(nVal) )
1025 bChanged = true;
1028 if ( bChanged || !pOldHeight ||
1029 bRel != ( MapUnit::MapRelative != pOldHeight->GetPropUnit() || 100 != pOldHeight->GetProp() ) )
1031 MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
1032 if ( pSizeBox->IsRelative() )
1034 DBG_ASSERT( GetItemSet().GetParent(), "No parent set" );
1035 const SvxFontHeightItem& rOldItem =
1036 static_cast<const SvxFontHeightItem&>(GetItemSet().GetParent()->Get( nWhich ));
1038 SvxFontHeightItem aHeight( 240, 100, nWhich );
1039 if ( pSizeBox->IsPtRelative() )
1040 aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>( nSize / 10 ), MapUnit::MapPoint, eUnit );
1041 else
1042 aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>(nSize) );
1043 rSet.Put( aHeight );
1045 else
1047 float fSize = static_cast<float>(nSize) / 10;
1048 rSet.Put( SvxFontHeightItem( CalcToUnit( fSize, eUnit ), 100, nWhich ) );
1050 bModified = true;
1052 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1053 rSet.InvalidateItem(nWhich);
1055 bChanged = true;
1056 switch ( eLangGrp )
1058 case Western : nSlot = SID_ATTR_CHAR_LANGUAGE; break;
1059 case Asian : nSlot = SID_ATTR_CHAR_CJK_LANGUAGE; break;
1060 case Ctl : nSlot = SID_ATTR_CHAR_CTL_LANGUAGE; break;
1063 // For language list boxes acting as ComboBox, check for, add and select an
1064 // edited entry.
1065 switch (pLangBox->GetEditedAndValid())
1067 case SvxLanguageBox::EditedAndValid::No:
1068 ; // nothing to do
1069 break;
1070 case SvxLanguageBox::EditedAndValid::Valid:
1072 SvxLanguageBox* ppBoxes[3]
1073 = {m_xWestFontLanguageLB.get(), m_xEastFontLanguageLB.get(), m_xCTLFontLanguageLB.get()};
1074 SvxLanguageBox* pBox = pLangBox->SaveEditedAsEntry(ppBoxes);
1075 if (pBox != pLangBox)
1077 // Get item from corresponding slot.
1078 if (pBox == m_xWestFontLanguageLB.get())
1079 nSlot = SID_ATTR_CHAR_LANGUAGE;
1080 else if (pBox == m_xEastFontLanguageLB.get())
1081 nSlot = SID_ATTR_CHAR_CJK_LANGUAGE;
1082 else if (pBox == m_xCTLFontLanguageLB.get())
1083 nSlot = SID_ATTR_CHAR_CTL_LANGUAGE;
1084 pLangBox = pBox;
1087 break;
1088 case SvxLanguageBox::EditedAndValid::Invalid:
1089 pLangBox->set_active_id(pLangBox->get_saved_active_id());
1090 break;
1093 nWhich = GetWhich( nSlot );
1094 pOld = GetOldItem( rSet, nSlot );
1096 int nLangPos = pLangBox->get_active();
1097 LanguageType eLangType = pLangBox->get_active_id();
1099 if (pOld)
1101 const SvxLanguageItem& rItem = *static_cast<const SvxLanguageItem*>(pOld);
1102 if (nLangPos == -1 || eLangType == rItem.GetValue())
1103 bChanged = false;
1106 if (!bChanged)
1107 bChanged = pLangBox->get_active_id_changed_from_saved();
1109 if (bChanged && nLangPos != -1)
1111 rSet.Put(SvxLanguageItem(eLangType, nWhich));
1112 bModified = true;
1114 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1115 rSet.InvalidateItem(nWhich);
1117 return bModified;
1120 IMPL_LINK_NOARG(SvxCharNamePage, UpdateHdl_Impl, Timer *, void)
1122 UpdatePreview_Impl();
1125 IMPL_LINK(SvxCharNamePage, FontModifyComboBoxHdl_Impl, weld::ComboBox&, rBox, void)
1127 FontModifyHdl_Impl(rBox);
1130 IMPL_LINK(SvxCharNamePage, FontFeatureButtonClicked, weld::Button&, rButton, void)
1132 OUString sFontName;
1133 weld::ComboBox* pNameBox = nullptr;
1135 if (&rButton == m_xWestFontFeaturesButton.get())
1137 pNameBox = m_xWestFontNameLB.get();
1138 sFontName = GetPreviewFont().GetFamilyName();
1140 else if (&rButton == m_xEastFontFeaturesButton.get())
1142 pNameBox = m_xEastFontNameLB.get();
1143 sFontName = GetPreviewCJKFont().GetFamilyName();
1145 else if (&rButton == m_xCTLFontFeaturesButton.get())
1147 pNameBox = m_xCTLFontNameLB.get();
1148 sFontName = GetPreviewCTLFont().GetFamilyName();
1151 if (!sFontName.isEmpty() && pNameBox)
1153 cui::FontFeaturesDialog aDialog(GetFrameWeld(), sFontName);
1154 if (aDialog.run() == RET_OK)
1156 pNameBox->set_entry_text(aDialog.getResultFontName());
1157 UpdatePreview_Impl();
1162 void SvxCharNamePage::FontModifyHdl_Impl(const weld::Widget& rNameBox)
1164 m_pImpl->m_aUpdateIdle.Start();
1166 if (m_xWestFontNameLB.get() == &rNameBox || m_xEastFontNameLB.get() == &rNameBox || m_xCTLFontNameLB.get() == &rNameBox)
1168 FillStyleBox_Impl(rNameBox);
1169 FillSizeBox_Impl(rNameBox);
1170 EnableFeatureButton(rNameBox);
1174 void SvxCharNamePage::ActivatePage( const SfxItemSet& rSet )
1176 SvxCharBasePage::ActivatePage( rSet );
1178 UpdatePreview_Impl(); // instead of asynchronous calling in ctor
1181 DeactivateRC SvxCharNamePage::DeactivatePage( SfxItemSet* _pSet )
1183 if ( _pSet )
1184 FillItemSet( _pSet );
1185 return DeactivateRC::LeavePage;
1188 std::unique_ptr<SfxTabPage> SvxCharNamePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
1190 return std::make_unique<SvxCharNamePage>(pPage, pController, *rSet );
1193 void SvxCharNamePage::Reset( const SfxItemSet* rSet )
1195 Reset_Impl( *rSet, Western );
1196 Reset_Impl( *rSet, Asian );
1197 Reset_Impl( *rSet, Ctl );
1199 SetPrevFontWidthScale( *rSet );
1200 UpdatePreview_Impl();
1203 void SvxCharNamePage::ChangesApplied()
1205 m_xWestFontNameLB->save_value();
1206 m_xWestFontStyleLB->save_value();
1207 m_xWestFontSizeLB->save_value();
1208 m_xWestFontLanguageLB->save_active_id();
1209 m_xEastFontNameLB->save_value();
1210 m_xEastFontStyleLB->save_value();
1211 m_xEastFontSizeLB->save_value();
1212 m_xEastFontLanguageLB->save_active_id();
1213 m_xCTLFontNameLB->save_value();
1214 m_xCTLFontStyleLB->save_value();
1215 m_xCTLFontSizeLB->save_value();
1216 m_xCTLFontLanguageLB->save_active_id();
1219 bool SvxCharNamePage::FillItemSet( SfxItemSet* rSet )
1221 bool bModified = FillItemSet_Impl( *rSet, Western );
1222 bModified |= FillItemSet_Impl( *rSet, Asian );
1223 bModified |= FillItemSet_Impl( *rSet, Ctl );
1224 return bModified;
1227 void SvxCharNamePage::SetFontList( const SvxFontListItem& rItem )
1229 m_pImpl->m_pFontList = rItem.GetFontList()->Clone();
1232 namespace
1234 void enableRelativeMode( SvxCharNamePage const * _pPage, FontSizeBox* _pFontSizeLB, sal_uInt16 _nHeightWhich )
1236 _pFontSizeLB->EnableRelativeMode( 5, 995 ); // min 5%, max 995%, step 5
1238 const SvxFontHeightItem& rHeightItem =
1239 static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nHeightWhich ));
1240 MapUnit eUnit = _pPage->GetItemSet().GetPool()->GetMetric( _nHeightWhich );
1241 short nCurHeight =
1242 static_cast< short >( CalcToPoint( rHeightItem.GetHeight(), eUnit, 1 ) * 10 );
1244 // based on the current height:
1245 // - negative until minimum of 2 pt
1246 // - positive until maximum of 999 pt
1247 _pFontSizeLB->EnablePtRelativeMode( sal::static_int_cast< short >(-(nCurHeight - 20)), (9999 - nCurHeight) );
1251 void SvxCharNamePage::EnableRelativeMode()
1253 DBG_ASSERT( GetItemSet().GetParent(), "RelativeMode, but no ParentSet!" );
1254 enableRelativeMode(this,m_xWestFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_FONTHEIGHT ));
1255 enableRelativeMode(this,m_xEastFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ));
1256 enableRelativeMode(this,m_xCTLFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ));
1259 void SvxCharNamePage::EnableSearchMode()
1261 m_pImpl->m_bInSearchMode = true;
1264 void SvxCharNamePage::DisableControls( sal_uInt16 nDisable )
1266 if ( DISABLE_HIDE_LANGUAGE & nDisable )
1268 if ( m_xWestFontLanguageFT ) m_xWestFontLanguageFT->hide();
1269 if ( m_xWestFontLanguageLB ) m_xWestFontLanguageLB->hide();
1270 if ( m_xEastFontLanguageFT ) m_xEastFontLanguageFT->hide();
1271 if ( m_xEastFontLanguageLB ) m_xEastFontLanguageLB->hide();
1272 if ( m_xCTLFontLanguageFT ) m_xCTLFontLanguageFT->hide();
1273 if ( m_xCTLFontLanguageLB ) m_xCTLFontLanguageLB->hide();
1277 void SvxCharNamePage::PageCreated(const SfxAllItemSet& aSet)
1279 const SvxFontListItem* pFontListItem = aSet.GetItem<SvxFontListItem>(SID_ATTR_CHAR_FONTLIST, false);
1280 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
1281 const SfxUInt16Item* pDisableItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false);
1282 if (pFontListItem)
1283 SetFontList(*pFontListItem);
1285 if (pFlagItem)
1287 sal_uInt32 nFlags=pFlagItem->GetValue();
1288 if ( ( nFlags & SVX_RELATIVE_MODE ) == SVX_RELATIVE_MODE )
1289 EnableRelativeMode();
1290 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
1291 // the writer uses SID_ATTR_BRUSH as font background
1292 m_bPreviewBackgroundToCharacter = true;
1294 if (pDisableItem)
1295 DisableControls(pDisableItem->GetValue());
1297 // class SvxCharEffectsPage ----------------------------------------------
1299 SvxCharEffectsPage::SvxCharEffectsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
1300 : SvxCharBasePage(pPage, pController, "cui/ui/effectspage.ui", "EffectsPage", rInSet)
1301 , m_bOrigFontColor(false)
1302 , m_bNewFontColor(false)
1303 , m_bEnableNoneFontColor(false)
1304 , m_xFontColorFT(m_xBuilder->weld_label("fontcolorft"))
1305 , m_xFontColorLB(new ColorListBox(m_xBuilder->weld_menu_button("fontcolorlb"),
1306 [this]{ return GetDialogController()->getDialog(); }))
1307 , m_xFontTransparencyFT(m_xBuilder->weld_label("fonttransparencyft"))
1308 , m_xFontTransparencyMtr(
1309 m_xBuilder->weld_metric_spin_button("fonttransparencymtr", FieldUnit::PERCENT))
1310 , m_xEffectsFT(m_xBuilder->weld_label("effectsft"))
1311 , m_xEffectsLB(m_xBuilder->weld_combo_box("effectslb"))
1312 , m_xReliefFT(m_xBuilder->weld_label("reliefft"))
1313 , m_xReliefLB(m_xBuilder->weld_combo_box("relieflb"))
1314 , m_xOutlineBtn(m_xBuilder->weld_check_button("outlinecb"))
1315 , m_xShadowBtn(m_xBuilder->weld_check_button("shadowcb"))
1316 , m_xHiddenBtn(m_xBuilder->weld_check_button("hiddencb"))
1317 , m_xOverlineLB(m_xBuilder->weld_combo_box("overlinelb"))
1318 , m_xOverlineColorFT(m_xBuilder->weld_label("overlinecolorft"))
1319 , m_xOverlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("overlinecolorlb"),
1320 [this]{ return GetDialogController()->getDialog(); }))
1321 , m_xStrikeoutLB(m_xBuilder->weld_combo_box("strikeoutlb"))
1322 , m_xUnderlineLB(m_xBuilder->weld_combo_box("underlinelb"))
1323 , m_xUnderlineColorFT(m_xBuilder->weld_label("underlinecolorft"))
1324 , m_xUnderlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("underlinecolorlb"),
1325 [this]{ return GetDialogController()->getDialog(); }))
1326 , m_xIndividualWordsBtn(m_xBuilder->weld_check_button("individualwordscb"))
1327 , m_xEmphasisFT(m_xBuilder->weld_label("emphasisft"))
1328 , m_xEmphasisLB(m_xBuilder->weld_combo_box("emphasislb"))
1329 , m_xPositionFT(m_xBuilder->weld_label("positionft"))
1330 , m_xPositionLB(m_xBuilder->weld_combo_box("positionlb"))
1331 , m_xA11yWarningFT(m_xBuilder->weld_label("a11ywarning"))
1333 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
1334 #ifdef IOS
1335 m_xPreviewWin->hide();
1336 #endif
1337 m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1338 m_xOverlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1339 m_xUnderlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1340 Initialize();
1343 void SvxCharEffectsPage::EnableNoneFontColor()
1345 m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR, true);
1346 m_bEnableNoneFontColor = true;
1349 SvxCharEffectsPage::~SvxCharEffectsPage()
1351 m_xUnderlineColorLB.reset();
1352 m_xOverlineColorLB.reset();
1353 m_xFontTransparencyMtr.reset();
1354 m_xFontColorLB.reset();
1357 void SvxCharEffectsPage::Initialize()
1359 // to handle the changes of the other pages
1360 SetExchangeSupport();
1362 // HTML-Mode
1363 const SfxUInt16Item* pHtmlModeItem = GetItemSet().GetItemIfSet( SID_HTML_MODE, false );
1364 if ( !pHtmlModeItem)
1366 if (SfxObjectShell* pShell = SfxObjectShell::Current())
1367 pHtmlModeItem = pShell->GetItem( SID_HTML_MODE );
1369 if (pHtmlModeItem)
1371 m_nHtmlMode = pHtmlModeItem->GetValue();
1372 if ( ( m_nHtmlMode & HTMLMODE_ON ) == HTMLMODE_ON )
1374 //!!! hide some controls please
1378 m_xFontColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
1379 m_xFontTransparencyMtr->connect_value_changed(
1380 LINK(this, SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl));
1382 // handler
1383 Link<weld::ComboBox&,void> aLink = LINK( this, SvxCharEffectsPage, SelectListBoxHdl_Impl );
1384 m_xUnderlineLB->connect_changed( aLink );
1385 m_xUnderlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
1386 m_xOverlineLB->connect_changed( aLink );
1387 m_xOverlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
1388 m_xStrikeoutLB->connect_changed( aLink );
1389 m_xEmphasisLB->connect_changed( aLink );
1390 m_xPositionLB->connect_changed( aLink );
1391 m_xEffectsLB->connect_changed( aLink );
1392 m_xReliefLB->connect_changed( aLink );
1394 m_xUnderlineLB->set_active( 0 );
1395 m_xOverlineLB->set_active( 0 );
1396 m_xStrikeoutLB->set_active( 0 );
1397 m_xEmphasisLB->set_active( 0 );
1398 m_xPositionLB->set_active( 0 );
1399 SelectHdl_Impl(nullptr);
1400 SelectHdl_Impl(m_xEmphasisLB.get());
1402 m_xEffectsLB->set_active( 0 );
1404 m_xHiddenBtn->connect_toggled(LINK(this, SvxCharEffectsPage, HiddenBtnClickHdl));
1405 m_xIndividualWordsBtn->connect_toggled(LINK(this, SvxCharEffectsPage, CbClickHdl_Impl));
1406 m_xOutlineBtn->connect_toggled(LINK(this, SvxCharEffectsPage, OutlineBtnClickHdl));
1407 m_xShadowBtn->connect_toggled(LINK(this, SvxCharEffectsPage, ShadowBtnClickHdl));
1409 if ( !SvtCJKOptions::IsAsianTypographyEnabled() )
1411 m_xEmphasisFT->hide();
1412 m_xEmphasisLB->hide();
1413 m_xPositionFT->hide();
1414 m_xPositionLB->hide();
1417 m_xA11yWarningFT->set_visible(officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get());
1420 void SvxCharEffectsPage::UpdatePreview_Impl()
1422 SvxFont& rFont = GetPreviewFont();
1423 SvxFont& rCJKFont = GetPreviewCJKFont();
1424 SvxFont& rCTLFont = GetPreviewCTLFont();
1426 const Color& rSelectedColor = m_xFontColorLB->GetSelectEntryColor();
1427 rFont.SetColor(rSelectedColor);
1428 rCJKFont.SetColor(rSelectedColor);
1429 rCTLFont.SetColor(rSelectedColor);
1430 m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO
1432 FontLineStyle eUnderline = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32());
1433 FontLineStyle eOverline = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32());
1434 FontStrikeout eStrikeout = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32());
1435 rFont.SetUnderline( eUnderline );
1436 rCJKFont.SetUnderline( eUnderline );
1437 rCTLFont.SetUnderline( eUnderline );
1438 m_aPreviewWin.SetTextLineColor( m_xUnderlineColorLB->GetSelectEntryColor() );
1439 rFont.SetOverline( eOverline );
1440 rCJKFont.SetOverline( eOverline );
1441 rCTLFont.SetOverline( eOverline );
1442 m_aPreviewWin.SetOverlineColor( m_xOverlineColorLB->GetSelectEntryColor() );
1443 rFont.SetStrikeout( eStrikeout );
1444 rCJKFont.SetStrikeout( eStrikeout );
1445 rCTLFont.SetStrikeout( eStrikeout );
1447 auto nEmphasis = m_xEmphasisLB->get_active();
1448 if (nEmphasis != -1)
1450 bool bUnder = (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32());
1451 FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nEmphasis);
1452 eMark |= bUnder ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove;
1453 rFont.SetEmphasisMark( eMark );
1454 rCJKFont.SetEmphasisMark( eMark );
1455 rCTLFont.SetEmphasisMark( eMark );
1458 auto nRelief = m_xReliefLB->get_active();
1459 if (nRelief != -1)
1461 rFont.SetRelief( static_cast<FontRelief>(nRelief) );
1462 rCJKFont.SetRelief( static_cast<FontRelief>(nRelief) );
1463 rCTLFont.SetRelief( static_cast<FontRelief>(nRelief) );
1466 rFont.SetOutline( StateToAttr( m_xOutlineBtn->get_state() ) );
1467 rCJKFont.SetOutline( rFont.IsOutline() );
1468 rCTLFont.SetOutline( rFont.IsOutline() );
1470 rFont.SetShadow( StateToAttr( m_xShadowBtn->get_state() ) );
1471 rCJKFont.SetShadow( rFont.IsShadow() );
1472 rCTLFont.SetShadow( rFont.IsShadow() );
1474 auto nCapsPos = m_xEffectsLB->get_active();
1475 if (nCapsPos != -1)
1477 SvxCaseMap eCaps = static_cast<SvxCaseMap>(nCapsPos);
1478 rFont.SetCaseMap( eCaps );
1479 rCJKFont.SetCaseMap( eCaps );
1480 // #i78474# small caps do not exist in CTL fonts
1481 rCTLFont.SetCaseMap( eCaps == SvxCaseMap::SmallCaps ? SvxCaseMap::NotMapped : eCaps );
1484 bool bWordLine = StateToAttr( m_xIndividualWordsBtn->get_state() );
1485 rFont.SetWordLineMode( bWordLine );
1486 rCJKFont.SetWordLineMode( bWordLine );
1487 rCTLFont.SetWordLineMode( bWordLine );
1489 m_aPreviewWin.Invalidate();
1492 void SvxCharEffectsPage::SetCaseMap_Impl( SvxCaseMap eCaseMap )
1494 if ( SvxCaseMap::End > eCaseMap )
1495 m_xEffectsLB->set_active(
1496 sal::static_int_cast< sal_Int32 >( eCaseMap ) );
1497 else
1499 // not mapped
1500 m_xEffectsLB->set_active(-1);
1503 UpdatePreview_Impl();
1506 void SvxCharEffectsPage::ResetColor_Impl( const SfxItemSet& rSet )
1508 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
1509 SfxItemState eState = rSet.GetItemState( nWhich );
1511 m_bOrigFontColor = false;
1512 switch ( eState )
1514 case SfxItemState::UNKNOWN:
1515 m_xFontColorFT->hide();
1516 m_xFontColorLB->hide();
1517 break;
1519 case SfxItemState::DISABLED:
1520 m_xFontColorFT->set_sensitive(false);
1521 m_xFontColorLB->set_sensitive(false);
1522 break;
1524 case SfxItemState::DONTCARE:
1525 //Related: tdf#106080 if there is no font color, then allow "none"
1526 //as a color so the listbox can display that state.
1527 EnableNoneFontColor();
1528 m_xFontColorLB->SetNoSelection();
1529 break;
1531 case SfxItemState::DEFAULT:
1532 case SfxItemState::SET:
1534 SvxFont& rFont = GetPreviewFont();
1535 SvxFont& rCJKFont = GetPreviewCJKFont();
1536 SvxFont& rCTLFont = GetPreviewCTLFont();
1538 const SvxColorItem& rItem = static_cast<const SvxColorItem&>(rSet.Get( nWhich ));
1539 Color aColor = rItem.GetValue();
1540 rFont.SetColor(aColor);
1541 rCJKFont.SetColor(aColor);
1542 rCTLFont.SetColor(aColor);
1543 m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO
1545 m_aPreviewWin.Invalidate();
1547 Color aRGBColor = aColor;
1548 if (aRGBColor.IsTransparent() && aColor != COL_AUTO)
1550 aRGBColor.SetAlpha(255);
1552 m_xFontColorLB->SelectEntry(aRGBColor);
1554 if (m_xFontTransparencyMtr->get_visible() && aColor != COL_AUTO)
1556 double fTransparency = (255 - aColor.GetAlpha()) * 100.0 / 255;
1557 m_xFontTransparencyMtr->set_value(basegfx::fround(fTransparency),
1558 FieldUnit::PERCENT);
1561 m_aOrigFontColor = aColor;
1562 m_bOrigFontColor = true;
1563 break;
1566 m_bNewFontColor = false;
1569 bool SvxCharEffectsPage::FillItemSetColor_Impl( SfxItemSet& rSet )
1571 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
1572 const SfxItemSet& rOldSet = GetItemSet();
1574 NamedColor aSelectedColor;
1575 bool bChanged = m_bNewFontColor;
1577 if (bChanged)
1579 aSelectedColor = m_xFontColorLB->GetSelectedEntryThemedColor();
1581 if (m_xFontTransparencyMtr->get_value_changed_from_saved())
1583 double fTransparency
1584 = m_xFontTransparencyMtr->get_value(FieldUnit::PERCENT) * 255.0 / 100;
1585 aSelectedColor.m_aColor.SetAlpha(255 - static_cast<sal_uInt8>(basegfx::fround(fTransparency)));
1588 if (m_bOrigFontColor)
1589 bChanged = aSelectedColor.m_aColor != m_aOrigFontColor;
1590 if (m_bEnableNoneFontColor && bChanged && aSelectedColor.m_aColor == COL_NONE_COLOR)
1591 bChanged = false;
1594 if (bChanged)
1596 SvxColorItem aItem( aSelectedColor.m_aColor, nWhich );
1598 // The color was picked from the theme palette, remember its index.
1599 model::ThemeColorType eType = model::convertToThemeColorType(aSelectedColor.m_nThemeIndex);
1600 if (eType != model::ThemeColorType::Unknown)
1602 model::ComplexColor aComplexColor;
1603 aComplexColor.setSchemeColor(eType);
1604 aComplexColor.addTransformation({model::TransformationType::LumMod, aSelectedColor.m_nLumMod});
1605 aComplexColor.addTransformation({model::TransformationType::LumOff, aSelectedColor.m_nLumOff});
1606 aItem.setComplexColor(aComplexColor);
1609 rSet.Put(aItem);
1611 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1612 rSet.InvalidateItem(nWhich);
1614 return bChanged;
1617 IMPL_LINK( SvxCharEffectsPage, SelectListBoxHdl_Impl, weld::ComboBox&, rBox, void )
1619 SelectHdl_Impl(&rBox);
1622 void SvxCharEffectsPage::SelectHdl_Impl(const weld::ComboBox* pBox)
1624 if (m_xEmphasisLB.get() == pBox)
1626 auto nEPos = m_xEmphasisLB->get_active();
1627 bool bEnable = nEPos > 0;
1628 m_xPositionFT->set_sensitive( bEnable );
1629 m_xPositionLB->set_sensitive( bEnable );
1631 else if (m_xReliefLB.get() == pBox)
1633 bool bEnable = ( pBox->get_active() == 0 );
1634 m_xOutlineBtn->set_sensitive( bEnable );
1635 m_xShadowBtn->set_sensitive( bEnable );
1637 else if (m_xPositionLB.get() != pBox)
1639 auto nUPos = m_xUnderlineLB->get_active();
1640 bool bUEnable = nUPos > 0;
1641 m_xUnderlineColorFT->set_sensitive(bUEnable);
1642 m_xUnderlineColorLB->set_sensitive(bUEnable);
1644 auto nOPos = m_xOverlineLB->get_active();
1645 bool bOEnable = nOPos > 0;
1646 m_xOverlineColorFT->set_sensitive(bOEnable);
1647 m_xOverlineColorLB->set_sensitive(bOEnable);
1649 auto nSPos = m_xStrikeoutLB->get_active();
1650 m_xIndividualWordsBtn->set_sensitive( bUEnable || bOEnable || nSPos > 0);
1652 UpdatePreview_Impl();
1655 IMPL_LINK(SvxCharEffectsPage, CbClickHdl_Impl, weld::Toggleable&, rToggle, void)
1657 m_aIndividualWordsState.ButtonToggled(rToggle);
1658 UpdatePreview_Impl();
1659 UpdatePreview_Impl();
1662 IMPL_LINK(SvxCharEffectsPage, ColorBoxSelectHdl_Impl, ColorListBox&, rBox, void)
1664 if (m_xFontColorLB.get() == &rBox)
1665 m_bNewFontColor = true;
1666 UpdatePreview_Impl();
1669 IMPL_LINK_NOARG(SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl, weld::MetricSpinButton&, void)
1671 m_bNewFontColor = true;
1674 DeactivateRC SvxCharEffectsPage::DeactivatePage( SfxItemSet* _pSet )
1676 if ( _pSet )
1677 FillItemSet( _pSet );
1678 return DeactivateRC::LeavePage;
1681 std::unique_ptr<SfxTabPage> SvxCharEffectsPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
1683 return std::make_unique<SvxCharEffectsPage>( pPage, pController, *rSet );
1686 void SvxCharEffectsPage::Reset( const SfxItemSet* rSet )
1688 SvxFont& rFont = GetPreviewFont();
1689 SvxFont& rCJKFont = GetPreviewCJKFont();
1690 SvxFont& rCTLFont = GetPreviewCTLFont();
1692 bool bEnable = false;
1694 // Underline
1695 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE );
1696 rFont.SetUnderline( LINESTYLE_NONE );
1697 rCJKFont.SetUnderline( LINESTYLE_NONE );
1698 rCTLFont.SetUnderline( LINESTYLE_NONE );
1700 m_xUnderlineLB->set_active( 0 );
1701 SfxItemState eState = rSet->GetItemState( nWhich );
1703 if ( eState >= SfxItemState::DONTCARE )
1705 if ( eState == SfxItemState::DONTCARE )
1706 m_xUnderlineLB->set_active(-1);
1707 else
1709 const SvxUnderlineItem& rItem = static_cast<const SvxUnderlineItem&>(rSet->Get( nWhich ));
1710 FontLineStyle eUnderline = rItem.GetValue();
1711 rFont.SetUnderline( eUnderline );
1712 rCJKFont.SetUnderline( eUnderline );
1713 rCTLFont.SetUnderline( eUnderline );
1715 if ( eUnderline != LINESTYLE_NONE )
1717 auto nPos = m_xUnderlineLB->find_id(OUString::number(eUnderline));
1718 if (nPos != -1)
1720 m_xUnderlineLB->set_active(nPos);
1721 bEnable = true;
1723 Color aColor = rItem.GetColor();
1724 m_xUnderlineColorLB->SelectEntry(aColor);
1726 else
1728 m_xUnderlineColorLB->SelectEntry(COL_AUTO);
1729 m_xUnderlineColorLB->set_sensitive(false);
1734 // Overline
1735 nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE );
1736 rFont.SetOverline( LINESTYLE_NONE );
1737 rCJKFont.SetOverline( LINESTYLE_NONE );
1738 rCTLFont.SetOverline( LINESTYLE_NONE );
1740 m_xOverlineLB->set_active( 0 );
1741 eState = rSet->GetItemState( nWhich );
1743 if ( eState >= SfxItemState::DONTCARE )
1745 if ( eState == SfxItemState::DONTCARE )
1746 m_xOverlineLB->set_active(-1);
1747 else
1749 const SvxOverlineItem& rItem = static_cast<const SvxOverlineItem&>(rSet->Get( nWhich ));
1750 FontLineStyle eOverline = rItem.GetValue();
1751 rFont.SetOverline( eOverline );
1752 rCJKFont.SetOverline( eOverline );
1753 rCTLFont.SetOverline( eOverline );
1755 if ( eOverline != LINESTYLE_NONE )
1757 auto nPos = m_xOverlineLB->find_id(OUString::number(eOverline));
1758 if (nPos != -1)
1760 m_xOverlineLB->set_active(nPos);
1761 bEnable = true;
1763 Color aColor = rItem.GetColor();
1764 m_xOverlineColorLB->SelectEntry(aColor);
1766 else
1768 m_xOverlineColorLB->SelectEntry(COL_AUTO);
1769 m_xOverlineColorLB->set_sensitive(false);
1774 // Strikeout
1775 nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT );
1776 rFont.SetStrikeout( STRIKEOUT_NONE );
1777 rCJKFont.SetStrikeout( STRIKEOUT_NONE );
1778 rCTLFont.SetStrikeout( STRIKEOUT_NONE );
1780 m_xStrikeoutLB->set_active( 0 );
1781 eState = rSet->GetItemState( nWhich );
1783 if ( eState >= SfxItemState::DONTCARE )
1785 if ( eState == SfxItemState::DONTCARE )
1786 m_xStrikeoutLB->set_active(-1);
1787 else
1789 const SvxCrossedOutItem& rItem = static_cast<const SvxCrossedOutItem&>(rSet->Get( nWhich ));
1790 FontStrikeout eStrikeout = rItem.GetValue();
1791 rFont.SetStrikeout( eStrikeout );
1792 rCJKFont.SetStrikeout( eStrikeout );
1793 rCTLFont.SetStrikeout( eStrikeout );
1795 if ( eStrikeout != STRIKEOUT_NONE )
1797 auto nPos = m_xStrikeoutLB->find_id(OUString::number(eStrikeout));
1798 if (nPos != -1)
1800 m_xStrikeoutLB->set_active(nPos);
1801 bEnable = true;
1807 // WordLineMode
1808 nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE );
1809 eState = rSet->GetItemState( nWhich );
1811 switch ( eState )
1813 case SfxItemState::UNKNOWN:
1814 m_aIndividualWordsState.bTriStateEnabled = false;
1815 m_xIndividualWordsBtn->hide();
1816 break;
1818 case SfxItemState::DISABLED:
1819 m_aIndividualWordsState.bTriStateEnabled = false;
1820 m_xIndividualWordsBtn->set_sensitive(false);
1821 break;
1823 case SfxItemState::DONTCARE:
1824 m_aIndividualWordsState.bTriStateEnabled = true;
1825 m_xIndividualWordsBtn->set_state( TRISTATE_INDET );
1826 break;
1828 case SfxItemState::DEFAULT:
1829 case SfxItemState::SET:
1831 const SvxWordLineModeItem& rItem = static_cast<const SvxWordLineModeItem&>(rSet->Get( nWhich ));
1832 rFont.SetWordLineMode( rItem.GetValue() );
1833 rCJKFont.SetWordLineMode( rItem.GetValue() );
1834 rCTLFont.SetWordLineMode( rItem.GetValue() );
1836 m_aIndividualWordsState.bTriStateEnabled = false;
1837 m_xIndividualWordsBtn->set_active(rItem.GetValue());
1838 m_xIndividualWordsBtn->set_sensitive(bEnable);
1839 break;
1843 // Emphasis
1844 nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK );
1845 eState = rSet->GetItemState( nWhich );
1847 if ( eState >= SfxItemState::DEFAULT )
1849 const SvxEmphasisMarkItem& rItem = static_cast<const SvxEmphasisMarkItem&>(rSet->Get( nWhich ));
1850 FontEmphasisMark eMark = rItem.GetEmphasisMark();
1851 rFont.SetEmphasisMark( eMark );
1852 rCJKFont.SetEmphasisMark( eMark );
1853 rCTLFont.SetEmphasisMark( eMark );
1855 m_xEmphasisLB->set_active( static_cast<sal_Int32>(FontEmphasisMark( eMark & FontEmphasisMark::Style )) );
1856 eMark &= ~FontEmphasisMark::Style;
1857 int nEntryData = ( eMark == FontEmphasisMark::PosAbove )
1858 ? CHRDLG_POSITION_OVER
1859 : ( eMark == FontEmphasisMark::PosBelow ) ? CHRDLG_POSITION_UNDER : 0;
1861 auto nPos = m_xPositionLB->find_id(OUString::number(nEntryData));
1862 if (nPos != -1)
1863 m_xPositionLB->set_active(nPos);
1865 else if ( eState == SfxItemState::DONTCARE )
1866 m_xEmphasisLB->set_active(-1);
1867 else if ( eState == SfxItemState::UNKNOWN )
1869 m_xEmphasisFT->hide();
1870 m_xEmphasisLB->hide();
1872 else // SfxItemState::DISABLED
1874 m_xEmphasisFT->set_sensitive(false);
1875 m_xEmphasisLB->set_sensitive(false);
1878 // the select handler for the underline/overline/strikeout list boxes
1879 SelectHdl_Impl(m_xUnderlineLB.get());
1881 // the select handler for the emphasis listbox
1882 SelectHdl_Impl(m_xEmphasisLB.get());
1884 // Effects
1885 SvxCaseMap eCaseMap = SvxCaseMap::End;
1886 nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP );
1887 eState = rSet->GetItemState( nWhich );
1888 switch ( eState )
1890 case SfxItemState::UNKNOWN:
1891 m_xEffectsFT->hide();
1892 m_xEffectsLB->hide();
1893 break;
1895 case SfxItemState::DISABLED:
1896 m_xEffectsFT->set_sensitive(false);
1897 m_xEffectsLB->set_sensitive(false);
1898 break;
1900 case SfxItemState::DONTCARE:
1901 m_xEffectsLB->set_active(-1);
1902 break;
1904 case SfxItemState::DEFAULT:
1905 case SfxItemState::SET:
1907 const SvxCaseMapItem& rItem = static_cast<const SvxCaseMapItem&>(rSet->Get( nWhich ));
1908 eCaseMap = rItem.GetValue();
1909 break;
1912 SetCaseMap_Impl( eCaseMap );
1914 //Relief
1915 nWhich = GetWhich(SID_ATTR_CHAR_RELIEF);
1916 eState = rSet->GetItemState( nWhich );
1917 switch ( eState )
1919 case SfxItemState::UNKNOWN:
1920 m_xReliefFT->hide();
1921 m_xReliefLB->hide();
1922 break;
1924 case SfxItemState::DISABLED:
1925 m_xReliefFT->set_sensitive(false);
1926 m_xReliefLB->set_sensitive(false);
1927 break;
1929 case SfxItemState::DONTCARE:
1930 m_xReliefLB->set_active(-1);
1931 break;
1933 case SfxItemState::DEFAULT:
1934 case SfxItemState::SET:
1936 const SvxCharReliefItem& rItem = static_cast<const SvxCharReliefItem&>(rSet->Get( nWhich ));
1937 m_xReliefLB->set_active(static_cast<sal_Int32>(rItem.GetValue()));
1938 SelectHdl_Impl(m_xReliefLB.get());
1939 break;
1943 // Outline
1944 nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR );
1945 eState = rSet->GetItemState( nWhich );
1946 switch ( eState )
1948 case SfxItemState::UNKNOWN:
1949 m_aOutlineState.bTriStateEnabled = false;
1950 m_xOutlineBtn->hide();
1951 break;
1953 case SfxItemState::DISABLED:
1954 m_aOutlineState.bTriStateEnabled = false;
1955 m_xOutlineBtn->set_sensitive(false);
1956 break;
1958 case SfxItemState::DONTCARE:
1959 m_aOutlineState.bTriStateEnabled = true;
1960 m_xOutlineBtn->set_state(TRISTATE_INDET);
1961 break;
1963 case SfxItemState::DEFAULT:
1964 case SfxItemState::SET:
1966 const SvxContourItem& rItem = static_cast<const SvxContourItem&>(rSet->Get( nWhich ));
1967 m_aOutlineState.bTriStateEnabled = false;
1968 m_xOutlineBtn->set_state(static_cast<TriState>(rItem.GetValue()));
1969 break;
1973 // Shadow
1974 nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED );
1975 eState = rSet->GetItemState( nWhich );
1977 switch ( eState )
1979 case SfxItemState::UNKNOWN:
1980 m_aShadowState.bTriStateEnabled = false;
1981 m_xShadowBtn->hide();
1982 break;
1984 case SfxItemState::DISABLED:
1985 m_aShadowState.bTriStateEnabled = false;
1986 m_xShadowBtn->set_sensitive(false);
1987 break;
1989 case SfxItemState::DONTCARE:
1990 m_aShadowState.bTriStateEnabled = true;
1991 m_xShadowBtn->set_state( TRISTATE_INDET );
1992 break;
1994 case SfxItemState::DEFAULT:
1995 case SfxItemState::SET:
1997 const SvxShadowedItem& rItem = static_cast<const SvxShadowedItem&>(rSet->Get( nWhich ));
1998 m_aShadowState.bTriStateEnabled = false;
1999 m_xShadowBtn->set_state( static_cast<TriState>(rItem.GetValue()) );
2000 break;
2004 // Hidden
2005 nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN );
2006 eState = rSet->GetItemState( nWhich );
2008 switch ( eState )
2010 case SfxItemState::UNKNOWN:
2011 m_aHiddenState.bTriStateEnabled = false;
2012 m_xHiddenBtn->hide();
2013 break;
2015 case SfxItemState::DISABLED:
2016 m_aHiddenState.bTriStateEnabled = false;
2017 m_xHiddenBtn->set_sensitive(false);
2018 break;
2020 case SfxItemState::DONTCARE:
2021 m_aHiddenState.bTriStateEnabled = true;
2022 m_xHiddenBtn->set_state(TRISTATE_INDET);
2023 break;
2025 case SfxItemState::DEFAULT:
2026 case SfxItemState::SET:
2028 const SvxCharHiddenItem& rItem = static_cast<const SvxCharHiddenItem&>(rSet->Get( nWhich ));
2029 m_aHiddenState.bTriStateEnabled = false;
2030 m_xHiddenBtn->set_state(static_cast<TriState>(rItem.GetValue()));
2031 break;
2035 SetPrevFontWidthScale( *rSet );
2036 ResetColor_Impl( *rSet );
2038 // preview update
2039 m_aPreviewWin.Invalidate();
2041 // save this settings
2042 ChangesApplied();
2045 IMPL_LINK(SvxCharEffectsPage, HiddenBtnClickHdl, weld::Toggleable&, rToggle, void)
2047 m_aHiddenState.ButtonToggled(rToggle);
2050 IMPL_LINK(SvxCharEffectsPage, OutlineBtnClickHdl, weld::Toggleable&, rToggle, void)
2052 m_aOutlineState.ButtonToggled(rToggle);
2053 UpdatePreview_Impl();
2056 IMPL_LINK(SvxCharEffectsPage, ShadowBtnClickHdl, weld::Toggleable&, rToggle, void)
2058 m_aShadowState.ButtonToggled(rToggle);
2059 UpdatePreview_Impl();
2062 void SvxCharEffectsPage::ChangesApplied()
2064 m_xUnderlineLB->save_value();
2065 m_xOverlineLB->save_value();
2066 m_xStrikeoutLB->save_value();
2067 m_xIndividualWordsBtn->save_state();
2068 m_xEmphasisLB->save_value();
2069 m_xPositionLB->save_value();
2070 m_xEffectsLB->save_value();
2071 m_xReliefLB->save_value();
2072 m_xOutlineBtn->save_state();
2073 m_xShadowBtn->save_state();
2074 m_xHiddenBtn->save_state();
2075 m_xFontTransparencyMtr->save_value();
2078 bool SvxCharEffectsPage::FillItemSet( SfxItemSet* rSet )
2080 const SfxPoolItem* pOld = nullptr;
2081 const SfxItemSet& rOldSet = GetItemSet();
2082 bool bModified = false;
2083 bool bChanged = true;
2085 // Underline
2086 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE );
2087 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_UNDERLINE );
2088 auto nPos = m_xUnderlineLB->get_active();
2089 FontLineStyle eUnder = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32());
2091 if ( pOld )
2093 //! if there are different underline styles in the selection the
2094 //! item-state in the 'rOldSet' will be invalid. In this case
2095 //! changing the underline style will be allowed if a style is
2096 //! selected in the listbox.
2097 bool bAllowChange = nPos != -1 &&
2098 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2100 const SvxUnderlineItem& rItem = *static_cast<const SvxUnderlineItem*>(pOld);
2101 if (rItem.GetValue() == eUnder &&
2102 (LINESTYLE_NONE == eUnder || (rItem.GetColor() == m_xUnderlineColorLB->GetSelectEntryColor() &&
2103 rItem.getComplexColor() == m_xUnderlineColorLB->GetSelectedEntry().getComplexColor())) &&
2104 !bAllowChange)
2106 bChanged = false;
2110 if ( bChanged )
2112 SvxUnderlineItem aNewItem( eUnder, nWhich );
2113 auto aNamedColor = m_xUnderlineColorLB->GetSelectedEntry();
2114 aNewItem.SetColor(aNamedColor.m_aColor);
2115 aNewItem.setComplexColor(aNamedColor.getComplexColor());
2116 rSet->Put(aNewItem);
2117 bModified = true;
2119 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2120 rSet->InvalidateItem(nWhich);
2122 bChanged = true;
2124 // Overline
2125 nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE );
2126 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_OVERLINE );
2127 nPos = m_xOverlineLB->get_active();
2128 FontLineStyle eOver = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32());
2130 if ( pOld )
2132 //! if there are different underline styles in the selection the
2133 //! item-state in the 'rOldSet' will be invalid. In this case
2134 //! changing the underline style will be allowed if a style is
2135 //! selected in the listbox.
2136 bool bAllowChange = nPos != -1 &&
2137 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2139 const SvxOverlineItem& rItem = *static_cast<const SvxOverlineItem*>(pOld);
2140 if (rItem.GetValue() == eOver &&
2141 (LINESTYLE_NONE == eOver || (rItem.GetColor() == m_xOverlineColorLB->GetSelectEntryColor() &&
2142 rItem.getComplexColor() == m_xOverlineColorLB->GetSelectedEntry().getComplexColor())) &&
2143 !bAllowChange)
2145 bChanged = false;
2149 if ( bChanged )
2151 SvxOverlineItem aNewItem( eOver, nWhich );
2152 auto aNamedColor = m_xOverlineColorLB->GetSelectedEntry();
2153 aNewItem.SetColor(aNamedColor.m_aColor);
2154 aNewItem.setComplexColor(aNamedColor.getComplexColor());
2155 rSet->Put(aNewItem);
2156 bModified = true;
2158 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2159 rSet->InvalidateItem(nWhich);
2161 bChanged = true;
2163 // Strikeout
2164 nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT );
2165 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_STRIKEOUT );
2166 nPos = m_xStrikeoutLB->get_active();
2167 FontStrikeout eStrike = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32());
2169 if ( pOld )
2171 //! if there are different strikeout styles in the selection the
2172 //! item-state in the 'rOldSet' will be invalid. In this case
2173 //! changing the strikeout style will be allowed if a style is
2174 //! selected in the listbox.
2175 bool bAllowChg = nPos != -1 &&
2176 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2178 const SvxCrossedOutItem& rItem = *static_cast<const SvxCrossedOutItem*>(pOld);
2179 if ( !m_xStrikeoutLB->get_sensitive()
2180 || (rItem.GetValue() == eStrike && !bAllowChg) )
2181 bChanged = false;
2184 if ( bChanged )
2186 rSet->Put( SvxCrossedOutItem( eStrike, nWhich ) );
2187 bModified = true;
2189 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2190 rSet->InvalidateItem(nWhich);
2192 bChanged = true;
2194 // Individual words
2195 const SfxItemSet* pExampleSet = GetDialogExampleSet();
2196 nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE );
2197 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_WORDLINEMODE );
2198 TriState eState = m_xIndividualWordsBtn->get_state();
2199 const SfxPoolItem* pItem;
2201 if ( pOld )
2203 const SvxWordLineModeItem& rItem = *static_cast<const SvxWordLineModeItem*>(pOld);
2204 if ( rItem.GetValue() == StateToAttr( eState ) && m_xIndividualWordsBtn->get_saved_state() == eState )
2205 bChanged = false;
2208 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2209 !StateToAttr( eState ) && static_cast<const SvxWordLineModeItem*>(pItem)->GetValue() )
2210 bChanged = true;
2212 if ( bChanged && eState != TRISTATE_INDET )
2214 rSet->Put( SvxWordLineModeItem( StateToAttr( eState ), nWhich ) );
2215 bModified = true;
2217 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2218 rSet->InvalidateItem(nWhich);
2220 bChanged = true;
2222 // Emphasis
2223 nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK );
2224 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_EMPHASISMARK );
2225 int nMarkPos = m_xEmphasisLB->get_active();
2226 OUString sMarkPos = m_xEmphasisLB->get_active_text();
2227 OUString sPosPos = m_xPositionLB->get_active_text();
2228 FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nMarkPos);
2229 if (m_xPositionLB->get_sensitive())
2231 eMark |= (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32())
2232 ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove;
2235 if ( pOld )
2237 if( rOldSet.GetItemState( nWhich ) != SfxItemState::DONTCARE )
2239 const SvxEmphasisMarkItem& rItem = *static_cast<const SvxEmphasisMarkItem*>(pOld);
2240 if ( rItem.GetEmphasisMark() == eMark )
2241 bChanged = false;
2245 if (rOldSet.GetItemState( nWhich ) == SfxItemState::DONTCARE &&
2246 m_xEmphasisLB->get_saved_value() == sMarkPos && m_xPositionLB->get_saved_value() == sPosPos)
2248 bChanged = false;
2251 if (bChanged)
2253 rSet->Put( SvxEmphasisMarkItem( eMark, TypedWhichId<SvxEmphasisMarkItem>(nWhich) ) );
2254 bModified = true;
2256 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2257 rSet->InvalidateItem(nWhich);
2259 bChanged = true;
2261 // Effects
2262 nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP );
2263 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CASEMAP );
2264 SvxCaseMap eCaseMap = SvxCaseMap::NotMapped;
2265 bool bChecked = false;
2266 auto nCapsPos = m_xEffectsLB->get_active();
2267 if (nCapsPos != -1)
2269 eCaseMap = static_cast<SvxCaseMap>(nCapsPos);
2270 bChecked = true;
2273 if ( pOld )
2275 //! if there are different effect styles in the selection the
2276 //! item-state in the 'rOldSet' will be invalid. In this case
2277 //! changing the effect style will be allowed if a style is
2278 //! selected in the listbox.
2279 bool bAllowChg = nPos != -1 &&
2280 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2282 const SvxCaseMapItem& rItem = *static_cast<const SvxCaseMapItem*>(pOld);
2283 if ( rItem.GetValue() == eCaseMap && !bAllowChg )
2284 bChanged = false;
2287 if ( bChanged && bChecked )
2289 rSet->Put( SvxCaseMapItem( eCaseMap, nWhich ) );
2290 bModified = true;
2292 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2293 rSet->InvalidateItem(nWhich);
2295 bChanged = true;
2297 //Relief
2298 nWhich = GetWhich(SID_ATTR_CHAR_RELIEF);
2299 if (m_xReliefLB->get_value_changed_from_saved())
2301 m_xReliefLB->save_value();
2302 SvxCharReliefItem aRelief(static_cast<FontRelief>(m_xReliefLB->get_active()), nWhich);
2303 rSet->Put(aRelief);
2306 // Outline
2307 nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR );
2308 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CONTOUR );
2309 eState = m_xOutlineBtn->get_state();
2311 if ( pOld )
2313 const SvxContourItem& rItem = *static_cast<const SvxContourItem*>(pOld);
2314 if ( rItem.GetValue() == StateToAttr( eState ) && m_xOutlineBtn->get_saved_state() == eState )
2315 bChanged = false;
2318 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2319 !StateToAttr( eState ) && static_cast<const SvxContourItem*>(pItem)->GetValue() )
2320 bChanged = true;
2322 if ( bChanged && eState != TRISTATE_INDET )
2324 rSet->Put( SvxContourItem( StateToAttr( eState ), nWhich ) );
2325 bModified = true;
2327 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2328 rSet->InvalidateItem(nWhich);
2330 bChanged = true;
2332 // Shadow
2333 nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED );
2334 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_SHADOWED );
2335 eState = m_xShadowBtn->get_state();
2337 if ( pOld )
2339 const SvxShadowedItem& rItem = *static_cast<const SvxShadowedItem*>(pOld);
2340 if ( rItem.GetValue() == StateToAttr( eState ) && m_xShadowBtn->get_saved_state() == eState )
2341 bChanged = false;
2344 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2345 !StateToAttr( eState ) && static_cast<const SvxShadowedItem*>(pItem)->GetValue() )
2346 bChanged = true;
2348 if ( bChanged && eState != TRISTATE_INDET )
2350 rSet->Put( SvxShadowedItem( StateToAttr( eState ), nWhich ) );
2351 bModified = true;
2353 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2354 rSet->InvalidateItem(nWhich);
2356 bChanged = true;
2358 // Hidden
2359 nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN );
2360 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_HIDDEN );
2361 eState = m_xHiddenBtn->get_state();
2362 bChanged = true;
2364 if ( pOld )
2366 const SvxCharHiddenItem& rItem = *static_cast<const SvxCharHiddenItem*>(pOld);
2367 if ( rItem.GetValue() == StateToAttr( eState ) && m_xHiddenBtn->get_saved_state() == eState )
2368 bChanged = false;
2371 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2372 !StateToAttr( eState ) && static_cast<const SvxCharHiddenItem*>(pItem)->GetValue() )
2373 bChanged = true;
2375 if ( bChanged && eState != TRISTATE_INDET )
2377 rSet->Put( SvxCharHiddenItem( StateToAttr( eState ), nWhich ) );
2378 bModified = true;
2380 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2381 rSet->InvalidateItem(nWhich);
2383 bModified |= FillItemSetColor_Impl( *rSet );
2385 return bModified;
2388 void SvxCharEffectsPage::DisableControls( sal_uInt16 nDisable )
2390 if ( ( DISABLE_CASEMAP & nDisable ) == DISABLE_CASEMAP )
2392 m_xEffectsFT->set_sensitive(false);
2393 m_xEffectsLB->set_sensitive(false);
2397 void SvxCharEffectsPage::PageCreated(const SfxAllItemSet& aSet)
2399 const SfxUInt16Item* pDisableCtlItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false);
2400 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
2401 if (pDisableCtlItem)
2402 DisableControls(pDisableCtlItem->GetValue());
2404 sal_uInt32 nFlags = pFlagItem ? pFlagItem->GetValue() : 0;
2405 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
2406 // the writer uses SID_ATTR_BRUSH as font background
2407 m_bPreviewBackgroundToCharacter = true;
2408 if ((nFlags & SVX_ENABLE_CHAR_TRANSPARENCY) != SVX_ENABLE_CHAR_TRANSPARENCY)
2410 // Only show these in case client code explicitly wants this.
2411 m_xFontTransparencyFT->hide();
2412 m_xFontTransparencyMtr->hide();
2416 // class SvxCharPositionPage ---------------------------------------------
2418 SvxCharPositionPage::SvxCharPositionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
2419 : SvxCharBasePage(pPage, pController, "cui/ui/positionpage.ui", "PositionPage", rInSet)
2420 , m_nSuperEsc(short(DFLT_ESC_SUPER))
2421 , m_nSubEsc(short(DFLT_ESC_SUB))
2422 , m_nScaleWidthItemSetVal(100)
2423 , m_nScaleWidthInitialVal(100)
2424 , m_nSuperProp(sal_uInt8(DFLT_ESC_PROP))
2425 , m_nSubProp(sal_uInt8(DFLT_ESC_PROP))
2426 , m_xHighPosBtn(m_xBuilder->weld_radio_button("superscript"))
2427 , m_xNormalPosBtn(m_xBuilder->weld_radio_button("normal"))
2428 , m_xLowPosBtn(m_xBuilder->weld_radio_button("subscript"))
2429 , m_xHighLowFT(m_xBuilder->weld_label("raiselower"))
2430 , m_xHighLowMF(m_xBuilder->weld_metric_spin_button("raiselowersb", FieldUnit::PERCENT))
2431 , m_xHighLowRB(m_xBuilder->weld_check_button("automatic"))
2432 , m_xFontSizeFT(m_xBuilder->weld_label("relativefontsize"))
2433 , m_xFontSizeMF(m_xBuilder->weld_metric_spin_button("fontsizesb", FieldUnit::PERCENT))
2434 , m_xRotationContainer(m_xBuilder->weld_widget("rotationcontainer"))
2435 , m_xScalingFT(m_xBuilder->weld_label("scale"))
2436 , m_xScalingAndRotationFT(m_xBuilder->weld_label("rotateandscale"))
2437 , m_x0degRB(m_xBuilder->weld_radio_button("0deg"))
2438 , m_x90degRB(m_xBuilder->weld_radio_button("90deg"))
2439 , m_x270degRB(m_xBuilder->weld_radio_button("270deg"))
2440 , m_xFitToLineCB(m_xBuilder->weld_check_button("fittoline"))
2441 , m_xScaleWidthMF(m_xBuilder->weld_metric_spin_button("scalewidthsb", FieldUnit::PERCENT))
2442 , m_xKerningMF(m_xBuilder->weld_metric_spin_button("kerningsb", FieldUnit::POINT))
2443 , m_xPairKerningBtn(m_xBuilder->weld_check_button("pairkerning"))
2445 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
2446 #ifdef IOS
2447 m_xPreviewWin->hide();
2448 #endif
2449 Initialize();
2452 SvxCharPositionPage::~SvxCharPositionPage()
2457 void SvxCharPositionPage::Initialize()
2459 // to handle the changes of the other pages
2460 SetExchangeSupport();
2462 GetPreviewFont().SetFontSize( Size( 0, 240 ) );
2463 GetPreviewCJKFont().SetFontSize( Size( 0, 240 ) );
2464 GetPreviewCTLFont().SetFontSize( Size( 0, 240 ) );
2466 m_xNormalPosBtn->set_active(true);
2467 PositionHdl_Impl(*m_xNormalPosBtn);
2469 Link<weld::Toggleable&,void> aLink2 = LINK(this, SvxCharPositionPage, PositionHdl_Impl);
2470 m_xHighPosBtn->connect_toggled(aLink2);
2471 m_xNormalPosBtn->connect_toggled(aLink2);
2472 m_xLowPosBtn->connect_toggled(aLink2);
2474 aLink2 = LINK( this, SvxCharPositionPage, RotationHdl_Impl );
2475 m_x0degRB->connect_toggled(aLink2);
2476 m_x90degRB->connect_toggled(aLink2);
2477 m_x270degRB->connect_toggled(aLink2);
2479 Link<weld::MetricSpinButton&,void> aLink3 = LINK(this, SvxCharPositionPage, ValueChangedHdl_Impl);
2480 m_xHighLowMF->connect_value_changed(aLink3);
2481 m_xFontSizeMF->connect_value_changed(aLink3);
2483 m_xHighLowRB->connect_toggled(LINK(this, SvxCharPositionPage, AutoPositionHdl_Impl));
2484 m_xFitToLineCB->connect_toggled(LINK(this, SvxCharPositionPage, FitToLineHdl_Impl));
2485 m_xKerningMF->connect_value_changed(LINK(this, SvxCharPositionPage, KerningModifyHdl_Impl));
2486 m_xScaleWidthMF->connect_value_changed(LINK(this, SvxCharPositionPage, ScaleWidthModifyHdl_Impl));
2489 void SvxCharPositionPage::UpdatePreview_Impl( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
2491 SetPrevFontEscapement( nProp, nEscProp, nEsc );
2495 void SvxCharPositionPage::SetEscapement_Impl( SvxEscapement nEsc )
2497 SvxEscapementItem aEscItm( nEsc, SID_ATTR_CHAR_ESCAPEMENT );
2499 if ( SvxEscapement::Superscript == nEsc )
2501 aEscItm.GetEsc() = m_nSuperEsc;
2502 aEscItm.GetProportionalHeight() = m_nSuperProp;
2504 else if ( SvxEscapement::Subscript == nEsc )
2506 aEscItm.GetEsc() = m_nSubEsc;
2507 aEscItm.GetProportionalHeight() = m_nSubProp;
2510 short nFac = aEscItm.GetEsc() < 0 ? -1 : 1;
2512 m_xHighLowMF->set_value(aEscItm.GetEsc() * nFac, FieldUnit::PERCENT);
2513 m_xFontSizeMF->set_value(aEscItm.GetProportionalHeight(), FieldUnit::PERCENT);
2515 if ( SvxEscapement::Off == nEsc )
2517 m_xHighLowFT->set_sensitive(false);
2518 m_xHighLowMF->set_sensitive(false);
2519 m_xFontSizeFT->set_sensitive(false);
2520 m_xFontSizeMF->set_sensitive(false);
2521 m_xHighLowRB->set_sensitive(false);
2523 else
2525 m_xFontSizeFT->set_sensitive(true);
2526 m_xFontSizeMF->set_sensitive(true);
2527 m_xHighLowRB->set_sensitive(true);
2529 if (!m_xHighLowRB->get_active())
2531 m_xHighLowFT->set_sensitive(true);
2532 m_xHighLowMF->set_sensitive(true);
2534 else
2535 AutoPositionHdl_Impl(*m_xHighLowRB);
2538 UpdatePreview_Impl( 100, aEscItm.GetProportionalHeight(), aEscItm.GetEsc() );
2542 IMPL_LINK_NOARG(SvxCharPositionPage, PositionHdl_Impl, weld::Toggleable&, void)
2544 SvxEscapement nEsc = SvxEscapement::Off; // also when pBtn == NULL
2546 if (m_xHighPosBtn->get_active())
2547 nEsc = SvxEscapement::Superscript;
2548 else if (m_xLowPosBtn->get_active())
2549 nEsc = SvxEscapement::Subscript;
2551 SetEscapement_Impl( nEsc );
2554 IMPL_LINK_NOARG(SvxCharPositionPage, RotationHdl_Impl, weld::Toggleable&, void)
2556 bool bEnable = false;
2557 if (m_x90degRB->get_active() || m_x270degRB->get_active())
2558 bEnable = true;
2559 else
2560 OSL_ENSURE(m_x0degRB->get_active(), "unexpected button");
2561 m_xFitToLineCB->set_sensitive(bEnable);
2564 void SvxCharPositionPage::FontModifyHdl_Impl()
2566 sal_uInt8 nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
2567 short nEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT));
2568 nEsc *= m_xLowPosBtn->get_active() ? -1 : 1;
2569 UpdatePreview_Impl( 100, nEscProp, nEsc );
2572 IMPL_LINK(SvxCharPositionPage, AutoPositionHdl_Impl, weld::Toggleable&, rBox, void)
2574 if (rBox.get_active())
2576 m_xHighLowFT->set_sensitive(false);
2577 m_xHighLowMF->set_sensitive(false);
2579 else
2580 PositionHdl_Impl(m_xHighPosBtn->get_active() ? *m_xHighPosBtn
2581 : m_xLowPosBtn->get_active() ? *m_xLowPosBtn
2582 : *m_xNormalPosBtn);
2585 IMPL_LINK_NOARG(SvxCharPositionPage, FitToLineHdl_Impl, weld::Toggleable&, void)
2587 sal_uInt16 nVal = m_nScaleWidthInitialVal;
2588 if (m_xFitToLineCB->get_active())
2589 nVal = m_nScaleWidthItemSetVal;
2590 m_xScaleWidthMF->set_value(nVal, FieldUnit::PERCENT);
2591 m_aPreviewWin.SetFontWidthScale( nVal );
2594 IMPL_LINK_NOARG(SvxCharPositionPage, KerningModifyHdl_Impl, weld::MetricSpinButton&, void)
2596 tools::Long nVal = static_cast<tools::Long>(m_xKerningMF->get_value(FieldUnit::POINT));
2597 nVal = o3tl::convert(nVal, o3tl::Length::pt, o3tl::Length::twip);
2599 tools::Long nKern = static_cast<short>(m_xKerningMF->denormalize(nVal));
2601 SvxFont& rFont = GetPreviewFont();
2602 SvxFont& rCJKFont = GetPreviewCJKFont();
2603 SvxFont& rCTLFont = GetPreviewCTLFont();
2605 rFont.SetFixKerning( static_cast<short>(nKern) );
2606 rCJKFont.SetFixKerning( static_cast<short>(nKern) );
2607 rCTLFont.SetFixKerning( static_cast<short>(nKern) );
2608 m_aPreviewWin.Invalidate();
2611 IMPL_LINK(SvxCharPositionPage, ValueChangedHdl_Impl, weld::MetricSpinButton&, rField, void)
2613 bool bHigh = m_xHighPosBtn->get_active();
2614 bool bLow = m_xLowPosBtn->get_active();
2615 DBG_ASSERT( bHigh || bLow, "normal position is not valid" );
2617 if (m_xHighLowMF.get() == &rField)
2619 if ( bLow )
2620 m_nSubEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT)) * -1;
2621 else
2622 m_nSuperEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT));
2624 else if (m_xFontSizeMF.get() == &rField)
2626 if ( bLow )
2627 m_nSubProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
2628 else
2629 m_nSuperProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
2632 FontModifyHdl_Impl();
2635 IMPL_LINK_NOARG(SvxCharPositionPage, ScaleWidthModifyHdl_Impl, weld::MetricSpinButton&, void)
2637 m_aPreviewWin.SetFontWidthScale(sal_uInt16(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)));
2640 DeactivateRC SvxCharPositionPage::DeactivatePage( SfxItemSet* _pSet )
2642 if ( _pSet )
2643 FillItemSet( _pSet );
2644 return DeactivateRC::LeavePage;
2647 std::unique_ptr<SfxTabPage> SvxCharPositionPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
2649 return std::make_unique<SvxCharPositionPage>(pPage, pController, *rSet);
2652 void SvxCharPositionPage::Reset( const SfxItemSet* rSet )
2654 OUString sUser = GetUserData();
2656 if ( !sUser.isEmpty() )
2658 sal_Int32 nIdx {0};
2659 m_nSuperEsc = static_cast<short>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
2660 m_nSubEsc = static_cast<short>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
2661 m_nSuperProp = static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
2662 m_nSubProp = static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
2664 m_xHighLowMF->set_max(MAX_ESC_POS, FieldUnit::PERCENT);
2666 //fdo#75307 validate all the entries and discard all of them if any are
2667 //out of range
2668 bool bValid = true;
2669 if (m_nSuperEsc < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSuperEsc > m_xHighLowMF->get_max(FieldUnit::PERCENT))
2670 bValid = false;
2671 if (m_nSubEsc*-1 < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSubEsc*-1 > m_xHighLowMF->get_max(FieldUnit::PERCENT))
2672 bValid = false;
2673 if (m_nSuperProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSuperProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT))
2674 bValid = false;
2675 if (m_nSubProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSubProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT))
2676 bValid = false;
2678 if (!bValid)
2680 m_nSuperEsc = DFLT_ESC_SUPER;
2681 m_nSubEsc = DFLT_ESC_SUB;
2682 m_nSuperProp = DFLT_ESC_PROP;
2683 m_nSubProp = DFLT_ESC_PROP;
2687 short nEsc = 0;
2688 sal_uInt8 nEscProp = 100;
2690 m_xHighLowFT->set_sensitive(false);
2691 m_xHighLowMF->set_sensitive(false);
2692 m_xFontSizeFT->set_sensitive(false);
2693 m_xFontSizeMF->set_sensitive(false);
2695 SvxFont& rFont = GetPreviewFont();
2696 SvxFont& rCJKFont = GetPreviewCJKFont();
2697 SvxFont& rCTLFont = GetPreviewCTLFont();
2698 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT );
2700 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2702 const SvxEscapementItem& rItem = static_cast<const SvxEscapementItem&>(rSet->Get( nWhich ));
2703 nEsc = rItem.GetEsc();
2704 nEscProp = rItem.GetProportionalHeight();
2706 if ( nEsc != 0 )
2708 m_xHighLowFT->set_sensitive(true);
2709 m_xHighLowMF->set_sensitive(true);
2710 m_xFontSizeFT->set_sensitive(true);
2711 m_xFontSizeMF->set_sensitive(true);
2713 short nFac;
2714 bool bAutomatic(false);
2716 if ( nEsc > 0 )
2718 nFac = 1;
2719 m_xHighPosBtn->set_active(true);
2720 if ( nEsc == DFLT_ESC_AUTO_SUPER )
2722 nEsc = .8 * (100 - nEscProp); //approximation of actual percentage used
2723 bAutomatic = true;
2726 else
2728 nFac = -1;
2729 m_xLowPosBtn->set_active(true);
2730 if ( nEsc == DFLT_ESC_AUTO_SUB )
2732 nEsc = .2 * -(100 - nEscProp); //approximation of actual percentage used
2733 bAutomatic = true;
2736 if (!m_xHighLowRB->get_sensitive())
2738 m_xHighLowRB->set_sensitive(true);
2740 m_xHighLowRB->set_active(bAutomatic);
2742 if (m_xHighLowRB->get_active())
2744 m_xHighLowFT->set_sensitive(false);
2745 m_xHighLowMF->set_sensitive(false);
2747 m_xHighLowMF->set_value(m_xHighLowMF->normalize(nFac * nEsc), FieldUnit::PERCENT);
2749 else
2751 m_xNormalPosBtn->set_active(true);
2752 m_xHighLowRB->set_active(true);
2753 PositionHdl_Impl(*m_xNormalPosBtn);
2755 //the height has to be set after the handler is called to keep the value also if the escapement is zero
2756 m_xFontSizeMF->set_value(m_xFontSizeMF->normalize(nEscProp), FieldUnit::PERCENT);
2758 else
2760 m_xHighPosBtn->set_active(false);
2761 m_xNormalPosBtn->set_active(false);
2762 m_xLowPosBtn->set_active(false);
2765 // set BspFont
2766 SetPrevFontEscapement( 100, nEscProp, nEsc );
2768 // Kerning
2769 nWhich = GetWhich( SID_ATTR_CHAR_KERNING );
2771 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2773 const SvxKerningItem& rItem = static_cast<const SvxKerningItem&>(rSet->Get( nWhich ));
2774 MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich );
2775 tools::Long nBig = static_cast<tools::Long>(m_xKerningMF->normalize( static_cast<tools::Long>(rItem.GetValue()) ));
2776 tools::Long nKerning = OutputDevice::LogicToLogic(nBig, eUnit, MapUnit::MapPoint);
2778 // set Kerning at the Font, convert into Twips before
2779 tools::Long nKern = OutputDevice::LogicToLogic(rItem.GetValue(), eUnit, MapUnit::MapTwip);
2780 rFont.SetFixKerning( static_cast<short>(nKern) );
2781 rCJKFont.SetFixKerning( static_cast<short>(nKern) );
2782 rCTLFont.SetFixKerning( static_cast<short>(nKern) );
2784 //the attribute value must be displayed also if it's above/below the maximum allowed value
2785 tools::Long nVal = static_cast<tools::Long>(m_xKerningMF->get_max(FieldUnit::POINT));
2786 if(nVal < nKerning)
2787 m_xKerningMF->set_max(nKerning, FieldUnit::POINT);
2788 nVal = static_cast<tools::Long>(m_xKerningMF->get_min(FieldUnit::POINT));
2789 if (nVal > nKerning)
2790 m_xKerningMF->set_min(nKerning, FieldUnit::POINT);
2791 m_xKerningMF->set_value(nKerning, FieldUnit::POINT);
2793 else
2794 m_xKerningMF->set_text(OUString());
2796 // Pair kerning
2797 nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN );
2799 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2801 const SvxAutoKernItem& rItem = static_cast<const SvxAutoKernItem&>(rSet->Get( nWhich ));
2802 m_xPairKerningBtn->set_active(rItem.GetValue());
2804 else
2805 m_xPairKerningBtn->set_active(false);
2807 // Scale Width
2808 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
2809 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2811 const SvxCharScaleWidthItem& rItem = static_cast<const SvxCharScaleWidthItem&>( rSet->Get( nWhich ) );
2812 m_nScaleWidthInitialVal = rItem.GetValue();
2813 m_xScaleWidthMF->set_value(m_nScaleWidthInitialVal, FieldUnit::PERCENT);
2815 else
2816 m_xScaleWidthMF->set_value(100, FieldUnit::PERCENT);
2818 if ( rSet->GetItemState( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ) >= SfxItemState::DEFAULT )
2819 m_nScaleWidthItemSetVal = rSet->Get( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ).GetValue();
2821 // Rotation
2822 nWhich = GetWhich( SID_ATTR_CHAR_ROTATED );
2823 SfxItemState eState = rSet->GetItemState( nWhich );
2824 if( SfxItemState::UNKNOWN == eState )
2826 m_xRotationContainer->hide();
2827 m_xScalingAndRotationFT->hide();
2828 m_xScalingFT->show();
2830 else
2832 m_xRotationContainer->show();
2833 m_xScalingAndRotationFT->show();
2834 m_xScalingFT->hide();
2836 if( eState >= SfxItemState::DEFAULT )
2838 const SvxCharRotateItem& rItem =
2839 static_cast<const SvxCharRotateItem&>( rSet->Get( nWhich ));
2840 if (rItem.IsBottomToTop())
2841 m_x90degRB->set_active(true);
2842 else if (rItem.IsTopToBottom())
2843 m_x270degRB->set_active(true);
2844 else
2846 DBG_ASSERT( 0_deg10 == rItem.GetValue(), "incorrect value" );
2847 m_x0degRB->set_active(true);
2849 m_xFitToLineCB->set_active(rItem.IsFitToLine());
2851 else
2853 if( eState == SfxItemState::DONTCARE )
2855 m_x0degRB->set_active(false);
2856 m_x90degRB->set_active(false);
2857 m_x270degRB->set_active(false);
2859 else
2860 m_x0degRB->set_active(true);
2862 m_xFitToLineCB->set_active(false);
2864 m_xFitToLineCB->set_sensitive(!m_x0degRB->get_active());
2866 // is this value set?
2867 if( SfxItemState::UNKNOWN == rSet->GetItemState(
2868 SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ))
2869 m_xFitToLineCB->hide();
2871 ChangesApplied();
2874 void SvxCharPositionPage::ChangesApplied()
2876 m_xHighPosBtn->save_state();
2877 m_xNormalPosBtn->save_state();
2878 m_xLowPosBtn->save_state();
2879 m_xHighLowRB->save_state();
2880 m_x0degRB->save_state();
2881 m_x90degRB->save_state();
2882 m_x270degRB->save_state();
2883 m_xFitToLineCB->save_state();
2884 m_xScaleWidthMF->save_value();
2885 m_xKerningMF->save_value();
2886 m_xPairKerningBtn->save_state();
2889 bool SvxCharPositionPage::FillItemSet( SfxItemSet* rSet )
2891 // Position (high, normal or low)
2892 const SfxItemSet& rOldSet = GetItemSet();
2893 bool bModified = false, bChanged = true;
2894 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT );
2895 const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_ESCAPEMENT );
2896 const bool bHigh = m_xHighPosBtn->get_active();
2897 short nEsc;
2898 sal_uInt8 nEscProp;
2900 if (bHigh || m_xLowPosBtn->get_active())
2902 if (m_xHighLowRB->get_active())
2903 nEsc = bHigh ? DFLT_ESC_AUTO_SUPER : DFLT_ESC_AUTO_SUB;
2904 else
2906 nEsc = static_cast<short>(m_xHighLowMF->denormalize(m_xHighLowMF->get_value(FieldUnit::PERCENT)));
2907 nEsc *= (bHigh ? 1 : -1);
2909 nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->denormalize(m_xFontSizeMF->get_value(FieldUnit::PERCENT)));
2911 else
2913 nEsc = 0;
2914 nEscProp = 100;
2917 if ( pOld )
2919 const SvxEscapementItem& rItem = *static_cast<const SvxEscapementItem*>(pOld);
2920 if (rItem.GetEsc() == nEsc && rItem.GetProportionalHeight() == nEscProp)
2921 bChanged = false;
2924 if ( !bChanged && !m_xHighPosBtn->get_saved_state() &&
2925 !m_xNormalPosBtn->get_saved_state() && !m_xLowPosBtn->get_saved_state() )
2926 bChanged = true;
2928 if ( bChanged &&
2929 ( m_xHighPosBtn->get_active() || m_xNormalPosBtn->get_active() || m_xLowPosBtn->get_active() ) )
2931 rSet->Put( SvxEscapementItem( nEsc, nEscProp, nWhich ) );
2932 bModified = true;
2934 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2935 rSet->InvalidateItem(nWhich);
2937 bChanged = true;
2939 // Kerning
2940 nWhich = GetWhich( SID_ATTR_CHAR_KERNING );
2941 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_KERNING );
2942 short nKerning = 0;
2943 MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich );
2945 tools::Long nTmp = static_cast<tools::Long>(m_xKerningMF->get_value(FieldUnit::POINT));
2946 tools::Long nVal = OutputDevice::LogicToLogic(nTmp, MapUnit::MapPoint, eUnit);
2947 nKerning = static_cast<short>(m_xKerningMF->denormalize( nVal ));
2949 SfxItemState eOldKernState = rOldSet.GetItemState( nWhich, false );
2950 if ( pOld )
2952 const SvxKerningItem& rItem = *static_cast<const SvxKerningItem*>(pOld);
2953 if ( (eOldKernState >= SfxItemState::DEFAULT || m_xKerningMF->get_text().isEmpty()) && rItem.GetValue() == nKerning )
2954 bChanged = false;
2957 if ( bChanged )
2959 rSet->Put( SvxKerningItem( nKerning, nWhich ) );
2960 bModified = true;
2962 else if ( SfxItemState::DEFAULT == eOldKernState )
2963 rSet->InvalidateItem(nWhich);
2965 // Pair-Kerning
2966 nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN );
2968 if (m_xPairKerningBtn->get_state_changed_from_saved())
2970 rSet->Put( SvxAutoKernItem( m_xPairKerningBtn->get_active(), nWhich ) );
2971 bModified = true;
2973 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2974 rSet->InvalidateItem(nWhich);
2976 // Scale Width
2977 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
2978 if (m_xScaleWidthMF->get_value_changed_from_saved())
2980 rSet->Put(SvxCharScaleWidthItem(static_cast<sal_uInt16>(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)), TypedWhichId<SvxCharScaleWidthItem>(nWhich)));
2981 bModified = true;
2983 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2984 rSet->InvalidateItem(nWhich);
2986 // Rotation
2987 nWhich = GetWhich( SID_ATTR_CHAR_ROTATED );
2988 if ( m_x0degRB->get_state_changed_from_saved() ||
2989 m_x90degRB->get_state_changed_from_saved() ||
2990 m_x270degRB->get_state_changed_from_saved() ||
2991 m_xFitToLineCB->get_state_changed_from_saved() )
2993 SvxCharRotateItem aItem( 0_deg10, m_xFitToLineCB->get_active(), TypedWhichId<SvxCharRotateItem>(nWhich) );
2994 if (m_x90degRB->get_active())
2995 aItem.SetBottomToTop();
2996 else if (m_x270degRB->get_active())
2997 aItem.SetTopToBottom();
2998 rSet->Put( aItem );
2999 bModified = true;
3001 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
3002 rSet->InvalidateItem(nWhich);
3004 return bModified;
3008 void SvxCharPositionPage::FillUserData()
3010 static const OUStringLiteral cTok( u";" );
3012 OUString sUser = OUString::number( m_nSuperEsc ) + cTok +
3013 OUString::number( m_nSubEsc ) + cTok +
3014 OUString::number( m_nSuperProp ) + cTok +
3015 OUString::number( m_nSubProp );
3016 SetUserData( sUser );
3020 void SvxCharPositionPage::PageCreated(const SfxAllItemSet& aSet)
3022 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
3023 if (pFlagItem)
3025 sal_uInt32 nFlags=pFlagItem->GetValue();
3026 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
3027 // the writer uses SID_ATTR_BRUSH as font background
3028 m_bPreviewBackgroundToCharacter = true;
3031 // class SvxCharTwoLinesPage ------------------------------------------------
3033 SvxCharTwoLinesPage::SvxCharTwoLinesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
3034 : SvxCharBasePage(pPage, pController, "cui/ui/twolinespage.ui", "TwoLinesPage", rInSet)
3035 , m_nStartBracketPosition( 0 )
3036 , m_nEndBracketPosition( 0 )
3037 , m_xTwoLinesBtn(m_xBuilder->weld_check_button("twolines"))
3038 , m_xEnclosingFrame(m_xBuilder->weld_widget("enclosing"))
3039 , m_xStartBracketLB(m_xBuilder->weld_tree_view("startbracket"))
3040 , m_xEndBracketLB(m_xBuilder->weld_tree_view("endbracket"))
3042 for (size_t i = 0; i < std::size(TWOLINE_OPEN); ++i)
3043 m_xStartBracketLB->append(OUString::number(TWOLINE_OPEN[i].second), CuiResId(TWOLINE_OPEN[i].first));
3044 for (size_t i = 0; i < std::size(TWOLINE_CLOSE); ++i)
3045 m_xEndBracketLB->append(OUString::number(TWOLINE_CLOSE[i].second), CuiResId(TWOLINE_CLOSE[i].first));
3047 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
3048 #ifdef IOS
3049 m_xPreviewWin->hide();
3050 #endif
3051 Initialize();
3054 SvxCharTwoLinesPage::~SvxCharTwoLinesPage()
3058 void SvxCharTwoLinesPage::Initialize()
3060 m_xTwoLinesBtn->set_active(false);
3061 TwoLinesHdl_Impl(*m_xTwoLinesBtn);
3063 m_xTwoLinesBtn->connect_toggled(LINK(this, SvxCharTwoLinesPage, TwoLinesHdl_Impl));
3065 Link<weld::TreeView&,void> aLink = LINK(this, SvxCharTwoLinesPage, CharacterMapHdl_Impl);
3066 m_xStartBracketLB->connect_changed(aLink);
3067 m_xEndBracketLB->connect_changed(aLink);
3069 SvxFont& rFont = GetPreviewFont();
3070 SvxFont& rCJKFont = GetPreviewCJKFont();
3071 SvxFont& rCTLFont = GetPreviewCTLFont();
3072 rFont.SetFontSize( Size( 0, 220 ) );
3073 rCJKFont.SetFontSize( Size( 0, 220 ) );
3074 rCTLFont.SetFontSize( Size( 0, 220 ) );
3077 void SvxCharTwoLinesPage::SelectCharacter(weld::TreeView* pBox)
3079 bool bStart = pBox == m_xStartBracketLB.get();
3080 SvxCharacterMap aDlg(GetFrameWeld(), nullptr, nullptr);
3081 aDlg.DisableFontSelection();
3083 if (aDlg.run() == RET_OK)
3085 sal_Unicode cChar = static_cast<sal_Unicode>(aDlg.GetChar());
3086 SetBracket( cChar, bStart );
3088 else
3090 pBox->select(bStart ? m_nStartBracketPosition : m_nEndBracketPosition);
3095 void SvxCharTwoLinesPage::SetBracket( sal_Unicode cBracket, bool bStart )
3097 int nEntryPos = 0;
3098 weld::TreeView* pBox = bStart ? m_xStartBracketLB.get() : m_xEndBracketLB.get();
3099 if (cBracket == 0)
3100 pBox->select(0);
3101 else
3103 bool bFound = false;
3104 for (int i = 1; i < pBox->n_children(); ++i)
3106 if (pBox->get_id(i).toInt32() != CHRDLG_ENCLOSE_SPECIAL_CHAR)
3108 const sal_Unicode cChar = pBox->get_text(i)[0];
3109 if (cChar == cBracket)
3111 pBox->select(i);
3112 nEntryPos = i;
3113 bFound = true;
3114 break;
3119 if (!bFound)
3121 pBox->append_text(OUString(cBracket));
3122 nEntryPos = pBox->n_children() - 1;
3123 pBox->select(nEntryPos);
3126 if (bStart)
3127 m_nStartBracketPosition = nEntryPos;
3128 else
3129 m_nEndBracketPosition = nEntryPos;
3132 IMPL_LINK_NOARG(SvxCharTwoLinesPage, TwoLinesHdl_Impl, weld::Toggleable&, void)
3134 bool bChecked = m_xTwoLinesBtn->get_active();
3135 m_xEnclosingFrame->set_sensitive(bChecked);
3136 UpdatePreview_Impl();
3139 IMPL_LINK(SvxCharTwoLinesPage, CharacterMapHdl_Impl, weld::TreeView&, rBox, void)
3141 int nPos = rBox.get_selected_index();
3142 if (rBox.get_id(nPos).toInt32() == CHRDLG_ENCLOSE_SPECIAL_CHAR)
3143 SelectCharacter( &rBox );
3144 else
3146 bool bStart = &rBox == m_xStartBracketLB.get();
3147 if (bStart)
3148 m_nStartBracketPosition = nPos;
3149 else
3150 m_nEndBracketPosition = nPos;
3152 UpdatePreview_Impl();
3155 void SvxCharTwoLinesPage::ActivatePage( const SfxItemSet& rSet )
3157 SvxCharBasePage::ActivatePage(rSet);
3160 DeactivateRC SvxCharTwoLinesPage::DeactivatePage( SfxItemSet* _pSet )
3162 if ( _pSet )
3163 FillItemSet( _pSet );
3164 return DeactivateRC::LeavePage;
3167 std::unique_ptr<SfxTabPage> SvxCharTwoLinesPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
3169 return std::make_unique<SvxCharTwoLinesPage>(pPage, pController, *rSet);
3172 void SvxCharTwoLinesPage::Reset( const SfxItemSet* rSet )
3174 m_xTwoLinesBtn->set_active(false);
3175 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES );
3176 SfxItemState eState = rSet->GetItemState( nWhich );
3178 if ( eState >= SfxItemState::DONTCARE )
3180 const SvxTwoLinesItem& rItem = static_cast<const SvxTwoLinesItem&>(rSet->Get( nWhich ));
3181 m_xTwoLinesBtn->set_active(rItem.GetValue());
3183 if ( rItem.GetValue() )
3185 SetBracket( rItem.GetStartBracket(), true );
3186 SetBracket( rItem.GetEndBracket(), false );
3189 TwoLinesHdl_Impl(*m_xTwoLinesBtn);
3191 SetPrevFontWidthScale( *rSet );
3194 bool SvxCharTwoLinesPage::FillItemSet( SfxItemSet* rSet )
3196 const SfxItemSet& rOldSet = GetItemSet();
3197 bool bModified = false, bChanged = true;
3198 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES );
3199 const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_TWO_LINES );
3200 bool bOn = m_xTwoLinesBtn->get_active();
3201 sal_Unicode cStart = ( bOn && m_xStartBracketLB->get_selected_index() > 0 )
3202 ? m_xStartBracketLB->get_selected_text()[0] : 0;
3203 sal_Unicode cEnd = ( bOn && m_xEndBracketLB->get_selected_index() > 0 )
3204 ? m_xEndBracketLB->get_selected_text()[0] : 0;
3206 if ( pOld )
3208 const SvxTwoLinesItem& rItem = *static_cast<const SvxTwoLinesItem*>(pOld);
3209 if ( rItem.GetValue() == bOn &&
3210 ( !bOn || ( rItem.GetStartBracket() == cStart && rItem.GetEndBracket() == cEnd ) ) )
3211 bChanged = false;
3214 if ( bChanged )
3216 rSet->Put( SvxTwoLinesItem( bOn, cStart, cEnd, nWhich ) );
3217 bModified = true;
3219 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
3220 rSet->InvalidateItem(nWhich);
3222 return bModified;
3225 void SvxCharTwoLinesPage::UpdatePreview_Impl()
3227 sal_Unicode cStart = m_xStartBracketLB->get_selected_index() > 0
3228 ? m_xStartBracketLB->get_selected_text()[0] : 0;
3229 sal_Unicode cEnd = m_xEndBracketLB->get_selected_index() > 0
3230 ? m_xEndBracketLB->get_selected_text()[0] : 0;
3231 m_aPreviewWin.SetBrackets(cStart, cEnd);
3232 m_aPreviewWin.SetTwoLines(m_xTwoLinesBtn->get_active());
3233 m_aPreviewWin.Invalidate();
3236 void SvxCharTwoLinesPage::PageCreated(const SfxAllItemSet& aSet)
3238 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
3239 if (pFlagItem)
3241 sal_uInt32 nFlags=pFlagItem->GetValue();
3242 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
3243 // the writer uses SID_ATTR_BRUSH as font background
3244 m_bPreviewBackgroundToCharacter = true;
3248 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */