summaryrefslogtreecommitdiffstats
path: root/cui/source/tabpages/chardlg.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'cui/source/tabpages/chardlg.cxx')
-rw-r--r--cui/source/tabpages/chardlg.cxx3230
1 files changed, 3230 insertions, 0 deletions
diff --git a/cui/source/tabpages/chardlg.cxx b/cui/source/tabpages/chardlg.cxx
new file mode 100644
index 000000000..5bf0975bb
--- /dev/null
+++ b/cui/source/tabpages/chardlg.cxx
@@ -0,0 +1,3230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/svapp.hxx>
+#include <vcl/idle.hxx>
+#include <svtools/ctrltool.hxx>
+#include <sfx2/objsh.hxx>
+#include <svx/svxids.hrc>
+#include <svtools/unitconv.hxx>
+#include <svl/cjkoptions.hxx>
+#include <svl/ctloptions.hxx>
+#include <chardlg.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/contouritem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/flstitem.hxx>
+#include <editeng/autokernitem.hxx>
+#include <editeng/colritem.hxx>
+#include <dialmgr.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <cui/cuicharmap.hxx>
+#include "chardlg.h"
+#include <editeng/emphasismarkitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <strings.hrc>
+#include <twolines.hrc>
+#include <svl/intitem.hxx>
+#include <svx/flagsdef.hxx>
+#include <FontFeatures.hxx>
+#include <FontFeaturesDialog.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/unit_conversion.hxx>
+#include <o3tl/string_view.hxx>
+
+using namespace ::com::sun::star;
+
+// static ----------------------------------------------------------------
+
+const WhichRangesContainer SvxCharNamePage::pNameRanges(svl::Items<
+ SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_WEIGHT,
+ SID_ATTR_CHAR_FONTHEIGHT, SID_ATTR_CHAR_FONTHEIGHT,
+ SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR,
+ SID_ATTR_CHAR_LANGUAGE, SID_ATTR_CHAR_LANGUAGE,
+ SID_ATTR_CHAR_CJK_FONT, SID_ATTR_CHAR_CJK_WEIGHT,
+ SID_ATTR_CHAR_CTL_FONT, SID_ATTR_CHAR_CTL_WEIGHT
+>);
+
+const WhichRangesContainer SvxCharEffectsPage::pEffectsRanges(svl::Items<
+ SID_ATTR_CHAR_SHADOWED, SID_ATTR_CHAR_UNDERLINE,
+ SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR,
+ SID_ATTR_CHAR_CASEMAP, SID_ATTR_CHAR_CASEMAP,
+ SID_ATTR_FLASH, SID_ATTR_FLASH,
+ SID_ATTR_CHAR_EMPHASISMARK, SID_ATTR_CHAR_EMPHASISMARK,
+ SID_ATTR_CHAR_RELIEF, SID_ATTR_CHAR_RELIEF,
+ SID_ATTR_CHAR_HIDDEN, SID_ATTR_CHAR_HIDDEN,
+ SID_ATTR_CHAR_OVERLINE, SID_ATTR_CHAR_OVERLINE
+>);
+
+const WhichRangesContainer SvxCharPositionPage::pPositionRanges(svl::Items<
+ SID_ATTR_CHAR_KERNING, SID_ATTR_CHAR_KERNING,
+ SID_ATTR_CHAR_ESCAPEMENT, SID_ATTR_CHAR_ESCAPEMENT,
+ SID_ATTR_CHAR_AUTOKERN, SID_ATTR_CHAR_AUTOKERN,
+ SID_ATTR_CHAR_ROTATED, SID_ATTR_CHAR_SCALEWIDTH,
+ SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, SID_ATTR_CHAR_WIDTH_FIT_TO_LINE
+>);
+
+const WhichRangesContainer SvxCharTwoLinesPage::pTwoLinesRanges(svl::Items<
+ SID_ATTR_CHAR_TWO_LINES, SID_ATTR_CHAR_TWO_LINES
+>);
+
+// C-Function ------------------------------------------------------------
+
+static bool StateToAttr( TriState aState )
+{
+ return ( TRISTATE_TRUE == aState );
+}
+
+namespace
+{
+ void setPrevFontEscapement(SvxFont& _rFont,sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
+ {
+ _rFont.SetPropr( nProp );
+ _rFont.SetProprRel( nEscProp );
+ _rFont.SetEscapement( nEsc );
+ }
+}
+
+inline SvxFont& SvxCharBasePage::GetPreviewFont()
+{
+ return m_aPreviewWin.GetFont();
+}
+
+inline SvxFont& SvxCharBasePage::GetPreviewCJKFont()
+{
+ return m_aPreviewWin.GetCJKFont();
+}
+
+inline SvxFont& SvxCharBasePage::GetPreviewCTLFont()
+{
+ return m_aPreviewWin.GetCTLFont();
+}
+
+SvxCharBasePage::SvxCharBasePage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rID, const SfxItemSet& rItemset)
+ : SfxTabPage(pPage, pController, rUIXMLDescription, rID, &rItemset)
+ , m_bPreviewBackgroundToCharacter( false )
+{
+}
+
+SvxCharBasePage::~SvxCharBasePage()
+{
+}
+
+void SvxCharBasePage::ActivatePage(const SfxItemSet& rSet)
+{
+ m_aPreviewWin.SetFromItemSet(rSet, m_bPreviewBackgroundToCharacter);
+}
+
+void SvxCharBasePage::SetPrevFontWidthScale( const SfxItemSet& rSet )
+{
+ sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
+ if (rSet.GetItemState(nWhich)>=SfxItemState::DEFAULT)
+ {
+ const SvxCharScaleWidthItem &rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
+ m_aPreviewWin.SetFontWidthScale(rItem.GetValue());
+ }
+}
+
+void SvxCharBasePage::SetPrevFontEscapement( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
+{
+ setPrevFontEscapement(GetPreviewFont(),nProp,nEscProp,nEsc);
+ setPrevFontEscapement(GetPreviewCJKFont(),nProp,nEscProp,nEsc);
+ setPrevFontEscapement(GetPreviewCTLFont(),nProp,nEscProp,nEsc);
+ m_aPreviewWin.Invalidate();
+}
+
+
+// SvxCharNamePage_Impl --------------------------------------------------
+
+struct SvxCharNamePage_Impl
+{
+ Idle m_aUpdateIdle { "cui SvxCharNamePage_Impl m_aUpdateIdle" };
+ OUString m_aNoStyleText;
+ std::unique_ptr<FontList> m_pFontList;
+ int m_nExtraEntryPos;
+ bool m_bInSearchMode;
+
+ SvxCharNamePage_Impl()
+ : m_nExtraEntryPos(std::numeric_limits<int>::max())
+ , m_bInSearchMode(false)
+
+ {
+ m_aUpdateIdle.SetPriority( TaskPriority::LOWEST );
+ }
+};
+
+// class SvxCharNamePage -------------------------------------------------
+
+SvxCharNamePage::SvxCharNamePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
+ : SvxCharBasePage(pPage, pController, "cui/ui/charnamepage.ui", "CharNamePage", rInSet)
+ , m_pImpl(new SvxCharNamePage_Impl)
+ // Western
+ , m_xWestern(m_xBuilder->weld_notebook("nbWestern"))
+ , m_xWestFontNameFT(m_xBuilder->weld_label("lbWestFontname"))
+ , m_xWestFontStyleFT(m_xBuilder->weld_label("lbWestStyle"))
+ , m_xWestFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("cbWestStyle")))
+ , m_xWestFontSizeFT(m_xBuilder->weld_label("lbWestSize"))
+ , m_xWestFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("cbWestSize")))
+ , m_xWestFontLanguageFT(m_xBuilder->weld_label("lbWestLanguage"))
+ , m_xWestFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("cbWestLanguage")))
+ , m_xWestFontFeaturesButton(m_xBuilder->weld_button("btnWestFeatures"))
+ , m_xWestFontTypeFT(m_xBuilder->weld_label("lbWestFontinfo"))
+ , m_xCJK_CTL(m_xBuilder->weld_notebook("nbCJKCTL"))
+ // CJK
+ , m_xEastFontNameFT(m_xBuilder->weld_label("lbCJKFontname"))
+ , m_xEastFontStyleFT(m_xBuilder->weld_label("lbCJKStyle"))
+ , m_xEastFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("cbCJKStyle")))
+ , m_xEastFontSizeFT(m_xBuilder->weld_label("lbCJKSize"))
+ , m_xEastFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("cbCJKSize")))
+ , m_xEastFontLanguageFT(m_xBuilder->weld_label("lbCJKLanguage"))
+ , m_xEastFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("cbCJKLanguage")))
+ , m_xEastFontFeaturesButton(m_xBuilder->weld_button("btnCJKFeatures"))
+ , m_xEastFontTypeFT(m_xBuilder->weld_label("lbCJKFontinfo"))
+ // CTL
+ , m_xCTLFontNameFT(m_xBuilder->weld_label("lbCTLFontname"))
+ // tree
+ , m_xCTLFontStyleFT(m_xBuilder->weld_label("lbCTLStyle"))
+ , m_xCTLFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("cbCTLStyle")))
+ , m_xCTLFontSizeFT(m_xBuilder->weld_label("lbCTLSize"))
+ , m_xCTLFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("cbCTLSize")))
+ , m_xCTLFontLanguageFT(m_xBuilder->weld_label("lbCTLLanguage"))
+ , m_xCTLFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("cbCTLLanguage")))
+ , m_xCTLFontFeaturesButton(m_xBuilder->weld_button("btnCTLFeatures"))
+ , m_xCTLFontTypeFT(m_xBuilder->weld_label("lbCTLFontinfo"))
+
+ , m_xVDev(*Application::GetDefaultDevice(), DeviceFormat::DEFAULT, DeviceFormat::DEFAULT)
+{
+ m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
+#ifdef IOS
+ m_xPreviewWin->hide();
+#endif
+ m_pImpl->m_aNoStyleText = CuiResId( RID_CUISTR_CHARNAME_NOSTYLE );
+
+ std::unique_ptr<weld::EntryTreeView> xWestFontName = m_xBuilder->weld_entry_tree_view("gdWestern", "edWestFontName", "trWestFontName");
+ std::unique_ptr<weld::EntryTreeView> xCJKFontName = m_xBuilder->weld_entry_tree_view("gdCJK", "edCJKFontName", "trCJKFontName");
+ std::unique_ptr<weld::EntryTreeView> xCTLFontName = m_xBuilder->weld_entry_tree_view("gdCTL", "edCTLFontName", "trCTLFontName");
+
+ // 7 lines in the treeview
+ xWestFontName->set_height_request_by_rows(7);
+ xCJKFontName->set_height_request_by_rows(7);
+ xCTLFontName->set_height_request_by_rows(7);
+
+ m_xWestFontNameLB = std::move(xWestFontName);
+ m_xEastFontNameLB = std::move(xCJKFontName);
+ m_xCTLFontNameLB = std::move(xCTLFontName);
+
+ SvtCTLOptions aCTLLanguageOptions;
+ bool bShowCJK = SvtCJKOptions::IsCJKFontEnabled();
+ bool bShowCTL = aCTLLanguageOptions.IsCTLFontEnabled();
+ bool bShowNonWestern = bShowCJK || bShowCTL;
+ if (!bShowNonWestern)
+ {
+ m_xCJK_CTL->hide();
+ m_xWestern->set_show_tabs(false); //hide single tab in case of Western only
+ }
+ else if (!bShowCJK) m_xCJK_CTL->remove_page("nbCJK");
+ else if (!bShowCTL) m_xCJK_CTL->remove_page("nbCTL");
+
+
+ //In MacOSX the standard dialogs name font-name, font-style as
+ //Family, Typeface
+ //In GNOME the standard dialogs name font-name, font-style as
+ //Family, Style
+ //In Windows the standard dialogs name font-name, font-style as
+ //Font, Style
+#ifdef _WIN32
+ OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FONT));
+#else
+ OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FAMILY));
+#endif
+ m_xWestFontNameFT->set_label(sFontFamilyString);
+ m_xCTLFontNameFT->set_label(sFontFamilyString);
+ m_xEastFontNameFT->set_label(sFontFamilyString);
+
+#ifdef MACOSX
+ OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_TYPEFACE));
+#else
+ OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_STYLE));
+#endif
+ m_xWestFontStyleFT->set_label(sFontStyleString);
+ m_xEastFontStyleFT->set_label(sFontStyleString);
+ m_xCTLFontStyleFT->set_label(sFontStyleString);
+
+ m_xWestFontLanguageLB->SetLanguageList(SvxLanguageListFlags::WESTERN, true, false, true, true,
+ LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN);
+ m_xEastFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CJK, true, false, true, true,
+ LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN);
+ m_xCTLFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CTL, true, false, true, true,
+ LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX);
+ int nVisibleChars = 15;
+ // read-only combobox / HasEntry asserts on set_width_char()
+ m_xWestFontLanguageLB->set_width_chars(nVisibleChars);
+ m_xEastFontLanguageLB->set_width_chars(nVisibleChars);
+ m_xCTLFontLanguageLB->set_width_chars(nVisibleChars);
+
+ Initialize();
+}
+
+SvxCharNamePage::~SvxCharNamePage()
+{
+ m_pImpl.reset();
+ m_xCTLFontStyleLB.reset();
+ m_xEastFontLanguageLB.reset();
+ m_xWestFontStyleLB.reset();
+ m_xCTLFontSizeLB.reset();
+ m_xEastFontSizeLB.reset();
+ m_xWestFontSizeLB.reset();
+ m_xWestFontLanguageLB.reset();
+ m_xPreviewWin.reset();
+ m_xCTLFontLanguageLB.reset();
+ m_xEastFontLanguageLB.reset();
+}
+
+void SvxCharNamePage::Initialize()
+{
+ // to handle the changes of the other pages
+ SetExchangeSupport();
+
+ Link<weld::ComboBox&,void> aLink = LINK(this, SvxCharNamePage, FontModifyComboBoxHdl_Impl);
+ m_xWestFontNameLB->connect_changed(aLink);
+ m_xWestFontStyleLB->connect_changed(aLink);
+ m_xWestFontSizeLB->connect_changed(aLink);
+ m_xWestFontLanguageLB->connect_changed(aLink);
+
+ m_xWestFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
+
+ m_xEastFontNameLB->connect_changed(aLink);
+ m_xEastFontStyleLB->connect_changed(aLink);
+ m_xEastFontSizeLB->connect_changed(aLink);
+ m_xEastFontLanguageLB->connect_changed(aLink);
+ m_xEastFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
+
+ m_xCTLFontNameLB->connect_changed(aLink);
+ m_xCTLFontStyleLB->connect_changed(aLink);
+ m_xCTLFontSizeLB->connect_changed(aLink);
+ m_xCTLFontLanguageLB->connect_changed(aLink);
+ m_xCTLFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
+
+ m_pImpl->m_aUpdateIdle.SetInvokeHandler( LINK( this, SvxCharNamePage, UpdateHdl_Impl ) );
+}
+
+const FontList* SvxCharNamePage::GetFontList() const
+{
+ if ( !m_pImpl->m_pFontList )
+ {
+ /* #110771# SvxFontListItem::GetFontList can return NULL */
+ if (SfxObjectShell* pDocSh = SfxObjectShell::Current())
+ {
+ const SfxPoolItem* pItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST );
+ if ( pItem != nullptr )
+ {
+ DBG_ASSERT(nullptr != static_cast<const SvxFontListItem*>(pItem)->GetFontList(),
+ "Where is the font list?");
+ m_pImpl->m_pFontList = static_cast<const SvxFontListItem*>(pItem )->GetFontList()->Clone();
+ }
+ }
+ if(!m_pImpl->m_pFontList)
+ {
+ m_pImpl->m_pFontList.reset(new FontList( Application::GetDefaultDevice() ));
+ }
+ }
+
+ return m_pImpl->m_pFontList.get();
+}
+
+
+namespace
+{
+ FontMetric calcFontMetrics( SvxFont& _rFont,
+ SvxCharNamePage const * _pPage,
+ const weld::ComboBox* _pFontNameLB,
+ const FontStyleBox* _pFontStyleLB,
+ const FontSizeBox* _pFontSizeLB,
+ const SvxLanguageBox* _pLanguageLB,
+ const FontList* _pFontList,
+ sal_uInt16 _nFontWhich,
+ sal_uInt16 _nFontHeightWhich)
+ {
+ Size aSize = _rFont.GetFontSize();
+ aSize.setWidth( 0 );
+ FontMetric aFontMetrics;
+ OUString sFontName(_pFontNameLB->get_active_text());
+ bool bFontAvailable = _pFontList->IsAvailable( sFontName );
+ if (bFontAvailable || _pFontNameLB->get_value_changed_from_saved())
+ aFontMetrics = _pFontList->Get(sFontName, _pFontStyleLB->get_active_text());
+ else
+ {
+ //get the font from itemset
+ SfxItemState eState = _pPage->GetItemSet().GetItemState( _nFontWhich );
+ if ( eState >= SfxItemState::DEFAULT )
+ {
+ const SvxFontItem* pFontItem = static_cast<const SvxFontItem*>(&( _pPage->GetItemSet().Get( _nFontWhich ) ));
+ aFontMetrics.SetFamilyName(pFontItem->GetFamilyName());
+ aFontMetrics.SetStyleName(pFontItem->GetStyleName());
+ aFontMetrics.SetFamily(pFontItem->GetFamily());
+ aFontMetrics.SetPitch(pFontItem->GetPitch());
+ aFontMetrics.SetCharSet(pFontItem->GetCharSet());
+ }
+ }
+ if ( _pFontSizeLB->IsRelative() )
+ {
+ DBG_ASSERT( _pPage->GetItemSet().GetParent(), "No parent set" );
+ const SvxFontHeightItem& rOldItem = static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nFontHeightWhich ));
+
+ // old value, scaled
+ tools::Long nHeight;
+ if ( _pFontSizeLB->IsPtRelative() )
+ nHeight = rOldItem.GetHeight()
+ + o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt,
+ o3tl::Length::twip) / 10;
+ else
+ nHeight = static_cast<tools::Long>(rOldItem.GetHeight() * _pFontSizeLB->get_value() / 100);
+
+ // conversion twips for the example-window
+ aSize.setHeight(
+ ItemToControl( nHeight, _pPage->GetItemSet().GetPool()->GetMetric( _nFontHeightWhich ), FieldUnit::TWIP ) );
+ }
+ else if ( !_pFontSizeLB->get_active_text().isEmpty() )
+ aSize.setHeight(o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt,
+ o3tl::Length::twip) / 10);
+ else
+ aSize.setHeight( 200 ); // default 10pt
+ aFontMetrics.SetFontSize( aSize );
+
+ _rFont.SetLanguage(_pLanguageLB->get_active_id());
+
+ _rFont.SetFamily( aFontMetrics.GetFamilyType() );
+ _rFont.SetFamilyName( aFontMetrics.GetFamilyName() );
+ _rFont.SetStyleName( aFontMetrics.GetStyleName() );
+ _rFont.SetPitch( aFontMetrics.GetPitch() );
+ _rFont.SetCharSet( aFontMetrics.GetCharSet() );
+ _rFont.SetWeight( aFontMetrics.GetWeight() );
+ _rFont.SetItalic( aFontMetrics.GetItalic() );
+ _rFont.SetFontSize( aFontMetrics.GetFontSize() );
+
+ return aFontMetrics;
+ }
+}
+
+
+void SvxCharNamePage::UpdatePreview_Impl()
+{
+ SvxFont& rFont = GetPreviewFont();
+ SvxFont& rCJKFont = GetPreviewCJKFont();
+ SvxFont& rCTLFont = GetPreviewCTLFont();
+ // Font
+ const FontList* pFontList = GetFontList();
+
+ FontMetric aWestFontMetric = calcFontMetrics(rFont, this, m_xWestFontNameLB.get(),
+ m_xWestFontStyleLB.get(), m_xWestFontSizeLB.get(), m_xWestFontLanguageLB.get(),
+ pFontList, GetWhich(SID_ATTR_CHAR_FONT),
+ GetWhich(SID_ATTR_CHAR_FONTHEIGHT));
+
+ m_xWestFontTypeFT->set_label(pFontList->GetFontMapText(aWestFontMetric));
+
+ FontMetric aEastFontMetric = calcFontMetrics(rCJKFont, this, m_xEastFontNameLB.get(),
+ m_xEastFontStyleLB.get(), m_xEastFontSizeLB.get(), m_xEastFontLanguageLB.get(),
+ pFontList, GetWhich(SID_ATTR_CHAR_CJK_FONT),
+ GetWhich(SID_ATTR_CHAR_CJK_FONTHEIGHT));
+
+ m_xEastFontTypeFT->set_label(pFontList->GetFontMapText(aEastFontMetric));
+
+ FontMetric aCTLFontMetric = calcFontMetrics(rCTLFont,
+ this, m_xCTLFontNameLB.get(), m_xCTLFontStyleLB.get(), m_xCTLFontSizeLB.get(),
+ m_xCTLFontLanguageLB.get(), pFontList, GetWhich(SID_ATTR_CHAR_CTL_FONT),
+ GetWhich(SID_ATTR_CHAR_CTL_FONTHEIGHT));
+
+ m_xCTLFontTypeFT->set_label(pFontList->GetFontMapText(aCTLFontMetric));
+
+ m_aPreviewWin.Invalidate();
+}
+void SvxCharNamePage::EnableFeatureButton(const weld::Widget& rNameBox)
+{
+ OUString sFontName;
+ weld::Button* pButton= nullptr;
+ if (m_xWestFontNameLB.get() == &rNameBox)
+ {
+ sFontName = m_xWestFontNameLB->get_active_text();
+ pButton= m_xWestFontFeaturesButton.get();
+ }
+ else if (m_xEastFontNameLB.get() == &rNameBox)
+ {
+ sFontName = m_xEastFontNameLB->get_active_text();
+ pButton=m_xEastFontFeaturesButton.get();
+ }
+ else if (m_xCTLFontNameLB.get() == &rNameBox)
+ {
+ sFontName = m_xCTLFontNameLB->get_active_text();
+ pButton= m_xCTLFontFeaturesButton.get();
+ }
+ else
+ {
+ SAL_WARN( "cui.tabpages", "invalid font name box" );
+ return;
+ }
+
+ bool bEnable = !getFontFeatureList(sFontName, *m_xVDev).empty();
+
+ pButton->set_sensitive(bEnable);
+}
+
+void SvxCharNamePage::FillStyleBox_Impl(const weld::Widget& rNameBox)
+{
+ const FontList* pFontList = GetFontList();
+ DBG_ASSERT( pFontList, "no fontlist" );
+
+ FontStyleBox* pStyleBox = nullptr;
+ OUString sFontName;
+
+ if (m_xWestFontNameLB.get() == &rNameBox)
+ {
+ pStyleBox = m_xWestFontStyleLB.get();
+ sFontName = m_xWestFontNameLB->get_active_text();
+ }
+ else if (m_xEastFontNameLB.get() == &rNameBox)
+ {
+ pStyleBox = m_xEastFontStyleLB.get();
+ sFontName = m_xEastFontStyleLB->get_active_text();
+ }
+ else if (m_xCTLFontNameLB.get() == &rNameBox)
+ {
+ pStyleBox = m_xCTLFontStyleLB.get();
+ sFontName = m_xCTLFontNameLB->get_active_text();
+ }
+ else
+ {
+ SAL_WARN( "cui.tabpages", "invalid font name box" );
+ return;
+ }
+
+ pStyleBox->Fill(sFontName, pFontList);
+
+ if ( !m_pImpl->m_bInSearchMode )
+ return;
+
+ // additional entries for the search:
+ // "not bold" and "not italic"
+ OUString aEntry = m_pImpl->m_aNoStyleText;
+ const char sS[] = "%1";
+ aEntry = aEntry.replaceFirst( sS, pFontList->GetBoldStr() );
+ m_pImpl->m_nExtraEntryPos = pStyleBox->get_count();
+ pStyleBox->append_text( aEntry );
+ aEntry = m_pImpl->m_aNoStyleText;
+ aEntry = aEntry.replaceFirst( sS, pFontList->GetItalicStr() );
+ pStyleBox->append_text(aEntry);
+}
+
+void SvxCharNamePage::FillSizeBox_Impl(const weld::Widget& rNameBox)
+{
+ const FontList* pFontList = GetFontList();
+ DBG_ASSERT( pFontList, "no fontlist" );
+
+ FontSizeBox* pSizeBox = nullptr;
+
+ if (m_xWestFontNameLB.get() == &rNameBox)
+ {
+ pSizeBox = m_xWestFontSizeLB.get();
+ }
+ else if (m_xEastFontNameLB.get() == &rNameBox)
+ {
+ pSizeBox = m_xEastFontSizeLB.get();
+ }
+ else if (m_xCTLFontNameLB.get() == &rNameBox)
+ {
+ pSizeBox = m_xCTLFontSizeLB.get();
+ }
+ else
+ {
+ SAL_WARN( "cui.tabpages", "invalid font name box" );
+ return;
+ }
+
+ pSizeBox->Fill( pFontList );
+}
+
+namespace
+{
+ void FillFontNames(weld::ComboBox& rBox, const FontList& rList)
+ {
+ // insert fonts
+ sal_uInt16 nFontCount = rList.GetFontNameCount();
+ std::vector<weld::ComboBoxEntry> aVector;
+ aVector.reserve(nFontCount);
+ for (sal_uInt16 i = 0; i < nFontCount; ++i)
+ {
+ const FontMetric& rFontMetric = rList.GetFontName(i);
+ aVector.emplace_back(rFontMetric.GetFamilyName());
+ }
+ rBox.insert_vector(aVector, false);
+ }
+}
+
+void SvxCharNamePage::Reset_Impl( const SfxItemSet& rSet, LanguageGroup eLangGrp )
+{
+ weld::ComboBox* pNameBox = nullptr;
+ weld::Label* pStyleLabel = nullptr;
+ FontStyleBox* pStyleBox = nullptr;
+ weld::Label* pSizeLabel = nullptr;
+ FontSizeBox* pSizeBox = nullptr;
+ weld::Label* pLangFT = nullptr;
+ SvxLanguageBox* pLangBox = nullptr;
+ sal_uInt16 nWhich = 0;
+
+ switch ( eLangGrp )
+ {
+ case Western :
+ pNameBox = m_xWestFontNameLB.get();
+ pStyleLabel = m_xWestFontStyleFT.get();
+ pStyleBox = m_xWestFontStyleLB.get();
+ pSizeLabel = m_xWestFontSizeFT.get();
+ pSizeBox = m_xWestFontSizeLB.get();
+ pLangFT = m_xWestFontLanguageFT.get();
+ pLangBox = m_xWestFontLanguageLB.get();
+ nWhich = GetWhich( SID_ATTR_CHAR_FONT );
+ break;
+
+ case Asian :
+ pNameBox = m_xEastFontNameLB.get();
+ pStyleLabel = m_xEastFontStyleFT.get();
+ pStyleBox = m_xEastFontStyleLB.get();
+ pSizeLabel = m_xEastFontSizeFT.get();
+ pSizeBox = m_xEastFontSizeLB.get();
+ pLangFT = m_xEastFontLanguageFT.get();
+ pLangBox = m_xEastFontLanguageLB.get();
+ nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONT );
+ break;
+
+ case Ctl :
+ pNameBox = m_xCTLFontNameLB.get();
+ pStyleLabel = m_xCTLFontStyleFT.get();
+ pStyleBox = m_xCTLFontStyleLB.get();
+ pSizeLabel = m_xCTLFontSizeFT.get();
+ pSizeBox = m_xCTLFontSizeLB.get();
+ pLangFT = m_xCTLFontLanguageFT.get();
+ pLangBox = m_xCTLFontLanguageLB.get();
+ nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONT );
+ break;
+ }
+
+ const FontList* pFontList = GetFontList();
+ FillFontNames(*pNameBox, *pFontList);
+
+ const SvxFontItem* pFontItem = nullptr;
+ SfxItemState eState = rSet.GetItemState( nWhich );
+
+ if ( eState >= SfxItemState::DEFAULT )
+ {
+ pFontItem = static_cast<const SvxFontItem*>(&( rSet.Get( nWhich ) ));
+ const OUString &rName = pFontItem->GetFamilyName();
+ int nIndex = pNameBox->find_text(rName);
+ pNameBox->set_active(nIndex);
+ // tdf#122992 if it didn't exist in the list, set the entry text to it anyway
+ if (nIndex == -1)
+ pNameBox->set_entry_text(rName);
+ }
+ else
+ {
+ pNameBox->set_active_text( OUString() );
+ }
+
+ FillStyleBox_Impl(*pNameBox);
+
+ bool bStyle = false;
+ bool bStyleAvailable = true;
+ FontItalic eItalic = ITALIC_NONE;
+ FontWeight eWeight = WEIGHT_NORMAL;
+ switch ( eLangGrp )
+ {
+ case Western : nWhich = GetWhich( SID_ATTR_CHAR_POSTURE ); break;
+ case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_POSTURE ); break;
+ case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_POSTURE ); break;
+ }
+ eState = rSet.GetItemState( nWhich );
+
+ if ( eState >= SfxItemState::DEFAULT )
+ {
+ const SvxPostureItem& rItem = static_cast<const SvxPostureItem&>(rSet.Get( nWhich ));
+ eItalic = rItem.GetValue();
+ bStyle = true;
+ }
+ bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE);
+
+ switch ( eLangGrp )
+ {
+ case Western : nWhich = GetWhich( SID_ATTR_CHAR_WEIGHT ); break;
+ case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_WEIGHT ); break;
+ case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_WEIGHT ); break;
+ }
+ eState = rSet.GetItemState( nWhich );
+
+ if ( eState >= SfxItemState::DEFAULT )
+ {
+ const SvxWeightItem& rItem = static_cast<const SvxWeightItem&>(rSet.Get( nWhich ));
+ eWeight = rItem.GetValue();
+ }
+ else
+ bStyle = false;
+ bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE);
+
+ // currently chosen font
+ if ( bStyle && pFontItem )
+ {
+ FontMetric aFontMetric = pFontList->Get( pFontItem->GetFamilyName(), eWeight, eItalic );
+ pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
+ }
+ else if ( !m_pImpl->m_bInSearchMode || !bStyle )
+ {
+ pStyleBox->set_active_text( OUString() );
+ }
+ else if ( bStyle )
+ {
+ FontMetric aFontMetric = pFontList->Get( OUString(), eWeight, eItalic );
+ pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
+ }
+ if (!bStyleAvailable)
+ {
+ pStyleBox->set_sensitive(false);
+ pStyleLabel->set_sensitive(false);
+ }
+
+ FillSizeBox_Impl(*pNameBox);
+ switch ( eLangGrp )
+ {
+ case Western : nWhich = GetWhich( SID_ATTR_CHAR_FONTHEIGHT ); break;
+ case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ); break;
+ case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ); break;
+ }
+ eState = rSet.GetItemState( nWhich );
+
+ if ( pSizeBox->IsRelativeMode() )
+ {
+ MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
+ const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));
+
+ if( rItem.GetProp() != 100 || MapUnit::MapRelative != rItem.GetPropUnit() )
+ {
+ bool bPtRel = MapUnit::MapPoint == rItem.GetPropUnit();
+ pSizeBox->SetPtRelative( bPtRel );
+ pSizeBox->set_value( bPtRel ? static_cast<short>(rItem.GetProp()) * 10 : rItem.GetProp() );
+ }
+ else
+ {
+ pSizeBox->SetRelative(false);
+ pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
+ }
+ }
+ else if ( eState >= SfxItemState::DEFAULT )
+ {
+ MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
+ const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));
+ pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
+ }
+ else
+ {
+ pSizeBox->set_active_or_entry_text(OUString());
+ if ( eState <= SfxItemState::DISABLED )
+ {
+ pSizeBox->set_sensitive(false);
+ pSizeLabel->set_sensitive(false);
+ }
+ }
+
+ switch ( eLangGrp )
+ {
+ case Western : nWhich = GetWhich( SID_ATTR_CHAR_LANGUAGE ); break;
+ case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_LANGUAGE ); break;
+ case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_LANGUAGE ); break;
+ }
+ pLangBox->set_active(-1);
+ eState = rSet.GetItemState( nWhich );
+
+ switch ( eState )
+ {
+ case SfxItemState::UNKNOWN:
+ pLangFT->hide();
+ pLangBox->hide();
+ break;
+
+ case SfxItemState::DISABLED:
+ pLangFT->set_sensitive(false);
+ pLangBox->set_sensitive(false);
+ break;
+
+ case SfxItemState::DEFAULT:
+ case SfxItemState::SET:
+ {
+ const SvxLanguageItem& rItem = static_cast<const SvxLanguageItem&>(rSet.Get( nWhich ));
+ LanguageType eLangType = rItem.GetValue();
+ DBG_ASSERT( eLangType != LANGUAGE_SYSTEM, "LANGUAGE_SYSTEM not allowed" );
+ if (eLangType != LANGUAGE_DONTKNOW)
+ pLangBox->set_active_id(eLangType);
+ break;
+ }
+ case SfxItemState::DONTCARE:
+ break;
+ }
+
+ OUString sMapText(pFontList->GetFontMapText(
+ pFontList->Get(pNameBox->get_active_text(), pStyleBox->get_active_text())));
+
+ switch (eLangGrp)
+ {
+ case Western:
+ m_xWestFontTypeFT->set_label(sMapText);
+ break;
+ case Asian:
+ m_xEastFontTypeFT->set_label(sMapText);
+ break;
+ case Ctl:
+ m_xCTLFontTypeFT->set_label(sMapText);
+ break;
+ }
+
+ EnableFeatureButton(*pNameBox);
+
+ // save these settings
+ pNameBox->save_value();
+ pStyleBox->save_value();
+ pSizeBox->save_value();
+ pLangBox->save_active_id();
+}
+
+bool SvxCharNamePage::FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp )
+{
+ bool bModified = false;
+
+ weld::ComboBox* pNameBox = nullptr;
+ FontStyleBox* pStyleBox = nullptr;
+ FontSizeBox* pSizeBox = nullptr;
+ SvxLanguageBox* pLangBox = nullptr;
+ sal_uInt16 nWhich = 0;
+ sal_uInt16 nSlot = 0;
+
+ switch ( eLangGrp )
+ {
+ case Western :
+ pNameBox = m_xWestFontNameLB.get();
+ pStyleBox = m_xWestFontStyleLB.get();
+ pSizeBox = m_xWestFontSizeLB.get();
+ pLangBox = m_xWestFontLanguageLB.get();
+ nSlot = SID_ATTR_CHAR_FONT;
+ break;
+
+ case Asian :
+ pNameBox = m_xEastFontNameLB.get();
+ pStyleBox = m_xEastFontStyleLB.get();
+ pSizeBox = m_xEastFontSizeLB.get();
+ pLangBox = m_xEastFontLanguageLB.get();
+ nSlot = SID_ATTR_CHAR_CJK_FONT;
+ break;
+
+ case Ctl :
+ pNameBox = m_xCTLFontNameLB.get();
+ pStyleBox = m_xCTLFontStyleLB.get();
+ pSizeBox = m_xCTLFontSizeLB.get();
+ pLangBox = m_xCTLFontLanguageLB.get();
+ nSlot = SID_ATTR_CHAR_CTL_FONT;
+ break;
+ }
+
+ nWhich = GetWhich( nSlot );
+ const SfxPoolItem* pItem = nullptr;
+ const SfxItemSet& rOldSet = GetItemSet();
+ const SfxPoolItem* pOld = nullptr;
+
+ const SfxItemSet* pExampleSet = GetDialogExampleSet();
+
+ bool bChanged = true;
+ const OUString& rFontName = pNameBox->get_active_text();
+ const FontList* pFontList = GetFontList();
+ OUString aStyleBoxText = pStyleBox->get_active_text();
+ int nEntryPos = pStyleBox->find_text(aStyleBoxText);
+ if (nEntryPos >= m_pImpl->m_nExtraEntryPos)
+ aStyleBoxText.clear();
+ FontMetric aInfo( pFontList->Get( rFontName, aStyleBoxText ) );
+ SvxFontItem aFontItem( aInfo.GetFamilyType(), aInfo.GetFamilyName(), aInfo.GetStyleName(),
+ aInfo.GetPitch(), aInfo.GetCharSet(), nWhich );
+ pOld = GetOldItem( rSet, nSlot );
+
+ if ( pOld )
+ {
+ const SvxFontItem& rItem = *static_cast<const SvxFontItem*>(pOld);
+
+ if ( rItem.GetFamilyName() == aFontItem.GetFamilyName() )
+ bChanged = false;
+ }
+
+ if ( !bChanged )
+ bChanged = pNameBox->get_saved_value().isEmpty();
+
+ if ( !bChanged && pExampleSet &&
+ pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
+ static_cast<const SvxFontItem*>(pItem)->GetFamilyName() != aFontItem.GetFamilyName() )
+ bChanged = true;
+
+ if ( bChanged && !rFontName.isEmpty() )
+ {
+ rSet.Put( aFontItem );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet.ClearItem( nWhich );
+
+
+ bChanged = true;
+ switch ( eLangGrp )
+ {
+ case Western : nSlot = SID_ATTR_CHAR_WEIGHT; break;
+ case Asian : nSlot = SID_ATTR_CHAR_CJK_WEIGHT; break;
+ case Ctl : nSlot = SID_ATTR_CHAR_CTL_WEIGHT; break;
+ }
+ nWhich = GetWhich( nSlot );
+ FontWeight eWeight = aInfo.GetWeight();
+ if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
+ eWeight = WEIGHT_NORMAL;
+ SvxWeightItem aWeightItem( eWeight, nWhich );
+ pOld = GetOldItem( rSet, nSlot );
+
+ if ( pOld )
+ {
+ const SvxWeightItem& rItem = *static_cast<const SvxWeightItem*>(pOld);
+
+ if ( rItem.GetValue() == aWeightItem.GetValue() )
+ bChanged = false;
+ }
+
+ if ( !bChanged )
+ {
+ bChanged = pStyleBox->get_saved_value().isEmpty();
+
+ if ( m_pImpl->m_bInSearchMode && bChanged &&
+ aInfo.GetWeight() == WEIGHT_NORMAL && aInfo.GetItalic() != ITALIC_NONE )
+ bChanged = false;
+ }
+
+ if ( !bChanged && pExampleSet &&
+ pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
+ static_cast<const SvxWeightItem*>(pItem)->GetValue() != aWeightItem.GetValue() )
+ bChanged = true;
+
+ if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
+ bChanged = ( nEntryPos == m_pImpl->m_nExtraEntryPos );
+
+ OUString aText( pStyleBox->get_active_text() ); // Tristate, then text empty
+
+ if ( bChanged && !aText.isEmpty() )
+ {
+ rSet.Put( aWeightItem );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet.InvalidateItem(nWhich);
+
+ bChanged = true;
+ switch ( eLangGrp )
+ {
+ case Western : nSlot = SID_ATTR_CHAR_POSTURE; break;
+ case Asian : nSlot = SID_ATTR_CHAR_CJK_POSTURE; break;
+ case Ctl : nSlot = SID_ATTR_CHAR_CTL_POSTURE; break;
+ }
+ nWhich = GetWhich( nSlot );
+ FontItalic eItalic = aInfo.GetItalic();
+ if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
+ eItalic = ITALIC_NONE;
+ SvxPostureItem aPostureItem( eItalic, nWhich );
+ pOld = GetOldItem( rSet, nSlot );
+
+ if ( pOld )
+ {
+ const SvxPostureItem& rItem = *static_cast<const SvxPostureItem*>(pOld);
+
+ if ( rItem.GetValue() == aPostureItem.GetValue() )
+ bChanged = false;
+ }
+
+ if ( !bChanged )
+ {
+ bChanged = pStyleBox->get_saved_value().isEmpty();
+
+ if ( m_pImpl->m_bInSearchMode && bChanged &&
+ aInfo.GetItalic() == ITALIC_NONE && aInfo.GetWeight() != WEIGHT_NORMAL )
+ bChanged = false;
+ }
+
+ if ( !bChanged && pExampleSet &&
+ pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
+ static_cast<const SvxPostureItem*>(pItem)->GetValue() != aPostureItem.GetValue() )
+ bChanged = true;
+
+ if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
+ bChanged = ( nEntryPos == ( m_pImpl->m_nExtraEntryPos + 1 ) );
+
+ if ( bChanged && !aText.isEmpty() )
+ {
+ rSet.Put( aPostureItem );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet.InvalidateItem(nWhich);
+
+ // FontSize
+ tools::Long nSize = pSizeBox->get_value();
+
+ if ( pSizeBox->get_active_text().isEmpty() ) // GetValue() returns the min-value
+ nSize = 0;
+ tools::Long nSavedSize = pSizeBox->get_saved_value();
+ const bool bRel = pSizeBox->IsRelative();
+
+ switch ( eLangGrp )
+ {
+ case Western : nSlot = SID_ATTR_CHAR_FONTHEIGHT; break;
+ case Asian : nSlot = SID_ATTR_CHAR_CJK_FONTHEIGHT; break;
+ case Ctl : nSlot = SID_ATTR_CHAR_CTL_FONTHEIGHT; break;
+ }
+ nWhich = GetWhich( nSlot );
+ const SvxFontHeightItem* pOldHeight = static_cast<const SvxFontHeightItem*>(GetOldItem( rSet, nSlot ));
+ bChanged = ( nSize != nSavedSize );
+
+ if ( !bChanged && pExampleSet &&
+ pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET )
+ {
+ float fSize = static_cast<float>(nSize) / 10;
+ tools::Long nVal = CalcToUnit( fSize, rSet.GetPool()->GetMetric( nWhich ) );
+ if ( static_cast<const SvxFontHeightItem*>(pItem)->GetHeight() != static_cast<sal_uInt32>(nVal) )
+ bChanged = true;
+ }
+
+ if ( bChanged || !pOldHeight ||
+ bRel != ( MapUnit::MapRelative != pOldHeight->GetPropUnit() || 100 != pOldHeight->GetProp() ) )
+ {
+ MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
+ if ( pSizeBox->IsRelative() )
+ {
+ DBG_ASSERT( GetItemSet().GetParent(), "No parent set" );
+ const SvxFontHeightItem& rOldItem =
+ static_cast<const SvxFontHeightItem&>(GetItemSet().GetParent()->Get( nWhich ));
+
+ SvxFontHeightItem aHeight( 240, 100, nWhich );
+ if ( pSizeBox->IsPtRelative() )
+ aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>( nSize / 10 ), MapUnit::MapPoint, eUnit );
+ else
+ aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>(nSize) );
+ rSet.Put( aHeight );
+ }
+ else
+ {
+ float fSize = static_cast<float>(nSize) / 10;
+ rSet.Put( SvxFontHeightItem( CalcToUnit( fSize, eUnit ), 100, nWhich ) );
+ }
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet.InvalidateItem(nWhich);
+
+ bChanged = true;
+ switch ( eLangGrp )
+ {
+ case Western : nSlot = SID_ATTR_CHAR_LANGUAGE; break;
+ case Asian : nSlot = SID_ATTR_CHAR_CJK_LANGUAGE; break;
+ case Ctl : nSlot = SID_ATTR_CHAR_CTL_LANGUAGE; break;
+ }
+ nWhich = GetWhich( nSlot );
+ pOld = GetOldItem( rSet, nSlot );
+
+ // For language list boxes acting as ComboBox, check for, add and select an
+ // edited entry.
+ if (pLangBox == m_xWestFontLanguageLB.get())
+ {
+ switch (pLangBox->GetEditedAndValid())
+ {
+ case SvxLanguageBox::EditedAndValid::No:
+ ; // nothing to do
+ break;
+ case SvxLanguageBox::EditedAndValid::Valid:
+ {
+ const int nPos = pLangBox->SaveEditedAsEntry();
+ if (nPos != -1)
+ pLangBox->set_active(nPos);
+ }
+ break;
+ case SvxLanguageBox::EditedAndValid::Invalid:
+ pLangBox->set_active_id(pLangBox->get_saved_active_id());
+ break;
+ }
+ }
+
+ int nLangPos = pLangBox->get_active();
+ LanguageType eLangType = pLangBox->get_active_id();
+
+ if (pOld)
+ {
+ const SvxLanguageItem& rItem = *static_cast<const SvxLanguageItem*>(pOld);
+ if (nLangPos == -1 || eLangType == rItem.GetValue())
+ bChanged = false;
+ }
+
+ if (!bChanged)
+ bChanged = pLangBox->get_active_id_changed_from_saved();
+
+ if (bChanged && nLangPos != -1)
+ {
+ rSet.Put(SvxLanguageItem(eLangType, nWhich));
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet.InvalidateItem(nWhich);
+
+ return bModified;
+}
+
+IMPL_LINK_NOARG(SvxCharNamePage, UpdateHdl_Impl, Timer *, void)
+{
+ UpdatePreview_Impl();
+}
+
+IMPL_LINK(SvxCharNamePage, FontModifyComboBoxHdl_Impl, weld::ComboBox&, rBox, void)
+{
+ FontModifyHdl_Impl(rBox);
+}
+
+IMPL_LINK(SvxCharNamePage, FontFeatureButtonClicked, weld::Button&, rButton, void)
+{
+ OUString sFontName;
+ weld::ComboBox* pNameBox = nullptr;
+
+ if (&rButton == m_xWestFontFeaturesButton.get())
+ {
+ pNameBox = m_xWestFontNameLB.get();
+ sFontName = GetPreviewFont().GetFamilyName();
+ }
+ else if (&rButton == m_xEastFontFeaturesButton.get())
+ {
+ pNameBox = m_xEastFontNameLB.get();
+ sFontName = GetPreviewCJKFont().GetFamilyName();
+ }
+ else if (&rButton == m_xCTLFontFeaturesButton.get())
+ {
+ pNameBox = m_xCTLFontNameLB.get();
+ sFontName = GetPreviewCTLFont().GetFamilyName();
+ }
+
+ if (!sFontName.isEmpty() && pNameBox)
+ {
+ cui::FontFeaturesDialog aDialog(GetFrameWeld(), sFontName);
+ if (aDialog.run() == RET_OK)
+ {
+ pNameBox->set_entry_text(aDialog.getResultFontName());
+ UpdatePreview_Impl();
+ }
+ }
+}
+
+void SvxCharNamePage::FontModifyHdl_Impl(const weld::Widget& rNameBox)
+{
+ m_pImpl->m_aUpdateIdle.Start();
+
+ if (m_xWestFontNameLB.get() == &rNameBox || m_xEastFontNameLB.get() == &rNameBox || m_xCTLFontNameLB.get() == &rNameBox)
+ {
+ FillStyleBox_Impl(rNameBox);
+ FillSizeBox_Impl(rNameBox);
+ EnableFeatureButton(rNameBox);
+ }
+}
+
+void SvxCharNamePage::ActivatePage( const SfxItemSet& rSet )
+{
+ SvxCharBasePage::ActivatePage( rSet );
+
+ UpdatePreview_Impl(); // instead of asynchronous calling in ctor
+}
+
+DeactivateRC SvxCharNamePage::DeactivatePage( SfxItemSet* _pSet )
+{
+ if ( _pSet )
+ FillItemSet( _pSet );
+ return DeactivateRC::LeavePage;
+}
+
+std::unique_ptr<SfxTabPage> SvxCharNamePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
+{
+ return std::make_unique<SvxCharNamePage>(pPage, pController, *rSet );
+}
+
+void SvxCharNamePage::Reset( const SfxItemSet* rSet )
+{
+ Reset_Impl( *rSet, Western );
+ Reset_Impl( *rSet, Asian );
+ Reset_Impl( *rSet, Ctl );
+
+ SetPrevFontWidthScale( *rSet );
+ UpdatePreview_Impl();
+}
+
+void SvxCharNamePage::ChangesApplied()
+{
+ m_xWestFontNameLB->save_value();
+ m_xWestFontStyleLB->save_value();
+ m_xWestFontSizeLB->save_value();
+ m_xWestFontLanguageLB->save_active_id();
+ m_xEastFontNameLB->save_value();
+ m_xEastFontStyleLB->save_value();
+ m_xEastFontSizeLB->save_value();
+ m_xEastFontLanguageLB->save_active_id();
+ m_xCTLFontNameLB->save_value();
+ m_xCTLFontStyleLB->save_value();
+ m_xCTLFontSizeLB->save_value();
+ m_xCTLFontLanguageLB->save_active_id();
+}
+
+bool SvxCharNamePage::FillItemSet( SfxItemSet* rSet )
+{
+ bool bModified = FillItemSet_Impl( *rSet, Western );
+ bModified |= FillItemSet_Impl( *rSet, Asian );
+ bModified |= FillItemSet_Impl( *rSet, Ctl );
+ return bModified;
+}
+
+void SvxCharNamePage::SetFontList( const SvxFontListItem& rItem )
+{
+ m_pImpl->m_pFontList = rItem.GetFontList()->Clone();
+}
+
+namespace
+{
+ void enableRelativeMode( SvxCharNamePage const * _pPage, FontSizeBox* _pFontSizeLB, sal_uInt16 _nHeightWhich )
+ {
+ _pFontSizeLB->EnableRelativeMode( 5, 995 ); // min 5%, max 995%, step 5
+
+ const SvxFontHeightItem& rHeightItem =
+ static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nHeightWhich ));
+ MapUnit eUnit = _pPage->GetItemSet().GetPool()->GetMetric( _nHeightWhich );
+ short nCurHeight =
+ static_cast< short >( CalcToPoint( rHeightItem.GetHeight(), eUnit, 1 ) * 10 );
+
+ // based on the current height:
+ // - negative until minimum of 2 pt
+ // - positive until maximum of 999 pt
+ _pFontSizeLB->EnablePtRelativeMode( sal::static_int_cast< short >(-(nCurHeight - 20)), (9999 - nCurHeight) );
+ }
+}
+
+void SvxCharNamePage::EnableRelativeMode()
+{
+ DBG_ASSERT( GetItemSet().GetParent(), "RelativeMode, but no ParentSet!" );
+ enableRelativeMode(this,m_xWestFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_FONTHEIGHT ));
+ enableRelativeMode(this,m_xEastFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ));
+ enableRelativeMode(this,m_xCTLFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ));
+}
+
+void SvxCharNamePage::EnableSearchMode()
+{
+ m_pImpl->m_bInSearchMode = true;
+}
+
+void SvxCharNamePage::DisableControls( sal_uInt16 nDisable )
+{
+ if ( DISABLE_HIDE_LANGUAGE & nDisable )
+ {
+ if ( m_xWestFontLanguageFT ) m_xWestFontLanguageFT->hide();
+ if ( m_xWestFontLanguageLB ) m_xWestFontLanguageLB->hide();
+ if ( m_xEastFontLanguageFT ) m_xEastFontLanguageFT->hide();
+ if ( m_xEastFontLanguageLB ) m_xEastFontLanguageLB->hide();
+ if ( m_xCTLFontLanguageFT ) m_xCTLFontLanguageFT->hide();
+ if ( m_xCTLFontLanguageLB ) m_xCTLFontLanguageLB->hide();
+ }
+}
+
+void SvxCharNamePage::PageCreated(const SfxAllItemSet& aSet)
+{
+ const SvxFontListItem* pFontListItem = aSet.GetItem<SvxFontListItem>(SID_ATTR_CHAR_FONTLIST, false);
+ const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
+ const SfxUInt16Item* pDisableItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false);
+ if (pFontListItem)
+ SetFontList(*pFontListItem);
+
+ if (pFlagItem)
+ {
+ sal_uInt32 nFlags=pFlagItem->GetValue();
+ if ( ( nFlags & SVX_RELATIVE_MODE ) == SVX_RELATIVE_MODE )
+ EnableRelativeMode();
+ if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
+ // the writer uses SID_ATTR_BRUSH as font background
+ m_bPreviewBackgroundToCharacter = true;
+ }
+ if (pDisableItem)
+ DisableControls(pDisableItem->GetValue());
+}
+// class SvxCharEffectsPage ----------------------------------------------
+
+SvxCharEffectsPage::SvxCharEffectsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
+ : SvxCharBasePage(pPage, pController, "cui/ui/effectspage.ui", "EffectsPage", rInSet)
+ , m_bOrigFontColor(false)
+ , m_bNewFontColor(false)
+ , m_bEnableNoneFontColor(false)
+ , m_xFontColorFT(m_xBuilder->weld_label("fontcolorft"))
+ , m_xFontColorLB(new ColorListBox(m_xBuilder->weld_menu_button("fontcolorlb"),
+ [this]{ return GetDialogController()->getDialog(); }))
+ , m_xFontTransparencyFT(m_xBuilder->weld_label("fonttransparencyft"))
+ , m_xFontTransparencyMtr(
+ m_xBuilder->weld_metric_spin_button("fonttransparencymtr", FieldUnit::PERCENT))
+ , m_xEffectsFT(m_xBuilder->weld_label("effectsft"))
+ , m_xEffectsLB(m_xBuilder->weld_combo_box("effectslb"))
+ , m_xReliefFT(m_xBuilder->weld_label("reliefft"))
+ , m_xReliefLB(m_xBuilder->weld_combo_box("relieflb"))
+ , m_xOutlineBtn(m_xBuilder->weld_check_button("outlinecb"))
+ , m_xShadowBtn(m_xBuilder->weld_check_button("shadowcb"))
+ , m_xHiddenBtn(m_xBuilder->weld_check_button("hiddencb"))
+ , m_xOverlineLB(m_xBuilder->weld_combo_box("overlinelb"))
+ , m_xOverlineColorFT(m_xBuilder->weld_label("overlinecolorft"))
+ , m_xOverlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("overlinecolorlb"),
+ [this]{ return GetDialogController()->getDialog(); }))
+ , m_xStrikeoutLB(m_xBuilder->weld_combo_box("strikeoutlb"))
+ , m_xUnderlineLB(m_xBuilder->weld_combo_box("underlinelb"))
+ , m_xUnderlineColorFT(m_xBuilder->weld_label("underlinecolorft"))
+ , m_xUnderlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("underlinecolorlb"),
+ [this]{ return GetDialogController()->getDialog(); }))
+ , m_xIndividualWordsBtn(m_xBuilder->weld_check_button("individualwordscb"))
+ , m_xEmphasisFT(m_xBuilder->weld_label("emphasisft"))
+ , m_xEmphasisLB(m_xBuilder->weld_combo_box("emphasislb"))
+ , m_xPositionFT(m_xBuilder->weld_label("positionft"))
+ , m_xPositionLB(m_xBuilder->weld_combo_box("positionlb"))
+ , m_xA11yWarningFT(m_xBuilder->weld_label("a11ywarning"))
+{
+ m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
+#ifdef IOS
+ m_xPreviewWin->hide();
+#endif
+ m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
+ m_xOverlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
+ m_xUnderlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
+ Initialize();
+}
+
+void SvxCharEffectsPage::EnableNoneFontColor()
+{
+ m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR, true);
+ m_bEnableNoneFontColor = true;
+}
+
+SvxCharEffectsPage::~SvxCharEffectsPage()
+{
+ m_xUnderlineColorLB.reset();
+ m_xOverlineColorLB.reset();
+ m_xFontTransparencyMtr.reset();
+ m_xFontColorLB.reset();
+}
+
+void SvxCharEffectsPage::Initialize()
+{
+ // to handle the changes of the other pages
+ SetExchangeSupport();
+
+ // HTML-Mode
+ const SfxUInt16Item* pHtmlModeItem = GetItemSet().GetItemIfSet( SID_HTML_MODE, false );
+ if ( !pHtmlModeItem)
+ {
+ if (SfxObjectShell* pShell = SfxObjectShell::Current())
+ pHtmlModeItem = pShell->GetItem( SID_HTML_MODE );
+ }
+ if (pHtmlModeItem)
+ {
+ m_nHtmlMode = pHtmlModeItem->GetValue();
+ if ( ( m_nHtmlMode & HTMLMODE_ON ) == HTMLMODE_ON )
+ {
+ //!!! hide some controls please
+ }
+ }
+
+ m_xFontColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
+ m_xFontTransparencyMtr->connect_value_changed(
+ LINK(this, SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl));
+
+ // handler
+ Link<weld::ComboBox&,void> aLink = LINK( this, SvxCharEffectsPage, SelectListBoxHdl_Impl );
+ m_xUnderlineLB->connect_changed( aLink );
+ m_xUnderlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
+ m_xOverlineLB->connect_changed( aLink );
+ m_xOverlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
+ m_xStrikeoutLB->connect_changed( aLink );
+ m_xEmphasisLB->connect_changed( aLink );
+ m_xPositionLB->connect_changed( aLink );
+ m_xEffectsLB->connect_changed( aLink );
+ m_xReliefLB->connect_changed( aLink );
+
+ m_xUnderlineLB->set_active( 0 );
+ m_xOverlineLB->set_active( 0 );
+ m_xStrikeoutLB->set_active( 0 );
+ m_xEmphasisLB->set_active( 0 );
+ m_xPositionLB->set_active( 0 );
+ SelectHdl_Impl(nullptr);
+ SelectHdl_Impl(m_xEmphasisLB.get());
+
+ m_xEffectsLB->set_active( 0 );
+
+ m_xHiddenBtn->connect_toggled(LINK(this, SvxCharEffectsPage, HiddenBtnClickHdl));
+ m_xIndividualWordsBtn->connect_toggled(LINK(this, SvxCharEffectsPage, CbClickHdl_Impl));
+ m_xOutlineBtn->connect_toggled(LINK(this, SvxCharEffectsPage, OutlineBtnClickHdl));
+ m_xShadowBtn->connect_toggled(LINK(this, SvxCharEffectsPage, ShadowBtnClickHdl));
+
+ if ( !SvtCJKOptions::IsAsianTypographyEnabled() )
+ {
+ m_xEmphasisFT->hide();
+ m_xEmphasisLB->hide();
+ m_xPositionFT->hide();
+ m_xPositionLB->hide();
+ }
+
+ m_xA11yWarningFT->set_visible(officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get());
+}
+
+void SvxCharEffectsPage::UpdatePreview_Impl()
+{
+ SvxFont& rFont = GetPreviewFont();
+ SvxFont& rCJKFont = GetPreviewCJKFont();
+ SvxFont& rCTLFont = GetPreviewCTLFont();
+
+ const Color& rSelectedColor = m_xFontColorLB->GetSelectEntryColor();
+ rFont.SetColor(rSelectedColor);
+ rCJKFont.SetColor(rSelectedColor);
+ rCTLFont.SetColor(rSelectedColor);
+ m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO
+
+ FontLineStyle eUnderline = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32());
+ FontLineStyle eOverline = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32());
+ FontStrikeout eStrikeout = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32());
+ rFont.SetUnderline( eUnderline );
+ rCJKFont.SetUnderline( eUnderline );
+ rCTLFont.SetUnderline( eUnderline );
+ m_aPreviewWin.SetTextLineColor( m_xUnderlineColorLB->GetSelectEntryColor() );
+ rFont.SetOverline( eOverline );
+ rCJKFont.SetOverline( eOverline );
+ rCTLFont.SetOverline( eOverline );
+ m_aPreviewWin.SetOverlineColor( m_xOverlineColorLB->GetSelectEntryColor() );
+ rFont.SetStrikeout( eStrikeout );
+ rCJKFont.SetStrikeout( eStrikeout );
+ rCTLFont.SetStrikeout( eStrikeout );
+
+ auto nEmphasis = m_xEmphasisLB->get_active();
+ if (nEmphasis != -1)
+ {
+ bool bUnder = (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32());
+ FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nEmphasis);
+ eMark |= bUnder ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove;
+ rFont.SetEmphasisMark( eMark );
+ rCJKFont.SetEmphasisMark( eMark );
+ rCTLFont.SetEmphasisMark( eMark );
+ }
+
+ auto nRelief = m_xReliefLB->get_active();
+ if (nRelief != -1)
+ {
+ rFont.SetRelief( static_cast<FontRelief>(nRelief) );
+ rCJKFont.SetRelief( static_cast<FontRelief>(nRelief) );
+ rCTLFont.SetRelief( static_cast<FontRelief>(nRelief) );
+ }
+
+ rFont.SetOutline( StateToAttr( m_xOutlineBtn->get_state() ) );
+ rCJKFont.SetOutline( rFont.IsOutline() );
+ rCTLFont.SetOutline( rFont.IsOutline() );
+
+ rFont.SetShadow( StateToAttr( m_xShadowBtn->get_state() ) );
+ rCJKFont.SetShadow( rFont.IsShadow() );
+ rCTLFont.SetShadow( rFont.IsShadow() );
+
+ auto nCapsPos = m_xEffectsLB->get_active();
+ if (nCapsPos != -1)
+ {
+ SvxCaseMap eCaps = static_cast<SvxCaseMap>(nCapsPos);
+ rFont.SetCaseMap( eCaps );
+ rCJKFont.SetCaseMap( eCaps );
+ // #i78474# small caps do not exist in CTL fonts
+ rCTLFont.SetCaseMap( eCaps == SvxCaseMap::SmallCaps ? SvxCaseMap::NotMapped : eCaps );
+ }
+
+ bool bWordLine = StateToAttr( m_xIndividualWordsBtn->get_state() );
+ rFont.SetWordLineMode( bWordLine );
+ rCJKFont.SetWordLineMode( bWordLine );
+ rCTLFont.SetWordLineMode( bWordLine );
+
+ m_aPreviewWin.Invalidate();
+}
+
+void SvxCharEffectsPage::SetCaseMap_Impl( SvxCaseMap eCaseMap )
+{
+ if ( SvxCaseMap::End > eCaseMap )
+ m_xEffectsLB->set_active(
+ sal::static_int_cast< sal_Int32 >( eCaseMap ) );
+ else
+ {
+ // not mapped
+ m_xEffectsLB->set_active(-1);
+ }
+
+ UpdatePreview_Impl();
+}
+
+void SvxCharEffectsPage::ResetColor_Impl( const SfxItemSet& rSet )
+{
+ sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
+ SfxItemState eState = rSet.GetItemState( nWhich );
+
+ m_bOrigFontColor = false;
+ switch ( eState )
+ {
+ case SfxItemState::UNKNOWN:
+ m_xFontColorFT->hide();
+ m_xFontColorLB->hide();
+ break;
+
+ case SfxItemState::DISABLED:
+ m_xFontColorFT->set_sensitive(false);
+ m_xFontColorLB->set_sensitive(false);
+ break;
+
+ case SfxItemState::DONTCARE:
+ //Related: tdf#106080 if there is no font color, then allow "none"
+ //as a color so the listbox can display that state.
+ EnableNoneFontColor();
+ m_xFontColorLB->SetNoSelection();
+ break;
+
+ case SfxItemState::DEFAULT:
+ case SfxItemState::SET:
+ {
+ SvxFont& rFont = GetPreviewFont();
+ SvxFont& rCJKFont = GetPreviewCJKFont();
+ SvxFont& rCTLFont = GetPreviewCTLFont();
+
+ const SvxColorItem& rItem = static_cast<const SvxColorItem&>(rSet.Get( nWhich ));
+ Color aColor = rItem.GetValue();
+ rFont.SetColor(aColor);
+ rCJKFont.SetColor(aColor);
+ rCTLFont.SetColor(aColor);
+ m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO
+
+ m_aPreviewWin.Invalidate();
+
+ Color aRGBColor = aColor;
+ if (aRGBColor.IsTransparent() && aColor != COL_AUTO)
+ {
+ aRGBColor.SetAlpha(255);
+ }
+ m_xFontColorLB->SelectEntry(aRGBColor);
+
+ if (m_xFontTransparencyMtr->get_visible() && aColor != COL_AUTO)
+ {
+ double fTransparency = (255 - aColor.GetAlpha()) * 100.0 / 255;
+ m_xFontTransparencyMtr->set_value(basegfx::fround(fTransparency),
+ FieldUnit::PERCENT);
+ }
+
+ m_aOrigFontColor = aColor;
+ m_bOrigFontColor = true;
+ break;
+ }
+ }
+ m_bNewFontColor = false;
+}
+
+bool SvxCharEffectsPage::FillItemSetColor_Impl( SfxItemSet& rSet )
+{
+ sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
+ const SfxItemSet& rOldSet = GetItemSet();
+
+ svx::NamedThemedColor aSelectedColor;
+ bool bChanged = m_bNewFontColor;
+
+ if (bChanged)
+ {
+ aSelectedColor = m_xFontColorLB->GetSelectedEntryThemedColor();
+
+ if (m_xFontTransparencyMtr->get_value_changed_from_saved())
+ {
+ double fTransparency
+ = m_xFontTransparencyMtr->get_value(FieldUnit::PERCENT) * 255.0 / 100;
+ aSelectedColor.m_aColor.SetAlpha(255 - static_cast<sal_uInt8>(basegfx::fround(fTransparency)));
+ }
+
+ if (m_bOrigFontColor)
+ bChanged = aSelectedColor.m_aColor != m_aOrigFontColor;
+ if (m_bEnableNoneFontColor && bChanged && aSelectedColor.m_aColor == COL_NONE_COLOR)
+ bChanged = false;
+ }
+
+ if (bChanged)
+ {
+ SvxColorItem aItem( aSelectedColor.m_aColor, nWhich );
+
+ if (aSelectedColor.m_nThemeIndex != -1)
+ {
+ // The color was picked from the theme palette, remember its index.
+ aItem.GetThemeColor().SetThemeIndex(aSelectedColor.m_nThemeIndex);
+ aItem.GetThemeColor().SetLumMod(aSelectedColor.m_nLumMod);
+ aItem.GetThemeColor().SetLumOff(aSelectedColor.m_nLumOff);
+ }
+
+ rSet.Put(aItem);
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet.InvalidateItem(nWhich);
+
+ return bChanged;
+}
+
+IMPL_LINK( SvxCharEffectsPage, SelectListBoxHdl_Impl, weld::ComboBox&, rBox, void )
+{
+ SelectHdl_Impl(&rBox);
+}
+
+void SvxCharEffectsPage::SelectHdl_Impl(const weld::ComboBox* pBox)
+{
+ if (m_xEmphasisLB.get() == pBox)
+ {
+ auto nEPos = m_xEmphasisLB->get_active();
+ bool bEnable = nEPos > 0;
+ m_xPositionFT->set_sensitive( bEnable );
+ m_xPositionLB->set_sensitive( bEnable );
+ }
+ else if (m_xReliefLB.get() == pBox)
+ {
+ bool bEnable = ( pBox->get_active() == 0 );
+ m_xOutlineBtn->set_sensitive( bEnable );
+ m_xShadowBtn->set_sensitive( bEnable );
+ }
+ else if (m_xPositionLB.get() != pBox)
+ {
+ auto nUPos = m_xUnderlineLB->get_active();
+ bool bUEnable = nUPos > 0;
+ m_xUnderlineColorFT->set_sensitive(bUEnable);
+ m_xUnderlineColorLB->set_sensitive(bUEnable);
+
+ auto nOPos = m_xOverlineLB->get_active();
+ bool bOEnable = nOPos > 0;
+ m_xOverlineColorFT->set_sensitive(bOEnable);
+ m_xOverlineColorLB->set_sensitive(bOEnable);
+
+ auto nSPos = m_xStrikeoutLB->get_active();
+ m_xIndividualWordsBtn->set_sensitive( bUEnable || bOEnable || nSPos > 0);
+ }
+ UpdatePreview_Impl();
+}
+
+IMPL_LINK(SvxCharEffectsPage, CbClickHdl_Impl, weld::Toggleable&, rToggle, void)
+{
+ m_aIndividualWordsState.ButtonToggled(rToggle);
+ UpdatePreview_Impl();
+ UpdatePreview_Impl();
+}
+
+IMPL_LINK(SvxCharEffectsPage, ColorBoxSelectHdl_Impl, ColorListBox&, rBox, void)
+{
+ if (m_xFontColorLB.get() == &rBox)
+ m_bNewFontColor = true;
+ UpdatePreview_Impl();
+}
+
+IMPL_LINK_NOARG(SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl, weld::MetricSpinButton&, void)
+{
+ m_bNewFontColor = true;
+}
+
+DeactivateRC SvxCharEffectsPage::DeactivatePage( SfxItemSet* _pSet )
+{
+ if ( _pSet )
+ FillItemSet( _pSet );
+ return DeactivateRC::LeavePage;
+}
+
+std::unique_ptr<SfxTabPage> SvxCharEffectsPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
+{
+ return std::make_unique<SvxCharEffectsPage>( pPage, pController, *rSet );
+}
+
+void SvxCharEffectsPage::Reset( const SfxItemSet* rSet )
+{
+ SvxFont& rFont = GetPreviewFont();
+ SvxFont& rCJKFont = GetPreviewCJKFont();
+ SvxFont& rCTLFont = GetPreviewCTLFont();
+
+ bool bEnable = false;
+
+ // Underline
+ sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE );
+ rFont.SetUnderline( LINESTYLE_NONE );
+ rCJKFont.SetUnderline( LINESTYLE_NONE );
+ rCTLFont.SetUnderline( LINESTYLE_NONE );
+
+ m_xUnderlineLB->set_active( 0 );
+ SfxItemState eState = rSet->GetItemState( nWhich );
+
+ if ( eState >= SfxItemState::DONTCARE )
+ {
+ if ( eState == SfxItemState::DONTCARE )
+ m_xUnderlineLB->set_active(-1);
+ else
+ {
+ const SvxUnderlineItem& rItem = static_cast<const SvxUnderlineItem&>(rSet->Get( nWhich ));
+ FontLineStyle eUnderline = rItem.GetValue();
+ rFont.SetUnderline( eUnderline );
+ rCJKFont.SetUnderline( eUnderline );
+ rCTLFont.SetUnderline( eUnderline );
+
+ if ( eUnderline != LINESTYLE_NONE )
+ {
+ auto nPos = m_xUnderlineLB->find_id(OUString::number(eUnderline));
+ if (nPos != -1)
+ {
+ m_xUnderlineLB->set_active(nPos);
+ bEnable = true;
+ }
+ Color aColor = rItem.GetColor();
+ m_xUnderlineColorLB->SelectEntry(aColor);
+ }
+ else
+ {
+ m_xUnderlineColorLB->SelectEntry(COL_AUTO);
+ m_xUnderlineColorLB->set_sensitive(false);
+ }
+ }
+ }
+
+ // Overline
+ nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE );
+ rFont.SetOverline( LINESTYLE_NONE );
+ rCJKFont.SetOverline( LINESTYLE_NONE );
+ rCTLFont.SetOverline( LINESTYLE_NONE );
+
+ m_xOverlineLB->set_active( 0 );
+ eState = rSet->GetItemState( nWhich );
+
+ if ( eState >= SfxItemState::DONTCARE )
+ {
+ if ( eState == SfxItemState::DONTCARE )
+ m_xOverlineLB->set_active(-1);
+ else
+ {
+ const SvxOverlineItem& rItem = static_cast<const SvxOverlineItem&>(rSet->Get( nWhich ));
+ FontLineStyle eOverline = rItem.GetValue();
+ rFont.SetOverline( eOverline );
+ rCJKFont.SetOverline( eOverline );
+ rCTLFont.SetOverline( eOverline );
+
+ if ( eOverline != LINESTYLE_NONE )
+ {
+ auto nPos = m_xOverlineLB->find_id(OUString::number(eOverline));
+ if (nPos != -1)
+ {
+ m_xOverlineLB->set_active(nPos);
+ bEnable = true;
+ }
+ Color aColor = rItem.GetColor();
+ m_xOverlineColorLB->SelectEntry(aColor);
+ }
+ else
+ {
+ m_xOverlineColorLB->SelectEntry(COL_AUTO);
+ m_xOverlineColorLB->set_sensitive(false);
+ }
+ }
+ }
+
+ // Strikeout
+ nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT );
+ rFont.SetStrikeout( STRIKEOUT_NONE );
+ rCJKFont.SetStrikeout( STRIKEOUT_NONE );
+ rCTLFont.SetStrikeout( STRIKEOUT_NONE );
+
+ m_xStrikeoutLB->set_active( 0 );
+ eState = rSet->GetItemState( nWhich );
+
+ if ( eState >= SfxItemState::DONTCARE )
+ {
+ if ( eState == SfxItemState::DONTCARE )
+ m_xStrikeoutLB->set_active(-1);
+ else
+ {
+ const SvxCrossedOutItem& rItem = static_cast<const SvxCrossedOutItem&>(rSet->Get( nWhich ));
+ FontStrikeout eStrikeout = rItem.GetValue();
+ rFont.SetStrikeout( eStrikeout );
+ rCJKFont.SetStrikeout( eStrikeout );
+ rCTLFont.SetStrikeout( eStrikeout );
+
+ if ( eStrikeout != STRIKEOUT_NONE )
+ {
+ auto nPos = m_xStrikeoutLB->find_id(OUString::number(eStrikeout));
+ if (nPos != -1)
+ {
+ m_xStrikeoutLB->set_active(nPos);
+ bEnable = true;
+ }
+ }
+ }
+ }
+
+ // WordLineMode
+ nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE );
+ eState = rSet->GetItemState( nWhich );
+
+ switch ( eState )
+ {
+ case SfxItemState::UNKNOWN:
+ m_aIndividualWordsState.bTriStateEnabled = false;
+ m_xIndividualWordsBtn->hide();
+ break;
+
+ case SfxItemState::DISABLED:
+ m_aIndividualWordsState.bTriStateEnabled = false;
+ m_xIndividualWordsBtn->set_sensitive(false);
+ break;
+
+ case SfxItemState::DONTCARE:
+ m_aIndividualWordsState.bTriStateEnabled = true;
+ m_xIndividualWordsBtn->set_state( TRISTATE_INDET );
+ break;
+
+ case SfxItemState::DEFAULT:
+ case SfxItemState::SET:
+ {
+ const SvxWordLineModeItem& rItem = static_cast<const SvxWordLineModeItem&>(rSet->Get( nWhich ));
+ rFont.SetWordLineMode( rItem.GetValue() );
+ rCJKFont.SetWordLineMode( rItem.GetValue() );
+ rCTLFont.SetWordLineMode( rItem.GetValue() );
+
+ m_aIndividualWordsState.bTriStateEnabled = false;
+ m_xIndividualWordsBtn->set_active(rItem.GetValue());
+ m_xIndividualWordsBtn->set_sensitive(bEnable);
+ break;
+ }
+ }
+
+ // Emphasis
+ nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK );
+ eState = rSet->GetItemState( nWhich );
+
+ if ( eState >= SfxItemState::DEFAULT )
+ {
+ const SvxEmphasisMarkItem& rItem = static_cast<const SvxEmphasisMarkItem&>(rSet->Get( nWhich ));
+ FontEmphasisMark eMark = rItem.GetEmphasisMark();
+ rFont.SetEmphasisMark( eMark );
+ rCJKFont.SetEmphasisMark( eMark );
+ rCTLFont.SetEmphasisMark( eMark );
+
+ m_xEmphasisLB->set_active( static_cast<sal_Int32>(FontEmphasisMark( eMark & FontEmphasisMark::Style )) );
+ eMark &= ~FontEmphasisMark::Style;
+ int nEntryData = ( eMark == FontEmphasisMark::PosAbove )
+ ? CHRDLG_POSITION_OVER
+ : ( eMark == FontEmphasisMark::PosBelow ) ? CHRDLG_POSITION_UNDER : 0;
+
+ auto nPos = m_xPositionLB->find_id(OUString::number(nEntryData));
+ if (nPos != -1)
+ m_xPositionLB->set_active(nPos);
+ }
+ else if ( eState == SfxItemState::DONTCARE )
+ m_xEmphasisLB->set_active(-1);
+ else if ( eState == SfxItemState::UNKNOWN )
+ {
+ m_xEmphasisFT->hide();
+ m_xEmphasisLB->hide();
+ }
+ else // SfxItemState::DISABLED
+ {
+ m_xEmphasisFT->set_sensitive(false);
+ m_xEmphasisLB->set_sensitive(false);
+ }
+
+ // the select handler for the underline/overline/strikeout list boxes
+ SelectHdl_Impl(m_xUnderlineLB.get());
+
+ // the select handler for the emphasis listbox
+ SelectHdl_Impl(m_xEmphasisLB.get());
+
+ // Effects
+ SvxCaseMap eCaseMap = SvxCaseMap::End;
+ nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP );
+ eState = rSet->GetItemState( nWhich );
+ switch ( eState )
+ {
+ case SfxItemState::UNKNOWN:
+ m_xEffectsFT->hide();
+ m_xEffectsLB->hide();
+ break;
+
+ case SfxItemState::DISABLED:
+ m_xEffectsFT->set_sensitive(false);
+ m_xEffectsLB->set_sensitive(false);
+ break;
+
+ case SfxItemState::DONTCARE:
+ m_xEffectsLB->set_active(-1);
+ break;
+
+ case SfxItemState::DEFAULT:
+ case SfxItemState::SET:
+ {
+ const SvxCaseMapItem& rItem = static_cast<const SvxCaseMapItem&>(rSet->Get( nWhich ));
+ eCaseMap = rItem.GetValue();
+ break;
+ }
+ }
+ SetCaseMap_Impl( eCaseMap );
+
+ //Relief
+ nWhich = GetWhich(SID_ATTR_CHAR_RELIEF);
+ eState = rSet->GetItemState( nWhich );
+ switch ( eState )
+ {
+ case SfxItemState::UNKNOWN:
+ m_xReliefFT->hide();
+ m_xReliefLB->hide();
+ break;
+
+ case SfxItemState::DISABLED:
+ m_xReliefFT->set_sensitive(false);
+ m_xReliefLB->set_sensitive(false);
+ break;
+
+ case SfxItemState::DONTCARE:
+ m_xReliefLB->set_active(-1);
+ break;
+
+ case SfxItemState::DEFAULT:
+ case SfxItemState::SET:
+ {
+ const SvxCharReliefItem& rItem = static_cast<const SvxCharReliefItem&>(rSet->Get( nWhich ));
+ m_xReliefLB->set_active(static_cast<sal_Int32>(rItem.GetValue()));
+ SelectHdl_Impl(m_xReliefLB.get());
+ break;
+ }
+ }
+
+ // Outline
+ nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR );
+ eState = rSet->GetItemState( nWhich );
+ switch ( eState )
+ {
+ case SfxItemState::UNKNOWN:
+ m_aOutlineState.bTriStateEnabled = false;
+ m_xOutlineBtn->hide();
+ break;
+
+ case SfxItemState::DISABLED:
+ m_aOutlineState.bTriStateEnabled = false;
+ m_xOutlineBtn->set_sensitive(false);
+ break;
+
+ case SfxItemState::DONTCARE:
+ m_aOutlineState.bTriStateEnabled = true;
+ m_xOutlineBtn->set_state(TRISTATE_INDET);
+ break;
+
+ case SfxItemState::DEFAULT:
+ case SfxItemState::SET:
+ {
+ const SvxContourItem& rItem = static_cast<const SvxContourItem&>(rSet->Get( nWhich ));
+ m_aOutlineState.bTriStateEnabled = false;
+ m_xOutlineBtn->set_state(static_cast<TriState>(rItem.GetValue()));
+ break;
+ }
+ }
+
+ // Shadow
+ nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED );
+ eState = rSet->GetItemState( nWhich );
+
+ switch ( eState )
+ {
+ case SfxItemState::UNKNOWN:
+ m_aShadowState.bTriStateEnabled = false;
+ m_xShadowBtn->hide();
+ break;
+
+ case SfxItemState::DISABLED:
+ m_aShadowState.bTriStateEnabled = false;
+ m_xShadowBtn->set_sensitive(false);
+ break;
+
+ case SfxItemState::DONTCARE:
+ m_aShadowState.bTriStateEnabled = true;
+ m_xShadowBtn->set_state( TRISTATE_INDET );
+ break;
+
+ case SfxItemState::DEFAULT:
+ case SfxItemState::SET:
+ {
+ const SvxShadowedItem& rItem = static_cast<const SvxShadowedItem&>(rSet->Get( nWhich ));
+ m_aShadowState.bTriStateEnabled = false;
+ m_xShadowBtn->set_state( static_cast<TriState>(rItem.GetValue()) );
+ break;
+ }
+ }
+
+ // Hidden
+ nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN );
+ eState = rSet->GetItemState( nWhich );
+
+ switch ( eState )
+ {
+ case SfxItemState::UNKNOWN:
+ m_aHiddenState.bTriStateEnabled = false;
+ m_xHiddenBtn->hide();
+ break;
+
+ case SfxItemState::DISABLED:
+ m_aHiddenState.bTriStateEnabled = false;
+ m_xHiddenBtn->set_sensitive(false);
+ break;
+
+ case SfxItemState::DONTCARE:
+ m_aHiddenState.bTriStateEnabled = true;
+ m_xHiddenBtn->set_state(TRISTATE_INDET);
+ break;
+
+ case SfxItemState::DEFAULT:
+ case SfxItemState::SET:
+ {
+ const SvxCharHiddenItem& rItem = static_cast<const SvxCharHiddenItem&>(rSet->Get( nWhich ));
+ m_aHiddenState.bTriStateEnabled = false;
+ m_xHiddenBtn->set_state(static_cast<TriState>(rItem.GetValue()));
+ break;
+ }
+ }
+
+ SetPrevFontWidthScale( *rSet );
+ ResetColor_Impl( *rSet );
+
+ // preview update
+ m_aPreviewWin.Invalidate();
+
+ // save this settings
+ ChangesApplied();
+}
+
+IMPL_LINK(SvxCharEffectsPage, HiddenBtnClickHdl, weld::Toggleable&, rToggle, void)
+{
+ m_aHiddenState.ButtonToggled(rToggle);
+}
+
+IMPL_LINK(SvxCharEffectsPage, OutlineBtnClickHdl, weld::Toggleable&, rToggle, void)
+{
+ m_aOutlineState.ButtonToggled(rToggle);
+ UpdatePreview_Impl();
+}
+
+IMPL_LINK(SvxCharEffectsPage, ShadowBtnClickHdl, weld::Toggleable&, rToggle, void)
+{
+ m_aShadowState.ButtonToggled(rToggle);
+ UpdatePreview_Impl();
+}
+
+void SvxCharEffectsPage::ChangesApplied()
+{
+ m_xUnderlineLB->save_value();
+ m_xOverlineLB->save_value();
+ m_xStrikeoutLB->save_value();
+ m_xIndividualWordsBtn->save_state();
+ m_xEmphasisLB->save_value();
+ m_xPositionLB->save_value();
+ m_xEffectsLB->save_value();
+ m_xReliefLB->save_value();
+ m_xOutlineBtn->save_state();
+ m_xShadowBtn->save_state();
+ m_xHiddenBtn->save_state();
+ m_xFontTransparencyMtr->save_value();
+}
+
+bool SvxCharEffectsPage::FillItemSet( SfxItemSet* rSet )
+{
+ const SfxPoolItem* pOld = nullptr;
+ const SfxItemSet& rOldSet = GetItemSet();
+ bool bModified = false;
+ bool bChanged = true;
+
+ // Underline
+ sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_UNDERLINE );
+ auto nPos = m_xUnderlineLB->get_active();
+ FontLineStyle eUnder = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32());
+
+ if ( pOld )
+ {
+ //! if there are different underline styles in the selection the
+ //! item-state in the 'rOldSet' will be invalid. In this case
+ //! changing the underline style will be allowed if a style is
+ //! selected in the listbox.
+ bool bAllowChg = nPos != -1 &&
+ SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
+
+ const SvxUnderlineItem& rItem = *static_cast<const SvxUnderlineItem*>(pOld);
+ if ( rItem.GetValue() == eUnder &&
+ ( LINESTYLE_NONE == eUnder || rItem.GetColor() == m_xUnderlineColorLB->GetSelectEntryColor() ) &&
+ ! bAllowChg )
+ bChanged = false;
+ }
+
+ if ( bChanged )
+ {
+ SvxUnderlineItem aNewItem( eUnder, nWhich );
+ aNewItem.SetColor( m_xUnderlineColorLB->GetSelectEntryColor() );
+ rSet->Put( aNewItem );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bChanged = true;
+
+ // Overline
+ nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_OVERLINE );
+ nPos = m_xOverlineLB->get_active();
+ FontLineStyle eOver = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32());
+
+ if ( pOld )
+ {
+ //! if there are different underline styles in the selection the
+ //! item-state in the 'rOldSet' will be invalid. In this case
+ //! changing the underline style will be allowed if a style is
+ //! selected in the listbox.
+ bool bAllowChg = nPos != -1 &&
+ SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
+
+ const SvxOverlineItem& rItem = *static_cast<const SvxOverlineItem*>(pOld);
+ if ( rItem.GetValue() == eOver &&
+ ( LINESTYLE_NONE == eOver || rItem.GetColor() == m_xOverlineColorLB->GetSelectEntryColor() ) &&
+ ! bAllowChg )
+ bChanged = false;
+ }
+
+ if ( bChanged )
+ {
+ SvxOverlineItem aNewItem( eOver, nWhich );
+ aNewItem.SetColor( m_xOverlineColorLB->GetSelectEntryColor() );
+ rSet->Put( aNewItem );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bChanged = true;
+
+ // Strikeout
+ nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_STRIKEOUT );
+ nPos = m_xStrikeoutLB->get_active();
+ FontStrikeout eStrike = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32());
+
+ if ( pOld )
+ {
+ //! if there are different strikeout styles in the selection the
+ //! item-state in the 'rOldSet' will be invalid. In this case
+ //! changing the strikeout style will be allowed if a style is
+ //! selected in the listbox.
+ bool bAllowChg = nPos != -1 &&
+ SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
+
+ const SvxCrossedOutItem& rItem = *static_cast<const SvxCrossedOutItem*>(pOld);
+ if ( !m_xStrikeoutLB->get_sensitive()
+ || (rItem.GetValue() == eStrike && !bAllowChg) )
+ bChanged = false;
+ }
+
+ if ( bChanged )
+ {
+ rSet->Put( SvxCrossedOutItem( eStrike, nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bChanged = true;
+
+ // Individual words
+ const SfxItemSet* pExampleSet = GetDialogExampleSet();
+ nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_WORDLINEMODE );
+ TriState eState = m_xIndividualWordsBtn->get_state();
+ const SfxPoolItem* pItem;
+
+ if ( pOld )
+ {
+ const SvxWordLineModeItem& rItem = *static_cast<const SvxWordLineModeItem*>(pOld);
+ if ( rItem.GetValue() == StateToAttr( eState ) && m_xIndividualWordsBtn->get_saved_state() == eState )
+ bChanged = false;
+ }
+
+ if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
+ !StateToAttr( eState ) && static_cast<const SvxWordLineModeItem*>(pItem)->GetValue() )
+ bChanged = true;
+
+ if ( bChanged && eState != TRISTATE_INDET )
+ {
+ rSet->Put( SvxWordLineModeItem( StateToAttr( eState ), nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bChanged = true;
+
+ // Emphasis
+ nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_EMPHASISMARK );
+ int nMarkPos = m_xEmphasisLB->get_active();
+ OUString sMarkPos = m_xEmphasisLB->get_active_text();
+ OUString sPosPos = m_xPositionLB->get_active_text();
+ FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nMarkPos);
+ if (m_xPositionLB->get_sensitive())
+ {
+ eMark |= (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32())
+ ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove;
+ }
+
+ if ( pOld )
+ {
+ if( rOldSet.GetItemState( nWhich ) != SfxItemState::DONTCARE )
+ {
+ const SvxEmphasisMarkItem& rItem = *static_cast<const SvxEmphasisMarkItem*>(pOld);
+ if ( rItem.GetEmphasisMark() == eMark )
+ bChanged = false;
+ }
+ }
+
+ if (rOldSet.GetItemState( nWhich ) == SfxItemState::DONTCARE &&
+ m_xEmphasisLB->get_saved_value() == sMarkPos && m_xPositionLB->get_saved_value() == sPosPos)
+ {
+ bChanged = false;
+ }
+
+ if (bChanged)
+ {
+ rSet->Put( SvxEmphasisMarkItem( eMark, nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bChanged = true;
+
+ // Effects
+ nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CASEMAP );
+ SvxCaseMap eCaseMap = SvxCaseMap::NotMapped;
+ bool bChecked = false;
+ auto nCapsPos = m_xEffectsLB->get_active();
+ if (nCapsPos != -1)
+ {
+ eCaseMap = static_cast<SvxCaseMap>(nCapsPos);
+ bChecked = true;
+ }
+
+ if ( pOld )
+ {
+ //! if there are different effect styles in the selection the
+ //! item-state in the 'rOldSet' will be invalid. In this case
+ //! changing the effect style will be allowed if a style is
+ //! selected in the listbox.
+ bool bAllowChg = nPos != -1 &&
+ SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
+
+ const SvxCaseMapItem& rItem = *static_cast<const SvxCaseMapItem*>(pOld);
+ if ( rItem.GetValue() == eCaseMap && !bAllowChg )
+ bChanged = false;
+ }
+
+ if ( bChanged && bChecked )
+ {
+ rSet->Put( SvxCaseMapItem( eCaseMap, nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bChanged = true;
+
+ //Relief
+ nWhich = GetWhich(SID_ATTR_CHAR_RELIEF);
+ if (m_xReliefLB->get_value_changed_from_saved())
+ {
+ m_xReliefLB->save_value();
+ SvxCharReliefItem aRelief(static_cast<FontRelief>(m_xReliefLB->get_active()), nWhich);
+ rSet->Put(aRelief);
+ }
+
+ // Outline
+ nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CONTOUR );
+ eState = m_xOutlineBtn->get_state();
+
+ if ( pOld )
+ {
+ const SvxContourItem& rItem = *static_cast<const SvxContourItem*>(pOld);
+ if ( rItem.GetValue() == StateToAttr( eState ) && m_xOutlineBtn->get_saved_state() == eState )
+ bChanged = false;
+ }
+
+ if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
+ !StateToAttr( eState ) && static_cast<const SvxContourItem*>(pItem)->GetValue() )
+ bChanged = true;
+
+ if ( bChanged && eState != TRISTATE_INDET )
+ {
+ rSet->Put( SvxContourItem( StateToAttr( eState ), nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bChanged = true;
+
+ // Shadow
+ nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_SHADOWED );
+ eState = m_xShadowBtn->get_state();
+
+ if ( pOld )
+ {
+ const SvxShadowedItem& rItem = *static_cast<const SvxShadowedItem*>(pOld);
+ if ( rItem.GetValue() == StateToAttr( eState ) && m_xShadowBtn->get_saved_state() == eState )
+ bChanged = false;
+ }
+
+ if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
+ !StateToAttr( eState ) && static_cast<const SvxShadowedItem*>(pItem)->GetValue() )
+ bChanged = true;
+
+ if ( bChanged && eState != TRISTATE_INDET )
+ {
+ rSet->Put( SvxShadowedItem( StateToAttr( eState ), nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bChanged = true;
+
+ // Hidden
+ nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_HIDDEN );
+ eState = m_xHiddenBtn->get_state();
+ bChanged = true;
+
+ if ( pOld )
+ {
+ const SvxCharHiddenItem& rItem = *static_cast<const SvxCharHiddenItem*>(pOld);
+ if ( rItem.GetValue() == StateToAttr( eState ) && m_xHiddenBtn->get_saved_state() == eState )
+ bChanged = false;
+ }
+
+ if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
+ !StateToAttr( eState ) && static_cast<const SvxCharHiddenItem*>(pItem)->GetValue() )
+ bChanged = true;
+
+ if ( bChanged && eState != TRISTATE_INDET )
+ {
+ rSet->Put( SvxCharHiddenItem( StateToAttr( eState ), nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bModified |= FillItemSetColor_Impl( *rSet );
+
+ return bModified;
+}
+
+void SvxCharEffectsPage::DisableControls( sal_uInt16 nDisable )
+{
+ if ( ( DISABLE_CASEMAP & nDisable ) == DISABLE_CASEMAP )
+ {
+ m_xEffectsFT->set_sensitive(false);
+ m_xEffectsLB->set_sensitive(false);
+ }
+}
+
+void SvxCharEffectsPage::PageCreated(const SfxAllItemSet& aSet)
+{
+ const SfxUInt16Item* pDisableCtlItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false);
+ const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
+ if (pDisableCtlItem)
+ DisableControls(pDisableCtlItem->GetValue());
+
+ if (!pFlagItem)
+ return;
+
+ sal_uInt32 nFlags=pFlagItem->GetValue();
+ if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
+ // the writer uses SID_ATTR_BRUSH as font background
+ m_bPreviewBackgroundToCharacter = true;
+ if ((nFlags & SVX_ENABLE_CHAR_TRANSPARENCY) != SVX_ENABLE_CHAR_TRANSPARENCY)
+ {
+ // Only show these in case client code explicitly wants this.
+ m_xFontTransparencyFT->hide();
+ m_xFontTransparencyMtr->hide();
+ }
+}
+
+// class SvxCharPositionPage ---------------------------------------------
+
+SvxCharPositionPage::SvxCharPositionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
+ : SvxCharBasePage(pPage, pController, "cui/ui/positionpage.ui", "PositionPage", rInSet)
+ , m_nSuperEsc(short(DFLT_ESC_SUPER))
+ , m_nSubEsc(short(DFLT_ESC_SUB))
+ , m_nScaleWidthItemSetVal(100)
+ , m_nScaleWidthInitialVal(100)
+ , m_nSuperProp(sal_uInt8(DFLT_ESC_PROP))
+ , m_nSubProp(sal_uInt8(DFLT_ESC_PROP))
+ , m_xHighPosBtn(m_xBuilder->weld_radio_button("superscript"))
+ , m_xNormalPosBtn(m_xBuilder->weld_radio_button("normal"))
+ , m_xLowPosBtn(m_xBuilder->weld_radio_button("subscript"))
+ , m_xHighLowFT(m_xBuilder->weld_label("raiselower"))
+ , m_xHighLowMF(m_xBuilder->weld_metric_spin_button("raiselowersb", FieldUnit::PERCENT))
+ , m_xHighLowRB(m_xBuilder->weld_check_button("automatic"))
+ , m_xFontSizeFT(m_xBuilder->weld_label("relativefontsize"))
+ , m_xFontSizeMF(m_xBuilder->weld_metric_spin_button("fontsizesb", FieldUnit::PERCENT))
+ , m_xRotationContainer(m_xBuilder->weld_widget("rotationcontainer"))
+ , m_xScalingFT(m_xBuilder->weld_label("scale"))
+ , m_xScalingAndRotationFT(m_xBuilder->weld_label("rotateandscale"))
+ , m_x0degRB(m_xBuilder->weld_radio_button("0deg"))
+ , m_x90degRB(m_xBuilder->weld_radio_button("90deg"))
+ , m_x270degRB(m_xBuilder->weld_radio_button("270deg"))
+ , m_xFitToLineCB(m_xBuilder->weld_check_button("fittoline"))
+ , m_xScaleWidthMF(m_xBuilder->weld_metric_spin_button("scalewidthsb", FieldUnit::PERCENT))
+ , m_xKerningMF(m_xBuilder->weld_metric_spin_button("kerningsb", FieldUnit::POINT))
+ , m_xPairKerningBtn(m_xBuilder->weld_check_button("pairkerning"))
+{
+ m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
+#ifdef IOS
+ m_xPreviewWin->hide();
+#endif
+ Initialize();
+}
+
+SvxCharPositionPage::~SvxCharPositionPage()
+{
+}
+
+
+void SvxCharPositionPage::Initialize()
+{
+ // to handle the changes of the other pages
+ SetExchangeSupport();
+
+ GetPreviewFont().SetFontSize( Size( 0, 240 ) );
+ GetPreviewCJKFont().SetFontSize( Size( 0, 240 ) );
+ GetPreviewCTLFont().SetFontSize( Size( 0, 240 ) );
+
+ m_xNormalPosBtn->set_active(true);
+ PositionHdl_Impl(*m_xNormalPosBtn);
+
+ Link<weld::Toggleable&,void> aLink2 = LINK(this, SvxCharPositionPage, PositionHdl_Impl);
+ m_xHighPosBtn->connect_toggled(aLink2);
+ m_xNormalPosBtn->connect_toggled(aLink2);
+ m_xLowPosBtn->connect_toggled(aLink2);
+
+ aLink2 = LINK( this, SvxCharPositionPage, RotationHdl_Impl );
+ m_x0degRB->connect_toggled(aLink2);
+ m_x90degRB->connect_toggled(aLink2);
+ m_x270degRB->connect_toggled(aLink2);
+
+ Link<weld::MetricSpinButton&,void> aLink3 = LINK(this, SvxCharPositionPage, ValueChangedHdl_Impl);
+ m_xHighLowMF->connect_value_changed(aLink3);
+ m_xFontSizeMF->connect_value_changed(aLink3);
+
+ m_xHighLowRB->connect_toggled(LINK(this, SvxCharPositionPage, AutoPositionHdl_Impl));
+ m_xFitToLineCB->connect_toggled(LINK(this, SvxCharPositionPage, FitToLineHdl_Impl));
+ m_xKerningMF->connect_value_changed(LINK(this, SvxCharPositionPage, KerningModifyHdl_Impl));
+ m_xScaleWidthMF->connect_value_changed(LINK(this, SvxCharPositionPage, ScaleWidthModifyHdl_Impl));
+}
+
+void SvxCharPositionPage::UpdatePreview_Impl( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
+{
+ SetPrevFontEscapement( nProp, nEscProp, nEsc );
+}
+
+
+void SvxCharPositionPage::SetEscapement_Impl( SvxEscapement nEsc )
+{
+ SvxEscapementItem aEscItm( nEsc, SID_ATTR_CHAR_ESCAPEMENT );
+
+ if ( SvxEscapement::Superscript == nEsc )
+ {
+ aEscItm.GetEsc() = m_nSuperEsc;
+ aEscItm.GetProportionalHeight() = m_nSuperProp;
+ }
+ else if ( SvxEscapement::Subscript == nEsc )
+ {
+ aEscItm.GetEsc() = m_nSubEsc;
+ aEscItm.GetProportionalHeight() = m_nSubProp;
+ }
+
+ short nFac = aEscItm.GetEsc() < 0 ? -1 : 1;
+
+ m_xHighLowMF->set_value(aEscItm.GetEsc() * nFac, FieldUnit::PERCENT);
+ m_xFontSizeMF->set_value(aEscItm.GetProportionalHeight(), FieldUnit::PERCENT);
+
+ if ( SvxEscapement::Off == nEsc )
+ {
+ m_xHighLowFT->set_sensitive(false);
+ m_xHighLowMF->set_sensitive(false);
+ m_xFontSizeFT->set_sensitive(false);
+ m_xFontSizeMF->set_sensitive(false);
+ m_xHighLowRB->set_sensitive(false);
+ }
+ else
+ {
+ m_xFontSizeFT->set_sensitive(true);
+ m_xFontSizeMF->set_sensitive(true);
+ m_xHighLowRB->set_sensitive(true);
+
+ if (!m_xHighLowRB->get_active())
+ {
+ m_xHighLowFT->set_sensitive(true);
+ m_xHighLowMF->set_sensitive(true);
+ }
+ else
+ AutoPositionHdl_Impl(*m_xHighLowRB);
+ }
+
+ UpdatePreview_Impl( 100, aEscItm.GetProportionalHeight(), aEscItm.GetEsc() );
+}
+
+
+IMPL_LINK_NOARG(SvxCharPositionPage, PositionHdl_Impl, weld::Toggleable&, void)
+{
+ SvxEscapement nEsc = SvxEscapement::Off; // also when pBtn == NULL
+
+ if (m_xHighPosBtn->get_active())
+ nEsc = SvxEscapement::Superscript;
+ else if (m_xLowPosBtn->get_active())
+ nEsc = SvxEscapement::Subscript;
+
+ SetEscapement_Impl( nEsc );
+}
+
+IMPL_LINK_NOARG(SvxCharPositionPage, RotationHdl_Impl, weld::Toggleable&, void)
+{
+ bool bEnable = false;
+ if (m_x90degRB->get_active() || m_x270degRB->get_active())
+ bEnable = true;
+ else
+ OSL_ENSURE(m_x0degRB->get_active(), "unexpected button");
+ m_xFitToLineCB->set_sensitive(bEnable);
+}
+
+void SvxCharPositionPage::FontModifyHdl_Impl()
+{
+ sal_uInt8 nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
+ short nEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT));
+ nEsc *= m_xLowPosBtn->get_active() ? -1 : 1;
+ UpdatePreview_Impl( 100, nEscProp, nEsc );
+}
+
+IMPL_LINK(SvxCharPositionPage, AutoPositionHdl_Impl, weld::Toggleable&, rBox, void)
+{
+ if (rBox.get_active())
+ {
+ m_xHighLowFT->set_sensitive(false);
+ m_xHighLowMF->set_sensitive(false);
+ }
+ else
+ PositionHdl_Impl(m_xHighPosBtn->get_active() ? *m_xHighPosBtn
+ : m_xLowPosBtn->get_active() ? *m_xLowPosBtn
+ : *m_xNormalPosBtn);
+}
+
+IMPL_LINK_NOARG(SvxCharPositionPage, FitToLineHdl_Impl, weld::Toggleable&, void)
+{
+ sal_uInt16 nVal = m_nScaleWidthInitialVal;
+ if (m_xFitToLineCB->get_active())
+ nVal = m_nScaleWidthItemSetVal;
+ m_xScaleWidthMF->set_value(nVal, FieldUnit::PERCENT);
+ m_aPreviewWin.SetFontWidthScale( nVal );
+}
+
+IMPL_LINK_NOARG(SvxCharPositionPage, KerningModifyHdl_Impl, weld::MetricSpinButton&, void)
+{
+ tools::Long nVal = static_cast<tools::Long>(m_xKerningMF->get_value(FieldUnit::POINT));
+ nVal = o3tl::convert(nVal, o3tl::Length::pt, o3tl::Length::twip);
+
+ tools::Long nKern = static_cast<short>(m_xKerningMF->denormalize(nVal));
+
+ SvxFont& rFont = GetPreviewFont();
+ SvxFont& rCJKFont = GetPreviewCJKFont();
+ SvxFont& rCTLFont = GetPreviewCTLFont();
+
+ rFont.SetFixKerning( static_cast<short>(nKern) );
+ rCJKFont.SetFixKerning( static_cast<short>(nKern) );
+ rCTLFont.SetFixKerning( static_cast<short>(nKern) );
+ m_aPreviewWin.Invalidate();
+}
+
+IMPL_LINK(SvxCharPositionPage, ValueChangedHdl_Impl, weld::MetricSpinButton&, rField, void)
+{
+ bool bHigh = m_xHighPosBtn->get_active();
+ bool bLow = m_xLowPosBtn->get_active();
+ DBG_ASSERT( bHigh || bLow, "normal position is not valid" );
+
+ if (m_xHighLowMF.get() == &rField)
+ {
+ if ( bLow )
+ m_nSubEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT)) * -1;
+ else
+ m_nSuperEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT));
+ }
+ else if (m_xFontSizeMF.get() == &rField)
+ {
+ if ( bLow )
+ m_nSubProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
+ else
+ m_nSuperProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
+ }
+
+ FontModifyHdl_Impl();
+}
+
+IMPL_LINK_NOARG(SvxCharPositionPage, ScaleWidthModifyHdl_Impl, weld::MetricSpinButton&, void)
+{
+ m_aPreviewWin.SetFontWidthScale(sal_uInt16(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)));
+}
+
+DeactivateRC SvxCharPositionPage::DeactivatePage( SfxItemSet* _pSet )
+{
+ if ( _pSet )
+ FillItemSet( _pSet );
+ return DeactivateRC::LeavePage;
+}
+
+std::unique_ptr<SfxTabPage> SvxCharPositionPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
+{
+ return std::make_unique<SvxCharPositionPage>(pPage, pController, *rSet);
+}
+
+void SvxCharPositionPage::Reset( const SfxItemSet* rSet )
+{
+ OUString sUser = GetUserData();
+
+ if ( !sUser.isEmpty() )
+ {
+ sal_Int32 nIdx {0};
+ m_nSuperEsc = static_cast<short>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
+ m_nSubEsc = static_cast<short>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
+ m_nSuperProp = static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
+ m_nSubProp = static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
+
+ m_xHighLowMF->set_max(MAX_ESC_POS, FieldUnit::PERCENT);
+
+ //fdo#75307 validate all the entries and discard all of them if any are
+ //out of range
+ bool bValid = true;
+ if (m_nSuperEsc < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSuperEsc > m_xHighLowMF->get_max(FieldUnit::PERCENT))
+ bValid = false;
+ if (m_nSubEsc*-1 < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSubEsc*-1 > m_xHighLowMF->get_max(FieldUnit::PERCENT))
+ bValid = false;
+ if (m_nSuperProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSuperProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT))
+ bValid = false;
+ if (m_nSubProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSubProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT))
+ bValid = false;
+
+ if (!bValid)
+ {
+ m_nSuperEsc = DFLT_ESC_SUPER;
+ m_nSubEsc = DFLT_ESC_SUB;
+ m_nSuperProp = DFLT_ESC_PROP;
+ m_nSubProp = DFLT_ESC_PROP;
+ }
+ }
+
+ short nEsc = 0;
+ sal_uInt8 nEscProp = 100;
+
+ m_xHighLowFT->set_sensitive(false);
+ m_xHighLowMF->set_sensitive(false);
+ m_xFontSizeFT->set_sensitive(false);
+ m_xFontSizeMF->set_sensitive(false);
+
+ SvxFont& rFont = GetPreviewFont();
+ SvxFont& rCJKFont = GetPreviewCJKFont();
+ SvxFont& rCTLFont = GetPreviewCTLFont();
+ sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT );
+
+ if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
+ {
+ const SvxEscapementItem& rItem = static_cast<const SvxEscapementItem&>(rSet->Get( nWhich ));
+ nEsc = rItem.GetEsc();
+ nEscProp = rItem.GetProportionalHeight();
+
+ if ( nEsc != 0 )
+ {
+ m_xHighLowFT->set_sensitive(true);
+ m_xHighLowMF->set_sensitive(true);
+ m_xFontSizeFT->set_sensitive(true);
+ m_xFontSizeMF->set_sensitive(true);
+
+ short nFac;
+ bool bAutomatic(false);
+
+ if ( nEsc > 0 )
+ {
+ nFac = 1;
+ m_xHighPosBtn->set_active(true);
+ if ( nEsc == DFLT_ESC_AUTO_SUPER )
+ {
+ nEsc = .8 * (100 - nEscProp); //approximation of actual percentage used
+ bAutomatic = true;
+ }
+ }
+ else
+ {
+ nFac = -1;
+ m_xLowPosBtn->set_active(true);
+ if ( nEsc == DFLT_ESC_AUTO_SUB )
+ {
+ nEsc = .2 * -(100 - nEscProp); //approximation of actual percentage used
+ bAutomatic = true;
+ }
+ }
+ if (!m_xHighLowRB->get_sensitive())
+ {
+ m_xHighLowRB->set_sensitive(true);
+ }
+ m_xHighLowRB->set_active(bAutomatic);
+
+ if (m_xHighLowRB->get_active())
+ {
+ m_xHighLowFT->set_sensitive(false);
+ m_xHighLowMF->set_sensitive(false);
+ }
+ m_xHighLowMF->set_value(m_xHighLowMF->normalize(nFac * nEsc), FieldUnit::PERCENT);
+ }
+ else
+ {
+ m_xNormalPosBtn->set_active(true);
+ m_xHighLowRB->set_active(true);
+ PositionHdl_Impl(*m_xNormalPosBtn);
+ }
+ //the height has to be set after the handler is called to keep the value also if the escapement is zero
+ m_xFontSizeMF->set_value(m_xFontSizeMF->normalize(nEscProp), FieldUnit::PERCENT);
+ }
+ else
+ {
+ m_xHighPosBtn->set_active(false);
+ m_xNormalPosBtn->set_active(false);
+ m_xLowPosBtn->set_active(false);
+ }
+
+ // set BspFont
+ SetPrevFontEscapement( 100, nEscProp, nEsc );
+
+ // Kerning
+ nWhich = GetWhich( SID_ATTR_CHAR_KERNING );
+
+ if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
+ {
+ const SvxKerningItem& rItem = static_cast<const SvxKerningItem&>(rSet->Get( nWhich ));
+ MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich );
+ tools::Long nBig = static_cast<tools::Long>(m_xKerningMF->normalize( static_cast<tools::Long>(rItem.GetValue()) ));
+ tools::Long nKerning = OutputDevice::LogicToLogic(nBig, eUnit, MapUnit::MapPoint);
+
+ // set Kerning at the Font, convert into Twips before
+ tools::Long nKern = OutputDevice::LogicToLogic(rItem.GetValue(), eUnit, MapUnit::MapTwip);
+ rFont.SetFixKerning( static_cast<short>(nKern) );
+ rCJKFont.SetFixKerning( static_cast<short>(nKern) );
+ rCTLFont.SetFixKerning( static_cast<short>(nKern) );
+
+ //the attribute value must be displayed also if it's above/below the maximum allowed value
+ tools::Long nVal = static_cast<tools::Long>(m_xKerningMF->get_max(FieldUnit::POINT));
+ if(nVal < nKerning)
+ m_xKerningMF->set_max(nKerning, FieldUnit::POINT);
+ nVal = static_cast<tools::Long>(m_xKerningMF->get_min(FieldUnit::POINT));
+ if (nVal > nKerning)
+ m_xKerningMF->set_min(nKerning, FieldUnit::POINT);
+ m_xKerningMF->set_value(nKerning, FieldUnit::POINT);
+ }
+ else
+ m_xKerningMF->set_text(OUString());
+
+ // Pair kerning
+ nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN );
+
+ if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
+ {
+ const SvxAutoKernItem& rItem = static_cast<const SvxAutoKernItem&>(rSet->Get( nWhich ));
+ m_xPairKerningBtn->set_active(rItem.GetValue());
+ }
+ else
+ m_xPairKerningBtn->set_active(false);
+
+ // Scale Width
+ nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
+ if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
+ {
+ const SvxCharScaleWidthItem& rItem = static_cast<const SvxCharScaleWidthItem&>( rSet->Get( nWhich ) );
+ m_nScaleWidthInitialVal = rItem.GetValue();
+ m_xScaleWidthMF->set_value(m_nScaleWidthInitialVal, FieldUnit::PERCENT);
+ }
+ else
+ m_xScaleWidthMF->set_value(100, FieldUnit::PERCENT);
+
+ if ( rSet->GetItemState( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ) >= SfxItemState::DEFAULT )
+ m_nScaleWidthItemSetVal = static_cast<const SfxUInt16Item&>( rSet->Get( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE )).GetValue();
+
+ // Rotation
+ nWhich = GetWhich( SID_ATTR_CHAR_ROTATED );
+ SfxItemState eState = rSet->GetItemState( nWhich );
+ if( SfxItemState::UNKNOWN == eState )
+ {
+ m_xRotationContainer->hide();
+ m_xScalingAndRotationFT->hide();
+ m_xScalingFT->show();
+ }
+ else
+ {
+ m_xRotationContainer->show();
+ m_xScalingAndRotationFT->show();
+ m_xScalingFT->hide();
+
+ if( eState >= SfxItemState::DEFAULT )
+ {
+ const SvxCharRotateItem& rItem =
+ static_cast<const SvxCharRotateItem&>( rSet->Get( nWhich ));
+ if (rItem.IsBottomToTop())
+ m_x90degRB->set_active(true);
+ else if (rItem.IsTopToBottom())
+ m_x270degRB->set_active(true);
+ else
+ {
+ DBG_ASSERT( 0_deg10 == rItem.GetValue(), "incorrect value" );
+ m_x0degRB->set_active(true);
+ }
+ m_xFitToLineCB->set_active(rItem.IsFitToLine());
+ }
+ else
+ {
+ if( eState == SfxItemState::DONTCARE )
+ {
+ m_x0degRB->set_active(false);
+ m_x90degRB->set_active(false);
+ m_x270degRB->set_active(false);
+ }
+ else
+ m_x0degRB->set_active(true);
+
+ m_xFitToLineCB->set_active(false);
+ }
+ m_xFitToLineCB->set_sensitive(!m_x0degRB->get_active());
+
+ // is this value set?
+ if( SfxItemState::UNKNOWN == rSet->GetItemState(
+ SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ))
+ m_xFitToLineCB->hide();
+ }
+ ChangesApplied();
+}
+
+void SvxCharPositionPage::ChangesApplied()
+{
+ m_xHighPosBtn->save_state();
+ m_xNormalPosBtn->save_state();
+ m_xLowPosBtn->save_state();
+ m_xHighLowRB->save_state();
+ m_x0degRB->save_state();
+ m_x90degRB->save_state();
+ m_x270degRB->save_state();
+ m_xFitToLineCB->save_state();
+ m_xScaleWidthMF->save_value();
+ m_xKerningMF->save_value();
+ m_xPairKerningBtn->save_state();
+}
+
+bool SvxCharPositionPage::FillItemSet( SfxItemSet* rSet )
+{
+ // Position (high, normal or low)
+ const SfxItemSet& rOldSet = GetItemSet();
+ bool bModified = false, bChanged = true;
+ sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT );
+ const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_ESCAPEMENT );
+ const bool bHigh = m_xHighPosBtn->get_active();
+ short nEsc;
+ sal_uInt8 nEscProp;
+
+ if (bHigh || m_xLowPosBtn->get_active())
+ {
+ if (m_xHighLowRB->get_active())
+ nEsc = bHigh ? DFLT_ESC_AUTO_SUPER : DFLT_ESC_AUTO_SUB;
+ else
+ {
+ nEsc = static_cast<short>(m_xHighLowMF->denormalize(m_xHighLowMF->get_value(FieldUnit::PERCENT)));
+ nEsc *= (bHigh ? 1 : -1);
+ }
+ nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->denormalize(m_xFontSizeMF->get_value(FieldUnit::PERCENT)));
+ }
+ else
+ {
+ nEsc = 0;
+ nEscProp = 100;
+ }
+
+ if ( pOld )
+ {
+ const SvxEscapementItem& rItem = *static_cast<const SvxEscapementItem*>(pOld);
+ if (rItem.GetEsc() == nEsc && rItem.GetProportionalHeight() == nEscProp)
+ bChanged = false;
+ }
+
+ if ( !bChanged && !m_xHighPosBtn->get_saved_state() &&
+ !m_xNormalPosBtn->get_saved_state() && !m_xLowPosBtn->get_saved_state() )
+ bChanged = true;
+
+ if ( bChanged &&
+ ( m_xHighPosBtn->get_active() || m_xNormalPosBtn->get_active() || m_xLowPosBtn->get_active() ) )
+ {
+ rSet->Put( SvxEscapementItem( nEsc, nEscProp, nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ bChanged = true;
+
+ // Kerning
+ nWhich = GetWhich( SID_ATTR_CHAR_KERNING );
+ pOld = GetOldItem( *rSet, SID_ATTR_CHAR_KERNING );
+ short nKerning = 0;
+ MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich );
+
+ tools::Long nTmp = static_cast<tools::Long>(m_xKerningMF->get_value(FieldUnit::POINT));
+ tools::Long nVal = OutputDevice::LogicToLogic(nTmp, MapUnit::MapPoint, eUnit);
+ nKerning = static_cast<short>(m_xKerningMF->denormalize( nVal ));
+
+ SfxItemState eOldKernState = rOldSet.GetItemState( nWhich, false );
+ if ( pOld )
+ {
+ const SvxKerningItem& rItem = *static_cast<const SvxKerningItem*>(pOld);
+ if ( (eOldKernState >= SfxItemState::DEFAULT || m_xKerningMF->get_text().isEmpty()) && rItem.GetValue() == nKerning )
+ bChanged = false;
+ }
+
+ if ( bChanged )
+ {
+ rSet->Put( SvxKerningItem( nKerning, nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == eOldKernState )
+ rSet->InvalidateItem(nWhich);
+
+ // Pair-Kerning
+ nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN );
+
+ if (m_xPairKerningBtn->get_state_changed_from_saved())
+ {
+ rSet->Put( SvxAutoKernItem( m_xPairKerningBtn->get_active(), nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ // Scale Width
+ nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
+ if (m_xScaleWidthMF->get_value_changed_from_saved())
+ {
+ rSet->Put(SvxCharScaleWidthItem(static_cast<sal_uInt16>(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)), nWhich));
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ // Rotation
+ nWhich = GetWhich( SID_ATTR_CHAR_ROTATED );
+ if ( m_x0degRB->get_state_changed_from_saved() ||
+ m_x90degRB->get_state_changed_from_saved() ||
+ m_x270degRB->get_state_changed_from_saved() ||
+ m_xFitToLineCB->get_state_changed_from_saved() )
+ {
+ SvxCharRotateItem aItem( 0_deg10, m_xFitToLineCB->get_active(), nWhich );
+ if (m_x90degRB->get_active())
+ aItem.SetBottomToTop();
+ else if (m_x270degRB->get_active())
+ aItem.SetTopToBottom();
+ rSet->Put( aItem );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ return bModified;
+}
+
+
+void SvxCharPositionPage::FillUserData()
+{
+ static const OUStringLiteral cTok( u";" );
+
+ OUString sUser = OUString::number( m_nSuperEsc ) + cTok +
+ OUString::number( m_nSubEsc ) + cTok +
+ OUString::number( m_nSuperProp ) + cTok +
+ OUString::number( m_nSubProp );
+ SetUserData( sUser );
+}
+
+
+void SvxCharPositionPage::PageCreated(const SfxAllItemSet& aSet)
+{
+ const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
+ if (pFlagItem)
+ {
+ sal_uInt32 nFlags=pFlagItem->GetValue();
+ if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
+ // the writer uses SID_ATTR_BRUSH as font background
+ m_bPreviewBackgroundToCharacter = true;
+ }
+}
+// class SvxCharTwoLinesPage ------------------------------------------------
+
+SvxCharTwoLinesPage::SvxCharTwoLinesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
+ : SvxCharBasePage(pPage, pController, "cui/ui/twolinespage.ui", "TwoLinesPage", rInSet)
+ , m_nStartBracketPosition( 0 )
+ , m_nEndBracketPosition( 0 )
+ , m_xTwoLinesBtn(m_xBuilder->weld_check_button("twolines"))
+ , m_xEnclosingFrame(m_xBuilder->weld_widget("enclosing"))
+ , m_xStartBracketLB(m_xBuilder->weld_tree_view("startbracket"))
+ , m_xEndBracketLB(m_xBuilder->weld_tree_view("endbracket"))
+{
+ for (size_t i = 0; i < std::size(TWOLINE_OPEN); ++i)
+ m_xStartBracketLB->append(OUString::number(TWOLINE_OPEN[i].second), CuiResId(TWOLINE_OPEN[i].first));
+ for (size_t i = 0; i < std::size(TWOLINE_CLOSE); ++i)
+ m_xEndBracketLB->append(OUString::number(TWOLINE_CLOSE[i].second), CuiResId(TWOLINE_CLOSE[i].first));
+
+ m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin));
+#ifdef IOS
+ m_xPreviewWin->hide();
+#endif
+ Initialize();
+}
+
+SvxCharTwoLinesPage::~SvxCharTwoLinesPage()
+{
+}
+
+void SvxCharTwoLinesPage::Initialize()
+{
+ m_xTwoLinesBtn->set_active(false);
+ TwoLinesHdl_Impl(*m_xTwoLinesBtn);
+
+ m_xTwoLinesBtn->connect_toggled(LINK(this, SvxCharTwoLinesPage, TwoLinesHdl_Impl));
+
+ Link<weld::TreeView&,void> aLink = LINK(this, SvxCharTwoLinesPage, CharacterMapHdl_Impl);
+ m_xStartBracketLB->connect_changed(aLink);
+ m_xEndBracketLB->connect_changed(aLink);
+
+ SvxFont& rFont = GetPreviewFont();
+ SvxFont& rCJKFont = GetPreviewCJKFont();
+ SvxFont& rCTLFont = GetPreviewCTLFont();
+ rFont.SetFontSize( Size( 0, 220 ) );
+ rCJKFont.SetFontSize( Size( 0, 220 ) );
+ rCTLFont.SetFontSize( Size( 0, 220 ) );
+}
+
+void SvxCharTwoLinesPage::SelectCharacter(weld::TreeView* pBox)
+{
+ bool bStart = pBox == m_xStartBracketLB.get();
+ SvxCharacterMap aDlg(GetFrameWeld(), nullptr, nullptr);
+ aDlg.DisableFontSelection();
+
+ if (aDlg.run() == RET_OK)
+ {
+ sal_Unicode cChar = static_cast<sal_Unicode>(aDlg.GetChar());
+ SetBracket( cChar, bStart );
+ }
+ else
+ {
+ pBox->select(bStart ? m_nStartBracketPosition : m_nEndBracketPosition);
+ }
+}
+
+
+void SvxCharTwoLinesPage::SetBracket( sal_Unicode cBracket, bool bStart )
+{
+ int nEntryPos = 0;
+ weld::TreeView* pBox = bStart ? m_xStartBracketLB.get() : m_xEndBracketLB.get();
+ if (cBracket == 0)
+ pBox->select(0);
+ else
+ {
+ bool bFound = false;
+ for (int i = 1; i < pBox->n_children(); ++i)
+ {
+ if (pBox->get_id(i).toInt32() != CHRDLG_ENCLOSE_SPECIAL_CHAR)
+ {
+ const sal_Unicode cChar = pBox->get_text(i)[0];
+ if (cChar == cBracket)
+ {
+ pBox->select(i);
+ nEntryPos = i;
+ bFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!bFound)
+ {
+ pBox->append_text(OUString(cBracket));
+ nEntryPos = pBox->n_children() - 1;
+ pBox->select(nEntryPos);
+ }
+ }
+ if (bStart)
+ m_nStartBracketPosition = nEntryPos;
+ else
+ m_nEndBracketPosition = nEntryPos;
+}
+
+IMPL_LINK_NOARG(SvxCharTwoLinesPage, TwoLinesHdl_Impl, weld::Toggleable&, void)
+{
+ bool bChecked = m_xTwoLinesBtn->get_active();
+ m_xEnclosingFrame->set_sensitive(bChecked);
+ UpdatePreview_Impl();
+}
+
+IMPL_LINK(SvxCharTwoLinesPage, CharacterMapHdl_Impl, weld::TreeView&, rBox, void)
+{
+ int nPos = rBox.get_selected_index();
+ if (rBox.get_id(nPos).toInt32() == CHRDLG_ENCLOSE_SPECIAL_CHAR)
+ SelectCharacter( &rBox );
+ else
+ {
+ bool bStart = &rBox == m_xStartBracketLB.get();
+ if (bStart)
+ m_nStartBracketPosition = nPos;
+ else
+ m_nEndBracketPosition = nPos;
+ }
+ UpdatePreview_Impl();
+}
+
+void SvxCharTwoLinesPage::ActivatePage( const SfxItemSet& rSet )
+{
+ SvxCharBasePage::ActivatePage(rSet);
+}
+
+DeactivateRC SvxCharTwoLinesPage::DeactivatePage( SfxItemSet* _pSet )
+{
+ if ( _pSet )
+ FillItemSet( _pSet );
+ return DeactivateRC::LeavePage;
+}
+
+std::unique_ptr<SfxTabPage> SvxCharTwoLinesPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
+{
+ return std::make_unique<SvxCharTwoLinesPage>(pPage, pController, *rSet);
+}
+
+void SvxCharTwoLinesPage::Reset( const SfxItemSet* rSet )
+{
+ m_xTwoLinesBtn->set_active(false);
+ sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES );
+ SfxItemState eState = rSet->GetItemState( nWhich );
+
+ if ( eState >= SfxItemState::DONTCARE )
+ {
+ const SvxTwoLinesItem& rItem = static_cast<const SvxTwoLinesItem&>(rSet->Get( nWhich ));
+ m_xTwoLinesBtn->set_active(rItem.GetValue());
+
+ if ( rItem.GetValue() )
+ {
+ SetBracket( rItem.GetStartBracket(), true );
+ SetBracket( rItem.GetEndBracket(), false );
+ }
+ }
+ TwoLinesHdl_Impl(*m_xTwoLinesBtn);
+
+ SetPrevFontWidthScale( *rSet );
+}
+
+bool SvxCharTwoLinesPage::FillItemSet( SfxItemSet* rSet )
+{
+ const SfxItemSet& rOldSet = GetItemSet();
+ bool bModified = false, bChanged = true;
+ sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES );
+ const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_TWO_LINES );
+ bool bOn = m_xTwoLinesBtn->get_active();
+ sal_Unicode cStart = ( bOn && m_xStartBracketLB->get_selected_index() > 0 )
+ ? m_xStartBracketLB->get_selected_text()[0] : 0;
+ sal_Unicode cEnd = ( bOn && m_xEndBracketLB->get_selected_index() > 0 )
+ ? m_xEndBracketLB->get_selected_text()[0] : 0;
+
+ if ( pOld )
+ {
+ const SvxTwoLinesItem& rItem = *static_cast<const SvxTwoLinesItem*>(pOld);
+ if ( rItem.GetValue() == bOn &&
+ ( !bOn || ( rItem.GetStartBracket() == cStart && rItem.GetEndBracket() == cEnd ) ) )
+ bChanged = false;
+ }
+
+ if ( bChanged )
+ {
+ rSet->Put( SvxTwoLinesItem( bOn, cStart, cEnd, nWhich ) );
+ bModified = true;
+ }
+ else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
+ rSet->InvalidateItem(nWhich);
+
+ return bModified;
+}
+
+void SvxCharTwoLinesPage::UpdatePreview_Impl()
+{
+ sal_Unicode cStart = m_xStartBracketLB->get_selected_index() > 0
+ ? m_xStartBracketLB->get_selected_text()[0] : 0;
+ sal_Unicode cEnd = m_xEndBracketLB->get_selected_index() > 0
+ ? m_xEndBracketLB->get_selected_text()[0] : 0;
+ m_aPreviewWin.SetBrackets(cStart, cEnd);
+ m_aPreviewWin.SetTwoLines(m_xTwoLinesBtn->get_active());
+ m_aPreviewWin.Invalidate();
+}
+
+void SvxCharTwoLinesPage::PageCreated(const SfxAllItemSet& aSet)
+{
+ const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
+ if (pFlagItem)
+ {
+ sal_uInt32 nFlags=pFlagItem->GetValue();
+ if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
+ // the writer uses SID_ATTR_BRUSH as font background
+ m_bPreviewBackgroundToCharacter = true;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */