1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <officecfg/Office/Common.hxx>
23 #include <svtools/ctrltool.hxx>
24 #include <vcl/svapp.hxx>
25 #include <svtools/fontsubstconfig.hxx>
26 #include "fontsubs.hxx"
29 /*********************************************************************/
31 /* TabPage font replacement */
33 /*********************************************************************/
35 SvxFontSubstTabPage::SvxFontSubstTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rSet
)
36 : SfxTabPage(pPage
, pController
, u
"cui/ui/optfontspage.ui"_ustr
, u
"OptFontsPage"_ustr
, &rSet
)
37 , m_xUseTableCB(m_xBuilder
->weld_check_button(u
"usetable"_ustr
))
38 , m_xUseTableImg(m_xBuilder
->weld_widget(u
"lockusetable"_ustr
))
39 , m_xFont1CB(m_xBuilder
->weld_combo_box(u
"font1"_ustr
))
40 , m_xFont2CB(m_xBuilder
->weld_combo_box(u
"font2"_ustr
))
41 , m_xApply(m_xBuilder
->weld_button(u
"apply"_ustr
))
42 , m_xDelete(m_xBuilder
->weld_button(u
"delete"_ustr
))
43 , m_xCheckLB(m_xBuilder
->weld_tree_view(u
"checklb"_ustr
))
44 , m_xFontNameLB(m_xBuilder
->weld_combo_box(u
"fontname"_ustr
))
45 , m_xFontNameLabel(m_xBuilder
->weld_label(u
"label8"_ustr
))
46 , m_xFontNameImg(m_xBuilder
->weld_widget(u
"lockfontname"_ustr
))
47 , m_xNonPropFontsOnlyCB(m_xBuilder
->weld_check_button(u
"nonpropfontonly"_ustr
))
48 , m_xNonPropFontsOnlyImg(m_xBuilder
->weld_widget(u
"locknonpropfontonly"_ustr
))
49 , m_xFontHeightLB(m_xBuilder
->weld_combo_box(u
"fontheight"_ustr
))
50 , m_xFontHeightLabel(m_xBuilder
->weld_label(u
"label9"_ustr
))
51 , m_xFontHeightImg(m_xBuilder
->weld_widget(u
"lockfontheight"_ustr
))
53 m_xFont1CB
->make_sorted();
54 m_xFont1CB
->set_size_request(1, -1);
55 m_xFont2CB
->make_sorted();
56 m_xFont2CB
->set_size_request(1, -1);
57 m_sAutomatic
= m_xFontNameLB
->get_text(0);
58 assert(!m_sAutomatic
.isEmpty());
60 m_xCheckLB
->set_size_request(m_xCheckLB
->get_approximate_digit_width() * 60,
61 m_xCheckLB
->get_height_rows(8));
62 m_xCheckLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
63 m_xCheckLB
->set_help_id(HID_OFA_FONT_SUBST_CLB
);
64 m_xCheckLB
->set_selection_mode(SelectionMode::Multiple
);
66 setColSizes(m_xCheckLB
->get_size_request());
67 m_xCheckLB
->connect_size_allocate(LINK(this, SvxFontSubstTabPage
, ResizeHdl
));
69 m_xCheckLB
->set_centered_column(0);
70 m_xCheckLB
->set_centered_column(1);
72 Link
<weld::ComboBox
&,void> aLink2(LINK(this, SvxFontSubstTabPage
, SelectComboBoxHdl
));
73 Link
<weld::Button
&,void> aClickLink(LINK(this, SvxFontSubstTabPage
, ClickHdl
));
75 m_xCheckLB
->connect_selection_changed(LINK(this, SvxFontSubstTabPage
, TreeListBoxSelectHdl
));
76 m_xCheckLB
->connect_column_clicked(LINK(this, SvxFontSubstTabPage
, HeaderBarClick
));
77 m_xUseTableCB
->connect_toggled(LINK(this, SvxFontSubstTabPage
, ToggleHdl
));
78 m_xFont1CB
->connect_changed(aLink2
);
79 m_xFont2CB
->connect_changed(aLink2
);
80 m_xApply
->connect_clicked(aClickLink
);
81 m_xDelete
->connect_clicked(aClickLink
);
83 m_xNonPropFontsOnlyCB
->connect_toggled(LINK(this, SvxFontSubstTabPage
, NonPropFontsHdl
));
86 for(nHeight
= 6; nHeight
<= 16; nHeight
++)
87 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
88 for(nHeight
= 18; nHeight
<= 28; nHeight
+= 2)
89 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
90 for(nHeight
= 32; nHeight
<= 48; nHeight
+= 4)
91 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
92 for(nHeight
= 54; nHeight
<= 72; nHeight
+= 6)
93 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
94 for(nHeight
= 80; nHeight
<= 96; nHeight
+= 8)
95 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
98 IMPL_LINK(SvxFontSubstTabPage
, HeaderBarClick
, int, nColumn
, void)
100 bool bSortAtoZ
= m_xCheckLB
->get_sort_order();
102 //set new arrow positions in headerbar
103 if (nColumn
== m_xCheckLB
->get_sort_column())
105 bSortAtoZ
= !bSortAtoZ
;
106 m_xCheckLB
->set_sort_order(bSortAtoZ
);
110 m_xCheckLB
->set_sort_indicator(TRISTATE_INDET
, m_xCheckLB
->get_sort_column());
111 m_xCheckLB
->set_sort_column(nColumn
);
117 m_xCheckLB
->set_sort_indicator(bSortAtoZ
? TRISTATE_TRUE
: TRISTATE_FALSE
, nColumn
);
121 void SvxFontSubstTabPage::setColSizes(const Size
& rSize
)
123 int nW1
= m_xCheckLB
->get_pixel_size(m_xCheckLB
->get_column_title(2)).Width();
124 int nW2
= m_xCheckLB
->get_pixel_size(m_xCheckLB
->get_column_title(3)).Width();
125 int nMax
= std::max( nW1
, nW2
) + 6; // width of the longest header + a little offset
126 int nMin
= m_xCheckLB
->get_checkbox_column_width();
127 nMax
= std::max(nMax
, nMin
);
128 const int nDoubleMax
= 2*nMax
;
129 const int nRest
= rSize
.Width() - nDoubleMax
;
130 std::vector
<int> aWidths
{ nMax
, nMax
, nRest
/2 };
131 m_xCheckLB
->set_column_fixed_widths(aWidths
);
134 IMPL_LINK(SvxFontSubstTabPage
, ResizeHdl
, const Size
&, rSize
, void)
139 SvxFontSubstTabPage::~SvxFontSubstTabPage()
143 std::unique_ptr
<SfxTabPage
> SvxFontSubstTabPage::Create( weld::Container
* pPage
, weld::DialogController
* pController
,
144 const SfxItemSet
* rAttrSet
)
146 return std::make_unique
<SvxFontSubstTabPage
>(pPage
, pController
, *rAttrSet
);
149 OUString
SvxFontSubstTabPage::GetAllStrings()
151 OUString sAllStrings
;
152 OUString labels
[] = { u
"label4"_ustr
, u
"label2"_ustr
, u
"label3"_ustr
, u
"label1"_ustr
, u
"label8"_ustr
, u
"label9"_ustr
};
154 for (const auto& label
: labels
)
156 if (const auto pString
= m_xBuilder
->weld_label(label
))
157 sAllStrings
+= pString
->get_label() + " ";
160 OUString checkButton
[] = { u
"usetable"_ustr
, u
"nonpropfontonly"_ustr
};
162 for (const auto& check
: checkButton
)
164 if (const auto pString
= m_xBuilder
->weld_check_button(check
))
165 sAllStrings
+= pString
->get_label() + " ";
168 return sAllStrings
.replaceAll("_", "");
171 bool SvxFontSubstTabPage::FillItemSet( SfxItemSet
* )
173 std::vector
<SubstitutionStruct
> aNewFontSubs
;
175 m_xCheckLB
->all_foreach([this, &aNewFontSubs
](weld::TreeIter
& rIter
) {
176 SubstitutionStruct aAdd
;
177 aAdd
.sFont
= m_xCheckLB
->get_text(rIter
, 2);
178 aAdd
.sReplaceBy
= m_xCheckLB
->get_text(rIter
, 3);
179 aAdd
.bReplaceAlways
= m_xCheckLB
->get_toggle(rIter
, 0);
180 aAdd
.bReplaceOnScreenOnly
= m_xCheckLB
->get_toggle(rIter
, 1);
181 aNewFontSubs
.push_back(aAdd
);
185 svtools::SetFontSubstitutions(m_xUseTableCB
->get_active(), aNewFontSubs
);
186 svtools::ApplyFontSubstitutionsToVcl();
188 std::shared_ptr
< comphelper::ConfigurationChanges
> batch(
189 comphelper::ConfigurationChanges::create());
190 if (m_xFontHeightLB
->get_value_changed_from_saved())
191 officecfg::Office::Common::Font::SourceViewFont::FontHeight::set(
192 static_cast< sal_Int16
>(m_xFontHeightLB
->get_active_text().toInt32()),
194 if (m_xNonPropFontsOnlyCB
->get_state_changed_from_saved())
195 officecfg::Office::Common::Font::SourceViewFont::
196 NonProportionalFontsOnly::set(
197 m_xNonPropFontsOnlyCB
->get_active(), batch
);
198 //font name changes cannot be detected by saved values
200 if (m_xFontNameLB
->get_active() != -1)
201 sFontName
= m_xFontNameLB
->get_active_text();
202 officecfg::Office::Common::Font::SourceViewFont::FontName::set(
203 std::optional
< OUString
>(sFontName
), batch
);
209 void SvxFontSubstTabPage::Reset( const SfxItemSet
* )
211 m_xCheckLB
->freeze();
214 m_xFont1CB
->freeze();
216 m_xFont2CB
->freeze();
219 FontList
aFntLst(Application::GetDefaultDevice());
220 sal_uInt16 nFontCount
= aFntLst
.GetFontNameCount();
221 for (sal_uInt16 i
= 0; i
< nFontCount
; ++i
)
223 const FontMetric
& rFontMetric
= aFntLst
.GetFontName(i
);
224 m_xFont1CB
->append_text(rFontMetric
.GetFamilyName());
225 m_xFont2CB
->append_text(rFontMetric
.GetFamilyName());
231 bool bEnable
= !officecfg::Office::Common::Font::Substitution::Replacement::isReadOnly();
232 m_xUseTableCB
->set_active(svtools::IsFontSubstitutionsEnabled());
233 m_xUseTableCB
->set_sensitive(bEnable
);
234 m_xUseTableImg
->set_visible(!bEnable
);
236 std::vector
<SubstitutionStruct
> aFontSubs
= svtools::GetFontSubstitutions();
237 std::unique_ptr
<weld::TreeIter
> xIter(m_xCheckLB
->make_iterator());
238 for (auto const & sub
: aFontSubs
)
240 m_xCheckLB
->append(xIter
.get());
241 m_xCheckLB
->set_toggle(*xIter
, sub
.bReplaceAlways
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
242 m_xCheckLB
->set_toggle(*xIter
, sub
.bReplaceOnScreenOnly
? TRISTATE_TRUE
: TRISTATE_FALSE
, 1);
243 m_xCheckLB
->set_text(*xIter
, sub
.sFont
, 2);
244 m_xCheckLB
->set_text(*xIter
, sub
.sReplaceBy
, 3);
249 m_xCheckLB
->make_sorted();
250 m_xCheckLB
->set_sort_column(2);
251 m_xCheckLB
->set_sort_indicator(TRISTATE_TRUE
, 2);
253 SelectHdl(m_xFont1CB
.get());
255 //fill font name box first
256 m_xNonPropFontsOnlyCB
->set_active(
257 officecfg::Office::Common::Font::SourceViewFont::
258 NonProportionalFontsOnly::get());
259 NonPropFontsHdl(*m_xNonPropFontsOnlyCB
);
261 officecfg::Office::Common::Font::SourceViewFont::FontName::get().
262 value_or(OUString()));
263 if(!sFontName
.isEmpty())
264 m_xFontNameLB
->set_active_text(sFontName
);
266 m_xFontNameLB
->set_active(0);
267 m_xFontHeightLB
->set_active_text(
269 officecfg::Office::Common::Font::SourceViewFont::FontHeight::
272 bEnable
= !officecfg::Office::Common::Font::SourceViewFont::FontName::isReadOnly();
273 m_xFontNameLB
->set_sensitive(bEnable
);
274 m_xFontNameLabel
->set_sensitive(bEnable
);
275 m_xFontNameImg
->set_visible(!bEnable
);
277 m_xNonPropFontsOnlyCB
->set_sensitive(bEnable
);
278 m_xNonPropFontsOnlyImg
->set_visible(!bEnable
);
280 m_xFontHeightLB
->set_sensitive(bEnable
);
281 m_xFontHeightLabel
->set_sensitive(bEnable
);
282 m_xFontHeightImg
->set_visible(!bEnable
);
284 m_xNonPropFontsOnlyCB
->save_state();
285 m_xFontHeightLB
->save_value();
288 IMPL_LINK(SvxFontSubstTabPage
, ToggleHdl
, weld::Toggleable
&, rButton
, void)
293 IMPL_LINK(SvxFontSubstTabPage
, ClickHdl
, weld::Button
&, rButton
, void)
298 IMPL_LINK(SvxFontSubstTabPage
, TreeListBoxSelectHdl
, weld::TreeView
&, rButton
, void)
303 IMPL_LINK(SvxFontSubstTabPage
, SelectComboBoxHdl
, weld::ComboBox
&, rBox
, void)
310 // search in the "font" column
311 int findText(const weld::TreeView
& rTreeView
, std::u16string_view rCol
)
313 for (int i
= 0, nEntryCount
= rTreeView
.n_children(); i
< nEntryCount
; ++i
)
315 if (rTreeView
.get_text(i
, 2) == rCol
)
321 bool findRow(const weld::TreeView
& rTreeView
, std::u16string_view rCol1
, std::u16string_view rCol2
)
323 int nRow
= findText(rTreeView
, rCol1
);
326 return rTreeView
.get_text(nRow
, 3) == rCol2
;
330 void SvxFontSubstTabPage::SelectHdl(const weld::Widget
* pWin
)
332 if (pWin
== m_xApply
.get() || pWin
== m_xDelete
.get())
334 int nPos
= findText(*m_xCheckLB
, m_xFont1CB
->get_active_text());
335 if (pWin
== m_xApply
.get())
337 m_xCheckLB
->unselect_all();
341 m_xCheckLB
->set_text(nPos
, m_xFont2CB
->get_active_text(), 3);
342 m_xCheckLB
->select(nPos
);
347 OUString sFont1
= m_xFont1CB
->get_active_text();
348 OUString sFont2
= m_xFont2CB
->get_active_text();
350 std::unique_ptr
<weld::TreeIter
> xIter(m_xCheckLB
->make_iterator());
351 m_xCheckLB
->append(xIter
.get());
352 m_xCheckLB
->set_toggle(*xIter
, TRISTATE_FALSE
, 0);
353 m_xCheckLB
->set_toggle(*xIter
, TRISTATE_FALSE
, 1);
354 m_xCheckLB
->set_text(*xIter
, sFont1
, 2);
355 m_xCheckLB
->set_text(*xIter
, sFont2
, 3);
356 m_xCheckLB
->select(*xIter
);
359 else if (pWin
== m_xDelete
.get())
361 m_xCheckLB
->remove_selection();
365 if (pWin
== m_xCheckLB
.get())
367 const int nSelectedRowCount
= m_xCheckLB
->count_selected_rows();
368 if (nSelectedRowCount
== 1)
370 int nRow
= m_xCheckLB
->get_selected_index();
371 m_xFont1CB
->set_entry_text(m_xCheckLB
->get_text(nRow
, 2));
372 m_xFont2CB
->set_entry_text(m_xCheckLB
->get_text(nRow
, 3));
374 else if (nSelectedRowCount
> 1)
376 m_xFont1CB
->set_entry_text(OUString());
377 m_xFont2CB
->set_entry_text(OUString());
381 if (pWin
== m_xFont1CB
.get())
383 int nPos
= findText(*m_xCheckLB
, m_xFont1CB
->get_active_text());
387 int nSelectedRow
= m_xCheckLB
->get_selected_index();
388 if (nPos
!= nSelectedRow
)
390 m_xCheckLB
->unselect_all();
391 m_xCheckLB
->select(nPos
);
395 m_xCheckLB
->unselect_all();
401 IMPL_LINK(SvxFontSubstTabPage
, NonPropFontsHdl
, weld::Toggleable
&, rBox
, void)
403 OUString sFontName
= m_xFontNameLB
->get_active_text();
404 bool bNonPropOnly
= rBox
.get_active();
405 m_xFontNameLB
->clear();
406 FontList
aFntLst( Application::GetDefaultDevice() );
407 m_xFontNameLB
->append_text(m_sAutomatic
);
408 sal_uInt16 nFontCount
= aFntLst
.GetFontNameCount();
409 for(sal_uInt16 nFont
= 0; nFont
< nFontCount
; nFont
++)
411 const FontMetric
& rFontMetric
= aFntLst
.GetFontName( nFont
);
412 if(!bNonPropOnly
|| rFontMetric
.GetPitch() == PITCH_FIXED
)
413 m_xFontNameLB
->append_text(rFontMetric
.GetFamilyName());
415 m_xFontNameLB
->set_active_text(sFontName
);
418 void SvxFontSubstTabPage::CheckEnable()
420 bool bEnableAll
= m_xUseTableCB
->get_active() && !officecfg::Office::Common::Font::SourceViewFont::FontName::isReadOnly();
421 m_xCheckLB
->set_sensitive(bEnableAll
);
422 m_xFont1CB
->set_sensitive(bEnableAll
);
423 m_xFont2CB
->set_sensitive(bEnableAll
);
425 bool bApply
= bEnableAll
, bDelete
= bEnableAll
;
429 int nEntry
= m_xCheckLB
->get_selected_index();
431 if (m_xFont1CB
->get_active_text().isEmpty() || m_xFont2CB
->get_active_text().isEmpty())
433 else if (m_xFont1CB
->get_active_text() == m_xFont2CB
->get_active_text())
435 else if (findRow(*m_xCheckLB
, m_xFont1CB
->get_active_text(), m_xFont2CB
->get_active_text()))
437 else if (nEntry
!= -1 && m_xCheckLB
->count_selected_rows() != 1)
442 bDelete
= nEntry
!= -1;
445 m_xApply
->set_sensitive(bApply
);
446 m_xDelete
->set_sensitive(bDelete
);
449 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */