1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <vcl/svapp.hxx>
21 #include <vcl/idle.hxx>
22 #include <svtools/ctrltool.hxx>
23 #include <sfx2/objsh.hxx>
24 #include <svx/svxids.hrc>
25 #include <svtools/unitconv.hxx>
26 #include <svl/cjkoptions.hxx>
27 #include <svl/ctloptions.hxx>
28 #include <chardlg.hxx>
29 #include <editeng/fontitem.hxx>
30 #include <editeng/postitem.hxx>
31 #include <editeng/udlnitem.hxx>
32 #include <editeng/crossedoutitem.hxx>
33 #include <editeng/contouritem.hxx>
34 #include <editeng/langitem.hxx>
35 #include <editeng/wghtitem.hxx>
36 #include <editeng/fhgtitem.hxx>
37 #include <editeng/shdditem.hxx>
38 #include <editeng/escapementitem.hxx>
39 #include <editeng/wrlmitem.hxx>
40 #include <editeng/cmapitem.hxx>
41 #include <editeng/kernitem.hxx>
42 #include <editeng/flstitem.hxx>
43 #include <editeng/autokernitem.hxx>
44 #include <editeng/nhypitem.hxx>
45 #include <editeng/colritem.hxx>
46 #include <dialmgr.hxx>
47 #include <sfx2/htmlmode.hxx>
48 #include <svx/cuicharmap.hxx>
49 #include "chardlg.h"
50 #include <editeng/emphasismarkitem.hxx>
51 #include <editeng/charreliefitem.hxx>
52 #include <editeng/twolinesitem.hxx>
53 #include <editeng/charhiddenitem.hxx>
54 #include <editeng/charscaleitem.hxx>
55 #include <editeng/charrotateitem.hxx>
56 #include <officecfg/Office/Common.hxx>
57 #include <strings.hrc>
58 #include <twolines.hrc>
59 #include <svl/intitem.hxx>
60 #include <svx/flagsdef.hxx>
61 #include <FontFeatures.hxx>
62 #include <FontFeaturesDialog.hxx>
63 #include <sal/log.hxx>
64 #include <osl/diagnose.h>
65 #include <o3tl/unit_conversion.hxx>
66 #include <o3tl/string_view.hxx>
67
68 using namespace ::com::sun::star;
69
70 // static ----------------------------------------------------------------
71
72 const WhichRangesContainer SvxCharNamePage::pNameRanges(svl::Items<
73 SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_WEIGHT,
74 SID_ATTR_CHAR_FONTHEIGHT, SID_ATTR_CHAR_FONTHEIGHT,
75 SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR,
76 SID_ATTR_CHAR_LANGUAGE, SID_ATTR_CHAR_LANGUAGE,
77 SID_ATTR_CHAR_CJK_FONT, SID_ATTR_CHAR_CJK_WEIGHT,
78 SID_ATTR_CHAR_CTL_FONT, SID_ATTR_CHAR_CTL_WEIGHT
79 >);
80
81 const WhichRangesContainer SvxCharEffectsPage::pEffectsRanges(svl::Items<
82 SID_ATTR_CHAR_SHADOWED, SID_ATTR_CHAR_UNDERLINE,
83 SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR,
84 SID_ATTR_CHAR_CASEMAP, SID_ATTR_CHAR_CASEMAP,
85 SID_ATTR_FLASH, SID_ATTR_FLASH,
86 SID_ATTR_CHAR_EMPHASISMARK, SID_ATTR_CHAR_EMPHASISMARK,
87 SID_ATTR_CHAR_RELIEF, SID_ATTR_CHAR_RELIEF,
88 SID_ATTR_CHAR_HIDDEN, SID_ATTR_CHAR_HIDDEN,
89 SID_ATTR_CHAR_OVERLINE, SID_ATTR_CHAR_OVERLINE
90 >);
91
92 const WhichRangesContainer SvxCharPositionPage::pPositionRanges(svl::Items<
93 SID_ATTR_CHAR_KERNING, SID_ATTR_CHAR_KERNING,
94 SID_ATTR_CHAR_ESCAPEMENT, SID_ATTR_CHAR_ESCAPEMENT,
95 SID_ATTR_CHAR_AUTOKERN, SID_ATTR_CHAR_AUTOKERN,
96 SID_ATTR_CHAR_ROTATED, SID_ATTR_CHAR_SCALEWIDTH,
97 SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, SID_ATTR_CHAR_WIDTH_FIT_TO_LINE
98 >);
99
100 const WhichRangesContainer SvxCharTwoLinesPage::pTwoLinesRanges(svl::Items<
101 SID_ATTR_CHAR_TWO_LINES, SID_ATTR_CHAR_TWO_LINES
102 >);
103
104 // C-Function ------------------------------------------------------------
105
StateToAttr(TriState aState)106 static bool StateToAttr( TriState aState )
107 {
108 return ( TRISTATE_TRUE == aState );
109 }
110
111 namespace
112 {
setPrevFontEscapement(SvxFont & _rFont,sal_uInt8 nProp,sal_uInt8 nEscProp,short nEsc)113 void setPrevFontEscapement(SvxFont& _rFont,sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
114 {
115 _rFont.SetPropr( nProp );
116 _rFont.SetProprRel( nEscProp );
117 _rFont.SetEscapement( nEsc );
118 }
119 }
120
GetPreviewFont()121 inline SvxFont& SvxCharBasePage::GetPreviewFont()
122 {
123 return m_aPreviewWin.GetFont();
124 }
125
GetPreviewCJKFont()126 inline SvxFont& SvxCharBasePage::GetPreviewCJKFont()
127 {
128 return m_aPreviewWin.GetCJKFont();
129 }
130
GetPreviewCTLFont()131 inline SvxFont& SvxCharBasePage::GetPreviewCTLFont()
132 {
133 return m_aPreviewWin.GetCTLFont();
134 }
135
SvxCharBasePage(weld::Container * pPage,weld::DialogController * pController,const OUString & rUIXMLDescription,const OUString & rID,const SfxItemSet & rItemset)136 SvxCharBasePage::SvxCharBasePage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OUString& rID, const SfxItemSet& rItemset)
137 : SfxTabPage(pPage, pController, rUIXMLDescription, rID, &rItemset)
138 , m_bPreviewBackgroundToCharacter( false )
139 {
140 }
141
~SvxCharBasePage()142 SvxCharBasePage::~SvxCharBasePage()
143 {
144 }
145
ActivatePage(const SfxItemSet & rSet)146 void SvxCharBasePage::ActivatePage(const SfxItemSet& rSet)
147 {
148 m_aPreviewWin.SetFromItemSet(rSet, m_bPreviewBackgroundToCharacter);
149 }
150
SetPrevFontWidthScale(const SfxItemSet & rSet)151 void SvxCharBasePage::SetPrevFontWidthScale( const SfxItemSet& rSet )
152 {
153 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
154 if (rSet.GetItemState(nWhich)>=SfxItemState::DEFAULT)
155 {
156 const SvxCharScaleWidthItem &rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
157 m_aPreviewWin.SetFontWidthScale(rItem.GetValue());
158 }
159 }
160
SetPrevFontEscapement(sal_uInt8 nProp,sal_uInt8 nEscProp,short nEsc)161 void SvxCharBasePage::SetPrevFontEscapement( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
162 {
163 setPrevFontEscapement(GetPreviewFont(),nProp,nEscProp,nEsc);
164 setPrevFontEscapement(GetPreviewCJKFont(),nProp,nEscProp,nEsc);
165 setPrevFontEscapement(GetPreviewCTLFont(),nProp,nEscProp,nEsc);
166 m_aPreviewWin.Invalidate();
167 }
168
169
170 // SvxCharNamePage_Impl --------------------------------------------------
171
172 struct SvxCharNamePage_Impl
173 {
174 Idle m_aUpdateIdle { "cui SvxCharNamePage_Impl m_aUpdateIdle" };
175 OUString m_aNoStyleText;
176 std::unique_ptr<FontList> m_pFontList;
177 int m_nExtraEntryPos;
178 bool m_bInSearchMode;
179
SvxCharNamePage_ImplSvxCharNamePage_Impl180 SvxCharNamePage_Impl()
181 : m_nExtraEntryPos(std::numeric_limits<int>::max())
182 , m_bInSearchMode(false)
183
184 {
185 m_aUpdateIdle.SetPriority( TaskPriority::LOWEST );
186 }
187 };
188
189 // class SvxCharNamePage -------------------------------------------------
190
SvxCharNamePage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rInSet)191 SvxCharNamePage::SvxCharNamePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
192 : SvxCharBasePage(pPage, pController, u"cui/ui/charnamepage.ui"_ustr, u"CharNamePage"_ustr, rInSet)
193 , m_pImpl(new SvxCharNamePage_Impl)
194 // Western
195 , m_xWestern(m_xBuilder->weld_notebook(u"nbWestern"_ustr))
196 , m_xWestFontNameFT(m_xBuilder->weld_label(u"lbWestFontname"_ustr))
197 , m_xWestFontStyleFT(m_xBuilder->weld_label(u"lbWestStyle"_ustr))
198 , m_xWestFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box(u"cbWestStyle"_ustr)))
199 , m_xWestFontSizeFT(m_xBuilder->weld_label(u"lbWestSize"_ustr))
200 , m_xWestFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box(u"cbWestSize"_ustr)))
201 , m_xWestFontLanguageFT(m_xBuilder->weld_label(u"lbWestLanguage"_ustr))
202 , m_xWestFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"cbWestLanguage"_ustr)))
203 , m_xWestFontFeaturesButton(m_xBuilder->weld_button(u"btnWestFeatures"_ustr))
204 , m_xWestFontTypeFT(m_xBuilder->weld_label(u"lbWestFontinfo"_ustr))
205 , m_xCJK_CTL(m_xBuilder->weld_notebook(u"nbCJKCTL"_ustr))
206 // CJK
207 , m_xEastFontNameFT(m_xBuilder->weld_label(u"lbCJKFontname"_ustr))
208 , m_xEastFontStyleFT(m_xBuilder->weld_label(u"lbCJKStyle"_ustr))
209 , m_xEastFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box(u"cbCJKStyle"_ustr)))
210 , m_xEastFontSizeFT(m_xBuilder->weld_label(u"lbCJKSize"_ustr))
211 , m_xEastFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box(u"cbCJKSize"_ustr)))
212 , m_xEastFontLanguageFT(m_xBuilder->weld_label(u"lbCJKLanguage"_ustr))
213 , m_xEastFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"cbCJKLanguage"_ustr)))
214 , m_xEastFontFeaturesButton(m_xBuilder->weld_button(u"btnCJKFeatures"_ustr))
215 , m_xEastFontTypeFT(m_xBuilder->weld_label(u"lbCJKFontinfo"_ustr))
216 // CTL
217 , m_xCTLFontNameFT(m_xBuilder->weld_label(u"lbCTLFontname"_ustr))
218 // tree
219 , m_xCTLFontStyleFT(m_xBuilder->weld_label(u"lbCTLStyle"_ustr))
220 , m_xCTLFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box(u"cbCTLStyle"_ustr)))
221 , m_xCTLFontSizeFT(m_xBuilder->weld_label(u"lbCTLSize"_ustr))
222 , m_xCTLFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box(u"cbCTLSize"_ustr)))
223 , m_xCTLFontLanguageFT(m_xBuilder->weld_label(u"lbCTLLanguage"_ustr))
224 , m_xCTLFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"cbCTLLanguage"_ustr)))
225 , m_xCTLFontFeaturesButton(m_xBuilder->weld_button(u"btnCTLFeatures"_ustr))
226 , m_xCTLFontTypeFT(m_xBuilder->weld_label(u"lbCTLFontinfo"_ustr))
227
228 , m_xVDev(*Application::GetDefaultDevice(), DeviceFormat::WITH_ALPHA)
229 {
230 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreviewWin));
231 #ifdef IOS
232 m_xPreviewWin->hide();
233 #endif
234 m_pImpl->m_aNoStyleText = CuiResId( RID_CUISTR_CHARNAME_NOSTYLE );
235
236 std::unique_ptr<weld::EntryTreeView> xWestFontName = m_xBuilder->weld_entry_tree_view(u"gdWestern"_ustr, u"edWestFontName"_ustr, u"trWestFontName"_ustr);
237 std::unique_ptr<weld::EntryTreeView> xCJKFontName = m_xBuilder->weld_entry_tree_view(u"gdCJK"_ustr, u"edCJKFontName"_ustr, u"trCJKFontName"_ustr);
238 std::unique_ptr<weld::EntryTreeView> xCTLFontName = m_xBuilder->weld_entry_tree_view(u"gdCTL"_ustr, u"edCTLFontName"_ustr, u"trCTLFontName"_ustr);
239
240 // 7 lines in the treeview
241 xWestFontName->set_height_request_by_rows(7);
242 xCJKFontName->set_height_request_by_rows(7);
243 xCTLFontName->set_height_request_by_rows(7);
244
245 m_xWestFontNameLB = std::move(xWestFontName);
246 m_xEastFontNameLB = std::move(xCJKFontName);
247 m_xCTLFontNameLB = std::move(xCTLFontName);
248
249 bool bShowCJK = SvtCJKOptions::IsCJKFontEnabled();
250 bool bShowCTL = SvtCTLOptions::IsCTLFontEnabled();
251 bool bShowNonWestern = bShowCJK || bShowCTL;
252 if (!bShowNonWestern)
253 {
254 m_xCJK_CTL->hide();
255 m_xWestern->set_show_tabs(false); //hide single tab in case of Western only
256 }
257 else if (!bShowCJK) m_xCJK_CTL->remove_page(u"nbCJK"_ustr);
258 else if (!bShowCTL) m_xCJK_CTL->remove_page(u"nbCTL"_ustr);
259
260
261 //In MacOSX the standard dialogs name font-name, font-style as
262 //Family, Typeface
263 //In GNOME the standard dialogs name font-name, font-style as
264 //Family, Style
265 //In Windows the standard dialogs name font-name, font-style as
266 //Font, Style
267 #ifdef _WIN32
268 OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FONT));
269 #else
270 OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FAMILY));
271 #endif
272 m_xWestFontNameFT->set_label(sFontFamilyString);
273 m_xCTLFontNameFT->set_label(sFontFamilyString);
274 m_xEastFontNameFT->set_label(sFontFamilyString);
275
276 #ifdef MACOSX
277 OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_TYPEFACE));
278 #else
279 OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_STYLE));
280 #endif
281 m_xWestFontStyleFT->set_label(sFontStyleString);
282 m_xEastFontStyleFT->set_label(sFontStyleString);
283 m_xCTLFontStyleFT->set_label(sFontStyleString);
284
285 m_xWestFontLanguageLB->SetLanguageList(SvxLanguageListFlags::WESTERN, true, false, true, true,
286 LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN);
287 m_xEastFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CJK, true, false, true, true,
288 LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN);
289 m_xCTLFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CTL, true, false, true, true,
290 LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX);
291 int nVisibleChars = 15;
292 // read-only combobox / HasEntry asserts on set_width_char()
293 m_xWestFontLanguageLB->set_width_chars(nVisibleChars);
294 m_xEastFontLanguageLB->set_width_chars(nVisibleChars);
295 m_xCTLFontLanguageLB->set_width_chars(nVisibleChars);
296
297 Initialize();
298 }
299
~SvxCharNamePage()300 SvxCharNamePage::~SvxCharNamePage()
301 {
302 m_pImpl.reset();
303 m_xCTLFontStyleLB.reset();
304 m_xEastFontLanguageLB.reset();
305 m_xWestFontStyleLB.reset();
306 m_xCTLFontSizeLB.reset();
307 m_xEastFontSizeLB.reset();
308 m_xWestFontSizeLB.reset();
309 m_xWestFontLanguageLB.reset();
310 m_xPreviewWin.reset();
311 m_xCTLFontLanguageLB.reset();
312 m_xEastFontLanguageLB.reset();
313 }
314
Initialize()315 void SvxCharNamePage::Initialize()
316 {
317 // to handle the changes of the other pages
318 SetExchangeSupport();
319
320 Link<weld::ComboBox&,void> aLink = LINK(this, SvxCharNamePage, FontModifyComboBoxHdl_Impl);
321 m_xWestFontNameLB->connect_changed(aLink);
322 m_xWestFontStyleLB->connect_changed(aLink);
323 m_xWestFontSizeLB->connect_changed(aLink);
324 m_xWestFontLanguageLB->connect_changed(aLink);
325
326 m_xWestFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
327
328 m_xEastFontNameLB->connect_changed(aLink);
329 m_xEastFontStyleLB->connect_changed(aLink);
330 m_xEastFontSizeLB->connect_changed(aLink);
331 m_xEastFontLanguageLB->connect_changed(aLink);
332 m_xEastFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
333
334 m_xCTLFontNameLB->connect_changed(aLink);
335 m_xCTLFontStyleLB->connect_changed(aLink);
336 m_xCTLFontSizeLB->connect_changed(aLink);
337 m_xCTLFontLanguageLB->connect_changed(aLink);
338 m_xCTLFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));
339
340 m_pImpl->m_aUpdateIdle.SetInvokeHandler( LINK( this, SvxCharNamePage, UpdateHdl_Impl ) );
341 }
342
GetFontList() const343 const FontList* SvxCharNamePage::GetFontList() const
344 {
345 if ( !m_pImpl->m_pFontList )
346 {
347 /* #110771# SvxFontListItem::GetFontList can return NULL */
348 if (SfxObjectShell* pDocSh = SfxObjectShell::Current())
349 {
350 const SfxPoolItem* pItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST );
351 if ( pItem != nullptr )
352 {
353 DBG_ASSERT(nullptr != static_cast<const SvxFontListItem*>(pItem)->GetFontList(),
354 "Where is the font list?");
355 m_pImpl->m_pFontList = static_cast<const SvxFontListItem*>(pItem )->GetFontList()->Clone();
356 }
357 }
358 if(!m_pImpl->m_pFontList)
359 {
360 m_pImpl->m_pFontList.reset(new FontList( Application::GetDefaultDevice() ));
361 }
362 }
363
364 return m_pImpl->m_pFontList.get();
365 }
366
367
368 namespace
369 {
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)370 FontMetric calcFontMetrics( SvxFont& _rFont,
371 SvxCharNamePage const * _pPage,
372 const weld::ComboBox* _pFontNameLB,
373 const FontStyleBox* _pFontStyleLB,
374 const FontSizeBox* _pFontSizeLB,
375 const SvxLanguageBox* _pLanguageLB,
376 const FontList* _pFontList,
377 sal_uInt16 _nFontWhich,
378 sal_uInt16 _nFontHeightWhich)
379 {
380 Size aSize = _rFont.GetFontSize();
381 aSize.setWidth( 0 );
382 FontMetric aFontMetrics;
383 OUString sFontName(_pFontNameLB->get_active_text());
384 bool bFontAvailable = _pFontList->IsAvailable( sFontName );
385 if (bFontAvailable || _pFontNameLB->get_value_changed_from_saved())
386 aFontMetrics = _pFontList->Get(sFontName, _pFontStyleLB->get_active_text());
387 else
388 {
389 //get the font from itemset
390 SfxItemState eState = _pPage->GetItemSet().GetItemState( _nFontWhich );
391 if ( eState >= SfxItemState::DEFAULT )
392 {
393 const SvxFontItem* pFontItem = static_cast<const SvxFontItem*>(&( _pPage->GetItemSet().Get( _nFontWhich ) ));
394 aFontMetrics.SetFamilyName(pFontItem->GetFamilyName());
395 aFontMetrics.SetStyleName(pFontItem->GetStyleName());
396 aFontMetrics.SetFamily(pFontItem->GetFamily());
397 aFontMetrics.SetPitch(pFontItem->GetPitch());
398 aFontMetrics.SetCharSet(pFontItem->GetCharSet());
399 }
400 }
401 if ( _pFontSizeLB->IsRelative() )
402 {
403 DBG_ASSERT( _pPage->GetItemSet().GetParent(), "No parent set" );
404 const SvxFontHeightItem& rOldItem = static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nFontHeightWhich ));
405
406 // old value, scaled
407 tools::Long nHeight;
408 if ( _pFontSizeLB->IsPtRelative() )
409 nHeight = rOldItem.GetHeight()
410 + o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt,
411 o3tl::Length::twip) / 10;
412 else
413 nHeight = static_cast<tools::Long>(rOldItem.GetHeight() * _pFontSizeLB->get_value() / 100);
414
415 // conversion twips for the example-window
416 aSize.setHeight(
417 ItemToControl( nHeight, _pPage->GetItemSet().GetPool()->GetMetric( _nFontHeightWhich ), FieldUnit::TWIP ) );
418 }
419 else if ( !_pFontSizeLB->get_active_text().isEmpty() )
420 aSize.setHeight(o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt,
421 o3tl::Length::twip) / 10);
422 else
423 aSize.setHeight( 200 ); // default 10pt
424 aFontMetrics.SetFontSize( aSize );
425
426 _rFont.SetLanguage(_pLanguageLB->get_active_id());
427
428 _rFont.SetFamily( aFontMetrics.GetFamilyTypeMaybeAskConfig() );
429 _rFont.SetFamilyName( aFontMetrics.GetFamilyName() );
430 _rFont.SetStyleName( aFontMetrics.GetStyleName() );
431 _rFont.SetPitch( aFontMetrics.GetPitchMaybeAskConfig() );
432 _rFont.SetCharSet( aFontMetrics.GetCharSet() );
433 _rFont.SetWeight( aFontMetrics.GetWeightMaybeAskConfig() );
434 _rFont.SetItalic( aFontMetrics.GetItalicMaybeAskConfig() );
435 _rFont.SetFontSize( aFontMetrics.GetFontSize() );
436
437 return aFontMetrics;
438 }
439 }
440
441
UpdatePreview_Impl()442 void SvxCharNamePage::UpdatePreview_Impl()
443 {
444 SvxFont& rFont = GetPreviewFont();
445 SvxFont& rCJKFont = GetPreviewCJKFont();
446 SvxFont& rCTLFont = GetPreviewCTLFont();
447 // Font
448 const FontList* pFontList = GetFontList();
449
450 FontMetric aWestFontMetric = calcFontMetrics(rFont, this, m_xWestFontNameLB.get(),
451 m_xWestFontStyleLB.get(), m_xWestFontSizeLB.get(), m_xWestFontLanguageLB.get(),
452 pFontList, GetWhich(SID_ATTR_CHAR_FONT),
453 GetWhich(SID_ATTR_CHAR_FONTHEIGHT));
454
455 m_xWestFontTypeFT->set_label(pFontList->GetFontMapText(aWestFontMetric));
456
457 FontMetric aEastFontMetric = calcFontMetrics(rCJKFont, this, m_xEastFontNameLB.get(),
458 m_xEastFontStyleLB.get(), m_xEastFontSizeLB.get(), m_xEastFontLanguageLB.get(),
459 pFontList, GetWhich(SID_ATTR_CHAR_CJK_FONT),
460 GetWhich(SID_ATTR_CHAR_CJK_FONTHEIGHT));
461
462 m_xEastFontTypeFT->set_label(pFontList->GetFontMapText(aEastFontMetric));
463
464 FontMetric aCTLFontMetric = calcFontMetrics(rCTLFont,
465 this, m_xCTLFontNameLB.get(), m_xCTLFontStyleLB.get(), m_xCTLFontSizeLB.get(),
466 m_xCTLFontLanguageLB.get(), pFontList, GetWhich(SID_ATTR_CHAR_CTL_FONT),
467 GetWhich(SID_ATTR_CHAR_CTL_FONTHEIGHT));
468
469 m_xCTLFontTypeFT->set_label(pFontList->GetFontMapText(aCTLFontMetric));
470
471 m_aPreviewWin.Invalidate();
472 }
EnableFeatureButton(const weld::Widget & rNameBox)473 void SvxCharNamePage::EnableFeatureButton(const weld::Widget& rNameBox)
474 {
475 OUString sFontName;
476 weld::Button* pButton= nullptr;
477 if (m_xWestFontNameLB.get() == &rNameBox)
478 {
479 sFontName = m_xWestFontNameLB->get_active_text();
480 pButton= m_xWestFontFeaturesButton.get();
481 }
482 else if (m_xEastFontNameLB.get() == &rNameBox)
483 {
484 sFontName = m_xEastFontNameLB->get_active_text();
485 pButton=m_xEastFontFeaturesButton.get();
486 }
487 else if (m_xCTLFontNameLB.get() == &rNameBox)
488 {
489 sFontName = m_xCTLFontNameLB->get_active_text();
490 pButton= m_xCTLFontFeaturesButton.get();
491 }
492 else
493 {
494 SAL_WARN( "cui.tabpages", "invalid font name box" );
495 return;
496 }
497
498 bool bEnable = !getFontFeatureList(sFontName, *m_xVDev).empty();
499
500 pButton->set_sensitive(bEnable);
501 }
502
FillStyleBox_Impl(const weld::Widget & rNameBox)503 void SvxCharNamePage::FillStyleBox_Impl(const weld::Widget& rNameBox)
504 {
505 const FontList* pFontList = GetFontList();
506 assert(pFontList && "no fontlist");
507
508 FontStyleBox* pStyleBox = nullptr;
509 OUString sFontName;
510
511 if (m_xWestFontNameLB.get() == &rNameBox)
512 {
513 pStyleBox = m_xWestFontStyleLB.get();
514 sFontName = m_xWestFontNameLB->get_active_text();
515 }
516 else if (m_xEastFontNameLB.get() == &rNameBox)
517 {
518 pStyleBox = m_xEastFontStyleLB.get();
519 sFontName = m_xEastFontStyleLB->get_active_text();
520 }
521 else if (m_xCTLFontNameLB.get() == &rNameBox)
522 {
523 pStyleBox = m_xCTLFontStyleLB.get();
524 sFontName = m_xCTLFontNameLB->get_active_text();
525 }
526 else
527 {
528 SAL_WARN( "cui.tabpages", "invalid font name box" );
529 return;
530 }
531
532 pStyleBox->Fill(sFontName, pFontList);
533
534 if ( !m_pImpl->m_bInSearchMode )
535 return;
536
537 // additional entries for the search:
538 // "not bold" and "not italic"
539 OUString aEntry = m_pImpl->m_aNoStyleText;
540 const char sS[] = "%1";
541 aEntry = aEntry.replaceFirst( sS, pFontList->GetBoldStr() );
542 m_pImpl->m_nExtraEntryPos = pStyleBox->get_count();
543 pStyleBox->append_text( aEntry );
544 aEntry = m_pImpl->m_aNoStyleText;
545 aEntry = aEntry.replaceFirst( sS, pFontList->GetItalicStr() );
546 pStyleBox->append_text(aEntry);
547 }
548
FillSizeBox_Impl(const weld::Widget & rNameBox)549 void SvxCharNamePage::FillSizeBox_Impl(const weld::Widget& rNameBox)
550 {
551 const FontList* pFontList = GetFontList();
552 DBG_ASSERT( pFontList, "no fontlist" );
553
554 FontSizeBox* pSizeBox = nullptr;
555
556 if (m_xWestFontNameLB.get() == &rNameBox)
557 {
558 pSizeBox = m_xWestFontSizeLB.get();
559 }
560 else if (m_xEastFontNameLB.get() == &rNameBox)
561 {
562 pSizeBox = m_xEastFontSizeLB.get();
563 }
564 else if (m_xCTLFontNameLB.get() == &rNameBox)
565 {
566 pSizeBox = m_xCTLFontSizeLB.get();
567 }
568 else
569 {
570 SAL_WARN( "cui.tabpages", "invalid font name box" );
571 return;
572 }
573
574 pSizeBox->Fill( pFontList );
575 }
576
577 namespace
578 {
FillFontNames(weld::ComboBox & rBox,const FontList & rList)579 void FillFontNames(weld::ComboBox& rBox, const FontList& rList)
580 {
581 // insert fonts
582 sal_uInt16 nFontCount = rList.GetFontNameCount();
583 std::vector<weld::ComboBoxEntry> aVector;
584 aVector.reserve(nFontCount);
585 for (sal_uInt16 i = 0; i < nFontCount; ++i)
586 {
587 const FontMetric& rFontMetric = rList.GetFontName(i);
588 aVector.emplace_back(rFontMetric.GetFamilyName());
589 }
590 rBox.insert_vector(aVector, false);
591 }
592 }
593
Reset_Impl(const SfxItemSet & rSet,LanguageGroup eLangGrp)594 void SvxCharNamePage::Reset_Impl( const SfxItemSet& rSet, LanguageGroup eLangGrp )
595 {
596 weld::ComboBox* pNameBox = nullptr;
597 weld::Label* pStyleLabel = nullptr;
598 FontStyleBox* pStyleBox = nullptr;
599 weld::Label* pSizeLabel = nullptr;
600 FontSizeBox* pSizeBox = nullptr;
601 weld::Label* pLangFT = nullptr;
602 SvxLanguageBox* pLangBox = nullptr;
603 sal_uInt16 nWhich = 0;
604
605 switch ( eLangGrp )
606 {
607 case Western :
608 pNameBox = m_xWestFontNameLB.get();
609 pStyleLabel = m_xWestFontStyleFT.get();
610 pStyleBox = m_xWestFontStyleLB.get();
611 pSizeLabel = m_xWestFontSizeFT.get();
612 pSizeBox = m_xWestFontSizeLB.get();
613 pLangFT = m_xWestFontLanguageFT.get();
614 pLangBox = m_xWestFontLanguageLB.get();
615 nWhich = GetWhich( SID_ATTR_CHAR_FONT );
616 break;
617
618 case Asian :
619 pNameBox = m_xEastFontNameLB.get();
620 pStyleLabel = m_xEastFontStyleFT.get();
621 pStyleBox = m_xEastFontStyleLB.get();
622 pSizeLabel = m_xEastFontSizeFT.get();
623 pSizeBox = m_xEastFontSizeLB.get();
624 pLangFT = m_xEastFontLanguageFT.get();
625 pLangBox = m_xEastFontLanguageLB.get();
626 nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONT );
627 break;
628
629 case Ctl :
630 pNameBox = m_xCTLFontNameLB.get();
631 pStyleLabel = m_xCTLFontStyleFT.get();
632 pStyleBox = m_xCTLFontStyleLB.get();
633 pSizeLabel = m_xCTLFontSizeFT.get();
634 pSizeBox = m_xCTLFontSizeLB.get();
635 pLangFT = m_xCTLFontLanguageFT.get();
636 pLangBox = m_xCTLFontLanguageLB.get();
637 nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONT );
638 break;
639 }
640
641 const FontList* pFontList = GetFontList();
642 FillFontNames(*pNameBox, *pFontList);
643
644 const SvxFontItem* pFontItem = nullptr;
645 SfxItemState eState = rSet.GetItemState( nWhich );
646
647 if ( eState >= SfxItemState::DEFAULT )
648 {
649 pFontItem = static_cast<const SvxFontItem*>(&( rSet.Get( nWhich ) ));
650 const OUString &rName = pFontItem->GetFamilyName();
651 int nIndex = pNameBox->find_text(rName);
652 pNameBox->set_active(nIndex);
653 // tdf#122992 if it didn't exist in the list, set the entry text to it anyway
654 if (nIndex == -1)
655 pNameBox->set_entry_text(rName);
656 }
657 else
658 {
659 pNameBox->set_active_text( OUString() );
660 }
661
662 FillStyleBox_Impl(*pNameBox);
663
664 bool bStyle = false;
665 bool bStyleAvailable = true;
666 FontItalic eItalic = ITALIC_NONE;
667 FontWeight eWeight = WEIGHT_NORMAL;
668 switch ( eLangGrp )
669 {
670 case Western : nWhich = GetWhich( SID_ATTR_CHAR_POSTURE ); break;
671 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_POSTURE ); break;
672 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_POSTURE ); break;
673 }
674 eState = rSet.GetItemState( nWhich );
675
676 if ( eState >= SfxItemState::DEFAULT )
677 {
678 const SvxPostureItem& rItem = static_cast<const SvxPostureItem&>(rSet.Get( nWhich ));
679 eItalic = rItem.GetValue();
680 bStyle = true;
681 }
682 bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::INVALID);
683
684 switch ( eLangGrp )
685 {
686 case Western : nWhich = GetWhich( SID_ATTR_CHAR_WEIGHT ); break;
687 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_WEIGHT ); break;
688 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_WEIGHT ); break;
689 }
690 eState = rSet.GetItemState( nWhich );
691
692 if ( eState >= SfxItemState::DEFAULT )
693 {
694 const SvxWeightItem& rItem = static_cast<const SvxWeightItem&>(rSet.Get( nWhich ));
695 eWeight = rItem.GetValue();
696 }
697 else
698 bStyle = false;
699 bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::INVALID);
700
701 // currently chosen font
702 if ( bStyle && pFontItem )
703 {
704 FontMetric aFontMetric = pFontList->Get( pFontItem->GetFamilyName(), eWeight, eItalic );
705 pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
706 }
707 else if ( !m_pImpl->m_bInSearchMode || !bStyle )
708 {
709 pStyleBox->set_active_text( OUString() );
710 }
711 else if ( bStyle )
712 {
713 FontMetric aFontMetric = pFontList->Get( OUString(), eWeight, eItalic );
714 pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
715 }
716 if (!bStyleAvailable)
717 {
718 pStyleBox->set_sensitive(false);
719 pStyleLabel->set_sensitive(false);
720 }
721
722 FillSizeBox_Impl(*pNameBox);
723 switch ( eLangGrp )
724 {
725 case Western : nWhich = GetWhich( SID_ATTR_CHAR_FONTHEIGHT ); break;
726 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ); break;
727 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ); break;
728 }
729 eState = rSet.GetItemState( nWhich );
730
731 if ( pSizeBox->IsRelativeMode() )
732 {
733 MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
734 const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));
735
736 if( rItem.GetProp() != 100 || MapUnit::MapRelative != rItem.GetPropUnit() )
737 {
738 bool bPtRel = MapUnit::MapPoint == rItem.GetPropUnit();
739 pSizeBox->SetPtRelative( bPtRel );
740 pSizeBox->set_value( bPtRel ? static_cast<short>(rItem.GetProp()) * 10 : rItem.GetProp() );
741 }
742 else
743 {
744 pSizeBox->SetRelative(false);
745 pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
746 }
747 }
748 else if ( eState >= SfxItemState::DEFAULT )
749 {
750 MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
751 const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));
752 pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
753 }
754 else
755 {
756 pSizeBox->set_active_or_entry_text(OUString());
757 if ( eState <= SfxItemState::DISABLED )
758 {
759 pSizeBox->set_sensitive(false);
760 pSizeLabel->set_sensitive(false);
761 }
762 }
763
764 switch ( eLangGrp )
765 {
766 case Western : nWhich = GetWhich( SID_ATTR_CHAR_LANGUAGE ); break;
767 case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_LANGUAGE ); break;
768 case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_LANGUAGE ); break;
769 }
770 pLangBox->set_active(-1);
771 eState = rSet.GetItemState( nWhich );
772
773 switch ( eState )
774 {
775 case SfxItemState::UNKNOWN:
776 pLangFT->hide();
777 pLangBox->hide();
778 break;
779
780 case SfxItemState::DISABLED:
781 pLangFT->set_sensitive(false);
782 pLangBox->set_sensitive(false);
783 break;
784
785 case SfxItemState::DEFAULT:
786 case SfxItemState::SET:
787 {
788 const SvxLanguageItem& rItem = static_cast<const SvxLanguageItem&>(rSet.Get( nWhich ));
789 LanguageType eLangType = rItem.GetValue();
790 DBG_ASSERT( eLangType != LANGUAGE_SYSTEM, "LANGUAGE_SYSTEM not allowed" );
791 if (eLangType != LANGUAGE_DONTKNOW)
792 pLangBox->set_active_id(eLangType);
793 break;
794 }
795 case SfxItemState::INVALID:
796 break;
797 }
798
799 OUString sMapText(pFontList->GetFontMapText(
800 pFontList->Get(pNameBox->get_active_text(), pStyleBox->get_active_text())));
801
802 switch (eLangGrp)
803 {
804 case Western:
805 m_xWestFontTypeFT->set_label(sMapText);
806 break;
807 case Asian:
808 m_xEastFontTypeFT->set_label(sMapText);
809 break;
810 case Ctl:
811 m_xCTLFontTypeFT->set_label(sMapText);
812 break;
813 }
814
815 EnableFeatureButton(*pNameBox);
816
817 // save these settings
818 pNameBox->save_value();
819 pStyleBox->save_value();
820 pSizeBox->save_value();
821 pLangBox->save_active_id();
822 }
823
FillItemSet_Impl(SfxItemSet & rSet,LanguageGroup eLangGrp)824 bool SvxCharNamePage::FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp )
825 {
826 bool bModified = false;
827
828 weld::ComboBox* pNameBox = nullptr;
829 FontStyleBox* pStyleBox = nullptr;
830 FontSizeBox* pSizeBox = nullptr;
831 SvxLanguageBox* pLangBox = nullptr;
832 sal_uInt16 nWhich = 0;
833 sal_uInt16 nSlot = 0;
834
835 switch ( eLangGrp )
836 {
837 case Western :
838 pNameBox = m_xWestFontNameLB.get();
839 pStyleBox = m_xWestFontStyleLB.get();
840 pSizeBox = m_xWestFontSizeLB.get();
841 pLangBox = m_xWestFontLanguageLB.get();
842 nSlot = SID_ATTR_CHAR_FONT;
843 break;
844
845 case Asian :
846 pNameBox = m_xEastFontNameLB.get();
847 pStyleBox = m_xEastFontStyleLB.get();
848 pSizeBox = m_xEastFontSizeLB.get();
849 pLangBox = m_xEastFontLanguageLB.get();
850 nSlot = SID_ATTR_CHAR_CJK_FONT;
851 break;
852
853 case Ctl :
854 pNameBox = m_xCTLFontNameLB.get();
855 pStyleBox = m_xCTLFontStyleLB.get();
856 pSizeBox = m_xCTLFontSizeLB.get();
857 pLangBox = m_xCTLFontLanguageLB.get();
858 nSlot = SID_ATTR_CHAR_CTL_FONT;
859 break;
860 }
861
862 nWhich = GetWhich( nSlot );
863 const SfxPoolItem* pItem = nullptr;
864 const SfxItemSet& rOldSet = GetItemSet();
865 const SfxPoolItem* pOld = nullptr;
866
867 const SfxItemSet* pExampleSet = GetDialogExampleSet();
868
869 bool bChanged = true;
870 const OUString aFontName = pNameBox->get_active_text();
871 const FontList* pFontList = GetFontList();
872 OUString aStyleBoxText = pStyleBox->get_active_text();
873 int nEntryPos = pStyleBox->find_text(aStyleBoxText);
874 if (nEntryPos >= m_pImpl->m_nExtraEntryPos)
875 aStyleBoxText.clear();
876 FontMetric aInfo( pFontList->Get( aFontName, aStyleBoxText ) );
877 SvxFontItem aFontItem( aInfo.GetFamilyTypeMaybeAskConfig(), aInfo.GetFamilyName(), aInfo.GetStyleName(),
878 aInfo.GetPitchMaybeAskConfig(), aInfo.GetCharSet(), nWhich );
879 pOld = GetOldItem( rSet, nSlot );
880
881 if ( pOld )
882 {
883 const SvxFontItem& rItem = *static_cast<const SvxFontItem*>(pOld);
884
885 if ( rItem.GetFamilyName() == aFontItem.GetFamilyName() )
886 bChanged = false;
887 }
888
889 if ( !bChanged )
890 bChanged = pNameBox->get_saved_value().isEmpty();
891
892 if ( !bChanged && pExampleSet &&
893 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
894 static_cast<const SvxFontItem*>(pItem)->GetFamilyName() != aFontItem.GetFamilyName() )
895 bChanged = true;
896
897 if ( bChanged && !aFontName.isEmpty() )
898 {
899 rSet.Put( aFontItem );
900 bModified = true;
901 }
902 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
903 rSet.ClearItem( nWhich );
904
905
906 bChanged = true;
907 switch ( eLangGrp )
908 {
909 case Western : nSlot = SID_ATTR_CHAR_WEIGHT; break;
910 case Asian : nSlot = SID_ATTR_CHAR_CJK_WEIGHT; break;
911 case Ctl : nSlot = SID_ATTR_CHAR_CTL_WEIGHT; break;
912 }
913 nWhich = GetWhich( nSlot );
914 FontWeight eWeight = aInfo.GetWeightMaybeAskConfig();
915 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
916 eWeight = WEIGHT_NORMAL;
917 SvxWeightItem aWeightItem( eWeight, nWhich );
918 pOld = GetOldItem( rSet, nSlot );
919
920 if ( pOld )
921 {
922 const SvxWeightItem& rItem = *static_cast<const SvxWeightItem*>(pOld);
923
924 if ( rItem.GetValue() == aWeightItem.GetValue() )
925 bChanged = false;
926 }
927
928 if ( !bChanged )
929 {
930 bChanged = pStyleBox->get_saved_value().isEmpty();
931
932 if ( m_pImpl->m_bInSearchMode && bChanged &&
933 aInfo.GetWeightMaybeAskConfig() == WEIGHT_NORMAL && aInfo.GetItalicMaybeAskConfig() != ITALIC_NONE )
934 bChanged = false;
935 }
936
937 if ( !bChanged && pExampleSet &&
938 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
939 static_cast<const SvxWeightItem*>(pItem)->GetValue() != aWeightItem.GetValue() )
940 bChanged = true;
941
942 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
943 bChanged = ( nEntryPos == m_pImpl->m_nExtraEntryPos );
944
945 OUString aText( pStyleBox->get_active_text() ); // Tristate, then text empty
946
947 if ( bChanged && !aText.isEmpty() )
948 {
949 rSet.Put( aWeightItem );
950 bModified = true;
951 }
952 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
953 rSet.InvalidateItem(nWhich);
954
955 bChanged = true;
956 switch ( eLangGrp )
957 {
958 case Western : nSlot = SID_ATTR_CHAR_POSTURE; break;
959 case Asian : nSlot = SID_ATTR_CHAR_CJK_POSTURE; break;
960 case Ctl : nSlot = SID_ATTR_CHAR_CTL_POSTURE; break;
961 }
962 nWhich = GetWhich( nSlot );
963 FontItalic eItalic = aInfo.GetItalicMaybeAskConfig();
964 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
965 eItalic = ITALIC_NONE;
966 SvxPostureItem aPostureItem( eItalic, nWhich );
967 pOld = GetOldItem( rSet, nSlot );
968
969 if ( pOld )
970 {
971 const SvxPostureItem& rItem = *static_cast<const SvxPostureItem*>(pOld);
972
973 if ( rItem.GetValue() == aPostureItem.GetValue() )
974 bChanged = false;
975 }
976
977 if ( !bChanged )
978 {
979 bChanged = pStyleBox->get_saved_value().isEmpty();
980
981 if ( m_pImpl->m_bInSearchMode && bChanged &&
982 aInfo.GetItalicMaybeAskConfig() == ITALIC_NONE && aInfo.GetWeightMaybeAskConfig() != WEIGHT_NORMAL )
983 bChanged = false;
984 }
985
986 if ( !bChanged && pExampleSet &&
987 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
988 static_cast<const SvxPostureItem*>(pItem)->GetValue() != aPostureItem.GetValue() )
989 bChanged = true;
990
991 if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
992 bChanged = ( nEntryPos == ( m_pImpl->m_nExtraEntryPos + 1 ) );
993
994 if ( bChanged && !aText.isEmpty() )
995 {
996 rSet.Put( aPostureItem );
997 bModified = true;
998 }
999 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1000 rSet.InvalidateItem(nWhich);
1001
1002 // FontSize
1003 tools::Long nSize = pSizeBox->get_value();
1004
1005 if ( pSizeBox->get_active_text().isEmpty() ) // GetValue() returns the min-value
1006 nSize = 0;
1007 tools::Long nSavedSize = pSizeBox->get_saved_value();
1008 const bool bRel = pSizeBox->IsRelative();
1009
1010 switch ( eLangGrp )
1011 {
1012 case Western : nSlot = SID_ATTR_CHAR_FONTHEIGHT; break;
1013 case Asian : nSlot = SID_ATTR_CHAR_CJK_FONTHEIGHT; break;
1014 case Ctl : nSlot = SID_ATTR_CHAR_CTL_FONTHEIGHT; break;
1015 }
1016 nWhich = GetWhich( nSlot );
1017 const SvxFontHeightItem* pOldHeight = static_cast<const SvxFontHeightItem*>(GetOldItem( rSet, nSlot ));
1018 bChanged = ( nSize != nSavedSize );
1019
1020 if ( !bChanged && pExampleSet &&
1021 pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET )
1022 {
1023 float fSize = static_cast<float>(nSize) / 10;
1024 tools::Long nVal = CalcToUnit( fSize, rSet.GetPool()->GetMetric( nWhich ) );
1025 if ( static_cast<const SvxFontHeightItem*>(pItem)->GetHeight() != static_cast<sal_uInt32>(nVal) )
1026 bChanged = true;
1027 }
1028
1029 if ( bChanged || !pOldHeight ||
1030 bRel != ( MapUnit::MapRelative != pOldHeight->GetPropUnit() || 100 != pOldHeight->GetProp() ) )
1031 {
1032 MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
1033 if ( pSizeBox->IsRelative() )
1034 {
1035 DBG_ASSERT( GetItemSet().GetParent(), "No parent set" );
1036 const SvxFontHeightItem& rOldItem =
1037 static_cast<const SvxFontHeightItem&>(GetItemSet().GetParent()->Get( nWhich ));
1038
1039 SvxFontHeightItem aHeight( 240, 100, nWhich );
1040 if ( pSizeBox->IsPtRelative() )
1041 aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>( nSize / 10 ), MapUnit::MapPoint, eUnit );
1042 else
1043 aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>(nSize) );
1044 rSet.Put( aHeight );
1045 }
1046 else
1047 {
1048 float fSize = static_cast<float>(nSize) / 10;
1049 rSet.Put( SvxFontHeightItem( CalcToUnit( fSize, eUnit ), 100, nWhich ) );
1050 }
1051 bModified = true;
1052 }
1053 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1054 rSet.InvalidateItem(nWhich);
1055
1056 bChanged = true;
1057 switch ( eLangGrp )
1058 {
1059 case Western : nSlot = SID_ATTR_CHAR_LANGUAGE; break;
1060 case Asian : nSlot = SID_ATTR_CHAR_CJK_LANGUAGE; break;
1061 case Ctl : nSlot = SID_ATTR_CHAR_CTL_LANGUAGE; break;
1062 }
1063
1064 // For language list boxes acting as ComboBox, check for, add and select an
1065 // edited entry.
1066 switch (pLangBox->GetEditedAndValid())
1067 {
1068 case SvxLanguageBox::EditedAndValid::No:
1069 ; // nothing to do
1070 break;
1071 case SvxLanguageBox::EditedAndValid::Valid:
1072 {
1073 SvxLanguageBox* ppBoxes[3]
1074 = {m_xWestFontLanguageLB.get(), m_xEastFontLanguageLB.get(), m_xCTLFontLanguageLB.get()};
1075 SvxLanguageBox* pBox = pLangBox->SaveEditedAsEntry(ppBoxes);
1076 if (pBox != pLangBox)
1077 {
1078 // Get item from corresponding slot.
1079 if (pBox == m_xWestFontLanguageLB.get())
1080 nSlot = SID_ATTR_CHAR_LANGUAGE;
1081 else if (pBox == m_xEastFontLanguageLB.get())
1082 nSlot = SID_ATTR_CHAR_CJK_LANGUAGE;
1083 else if (pBox == m_xCTLFontLanguageLB.get())
1084 nSlot = SID_ATTR_CHAR_CTL_LANGUAGE;
1085 pLangBox = pBox;
1086 }
1087 }
1088 break;
1089 case SvxLanguageBox::EditedAndValid::Invalid:
1090 pLangBox->set_active_id(pLangBox->get_saved_active_id());
1091 break;
1092 }
1093
1094 nWhich = GetWhich( nSlot );
1095 pOld = GetOldItem( rSet, nSlot );
1096
1097 int nLangPos = pLangBox->get_active();
1098 LanguageType eLangType = pLangBox->get_active_id();
1099
1100 if (pOld)
1101 {
1102 const SvxLanguageItem& rItem = *static_cast<const SvxLanguageItem*>(pOld);
1103 if (nLangPos == -1 || eLangType == rItem.GetValue())
1104 bChanged = false;
1105 }
1106
1107 if (!bChanged)
1108 bChanged = pLangBox->get_active_id_changed_from_saved();
1109
1110 if (bChanged && nLangPos != -1)
1111 {
1112 rSet.Put(SvxLanguageItem(eLangType, nWhich));
1113 bModified = true;
1114 }
1115 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1116 rSet.InvalidateItem(nWhich);
1117
1118 return bModified;
1119 }
1120
IMPL_LINK_NOARG(SvxCharNamePage,UpdateHdl_Impl,Timer *,void)1121 IMPL_LINK_NOARG(SvxCharNamePage, UpdateHdl_Impl, Timer *, void)
1122 {
1123 UpdatePreview_Impl();
1124 }
1125
IMPL_LINK(SvxCharNamePage,FontModifyComboBoxHdl_Impl,weld::ComboBox &,rBox,void)1126 IMPL_LINK(SvxCharNamePage, FontModifyComboBoxHdl_Impl, weld::ComboBox&, rBox, void)
1127 {
1128 FontModifyHdl_Impl(rBox);
1129 }
1130
IMPL_LINK(SvxCharNamePage,FontFeatureButtonClicked,weld::Button &,rButton,void)1131 IMPL_LINK(SvxCharNamePage, FontFeatureButtonClicked, weld::Button&, rButton, void)
1132 {
1133 OUString sFontName;
1134 weld::ComboBox* pNameBox = nullptr;
1135
1136 if (&rButton == m_xWestFontFeaturesButton.get())
1137 {
1138 pNameBox = m_xWestFontNameLB.get();
1139 sFontName = GetPreviewFont().GetFamilyName();
1140 }
1141 else if (&rButton == m_xEastFontFeaturesButton.get())
1142 {
1143 pNameBox = m_xEastFontNameLB.get();
1144 sFontName = GetPreviewCJKFont().GetFamilyName();
1145 }
1146 else if (&rButton == m_xCTLFontFeaturesButton.get())
1147 {
1148 pNameBox = m_xCTLFontNameLB.get();
1149 sFontName = GetPreviewCTLFont().GetFamilyName();
1150 }
1151
1152 if (!sFontName.isEmpty() && pNameBox)
1153 {
1154 cui::FontFeaturesDialog aDialog(GetFrameWeld(), sFontName);
1155 if (aDialog.run() == RET_OK)
1156 {
1157 pNameBox->set_entry_text(aDialog.getResultFontName());
1158 UpdatePreview_Impl();
1159 }
1160 }
1161 }
1162
FontModifyHdl_Impl(const weld::Widget & rNameBox)1163 void SvxCharNamePage::FontModifyHdl_Impl(const weld::Widget& rNameBox)
1164 {
1165 m_pImpl->m_aUpdateIdle.Start();
1166
1167 if (m_xWestFontNameLB.get() == &rNameBox || m_xEastFontNameLB.get() == &rNameBox || m_xCTLFontNameLB.get() == &rNameBox)
1168 {
1169 FillStyleBox_Impl(rNameBox);
1170 FillSizeBox_Impl(rNameBox);
1171 EnableFeatureButton(rNameBox);
1172 }
1173 }
1174
ActivatePage(const SfxItemSet & rSet)1175 void SvxCharNamePage::ActivatePage( const SfxItemSet& rSet )
1176 {
1177 SvxCharBasePage::ActivatePage( rSet );
1178
1179 UpdatePreview_Impl(); // instead of asynchronous calling in ctor
1180 }
1181
DeactivatePage(SfxItemSet * _pSet)1182 DeactivateRC SvxCharNamePage::DeactivatePage( SfxItemSet* _pSet )
1183 {
1184 if ( _pSet )
1185 FillItemSet( _pSet );
1186 return DeactivateRC::LeavePage;
1187 }
1188
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)1189 std::unique_ptr<SfxTabPage> SvxCharNamePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
1190 {
1191 return std::make_unique<SvxCharNamePage>(pPage, pController, *rSet );
1192 }
1193
Reset(const SfxItemSet * rSet)1194 void SvxCharNamePage::Reset( const SfxItemSet* rSet )
1195 {
1196 Reset_Impl( *rSet, Western );
1197 Reset_Impl( *rSet, Asian );
1198 Reset_Impl( *rSet, Ctl );
1199
1200 SetPrevFontWidthScale( *rSet );
1201 UpdatePreview_Impl();
1202 }
1203
ChangesApplied()1204 void SvxCharNamePage::ChangesApplied()
1205 {
1206 m_xWestFontNameLB->save_value();
1207 m_xWestFontStyleLB->save_value();
1208 m_xWestFontSizeLB->save_value();
1209 m_xWestFontLanguageLB->save_active_id();
1210 m_xEastFontNameLB->save_value();
1211 m_xEastFontStyleLB->save_value();
1212 m_xEastFontSizeLB->save_value();
1213 m_xEastFontLanguageLB->save_active_id();
1214 m_xCTLFontNameLB->save_value();
1215 m_xCTLFontStyleLB->save_value();
1216 m_xCTLFontSizeLB->save_value();
1217 m_xCTLFontLanguageLB->save_active_id();
1218 }
1219
FillItemSet(SfxItemSet * rSet)1220 bool SvxCharNamePage::FillItemSet( SfxItemSet* rSet )
1221 {
1222 bool bModified = FillItemSet_Impl( *rSet, Western );
1223 bModified |= FillItemSet_Impl( *rSet, Asian );
1224 bModified |= FillItemSet_Impl( *rSet, Ctl );
1225 return bModified;
1226 }
1227
SetFontList(const SvxFontListItem & rItem)1228 void SvxCharNamePage::SetFontList( const SvxFontListItem& rItem )
1229 {
1230 m_pImpl->m_pFontList = rItem.GetFontList()->Clone();
1231 }
1232
1233 namespace
1234 {
enableRelativeMode(SvxCharNamePage const * _pPage,FontSizeBox * _pFontSizeLB,sal_uInt16 _nHeightWhich)1235 void enableRelativeMode( SvxCharNamePage const * _pPage, FontSizeBox* _pFontSizeLB, sal_uInt16 _nHeightWhich )
1236 {
1237 _pFontSizeLB->EnableRelativeMode( 5, 995 ); // min 5%, max 995%, step 5
1238
1239 const SvxFontHeightItem& rHeightItem =
1240 static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nHeightWhich ));
1241 MapUnit eUnit = _pPage->GetItemSet().GetPool()->GetMetric( _nHeightWhich );
1242 short nCurHeight =
1243 static_cast< short >( CalcToPoint( rHeightItem.GetHeight(), eUnit, 1 ) * 10 );
1244
1245 // based on the current height:
1246 // - negative until minimum of 2 pt
1247 // - positive until maximum of 999 pt
1248 _pFontSizeLB->EnablePtRelativeMode( sal::static_int_cast< short >(-(nCurHeight - 20)), (9999 - nCurHeight) );
1249 }
1250 }
1251
EnableRelativeMode()1252 void SvxCharNamePage::EnableRelativeMode()
1253 {
1254 DBG_ASSERT( GetItemSet().GetParent(), "RelativeMode, but no ParentSet!" );
1255 enableRelativeMode(this,m_xWestFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_FONTHEIGHT ));
1256 enableRelativeMode(this,m_xEastFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ));
1257 enableRelativeMode(this,m_xCTLFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ));
1258 }
1259
EnableSearchMode()1260 void SvxCharNamePage::EnableSearchMode()
1261 {
1262 m_pImpl->m_bInSearchMode = true;
1263 }
1264
DisableControls(sal_uInt16 nDisable)1265 void SvxCharNamePage::DisableControls( sal_uInt16 nDisable )
1266 {
1267 if ( DISABLE_HIDE_LANGUAGE & nDisable )
1268 {
1269 if ( m_xWestFontLanguageFT ) m_xWestFontLanguageFT->hide();
1270 if ( m_xWestFontLanguageLB ) m_xWestFontLanguageLB->hide();
1271 if ( m_xEastFontLanguageFT ) m_xEastFontLanguageFT->hide();
1272 if ( m_xEastFontLanguageLB ) m_xEastFontLanguageLB->hide();
1273 if ( m_xCTLFontLanguageFT ) m_xCTLFontLanguageFT->hide();
1274 if ( m_xCTLFontLanguageLB ) m_xCTLFontLanguageLB->hide();
1275 }
1276 }
1277
PageCreated(const SfxAllItemSet & aSet)1278 void SvxCharNamePage::PageCreated(const SfxAllItemSet& aSet)
1279 {
1280 const SvxFontListItem* pFontListItem = aSet.GetItem<SvxFontListItem>(SID_ATTR_CHAR_FONTLIST, false);
1281 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
1282 const SfxUInt16Item* pDisableItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false);
1283 if (pFontListItem)
1284 SetFontList(*pFontListItem);
1285
1286 if (pFlagItem)
1287 {
1288 sal_uInt32 nFlags=pFlagItem->GetValue();
1289 if ( ( nFlags & SVX_RELATIVE_MODE ) == SVX_RELATIVE_MODE )
1290 EnableRelativeMode();
1291 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
1292 // the writer uses SID_ATTR_BRUSH as font background
1293 m_bPreviewBackgroundToCharacter = true;
1294 }
1295 if (pDisableItem)
1296 DisableControls(pDisableItem->GetValue());
1297 }
1298 // class SvxCharEffectsPage ----------------------------------------------
1299
SvxCharEffectsPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rInSet)1300 SvxCharEffectsPage::SvxCharEffectsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
1301 : SvxCharBasePage(pPage, pController, u"cui/ui/effectspage.ui"_ustr, u"EffectsPage"_ustr, rInSet)
1302 , m_bOrigFontColor(false)
1303 , m_bNewFontColor(false)
1304 , m_bEnableNoneFontColor(false)
1305 , m_xFontColorFT(m_xBuilder->weld_label(u"fontcolorft"_ustr))
1306 , m_xFontColorLB(new ColorListBox(m_xBuilder->weld_menu_button(u"fontcolorlb"_ustr),
1307 [this]{ return GetDialogController()->getDialog(); }))
1308 , m_xFontTransparencyFT(m_xBuilder->weld_label(u"fonttransparencyft"_ustr))
1309 , m_xFontTransparencyMtr(
1310 m_xBuilder->weld_metric_spin_button(u"fonttransparencymtr"_ustr, FieldUnit::PERCENT))
1311 , m_xEffectsFT(m_xBuilder->weld_label(u"effectsft"_ustr))
1312 , m_xEffectsLB(m_xBuilder->weld_combo_box(u"effectslb"_ustr))
1313 , m_xReliefFT(m_xBuilder->weld_label(u"reliefft"_ustr))
1314 , m_xReliefLB(m_xBuilder->weld_combo_box(u"relieflb"_ustr))
1315 , m_xOutlineBtn(m_xBuilder->weld_check_button(u"outlinecb"_ustr))
1316 , m_xShadowBtn(m_xBuilder->weld_check_button(u"shadowcb"_ustr))
1317 , m_xHiddenBtn(m_xBuilder->weld_check_button(u"hiddencb"_ustr))
1318 , m_xOverlineLB(m_xBuilder->weld_combo_box(u"overlinelb"_ustr))
1319 , m_xOverlineColorFT(m_xBuilder->weld_label(u"overlinecolorft"_ustr))
1320 , m_xOverlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button(u"overlinecolorlb"_ustr),
__anonb1fa9ad10602null1321 [this]{ return GetDialogController()->getDialog(); }))
1322 , m_xStrikeoutLB(m_xBuilder->weld_combo_box(u"strikeoutlb"_ustr))
1323 , m_xUnderlineLB(m_xBuilder->weld_combo_box(u"underlinelb"_ustr))
1324 , m_xUnderlineColorFT(m_xBuilder->weld_label(u"underlinecolorft"_ustr))
1325 , m_xUnderlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button(u"underlinecolorlb"_ustr),
__anonb1fa9ad10702null1326 [this]{ return GetDialogController()->getDialog(); }))
1327 , m_xIndividualWordsBtn(m_xBuilder->weld_check_button(u"individualwordscb"_ustr))
1328 , m_xEmphasisFT(m_xBuilder->weld_label(u"emphasisft"_ustr))
1329 , m_xEmphasisLB(m_xBuilder->weld_combo_box(u"emphasislb"_ustr))
1330 , m_xPositionFT(m_xBuilder->weld_label(u"positionft"_ustr))
1331 , m_xPositionLB(m_xBuilder->weld_combo_box(u"positionlb"_ustr))
1332 , m_xA11yWarningFT(m_xBuilder->weld_label(u"a11ywarning"_ustr))
1333 {
1334 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreviewWin));
1335 #ifdef IOS
1336 m_xPreviewWin->hide();
1337 #endif
1338 m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1339 m_xOverlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1340 m_xUnderlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
1341 Initialize();
1342 }
1343
EnableNoneFontColor()1344 void SvxCharEffectsPage::EnableNoneFontColor()
1345 {
1346 m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR, true);
1347 m_bEnableNoneFontColor = true;
1348 }
1349
~SvxCharEffectsPage()1350 SvxCharEffectsPage::~SvxCharEffectsPage()
1351 {
1352 m_xUnderlineColorLB.reset();
1353 m_xOverlineColorLB.reset();
1354 m_xFontTransparencyMtr.reset();
1355 m_xFontColorLB.reset();
1356 }
1357
Initialize()1358 void SvxCharEffectsPage::Initialize()
1359 {
1360 // to handle the changes of the other pages
1361 SetExchangeSupport();
1362
1363 // HTML-Mode
1364 const SfxUInt16Item* pHtmlModeItem = GetItemSet().GetItemIfSet( SID_HTML_MODE, false );
1365 if ( !pHtmlModeItem)
1366 {
1367 if (SfxObjectShell* pShell = SfxObjectShell::Current())
1368 pHtmlModeItem = pShell->GetItem( SID_HTML_MODE );
1369 }
1370 if (pHtmlModeItem)
1371 {
1372 sal_uInt16 nHtmlMode = pHtmlModeItem->GetValue();
1373 if ( ( nHtmlMode & HTMLMODE_ON ) == HTMLMODE_ON )
1374 {
1375 //!!! hide some controls please
1376 }
1377 }
1378
1379 m_xFontColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
1380 m_xFontTransparencyMtr->connect_value_changed(
1381 LINK(this, SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl));
1382
1383 // handler
1384 Link<weld::ComboBox&,void> aLink = LINK( this, SvxCharEffectsPage, SelectListBoxHdl_Impl );
1385 m_xUnderlineLB->connect_changed( aLink );
1386 m_xUnderlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
1387 m_xOverlineLB->connect_changed( aLink );
1388 m_xOverlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
1389 m_xStrikeoutLB->connect_changed( aLink );
1390 m_xEmphasisLB->connect_changed( aLink );
1391 m_xPositionLB->connect_changed( aLink );
1392 m_xEffectsLB->connect_changed( aLink );
1393 m_xReliefLB->connect_changed( aLink );
1394
1395 m_xUnderlineLB->set_active( 0 );
1396 m_xOverlineLB->set_active( 0 );
1397 m_xStrikeoutLB->set_active( 0 );
1398 m_xEmphasisLB->set_active( 0 );
1399 m_xPositionLB->set_active( 0 );
1400 SelectHdl_Impl(nullptr);
1401 SelectHdl_Impl(m_xEmphasisLB.get());
1402
1403 m_xEffectsLB->set_active( 0 );
1404
1405 m_xHiddenBtn->connect_toggled(LINK(this, SvxCharEffectsPage, HiddenBtnClickHdl));
1406 m_xIndividualWordsBtn->connect_toggled(LINK(this, SvxCharEffectsPage, CbClickHdl_Impl));
1407 m_xOutlineBtn->connect_toggled(LINK(this, SvxCharEffectsPage, OutlineBtnClickHdl));
1408 m_xShadowBtn->connect_toggled(LINK(this, SvxCharEffectsPage, ShadowBtnClickHdl));
1409
1410 if ( !SvtCJKOptions::IsAsianTypographyEnabled() )
1411 {
1412 m_xEmphasisFT->hide();
1413 m_xEmphasisLB->hide();
1414 m_xPositionFT->hide();
1415 m_xPositionLB->hide();
1416 }
1417
1418 m_xA11yWarningFT->set_visible(officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get());
1419 }
1420
UpdatePreview_Impl()1421 void SvxCharEffectsPage::UpdatePreview_Impl()
1422 {
1423 SvxFont& rFont = GetPreviewFont();
1424 SvxFont& rCJKFont = GetPreviewCJKFont();
1425 SvxFont& rCTLFont = GetPreviewCTLFont();
1426
1427 const Color& rSelectedColor = m_xFontColorLB->GetSelectEntryColor();
1428 rFont.SetColor(rSelectedColor);
1429 rCJKFont.SetColor(rSelectedColor);
1430 rCTLFont.SetColor(rSelectedColor);
1431 m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO
1432
1433 FontLineStyle eUnderline = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32());
1434 FontLineStyle eOverline = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32());
1435 FontStrikeout eStrikeout = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32());
1436 rFont.SetUnderline( eUnderline );
1437 rCJKFont.SetUnderline( eUnderline );
1438 rCTLFont.SetUnderline( eUnderline );
1439 m_aPreviewWin.SetTextLineColor( m_xUnderlineColorLB->GetSelectEntryColor() );
1440 rFont.SetOverline( eOverline );
1441 rCJKFont.SetOverline( eOverline );
1442 rCTLFont.SetOverline( eOverline );
1443 m_aPreviewWin.SetOverlineColor( m_xOverlineColorLB->GetSelectEntryColor() );
1444 rFont.SetStrikeout( eStrikeout );
1445 rCJKFont.SetStrikeout( eStrikeout );
1446 rCTLFont.SetStrikeout( eStrikeout );
1447
1448 auto nEmphasis = m_xEmphasisLB->get_active();
1449 if (nEmphasis != -1)
1450 {
1451 bool bUnder = (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32());
1452 FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nEmphasis);
1453 eMark |= bUnder ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove;
1454 rFont.SetEmphasisMark( eMark );
1455 rCJKFont.SetEmphasisMark( eMark );
1456 rCTLFont.SetEmphasisMark( eMark );
1457 }
1458
1459 auto nRelief = m_xReliefLB->get_active();
1460 if (nRelief != -1)
1461 {
1462 rFont.SetRelief( static_cast<FontRelief>(nRelief) );
1463 rCJKFont.SetRelief( static_cast<FontRelief>(nRelief) );
1464 rCTLFont.SetRelief( static_cast<FontRelief>(nRelief) );
1465 }
1466
1467 rFont.SetOutline( StateToAttr( m_xOutlineBtn->get_state() ) );
1468 rCJKFont.SetOutline( rFont.IsOutline() );
1469 rCTLFont.SetOutline( rFont.IsOutline() );
1470
1471 rFont.SetShadow( StateToAttr( m_xShadowBtn->get_state() ) );
1472 rCJKFont.SetShadow( rFont.IsShadow() );
1473 rCTLFont.SetShadow( rFont.IsShadow() );
1474
1475 auto nCapsPos = m_xEffectsLB->get_active();
1476 if (nCapsPos != -1)
1477 {
1478 SvxCaseMap eCaps = static_cast<SvxCaseMap>(nCapsPos);
1479 rFont.SetCaseMap( eCaps );
1480 rCJKFont.SetCaseMap( eCaps );
1481 // #i78474# small caps do not exist in CTL fonts
1482 rCTLFont.SetCaseMap( eCaps == SvxCaseMap::SmallCaps ? SvxCaseMap::NotMapped : eCaps );
1483 }
1484
1485 bool bWordLine = StateToAttr( m_xIndividualWordsBtn->get_state() );
1486 rFont.SetWordLineMode( bWordLine );
1487 rCJKFont.SetWordLineMode( bWordLine );
1488 rCTLFont.SetWordLineMode( bWordLine );
1489
1490 m_aPreviewWin.Invalidate();
1491 }
1492
SetCaseMap_Impl(SvxCaseMap eCaseMap)1493 void SvxCharEffectsPage::SetCaseMap_Impl( SvxCaseMap eCaseMap )
1494 {
1495 if ( SvxCaseMap::End > eCaseMap )
1496 m_xEffectsLB->set_active(
1497 sal::static_int_cast< sal_Int32 >( eCaseMap ) );
1498 else
1499 {
1500 // not mapped
1501 m_xEffectsLB->set_active(-1);
1502 }
1503
1504 UpdatePreview_Impl();
1505 }
1506
ResetColor_Impl(const SfxItemSet & rSet)1507 void SvxCharEffectsPage::ResetColor_Impl( const SfxItemSet& rSet )
1508 {
1509 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
1510 SfxItemState eState = rSet.GetItemState( nWhich );
1511
1512 m_bOrigFontColor = false;
1513 switch ( eState )
1514 {
1515 case SfxItemState::UNKNOWN:
1516 m_xFontColorFT->hide();
1517 m_xFontColorLB->hide();
1518 break;
1519
1520 case SfxItemState::DISABLED:
1521 m_xFontColorFT->set_sensitive(false);
1522 m_xFontColorLB->set_sensitive(false);
1523 break;
1524
1525 case SfxItemState::INVALID:
1526 //Related: tdf#106080 if there is no font color, then allow "none"
1527 //as a color so the listbox can display that state.
1528 EnableNoneFontColor();
1529 m_xFontColorLB->SetNoSelection();
1530 break;
1531
1532 case SfxItemState::DEFAULT:
1533 case SfxItemState::SET:
1534 {
1535 SvxFont& rFont = GetPreviewFont();
1536 SvxFont& rCJKFont = GetPreviewCJKFont();
1537 SvxFont& rCTLFont = GetPreviewCTLFont();
1538
1539 const SvxColorItem& rItem = static_cast<const SvxColorItem&>(rSet.Get( nWhich ));
1540 Color aColor = rItem.GetValue();
1541 rFont.SetColor(aColor);
1542 rCJKFont.SetColor(aColor);
1543 rCTLFont.SetColor(aColor);
1544 m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO
1545
1546 m_aPreviewWin.Invalidate();
1547
1548 Color aRGBColor = aColor;
1549 if (aRGBColor.IsTransparent() && aColor != COL_AUTO)
1550 {
1551 aRGBColor.SetAlpha(255);
1552 }
1553 m_xFontColorLB->SelectEntry(aRGBColor);
1554
1555 if (m_xFontTransparencyMtr->get_visible() && aColor != COL_AUTO)
1556 {
1557 double fTransparency = (255 - aColor.GetAlpha()) * 100.0 / 255;
1558 m_xFontTransparencyMtr->set_value(basegfx::fround(fTransparency),
1559 FieldUnit::PERCENT);
1560 }
1561
1562 m_aOrigFontColor = aColor;
1563 m_bOrigFontColor = true;
1564 break;
1565 }
1566 }
1567 m_bNewFontColor = false;
1568 }
1569
FillItemSetColor_Impl(SfxItemSet & rSet)1570 bool SvxCharEffectsPage::FillItemSetColor_Impl( SfxItemSet& rSet )
1571 {
1572 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
1573 const SfxItemSet& rOldSet = GetItemSet();
1574
1575 NamedColor aSelectedColor;
1576 bool bChanged = m_bNewFontColor;
1577
1578 if (bChanged)
1579 {
1580 aSelectedColor = m_xFontColorLB->GetSelectedEntryThemedColor();
1581
1582 if (m_xFontTransparencyMtr->get_value_changed_from_saved())
1583 {
1584 double fTransparency
1585 = m_xFontTransparencyMtr->get_value(FieldUnit::PERCENT) * 255.0 / 100;
1586 aSelectedColor.m_aColor.SetAlpha(255 - static_cast<sal_uInt8>(basegfx::fround(fTransparency)));
1587 }
1588
1589 if (m_bOrigFontColor)
1590 bChanged = aSelectedColor.m_aColor != m_aOrigFontColor;
1591 if (m_bEnableNoneFontColor && bChanged && aSelectedColor.m_aColor == COL_NONE_COLOR)
1592 bChanged = false;
1593 }
1594
1595 if (bChanged)
1596 {
1597 SvxColorItem aItem(aSelectedColor.m_aColor, aSelectedColor.getComplexColor(), nWhich);
1598 rSet.Put(aItem);
1599 }
1600 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
1601 rSet.InvalidateItem(nWhich);
1602
1603 return bChanged;
1604 }
1605
IMPL_LINK(SvxCharEffectsPage,SelectListBoxHdl_Impl,weld::ComboBox &,rBox,void)1606 IMPL_LINK( SvxCharEffectsPage, SelectListBoxHdl_Impl, weld::ComboBox&, rBox, void )
1607 {
1608 SelectHdl_Impl(&rBox);
1609 }
1610
SelectHdl_Impl(const weld::ComboBox * pBox)1611 void SvxCharEffectsPage::SelectHdl_Impl(const weld::ComboBox* pBox)
1612 {
1613 if (m_xEmphasisLB.get() == pBox)
1614 {
1615 auto nEPos = m_xEmphasisLB->get_active();
1616 bool bEnable = nEPos > 0;
1617 m_xPositionFT->set_sensitive( bEnable );
1618 m_xPositionLB->set_sensitive( bEnable );
1619 }
1620 else if (m_xReliefLB.get() == pBox)
1621 {
1622 bool bEnable = ( pBox->get_active() == 0 );
1623 m_xOutlineBtn->set_sensitive( bEnable );
1624 m_xShadowBtn->set_sensitive( bEnable );
1625 }
1626 else if (m_xPositionLB.get() != pBox)
1627 {
1628 auto nUPos = m_xUnderlineLB->get_active();
1629 bool bUEnable = nUPos > 0;
1630 m_xUnderlineColorFT->set_sensitive(bUEnable);
1631 m_xUnderlineColorLB->set_sensitive(bUEnable);
1632
1633 auto nOPos = m_xOverlineLB->get_active();
1634 bool bOEnable = nOPos > 0;
1635 m_xOverlineColorFT->set_sensitive(bOEnable);
1636 m_xOverlineColorLB->set_sensitive(bOEnable);
1637
1638 auto nSPos = m_xStrikeoutLB->get_active();
1639 m_xIndividualWordsBtn->set_sensitive( bUEnable || bOEnable || nSPos > 0);
1640 }
1641 UpdatePreview_Impl();
1642 }
1643
IMPL_LINK_NOARG(SvxCharEffectsPage,CbClickHdl_Impl,weld::Toggleable &,void)1644 IMPL_LINK_NOARG(SvxCharEffectsPage, CbClickHdl_Impl, weld::Toggleable&, void)
1645 {
1646 m_aIndividualWordsState.CheckButtonToggled(*m_xIndividualWordsBtn);
1647 UpdatePreview_Impl();
1648 UpdatePreview_Impl();
1649 }
1650
IMPL_LINK(SvxCharEffectsPage,ColorBoxSelectHdl_Impl,ColorListBox &,rBox,void)1651 IMPL_LINK(SvxCharEffectsPage, ColorBoxSelectHdl_Impl, ColorListBox&, rBox, void)
1652 {
1653 if (m_xFontColorLB.get() == &rBox)
1654 m_bNewFontColor = true;
1655 UpdatePreview_Impl();
1656 }
1657
IMPL_LINK_NOARG(SvxCharEffectsPage,ModifyFontTransparencyHdl_Impl,weld::MetricSpinButton &,void)1658 IMPL_LINK_NOARG(SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl, weld::MetricSpinButton&, void)
1659 {
1660 m_bNewFontColor = true;
1661 }
1662
DeactivatePage(SfxItemSet * _pSet)1663 DeactivateRC SvxCharEffectsPage::DeactivatePage( SfxItemSet* _pSet )
1664 {
1665 if ( _pSet )
1666 FillItemSet( _pSet );
1667 return DeactivateRC::LeavePage;
1668 }
1669
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)1670 std::unique_ptr<SfxTabPage> SvxCharEffectsPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
1671 {
1672 return std::make_unique<SvxCharEffectsPage>( pPage, pController, *rSet );
1673 }
1674
Reset(const SfxItemSet * rSet)1675 void SvxCharEffectsPage::Reset( const SfxItemSet* rSet )
1676 {
1677 SvxFont& rFont = GetPreviewFont();
1678 SvxFont& rCJKFont = GetPreviewCJKFont();
1679 SvxFont& rCTLFont = GetPreviewCTLFont();
1680
1681 bool bEnable = false;
1682
1683 // Underline
1684 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE );
1685 rFont.SetUnderline( LINESTYLE_NONE );
1686 rCJKFont.SetUnderline( LINESTYLE_NONE );
1687 rCTLFont.SetUnderline( LINESTYLE_NONE );
1688
1689 m_xUnderlineLB->set_active( 0 );
1690 SfxItemState eState = rSet->GetItemState( nWhich );
1691
1692 if ( eState >= SfxItemState::INVALID )
1693 {
1694 if ( eState == SfxItemState::INVALID )
1695 m_xUnderlineLB->set_active(-1);
1696 else
1697 {
1698 const SvxUnderlineItem& rItem = static_cast<const SvxUnderlineItem&>(rSet->Get( nWhich ));
1699 FontLineStyle eUnderline = rItem.GetValue();
1700 rFont.SetUnderline( eUnderline );
1701 rCJKFont.SetUnderline( eUnderline );
1702 rCTLFont.SetUnderline( eUnderline );
1703
1704 if ( eUnderline != LINESTYLE_NONE )
1705 {
1706 auto nPos = m_xUnderlineLB->find_id(OUString::number(eUnderline));
1707 if (nPos != -1)
1708 {
1709 m_xUnderlineLB->set_active(nPos);
1710 bEnable = true;
1711 }
1712 Color aColor = rItem.GetColor();
1713 m_xUnderlineColorLB->SelectEntry(aColor);
1714 }
1715 else
1716 {
1717 m_xUnderlineColorLB->SelectEntry(COL_AUTO);
1718 m_xUnderlineColorLB->set_sensitive(false);
1719 }
1720 }
1721 }
1722
1723 // Overline
1724 nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE );
1725 rFont.SetOverline( LINESTYLE_NONE );
1726 rCJKFont.SetOverline( LINESTYLE_NONE );
1727 rCTLFont.SetOverline( LINESTYLE_NONE );
1728
1729 m_xOverlineLB->set_active( 0 );
1730 eState = rSet->GetItemState( nWhich );
1731
1732 if ( eState >= SfxItemState::INVALID )
1733 {
1734 if ( eState == SfxItemState::INVALID )
1735 m_xOverlineLB->set_active(-1);
1736 else
1737 {
1738 const SvxOverlineItem& rItem = static_cast<const SvxOverlineItem&>(rSet->Get( nWhich ));
1739 FontLineStyle eOverline = rItem.GetValue();
1740 rFont.SetOverline( eOverline );
1741 rCJKFont.SetOverline( eOverline );
1742 rCTLFont.SetOverline( eOverline );
1743
1744 if ( eOverline != LINESTYLE_NONE )
1745 {
1746 auto nPos = m_xOverlineLB->find_id(OUString::number(eOverline));
1747 if (nPos != -1)
1748 {
1749 m_xOverlineLB->set_active(nPos);
1750 bEnable = true;
1751 }
1752 Color aColor = rItem.GetColor();
1753 m_xOverlineColorLB->SelectEntry(aColor);
1754 }
1755 else
1756 {
1757 m_xOverlineColorLB->SelectEntry(COL_AUTO);
1758 m_xOverlineColorLB->set_sensitive(false);
1759 }
1760 }
1761 }
1762
1763 // Strikeout
1764 nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT );
1765 rFont.SetStrikeout( STRIKEOUT_NONE );
1766 rCJKFont.SetStrikeout( STRIKEOUT_NONE );
1767 rCTLFont.SetStrikeout( STRIKEOUT_NONE );
1768
1769 m_xStrikeoutLB->set_active( 0 );
1770 eState = rSet->GetItemState( nWhich );
1771
1772 if ( eState >= SfxItemState::INVALID )
1773 {
1774 if ( eState == SfxItemState::INVALID )
1775 m_xStrikeoutLB->set_active(-1);
1776 else
1777 {
1778 const SvxCrossedOutItem& rItem = static_cast<const SvxCrossedOutItem&>(rSet->Get( nWhich ));
1779 FontStrikeout eStrikeout = rItem.GetValue();
1780 rFont.SetStrikeout( eStrikeout );
1781 rCJKFont.SetStrikeout( eStrikeout );
1782 rCTLFont.SetStrikeout( eStrikeout );
1783
1784 if ( eStrikeout != STRIKEOUT_NONE )
1785 {
1786 auto nPos = m_xStrikeoutLB->find_id(OUString::number(eStrikeout));
1787 if (nPos != -1)
1788 {
1789 m_xStrikeoutLB->set_active(nPos);
1790 bEnable = true;
1791 }
1792 }
1793 }
1794 }
1795
1796 // WordLineMode
1797 nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE );
1798 eState = rSet->GetItemState( nWhich );
1799
1800 switch ( eState )
1801 {
1802 case SfxItemState::UNKNOWN:
1803 m_aIndividualWordsState.bTriStateEnabled = false;
1804 m_xIndividualWordsBtn->hide();
1805 break;
1806
1807 case SfxItemState::DISABLED:
1808 m_aIndividualWordsState.bTriStateEnabled = false;
1809 m_xIndividualWordsBtn->set_sensitive(false);
1810 break;
1811
1812 case SfxItemState::INVALID:
1813 m_aIndividualWordsState.bTriStateEnabled = true;
1814 m_xIndividualWordsBtn->set_state( TRISTATE_INDET );
1815 break;
1816
1817 case SfxItemState::DEFAULT:
1818 case SfxItemState::SET:
1819 {
1820 const SvxWordLineModeItem& rItem = static_cast<const SvxWordLineModeItem&>(rSet->Get( nWhich ));
1821 rFont.SetWordLineMode( rItem.GetValue() );
1822 rCJKFont.SetWordLineMode( rItem.GetValue() );
1823 rCTLFont.SetWordLineMode( rItem.GetValue() );
1824
1825 m_aIndividualWordsState.bTriStateEnabled = false;
1826 m_xIndividualWordsBtn->set_active(rItem.GetValue());
1827 m_xIndividualWordsBtn->set_sensitive(bEnable);
1828 break;
1829 }
1830 }
1831
1832 // Emphasis
1833 nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK );
1834 eState = rSet->GetItemState( nWhich );
1835
1836 if ( eState >= SfxItemState::DEFAULT )
1837 {
1838 const SvxEmphasisMarkItem& rItem = static_cast<const SvxEmphasisMarkItem&>(rSet->Get( nWhich ));
1839 FontEmphasisMark eMark = rItem.GetEmphasisMark();
1840 rFont.SetEmphasisMark( eMark );
1841 rCJKFont.SetEmphasisMark( eMark );
1842 rCTLFont.SetEmphasisMark( eMark );
1843
1844 m_xEmphasisLB->set_active( static_cast<sal_Int32>(FontEmphasisMark( eMark & FontEmphasisMark::Style )) );
1845 eMark &= ~FontEmphasisMark::Style;
1846 int nEntryData = ( eMark == FontEmphasisMark::PosAbove )
1847 ? CHRDLG_POSITION_OVER
1848 : ( eMark == FontEmphasisMark::PosBelow ) ? CHRDLG_POSITION_UNDER : 0;
1849
1850 auto nPos = m_xPositionLB->find_id(OUString::number(nEntryData));
1851 if (nPos != -1)
1852 m_xPositionLB->set_active(nPos);
1853 }
1854 else if ( eState == SfxItemState::INVALID )
1855 m_xEmphasisLB->set_active(-1);
1856 else if ( eState == SfxItemState::UNKNOWN )
1857 {
1858 m_xEmphasisFT->hide();
1859 m_xEmphasisLB->hide();
1860 }
1861 else // SfxItemState::DISABLED
1862 {
1863 m_xEmphasisFT->set_sensitive(false);
1864 m_xEmphasisLB->set_sensitive(false);
1865 }
1866
1867 // the select handler for the underline/overline/strikeout list boxes
1868 SelectHdl_Impl(m_xUnderlineLB.get());
1869
1870 // the select handler for the emphasis listbox
1871 SelectHdl_Impl(m_xEmphasisLB.get());
1872
1873 // Effects
1874 SvxCaseMap eCaseMap = SvxCaseMap::End;
1875 nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP );
1876 eState = rSet->GetItemState( nWhich );
1877 switch ( eState )
1878 {
1879 case SfxItemState::UNKNOWN:
1880 m_xEffectsFT->hide();
1881 m_xEffectsLB->hide();
1882 break;
1883
1884 case SfxItemState::DISABLED:
1885 m_xEffectsFT->set_sensitive(false);
1886 m_xEffectsLB->set_sensitive(false);
1887 break;
1888
1889 case SfxItemState::INVALID:
1890 m_xEffectsLB->set_active(-1);
1891 break;
1892
1893 case SfxItemState::DEFAULT:
1894 case SfxItemState::SET:
1895 {
1896 const SvxCaseMapItem& rItem = static_cast<const SvxCaseMapItem&>(rSet->Get( nWhich ));
1897 eCaseMap = rItem.GetValue();
1898 break;
1899 }
1900 }
1901 SetCaseMap_Impl( eCaseMap );
1902
1903 //Relief
1904 nWhich = GetWhich(SID_ATTR_CHAR_RELIEF);
1905 eState = rSet->GetItemState( nWhich );
1906 switch ( eState )
1907 {
1908 case SfxItemState::UNKNOWN:
1909 m_xReliefFT->hide();
1910 m_xReliefLB->hide();
1911 break;
1912
1913 case SfxItemState::DISABLED:
1914 m_xReliefFT->set_sensitive(false);
1915 m_xReliefLB->set_sensitive(false);
1916 break;
1917
1918 case SfxItemState::INVALID:
1919 m_xReliefLB->set_active(-1);
1920 break;
1921
1922 case SfxItemState::DEFAULT:
1923 case SfxItemState::SET:
1924 {
1925 const SvxCharReliefItem& rItem = static_cast<const SvxCharReliefItem&>(rSet->Get( nWhich ));
1926 m_xReliefLB->set_active(static_cast<sal_Int32>(rItem.GetValue()));
1927 SelectHdl_Impl(m_xReliefLB.get());
1928 break;
1929 }
1930 }
1931
1932 // Outline
1933 nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR );
1934 eState = rSet->GetItemState( nWhich );
1935 switch ( eState )
1936 {
1937 case SfxItemState::UNKNOWN:
1938 m_aOutlineState.bTriStateEnabled = false;
1939 m_xOutlineBtn->hide();
1940 break;
1941
1942 case SfxItemState::DISABLED:
1943 m_aOutlineState.bTriStateEnabled = false;
1944 m_xOutlineBtn->set_sensitive(false);
1945 break;
1946
1947 case SfxItemState::INVALID:
1948 m_aOutlineState.bTriStateEnabled = true;
1949 m_xOutlineBtn->set_state(TRISTATE_INDET);
1950 break;
1951
1952 case SfxItemState::DEFAULT:
1953 case SfxItemState::SET:
1954 {
1955 const SvxContourItem& rItem = static_cast<const SvxContourItem&>(rSet->Get( nWhich ));
1956 m_aOutlineState.bTriStateEnabled = false;
1957 m_xOutlineBtn->set_state(static_cast<TriState>(rItem.GetValue()));
1958 break;
1959 }
1960 }
1961
1962 // Shadow
1963 nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED );
1964 eState = rSet->GetItemState( nWhich );
1965
1966 switch ( eState )
1967 {
1968 case SfxItemState::UNKNOWN:
1969 m_aShadowState.bTriStateEnabled = false;
1970 m_xShadowBtn->hide();
1971 break;
1972
1973 case SfxItemState::DISABLED:
1974 m_aShadowState.bTriStateEnabled = false;
1975 m_xShadowBtn->set_sensitive(false);
1976 break;
1977
1978 case SfxItemState::INVALID:
1979 m_aShadowState.bTriStateEnabled = true;
1980 m_xShadowBtn->set_state( TRISTATE_INDET );
1981 break;
1982
1983 case SfxItemState::DEFAULT:
1984 case SfxItemState::SET:
1985 {
1986 const SvxShadowedItem& rItem = static_cast<const SvxShadowedItem&>(rSet->Get( nWhich ));
1987 m_aShadowState.bTriStateEnabled = false;
1988 m_xShadowBtn->set_state( static_cast<TriState>(rItem.GetValue()) );
1989 break;
1990 }
1991 }
1992
1993 // Hidden
1994 nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN );
1995 eState = rSet->GetItemState( nWhich );
1996
1997 switch ( eState )
1998 {
1999 case SfxItemState::UNKNOWN:
2000 m_aHiddenState.bTriStateEnabled = false;
2001 m_xHiddenBtn->hide();
2002 break;
2003
2004 case SfxItemState::DISABLED:
2005 m_aHiddenState.bTriStateEnabled = false;
2006 m_xHiddenBtn->set_sensitive(false);
2007 break;
2008
2009 case SfxItemState::INVALID:
2010 m_aHiddenState.bTriStateEnabled = true;
2011 m_xHiddenBtn->set_state(TRISTATE_INDET);
2012 break;
2013
2014 case SfxItemState::DEFAULT:
2015 case SfxItemState::SET:
2016 {
2017 const SvxCharHiddenItem& rItem = static_cast<const SvxCharHiddenItem&>(rSet->Get( nWhich ));
2018 m_aHiddenState.bTriStateEnabled = false;
2019 m_xHiddenBtn->set_state(static_cast<TriState>(rItem.GetValue()));
2020 break;
2021 }
2022 }
2023
2024 SetPrevFontWidthScale( *rSet );
2025 ResetColor_Impl( *rSet );
2026
2027 // preview update
2028 m_aPreviewWin.Invalidate();
2029
2030 // save this settings
2031 ChangesApplied();
2032 }
2033
IMPL_LINK_NOARG(SvxCharEffectsPage,HiddenBtnClickHdl,weld::Toggleable &,void)2034 IMPL_LINK_NOARG(SvxCharEffectsPage, HiddenBtnClickHdl, weld::Toggleable&, void)
2035 {
2036 m_aHiddenState.CheckButtonToggled(*m_xHiddenBtn);
2037 }
2038
IMPL_LINK_NOARG(SvxCharEffectsPage,OutlineBtnClickHdl,weld::Toggleable &,void)2039 IMPL_LINK_NOARG(SvxCharEffectsPage, OutlineBtnClickHdl, weld::Toggleable&, void)
2040 {
2041 m_aOutlineState.CheckButtonToggled(*m_xOutlineBtn);
2042 UpdatePreview_Impl();
2043 }
2044
IMPL_LINK_NOARG(SvxCharEffectsPage,ShadowBtnClickHdl,weld::Toggleable &,void)2045 IMPL_LINK_NOARG(SvxCharEffectsPage, ShadowBtnClickHdl, weld::Toggleable&, void)
2046 {
2047 m_aShadowState.CheckButtonToggled(*m_xShadowBtn);
2048 UpdatePreview_Impl();
2049 }
2050
ChangesApplied()2051 void SvxCharEffectsPage::ChangesApplied()
2052 {
2053 m_xUnderlineLB->save_value();
2054 m_xOverlineLB->save_value();
2055 m_xStrikeoutLB->save_value();
2056 m_xIndividualWordsBtn->save_state();
2057 m_xEmphasisLB->save_value();
2058 m_xPositionLB->save_value();
2059 m_xEffectsLB->save_value();
2060 m_xReliefLB->save_value();
2061 m_xOutlineBtn->save_state();
2062 m_xShadowBtn->save_state();
2063 m_xHiddenBtn->save_state();
2064 m_xFontTransparencyMtr->save_value();
2065 }
2066
FillItemSet(SfxItemSet * rSet)2067 bool SvxCharEffectsPage::FillItemSet( SfxItemSet* rSet )
2068 {
2069 const SfxPoolItem* pOld = nullptr;
2070 const SfxItemSet& rOldSet = GetItemSet();
2071 bool bModified = false;
2072 bool bChanged = true;
2073
2074 // Underline
2075 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE );
2076 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_UNDERLINE );
2077 auto nPos = m_xUnderlineLB->get_active();
2078 FontLineStyle eUnder = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32());
2079
2080 if ( pOld )
2081 {
2082 //! if there are different underline styles in the selection the
2083 //! item-state in the 'rOldSet' will be invalid. In this case
2084 //! changing the underline style will be allowed if a style is
2085 //! selected in the listbox.
2086 bool bAllowChange = nPos != -1 &&
2087 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2088
2089 const SvxUnderlineItem& rItem = *static_cast<const SvxUnderlineItem*>(pOld);
2090 if (rItem.GetValue() == eUnder &&
2091 (LINESTYLE_NONE == eUnder || (rItem.GetColor() == m_xUnderlineColorLB->GetSelectEntryColor() &&
2092 rItem.getComplexColor() == m_xUnderlineColorLB->GetSelectedEntry().getComplexColor())) &&
2093 !bAllowChange)
2094 {
2095 bChanged = false;
2096 }
2097 }
2098
2099 if ( bChanged )
2100 {
2101 SvxUnderlineItem aNewItem( eUnder, nWhich );
2102 const NamedColor& rNamedColor = m_xUnderlineColorLB->GetSelectedEntry();
2103 aNewItem.SetColor(rNamedColor.m_aColor);
2104 aNewItem.setComplexColor(rNamedColor.getComplexColor());
2105 rSet->Put(aNewItem);
2106 bModified = true;
2107 }
2108 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2109 rSet->InvalidateItem(nWhich);
2110
2111 bChanged = true;
2112
2113 // Overline
2114 nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE );
2115 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_OVERLINE );
2116 nPos = m_xOverlineLB->get_active();
2117 FontLineStyle eOver = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32());
2118
2119 if ( pOld )
2120 {
2121 //! if there are different underline styles in the selection the
2122 //! item-state in the 'rOldSet' will be invalid. In this case
2123 //! changing the underline style will be allowed if a style is
2124 //! selected in the listbox.
2125 bool bAllowChange = nPos != -1 &&
2126 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2127
2128 const SvxOverlineItem& rItem = *static_cast<const SvxOverlineItem*>(pOld);
2129 if (rItem.GetValue() == eOver &&
2130 (LINESTYLE_NONE == eOver || (rItem.GetColor() == m_xOverlineColorLB->GetSelectEntryColor() &&
2131 rItem.getComplexColor() == m_xOverlineColorLB->GetSelectedEntry().getComplexColor())) &&
2132 !bAllowChange)
2133 {
2134 bChanged = false;
2135 }
2136 }
2137
2138 if ( bChanged )
2139 {
2140 SvxOverlineItem aNewItem( eOver, nWhich );
2141 const NamedColor& rNamedColor = m_xOverlineColorLB->GetSelectedEntry();
2142 aNewItem.SetColor(rNamedColor.m_aColor);
2143 aNewItem.setComplexColor(rNamedColor.getComplexColor());
2144 rSet->Put(aNewItem);
2145 bModified = true;
2146 }
2147 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2148 rSet->InvalidateItem(nWhich);
2149
2150 bChanged = true;
2151
2152 // Strikeout
2153 nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT );
2154 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_STRIKEOUT );
2155 nPos = m_xStrikeoutLB->get_active();
2156 FontStrikeout eStrike = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32());
2157
2158 if ( pOld )
2159 {
2160 //! if there are different strikeout styles in the selection the
2161 //! item-state in the 'rOldSet' will be invalid. In this case
2162 //! changing the strikeout style will be allowed if a style is
2163 //! selected in the listbox.
2164 bool bAllowChg = nPos != -1 &&
2165 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2166
2167 const SvxCrossedOutItem& rItem = *static_cast<const SvxCrossedOutItem*>(pOld);
2168 if ( !m_xStrikeoutLB->get_sensitive()
2169 || (rItem.GetValue() == eStrike && !bAllowChg) )
2170 bChanged = false;
2171 }
2172
2173 if ( bChanged )
2174 {
2175 rSet->Put( SvxCrossedOutItem( eStrike, nWhich ) );
2176 bModified = true;
2177 }
2178 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2179 rSet->InvalidateItem(nWhich);
2180
2181 bChanged = true;
2182
2183 // Individual words
2184 const SfxItemSet* pExampleSet = GetDialogExampleSet();
2185 nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE );
2186 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_WORDLINEMODE );
2187 TriState eState = m_xIndividualWordsBtn->get_state();
2188 const SfxPoolItem* pItem;
2189
2190 if ( pOld )
2191 {
2192 const SvxWordLineModeItem& rItem = *static_cast<const SvxWordLineModeItem*>(pOld);
2193 if ( rItem.GetValue() == StateToAttr( eState ) && m_xIndividualWordsBtn->get_saved_state() == eState )
2194 bChanged = false;
2195 }
2196
2197 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2198 !StateToAttr( eState ) && static_cast<const SvxWordLineModeItem*>(pItem)->GetValue() )
2199 bChanged = true;
2200
2201 if ( bChanged && eState != TRISTATE_INDET )
2202 {
2203 rSet->Put( SvxWordLineModeItem( StateToAttr( eState ), nWhich ) );
2204 bModified = true;
2205 }
2206 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2207 rSet->InvalidateItem(nWhich);
2208
2209 bChanged = true;
2210
2211 // Emphasis
2212 nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK );
2213 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_EMPHASISMARK );
2214 int nMarkPos = m_xEmphasisLB->get_active();
2215 OUString sMarkPos = m_xEmphasisLB->get_active_text();
2216 OUString sPosPos = m_xPositionLB->get_active_text();
2217 FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nMarkPos);
2218 if (m_xPositionLB->get_sensitive())
2219 {
2220 eMark |= (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32())
2221 ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove;
2222 }
2223
2224 if ( pOld )
2225 {
2226 if( rOldSet.GetItemState( nWhich ) != SfxItemState::INVALID )
2227 {
2228 const SvxEmphasisMarkItem& rItem = *static_cast<const SvxEmphasisMarkItem*>(pOld);
2229 if ( rItem.GetEmphasisMark() == eMark )
2230 bChanged = false;
2231 }
2232 }
2233
2234 if (rOldSet.GetItemState( nWhich ) == SfxItemState::INVALID &&
2235 m_xEmphasisLB->get_saved_value() == sMarkPos && m_xPositionLB->get_saved_value() == sPosPos)
2236 {
2237 bChanged = false;
2238 }
2239
2240 if (bChanged)
2241 {
2242 rSet->Put( SvxEmphasisMarkItem( eMark, TypedWhichId<SvxEmphasisMarkItem>(nWhich) ) );
2243 bModified = true;
2244 }
2245 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2246 rSet->InvalidateItem(nWhich);
2247
2248 bChanged = true;
2249
2250 // Effects
2251 nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP );
2252 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CASEMAP );
2253 SvxCaseMap eCaseMap = SvxCaseMap::NotMapped;
2254 bool bChecked = false;
2255 auto nCapsPos = m_xEffectsLB->get_active();
2256 if (nCapsPos != -1)
2257 {
2258 eCaseMap = static_cast<SvxCaseMap>(nCapsPos);
2259 bChecked = true;
2260 }
2261
2262 if ( pOld )
2263 {
2264 //! if there are different effect styles in the selection the
2265 //! item-state in the 'rOldSet' will be invalid. In this case
2266 //! changing the effect style will be allowed if a style is
2267 //! selected in the listbox.
2268 bool bAllowChg = nPos != -1 &&
2269 SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich );
2270
2271 const SvxCaseMapItem& rItem = *static_cast<const SvxCaseMapItem*>(pOld);
2272 if ( rItem.GetValue() == eCaseMap && !bAllowChg )
2273 bChanged = false;
2274 }
2275
2276 if ( bChanged && bChecked )
2277 {
2278 rSet->Put( SvxCaseMapItem( eCaseMap, nWhich ) );
2279 bModified = true;
2280 }
2281 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2282 rSet->InvalidateItem(nWhich);
2283
2284 bChanged = true;
2285
2286 //Relief
2287 nWhich = GetWhich(SID_ATTR_CHAR_RELIEF);
2288 if (m_xReliefLB->get_value_changed_from_saved())
2289 {
2290 m_xReliefLB->save_value();
2291 SvxCharReliefItem aRelief(static_cast<FontRelief>(m_xReliefLB->get_active()), nWhich);
2292 rSet->Put(aRelief);
2293 }
2294
2295 // Outline
2296 nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR );
2297 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CONTOUR );
2298 eState = m_xOutlineBtn->get_state();
2299
2300 if ( pOld )
2301 {
2302 const SvxContourItem& rItem = *static_cast<const SvxContourItem*>(pOld);
2303 if ( rItem.GetValue() == StateToAttr( eState ) && m_xOutlineBtn->get_saved_state() == eState )
2304 bChanged = false;
2305 }
2306
2307 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2308 !StateToAttr( eState ) && static_cast<const SvxContourItem*>(pItem)->GetValue() )
2309 bChanged = true;
2310
2311 if ( bChanged && eState != TRISTATE_INDET )
2312 {
2313 rSet->Put( SvxContourItem( StateToAttr( eState ), nWhich ) );
2314 bModified = true;
2315 }
2316 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2317 rSet->InvalidateItem(nWhich);
2318
2319 bChanged = true;
2320
2321 // Shadow
2322 nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED );
2323 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_SHADOWED );
2324 eState = m_xShadowBtn->get_state();
2325
2326 if ( pOld )
2327 {
2328 const SvxShadowedItem& rItem = *static_cast<const SvxShadowedItem*>(pOld);
2329 if ( rItem.GetValue() == StateToAttr( eState ) && m_xShadowBtn->get_saved_state() == eState )
2330 bChanged = false;
2331 }
2332
2333 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2334 !StateToAttr( eState ) && static_cast<const SvxShadowedItem*>(pItem)->GetValue() )
2335 bChanged = true;
2336
2337 if ( bChanged && eState != TRISTATE_INDET )
2338 {
2339 rSet->Put( SvxShadowedItem( StateToAttr( eState ), nWhich ) );
2340 bModified = true;
2341 }
2342 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2343 rSet->InvalidateItem(nWhich);
2344
2345 bChanged = true;
2346
2347 // Hidden
2348 nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN );
2349 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_HIDDEN );
2350 eState = m_xHiddenBtn->get_state();
2351 bChanged = true;
2352
2353 if ( pOld )
2354 {
2355 const SvxCharHiddenItem& rItem = *static_cast<const SvxCharHiddenItem*>(pOld);
2356 if ( rItem.GetValue() == StateToAttr( eState ) && m_xHiddenBtn->get_saved_state() == eState )
2357 bChanged = false;
2358 }
2359
2360 if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
2361 !StateToAttr( eState ) && static_cast<const SvxCharHiddenItem*>(pItem)->GetValue() )
2362 bChanged = true;
2363
2364 if ( bChanged && eState != TRISTATE_INDET )
2365 {
2366 rSet->Put( SvxCharHiddenItem( StateToAttr( eState ), nWhich ) );
2367 bModified = true;
2368 }
2369 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2370 rSet->InvalidateItem(nWhich);
2371
2372 bModified |= FillItemSetColor_Impl( *rSet );
2373
2374 return bModified;
2375 }
2376
DisableControls(sal_uInt16 nDisable)2377 void SvxCharEffectsPage::DisableControls( sal_uInt16 nDisable )
2378 {
2379 if ( ( DISABLE_CASEMAP & nDisable ) == DISABLE_CASEMAP )
2380 {
2381 m_xEffectsFT->set_sensitive(false);
2382 m_xEffectsLB->set_sensitive(false);
2383 }
2384 }
2385
PageCreated(const SfxAllItemSet & aSet)2386 void SvxCharEffectsPage::PageCreated(const SfxAllItemSet& aSet)
2387 {
2388 const SfxUInt16Item* pDisableCtlItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false);
2389 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
2390 if (pDisableCtlItem)
2391 DisableControls(pDisableCtlItem->GetValue());
2392
2393 sal_uInt32 nFlags = pFlagItem ? pFlagItem->GetValue() : 0;
2394 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
2395 // the writer uses SID_ATTR_BRUSH as font background
2396 m_bPreviewBackgroundToCharacter = true;
2397 if ((nFlags & SVX_ENABLE_CHAR_TRANSPARENCY) != SVX_ENABLE_CHAR_TRANSPARENCY)
2398 {
2399 // Only show these in case client code explicitly wants this.
2400 m_xFontTransparencyFT->hide();
2401 m_xFontTransparencyMtr->hide();
2402 }
2403 }
2404
2405 // class SvxCharPositionPage ---------------------------------------------
2406
SvxCharPositionPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rInSet)2407 SvxCharPositionPage::SvxCharPositionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
2408 : SvxCharBasePage(pPage, pController, u"cui/ui/positionpage.ui"_ustr, u"PositionPage"_ustr, rInSet)
2409 , m_nSuperEsc(short(DFLT_ESC_SUPER))
2410 , m_nSubEsc(short(DFLT_ESC_SUB))
2411 , m_nScaleWidthItemSetVal(100)
2412 , m_nScaleWidthInitialVal(100)
2413 , m_nSuperProp(sal_uInt8(DFLT_ESC_PROP))
2414 , m_nSubProp(sal_uInt8(DFLT_ESC_PROP))
2415 , m_xHighPosBtn(m_xBuilder->weld_radio_button(u"superscript"_ustr))
2416 , m_xNormalPosBtn(m_xBuilder->weld_radio_button(u"normal"_ustr))
2417 , m_xLowPosBtn(m_xBuilder->weld_radio_button(u"subscript"_ustr))
2418 , m_xHighLowFT(m_xBuilder->weld_label(u"raiselower"_ustr))
2419 , m_xHighLowMF(m_xBuilder->weld_metric_spin_button(u"raiselowersb"_ustr, FieldUnit::PERCENT))
2420 , m_xHighLowRB(m_xBuilder->weld_check_button(u"automatic"_ustr))
2421 , m_xFontSizeFT(m_xBuilder->weld_label(u"relativefontsize"_ustr))
2422 , m_xFontSizeMF(m_xBuilder->weld_metric_spin_button(u"fontsizesb"_ustr, FieldUnit::PERCENT))
2423 , m_xRotationContainer(m_xBuilder->weld_widget(u"rotationcontainer"_ustr))
2424 , m_xRotationAndScalingFrame(m_xBuilder->weld_frame(u"rotationandscalingframe"_ustr))
2425 , m_x0degRB(m_xBuilder->weld_radio_button(u"0deg"_ustr))
2426 , m_x90degRB(m_xBuilder->weld_radio_button(u"90deg"_ustr))
2427 , m_x270degRB(m_xBuilder->weld_radio_button(u"270deg"_ustr))
2428 , m_xFitToLineCB(m_xBuilder->weld_check_button(u"fittoline"_ustr))
2429 , m_xScaleWidthMF(m_xBuilder->weld_metric_spin_button(u"scalewidthsb"_ustr, FieldUnit::PERCENT))
2430 , m_xKerningMF(m_xBuilder->weld_metric_spin_button(u"kerningsb"_ustr, FieldUnit::POINT))
2431 , m_xPairKerningBtn(m_xBuilder->weld_check_button(u"pairkerning"_ustr))
2432 , m_xNoHyphenationBtn(m_xBuilder->weld_check_button(u"nohyphenation"_ustr))
2433 {
2434 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreviewWin));
2435 #ifdef IOS
2436 m_xPreviewWin->hide();
2437 #endif
2438 Initialize();
2439 }
2440
~SvxCharPositionPage()2441 SvxCharPositionPage::~SvxCharPositionPage()
2442 {
2443 }
2444
2445
Initialize()2446 void SvxCharPositionPage::Initialize()
2447 {
2448 // to handle the changes of the other pages
2449 SetExchangeSupport();
2450
2451 GetPreviewFont().SetFontSize( Size( 0, 240 ) );
2452 GetPreviewCJKFont().SetFontSize( Size( 0, 240 ) );
2453 GetPreviewCTLFont().SetFontSize( Size( 0, 240 ) );
2454
2455 m_xNormalPosBtn->set_active(true);
2456 PositionHdl_Impl(*m_xNormalPosBtn);
2457
2458 Link<weld::Toggleable&,void> aLink2 = LINK(this, SvxCharPositionPage, PositionHdl_Impl);
2459 m_xHighPosBtn->connect_toggled(aLink2);
2460 m_xNormalPosBtn->connect_toggled(aLink2);
2461 m_xLowPosBtn->connect_toggled(aLink2);
2462
2463 aLink2 = LINK( this, SvxCharPositionPage, RotationHdl_Impl );
2464 m_x0degRB->connect_toggled(aLink2);
2465 m_x90degRB->connect_toggled(aLink2);
2466 m_x270degRB->connect_toggled(aLink2);
2467
2468 Link<weld::MetricSpinButton&,void> aLink3 = LINK(this, SvxCharPositionPage, ValueChangedHdl_Impl);
2469 m_xHighLowMF->connect_value_changed(aLink3);
2470 m_xFontSizeMF->connect_value_changed(aLink3);
2471
2472 m_xHighLowRB->connect_toggled(LINK(this, SvxCharPositionPage, AutoPositionHdl_Impl));
2473 m_xFitToLineCB->connect_toggled(LINK(this, SvxCharPositionPage, FitToLineHdl_Impl));
2474 m_xKerningMF->connect_value_changed(LINK(this, SvxCharPositionPage, KerningModifyHdl_Impl));
2475 m_xScaleWidthMF->connect_value_changed(LINK(this, SvxCharPositionPage, ScaleWidthModifyHdl_Impl));
2476 }
2477
UpdatePreview_Impl(sal_uInt8 nProp,sal_uInt8 nEscProp,short nEsc)2478 void SvxCharPositionPage::UpdatePreview_Impl( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
2479 {
2480 SetPrevFontEscapement( nProp, nEscProp, nEsc );
2481 }
2482
2483
SetEscapement_Impl(SvxEscapement nEsc)2484 void SvxCharPositionPage::SetEscapement_Impl( SvxEscapement nEsc )
2485 {
2486 SvxEscapementItem aEscItm( nEsc, SID_ATTR_CHAR_ESCAPEMENT );
2487
2488 if ( SvxEscapement::Superscript == nEsc )
2489 {
2490 aEscItm.SetEsc( m_nSuperEsc );
2491 aEscItm.SetProportionalHeight(m_nSuperProp);
2492 }
2493 else if ( SvxEscapement::Subscript == nEsc )
2494 {
2495 aEscItm.SetEsc( m_nSubEsc );
2496 aEscItm.SetProportionalHeight( m_nSubProp );
2497 }
2498
2499 short nFac = aEscItm.GetEsc() < 0 ? -1 : 1;
2500
2501 m_xHighLowMF->set_value(aEscItm.GetEsc() * nFac, FieldUnit::PERCENT);
2502 m_xFontSizeMF->set_value(aEscItm.GetProportionalHeight(), FieldUnit::PERCENT);
2503
2504 if ( SvxEscapement::Off == nEsc )
2505 {
2506 m_xHighLowFT->set_sensitive(false);
2507 m_xHighLowMF->set_sensitive(false);
2508 m_xFontSizeFT->set_sensitive(false);
2509 m_xFontSizeMF->set_sensitive(false);
2510 m_xHighLowRB->set_sensitive(false);
2511 }
2512 else
2513 {
2514 m_xFontSizeFT->set_sensitive(true);
2515 m_xFontSizeMF->set_sensitive(true);
2516 m_xHighLowRB->set_sensitive(true);
2517
2518 if (!m_xHighLowRB->get_active())
2519 {
2520 m_xHighLowFT->set_sensitive(true);
2521 m_xHighLowMF->set_sensitive(true);
2522 }
2523 else
2524 AutoPositionHdl_Impl(*m_xHighLowRB);
2525 }
2526
2527 UpdatePreview_Impl( 100, aEscItm.GetProportionalHeight(), aEscItm.GetEsc() );
2528 }
2529
2530
IMPL_LINK_NOARG(SvxCharPositionPage,PositionHdl_Impl,weld::Toggleable &,void)2531 IMPL_LINK_NOARG(SvxCharPositionPage, PositionHdl_Impl, weld::Toggleable&, void)
2532 {
2533 SvxEscapement nEsc = SvxEscapement::Off; // also when pBtn == NULL
2534
2535 if (m_xHighPosBtn->get_active())
2536 nEsc = SvxEscapement::Superscript;
2537 else if (m_xLowPosBtn->get_active())
2538 nEsc = SvxEscapement::Subscript;
2539
2540 SetEscapement_Impl( nEsc );
2541 }
2542
IMPL_LINK_NOARG(SvxCharPositionPage,RotationHdl_Impl,weld::Toggleable &,void)2543 IMPL_LINK_NOARG(SvxCharPositionPage, RotationHdl_Impl, weld::Toggleable&, void)
2544 {
2545 bool bEnable = false;
2546 if (m_x90degRB->get_active() || m_x270degRB->get_active())
2547 bEnable = true;
2548 else
2549 OSL_ENSURE(m_x0degRB->get_active(), "unexpected button");
2550 m_xFitToLineCB->set_sensitive(bEnable);
2551 }
2552
FontModifyHdl_Impl()2553 void SvxCharPositionPage::FontModifyHdl_Impl()
2554 {
2555 sal_uInt8 nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
2556 short nEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT));
2557 nEsc *= m_xLowPosBtn->get_active() ? -1 : 1;
2558 UpdatePreview_Impl( 100, nEscProp, nEsc );
2559 }
2560
IMPL_LINK(SvxCharPositionPage,AutoPositionHdl_Impl,weld::Toggleable &,rBox,void)2561 IMPL_LINK(SvxCharPositionPage, AutoPositionHdl_Impl, weld::Toggleable&, rBox, void)
2562 {
2563 if (rBox.get_active())
2564 {
2565 m_xHighLowFT->set_sensitive(false);
2566 m_xHighLowMF->set_sensitive(false);
2567 }
2568 else
2569 PositionHdl_Impl(m_xHighPosBtn->get_active() ? *m_xHighPosBtn
2570 : m_xLowPosBtn->get_active() ? *m_xLowPosBtn
2571 : *m_xNormalPosBtn);
2572 }
2573
IMPL_LINK_NOARG(SvxCharPositionPage,FitToLineHdl_Impl,weld::Toggleable &,void)2574 IMPL_LINK_NOARG(SvxCharPositionPage, FitToLineHdl_Impl, weld::Toggleable&, void)
2575 {
2576 sal_uInt16 nVal = m_nScaleWidthInitialVal;
2577 if (m_xFitToLineCB->get_active())
2578 nVal = m_nScaleWidthItemSetVal;
2579 m_xScaleWidthMF->set_value(nVal, FieldUnit::PERCENT);
2580 m_aPreviewWin.SetFontWidthScale( nVal );
2581 }
2582
IMPL_LINK_NOARG(SvxCharPositionPage,KerningModifyHdl_Impl,weld::MetricSpinButton &,void)2583 IMPL_LINK_NOARG(SvxCharPositionPage, KerningModifyHdl_Impl, weld::MetricSpinButton&, void)
2584 {
2585 tools::Long nVal = static_cast<tools::Long>(m_xKerningMF->get_value(FieldUnit::POINT));
2586 nVal = o3tl::convert(nVal, o3tl::Length::pt, o3tl::Length::twip);
2587
2588 tools::Long nKern = static_cast<short>(m_xKerningMF->denormalize(nVal));
2589
2590 SvxFont& rFont = GetPreviewFont();
2591 SvxFont& rCJKFont = GetPreviewCJKFont();
2592 SvxFont& rCTLFont = GetPreviewCTLFont();
2593
2594 rFont.SetFixKerning( static_cast<short>(nKern) );
2595 rCJKFont.SetFixKerning( static_cast<short>(nKern) );
2596 rCTLFont.SetFixKerning( static_cast<short>(nKern) );
2597 m_aPreviewWin.Invalidate();
2598 }
2599
IMPL_LINK(SvxCharPositionPage,ValueChangedHdl_Impl,weld::MetricSpinButton &,rField,void)2600 IMPL_LINK(SvxCharPositionPage, ValueChangedHdl_Impl, weld::MetricSpinButton&, rField, void)
2601 {
2602 bool bHigh = m_xHighPosBtn->get_active();
2603 bool bLow = m_xLowPosBtn->get_active();
2604 DBG_ASSERT( bHigh || bLow, "normal position is not valid" );
2605
2606 if (m_xHighLowMF.get() == &rField)
2607 {
2608 if ( bLow )
2609 m_nSubEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT)) * -1;
2610 else
2611 m_nSuperEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT));
2612 }
2613 else if (m_xFontSizeMF.get() == &rField)
2614 {
2615 if ( bLow )
2616 m_nSubProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
2617 else
2618 m_nSuperProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT));
2619 }
2620
2621 FontModifyHdl_Impl();
2622 }
2623
IMPL_LINK_NOARG(SvxCharPositionPage,ScaleWidthModifyHdl_Impl,weld::MetricSpinButton &,void)2624 IMPL_LINK_NOARG(SvxCharPositionPage, ScaleWidthModifyHdl_Impl, weld::MetricSpinButton&, void)
2625 {
2626 m_aPreviewWin.SetFontWidthScale(sal_uInt16(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)));
2627 }
2628
DeactivatePage(SfxItemSet * _pSet)2629 DeactivateRC SvxCharPositionPage::DeactivatePage( SfxItemSet* _pSet )
2630 {
2631 if ( _pSet )
2632 FillItemSet( _pSet );
2633 return DeactivateRC::LeavePage;
2634 }
2635
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)2636 std::unique_ptr<SfxTabPage> SvxCharPositionPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
2637 {
2638 return std::make_unique<SvxCharPositionPage>(pPage, pController, *rSet);
2639 }
2640
Reset(const SfxItemSet * rSet)2641 void SvxCharPositionPage::Reset( const SfxItemSet* rSet )
2642 {
2643 OUString sUser = GetUserData();
2644
2645 if ( !sUser.isEmpty() )
2646 {
2647 sal_Int32 nIdx {0};
2648 m_nSuperEsc = static_cast<short>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
2649 m_nSubEsc = static_cast<short>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
2650 m_nSuperProp = static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
2651 m_nSubProp = static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx )));
2652
2653 m_xHighLowMF->set_max(MAX_ESC_POS, FieldUnit::PERCENT);
2654
2655 //fdo#75307 validate all the entries and discard all of them if any are
2656 //out of range
2657 bool bValid = true;
2658 if (m_nSuperEsc < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSuperEsc > m_xHighLowMF->get_max(FieldUnit::PERCENT))
2659 bValid = false;
2660 if (m_nSubEsc*-1 < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSubEsc*-1 > m_xHighLowMF->get_max(FieldUnit::PERCENT))
2661 bValid = false;
2662 if (m_nSuperProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSuperProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT))
2663 bValid = false;
2664 if (m_nSubProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSubProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT))
2665 bValid = false;
2666
2667 if (!bValid)
2668 {
2669 m_nSuperEsc = DFLT_ESC_SUPER;
2670 m_nSubEsc = DFLT_ESC_SUB;
2671 m_nSuperProp = DFLT_ESC_PROP;
2672 m_nSubProp = DFLT_ESC_PROP;
2673 }
2674 }
2675
2676 short nEsc = 0;
2677 sal_uInt8 nEscProp = 100;
2678
2679 m_xHighLowFT->set_sensitive(false);
2680 m_xHighLowMF->set_sensitive(false);
2681 m_xFontSizeFT->set_sensitive(false);
2682 m_xFontSizeMF->set_sensitive(false);
2683
2684 SvxFont& rFont = GetPreviewFont();
2685 SvxFont& rCJKFont = GetPreviewCJKFont();
2686 SvxFont& rCTLFont = GetPreviewCTLFont();
2687 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT );
2688
2689 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2690 {
2691 const SvxEscapementItem& rItem = static_cast<const SvxEscapementItem&>(rSet->Get( nWhich ));
2692 nEsc = rItem.GetEsc();
2693 nEscProp = rItem.GetProportionalHeight();
2694
2695 if ( nEsc != 0 )
2696 {
2697 m_xHighLowFT->set_sensitive(true);
2698 m_xHighLowMF->set_sensitive(true);
2699 m_xFontSizeFT->set_sensitive(true);
2700 m_xFontSizeMF->set_sensitive(true);
2701
2702 short nFac;
2703 bool bAutomatic(false);
2704
2705 if ( nEsc > 0 )
2706 {
2707 nFac = 1;
2708 m_xHighPosBtn->set_active(true);
2709 if ( nEsc == DFLT_ESC_AUTO_SUPER )
2710 {
2711 nEsc = .8 * (100 - nEscProp); //approximation of actual percentage used
2712 bAutomatic = true;
2713 }
2714 }
2715 else
2716 {
2717 nFac = -1;
2718 m_xLowPosBtn->set_active(true);
2719 if ( nEsc == DFLT_ESC_AUTO_SUB )
2720 {
2721 nEsc = .2 * -(100 - nEscProp); //approximation of actual percentage used
2722 bAutomatic = true;
2723 }
2724 }
2725 if (!m_xHighLowRB->get_sensitive())
2726 {
2727 m_xHighLowRB->set_sensitive(true);
2728 }
2729 m_xHighLowRB->set_active(bAutomatic);
2730
2731 if (m_xHighLowRB->get_active())
2732 {
2733 m_xHighLowFT->set_sensitive(false);
2734 m_xHighLowMF->set_sensitive(false);
2735 }
2736 m_xHighLowMF->set_value(m_xHighLowMF->normalize(nFac * nEsc), FieldUnit::PERCENT);
2737 }
2738 else
2739 {
2740 m_xNormalPosBtn->set_active(true);
2741 m_xHighLowRB->set_active(true);
2742 PositionHdl_Impl(*m_xNormalPosBtn);
2743 }
2744 //the height has to be set after the handler is called to keep the value also if the escapement is zero
2745 m_xFontSizeMF->set_value(m_xFontSizeMF->normalize(nEscProp), FieldUnit::PERCENT);
2746 }
2747 else
2748 {
2749 m_xHighPosBtn->set_active(false);
2750 m_xNormalPosBtn->set_active(false);
2751 m_xLowPosBtn->set_active(false);
2752
2753 m_xHighLowRB->set_active(true);
2754 }
2755
2756 // set BspFont
2757 SetPrevFontEscapement( 100, nEscProp, nEsc );
2758
2759 // Kerning
2760 nWhich = GetWhich( SID_ATTR_CHAR_KERNING );
2761
2762 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2763 {
2764 const SvxKerningItem& rItem = static_cast<const SvxKerningItem&>(rSet->Get( nWhich ));
2765 MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich );
2766 tools::Long nBig = static_cast<tools::Long>(m_xKerningMF->normalize( static_cast<tools::Long>(rItem.GetValue()) ));
2767 tools::Long nKerning = OutputDevice::LogicToLogic(nBig, eUnit, MapUnit::MapPoint);
2768
2769 // set Kerning at the Font, convert into Twips before
2770 tools::Long nKern = OutputDevice::LogicToLogic(rItem.GetValue(), eUnit, MapUnit::MapTwip);
2771 rFont.SetFixKerning( static_cast<short>(nKern) );
2772 rCJKFont.SetFixKerning( static_cast<short>(nKern) );
2773 rCTLFont.SetFixKerning( static_cast<short>(nKern) );
2774
2775 //the attribute value must be displayed also if it's above/below the maximum allowed value
2776 tools::Long nVal = static_cast<tools::Long>(m_xKerningMF->get_max(FieldUnit::POINT));
2777 if(nVal < nKerning)
2778 m_xKerningMF->set_max(nKerning, FieldUnit::POINT);
2779 nVal = static_cast<tools::Long>(m_xKerningMF->get_min(FieldUnit::POINT));
2780 if (nVal > nKerning)
2781 m_xKerningMF->set_min(nKerning, FieldUnit::POINT);
2782 m_xKerningMF->set_value(nKerning, FieldUnit::POINT);
2783 }
2784 else
2785 m_xKerningMF->set_text(OUString());
2786
2787 // Pair kerning
2788 nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN );
2789
2790 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2791 {
2792 const SvxAutoKernItem& rItem = static_cast<const SvxAutoKernItem&>(rSet->Get( nWhich ));
2793 m_xPairKerningBtn->set_active(rItem.GetValue());
2794 }
2795 else
2796 m_xPairKerningBtn->set_active(false);
2797
2798 // No hyphenation
2799 nWhich = GetWhich( sal_uInt16(19) ); // number borrowed from RES_CHRATR_NOHYPHEN
2800 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2801 {
2802 const SvxNoHyphenItem& rItem = static_cast<const SvxNoHyphenItem&>(rSet->Get( nWhich ));
2803 m_xNoHyphenationBtn->set_active(rItem.GetValue());
2804 }
2805 else
2806 m_xNoHyphenationBtn->set_active(false);
2807
2808 // Scale Width
2809 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
2810 if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT )
2811 {
2812 const SvxCharScaleWidthItem& rItem = static_cast<const SvxCharScaleWidthItem&>( rSet->Get( nWhich ) );
2813 m_nScaleWidthInitialVal = rItem.GetValue();
2814 m_xScaleWidthMF->set_value(m_nScaleWidthInitialVal, FieldUnit::PERCENT);
2815 }
2816 else
2817 m_xScaleWidthMF->set_value(100, FieldUnit::PERCENT);
2818
2819 if ( rSet->GetItemState( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ) >= SfxItemState::DEFAULT )
2820 m_nScaleWidthItemSetVal = rSet->Get( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ).GetValue();
2821
2822 // Rotation
2823 nWhich = GetWhich( SID_ATTR_CHAR_ROTATED );
2824 SfxItemState eState = rSet->GetItemState( nWhich );
2825 if( SfxItemState::UNKNOWN == eState )
2826 {
2827 m_xRotationContainer->hide();
2828 m_xRotationAndScalingFrame->set_label(CuiResId(RID_CUISTR_SCALING));
2829 }
2830 else
2831 {
2832 m_xRotationContainer->show();
2833 m_xRotationAndScalingFrame->set_label(CuiResId(RID_CUISTR_ROTATION_SCALING));
2834
2835 if( eState >= SfxItemState::DEFAULT )
2836 {
2837 const SvxCharRotateItem& rItem =
2838 static_cast<const SvxCharRotateItem&>( rSet->Get( nWhich ));
2839 if (rItem.IsBottomToTop())
2840 m_x90degRB->set_active(true);
2841 else if (rItem.IsTopToBottom())
2842 m_x270degRB->set_active(true);
2843 else
2844 {
2845 DBG_ASSERT( 0_deg10 == rItem.GetValue(), "incorrect value" );
2846 m_x0degRB->set_active(true);
2847 }
2848 m_xFitToLineCB->set_active(rItem.IsFitToLine());
2849 }
2850 else
2851 {
2852 if( eState == SfxItemState::INVALID )
2853 {
2854 m_x0degRB->set_active(false);
2855 m_x90degRB->set_active(false);
2856 m_x270degRB->set_active(false);
2857 }
2858 else
2859 m_x0degRB->set_active(true);
2860
2861 m_xFitToLineCB->set_active(false);
2862 }
2863 m_xFitToLineCB->set_sensitive(!m_x0degRB->get_active());
2864
2865 // is this value set?
2866 if( SfxItemState::UNKNOWN == rSet->GetItemState(
2867 SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ))
2868 m_xFitToLineCB->hide();
2869 }
2870 ChangesApplied();
2871 }
2872
ChangesApplied()2873 void SvxCharPositionPage::ChangesApplied()
2874 {
2875 m_xHighPosBtn->save_state();
2876 m_xNormalPosBtn->save_state();
2877 m_xLowPosBtn->save_state();
2878 m_xHighLowRB->save_state();
2879 m_x0degRB->save_state();
2880 m_x90degRB->save_state();
2881 m_x270degRB->save_state();
2882 m_xFitToLineCB->save_state();
2883 m_xScaleWidthMF->save_value();
2884 m_xKerningMF->save_value();
2885 m_xPairKerningBtn->save_state();
2886 m_xNoHyphenationBtn->save_state();
2887 }
2888
FillItemSet(SfxItemSet * rSet)2889 bool SvxCharPositionPage::FillItemSet( SfxItemSet* rSet )
2890 {
2891 // Position (high, normal or low)
2892 const SfxItemSet& rOldSet = GetItemSet();
2893 bool bModified = false, bChanged = true;
2894 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT );
2895 const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_ESCAPEMENT );
2896 const bool bHigh = m_xHighPosBtn->get_active();
2897 short nEsc;
2898 sal_uInt8 nEscProp;
2899
2900 if (bHigh || m_xLowPosBtn->get_active())
2901 {
2902 if (m_xHighLowRB->get_active())
2903 nEsc = bHigh ? DFLT_ESC_AUTO_SUPER : DFLT_ESC_AUTO_SUB;
2904 else
2905 {
2906 nEsc = static_cast<short>(m_xHighLowMF->denormalize(m_xHighLowMF->get_value(FieldUnit::PERCENT)));
2907 nEsc *= (bHigh ? 1 : -1);
2908 }
2909 nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->denormalize(m_xFontSizeMF->get_value(FieldUnit::PERCENT)));
2910 }
2911 else
2912 {
2913 nEsc = 0;
2914 nEscProp = 100;
2915 }
2916
2917 if ( pOld )
2918 {
2919 const SvxEscapementItem& rItem = *static_cast<const SvxEscapementItem*>(pOld);
2920 if (rItem.GetEsc() == nEsc && rItem.GetProportionalHeight() == nEscProp)
2921 bChanged = false;
2922 }
2923
2924 if ( !bChanged && !m_xHighPosBtn->get_saved_state() &&
2925 !m_xNormalPosBtn->get_saved_state() && !m_xLowPosBtn->get_saved_state() )
2926 bChanged = true;
2927
2928 if ( bChanged &&
2929 ( m_xHighPosBtn->get_active() || m_xNormalPosBtn->get_active() || m_xLowPosBtn->get_active() ) )
2930 {
2931 rSet->Put( SvxEscapementItem( nEsc, nEscProp, nWhich ) );
2932 bModified = true;
2933 }
2934 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2935 rSet->InvalidateItem(nWhich);
2936
2937 bChanged = true;
2938
2939 // Kerning
2940 nWhich = GetWhich( SID_ATTR_CHAR_KERNING );
2941 pOld = GetOldItem( *rSet, SID_ATTR_CHAR_KERNING );
2942 short nKerning = 0;
2943 MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich );
2944
2945 tools::Long nTmp = static_cast<tools::Long>(m_xKerningMF->get_value(FieldUnit::POINT));
2946 tools::Long nVal = OutputDevice::LogicToLogic(nTmp, MapUnit::MapPoint, eUnit);
2947 nKerning = static_cast<short>(m_xKerningMF->denormalize( nVal ));
2948
2949 SfxItemState eOldKernState = rOldSet.GetItemState( nWhich, false );
2950 if ( pOld )
2951 {
2952 const SvxKerningItem& rItem = *static_cast<const SvxKerningItem*>(pOld);
2953 if ( (eOldKernState >= SfxItemState::DEFAULT || m_xKerningMF->get_text().isEmpty()) && rItem.GetValue() == nKerning )
2954 bChanged = false;
2955 }
2956
2957 if ( bChanged )
2958 {
2959 rSet->Put( SvxKerningItem( nKerning, nWhich ) );
2960 bModified = true;
2961 }
2962 else if ( SfxItemState::DEFAULT == eOldKernState )
2963 rSet->InvalidateItem(nWhich);
2964
2965 // Pair-Kerning
2966 nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN );
2967
2968 if (m_xPairKerningBtn->get_state_changed_from_saved())
2969 {
2970 rSet->Put( SvxAutoKernItem( m_xPairKerningBtn->get_active(), nWhich ) );
2971 bModified = true;
2972 }
2973 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2974 rSet->InvalidateItem(nWhich);
2975
2976 // No hyphenation
2977
2978 nWhich = GetWhich( sal_uInt16(19) ); // number borrowed from RES_CHRATR_NOHYPHEN
2979
2980 if (m_xNoHyphenationBtn->get_state_changed_from_saved())
2981 {
2982 rSet->Put( SvxNoHyphenItem( m_xNoHyphenationBtn->get_active(), nWhich ) );
2983 bModified = true;
2984 }
2985 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2986 rSet->InvalidateItem(nWhich);
2987
2988 // Scale Width
2989 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
2990 if (m_xScaleWidthMF->get_value_changed_from_saved())
2991 {
2992 rSet->Put(SvxCharScaleWidthItem(static_cast<sal_uInt16>(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)), TypedWhichId<SvxCharScaleWidthItem>(nWhich)));
2993 bModified = true;
2994 }
2995 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
2996 rSet->InvalidateItem(nWhich);
2997
2998 // Rotation
2999 nWhich = GetWhich( SID_ATTR_CHAR_ROTATED );
3000 if ( m_x0degRB->get_state_changed_from_saved() ||
3001 m_x90degRB->get_state_changed_from_saved() ||
3002 m_x270degRB->get_state_changed_from_saved() ||
3003 m_xFitToLineCB->get_state_changed_from_saved() )
3004 {
3005 SvxCharRotateItem aItem( 0_deg10, m_xFitToLineCB->get_active(), TypedWhichId<SvxCharRotateItem>(nWhich) );
3006 if (m_x90degRB->get_active())
3007 aItem.SetBottomToTop();
3008 else if (m_x270degRB->get_active())
3009 aItem.SetTopToBottom();
3010 rSet->Put( aItem );
3011 bModified = true;
3012 }
3013 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
3014 rSet->InvalidateItem(nWhich);
3015
3016 return bModified;
3017 }
3018
3019
FillUserData()3020 void SvxCharPositionPage::FillUserData()
3021 {
3022 static constexpr OUString cTok( u";"_ustr );
3023
3024 OUString sUser = OUString::number( m_nSuperEsc ) + cTok +
3025 OUString::number( m_nSubEsc ) + cTok +
3026 OUString::number( m_nSuperProp ) + cTok +
3027 OUString::number( m_nSubProp );
3028 SetUserData( sUser );
3029 }
3030
3031
PageCreated(const SfxAllItemSet & aSet)3032 void SvxCharPositionPage::PageCreated(const SfxAllItemSet& aSet)
3033 {
3034 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
3035 if (pFlagItem)
3036 {
3037 sal_uInt32 nFlags=pFlagItem->GetValue();
3038 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
3039 // the writer uses SID_ATTR_BRUSH as font background
3040 m_bPreviewBackgroundToCharacter = true;
3041 }
3042 }
3043 // class SvxCharTwoLinesPage ------------------------------------------------
3044
SvxCharTwoLinesPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rInSet)3045 SvxCharTwoLinesPage::SvxCharTwoLinesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
3046 : SvxCharBasePage(pPage, pController, u"cui/ui/twolinespage.ui"_ustr, u"TwoLinesPage"_ustr, rInSet)
3047 , m_nStartBracketPosition( 0 )
3048 , m_nEndBracketPosition( 0 )
3049 , m_xTwoLinesBtn(m_xBuilder->weld_check_button(u"twolines"_ustr))
3050 , m_xEnclosingFrame(m_xBuilder->weld_widget(u"enclosing"_ustr))
3051 , m_xStartBracketLB(m_xBuilder->weld_tree_view(u"startbracket"_ustr))
3052 , m_xEndBracketLB(m_xBuilder->weld_tree_view(u"endbracket"_ustr))
3053 {
3054 for (size_t i = 0; i < std::size(TWOLINE_OPEN); ++i)
3055 m_xStartBracketLB->append(OUString::number(TWOLINE_OPEN[i].second), CuiResId(TWOLINE_OPEN[i].first));
3056 for (size_t i = 0; i < std::size(TWOLINE_CLOSE); ++i)
3057 m_xEndBracketLB->append(OUString::number(TWOLINE_CLOSE[i].second), CuiResId(TWOLINE_CLOSE[i].first));
3058
3059 m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreviewWin));
3060 #ifdef IOS
3061 m_xPreviewWin->hide();
3062 #endif
3063 Initialize();
3064 }
3065
~SvxCharTwoLinesPage()3066 SvxCharTwoLinesPage::~SvxCharTwoLinesPage()
3067 {
3068 }
3069
Initialize()3070 void SvxCharTwoLinesPage::Initialize()
3071 {
3072 m_xTwoLinesBtn->set_active(false);
3073 TwoLinesHdl_Impl(*m_xTwoLinesBtn);
3074
3075 m_xTwoLinesBtn->connect_toggled(LINK(this, SvxCharTwoLinesPage, TwoLinesHdl_Impl));
3076
3077 Link<weld::TreeView&,void> aLink = LINK(this, SvxCharTwoLinesPage, CharacterMapHdl_Impl);
3078 m_xStartBracketLB->connect_selection_changed(aLink);
3079 m_xEndBracketLB->connect_selection_changed(aLink);
3080
3081 SvxFont& rFont = GetPreviewFont();
3082 SvxFont& rCJKFont = GetPreviewCJKFont();
3083 SvxFont& rCTLFont = GetPreviewCTLFont();
3084 rFont.SetFontSize( Size( 0, 220 ) );
3085 rCJKFont.SetFontSize( Size( 0, 220 ) );
3086 rCTLFont.SetFontSize( Size( 0, 220 ) );
3087 }
3088
SelectCharacter(weld::TreeView * pBox)3089 void SvxCharTwoLinesPage::SelectCharacter(weld::TreeView* pBox)
3090 {
3091 bool bStart = pBox == m_xStartBracketLB.get();
3092 SvxCharacterMap aDlg(GetFrameWeld(), nullptr, nullptr);
3093 aDlg.DisableFontSelection();
3094
3095 if (aDlg.run() == RET_OK)
3096 {
3097 sal_Unicode cChar = static_cast<sal_Unicode>(aDlg.GetChar());
3098 SetBracket( cChar, bStart );
3099 }
3100 else
3101 {
3102 pBox->select(bStart ? m_nStartBracketPosition : m_nEndBracketPosition);
3103 }
3104 }
3105
3106
SetBracket(sal_Unicode cBracket,bool bStart)3107 void SvxCharTwoLinesPage::SetBracket( sal_Unicode cBracket, bool bStart )
3108 {
3109 int nEntryPos = 0;
3110 weld::TreeView* pBox = bStart ? m_xStartBracketLB.get() : m_xEndBracketLB.get();
3111 if (cBracket == 0)
3112 pBox->select(0);
3113 else
3114 {
3115 bool bFound = false;
3116 for (int i = 1; i < pBox->n_children(); ++i)
3117 {
3118 if (pBox->get_id(i).toInt32() != CHRDLG_ENCLOSE_SPECIAL_CHAR)
3119 {
3120 const sal_Unicode cChar = pBox->get_text(i)[0];
3121 if (cChar == cBracket)
3122 {
3123 pBox->select(i);
3124 nEntryPos = i;
3125 bFound = true;
3126 break;
3127 }
3128 }
3129 }
3130
3131 if (!bFound)
3132 {
3133 pBox->append_text(OUString(cBracket));
3134 nEntryPos = pBox->n_children() - 1;
3135 pBox->select(nEntryPos);
3136 }
3137 }
3138 if (bStart)
3139 m_nStartBracketPosition = nEntryPos;
3140 else
3141 m_nEndBracketPosition = nEntryPos;
3142 }
3143
IMPL_LINK_NOARG(SvxCharTwoLinesPage,TwoLinesHdl_Impl,weld::Toggleable &,void)3144 IMPL_LINK_NOARG(SvxCharTwoLinesPage, TwoLinesHdl_Impl, weld::Toggleable&, void)
3145 {
3146 bool bChecked = m_xTwoLinesBtn->get_active();
3147 m_xEnclosingFrame->set_sensitive(bChecked);
3148 UpdatePreview_Impl();
3149 }
3150
IMPL_LINK(SvxCharTwoLinesPage,CharacterMapHdl_Impl,weld::TreeView &,rBox,void)3151 IMPL_LINK(SvxCharTwoLinesPage, CharacterMapHdl_Impl, weld::TreeView&, rBox, void)
3152 {
3153 int nPos = rBox.get_selected_index();
3154 if (rBox.get_id(nPos).toInt32() == CHRDLG_ENCLOSE_SPECIAL_CHAR)
3155 SelectCharacter( &rBox );
3156 else
3157 {
3158 bool bStart = &rBox == m_xStartBracketLB.get();
3159 if (bStart)
3160 m_nStartBracketPosition = nPos;
3161 else
3162 m_nEndBracketPosition = nPos;
3163 }
3164 UpdatePreview_Impl();
3165 }
3166
ActivatePage(const SfxItemSet & rSet)3167 void SvxCharTwoLinesPage::ActivatePage( const SfxItemSet& rSet )
3168 {
3169 SvxCharBasePage::ActivatePage(rSet);
3170 }
3171
DeactivatePage(SfxItemSet * _pSet)3172 DeactivateRC SvxCharTwoLinesPage::DeactivatePage( SfxItemSet* _pSet )
3173 {
3174 if ( _pSet )
3175 FillItemSet( _pSet );
3176 return DeactivateRC::LeavePage;
3177 }
3178
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)3179 std::unique_ptr<SfxTabPage> SvxCharTwoLinesPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
3180 {
3181 return std::make_unique<SvxCharTwoLinesPage>(pPage, pController, *rSet);
3182 }
3183
Reset(const SfxItemSet * rSet)3184 void SvxCharTwoLinesPage::Reset( const SfxItemSet* rSet )
3185 {
3186 m_xTwoLinesBtn->set_active(false);
3187 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES );
3188 SfxItemState eState = rSet->GetItemState( nWhich );
3189
3190 if ( eState >= SfxItemState::INVALID )
3191 {
3192 const SvxTwoLinesItem& rItem = static_cast<const SvxTwoLinesItem&>(rSet->Get( nWhich ));
3193 m_xTwoLinesBtn->set_active(rItem.GetValue());
3194
3195 if ( rItem.GetValue() )
3196 {
3197 SetBracket( rItem.GetStartBracket(), true );
3198 SetBracket( rItem.GetEndBracket(), false );
3199 }
3200 }
3201 TwoLinesHdl_Impl(*m_xTwoLinesBtn);
3202
3203 SetPrevFontWidthScale( *rSet );
3204 }
3205
FillItemSet(SfxItemSet * rSet)3206 bool SvxCharTwoLinesPage::FillItemSet( SfxItemSet* rSet )
3207 {
3208 const SfxItemSet& rOldSet = GetItemSet();
3209 bool bModified = false, bChanged = true;
3210 sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES );
3211 const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_TWO_LINES );
3212 bool bOn = m_xTwoLinesBtn->get_active();
3213 sal_Unicode cStart = ( bOn && m_xStartBracketLB->get_selected_index() > 0 )
3214 ? m_xStartBracketLB->get_selected_text()[0] : 0;
3215 sal_Unicode cEnd = ( bOn && m_xEndBracketLB->get_selected_index() > 0 )
3216 ? m_xEndBracketLB->get_selected_text()[0] : 0;
3217
3218 if ( pOld )
3219 {
3220 const SvxTwoLinesItem& rItem = *static_cast<const SvxTwoLinesItem*>(pOld);
3221 if ( rItem.GetValue() == bOn &&
3222 ( !bOn || ( rItem.GetStartBracket() == cStart && rItem.GetEndBracket() == cEnd ) ) )
3223 bChanged = false;
3224 }
3225
3226 if ( bChanged )
3227 {
3228 rSet->Put( SvxTwoLinesItem( bOn, cStart, cEnd, nWhich ) );
3229 bModified = true;
3230 }
3231 else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
3232 rSet->InvalidateItem(nWhich);
3233
3234 return bModified;
3235 }
3236
UpdatePreview_Impl()3237 void SvxCharTwoLinesPage::UpdatePreview_Impl()
3238 {
3239 sal_Unicode cStart = m_xStartBracketLB->get_selected_index() > 0
3240 ? m_xStartBracketLB->get_selected_text()[0] : 0;
3241 sal_Unicode cEnd = m_xEndBracketLB->get_selected_index() > 0
3242 ? m_xEndBracketLB->get_selected_text()[0] : 0;
3243 m_aPreviewWin.SetBrackets(cStart, cEnd);
3244 m_aPreviewWin.SetTwoLines(m_xTwoLinesBtn->get_active());
3245 m_aPreviewWin.Invalidate();
3246 }
3247
PageCreated(const SfxAllItemSet & aSet)3248 void SvxCharTwoLinesPage::PageCreated(const SfxAllItemSet& aSet)
3249 {
3250 const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
3251 if (pFlagItem)
3252 {
3253 sal_uInt32 nFlags=pFlagItem->GetValue();
3254 if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
3255 // the writer uses SID_ATTR_BRUSH as font background
3256 m_bPreviewBackgroundToCharacter = true;
3257 }
3258 }
3259
3260 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3261