LibreOffice Module cui (master)  1
fontsubs.cxx
Go to the documentation of this file.
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 <sal/config.h>
21 
22 #include <officecfg/Office/Common.hxx>
23 #include <svtools/ctrltool.hxx>
24 #include <vcl/svapp.hxx>
26 #include "fontsubs.hxx"
27 #include <helpids.h>
28 
29 /*********************************************************************/
30 /* */
31 /* TabPage font replacement */
32 /* */
33 /*********************************************************************/
34 
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"))
46 {
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());
53 
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);
59 
60  setColSizes(m_xCheckLB->get_size_request());
61  m_xCheckLB->connect_size_allocate(LINK(this, SvxFontSubstTabPage, ResizeHdl));
62 
63  m_xCheckLB->set_centered_column(0);
64  m_xCheckLB->set_centered_column(1);
65 
66  Link<weld::ComboBox&,void> aLink2(LINK(this, SvxFontSubstTabPage, SelectComboBoxHdl));
67  Link<weld::Button&,void> aClickLink(LINK(this, SvxFontSubstTabPage, ClickHdl));
68 
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);
76 
77  m_xNonPropFontsOnlyCB->connect_toggled(LINK(this, SvxFontSubstTabPage, NonPropFontsHdl));
78 
79  sal_uInt16 nHeight;
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));
90 }
91 
92 IMPL_LINK(SvxFontSubstTabPage, HeaderBarClick, int, nColumn, void)
93 {
94  bool bSortAtoZ = m_xCheckLB->get_sort_order();
95 
96  //set new arrow positions in headerbar
97  if (nColumn == m_xCheckLB->get_sort_column())
98  {
99  bSortAtoZ = !bSortAtoZ;
100  m_xCheckLB->set_sort_order(bSortAtoZ);
101  }
102  else
103  {
104  m_xCheckLB->set_sort_indicator(TRISTATE_INDET, m_xCheckLB->get_sort_column());
105  m_xCheckLB->set_sort_column(nColumn);
106  }
107 
108  if (nColumn != -1)
109  {
110  //sort lists
111  m_xCheckLB->set_sort_indicator(bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn);
112  }
113 }
114 
116 {
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;
125  aWidths.push_back(nMax);
126  aWidths.push_back(nMax);
127  aWidths.push_back(nRest/2);
128  m_xCheckLB->set_column_fixed_widths(aWidths);
129 }
130 
131 IMPL_LINK(SvxFontSubstTabPage, ResizeHdl, const Size&, rSize, void)
132 {
133  setColSizes(rSize);
134 }
135 
137 {
138 }
139 
140 std::unique_ptr<SfxTabPage> SvxFontSubstTabPage::Create( weld::Container* pPage, weld::DialogController* pController,
141  const SfxItemSet* rAttrSet)
142 {
143  return std::make_unique<SvxFontSubstTabPage>(pPage, pController, *rAttrSet);
144 }
145 
147 {
148  std::vector<SubstitutionStruct> aNewFontSubs;
149 
150  m_xCheckLB->all_foreach([this, &aNewFontSubs](weld::TreeIter& rIter) {
151  SubstitutionStruct aAdd;
152  aAdd.sFont = m_xCheckLB->get_text(rIter, 2);
153  aAdd.sReplaceBy = m_xCheckLB->get_text(rIter, 3);
154  aAdd.bReplaceAlways = m_xCheckLB->get_toggle(rIter, 0);
155  aAdd.bReplaceOnScreenOnly = m_xCheckLB->get_toggle(rIter, 1);
156  aNewFontSubs.push_back(aAdd);
157  return false;
158  });
159 
160  svtools::SetFontSubstitutions(m_xUseTableCB->get_active(), aNewFontSubs);
162 
163  std::shared_ptr< comphelper::ConfigurationChanges > batch(
165  if (m_xFontHeightLB->get_value_changed_from_saved())
166  officecfg::Office::Common::Font::SourceViewFont::FontHeight::set(
167  static_cast< sal_Int16 >(m_xFontHeightLB->get_active_text().toInt32()),
168  batch);
169  if (m_xNonPropFontsOnlyCB->get_state_changed_from_saved())
170  officecfg::Office::Common::Font::SourceViewFont::
171  NonProportionalFontsOnly::set(
172  m_xNonPropFontsOnlyCB->get_active(), batch);
173  //font name changes cannot be detected by saved values
174  OUString sFontName;
175  if (m_xFontNameLB->get_active() != -1)
176  sFontName = m_xFontNameLB->get_active_text();
177  officecfg::Office::Common::Font::SourceViewFont::FontName::set(
178  std::optional< OUString >(sFontName), batch);
179  batch->commit();
180 
181  return false;
182 }
183 
185 {
186  m_xCheckLB->freeze();
187  m_xCheckLB->clear();
188 
189  m_xFont1CB->freeze();
190  m_xFont1CB->clear();
191  m_xFont2CB->freeze();
192  m_xFont2CB->clear();
193 
195  sal_uInt16 nFontCount = aFntLst.GetFontNameCount();
196  for (sal_uInt16 i = 0; i < nFontCount; ++i)
197  {
198  const FontMetric& rFontMetric = aFntLst.GetFontName(i);
199  m_xFont1CB->append_text(rFontMetric.GetFamilyName());
200  m_xFont2CB->append_text(rFontMetric.GetFamilyName());
201  }
202 
203  m_xFont2CB->thaw();
204  m_xFont1CB->thaw();
205 
207 
208  std::vector<SubstitutionStruct> aFontSubs = svtools::GetFontSubstitutions();
209  std::unique_ptr<weld::TreeIter> xIter(m_xCheckLB->make_iterator());
210  for (sal_Int32 i = 0; i < static_cast<sal_Int32>(aFontSubs.size()); ++i)
211  {
212  m_xCheckLB->append(xIter.get());
213  const SubstitutionStruct* pSubs = &aFontSubs[i];
214  m_xCheckLB->set_toggle(*xIter, pSubs->bReplaceAlways ? TRISTATE_TRUE : TRISTATE_FALSE, 0);
215  m_xCheckLB->set_toggle(*xIter, pSubs->bReplaceOnScreenOnly ? TRISTATE_TRUE : TRISTATE_FALSE, 1);
216  m_xCheckLB->set_text(*xIter, pSubs->sFont, 2);
217  m_xCheckLB->set_text(*xIter, pSubs->sReplaceBy, 3);
218  }
219 
220  m_xCheckLB->thaw();
221 
222  m_xCheckLB->make_sorted();
223  m_xCheckLB->set_sort_column(2);
224  m_xCheckLB->set_sort_indicator(TRISTATE_TRUE, 2);
225 
226  SelectHdl(m_xFont1CB.get());
227 
228  //fill font name box first
229  m_xNonPropFontsOnlyCB->set_active(
230  officecfg::Office::Common::Font::SourceViewFont::
231  NonProportionalFontsOnly::get());
232  NonPropFontsHdl(*m_xNonPropFontsOnlyCB);
233  OUString sFontName(
234  officecfg::Office::Common::Font::SourceViewFont::FontName::get().
235  value_or(OUString()));
236  if(!sFontName.isEmpty())
237  m_xFontNameLB->set_active_text(sFontName);
238  else
239  m_xFontNameLB->set_active(0);
240  m_xFontHeightLB->set_active_text(
241  OUString::number(
242  officecfg::Office::Common::Font::SourceViewFont::FontHeight::
243  get()));
244  m_xNonPropFontsOnlyCB->save_state();
245  m_xFontHeightLB->save_value();
246 }
247 
248 IMPL_LINK(SvxFontSubstTabPage, ToggleHdl, weld::Toggleable&, rButton, void)
249 {
250  SelectHdl(&rButton);
251 }
252 
253 IMPL_LINK(SvxFontSubstTabPage, ClickHdl, weld::Button&, rButton, void)
254 {
255  SelectHdl(&rButton);
256 }
257 
258 IMPL_LINK(SvxFontSubstTabPage, TreeListBoxSelectHdl, weld::TreeView&, rButton, void)
259 {
260  SelectHdl(&rButton);
261 }
262 
263 IMPL_LINK(SvxFontSubstTabPage, SelectComboBoxHdl, weld::ComboBox&, rBox, void)
264 {
265  SelectHdl(&rBox);
266 }
267 
268 namespace
269 {
270  // search in the "font" column
271  int findText(const weld::TreeView& rTreeView, std::u16string_view rCol)
272  {
273  for (int i = 0, nEntryCount = rTreeView.n_children(); i < nEntryCount; ++i)
274  {
275  if (rTreeView.get_text(i, 2) == rCol)
276  return i;
277  }
278  return -1;
279  }
280 
281  bool findRow(const weld::TreeView& rTreeView, std::u16string_view rCol1, std::u16string_view rCol2)
282  {
283  int nRow = findText(rTreeView, rCol1);
284  if (nRow == -1)
285  return false;
286  return rTreeView.get_text(nRow, 3) == rCol2;
287  }
288 }
289 
291 {
292  if (pWin == m_xApply.get() || pWin == m_xDelete.get())
293  {
294  int nPos = findText(*m_xCheckLB, m_xFont1CB->get_active_text());
295  if (pWin == m_xApply.get())
296  {
297  m_xCheckLB->unselect_all();
298  if (nPos != -1)
299  {
300  // change entry
301  m_xCheckLB->set_text(nPos, m_xFont2CB->get_active_text(), 3);
302  m_xCheckLB->select(nPos);
303  }
304  else
305  {
306  // new entry
307  OUString sFont1 = m_xFont1CB->get_active_text();
308  OUString sFont2 = m_xFont2CB->get_active_text();
309 
310  std::unique_ptr<weld::TreeIter> xIter(m_xCheckLB->make_iterator());
311  m_xCheckLB->append(xIter.get());
312  m_xCheckLB->set_toggle(*xIter, TRISTATE_FALSE, 0);
313  m_xCheckLB->set_toggle(*xIter, TRISTATE_FALSE, 1);
314  m_xCheckLB->set_text(*xIter, sFont1, 2);
315  m_xCheckLB->set_text(*xIter, sFont2, 3);
316  m_xCheckLB->select(*xIter);
317  }
318  }
319  else if (pWin == m_xDelete.get())
320  {
321  m_xCheckLB->remove_selection();
322  }
323  }
324 
325  if (pWin == m_xCheckLB.get())
326  {
327  const int nSelectedRowCount = m_xCheckLB->count_selected_rows();
328  if (nSelectedRowCount == 1)
329  {
330  int nRow = m_xCheckLB->get_selected_index();
331  m_xFont1CB->set_entry_text(m_xCheckLB->get_text(nRow, 2));
332  m_xFont2CB->set_entry_text(m_xCheckLB->get_text(nRow, 3));
333  }
334  else if (nSelectedRowCount > 1)
335  {
336  m_xFont1CB->set_entry_text(OUString());
337  m_xFont2CB->set_entry_text(OUString());
338  }
339  }
340 
341  if (pWin == m_xFont1CB.get())
342  {
343  int nPos = findText(*m_xCheckLB, m_xFont1CB->get_active_text());
344 
345  if (nPos != -1)
346  {
347  int nSelectedRow = m_xCheckLB->get_selected_index();
348  if (nPos != nSelectedRow)
349  {
350  m_xCheckLB->unselect_all();
351  m_xCheckLB->select(nPos);
352  }
353  }
354  else
355  m_xCheckLB->unselect_all();
356  }
357 
358  CheckEnable();
359 }
360 
361 IMPL_LINK(SvxFontSubstTabPage, NonPropFontsHdl, weld::Toggleable&, rBox, void)
362 {
363  OUString sFontName = m_xFontNameLB->get_active_text();
364  bool bNonPropOnly = rBox.get_active();
365  m_xFontNameLB->clear();
367  m_xFontNameLB->append_text(m_sAutomatic);
368  sal_uInt16 nFontCount = aFntLst.GetFontNameCount();
369  for(sal_uInt16 nFont = 0; nFont < nFontCount; nFont++)
370  {
371  const FontMetric& rFontMetric = aFntLst.GetFontName( nFont );
372  if(!bNonPropOnly || rFontMetric.GetPitch() == PITCH_FIXED)
373  m_xFontNameLB->append_text(rFontMetric.GetFamilyName());
374  }
375  m_xFontNameLB->set_active_text(sFontName);
376 }
377 
379 {
380  bool bEnableAll = m_xUseTableCB->get_active();
381  m_xCheckLB->set_sensitive(bEnableAll);
382  m_xFont1CB->set_sensitive(bEnableAll);
383  m_xFont2CB->set_sensitive(bEnableAll);
384 
385  bool bApply = bEnableAll, bDelete = bEnableAll;
386 
387  if (bEnableAll)
388  {
389  int nEntry = m_xCheckLB->get_selected_index();
390 
391  if (m_xFont1CB->get_active_text().isEmpty() || m_xFont2CB->get_active_text().isEmpty())
392  bApply = false;
393  else if (m_xFont1CB->get_active_text() == m_xFont2CB->get_active_text())
394  bApply = false;
395  else if (findRow(*m_xCheckLB, m_xFont1CB->get_active_text(), m_xFont2CB->get_active_text()))
396  bApply = false;
397  else if (nEntry != -1 && m_xCheckLB->count_selected_rows() != 1)
398  bApply = false;
399  else
400  bApply = true;
401 
402  bDelete = nEntry != -1;
403  }
404 
405  m_xApply->set_sensitive(bApply);
406  m_xDelete->set_sensitive(bDelete);
407 }
408 
409 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const OUString & GetFamilyName() const
std::unique_ptr< weld::ComboBox > m_xFontHeightLB
Definition: fontsubs.hxx:38
TRISTATE_TRUE
std::unique_ptr< weld::Button > m_xDelete
Definition: fontsubs.hxx:34
std::unique_ptr< weld::ComboBox > m_xFont1CB
Definition: fontsubs.hxx:31
#define HID_OFA_FONT_SUBST_CLB
Definition: helpids.h:22
virtual bool FillItemSet(SfxItemSet *rSet) override
Definition: fontsubs.cxx:146
static OutputDevice * GetDefaultDevice()
constexpr tools::Long Width() const
std::unique_ptr< weld::ComboBox > m_xFontNameLB
Definition: fontsubs.hxx:36
virtual int n_children() const =0
std::unique_ptr< weld::TreeView > m_xCheckLB
Definition: fontsubs.hxx:35
bool IsFontSubstitutionsEnabled()
static std::shared_ptr< ConfigurationChanges > create(css::uno::Reference< css::uno::XComponentContext > const &context=comphelper::getProcessComponentContext())
void SetFontSubstitutions(bool bIsEnabled, std::vector< SubstitutionStruct > const &aSubstArr)
TRISTATE_INDET
OUString m_sAutomatic
Definition: fontsubs.hxx:28
const FontMetric & GetFontName(size_t nFont) const
FontPitch GetPitch()
int i
PITCH_FIXED
TRISTATE_FALSE
virtual OUString get_text(int row, int col=-1) const =0
SvxFontSubstTabPage(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet &rSet)
Definition: fontsubs.cxx:35
std::unique_ptr< weld::CheckButton > m_xUseTableCB
Definition: fontsubs.hxx:30
void setColSizes(const Size &rSize)
Definition: fontsubs.cxx:115
void ApplyFontSubstitutionsToVcl()
size_t GetFontNameCount() const
static std::unique_ptr< SfxTabPage > Create(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet *rAttrSet)
Definition: fontsubs.cxx:140
std::unique_ptr< weld::ComboBox > m_xFont2CB
Definition: fontsubs.hxx:32
std::vector< SubstitutionStruct > GetFontSubstitutions()
std::unique_ptr< weld::CheckButton > m_xNonPropFontsOnlyCB
Definition: fontsubs.hxx:37
virtual ~SvxFontSubstTabPage() override
Definition: fontsubs.cxx:136
std::unique_ptr< weld::Button > m_xApply
Definition: fontsubs.hxx:33
void SelectHdl(const weld::Widget *pWidget)
Definition: fontsubs.cxx:290
IMPL_LINK(SvxFontSubstTabPage, HeaderBarClick, int, nColumn, void)
Definition: fontsubs.cxx:92
virtual void Reset(const SfxItemSet *rSet) override
Definition: fontsubs.cxx:184
sal_uInt16 nPos