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
, "cui/ui/optfontspage.ui", "OptFontsPage", &rSet
)
37 , m_xUseTableCB(m_xBuilder
->weld_check_button("usetable"))
38 , m_xFont1CB(m_xBuilder
->weld_combo_box("font1"))
39 , m_xFont2CB(m_xBuilder
->weld_combo_box("font2"))
40 , m_xApply(m_xBuilder
->weld_button("apply"))
41 , m_xDelete(m_xBuilder
->weld_button("delete"))
42 , m_xCheckLB(m_xBuilder
->weld_tree_view("checklb"))
43 , m_xFontNameLB(m_xBuilder
->weld_combo_box("fontname"))
44 , m_xNonPropFontsOnlyCB(m_xBuilder
->weld_check_button("nonpropfontonly"))
45 , m_xFontHeightLB(m_xBuilder
->weld_combo_box("fontheight"))
47 m_xFont1CB
->make_sorted();
48 m_xFont1CB
->set_size_request(1, -1);
49 m_xFont2CB
->make_sorted();
50 m_xFont2CB
->set_size_request(1, -1);
51 m_sAutomatic
= m_xFontNameLB
->get_text(0);
52 assert(!m_sAutomatic
.isEmpty());
54 m_xCheckLB
->set_size_request(m_xCheckLB
->get_approximate_digit_width() * 60,
55 m_xCheckLB
->get_height_rows(8));
56 m_xCheckLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
57 m_xCheckLB
->set_help_id(HID_OFA_FONT_SUBST_CLB
);
58 m_xCheckLB
->set_selection_mode(SelectionMode::Multiple
);
60 setColSizes(m_xCheckLB
->get_size_request());
61 m_xCheckLB
->connect_size_allocate(LINK(this, SvxFontSubstTabPage
, ResizeHdl
));
63 m_xCheckLB
->set_centered_column(0);
64 m_xCheckLB
->set_centered_column(1);
66 Link
<weld::ComboBox
&,void> aLink2(LINK(this, SvxFontSubstTabPage
, SelectComboBoxHdl
));
67 Link
<weld::Button
&,void> aClickLink(LINK(this, SvxFontSubstTabPage
, ClickHdl
));
69 m_xCheckLB
->connect_changed(LINK(this, SvxFontSubstTabPage
, TreeListBoxSelectHdl
));
70 m_xCheckLB
->connect_column_clicked(LINK(this, SvxFontSubstTabPage
, HeaderBarClick
));
71 m_xUseTableCB
->connect_toggled(LINK(this, SvxFontSubstTabPage
, ToggleHdl
));
72 m_xFont1CB
->connect_changed(aLink2
);
73 m_xFont2CB
->connect_changed(aLink2
);
74 m_xApply
->connect_clicked(aClickLink
);
75 m_xDelete
->connect_clicked(aClickLink
);
77 m_xNonPropFontsOnlyCB
->connect_toggled(LINK(this, SvxFontSubstTabPage
, NonPropFontsHdl
));
80 for(nHeight
= 6; nHeight
<= 16; nHeight
++)
81 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
82 for(nHeight
= 18; nHeight
<= 28; nHeight
+= 2)
83 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
84 for(nHeight
= 32; nHeight
<= 48; nHeight
+= 4)
85 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
86 for(nHeight
= 54; nHeight
<= 72; nHeight
+= 6)
87 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
88 for(nHeight
= 80; nHeight
<= 96; nHeight
+= 8)
89 m_xFontHeightLB
->append_text(OUString::number(nHeight
));
92 IMPL_LINK(SvxFontSubstTabPage
, HeaderBarClick
, int, nColumn
, void)
94 bool bSortAtoZ
= m_xCheckLB
->get_sort_order();
96 //set new arrow positions in headerbar
97 if (nColumn
== m_xCheckLB
->get_sort_column())
99 bSortAtoZ
= !bSortAtoZ
;
100 m_xCheckLB
->set_sort_order(bSortAtoZ
);
104 m_xCheckLB
->set_sort_indicator(TRISTATE_INDET
, m_xCheckLB
->get_sort_column());
105 m_xCheckLB
->set_sort_column(nColumn
);
111 m_xCheckLB
->set_sort_indicator(bSortAtoZ
? TRISTATE_TRUE
: TRISTATE_FALSE
, nColumn
);
115 void SvxFontSubstTabPage::setColSizes(const Size
& rSize
)
117 int nW1
= m_xCheckLB
->get_pixel_size(m_xCheckLB
->get_column_title(2)).Width();
118 int nW2
= m_xCheckLB
->get_pixel_size(m_xCheckLB
->get_column_title(3)).Width();
119 int nMax
= std::max( nW1
, nW2
) + 6; // width of the longest header + a little offset
120 int nMin
= m_xCheckLB
->get_checkbox_column_width();
121 nMax
= std::max(nMax
, nMin
);
122 const int nDoubleMax
= 2*nMax
;
123 const int nRest
= rSize
.Width() - nDoubleMax
;
124 std::vector
<int> aWidths
{ nMax
, nMax
, nRest
/2 };
125 m_xCheckLB
->set_column_fixed_widths(aWidths
);
128 IMPL_LINK(SvxFontSubstTabPage
, ResizeHdl
, const Size
&, rSize
, void)
133 SvxFontSubstTabPage::~SvxFontSubstTabPage()
137 std::unique_ptr
<SfxTabPage
> SvxFontSubstTabPage::Create( weld::Container
* pPage
, weld::DialogController
* pController
,
138 const SfxItemSet
* rAttrSet
)
140 return std::make_unique
<SvxFontSubstTabPage
>(pPage
, pController
, *rAttrSet
);
143 bool SvxFontSubstTabPage::FillItemSet( SfxItemSet
* )
145 std::vector
<SubstitutionStruct
> aNewFontSubs
;
147 m_xCheckLB
->all_foreach([this, &aNewFontSubs
](weld::TreeIter
& rIter
) {
148 SubstitutionStruct aAdd
;
149 aAdd
.sFont
= m_xCheckLB
->get_text(rIter
, 2);
150 aAdd
.sReplaceBy
= m_xCheckLB
->get_text(rIter
, 3);
151 aAdd
.bReplaceAlways
= m_xCheckLB
->get_toggle(rIter
, 0);
152 aAdd
.bReplaceOnScreenOnly
= m_xCheckLB
->get_toggle(rIter
, 1);
153 aNewFontSubs
.push_back(aAdd
);
157 svtools::SetFontSubstitutions(m_xUseTableCB
->get_active(), aNewFontSubs
);
158 svtools::ApplyFontSubstitutionsToVcl();
160 std::shared_ptr
< comphelper::ConfigurationChanges
> batch(
161 comphelper::ConfigurationChanges::create());
162 if (m_xFontHeightLB
->get_value_changed_from_saved())
163 officecfg::Office::Common::Font::SourceViewFont::FontHeight::set(
164 static_cast< sal_Int16
>(m_xFontHeightLB
->get_active_text().toInt32()),
166 if (m_xNonPropFontsOnlyCB
->get_state_changed_from_saved())
167 officecfg::Office::Common::Font::SourceViewFont::
168 NonProportionalFontsOnly::set(
169 m_xNonPropFontsOnlyCB
->get_active(), batch
);
170 //font name changes cannot be detected by saved values
172 if (m_xFontNameLB
->get_active() != -1)
173 sFontName
= m_xFontNameLB
->get_active_text();
174 officecfg::Office::Common::Font::SourceViewFont::FontName::set(
175 std::optional
< OUString
>(sFontName
), batch
);
181 void SvxFontSubstTabPage::Reset( const SfxItemSet
* )
183 m_xCheckLB
->freeze();
186 m_xFont1CB
->freeze();
188 m_xFont2CB
->freeze();
191 FontList
aFntLst(Application::GetDefaultDevice());
192 sal_uInt16 nFontCount
= aFntLst
.GetFontNameCount();
193 for (sal_uInt16 i
= 0; i
< nFontCount
; ++i
)
195 const FontMetric
& rFontMetric
= aFntLst
.GetFontName(i
);
196 m_xFont1CB
->append_text(rFontMetric
.GetFamilyName());
197 m_xFont2CB
->append_text(rFontMetric
.GetFamilyName());
203 m_xUseTableCB
->set_active(svtools::IsFontSubstitutionsEnabled());
205 std::vector
<SubstitutionStruct
> aFontSubs
= svtools::GetFontSubstitutions();
206 std::unique_ptr
<weld::TreeIter
> xIter(m_xCheckLB
->make_iterator());
207 for (auto const & sub
: aFontSubs
)
209 m_xCheckLB
->append(xIter
.get());
210 m_xCheckLB
->set_toggle(*xIter
, sub
.bReplaceAlways
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
211 m_xCheckLB
->set_toggle(*xIter
, sub
.bReplaceOnScreenOnly
? TRISTATE_TRUE
: TRISTATE_FALSE
, 1);
212 m_xCheckLB
->set_text(*xIter
, sub
.sFont
, 2);
213 m_xCheckLB
->set_text(*xIter
, sub
.sReplaceBy
, 3);
218 m_xCheckLB
->make_sorted();
219 m_xCheckLB
->set_sort_column(2);
220 m_xCheckLB
->set_sort_indicator(TRISTATE_TRUE
, 2);
222 SelectHdl(m_xFont1CB
.get());
224 //fill font name box first
225 m_xNonPropFontsOnlyCB
->set_active(
226 officecfg::Office::Common::Font::SourceViewFont::
227 NonProportionalFontsOnly::get());
228 NonPropFontsHdl(*m_xNonPropFontsOnlyCB
);
230 officecfg::Office::Common::Font::SourceViewFont::FontName::get().
231 value_or(OUString()));
232 if(!sFontName
.isEmpty())
233 m_xFontNameLB
->set_active_text(sFontName
);
235 m_xFontNameLB
->set_active(0);
236 m_xFontHeightLB
->set_active_text(
238 officecfg::Office::Common::Font::SourceViewFont::FontHeight::
240 m_xNonPropFontsOnlyCB
->save_state();
241 m_xFontHeightLB
->save_value();
244 IMPL_LINK(SvxFontSubstTabPage
, ToggleHdl
, weld::Toggleable
&, rButton
, void)
249 IMPL_LINK(SvxFontSubstTabPage
, ClickHdl
, weld::Button
&, rButton
, void)
254 IMPL_LINK(SvxFontSubstTabPage
, TreeListBoxSelectHdl
, weld::TreeView
&, rButton
, void)
259 IMPL_LINK(SvxFontSubstTabPage
, SelectComboBoxHdl
, weld::ComboBox
&, rBox
, void)
266 // search in the "font" column
267 int findText(const weld::TreeView
& rTreeView
, std::u16string_view rCol
)
269 for (int i
= 0, nEntryCount
= rTreeView
.n_children(); i
< nEntryCount
; ++i
)
271 if (rTreeView
.get_text(i
, 2) == rCol
)
277 bool findRow(const weld::TreeView
& rTreeView
, std::u16string_view rCol1
, std::u16string_view rCol2
)
279 int nRow
= findText(rTreeView
, rCol1
);
282 return rTreeView
.get_text(nRow
, 3) == rCol2
;
286 void SvxFontSubstTabPage::SelectHdl(const weld::Widget
* pWin
)
288 if (pWin
== m_xApply
.get() || pWin
== m_xDelete
.get())
290 int nPos
= findText(*m_xCheckLB
, m_xFont1CB
->get_active_text());
291 if (pWin
== m_xApply
.get())
293 m_xCheckLB
->unselect_all();
297 m_xCheckLB
->set_text(nPos
, m_xFont2CB
->get_active_text(), 3);
298 m_xCheckLB
->select(nPos
);
303 OUString sFont1
= m_xFont1CB
->get_active_text();
304 OUString sFont2
= m_xFont2CB
->get_active_text();
306 std::unique_ptr
<weld::TreeIter
> xIter(m_xCheckLB
->make_iterator());
307 m_xCheckLB
->append(xIter
.get());
308 m_xCheckLB
->set_toggle(*xIter
, TRISTATE_FALSE
, 0);
309 m_xCheckLB
->set_toggle(*xIter
, TRISTATE_FALSE
, 1);
310 m_xCheckLB
->set_text(*xIter
, sFont1
, 2);
311 m_xCheckLB
->set_text(*xIter
, sFont2
, 3);
312 m_xCheckLB
->select(*xIter
);
315 else if (pWin
== m_xDelete
.get())
317 m_xCheckLB
->remove_selection();
321 if (pWin
== m_xCheckLB
.get())
323 const int nSelectedRowCount
= m_xCheckLB
->count_selected_rows();
324 if (nSelectedRowCount
== 1)
326 int nRow
= m_xCheckLB
->get_selected_index();
327 m_xFont1CB
->set_entry_text(m_xCheckLB
->get_text(nRow
, 2));
328 m_xFont2CB
->set_entry_text(m_xCheckLB
->get_text(nRow
, 3));
330 else if (nSelectedRowCount
> 1)
332 m_xFont1CB
->set_entry_text(OUString());
333 m_xFont2CB
->set_entry_text(OUString());
337 if (pWin
== m_xFont1CB
.get())
339 int nPos
= findText(*m_xCheckLB
, m_xFont1CB
->get_active_text());
343 int nSelectedRow
= m_xCheckLB
->get_selected_index();
344 if (nPos
!= nSelectedRow
)
346 m_xCheckLB
->unselect_all();
347 m_xCheckLB
->select(nPos
);
351 m_xCheckLB
->unselect_all();
357 IMPL_LINK(SvxFontSubstTabPage
, NonPropFontsHdl
, weld::Toggleable
&, rBox
, void)
359 OUString sFontName
= m_xFontNameLB
->get_active_text();
360 bool bNonPropOnly
= rBox
.get_active();
361 m_xFontNameLB
->clear();
362 FontList
aFntLst( Application::GetDefaultDevice() );
363 m_xFontNameLB
->append_text(m_sAutomatic
);
364 sal_uInt16 nFontCount
= aFntLst
.GetFontNameCount();
365 for(sal_uInt16 nFont
= 0; nFont
< nFontCount
; nFont
++)
367 const FontMetric
& rFontMetric
= aFntLst
.GetFontName( nFont
);
368 if(!bNonPropOnly
|| rFontMetric
.GetPitch() == PITCH_FIXED
)
369 m_xFontNameLB
->append_text(rFontMetric
.GetFamilyName());
371 m_xFontNameLB
->set_active_text(sFontName
);
374 void SvxFontSubstTabPage::CheckEnable()
376 bool bEnableAll
= m_xUseTableCB
->get_active();
377 m_xCheckLB
->set_sensitive(bEnableAll
);
378 m_xFont1CB
->set_sensitive(bEnableAll
);
379 m_xFont2CB
->set_sensitive(bEnableAll
);
381 bool bApply
= bEnableAll
, bDelete
= bEnableAll
;
385 int nEntry
= m_xCheckLB
->get_selected_index();
387 if (m_xFont1CB
->get_active_text().isEmpty() || m_xFont2CB
->get_active_text().isEmpty())
389 else if (m_xFont1CB
->get_active_text() == m_xFont2CB
->get_active_text())
391 else if (findRow(*m_xCheckLB
, m_xFont1CB
->get_active_text(), m_xFont2CB
->get_active_text()))
393 else if (nEntry
!= -1 && m_xCheckLB
->count_selected_rows() != 1)
398 bDelete
= nEntry
!= -1;
401 m_xApply
->set_sensitive(bApply
);
402 m_xDelete
->set_sensitive(bDelete
);
405 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */